From f0c361ebca12ee8563c90adcf42356d71a375f69 Mon Sep 17 00:00:00 2001 From: Jiayuan Zhang Date: Wed, 28 Oct 2026 23:52:28 +0800 Subject: [PATCH] feat(ui): Multica icons, roomier menus and typography pass (MUL-8334, MUL-8338) (#9640) * refactor(ui): add @multica/ui/icons as the single icon entry point (MUL-8334) Co-authored-by: Cursor Co-authored-by: multica-agent * refactor: import icons from @multica/ui/icons instead of lucide-react (MUL-8334) Co-authored-by: Cursor Co-authored-by: multica-agent * chore(lint): ban direct lucide-react imports outside @multica/ui/icons (MUL-8334) Co-authored-by: Cursor Co-authored-by: multica-agent * feat(ui): draw Multica icons and enlarge primitive icon sizes (MUL-8334) Co-authored-by: Cursor Co-authored-by: multica-agent * feat(ui): roomier menu and sidebar rhythm (MUL-8334) Co-authored-by: Cursor Co-authored-by: multica-agent * feat(ui): mark body and detail layers in icon glyphs (MUL-8334) Co-authored-by: Cursor Co-authored-by: multica-agent * feat(ui): Inter optical sizing, lighter titles, CJK leading and zh-TW font stack (MUL-8338) Co-authored-by: Cursor Co-authored-by: multica-agent * feat(ui): 13px for in-place reading text, regular weight for descriptive labels (MUL-8338) Issue detail timeline, comment headers, properties panel, wakeup and PR rows move from 12px to 13px; sub-issue identifiers match list/board (12px regular); sidebar group labels drop to regular weight; board card titles get more leading under a CJK UI via a new cjk: variant. Co-authored-by: Cursor Co-authored-by: multica-agent * feat(ui): tint the active sidebar icon's body with a light fill (MUL-8334) Co-authored-by: Cursor Co-authored-by: multica-agent * feat(ui): draw every remaining icon and drop lucide-react (MUL-8334) All 286 icon names now render Multica drawings. The drawings, their construction helpers and the generator live in packages/ui/icons/drawings; glyphs.ts and index.ts are generated and a test fails when they drift. Search loses its lens highlight and Inbox its arrow. Co-authored-by: Cursor Co-authored-by: multica-agent * chore: guard against icon libraries and document drawing new icons (MUL-8334) Lint bans the common React icon libraries, AGENTS.md points to a new multica-icons skill, route icons must mark a body for the active tint, and comments no longer describe product icons as Lucide. Co-authored-by: Cursor Co-authored-by: multica-agent * feat(ui): fill the active sidebar icon solid with its details knocked out (MUL-8334) Co-authored-by: Cursor Co-authored-by: multica-agent * fix(lint): ban icon library subpaths too (MUL-8334) Co-authored-by: Cursor Co-authored-by: multica-agent --------- Co-authored-by: Cursor Co-authored-by: multica-agent --- .agents/skills/multica-icons/SKILL.md | 53 ++ AGENTS.md | 1 + apps/desktop/eslint.config.mjs | 2 + apps/desktop/package.json | 1 - .../renderer/src/components/daemon-panel.tsx | 2 +- .../src/components/daemon-runtime-card.tsx | 2 +- .../src/components/daemon-settings-tab.tsx | 2 +- .../renderer/src/components/issue-window.tsx | 2 +- .../src/components/route-error-page.tsx | 2 +- .../renderer/src/components/tab-bar.test.tsx | 2 +- .../src/renderer/src/components/tab-bar.tsx | 2 +- .../src/components/update-notification.tsx | 2 +- .../src/components/updates-settings-tab.tsx | 2 +- .../src/components/window-toolbar.tsx | 2 +- apps/desktop/src/renderer/src/globals.css | 11 + apps/desktop/src/renderer/src/main.tsx | 7 +- apps/desktop/src/renderer/src/routes.tsx | 2 +- apps/docs/app/layout.config.tsx | 2 +- .../components/demos/agent-access-demo.tsx | 2 +- apps/docs/components/demos/assign-demo.tsx | 2 +- apps/docs/components/demos/autopilot-demo.tsx | 2 +- .../components/demos/channel-chat-demo.tsx | 2 +- apps/docs/components/demos/chat-demo.tsx | 2 +- .../docs/components/demos/chat-queue-demo.tsx | 2 +- .../components/demos/concept-map-demo.tsx | 2 +- .../components/demos/create-agent-demo.tsx | 2 +- .../components/demos/deliverables-demo.tsx | 2 +- apps/docs/components/demos/demo-kit.tsx | 2 +- .../components/demos/desktop-tabs-demo.tsx | 2 +- apps/docs/components/demos/inbox-demo.tsx | 2 +- .../components/demos/issue-draft-demo.tsx | 2 +- .../components/demos/issue-status-demo.tsx | 2 +- .../components/demos/local-dir-mode-demo.tsx | 2 +- apps/docs/components/demos/pr-link-demo.tsx | 2 +- apps/docs/components/demos/project-demo.tsx | 2 +- .../components/demos/provider-picker-demo.tsx | 2 +- .../components/demos/quick-action-demo.tsx | 2 +- .../components/demos/resolve-thread-demo.tsx | 2 +- apps/docs/components/demos/roles-demo.tsx | 2 +- .../components/demos/run-lifecycle-demo.tsx | 2 +- apps/docs/components/demos/run-path-demo.tsx | 2 +- .../components/demos/runtime-offline-demo.tsx | 2 +- apps/docs/components/demos/skill-demo.tsx | 2 +- apps/docs/components/demos/squad-demo.tsx | 2 +- apps/docs/components/demos/steer-demo.tsx | 2 +- .../components/demos/trigger-chooser-demo.tsx | 2 +- apps/docs/components/demos/usage-demo.tsx | 2 +- apps/docs/components/demos/wakeup-demo.tsx | 2 +- apps/docs/components/demos/workflow-demo.tsx | 2 +- apps/docs/components/docs-settings.tsx | 2 +- apps/docs/components/video-embed.tsx | 2 +- apps/docs/package.json | 1 - apps/ui-lab/package.json | 1 - apps/ui-lab/src/app.tsx | 2 +- apps/ui-lab/src/button-scene.tsx | 2 +- apps/ui-lab/src/catalog-content.tsx | 2 +- apps/ui-lab/src/catalog-navigation.tsx | 2 +- apps/ui-lab/src/color-editor.tsx | 2 +- apps/ui-lab/src/inspector.tsx | 2 +- apps/ui-lab/src/number-field.tsx | 2 +- apps/ui-lab/src/preview.tsx | 2 +- apps/ui-lab/src/token-changes.tsx | 2 +- apps/web/app/(auth)/login/page.tsx | 2 +- apps/web/app/auth/callback/page.tsx | 2 +- apps/web/app/globals.css | 11 + apps/web/app/layout.tsx | 8 +- .../components/download/cli-section.tsx | 2 +- .../landing/components/download/hero.tsx | 2 +- .../landing/components/features-section.tsx | 2 +- .../landing/components/landing-header.tsx | 2 +- .../landing/components/landing-hero.tsx | 2 +- apps/web/package.json | 1 - e2e/comments.spec.ts | 2 +- e2e/perf/floating-chat-lifetime.spec.ts | 4 +- packages/core/paths/route-icons.ts | 2 +- packages/core/paths/tab-presentation.ts | 2 +- packages/core/paths/tab-subject.ts | 2 +- packages/eslint-config/base.js | 25 + packages/eslint-config/icon-imports.test.js | 39 ++ packages/eslint-config/package.json | 3 + .../ui/components/common/actor-avatar.tsx | 2 +- .../components/common/capability-banner.tsx | 2 +- .../components/common/file-upload-button.tsx | 2 +- .../components/common/quick-emoji-picker.tsx | 2 +- .../ui/components/common/submit-button.tsx | 2 +- packages/ui/components/ui/button.tsx | 6 +- packages/ui/components/ui/calendar.tsx | 2 +- packages/ui/components/ui/checkbox.tsx | 2 +- packages/ui/components/ui/command.tsx | 4 +- packages/ui/components/ui/context-menu.tsx | 16 +- packages/ui/components/ui/dialog.tsx | 2 +- packages/ui/components/ui/dropdown-menu.tsx | 18 +- packages/ui/components/ui/input-otp.tsx | 2 +- packages/ui/components/ui/list-grid.tsx | 2 +- packages/ui/components/ui/select.tsx | 10 +- packages/ui/components/ui/sheet.tsx | 2 +- packages/ui/components/ui/sidebar.tsx | 10 +- packages/ui/components/ui/sonner.tsx | 2 +- packages/ui/components/ui/spinner.tsx | 2 +- packages/ui/components/ui/time-input.tsx | 2 +- packages/ui/eslint.config.mjs | 10 +- packages/ui/icons/create-icon.ts | 63 +++ packages/ui/icons/drawings/construction.mjs | 79 +++ packages/ui/icons/drawings/drawings.mjs | 470 ++++++++++++++++++ packages/ui/icons/drawings/generate.d.mts | 5 + packages/ui/icons/drawings/generate.mjs | 123 +++++ packages/ui/icons/glyphs.ts | 268 ++++++++++ packages/ui/icons/icons.test.ts | 26 + packages/ui/icons/index.ts | 302 +++++++++++ packages/ui/markdown/CodeBlock.tsx | 2 +- packages/ui/markdown/Markdown.tsx | 2 +- packages/ui/package.json | 3 +- packages/ui/styles/base.css | 6 + packages/ui/styles/tokens.css | 7 +- .../agent-activity-hover-content.tsx | 2 +- .../agents/components/agent-batch-toolbar.tsx | 2 +- .../agents/components/agent-detail-page.tsx | 2 +- .../agents/components/agent-list-toolbar.tsx | 2 +- .../components/agent-live-peek-card.tsx | 2 +- .../components/agent-overview-summary.tsx | 2 +- .../components/agent-profile-card.test.tsx | 6 +- .../agents/components/agent-row-actions.tsx | 2 +- .../views/agents/components/agents-page.tsx | 2 +- .../conversation-starters-editor.tsx | 2 +- .../agents/components/create-agent-dialog.tsx | 2 +- .../components/inspector/access-picker.tsx | 2 +- .../components/inspector/model-picker.tsx | 2 +- .../components/inspector/runtime-picker.tsx | 2 +- .../inspector/service-tier-setting-field.tsx | 2 +- .../components/inspector/skill-attach.tsx | 2 +- .../components/inspector/thinking-picker.tsx | 2 +- .../inspector/visibility-picker.tsx | 2 +- .../agents/components/instructions-editor.tsx | 2 +- .../agents/components/model-dropdown.tsx | 2 +- .../agents/components/model-search-header.tsx | 2 +- .../runtime-machine-filter-dropdown.tsx | 2 +- .../agents/components/runtime-picker.tsx | 2 +- .../agents/components/skill-multi-select.tsx | 2 +- .../agents/components/skill-picker-list.tsx | 2 +- .../agents/components/tabs/activity-tab.tsx | 2 +- .../agents/components/tabs/agent-mcp-tab.tsx | 2 +- .../components/tabs/custom-args-tab.tsx | 2 +- .../views/agents/components/tabs/env-tab.tsx | 2 +- .../components/tabs/instructions-tab.tsx | 2 +- .../agents/components/tabs/mcp-config-tab.tsx | 2 +- .../components/tabs/mcp-server-dialog.tsx | 2 +- .../components/tabs/runtime-config-tab.tsx | 2 +- .../agents/components/tabs/skills-tab.tsx | 2 +- .../agents/components/visibility-badge.tsx | 2 +- packages/views/agents/config.ts | 2 +- .../agents/create/agent-created-page.tsx | 2 +- .../agents/create/builder-conversation.tsx | 2 +- .../agents/create/choose-runtime-page.tsx | 2 +- .../agents/create/create-agent-footer.tsx | 2 +- packages/views/agents/create/create-shell.tsx | 2 +- .../create/manual-create-agent-page.tsx | 2 +- .../agents/create/runtime-choice-list.tsx | 2 +- .../views/agents/create/unfinished-drafts.tsx | 2 +- packages/views/agents/presence.ts | 8 +- .../attachments/attachment-preview-page.tsx | 2 +- .../components/autopilot-access-manager.tsx | 2 +- .../components/autopilot-detail-page.tsx | 2 +- .../components/autopilot-dialog.tsx | 2 +- .../components/autopilot-list-actions.tsx | 2 +- .../components/autopilot-list-toolbar.tsx | 2 +- .../autopilots/components/autopilots-page.tsx | 2 +- .../components/pickers/agent-picker.tsx | 2 +- .../components/pickers/timezone-picker.tsx | 2 +- .../schedule-editor/schedule-editor.tsx | 2 +- .../components/subscriber-multi-select.tsx | 2 +- .../components/webhook-deliveries-section.tsx | 2 +- .../webhook-event-filter-section.tsx | 2 +- .../components/webhook-payload-preview.tsx | 2 +- .../components/webhook-url-field.tsx | 2 +- .../components/workspace-wakeups.tsx | 2 +- .../views/billing/billing-return-page.tsx | 2 +- packages/views/billing/billing-test-page.tsx | 2 +- packages/views/chat/chat-page.tsx | 2 +- .../agent-access-revoked-banner.tsx | 2 +- .../chat/components/archived-agent-banner.tsx | 2 +- .../views/chat/components/chat-add-menu.tsx | 2 +- .../chat/components/chat-empty-state.tsx | 2 +- packages/views/chat/components/chat-fab.tsx | 2 +- packages/views/chat/components/chat-input.tsx | 2 +- .../chat/components/chat-message-list.tsx | 2 +- packages/views/chat/components/chat-queue.tsx | 2 +- .../chat/components/chat-session-header.tsx | 2 +- .../chat/components/chat-thread-list.tsx | 2 +- .../views/chat/components/chat-window.tsx | 2 +- .../views/chat/components/new-chat-button.tsx | 2 +- .../views/chat/components/no-agent-banner.tsx | 2 +- .../views/chat/components/offline-banner.tsx | 2 +- .../components/onboarding-starter-cards.tsx | 2 +- .../views/chat/components/quick-agent-bar.tsx | 2 +- .../components/runtime-required-banner.tsx | 2 +- packages/views/common/actor-issues-panel.tsx | 2 +- packages/views/common/avatar-crop-dialog.tsx | 2 +- .../views/common/avatar-upload-control.tsx | 2 +- packages/views/common/color-picker.tsx | 2 +- packages/views/common/date-only-picker.tsx | 2 +- packages/views/common/hover-check.tsx | 2 +- packages/views/common/mcp-server-row.test.tsx | 2 +- packages/views/common/mcp-server-row.tsx | 2 +- packages/views/common/pill-button.tsx | 2 +- packages/views/common/prop-row.tsx | 4 +- packages/views/common/property-icon.tsx | 8 +- packages/views/common/row-actions-menu.tsx | 2 +- .../views/common/shortcut-keycaps.test.tsx | 14 +- packages/views/common/shortcut-keycaps.tsx | 6 +- .../agent-transcript-dialog.test.tsx | 10 +- .../agent-transcript-dialog.tsx | 2 +- .../common/task-transcript/run-timeline.tsx | 2 +- .../task-transcript/transcript-button.tsx | 2 +- .../components/dashboard-filters.tsx | 2 +- .../dashboard/components/dashboard-page.tsx | 2 +- .../views/dashboard/components/errors-tab.tsx | 2 +- .../dashboard/components/leaderboard.tsx | 2 +- .../dashboard/components/usage-trend-card.tsx | 2 +- packages/views/editor/attachment-card.tsx | 2 +- .../views/editor/attachment-preview-modal.tsx | 10 +- packages/views/editor/attachment.tsx | 2 +- packages/views/editor/bubble-menu.tsx | 2 +- packages/views/editor/dynamic-block.tsx | 2 +- .../editor/extensions/code-block-view.tsx | 2 +- .../editor/extensions/mention-suggestion.tsx | 2 +- .../views/editor/html-preview-surface.tsx | 2 +- packages/views/editor/link-hover-card.tsx | 2 +- packages/views/editor/mermaid-diagram.tsx | 2 +- packages/views/editor/mermaid-viewer.tsx | 2 +- packages/views/editor/structured-tree.tsx | 2 +- packages/views/editor/styles/prose.css | 15 +- packages/views/editor/table-preview.tsx | 2 +- packages/views/editor/utils/file-icon.ts | 6 +- packages/views/editor/zoom-canvas.tsx | 2 +- .../inbox/components/inbox-filter-menu.tsx | 2 +- .../inbox/components/inbox-item-actions.tsx | 2 +- .../inbox/components/inbox-list-item.tsx | 2 +- .../views/inbox/components/inbox-list.tsx | 2 +- .../views/inbox/components/inbox-page.tsx | 2 +- .../views/invitations/invitations-page.tsx | 2 +- packages/views/invite/invite-page.tsx | 2 +- .../actions/issue-actions-menu-items.tsx | 2 +- .../components/batch-action-toolbar.tsx | 2 +- .../views/issues/components/board-card.tsx | 4 +- .../views/issues/components/board-column.tsx | 2 +- .../views/issues/components/comment-card.tsx | 10 +- .../components/comment-trigger-chips.tsx | 2 +- .../components/create-renderers.test.tsx | 2 +- .../deliverables/deliverable-details.tsx | 2 +- .../deliverables/deliverables-overview.tsx | 2 +- .../deliverables/deliverables-section.tsx | 2 +- .../components/execution-log-section.tsx | 2 +- .../issues/components/filter-chips-bar.tsx | 2 +- packages/views/issues/components/find-bar.tsx | 2 +- .../components/infinite-scroll-sentinel.tsx | 2 +- .../issues/components/inline-comment-run.tsx | 10 +- .../issue-agent-activity-indicator.tsx | 2 +- .../issues/components/issue-detail.test.tsx | 2 +- .../views/issues/components/issue-detail.tsx | 30 +- .../issues/components/issue-duplicates.tsx | 2 +- .../issues/components/issue-hover-card.tsx | 6 +- .../views/issues/components/issue-peek.tsx | 2 +- .../issues/components/issue-runs-dialog.tsx | 2 +- .../components/issue-sidebar-section.tsx | 6 +- .../components/issue-wakeup-header-chip.tsx | 2 +- .../views/issues/components/issues-header.tsx | 2 +- .../views/issues/components/issues-page.tsx | 2 +- .../views/issues/components/list-view.tsx | 2 +- .../issues/components/manage-views-dialog.tsx | 2 +- .../issues/components/metadata-section.tsx | 2 +- .../components/pickers/assignee-picker.tsx | 2 +- .../pickers/custom-property-picker.tsx | 2 +- .../components/pickers/due-date-picker.tsx | 2 +- .../components/pickers/label-picker.tsx | 2 +- .../components/pickers/property-picker.tsx | 2 +- .../components/pickers/stage-picker.tsx | 2 +- .../components/pickers/start-date-picker.tsx | 2 +- .../components/pickers/status-picker.test.tsx | 2 +- .../components/pickers/status-picker.tsx | 2 +- .../issues/components/pull-request-list.tsx | 12 +- .../components/pull-requests-section.tsx | 2 +- .../components/quick-actions-section.tsx | 2 +- .../issues/components/reply-annotations.tsx | 2 +- .../issues/components/resolved-thread-bar.tsx | 2 +- .../issues/components/retry-run-button.tsx | 2 +- .../issues/components/save-view-dialog.tsx | 2 +- .../components/source-context-viewer.test.tsx | 2 +- .../components/source-context-viewer.tsx | 2 +- .../components/steer-attachment-notice.tsx | 2 +- .../issues/components/steer-receipts.tsx | 2 +- .../views/issues/components/swimlane-view.tsx | 2 +- .../issues/components/system-wakeup-row.tsx | 6 +- .../views/issues/components/table-view.tsx | 2 +- .../issues/components/task-status-icon.tsx | 2 +- .../issues/components/thread-minimap.test.tsx | 2 +- .../issues/components/thread-minimap.tsx | 2 +- .../components/use-comment-annotations.tsx | 2 +- .../issues/components/view-bar-popover.tsx | 2 +- packages/views/issues/components/view-bar.tsx | 2 +- .../issues/components/wakeup-activity.tsx | 2 +- .../views/issues/components/wakeup-create.tsx | 6 +- .../components/wakeup-instruction-editor.tsx | 2 +- .../issues/components/wakeup-source-chip.tsx | 2 +- .../issues/components/wakeups-section.tsx | 12 +- .../views/issues/surface/issue-surface.tsx | 2 +- packages/views/labels/label-chip.tsx | 2 +- packages/views/labels/label-manager.tsx | 2 +- .../views/labels/resource-label-picker.tsx | 2 +- packages/views/layout/app-sidebar.tsx | 2 +- packages/views/layout/breadcrumb-header.tsx | 2 +- .../views/layout/collection-page.test.tsx | 2 +- packages/views/layout/collection-page.tsx | 8 +- packages/views/layout/help-launcher.tsx | 2 +- packages/views/layout/join-discord-card.tsx | 2 +- packages/views/layout/page-header.test.tsx | 2 +- .../layout/route-icon-components.test.tsx | 8 + .../views/layout/route-icon-components.tsx | 8 +- .../views/layout/tab-presentation.test.tsx | 2 +- packages/views/members/member-detail-page.tsx | 2 +- packages/views/modals/create-issue.tsx | 2 +- packages/views/modals/create-project.tsx | 2 +- packages/views/modals/create-squad.tsx | 2 +- .../modals/issue-limit-upgrade-dialog.tsx | 2 +- packages/views/modals/quick-create-issue.tsx | 2 +- .../views/modals/source-context-preview.tsx | 2 +- .../my-issues/components/my-issues-header.tsx | 2 +- .../my-issues/components/my-issues-page.tsx | 2 +- .../components/cloud-waitlist-expand.tsx | 2 +- .../components/icon-option-card.tsx | 4 +- .../components/onboarding-logout-button.tsx | 2 +- .../onboarding/components/step-sidebar.tsx | 2 +- .../onboarding/source-backfill-modal.tsx | 2 +- .../steps/cli-install-instructions.tsx | 2 +- .../views/onboarding/steps/step-about-you.tsx | 2 +- .../onboarding/steps/step-platform-fork.tsx | 2 +- .../onboarding/steps/step-runtime-connect.tsx | 2 +- .../views/onboarding/steps/step-welcome.tsx | 2 +- .../views/onboarding/steps/step-workspace.tsx | 2 +- packages/views/package.json | 1 - .../views/plugins/plugin-hook-actions.tsx | 2 +- .../views/plugins/plugin-hook-activity.tsx | 2 +- .../views/plugins/plugin-mcp-approval.tsx | 2 +- .../views/plugins/plugin-modal-surface.tsx | 2 +- .../projects/components/github-ref-dialog.tsx | 2 +- .../components/local-directory-hint.tsx | 2 +- .../local-directory-mode-dialog.tsx | 2 +- .../projects/components/project-badge.tsx | 2 +- .../projects/components/project-detail.tsx | 2 +- .../components/project-due-date-picker.tsx | 2 +- .../components/project-lead-picker.tsx | 2 +- .../projects/components/project-picker.tsx | 2 +- .../components/project-resources-section.tsx | 2 +- .../components/project-start-date-picker.tsx | 2 +- .../projects/components/projects-page.tsx | 2 +- .../components/quick-action-dialog.tsx | 2 +- .../views/rich-content/rich-code-block.tsx | 2 +- .../rich-content/rich-content-parity.test.tsx | 2 +- .../views/rich-content/rich-table-dialog.tsx | 2 +- packages/views/rich-content/rich-table.tsx | 2 +- .../components/cloud-runtime-dialog.tsx | 2 +- .../components/connect-remote-dialog.tsx | 2 +- .../components/custom-pricing-dialog.tsx | 2 +- .../components/delete-runtime-dialog.tsx | 2 +- .../delete-runtime-profile-dialog.tsx | 2 +- .../runtimes/components/provider-logo.tsx | 2 +- .../components/qoder-connect-form.tsx | 2 +- .../components/qoder-connection-cards.tsx | 2 +- .../runtimes/components/qoder-detail-page.tsx | 2 +- .../revoke-runtime-access-dialog.tsx | 2 +- .../components/runtime-access-editor.tsx | 2 +- .../components/runtime-detail-page.tsx | 2 +- .../runtimes/components/runtime-detail.tsx | 2 +- .../runtimes/components/runtime-list.tsx | 2 +- .../components/runtime-profiles-dialog.tsx | 2 +- .../components/runtime-settings-page.tsx | 2 +- .../runtimes/components/runtimes-page.tsx | 2 +- packages/views/runtimes/components/shared.tsx | 2 +- .../runtimes/components/update-section.tsx | 2 +- .../runtimes/components/usage-section.tsx | 2 +- .../search/commands/context-commands.tsx | 2 +- .../views/search/commands/global-commands.tsx | 2 +- .../views/search/commands/issue-commands.tsx | 2 +- .../views/search/delegate/delegate-group.tsx | 2 +- packages/views/search/pages/issue-pages.tsx | 2 +- packages/views/search/pages/other-pages.tsx | 2 +- packages/views/search/result-rows.tsx | 2 +- packages/views/search/root-view.tsx | 4 +- packages/views/search/rows.tsx | 2 +- packages/views/search/search-command.tsx | 2 +- packages/views/search/search-trigger.tsx | 2 +- .../views/settings/components/billing-tab.tsx | 2 +- .../settings/components/channels-tab.tsx | 2 +- .../views/settings/components/code-tab.tsx | 2 +- .../views/settings/components/code-vcs.tsx | 2 +- .../settings/components/composio-tab.tsx | 2 +- .../settings/components/dingtalk-tab.tsx | 2 +- .../components/issue-statuses-tab.test.tsx | 4 +- .../components/issue-statuses-tab.tsx | 2 +- .../components/keyboard-shortcuts-tab.tsx | 2 +- .../views/settings/components/lark-tab.tsx | 2 +- .../views/settings/components/mcp-tab.tsx | 2 +- .../views/settings/components/members-tab.tsx | 2 +- .../views/settings/components/plugins-tab.tsx | 2 +- .../components/pr-merge-status-row.tsx | 2 +- .../settings/components/preferences-tab.tsx | 2 +- .../settings/components/properties-tab.tsx | 2 +- .../settings/components/quick-actions-tab.tsx | 2 +- .../components/repositories-section.tsx | 2 +- .../settings/components/settings-layout.tsx | 2 +- .../settings/components/settings-page.tsx | 2 +- .../views/settings/components/slack-tab.tsx | 2 +- .../settings/components/telegram-tab.tsx | 2 +- .../views/settings/components/tokens-tab.tsx | 2 +- .../views/settings/components/wecom-tab.tsx | 2 +- .../settings/components/workspace-tab.tsx | 2 +- .../skills/components/create-skill-dialog.tsx | 2 +- .../views/skills/components/file-tree.tsx | 2 +- .../components/refresh-skill-dialog.tsx | 2 +- .../runtime-local-skill-import-panel.tsx | 2 +- .../skills/components/skill-detail-page.tsx | 2 +- .../skills/components/skill-list-actions.tsx | 2 +- .../skills/components/skill-list-toolbar.tsx | 2 +- .../views/skills/components/skills-page.tsx | 2 +- packages/views/skills/lib/skill-icon.ts | 4 +- .../squads/components/squad-detail-page.tsx | 4 +- .../views/squads/components/squads-page.tsx | 2 +- packages/views/workflows/column-handoff.tsx | 2 +- .../workflows/handoff-confirm-dialog.tsx | 2 +- packages/views/workflows/handoff-form.tsx | 2 +- packages/views/workflows/issue-flow-card.tsx | 2 +- .../views/workflows/project-workflow-menu.tsx | 2 +- .../views/workflows/project-workflow-row.tsx | 2 +- packages/views/workflows/timeline-handoff.tsx | 2 +- .../views/workflows/workflow-editor-page.tsx | 2 +- .../workflows/workflow-mapping-dialog.tsx | 2 +- packages/views/workflows/workflow-pill.tsx | 2 +- packages/views/workflows/workflows-tab.tsx | 2 +- pnpm-lock.yaml | 60 +-- pnpm-workspace.yaml | 1 - server/internal/handler/property.go | 4 +- 440 files changed, 2067 insertions(+), 576 deletions(-) create mode 100644 .agents/skills/multica-icons/SKILL.md create mode 100644 packages/eslint-config/icon-imports.test.js create mode 100644 packages/ui/icons/create-icon.ts create mode 100644 packages/ui/icons/drawings/construction.mjs create mode 100644 packages/ui/icons/drawings/drawings.mjs create mode 100644 packages/ui/icons/drawings/generate.d.mts create mode 100644 packages/ui/icons/drawings/generate.mjs create mode 100644 packages/ui/icons/glyphs.ts create mode 100644 packages/ui/icons/icons.test.ts create mode 100644 packages/ui/icons/index.ts diff --git a/.agents/skills/multica-icons/SKILL.md b/.agents/skills/multica-icons/SKILL.md new file mode 100644 index 000000000..d772ac7b1 --- /dev/null +++ b/.agents/skills/multica-icons/SKILL.md @@ -0,0 +1,53 @@ +--- +name: multica-icons +description: Use when a Multica web/desktop UI change needs an icon that `@multica/ui/icons` does not export yet, or when redrawing or reviewing a Multica glyph. Covers the grid, corner and stroke construction, the body/detail markers, and the generate-and-preview loop. Never reach for an icon library, inline SVG, or emoji instead. +--- + +# Drawing Multica icons + +Every icon in the product is a Multica drawing exported from `@multica/ui/icons`. No icon library is installed, and lint rejects imports from one. When you need a new symbol, draw it. + +## Before drawing + +1. Search `packages/ui/icons/index.ts` for the name and for synonyms. If an existing glyph already means the same thing, add an alias to `ALIASES` in `drawings.mjs` instead of drawing a near-duplicate. +2. Pick a name that describes the symbol, not the feature (`Webhook`, not `IntegrationsNav`). Follow the existing PascalCase names. + +## Where things live + +- `packages/ui/icons/drawings/construction.mjs` holds the shared geometry helpers. +- `packages/ui/icons/drawings/drawings.mjs` holds every drawing as inner SVG markup, plus `ALIASES`. +- `packages/ui/icons/glyphs.ts` and `index.ts` are generated. Never edit them by hand; `icons.test.ts` fails when they drift. + +## Construction + +- **Grid.** 24×24 viewBox, with a 2px round-capped, round-joined stroke from the renderer. Keep geometry inside 2.5–21.5. Most silhouettes span 2.75–21.25. +- **Corners.** Use `shape([[x, y, k], ...])` and `rect(x, y, w, h, k)`, which build continuous-curvature (squircle) corners. Typical `k` values: + - 5–7 for large containers such as cards, windows and chat bubbles. + - 2.5–4 for small parts. + - 1–1.5 for tips and points. + - 0 for a hard corner, which is rare. + + Do not hand-write `a r r` arc corners for rectangles. +- **Arrowheads and chevrons.** Use `head(x, y, dir, depth, half)` for a soft arrowhead with its tip at (x, y). For chevrons, copy the existing `M… s…` soft curves. Never use sharp polyline arrowheads. +- **Dots.** `dot(x, y, r)` with r 1.1–1.5. Use dots only where they carry meaning: info, alert, eyes, status lights. +- **Polygons and stars.** `polygon(cx, cy, radii, count, k)`. +- **Reuse parts.** `file()`, `folderBody`, `bubble`, `ring`, `user()`, `link`, `cw` and `ccw` already exist. A variant (`…Off`, `…Plus`, `…X`) is the base drawing plus one stroke. A slash runs `m3 3 18 18`. + +## Body and details + +- Mark the main closed silhouette with `class="b"` (body). The active sidebar item fills it solid. + - Any icon that can appear in navigation must have a body. A test enforces this for route icons. + - Only mark closed shapes. An open arc with a fill closes into a stray chord. +- Mark every stroke or dot that sits inside the body with `class="k"` (detail). The solid state knocks details out in the background colour; an unmarked detail disappears into the fill. +- **Detail budget.** At most two inner details. Every detail must carry meaning: a check, a symbol, a divider that defines the object. Drop decorative highlights, extra lines and texture. Icons render at 14px in dense rows, where a third detail turns into noise. + +## Loop + +1. Add the drawing to `DRAWINGS` in `drawings.mjs`. Keep sections grouped by subject. +2. Run `pnpm --filter @multica/ui icons --preview NewName Neighbour1 Neighbour2`. Open the printed HTML file in a browser and check four things: + - At 48px: does the geometry sit on the grid, with even optical weight next to its neighbours? + - At 18px and 14px: is it still legible, or do inner details merge? + - In the solid (active) tile: does the silhouette fill, with every inner detail still visible? + - Against similar glyphs: can it be told apart at a glance? +3. Run `pnpm --filter @multica/ui icons` to regenerate `glyphs.ts` and `index.ts`. +4. Import the new name from `@multica/ui/icons`. Then run `pnpm --filter @multica/ui test` and the typecheck for the package that uses it. diff --git a/AGENTS.md b/AGENTS.md index 4c14d5f2a..5f48af199 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -103,6 +103,7 @@ Workspace-scoped queries filter by `workspace_id`; membership gates access and ` - For Button and Dialog usage, read `packages/ui/docs/button.md` and `packages/ui/docs/dialog.md`. These component contracts also power UI Lab documentation. - Prefer existing shadcn/Base UI primitives. Add components with `pnpm ui:add `. - For `pnpm ui:add @reui/`, decline overwrite prompts. Keep `REUI_LICENSE_KEY` in the environment, never in repo files. Adapt vendored primitives into `packages/ui/components/ui/` and compositions into `packages/views/`. +- Import icons from `@multica/ui/icons`; no icon library is installed. If the icon you need is missing, draw it by following `.agents/skills/multica-icons/SKILL.md`. Do not substitute an inline SVG or an emoji. Rewrite icon imports in `ui:add` output before committing. - Use shared semantic tokens in `packages/ui/styles/`. Typography uses the role-named `--text-*` scale in `packages/ui/styles/tokens.css`, not Tailwind's default size ramp. - Selected states remain identifiable on hover. Handle overflow, long text, and scrolling deliberately; avoid unnecessary local state and dividers. diff --git a/apps/desktop/eslint.config.mjs b/apps/desktop/eslint.config.mjs index d72268b23..3e56f67ae 100644 --- a/apps/desktop/eslint.config.mjs +++ b/apps/desktop/eslint.config.mjs @@ -1,5 +1,6 @@ import globals from "globals"; import reactConfig from "@multica/eslint-config/react"; +import { ICON_LIBRARY_IMPORT_PATTERNS } from "@multica/eslint-config/base"; export default [ ...reactConfig, @@ -63,6 +64,7 @@ export default [ "Direct navigation from application code breaks the Coordinator protocol (MUL-4741). Use the navigation adapter from src/platform instead.", }, ], + patterns: ICON_LIBRARY_IMPORT_PATTERNS, }, ], "no-restricted-syntax": [ diff --git a/apps/desktop/package.json b/apps/desktop/package.json index fc9cbfbb0..ce9990ba4 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -48,7 +48,6 @@ "@tanstack/react-query": "catalog:", "electron-updater": "^6.8.3", "fix-path": "^5.0.0", - "lucide-react": "catalog:", "motion": "^12.38.0", "react": "catalog:", "react-dom": "catalog:", diff --git a/apps/desktop/src/renderer/src/components/daemon-panel.tsx b/apps/desktop/src/renderer/src/components/daemon-panel.tsx index 2214c6e04..55167b841 100644 --- a/apps/desktop/src/renderer/src/components/daemon-panel.tsx +++ b/apps/desktop/src/renderer/src/components/daemon-panel.tsx @@ -14,7 +14,7 @@ import { Server, Trash2, X, -} from "lucide-react"; +} from "@multica/ui/icons"; import { truncateWithEllipsis } from "@multica/core/utils"; import { cn } from "@multica/ui/lib/utils"; import { copyText } from "@multica/ui/lib/clipboard"; diff --git a/apps/desktop/src/renderer/src/components/daemon-runtime-card.tsx b/apps/desktop/src/renderer/src/components/daemon-runtime-card.tsx index fdf1ee123..3cad02334 100644 --- a/apps/desktop/src/renderer/src/components/daemon-runtime-card.tsx +++ b/apps/desktop/src/renderer/src/components/daemon-runtime-card.tsx @@ -8,7 +8,7 @@ import { ScrollText, LogIn, Info, -} from "lucide-react"; +} from "@multica/ui/icons"; import { useQuery } from "@tanstack/react-query"; import { useWorkspaceId } from "@multica/core/hooks"; import { runtimeListOptions } from "@multica/core/runtimes"; diff --git a/apps/desktop/src/renderer/src/components/daemon-settings-tab.tsx b/apps/desktop/src/renderer/src/components/daemon-settings-tab.tsx index e983b16b2..d97432f3c 100644 --- a/apps/desktop/src/renderer/src/components/daemon-settings-tab.tsx +++ b/apps/desktop/src/renderer/src/components/daemon-settings-tab.tsx @@ -1,5 +1,5 @@ import { useState, useEffect, useCallback, type ReactNode } from "react"; -import { AlertCircle, Info, LogIn } from "lucide-react"; +import { AlertCircle, Info, LogIn } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { Switch } from "@multica/ui/components/ui/switch"; import { cn } from "@multica/ui/lib/utils"; diff --git a/apps/desktop/src/renderer/src/components/issue-window.tsx b/apps/desktop/src/renderer/src/components/issue-window.tsx index 9719f366c..5f1f4f876 100644 --- a/apps/desktop/src/renderer/src/components/issue-window.tsx +++ b/apps/desktop/src/renderer/src/components/issue-window.tsx @@ -5,7 +5,7 @@ import { useParams, useRouteError, } from "react-router-dom"; -import { AlertTriangle, RotateCw, X } from "lucide-react"; +import { AlertTriangle, RotateCw, X } from "@multica/ui/icons"; import { useAuthStore } from "@multica/core/auth"; import { setCurrentWorkspace } from "@multica/core/platform"; import { WorkspaceSlugProvider } from "@multica/core/paths"; diff --git a/apps/desktop/src/renderer/src/components/route-error-page.tsx b/apps/desktop/src/renderer/src/components/route-error-page.tsx index 7043e358e..e52eb8dff 100644 --- a/apps/desktop/src/renderer/src/components/route-error-page.tsx +++ b/apps/desktop/src/renderer/src/components/route-error-page.tsx @@ -1,6 +1,6 @@ import { useMemo } from "react"; import { isRouteErrorResponse, useLocation, useRouteError } from "react-router-dom"; -import { AlertTriangle, Compass, RotateCw, Send, X } from "lucide-react"; +import { AlertTriangle, Compass, RotateCw, Send, X } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import type { DesktopRouteErrorFeedbackContext } from "@multica/core/feedback"; import { useModalStore } from "@multica/core/modals"; diff --git a/apps/desktop/src/renderer/src/components/tab-bar.test.tsx b/apps/desktop/src/renderer/src/components/tab-bar.test.tsx index b345ffc8f..166066039 100644 --- a/apps/desktop/src/renderer/src/components/tab-bar.test.tsx +++ b/apps/desktop/src/renderer/src/components/tab-bar.test.tsx @@ -244,7 +244,7 @@ describe("TabBar hover action buttons", () => { // The leading slot is the resource visual (size-3.5), not a Pin glyph. The // only Pin lives in the size-2.5 hover action button. expect(pinnedTab.querySelector('[data-testid="tab-leading"]')).toBeTruthy(); - expect(pinnedTab.querySelector(".lucide-pin.size-3\\.5")).toBeNull(); + expect(pinnedTab.querySelector(".icon-pin.size-3\\.5")).toBeNull(); }); }); diff --git a/apps/desktop/src/renderer/src/components/tab-bar.tsx b/apps/desktop/src/renderer/src/components/tab-bar.tsx index 444889781..2ba6ea24f 100644 --- a/apps/desktop/src/renderer/src/components/tab-bar.tsx +++ b/apps/desktop/src/renderer/src/components/tab-bar.tsx @@ -7,7 +7,7 @@ import { type RefObject, } from "react"; import { motion, useReducedMotion } from "motion/react"; -import { X, Plus, Pin, PinOff, ListX, AppWindow } from "lucide-react"; +import { X, Plus, Pin, PinOff, ListX, AppWindow } from "@multica/ui/icons"; import { DndContext, PointerSensor, diff --git a/apps/desktop/src/renderer/src/components/update-notification.tsx b/apps/desktop/src/renderer/src/components/update-notification.tsx index 2da1b767b..f6ee1ece4 100644 --- a/apps/desktop/src/renderer/src/components/update-notification.tsx +++ b/apps/desktop/src/renderer/src/components/update-notification.tsx @@ -1,5 +1,5 @@ import { useEffect, useState } from "react"; -import { RefreshCw, X } from "lucide-react"; +import { RefreshCw, X } from "@multica/ui/icons"; // Downloads run silently in the background (main process has // autoDownload=true). The renderer only renders UI once the package is fully diff --git a/apps/desktop/src/renderer/src/components/updates-settings-tab.tsx b/apps/desktop/src/renderer/src/components/updates-settings-tab.tsx index 20c52a9f9..d8e771094 100644 --- a/apps/desktop/src/renderer/src/components/updates-settings-tab.tsx +++ b/apps/desktop/src/renderer/src/components/updates-settings-tab.tsx @@ -1,5 +1,5 @@ import { useCallback, useEffect, useState } from "react"; -import { AlertCircle, ArrowDownToLine, Check, Loader2 } from "lucide-react"; +import { AlertCircle, ArrowDownToLine, Check, Loader2 } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { Switch } from "@multica/ui/components/ui/switch"; import { useT } from "@multica/views/i18n"; diff --git a/apps/desktop/src/renderer/src/components/window-toolbar.tsx b/apps/desktop/src/renderer/src/components/window-toolbar.tsx index f3ac5596e..873ad69bb 100644 --- a/apps/desktop/src/renderer/src/components/window-toolbar.tsx +++ b/apps/desktop/src/renderer/src/components/window-toolbar.tsx @@ -6,7 +6,7 @@ import { useState, type PointerEventHandler, } from "react"; -import { ArrowLeft, ArrowRight } from "lucide-react"; +import { ArrowLeft, ArrowRight } from "@multica/ui/icons"; import { SidebarTrigger, useSidebar, diff --git a/apps/desktop/src/renderer/src/globals.css b/apps/desktop/src/renderer/src/globals.css index acb6c3f3c..551ede7b8 100644 --- a/apps/desktop/src/renderer/src/globals.css +++ b/apps/desktop/src/renderer/src/globals.css @@ -65,6 +65,17 @@ html[lang|="ja"] { "Noto Sans CJK KR", sans-serif; } +/* Traditional Chinese: same problem one level down — the default stack is + Simplified-first, so zh-TW users get Simplified glyph shapes for shared + ideographs. App.tsx maps zh-Hant to `zh-TW`. Mirrors apps/web/app/globals.css. */ +html[lang="zh-TW"] { + --font-sans: "Inter Variable", "Inter", -apple-system, BlinkMacSystemFont, + "Segoe UI", "PingFang TC", "Microsoft JhengHei", + "Noto Sans CJK TC", "PingFang SC", "Microsoft YaHei", + "Noto Sans CJK SC", "Apple SD Gothic Neo", "Malgun Gothic", + "Noto Sans CJK KR", sans-serif; +} + @source "../../../../../packages/ui/**/*.tsx"; @source "../../../../../packages/core/**/*.{ts,tsx}"; @source "../../../../../packages/views/**/*.{ts,tsx}"; diff --git a/apps/desktop/src/renderer/src/main.tsx b/apps/desktop/src/renderer/src/main.tsx index 56852a09c..fc9714d9b 100644 --- a/apps/desktop/src/renderer/src/main.tsx +++ b/apps/desktop/src/renderer/src/main.tsx @@ -4,10 +4,13 @@ import { AppCrashBoundary } from "./components/app-crash-boundary"; // Inter variable font covers all weights (100-900) in a single file. // CJK is handled by system font fallback (see globals.css --font-sans chain). // Keep font stack in sync with apps/web/app/layout.tsx. +// The opsz files carry the optical-size axis on top of weight, so headings get +// Inter Display's cut while body text keeps the text cut — web loads the same +// axis via next/font `axes: ["opsz"]`. // The italic axis ships as a separate file — without it the ~20 semantic italic // labels and every markdown /blockquote render as synthesized oblique. -import "@fontsource-variable/inter"; -import "@fontsource-variable/inter/wght-italic.css"; +import "@fontsource-variable/inter/opsz.css"; +import "@fontsource-variable/inter/opsz-italic.css"; // Editorial serif — matches web's next/font Source_Serif_4. Loaded app-wide so // onboarding headings and any future editorial surface can use `font-serif` // (see tokens.css @theme inline). Variable font = one file covers all weights. diff --git a/apps/desktop/src/renderer/src/routes.tsx b/apps/desktop/src/renderer/src/routes.tsx index 39350edc4..e16c412e7 100644 --- a/apps/desktop/src/renderer/src/routes.tsx +++ b/apps/desktop/src/renderer/src/routes.tsx @@ -32,7 +32,7 @@ import { InboxPage } from "@multica/views/inbox"; import { ChatPage } from "@multica/views/chat"; import { SettingsPage } from "@multica/views/settings"; import { useT } from "@multica/views/i18n"; -import { Download, Server } from "lucide-react"; +import { Download, Server } from "@multica/ui/icons"; import { DaemonSettingsTab } from "./components/daemon-settings-tab"; import { UpdatesSettingsTab } from "./components/updates-settings-tab"; import { WorkspaceRouteLayout } from "./components/workspace-route-layout"; diff --git a/apps/docs/app/layout.config.tsx b/apps/docs/app/layout.config.tsx index c68ca356b..e5572619a 100644 --- a/apps/docs/app/layout.config.tsx +++ b/apps/docs/app/layout.config.tsx @@ -1,5 +1,5 @@ import type { BaseLayoutProps } from "fumadocs-ui/layouts/shared"; -import { ArrowUpRight } from "lucide-react"; +import { ArrowUpRight } from "@multica/ui/icons"; // Docs-local stateless Multica mark — matches @multica/ui's MulticaIcon // visually (same 8-pointed-asterisk clip-path), but without useState/ diff --git a/apps/docs/components/demos/agent-access-demo.tsx b/apps/docs/components/demos/agent-access-demo.tsx index c4c57cfcb..d62b861e9 100644 --- a/apps/docs/components/demos/agent-access-demo.tsx +++ b/apps/docs/components/demos/agent-access-demo.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { ArrowLeft, Check, Globe, Lock, Minus, Users } from "lucide-react"; +import { ArrowLeft, Check, Globe, Lock, Minus, Users } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { cn } from "@multica/ui/lib/utils"; import { CoachMark, DemoAvatar, DemoFrame, useDemoCopy, useStartWhenVisible } from "./demo-kit"; diff --git a/apps/docs/components/demos/assign-demo.tsx b/apps/docs/components/demos/assign-demo.tsx index 392bd8f21..6ca823cc6 100644 --- a/apps/docs/components/demos/assign-demo.tsx +++ b/apps/docs/components/demos/assign-demo.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { ChevronDown, X } from "lucide-react"; +import { ChevronDown, X } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { cn } from "@multica/ui/lib/utils"; import { diff --git a/apps/docs/components/demos/autopilot-demo.tsx b/apps/docs/components/demos/autopilot-demo.tsx index ddc1b305b..f9e6f189c 100644 --- a/apps/docs/components/demos/autopilot-demo.tsx +++ b/apps/docs/components/demos/autopilot-demo.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useState } from "react"; -import { CheckCircle2, Clock, FastForward, Loader2, Pencil, Play } from "lucide-react"; +import { CheckCircle2, Clock, FastForward, Loader2, Pencil, Play } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { cn } from "@multica/ui/lib/utils"; import { diff --git a/apps/docs/components/demos/channel-chat-demo.tsx b/apps/docs/components/demos/channel-chat-demo.tsx index a367b3fa8..b519faa1b 100644 --- a/apps/docs/components/demos/channel-chat-demo.tsx +++ b/apps/docs/components/demos/channel-chat-demo.tsx @@ -1,7 +1,7 @@ "use client"; import { useState, type ReactNode } from "react"; -import { Users } from "lucide-react"; +import { Users } from "@multica/ui/icons"; import { cn } from "@multica/ui/lib/utils"; import { CoachMark, diff --git a/apps/docs/components/demos/chat-demo.tsx b/apps/docs/components/demos/chat-demo.tsx index a3eb9a0ee..ea322cab2 100644 --- a/apps/docs/components/demos/chat-demo.tsx +++ b/apps/docs/components/demos/chat-demo.tsx @@ -1,7 +1,7 @@ "use client"; import { type ReactNode, useState } from "react"; -import { CircleDashed, Loader2 } from "lucide-react"; +import { CircleDashed, Loader2 } from "@multica/ui/icons"; import { CoachMark, DemoAvatar, DemoFrame, DemoSendButton, useDemoCopy, useDemoTimers, useStartWhenVisible } from "./demo-kit"; type Suggestion = { label: string; prompt: string }; diff --git a/apps/docs/components/demos/chat-queue-demo.tsx b/apps/docs/components/demos/chat-queue-demo.tsx index 3841e11e9..fd2d1e5fe 100644 --- a/apps/docs/components/demos/chat-queue-demo.tsx +++ b/apps/docs/components/demos/chat-queue-demo.tsx @@ -1,7 +1,7 @@ "use client"; import { type ReactNode, useEffect, useState } from "react"; -import { CornerDownRight, Ellipsis, ListEnd, Loader2, Pencil, Square, Trash2 } from "lucide-react"; +import { CornerDownRight, Ellipsis, ListEnd, Loader2, Pencil, Square, Trash2 } from "@multica/ui/icons"; import { CoachMark, DemoAvatar, diff --git a/apps/docs/components/demos/concept-map-demo.tsx b/apps/docs/components/demos/concept-map-demo.tsx index 1f9a605f0..42a47a793 100644 --- a/apps/docs/components/demos/concept-map-demo.tsx +++ b/apps/docs/components/demos/concept-map-demo.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { CornerDownRight } from "lucide-react"; +import { CornerDownRight } from "@multica/ui/icons"; import { cn } from "@multica/ui/lib/utils"; import { LocaleLink } from "@/components/locale-link"; import { CoachMark, DemoFrame, useDemoCopy, useStartWhenVisible } from "./demo-kit"; diff --git a/apps/docs/components/demos/create-agent-demo.tsx b/apps/docs/components/demos/create-agent-demo.tsx index 13e40bc0b..10e893399 100644 --- a/apps/docs/components/demos/create-agent-demo.tsx +++ b/apps/docs/components/demos/create-agent-demo.tsx @@ -1,7 +1,7 @@ "use client"; import { useState, type ReactNode } from "react"; -import { ArrowRight, AtSign, Bot, Check, CircleCheck, ListPlus, Monitor, Sparkles, Users } from "lucide-react"; +import { ArrowRight, AtSign, Bot, Check, CircleCheck, ListPlus, Monitor, Sparkles, Users } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { cn } from "@multica/ui/lib/utils"; import { CoachMark, DemoFrame, useDemoCopy, useDemoTimers, useStartWhenVisible } from "./demo-kit"; diff --git a/apps/docs/components/demos/deliverables-demo.tsx b/apps/docs/components/demos/deliverables-demo.tsx index 048801837..08b17ac8c 100644 --- a/apps/docs/components/demos/deliverables-demo.tsx +++ b/apps/docs/components/demos/deliverables-demo.tsx @@ -1,7 +1,7 @@ "use client"; import { useState, type ReactNode } from "react"; -import { Check, ChevronDown, ChevronRight, FileText, LayoutGrid, MessageSquareText, X } from "lucide-react"; +import { Check, ChevronDown, ChevronRight, FileText, LayoutGrid, MessageSquareText, X } from "@multica/ui/icons"; import { cn } from "@multica/ui/lib/utils"; import { CoachMark, DemoAvatar, DemoFrame, useDemoCopy, useStartWhenVisible } from "./demo-kit"; diff --git a/apps/docs/components/demos/demo-kit.tsx b/apps/docs/components/demos/demo-kit.tsx index f6617cb22..ed75d185d 100644 --- a/apps/docs/components/demos/demo-kit.tsx +++ b/apps/docs/components/demos/demo-kit.tsx @@ -18,7 +18,7 @@ import { CornerDownRight, Loader2, RotateCcw, -} from "lucide-react"; +} from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { cn } from "@multica/ui/lib/utils"; import { useDocsLocale } from "@/components/locale-link"; diff --git a/apps/docs/components/demos/desktop-tabs-demo.tsx b/apps/docs/components/demos/desktop-tabs-demo.tsx index 0307188ea..8a85e921a 100644 --- a/apps/docs/components/demos/desktop-tabs-demo.tsx +++ b/apps/docs/components/demos/desktop-tabs-demo.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { Check, ChevronsUpDown, Inbox, ListTodo, Pin, PinOff, UserRound, X } from "lucide-react"; +import { Check, ChevronsUpDown, Inbox, ListTodo, Pin, PinOff, UserRound, X } from "@multica/ui/icons"; import { cn } from "@multica/ui/lib/utils"; import { CoachMark, DemoFrame, useDemoCopy, useStartWhenVisible } from "./demo-kit"; diff --git a/apps/docs/components/demos/inbox-demo.tsx b/apps/docs/components/demos/inbox-demo.tsx index 7c01921b9..338d7d4df 100644 --- a/apps/docs/components/demos/inbox-demo.tsx +++ b/apps/docs/components/demos/inbox-demo.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { Archive, ArchiveRestore, ChevronLeft, ChevronRight, CircleCheck, X } from "lucide-react"; +import { Archive, ArchiveRestore, ChevronLeft, ChevronRight, CircleCheck, X } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { cn } from "@multica/ui/lib/utils"; import { CoachMark, DemoAvatar, DemoComment, DemoFrame, useDemoCopy, useStartWhenVisible } from "./demo-kit"; diff --git a/apps/docs/components/demos/issue-draft-demo.tsx b/apps/docs/components/demos/issue-draft-demo.tsx index 582e7fa25..1db8dbd82 100644 --- a/apps/docs/components/demos/issue-draft-demo.tsx +++ b/apps/docs/components/demos/issue-draft-demo.tsx @@ -11,7 +11,7 @@ import { Paperclip, Users, X, -} from "lucide-react"; +} from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { cn } from "@multica/ui/lib/utils"; import { diff --git a/apps/docs/components/demos/issue-status-demo.tsx b/apps/docs/components/demos/issue-status-demo.tsx index 4f3bd9682..60a70b444 100644 --- a/apps/docs/components/demos/issue-status-demo.tsx +++ b/apps/docs/components/demos/issue-status-demo.tsx @@ -1,7 +1,7 @@ "use client"; import { useRef, useState } from "react"; -import { ChevronDown } from "lucide-react"; +import { ChevronDown } from "@multica/ui/icons"; import { cn } from "@multica/ui/lib/utils"; import { CoachMark, diff --git a/apps/docs/components/demos/local-dir-mode-demo.tsx b/apps/docs/components/demos/local-dir-mode-demo.tsx index 4c36534d8..581274d5e 100644 --- a/apps/docs/components/demos/local-dir-mode-demo.tsx +++ b/apps/docs/components/demos/local-dir-mode-demo.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { Check, Clock, FileText, Folder, GitBranch, Loader2, Pencil } from "lucide-react"; +import { Check, Clock, FileText, Folder, GitBranch, Loader2, Pencil } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { cn } from "@multica/ui/lib/utils"; import { diff --git a/apps/docs/components/demos/pr-link-demo.tsx b/apps/docs/components/demos/pr-link-demo.tsx index 7e5751915..1852d557e 100644 --- a/apps/docs/components/demos/pr-link-demo.tsx +++ b/apps/docs/components/demos/pr-link-demo.tsx @@ -8,7 +8,7 @@ import { GitMerge, GitPullRequestArrow, MoreHorizontal, -} from "lucide-react"; +} from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { cn } from "@multica/ui/lib/utils"; import { CoachMark, DemoAvatar, DemoFrame, useDemoCopy, useDemoTimers, useStartWhenVisible } from "./demo-kit"; diff --git a/apps/docs/components/demos/project-demo.tsx b/apps/docs/components/demos/project-demo.tsx index 737a9ee43..e6ce14c6b 100644 --- a/apps/docs/components/demos/project-demo.tsx +++ b/apps/docs/components/demos/project-demo.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { ChevronDown, FolderKanban } from "lucide-react"; +import { ChevronDown, FolderKanban } from "@multica/ui/icons"; import { cn } from "@multica/ui/lib/utils"; import { CoachMark, DemoAvatar, DemoFrame, useDemoCopy, useStartWhenVisible } from "./demo-kit"; diff --git a/apps/docs/components/demos/provider-picker-demo.tsx b/apps/docs/components/demos/provider-picker-demo.tsx index 379fa49fb..e6cb74911 100644 --- a/apps/docs/components/demos/provider-picker-demo.tsx +++ b/apps/docs/components/demos/provider-picker-demo.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { Check, Cpu, History, Plug } from "lucide-react"; +import { Check, Cpu, History, Plug } from "@multica/ui/icons"; import { cn } from "@multica/ui/lib/utils"; import { CoachMark, DemoFrame, useDemoCopy, useStartWhenVisible } from "./demo-kit"; diff --git a/apps/docs/components/demos/quick-action-demo.tsx b/apps/docs/components/demos/quick-action-demo.tsx index 7bcdc72d7..0276a723c 100644 --- a/apps/docs/components/demos/quick-action-demo.tsx +++ b/apps/docs/components/demos/quick-action-demo.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { ChevronRight, CircleCheck, Loader2, Zap } from "lucide-react"; +import { ChevronRight, CircleCheck, Loader2, Zap } from "@multica/ui/icons"; import { CoachMark, DemoAvatar, diff --git a/apps/docs/components/demos/resolve-thread-demo.tsx b/apps/docs/components/demos/resolve-thread-demo.tsx index 95901fc2b..2e101c0f9 100644 --- a/apps/docs/components/demos/resolve-thread-demo.tsx +++ b/apps/docs/components/demos/resolve-thread-demo.tsx @@ -1,7 +1,7 @@ "use client"; import { type ReactNode, useState } from "react"; -import { CheckCircle2, ChevronRight, Copy, ListChevronsDownUp, MoreHorizontal } from "lucide-react"; +import { CheckCircle2, ChevronRight, Copy, ListChevronsDownUp, MoreHorizontal } from "@multica/ui/icons"; import { CoachMark, DemoAvatar, DemoFrame, useDemoCopy, useStartWhenVisible } from "./demo-kit"; type Entry = { author: string; agent: boolean; body: string }; diff --git a/apps/docs/components/demos/roles-demo.tsx b/apps/docs/components/demos/roles-demo.tsx index 3133ec781..1a7913e42 100644 --- a/apps/docs/components/demos/roles-demo.tsx +++ b/apps/docs/components/demos/roles-demo.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { Check, Crown, Minus, MoreHorizontal, Plus, Shield, User, UserMinus } from "lucide-react"; +import { Check, Crown, Minus, MoreHorizontal, Plus, Shield, User, UserMinus } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { cn } from "@multica/ui/lib/utils"; import { CoachMark, DemoAvatar, DemoFrame, useDemoCopy, useStartWhenVisible } from "./demo-kit"; diff --git a/apps/docs/components/demos/run-lifecycle-demo.tsx b/apps/docs/components/demos/run-lifecycle-demo.tsx index 0265670f9..5db49541e 100644 --- a/apps/docs/components/demos/run-lifecycle-demo.tsx +++ b/apps/docs/components/demos/run-lifecycle-demo.tsx @@ -1,7 +1,7 @@ "use client"; import { useCallback, useEffect, useRef, useState } from "react"; -import { Ban, CheckCircle2, ChevronRight, Loader2, RotateCcw, Square, XCircle } from "lucide-react"; +import { Ban, CheckCircle2, ChevronRight, Loader2, RotateCcw, Square, XCircle } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { cn } from "@multica/ui/lib/utils"; import { diff --git a/apps/docs/components/demos/run-path-demo.tsx b/apps/docs/components/demos/run-path-demo.tsx index f4709d739..0caa23b00 100644 --- a/apps/docs/components/demos/run-path-demo.tsx +++ b/apps/docs/components/demos/run-path-demo.tsx @@ -1,7 +1,7 @@ "use client"; import { useState, type ReactNode } from "react"; -import { ArrowRight, Laptop, Loader2 } from "lucide-react"; +import { ArrowRight, Laptop, Loader2 } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { cn } from "@multica/ui/lib/utils"; import { diff --git a/apps/docs/components/demos/runtime-offline-demo.tsx b/apps/docs/components/demos/runtime-offline-demo.tsx index 26e6ebdcd..4c501171c 100644 --- a/apps/docs/components/demos/runtime-offline-demo.tsx +++ b/apps/docs/components/demos/runtime-offline-demo.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useState } from "react"; -import { Laptop, Loader2, Power } from "lucide-react"; +import { Laptop, Loader2, Power } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { cn } from "@multica/ui/lib/utils"; import { diff --git a/apps/docs/components/demos/skill-demo.tsx b/apps/docs/components/demos/skill-demo.tsx index b176d620f..f6c99fad7 100644 --- a/apps/docs/components/demos/skill-demo.tsx +++ b/apps/docs/components/demos/skill-demo.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { Check, Plus, Search } from "lucide-react"; +import { Check, Plus, Search } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { cn } from "@multica/ui/lib/utils"; import { diff --git a/apps/docs/components/demos/squad-demo.tsx b/apps/docs/components/demos/squad-demo.tsx index 376fbd2c6..67a3a76d2 100644 --- a/apps/docs/components/demos/squad-demo.tsx +++ b/apps/docs/components/demos/squad-demo.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { ChevronDown, Users, X } from "lucide-react"; +import { ChevronDown, Users, X } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { cn } from "@multica/ui/lib/utils"; import { diff --git a/apps/docs/components/demos/steer-demo.tsx b/apps/docs/components/demos/steer-demo.tsx index 7601af749..ac84f9229 100644 --- a/apps/docs/components/demos/steer-demo.tsx +++ b/apps/docs/components/demos/steer-demo.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useState } from "react"; -import { CornerDownRight } from "lucide-react"; +import { CornerDownRight } from "@multica/ui/icons"; import { CoachMark, DemoAvatar, diff --git a/apps/docs/components/demos/trigger-chooser-demo.tsx b/apps/docs/components/demos/trigger-chooser-demo.tsx index a4c41a40f..bc9bcba72 100644 --- a/apps/docs/components/demos/trigger-chooser-demo.tsx +++ b/apps/docs/components/demos/trigger-chooser-demo.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { ArrowRight, Check } from "lucide-react"; +import { ArrowRight, Check } from "@multica/ui/icons"; import { cn } from "@multica/ui/lib/utils"; import { LocaleLink } from "@/components/locale-link"; import { CoachMark, DemoFrame, useDemoCopy, useStartWhenVisible } from "./demo-kit"; diff --git a/apps/docs/components/demos/usage-demo.tsx b/apps/docs/components/demos/usage-demo.tsx index 9e5828e89..15b28bbde 100644 --- a/apps/docs/components/demos/usage-demo.tsx +++ b/apps/docs/components/demos/usage-demo.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useState, type CSSProperties } from "react"; -import { BarChart3, CalendarDays, ChevronDown, FolderKanban, RefreshCw } from "lucide-react"; +import { BarChart3, CalendarDays, ChevronDown, FolderKanban, RefreshCw } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { cn } from "@multica/ui/lib/utils"; import { diff --git a/apps/docs/components/demos/wakeup-demo.tsx b/apps/docs/components/demos/wakeup-demo.tsx index 12b7235b6..25cbda672 100644 --- a/apps/docs/components/demos/wakeup-demo.tsx +++ b/apps/docs/components/demos/wakeup-demo.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useState, type ReactNode } from "react"; -import { Bell, ChevronDown, ChevronRight, Clock3, FastForward, Info, Plus, RefreshCw } from "lucide-react"; +import { Bell, ChevronDown, ChevronRight, Clock3, FastForward, Info, Plus, RefreshCw } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { cn } from "@multica/ui/lib/utils"; import { diff --git a/apps/docs/components/demos/workflow-demo.tsx b/apps/docs/components/demos/workflow-demo.tsx index bfde956d8..f94f2e7c7 100644 --- a/apps/docs/components/demos/workflow-demo.tsx +++ b/apps/docs/components/demos/workflow-demo.tsx @@ -1,7 +1,7 @@ "use client"; import { useRef, useState } from "react"; -import { ArrowRight, ChevronDown, ChevronRight, CornerDownRight, X } from "lucide-react"; +import { ArrowRight, ChevronDown, ChevronRight, CornerDownRight, X } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { cn } from "@multica/ui/lib/utils"; import { diff --git a/apps/docs/components/docs-settings.tsx b/apps/docs/components/docs-settings.tsx index 40df390a4..3f523bd1d 100644 --- a/apps/docs/components/docs-settings.tsx +++ b/apps/docs/components/docs-settings.tsx @@ -1,6 +1,6 @@ "use client"; -import { Monitor, Moon, Sun } from "lucide-react"; +import { Monitor, Moon, Sun } from "@multica/ui/icons"; import { useTheme } from "next-themes"; import { usePathname, useRouter } from "next/navigation"; import { useEffect, useState, type ReactNode } from "react"; diff --git a/apps/docs/components/video-embed.tsx b/apps/docs/components/video-embed.tsx index 954433dc2..b31533885 100644 --- a/apps/docs/components/video-embed.tsx +++ b/apps/docs/components/video-embed.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { Play } from "lucide-react"; +import { Play } from "@multica/ui/icons"; /** * VideoEmbed — provider-agnostic, click-to-load video embed for docs MDX. diff --git a/apps/docs/package.json b/apps/docs/package.json index 1d899f5c3..e84e43f50 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -17,7 +17,6 @@ "fumadocs-core": "^16.17.8", "fumadocs-mdx": "^15.4.10", "fumadocs-ui": "^16.17.8", - "lucide-react": "catalog:", "mermaid": "^11.14.0", "next": "^16.3.8", "next-themes": "^0.4.6", diff --git a/apps/ui-lab/package.json b/apps/ui-lab/package.json index 52eeae456..fdf0048c1 100644 --- a/apps/ui-lab/package.json +++ b/apps/ui-lab/package.json @@ -19,7 +19,6 @@ "@tanstack/react-query": "catalog:", "colorjs.io": "^0.7.1", "i18next": "catalog:", - "lucide-react": "catalog:", "react": "catalog:", "react-colorful": "^5.8.1", "react-dom": "catalog:", diff --git a/apps/ui-lab/src/app.tsx b/apps/ui-lab/src/app.tsx index b09854efb..72827c1ed 100644 --- a/apps/ui-lab/src/app.tsx +++ b/apps/ui-lab/src/app.tsx @@ -30,7 +30,7 @@ import { Trash2, Undo2, X, -} from "lucide-react"; +} from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { MulticaIcon } from "@multica/ui/components/common/multica-icon"; import { Input } from "@multica/ui/components/ui/input"; diff --git a/apps/ui-lab/src/button-scene.tsx b/apps/ui-lab/src/button-scene.tsx index 5909271d9..46cff3891 100644 --- a/apps/ui-lab/src/button-scene.tsx +++ b/apps/ui-lab/src/button-scene.tsx @@ -8,7 +8,7 @@ import { Loader2, Plus, Send, -} from "lucide-react"; +} from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { Input } from "@multica/ui/components/ui/input"; import { diff --git a/apps/ui-lab/src/catalog-content.tsx b/apps/ui-lab/src/catalog-content.tsx index 28b6bc526..4d9b268ac 100644 --- a/apps/ui-lab/src/catalog-content.tsx +++ b/apps/ui-lab/src/catalog-content.tsx @@ -1,6 +1,6 @@ import type { ReactNode } from "react"; import { useTranslation } from "react-i18next"; -import { ArrowRight, CircleDashed, RotateCcw } from "lucide-react"; +import { ArrowRight, CircleDashed, RotateCcw } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { catalog, diff --git a/apps/ui-lab/src/catalog-navigation.tsx b/apps/ui-lab/src/catalog-navigation.tsx index e157ba7e9..653f45d83 100644 --- a/apps/ui-lab/src/catalog-navigation.tsx +++ b/apps/ui-lab/src/catalog-navigation.tsx @@ -9,7 +9,7 @@ import { History, LayoutDashboard, Palette, -} from "lucide-react"; +} from "@multica/ui/icons"; import { catalog, availableCount, diff --git a/apps/ui-lab/src/color-editor.tsx b/apps/ui-lab/src/color-editor.tsx index 62040f10b..1b99ea664 100644 --- a/apps/ui-lab/src/color-editor.tsx +++ b/apps/ui-lab/src/color-editor.tsx @@ -1,7 +1,7 @@ import { useTranslation } from "react-i18next"; import { useEffect, useId, useRef, useState } from "react"; import { HexColorPicker } from "react-colorful"; -import { Check, ChevronDown, Copy, RotateCcw, Search } from "lucide-react"; +import { Check, ChevronDown, Copy, RotateCcw, Search } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { Input } from "@multica/ui/components/ui/input"; import { diff --git a/apps/ui-lab/src/inspector.tsx b/apps/ui-lab/src/inspector.tsx index 08e824f4c..0402b8dc3 100644 --- a/apps/ui-lab/src/inspector.tsx +++ b/apps/ui-lab/src/inspector.tsx @@ -7,7 +7,7 @@ import { Component, RotateCcw, X, -} from "lucide-react"; +} from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { Popover, diff --git a/apps/ui-lab/src/number-field.tsx b/apps/ui-lab/src/number-field.tsx index ffc0cdcde..fd8a35043 100644 --- a/apps/ui-lab/src/number-field.tsx +++ b/apps/ui-lab/src/number-field.tsx @@ -1,6 +1,6 @@ import { useTranslation } from "react-i18next"; import { useEffect, useId, useRef, useState } from "react"; -import { RotateCcw } from "lucide-react"; +import { RotateCcw } from "@multica/ui/icons"; export function NumberField({ label, diff --git a/apps/ui-lab/src/preview.tsx b/apps/ui-lab/src/preview.tsx index 6fa6438c4..15381603e 100644 --- a/apps/ui-lab/src/preview.tsx +++ b/apps/ui-lab/src/preview.tsx @@ -1,7 +1,7 @@ import { LabI18nProvider } from "./lab-i18n"; import { useTranslation } from "react-i18next"; import { useEffect, useState, type ReactNode } from "react"; -import { ArrowUpRight, Check, Inbox, Plus } from "lucide-react"; +import { ArrowUpRight, Check, Inbox, Plus } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { Badge } from "@multica/ui/components/ui/badge"; import { Input } from "@multica/ui/components/ui/input"; diff --git a/apps/ui-lab/src/token-changes.tsx b/apps/ui-lab/src/token-changes.tsx index 2898a3966..6264ebe0c 100644 --- a/apps/ui-lab/src/token-changes.tsx +++ b/apps/ui-lab/src/token-changes.tsx @@ -1,5 +1,5 @@ import { useTranslation } from "react-i18next"; -import { Check, RotateCcw } from "lucide-react"; +import { Check, RotateCcw } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { baseline, diff --git a/apps/web/app/(auth)/login/page.tsx b/apps/web/app/(auth)/login/page.tsx index 2702da0a0..57820a276 100644 --- a/apps/web/app/(auth)/login/page.tsx +++ b/apps/web/app/(auth)/login/page.tsx @@ -24,7 +24,7 @@ import { CardContent, } from "@multica/ui/components/ui/card"; import { Button } from "@multica/ui/components/ui/button"; -import { Loader2 } from "lucide-react"; +import { Loader2 } from "@multica/ui/icons"; import { setLoggedInCookie } from "@/features/auth/auth-cookie"; import Link from "next/link"; import { LoginPage, validateCliCallback } from "@multica/views/auth"; diff --git a/apps/web/app/auth/callback/page.tsx b/apps/web/app/auth/callback/page.tsx index d693990a8..bdbd8f779 100644 --- a/apps/web/app/auth/callback/page.tsx +++ b/apps/web/app/auth/callback/page.tsx @@ -18,7 +18,7 @@ import { } from "@multica/ui/components/ui/card"; import { Button } from "@multica/ui/components/ui/button"; import { useT } from "@multica/views/i18n"; -import { Loader2 } from "lucide-react"; +import { Loader2 } from "@multica/ui/icons"; import { callbackErrorFrom, type CallbackError } from "./callback-error"; const authLogger = createLogger("auth.callback"); diff --git a/apps/web/app/globals.css b/apps/web/app/globals.css index f37baa00f..11b9eda17 100644 --- a/apps/web/app/globals.css +++ b/apps/web/app/globals.css @@ -44,6 +44,17 @@ html[lang|="ja"] { "Noto Sans CJK KR", sans-serif; } +/* Traditional Chinese: the default stack is Simplified-first, which hands zh-TW + users Simplified glyph shapes for every ideograph the two share a code point + for. Promote the Traditional families for that locale only (layout.tsx emits + `zh-TW` for zh-Hant). Kept in sync with the desktop stack. */ +html[lang="zh-TW"] { + --font-sans: var(--font-inter), -apple-system, BlinkMacSystemFont, "Segoe UI", + "PingFang TC", "Microsoft JhengHei", "Noto Sans CJK TC", "PingFang SC", + "Microsoft YaHei", "Noto Sans CJK SC", "Apple SD Gothic Neo", "Malgun Gothic", + "Noto Sans CJK KR", sans-serif; +} + /* The landing tree overrides `--font-serif` with its own Instrument Serif + per-locale CJK chain, built on the same structure; see "Landing editorial serif" in ./custom.css and keep the two CJK orderings in sync. */ diff --git a/apps/web/app/layout.tsx b/apps/web/app/layout.tsx index 24cb73720..feabf87be 100644 --- a/apps/web/app/layout.tsx +++ b/apps/web/app/layout.tsx @@ -32,10 +32,16 @@ import "./globals.css"; // italic face the ~20 semantic italic labels (chat empty states, model-picker's // "Managed by runtime", dashboard/squad placeholders) plus every markdown and // blockquote rendered as browser-synthesized oblique. Keep in sync with desktop's -// `@fontsource-variable/inter/wght-italic.css` import. +// `@fontsource-variable/inter/opsz-italic.css` import. +// +// The `opsz` axis lets Inter draw each size with its own cut: 14px and below +// keep the open text design, while titles and headings get Inter Display's +// tighter spacing and finer details automatically (`font-optical-sizing: auto` +// is the CSS default). Keep in sync with desktop's `opsz.css` import. const inter = Inter({ subsets: ["latin"], style: ["normal", "italic"], + axes: ["opsz"], variable: "--font-inter", }); // Mono font has no explicit CJK fallback: CJK chars in code blocks are inherently diff --git a/apps/web/features/landing/components/download/cli-section.tsx b/apps/web/features/landing/components/download/cli-section.tsx index 1251460db..7eb0bd021 100644 --- a/apps/web/features/landing/components/download/cli-section.tsx +++ b/apps/web/features/landing/components/download/cli-section.tsx @@ -1,7 +1,7 @@ "use client"; import { useState, type ReactNode } from "react"; -import { Check, Copy, Terminal } from "lucide-react"; +import { Check, Copy, Terminal } from "@multica/ui/icons"; import { CliInstallCommand } from "@multica/views/common/cli-install-command"; import { copyText } from "@multica/ui/lib/clipboard"; import { useLocale } from "../../i18n"; diff --git a/apps/web/features/landing/components/download/hero.tsx b/apps/web/features/landing/components/download/hero.tsx index 13028684b..c920edbeb 100644 --- a/apps/web/features/landing/components/download/hero.tsx +++ b/apps/web/features/landing/components/download/hero.tsx @@ -1,5 +1,5 @@ import Link from "next/link"; -import { ArrowRight, Download } from "lucide-react"; +import { ArrowRight, Download } from "@multica/ui/icons"; import { useLocale } from "../../i18n"; import type { DetectResult } from "../../utils/os-detect"; import type { DownloadAssets } from "../../utils/parse-release-assets"; diff --git a/apps/web/features/landing/components/features-section.tsx b/apps/web/features/landing/components/features-section.tsx index f12b7b930..1b53e221c 100644 --- a/apps/web/features/landing/components/features-section.tsx +++ b/apps/web/features/landing/components/features-section.tsx @@ -17,7 +17,7 @@ import { Monitor, Sparkles, UserMinus, -} from "lucide-react"; +} from "@multica/ui/icons"; import { cn } from "@multica/ui/lib/utils"; import { ImageIcon } from "./shared"; import { useLocale } from "../i18n"; diff --git a/apps/web/features/landing/components/landing-header.tsx b/apps/web/features/landing/components/landing-header.tsx index 74ac4436b..2aa7eacb6 100644 --- a/apps/web/features/landing/components/landing-header.tsx +++ b/apps/web/features/landing/components/landing-header.tsx @@ -2,7 +2,7 @@ import { useState } from "react"; import Link from "next/link"; -import { Menu, X } from "lucide-react"; +import { Menu, X } from "@multica/ui/icons"; import { MulticaIcon } from "@multica/ui/components/common/multica-icon"; import { cn } from "@multica/ui/lib/utils"; import { useAuthStore } from "@multica/core/auth"; diff --git a/apps/web/features/landing/components/landing-hero.tsx b/apps/web/features/landing/components/landing-hero.tsx index 31839a157..44edf11f1 100644 --- a/apps/web/features/landing/components/landing-hero.tsx +++ b/apps/web/features/landing/components/landing-hero.tsx @@ -2,7 +2,7 @@ import Image from "next/image"; import Link from "next/link"; -import { ArrowRight, Download } from "lucide-react"; +import { ArrowRight, Download } from "@multica/ui/icons"; import { useAuthStore } from "@multica/core/auth"; import { docsHrefForLocale, useLocale } from "../i18n"; import { useDashboardCtaHref } from "../utils/use-dashboard-cta"; diff --git a/apps/web/package.json b/apps/web/package.json index 7353c4718..12d3fb385 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -21,7 +21,6 @@ "dotenv": "^17.4.1", "fumadocs-core": "^15.5.2", "fumadocs-mdx": "^12.0.3", - "lucide-react": "catalog:", "next": "^16.3.8", "react": "catalog:", "react-dom": "catalog:", diff --git a/e2e/comments.spec.ts b/e2e/comments.spec.ts index 084cbeec8..96e3adbcd 100644 --- a/e2e/comments.spec.ts +++ b/e2e/comments.spec.ts @@ -64,7 +64,7 @@ test.describe("Comments", () => { const shell = page.getByTestId("comment-composer-shell"); await expect(shell).toBeVisible(); const composer = shell.locator("xpath=ancestor::div[contains(@class, 'rounded-lg')][1]"); - const submitBtn = composer.locator("button:has(svg.lucide-arrow-up)").last(); + const submitBtn = composer.locator("button:has(svg.icon-arrow-up)").last(); await expect(submitBtn).toBeDisabled(); }); }); diff --git a/e2e/perf/floating-chat-lifetime.spec.ts b/e2e/perf/floating-chat-lifetime.spec.ts index d63c54654..80880f057 100644 --- a/e2e/perf/floating-chat-lifetime.spec.ts +++ b/e2e/perf/floating-chat-lifetime.spec.ts @@ -159,7 +159,7 @@ test("closing floating chat releases its list and preserves the live composer", element.dispatchEvent(new ClipboardEvent("paste", { bubbles: true, cancelable: true, clipboardData: files })); }); await expect.poll(() => uploadStarted).toBe(true); - await shell.locator('button:has(svg.lucide-minus)').evaluate(button => (button as HTMLButtonElement).click()); + await shell.locator('button:has(svg.icon-minus)').evaluate(button => (button as HTMLButtonElement).click()); await expect(page.locator('[data-tab-scroll-root]').filter({ hasText: "Latest fixture message" })).toHaveCount(0); expect(await composer?.evaluate(element => element.isConnected)).toBe(true); expect(await composer?.textContent()).toContain("Last edit before closing"); @@ -186,7 +186,7 @@ test("closing floating chat releases its list and preserves the live composer", await expect(reopened).toHaveCSS("transform", "none"); // Reopening inside the exit animation must cancel removal of the same list. - await reopened.locator('button:has(svg.lucide-minus)').evaluate(button => (button as HTMLButtonElement).click()); + await reopened.locator('button:has(svg.icon-minus)').evaluate(button => (button as HTMLButtonElement).click()); await page.getByRole("button", { name: "Multica is working...", exact: true }).evaluate(button => (button as HTMLButtonElement).click()); // Let the interrupted 150ms exit finish before checking that it cannot remove the reopened list. await page.waitForTimeout(250); diff --git a/packages/core/paths/route-icons.ts b/packages/core/paths/route-icons.ts index c113e2490..814d247b0 100644 --- a/packages/core/paths/route-icons.ts +++ b/packages/core/paths/route-icons.ts @@ -14,7 +14,7 @@ * Icon values are *names*, not React components, so this module stays * React-free and safe inside `@multica/core`. The name → component registry * lives in `packages/views/layout/route-icon-components.tsx`; its - * `Record` type makes a missing component a compile + * `Record` type makes a missing component a compile * error. */ diff --git a/packages/core/paths/tab-presentation.ts b/packages/core/paths/tab-presentation.ts index 7401b3067..9024842d4 100644 --- a/packages/core/paths/tab-presentation.ts +++ b/packages/core/paths/tab-presentation.ts @@ -27,7 +27,7 @@ import type { TabActorType, TabSubject } from "./tab-subject"; /** The leading visual a tab should render. */ export type TabVisual = - /** A static Lucide icon (page icon or resourceless type icon). */ + /** A static route icon (page icon or resourceless type icon). */ | { kind: "icon"; icon: RouteIconName } /** An issue's live status glyph. `null` while the issue is loading. * `category` is what selects the glyph — carried here so the tab strip diff --git a/packages/core/paths/tab-subject.ts b/packages/core/paths/tab-subject.ts index 3837b0806..93cf6f5af 100644 --- a/packages/core/paths/tab-subject.ts +++ b/packages/core/paths/tab-subject.ts @@ -5,7 +5,7 @@ * resource, a container with a selected item, a creation flow, or something * unrecognized — is what decides how it should look (icon + title). This module * turns a URL into that semantic {@link TabSubject}. It is pure: no React, no - * Lucide, no query — only URL parsing. The visual/title mapping lives in + * icons, no query — only URL parsing. The visual/title mapping lives in * `tab-presentation.ts`; the React glue lives in `@multica/views`. * * Workspace URLs are `/{slug}/{segment}/...`. The slug is index 0, the route diff --git a/packages/eslint-config/base.js b/packages/eslint-config/base.js index 99aa188a1..59fb66a34 100644 --- a/packages/eslint-config/base.js +++ b/packages/eslint-config/base.js @@ -2,6 +2,28 @@ import eslint from "@eslint/js"; import tseslint from "typescript-eslint"; import importPlugin from "eslint-plugin-import-x"; +// Multica draws its own icons: every glyph comes from @multica/ui/icons, and a +// missing one is drawn in packages/ui/icons/drawings. The pattern covers each +// library's root and its subpaths (`react-icons/fa`, `@heroicons/react/24/outline`). +// Exported because flat config replaces a rule's options wholesale: a package +// that sets its own `no-restricted-imports` must include these patterns again. +export const ICON_LIBRARIES = [ + "lucide-react", + "react-icons", + "@heroicons/react", + "@tabler/icons-react", + "@radix-ui/react-icons", + "@phosphor-icons/react", +]; +const escape = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); +export const ICON_LIBRARY_IMPORT_PATTERNS = [ + { + regex: `^(${ICON_LIBRARIES.map(escape).join("|")})(/.*)?$`, + message: + "Import icons from @multica/ui/icons; draw a missing one in packages/ui/icons/drawings (see .agents/skills/multica-icons).", + }, +]; + /** @type {import("eslint").Linter.Config[]} */ export default [ eslint.configs.recommended, @@ -32,6 +54,9 @@ export default [ ], peerDependencies: true, }], + "no-restricted-imports": ["error", { + patterns: ICON_LIBRARY_IMPORT_PATTERNS, + }], }, }, { diff --git a/packages/eslint-config/icon-imports.test.js b/packages/eslint-config/icon-imports.test.js new file mode 100644 index 000000000..7f25cbcfe --- /dev/null +++ b/packages/eslint-config/icon-imports.test.js @@ -0,0 +1,39 @@ +import assert from "node:assert/strict"; +import { test } from "node:test"; +import { fileURLToPath } from "node:url"; +import { ESLint } from "eslint"; +import base from "./base.js"; + +const BANNED = [ + "lucide-react", + "react-icons/fa", + "@heroicons/react/24/outline", + "@tabler/icons-react", + "@radix-ui/react-icons", + "@phosphor-icons/react/dist/ssr", +]; +const ALLOWED = ["@multica/ui/icons", "react-icons-extra", "@radix-ui/react-dialog", "@heroicons/reactive"]; + +async function restricted(eslint, filePath, source) { + const [result] = await eslint.lintText(`import { X } from "${source}";\nexport { X };\n`, { filePath }); + return result.messages.filter((m) => m.ruleId === "no-restricted-imports").length; +} + +const targets = [ + ["base config", new ESLint({ overrideConfigFile: true, overrideConfig: base }), "src/icon.ts"], + [ + "desktop renderer config", + new ESLint({ cwd: fileURLToPath(new URL("../../apps/desktop", import.meta.url)) }), + "src/renderer/src/icon.tsx", + ], +]; + +for (const [label, eslint, filePath] of targets) { + test(`${label} bans icon libraries and their subpaths`, async () => { + for (const source of BANNED) assert.equal(await restricted(eslint, filePath, source), 1, source); + }); + + test(`${label} allows @multica/ui/icons and look-alike packages`, async () => { + for (const source of ALLOWED) assert.equal(await restricted(eslint, filePath, source), 0, source); + }); +} diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json index dd7e59df1..47b9e056e 100644 --- a/packages/eslint-config/package.json +++ b/packages/eslint-config/package.json @@ -3,6 +3,9 @@ "version": "0.0.0", "private": true, "type": "module", + "scripts": { + "test": "node --test" + }, "exports": { "./base": "./base.js", "./react": "./react.js", diff --git a/packages/ui/components/common/actor-avatar.tsx b/packages/ui/components/common/actor-avatar.tsx index 90d76ae50..b2da55499 100644 --- a/packages/ui/components/common/actor-avatar.tsx +++ b/packages/ui/components/common/actor-avatar.tsx @@ -1,7 +1,7 @@ "use client"; import { useState, useEffect } from "react"; -import { Bot, Users } from "lucide-react"; +import { Bot, Users } from "@multica/ui/icons"; import { cn } from "@multica/ui/lib/utils"; import { AVATAR_SIZE_PX, diff --git a/packages/ui/components/common/capability-banner.tsx b/packages/ui/components/common/capability-banner.tsx index 42291efac..f21a08a4b 100644 --- a/packages/ui/components/common/capability-banner.tsx +++ b/packages/ui/components/common/capability-banner.tsx @@ -1,4 +1,4 @@ -import { Lock } from "lucide-react"; +import { Lock } from "@multica/ui/icons"; import { cn } from "@multica/ui/lib/utils"; type Resource = "agent" | "skill" | "comment" | "runtime" | "workspace"; diff --git a/packages/ui/components/common/file-upload-button.tsx b/packages/ui/components/common/file-upload-button.tsx index 170f3fc33..247551e92 100644 --- a/packages/ui/components/common/file-upload-button.tsx +++ b/packages/ui/components/common/file-upload-button.tsx @@ -1,7 +1,7 @@ "use client"; import { useRef } from "react"; -import { Paperclip } from "lucide-react"; +import { Paperclip } from "@multica/ui/icons"; import { useTranslation } from "react-i18next"; import { IconButton } from "@multica/ui/components/common/icon-button"; import { cn } from "@multica/ui/lib/utils"; diff --git a/packages/ui/components/common/quick-emoji-picker.tsx b/packages/ui/components/common/quick-emoji-picker.tsx index 3b03f02ed..20fe23e70 100644 --- a/packages/ui/components/common/quick-emoji-picker.tsx +++ b/packages/ui/components/common/quick-emoji-picker.tsx @@ -1,7 +1,7 @@ "use client"; import { useState, lazy, Suspense } from "react"; -import { SmilePlus } from "lucide-react"; +import { SmilePlus } from "@multica/ui/icons"; import { cn } from "@multica/ui/lib/utils"; import { Popover, PopoverTrigger, PopoverContent } from "@multica/ui/components/ui/popover"; import { DeferredTooltip } from "./deferred-tooltip"; diff --git a/packages/ui/components/common/submit-button.tsx b/packages/ui/components/common/submit-button.tsx index 44573ea17..1f7d284a9 100644 --- a/packages/ui/components/common/submit-button.tsx +++ b/packages/ui/components/common/submit-button.tsx @@ -1,7 +1,7 @@ "use client"; import type { ReactNode, SyntheticEvent } from "react"; -import { ArrowUp, Loader2, Square } from "lucide-react"; +import { ArrowUp, Loader2, Square } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { Tooltip, diff --git a/packages/ui/components/ui/button.tsx b/packages/ui/components/ui/button.tsx index 62251611e..2e280d144 100644 --- a/packages/ui/components/ui/button.tsx +++ b/packages/ui/components/ui/button.tsx @@ -6,7 +6,7 @@ import { cva, type VariantProps } from "class-variance-authority" import { cn } from "@multica/ui/lib/utils" const buttonVariants = cva( - "group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-body font-medium whitespace-nowrap transition-[color,background-color,border-color,box-shadow,transform] outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", + "group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-body font-medium whitespace-nowrap transition-[color,background-color,border-color,box-shadow,transform] outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4.5", { variants: { variant: { @@ -45,8 +45,8 @@ const buttonVariants = cva( size: { default: "h-[var(--button-height-default)] gap-[var(--button-gap-default)] px-[var(--button-padding-default)] has-data-[icon=inline-end]:pr-[max(0px,calc(var(--button-padding-default)-0.125rem))] has-data-[icon=inline-start]:pl-[max(0px,calc(var(--button-padding-default)-0.125rem))]", - xs: "h-[var(--button-height-xs)] gap-[var(--button-gap-xs)] rounded-md px-[var(--button-padding-xs)] text-caption in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-[max(0px,calc(var(--button-padding-xs)-0.125rem))] has-data-[icon=inline-start]:pl-[max(0px,calc(var(--button-padding-xs)-0.125rem))] [&_svg:not([class*='size-'])]:size-3", - sm: "h-[var(--button-height-sm)] gap-[var(--button-gap-sm)] rounded-md px-[var(--button-padding-sm)] text-label in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-[max(0px,calc(var(--button-padding-sm)-0.25rem))] has-data-[icon=inline-start]:pl-[max(0px,calc(var(--button-padding-sm)-0.25rem))] [&_svg:not([class*='size-'])]:size-3.5", + xs: "h-[var(--button-height-xs)] gap-[var(--button-gap-xs)] rounded-md px-[var(--button-padding-xs)] text-caption in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-[max(0px,calc(var(--button-padding-xs)-0.125rem))] has-data-[icon=inline-start]:pl-[max(0px,calc(var(--button-padding-xs)-0.125rem))] [&_svg:not([class*='size-'])]:size-3.5", + sm: "h-[var(--button-height-sm)] gap-[var(--button-gap-sm)] rounded-md px-[var(--button-padding-sm)] text-label in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-[max(0px,calc(var(--button-padding-sm)-0.25rem))] has-data-[icon=inline-start]:pl-[max(0px,calc(var(--button-padding-sm)-0.25rem))] [&_svg:not([class*='size-'])]:size-4", lg: "h-[var(--button-height-lg)] gap-[var(--button-gap-lg)] px-[var(--button-padding-lg)] has-data-[icon=inline-end]:pr-[calc(var(--button-padding-lg)+0.125rem)] has-data-[icon=inline-start]:pl-[calc(var(--button-padding-lg)+0.125rem)]", icon: "size-[var(--button-height-default)]", "icon-xs": diff --git a/packages/ui/components/ui/calendar.tsx b/packages/ui/components/ui/calendar.tsx index 97bf0ff88..e089caec5 100644 --- a/packages/ui/components/ui/calendar.tsx +++ b/packages/ui/components/ui/calendar.tsx @@ -10,7 +10,7 @@ import { import { cn } from "@multica/ui/lib/utils" import { Button, buttonVariants } from "@multica/ui/components/ui/button" -import { ChevronLeftIcon, ChevronRightIcon, ChevronDownIcon } from "lucide-react" +import { ChevronLeftIcon, ChevronRightIcon, ChevronDownIcon } from "@multica/ui/icons" function Calendar({ className, diff --git a/packages/ui/components/ui/checkbox.tsx b/packages/ui/components/ui/checkbox.tsx index ffcf29693..2ebca04fb 100644 --- a/packages/ui/components/ui/checkbox.tsx +++ b/packages/ui/components/ui/checkbox.tsx @@ -3,7 +3,7 @@ import { Checkbox as CheckboxPrimitive } from "@base-ui/react/checkbox" import { cn } from "@multica/ui/lib/utils" -import { CheckIcon, MinusIcon } from "lucide-react" +import { CheckIcon, MinusIcon } from "@multica/ui/icons" function Checkbox({ className, indeterminate, ...props }: CheckboxPrimitive.Root.Props) { return ( diff --git a/packages/ui/components/ui/command.tsx b/packages/ui/components/ui/command.tsx index 99d5e6e58..e1a4242f8 100644 --- a/packages/ui/components/ui/command.tsx +++ b/packages/ui/components/ui/command.tsx @@ -15,7 +15,7 @@ import { InputGroup, InputGroupAddon, } from "@multica/ui/components/ui/input-group" -import { SearchIcon, CheckIcon } from "lucide-react" +import { SearchIcon, CheckIcon } from "@multica/ui/icons" function Command({ className, @@ -165,7 +165,7 @@ function CommandItem({ @@ -54,7 +54,7 @@ function ContextMenuContent({ > @@ -80,7 +80,7 @@ function ContextMenuLabel({ data-slot="context-menu-label" data-inset={inset} className={cn( - "px-1.5 py-1 text-caption font-medium text-muted-foreground data-inset:pl-7", + "px-2 py-1 text-caption font-medium text-muted-foreground data-inset:pl-9", className )} {...props} @@ -103,7 +103,7 @@ function ContextMenuItem({ data-inset={inset} data-variant={variant} className={cn( - "group/context-menu-item relative flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-body outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-7 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", + "group/context-menu-item relative flex cursor-default items-center gap-2.5 rounded-lg px-2 py-1.25 text-body-lg outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-9 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4.5", className )} {...props} @@ -130,7 +130,7 @@ function ContextMenuSubTrigger({ data-slot="context-menu-sub-trigger" data-inset={inset} className={cn( - "flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-body outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-7 data-open:bg-accent data-open:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", + "flex cursor-default items-center gap-2.5 rounded-lg px-2 py-1.25 text-body-lg outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-9 data-open:bg-accent data-open:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4.5", className )} {...props} @@ -167,7 +167,7 @@ function ContextMenuCheckboxItem({ data-slot="context-menu-checkbox-item" data-inset={inset} className={cn( - "relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-body outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", + "relative flex cursor-default items-center gap-2.5 rounded-lg py-1.25 pr-8 pl-2 text-body-lg outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-9 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4.5", className )} checked={checked} @@ -208,7 +208,7 @@ function ContextMenuRadioItem({ data-slot="context-menu-radio-item" data-inset={inset} className={cn( - "relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-body outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", + "relative flex cursor-default items-center gap-2.5 rounded-lg py-1.25 pr-8 pl-2 text-body-lg outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-9 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4.5", className )} {...props} @@ -231,7 +231,7 @@ function ContextMenuSeparator({ return ( ) diff --git a/packages/ui/components/ui/dialog.tsx b/packages/ui/components/ui/dialog.tsx index a07a3af7f..ff93dc000 100644 --- a/packages/ui/components/ui/dialog.tsx +++ b/packages/ui/components/ui/dialog.tsx @@ -5,7 +5,7 @@ import { Dialog as DialogPrimitive } from "@base-ui/react/dialog" import { cn } from "@multica/ui/lib/utils" import { Button } from "@multica/ui/components/ui/button" -import { XIcon } from "lucide-react" +import { XIcon } from "@multica/ui/icons" function Dialog({ ...props }: DialogPrimitive.Root.Props) { return diff --git a/packages/ui/components/ui/dropdown-menu.tsx b/packages/ui/components/ui/dropdown-menu.tsx index 02d135cf8..73f1f8e66 100644 --- a/packages/ui/components/ui/dropdown-menu.tsx +++ b/packages/ui/components/ui/dropdown-menu.tsx @@ -4,7 +4,7 @@ import * as React from "react" import { Menu as MenuPrimitive } from "@base-ui/react/menu" import { cn } from "@multica/ui/lib/utils" -import { ChevronRightIcon, CheckIcon } from "lucide-react" +import { ChevronRightIcon, CheckIcon } from "@multica/ui/icons" function DropdownMenu({ ...props }: MenuPrimitive.Root.Props) { return @@ -53,7 +53,7 @@ function DropdownMenuContent({ e.stopPropagation() onClick?.(e) }} - className={cn("z-50 max-h-(--available-height) min-w-32 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-surface-raised p-1 text-popover-foreground shadow-[var(--menu-shadow)] ring-1 ring-surface-border duration-100 outline-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:overflow-hidden data-closed:fade-out-0 data-closed:zoom-out-95", className )} + className={cn("z-50 max-h-(--available-height) min-w-32 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-xl bg-surface-raised p-1.5 text-popover-foreground shadow-[var(--menu-shadow)] ring-1 ring-surface-border duration-100 outline-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:overflow-hidden data-closed:fade-out-0 data-closed:zoom-out-95", className )} {...props} /> @@ -77,7 +77,7 @@ function DropdownMenuLabel({ data-slot="dropdown-menu-label" data-inset={inset} className={cn( - "px-1.5 py-1 text-caption font-medium text-muted-foreground data-inset:pl-7", + "px-2 py-1 text-caption font-medium text-muted-foreground data-inset:pl-9", className )} {...props} @@ -100,7 +100,7 @@ function DropdownMenuItem({ data-inset={inset} data-variant={variant} className={cn( - "group/dropdown-menu-item relative flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-body outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-7 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", + "group/dropdown-menu-item relative flex cursor-default items-center gap-2.5 rounded-lg px-2 py-1.25 text-body-lg outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-9 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4.5", className )} {...props} @@ -125,7 +125,7 @@ function DropdownMenuSubTrigger({ data-slot="dropdown-menu-sub-trigger" data-inset={inset} className={cn( - "flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-body outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-7 data-popup-open:bg-accent data-popup-open:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", + "flex cursor-default items-center gap-2.5 rounded-lg px-2 py-1.25 text-body-lg outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-9 data-popup-open:bg-accent data-popup-open:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4.5", className )} {...props} @@ -147,7 +147,7 @@ function DropdownMenuSubContent({ return ( ) diff --git a/packages/ui/components/ui/input-otp.tsx b/packages/ui/components/ui/input-otp.tsx index c6b082acb..15f68136f 100644 --- a/packages/ui/components/ui/input-otp.tsx +++ b/packages/ui/components/ui/input-otp.tsx @@ -4,7 +4,7 @@ import * as React from "react" import { OTPInput, OTPInputContext } from "input-otp" import { cn } from "@multica/ui/lib/utils" -import { MinusIcon } from "lucide-react" +import { MinusIcon } from "@multica/ui/icons" function InputOTP({ className, diff --git a/packages/ui/components/ui/list-grid.tsx b/packages/ui/components/ui/list-grid.tsx index 84553e69a..6c8db867d 100644 --- a/packages/ui/components/ui/list-grid.tsx +++ b/packages/ui/components/ui/list-grid.tsx @@ -1,6 +1,6 @@ "use client"; -import { ArrowDown, ArrowUp } from "lucide-react"; +import { ArrowDown, ArrowUp } from "@multica/ui/icons"; import { cn } from "../../lib/utils"; diff --git a/packages/ui/components/ui/select.tsx b/packages/ui/components/ui/select.tsx index 63d3c0ecf..4c2df3b36 100644 --- a/packages/ui/components/ui/select.tsx +++ b/packages/ui/components/ui/select.tsx @@ -4,7 +4,7 @@ import * as React from "react" import { Select as SelectPrimitive } from "@base-ui/react/select" import { cn } from "@multica/ui/lib/utils" -import { ChevronDownIcon, CheckIcon, ChevronUpIcon } from "lucide-react" +import { ChevronDownIcon, CheckIcon, ChevronUpIcon } from "@multica/ui/icons" type SelectProps< Value, @@ -56,7 +56,7 @@ function SelectTrigger({ data-slot="select-trigger" data-size={size} className={cn( - "flex w-fit items-center justify-between gap-1.5 rounded-lg border border-input bg-transparent py-2 pr-2 pl-2.5 text-body whitespace-nowrap transition-colors outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-placeholder:text-muted-foreground data-[size=default]:h-8 data-[size=sm]:h-7 data-[size=sm]:rounded-md *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", + "flex w-fit items-center justify-between gap-1.5 rounded-lg border border-input bg-transparent py-2 pr-2 pl-2.5 text-body whitespace-nowrap transition-colors outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-placeholder:text-muted-foreground data-[size=default]:h-8 data-[size=sm]:h-7 data-[size=sm]:rounded-md *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4.5", className )} {...props} @@ -132,7 +132,7 @@ function SelectItem({ diff --git a/packages/ui/components/ui/sidebar.tsx b/packages/ui/components/ui/sidebar.tsx index 43c17d03c..e44d154e2 100644 --- a/packages/ui/components/ui/sidebar.tsx +++ b/packages/ui/components/ui/sidebar.tsx @@ -24,7 +24,7 @@ import { TooltipContent, TooltipTrigger, } from "@multica/ui/components/ui/tooltip" -import { PanelLeftIcon } from "lucide-react" +import { PanelLeftIcon } from "@multica/ui/icons" const SIDEBAR_WIDTH_DEFAULT = 256 const SIDEBAR_WIDTH_MIN = 200 @@ -686,7 +686,7 @@ function SidebarGroupLabel({ props: mergeProps<"div">( { className: cn( - "flex h-8 shrink-0 items-center rounded-md px-2 text-caption font-medium text-muted-foreground ring-sidebar-ring outline-hidden transition-[margin,opacity] duration-200 ease-linear group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0 focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0", + "flex h-8 shrink-0 items-center rounded-md px-2 text-caption text-muted-foreground ring-sidebar-ring outline-hidden transition-[margin,opacity] duration-200 ease-linear group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0 focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0", className ), }, @@ -761,7 +761,7 @@ function SidebarMenuItem({ className, ...props }: React.ComponentProps<"li">) { } const sidebarMenuButtonVariants = cva( - "peer/menu-button group/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-body ring-sidebar-ring outline-hidden transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:font-medium data-active:text-sidebar-accent-foreground data-active:hover:bg-sidebar-accent [&_svg]:size-4 [&_svg]:shrink-0 [&>span:last-child]:truncate", + "peer/menu-button group/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-body ring-sidebar-ring outline-hidden transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:font-medium data-active:text-sidebar-accent-foreground data-active:hover:bg-sidebar-accent data-active:[&_svg_.icon-body]:fill-current data-active:[&_svg_.icon-cut]:stroke-sidebar-accent data-active:[&_svg_.icon-cut-fill]:fill-sidebar-accent [&_svg]:size-4.5 [&_svg]:shrink-0 [&>span:last-child]:truncate", { variants: { variant: { @@ -770,7 +770,7 @@ const sidebarMenuButtonVariants = cva( "bg-background shadow-[0_0_0_1px_var(--color-sidebar-border)] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_var(--color-sidebar-accent)]", }, size: { - default: "h-8 text-body", + default: "h-[34px] text-body-lg", sm: "h-7 text-caption", lg: "h-12 text-body group-data-[collapsible=icon]:p-0!", }, @@ -965,7 +965,7 @@ function SidebarMenuSubButton({ props: mergeProps<"a">( { className: cn( - "flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground ring-sidebar-ring outline-hidden group-data-[collapsible=icon]:hidden hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[size=md]:text-body data-[size=sm]:text-caption data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground data-active:hover:bg-sidebar-accent [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground", + "flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground ring-sidebar-ring outline-hidden group-data-[collapsible=icon]:hidden hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[size=md]:text-body data-[size=sm]:text-caption data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground data-active:hover:bg-sidebar-accent [&>span:last-child]:truncate [&>svg]:size-4.5 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground", className ), }, diff --git a/packages/ui/components/ui/sonner.tsx b/packages/ui/components/ui/sonner.tsx index 72daa8600..bdc2dd7c5 100644 --- a/packages/ui/components/ui/sonner.tsx +++ b/packages/ui/components/ui/sonner.tsx @@ -2,7 +2,7 @@ import { useTheme } from "next-themes" import { Toaster as Sonner, type ToasterProps } from "sonner" -import { CircleCheckIcon, InfoIcon, TriangleAlertIcon, OctagonXIcon, Loader2Icon } from "lucide-react" +import { CircleCheckIcon, InfoIcon, TriangleAlertIcon, OctagonXIcon, Loader2Icon } from "@multica/ui/icons" const Toaster = ({ ...props }: ToasterProps) => { // Use `resolvedTheme` (the concrete "light" / "dark" value) instead of diff --git a/packages/ui/components/ui/spinner.tsx b/packages/ui/components/ui/spinner.tsx index 9b6c07075..b988b73b7 100644 --- a/packages/ui/components/ui/spinner.tsx +++ b/packages/ui/components/ui/spinner.tsx @@ -1,5 +1,5 @@ import { cn } from "@multica/ui/lib/utils" -import { Loader2Icon } from "lucide-react" +import { Loader2Icon } from "@multica/ui/icons" function Spinner({ className, ...props }: React.ComponentProps<"svg">) { return ( diff --git a/packages/ui/components/ui/time-input.tsx b/packages/ui/components/ui/time-input.tsx index 3fe44cb7a..730960e8e 100644 --- a/packages/ui/components/ui/time-input.tsx +++ b/packages/ui/components/ui/time-input.tsx @@ -1,7 +1,7 @@ "use client"; import * as React from "react"; -import { Clock } from "lucide-react"; +import { Clock } from "@multica/ui/icons"; import { cn } from "@multica/ui/lib/utils"; diff --git a/packages/ui/eslint.config.mjs b/packages/ui/eslint.config.mjs index 50da62496..51952011a 100644 --- a/packages/ui/eslint.config.mjs +++ b/packages/ui/eslint.config.mjs @@ -1,3 +1,11 @@ import reactConfig from "@multica/eslint-config/react"; -export default [...reactConfig]; +export default [ + ...reactConfig, + { + files: ["icons/drawings/*.mjs"], + languageOptions: { + globals: { process: "readonly", console: "readonly", URL: "readonly" }, + }, + }, +]; diff --git a/packages/ui/icons/create-icon.ts b/packages/ui/icons/create-icon.ts new file mode 100644 index 000000000..e0727e959 --- /dev/null +++ b/packages/ui/icons/create-icon.ts @@ -0,0 +1,63 @@ +import { + createElement, + forwardRef, + type ForwardRefExoticComponent, + type RefAttributes, + type SVGProps, +} from "react"; + +export interface IconProps extends Partial> { + size?: string | number; +} + +export type IconComponent = ForwardRefExoticComponent< + Omit & RefAttributes +>; + +/** A glyph's children on the 24×24 grid: `[tag, attributes]` pairs. */ +export type IconNode = ReadonlyArray]>; + +/** Stroke on the 24px grid; 1.5px at the 18px nav size, 1.33px at 16px. */ +export const ICON_STROKE_WIDTH = 2; + +function iconClassName(name: string, className?: string) { + const slug = name + .replace(/Icon$/, "") + .replace(/([a-z0-9])([A-Z])/g, "$1-$2") + .replace(/([A-Z])([A-Z][a-z])/g, "$1-$2") + .toLowerCase(); + return className ? `icon icon-${slug} ${className}` : `icon icon-${slug}`; +} + +function isLabelled(props: Record) { + return Object.keys(props).some((key) => key.startsWith("aria-") || key === "role" || key === "title"); +} + +export function createIcon(name: string, node: IconNode): IconComponent { + const children = node.map(([tag, attrs], i) => createElement(tag, { key: i, ...attrs })); + const Icon = forwardRef>( + ({ size = 24, strokeWidth = ICON_STROKE_WIDTH, className, children: extra, ...rest }, ref) => + createElement( + "svg", + { + ref, + xmlns: "http://www.w3.org/2000/svg", + width: size, + height: size, + viewBox: "0 0 24 24", + fill: "none", + stroke: "currentColor", + strokeWidth, + strokeLinecap: "round", + strokeLinejoin: "round", + "aria-hidden": isLabelled(rest) ? undefined : true, + className: iconClassName(name, className), + ...rest, + }, + ...children, + extra, + ), + ); + Icon.displayName = name; + return Icon; +} diff --git a/packages/ui/icons/drawings/construction.mjs b/packages/ui/icons/drawings/construction.mjs new file mode 100644 index 000000000..4200fab00 --- /dev/null +++ b/packages/ui/icons/drawings/construction.mjs @@ -0,0 +1,79 @@ +// Shared construction for Multica glyphs: a 24px grid, continuous-curvature +// (squircle) corners and soft stroke ends. Drawings are inner SVG markup; +// `class="b"` marks the body silhouette and `class="k"` a detail cut into it. + +export const f = (n) => +n.toFixed(2); +const dist = (a, b) => Math.hypot(a[0] - b[0], a[1] - b[1]); +const unit = (a, b) => { + const d = dist(a, b) || 1; + return [(a[0] - b[0]) / d, (a[1] - b[1]) / d]; +}; +const pt = (p) => `${f(p[0])} ${f(p[1])}`; + +function corner(prev, v, next, k) { + const ua = unit(prev, v); + const ub = unit(next, v); + const kk = Math.min(k, dist(prev, v) / 2, dist(next, v) / 2); + const p = (u, t) => [v[0] + u[0] * t, v[1] + u[1] * t]; + const m = [v[0] + (ua[0] + ub[0]) * 0.146 * kk, v[1] + (ua[1] + ub[1]) * 0.146 * kk]; + return { + start: p(ua, kk), + curve: `C${pt(p(ua, 0.5 * kk))} ${pt(p(ua, 0.293 * kk))} ${pt(m)} C${pt(p(ub, 0.293 * kk))} ${pt(p(ub, 0.5 * kk))} ${pt(p(ub, kk))}`, + }; +} + +/** + * Path through `[x, y, k]` points, rounding each vertex with a squircle corner + * of size `k`. Closed shapes round every vertex; open paths keep their ends. + */ +export function shape(pts, closed = true) { + const n = pts.length; + const at = (i) => pts[(i + n) % n]; + let d = closed ? "" : `M${pt(pts[0])}`; + const first = closed ? 0 : 1; + const last = closed ? n - 1 : n - 2; + for (let i = first; i <= last; i++) { + const c = corner(at(i - 1), at(i), at(i + 1), at(i)[2] ?? 0); + d += (d ? ` L${pt(c.start)} ` : `M${pt(c.start)} `) + c.curve; + } + return closed ? `${d} Z` : `${d} L${pt(pts[n - 1])}`; +} + +export const rect = (x, y, w, h, k) => shape([[x, y, k], [x + w, y, k], [x + w, y + h, k], [x, y + h, k]]); + +/** Regular polygon or star: `radii` alternate around the centre, starting at `start` degrees. */ +export function polygon(cx, cy, radii, count, k, start = -90) { + const pts = []; + for (let i = 0; i < count * radii.length; i++) { + const r = radii[i % radii.length]; + const a = ((start + (i * 360) / (count * radii.length)) * Math.PI) / 180; + pts.push([cx + r * Math.cos(a), cy + r * Math.sin(a), Array.isArray(k) ? k[i % k.length] : k]); + } + return shape(pts); +} + +export function gear() { + const pts = []; + for (let i = 0; i < 8; i++) { + const a = (i / 8) * Math.PI * 2 - Math.PI / 2; + const P = (r, t) => [12 + r * Math.cos(t), 12 + r * Math.sin(t), 1.1]; + pts.push(P(7.4, a - 0.3), P(9.6, a - 0.17), P(9.6, a + 0.17), P(7.4, a + 0.3)); + } + return shape(pts); +} + +/** + * Soft arrowhead whose tip sits at (x, y), pointing `dir` degrees + * (0 right, 90 down, 180 left, 270 up), `depth` long and `half` wide each side. + */ +export function head(x, y, dir, depth, half) { + const a = (dir * Math.PI) / 180; + const c = Math.cos(a); + const s = Math.sin(a); + const P = (u, v) => pt([x + u * c - v * s, y + u * s + v * c]); + const t = 0.263 * half; + return ``; +} + +export const S = 'fill="currentColor" stroke="none"'; +export const dot = (x, y, r = 1.15) => ``; diff --git a/packages/ui/icons/drawings/drawings.mjs b/packages/ui/icons/drawings/drawings.mjs new file mode 100644 index 000000000..f359aa6d2 --- /dev/null +++ b/packages/ui/icons/drawings/drawings.mjs @@ -0,0 +1,470 @@ +// Every Multica glyph, as inner SVG markup on the 24px grid. Run +// `pnpm --filter @multica/ui icons` after editing to regenerate ../glyphs.ts +// and ../index.ts. + +import { S, dot, f, gear, head, polygon, rect, shape } from "./construction.mjs"; + +const ring = ``; +const page = shape([[4.75, 2.75, 4.5], [13.75, 2.75, 1.2], [19.25, 8.25, 1.2], [19.25, 21.25, 4.5], [4.75, 21.25, 4.5]]); +const fold = ``; +const file = (inner = "") => `${fold}${inner}`; +const folderBody = shape([[2.75, 3.75, 3.5], [9.25, 3.75, 1.5], [11.5, 6.25, 1.5], [21.25, 6.25, 4.5], [21.25, 20.25, 6], [2.75, 20.25, 6]]); +const cw = ``; +const ccw = ``; +const smallCheck = (x, y) => ``; +const bubble = shape([[2.75, 3.5, 7], [21.25, 3.5, 7], [21.25, 17.5, 6], [9, 17.5, 2], [3.75, 21, 1], [2.75, 14.5, 2]]); +const panel = rect(2.75, 3.5, 18.5, 17, 6); +const eye = ``; +const link = ``; +const user = (cx) => ``; +const wifi = (arcs) => [ + dot(12, 19, 1.3), + ``, + ``, + ``, +].slice(0, arcs + 1).join(""); + +export const DRAWINGS = { + Inbox: ` + `, + CircleUser: ` + `, + MessageSquare: ` + `, + ListTodo: ` + + `, + FolderKanban: ` + `, + Zap: ` + `, + Bot: ` + + `, + Users: ` + + `, + BookOpenText: ` + + `, + Monitor: ` + `, + BarChart3: ` + + `, + Settings: ``, + SquarePen: ` + `, + Search: ``, + + Plus: ``, + Check: ``, + X: ``, + ChevronRight: ``, + ChevronDown: ``, + MoreHorizontal: ``, + Pencil: ``, + Trash2: ` + + `, + Copy: ` + `, + Loader2: ``, + ExternalLink: ` + `, + Bell: ` + `, + Filter: ``, + Pin: ` + `, + Archive: ` + `, + Lock: ` + `, + Clock: ``, + CalendarDays: ` + `, + ArrowUp: ``, +}; + +Object.assign(DRAWINGS, { + // Arrows and chevrons + ArrowDown: ``, + ArrowRight: ``, + ArrowLeft: ``, + ArrowUpRight: ``, + ArrowDownToLine: ``, + ArrowLeftRight: ``, + CornerDownRight: ``, + CornerDownLeft: ``, + ChevronLeft: ``, + ChevronUp: ``, + ChevronsUpDown: ``, + Download: ``, + Upload: ``, + RotateCw: cw, + RotateCcw: ccw, + RefreshCw: ` + `, + History: `${ccw}`, + Maximize2: ``, + Minimize2: ``, + + // Circles and status + AlertCircle: `${ring}${dot(12, 16.25)}`, + CheckCircle2: `${ring}`, + XCircle: `${ring}`, + Info: `${ring}${dot(12, 7.9)}`, + CircleHelp: `${ring}${dot(12, 16.75)}`, + CircleDot: `${ring}${dot(12, 12, 2.25)}`, + CircleDashed: ``, + CircleSlash: `${ring}`, + CircleEqual: `${ring}`, + CirclePause: `${ring}`, + Circle: ring, + Ban: `${ring}`, + AlertTriangle: `${dot(12, 16.6)}`, + + // Basic shapes and controls + Minus: ``, + Square: ``, + Play: ``, + Pause: ``, + GripVertical: [5, 12, 19].map((y) => dot(9, y, 1.5) + dot(15, y, 1.5)).join(""), + Hash: ``, + AtSign: ``, + Menu: ``, + + // People + UserRound: user(12), + UserMinus: `${user(10)}`, + UserPlus: `${user(10)}`, + Crown: ``, + + // Files and folders + File: file(), + FileText: file(``), + FileCode: file(``), + FileImage: file(`${dot(9.5, 12.25, 1.35)}`), + FileArchive: `${fold}`, + FileAudio: file(``), + FileVideo: file(``), + FileQuestion: file(`${dot(12, 18.1, 1)}`), + FilePlus: file(``), + Folder: ``, + FolderOpen: ` + `, + + // Time + Clock3: `${ring}`, + Calendar: ``, + CalendarClock: ` + `, + + // Tools and settings + Settings2: ``, + SlidersHorizontal: ` + `, + Tag: `${dot(7.75, 7.75, 1.4)}`, + Save: ` + `, + Workflow: ``, + Plug: ``, + Link2: `${link}`, + Unlink: `${link}`, + Eye: eye, + EyeOff: `${eye}`, + Shield: ``, + ShieldCheck: ` + `, + Sparkles: ` + ${dot(18.5, 4.75, 1.2)}`, + + // Devices and infrastructure + Server: `${dot(7, 7)}${dot(7, 17)}`, + HardDrive: `${dot(7, 17)}`, + Laptop: ``, + Smartphone: ``, + Cpu: ` + `, + Terminal: ``, + SquareTerminal: ``, + Code: ``, + Code2: ``, + Globe: `${ring}`, + Cloud: ``, + Wifi: wifi(3), + WifiHigh: wifi(2), + WifiOff: `${wifi(3)}`, + SignalHigh: ``, + GitBranch: ``, + GitPullRequest: ` + `, + + // Layout and lists + LayoutGrid: [[3.25, 3.25], [13.5, 3.25], [3.25, 13.5], [13.5, 13.5]].map(([x, y]) => ``).join(""), + Layers: ``, + List: `${dot(4.25, 6, 1.3)}${dot(4.25, 12, 1.3)}${dot(4.25, 18, 1.3)}`, + ListChecks: `${smallCheck(3.5, 7)}${smallCheck(3.5, 18)}`, + ListPlus: ``, + ListTree: ``, + PanelLeft: ``, + PanelLeftClose: ``, + PanelLeftOpen: ``, + PanelRight: ``, + PanelRightClose: ``, + PanelRightOpen: ``, + AppWindow: `${dot(6.25, 6.15, 0.9)}${dot(9, 6.15, 0.9)}`, + Image: `${dot(9, 9, 1.75)}`, + CreditCard: ``, + + // Communication and state + MessageSquarePlus: ``, + Mail: ``, + Send: ``, + LogOut: ``, + LogIn: ``, + PinOff: `${DRAWINGS.Pin}`, + ArchiveRestore: ` + `, + Sun: ``, + Moon: ``, +}); + +function wrench() { + const C = [15, 9]; + const R = 5.75; + const d = [Math.SQRT1_2, -Math.SQRT1_2]; + const u = [-Math.SQRT1_2, Math.SQRT1_2]; + const p = [Math.SQRT1_2, Math.SQRT1_2]; + const at = (s, along, w) => [C[0] + along[0] * s + p[0] * w, C[1] + along[1] * s + p[1] * w]; + const P = (q) => `${f(q[0])} ${f(q[1])}`; + const w = 1.75; + const h = 1.75; + const s = Math.sqrt(R * R - w * w); + const t = Math.sqrt(R * R - h * h); + const L = 13.75; + return [ + `M${P(at(s, d, w))}`, + `L${P(at(2, d, w))}`, + `A${w} ${w} 0 0 1 ${P(at(2, d, -w))}`, + `L${P(at(s, d, -w))}`, + `A${R} ${R} 0 0 0 ${P(at(t, u, -h))}`, + `L${P(at(L, u, -h))}`, + `A${h} ${h} 0 0 0 ${P(at(L, u, h))}`, + `L${P(at(t, u, h))}`, + `A${R} ${R} 0 0 0 ${P(at(s, d, w))}`, + "Z", + ].join(" "); +} + +function paperclip() { + const a = Math.PI / 4; + const R = ([x, y]) => { + const dx = x - 12; + const dy = y - 11.5; + return `${f(12 + dx * Math.cos(a) - dy * Math.sin(a))} ${f(11.5 + dx * Math.sin(a) + dy * Math.cos(a))}`; + }; + return `M${R([15.5, 8.5])}L${R([15.5, 15.25])}A3.5 3.5 0 0 1 ${R([8.5, 15.25])}L${R([8.5, 6.25])}A2.25 2.25 0 0 1 ${R([13, 6.25])}L${R([13, 15])}A1.25 1.25 0 0 1 ${R([10.5, 15])}L${R([10.5, 8.5])}`; +} + +const wave = (y, a = 1.75) => `M2.75 ${y}c1.85 0 2.78-${a} 4.63-${a}s2.78 ${a} 4.62 ${a} 2.78-${a} 4.63-${a} 2.77 ${a} 4.62 ${a}`; +const box = shape([[12, 2.75, 2.5], [20.5, 7.4, 2.5], [20.5, 16.6, 2.5], [12, 21.25, 2.5], [3.5, 16.6, 2.5], [3.5, 7.4, 2.5]]); +const shield = DRAWINGS.Shield; +const grid = rect(3, 3, 18, 18, 7); +const diamond = (cx, cy, r) => shape([[cx, cy - r, 1.5], [cx + r, cy, 1.5], [cx, cy + r, 1.5], [cx - r, cy, 1.5]]); + +Object.assign(DRAWINGS, { + // Text and editor + Bold: ``, + Italic: ``, + Strikethrough: ``, + Heading1: ``, + Heading2: ``, + Heading3: ``, + Quote: ` + `, + Type: ``, + ListOrdered: ``, + WrapText: `${head(13.5, 18.5, 180, 2.5, 2.5)}`, + Highlighter: ` + `, + Pipette: ` + `, + Space: ``, + Option: ``, + Command: ``, + Keyboard: `${dot(7.5, 10)}${dot(12, 10)}${dot(16.5, 10)}`, + Delete: ``, + + // Arrows and motion + ArrowBigUp: ``, + ArrowDownNarrowWide: `${head(7, 19.5, 90, 3.5, 3.5)}`, + ArrowUpNarrowWide: `${head(7, 4.5, 270, 3.5, 3.5)}`, + ArrowRightToLine: `${head(16.5, 12, 0, 5, 5.5)}`, + ArrowUpCircle: `${head(12, 8, 270, 3.25, 3.5).replace("${head(7, 4.5, 270, 3.5, 3.5)}${head(17, 19.5, 90, 3.5, 3.5)}`, + CornerLeftUp: `${head(9, 4.5, 270, 4.5, 4.5)}`, + CornerUpLeft: `${head(4.5, 9, 180, 4.5, 4.5)}`, + Undo2: `${head(4.5, 9, 180, 4.5, 4.5)}`, + Redo2: `${head(19.5, 9, 0, 4.5, 4.5)}`, + FastForward: ``, + SkipForward: ``, + Maximize: ` + `, + Activity: ``, + Waves: ``, + + // Lists and layout + ListChevronsDownUp: ``, + ListChevronsUpDown: ``, + ListEnd: `${head(13.5, 19, 180, 3, 3)}`, + ListX: ``, + FilterX: ``, + Columns2: ``, + Columns3: ``, + Rows3: ``, + Table2: ``, + Frame: ``, + LayoutDashboard: ` + `, + LayoutTemplate: ``, + ChartGantt: ``, + Blocks: ` + `, + Component: ``, + Shapes: ` + `, + Network: ` + `, + + // Files and folders + FilePen: file(``), + FileSearch: file(``), + FileSpreadsheet: file(``), + FolderGit: ``, + FolderMinus: ``, + ScrollText: ` + `, + BookOpen: ` + `, + BookCheck: ``, + Bookmark: ``, + Newspaper: ` + `, + ImagePlus: `${dot(9, 9.5, 1.75)} + `, + + // Objects + Webhook: ` + + `, + Brain: ` + `, + Rocket: ` + `, + Milestone: ``, + Gauge: ``, + Bug: ``, + Box: ``, + Package: ``, + Briefcase: ``, + Compass: ``, + Database: ``, + Dices: `${dot(17.25, 6.75, 1.2)} + ${dot(6.75, 12.75, 1.2)}${dot(11.25, 17.25, 1.2)}`, + Flag: ``, + Megaphone: ` + `, + Star: ``, + Heart: ``, + Tags: `${dot(6.75, 8.25, 1.3)} + `, + Target: `${dot(12, 12, 1.5)}`, + LocateFixed: `${dot(12, 12, 2.25)}`, + MapPin: ``, + Palette: ` + ${dot(7.5, 11.5, 1.3)}${dot(9.5, 7.25, 1.3)}${dot(14.5, 7.25, 1.3)}`, + Wrench: ``, + Paperclip: ``, + KeyRound: ``, + Lightbulb: ``, + Hourglass: ` + `, + AlarmClock: ``, + GraduationCap: ` + `, + Building2: ``, + Camera: ``, + Coins: ``, + Tablet: ``, + Power: ``, + PlugZap: `${DRAWINGS.Plug}`, + Unplug: `${DRAWINGS.Plug}`, + ShieldOff: `${shield}`, + CircleOff: ``, + OctagonXIcon: ``, + + // People and communication + UserPen: ` + `, + SmilePlus: `${dot(9, 9.5, 1.1)}${dot(15, 9.5, 1.1)}`, + MessageCircle: ``, + MessagesSquare: ` + `, + CheckCheck: ``, + + // Code and git + GitMerge: ``, + GitPullRequestClosed: ``, + GitPullRequestDraft: `${dot(17.75, 6, 1.3)}${dot(17.75, 11, 1.3)}`, + BotOff: `${DRAWINGS.Bot}`, + PencilLine: `${DRAWINGS.Pencil}`, + + // Command palette + BellOff: `${DRAWINGS.Bell}`, + BellRing: `${DRAWINGS.Bell}`, + CalendarX: ` + `, + FolderPlus: ``, + FolderInput: ``, + MailOpen: ` + `, + MessageCircleQuestion: ` + `, + SquarePlus: ``, +}); + +/** Product names that render an existing drawing. */ +export const ALIASES = { + AlertCircle: ["CircleAlert"], + AlertTriangle: ["TriangleAlert", "TriangleAlertIcon"], + Check: ["CheckIcon"], + CheckCircle2: ["CircleCheck", "CircleCheckIcon"], + ChevronDown: ["ChevronDownIcon"], + ChevronLeft: ["ChevronLeftIcon"], + ChevronRight: ["ChevronRightIcon"], + ChevronUp: ["ChevronUpIcon"], + CircleHelp: ["HelpCircle"], + Code2: ["CodeXml"], + Globe: ["Globe2"], + Image: ["ImageIcon"], + Info: ["InfoIcon"], + Layers: ["Layers3"], + Link2: ["Link"], + Loader2: ["Loader2Icon", "LoaderCircle"], + MessageSquare: ["MessageSquareText"], + Minus: ["MinusIcon"], + MoreHorizontal: ["Ellipsis"], + PanelLeft: ["PanelLeftIcon"], + Search: ["SearchIcon"], + UserRound: ["User"], + X: ["XIcon"], + FilePlus: ["FilePlus2"], + Briefcase: ["BriefcaseBusiness"], + FilePen: ["FileEdit"], + FolderGit: ["FolderGit2"], + GitPullRequest: ["GitPullRequestArrow"], + Lock: ["LockKeyhole"], + PencilLine: ["PenLine"], +}; diff --git a/packages/ui/icons/drawings/generate.d.mts b/packages/ui/icons/drawings/generate.d.mts new file mode 100644 index 000000000..2806c019e --- /dev/null +++ b/packages/ui/icons/drawings/generate.d.mts @@ -0,0 +1,5 @@ +export function renderGlyphs(): string; +export function renderIndex(): string; +export function exportNames(): Record; +export const OUTPUTS: Record<"glyphs.ts" | "index.ts", () => string>; +export function renderPreview(names?: string[]): string; diff --git a/packages/ui/icons/drawings/generate.mjs b/packages/ui/icons/drawings/generate.mjs new file mode 100644 index 000000000..dc6c17fda --- /dev/null +++ b/packages/ui/icons/drawings/generate.mjs @@ -0,0 +1,123 @@ +// Builds ../glyphs.ts and ../index.ts from drawings.mjs. +// pnpm --filter @multica/ui icons write both files +// pnpm --filter @multica/ui icons --check exit 1 if either is stale +// pnpm --filter @multica/ui icons --preview [Name…] write a contact sheet and print its path + +import { readFileSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { fileURLToPath } from "node:url"; +import { ALIASES, DRAWINGS } from "./drawings.mjs"; + +const ROLES = { b: "icon-body", k: "icon-cut" }; +const camel = (s) => s.replace(/-([a-z])/g, (_, c) => c.toUpperCase()); + +function nodes(name, markup) { + const list = []; + for (const m of markup.matchAll(/<(\w+)([^>]*?)\/>/g)) { + const attrs = {}; + for (const a of m[2].matchAll(/([\w-]+)="([^"]*)"/g)) attrs[a[1]] = a[2]; + const role = ROLES[attrs.class]; + delete attrs.class; + if (role) attrs.className = role === "icon-cut" && attrs.fill === "currentColor" ? "icon-cut-fill" : role; + const clean = {}; + for (const [k, v] of Object.entries(attrs)) clean[k === "className" ? k : camel(k)] = v.replace(/\s+/g, " ").trim(); + list.push([m[1], clean]); + } + if (!list.length) throw new Error(`${name}: empty drawing`); + return list; +} + +export function renderGlyphs() { + return [ + 'import type { IconNode } from "./create-icon";', + "", + "// Generated by drawings/generate.mjs from drawings/drawings.mjs; do not edit.", + "// `icon-body` marks the main silhouette, which the active sidebar item fills", + "// solid; `icon-cut` / `icon-cut-fill` mark the stroked / filled details inside", + "// it, which that state knocks out in the background colour.", + "", + ...Object.keys(DRAWINGS) + .sort() + .map((n) => `export const ${n}: IconNode = ${JSON.stringify(nodes(n, DRAWINGS[n]))};`), + "", + ].join("\n"); +} + +export function exportNames() { + const canonical = Object.fromEntries(Object.keys(DRAWINGS).map((n) => [n, n])); + for (const [n, aliases] of Object.entries(ALIASES)) { + if (!DRAWINGS[n]) throw new Error(`alias target ${n} has no drawing`); + for (const a of aliases) { + if (canonical[a]) throw new Error(`${a} is both a drawing and an alias`); + canonical[a] = n; + } + } + return canonical; +} + +export function renderIndex() { + const canonical = exportNames(); + return [ + 'import { createIcon } from "./create-icon";', + 'import * as glyph from "./glyphs";', + "", + "// Generated by drawings/generate.mjs; do not edit. Every icon the product", + "// uses is a Multica drawing: add new ones to drawings/drawings.mjs.", + "", + 'export { ICON_STROKE_WIDTH, type IconComponent, type IconNode, type IconProps } from "./create-icon";', + "", + ...Object.keys(canonical) + .sort() + .map((n) => `export const ${n} = /* @__PURE__ */ createIcon("${n}", glyph.${canonical[n]});`), + "", + ].join("\n"); +} + +export const OUTPUTS = { + "glyphs.ts": renderGlyphs, + "index.ts": renderIndex, +}; + +/** Contact sheet of `names` (default: all) at 48, 18 and 14px, plus the solid active-sidebar state. */ +export function renderPreview(names = Object.keys(DRAWINGS)) { + const svg = (body, px) => + `${body}`; + const tiles = names.map((n) => { + if (!DRAWINGS[n]) throw new Error(`no drawing named ${n}`); + const solid = DRAWINGS[n] + .replace(/class="b"/g, 'class="b" fill="currentColor"') + .replace(/class="k"([^>]*?)fill="currentColor"/g, 'class="k"$1fill="#ececef"') + .replace(/class="k"(?![^>]*fill="#)/g, 'class="k" stroke="#ececef"'); + return `
${svg(DRAWINGS[n], 48)}
${svg(DRAWINGS[n], 18)}${svg(DRAWINGS[n], 14)}${svg(solid, 18)}
${n}
`; + }); + return `${tiles.join("")}`; +} + +if (process.argv[1] === fileURLToPath(import.meta.url)) { + const preview = process.argv.indexOf("--preview"); + if (preview !== -1) { + const names = process.argv.slice(preview + 1); + const file = join(tmpdir(), "multica-icons-preview.html"); + writeFileSync(file, renderPreview(names.length ? names : undefined)); + console.log(file); + process.exit(0); + } + const check = process.argv.includes("--check"); + let stale = 0; + for (const [file, render] of Object.entries(OUTPUTS)) { + const url = new URL(`../${file}`, import.meta.url); + const next = render(); + if (readFileSync(url, "utf8") === next) continue; + stale++; + if (check) console.error(`icons/${file} is out of date; run pnpm --filter @multica/ui icons`); + else writeFileSync(url, next); + } + if (check && stale) process.exit(1); + console.log(`${Object.keys(DRAWINGS).length} drawings, ${Object.keys(exportNames()).length} names`); +} diff --git a/packages/ui/icons/glyphs.ts b/packages/ui/icons/glyphs.ts new file mode 100644 index 000000000..5fc8a26a2 --- /dev/null +++ b/packages/ui/icons/glyphs.ts @@ -0,0 +1,268 @@ +import type { IconNode } from "./create-icon"; + +// Generated by drawings/generate.mjs from drawings/drawings.mjs; do not edit. +// `icon-body` marks the main silhouette, which the active sidebar item fills +// solid; `icon-cut` / `icon-cut-fill` mark the stroked / filled details inside +// it, which that state knocks out in the background colour. + +export const Activity: IconNode = [["path",{"d":"M2.75 12h3.5l2.75-7 6 14 2.75-7h3.5"}]]; +export const AlarmClock: IconNode = [["circle",{"cx":"12","cy":"13","r":"7.75","className":"icon-body"}],["path",{"d":"M12 9.5V13l2.25 1.5","className":"icon-cut"}],["path",{"d":"M3 5.75 5.75 3M21 5.75 18.25 3"}]]; +export const AlertCircle: IconNode = [["circle",{"cx":"12","cy":"12","r":"9.25","className":"icon-body"}],["path",{"d":"M12 7.75v4.75"}],["circle",{"fill":"currentColor","stroke":"none","cx":"12","cy":"16.25","r":"1.15"}]]; +export const AlertTriangle: IconNode = [["path",{"d":"M10.27 6.04 C11.14 4.52 11.49 3.89 12 3.89 C12.51 3.89 12.86 4.52 13.73 6.04 L19.77 16.71 C20.64 18.23 20.99 18.86 20.74 19.31 C20.47 19.75 19.75 19.75 18 19.75 L6 19.75 C4.25 19.75 3.53 19.75 3.26 19.31 C3.01 18.86 3.36 18.23 4.23 16.71 Z","className":"icon-body"}],["path",{"d":"M12 9.5v4"}],["circle",{"fill":"currentColor","stroke":"none","cx":"12","cy":"16.6","r":"1.15"}]]; +export const AppWindow: IconNode = [["path",{"d":"M2.75 9.5 C2.75 6.5 2.75 5.26 3.63 4.38 C4.51 3.5 5.75 3.5 8.75 3.5 L15.25 3.5 C18.25 3.5 19.49 3.5 20.37 4.38 C21.25 5.26 21.25 6.5 21.25 9.5 L21.25 14.5 C21.25 17.5 21.25 18.74 20.37 19.62 C19.49 20.5 18.25 20.5 15.25 20.5 L8.75 20.5 C5.75 20.5 4.51 20.5 3.63 19.62 C2.75 18.74 2.75 17.5 2.75 14.5 Z","className":"icon-body"}],["path",{"d":"M2.75 8.75h18.5"}],["circle",{"fill":"currentColor","stroke":"none","cx":"6.25","cy":"6.15","r":"0.9"}],["circle",{"fill":"currentColor","stroke":"none","cx":"9","cy":"6.15","r":"0.9"}]]; +export const Archive: IconNode = [["path",{"d":"M2.5 6 C2.5 4.75 2.5 4.23 2.87 3.87 C3.23 3.5 3.75 3.5 5 3.5 L19 3.5 C20.25 3.5 20.77 3.5 21.14 3.87 C21.5 4.23 21.5 4.75 21.5 6 L21.5 6 C21.5 7.25 21.5 7.77 21.14 8.13 C20.77 8.5 20.25 8.5 19 8.5 L5 8.5 C3.75 8.5 3.23 8.5 2.87 8.13 C2.5 7.77 2.5 7.25 2.5 6 Z","className":"icon-body"}],["path",{"d":"M4 8.5 L4 15.5 C4 18 4 19.04 4.73 19.77 C5.46 20.5 6.5 20.5 9 20.5 L15 20.5 C17.5 20.5 18.54 20.5 19.27 19.77 C20 19.04 20 18 20 15.5 L20 8.5"}],["path",{"d":"M10 12.75h4"}]]; +export const ArchiveRestore: IconNode = [["path",{"d":"M2.5 6 C2.5 4.75 2.5 4.23 2.87 3.87 C3.23 3.5 3.75 3.5 5 3.5 L19 3.5 C20.25 3.5 20.77 3.5 21.14 3.87 C21.5 4.23 21.5 4.75 21.5 6 L21.5 6 C21.5 7.25 21.5 7.77 21.14 8.13 C20.77 8.5 20.25 8.5 19 8.5 L5 8.5 C3.75 8.5 3.23 8.5 2.87 8.13 C2.5 7.77 2.5 7.25 2.5 6 Z","className":"icon-body"}],["path",{"d":"M4 8.5 L4 15.5 C4 18 4 19.04 4.73 19.77 C5.46 20.5 6.5 20.5 9 20.5 L15 20.5 C17.5 20.5 18.54 20.5 19.27 19.77 C20 19.04 20 18 20 15.5 L20 8.5"}],["path",{"d":"M12 18v-6.25M9.5 14s1.85-2.5 2.5-2.5 2.5 2.5 2.5 2.5"}]]; +export const ArrowBigUp: IconNode = [["path",{"d":"M10.94 4.31 C11.47 3.78 11.69 3.56 12 3.56 C12.31 3.56 12.53 3.78 13.06 4.31 L19.44 10.69 C19.97 11.22 20.19 11.44 20.13 11.6 C20.06 11.75 19.75 11.75 19 11.75 L17 11.75 C16.5 11.75 16.29 11.75 16.15 11.9 C16 12.04 16 12.25 16 12.75 L16 18.75 C16 19.75 16 20.16 15.71 20.46 C15.41 20.75 15 20.75 14 20.75 L10 20.75 C9 20.75 8.59 20.75 8.29 20.46 C8 20.16 8 19.75 8 18.75 L8 12.75 C8 12.25 8 12.04 7.85 11.9 C7.71 11.75 7.5 11.75 7 11.75 L5 11.75 C4.25 11.75 3.94 11.75 3.87 11.6 C3.81 11.44 4.03 11.22 4.56 10.69 Z","className":"icon-body"}]]; +export const ArrowDown: IconNode = [["path",{"d":"M12 18.5V4.5M6 13s4.42 6 6 6 6-6 6-6"}]]; +export const ArrowDownNarrowWide: IconNode = [["path",{"d":"M7 4v15.25"}],["path",{"d":"M10.5 16C10.5 16 7.92 19.5 7 19.5C6.08 19.5 3.5 16 3.5 16"}],["path",{"d":"M12 5h3.5M12 10h6M12 15h8.5"}]]; +export const ArrowDownToLine: IconNode = [["path",{"d":"M12 3.5v11.5M6.5 10s4 5.5 5.5 5.5 5.5-5.5 5.5-5.5M5 20.5h14"}]]; +export const ArrowLeft: IconNode = [["path",{"d":"M19.5 12h-14M11 6s-6 4.42-6 6 6 6 6 6"}]]; +export const ArrowLeftRight: IconNode = [["path",{"d":"M4 8h16M16.5 4.5s3.5 2.6 3.5 3.5-3.5 3.5-3.5 3.5M20 16H4M7.5 12.5S4 15.1 4 16s3.5 3.5 3.5 3.5"}]]; +export const ArrowRight: IconNode = [["path",{"d":"M4.5 12h14M13 6s6 4.42 6 6-6 6-6 6"}]]; +export const ArrowRightToLine: IconNode = [["path",{"d":"M3.5 12h12.75"}],["path",{"d":"M11.5 6.5C11.5 6.5 16.5 10.55 16.5 12C16.5 13.45 11.5 17.5 11.5 17.5"}],["path",{"d":"M20.5 5v14"}]]; +export const ArrowUp: IconNode = [["path",{"d":"M12 5.5V19.5M18 11s-4.42-6-6-6-6 6-6 6"}]]; +export const ArrowUpCircle: IconNode = [["circle",{"cx":"12","cy":"12","r":"9.25","className":"icon-body"}],["path",{"d":"M12 16.5V8.25","className":"icon-cut"}],["path",{"d":"M8.5 11.25C8.5 11.25 11.08 8 12 8C12.92 8 15.5 11.25 15.5 11.25","className":"icon-cut"}]]; +export const ArrowUpDown: IconNode = [["path",{"d":"M7 19.5V4.75M17 4.5v14.75"}],["path",{"d":"M3.5 8C3.5 8 6.08 4.5 7 4.5C7.92 4.5 10.5 8 10.5 8"}],["path",{"d":"M20.5 16C20.5 16 17.92 19.5 17 19.5C16.08 19.5 13.5 16 13.5 16"}]]; +export const ArrowUpNarrowWide: IconNode = [["path",{"d":"M7 20V4.75"}],["path",{"d":"M3.5 8C3.5 8 6.08 4.5 7 4.5C7.92 4.5 10.5 8 10.5 8"}],["path",{"d":"M12 9h3.5M12 14h6M12 19h8.5"}]]; +export const ArrowUpRight: IconNode = [["path",{"d":"M6.75 17.25 16.5 7.5"}],["path",{"d":"M8.5 6.75 L14.25 6.75 C15.75 6.75 16.37 6.75 16.81 7.19 C17.25 7.63 17.25 8.25 17.25 9.75 L17.25 15.5"}]]; +export const AtSign: IconNode = [["circle",{"cx":"12","cy":"12","r":"3.75"}],["path",{"d":"M15.75 8.5v5a2.75 2.75 0 0 0 5.5 0V12a9.25 9.25 0 1 0-3.62 7.34"}]]; +export const Ban: IconNode = [["circle",{"cx":"12","cy":"12","r":"9.25","className":"icon-body"}],["path",{"d":"m5.5 5.5 13 13"}]]; +export const BarChart3: IconNode = [["path",{"stroke":"none","d":"M3.25 17.25 8.1 11.8c.4-.45 1.05-.5 1.5-.12l2.9 2.44c.45.38 1.1.33 1.5-.1l6.75-7.27V20.5H3.25Z","className":"icon-body"}],["path",{"d":"M3.25 17.25 8.1 11.8c.4-.45 1.05-.5 1.5-.12l2.9 2.44c.45.38 1.1.33 1.5-.1l6.75-7.27"}],["path",{"d":"M3.25 20.75h17.5"}]]; +export const Bell: IconNode = [["path",{"d":"M5 17.25h14l-1.35-1.95a3 3 0 0 1-.55-1.73V10a5.1 5.1 0 0 0-10.2 0v3.57c0 .62-.19 1.22-.55 1.73Z","className":"icon-body"}],["path",{"d":"M9.5 20.25c.55.95 1.5 1.5 2.5 1.5s1.95-.55 2.5-1.5"}]]; +export const BellOff: IconNode = [["path",{"d":"M5 17.25h14l-1.35-1.95a3 3 0 0 1-.55-1.73V10a5.1 5.1 0 0 0-10.2 0v3.57c0 .62-.19 1.22-.55 1.73Z","className":"icon-body"}],["path",{"d":"M9.5 20.25c.55.95 1.5 1.5 2.5 1.5s1.95-.55 2.5-1.5"}],["path",{"d":"m3 3 18 18"}]]; +export const BellRing: IconNode = [["path",{"d":"M5 17.25h14l-1.35-1.95a3 3 0 0 1-.55-1.73V10a5.1 5.1 0 0 0-10.2 0v3.57c0 .62-.19 1.22-.55 1.73Z","className":"icon-body"}],["path",{"d":"M9.5 20.25c.55.95 1.5 1.5 2.5 1.5s1.95-.55 2.5-1.5"}],["path",{"d":"M3.25 9.5c.2-2.1 1.05-3.95 2.5-5.25M20.75 9.5c-.2-2.1-1.05-3.95-2.5-5.25"}]]; +export const Blocks: IconNode = [["path",{"d":"M3.25 10.75 C3.25 9.25 3.25 8.63 3.69 8.19 C4.13 7.75 4.75 7.75 6.25 7.75 L9.25 7.75 C10 7.75 10.31 7.75 10.53 7.97 C10.75 8.19 10.75 8.5 10.75 9.25 L10.75 11.75 C10.75 12.5 10.75 12.81 10.97 13.03 C11.19 13.25 11.5 13.25 12.25 13.25 L15.25 13.25 C16 13.25 16.31 13.25 16.53 13.47 C16.75 13.69 16.75 14 16.75 14.75 L16.75 17.75 C16.75 19.25 16.75 19.87 16.31 20.31 C15.87 20.75 15.25 20.75 13.75 20.75 L6.25 20.75 C4.75 20.75 4.13 20.75 3.69 20.31 C3.25 19.87 3.25 19.25 3.25 17.75 Z","className":"icon-body"}],["path",{"d":"M14 5.75 C14 4.5 14 3.98 14.37 3.62 C14.73 3.25 15.25 3.25 16.5 3.25 L18.25 3.25 C19.5 3.25 20.02 3.25 20.39 3.62 C20.75 3.98 20.75 4.5 20.75 5.75 L20.75 7.5 C20.75 8.75 20.75 9.27 20.39 9.63 C20.02 10 19.5 10 18.25 10 L16.5 10 C15.25 10 14.73 10 14.37 9.63 C14 9.27 14 8.75 14 7.5 Z","className":"icon-body"}]]; +export const Bold: IconNode = [["path",{"d":"M7.25 12h5.5a3.75 3.75 0 0 0 0-7.5H8.75a1.5 1.5 0 0 0-1.5 1.5v12a1.5 1.5 0 0 0 1.5 1.5h5.25a3.75 3.75 0 0 0 0-7.5H7.25"}]]; +export const BookCheck: IconNode = [["path",{"d":"M4 7.75 C4 5.25 4 4.21 4.73 3.48 C5.46 2.75 6.5 2.75 9 2.75 L15 2.75 C17.5 2.75 18.54 2.75 19.27 3.48 C20 4.21 20 5.25 20 7.75 L20 16.25 C20 18.75 20 19.79 19.27 20.52 C18.54 21.25 17.5 21.25 15 21.25 L9 21.25 C6.5 21.25 5.46 21.25 4.73 20.52 C4 19.79 4 18.75 4 16.25 Z","className":"icon-body"}],["path",{"d":"M8 2.75v18.5","className":"icon-cut"}],["path",{"d":"M11.25 12s1.25 1.75 1.85 1.75c.8 0 3.65-3.5 3.65-3.5","className":"icon-cut"}]]; +export const BookOpen: IconNode = [["path",{"d":"M12 6.75C10.4 5.4 8.3 4.75 3.75 4.75c-.55 0-1 .45-1 1V17.5c0 .55.45 1 1 1 4.55 0 6.65.65 8.25 2 1.6-1.35 3.7-2 8.25-2 .55 0 1-.45 1-1V5.75c0-.55-.45-1-1-1-4.55 0-6.65.65-8.25 2Z","className":"icon-body"}],["path",{"d":"M12 6.75V20.5","className":"icon-cut"}]]; +export const BookOpenText: IconNode = [["path",{"d":"M4 7.75 C4 5.25 4 4.21 4.73 3.48 C5.46 2.75 6.5 2.75 9 2.75 L15 2.75 C17.5 2.75 18.54 2.75 19.27 3.48 C20 4.21 20 5.25 20 7.75 L20 16.25 C20 18.75 20 19.79 19.27 20.52 C18.54 21.25 17.5 21.25 15 21.25 L9 21.25 C6.5 21.25 5.46 21.25 4.73 20.52 C4 19.79 4 18.75 4 16.25 Z","className":"icon-body"}],["path",{"d":"M8 2.75v18.5","className":"icon-cut"}],["path",{"fill":"currentColor","stroke":"none","d":"M14.5 7.25c.3 1.65 1.35 2.7 3 3-1.65.3-2.7 1.35-3 3-.3-1.65-1.35-2.7-3-3 1.65-.3 2.7-1.35 3-3Z","className":"icon-cut-fill"}]]; +export const Bookmark: IconNode = [["path",{"d":"M5.5 7.25 C5.5 5.25 5.5 4.42 6.08 3.83 C6.67 3.25 7.5 3.25 9.5 3.25 L14.5 3.25 C16.5 3.25 17.33 3.25 17.92 3.83 C18.5 4.42 18.5 5.25 18.5 7.25 L18.5 19.75 C18.5 20.25 18.5 20.46 18.38 20.52 C18.25 20.59 18.08 20.48 17.66 20.2 L13.26 17.32 C12.63 16.91 12.37 16.74 12 16.74 C11.63 16.74 11.37 16.91 10.74 17.32 L6.34 20.2 C5.92 20.48 5.75 20.59 5.62 20.52 C5.5 20.46 5.5 20.25 5.5 19.75 Z","className":"icon-body"}]]; +export const Bot: IconNode = [["path",{"d":"M3.5 13.25 C3.5 10.25 3.5 9.01 4.38 8.13 C5.26 7.25 6.5 7.25 9.5 7.25 L14.5 7.25 C17.5 7.25 18.74 7.25 19.62 8.13 C20.5 9.01 20.5 10.25 20.5 13.25 L20.5 14.75 C20.5 17.75 20.5 18.99 19.62 19.87 C18.74 20.75 17.5 20.75 14.5 20.75 L9.5 20.75 C6.5 20.75 5.26 20.75 4.38 19.87 C3.5 18.99 3.5 17.75 3.5 14.75 Z","className":"icon-body"}],["path",{"d":"M12 7.25V4.5"}],["circle",{"fill":"currentColor","stroke":"none","cx":"12","cy":"3.25","r":"1.35"}],["path",{"d":"M9 12.75v2M15 12.75v2","className":"icon-cut"}],["path",{"d":"M1.75 12.75v3M22.25 12.75v3"}]]; +export const BotOff: IconNode = [["path",{"d":"M3.5 13.25 C3.5 10.25 3.5 9.01 4.38 8.13 C5.26 7.25 6.5 7.25 9.5 7.25 L14.5 7.25 C17.5 7.25 18.74 7.25 19.62 8.13 C20.5 9.01 20.5 10.25 20.5 13.25 L20.5 14.75 C20.5 17.75 20.5 18.99 19.62 19.87 C18.74 20.75 17.5 20.75 14.5 20.75 L9.5 20.75 C6.5 20.75 5.26 20.75 4.38 19.87 C3.5 18.99 3.5 17.75 3.5 14.75 Z","className":"icon-body"}],["path",{"d":"M12 7.25V4.5"}],["circle",{"fill":"currentColor","stroke":"none","cx":"12","cy":"3.25","r":"1.35"}],["path",{"d":"M9 12.75v2M15 12.75v2","className":"icon-cut"}],["path",{"d":"M1.75 12.75v3M22.25 12.75v3"}],["path",{"d":"m2.5 2.5 19 19"}]]; +export const Box: IconNode = [["path",{"d":"M9.81 3.95 C10.9 3.35 11.36 3.1 12 3.1 C12.64 3.1 13.1 3.35 14.19 3.95 L18.31 6.2 C19.4 6.8 19.86 7.05 20.18 7.59 C20.5 8.13 20.5 8.65 20.5 9.9 L20.5 14.1 C20.5 15.35 20.5 15.87 20.18 16.41 C19.86 16.95 19.4 17.2 18.31 17.8 L14.19 20.05 C13.1 20.65 12.64 20.9 12 20.9 C11.36 20.9 10.9 20.65 9.81 20.05 L5.69 17.8 C4.6 17.2 4.14 16.95 3.82 16.41 C3.5 15.87 3.5 15.35 3.5 14.1 L3.5 9.9 C3.5 8.65 3.5 8.13 3.82 7.59 C4.14 7.05 4.6 6.8 5.69 6.2 Z","className":"icon-body"}],["path",{"d":"M3.75 7.5 12 12l8.25-4.5M12 12v9.25","className":"icon-cut"}]]; +export const Brain: IconNode = [["path",{"d":"M12 5.25a3.25 3.25 0 0 0-6.2 1.3A3.5 3.5 0 0 0 4.25 12.8a3.5 3.5 0 0 0 2.5 5.45A3.25 3.25 0 0 0 12 19.75a3.25 3.25 0 0 0 5.25-1.5 3.5 3.5 0 0 0 2.5-5.45 3.5 3.5 0 0 0-1.55-6.25A3.25 3.25 0 0 0 12 5.25Z","className":"icon-body"}],["path",{"d":"M12 5.25v14.5","className":"icon-cut"}]]; +export const Briefcase: IconNode = [["path",{"d":"M2.75 12.5 C2.75 9.75 2.75 8.61 3.55 7.8 C4.36 7 5.5 7 8.25 7 L15.75 7 C18.5 7 19.64 7 20.45 7.8 C21.25 8.61 21.25 9.75 21.25 12.5 L21.25 15 C21.25 17.75 21.25 18.89 20.45 19.7 C19.64 20.5 18.5 20.5 15.75 20.5 L8.25 20.5 C5.5 20.5 4.36 20.5 3.55 19.7 C2.75 18.89 2.75 17.75 2.75 15 Z","className":"icon-body"}],["path",{"d":"M8.5 7V5.25c0-.83.67-1.5 1.5-1.5h4c.83 0 1.5.67 1.5 1.5V7"}]]; +export const Bug: IconNode = [["path",{"d":"M6.5 13 C6.5 10.25 6.5 9.11 7.3 8.3 C8.11 7.5 9.25 7.5 12 7.5 L12 7.5 C14.75 7.5 15.89 7.5 16.7 8.3 C17.5 9.11 17.5 10.25 17.5 13 L17.5 15.5 C17.5 18.25 17.5 19.39 16.7 20.2 C15.89 21 14.75 21 12 21 L12 21 C9.25 21 8.11 21 7.3 20.2 C6.5 19.39 6.5 18.25 6.5 15.5 Z","className":"icon-body"}],["path",{"d":"M8.75 7.5a3.25 3.25 0 0 1 6.5 0M6.5 12H3.5M20.5 12h-3M6.5 17H3.5M20.5 17h-3"}]]; +export const Building2: IconNode = [["path",{"d":"M4.5 21V6a3 3 0 0 1 3-3h4.5a3 3 0 0 1 3 3v15Z","className":"icon-body"}],["path",{"d":"M15 10h3a2.5 2.5 0 0 1 2.5 2.5V21M2.5 21h19"}],["path",{"d":"M8.5 8.5h3M8.5 13h3","className":"icon-cut"}]]; +export const Calendar: IconNode = [["path",{"d":"M3 11.25 C3 7.75 3 6.3 4.02 5.27 C5.05 4.25 6.5 4.25 10 4.25 L14 4.25 C17.5 4.25 18.95 4.25 19.98 5.27 C21 6.3 21 7.75 21 11.25 L21 14.25 C21 17.75 21 19.2 19.98 20.23 C18.95 21.25 17.5 21.25 14 21.25 L10 21.25 C6.5 21.25 5.05 21.25 4.02 20.23 C3 19.2 3 17.75 3 14.25 Z","className":"icon-body"}],["path",{"d":"M8 2.75v3M16 2.75v3M3 9.75h18"}]]; +export const CalendarClock: IconNode = [["path",{"d":"M10.75 21.25 L6.88 21.25 C4.94 21.25 4.14 21.25 3.57 20.68 C3 20.11 3 19.31 3 17.38 L3 10.25 C3 7.25 3 6.01 3.88 5.13 C4.76 4.25 6 4.25 9 4.25 L18 4.25 C19.5 4.25 20.12 4.25 20.56 4.69 C21 5.13 21 5.75 21 7.25 L21 10.25"}],["path",{"d":"M8 2.75v3M16 2.75v3M3 9.75h7.25"}],["circle",{"cx":"17","cy":"17","r":"4.75","className":"icon-body"}],["path",{"d":"M17 15v2l1.25 1"}]]; +export const CalendarDays: IconNode = [["path",{"d":"M3 11.25 C3 7.75 3 6.3 4.02 5.27 C5.05 4.25 6.5 4.25 10 4.25 L14 4.25 C17.5 4.25 18.95 4.25 19.98 5.27 C21 6.3 21 7.75 21 11.25 L21 14.25 C21 17.75 21 19.2 19.98 20.23 C18.95 21.25 17.5 21.25 14 21.25 L10 21.25 C6.5 21.25 5.05 21.25 4.02 20.23 C3 19.2 3 17.75 3 14.25 Z","className":"icon-body"}],["path",{"d":"M8 2.75v3M16 2.75v3M3 9.75h18"}],["circle",{"fill":"currentColor","stroke":"none","cx":"8","cy":"15","r":"1.1"}],["circle",{"fill":"currentColor","stroke":"none","cx":"12","cy":"15","r":"1.1"}],["circle",{"fill":"currentColor","stroke":"none","cx":"16","cy":"15","r":"1.1"}]]; +export const CalendarX: IconNode = [["path",{"d":"M3 11.25 C3 7.75 3 6.3 4.02 5.27 C5.05 4.25 6.5 4.25 10 4.25 L14 4.25 C17.5 4.25 18.95 4.25 19.98 5.27 C21 6.3 21 7.75 21 11.25 L21 14.25 C21 17.75 21 19.2 19.98 20.23 C18.95 21.25 17.5 21.25 14 21.25 L10 21.25 C6.5 21.25 5.05 21.25 4.02 20.23 C3 19.2 3 17.75 3 14.25 Z","className":"icon-body"}],["path",{"d":"M8 2.75v3M16 2.75v3M3 9.75h18"}],["path",{"d":"m9.75 13.25 4.5 4.5M14.25 13.25l-4.5 4.5","className":"icon-cut"}]]; +export const Camera: IconNode = [["path",{"d":"M2.75 9.63 C2.75 8.44 2.75 7.95 3.1 7.6 C3.45 7.25 3.94 7.25 5.13 7.25 L6.5 7.25 C7 7.25 7.21 7.25 7.42 7.12 C7.63 6.99 7.72 6.8 7.95 6.36 L8.33 5.59 C8.66 4.92 8.8 4.64 9.12 4.45 C9.44 4.25 9.75 4.25 10.5 4.25 L13.5 4.25 C14.25 4.25 14.56 4.25 14.88 4.45 C15.2 4.64 15.34 4.92 15.67 5.59 L16.05 6.36 C16.28 6.8 16.37 6.99 16.58 7.12 C16.79 7.25 17 7.25 17.5 7.25 L18.88 7.25 C20.06 7.25 20.55 7.25 20.9 7.6 C21.25 7.95 21.25 8.44 21.25 9.63 L21.25 15.5 C21.25 17.75 21.25 18.68 20.59 19.34 C19.93 20 19 20 16.75 20 L7.25 20 C5 20 4.07 20 3.41 19.34 C2.75 18.68 2.75 17.75 2.75 15.5 Z","className":"icon-body"}],["circle",{"cx":"12","cy":"13.25","r":"3.5","className":"icon-cut"}]]; +export const ChartGantt: IconNode = [["path",{"d":"M3.5 3.5 L3.5 16.5 C3.5 18.5 3.5 19.33 4.08 19.92 C4.67 20.5 5.5 20.5 7.5 20.5 L20.5 20.5"}],["path",{"d":"M8.5 7.5h6.5M11 12h7M9.5 16.5h5"}]]; +export const Check: IconNode = [["path",{"d":"M5 13s2.6 4 3.75 4C10.4 17 19 7 19 7"}]]; +export const CheckCheck: IconNode = [["path",{"d":"M2.5 12.75s2.15 3.5 3.1 3.5C6.9 16.25 13.75 7.5 13.75 7.5M11.5 15.25c.5.6.95 1 1.35 1 1.3 0 7.65-8.75 7.65-8.75"}]]; +export const CheckCircle2: IconNode = [["circle",{"cx":"12","cy":"12","r":"9.25","className":"icon-body"}],["path",{"d":"M8.25 12.5s1.45 2.25 2.1 2.25C11.15 14.75 15.75 9.25 15.75 9.25"}]]; +export const ChevronDown: IconNode = [["path",{"d":"M18 9s-4.42 6-6 6-6-6-6-6"}]]; +export const ChevronLeft: IconNode = [["path",{"d":"M15 6s-6 4.42-6 6 6 6 6 6"}]]; +export const ChevronRight: IconNode = [["path",{"d":"M9 6s6 4.42 6 6-6 6-6 6"}]]; +export const ChevronUp: IconNode = [["path",{"d":"M6 15s4.42-6 6-6 6 6 6 6"}]]; +export const ChevronsUpDown: IconNode = [["path",{"d":"M8 9s3-3.5 4-3.5 4 3.5 4 3.5M8 15s3 3.5 4 3.5 4-3.5 4-3.5"}]]; +export const Circle: IconNode = [["circle",{"cx":"12","cy":"12","r":"9.25","className":"icon-body"}]]; +export const CircleDashed: IconNode = [["circle",{"cx":"12","cy":"12","r":"9.25","strokeDasharray":"2.4 4.865"}]]; +export const CircleDot: IconNode = [["circle",{"cx":"12","cy":"12","r":"9.25","className":"icon-body"}],["circle",{"fill":"currentColor","stroke":"none","cx":"12","cy":"12","r":"2.25"}]]; +export const CircleEqual: IconNode = [["circle",{"cx":"12","cy":"12","r":"9.25","className":"icon-body"}],["path",{"d":"M8.5 10h7M8.5 14h7"}]]; +export const CircleHelp: IconNode = [["circle",{"cx":"12","cy":"12","r":"9.25","className":"icon-body"}],["path",{"d":"M9.6 9.6a2.45 2.45 0 1 1 3.42 2.25c-.6.27-1.02.85-1.02 1.5v.4"}],["circle",{"fill":"currentColor","stroke":"none","cx":"12","cy":"16.75","r":"1.15"}]]; +export const CircleOff: IconNode = [["circle",{"cx":"12","cy":"12","r":"9.25","className":"icon-body"}],["path",{"d":"m3 3 18 18"}]]; +export const CirclePause: IconNode = [["circle",{"cx":"12","cy":"12","r":"9.25","className":"icon-body"}],["path",{"d":"M10 9v6M14 9v6"}]]; +export const CircleSlash: IconNode = [["circle",{"cx":"12","cy":"12","r":"9.25","className":"icon-body"}],["path",{"d":"m9 15 6-6"}]]; +export const CircleUser: IconNode = [["circle",{"cx":"12","cy":"12","r":"9.25","className":"icon-body"}],["circle",{"cx":"12","cy":"10","r":"3","className":"icon-cut"}],["path",{"d":"M6.6 18.4c1.3-1.85 3.2-2.8 5.4-2.8s4.1.95 5.4 2.8","className":"icon-cut"}]]; +export const Clock: IconNode = [["circle",{"cx":"12","cy":"12","r":"9.25","className":"icon-body"}],["path",{"d":"M12 7.5V12l3 2"}]]; +export const Clock3: IconNode = [["circle",{"cx":"12","cy":"12","r":"9.25","className":"icon-body"}],["path",{"d":"M12 7.5 L12 10.5 C12 11.25 12 11.56 12.22 11.78 C12.44 12 12.75 12 13.5 12 L15.75 12"}]]; +export const Cloud: IconNode = [["path",{"d":"M7 19.25h10a4.75 4.75 0 0 0 .85-9.42 6 6 0 0 0-11.7.02A4.7 4.7 0 0 0 7 19.25Z","className":"icon-body"}]]; +export const Code: IconNode = [["path",{"d":"M8 6.5S2.75 10.75 2.75 12 8 17.5 8 17.5M16 6.5s5.25 4.25 5.25 5.5S16 17.5 16 17.5"}]]; +export const Code2: IconNode = [["path",{"d":"M7.5 7S3 10.9 3 12s4.5 5 4.5 5M16.5 7s4.5 3.9 4.5 5-4.5 5-4.5 5M13.75 4.5l-3.5 15"}]]; +export const Coins: IconNode = [["circle",{"cx":"9","cy":"9","r":"6.25","className":"icon-body"}],["path",{"d":"M15.25 8.75a6.25 6.25 0 1 1-6.5 6.5"}]]; +export const Columns2: IconNode = [["path",{"d":"M3 10 C3 6.5 3 5.05 4.02 4.02 C5.05 3 6.5 3 10 3 L14 3 C17.5 3 18.95 3 19.98 4.02 C21 5.05 21 6.5 21 10 L21 14 C21 17.5 21 18.95 19.98 19.98 C18.95 21 17.5 21 14 21 L10 21 C6.5 21 5.05 21 4.02 19.98 C3 18.95 3 17.5 3 14 Z","className":"icon-body"}],["path",{"d":"M12 3v18","className":"icon-cut"}]]; +export const Columns3: IconNode = [["path",{"d":"M3 10 C3 6.5 3 5.05 4.02 4.02 C5.05 3 6.5 3 10 3 L14 3 C17.5 3 18.95 3 19.98 4.02 C21 5.05 21 6.5 21 10 L21 14 C21 17.5 21 18.95 19.98 19.98 C18.95 21 17.5 21 14 21 L10 21 C6.5 21 5.05 21 4.02 19.98 C3 18.95 3 17.5 3 14 Z","className":"icon-body"}],["path",{"d":"M9 3v18M15 3v18","className":"icon-cut"}]]; +export const Command: IconNode = [["path",{"d":"M15 6.75v10.5a2.75 2.75 0 1 0 2.75-2.75H6.25A2.75 2.75 0 1 0 9 17.25V6.75A2.75 2.75 0 1 0 6.25 9.5h11.5A2.75 2.75 0 1 0 15 6.75Z"}]]; +export const Compass: IconNode = [["circle",{"cx":"12","cy":"12","r":"9.25","className":"icon-body"}],["path",{"d":"M14.82 8.62 C15.29 8.44 15.48 8.36 15.56 8.44 C15.64 8.52 15.56 8.71 15.38 9.18 L13.97 12.67 C13.79 13.14 13.71 13.33 13.52 13.52 C13.33 13.71 13.14 13.79 12.67 13.97 L9.18 15.38 C8.71 15.56 8.52 15.64 8.44 15.56 C8.36 15.48 8.44 15.29 8.62 14.82 L10.03 11.33 C10.21 10.86 10.29 10.67 10.48 10.48 C10.67 10.29 10.86 10.21 11.33 10.03 Z","className":"icon-cut"}]]; +export const Component: IconNode = [["path",{"d":"M10.94 3.56 C11.47 3.03 11.69 2.81 12 2.81 C12.31 2.81 12.53 3.03 13.06 3.56 L14.19 4.69 C14.72 5.22 14.94 5.44 14.94 5.75 C14.94 6.06 14.72 6.28 14.19 6.81 L13.06 7.94 C12.53 8.47 12.31 8.69 12 8.69 C11.69 8.69 11.47 8.47 10.94 7.94 L9.81 6.81 C9.28 6.28 9.06 6.06 9.06 5.75 C9.06 5.44 9.28 5.22 9.81 4.69 Z","className":"icon-body"}],["path",{"d":"M17.19 9.81 C17.72 9.28 17.94 9.06 18.25 9.06 C18.56 9.06 18.78 9.28 19.31 9.81 L20.44 10.94 C20.97 11.47 21.19 11.69 21.19 12 C21.19 12.31 20.97 12.53 20.44 13.06 L19.31 14.19 C18.78 14.72 18.56 14.94 18.25 14.94 C17.94 14.94 17.72 14.72 17.19 14.19 L16.06 13.06 C15.53 12.53 15.31 12.31 15.31 12 C15.31 11.69 15.53 11.47 16.06 10.94 Z","className":"icon-body"}],["path",{"d":"M10.94 16.06 C11.47 15.53 11.69 15.31 12 15.31 C12.31 15.31 12.53 15.53 13.06 16.06 L14.19 17.19 C14.72 17.72 14.94 17.94 14.94 18.25 C14.94 18.56 14.72 18.78 14.19 19.31 L13.06 20.44 C12.53 20.97 12.31 21.19 12 21.19 C11.69 21.19 11.47 20.97 10.94 20.44 L9.81 19.31 C9.28 18.78 9.06 18.56 9.06 18.25 C9.06 17.94 9.28 17.72 9.81 17.19 Z","className":"icon-body"}],["path",{"d":"M4.69 9.81 C5.22 9.28 5.44 9.06 5.75 9.06 C6.06 9.06 6.28 9.28 6.81 9.81 L7.94 10.94 C8.47 11.47 8.69 11.69 8.69 12 C8.69 12.31 8.47 12.53 7.94 13.06 L6.81 14.19 C6.28 14.72 6.06 14.94 5.75 14.94 C5.44 14.94 5.22 14.72 4.69 14.19 L3.56 13.06 C3.03 12.53 2.81 12.31 2.81 12 C2.81 11.69 3.03 11.47 3.56 10.94 Z","className":"icon-body"}]]; +export const Copy: IconNode = [["path",{"d":"M3 13.5 L3 8.25 C3 5.63 3 4.54 3.77 3.77 C4.54 3 5.63 3 8.25 3 L13.5 3"}],["path",{"d":"M7.75 13.75 C7.75 10.75 7.75 9.51 8.63 8.63 C9.51 7.75 10.75 7.75 13.75 7.75 L15.25 7.75 C18.25 7.75 19.49 7.75 20.37 8.63 C21.25 9.51 21.25 10.75 21.25 13.75 L21.25 15.25 C21.25 18.25 21.25 19.49 20.37 20.37 C19.49 21.25 18.25 21.25 15.25 21.25 L13.75 21.25 C10.75 21.25 9.51 21.25 8.63 20.37 C7.75 19.49 7.75 18.25 7.75 15.25 Z","className":"icon-body"}]]; +export const CornerDownLeft: IconNode = [["path",{"d":"M19 4.5 L19 10 C19 12.5 19 13.54 18.27 14.27 C17.54 15 16.5 15 14 15 L5.5 15"}],["path",{"d":"M9.5 10.5S5 14.25 5 15s4.5 4.5 4.5 4.5"}]]; +export const CornerDownRight: IconNode = [["path",{"d":"M5 4.5 L5 10 C5 12.5 5 13.54 5.73 14.27 C6.46 15 7.5 15 10 15 L18.5 15"}],["path",{"d":"M14.5 10.5s4.5 3.75 4.5 4.5-4.5 4.5-4.5 4.5"}]]; +export const CornerLeftUp: IconNode = [["path",{"d":"M20 19.5 L14 19.5 C11.5 19.5 10.46 19.5 9.73 18.77 C9 18.04 9 17 9 14.5 L9 4.75"}],["path",{"d":"M4.5 9C4.5 9 7.82 4.5 9 4.5C10.18 4.5 13.5 9 13.5 9"}]]; +export const CornerUpLeft: IconNode = [["path",{"d":"M19.5 20 L19.5 14 C19.5 11.5 19.5 10.46 18.77 9.73 C18.04 9 17 9 14.5 9 L4.75 9"}],["path",{"d":"M9 13.5C9 13.5 4.5 10.18 4.5 9C4.5 7.82 9 4.5 9 4.5"}]]; +export const Cpu: IconNode = [["path",{"d":"M5 10 C5 7.5 5 6.46 5.73 5.73 C6.46 5 7.5 5 10 5 L14 5 C16.5 5 17.54 5 18.27 5.73 C19 6.46 19 7.5 19 10 L19 14 C19 16.5 19 17.54 18.27 18.27 C17.54 19 16.5 19 14 19 L10 19 C7.5 19 6.46 19 5.73 18.27 C5 17.54 5 16.5 5 14 Z","className":"icon-body"}],["path",{"d":"M9.25 10.75 C9.25 10 9.25 9.69 9.47 9.47 C9.69 9.25 10 9.25 10.75 9.25 L13.25 9.25 C14 9.25 14.31 9.25 14.53 9.47 C14.75 9.69 14.75 10 14.75 10.75 L14.75 13.25 C14.75 14 14.75 14.31 14.53 14.53 C14.31 14.75 14 14.75 13.25 14.75 L10.75 14.75 C10 14.75 9.69 14.75 9.47 14.53 C9.25 14.31 9.25 14 9.25 13.25 Z"}],["path",{"d":"M9.5 2.5V5M14.5 2.5V5M9.5 19v2.5M14.5 19v2.5M2.5 9.5H5M2.5 14.5H5M19 9.5h2.5M19 14.5h2.5"}]]; +export const CreditCard: IconNode = [["path",{"d":"M2.5 10 C2.5 7.5 2.5 6.46 3.23 5.73 C3.96 5 5 5 7.5 5 L16.5 5 C19 5 20.04 5 20.77 5.73 C21.5 6.46 21.5 7.5 21.5 10 L21.5 14 C21.5 16.5 21.5 17.54 20.77 18.27 C20.04 19 19 19 16.5 19 L7.5 19 C5 19 3.96 19 3.23 18.27 C2.5 17.54 2.5 16.5 2.5 14 Z","className":"icon-body"}],["path",{"d":"M2.5 10h19M6.5 15h3"}]]; +export const Crown: IconNode = [["path",{"d":"M3.45 8.18 C3.35 7.59 3.31 7.35 3.41 7.29 C3.51 7.23 3.7 7.4 4.14 7.8 L7.11 10.45 C7.55 10.85 7.74 11.02 7.96 10.98 C8.18 10.95 8.31 10.73 8.61 10.22 L11.39 5.53 C11.69 5.02 11.82 4.8 12 4.8 C12.18 4.8 12.31 5.02 12.61 5.53 L15.39 10.22 C15.69 10.73 15.82 10.95 16.04 10.98 C16.26 11.02 16.45 10.85 16.89 10.45 L19.86 7.8 C20.3 7.4 20.49 7.23 20.59 7.29 C20.69 7.35 20.65 7.59 20.55 8.18 L19.41 15.03 C19.21 16.27 19.12 16.78 18.7 17.14 C18.27 17.5 17.75 17.5 16.5 17.5 L7.5 17.5 C6.25 17.5 5.73 17.5 5.3 17.14 C4.88 16.78 4.79 16.27 4.59 15.03 Z","className":"icon-body"}],["path",{"d":"M5.5 21h13"}]]; +export const Database: IconNode = [["ellipse",{"cx":"12","cy":"5.5","rx":"8","ry":"2.75","className":"icon-body"}],["path",{"d":"M4 5.5v13c0 1.5 3.6 2.75 8 2.75s8-1.25 8-2.75v-13M4 12c0 1.5 3.6 2.75 8 2.75s8-1.25 8-2.75"}]]; +export const Delete: IconNode = [["path",{"d":"M7.64 6.47 C8.32 5.73 8.6 5.43 9.09 5.21 C9.59 5 10 5 11 5 L17.25 5 C19.25 5 20.08 5 20.67 5.58 C21.25 6.17 21.25 7 21.25 9 L21.25 15 C21.25 17 21.25 17.83 20.67 18.42 C20.08 19 19.25 19 17.25 19 L11 19 C10 19 9.59 19 9.09 18.79 C8.6 18.57 8.32 18.27 7.64 17.53 L3.52 13.1 C3.01 12.55 2.8 12.32 2.8 12 C2.8 11.68 3.01 11.45 3.52 10.9 Z","className":"icon-body"}],["path",{"d":"m12.75 9.5 5 5M17.75 9.5l-5 5","className":"icon-cut"}]]; +export const Dices: IconNode = [["path",{"d":"M9 8.75V7.25a4.5 4.5 0 0 1 4.5-4.5h3.25a4.5 4.5 0 0 1 4.5 4.5v3.25a4.5 4.5 0 0 1-4.5 4.5h-1.5"}],["circle",{"fill":"currentColor","stroke":"none","cx":"17.25","cy":"6.75","r":"1.2"}],["path",{"d":"M2.75 13.25 C2.75 11 2.75 10.07 3.41 9.41 C4.07 8.75 5 8.75 7.25 8.75 L10.75 8.75 C13 8.75 13.93 8.75 14.59 9.41 C15.25 10.07 15.25 11 15.25 13.25 L15.25 16.75 C15.25 19 15.25 19.93 14.59 20.59 C13.93 21.25 13 21.25 10.75 21.25 L7.25 21.25 C5 21.25 4.07 21.25 3.41 20.59 C2.75 19.93 2.75 19 2.75 16.75 Z","className":"icon-body"}],["circle",{"fill":"currentColor","stroke":"none","cx":"6.75","cy":"12.75","r":"1.2"}],["circle",{"fill":"currentColor","stroke":"none","cx":"11.25","cy":"17.25","r":"1.2"}]]; +export const Download: IconNode = [["path",{"d":"M12 3.5v11M7.5 10.5s3.32 4.5 4.5 4.5 4.5-4.5 4.5-4.5"}],["path",{"d":"M3.5 15 L3.5 17.75 C3.5 19.13 3.5 19.69 3.9 20.1 C4.31 20.5 4.88 20.5 6.25 20.5 L17.75 20.5 C19.13 20.5 19.69 20.5 20.1 20.1 C20.5 19.69 20.5 19.13 20.5 17.75 L20.5 15"}]]; +export const ExternalLink: IconNode = [["path",{"d":"M11 3.25 L7.13 3.25 C5.19 3.25 4.39 3.25 3.82 3.82 C3.25 4.39 3.25 5.19 3.25 7.13 L3.25 13.75 C3.25 17.25 3.25 18.7 4.27 19.73 C5.3 20.75 6.75 20.75 10.25 20.75 L16.88 20.75 C18.81 20.75 19.61 20.75 20.18 20.18 C20.75 19.61 20.75 18.81 20.75 16.88 L20.75 13"}],["path",{"d":"M14.5 3.25h6.25V9.5M20.75 3.25 12.5 11.5"}]]; +export const Eye: IconNode = [["path",{"d":"M2.75 12C4.6 7.75 8 5.5 12 5.5s7.4 2.25 9.25 6.5c-1.85 4.25-5.25 6.5-9.25 6.5S4.6 16.25 2.75 12Z","className":"icon-body"}],["circle",{"cx":"12","cy":"12","r":"3"}]]; +export const EyeOff: IconNode = [["path",{"d":"M2.75 12C4.6 7.75 8 5.5 12 5.5s7.4 2.25 9.25 6.5c-1.85 4.25-5.25 6.5-9.25 6.5S4.6 16.25 2.75 12Z","className":"icon-body"}],["circle",{"cx":"12","cy":"12","r":"3"}],["path",{"d":"m4 4 16 16"}]]; +export const FastForward: IconNode = [["path",{"d":"M3 7.5 C3 6.75 3 6.44 3.18 6.35 C3.36 6.25 3.61 6.43 4.23 6.87 L10.27 11.13 C10.89 11.57 11.14 11.75 11.14 12 C11.14 12.25 10.89 12.43 10.27 12.87 L4.23 17.13 C3.61 17.57 3.36 17.75 3.18 17.65 C3 17.56 3 17.25 3 16.5 Z","className":"icon-body"}],["path",{"d":"M12.5 7.5 C12.5 6.75 12.5 6.44 12.68 6.35 C12.86 6.25 13.11 6.43 13.73 6.87 L19.77 11.13 C20.39 11.57 20.64 11.75 20.64 12 C20.64 12.25 20.39 12.43 19.77 12.87 L13.73 17.13 C13.11 17.57 12.86 17.75 12.68 17.65 C12.5 17.56 12.5 17.25 12.5 16.5 Z","className":"icon-body"}]]; +export const File: IconNode = [["path",{"d":"M4.75 7.25 C4.75 5 4.75 4.07 5.41 3.41 C6.07 2.75 7 2.75 9.25 2.75 L12.55 2.75 C13.15 2.75 13.4 2.75 13.7 2.87 C14 3 14.17 3.17 14.6 3.6 L18.4 7.4 C18.83 7.83 19 8 19.13 8.3 C19.25 8.6 19.25 8.85 19.25 9.45 L19.25 16.75 C19.25 19 19.25 19.93 18.59 20.59 C17.93 21.25 17 21.25 14.75 21.25 L9.25 21.25 C7 21.25 6.07 21.25 5.41 20.59 C4.75 19.93 4.75 19 4.75 16.75 Z","className":"icon-body"}],["path",{"d":"M13.5 3v3.25c0 1.1.9 2 2 2h3.5"}]]; +export const FileArchive: IconNode = [["path",{"d":"M4.75 7.25 C4.75 5 4.75 4.07 5.41 3.41 C6.07 2.75 7 2.75 9.25 2.75 L12.55 2.75 C13.15 2.75 13.4 2.75 13.7 2.87 C14 3 14.17 3.17 14.6 3.6 L18.4 7.4 C18.83 7.83 19 8 19.13 8.3 C19.25 8.6 19.25 8.85 19.25 9.45 L19.25 16.75 C19.25 19 19.25 19.93 18.59 20.59 C17.93 21.25 17 21.25 14.75 21.25 L9.25 21.25 C7 21.25 6.07 21.25 5.41 20.59 C4.75 19.93 4.75 19 4.75 16.75 Z","className":"icon-body"}],["path",{"d":"M13.5 3v3.25c0 1.1.9 2 2 2h3.5"}],["path",{"d":"M10.25 3v1.75M10.25 7.25V9"}],["path",{"d":"M8.75 12.7 C8.75 12.1 8.75 11.85 8.93 11.68 C9.1 11.5 9.35 11.5 9.95 11.5 L10.55 11.5 C11.15 11.5 11.4 11.5 11.57 11.68 C11.75 11.85 11.75 12.1 11.75 12.7 L11.75 14.8 C11.75 15.4 11.75 15.65 11.57 15.82 C11.4 16 11.15 16 10.55 16 L9.95 16 C9.35 16 9.1 16 8.93 15.82 C8.75 15.65 8.75 15.4 8.75 14.8 Z"}]]; +export const FileAudio: IconNode = [["path",{"d":"M4.75 7.25 C4.75 5 4.75 4.07 5.41 3.41 C6.07 2.75 7 2.75 9.25 2.75 L12.55 2.75 C13.15 2.75 13.4 2.75 13.7 2.87 C14 3 14.17 3.17 14.6 3.6 L18.4 7.4 C18.83 7.83 19 8 19.13 8.3 C19.25 8.6 19.25 8.85 19.25 9.45 L19.25 16.75 C19.25 19 19.25 19.93 18.59 20.59 C17.93 21.25 17 21.25 14.75 21.25 L9.25 21.25 C7 21.25 6.07 21.25 5.41 20.59 C4.75 19.93 4.75 19 4.75 16.75 Z","className":"icon-body"}],["path",{"d":"M13.5 3v3.25c0 1.1.9 2 2 2h3.5"}],["circle",{"cx":"10.25","cy":"16.25","r":"1.75"}],["path",{"d":"M12 16.25v-5l3 1.25"}]]; +export const FileCode: IconNode = [["path",{"d":"M4.75 7.25 C4.75 5 4.75 4.07 5.41 3.41 C6.07 2.75 7 2.75 9.25 2.75 L12.55 2.75 C13.15 2.75 13.4 2.75 13.7 2.87 C14 3 14.17 3.17 14.6 3.6 L18.4 7.4 C18.83 7.83 19 8 19.13 8.3 C19.25 8.6 19.25 8.85 19.25 9.45 L19.25 16.75 C19.25 19 19.25 19.93 18.59 20.59 C17.93 21.25 17 21.25 14.75 21.25 L9.25 21.25 C7 21.25 6.07 21.25 5.41 20.59 C4.75 19.93 4.75 19 4.75 16.75 Z","className":"icon-body"}],["path",{"d":"M13.5 3v3.25c0 1.1.9 2 2 2h3.5"}],["path",{"d":"M10.25 12.25s-2 1.7-2 2.5 2 2.5 2 2.5M13.75 12.25s2 1.7 2 2.5-2 2.5-2 2.5"}]]; +export const FileImage: IconNode = [["path",{"d":"M4.75 7.25 C4.75 5 4.75 4.07 5.41 3.41 C6.07 2.75 7 2.75 9.25 2.75 L12.55 2.75 C13.15 2.75 13.4 2.75 13.7 2.87 C14 3 14.17 3.17 14.6 3.6 L18.4 7.4 C18.83 7.83 19 8 19.13 8.3 C19.25 8.6 19.25 8.85 19.25 9.45 L19.25 16.75 C19.25 19 19.25 19.93 18.59 20.59 C17.93 21.25 17 21.25 14.75 21.25 L9.25 21.25 C7 21.25 6.07 21.25 5.41 20.59 C4.75 19.93 4.75 19 4.75 16.75 Z","className":"icon-body"}],["path",{"d":"M13.5 3v3.25c0 1.1.9 2 2 2h3.5"}],["circle",{"fill":"currentColor","stroke":"none","cx":"9.5","cy":"12.25","r":"1.35"}],["path",{"d":"m7.5 18.25 2.4-2.4a1.5 1.5 0 0 1 2.12 0l.98.98 1.18-1.18a1.5 1.5 0 0 1 2.12 0l.95.95"}]]; +export const FilePen: IconNode = [["path",{"d":"M4.75 7.25 C4.75 5 4.75 4.07 5.41 3.41 C6.07 2.75 7 2.75 9.25 2.75 L12.55 2.75 C13.15 2.75 13.4 2.75 13.7 2.87 C14 3 14.17 3.17 14.6 3.6 L18.4 7.4 C18.83 7.83 19 8 19.13 8.3 C19.25 8.6 19.25 8.85 19.25 9.45 L19.25 16.75 C19.25 19 19.25 19.93 18.59 20.59 C17.93 21.25 17 21.25 14.75 21.25 L9.25 21.25 C7 21.25 6.07 21.25 5.41 20.59 C4.75 19.93 4.75 19 4.75 16.75 Z","className":"icon-body"}],["path",{"d":"M13.5 3v3.25c0 1.1.9 2 2 2h3.5"}],["path",{"d":"M9 18.25l.5-2.25 4.75-4.75a1.24 1.24 0 0 1 1.75 1.75l-4.75 4.75Z"}]]; +export const FilePlus: IconNode = [["path",{"d":"M4.75 7.25 C4.75 5 4.75 4.07 5.41 3.41 C6.07 2.75 7 2.75 9.25 2.75 L12.55 2.75 C13.15 2.75 13.4 2.75 13.7 2.87 C14 3 14.17 3.17 14.6 3.6 L18.4 7.4 C18.83 7.83 19 8 19.13 8.3 C19.25 8.6 19.25 8.85 19.25 9.45 L19.25 16.75 C19.25 19 19.25 19.93 18.59 20.59 C17.93 21.25 17 21.25 14.75 21.25 L9.25 21.25 C7 21.25 6.07 21.25 5.41 20.59 C4.75 19.93 4.75 19 4.75 16.75 Z","className":"icon-body"}],["path",{"d":"M13.5 3v3.25c0 1.1.9 2 2 2h3.5"}],["path",{"d":"M12 11.5v6M9 14.5h6"}]]; +export const FileQuestion: IconNode = [["path",{"d":"M4.75 7.25 C4.75 5 4.75 4.07 5.41 3.41 C6.07 2.75 7 2.75 9.25 2.75 L12.55 2.75 C13.15 2.75 13.4 2.75 13.7 2.87 C14 3 14.17 3.17 14.6 3.6 L18.4 7.4 C18.83 7.83 19 8 19.13 8.3 C19.25 8.6 19.25 8.85 19.25 9.45 L19.25 16.75 C19.25 19 19.25 19.93 18.59 20.59 C17.93 21.25 17 21.25 14.75 21.25 L9.25 21.25 C7 21.25 6.07 21.25 5.41 20.59 C4.75 19.93 4.75 19 4.75 16.75 Z","className":"icon-body"}],["path",{"d":"M13.5 3v3.25c0 1.1.9 2 2 2h3.5"}],["path",{"d":"M10 12.25a2.1 2.1 0 1 1 2.9 1.94c-.5.21-.9.7-.9 1.25v.31"}],["circle",{"fill":"currentColor","stroke":"none","cx":"12","cy":"18.1","r":"1"}]]; +export const FileSearch: IconNode = [["path",{"d":"M4.75 7.25 C4.75 5 4.75 4.07 5.41 3.41 C6.07 2.75 7 2.75 9.25 2.75 L12.55 2.75 C13.15 2.75 13.4 2.75 13.7 2.87 C14 3 14.17 3.17 14.6 3.6 L18.4 7.4 C18.83 7.83 19 8 19.13 8.3 C19.25 8.6 19.25 8.85 19.25 9.45 L19.25 16.75 C19.25 19 19.25 19.93 18.59 20.59 C17.93 21.25 17 21.25 14.75 21.25 L9.25 21.25 C7 21.25 6.07 21.25 5.41 20.59 C4.75 19.93 4.75 19 4.75 16.75 Z","className":"icon-body"}],["path",{"d":"M13.5 3v3.25c0 1.1.9 2 2 2h3.5"}],["circle",{"cx":"11","cy":"14","r":"2.5"}],["path",{"d":"m12.85 15.85 2.15 2.15"}]]; +export const FileSpreadsheet: IconNode = [["path",{"d":"M4.75 7.25 C4.75 5 4.75 4.07 5.41 3.41 C6.07 2.75 7 2.75 9.25 2.75 L12.55 2.75 C13.15 2.75 13.4 2.75 13.7 2.87 C14 3 14.17 3.17 14.6 3.6 L18.4 7.4 C18.83 7.83 19 8 19.13 8.3 C19.25 8.6 19.25 8.85 19.25 9.45 L19.25 16.75 C19.25 19 19.25 19.93 18.59 20.59 C17.93 21.25 17 21.25 14.75 21.25 L9.25 21.25 C7 21.25 6.07 21.25 5.41 20.59 C4.75 19.93 4.75 19 4.75 16.75 Z","className":"icon-body"}],["path",{"d":"M13.5 3v3.25c0 1.1.9 2 2 2h3.5"}],["path",{"d":"M8.25 13.25h7.5M8.25 17h7.5M12 11.5v7"}]]; +export const FileText: IconNode = [["path",{"d":"M4.75 7.25 C4.75 5 4.75 4.07 5.41 3.41 C6.07 2.75 7 2.75 9.25 2.75 L12.55 2.75 C13.15 2.75 13.4 2.75 13.7 2.87 C14 3 14.17 3.17 14.6 3.6 L18.4 7.4 C18.83 7.83 19 8 19.13 8.3 C19.25 8.6 19.25 8.85 19.25 9.45 L19.25 16.75 C19.25 19 19.25 19.93 18.59 20.59 C17.93 21.25 17 21.25 14.75 21.25 L9.25 21.25 C7 21.25 6.07 21.25 5.41 20.59 C4.75 19.93 4.75 19 4.75 16.75 Z","className":"icon-body"}],["path",{"d":"M13.5 3v3.25c0 1.1.9 2 2 2h3.5"}],["path",{"d":"M8.5 13h7M8.5 16.75h4.5"}]]; +export const FileVideo: IconNode = [["path",{"d":"M4.75 7.25 C4.75 5 4.75 4.07 5.41 3.41 C6.07 2.75 7 2.75 9.25 2.75 L12.55 2.75 C13.15 2.75 13.4 2.75 13.7 2.87 C14 3 14.17 3.17 14.6 3.6 L18.4 7.4 C18.83 7.83 19 8 19.13 8.3 C19.25 8.6 19.25 8.85 19.25 9.45 L19.25 16.75 C19.25 19 19.25 19.93 18.59 20.59 C17.93 21.25 17 21.25 14.75 21.25 L9.25 21.25 C7 21.25 6.07 21.25 5.41 20.59 C4.75 19.93 4.75 19 4.75 16.75 Z","className":"icon-body"}],["path",{"d":"M13.5 3v3.25c0 1.1.9 2 2 2h3.5"}],["path",{"d":"M9.75 12.75 C9.75 12.25 9.75 12.04 9.88 11.97 C10.01 11.89 10.19 11.99 10.63 12.23 L14.37 14.27 C14.81 14.51 14.99 14.61 14.99 14.75 C14.99 14.89 14.81 14.99 14.37 15.23 L10.63 17.27 C10.19 17.51 10.01 17.61 9.88 17.53 C9.75 17.46 9.75 17.25 9.75 16.75 Z"}]]; +export const Filter: IconNode = [["path",{"d":"M3.75 6.5h16.5M7 12h10M10.25 17.5h3.5"}]]; +export const FilterX: IconNode = [["path",{"d":"M3.75 6.5h16.5M7 12h7M10.25 17.5h2M16 14.25l4.5 4.5M20.5 14.25 16 18.75"}]]; +export const Flag: IconNode = [["path",{"d":"M4.75 14.5c4.5-3 7.5 2.5 14.5-1V4.5c-7 3.5-10-2-14.5 1Z","className":"icon-body"}],["path",{"d":"M4.75 21.25V4.5"}]]; +export const Folder: IconNode = [["path",{"d":"M2.75 7 C2.75 5.38 2.75 4.7 3.22 4.22 C3.7 3.75 4.38 3.75 6 3.75 L7.75 3.75 C8.5 3.75 8.81 3.75 9.18 3.91 C9.54 4.08 9.75 4.31 10.25 4.86 L10.5 5.14 C11 5.69 11.21 5.92 11.57 6.09 C11.94 6.25 12.25 6.25 13 6.25 L16.75 6.25 C19 6.25 19.93 6.25 20.59 6.91 C21.25 7.57 21.25 8.5 21.25 10.75 L21.25 14.25 C21.25 17.25 21.25 18.49 20.37 19.37 C19.49 20.25 18.25 20.25 15.25 20.25 L8.75 20.25 C5.75 20.25 4.51 20.25 3.63 19.37 C2.75 18.49 2.75 17.25 2.75 14.25 Z","className":"icon-body"}]]; +export const FolderGit: IconNode = [["path",{"d":"M2.75 7 C2.75 5.38 2.75 4.7 3.22 4.22 C3.7 3.75 4.38 3.75 6 3.75 L7.75 3.75 C8.5 3.75 8.81 3.75 9.18 3.91 C9.54 4.08 9.75 4.31 10.25 4.86 L10.5 5.14 C11 5.69 11.21 5.92 11.57 6.09 C11.94 6.25 12.25 6.25 13 6.25 L16.75 6.25 C19 6.25 19.93 6.25 20.59 6.91 C21.25 7.57 21.25 8.5 21.25 10.75 L21.25 14.25 C21.25 17.25 21.25 18.49 20.37 19.37 C19.49 20.25 18.25 20.25 15.25 20.25 L8.75 20.25 C5.75 20.25 4.51 20.25 3.63 19.37 C2.75 18.49 2.75 17.25 2.75 14.25 Z","className":"icon-body"}],["circle",{"cx":"12","cy":"13.25","r":"2.25","className":"icon-cut"}],["path",{"d":"M6.75 13.25h3M14.25 13.25h3","className":"icon-cut"}]]; +export const FolderInput: IconNode = [["path",{"d":"M2.75 7 C2.75 5.38 2.75 4.7 3.22 4.22 C3.7 3.75 4.38 3.75 6 3.75 L7.75 3.75 C8.5 3.75 8.81 3.75 9.18 3.91 C9.54 4.08 9.75 4.31 10.25 4.86 L10.5 5.14 C11 5.69 11.21 5.92 11.57 6.09 C11.94 6.25 12.25 6.25 13 6.25 L16.75 6.25 C19 6.25 19.93 6.25 20.59 6.91 C21.25 7.57 21.25 8.5 21.25 10.75 L21.25 14.25 C21.25 17.25 21.25 18.49 20.37 19.37 C19.49 20.25 18.25 20.25 15.25 20.25 L8.75 20.25 C5.75 20.25 4.51 20.25 3.63 19.37 C2.75 18.49 2.75 17.25 2.75 14.25 Z","className":"icon-body"}],["path",{"d":"M8 13.25h7.5M13 10.5s2.75 2.2 2.75 2.75S13 16 13 16","className":"icon-cut"}]]; +export const FolderKanban: IconNode = [["path",{"d":"M2.75 7 C2.75 5.38 2.75 4.7 3.22 4.22 C3.7 3.75 4.38 3.75 6 3.75 L7.75 3.75 C8.5 3.75 8.81 3.75 9.18 3.91 C9.54 4.08 9.75 4.31 10.25 4.86 L10.5 5.14 C11 5.69 11.21 5.92 11.57 6.09 C11.94 6.25 12.25 6.25 13 6.25 L16.75 6.25 C19 6.25 19.93 6.25 20.59 6.91 C21.25 7.57 21.25 8.5 21.25 10.75 L21.25 14.25 C21.25 17.25 21.25 18.49 20.37 19.37 C19.49 20.25 18.25 20.25 15.25 20.25 L8.75 20.25 C5.75 20.25 4.51 20.25 3.63 19.37 C2.75 18.49 2.75 17.25 2.75 14.25 Z","className":"icon-body"}],["path",{"d":"M8.5 11.5v4.5M12 11.5v2.25M15.5 11.5v4.5","className":"icon-cut"}]]; +export const FolderMinus: IconNode = [["path",{"d":"M2.75 7 C2.75 5.38 2.75 4.7 3.22 4.22 C3.7 3.75 4.38 3.75 6 3.75 L7.75 3.75 C8.5 3.75 8.81 3.75 9.18 3.91 C9.54 4.08 9.75 4.31 10.25 4.86 L10.5 5.14 C11 5.69 11.21 5.92 11.57 6.09 C11.94 6.25 12.25 6.25 13 6.25 L16.75 6.25 C19 6.25 19.93 6.25 20.59 6.91 C21.25 7.57 21.25 8.5 21.25 10.75 L21.25 14.25 C21.25 17.25 21.25 18.49 20.37 19.37 C19.49 20.25 18.25 20.25 15.25 20.25 L8.75 20.25 C5.75 20.25 4.51 20.25 3.63 19.37 C2.75 18.49 2.75 17.25 2.75 14.25 Z","className":"icon-body"}],["path",{"d":"M9 13.25h6","className":"icon-cut"}]]; +export const FolderOpen: IconNode = [["path",{"d":"M2.75 19.5 L2.75 7 C2.75 5.38 2.75 4.7 3.22 4.22 C3.7 3.75 4.38 3.75 6 3.75 L7.75 3.75 C8.5 3.75 8.81 3.75 9.18 3.91 C9.54 4.08 9.75 4.31 10.25 4.86 L10.5 5.14 C11 5.69 11.21 5.92 11.57 6.09 C11.94 6.25 12.25 6.25 13 6.25 L16 6.25 C17.13 6.25 17.59 6.25 17.92 6.58 C18.25 6.91 18.25 7.38 18.25 8.5 L18.25 10.75"}],["path",{"d":"M4.75 20.25 C3.75 20.25 3.34 20.25 3.14 19.97 C2.94 19.7 3.08 19.31 3.41 18.36 L5.17 13.36 C5.59 12.18 5.76 11.69 6.24 11.34 C6.73 11 7.25 11 8.5 11 L19.25 11 C20.5 11 21.02 11 21.26 11.34 C21.51 11.69 21.34 12.18 20.92 13.36 L19.49 17.42 C19 18.83 18.79 19.42 18.21 19.84 C17.62 20.25 17 20.25 15.5 20.25 Z","className":"icon-body"}]]; +export const FolderPlus: IconNode = [["path",{"d":"M2.75 7 C2.75 5.38 2.75 4.7 3.22 4.22 C3.7 3.75 4.38 3.75 6 3.75 L7.75 3.75 C8.5 3.75 8.81 3.75 9.18 3.91 C9.54 4.08 9.75 4.31 10.25 4.86 L10.5 5.14 C11 5.69 11.21 5.92 11.57 6.09 C11.94 6.25 12.25 6.25 13 6.25 L16.75 6.25 C19 6.25 19.93 6.25 20.59 6.91 C21.25 7.57 21.25 8.5 21.25 10.75 L21.25 14.25 C21.25 17.25 21.25 18.49 20.37 19.37 C19.49 20.25 18.25 20.25 15.25 20.25 L8.75 20.25 C5.75 20.25 4.51 20.25 3.63 19.37 C2.75 18.49 2.75 17.25 2.75 14.25 Z","className":"icon-body"}],["path",{"d":"M12 10.25v6M9 13.25h6","className":"icon-cut"}]]; +export const Frame: IconNode = [["path",{"d":"M2.75 7h18.5M2.75 17h18.5M7 2.75v18.5M17 2.75v18.5"}]]; +export const Gauge: IconNode = [["path",{"d":"M4.25 18.5a9.25 9.25 0 1 1 15.5 0"}],["path",{"d":"m12 14 3.75-3.75"}]]; +export const GitBranch: IconNode = [["circle",{"cx":"6.5","cy":"18","r":"2.75"}],["circle",{"cx":"17.5","cy":"6.5","r":"2.75"}],["path",{"d":"M6.5 3v12.25M17.5 9.25c0 4.8-3.45 8.75-8.25 8.75"}]]; +export const GitMerge: IconNode = [["circle",{"cx":"6.5","cy":"5.75","r":"2.75"}],["circle",{"cx":"17.5","cy":"17.25","r":"2.75"}],["path",{"d":"M6.5 8.5v12.75M6.5 8.5c0 4.8 3.45 8.75 8.25 8.75"}]]; +export const GitPullRequest: IconNode = [["circle",{"cx":"6.25","cy":"6","r":"2.75"}],["circle",{"cx":"17.75","cy":"18","r":"2.75"}],["path",{"d":"M6.25 8.75v12.5M12.75 6h2.5a2.5 2.5 0 0 1 2.5 2.5v6.75M15 3.5s-2.25 1.85-2.25 2.5S15 8.5 15 8.5"}]]; +export const GitPullRequestClosed: IconNode = [["circle",{"cx":"6.25","cy":"6","r":"2.75"}],["circle",{"cx":"17.75","cy":"18","r":"2.75"}],["path",{"d":"M6.25 8.75v12.5M17.75 15.25V11M15.5 3.5 20 8M20 3.5 15.5 8"}]]; +export const GitPullRequestDraft: IconNode = [["circle",{"cx":"6.25","cy":"6","r":"2.75"}],["circle",{"cx":"17.75","cy":"18","r":"2.75"}],["path",{"d":"M6.25 8.75v12.5"}],["circle",{"fill":"currentColor","stroke":"none","cx":"17.75","cy":"6","r":"1.3"}],["circle",{"fill":"currentColor","stroke":"none","cx":"17.75","cy":"11","r":"1.3"}]]; +export const Globe: IconNode = [["circle",{"cx":"12","cy":"12","r":"9.25","className":"icon-body"}],["path",{"d":"M2.75 12h18.5"}],["path",{"d":"M12 2.75c-2.6 2.6-3.9 5.7-3.9 9.25s1.3 6.65 3.9 9.25c2.6-2.6 3.9-5.7 3.9-9.25S14.6 5.35 12 2.75Z"}]]; +export const GraduationCap: IconNode = [["path",{"d":"M10.66 4.67 C11.33 4.34 11.61 4.2 12 4.2 C12.39 4.2 12.67 4.34 13.34 4.67 L20.66 8.33 C21.33 8.66 21.61 8.8 21.61 9 C21.61 9.2 21.33 9.34 20.66 9.67 L13.34 13.33 C12.67 13.66 12.39 13.8 12 13.8 C11.61 13.8 11.33 13.66 10.66 13.33 L3.34 9.67 C2.67 9.34 2.39 9.2 2.39 9 C2.39 8.8 2.67 8.66 3.34 8.33 Z","className":"icon-body"}],["path",{"d":"M6 11.25v4.25c0 1.65 2.7 3.25 6 3.25s6-1.6 6-3.25v-4.25M22 9v5.5"}]]; +export const GripVertical: IconNode = [["circle",{"fill":"currentColor","stroke":"none","cx":"9","cy":"5","r":"1.5"}],["circle",{"fill":"currentColor","stroke":"none","cx":"15","cy":"5","r":"1.5"}],["circle",{"fill":"currentColor","stroke":"none","cx":"9","cy":"12","r":"1.5"}],["circle",{"fill":"currentColor","stroke":"none","cx":"15","cy":"12","r":"1.5"}],["circle",{"fill":"currentColor","stroke":"none","cx":"9","cy":"19","r":"1.5"}],["circle",{"fill":"currentColor","stroke":"none","cx":"15","cy":"19","r":"1.5"}]]; +export const HardDrive: IconNode = [["path",{"d":"M2.75 13.5 5.7 5.3a2.5 2.5 0 0 1 2.35-1.55h7.9a2.5 2.5 0 0 1 2.35 1.55l2.95 8.2"}],["path",{"d":"M2.75 17 C2.75 15.25 2.75 14.53 3.26 14.01 C3.78 13.5 4.5 13.5 6.25 13.5 L17.75 13.5 C19.5 13.5 20.22 13.5 20.74 14.01 C21.25 14.53 21.25 15.25 21.25 17 L21.25 17 C21.25 18.75 21.25 19.47 20.74 19.99 C20.22 20.5 19.5 20.5 17.75 20.5 L6.25 20.5 C4.5 20.5 3.78 20.5 3.26 19.99 C2.75 19.47 2.75 18.75 2.75 17 Z","className":"icon-body"}],["circle",{"fill":"currentColor","stroke":"none","cx":"7","cy":"17","r":"1.15"}]]; +export const Hash: IconNode = [["path",{"d":"M4 9h16M4 15h16M10.25 3.5l-2 17M15.75 3.5l-2 17"}]]; +export const Heading1: IconNode = [["path",{"d":"M3.5 5.5v13M11.5 5.5v13M3.5 12h8M16.75 11.25 19.75 9v9.5"}]]; +export const Heading2: IconNode = [["path",{"d":"M3.5 5.5v13M11.5 5.5v13M3.5 12h8M21 18.5h-4.75c0-4.1 4.75-3.4 4.75-6.6 0-1.6-1.15-2.65-2.55-2.65-1.05 0-1.9.55-2.3 1.4"}]]; +export const Heading3: IconNode = [["path",{"d":"M3.5 5.5v13M11.5 5.5v13M3.5 12h8M16.5 10.25c.4-.8 1.2-1.25 2.15-1.25 1.3 0 2.35.95 2.35 2.2s-1.05 2.3-2.35 2.3c1.3 0 2.35 1.05 2.35 2.3 0 1.3-1.05 2.45-2.35 2.45-.95 0-1.75-.45-2.15-1.25"}]]; +export const Heart: IconNode = [["path",{"d":"M12 20.25s-8.75-4.9-8.75-11a4.75 4.75 0 0 1 8.75-2.6 4.75 4.75 0 0 1 8.75 2.6c0 6.1-8.75 11-8.75 11Z","className":"icon-body"}]]; +export const Highlighter: IconNode = [["path",{"d":"M14.19 4.31 C14.72 3.78 14.94 3.56 15.25 3.56 C15.56 3.56 15.78 3.78 16.31 4.31 L19.69 7.69 C20.22 8.22 20.44 8.44 20.44 8.75 C20.44 9.06 20.22 9.28 19.69 9.81 L13.46 16.04 C13.1 16.4 12.96 16.54 12.75 16.54 C12.54 16.54 12.4 16.4 12.04 16.04 L7.96 11.96 C7.6 11.6 7.46 11.46 7.46 11.25 C7.46 11.04 7.6 10.9 7.96 10.54 Z","className":"icon-body"}],["path",{"d":"M8.75 12.75 4.25 17.25v3h3l4-4M14 20.25h6.5"}]]; +export const History: IconNode = [["path",{"d":"M3.5 12a8.5 8.5 0 1 0 2.49-6.01L4.5 7.5"}],["path",{"d":"M4.5 3.25 L4.5 6 C4.5 6.75 4.5 7.06 4.72 7.28 C4.94 7.5 5.25 7.5 6 7.5 L8.75 7.5"}],["path",{"d":"M12 8v4l2.75 1.75"}]]; +export const Hourglass: IconNode = [["path",{"d":"M5.5 2.75h13M5.5 21.25h13"}],["path",{"d":"M7 2.75v2.6c0 1.45.65 2.8 1.8 3.7L12 12l3.2-2.95A4.75 4.75 0 0 0 17 5.35v-2.6Z","className":"icon-body"}],["path",{"d":"M7 21.25v-2.6c0-1.45.65-2.8 1.8-3.7L12 12l3.2 2.95A4.75 4.75 0 0 1 17 18.65v2.6Z","className":"icon-body"}]]; +export const Image: IconNode = [["path",{"d":"M3 10 C3 6.5 3 5.05 4.02 4.02 C5.05 3 6.5 3 10 3 L14 3 C17.5 3 18.95 3 19.98 4.02 C21 5.05 21 6.5 21 10 L21 14 C21 17.5 21 18.95 19.98 19.98 C18.95 21 17.5 21 14 21 L10 21 C6.5 21 5.05 21 4.02 19.98 C3 18.95 3 17.5 3 14 Z","className":"icon-body"}],["circle",{"fill":"currentColor","stroke":"none","cx":"9","cy":"9","r":"1.75"}],["path",{"d":"m20.75 15.25-3.3-3.3a2 2 0 0 0-2.83 0L5.75 20.5"}]]; +export const ImagePlus: IconNode = [["path",{"d":"M12.5 3 L7.75 3 C5.38 3 4.39 3 3.69 3.69 C3 4.39 3 5.38 3 7.75 L3 14 C3 17.5 3 18.95 4.02 19.98 C5.05 21 6.5 21 10 21 L16.25 21 C18.63 21 19.61 21 20.31 20.31 C21 19.61 21 18.63 21 16.25 L21 11.5"}],["circle",{"fill":"currentColor","stroke":"none","cx":"9","cy":"9.5","r":"1.75"}],["path",{"d":"m21 15.25-3.3-3.3a2 2 0 0 0-2.83 0L5.75 20.5M18.5 2.5v6M15.5 5.5h6"}]]; +export const Inbox: IconNode = [["path",{"d":"M2.75 11 C2.75 7 2.75 5.34 3.92 4.17 C5.09 3 6.75 3 10.75 3 L13.25 3 C17.25 3 18.91 3 20.08 4.17 C21.25 5.34 21.25 7 21.25 11 L21.25 13 C21.25 17 21.25 18.66 20.08 19.83 C18.91 21 17.25 21 13.25 21 L10.75 21 C6.75 21 5.09 21 3.92 19.83 C2.75 18.66 2.75 17 2.75 13 Z","className":"icon-body"}],["path",{"d":"M2.75 14h4.4c.75 0 1.35.55 1.75 1.2.55.95 1.6 1.8 3.1 1.8s2.55-.85 3.1-1.8c.4-.65 1-1.2 1.75-1.2h4.4","className":"icon-cut"}]]; +export const Info: IconNode = [["circle",{"cx":"12","cy":"12","r":"9.25","className":"icon-body"}],["path",{"d":"M12 11v5.25"}],["circle",{"fill":"currentColor","stroke":"none","cx":"12","cy":"7.9","r":"1.15"}]]; +export const Italic: IconNode = [["path",{"d":"M10 4.5h8M6 19.5h8M14.75 4.5l-5.5 15"}]]; +export const KeyRound: IconNode = [["circle",{"cx":"15","cy":"9","r":"5.75","className":"icon-body"}],["path",{"d":"M10.9 13.1 3.5 20.5M6.5 17.5l2.25 2.25M8.75 15.25l2 2"}]]; +export const Keyboard: IconNode = [["path",{"d":"M2.5 10 C2.5 7.5 2.5 6.46 3.23 5.73 C3.96 5 5 5 7.5 5 L16.5 5 C19 5 20.04 5 20.77 5.73 C21.5 6.46 21.5 7.5 21.5 10 L21.5 14 C21.5 16.5 21.5 17.54 20.77 18.27 C20.04 19 19 19 16.5 19 L7.5 19 C5 19 3.96 19 3.23 18.27 C2.5 17.54 2.5 16.5 2.5 14 Z","className":"icon-body"}],["circle",{"fill":"currentColor","stroke":"none","cx":"7.5","cy":"10","r":"1.15"}],["circle",{"fill":"currentColor","stroke":"none","cx":"12","cy":"10","r":"1.15"}],["circle",{"fill":"currentColor","stroke":"none","cx":"16.5","cy":"10","r":"1.15"}],["path",{"d":"M8 14.75h8","className":"icon-cut"}]]; +export const Laptop: IconNode = [["path",{"d":"M4 8.5 C4 6.25 4 5.32 4.66 4.66 C5.32 4 6.25 4 8.5 4 L15.5 4 C17.75 4 18.68 4 19.34 4.66 C20 5.32 20 6.25 20 8.5 L20 11.5 C20 13.75 20 14.68 19.34 15.34 C18.68 16 17.75 16 15.5 16 L8.5 16 C6.25 16 5.32 16 4.66 15.34 C4 14.68 4 13.75 4 11.5 Z","className":"icon-body"}],["path",{"d":"M2.25 19.75h19.5"}]]; +export const Layers: IconNode = [["path",{"d":"M10.23 3.93 C11.12 3.47 11.48 3.27 12 3.27 C12.52 3.27 12.88 3.47 13.77 3.93 L19.23 6.82 C20.12 7.28 20.48 7.48 20.48 7.75 C20.48 8.02 20.12 8.22 19.23 8.68 L13.77 11.57 C12.88 12.03 12.52 12.23 12 12.23 C11.48 12.23 11.12 12.03 10.23 11.57 L4.77 8.68 C3.88 8.22 3.52 8.02 3.52 7.75 C3.52 7.48 3.88 7.28 4.77 6.82 Z","className":"icon-body"}],["path",{"d":"M3.5 12.25 12 16.75l8.5-4.5M3.5 16.5 12 21l8.5-4.5"}]]; +export const LayoutDashboard: IconNode = [["path",{"d":"M3 6 C3 4.5 3 3.88 3.44 3.44 C3.88 3 4.5 3 6 3 L7.5 3 C9 3 9.62 3 10.06 3.44 C10.5 3.88 10.5 4.5 10.5 6 L10.5 9.5 C10.5 11 10.5 11.62 10.06 12.06 C9.62 12.5 9 12.5 7.5 12.5 L6 12.5 C4.5 12.5 3.88 12.5 3.44 12.06 C3 11.62 3 11 3 9.5 Z","className":"icon-body"}],["path",{"d":"M13.5 5.75 C13.5 4.38 13.5 3.81 13.9 3.4 C14.31 3 14.88 3 16.25 3 L18.25 3 C19.63 3 20.19 3 20.6 3.4 C21 3.81 21 4.38 21 5.75 L21 5.75 C21 7.13 21 7.69 20.6 8.1 C20.19 8.5 19.63 8.5 18.25 8.5 L16.25 8.5 C14.88 8.5 14.31 8.5 13.9 8.1 C13.5 7.69 13.5 7.13 13.5 5.75 Z","className":"icon-body"}],["path",{"d":"M13.5 14.5 C13.5 13 13.5 12.38 13.94 11.94 C14.38 11.5 15 11.5 16.5 11.5 L18 11.5 C19.5 11.5 20.12 11.5 20.56 11.94 C21 12.38 21 13 21 14.5 L21 18 C21 19.5 21 20.12 20.56 20.56 C20.12 21 19.5 21 18 21 L16.5 21 C15 21 14.38 21 13.94 20.56 C13.5 20.12 13.5 19.5 13.5 18 Z","className":"icon-body"}],["path",{"d":"M3 18.25 C3 16.88 3 16.31 3.4 15.9 C3.81 15.5 4.38 15.5 5.75 15.5 L7.75 15.5 C9.13 15.5 9.69 15.5 10.1 15.9 C10.5 16.31 10.5 16.88 10.5 18.25 L10.5 18.25 C10.5 19.63 10.5 20.19 10.1 20.6 C9.69 21 9.13 21 7.75 21 L5.75 21 C4.38 21 3.81 21 3.4 20.6 C3 20.19 3 19.63 3 18.25 Z","className":"icon-body"}]]; +export const LayoutGrid: IconNode = [["path",{"d":"M3.25 6.25 C3.25 4.75 3.25 4.13 3.69 3.69 C4.13 3.25 4.75 3.25 6.25 3.25 L7.5 3.25 C9 3.25 9.62 3.25 10.06 3.69 C10.5 4.13 10.5 4.75 10.5 6.25 L10.5 7.5 C10.5 9 10.5 9.62 10.06 10.06 C9.62 10.5 9 10.5 7.5 10.5 L6.25 10.5 C4.75 10.5 4.13 10.5 3.69 10.06 C3.25 9.62 3.25 9 3.25 7.5 Z","className":"icon-body"}],["path",{"d":"M13.5 6.25 C13.5 4.75 13.5 4.13 13.94 3.69 C14.38 3.25 15 3.25 16.5 3.25 L17.75 3.25 C19.25 3.25 19.87 3.25 20.31 3.69 C20.75 4.13 20.75 4.75 20.75 6.25 L20.75 7.5 C20.75 9 20.75 9.62 20.31 10.06 C19.87 10.5 19.25 10.5 17.75 10.5 L16.5 10.5 C15 10.5 14.38 10.5 13.94 10.06 C13.5 9.62 13.5 9 13.5 7.5 Z","className":"icon-body"}],["path",{"d":"M3.25 16.5 C3.25 15 3.25 14.38 3.69 13.94 C4.13 13.5 4.75 13.5 6.25 13.5 L7.5 13.5 C9 13.5 9.62 13.5 10.06 13.94 C10.5 14.38 10.5 15 10.5 16.5 L10.5 17.75 C10.5 19.25 10.5 19.87 10.06 20.31 C9.62 20.75 9 20.75 7.5 20.75 L6.25 20.75 C4.75 20.75 4.13 20.75 3.69 20.31 C3.25 19.87 3.25 19.25 3.25 17.75 Z","className":"icon-body"}],["path",{"d":"M13.5 16.5 C13.5 15 13.5 14.38 13.94 13.94 C14.38 13.5 15 13.5 16.5 13.5 L17.75 13.5 C19.25 13.5 19.87 13.5 20.31 13.94 C20.75 14.38 20.75 15 20.75 16.5 L20.75 17.75 C20.75 19.25 20.75 19.87 20.31 20.31 C19.87 20.75 19.25 20.75 17.75 20.75 L16.5 20.75 C15 20.75 14.38 20.75 13.94 20.31 C13.5 19.87 13.5 19.25 13.5 17.75 Z","className":"icon-body"}]]; +export const LayoutTemplate: IconNode = [["path",{"d":"M3 6 C3 4.5 3 3.88 3.44 3.44 C3.88 3 4.5 3 6 3 L18 3 C19.5 3 20.12 3 20.56 3.44 C21 3.88 21 4.5 21 6 L21 7 C21 8.5 21 9.12 20.56 9.56 C20.12 10 19.5 10 18 10 L6 10 C4.5 10 3.88 10 3.44 9.56 C3 9.12 3 8.5 3 7 Z","className":"icon-body"}],["path",{"d":"M3 16.5 C3 15 3 14.38 3.44 13.94 C3.88 13.5 4.5 13.5 6 13.5 L9.5 13.5 C11 13.5 11.62 13.5 12.06 13.94 C12.5 14.38 12.5 15 12.5 16.5 L12.5 18 C12.5 19.5 12.5 20.12 12.06 20.56 C11.62 21 11 21 9.5 21 L6 21 C4.5 21 3.88 21 3.44 20.56 C3 20.12 3 19.5 3 18 Z","className":"icon-body"}],["path",{"d":"M15.5 16 C15.5 14.75 15.5 14.23 15.87 13.87 C16.23 13.5 16.75 13.5 18 13.5 L18.5 13.5 C19.75 13.5 20.27 13.5 20.64 13.87 C21 14.23 21 14.75 21 16 L21 18.5 C21 19.75 21 20.27 20.64 20.64 C20.27 21 19.75 21 18.5 21 L18 21 C16.75 21 16.23 21 15.87 20.64 C15.5 20.27 15.5 19.75 15.5 18.5 Z","className":"icon-body"}]]; +export const Lightbulb: IconNode = [["path",{"d":"M9 17.25h6v-1.5c0-1 .5-1.9 1.25-2.6a6.25 6.25 0 1 0-8.5 0c.75.7 1.25 1.6 1.25 2.6Z","className":"icon-body"}],["path",{"d":"M9.75 21h4.5"}]]; +export const Link2: IconNode = [["path",{"d":"M9.5 17H7.25a5 5 0 0 1 0-10H9.5M14.5 7h2.25a5 5 0 0 1 0 10H14.5"}],["path",{"d":"M8.5 12h7"}]]; +export const List: IconNode = [["path",{"d":"M8.75 6h11.5M8.75 12h11.5M8.75 18h11.5"}],["circle",{"fill":"currentColor","stroke":"none","cx":"4.25","cy":"6","r":"1.3"}],["circle",{"fill":"currentColor","stroke":"none","cx":"4.25","cy":"12","r":"1.3"}],["circle",{"fill":"currentColor","stroke":"none","cx":"4.25","cy":"18","r":"1.3"}]]; +export const ListChecks: IconNode = [["path",{"d":"M3.5 7s1.1 1.75 1.65 1.75C6.05 8.75 8.5 5 8.5 5"}],["path",{"d":"M3.5 18s1.1 1.75 1.65 1.75C6.05 19.75 8.5 16 8.5 16"}],["path",{"d":"M12 6h8.5M12 12h8.5M12 18h8.5"}]]; +export const ListChevronsDownUp: IconNode = [["path",{"d":"M3.5 5h8M3.5 12h8M3.5 19h8M15 5.5s2.2 2.5 3 2.5 3-2.5 3-2.5M15 18.5s2.2-2.5 3-2.5 3 2.5 3 2.5"}]]; +export const ListChevronsUpDown: IconNode = [["path",{"d":"M3.5 5h8M3.5 12h8M3.5 19h8M15 8s2.2-2.5 3-2.5S21 8 21 8M15 16s2.2 2.5 3 2.5 3-2.5 3-2.5"}]]; +export const ListEnd: IconNode = [["path",{"d":"M3.5 5h12M3.5 12h12M3.5 19h6.5"}],["path",{"d":"M20.5 5 L20.5 16 C20.5 17.5 20.5 18.12 20.06 18.56 C19.62 19 19 19 17.5 19 L13.75 19"}],["path",{"d":"M16.5 22C16.5 22 13.5 19.79 13.5 19C13.5 18.21 16.5 16 16.5 16"}]]; +export const ListOrdered: IconNode = [["path",{"d":"M10.5 6h10M10.5 12h10M10.5 18h10M3.5 5.25 5 4.25v5.25M3.5 15.25a1.75 1.75 0 1 1 3.1 1.1L3.5 20h3.5"}]]; +export const ListPlus: IconNode = [["path",{"d":"M3.75 6h12.5M3.75 12h12.5M3.75 18h7M18 15v6M15 18h6"}]]; +export const ListTodo: IconNode = [["path",{"d":"M4 10.5 C4 7.25 4 5.9 4.95 4.95 C5.9 4 7.25 4 10.5 4 L13.5 4 C16.75 4 18.1 4 19.05 4.95 C20 5.9 20 7.25 20 10.5 L20 14.75 C20 18 20 19.35 19.05 20.3 C18.1 21.25 16.75 21.25 13.5 21.25 L10.5 21.25 C7.25 21.25 5.9 21.25 4.95 20.3 C4 19.35 4 18 4 14.75 Z","className":"icon-body"}],["path",{"d":"M8.5 4.1 C8.5 3.3 8.5 2.97 8.73 2.73 C8.97 2.5 9.3 2.5 10.1 2.5 L13.9 2.5 C14.7 2.5 15.03 2.5 15.27 2.73 C15.5 2.97 15.5 3.3 15.5 4.1 L15.5 4.65 C15.5 5.45 15.5 5.78 15.27 6.02 C15.03 6.25 14.7 6.25 13.9 6.25 L10.1 6.25 C9.3 6.25 8.97 6.25 8.73 6.02 C8.5 5.78 8.5 5.45 8.5 4.65 Z","className":"icon-body"}],["path",{"d":"M8.75 13.5S10.4 15.5 11 15.5c.9 0 4.25-4.25 4.25-4.25","className":"icon-cut"}]]; +export const ListTree: IconNode = [["path",{"d":"M20.5 6h-12M20.5 12H13M20.5 18H13M4 4.5V9a3 3 0 0 0 3 3h2.5M4 9v6a3 3 0 0 0 3 3h2.5"}]]; +export const ListX: IconNode = [["path",{"d":"M3.5 5h17M3.5 12h11M3.5 19h9M16.5 15.5l4 4M20.5 15.5l-4 4"}]]; +export const Loader2: IconNode = [["circle",{"cx":"12","cy":"12","r":"8.75","strokeOpacity":".2"}],["path",{"d":"M12 3.25A8.75 8.75 0 0 1 20.75 12"}]]; +export const LocateFixed: IconNode = [["circle",{"cx":"12","cy":"12","r":"7","className":"icon-body"}],["circle",{"fill":"currentColor","stroke":"none","cx":"12","cy":"12","r":"2.25"}],["path",{"d":"M12 2.5V5M12 19v2.5M2.5 12H5M19 12h2.5"}]]; +export const Lock: IconNode = [["path",{"d":"M4 15.63 C4 12.81 4 11.65 4.82 10.82 C5.65 10 6.81 10 9.63 10 L14.38 10 C17.19 10 18.35 10 19.18 10.82 C20 11.65 20 12.81 20 15.63 L20 15.63 C20 18.44 20 19.6 19.18 20.43 C18.35 21.25 17.19 21.25 14.38 21.25 L9.63 21.25 C6.81 21.25 5.65 21.25 4.82 20.43 C4 19.6 4 18.44 4 15.63 Z","className":"icon-body"}],["path",{"d":"M7.75 10V7.25a4.25 4.25 0 0 1 8.5 0V10M12 14.5v2.5"}]]; +export const LogIn: IconNode = [["path",{"d":"M14.5 3.5 L16.75 3.5 C17.88 3.5 18.34 3.5 18.67 3.83 C19 4.16 19 4.63 19 5.75 L19 18.25 C19 19.38 19 19.84 18.67 20.17 C18.34 20.5 17.88 20.5 16.75 20.5 L14.5 20.5"}],["path",{"d":"M3.5 12H14M10 7.5s4 3.75 4 4.5-4 4.5-4 4.5"}]]; +export const LogOut: IconNode = [["path",{"d":"M9.5 3.5 L7.25 3.5 C6.13 3.5 5.66 3.5 5.33 3.83 C5 4.16 5 4.63 5 5.75 L5 18.25 C5 19.38 5 19.84 5.33 20.17 C5.66 20.5 6.13 20.5 7.25 20.5 L9.5 20.5"}],["path",{"d":"M10 12h10.5M16.5 7.5s4 3.75 4 4.5-4 4.5-4 4.5"}]]; +export const Mail: IconNode = [["path",{"d":"M2.5 10 C2.5 7.25 2.5 6.11 3.3 5.3 C4.11 4.5 5.25 4.5 8 4.5 L16 4.5 C18.75 4.5 19.89 4.5 20.7 5.3 C21.5 6.11 21.5 7.25 21.5 10 L21.5 14 C21.5 16.75 21.5 17.89 20.7 18.7 C19.89 19.5 18.75 19.5 16 19.5 L8 19.5 C5.25 19.5 4.11 19.5 3.3 18.7 C2.5 17.89 2.5 16.75 2.5 14 Z","className":"icon-body"}],["path",{"d":"M6.5 9s3.9 3 5.5 3 5.5-3 5.5-3"}]]; +export const MailOpen: IconNode = [["path",{"d":"M2.75 12.5 C2.75 11 2.75 10.38 3.11 9.69 C3.48 9.01 3.99 8.66 5.24 7.82 L9.51 4.93 C10.76 4.09 11.27 3.74 12 3.74 C12.73 3.74 13.24 4.09 14.49 4.93 L18.76 7.82 C20.01 8.66 20.52 9.01 20.89 9.69 C21.25 10.38 21.25 11 21.25 12.5 L21.25 15.25 C21.25 17.75 21.25 18.79 20.52 19.52 C19.79 20.25 18.75 20.25 16.25 20.25 L7.75 20.25 C5.25 20.25 4.21 20.25 3.48 19.52 C2.75 18.79 2.75 17.75 2.75 15.25 Z","className":"icon-body"}],["path",{"d":"M6.5 12.75s3.9 2.75 5.5 2.75 5.5-2.75 5.5-2.75","className":"icon-cut"}]]; +export const MapPin: IconNode = [["path",{"d":"M12 21.25s7.25-5.75 7.25-11.75a7.25 7.25 0 0 0-14.5 0c0 6 7.25 11.75 7.25 11.75Z","className":"icon-body"}],["circle",{"cx":"12","cy":"9.5","r":"2.5","className":"icon-cut"}]]; +export const Maximize: IconNode = [["path",{"d":"M3.5 8.5 L3.5 6 C3.5 4.75 3.5 4.23 3.87 3.87 C4.23 3.5 4.75 3.5 6 3.5 L8.5 3.5"}],["path",{"d":"M15.5 3.5 L18 3.5 C19.25 3.5 19.77 3.5 20.14 3.87 C20.5 4.23 20.5 4.75 20.5 6 L20.5 8.5"}],["path",{"d":"M20.5 15.5 L20.5 18 C20.5 19.25 20.5 19.77 20.14 20.14 C19.77 20.5 19.25 20.5 18 20.5 L15.5 20.5"}],["path",{"d":"M8.5 20.5 L6 20.5 C4.75 20.5 4.23 20.5 3.87 20.14 C3.5 19.77 3.5 19.25 3.5 18 L3.5 15.5"}]]; +export const Maximize2: IconNode = [["path",{"d":"M14.5 3.5 L18 3.5 C19.25 3.5 19.77 3.5 20.14 3.87 C20.5 4.23 20.5 4.75 20.5 6 L20.5 9.5"}],["path",{"d":"M9.5 20.5 L6 20.5 C4.75 20.5 4.23 20.5 3.87 20.14 C3.5 19.77 3.5 19.25 3.5 18 L3.5 14.5"}],["path",{"d":"m20 4-6 6M4 20l6-6"}]]; +export const Megaphone: IconNode = [["path",{"d":"M3.5 11 C3.5 10 3.5 9.59 3.79 9.29 C4.09 9 4.5 9 5.5 9 L7.5 9 C7.75 9 7.85 9 7.99 8.97 C8.13 8.94 8.23 8.9 8.46 8.8 L17.92 4.57 C18.84 4.16 19.21 3.99 19.48 4.16 C19.75 4.34 19.75 4.75 19.75 5.75 L19.75 17.25 C19.75 18.25 19.75 18.66 19.48 18.84 C19.21 19.01 18.84 18.84 17.92 18.43 L8.46 14.2 C8.23 14.1 8.13 14.06 7.99 14.03 C7.85 14 7.75 14 7.5 14 L5.5 14 C4.5 14 4.09 14 3.79 13.71 C3.5 13.41 3.5 13 3.5 12 Z","className":"icon-body"}],["path",{"d":"m7.25 14 1.25 5.75c.15.6.65 1 1.25 1h.75c.65 0 1.15-.6 1-1.25L10.75 15.5"}]]; +export const Menu: IconNode = [["path",{"d":"M4 6.5h16M4 12h16M4 17.5h16"}]]; +export const MessageCircle: IconNode = [["path",{"d":"M12 21a9 9 0 1 0-7.85-4.6l-.95 3.3c-.2.7.4 1.3 1.1 1.1l3.3-.95A9 9 0 0 0 12 21Z","className":"icon-body"}]]; +export const MessageCircleQuestion: IconNode = [["path",{"d":"M12 21a9 9 0 1 0-7.85-4.6l-.95 3.3c-.2.7.4 1.3 1.1 1.1l3.3-.95A9 9 0 0 0 12 21Z","className":"icon-body"}],["path",{"d":"M9.6 9.6a2.45 2.45 0 1 1 3.42 2.25c-.6.27-1.02.85-1.02 1.5v.4","className":"icon-cut"}],["circle",{"fill":"currentColor","stroke":"none","cx":"12","cy":"16.75","r":"1.15","className":"icon-cut-fill"}]]; +export const MessageSquare: IconNode = [["path",{"d":"M2.75 9 C2.75 6.25 2.75 5.11 3.55 4.3 C4.36 3.5 5.5 3.5 8.25 3.5 L14.25 3.5 C17.75 3.5 19.2 3.5 20.23 4.52 C21.25 5.55 21.25 7 21.25 10.5 L21.25 11.5 C21.25 14.5 21.25 15.74 20.37 16.62 C19.49 17.5 18.25 17.5 15.25 17.5 L11 17.5 C10 17.5 9.59 17.5 9.05 17.66 C8.51 17.83 8.17 18.05 7.34 18.61 L4.58 20.45 C4.17 20.72 3.99 20.84 3.85 20.77 C3.71 20.71 3.67 20.51 3.6 20.01 L3.05 16.48 C2.9 15.49 2.84 15.08 2.79 14.5 C2.75 13.91 2.75 13.5 2.75 12.5 Z","className":"icon-body"}],["path",{"d":"M8 9.5h8M8 13h4.5","className":"icon-cut"}]]; +export const MessageSquarePlus: IconNode = [["path",{"d":"M2.75 9 C2.75 6.25 2.75 5.11 3.55 4.3 C4.36 3.5 5.5 3.5 8.25 3.5 L14.25 3.5 C17.75 3.5 19.2 3.5 20.23 4.52 C21.25 5.55 21.25 7 21.25 10.5 L21.25 11.5 C21.25 14.5 21.25 15.74 20.37 16.62 C19.49 17.5 18.25 17.5 15.25 17.5 L11 17.5 C10 17.5 9.59 17.5 9.05 17.66 C8.51 17.83 8.17 18.05 7.34 18.61 L4.58 20.45 C4.17 20.72 3.99 20.84 3.85 20.77 C3.71 20.71 3.67 20.51 3.6 20.01 L3.05 16.48 C2.9 15.49 2.84 15.08 2.79 14.5 C2.75 13.91 2.75 13.5 2.75 12.5 Z","className":"icon-body"}],["path",{"d":"M12 7.5v6M9 10.5h6"}]]; +export const MessagesSquare: IconNode = [["path",{"d":"M8.75 8.75 L8.75 5.88 C8.75 4.44 8.75 3.84 9.17 3.42 C9.59 3 10.19 3 11.63 3 L17.25 3 C19.25 3 20.08 3 20.67 3.58 C21.25 4.17 21.25 5 21.25 7 L21.25 14 C21.25 14.5 21.25 14.71 21.14 14.76 C21.03 14.81 20.87 14.68 20.49 14.35 L18.76 12.9 C18.38 12.57 18.22 12.44 17.97 12.34 C17.71 12.25 17.5 12.25 17 12.25 L15.25 12.25"}],["path",{"d":"M2.75 13 C2.75 11 2.75 10.17 3.33 9.58 C3.92 9 4.75 9 6.75 9 L11.25 9 C13.25 9 14.08 9 14.67 9.58 C15.25 10.17 15.25 11 15.25 13 L15.25 13.5 C15.25 15.5 15.25 16.33 14.67 16.92 C14.08 17.5 13.25 17.5 11.25 17.5 L8.25 17.5 C7.75 17.5 7.54 17.5 7.28 17.59 C7.02 17.68 6.86 17.81 6.46 18.11 L3.54 20.39 C3.14 20.69 2.98 20.82 2.87 20.76 C2.75 20.71 2.75 20.5 2.75 20 Z","className":"icon-body"}]]; +export const Milestone: IconNode = [["path",{"d":"M3.25 8 C3.25 7 3.25 6.59 3.54 6.29 C3.84 6 4.25 6 5.25 6 L14.5 6 C15.5 6 15.91 6 16.43 6.19 C16.95 6.37 17.27 6.64 18.04 7.27 L19.59 8.55 C20.17 9.02 20.41 9.22 20.41 9.5 C20.41 9.78 20.17 9.98 19.59 10.45 L18.04 11.73 C17.27 12.36 16.95 12.63 16.43 12.81 C15.91 13 15.5 13 14.5 13 L5.25 13 C4.25 13 3.84 13 3.54 12.71 C3.25 12.41 3.25 12 3.25 11 Z","className":"icon-body"}],["path",{"d":"M12 2.75V6M12 13v8.25"}]]; +export const Minimize2: IconNode = [["path",{"d":"M4 14 L7.5 14 C8.75 14 9.27 14 9.63 14.37 C10 14.73 10 15.25 10 16.5 L10 20"}],["path",{"d":"M20 10 L16.5 10 C15.25 10 14.73 10 14.37 9.63 C14 9.27 14 8.75 14 7.5 L14 4"}],["path",{"d":"m10 14-6.5 6.5M14 10l6.5-6.5"}]]; +export const Minus: IconNode = [["path",{"d":"M4.5 12h15"}]]; +export const Monitor: IconNode = [["path",{"d":"M2.5 8.5 C2.5 6 2.5 4.96 3.23 4.23 C3.96 3.5 5 3.5 7.5 3.5 L16.5 3.5 C19 3.5 20.04 3.5 20.77 4.23 C21.5 4.96 21.5 6 21.5 8.5 L21.5 12 C21.5 14.5 21.5 15.54 20.77 16.27 C20.04 17 19 17 16.5 17 L7.5 17 C5 17 3.96 17 3.23 16.27 C2.5 15.54 2.5 14.5 2.5 12 Z","className":"icon-body"}],["path",{"d":"M8.5 20.75h7"}],["path",{"d":"M7.25 8.5s2.5 1.45 2.5 2-2.5 2-2.5 2M12.5 12.75h4","className":"icon-cut"}]]; +export const Moon: IconNode = [["path",{"d":"M20.25 14.25A8.5 8.5 0 1 1 9.75 3.75a6.5 6.5 0 0 0 10.5 10.5Z","className":"icon-body"}]]; +export const MoreHorizontal: IconNode = [["circle",{"fill":"currentColor","stroke":"none","cx":"5","cy":"12","r":"1.6"}],["circle",{"fill":"currentColor","stroke":"none","cx":"12","cy":"12","r":"1.6"}],["circle",{"fill":"currentColor","stroke":"none","cx":"19","cy":"12","r":"1.6"}]]; +export const Network: IconNode = [["path",{"d":"M9 4.75 C9 3.75 9 3.34 9.29 3.04 C9.59 2.75 10 2.75 11 2.75 L13 2.75 C14 2.75 14.41 2.75 14.71 3.04 C15 3.34 15 3.75 15 4.75 L15 6.25 C15 7.25 15 7.66 14.71 7.96 C14.41 8.25 14 8.25 13 8.25 L11 8.25 C10 8.25 9.59 8.25 9.29 7.96 C9 7.66 9 7.25 9 6.25 Z","className":"icon-body"}],["path",{"d":"M2.75 17.75 C2.75 16.75 2.75 16.34 3.04 16.04 C3.34 15.75 3.75 15.75 4.75 15.75 L6.75 15.75 C7.75 15.75 8.16 15.75 8.46 16.04 C8.75 16.34 8.75 16.75 8.75 17.75 L8.75 19.25 C8.75 20.25 8.75 20.66 8.46 20.96 C8.16 21.25 7.75 21.25 6.75 21.25 L4.75 21.25 C3.75 21.25 3.34 21.25 3.04 20.96 C2.75 20.66 2.75 20.25 2.75 19.25 Z","className":"icon-body"}],["path",{"d":"M15.25 17.75 C15.25 16.75 15.25 16.34 15.54 16.04 C15.84 15.75 16.25 15.75 17.25 15.75 L19.25 15.75 C20.25 15.75 20.66 15.75 20.96 16.04 C21.25 16.34 21.25 16.75 21.25 17.75 L21.25 19.25 C21.25 20.25 21.25 20.66 20.96 20.96 C20.66 21.25 20.25 21.25 19.25 21.25 L17.25 21.25 C16.25 21.25 15.84 21.25 15.54 20.96 C15.25 20.66 15.25 20.25 15.25 19.25 Z","className":"icon-body"}],["path",{"d":"M12 8.25V12M5.75 15.75V14a2 2 0 0 1 2-2h8.5a2 2 0 0 1 2 2v1.75"}]]; +export const Newspaper: IconNode = [["path",{"d":"M6.75 8.25 C6.75 5.75 6.75 4.71 7.48 3.98 C8.21 3.25 9.25 3.25 11.75 3.25 L16.25 3.25 C18.75 3.25 19.79 3.25 20.52 3.98 C21.25 4.71 21.25 5.75 21.25 8.25 L21.25 15.75 C21.25 18.25 21.25 19.29 20.52 20.02 C19.79 20.75 18.75 20.75 16.25 20.75 L11.75 20.75 C9.25 20.75 8.21 20.75 7.48 20.02 C6.75 19.29 6.75 18.25 6.75 15.75 Z","className":"icon-body"}],["path",{"d":"M6.75 9H4.5c-.97 0-1.75.78-1.75 1.75v7.5a2.5 2.5 0 0 0 5 0"}],["path",{"d":"M11 8.5h6M11 12.25h6M11 16h3.5","className":"icon-cut"}]]; +export const OctagonXIcon: IconNode = [["path",{"d":"M6.77 4.81 C7.57 4.02 7.9 3.69 8.46 3.46 C9.02 3.22 9.49 3.22 10.61 3.22 L13.39 3.22 C14.51 3.22 14.98 3.22 15.54 3.46 C16.1 3.69 16.43 4.02 17.23 4.81 L19.19 6.77 C19.98 7.57 20.31 7.9 20.54 8.46 C20.78 9.02 20.78 9.49 20.78 10.61 L20.78 13.39 C20.78 14.51 20.78 14.98 20.54 15.54 C20.31 16.1 19.98 16.43 19.19 17.23 L17.23 19.19 C16.43 19.98 16.1 20.31 15.54 20.54 C14.98 20.78 14.51 20.78 13.39 20.78 L10.61 20.78 C9.49 20.78 9.02 20.78 8.46 20.54 C7.9 20.31 7.57 19.98 6.77 19.19 L4.81 17.23 C4.02 16.43 3.69 16.1 3.46 15.54 C3.22 14.98 3.22 14.51 3.22 13.39 L3.22 10.61 C3.22 9.49 3.22 9.02 3.46 8.46 C3.69 7.9 4.02 7.57 4.81 6.77 Z","className":"icon-body"}],["path",{"d":"m14.75 9.25-5.5 5.5M9.25 9.25l5.5 5.5","className":"icon-cut"}]]; +export const Option: IconNode = [["path",{"d":"M3 4.5h5.5l7 15H21M14.5 4.5H21"}]]; +export const Package: IconNode = [["path",{"d":"M9.81 3.95 C10.9 3.35 11.36 3.1 12 3.1 C12.64 3.1 13.1 3.35 14.19 3.95 L18.31 6.2 C19.4 6.8 19.86 7.05 20.18 7.59 C20.5 8.13 20.5 8.65 20.5 9.9 L20.5 14.1 C20.5 15.35 20.5 15.87 20.18 16.41 C19.86 16.95 19.4 17.2 18.31 17.8 L14.19 20.05 C13.1 20.65 12.64 20.9 12 20.9 C11.36 20.9 10.9 20.65 9.81 20.05 L5.69 17.8 C4.6 17.2 4.14 16.95 3.82 16.41 C3.5 15.87 3.5 15.35 3.5 14.1 L3.5 9.9 C3.5 8.65 3.5 8.13 3.82 7.59 C4.14 7.05 4.6 6.8 5.69 6.2 Z","className":"icon-body"}],["path",{"d":"M3.75 7.5 12 12l8.25-4.5M12 12v9.25M7.75 5.1l8.5 4.75","className":"icon-cut"}]]; +export const Palette: IconNode = [["path",{"d":"M12 2.75a9.25 9.25 0 0 0 0 18.5c1.1 0 1.75-.75 1.75-1.65 0-.45-.2-.85-.45-1.15-.25-.3-.45-.7-.45-1.1 0-.95.75-1.6 1.65-1.6h1.9a4.85 4.85 0 0 0 4.85-4.85C21.25 6.5 17.1 2.75 12 2.75Z","className":"icon-body"}],["circle",{"fill":"currentColor","stroke":"none","cx":"7.5","cy":"11.5","r":"1.3"}],["circle",{"fill":"currentColor","stroke":"none","cx":"9.5","cy":"7.25","r":"1.3"}],["circle",{"fill":"currentColor","stroke":"none","cx":"14.5","cy":"7.25","r":"1.3"}]]; +export const PanelLeft: IconNode = [["path",{"d":"M2.75 9.5 C2.75 6.5 2.75 5.26 3.63 4.38 C4.51 3.5 5.75 3.5 8.75 3.5 L15.25 3.5 C18.25 3.5 19.49 3.5 20.37 4.38 C21.25 5.26 21.25 6.5 21.25 9.5 L21.25 14.5 C21.25 17.5 21.25 18.74 20.37 19.62 C19.49 20.5 18.25 20.5 15.25 20.5 L8.75 20.5 C5.75 20.5 4.51 20.5 3.63 19.62 C2.75 18.74 2.75 17.5 2.75 14.5 Z","className":"icon-body"}],["path",{"d":"M9 3.5v17"}]]; +export const PanelLeftClose: IconNode = [["path",{"d":"M2.75 9.5 C2.75 6.5 2.75 5.26 3.63 4.38 C4.51 3.5 5.75 3.5 8.75 3.5 L15.25 3.5 C18.25 3.5 19.49 3.5 20.37 4.38 C21.25 5.26 21.25 6.5 21.25 9.5 L21.25 14.5 C21.25 17.5 21.25 18.74 20.37 19.62 C19.49 20.5 18.25 20.5 15.25 20.5 L8.75 20.5 C5.75 20.5 4.51 20.5 3.63 19.62 C2.75 18.74 2.75 17.5 2.75 14.5 Z","className":"icon-body"}],["path",{"d":"M9 3.5v17M16 9.5s-2.5 1.8-2.5 2.5 2.5 2.5 2.5 2.5"}]]; +export const PanelLeftOpen: IconNode = [["path",{"d":"M2.75 9.5 C2.75 6.5 2.75 5.26 3.63 4.38 C4.51 3.5 5.75 3.5 8.75 3.5 L15.25 3.5 C18.25 3.5 19.49 3.5 20.37 4.38 C21.25 5.26 21.25 6.5 21.25 9.5 L21.25 14.5 C21.25 17.5 21.25 18.74 20.37 19.62 C19.49 20.5 18.25 20.5 15.25 20.5 L8.75 20.5 C5.75 20.5 4.51 20.5 3.63 19.62 C2.75 18.74 2.75 17.5 2.75 14.5 Z","className":"icon-body"}],["path",{"d":"M9 3.5v17M13.5 9.5s2.5 1.8 2.5 2.5-2.5 2.5-2.5 2.5"}]]; +export const PanelRight: IconNode = [["path",{"d":"M2.75 9.5 C2.75 6.5 2.75 5.26 3.63 4.38 C4.51 3.5 5.75 3.5 8.75 3.5 L15.25 3.5 C18.25 3.5 19.49 3.5 20.37 4.38 C21.25 5.26 21.25 6.5 21.25 9.5 L21.25 14.5 C21.25 17.5 21.25 18.74 20.37 19.62 C19.49 20.5 18.25 20.5 15.25 20.5 L8.75 20.5 C5.75 20.5 4.51 20.5 3.63 19.62 C2.75 18.74 2.75 17.5 2.75 14.5 Z","className":"icon-body"}],["path",{"d":"M15 3.5v17"}]]; +export const PanelRightClose: IconNode = [["path",{"d":"M2.75 9.5 C2.75 6.5 2.75 5.26 3.63 4.38 C4.51 3.5 5.75 3.5 8.75 3.5 L15.25 3.5 C18.25 3.5 19.49 3.5 20.37 4.38 C21.25 5.26 21.25 6.5 21.25 9.5 L21.25 14.5 C21.25 17.5 21.25 18.74 20.37 19.62 C19.49 20.5 18.25 20.5 15.25 20.5 L8.75 20.5 C5.75 20.5 4.51 20.5 3.63 19.62 C2.75 18.74 2.75 17.5 2.75 14.5 Z","className":"icon-body"}],["path",{"d":"M15 3.5v17M8 9.5s2.5 1.8 2.5 2.5S8 14.5 8 14.5"}]]; +export const PanelRightOpen: IconNode = [["path",{"d":"M2.75 9.5 C2.75 6.5 2.75 5.26 3.63 4.38 C4.51 3.5 5.75 3.5 8.75 3.5 L15.25 3.5 C18.25 3.5 19.49 3.5 20.37 4.38 C21.25 5.26 21.25 6.5 21.25 9.5 L21.25 14.5 C21.25 17.5 21.25 18.74 20.37 19.62 C19.49 20.5 18.25 20.5 15.25 20.5 L8.75 20.5 C5.75 20.5 4.51 20.5 3.63 19.62 C2.75 18.74 2.75 17.5 2.75 14.5 Z","className":"icon-body"}],["path",{"d":"M15 3.5v17M10.5 9.5S8 11.3 8 12s2.5 2.5 2.5 2.5"}]]; +export const Paperclip: IconNode = [["path",{"d":"M16.6 11.85L11.82 16.63A3.5 3.5 0 0 1 6.87 11.68L13.24 5.31A2.25 2.25 0 0 1 16.42 8.49L10.23 14.68A1.25 1.25 0 0 1 8.46 12.91L13.06 8.32"}]]; +export const Pause: IconNode = [["path",{"d":"M6 6.25 C6 5.38 6 5.01 6.26 4.76 C6.51 4.5 6.88 4.5 7.75 4.5 L8 4.5 C8.88 4.5 9.24 4.5 9.49 4.76 C9.75 5.01 9.75 5.38 9.75 6.25 L9.75 17.75 C9.75 18.63 9.75 18.99 9.49 19.24 C9.24 19.5 8.88 19.5 8 19.5 L7.75 19.5 C6.88 19.5 6.51 19.5 6.26 19.24 C6 18.99 6 18.63 6 17.75 Z","className":"icon-body"}],["path",{"d":"M14.25 6.25 C14.25 5.38 14.25 5.01 14.51 4.76 C14.76 4.5 15.13 4.5 16 4.5 L16.25 4.5 C17.13 4.5 17.49 4.5 17.74 4.76 C18 5.01 18 5.38 18 6.25 L18 17.75 C18 18.63 18 18.99 17.74 19.24 C17.49 19.5 17.13 19.5 16.25 19.5 L16 19.5 C15.13 19.5 14.76 19.5 14.51 19.24 C14.25 18.99 14.25 18.63 14.25 17.75 Z","className":"icon-body"}]]; +export const Pencil: IconNode = [["path",{"d":"M15.1 4.4a2.65 2.65 0 0 1 3.75 3.75L8.5 18.5l-5 1.25 1.25-5Z","className":"icon-body"}],["path",{"d":"m13.5 6 4.5 4.5"}]]; +export const PencilLine: IconNode = [["path",{"d":"M15.1 4.4a2.65 2.65 0 0 1 3.75 3.75L8.5 18.5l-5 1.25 1.25-5Z","className":"icon-body"}],["path",{"d":"m13.5 6 4.5 4.5"}],["path",{"d":"M13 20.25h7.5"}]]; +export const Pin: IconNode = [["path",{"d":"M9.25 4 C9.25 3.5 9.25 3.29 9.4 3.15 C9.54 3 9.75 3 10.25 3 L13.75 3 C14.25 3 14.46 3 14.6 3.15 C14.75 3.29 14.75 3.5 14.75 4 L14.75 7.25 C14.75 7.75 14.75 7.96 14.84 8.22 C14.92 8.49 15.04 8.66 15.34 9.06 L17.12 11.53 C17.56 12.14 17.74 12.39 17.65 12.57 C17.56 12.75 17.25 12.75 16.5 12.75 L7.5 12.75 C6.75 12.75 6.44 12.75 6.35 12.57 C6.26 12.39 6.44 12.14 6.88 11.53 L8.66 9.06 C8.96 8.66 9.08 8.49 9.16 8.22 C9.25 7.96 9.25 7.75 9.25 7.25 Z","className":"icon-body"}],["path",{"d":"M12 12.75v8.5M8 3h8"}]]; +export const PinOff: IconNode = [["path",{"d":"M9.25 4 C9.25 3.5 9.25 3.29 9.4 3.15 C9.54 3 9.75 3 10.25 3 L13.75 3 C14.25 3 14.46 3 14.6 3.15 C14.75 3.29 14.75 3.5 14.75 4 L14.75 7.25 C14.75 7.75 14.75 7.96 14.84 8.22 C14.92 8.49 15.04 8.66 15.34 9.06 L17.12 11.53 C17.56 12.14 17.74 12.39 17.65 12.57 C17.56 12.75 17.25 12.75 16.5 12.75 L7.5 12.75 C6.75 12.75 6.44 12.75 6.35 12.57 C6.26 12.39 6.44 12.14 6.88 11.53 L8.66 9.06 C8.96 8.66 9.08 8.49 9.16 8.22 C9.25 7.96 9.25 7.75 9.25 7.25 Z","className":"icon-body"}],["path",{"d":"M12 12.75v8.5M8 3h8"}],["path",{"d":"m3.5 3.5 17 17"}]]; +export const Pipette: IconNode = [["path",{"d":"M12.71 8.96 C12.35 8.6 12.21 8.46 12.21 8.25 C12.21 8.04 12.35 7.9 12.71 7.54 L14.91 5.34 C15.83 4.42 16.21 4.04 16.75 4.04 C17.29 4.04 17.67 4.42 18.59 5.34 L18.66 5.41 C19.58 6.33 19.96 6.71 19.96 7.25 C19.96 7.79 19.58 8.17 18.66 9.09 L16.46 11.29 C16.1 11.65 15.96 11.79 15.75 11.79 C15.54 11.79 15.4 11.65 15.04 11.29 Z","className":"icon-body"}],["path",{"d":"m10.25 7 6.75 6.75M11.75 9.25 4.75 16.25v3h3l7-7"}]]; +export const Play: IconNode = [["path",{"d":"M6.75 7.5 C6.75 6 6.75 5.38 7.13 5.16 C7.51 4.95 8.04 5.26 9.34 6.02 L16.91 10.48 C18.21 11.24 18.74 11.55 18.74 12 C18.74 12.45 18.21 12.76 16.91 13.52 L9.34 17.98 C8.04 18.74 7.51 19.05 7.13 18.84 C6.75 18.62 6.75 18 6.75 16.5 Z","className":"icon-body"}]]; +export const Plug: IconNode = [["path",{"d":"M9 2.75V7M15 2.75V7M12 16.5v4.75"}],["path",{"d":"M6.75 7h10.5c.41 0 .75.34.75.75v2.75a6 6 0 0 1-12 0V7.75c0-.41.34-.75.75-.75Z","className":"icon-body"}]]; +export const PlugZap: IconNode = [["path",{"d":"M9 2.75V7M15 2.75V7M12 16.5v4.75"}],["path",{"d":"M6.75 7h10.5c.41 0 .75.34.75.75v2.75a6 6 0 0 1-12 0V7.75c0-.41.34-.75.75-.75Z","className":"icon-body"}],["path",{"d":"m12.75 8.75-1.75 2.75h2.25l-1.75 2.75","className":"icon-cut"}]]; +export const Plus: IconNode = [["path",{"d":"M12 4.5v15M4.5 12h15"}]]; +export const Power: IconNode = [["path",{"d":"M12 2.75v8M6.4 6.4a8 8 0 1 0 11.2 0"}]]; +export const Quote: IconNode = [["path",{"d":"M3.25 14.25 C3.25 12.75 3.25 12.13 3.69 11.69 C4.13 11.25 4.75 11.25 6.25 11.25 L7.5 11.25 C9 11.25 9.62 11.25 10.06 11.69 C10.5 12.13 10.5 12.75 10.5 14.25 L10.5 15.5 C10.5 17 10.5 17.62 10.06 18.06 C9.62 18.5 9 18.5 7.5 18.5 L6.25 18.5 C4.75 18.5 4.13 18.5 3.69 18.06 C3.25 17.62 3.25 17 3.25 15.5 Z","className":"icon-body"}],["path",{"d":"M3.25 14.5v-3a5.75 5.75 0 0 1 5.75-5.75"}],["path",{"d":"M13.5 14.25 C13.5 12.75 13.5 12.13 13.94 11.69 C14.38 11.25 15 11.25 16.5 11.25 L17.75 11.25 C19.25 11.25 19.87 11.25 20.31 11.69 C20.75 12.13 20.75 12.75 20.75 14.25 L20.75 15.5 C20.75 17 20.75 17.62 20.31 18.06 C19.87 18.5 19.25 18.5 17.75 18.5 L16.5 18.5 C15 18.5 14.38 18.5 13.94 18.06 C13.5 17.62 13.5 17 13.5 15.5 Z","className":"icon-body"}],["path",{"d":"M13.5 14.5v-3a5.75 5.75 0 0 1 5.75-5.75"}]]; +export const Redo2: IconNode = [["path",{"d":"M19.25 9H9.5a5.25 5.25 0 0 0 0 10.5H13"}],["path",{"d":"M15 4.5C15 4.5 19.5 7.82 19.5 9C19.5 10.18 15 13.5 15 13.5"}]]; +export const RefreshCw: IconNode = [["path",{"d":"M3.75 12a8.25 8.25 0 0 1 14.08-5.83L20 8.25"}],["path",{"d":"M20 3.75 L20 6.75 C20 7.5 20 7.81 19.78 8.03 C19.56 8.25 19.25 8.25 18.5 8.25 L15.75 8.25"}],["path",{"d":"M20.25 12a8.25 8.25 0 0 1-14.08 5.83L4 15.75"}],["path",{"d":"M4 20.25 L4 17.25 C4 16.5 4 16.19 4.22 15.97 C4.44 15.75 4.75 15.75 5.5 15.75 L8.25 15.75"}]]; +export const Rocket: IconNode = [["path",{"d":"M9.75 16.5 7.5 14.25C9.75 8.5 14 4.5 20.25 3.75c-.75 6.25-4.75 10.5-10.5 12.75Z","className":"icon-body"}],["circle",{"cx":"15","cy":"9","r":"1.75","className":"icon-cut"}],["path",{"d":"M8.25 12.25H5l2.75-4h3.5M11.75 15.75V19l4-2.75v-3.5"}]]; +export const RotateCcw: IconNode = [["path",{"d":"M3.5 12a8.5 8.5 0 1 0 2.49-6.01L4.5 7.5"}],["path",{"d":"M4.5 3.25 L4.5 6 C4.5 6.75 4.5 7.06 4.72 7.28 C4.94 7.5 5.25 7.5 6 7.5 L8.75 7.5"}]]; +export const RotateCw: IconNode = [["path",{"d":"M20.5 12a8.5 8.5 0 1 1-2.49-6.01L19.5 7.5"}],["path",{"d":"M19.5 3.25 L19.5 6 C19.5 6.75 19.5 7.06 19.28 7.28 C19.06 7.5 18.75 7.5 18 7.5 L15.25 7.5"}]]; +export const Rows3: IconNode = [["path",{"d":"M3 10 C3 6.5 3 5.05 4.02 4.02 C5.05 3 6.5 3 10 3 L14 3 C17.5 3 18.95 3 19.98 4.02 C21 5.05 21 6.5 21 10 L21 14 C21 17.5 21 18.95 19.98 19.98 C18.95 21 17.5 21 14 21 L10 21 C6.5 21 5.05 21 4.02 19.98 C3 18.95 3 17.5 3 14 Z","className":"icon-body"}],["path",{"d":"M3 9h18M3 15h18","className":"icon-cut"}]]; +export const Save: IconNode = [["path",{"d":"M3.25 8.25 C3.25 5.75 3.25 4.71 3.98 3.98 C4.71 3.25 5.75 3.25 8.25 3.25 L15 3.25 C15.75 3.25 16.06 3.25 16.44 3.4 C16.81 3.56 17.03 3.78 17.56 4.31 L19.69 6.44 C20.22 6.97 20.44 7.19 20.6 7.56 C20.75 7.94 20.75 8.25 20.75 9 L20.75 15.75 C20.75 18.25 20.75 19.29 20.02 20.02 C19.29 20.75 18.25 20.75 15.75 20.75 L8.25 20.75 C5.75 20.75 4.71 20.75 3.98 20.02 C3.25 19.29 3.25 18.25 3.25 15.75 Z","className":"icon-body"}],["path",{"d":"M7.5 20.75 L7.5 15.5 C7.5 14.75 7.5 14.44 7.72 14.22 C7.94 14 8.25 14 9 14 L15 14 C15.75 14 16.06 14 16.28 14.22 C16.5 14.44 16.5 14.75 16.5 15.5 L16.5 20.75"}],["path",{"d":"M7.5 3.25 L7.5 6 C7.5 6.75 7.5 7.06 7.72 7.28 C7.94 7.5 8.25 7.5 9 7.5 L14 7.5"}]]; +export const ScrollText: IconNode = [["path",{"d":"M9.75 3.25h9a2.25 2.25 0 0 1 0 4.5H16.5V18a2.75 2.75 0 0 1-2.75 2.75H5.5a2.25 2.25 0 0 1 0-4.5h1.75V5.75a2.5 2.5 0 0 1 2.5-2.5Z","className":"icon-body"}],["path",{"d":"M7.25 16.25h3.5c.97 0 1.75.78 1.75 1.75v.25"}],["path",{"d":"M10.5 8.5h2.75M10.5 12.25h2.75","className":"icon-cut"}]]; +export const Search: IconNode = [["circle",{"cx":"11","cy":"11","r":"7.75","className":"icon-body"}],["path",{"d":"m16.75 16.75 4.5 4.5"}]]; +export const Send: IconNode = [["path",{"d":"M19.34 3.75 C20.04 3.5 20.34 3.4 20.47 3.53 C20.6 3.66 20.5 3.96 20.25 4.66 L15 19.34 C14.75 20.04 14.65 20.34 14.48 20.35 C14.3 20.36 14.16 20.08 13.83 19.41 L11.02 13.79 C10.88 13.52 10.83 13.41 10.71 13.29 C10.59 13.17 10.48 13.12 10.21 12.98 L4.59 10.17 C3.92 9.84 3.64 9.7 3.65 9.52 C3.66 9.35 3.96 9.25 4.66 9 Z","className":"icon-body"}],["path",{"d":"M20.5 3.5 10.75 13.25"}]]; +export const Server: IconNode = [["path",{"d":"M3 6.75 C3 5 3 4.28 3.51 3.76 C4.03 3.25 4.75 3.25 6.5 3.25 L17.5 3.25 C19.25 3.25 19.97 3.25 20.49 3.76 C21 4.28 21 5 21 6.75 L21 7.25 C21 9 21 9.72 20.49 10.24 C19.97 10.75 19.25 10.75 17.5 10.75 L6.5 10.75 C4.75 10.75 4.03 10.75 3.51 10.24 C3 9.72 3 9 3 7.25 Z","className":"icon-body"}],["path",{"d":"M3 16.75 C3 15 3 14.28 3.51 13.76 C4.03 13.25 4.75 13.25 6.5 13.25 L17.5 13.25 C19.25 13.25 19.97 13.25 20.49 13.76 C21 14.28 21 15 21 16.75 L21 17.25 C21 19 21 19.72 20.49 20.24 C19.97 20.75 19.25 20.75 17.5 20.75 L6.5 20.75 C4.75 20.75 4.03 20.75 3.51 20.24 C3 19.72 3 19 3 17.25 Z","className":"icon-body"}],["circle",{"fill":"currentColor","stroke":"none","cx":"7","cy":"7","r":"1.15"}],["circle",{"fill":"currentColor","stroke":"none","cx":"7","cy":"17","r":"1.15"}]]; +export const Settings: IconNode = [["path",{"d":"M9.18 5.19 C9.5 5.06 9.63 5.01 9.74 4.87 C9.86 4.74 9.89 4.6 9.97 4.26 L10.12 3.61 C10.25 3.07 10.3 2.85 10.5 2.69 C10.7 2.54 10.93 2.54 11.48 2.54 L12.52 2.54 C13.07 2.54 13.3 2.54 13.5 2.69 C13.7 2.85 13.75 3.07 13.88 3.61 L14.03 4.26 C14.11 4.6 14.14 4.74 14.26 4.87 C14.37 5.01 14.5 5.06 14.82 5.19 L14.82 5.19 C15.14 5.32 15.27 5.38 15.45 5.36 C15.62 5.35 15.74 5.27 16.03 5.09 L16.61 4.74 C17.07 4.45 17.27 4.33 17.52 4.36 C17.77 4.39 17.93 4.55 18.32 4.94 L19.06 5.68 C19.45 6.07 19.61 6.23 19.64 6.48 C19.67 6.73 19.55 6.93 19.26 7.39 L18.91 7.97 C18.73 8.26 18.65 8.38 18.64 8.55 C18.62 8.73 18.68 8.86 18.81 9.18 L18.81 9.18 C18.94 9.5 18.99 9.63 19.13 9.74 C19.26 9.86 19.4 9.89 19.74 9.97 L20.39 10.12 C20.93 10.25 21.15 10.3 21.31 10.5 C21.46 10.7 21.46 10.93 21.46 11.48 L21.46 12.52 C21.46 13.07 21.46 13.3 21.31 13.5 C21.15 13.7 20.93 13.75 20.39 13.88 L19.74 14.03 C19.4 14.11 19.26 14.14 19.13 14.26 C18.99 14.37 18.94 14.5 18.81 14.82 L18.81 14.82 C18.68 15.14 18.62 15.27 18.64 15.45 C18.65 15.62 18.73 15.74 18.91 16.03 L19.26 16.61 C19.55 17.07 19.67 17.27 19.64 17.52 C19.61 17.77 19.45 17.93 19.06 18.32 L18.32 19.06 C17.93 19.45 17.77 19.61 17.52 19.64 C17.27 19.67 17.07 19.55 16.61 19.26 L16.03 18.91 C15.74 18.73 15.62 18.65 15.45 18.64 C15.27 18.62 15.14 18.68 14.82 18.81 L14.82 18.81 C14.5 18.94 14.37 18.99 14.26 19.13 C14.14 19.26 14.11 19.4 14.03 19.74 L13.88 20.39 C13.75 20.93 13.7 21.15 13.5 21.31 C13.3 21.46 13.07 21.46 12.52 21.46 L11.48 21.46 C10.93 21.46 10.7 21.46 10.5 21.31 C10.3 21.15 10.25 20.93 10.12 20.39 L9.97 19.74 C9.89 19.4 9.86 19.26 9.74 19.13 C9.63 18.99 9.5 18.94 9.18 18.81 L9.18 18.81 C8.86 18.68 8.73 18.62 8.55 18.64 C8.38 18.65 8.26 18.73 7.97 18.91 L7.39 19.26 C6.93 19.55 6.73 19.67 6.48 19.64 C6.23 19.61 6.07 19.45 5.68 19.06 L4.94 18.32 C4.55 17.93 4.39 17.77 4.36 17.52 C4.33 17.27 4.45 17.07 4.74 16.61 L5.09 16.03 C5.27 15.74 5.35 15.62 5.36 15.45 C5.38 15.27 5.32 15.14 5.19 14.82 L5.19 14.82 C5.06 14.5 5.01 14.37 4.87 14.26 C4.74 14.14 4.6 14.11 4.26 14.03 L3.61 13.88 C3.07 13.75 2.85 13.7 2.69 13.5 C2.54 13.3 2.54 13.07 2.54 12.52 L2.54 11.48 C2.54 10.93 2.54 10.7 2.69 10.5 C2.85 10.3 3.07 10.25 3.61 10.12 L4.26 9.97 C4.6 9.89 4.74 9.86 4.87 9.74 C5.01 9.63 5.06 9.5 5.19 9.18 L5.19 9.18 C5.32 8.86 5.38 8.73 5.36 8.55 C5.35 8.38 5.27 8.26 5.09 7.97 L4.74 7.39 C4.45 6.93 4.33 6.73 4.36 6.48 C4.39 6.23 4.55 6.07 4.94 5.68 L5.68 4.94 C6.07 4.55 6.23 4.39 6.48 4.36 C6.73 4.33 6.93 4.45 7.39 4.74 L7.97 5.09 C8.26 5.27 8.38 5.35 8.55 5.36 C8.73 5.38 8.86 5.32 9.18 5.19 Z","className":"icon-body"}],["circle",{"cx":"12","cy":"12","r":"3","className":"icon-cut"}]]; +export const Settings2: IconNode = [["path",{"d":"M3.75 7.5h9.5M18.75 7.5h1.5M3.75 16.5h1.5M10.75 16.5h9.5"}],["circle",{"cx":"16","cy":"7.5","r":"2.75","className":"icon-body"}],["circle",{"cx":"8","cy":"16.5","r":"2.75","className":"icon-body"}]]; +export const Shapes: IconNode = [["path",{"d":"M6.23 4.04 C6.61 3.39 6.77 3.13 7 3.13 C7.23 3.13 7.39 3.39 7.77 4.04 L10.73 8.96 C11.11 9.61 11.27 9.87 11.17 10.06 C11.06 10.25 10.75 10.25 10 10.25 L4 10.25 C3.25 10.25 2.94 10.25 2.83 10.06 C2.73 9.87 2.89 9.61 3.27 8.96 Z","className":"icon-body"}],["circle",{"cx":"17","cy":"7","r":"4.25","className":"icon-body"}],["path",{"d":"M7.75 16.25 C7.75 14.75 7.75 14.13 8.19 13.69 C8.63 13.25 9.25 13.25 10.75 13.25 L13.25 13.25 C14.75 13.25 15.37 13.25 15.81 13.69 C16.25 14.13 16.25 14.75 16.25 16.25 L16.25 18.25 C16.25 19.75 16.25 20.37 15.81 20.81 C15.37 21.25 14.75 21.25 13.25 21.25 L10.75 21.25 C9.25 21.25 8.63 21.25 8.19 20.81 C7.75 20.37 7.75 19.75 7.75 18.25 Z","className":"icon-body"}]]; +export const Shield: IconNode = [["path",{"d":"M12 21.25s7.75-3.25 7.75-9.75V6.1c0-.5-.3-.95-.78-1.13l-6.1-2.25a2.5 2.5 0 0 0-1.74 0L5.03 4.97c-.48.18-.78.63-.78 1.13v5.4c0 6.5 7.75 9.75 7.75 9.75Z","className":"icon-body"}]]; +export const ShieldCheck: IconNode = [["path",{"d":"M12 21.25s7.75-3.25 7.75-9.75V6.1c0-.5-.3-.95-.78-1.13l-6.1-2.25a2.5 2.5 0 0 0-1.74 0L5.03 4.97c-.48.18-.78.63-.78 1.13v5.4c0 6.5 7.75 9.75 7.75 9.75Z","className":"icon-body"}],["path",{"d":"M8.75 12s1.3 2 1.9 2c.85 0 4.6-4.25 4.6-4.25"}]]; +export const ShieldOff: IconNode = [["path",{"d":"M12 21.25s7.75-3.25 7.75-9.75V6.1c0-.5-.3-.95-.78-1.13l-6.1-2.25a2.5 2.5 0 0 0-1.74 0L5.03 4.97c-.48.18-.78.63-.78 1.13v5.4c0 6.5 7.75 9.75 7.75 9.75Z","className":"icon-body"}],["path",{"d":"m3 3 18 18"}]]; +export const SignalHigh: IconNode = [["path",{"d":"M3.25 20.5h.01M7.75 20.5V16M12.25 20.5V12M16.75 20.5V8"}]]; +export const SkipForward: IconNode = [["path",{"d":"M5 7.5 C5 6.25 5 5.73 5.31 5.55 C5.63 5.38 6.07 5.65 7.14 6.3 L14.36 10.7 C15.43 11.35 15.87 11.62 15.88 12 C15.87 12.38 15.43 12.65 14.36 13.3 L7.14 17.7 C6.07 18.35 5.63 18.62 5.31 18.45 C5 18.27 5 17.75 5 16.5 Z","className":"icon-body"}],["path",{"d":"M19.5 5v14"}]]; +export const SlidersHorizontal: IconNode = [["path",{"d":"M3.75 5h9M17.25 5h3M3.75 12h2.5M10.75 12h9.5M3.75 19h8M16.25 19h4"}],["circle",{"cx":"15","cy":"5","r":"2.25","className":"icon-body"}],["circle",{"cx":"8.5","cy":"12","r":"2.25","className":"icon-body"}],["circle",{"cx":"14","cy":"19","r":"2.25","className":"icon-body"}]]; +export const Smartphone: IconNode = [["path",{"d":"M5.75 7 C5.75 4.75 5.75 3.82 6.41 3.16 C7.07 2.5 8 2.5 10.25 2.5 L13.75 2.5 C16 2.5 16.93 2.5 17.59 3.16 C18.25 3.82 18.25 4.75 18.25 7 L18.25 17 C18.25 19.25 18.25 20.18 17.59 20.84 C16.93 21.5 16 21.5 13.75 21.5 L10.25 21.5 C8 21.5 7.07 21.5 6.41 20.84 C5.75 20.18 5.75 19.25 5.75 17 Z","className":"icon-body"}],["path",{"d":"M11 18.25h2"}]]; +export const SmilePlus: IconNode = [["path",{"d":"M21.15 11A9.25 9.25 0 1 1 13 2.8"}],["path",{"d":"M8 14.5s1.5 2 4 2 4-2 4-2M19 2.5v5M16.5 5h5"}],["circle",{"fill":"currentColor","stroke":"none","cx":"9","cy":"9.5","r":"1.1"}],["circle",{"fill":"currentColor","stroke":"none","cx":"15","cy":"9.5","r":"1.1"}]]; +export const Space: IconNode = [["path",{"d":"M3 13.5 L3 15.75 C3 16.88 3 17.34 3.33 17.67 C3.66 18 4.13 18 5.25 18 L18.75 18 C19.88 18 20.34 18 20.67 17.67 C21 17.34 21 16.88 21 15.75 L21 13.5"}]]; +export const Sparkles: IconNode = [["path",{"d":"M10 3.5c.5 3.3 3.2 6 6.5 6.5-3.3.5-6 3.2-6.5 6.5-.5-3.3-3.2-6-6.5-6.5 3.3-.5 6-3.2 6.5-6.5Z","className":"icon-body"}],["path",{"fill":"currentColor","stroke":"none","d":"M18 14.25c.24 1.45 1.3 2.51 2.75 2.75-1.45.24-2.51 1.3-2.75 2.75-.24-1.45-1.3-2.51-2.75-2.75 1.45-.24 2.51-1.3 2.75-2.75Z"}],["circle",{"fill":"currentColor","stroke":"none","cx":"18.5","cy":"4.75","r":"1.2"}]]; +export const Square: IconNode = [["path",{"d":"M4 10.5 C4 7.25 4 5.9 4.95 4.95 C5.9 4 7.25 4 10.5 4 L13.5 4 C16.75 4 18.1 4 19.05 4.95 C20 5.9 20 7.25 20 10.5 L20 13.5 C20 16.75 20 18.1 19.05 19.05 C18.1 20 16.75 20 13.5 20 L10.5 20 C7.25 20 5.9 20 4.95 19.05 C4 18.1 4 16.75 4 13.5 Z","className":"icon-body"}]]; +export const SquarePen: IconNode = [["path",{"d":"M11 3.25 L7.13 3.25 C5.19 3.25 4.39 3.25 3.82 3.82 C3.25 4.39 3.25 5.19 3.25 7.13 L3.25 13.75 C3.25 17.25 3.25 18.7 4.27 19.73 C5.3 20.75 6.75 20.75 10.25 20.75 L16.88 20.75 C18.81 20.75 19.61 20.75 20.18 20.18 C20.75 19.61 20.75 18.81 20.75 16.88 L20.75 13"}],["path",{"d":"M17.9 3.6a2.05 2.05 0 0 1 2.9 2.9l-7.35 7.35-3.7.85.85-3.7Z","className":"icon-body"}]]; +export const SquarePlus: IconNode = [["path",{"d":"M3 10 C3 6.5 3 5.05 4.02 4.02 C5.05 3 6.5 3 10 3 L14 3 C17.5 3 18.95 3 19.98 4.02 C21 5.05 21 6.5 21 10 L21 14 C21 17.5 21 18.95 19.98 19.98 C18.95 21 17.5 21 14 21 L10 21 C6.5 21 5.05 21 4.02 19.98 C3 18.95 3 17.5 3 14 Z","className":"icon-body"}],["path",{"d":"M12 8v8M8 12h8","className":"icon-cut"}]]; +export const SquareTerminal: IconNode = [["path",{"d":"M3 10 C3 6.5 3 5.05 4.02 4.02 C5.05 3 6.5 3 10 3 L14 3 C17.5 3 18.95 3 19.98 4.02 C21 5.05 21 6.5 21 10 L21 14 C21 17.5 21 18.95 19.98 19.98 C18.95 21 17.5 21 14 21 L10 21 C6.5 21 5.05 21 4.02 19.98 C3 18.95 3 17.5 3 14 Z","className":"icon-body"}],["path",{"d":"M7.5 9s2.5 2.25 2.5 3-2.5 3-2.5 3M12.75 15.25h4"}]]; +export const Star: IconNode = [["path",{"d":"M11.39 4.58 C11.7 3.84 11.82 3.53 12 3.53 C12.18 3.53 12.3 3.84 12.61 4.58 L14.12 8.24 C14.31 8.7 14.39 8.89 14.59 9.04 C14.79 9.18 15 9.2 15.5 9.24 L19.44 9.54 C20.24 9.6 20.57 9.63 20.62 9.8 C20.68 9.97 20.43 10.18 19.82 10.7 L16.8 13.27 C16.42 13.59 16.27 13.72 16.19 13.96 C16.11 14.2 16.16 14.4 16.28 14.89 L17.21 18.73 C17.4 19.51 17.47 19.83 17.33 19.94 C17.18 20.04 16.9 19.87 16.22 19.45 L12.85 17.37 C12.43 17.11 12.25 17 12 17 C11.75 17 11.57 17.11 11.15 17.37 L7.78 19.45 C7.1 19.87 6.82 20.04 6.67 19.94 C6.53 19.83 6.6 19.51 6.79 18.73 L7.72 14.89 C7.84 14.4 7.89 14.2 7.81 13.96 C7.73 13.72 7.58 13.59 7.2 13.27 L4.18 10.7 C3.57 10.18 3.32 9.97 3.38 9.8 C3.43 9.63 3.76 9.6 4.56 9.54 L8.5 9.24 C9 9.2 9.21 9.18 9.41 9.04 C9.61 8.89 9.69 8.7 9.88 8.24 Z","className":"icon-body"}]]; +export const Strikethrough: IconNode = [["path",{"d":"M4 12h16"}],["path",{"d":"M16.75 7.5c-.45-1.8-2.2-3-4.6-3-2.65 0-4.65 1.4-4.65 3.4 0 1.1.5 1.95 1.5 2.6M7.25 16.25c.45 1.95 2.2 3.25 4.85 3.25 2.8 0 4.65-1.4 4.65-3.5 0-.6-.15-1.1-.45-1.5"}]]; +export const Sun: IconNode = [["circle",{"cx":"12","cy":"12","r":"4","className":"icon-body"}],["path",{"d":"M12 2.75v1.5M12 19.75v1.5M2.75 12h1.5M19.75 12h1.5M5.46 5.46l1.06 1.06M17.48 17.48l1.06 1.06M5.46 18.54l1.06-1.06M17.48 6.52l1.06-1.06"}]]; +export const Table2: IconNode = [["path",{"d":"M3 10 C3 6.5 3 5.05 4.02 4.02 C5.05 3 6.5 3 10 3 L14 3 C17.5 3 18.95 3 19.98 4.02 C21 5.05 21 6.5 21 10 L21 14 C21 17.5 21 18.95 19.98 19.98 C18.95 21 17.5 21 14 21 L10 21 C6.5 21 5.05 21 4.02 19.98 C3 18.95 3 17.5 3 14 Z","className":"icon-body"}],["path",{"d":"M3 9h18M9 3v18","className":"icon-cut"}]]; +export const Tablet: IconNode = [["path",{"d":"M4 7 C4 4.75 4 3.82 4.66 3.16 C5.32 2.5 6.25 2.5 8.5 2.5 L15.5 2.5 C17.75 2.5 18.68 2.5 19.34 3.16 C20 3.82 20 4.75 20 7 L20 17 C20 19.25 20 20.18 19.34 20.84 C18.68 21.5 17.75 21.5 15.5 21.5 L8.5 21.5 C6.25 21.5 5.32 21.5 4.66 20.84 C4 20.18 4 19.25 4 17 Z","className":"icon-body"}],["path",{"d":"M11 18.25h2"}]]; +export const Tag: IconNode = [["path",{"d":"M3.25 6.25 C3.25 4.75 3.25 4.13 3.69 3.69 C4.13 3.25 4.75 3.25 6.25 3.25 L9.5 3.25 C10.5 3.25 10.91 3.25 11.41 3.46 C11.91 3.66 12.21 3.96 12.91 4.66 L18.81 10.56 C19.78 11.53 20.18 11.93 20.18 12.5 C20.18 13.07 19.78 13.47 18.81 14.44 L14.44 18.81 C13.47 19.78 13.07 20.18 12.5 20.18 C11.93 20.18 11.53 19.78 10.56 18.81 L4.66 12.91 C3.96 12.21 3.66 11.91 3.46 11.41 C3.25 10.91 3.25 10.5 3.25 9.5 Z","className":"icon-body"}],["circle",{"fill":"currentColor","stroke":"none","cx":"7.75","cy":"7.75","r":"1.4"}]]; +export const Tags: IconNode = [["path",{"d":"M2.75 6.75 C2.75 5.5 2.75 4.98 3.12 4.62 C3.48 4.25 4 4.25 5.25 4.25 L8 4.25 C9 4.25 9.41 4.25 9.91 4.46 C10.41 4.66 10.71 4.96 11.41 5.66 L16.23 10.48 C17.12 11.37 17.48 11.73 17.48 12.25 C17.48 12.77 17.12 13.13 16.23 14.02 L12.77 17.48 C11.88 18.37 11.52 18.73 11 18.73 C10.48 18.73 10.12 18.37 9.23 17.48 L4.16 12.41 C3.46 11.71 3.16 11.41 2.96 10.91 C2.75 10.41 2.75 10 2.75 9 Z","className":"icon-body"}],["circle",{"fill":"currentColor","stroke":"none","cx":"6.75","cy":"8.25","r":"1.3"}],["path",{"d":"m14 4.25 6.75 6.75a1.75 1.75 0 0 1 0 2.5l-5.25 5.25"}]]; +export const Target: IconNode = [["circle",{"cx":"12","cy":"12","r":"9.25","className":"icon-body"}],["circle",{"cx":"12","cy":"12","r":"5.25","className":"icon-cut"}],["circle",{"fill":"currentColor","stroke":"none","cx":"12","cy":"12","r":"1.5"}]]; +export const Terminal: IconNode = [["path",{"d":"M4.5 6.5s5 4.1 5 5.5-5 5.5-5 5.5M12.5 17.5h7"}]]; +export const Trash2: IconNode = [["path",{"d":"M3.5 6h17M9 6V4.75c0-.7.55-1.25 1.25-1.25h3.5c.7 0 1.25.55 1.25 1.25V6"}],["path",{"d":"m5.5 6 .9 12.3a2.5 2.5 0 0 0 2.5 2.2h6.2a2.5 2.5 0 0 0 2.5-2.2L18.5 6","className":"icon-body"}],["path",{"d":"M10 11v5M14 11v5"}]]; +export const Type: IconNode = [["path",{"d":"M4.5 7V5.25c0-.41.34-.75.75-.75h13.5c.41 0 .75.34.75.75V7M12 4.5v15M9 19.5h6"}]]; +export const Undo2: IconNode = [["path",{"d":"M4.75 9h9.75a5.25 5.25 0 0 1 0 10.5H11"}],["path",{"d":"M9 13.5C9 13.5 4.5 10.18 4.5 9C4.5 7.82 9 4.5 9 4.5"}]]; +export const Unlink: IconNode = [["path",{"d":"M9.5 17H7.25a5 5 0 0 1 0-10H9.5M14.5 7h2.25a5 5 0 0 1 0 10H14.5"}],["path",{"d":"M12 2.75v2.5M12 18.75v2.5"}]]; +export const Unplug: IconNode = [["path",{"d":"M9 2.75V7M15 2.75V7M12 16.5v4.75"}],["path",{"d":"M6.75 7h10.5c.41 0 .75.34.75.75v2.75a6 6 0 0 1-12 0V7.75c0-.41.34-.75.75-.75Z","className":"icon-body"}],["path",{"d":"m3 3 18 18"}]]; +export const Upload: IconNode = [["path",{"d":"M12 15V4M7.5 8s3.32-4.5 4.5-4.5S16.5 8 16.5 8"}],["path",{"d":"M3.5 15 L3.5 17.75 C3.5 19.13 3.5 19.69 3.9 20.1 C4.31 20.5 4.88 20.5 6.25 20.5 L17.75 20.5 C19.13 20.5 19.69 20.5 20.1 20.1 C20.5 19.69 20.5 19.13 20.5 17.75 L20.5 15"}]]; +export const UserMinus: IconNode = [["circle",{"cx":"10","cy":"7.75","r":"4.25","className":"icon-body"}],["path",{"d":"M3 20.75c0-3.6 3.13-6.25 7-6.25s7 2.65 7 6.25"}],["path",{"d":"M16.5 10h5"}]]; +export const UserPen: IconNode = [["circle",{"cx":"10","cy":"7.75","r":"4.25","className":"icon-body"}],["path",{"d":"M3 20.75c0-3.6 3.13-6.25 7-6.25 1 0 1.95.18 2.8.5"}],["path",{"d":"m14.25 21 .6-2.6 4.6-4.6a1.42 1.42 0 0 1 2 2l-4.6 4.6Z"}]]; +export const UserPlus: IconNode = [["circle",{"cx":"10","cy":"7.75","r":"4.25","className":"icon-body"}],["path",{"d":"M3 20.75c0-3.6 3.13-6.25 7-6.25s7 2.65 7 6.25"}],["path",{"d":"M19 7.5v5M16.5 10h5"}]]; +export const UserRound: IconNode = [["circle",{"cx":"12","cy":"7.75","r":"4.25","className":"icon-body"}],["path",{"d":"M5 20.75c0-3.6 3.13-6.25 7-6.25s7 2.65 7 6.25"}]]; +export const Users: IconNode = [["path",{"d":"M6.25 14.5 L4.38 14.5 C3.44 14.5 3.05 14.5 2.77 14.23 C2.5 13.95 2.5 13.56 2.5 12.63 L2.5 8.5 C2.5 6.25 2.5 5.32 3.16 4.66 C3.82 4 4.75 4 7 4 L12.63 4 C13.56 4 13.95 4 14.23 4.27 C14.5 4.55 14.5 4.94 14.5 5.88 L14.5 7.75"}],["path",{"d":"M8.25 14.75 C8.25 12.25 8.25 11.21 8.98 10.48 C9.71 9.75 10.75 9.75 13.25 9.75 L16.5 9.75 C19 9.75 20.04 9.75 20.77 10.48 C21.5 11.21 21.5 12.25 21.5 14.75 L21.5 16 C21.5 18.5 21.5 19.54 20.77 20.27 C20.04 21 19 21 16.5 21 L13.25 21 C10.75 21 9.71 21 8.98 20.27 C8.25 19.54 8.25 18.5 8.25 16 Z","className":"icon-body"}],["path",{"d":"M12.5 14.25v2M17.25 14.25v2","className":"icon-cut"}]]; +export const Waves: IconNode = [["path",{"d":"M2.75 6.75c1.85 0 2.78-1.75 4.63-1.75s2.78 1.75 4.62 1.75 2.78-1.75 4.63-1.75 2.77 1.75 4.62 1.75M2.75 12c1.85 0 2.78-1.75 4.63-1.75s2.78 1.75 4.62 1.75 2.78-1.75 4.63-1.75 2.77 1.75 4.62 1.75M2.75 17.25c1.85 0 2.78-1.75 4.63-1.75s2.78 1.75 4.62 1.75 2.78-1.75 4.63-1.75 2.77 1.75 4.62 1.75"}]]; +export const Webhook: IconNode = [["path",{"d":"M17.5 17.25h-5.75c-1.05 0-1.9.8-2.4 1.7a3.75 3.75 0 1 1-4.85-5.3"}],["path",{"d":"m5.75 17.25 3.15-5.5c.55-.95.15-2.1-.4-2.95a3.75 3.75 0 1 1 6.6-3.6"}],["path",{"d":"m12 6.5 3.15 5.45c.55.95 1.75 1.3 2.85 1.3a3.75 3.75 0 1 1-.5 7.5"}]]; +export const Wifi: IconNode = [["circle",{"fill":"currentColor","stroke":"none","cx":"12","cy":"19","r":"1.3"}],["path",{"d":"M8.75 15.5a4.6 4.6 0 0 1 6.5 0"}],["path",{"d":"M5.5 12.25a9.2 9.2 0 0 1 13 0"}],["path",{"d":"M2.25 9a13.8 13.8 0 0 1 19.5 0"}]]; +export const WifiHigh: IconNode = [["circle",{"fill":"currentColor","stroke":"none","cx":"12","cy":"19","r":"1.3"}],["path",{"d":"M8.75 15.5a4.6 4.6 0 0 1 6.5 0"}],["path",{"d":"M5.5 12.25a9.2 9.2 0 0 1 13 0"}]]; +export const WifiOff: IconNode = [["circle",{"fill":"currentColor","stroke":"none","cx":"12","cy":"19","r":"1.3"}],["path",{"d":"M8.75 15.5a4.6 4.6 0 0 1 6.5 0"}],["path",{"d":"M5.5 12.25a9.2 9.2 0 0 1 13 0"}],["path",{"d":"M2.25 9a13.8 13.8 0 0 1 19.5 0"}],["path",{"d":"m3 3 18 18"}]]; +export const Workflow: IconNode = [["path",{"d":"M3 6 C3 4.5 3 3.88 3.44 3.44 C3.88 3 4.5 3 6 3 L7.5 3 C9 3 9.62 3 10.06 3.44 C10.5 3.88 10.5 4.5 10.5 6 L10.5 7.5 C10.5 9 10.5 9.62 10.06 10.06 C9.62 10.5 9 10.5 7.5 10.5 L6 10.5 C4.5 10.5 3.88 10.5 3.44 10.06 C3 9.62 3 9 3 7.5 Z","className":"icon-body"}],["path",{"d":"M13.5 16.5 C13.5 15 13.5 14.38 13.94 13.94 C14.38 13.5 15 13.5 16.5 13.5 L18 13.5 C19.5 13.5 20.12 13.5 20.56 13.94 C21 14.38 21 15 21 16.5 L21 18 C21 19.5 21 20.12 20.56 20.56 C20.12 21 19.5 21 18 21 L16.5 21 C15 21 14.38 21 13.94 20.56 C13.5 20.12 13.5 19.5 13.5 18 Z","className":"icon-body"}],["path",{"d":"M6.75 10.5 L6.75 13.88 C6.75 15.56 6.75 16.26 7.24 16.76 C7.74 17.25 8.44 17.25 10.13 17.25 L13.5 17.25"}]]; +export const WrapText: IconNode = [["path",{"d":"M3.5 6h17M3.5 18h5.5M3.5 12h13.25a3.25 3.25 0 0 1 0 6.5H13.5"}],["path",{"d":"M16 21C16 21 13.5 19.16 13.5 18.5C13.5 17.84 16 16 16 16"}]]; +export const Wrench: IconNode = [["path",{"d":"M20.11 6.36 L17.65 8.82 A1.75 1.75 0 0 1 15.18 6.35 L17.64 3.89 A5.75 5.75 0 0 0 9.89 11.64 L4.04 17.49 A1.75 1.75 0 0 0 6.51 19.96 L12.36 14.11 A5.75 5.75 0 0 0 20.11 6.36 Z","className":"icon-body"}]]; +export const X: IconNode = [["path",{"d":"M18 6 6 18M6 6l12 12"}]]; +export const XCircle: IconNode = [["circle",{"cx":"12","cy":"12","r":"9.25","className":"icon-body"}],["path",{"d":"m14.75 9.25-5.5 5.5M9.25 9.25l5.5 5.5"}]]; +export const Zap: IconNode = [["path",{"d":"M20.5 12a8.5 8.5 0 1 1-2.5-6.02"}],["path",{"d":"M18.75 2.75v3.5h-3.5"}],["path",{"d":"m12.6 7.5-3.35 5h3l-.85 4 3.35-5h-3Z","className":"icon-body"}]]; diff --git a/packages/ui/icons/icons.test.ts b/packages/ui/icons/icons.test.ts new file mode 100644 index 000000000..fcb8724cd --- /dev/null +++ b/packages/ui/icons/icons.test.ts @@ -0,0 +1,26 @@ +import { readFileSync } from "node:fs"; +import { join } from "node:path"; +import { createElement } from "react"; +import { renderToStaticMarkup } from "react-dom/server"; +import { describe, expect, it } from "vitest"; +import { OUTPUTS, exportNames } from "./drawings/generate.mjs"; +import * as icons from "./index"; + +describe("@multica/ui/icons", () => { + it.each(Object.entries(OUTPUTS))("%s matches drawings/drawings.mjs", (file, render) => { + expect(readFileSync(join(__dirname, file), "utf8"), "run pnpm --filter @multica/ui icons").toBe(render()); + }); + + it("exports every drawn name and nothing borrowed from an icon library", () => { + const exported = Object.keys(icons).filter((n) => n !== "ICON_STROKE_WIDTH"); + expect(exported.sort()).toEqual(Object.keys(exportNames()).sort()); + expect(readFileSync(join(__dirname, "index.ts"), "utf8")).not.toMatch(/from "(?!\.\/)/); + }); + + it.each(Object.keys(exportNames()))("%s renders a Multica glyph", (name) => { + const Icon = icons[name as keyof typeof icons] as icons.IconComponent; + const markup = renderToStaticMarkup(createElement(Icon)); + expect(markup).toMatch(/^]*class="icon icon-[a-z0-9-]+"/); + expect(markup).toMatch(/<(path|circle|ellipse|rect)\b/); + }); +}); diff --git a/packages/ui/icons/index.ts b/packages/ui/icons/index.ts new file mode 100644 index 000000000..eed2d3b06 --- /dev/null +++ b/packages/ui/icons/index.ts @@ -0,0 +1,302 @@ +import { createIcon } from "./create-icon"; +import * as glyph from "./glyphs"; + +// Generated by drawings/generate.mjs; do not edit. Every icon the product +// uses is a Multica drawing: add new ones to drawings/drawings.mjs. + +export { ICON_STROKE_WIDTH, type IconComponent, type IconNode, type IconProps } from "./create-icon"; + +export const Activity = /* @__PURE__ */ createIcon("Activity", glyph.Activity); +export const AlarmClock = /* @__PURE__ */ createIcon("AlarmClock", glyph.AlarmClock); +export const AlertCircle = /* @__PURE__ */ createIcon("AlertCircle", glyph.AlertCircle); +export const AlertTriangle = /* @__PURE__ */ createIcon("AlertTriangle", glyph.AlertTriangle); +export const AppWindow = /* @__PURE__ */ createIcon("AppWindow", glyph.AppWindow); +export const Archive = /* @__PURE__ */ createIcon("Archive", glyph.Archive); +export const ArchiveRestore = /* @__PURE__ */ createIcon("ArchiveRestore", glyph.ArchiveRestore); +export const ArrowBigUp = /* @__PURE__ */ createIcon("ArrowBigUp", glyph.ArrowBigUp); +export const ArrowDown = /* @__PURE__ */ createIcon("ArrowDown", glyph.ArrowDown); +export const ArrowDownNarrowWide = /* @__PURE__ */ createIcon("ArrowDownNarrowWide", glyph.ArrowDownNarrowWide); +export const ArrowDownToLine = /* @__PURE__ */ createIcon("ArrowDownToLine", glyph.ArrowDownToLine); +export const ArrowLeft = /* @__PURE__ */ createIcon("ArrowLeft", glyph.ArrowLeft); +export const ArrowLeftRight = /* @__PURE__ */ createIcon("ArrowLeftRight", glyph.ArrowLeftRight); +export const ArrowRight = /* @__PURE__ */ createIcon("ArrowRight", glyph.ArrowRight); +export const ArrowRightToLine = /* @__PURE__ */ createIcon("ArrowRightToLine", glyph.ArrowRightToLine); +export const ArrowUp = /* @__PURE__ */ createIcon("ArrowUp", glyph.ArrowUp); +export const ArrowUpCircle = /* @__PURE__ */ createIcon("ArrowUpCircle", glyph.ArrowUpCircle); +export const ArrowUpDown = /* @__PURE__ */ createIcon("ArrowUpDown", glyph.ArrowUpDown); +export const ArrowUpNarrowWide = /* @__PURE__ */ createIcon("ArrowUpNarrowWide", glyph.ArrowUpNarrowWide); +export const ArrowUpRight = /* @__PURE__ */ createIcon("ArrowUpRight", glyph.ArrowUpRight); +export const AtSign = /* @__PURE__ */ createIcon("AtSign", glyph.AtSign); +export const Ban = /* @__PURE__ */ createIcon("Ban", glyph.Ban); +export const BarChart3 = /* @__PURE__ */ createIcon("BarChart3", glyph.BarChart3); +export const Bell = /* @__PURE__ */ createIcon("Bell", glyph.Bell); +export const BellOff = /* @__PURE__ */ createIcon("BellOff", glyph.BellOff); +export const BellRing = /* @__PURE__ */ createIcon("BellRing", glyph.BellRing); +export const Blocks = /* @__PURE__ */ createIcon("Blocks", glyph.Blocks); +export const Bold = /* @__PURE__ */ createIcon("Bold", glyph.Bold); +export const BookCheck = /* @__PURE__ */ createIcon("BookCheck", glyph.BookCheck); +export const BookOpen = /* @__PURE__ */ createIcon("BookOpen", glyph.BookOpen); +export const BookOpenText = /* @__PURE__ */ createIcon("BookOpenText", glyph.BookOpenText); +export const Bookmark = /* @__PURE__ */ createIcon("Bookmark", glyph.Bookmark); +export const Bot = /* @__PURE__ */ createIcon("Bot", glyph.Bot); +export const BotOff = /* @__PURE__ */ createIcon("BotOff", glyph.BotOff); +export const Box = /* @__PURE__ */ createIcon("Box", glyph.Box); +export const Brain = /* @__PURE__ */ createIcon("Brain", glyph.Brain); +export const Briefcase = /* @__PURE__ */ createIcon("Briefcase", glyph.Briefcase); +export const BriefcaseBusiness = /* @__PURE__ */ createIcon("BriefcaseBusiness", glyph.Briefcase); +export const Bug = /* @__PURE__ */ createIcon("Bug", glyph.Bug); +export const Building2 = /* @__PURE__ */ createIcon("Building2", glyph.Building2); +export const Calendar = /* @__PURE__ */ createIcon("Calendar", glyph.Calendar); +export const CalendarClock = /* @__PURE__ */ createIcon("CalendarClock", glyph.CalendarClock); +export const CalendarDays = /* @__PURE__ */ createIcon("CalendarDays", glyph.CalendarDays); +export const CalendarX = /* @__PURE__ */ createIcon("CalendarX", glyph.CalendarX); +export const Camera = /* @__PURE__ */ createIcon("Camera", glyph.Camera); +export const ChartGantt = /* @__PURE__ */ createIcon("ChartGantt", glyph.ChartGantt); +export const Check = /* @__PURE__ */ createIcon("Check", glyph.Check); +export const CheckCheck = /* @__PURE__ */ createIcon("CheckCheck", glyph.CheckCheck); +export const CheckCircle2 = /* @__PURE__ */ createIcon("CheckCircle2", glyph.CheckCircle2); +export const CheckIcon = /* @__PURE__ */ createIcon("CheckIcon", glyph.Check); +export const ChevronDown = /* @__PURE__ */ createIcon("ChevronDown", glyph.ChevronDown); +export const ChevronDownIcon = /* @__PURE__ */ createIcon("ChevronDownIcon", glyph.ChevronDown); +export const ChevronLeft = /* @__PURE__ */ createIcon("ChevronLeft", glyph.ChevronLeft); +export const ChevronLeftIcon = /* @__PURE__ */ createIcon("ChevronLeftIcon", glyph.ChevronLeft); +export const ChevronRight = /* @__PURE__ */ createIcon("ChevronRight", glyph.ChevronRight); +export const ChevronRightIcon = /* @__PURE__ */ createIcon("ChevronRightIcon", glyph.ChevronRight); +export const ChevronUp = /* @__PURE__ */ createIcon("ChevronUp", glyph.ChevronUp); +export const ChevronUpIcon = /* @__PURE__ */ createIcon("ChevronUpIcon", glyph.ChevronUp); +export const ChevronsUpDown = /* @__PURE__ */ createIcon("ChevronsUpDown", glyph.ChevronsUpDown); +export const Circle = /* @__PURE__ */ createIcon("Circle", glyph.Circle); +export const CircleAlert = /* @__PURE__ */ createIcon("CircleAlert", glyph.AlertCircle); +export const CircleCheck = /* @__PURE__ */ createIcon("CircleCheck", glyph.CheckCircle2); +export const CircleCheckIcon = /* @__PURE__ */ createIcon("CircleCheckIcon", glyph.CheckCircle2); +export const CircleDashed = /* @__PURE__ */ createIcon("CircleDashed", glyph.CircleDashed); +export const CircleDot = /* @__PURE__ */ createIcon("CircleDot", glyph.CircleDot); +export const CircleEqual = /* @__PURE__ */ createIcon("CircleEqual", glyph.CircleEqual); +export const CircleHelp = /* @__PURE__ */ createIcon("CircleHelp", glyph.CircleHelp); +export const CircleOff = /* @__PURE__ */ createIcon("CircleOff", glyph.CircleOff); +export const CirclePause = /* @__PURE__ */ createIcon("CirclePause", glyph.CirclePause); +export const CircleSlash = /* @__PURE__ */ createIcon("CircleSlash", glyph.CircleSlash); +export const CircleUser = /* @__PURE__ */ createIcon("CircleUser", glyph.CircleUser); +export const Clock = /* @__PURE__ */ createIcon("Clock", glyph.Clock); +export const Clock3 = /* @__PURE__ */ createIcon("Clock3", glyph.Clock3); +export const Cloud = /* @__PURE__ */ createIcon("Cloud", glyph.Cloud); +export const Code = /* @__PURE__ */ createIcon("Code", glyph.Code); +export const Code2 = /* @__PURE__ */ createIcon("Code2", glyph.Code2); +export const CodeXml = /* @__PURE__ */ createIcon("CodeXml", glyph.Code2); +export const Coins = /* @__PURE__ */ createIcon("Coins", glyph.Coins); +export const Columns2 = /* @__PURE__ */ createIcon("Columns2", glyph.Columns2); +export const Columns3 = /* @__PURE__ */ createIcon("Columns3", glyph.Columns3); +export const Command = /* @__PURE__ */ createIcon("Command", glyph.Command); +export const Compass = /* @__PURE__ */ createIcon("Compass", glyph.Compass); +export const Component = /* @__PURE__ */ createIcon("Component", glyph.Component); +export const Copy = /* @__PURE__ */ createIcon("Copy", glyph.Copy); +export const CornerDownLeft = /* @__PURE__ */ createIcon("CornerDownLeft", glyph.CornerDownLeft); +export const CornerDownRight = /* @__PURE__ */ createIcon("CornerDownRight", glyph.CornerDownRight); +export const CornerLeftUp = /* @__PURE__ */ createIcon("CornerLeftUp", glyph.CornerLeftUp); +export const CornerUpLeft = /* @__PURE__ */ createIcon("CornerUpLeft", glyph.CornerUpLeft); +export const Cpu = /* @__PURE__ */ createIcon("Cpu", glyph.Cpu); +export const CreditCard = /* @__PURE__ */ createIcon("CreditCard", glyph.CreditCard); +export const Crown = /* @__PURE__ */ createIcon("Crown", glyph.Crown); +export const Database = /* @__PURE__ */ createIcon("Database", glyph.Database); +export const Delete = /* @__PURE__ */ createIcon("Delete", glyph.Delete); +export const Dices = /* @__PURE__ */ createIcon("Dices", glyph.Dices); +export const Download = /* @__PURE__ */ createIcon("Download", glyph.Download); +export const Ellipsis = /* @__PURE__ */ createIcon("Ellipsis", glyph.MoreHorizontal); +export const ExternalLink = /* @__PURE__ */ createIcon("ExternalLink", glyph.ExternalLink); +export const Eye = /* @__PURE__ */ createIcon("Eye", glyph.Eye); +export const EyeOff = /* @__PURE__ */ createIcon("EyeOff", glyph.EyeOff); +export const FastForward = /* @__PURE__ */ createIcon("FastForward", glyph.FastForward); +export const File = /* @__PURE__ */ createIcon("File", glyph.File); +export const FileArchive = /* @__PURE__ */ createIcon("FileArchive", glyph.FileArchive); +export const FileAudio = /* @__PURE__ */ createIcon("FileAudio", glyph.FileAudio); +export const FileCode = /* @__PURE__ */ createIcon("FileCode", glyph.FileCode); +export const FileEdit = /* @__PURE__ */ createIcon("FileEdit", glyph.FilePen); +export const FileImage = /* @__PURE__ */ createIcon("FileImage", glyph.FileImage); +export const FilePen = /* @__PURE__ */ createIcon("FilePen", glyph.FilePen); +export const FilePlus = /* @__PURE__ */ createIcon("FilePlus", glyph.FilePlus); +export const FilePlus2 = /* @__PURE__ */ createIcon("FilePlus2", glyph.FilePlus); +export const FileQuestion = /* @__PURE__ */ createIcon("FileQuestion", glyph.FileQuestion); +export const FileSearch = /* @__PURE__ */ createIcon("FileSearch", glyph.FileSearch); +export const FileSpreadsheet = /* @__PURE__ */ createIcon("FileSpreadsheet", glyph.FileSpreadsheet); +export const FileText = /* @__PURE__ */ createIcon("FileText", glyph.FileText); +export const FileVideo = /* @__PURE__ */ createIcon("FileVideo", glyph.FileVideo); +export const Filter = /* @__PURE__ */ createIcon("Filter", glyph.Filter); +export const FilterX = /* @__PURE__ */ createIcon("FilterX", glyph.FilterX); +export const Flag = /* @__PURE__ */ createIcon("Flag", glyph.Flag); +export const Folder = /* @__PURE__ */ createIcon("Folder", glyph.Folder); +export const FolderGit = /* @__PURE__ */ createIcon("FolderGit", glyph.FolderGit); +export const FolderGit2 = /* @__PURE__ */ createIcon("FolderGit2", glyph.FolderGit); +export const FolderInput = /* @__PURE__ */ createIcon("FolderInput", glyph.FolderInput); +export const FolderKanban = /* @__PURE__ */ createIcon("FolderKanban", glyph.FolderKanban); +export const FolderMinus = /* @__PURE__ */ createIcon("FolderMinus", glyph.FolderMinus); +export const FolderOpen = /* @__PURE__ */ createIcon("FolderOpen", glyph.FolderOpen); +export const FolderPlus = /* @__PURE__ */ createIcon("FolderPlus", glyph.FolderPlus); +export const Frame = /* @__PURE__ */ createIcon("Frame", glyph.Frame); +export const Gauge = /* @__PURE__ */ createIcon("Gauge", glyph.Gauge); +export const GitBranch = /* @__PURE__ */ createIcon("GitBranch", glyph.GitBranch); +export const GitMerge = /* @__PURE__ */ createIcon("GitMerge", glyph.GitMerge); +export const GitPullRequest = /* @__PURE__ */ createIcon("GitPullRequest", glyph.GitPullRequest); +export const GitPullRequestArrow = /* @__PURE__ */ createIcon("GitPullRequestArrow", glyph.GitPullRequest); +export const GitPullRequestClosed = /* @__PURE__ */ createIcon("GitPullRequestClosed", glyph.GitPullRequestClosed); +export const GitPullRequestDraft = /* @__PURE__ */ createIcon("GitPullRequestDraft", glyph.GitPullRequestDraft); +export const Globe = /* @__PURE__ */ createIcon("Globe", glyph.Globe); +export const Globe2 = /* @__PURE__ */ createIcon("Globe2", glyph.Globe); +export const GraduationCap = /* @__PURE__ */ createIcon("GraduationCap", glyph.GraduationCap); +export const GripVertical = /* @__PURE__ */ createIcon("GripVertical", glyph.GripVertical); +export const HardDrive = /* @__PURE__ */ createIcon("HardDrive", glyph.HardDrive); +export const Hash = /* @__PURE__ */ createIcon("Hash", glyph.Hash); +export const Heading1 = /* @__PURE__ */ createIcon("Heading1", glyph.Heading1); +export const Heading2 = /* @__PURE__ */ createIcon("Heading2", glyph.Heading2); +export const Heading3 = /* @__PURE__ */ createIcon("Heading3", glyph.Heading3); +export const Heart = /* @__PURE__ */ createIcon("Heart", glyph.Heart); +export const HelpCircle = /* @__PURE__ */ createIcon("HelpCircle", glyph.CircleHelp); +export const Highlighter = /* @__PURE__ */ createIcon("Highlighter", glyph.Highlighter); +export const History = /* @__PURE__ */ createIcon("History", glyph.History); +export const Hourglass = /* @__PURE__ */ createIcon("Hourglass", glyph.Hourglass); +export const Image = /* @__PURE__ */ createIcon("Image", glyph.Image); +export const ImageIcon = /* @__PURE__ */ createIcon("ImageIcon", glyph.Image); +export const ImagePlus = /* @__PURE__ */ createIcon("ImagePlus", glyph.ImagePlus); +export const Inbox = /* @__PURE__ */ createIcon("Inbox", glyph.Inbox); +export const Info = /* @__PURE__ */ createIcon("Info", glyph.Info); +export const InfoIcon = /* @__PURE__ */ createIcon("InfoIcon", glyph.Info); +export const Italic = /* @__PURE__ */ createIcon("Italic", glyph.Italic); +export const KeyRound = /* @__PURE__ */ createIcon("KeyRound", glyph.KeyRound); +export const Keyboard = /* @__PURE__ */ createIcon("Keyboard", glyph.Keyboard); +export const Laptop = /* @__PURE__ */ createIcon("Laptop", glyph.Laptop); +export const Layers = /* @__PURE__ */ createIcon("Layers", glyph.Layers); +export const Layers3 = /* @__PURE__ */ createIcon("Layers3", glyph.Layers); +export const LayoutDashboard = /* @__PURE__ */ createIcon("LayoutDashboard", glyph.LayoutDashboard); +export const LayoutGrid = /* @__PURE__ */ createIcon("LayoutGrid", glyph.LayoutGrid); +export const LayoutTemplate = /* @__PURE__ */ createIcon("LayoutTemplate", glyph.LayoutTemplate); +export const Lightbulb = /* @__PURE__ */ createIcon("Lightbulb", glyph.Lightbulb); +export const Link = /* @__PURE__ */ createIcon("Link", glyph.Link2); +export const Link2 = /* @__PURE__ */ createIcon("Link2", glyph.Link2); +export const List = /* @__PURE__ */ createIcon("List", glyph.List); +export const ListChecks = /* @__PURE__ */ createIcon("ListChecks", glyph.ListChecks); +export const ListChevronsDownUp = /* @__PURE__ */ createIcon("ListChevronsDownUp", glyph.ListChevronsDownUp); +export const ListChevronsUpDown = /* @__PURE__ */ createIcon("ListChevronsUpDown", glyph.ListChevronsUpDown); +export const ListEnd = /* @__PURE__ */ createIcon("ListEnd", glyph.ListEnd); +export const ListOrdered = /* @__PURE__ */ createIcon("ListOrdered", glyph.ListOrdered); +export const ListPlus = /* @__PURE__ */ createIcon("ListPlus", glyph.ListPlus); +export const ListTodo = /* @__PURE__ */ createIcon("ListTodo", glyph.ListTodo); +export const ListTree = /* @__PURE__ */ createIcon("ListTree", glyph.ListTree); +export const ListX = /* @__PURE__ */ createIcon("ListX", glyph.ListX); +export const Loader2 = /* @__PURE__ */ createIcon("Loader2", glyph.Loader2); +export const Loader2Icon = /* @__PURE__ */ createIcon("Loader2Icon", glyph.Loader2); +export const LoaderCircle = /* @__PURE__ */ createIcon("LoaderCircle", glyph.Loader2); +export const LocateFixed = /* @__PURE__ */ createIcon("LocateFixed", glyph.LocateFixed); +export const Lock = /* @__PURE__ */ createIcon("Lock", glyph.Lock); +export const LockKeyhole = /* @__PURE__ */ createIcon("LockKeyhole", glyph.Lock); +export const LogIn = /* @__PURE__ */ createIcon("LogIn", glyph.LogIn); +export const LogOut = /* @__PURE__ */ createIcon("LogOut", glyph.LogOut); +export const Mail = /* @__PURE__ */ createIcon("Mail", glyph.Mail); +export const MailOpen = /* @__PURE__ */ createIcon("MailOpen", glyph.MailOpen); +export const MapPin = /* @__PURE__ */ createIcon("MapPin", glyph.MapPin); +export const Maximize = /* @__PURE__ */ createIcon("Maximize", glyph.Maximize); +export const Maximize2 = /* @__PURE__ */ createIcon("Maximize2", glyph.Maximize2); +export const Megaphone = /* @__PURE__ */ createIcon("Megaphone", glyph.Megaphone); +export const Menu = /* @__PURE__ */ createIcon("Menu", glyph.Menu); +export const MessageCircle = /* @__PURE__ */ createIcon("MessageCircle", glyph.MessageCircle); +export const MessageCircleQuestion = /* @__PURE__ */ createIcon("MessageCircleQuestion", glyph.MessageCircleQuestion); +export const MessageSquare = /* @__PURE__ */ createIcon("MessageSquare", glyph.MessageSquare); +export const MessageSquarePlus = /* @__PURE__ */ createIcon("MessageSquarePlus", glyph.MessageSquarePlus); +export const MessageSquareText = /* @__PURE__ */ createIcon("MessageSquareText", glyph.MessageSquare); +export const MessagesSquare = /* @__PURE__ */ createIcon("MessagesSquare", glyph.MessagesSquare); +export const Milestone = /* @__PURE__ */ createIcon("Milestone", glyph.Milestone); +export const Minimize2 = /* @__PURE__ */ createIcon("Minimize2", glyph.Minimize2); +export const Minus = /* @__PURE__ */ createIcon("Minus", glyph.Minus); +export const MinusIcon = /* @__PURE__ */ createIcon("MinusIcon", glyph.Minus); +export const Monitor = /* @__PURE__ */ createIcon("Monitor", glyph.Monitor); +export const Moon = /* @__PURE__ */ createIcon("Moon", glyph.Moon); +export const MoreHorizontal = /* @__PURE__ */ createIcon("MoreHorizontal", glyph.MoreHorizontal); +export const Network = /* @__PURE__ */ createIcon("Network", glyph.Network); +export const Newspaper = /* @__PURE__ */ createIcon("Newspaper", glyph.Newspaper); +export const OctagonXIcon = /* @__PURE__ */ createIcon("OctagonXIcon", glyph.OctagonXIcon); +export const Option = /* @__PURE__ */ createIcon("Option", glyph.Option); +export const Package = /* @__PURE__ */ createIcon("Package", glyph.Package); +export const Palette = /* @__PURE__ */ createIcon("Palette", glyph.Palette); +export const PanelLeft = /* @__PURE__ */ createIcon("PanelLeft", glyph.PanelLeft); +export const PanelLeftClose = /* @__PURE__ */ createIcon("PanelLeftClose", glyph.PanelLeftClose); +export const PanelLeftIcon = /* @__PURE__ */ createIcon("PanelLeftIcon", glyph.PanelLeft); +export const PanelLeftOpen = /* @__PURE__ */ createIcon("PanelLeftOpen", glyph.PanelLeftOpen); +export const PanelRight = /* @__PURE__ */ createIcon("PanelRight", glyph.PanelRight); +export const PanelRightClose = /* @__PURE__ */ createIcon("PanelRightClose", glyph.PanelRightClose); +export const PanelRightOpen = /* @__PURE__ */ createIcon("PanelRightOpen", glyph.PanelRightOpen); +export const Paperclip = /* @__PURE__ */ createIcon("Paperclip", glyph.Paperclip); +export const Pause = /* @__PURE__ */ createIcon("Pause", glyph.Pause); +export const PenLine = /* @__PURE__ */ createIcon("PenLine", glyph.PencilLine); +export const Pencil = /* @__PURE__ */ createIcon("Pencil", glyph.Pencil); +export const PencilLine = /* @__PURE__ */ createIcon("PencilLine", glyph.PencilLine); +export const Pin = /* @__PURE__ */ createIcon("Pin", glyph.Pin); +export const PinOff = /* @__PURE__ */ createIcon("PinOff", glyph.PinOff); +export const Pipette = /* @__PURE__ */ createIcon("Pipette", glyph.Pipette); +export const Play = /* @__PURE__ */ createIcon("Play", glyph.Play); +export const Plug = /* @__PURE__ */ createIcon("Plug", glyph.Plug); +export const PlugZap = /* @__PURE__ */ createIcon("PlugZap", glyph.PlugZap); +export const Plus = /* @__PURE__ */ createIcon("Plus", glyph.Plus); +export const Power = /* @__PURE__ */ createIcon("Power", glyph.Power); +export const Quote = /* @__PURE__ */ createIcon("Quote", glyph.Quote); +export const Redo2 = /* @__PURE__ */ createIcon("Redo2", glyph.Redo2); +export const RefreshCw = /* @__PURE__ */ createIcon("RefreshCw", glyph.RefreshCw); +export const Rocket = /* @__PURE__ */ createIcon("Rocket", glyph.Rocket); +export const RotateCcw = /* @__PURE__ */ createIcon("RotateCcw", glyph.RotateCcw); +export const RotateCw = /* @__PURE__ */ createIcon("RotateCw", glyph.RotateCw); +export const Rows3 = /* @__PURE__ */ createIcon("Rows3", glyph.Rows3); +export const Save = /* @__PURE__ */ createIcon("Save", glyph.Save); +export const ScrollText = /* @__PURE__ */ createIcon("ScrollText", glyph.ScrollText); +export const Search = /* @__PURE__ */ createIcon("Search", glyph.Search); +export const SearchIcon = /* @__PURE__ */ createIcon("SearchIcon", glyph.Search); +export const Send = /* @__PURE__ */ createIcon("Send", glyph.Send); +export const Server = /* @__PURE__ */ createIcon("Server", glyph.Server); +export const Settings = /* @__PURE__ */ createIcon("Settings", glyph.Settings); +export const Settings2 = /* @__PURE__ */ createIcon("Settings2", glyph.Settings2); +export const Shapes = /* @__PURE__ */ createIcon("Shapes", glyph.Shapes); +export const Shield = /* @__PURE__ */ createIcon("Shield", glyph.Shield); +export const ShieldCheck = /* @__PURE__ */ createIcon("ShieldCheck", glyph.ShieldCheck); +export const ShieldOff = /* @__PURE__ */ createIcon("ShieldOff", glyph.ShieldOff); +export const SignalHigh = /* @__PURE__ */ createIcon("SignalHigh", glyph.SignalHigh); +export const SkipForward = /* @__PURE__ */ createIcon("SkipForward", glyph.SkipForward); +export const SlidersHorizontal = /* @__PURE__ */ createIcon("SlidersHorizontal", glyph.SlidersHorizontal); +export const Smartphone = /* @__PURE__ */ createIcon("Smartphone", glyph.Smartphone); +export const SmilePlus = /* @__PURE__ */ createIcon("SmilePlus", glyph.SmilePlus); +export const Space = /* @__PURE__ */ createIcon("Space", glyph.Space); +export const Sparkles = /* @__PURE__ */ createIcon("Sparkles", glyph.Sparkles); +export const Square = /* @__PURE__ */ createIcon("Square", glyph.Square); +export const SquarePen = /* @__PURE__ */ createIcon("SquarePen", glyph.SquarePen); +export const SquarePlus = /* @__PURE__ */ createIcon("SquarePlus", glyph.SquarePlus); +export const SquareTerminal = /* @__PURE__ */ createIcon("SquareTerminal", glyph.SquareTerminal); +export const Star = /* @__PURE__ */ createIcon("Star", glyph.Star); +export const Strikethrough = /* @__PURE__ */ createIcon("Strikethrough", glyph.Strikethrough); +export const Sun = /* @__PURE__ */ createIcon("Sun", glyph.Sun); +export const Table2 = /* @__PURE__ */ createIcon("Table2", glyph.Table2); +export const Tablet = /* @__PURE__ */ createIcon("Tablet", glyph.Tablet); +export const Tag = /* @__PURE__ */ createIcon("Tag", glyph.Tag); +export const Tags = /* @__PURE__ */ createIcon("Tags", glyph.Tags); +export const Target = /* @__PURE__ */ createIcon("Target", glyph.Target); +export const Terminal = /* @__PURE__ */ createIcon("Terminal", glyph.Terminal); +export const Trash2 = /* @__PURE__ */ createIcon("Trash2", glyph.Trash2); +export const TriangleAlert = /* @__PURE__ */ createIcon("TriangleAlert", glyph.AlertTriangle); +export const TriangleAlertIcon = /* @__PURE__ */ createIcon("TriangleAlertIcon", glyph.AlertTriangle); +export const Type = /* @__PURE__ */ createIcon("Type", glyph.Type); +export const Undo2 = /* @__PURE__ */ createIcon("Undo2", glyph.Undo2); +export const Unlink = /* @__PURE__ */ createIcon("Unlink", glyph.Unlink); +export const Unplug = /* @__PURE__ */ createIcon("Unplug", glyph.Unplug); +export const Upload = /* @__PURE__ */ createIcon("Upload", glyph.Upload); +export const User = /* @__PURE__ */ createIcon("User", glyph.UserRound); +export const UserMinus = /* @__PURE__ */ createIcon("UserMinus", glyph.UserMinus); +export const UserPen = /* @__PURE__ */ createIcon("UserPen", glyph.UserPen); +export const UserPlus = /* @__PURE__ */ createIcon("UserPlus", glyph.UserPlus); +export const UserRound = /* @__PURE__ */ createIcon("UserRound", glyph.UserRound); +export const Users = /* @__PURE__ */ createIcon("Users", glyph.Users); +export const Waves = /* @__PURE__ */ createIcon("Waves", glyph.Waves); +export const Webhook = /* @__PURE__ */ createIcon("Webhook", glyph.Webhook); +export const Wifi = /* @__PURE__ */ createIcon("Wifi", glyph.Wifi); +export const WifiHigh = /* @__PURE__ */ createIcon("WifiHigh", glyph.WifiHigh); +export const WifiOff = /* @__PURE__ */ createIcon("WifiOff", glyph.WifiOff); +export const Workflow = /* @__PURE__ */ createIcon("Workflow", glyph.Workflow); +export const WrapText = /* @__PURE__ */ createIcon("WrapText", glyph.WrapText); +export const Wrench = /* @__PURE__ */ createIcon("Wrench", glyph.Wrench); +export const X = /* @__PURE__ */ createIcon("X", glyph.X); +export const XCircle = /* @__PURE__ */ createIcon("XCircle", glyph.XCircle); +export const XIcon = /* @__PURE__ */ createIcon("XIcon", glyph.X); +export const Zap = /* @__PURE__ */ createIcon("Zap", glyph.Zap); diff --git a/packages/ui/markdown/CodeBlock.tsx b/packages/ui/markdown/CodeBlock.tsx index a310fef12..637238728 100644 --- a/packages/ui/markdown/CodeBlock.tsx +++ b/packages/ui/markdown/CodeBlock.tsx @@ -1,6 +1,6 @@ import * as React from 'react' import { codeToHtml, bundledLanguages, type BundledLanguage } from 'shiki' -import { Copy, Check } from "lucide-react" +import { Copy, Check } from "@multica/ui/icons" import { useTranslation } from "react-i18next" import { Button } from "@multica/ui/components/ui/button" import { Tooltip, TooltipTrigger, TooltipContent } from "@multica/ui/components/ui/tooltip" diff --git a/packages/ui/markdown/Markdown.tsx b/packages/ui/markdown/Markdown.tsx index 675b55bad..6c3c1d86f 100644 --- a/packages/ui/markdown/Markdown.tsx +++ b/packages/ui/markdown/Markdown.tsx @@ -6,7 +6,7 @@ import rehypeSanitize from 'rehype-sanitize' import remarkBreaks from 'remark-breaks' import remarkGfm from 'remark-gfm' import remarkMath from 'remark-math' -import { FileText, Download } from 'lucide-react' +import { FileText, Download } from '@multica/ui/icons' import { cn } from '@multica/ui/lib/utils' import { CODE_LIGATURE_CLASS } from '@multica/ui/lib/code-style' import { CodeBlock, InlineCode } from './CodeBlock' diff --git a/packages/ui/package.json b/packages/ui/package.json index 55e57ec53..078dfc02b 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -5,6 +5,7 @@ "type": "module", "scripts": { "typecheck": "tsc --noEmit", + "icons": "node icons/drawings/generate.mjs", "lint": "eslint .", "test": "vitest run" }, @@ -23,6 +24,7 @@ "./lib/code-style": "./lib/code-style.ts", "./lib/clipboard": "./lib/clipboard.ts", "./lib/motion": "./lib/motion.ts", + "./icons": "./icons/index.ts", "./i18n-types": "./types/i18next.ts", "./styles/tokens.css": "./styles/tokens.css", "./styles/base.css": "./styles/base.css", @@ -44,7 +46,6 @@ "input-otp": "^1.4.2", "linkify-it": "^5.0.0", "katex": "catalog:", - "lucide-react": "catalog:", "next-themes": "^0.4.6", "react-day-picker": "^9.14.0", "react-markdown": "^10.1.0", diff --git a/packages/ui/styles/base.css b/packages/ui/styles/base.css index 940a2b7f0..e11e69180 100644 --- a/packages/ui/styles/base.css +++ b/packages/ui/styles/base.css @@ -2,6 +2,12 @@ * Multica shared base styles — imported by all apps * ============================================================================= */ +/* The UI locale is Chinese, Japanese or Korean. Han, kana and Hangul fill the + * whole em square, so wrapped CJK text needs more leading than the Latin value + * the type scale pairs with each size. Keyed to , which both apps + * set from the active locale. */ +@custom-variant cjk (&:is(:lang(zh), :lang(ja), :lang(ko))); + /* The chat launcher overlays the dashboard's bottom-right corner on every * workspace page, so anything that runs to that corner has to stop short of * it. Named rather than spelled out at each site: the intent is legible, every diff --git a/packages/ui/styles/tokens.css b/packages/ui/styles/tokens.css index 66579cae9..196a2aae5 100644 --- a/packages/ui/styles/tokens.css +++ b/packages/ui/styles/tokens.css @@ -93,10 +93,13 @@ /* counters, badges, timestamps, overline labels */ --text-micro: 11px; --text-micro--line-height: 15px; - /* secondary and helper text — was text-xs */ + /* chips, shortcut hints, tooltips, helper text under a field, issue + identifiers — was text-xs. Not for text people read in place: + that is label. */ --text-caption: 12px; --text-caption--line-height: 16px; - /* dense labels: table headers, metadata rows */ + /* text read in place beside body copy: activity entries, comment + timestamps, property panel rows, table headers, metadata rows */ --text-label: 13px; --text-label--line-height: 18px; /* UI body, the workhorse — was text-sm */ diff --git a/packages/views/agents/components/agent-activity-hover-content.tsx b/packages/views/agents/components/agent-activity-hover-content.tsx index aa2f1fd89..c554f2cff 100644 --- a/packages/views/agents/components/agent-activity-hover-content.tsx +++ b/packages/views/agents/components/agent-activity-hover-content.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useState } from "react"; -import { Bell } from "lucide-react"; +import { Bell } from "@multica/ui/icons"; import { useQuery } from "@tanstack/react-query"; import { ActorAvatar as ActorAvatarBase } from "@multica/ui/components/common/actor-avatar"; import { useActorName } from "@multica/core/workspace/hooks"; diff --git a/packages/views/agents/components/agent-batch-toolbar.tsx b/packages/views/agents/components/agent-batch-toolbar.tsx index 76e3cea36..d3746679e 100644 --- a/packages/views/agents/components/agent-batch-toolbar.tsx +++ b/packages/views/agents/components/agent-batch-toolbar.tsx @@ -22,7 +22,7 @@ import { DialogHeader, DialogTitle, } from "@multica/ui/components/ui/dialog"; -import { Archive, ArchiveRestore, Loader2, X } from "lucide-react"; +import { Archive, ArchiveRestore, Loader2, X } from "@multica/ui/icons"; import { useT } from "../../i18n"; import { AccessPicker, type AccessChange } from "./inspector/access-picker"; import type { AgentListRow } from "./agents-page"; diff --git a/packages/views/agents/components/agent-detail-page.tsx b/packages/views/agents/components/agent-detail-page.tsx index e50db669b..c38254eef 100644 --- a/packages/views/agents/components/agent-detail-page.tsx +++ b/packages/views/agents/components/agent-detail-page.tsx @@ -13,7 +13,7 @@ import { Plus, Server, Trash2, -} from "lucide-react"; +} from "@multica/ui/icons"; import { toast } from "sonner"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import type { diff --git a/packages/views/agents/components/agent-list-toolbar.tsx b/packages/views/agents/components/agent-list-toolbar.tsx index c649dd07b..8ebb703f6 100644 --- a/packages/views/agents/components/agent-list-toolbar.tsx +++ b/packages/views/agents/components/agent-list-toolbar.tsx @@ -7,7 +7,7 @@ import { Filter, Search, X, -} from "lucide-react"; +} from "@multica/ui/icons"; import { ALL_ACCESS_SCOPES, effectiveAccessScope, diff --git a/packages/views/agents/components/agent-live-peek-card.tsx b/packages/views/agents/components/agent-live-peek-card.tsx index 91dd15090..4081091af 100644 --- a/packages/views/agents/components/agent-live-peek-card.tsx +++ b/packages/views/agents/components/agent-live-peek-card.tsx @@ -14,7 +14,7 @@ import { } from "@multica/core/agents"; import { issueDetailOptions } from "@multica/core/issues"; import type { AgentTask } from "@multica/core/types"; -import { AlertTriangle } from "lucide-react"; +import { AlertTriangle } from "@multica/ui/icons"; import { AppLink } from "../../navigation"; import { useT, useTimeAgo } from "../../i18n"; import { availabilityConfig, workloadConfig } from "../presence"; diff --git a/packages/views/agents/components/agent-overview-summary.tsx b/packages/views/agents/components/agent-overview-summary.tsx index 76d235ba1..e1743f145 100644 --- a/packages/views/agents/components/agent-overview-summary.tsx +++ b/packages/views/agents/components/agent-overview-summary.tsx @@ -1,6 +1,6 @@ "use client"; -import { Bot, Server } from "lucide-react"; +import { Bot, Server } from "@multica/ui/icons"; import type { Agent, AgentRuntime, diff --git a/packages/views/agents/components/agent-profile-card.test.tsx b/packages/views/agents/components/agent-profile-card.test.tsx index 981e761cc..da35aba89 100644 --- a/packages/views/agents/components/agent-profile-card.test.tsx +++ b/packages/views/agents/components/agent-profile-card.test.tsx @@ -141,9 +141,9 @@ beforeEach(() => { describe("AgentProfileCard — Runtime row", () => { it.each([ - ["online", "svg.lucide-wifi"], - ["unstable", "svg.lucide-wifi-high"], - ["offline", "svg.lucide-wifi-off"], + ["online", "svg.icon-wifi"], + ["unstable", "svg.icon-wifi-high"], + ["offline", "svg.icon-wifi-off"], ] as const)( "uses projected %s availability when the private runtime row is hidden", (runtimeAvailability, iconSelector) => { diff --git a/packages/views/agents/components/agent-row-actions.tsx b/packages/views/agents/components/agent-row-actions.tsx index 3bfe1a91d..0b1b44f63 100644 --- a/packages/views/agents/components/agent-row-actions.tsx +++ b/packages/views/agents/components/agent-row-actions.tsx @@ -9,7 +9,7 @@ import { RotateCcw, Square, Trash2, -} from "lucide-react"; +} from "@multica/ui/icons"; import { useQueryClient } from "@tanstack/react-query"; import { toast } from "sonner"; import type { Agent } from "@multica/core/types"; diff --git a/packages/views/agents/components/agents-page.tsx b/packages/views/agents/components/agents-page.tsx index 625bf82b3..08394a53d 100644 --- a/packages/views/agents/components/agents-page.tsx +++ b/packages/views/agents/components/agents-page.tsx @@ -6,7 +6,7 @@ import { Bot, Lock, Plus, -} from "lucide-react"; +} from "@multica/ui/icons"; import { useQuery } from "@tanstack/react-query"; import { useVirtualizer } from "@tanstack/react-virtual"; import type { diff --git a/packages/views/agents/components/conversation-starters-editor.tsx b/packages/views/agents/components/conversation-starters-editor.tsx index dd6a345f5..385720ee9 100644 --- a/packages/views/agents/components/conversation-starters-editor.tsx +++ b/packages/views/agents/components/conversation-starters-editor.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { MessageSquare, Pencil, Plus, Trash2 } from "lucide-react"; +import { MessageSquare, Pencil, Plus, Trash2 } from "@multica/ui/icons"; import { AGENT_CONVERSATION_STARTER_LABEL_MAX_LENGTH, AGENT_CONVERSATION_STARTER_MAX_LENGTH, diff --git a/packages/views/agents/components/create-agent-dialog.tsx b/packages/views/agents/components/create-agent-dialog.tsx index b6cebdb2b..d3351c811 100644 --- a/packages/views/agents/components/create-agent-dialog.tsx +++ b/packages/views/agents/components/create-agent-dialog.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { Globe, Lock, Users } from "lucide-react"; +import { Globe, Lock, Users } from "@multica/ui/icons"; import { useQueryClient } from "@tanstack/react-query"; import { ModelDropdown } from "./model-dropdown"; import { RuntimePicker } from "./runtime-picker"; diff --git a/packages/views/agents/components/inspector/access-picker.tsx b/packages/views/agents/components/inspector/access-picker.tsx index d33c38b50..53f8b9d20 100644 --- a/packages/views/agents/components/inspector/access-picker.tsx +++ b/packages/views/agents/components/inspector/access-picker.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useMemo, useRef, useState } from "react"; -import { Globe, Loader2, Lock, Users } from "lucide-react"; +import { Globe, Loader2, Lock, Users } from "@multica/ui/icons"; import type { AgentInvocationTarget, AgentInvocationTargetInput, diff --git a/packages/views/agents/components/inspector/model-picker.tsx b/packages/views/agents/components/inspector/model-picker.tsx index ae423b64c..ca4304d94 100644 --- a/packages/views/agents/components/inspector/model-picker.tsx +++ b/packages/views/agents/components/inspector/model-picker.tsx @@ -2,7 +2,7 @@ import { useMemo, useState } from "react"; import { useQuery, useQueryClient } from "@tanstack/react-query"; -import { ChevronDown, Cpu, Loader2, Plus } from "lucide-react"; +import { ChevronDown, Cpu, Loader2, Plus } from "@multica/ui/icons"; import { refreshRuntimeModels, runtimeModelsOptions, diff --git a/packages/views/agents/components/inspector/runtime-picker.tsx b/packages/views/agents/components/inspector/runtime-picker.tsx index b22480cee..665701d0d 100644 --- a/packages/views/agents/components/inspector/runtime-picker.tsx +++ b/packages/views/agents/components/inspector/runtime-picker.tsx @@ -8,7 +8,7 @@ import { ChevronRight, Lock, Monitor, -} from "lucide-react"; +} from "@multica/ui/icons"; import { isRuntimeUsableForUser } from "@multica/core/runtimes"; import type { AgentRuntime, MemberWithUser } from "@multica/core/types"; import { ActorAvatar } from "../../../common/actor-avatar"; diff --git a/packages/views/agents/components/inspector/service-tier-setting-field.tsx b/packages/views/agents/components/inspector/service-tier-setting-field.tsx index 7d5d8ada5..bb5a86cb3 100644 --- a/packages/views/agents/components/inspector/service-tier-setting-field.tsx +++ b/packages/views/agents/components/inspector/service-tier-setting-field.tsx @@ -2,7 +2,7 @@ import { useState, type ReactNode } from "react"; import { useQuery } from "@tanstack/react-query"; -import { ChevronDown, Gauge } from "lucide-react"; +import { ChevronDown, Gauge } from "@multica/ui/icons"; import type { RuntimeModelServiceTier } from "@multica/core/types"; import { runtimeModelsOptions } from "@multica/core/runtimes"; import { diff --git a/packages/views/agents/components/inspector/skill-attach.tsx b/packages/views/agents/components/inspector/skill-attach.tsx index dc0b4e8de..f01ca24d0 100644 --- a/packages/views/agents/components/inspector/skill-attach.tsx +++ b/packages/views/agents/components/inspector/skill-attach.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { Plus } from "lucide-react"; +import { Plus } from "@multica/ui/icons"; import { useQuery } from "@tanstack/react-query"; import type { Agent } from "@multica/core/types"; import { useWorkspaceId } from "@multica/core/hooks"; diff --git a/packages/views/agents/components/inspector/thinking-picker.tsx b/packages/views/agents/components/inspector/thinking-picker.tsx index 67992ff65..4953a1ae0 100644 --- a/packages/views/agents/components/inspector/thinking-picker.tsx +++ b/packages/views/agents/components/inspector/thinking-picker.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { Brain, ChevronDown } from "lucide-react"; +import { Brain, ChevronDown } from "@multica/ui/icons"; import type { RuntimeModelThinkingLevel } from "@multica/core/types"; import { Label } from "@multica/ui/components/ui/label"; import { diff --git a/packages/views/agents/components/inspector/visibility-picker.tsx b/packages/views/agents/components/inspector/visibility-picker.tsx index 52919ab13..e7e2c6e2e 100644 --- a/packages/views/agents/components/inspector/visibility-picker.tsx +++ b/packages/views/agents/components/inspector/visibility-picker.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { Globe, Lock } from "lucide-react"; +import { Globe, Lock } from "@multica/ui/icons"; import { VISIBILITY_DESCRIPTION, VISIBILITY_LABEL, diff --git a/packages/views/agents/components/instructions-editor.tsx b/packages/views/agents/components/instructions-editor.tsx index 5b61ca2a4..b167a94e5 100644 --- a/packages/views/agents/components/instructions-editor.tsx +++ b/packages/views/agents/components/instructions-editor.tsx @@ -1,7 +1,7 @@ "use client"; import { useRef, useState } from "react"; -import { ChevronDown, FileText, X } from "lucide-react"; +import { ChevronDown, FileText, X } from "@multica/ui/icons"; import { ContentEditor, type ContentEditorRef } from "../../editor"; import { Button } from "@multica/ui/components/ui/button"; import { cn } from "@multica/ui/lib/utils"; diff --git a/packages/views/agents/components/model-dropdown.tsx b/packages/views/agents/components/model-dropdown.tsx index f64bcaeb8..ef35fba5a 100644 --- a/packages/views/agents/components/model-dropdown.tsx +++ b/packages/views/agents/components/model-dropdown.tsx @@ -2,7 +2,7 @@ import { useEffect, useMemo, useState } from "react"; import { useQuery, useQueryClient } from "@tanstack/react-query"; -import { ChevronDown, Cpu, Loader2, Plus, Check, Info } from "lucide-react"; +import { ChevronDown, Cpu, Loader2, Plus, Check, Info } from "@multica/ui/icons"; import { refreshRuntimeModels, runtimeModelsOptions, diff --git a/packages/views/agents/components/model-search-header.tsx b/packages/views/agents/components/model-search-header.tsx index 5b1ec141b..4f3bd8d29 100644 --- a/packages/views/agents/components/model-search-header.tsx +++ b/packages/views/agents/components/model-search-header.tsx @@ -1,6 +1,6 @@ "use client"; -import { RefreshCw } from "lucide-react"; +import { RefreshCw } from "@multica/ui/icons"; import { IconButton } from "@multica/ui/components/common/icon-button"; import { Input } from "@multica/ui/components/ui/input"; import { useT } from "../../i18n"; diff --git a/packages/views/agents/components/runtime-machine-filter-dropdown.tsx b/packages/views/agents/components/runtime-machine-filter-dropdown.tsx index ddfd0ced2..92a6ded95 100644 --- a/packages/views/agents/components/runtime-machine-filter-dropdown.tsx +++ b/packages/views/agents/components/runtime-machine-filter-dropdown.tsx @@ -1,5 +1,5 @@ import { useMemo } from "react"; -import { ChevronDown, Server } from "lucide-react"; +import { ChevronDown, Server } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { DropdownMenu, diff --git a/packages/views/agents/components/runtime-picker.tsx b/packages/views/agents/components/runtime-picker.tsx index 5eb1047fe..38fd78239 100644 --- a/packages/views/agents/components/runtime-picker.tsx +++ b/packages/views/agents/components/runtime-picker.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useMemo, useState } from "react"; -import { ChevronDown, Cloud, Loader2, Lock, Search } from "lucide-react"; +import { ChevronDown, Cloud, Loader2, Lock, Search } from "@multica/ui/icons"; import { ProviderLogo } from "../../runtimes/components/provider-logo"; import { ActorAvatar } from "../../common/actor-avatar"; import { diff --git a/packages/views/agents/components/skill-multi-select.tsx b/packages/views/agents/components/skill-multi-select.tsx index 125a21440..24a8b4b5f 100644 --- a/packages/views/agents/components/skill-multi-select.tsx +++ b/packages/views/agents/components/skill-multi-select.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { ChevronDown, Plus, X } from "lucide-react"; +import { ChevronDown, Plus, X } from "@multica/ui/icons"; import { useQuery } from "@tanstack/react-query"; import type { SkillSummary } from "@multica/core/types"; import { useWorkspaceId } from "@multica/core/hooks"; diff --git a/packages/views/agents/components/skill-picker-list.tsx b/packages/views/agents/components/skill-picker-list.tsx index 497384b70..ae97fdec2 100644 --- a/packages/views/agents/components/skill-picker-list.tsx +++ b/packages/views/agents/components/skill-picker-list.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { Search } from "lucide-react"; +import { Search } from "@multica/ui/icons"; import { SkillIcon } from "../../skills/lib/skill-icon"; import type { SkillSummary } from "@multica/core/types"; import { Checkbox } from "@multica/ui/components/ui/checkbox"; diff --git a/packages/views/agents/components/tabs/activity-tab.tsx b/packages/views/agents/components/tabs/activity-tab.tsx index d1d3c93c9..137683dd8 100644 --- a/packages/views/agents/components/tabs/activity-tab.tsx +++ b/packages/views/agents/components/tabs/activity-tab.tsx @@ -9,7 +9,7 @@ import { MessageSquare, Workflow, X, -} from "lucide-react"; +} from "@multica/ui/icons"; import { toast } from "sonner"; import { Tooltip, diff --git a/packages/views/agents/components/tabs/agent-mcp-tab.tsx b/packages/views/agents/components/tabs/agent-mcp-tab.tsx index ef42461f3..2d4051483 100644 --- a/packages/views/agents/components/tabs/agent-mcp-tab.tsx +++ b/packages/views/agents/components/tabs/agent-mcp-tab.tsx @@ -2,7 +2,7 @@ import { useMemo } from "react"; import { useQuery } from "@tanstack/react-query"; -import { AlertTriangle, Loader2, Lock, Plug } from "lucide-react"; +import { AlertTriangle, Loader2, Lock, Plug } from "@multica/ui/icons"; import { toast } from "sonner"; import type { Agent, ComposioToolkit } from "@multica/core/types"; import { useUpdateAgentAllowlist } from "@multica/core/agents"; diff --git a/packages/views/agents/components/tabs/custom-args-tab.tsx b/packages/views/agents/components/tabs/custom-args-tab.tsx index 217ffcfab..8a91e9474 100644 --- a/packages/views/agents/components/tabs/custom-args-tab.tsx +++ b/packages/views/agents/components/tabs/custom-args-tab.tsx @@ -8,7 +8,7 @@ import { Save, Terminal, Trash2, -} from "lucide-react"; +} from "@multica/ui/icons"; import type { Agent, RuntimeDevice } from "@multica/core/types"; import { createSafeId } from "@multica/core/utils"; import { Button } from "@multica/ui/components/ui/button"; diff --git a/packages/views/agents/components/tabs/env-tab.tsx b/packages/views/agents/components/tabs/env-tab.tsx index 33b5c3b7e..fe1659f73 100644 --- a/packages/views/agents/components/tabs/env-tab.tsx +++ b/packages/views/agents/components/tabs/env-tab.tsx @@ -12,7 +12,7 @@ import { Save, Trash2, WrapText, -} from "lucide-react"; +} from "@multica/ui/icons"; import { api } from "@multica/core/api"; import type { Agent } from "@multica/core/types"; import { Button } from "@multica/ui/components/ui/button"; diff --git a/packages/views/agents/components/tabs/instructions-tab.tsx b/packages/views/agents/components/tabs/instructions-tab.tsx index 94c800ab6..b6f22f036 100644 --- a/packages/views/agents/components/tabs/instructions-tab.tsx +++ b/packages/views/agents/components/tabs/instructions-tab.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useRef, useState } from "react"; -import { Loader2, Save } from "lucide-react"; +import { Loader2, Save } from "@multica/ui/icons"; import type { Agent } from "@multica/core/types"; import { Button } from "@multica/ui/components/ui/button"; import { Textarea } from "@multica/ui/components/ui/textarea"; diff --git a/packages/views/agents/components/tabs/mcp-config-tab.tsx b/packages/views/agents/components/tabs/mcp-config-tab.tsx index 0d4ddba96..779a85dae 100644 --- a/packages/views/agents/components/tabs/mcp-config-tab.tsx +++ b/packages/views/agents/components/tabs/mcp-config-tab.tsx @@ -7,7 +7,7 @@ import { Plus, RefreshCw, Server, -} from "lucide-react"; +} from "@multica/ui/icons"; import { useQuery } from "@tanstack/react-query"; import type { Agent, AgentRuntime, WorkspaceMcpServer } from "@multica/core/types"; import { ApiError } from "@multica/core/api"; diff --git a/packages/views/agents/components/tabs/mcp-server-dialog.tsx b/packages/views/agents/components/tabs/mcp-server-dialog.tsx index 42057b788..d2dc5bfda 100644 --- a/packages/views/agents/components/tabs/mcp-server-dialog.tsx +++ b/packages/views/agents/components/tabs/mcp-server-dialog.tsx @@ -7,7 +7,7 @@ import { useRef, useState, } from "react"; -import { Globe2, Loader2, Plus, SquareTerminal, Trash2 } from "lucide-react"; +import { Globe2, Loader2, Plus, SquareTerminal, Trash2 } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { IconButton } from "@multica/ui/components/common/icon-button"; import { cn } from "@multica/ui/lib/utils"; diff --git a/packages/views/agents/components/tabs/runtime-config-tab.tsx b/packages/views/agents/components/tabs/runtime-config-tab.tsx index 0aa3a52f3..ba9dffa2b 100644 --- a/packages/views/agents/components/tabs/runtime-config-tab.tsx +++ b/packages/views/agents/components/tabs/runtime-config-tab.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useMemo, useRef, useState } from "react"; -import { Loader2, Save } from "lucide-react"; +import { Loader2, Save } from "@multica/ui/icons"; import type { Agent } from "@multica/core/types"; import { OPENCLAW_GATEWAY_TOKEN_MASK, diff --git a/packages/views/agents/components/tabs/skills-tab.tsx b/packages/views/agents/components/tabs/skills-tab.tsx index ef8da528e..6c3e402ab 100644 --- a/packages/views/agents/components/tabs/skills-tab.tsx +++ b/packages/views/agents/components/tabs/skills-tab.tsx @@ -7,7 +7,7 @@ import { RefreshCw, Server, Trash2, -} from "lucide-react"; +} from "@multica/ui/icons"; import { SkillIcon } from "../../../skills/lib/skill-icon"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { toast } from "sonner"; diff --git a/packages/views/agents/components/visibility-badge.tsx b/packages/views/agents/components/visibility-badge.tsx index eebaeee6a..8fcdddfd7 100644 --- a/packages/views/agents/components/visibility-badge.tsx +++ b/packages/views/agents/components/visibility-badge.tsx @@ -1,6 +1,6 @@ "use client"; -import { Globe, Lock } from "lucide-react"; +import { Globe, Lock } from "@multica/ui/icons"; import type { AgentVisibility } from "@multica/core/types"; import { Tooltip, TooltipTrigger, TooltipContent } from "@multica/ui/components/ui/tooltip"; import { useT } from "../../i18n"; diff --git a/packages/views/agents/config.ts b/packages/views/agents/config.ts index 0e694be21..44d717046 100644 --- a/packages/views/agents/config.ts +++ b/packages/views/agents/config.ts @@ -4,7 +4,7 @@ import { XCircle, Loader2, Play, -} from "lucide-react"; +} from "@multica/ui/icons"; // Visual-only mapping for a task status: icon + tone. Deliberately carries no // `label` — the human-readable status word comes from `taskStatusLabel(status, t)` diff --git a/packages/views/agents/create/agent-created-page.tsx b/packages/views/agents/create/agent-created-page.tsx index deb8e4796..194fca6a4 100644 --- a/packages/views/agents/create/agent-created-page.tsx +++ b/packages/views/agents/create/agent-created-page.tsx @@ -1,7 +1,7 @@ "use client"; import type { ReactNode } from "react"; -import { ArrowRight, AtSign, CircleCheck, ListPlus, Users } from "lucide-react"; +import { ArrowRight, AtSign, CircleCheck, ListPlus, Users } from "@multica/ui/icons"; import { useQuery } from "@tanstack/react-query"; import { useWorkspaceId } from "@multica/core/hooks"; import { useModalStore } from "@multica/core/modals"; diff --git a/packages/views/agents/create/builder-conversation.tsx b/packages/views/agents/create/builder-conversation.tsx index 3a57b5d31..55015f375 100644 --- a/packages/views/agents/create/builder-conversation.tsx +++ b/packages/views/agents/create/builder-conversation.tsx @@ -1,7 +1,7 @@ "use client"; import type { ReactNode } from "react"; -import { Loader2, MessageSquare, X } from "lucide-react"; +import { Loader2, MessageSquare, X } from "@multica/ui/icons"; import { applyDraftModelChange, applyDraftRuntimeChange, diff --git a/packages/views/agents/create/choose-runtime-page.tsx b/packages/views/agents/create/choose-runtime-page.tsx index 94060651b..7a9250e3b 100644 --- a/packages/views/agents/create/choose-runtime-page.tsx +++ b/packages/views/agents/create/choose-runtime-page.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useMemo, useRef, useState } from "react"; -import { ArrowRight, Search } from "lucide-react"; +import { ArrowRight, Search } from "@multica/ui/icons"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { agentBuilderSessionListOptions } from "@multica/core/agents"; import { useAuthStore } from "@multica/core/auth"; diff --git a/packages/views/agents/create/create-agent-footer.tsx b/packages/views/agents/create/create-agent-footer.tsx index 95c96c474..e25b4651d 100644 --- a/packages/views/agents/create/create-agent-footer.tsx +++ b/packages/views/agents/create/create-agent-footer.tsx @@ -1,6 +1,6 @@ "use client"; -import { Loader2 } from "lucide-react"; +import { Loader2 } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { cn } from "@multica/ui/lib/utils"; import { useT } from "../../i18n"; diff --git a/packages/views/agents/create/create-shell.tsx b/packages/views/agents/create/create-shell.tsx index d7591288e..25c3520a5 100644 --- a/packages/views/agents/create/create-shell.tsx +++ b/packages/views/agents/create/create-shell.tsx @@ -1,7 +1,7 @@ "use client"; import { Fragment, type ReactNode } from "react"; -import { ArrowLeft, Check, X } from "lucide-react"; +import { ArrowLeft, Check, X } from "@multica/ui/icons"; import { IconButton } from "@multica/ui/components/common/icon-button"; import { cn } from "@multica/ui/lib/utils"; import { useT } from "../../i18n"; diff --git a/packages/views/agents/create/manual-create-agent-page.tsx b/packages/views/agents/create/manual-create-agent-page.tsx index 5a4dfbfa4..5ee69ad9e 100644 --- a/packages/views/agents/create/manual-create-agent-page.tsx +++ b/packages/views/agents/create/manual-create-agent-page.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useState } from "react"; -import { Loader2, Sparkles } from "lucide-react"; +import { Loader2, Sparkles } from "@multica/ui/icons"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { api } from "@multica/core/api"; import { diff --git a/packages/views/agents/create/runtime-choice-list.tsx b/packages/views/agents/create/runtime-choice-list.tsx index 26a9befaf..13a839fe7 100644 --- a/packages/views/agents/create/runtime-choice-list.tsx +++ b/packages/views/agents/create/runtime-choice-list.tsx @@ -13,7 +13,7 @@ import { Plus, SquareTerminal, TriangleAlert, -} from "lucide-react"; +} from "@multica/ui/icons"; import type { QoderConnection } from "@multica/core/runtimes/qoder"; import { Button, buttonVariants } from "@multica/ui/components/ui/button"; import { cn } from "@multica/ui/lib/utils"; diff --git a/packages/views/agents/create/unfinished-drafts.tsx b/packages/views/agents/create/unfinished-drafts.tsx index 26919234e..fb518a2bc 100644 --- a/packages/views/agents/create/unfinished-drafts.tsx +++ b/packages/views/agents/create/unfinished-drafts.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { ChevronRight, MessageSquare } from "lucide-react"; +import { ChevronRight, MessageSquare } from "@multica/ui/icons"; import { decodeBuilderInput, stripBuilderDraft } from "@multica/core/agents"; import type { AgentBuilderSessionSummary } from "@multica/core/types"; import { diff --git a/packages/views/agents/presence.ts b/packages/views/agents/presence.ts index 556b4956f..e5388296e 100644 --- a/packages/views/agents/presence.ts +++ b/packages/views/agents/presence.ts @@ -6,8 +6,8 @@ import { Clock, Loader2, PlugZap, - type LucideIcon, -} from "lucide-react"; + type IconComponent, +} from "@multica/ui/icons"; import type { AgentAvailability, Workload } from "@multica/core/agents"; // Visual mapping for the two presence dimensions, kept in matching shape @@ -44,7 +44,7 @@ export interface AvailabilityVisual { // Foreground colour for the label text alongside the dot. textClass: string; // Icon used in larger badge contexts (detail header, hover card). - icon: LucideIcon; + icon: IconComponent; } export const availabilityConfig: Record = { @@ -86,7 +86,7 @@ export interface WorkloadVisual { // Foreground colour for icon + label text. textClass: string; // Icon used inline. - icon: LucideIcon; + icon: IconComponent; } export const workloadConfig: Record = { diff --git a/packages/views/attachments/attachment-preview-page.tsx b/packages/views/attachments/attachment-preview-page.tsx index 923845283..45c63e0dd 100644 --- a/packages/views/attachments/attachment-preview-page.tsx +++ b/packages/views/attachments/attachment-preview-page.tsx @@ -29,7 +29,7 @@ import { useCallback, useEffect } from "react"; import { useQuery } from "@tanstack/react-query"; -import { Loader2 } from "lucide-react"; +import { Loader2 } from "@multica/ui/icons"; import { api } from "@multica/core/api"; import { useT } from "../i18n"; import { useRestoredViewState, useViewStateWriter } from "../platform"; diff --git a/packages/views/autopilots/components/autopilot-access-manager.tsx b/packages/views/autopilots/components/autopilot-access-manager.tsx index bd1b57119..bf9d89981 100644 --- a/packages/views/autopilots/components/autopilot-access-manager.tsx +++ b/packages/views/autopilots/components/autopilot-access-manager.tsx @@ -1,7 +1,7 @@ "use client"; import { useMemo, useState } from "react"; -import { Plus, X } from "lucide-react"; +import { Plus, X } from "@multica/ui/icons"; import { useQuery } from "@tanstack/react-query"; import { useWorkspaceId } from "@multica/core/hooks"; import { memberListOptions } from "@multica/core/workspace/queries"; diff --git a/packages/views/autopilots/components/autopilot-detail-page.tsx b/packages/views/autopilots/components/autopilot-detail-page.tsx index 5f93ec2e9..1800dfe1c 100644 --- a/packages/views/autopilots/components/autopilot-detail-page.tsx +++ b/packages/views/autopilots/components/autopilot-detail-page.tsx @@ -5,7 +5,7 @@ import { Zap, Play, Clock, Plus, Trash2, CheckCircle2, XCircle, Loader2, Pencil, Ban, ChevronDown, ChevronRight, Webhook, RotateCw, Server, -} from "lucide-react"; +} from "@multica/ui/icons"; import { useQuery } from "@tanstack/react-query"; import { autopilotDetailOptions, autopilotRunsOptions, autopilotRunOptions } from "@multica/core/autopilots/queries"; import { projectDetailOptions } from "@multica/core/projects/queries"; diff --git a/packages/views/autopilots/components/autopilot-dialog.tsx b/packages/views/autopilots/components/autopilot-dialog.tsx index fb5036659..9c18ac1a5 100644 --- a/packages/views/autopilots/components/autopilot-dialog.tsx +++ b/packages/views/autopilots/components/autopilot-dialog.tsx @@ -19,7 +19,7 @@ import { Webhook, X as XIcon, Zap, -} from "lucide-react"; +} from "@multica/ui/icons"; import { cn } from "@multica/ui/lib/utils"; import { Dialog, diff --git a/packages/views/autopilots/components/autopilot-list-actions.tsx b/packages/views/autopilots/components/autopilot-list-actions.tsx index f9c17b4fd..fc3ef387d 100644 --- a/packages/views/autopilots/components/autopilot-list-actions.tsx +++ b/packages/views/autopilots/components/autopilot-list-actions.tsx @@ -9,7 +9,7 @@ import { Play, Trash2, X, -} from "lucide-react"; +} from "@multica/ui/icons"; import { toast } from "sonner"; import type { Autopilot } from "@multica/core/types"; import { diff --git a/packages/views/autopilots/components/autopilot-list-toolbar.tsx b/packages/views/autopilots/components/autopilot-list-toolbar.tsx index 95c3b6f26..5553467a5 100644 --- a/packages/views/autopilots/components/autopilot-list-toolbar.tsx +++ b/packages/views/autopilots/components/autopilot-list-toolbar.tsx @@ -6,7 +6,7 @@ import { ChevronDown, Filter, X, -} from "lucide-react"; +} from "@multica/ui/icons"; import type { Autopilot } from "@multica/core/types"; import { AUTOPILOT_SCOPES, diff --git a/packages/views/autopilots/components/autopilots-page.tsx b/packages/views/autopilots/components/autopilots-page.tsx index a0ec289c6..9321bb090 100644 --- a/packages/views/autopilots/components/autopilots-page.tsx +++ b/packages/views/autopilots/components/autopilots-page.tsx @@ -15,7 +15,7 @@ import { Shield, Webhook, Zap, -} from "lucide-react"; +} from "@multica/ui/icons"; import { useQuery } from "@tanstack/react-query"; import { useVirtualizer } from "@tanstack/react-virtual"; import { autopilotListOptions } from "@multica/core/autopilots/queries"; diff --git a/packages/views/autopilots/components/pickers/agent-picker.tsx b/packages/views/autopilots/components/pickers/agent-picker.tsx index 06175b82e..32e184cf0 100644 --- a/packages/views/autopilots/components/pickers/agent-picker.tsx +++ b/packages/views/autopilots/components/pickers/agent-picker.tsx @@ -2,7 +2,7 @@ import { useMemo, useState } from "react"; import { useQuery } from "@tanstack/react-query"; -import { Bot, CircleDashed } from "lucide-react"; +import { Bot, CircleDashed } from "@multica/ui/icons"; import { useWorkspaceId } from "@multica/core/hooks"; import { isAgentRuntimeBound } from "@multica/core/agents"; import { agentListOptions, squadListOptions } from "@multica/core/workspace/queries"; diff --git a/packages/views/autopilots/components/pickers/timezone-picker.tsx b/packages/views/autopilots/components/pickers/timezone-picker.tsx index 5dbeb0567..8fb1da5b5 100644 --- a/packages/views/autopilots/components/pickers/timezone-picker.tsx +++ b/packages/views/autopilots/components/pickers/timezone-picker.tsx @@ -1,7 +1,7 @@ "use client"; import { useMemo, useState } from "react"; -import { Check, ChevronDown, Globe } from "lucide-react"; +import { Check, ChevronDown, Globe } from "@multica/ui/icons"; import { cn } from "@multica/ui/lib/utils"; import { PropertyPicker, diff --git a/packages/views/autopilots/components/schedule-editor/schedule-editor.tsx b/packages/views/autopilots/components/schedule-editor/schedule-editor.tsx index 7b0ebba9b..52c5de350 100644 --- a/packages/views/autopilots/components/schedule-editor/schedule-editor.tsx +++ b/packages/views/autopilots/components/schedule-editor/schedule-editor.tsx @@ -11,7 +11,7 @@ import { type ReactNode, } from "react"; import { useQuery } from "@tanstack/react-query"; -import { Clock, Pencil } from "lucide-react"; +import { Clock, Pencil } from "@multica/ui/icons"; import { cn } from "@multica/ui/lib/utils"; import { Input } from "@multica/ui/components/ui/input"; import { diff --git a/packages/views/autopilots/components/subscriber-multi-select.tsx b/packages/views/autopilots/components/subscriber-multi-select.tsx index a49082ed7..92d401f9a 100644 --- a/packages/views/autopilots/components/subscriber-multi-select.tsx +++ b/packages/views/autopilots/components/subscriber-multi-select.tsx @@ -1,7 +1,7 @@ "use client"; import { useMemo, useState } from "react"; -import { Plus, X } from "lucide-react"; +import { Plus, X } from "@multica/ui/icons"; import { useQuery } from "@tanstack/react-query"; import { useWorkspaceId } from "@multica/core/hooks"; import { memberListOptions } from "@multica/core/workspace/queries"; diff --git a/packages/views/autopilots/components/webhook-deliveries-section.tsx b/packages/views/autopilots/components/webhook-deliveries-section.tsx index 70259e188..4a2a80bf2 100644 --- a/packages/views/autopilots/components/webhook-deliveries-section.tsx +++ b/packages/views/autopilots/components/webhook-deliveries-section.tsx @@ -12,7 +12,7 @@ import { Copy, Check, Webhook, -} from "lucide-react"; +} from "@multica/ui/icons"; import { useQuery } from "@tanstack/react-query"; import { autopilotDeliveriesOptions, diff --git a/packages/views/autopilots/components/webhook-event-filter-section.tsx b/packages/views/autopilots/components/webhook-event-filter-section.tsx index f5e740701..cd85ef990 100644 --- a/packages/views/autopilots/components/webhook-event-filter-section.tsx +++ b/packages/views/autopilots/components/webhook-event-filter-section.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { X, Plus, Filter, ExternalLink } from "lucide-react"; +import { X, Plus, Filter, ExternalLink } from "@multica/ui/icons"; import { cn } from "@multica/ui/lib/utils"; import { TooltipHint } from "@multica/ui/components/common/tooltip-hint"; import type { WebhookEventFilter } from "@multica/core/types"; diff --git a/packages/views/autopilots/components/webhook-payload-preview.tsx b/packages/views/autopilots/components/webhook-payload-preview.tsx index 51fd09c7b..01b9df18b 100644 --- a/packages/views/autopilots/components/webhook-payload-preview.tsx +++ b/packages/views/autopilots/components/webhook-payload-preview.tsx @@ -1,7 +1,7 @@ "use client"; import { useState, useMemo } from "react"; -import { Webhook, ChevronDown, ChevronRight, Copy, Check } from "lucide-react"; +import { Webhook, ChevronDown, ChevronRight, Copy, Check } from "@multica/ui/icons"; import { toast } from "sonner"; import { cn } from "@multica/ui/lib/utils"; import { copyText } from "@multica/ui/lib/clipboard"; diff --git a/packages/views/autopilots/components/webhook-url-field.tsx b/packages/views/autopilots/components/webhook-url-field.tsx index 7f8e567ca..e1f94340b 100644 --- a/packages/views/autopilots/components/webhook-url-field.tsx +++ b/packages/views/autopilots/components/webhook-url-field.tsx @@ -1,7 +1,7 @@ "use client"; import { useState, type ReactNode } from "react"; -import { Check, Copy, Eye, EyeOff } from "lucide-react"; +import { Check, Copy, Eye, EyeOff } from "@multica/ui/icons"; import { toast } from "sonner"; import { maskAutopilotWebhookUrl } from "@multica/core/autopilots"; import { IconButton } from "@multica/ui/components/common/icon-button"; diff --git a/packages/views/autopilots/components/workspace-wakeups.tsx b/packages/views/autopilots/components/workspace-wakeups.tsx index 105f899a0..b50998036 100644 --- a/packages/views/autopilots/components/workspace-wakeups.tsx +++ b/packages/views/autopilots/components/workspace-wakeups.tsx @@ -2,7 +2,7 @@ import { useCallback, useEffect, useRef, useState, type ReactNode } from "react"; import { useQuery } from "@tanstack/react-query"; -import { Bell, Clock3, AlertCircle, ListChecks, Search, TriangleAlert } from "lucide-react"; +import { Bell, Clock3, AlertCircle, ListChecks, Search, TriangleAlert } from "@multica/ui/icons"; import { toast } from "sonner"; import { useWorkspaceId } from "@multica/core/hooks"; import { useWorkspacePaths } from "@multica/core/paths"; diff --git a/packages/views/billing/billing-return-page.tsx b/packages/views/billing/billing-return-page.tsx index 086140c7d..db8f183ec 100644 --- a/packages/views/billing/billing-return-page.tsx +++ b/packages/views/billing/billing-return-page.tsx @@ -2,7 +2,7 @@ import { useEffect } from "react"; import { useQuery } from "@tanstack/react-query"; -import { AlertCircle, Loader2, RefreshCw } from "lucide-react"; +import { AlertCircle, Loader2, RefreshCw } from "@multica/ui/icons"; import { useAuthStore } from "@multica/core/auth"; import { paths } from "@multica/core/paths"; import { workspaceListOptions } from "@multica/core/workspace/queries"; diff --git a/packages/views/billing/billing-test-page.tsx b/packages/views/billing/billing-test-page.tsx index 11c23e6e6..7a448de57 100644 --- a/packages/views/billing/billing-test-page.tsx +++ b/packages/views/billing/billing-test-page.tsx @@ -24,7 +24,7 @@ import { useEffect, useState } from "react"; import { useQuery } from "@tanstack/react-query"; -import { Loader2, RefreshCw, ExternalLink } from "lucide-react"; +import { Loader2, RefreshCw, ExternalLink } from "@multica/ui/icons"; import { toast } from "sonner"; import { billingBalanceOptions, diff --git a/packages/views/chat/chat-page.tsx b/packages/views/chat/chat-page.tsx index c5ba0a4d2..a2ca883ba 100644 --- a/packages/views/chat/chat-page.tsx +++ b/packages/views/chat/chat-page.tsx @@ -2,7 +2,7 @@ import { useEffect, useMemo, useRef, useState } from "react"; import { useDefaultLayout } from "react-resizable-panels"; -import { ArrowLeft, MessageSquare } from "lucide-react"; +import { ArrowLeft, MessageSquare } from "@multica/ui/icons"; import { toast } from "sonner"; import { Button } from "@multica/ui/components/ui/button"; import { diff --git a/packages/views/chat/components/agent-access-revoked-banner.tsx b/packages/views/chat/components/agent-access-revoked-banner.tsx index e430efc18..583753b0e 100644 --- a/packages/views/chat/components/agent-access-revoked-banner.tsx +++ b/packages/views/chat/components/agent-access-revoked-banner.tsx @@ -1,6 +1,6 @@ "use client"; -import { Lock } from "lucide-react"; +import { Lock } from "@multica/ui/icons"; import { cn } from "@multica/ui/lib/utils"; import { CHAT_COLUMN, CHAT_GUTTER } from "./chat-column"; import { useT } from "../../i18n"; diff --git a/packages/views/chat/components/archived-agent-banner.tsx b/packages/views/chat/components/archived-agent-banner.tsx index 980f13a73..d09fc7b3c 100644 --- a/packages/views/chat/components/archived-agent-banner.tsx +++ b/packages/views/chat/components/archived-agent-banner.tsx @@ -1,6 +1,6 @@ "use client"; -import { Archive } from "lucide-react"; +import { Archive } from "@multica/ui/icons"; import { cn } from "@multica/ui/lib/utils"; import { CHAT_COLUMN, CHAT_GUTTER } from "./chat-column"; import { useT } from "../../i18n"; diff --git a/packages/views/chat/components/chat-add-menu.tsx b/packages/views/chat/components/chat-add-menu.tsx index 4f02d420d..45b58071b 100644 --- a/packages/views/chat/components/chat-add-menu.tsx +++ b/packages/views/chat/components/chat-add-menu.tsx @@ -1,7 +1,7 @@ "use client"; import { useRef } from "react"; -import { Check, FolderKanban, Image as ImageIcon, Plus, X } from "lucide-react"; +import { Check, FolderKanban, Image as ImageIcon, Plus, X } from "@multica/ui/icons"; import { IconButton } from "@multica/ui/components/common/icon-button"; import { DropdownMenu, diff --git a/packages/views/chat/components/chat-empty-state.tsx b/packages/views/chat/components/chat-empty-state.tsx index 05f91a8fb..79d0dc002 100644 --- a/packages/views/chat/components/chat-empty-state.tsx +++ b/packages/views/chat/components/chat-empty-state.tsx @@ -1,6 +1,6 @@ "use client"; -import { Settings2 } from "lucide-react"; +import { Settings2 } from "@multica/ui/icons"; import { selectConversationStarters } from "@multica/core/agents"; import type { Agent } from "@multica/core/types"; import { ActorAvatar } from "../../common/actor-avatar"; diff --git a/packages/views/chat/components/chat-fab.tsx b/packages/views/chat/components/chat-fab.tsx index e2dfd0276..afe049766 100644 --- a/packages/views/chat/components/chat-fab.tsx +++ b/packages/views/chat/components/chat-fab.tsx @@ -1,6 +1,6 @@ "use client"; -import { MessageCircle } from "lucide-react"; +import { MessageCircle } from "@multica/ui/icons"; import { useQuery } from "@tanstack/react-query"; import { cn } from "@multica/ui/lib/utils"; import { useChatStore } from "@multica/core/chat"; diff --git a/packages/views/chat/components/chat-input.tsx b/packages/views/chat/components/chat-input.tsx index 25071f351..7d9ec2995 100644 --- a/packages/views/chat/components/chat-input.tsx +++ b/packages/views/chat/components/chat-input.tsx @@ -2,7 +2,7 @@ import type { ReactNode } from "react"; import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react"; -import { TriangleAlert } from "lucide-react"; +import { TriangleAlert } from "@multica/ui/icons"; import { toast } from "sonner"; import { cn } from "@multica/ui/lib/utils"; import { diff --git a/packages/views/chat/components/chat-message-list.tsx b/packages/views/chat/components/chat-message-list.tsx index f4904ee50..ecfa25934 100644 --- a/packages/views/chat/components/chat-message-list.tsx +++ b/packages/views/chat/components/chat-message-list.tsx @@ -26,7 +26,7 @@ import { ArrowUpRight, Copy, RotateCw, -} from "lucide-react"; +} from "@multica/ui/icons"; import { useScrollFade } from "@multica/ui/hooks/use-scroll-fade"; import { isTaskMessageTaskId, taskMessagesOptions } from "@multica/core/chat/queries"; import { RichContent } from "../../rich-content"; diff --git a/packages/views/chat/components/chat-queue.tsx b/packages/views/chat/components/chat-queue.tsx index 151ecbb53..0963957ba 100644 --- a/packages/views/chat/components/chat-queue.tsx +++ b/packages/views/chat/components/chat-queue.tsx @@ -8,7 +8,7 @@ import { Loader2, Pencil, Trash2, -} from "lucide-react"; +} from "@multica/ui/icons"; import type { ChatQueuedTask } from "@multica/core/types"; import { Button } from "@multica/ui/components/ui/button"; import { IconButton } from "@multica/ui/components/common/icon-button"; diff --git a/packages/views/chat/components/chat-session-header.tsx b/packages/views/chat/components/chat-session-header.tsx index 2a6f00adb..ed85b159c 100644 --- a/packages/views/chat/components/chat-session-header.tsx +++ b/packages/views/chat/components/chat-session-header.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useRef, useState } from "react"; -import { Archive, ArchiveRestore, MoreHorizontal, Pencil, Trash2, UserRound } from "lucide-react"; +import { Archive, ArchiveRestore, MoreHorizontal, Pencil, Trash2, UserRound } from "@multica/ui/icons"; import { IconButton } from "@multica/ui/components/common/icon-button"; import { DropdownMenu, diff --git a/packages/views/chat/components/chat-thread-list.tsx b/packages/views/chat/components/chat-thread-list.tsx index 1d5d760e0..202aeeb2b 100644 --- a/packages/views/chat/components/chat-thread-list.tsx +++ b/packages/views/chat/components/chat-thread-list.tsx @@ -13,7 +13,7 @@ import { PinOff, Square, Trash2, -} from "lucide-react"; +} from "@multica/ui/icons"; import { cn } from "@multica/ui/lib/utils"; import { useWorkspaceId } from "@multica/core/hooks"; import { paths, useWorkspaceSlug } from "@multica/core/paths"; diff --git a/packages/views/chat/components/chat-window.tsx b/packages/views/chat/components/chat-window.tsx index 1b81470d2..aa560ee21 100644 --- a/packages/views/chat/components/chat-window.tsx +++ b/packages/views/chat/components/chat-window.tsx @@ -3,7 +3,7 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { AnimatePresence, motion } from "motion/react"; -import { Minus, Maximize2, Minimize2, ChevronDown, Plus, Check, Archive, Pencil, Loader2, Square } from "lucide-react"; +import { Minus, Maximize2, Minimize2, ChevronDown, Plus, Check, Archive, Pencil, Loader2, Square } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { cn } from "@multica/ui/lib/utils"; import { Tooltip, TooltipTrigger, TooltipContent } from "@multica/ui/components/ui/tooltip"; diff --git a/packages/views/chat/components/new-chat-button.tsx b/packages/views/chat/components/new-chat-button.tsx index 11702c7b2..719b37b1c 100644 --- a/packages/views/chat/components/new-chat-button.tsx +++ b/packages/views/chat/components/new-chat-button.tsx @@ -1,7 +1,7 @@ "use client"; import React, { useMemo, useState } from "react"; -import { Plus } from "lucide-react"; +import { Plus } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { IconButton } from "@multica/ui/components/common/icon-button"; import { Tooltip, TooltipTrigger, TooltipContent } from "@multica/ui/components/ui/tooltip"; diff --git a/packages/views/chat/components/no-agent-banner.tsx b/packages/views/chat/components/no-agent-banner.tsx index 439b43a82..ac8d1d864 100644 --- a/packages/views/chat/components/no-agent-banner.tsx +++ b/packages/views/chat/components/no-agent-banner.tsx @@ -1,6 +1,6 @@ "use client"; -import { Bot } from "lucide-react"; +import { Bot } from "@multica/ui/icons"; import { cn } from "@multica/ui/lib/utils"; import { CHAT_COLUMN, CHAT_GUTTER } from "./chat-column"; import { useT } from "../../i18n"; diff --git a/packages/views/chat/components/offline-banner.tsx b/packages/views/chat/components/offline-banner.tsx index 8775cf824..a15167aed 100644 --- a/packages/views/chat/components/offline-banner.tsx +++ b/packages/views/chat/components/offline-banner.tsx @@ -1,6 +1,6 @@ "use client"; -import { AlertCircle, WifiOff } from "lucide-react"; +import { AlertCircle, WifiOff } from "@multica/ui/icons"; import { cn } from "@multica/ui/lib/utils"; import type { AgentAvailability } from "@multica/core/agents"; import { CHAT_COLUMN, CHAT_GUTTER } from "./chat-column"; diff --git a/packages/views/chat/components/onboarding-starter-cards.tsx b/packages/views/chat/components/onboarding-starter-cards.tsx index 39f088114..b37957b9d 100644 --- a/packages/views/chat/components/onboarding-starter-cards.tsx +++ b/packages/views/chat/components/onboarding-starter-cards.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { ArrowUpRight, Check, Clock, LoaderCircle } from "lucide-react"; +import { ArrowUpRight, Check, Clock, LoaderCircle } from "@multica/ui/icons"; import { cn } from "@multica/ui/lib/utils"; import { Tooltip, diff --git a/packages/views/chat/components/quick-agent-bar.tsx b/packages/views/chat/components/quick-agent-bar.tsx index 8005a6b00..fadbf9b12 100644 --- a/packages/views/chat/components/quick-agent-bar.tsx +++ b/packages/views/chat/components/quick-agent-bar.tsx @@ -2,7 +2,7 @@ import { useMemo } from "react"; import { useQuery } from "@tanstack/react-query"; -import { Plus } from "lucide-react"; +import { Plus } from "@multica/ui/icons"; import { useWorkspaceId } from "@multica/core/hooks"; import { chatPinnedAgentsOptions } from "@multica/core/chat/queries"; import { usePinChatAgent, useUnpinChatAgent } from "@multica/core/chat/mutations"; diff --git a/packages/views/chat/components/runtime-required-banner.tsx b/packages/views/chat/components/runtime-required-banner.tsx index ba0ced962..292e4e098 100644 --- a/packages/views/chat/components/runtime-required-banner.tsx +++ b/packages/views/chat/components/runtime-required-banner.tsx @@ -1,6 +1,6 @@ "use client"; -import { Server } from "lucide-react"; +import { Server } from "@multica/ui/icons"; import { useWorkspacePaths } from "@multica/core/paths"; import { Button } from "@multica/ui/components/ui/button"; import { cn } from "@multica/ui/lib/utils"; diff --git a/packages/views/common/actor-issues-panel.tsx b/packages/views/common/actor-issues-panel.tsx index 51335c247..69de25f83 100644 --- a/packages/views/common/actor-issues-panel.tsx +++ b/packages/views/common/actor-issues-panel.tsx @@ -2,7 +2,7 @@ import { useMemo, useState } from "react"; import { useStore } from "zustand"; -import { ListTodo, Search } from "lucide-react"; +import { ListTodo, Search } from "@multica/ui/icons"; import type { Issue, IssueTableFacetSpec, diff --git a/packages/views/common/avatar-crop-dialog.tsx b/packages/views/common/avatar-crop-dialog.tsx index 7298fe1ec..091ab3128 100644 --- a/packages/views/common/avatar-crop-dialog.tsx +++ b/packages/views/common/avatar-crop-dialog.tsx @@ -2,7 +2,7 @@ import { useEffect, useState } from "react"; import Cropper, { type Area, type Point } from "react-easy-crop"; -import { Loader2, Minus, Plus, RotateCw } from "lucide-react"; +import { Loader2, Minus, Plus, RotateCw } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { Slider } from "@multica/ui/components/ui/slider"; import { TooltipHint } from "@multica/ui/components/common/tooltip-hint"; diff --git a/packages/views/common/avatar-upload-control.tsx b/packages/views/common/avatar-upload-control.tsx index 80fef6511..e08c53cb8 100644 --- a/packages/views/common/avatar-upload-control.tsx +++ b/packages/views/common/avatar-upload-control.tsx @@ -1,7 +1,7 @@ "use client"; import { Suspense, lazy, useRef, useState } from "react"; -import { Bot, Camera, ImagePlus, Loader2, Users, X } from "lucide-react"; +import { Bot, Camera, ImagePlus, Loader2, Users, X } from "@multica/ui/icons"; import { toast } from "sonner"; import { api } from "@multica/core/api"; import { useFileUpload } from "@multica/core/hooks/use-file-upload"; diff --git a/packages/views/common/color-picker.tsx b/packages/views/common/color-picker.tsx index e3ed8d93d..5b0ecb8f0 100644 --- a/packages/views/common/color-picker.tsx +++ b/packages/views/common/color-picker.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useState } from "react"; -import { Dices, Pipette } from "lucide-react"; +import { Dices, Pipette } from "@multica/ui/icons"; import { Popover, PopoverContent, diff --git a/packages/views/common/date-only-picker.tsx b/packages/views/common/date-only-picker.tsx index 7d36f1cd6..13cc84929 100644 --- a/packages/views/common/date-only-picker.tsx +++ b/packages/views/common/date-only-picker.tsx @@ -7,7 +7,7 @@ import { formatDateOnly, isPastDateOnly, } from "@multica/core/issues/date"; -import { Check } from "lucide-react"; +import { Check } from "@multica/ui/icons"; import { Calendar } from "@multica/ui/components/ui/calendar"; import { Popover, diff --git a/packages/views/common/hover-check.tsx b/packages/views/common/hover-check.tsx index 69db68cbd..6a897ad21 100644 --- a/packages/views/common/hover-check.tsx +++ b/packages/views/common/hover-check.tsx @@ -1,6 +1,6 @@ "use client"; -import { Check } from "lucide-react"; +import { Check } from "@multica/ui/icons"; // shadcn official pattern (PR #6862): a checkbox indicator that appears on // item hover/focus inside DropdownMenuCheckboxItem rows. Pair it with diff --git a/packages/views/common/mcp-server-row.test.tsx b/packages/views/common/mcp-server-row.test.tsx index 732e68853..bba63e059 100644 --- a/packages/views/common/mcp-server-row.test.tsx +++ b/packages/views/common/mcp-server-row.test.tsx @@ -86,7 +86,7 @@ describe("McpServerRow", () => { .getByRole("button", { name: "Replace configuration linear" }) .querySelector("svg"); - expect(icon).toHaveClass("lucide-sliders-horizontal"); + expect(icon).toHaveClass("icon-sliders-horizontal"); expect(icon?.getAttribute("class")).not.toMatch(/refresh|rotate/i); }); diff --git a/packages/views/common/mcp-server-row.tsx b/packages/views/common/mcp-server-row.tsx index 592c2b4d1..ea4ce4f2c 100644 --- a/packages/views/common/mcp-server-row.tsx +++ b/packages/views/common/mcp-server-row.tsx @@ -11,7 +11,7 @@ import { SquareTerminal, Trash2, X, -} from "lucide-react"; +} from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { IconButton } from "@multica/ui/components/common/icon-button"; import { Input } from "@multica/ui/components/ui/input"; diff --git a/packages/views/common/pill-button.tsx b/packages/views/common/pill-button.tsx index cac6b41b5..51a6d3bf0 100644 --- a/packages/views/common/pill-button.tsx +++ b/packages/views/common/pill-button.tsx @@ -1,6 +1,6 @@ "use client"; -import { X as XIcon } from "lucide-react"; +import { X as XIcon } from "@multica/ui/icons"; import { TooltipHint } from "@multica/ui/components/common/tooltip-hint"; import { cn } from "@multica/ui/lib/utils"; diff --git a/packages/views/common/prop-row.tsx b/packages/views/common/prop-row.tsx index 3bbd123ba..5e2c94c63 100644 --- a/packages/views/common/prop-row.tsx +++ b/packages/views/common/prop-row.tsx @@ -43,10 +43,10 @@ export function PropRow({ interactive ? "transition-colors hover:bg-accent/50" : "" }`} > - + {label} -
+
{children}
diff --git a/packages/views/common/property-icon.tsx b/packages/views/common/property-icon.tsx index 0cddc7b57..9c2942e4f 100644 --- a/packages/views/common/property-icon.tsx +++ b/packages/views/common/property-icon.tsx @@ -42,18 +42,18 @@ import { Wrench, X, Zap, - type LucideIcon, -} from "lucide-react"; + type IconComponent, +} from "@multica/ui/icons"; import { DeferredTooltip } from "./deferred-tooltip"; interface PropertyIconOption { value: string; label: string; - Icon: LucideIcon; + Icon: IconComponent; } /** - * A deliberately small Lucide catalog that starts with the same symbols used + * A deliberately small icon catalog that starts with the same symbols used * by built-in issue properties. Persist stable keys rather than SVG data or * component names so the visual implementation can evolve independently. */ diff --git a/packages/views/common/row-actions-menu.tsx b/packages/views/common/row-actions-menu.tsx index 4a4c8d2d8..09983224d 100644 --- a/packages/views/common/row-actions-menu.tsx +++ b/packages/views/common/row-actions-menu.tsx @@ -1,7 +1,7 @@ "use client"; import { Fragment, type KeyboardEvent, type ReactNode } from "react"; -import { MoreHorizontal } from "lucide-react"; +import { MoreHorizontal } from "@multica/ui/icons"; import { DropdownMenu, DropdownMenuContent, diff --git a/packages/views/common/shortcut-keycaps.test.tsx b/packages/views/common/shortcut-keycaps.test.tsx index 9682876ae..5276bb2bf 100644 --- a/packages/views/common/shortcut-keycaps.test.tsx +++ b/packages/views/common/shortcut-keycaps.test.tsx @@ -4,7 +4,7 @@ import { createShortcutChord } from "@multica/core/shortcuts"; import { ShortcutKeycaps } from "./shortcut-keycaps"; describe("ShortcutKeycaps", () => { - it("uses Lucide icons for macOS Command and Enter", () => { + it("uses icons for macOS Command and Enter", () => { const { container } = render( { ); expect(screen.getByRole("img", { name: "⌘↵" })).toBeInTheDocument(); - expect(container.querySelector(".lucide-command")).toBeInTheDocument(); - expect(container.querySelector(".lucide-corner-down-left")).toBeInTheDocument(); + expect(container.querySelector(".icon-command")).toBeInTheDocument(); + expect(container.querySelector(".icon-corner-down-left")).toBeInTheDocument(); expect(container.querySelector("[title='Enter']")?.textContent).toBe(""); }); @@ -28,8 +28,8 @@ describe("ShortcutKeycaps", () => { expect(screen.getByRole("img", { name: "Ctrl+Enter" })).toBeInTheDocument(); expect(container.querySelector("[title='Ctrl']")).toHaveTextContent("Ctrl"); - expect(container.querySelector(".lucide-corner-down-left")).toBeInTheDocument(); - expect(container.querySelector(".lucide-command")).not.toBeInTheDocument(); + expect(container.querySelector(".icon-corner-down-left")).toBeInTheDocument(); + expect(container.querySelector(".icon-command")).not.toBeInTheDocument(); }); it("uses the canonical macOS Control glyph instead of an unrelated icon", () => { @@ -42,10 +42,10 @@ describe("ShortcutKeycaps", () => { expect(screen.getByRole("img", { name: "⌃F" })).toBeInTheDocument(); expect(container.querySelector("[title='Control']")).toHaveTextContent("⌃"); - expect(container.querySelector(".lucide-command")).not.toBeInTheDocument(); + expect(container.querySelector(".icon-command")).not.toBeInTheDocument(); }); - it("falls back to compact text when Lucide has no exact semantic icon", () => { + it("falls back to compact text when there is no exact semantic icon", () => { const { container } = render( , ); diff --git a/packages/views/common/shortcut-keycaps.tsx b/packages/views/common/shortcut-keycaps.tsx index 02856a53d..942221579 100644 --- a/packages/views/common/shortcut-keycaps.tsx +++ b/packages/views/common/shortcut-keycaps.tsx @@ -12,8 +12,8 @@ import { Delete, Option, Space, - type LucideIcon, -} from "lucide-react"; + type IconComponent, +} from "@multica/ui/icons"; import { formatShortcut, getShortcutPlatform, @@ -29,7 +29,7 @@ type ShortcutToken = { id: string; label: string; text?: string; - icon?: LucideIcon; + icon?: IconComponent; }; const KEY_TOKENS: Record> = { diff --git a/packages/views/common/task-transcript/agent-transcript-dialog.test.tsx b/packages/views/common/task-transcript/agent-transcript-dialog.test.tsx index 22d39e181..e6769449e 100644 --- a/packages/views/common/task-transcript/agent-transcript-dialog.test.tsx +++ b/packages/views/common/task-transcript/agent-transcript-dialog.test.tsx @@ -250,9 +250,9 @@ afterEach(() => { describe("AgentTranscriptDialog", () => { it.each([ - { type: "text", label: "Agent", icon: ".lucide-bot" }, - { type: "thinking", label: "Thinking", icon: ".lucide-brain" }, - { type: "error", label: "Error", icon: ".lucide-circle-alert" }, + { type: "text", label: "Agent", icon: ".icon-bot" }, + { type: "thinking", label: "Thinking", icon: ".icon-brain" }, + { type: "error", label: "Error", icon: ".icon-circle-alert" }, ] as const)("labels a $type step correctly when opened from the timeline", ({ type, label, icon }) => { renderDialog([ { seq: 1, type, content: "Final delivered reply", created_at: baseTask.started_at! }, @@ -438,10 +438,10 @@ describe("AgentTranscriptDialog", () => { ]); const agentFacet = screen.getByRole("menuitemcheckbox", { name: "Agent" }); - expect(agentFacet.querySelector(".lucide-bot")).not.toBeNull(); + expect(agentFacet.querySelector(".icon-bot")).not.toBeNull(); const proseRow = screen.getByTestId("rich-content").closest(".group"); - expect(proseRow?.querySelector(".lucide-bot")).not.toBeNull(); + expect(proseRow?.querySelector(".icon-bot")).not.toBeNull(); }); it("names a tool facet the way its rows do, keeping the prefix in the key", () => { diff --git a/packages/views/common/task-transcript/agent-transcript-dialog.tsx b/packages/views/common/task-transcript/agent-transcript-dialog.tsx index 5cb98b2ef..4edbbe1ee 100644 --- a/packages/views/common/task-transcript/agent-transcript-dialog.tsx +++ b/packages/views/common/task-transcript/agent-transcript-dialog.tsx @@ -27,7 +27,7 @@ import { Info, Coins, GitBranch, -} from "lucide-react"; +} from "@multica/ui/icons"; import { cn } from "@multica/ui/lib/utils"; import { copyText } from "@multica/ui/lib/clipboard"; import { Button } from "@multica/ui/components/ui/button"; diff --git a/packages/views/common/task-transcript/run-timeline.tsx b/packages/views/common/task-transcript/run-timeline.tsx index dca9aa77f..b9ecdcdf7 100644 --- a/packages/views/common/task-transcript/run-timeline.tsx +++ b/packages/views/common/task-transcript/run-timeline.tsx @@ -1,7 +1,7 @@ "use client"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; -import { Minus, Plus } from "lucide-react"; +import { Minus, Plus } from "@multica/ui/icons"; import { TooltipHint } from "@multica/ui/components/common/tooltip-hint"; import { cn } from "@multica/ui/lib/utils"; import { diff --git a/packages/views/common/task-transcript/transcript-button.tsx b/packages/views/common/task-transcript/transcript-button.tsx index 55985364b..d7f64f597 100644 --- a/packages/views/common/task-transcript/transcript-button.tsx +++ b/packages/views/common/task-transcript/transcript-button.tsx @@ -1,7 +1,7 @@ "use client"; import { useCallback, useEffect, useMemo, useState } from "react"; -import { Loader2, ScrollText } from "lucide-react"; +import { Loader2, ScrollText } from "@multica/ui/icons"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { cn } from "@multica/ui/lib/utils"; import { diff --git a/packages/views/dashboard/components/dashboard-filters.tsx b/packages/views/dashboard/components/dashboard-filters.tsx index 9c88449b0..3ac62ca94 100644 --- a/packages/views/dashboard/components/dashboard-filters.tsx +++ b/packages/views/dashboard/components/dashboard-filters.tsx @@ -1,6 +1,6 @@ "use client"; -import { CalendarDays, ChevronDown, FolderKanban } from "lucide-react"; +import { CalendarDays, ChevronDown, FolderKanban } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { DropdownMenu, diff --git a/packages/views/dashboard/components/dashboard-page.tsx b/packages/views/dashboard/components/dashboard-page.tsx index bf88894c6..df6f4558c 100644 --- a/packages/views/dashboard/components/dashboard-page.tsx +++ b/packages/views/dashboard/components/dashboard-page.tsx @@ -1,7 +1,7 @@ "use client"; import { useMemo, useState } from "react"; -import { BarChart3, RefreshCw } from "lucide-react"; +import { BarChart3, RefreshCw } from "@multica/ui/icons"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { IconButton } from "@multica/ui/components/common/icon-button"; import { Skeleton } from "@multica/ui/components/ui/skeleton"; diff --git a/packages/views/dashboard/components/errors-tab.tsx b/packages/views/dashboard/components/errors-tab.tsx index 6f267e134..4aac699a0 100644 --- a/packages/views/dashboard/components/errors-tab.tsx +++ b/packages/views/dashboard/components/errors-tab.tsx @@ -1,7 +1,7 @@ "use client"; import { useMemo, useState } from "react"; -import { BarChart3 } from "lucide-react"; +import { BarChart3 } from "@multica/ui/icons"; import { NumberFlow } from "@multica/ui/components/ui/number-flow"; import { FAILURE_CLASSES, type FailureClass } from "@multica/core/dashboard"; import { useWorkspacePaths } from "@multica/core/paths"; diff --git a/packages/views/dashboard/components/leaderboard.tsx b/packages/views/dashboard/components/leaderboard.tsx index b945ffe24..c6fbf6371 100644 --- a/packages/views/dashboard/components/leaderboard.tsx +++ b/packages/views/dashboard/components/leaderboard.tsx @@ -1,7 +1,7 @@ "use client"; import { useMemo, useState, type CSSProperties } from "react"; -import { EyeOff, Trash2 } from "lucide-react"; +import { EyeOff, Trash2 } from "@multica/ui/icons"; import { ActorAvatar } from "../../common/actor-avatar"; import { formatTokens } from "../../runtimes/utils"; import { useT } from "../../i18n"; diff --git a/packages/views/dashboard/components/usage-trend-card.tsx b/packages/views/dashboard/components/usage-trend-card.tsx index 974bcf90a..a846c1923 100644 --- a/packages/views/dashboard/components/usage-trend-card.tsx +++ b/packages/views/dashboard/components/usage-trend-card.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { BarChart3 } from "lucide-react"; +import { BarChart3 } from "@multica/ui/icons"; import { DailyCostChart, DailyTokensChart, diff --git a/packages/views/editor/attachment-card.tsx b/packages/views/editor/attachment-card.tsx index 8b75615e0..4339efb48 100644 --- a/packages/views/editor/attachment-card.tsx +++ b/packages/views/editor/attachment-card.tsx @@ -12,7 +12,7 @@ */ import type { ReactNode } from "react"; -import { Download, Eye, FileText, Loader2, Trash2 } from "lucide-react"; +import { Download, Eye, FileText, Loader2, Trash2 } from "@multica/ui/icons"; import { useT } from "../i18n"; import { DeferredTooltip } from "../common/deferred-tooltip"; import { formatBytes } from "../common/format-bytes"; diff --git a/packages/views/editor/attachment-preview-modal.tsx b/packages/views/editor/attachment-preview-modal.tsx index 7b7792ffd..0ac3dee65 100644 --- a/packages/views/editor/attachment-preview-modal.tsx +++ b/packages/views/editor/attachment-preview-modal.tsx @@ -52,8 +52,8 @@ import { Tablet, WrapText, X, - type LucideIcon, -} from "lucide-react"; + type IconComponent, +} from "@multica/ui/icons"; import type { Attachment } from "@multica/core/types"; import { paths, useWorkspaceSlug } from "@multica/core/paths"; import { createShortcutChord } from "@multica/core/shortcuts"; @@ -597,7 +597,7 @@ export function AttachmentPreviewModal({ // Panel — top bar + stage -const KIND_ICONS: Record = { +const KIND_ICONS: Record = { image: ImageIcon, pdf: FileText, video: FileVideo, @@ -611,7 +611,7 @@ const KIND_ICONS: Record = { type StructuredView = "tree" | "raw"; -const VIEWPORT_ICONS: Record = { +const VIEWPORT_ICONS: Record = { fill: Maximize2, desktop: Monitor, tablet: Tablet, @@ -1141,7 +1141,7 @@ function ChromeSegmented({ }: { label: string; value: T; - options: ReadonlyArray<{ value: T; label: string; icon: LucideIcon }>; + options: ReadonlyArray<{ value: T; label: string; icon: IconComponent }>; disabled?: boolean; onChange: (value: T) => void; }) { diff --git a/packages/views/editor/attachment.tsx b/packages/views/editor/attachment.tsx index 127efe0e4..f1b53c860 100644 --- a/packages/views/editor/attachment.tsx +++ b/packages/views/editor/attachment.tsx @@ -32,7 +32,7 @@ import { Link as LinkIcon, Maximize2, Trash2, -} from "lucide-react"; +} from "@multica/ui/icons"; import type { ReactNode } from "react"; import { toast } from "sonner"; import { cn } from "@multica/ui/lib/utils"; diff --git a/packages/views/editor/bubble-menu.tsx b/packages/views/editor/bubble-menu.tsx index 32a635ee0..fc61d8909 100644 --- a/packages/views/editor/bubble-menu.tsx +++ b/packages/views/editor/bubble-menu.tsx @@ -74,7 +74,7 @@ import { FilePlus, Loader2, MessageSquarePlus, -} from "lucide-react"; +} from "@multica/ui/icons"; // Helpers diff --git a/packages/views/editor/dynamic-block.tsx b/packages/views/editor/dynamic-block.tsx index 57599c983..602504d60 100644 --- a/packages/views/editor/dynamic-block.tsx +++ b/packages/views/editor/dynamic-block.tsx @@ -35,7 +35,7 @@ import { RotateCw, TriangleAlert, Workflow, -} from "lucide-react"; +} from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { IconButton } from "@multica/ui/components/common/icon-button"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@multica/ui/components/ui/tabs"; diff --git a/packages/views/editor/extensions/code-block-view.tsx b/packages/views/editor/extensions/code-block-view.tsx index 48ae29c40..0c76f58bd 100644 --- a/packages/views/editor/extensions/code-block-view.tsx +++ b/packages/views/editor/extensions/code-block-view.tsx @@ -3,7 +3,7 @@ import { useState } from "react"; import { NodeViewWrapper, NodeViewContent } from "@tiptap/react"; import type { NodeViewProps } from "@tiptap/react"; -import { Code as CodeIcon, Copy, Check, Eye, Maximize2, RotateCw } from "lucide-react"; +import { Code as CodeIcon, Copy, Check, Eye, Maximize2, RotateCw } from "@multica/ui/icons"; import { IconButton } from "@multica/ui/components/common/icon-button"; import { TooltipHint } from "@multica/ui/components/common/tooltip-hint"; import { HtmlPreviewSurface } from "../html-preview-surface"; diff --git a/packages/views/editor/extensions/mention-suggestion.tsx b/packages/views/editor/extensions/mention-suggestion.tsx index d62f2da53..54cbfeb0e 100644 --- a/packages/views/editor/extensions/mention-suggestion.tsx +++ b/packages/views/editor/extensions/mention-suggestion.tsx @@ -33,7 +33,7 @@ import type { Agent, Squad, } from "@multica/core/types"; -import { ListTodo } from "lucide-react"; +import { ListTodo } from "@multica/ui/icons"; import { ActorAvatar } from "../../common/actor-avatar"; import { StatusIcon } from "../../issues/components/status-icon"; import { ProjectIcon } from "../../projects/components/project-icon"; diff --git a/packages/views/editor/html-preview-surface.tsx b/packages/views/editor/html-preview-surface.tsx index 7fd357b50..d4ed678fb 100644 --- a/packages/views/editor/html-preview-surface.tsx +++ b/packages/views/editor/html-preview-surface.tsx @@ -8,7 +8,7 @@ import { type MouseEvent, type ReactNode, } from "react"; -import { RotateCw, X } from "lucide-react"; +import { RotateCw, X } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { useT } from "../i18n"; diff --git a/packages/views/editor/link-hover-card.tsx b/packages/views/editor/link-hover-card.tsx index 132434cd1..6583bde1b 100644 --- a/packages/views/editor/link-hover-card.tsx +++ b/packages/views/editor/link-hover-card.tsx @@ -12,7 +12,7 @@ import { useState, useEffect, useCallback, useRef } from "react"; import { createPortal } from "react-dom"; import { computePosition, offset, flip, shift } from "@floating-ui/dom"; -import { ExternalLink, Copy } from "lucide-react"; +import { ExternalLink, Copy } from "@multica/ui/icons"; import { toast } from "sonner"; import { IconButton } from "@multica/ui/components/common/icon-button"; import { copyText } from "@multica/ui/lib/clipboard"; diff --git a/packages/views/editor/mermaid-diagram.tsx b/packages/views/editor/mermaid-diagram.tsx index 5b5903499..2a42a8506 100644 --- a/packages/views/editor/mermaid-diagram.tsx +++ b/packages/views/editor/mermaid-diagram.tsx @@ -39,7 +39,7 @@ import { type CSSProperties, type RefObject, } from "react"; -import { Check, Copy, Frame, Maximize2, Minus, Plus } from "lucide-react"; +import { Check, Copy, Frame, Maximize2, Minus, Plus } from "@multica/ui/icons"; import { copyText } from "@multica/ui/lib/clipboard"; import { TooltipHint } from "@multica/ui/components/common/tooltip-hint"; import { useT } from "../i18n"; diff --git a/packages/views/editor/mermaid-viewer.tsx b/packages/views/editor/mermaid-viewer.tsx index 7fb526cda..94d359f68 100644 --- a/packages/views/editor/mermaid-viewer.tsx +++ b/packages/views/editor/mermaid-viewer.tsx @@ -23,7 +23,7 @@ import { Download, Image as ImageIcon, X, -} from "lucide-react"; +} from "@multica/ui/icons"; import { cn } from "@multica/ui/lib/utils"; import { copyText } from "@multica/ui/lib/clipboard"; import { Dialog, DialogContent, DialogTitle } from "@multica/ui/components/ui/dialog"; diff --git a/packages/views/editor/structured-tree.tsx b/packages/views/editor/structured-tree.tsx index fa5db55b0..aaa9bdf9e 100644 --- a/packages/views/editor/structured-tree.tsx +++ b/packages/views/editor/structured-tree.tsx @@ -15,7 +15,7 @@ */ import { useState, type ReactNode } from "react"; -import { ChevronRight } from "lucide-react"; +import { ChevronRight } from "@multica/ui/icons"; import { cn } from "@multica/ui/lib/utils"; import { useT } from "../i18n"; import "./styles/code.css"; diff --git a/packages/views/editor/styles/prose.css b/packages/views/editor/styles/prose.css index 7ccfc5791..5ebb690b1 100644 --- a/packages/views/editor/styles/prose.css +++ b/packages/views/editor/styles/prose.css @@ -49,13 +49,15 @@ } /* Headings — compact but with clear visual hierarchy */ +/* No negative tracking: Inter's optical-size axis already draws 24px in its + display cut, which is tighter than the text cut. Weight stops at 600 so h1 + sits on the same weight as the issue title above it. */ .rich-text-editor h1 { font-size: var(--text-display-sm); - font-weight: 700; + font-weight: 600; margin-top: 1.5rem; margin-bottom: 0.5rem; line-height: 1.3; - letter-spacing: -0.01em; } .rich-text-editor h2 { @@ -144,6 +146,15 @@ margin-top: 0.25rem; } +/* Han, kana and Hangul fill the whole em square and carry no ascender or + descender gaps, so the 1.625 that reads airy for Latin reads cramped for CJK. + Keyed to the UI locale (), the best signal available for the + language people write their issues and comments in. Table cells are listed + so editable cells (text in a

) and readonly cells (bare text) stay equal. */ +.rich-text-editor :is(p, li, th, td):is(:lang(zh), :lang(ja), :lang(ko)) { + line-height: 1.75; +} + .rich-text-editor li::marker { color: var(--muted-foreground); } diff --git a/packages/views/editor/table-preview.tsx b/packages/views/editor/table-preview.tsx index 0f7fb10a5..f198675a2 100644 --- a/packages/views/editor/table-preview.tsx +++ b/packages/views/editor/table-preview.tsx @@ -23,7 +23,7 @@ import { type Row, type SortingState, } from "@tanstack/react-table"; -import { ArrowDown, ArrowUp, ArrowUpDown } from "lucide-react"; +import { ArrowDown, ArrowUp, ArrowUpDown } from "@multica/ui/icons"; import { DataTable } from "@multica/ui/components/ui/data-table"; import { cn } from "@multica/ui/lib/utils"; import { TruncatedTooltip } from "@multica/ui/components/common/truncated-tooltip"; diff --git a/packages/views/editor/utils/file-icon.ts b/packages/views/editor/utils/file-icon.ts index f7d35db3b..f75952e4d 100644 --- a/packages/views/editor/utils/file-icon.ts +++ b/packages/views/editor/utils/file-icon.ts @@ -12,8 +12,8 @@ import { FileText, FileVideo, ImageIcon, - type LucideIcon, -} from "lucide-react"; + type IconComponent, +} from "@multica/ui/icons"; import { getPreviewKind } from "./preview"; function extensionOf(filename: string): string { @@ -40,7 +40,7 @@ export function isDocumentFile(contentType: string, filename: string): boolean { return DOCUMENT_EXTENSIONS.has(extensionOf(filename)); } -export function fileIcon(contentType: string, filename: string): LucideIcon { +export function fileIcon(contentType: string, filename: string): IconComponent { const ext = extensionOf(filename); if (SPREADSHEET_EXTENSIONS.has(ext)) return FileSpreadsheet; if (ARCHIVE_EXTENSIONS.has(ext)) return FileArchive; diff --git a/packages/views/editor/zoom-canvas.tsx b/packages/views/editor/zoom-canvas.tsx index 268d6f00b..2e1c9e34f 100644 --- a/packages/views/editor/zoom-canvas.tsx +++ b/packages/views/editor/zoom-canvas.tsx @@ -13,7 +13,7 @@ */ import { useCallback, type ReactNode, type RefObject } from "react"; -import { Frame, Maximize, Minus, Plus } from "lucide-react"; +import { Frame, Maximize, Minus, Plus } from "@multica/ui/icons"; import { cn } from "@multica/ui/lib/utils"; import { Tooltip, diff --git a/packages/views/inbox/components/inbox-filter-menu.tsx b/packages/views/inbox/components/inbox-filter-menu.tsx index a1938c2bc..a51f3dab6 100644 --- a/packages/views/inbox/components/inbox-filter-menu.tsx +++ b/packages/views/inbox/components/inbox-filter-menu.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useMemo, useState } from "react"; -import { BotOff, CircleDot, Filter, Mail, RotateCcw, SignalHigh, UserRound } from "lucide-react"; +import { BotOff, CircleDot, Filter, Mail, RotateCcw, SignalHigh, UserRound } from "@multica/ui/icons"; import { PRIORITY_DISPLAY_ORDER } from "@multica/core/issues/config"; import { filterInboxItems, diff --git a/packages/views/inbox/components/inbox-item-actions.tsx b/packages/views/inbox/components/inbox-item-actions.tsx index 83de4a74e..f7bcf6f58 100644 --- a/packages/views/inbox/components/inbox-item-actions.tsx +++ b/packages/views/inbox/components/inbox-item-actions.tsx @@ -1,6 +1,6 @@ "use client"; -import { Archive, ArchiveRestore, Check, CircleDot, ExternalLink } from "lucide-react"; +import { Archive, ArchiveRestore, Check, CircleDot, ExternalLink } from "@multica/ui/icons"; import { paths, useWorkspaceSlug } from "@multica/core/paths"; import type { InboxItem } from "@multica/core/types"; import type { RowActionItem } from "../../common/row-actions-menu"; diff --git a/packages/views/inbox/components/inbox-list-item.tsx b/packages/views/inbox/components/inbox-list-item.tsx index 4bbc882ab..07344c6fe 100644 --- a/packages/views/inbox/components/inbox-list-item.tsx +++ b/packages/views/inbox/components/inbox-list-item.tsx @@ -7,7 +7,7 @@ import { } from "../../issues/components/issue-agent-activity-indicator"; import { ActorAvatar } from "../../common/actor-avatar"; import { DeferredTooltip } from "../../common/deferred-tooltip"; -import { Archive, ArchiveRestore } from "lucide-react"; +import { Archive, ArchiveRestore } from "@multica/ui/icons"; import type { InboxItem } from "@multica/core/types"; import type { InboxView } from "./inbox-view"; import { InboxDetailLabel, useTypeLabels } from "./inbox-detail-label"; diff --git a/packages/views/inbox/components/inbox-list.tsx b/packages/views/inbox/components/inbox-list.tsx index 252186777..18d93ee88 100644 --- a/packages/views/inbox/components/inbox-list.tsx +++ b/packages/views/inbox/components/inbox-list.tsx @@ -10,7 +10,7 @@ import { type ReactNode, } from "react"; import { Virtuoso, type VirtuosoHandle } from "react-virtuoso"; -import { Archive, ChevronRight, Inbox } from "lucide-react"; +import { Archive, ChevronRight, Inbox } from "@multica/ui/icons"; import { isEditableShortcutTarget } from "@multica/core/shortcuts"; import { isImeComposing } from "@multica/core/utils"; import type { InboxItem } from "@multica/core/types"; diff --git a/packages/views/inbox/components/inbox-page.tsx b/packages/views/inbox/components/inbox-page.tsx index 4692b2240..1fd27c52b 100644 --- a/packages/views/inbox/components/inbox-page.tsx +++ b/packages/views/inbox/components/inbox-page.tsx @@ -70,7 +70,7 @@ import { ChevronLeft, ListChecks, ArrowLeft, -} from "lucide-react"; +} from "@multica/ui/icons"; import type { InboxItem } from "@multica/core/types"; import { Button } from "@multica/ui/components/ui/button"; import { IconButton } from "@multica/ui/components/common/icon-button"; diff --git a/packages/views/invitations/invitations-page.tsx b/packages/views/invitations/invitations-page.tsx index 84bf88950..20f4efa19 100644 --- a/packages/views/invitations/invitations-page.tsx +++ b/packages/views/invitations/invitations-page.tsx @@ -19,7 +19,7 @@ import { Button } from "@multica/ui/components/ui/button"; import { Card, CardContent } from "@multica/ui/components/ui/card"; import { Checkbox } from "@multica/ui/components/ui/checkbox"; import { Skeleton } from "@multica/ui/components/ui/skeleton"; -import { LogOut, Mail, Users } from "lucide-react"; +import { LogOut, Mail, Users } from "@multica/ui/icons"; /** * Batch invitation handling page for first-contact users who land here diff --git a/packages/views/invite/invite-page.tsx b/packages/views/invite/invite-page.tsx index a63fe4872..d41024a2c 100644 --- a/packages/views/invite/invite-page.tsx +++ b/packages/views/invite/invite-page.tsx @@ -20,7 +20,7 @@ import { useT } from "../i18n"; import { Button } from "@multica/ui/components/ui/button"; import { Card, CardContent } from "@multica/ui/components/ui/card"; import { Skeleton } from "@multica/ui/components/ui/skeleton"; -import { ArrowLeft, LogOut, Users, Check, X } from "lucide-react"; +import { ArrowLeft, LogOut, Users, Check, X } from "@multica/ui/icons"; export interface InvitePageProps { invitationId: string; diff --git a/packages/views/issues/actions/issue-actions-menu-items.tsx b/packages/views/issues/actions/issue-actions-menu-items.tsx index 6bacabbf8..b8d56f8df 100644 --- a/packages/views/issues/actions/issue-actions-menu-items.tsx +++ b/packages/views/issues/actions/issue-actions-menu-items.tsx @@ -20,7 +20,7 @@ import { Trash2, Unlink, UserMinus, -} from "lucide-react"; +} from "@multica/ui/icons"; import type { Issue } from "@multica/core/types"; import { resolveWorkdirCopyTarget } from "@multica/core/issues"; import { todayDateOnly, addDaysDateOnly } from "@multica/core/issues/date"; diff --git a/packages/views/issues/components/batch-action-toolbar.tsx b/packages/views/issues/components/batch-action-toolbar.tsx index b7daca353..7b3208780 100644 --- a/packages/views/issues/components/batch-action-toolbar.tsx +++ b/packages/views/issues/components/batch-action-toolbar.tsx @@ -2,7 +2,7 @@ import { useEffect, useMemo, useState } from "react"; import { AnimatePresence, motion, useReducedMotion } from "motion/react"; -import { X, Trash2 } from "lucide-react"; +import { X, Trash2 } from "@multica/ui/icons"; import { toast } from "sonner"; import { Button } from "@multica/ui/components/ui/button"; import { diff --git a/packages/views/issues/components/board-card.tsx b/packages/views/issues/components/board-card.tsx index a5b5ad3db..af6e2a2d8 100644 --- a/packages/views/issues/components/board-card.tsx +++ b/packages/views/issues/components/board-card.tsx @@ -12,7 +12,7 @@ import { propertyListOptions } from "@multica/core/properties"; import { CustomPropertyValueDisplay } from "./pickers/custom-property-picker"; import { descriptionPreview } from "./description-preview"; import { formatDateOnly, isPastDateOnly } from "@multica/core/issues/date"; -import { CalendarClock, CalendarDays } from "lucide-react"; +import { CalendarClock, CalendarDays } from "@multica/ui/icons"; import { ActorAvatar } from "../../common/actor-avatar"; import { PropertyIcon } from "../../common/property-icon"; import { useWorkspacePaths } from "@multica/core/paths"; @@ -210,7 +210,7 @@ export const BoardCardContent = memo(function BoardCardContent({ {/* Row 2: Title */} -

+

{issue.title}

diff --git a/packages/views/issues/components/board-column.tsx b/packages/views/issues/components/board-column.tsx index aa61e0cb5..99c8f3cf7 100644 --- a/packages/views/issues/components/board-column.tsx +++ b/packages/views/issues/components/board-column.tsx @@ -2,7 +2,7 @@ import { memo, useCallback, useMemo, useState, type ReactNode } from "react"; import { Virtuoso } from "react-virtuoso"; -import { Ban, EyeOff, FolderMinus, MoreHorizontal, Plus, UserMinus } from "lucide-react"; +import { Ban, EyeOff, FolderMinus, MoreHorizontal, Plus, UserMinus } from "@multica/ui/icons"; import { useDroppable } from "@dnd-kit/core"; import { SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable"; import type { diff --git a/packages/views/issues/components/comment-card.tsx b/packages/views/issues/components/comment-card.tsx index 1202d3280..712c831ec 100644 --- a/packages/views/issues/components/comment-card.tsx +++ b/packages/views/issues/components/comment-card.tsx @@ -1,7 +1,7 @@ "use client"; import { Fragment, memo, useCallback, useEffect, useRef, useState, type ReactNode } from "react"; -import { CheckCircle2, ChevronRight, CornerUpLeft, ListChevronsDownUp, Copy, Link2, Loader2, MessageSquarePlus, MoreHorizontal, Pencil, RotateCcw, Trash2 } from "lucide-react"; +import { CheckCircle2, ChevronRight, CornerUpLeft, ListChevronsDownUp, Copy, Link2, Loader2, MessageSquarePlus, MoreHorizontal, Pencil, RotateCcw, Trash2 } from "@multica/ui/icons"; import { toast } from "sonner"; import { Card } from "@multica/ui/components/ui/card"; import { Button, buttonVariants } from "@multica/ui/components/ui/button"; @@ -712,7 +712,7 @@ function CommentRow({ + {timeAgo(entry.created_at)} } @@ -1230,7 +1230,7 @@ function CommentCardImpl({ + {timeAgo(entry.created_at)} } @@ -1249,12 +1249,12 @@ function CommentCardImpl({ )} {!open && contentPreview && ( - + {contentPreview} )} {!open && replyCount > 0 && ( - + {t(($) => $.comment.reply_count, { count: replyCount })} )} diff --git a/packages/views/issues/components/comment-trigger-chips.tsx b/packages/views/issues/components/comment-trigger-chips.tsx index 93ca9f43a..c0a1e1c65 100644 --- a/packages/views/issues/components/comment-trigger-chips.tsx +++ b/packages/views/issues/components/comment-trigger-chips.tsx @@ -1,7 +1,7 @@ "use client"; import { useMemo, useState, type ReactElement } from "react"; -import { ChevronDown, TriangleAlert, Users } from "lucide-react"; +import { ChevronDown, TriangleAlert, Users } from "@multica/ui/icons"; import type { CommentTriggerPreviewAgent, CommentTriggerOutcome } from "@multica/core/types"; import type { AgentRunState, RecipientAction } from "@multica/core/issues/run-steering"; import { useAgentPresenceDetail } from "@multica/core/agents"; diff --git a/packages/views/issues/components/create-renderers.test.tsx b/packages/views/issues/components/create-renderers.test.tsx index a9db3a3b4..cab7d23b7 100644 --- a/packages/views/issues/components/create-renderers.test.tsx +++ b/packages/views/issues/components/create-renderers.test.tsx @@ -127,7 +127,7 @@ describe("issue renderer create entrypoints", () => { ); - expect(container.querySelector(".lucide-plus")).toBeNull(); + expect(container.querySelector(".icon-plus")).toBeNull(); expect(onCreateIssue).not.toHaveBeenCalled(); }); diff --git a/packages/views/issues/components/deliverables/deliverable-details.tsx b/packages/views/issues/components/deliverables/deliverable-details.tsx index 80ff2121b..e76f12d5e 100644 --- a/packages/views/issues/components/deliverables/deliverable-details.tsx +++ b/packages/views/issues/components/deliverables/deliverable-details.tsx @@ -1,7 +1,7 @@ "use client"; import { useCallback, type ReactNode } from "react"; -import { Check, ChevronDown, FileText, ImageIcon, MessageSquareText } from "lucide-react"; +import { Check, ChevronDown, FileText, ImageIcon, MessageSquareText } from "@multica/ui/icons"; import { findDeliverableVersion, type DeliverableFile, diff --git a/packages/views/issues/components/deliverables/deliverables-overview.tsx b/packages/views/issues/components/deliverables/deliverables-overview.tsx index 5e02dde0f..3445d044f 100644 --- a/packages/views/issues/components/deliverables/deliverables-overview.tsx +++ b/packages/views/issues/components/deliverables/deliverables-overview.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useMemo, useState, type CSSProperties, type ReactNode } from "react"; -import { LayoutGrid, MessageSquareText, X } from "lucide-react"; +import { LayoutGrid, MessageSquareText, X } from "@multica/ui/icons"; import type { DeliverableFile } from "@multica/core/attachments/deliverables"; import type { TimelineEntry } from "@multica/core/types"; import { useActorName } from "@multica/core/workspace/hooks"; diff --git a/packages/views/issues/components/deliverables/deliverables-section.tsx b/packages/views/issues/components/deliverables/deliverables-section.tsx index 33d093eeb..137bd2779 100644 --- a/packages/views/issues/components/deliverables/deliverables-section.tsx +++ b/packages/views/issues/components/deliverables/deliverables-section.tsx @@ -3,7 +3,7 @@ import { IssueSidebarSectionHeader } from "../issue-sidebar-section"; import { useState } from "react"; -import { LayoutGrid } from "lucide-react"; +import { LayoutGrid } from "@multica/ui/icons"; import type { DeliverableFile } from "@multica/core/attachments/deliverables"; import { IconButton } from "@multica/ui/components/common/icon-button"; import { TooltipHint } from "@multica/ui/components/common/tooltip-hint"; diff --git a/packages/views/issues/components/execution-log-section.tsx b/packages/views/issues/components/execution-log-section.tsx index 09efae168..378c7320a 100644 --- a/packages/views/issues/components/execution-log-section.tsx +++ b/packages/views/issues/components/execution-log-section.tsx @@ -2,7 +2,7 @@ import { Fragment, useEffect, useMemo, useState } from "react"; import { useQuery } from "@tanstack/react-query"; -import { Loader2, Maximize2, Square } from "lucide-react"; +import { Loader2, Maximize2, Square } from "@multica/ui/icons"; import { toast } from "sonner"; import { api } from "@multica/core/api"; import { issueTasksOptions } from "@multica/core/issues/queries"; diff --git a/packages/views/issues/components/filter-chips-bar.tsx b/packages/views/issues/components/filter-chips-bar.tsx index 5f4a1dab2..be3513f73 100644 --- a/packages/views/issues/components/filter-chips-bar.tsx +++ b/packages/views/issues/components/filter-chips-bar.tsx @@ -14,7 +14,7 @@ import { User, UserPen, X, -} from "lucide-react"; +} from "@multica/ui/icons"; import { useQuery } from "@tanstack/react-query"; import { Button } from "@multica/ui/components/ui/button"; import { TooltipHint } from "@multica/ui/components/common/tooltip-hint"; diff --git a/packages/views/issues/components/find-bar.tsx b/packages/views/issues/components/find-bar.tsx index f3ab7a263..96091184f 100644 --- a/packages/views/issues/components/find-bar.tsx +++ b/packages/views/issues/components/find-bar.tsx @@ -1,7 +1,7 @@ "use client"; import type { KeyboardEvent } from "react"; -import { ChevronDown, ChevronUp, Search, X } from "lucide-react"; +import { ChevronDown, ChevronUp, Search, X } from "@multica/ui/icons"; import { Input } from "@multica/ui/components/ui/input"; import { IconButton } from "@multica/ui/components/common/icon-button"; import { cn } from "@multica/ui/lib/utils"; diff --git a/packages/views/issues/components/infinite-scroll-sentinel.tsx b/packages/views/issues/components/infinite-scroll-sentinel.tsx index d30a63422..130a38a7a 100644 --- a/packages/views/issues/components/infinite-scroll-sentinel.tsx +++ b/packages/views/issues/components/infinite-scroll-sentinel.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useRef, type ReactNode } from "react"; -import { Loader2 } from "lucide-react"; +import { Loader2 } from "@multica/ui/icons"; /** Sentinel that triggers once per visibility transition. Callback/loading * changes are read through refs/props without rebuilding the observer, so a diff --git a/packages/views/issues/components/inline-comment-run.tsx b/packages/views/issues/components/inline-comment-run.tsx index a9e5848b7..03ef2dc28 100644 --- a/packages/views/issues/components/inline-comment-run.tsx +++ b/packages/views/issues/components/inline-comment-run.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useId, useMemo, useState, type ReactNode } from "react"; -import { AlertCircle, Brain, Check, ChevronRight, CirclePause, Clock3, CornerDownRight, Loader2, MessageSquare, RotateCcw, ScrollText, Square, Terminal } from "lucide-react"; +import { AlertCircle, Brain, Check, ChevronRight, CirclePause, Clock3, CornerDownRight, Loader2, MessageSquare, RotateCcw, ScrollText, Square, Terminal } from "@multica/ui/icons"; import { useQuery } from "@tanstack/react-query"; import { toast } from "sonner"; import { useWorkspaceId } from "@multica/core/hooks"; @@ -185,14 +185,14 @@ export function InlineCommentRun({ run, className, viewState, showIdentity = fal {name} {!active && task.completed_at && - + {timeAgo(task.completed_at)} } /> {new Date(task.completed_at).toLocaleString(locale)} } } @@ -207,7 +207,7 @@ export function InlineCommentRun({ run, className, viewState, showIdentity = fal } - {elapsed} + {elapsed} {hasTranscript && fullLogButton} {stopButton} {(!hasReply || replacesFailureNotice) && ended && : ( -
+
{title}
)} diff --git a/packages/views/issues/components/issue-wakeup-header-chip.tsx b/packages/views/issues/components/issue-wakeup-header-chip.tsx index 20253f349..160f33240 100644 --- a/packages/views/issues/components/issue-wakeup-header-chip.tsx +++ b/packages/views/issues/components/issue-wakeup-header-chip.tsx @@ -2,7 +2,7 @@ import { memo } from "react"; import { useQuery } from "@tanstack/react-query"; -import { Bell, TriangleAlert } from "lucide-react"; +import { Bell, TriangleAlert } from "@multica/ui/icons"; import { issueSystemWakeupsOptions, issueWakeupsOptions } from "@multica/core/issues"; import type { IssueWakeup, SystemWakeup } from "@multica/core/types"; import { useWorkspaceId } from "@multica/core/hooks"; diff --git a/packages/views/issues/components/issues-header.tsx b/packages/views/issues/components/issues-header.tsx index f2fb48059..04532787f 100644 --- a/packages/views/issues/components/issues-header.tsx +++ b/packages/views/issues/components/issues-header.tsx @@ -21,7 +21,7 @@ import { UserMinus, UserPen, Waves, -} from "lucide-react"; +} from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { Spinner } from "@multica/ui/components/ui/spinner"; import { Input } from "@multica/ui/components/ui/input"; diff --git a/packages/views/issues/components/issues-page.tsx b/packages/views/issues/components/issues-page.tsx index dc4e4557f..ae7cba35f 100644 --- a/packages/views/issues/components/issues-page.tsx +++ b/packages/views/issues/components/issues-page.tsx @@ -1,6 +1,6 @@ "use client"; -import { ListTodo } from "lucide-react"; +import { ListTodo } from "@multica/ui/icons"; import type { Issue, IssueTableFacetSpec, diff --git a/packages/views/issues/components/list-view.tsx b/packages/views/issues/components/list-view.tsx index add8e56df..8da4b8ff5 100644 --- a/packages/views/issues/components/list-view.tsx +++ b/packages/views/issues/components/list-view.tsx @@ -4,7 +4,7 @@ import { useIssueStatuses } from "@multica/core/issue-statuses/hooks"; import { useWorkspaceId } from "@multica/core/hooks"; import { memo, useState, useCallback, useMemo, useEffect, useRef } from "react"; -import { ChevronRight, Plus } from "lucide-react"; +import { ChevronRight, Plus } from "@multica/ui/icons"; import { Accordion } from "@base-ui/react/accordion"; import { DndContext, diff --git a/packages/views/issues/components/manage-views-dialog.tsx b/packages/views/issues/components/manage-views-dialog.tsx index c6ba532eb..28a9249ea 100644 --- a/packages/views/issues/components/manage-views-dialog.tsx +++ b/packages/views/issues/components/manage-views-dialog.tsx @@ -17,7 +17,7 @@ import { } from "@dnd-kit/sortable"; import { CSS } from "@dnd-kit/utilities"; import { restrictToVerticalAxis } from "@dnd-kit/modifiers"; -import { GripVertical, Layers, Pencil, Trash2 } from "lucide-react"; +import { GripVertical, Layers, Pencil, Trash2 } from "@multica/ui/icons"; import { IconButton } from "@multica/ui/components/common/icon-button"; import { TooltipHint } from "@multica/ui/components/common/tooltip-hint"; import { Switch } from "@multica/ui/components/ui/switch"; diff --git a/packages/views/issues/components/metadata-section.tsx b/packages/views/issues/components/metadata-section.tsx index 849951f74..3d6fb7386 100644 --- a/packages/views/issues/components/metadata-section.tsx +++ b/packages/views/issues/components/metadata-section.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { Copy, Maximize2, Minimize2, X } from "lucide-react"; +import { Copy, Maximize2, Minimize2, X } from "@multica/ui/icons"; import { toast } from "sonner"; import type { IssueMetadata } from "@multica/core/types"; import { IconButton } from "@multica/ui/components/common/icon-button"; diff --git a/packages/views/issues/components/pickers/assignee-picker.tsx b/packages/views/issues/components/pickers/assignee-picker.tsx index 8b9ee6044..351e9ad9d 100644 --- a/packages/views/issues/components/pickers/assignee-picker.tsx +++ b/packages/views/issues/components/pickers/assignee-picker.tsx @@ -1,7 +1,7 @@ "use client"; import { useMemo, useState } from "react"; -import { Lock, UserMinus } from "lucide-react"; +import { Lock, UserMinus } from "@multica/ui/icons"; import type { Agent, IssueAssigneeType, UpdateIssueRequest } from "@multica/core/types"; import { useQuery } from "@tanstack/react-query"; import { useAuthStore } from "@multica/core/auth"; diff --git a/packages/views/issues/components/pickers/custom-property-picker.tsx b/packages/views/issues/components/pickers/custom-property-picker.tsx index b4bedbe61..b029fb70d 100644 --- a/packages/views/issues/components/pickers/custom-property-picker.tsx +++ b/packages/views/issues/components/pickers/custom-property-picker.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useId, useRef, useState } from "react"; -import { CalendarDays, Check, ExternalLink, X } from "lucide-react"; +import { CalendarDays, Check, ExternalLink, X } from "@multica/ui/icons"; import { toast } from "sonner"; import type { Issue, IssueProperty, IssuePropertyValue } from "@multica/core/types"; import { hasUnknownActorRef, isListPropertyType } from "@multica/core/types"; diff --git a/packages/views/issues/components/pickers/due-date-picker.tsx b/packages/views/issues/components/pickers/due-date-picker.tsx index bb07c9ddf..388912f20 100644 --- a/packages/views/issues/components/pickers/due-date-picker.tsx +++ b/packages/views/issues/components/pickers/due-date-picker.tsx @@ -1,6 +1,6 @@ "use client"; -import { CalendarDays } from "lucide-react"; +import { CalendarDays } from "@multica/ui/icons"; import type { UpdateIssueRequest } from "@multica/core/types"; import { DateOnlyPicker } from "../../../common/date-only-picker"; import { useT } from "../../../i18n"; diff --git a/packages/views/issues/components/pickers/label-picker.tsx b/packages/views/issues/components/pickers/label-picker.tsx index 18201e121..b39925b16 100644 --- a/packages/views/issues/components/pickers/label-picker.tsx +++ b/packages/views/issues/components/pickers/label-picker.tsx @@ -2,7 +2,7 @@ import { useMemo, useRef, useState } from "react"; import { useQuery } from "@tanstack/react-query"; -import { Tag, Plus, Settings2 } from "lucide-react"; +import { Tag, Plus, Settings2 } from "@multica/ui/icons"; import { toast } from "sonner"; import type { Label } from "@multica/core/types"; import { useWorkspaceId } from "@multica/core/hooks"; diff --git a/packages/views/issues/components/pickers/property-picker.tsx b/packages/views/issues/components/pickers/property-picker.tsx index 8e9e5f032..a9d99c6bc 100644 --- a/packages/views/issues/components/pickers/property-picker.tsx +++ b/packages/views/issues/components/pickers/property-picker.tsx @@ -1,7 +1,7 @@ "use client"; import { useState, useCallback, useRef, useEffect } from "react"; -import { Check } from "lucide-react"; +import { Check } from "@multica/ui/icons"; import { Popover, PopoverTrigger, diff --git a/packages/views/issues/components/pickers/stage-picker.tsx b/packages/views/issues/components/pickers/stage-picker.tsx index 49f3bc4d4..3005328c7 100644 --- a/packages/views/issues/components/pickers/stage-picker.tsx +++ b/packages/views/issues/components/pickers/stage-picker.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { Milestone } from "lucide-react"; +import { Milestone } from "@multica/ui/icons"; import type { UpdateIssueRequest } from "@multica/core/types"; import { PropertyPicker, PickerItem } from "./property-picker"; import { useT } from "../../../i18n"; diff --git a/packages/views/issues/components/pickers/start-date-picker.tsx b/packages/views/issues/components/pickers/start-date-picker.tsx index 77ddd9d87..da3e028e1 100644 --- a/packages/views/issues/components/pickers/start-date-picker.tsx +++ b/packages/views/issues/components/pickers/start-date-picker.tsx @@ -1,6 +1,6 @@ "use client"; -import { CalendarClock } from "lucide-react"; +import { CalendarClock } from "@multica/ui/icons"; import type { UpdateIssueRequest } from "@multica/core/types"; import { DateOnlyPicker } from "../../../common/date-only-picker"; import { useT } from "../../../i18n"; diff --git a/packages/views/issues/components/pickers/status-picker.test.tsx b/packages/views/issues/components/pickers/status-picker.test.tsx index 55b841e15..84e5b7056 100644 --- a/packages/views/issues/components/pickers/status-picker.test.tsx +++ b/packages/views/issues/components/pickers/status-picker.test.tsx @@ -69,7 +69,7 @@ const IN_REVIEW = entry({ const QA = entry({ id: "qa", key: "qa", name: "QA", color: "#ec7a2d" }); -/** StatusIcon's own glyph, told apart from the lucide check mark beside it. */ +/** StatusIcon's own glyph, told apart from the check mark beside it. */ const STATUS_ICON = 'svg[viewBox="0 0 14 14"]'; function iconOf(row: Element | null): SVGElement | null { diff --git a/packages/views/issues/components/pickers/status-picker.tsx b/packages/views/issues/components/pickers/status-picker.tsx index d32ef2dc2..e4386d718 100644 --- a/packages/views/issues/components/pickers/status-picker.tsx +++ b/packages/views/issues/components/pickers/status-picker.tsx @@ -1,7 +1,7 @@ "use client"; import { useMemo, useState } from "react"; -import { CircleEqual, CornerDownRight } from "lucide-react"; +import { CircleEqual, CornerDownRight } from "@multica/ui/icons"; import type { IssueStatus, UpdateIssueRequest } from "@multica/core/types"; import { STATUS_CONFIG } from "@multica/core/issues/config"; import { useIssueStatuses } from "@multica/core/issue-statuses/hooks"; diff --git a/packages/views/issues/components/pull-request-list.tsx b/packages/views/issues/components/pull-request-list.tsx index 4d5c910f2..875f6499c 100644 --- a/packages/views/issues/components/pull-request-list.tsx +++ b/packages/views/issues/components/pull-request-list.tsx @@ -19,7 +19,7 @@ import { GitPullRequestDraft, TriangleAlert, XCircle, -} from "lucide-react"; +} from "@multica/ui/icons"; import { issuePullRequestsOptions, derivePullRequestVerdict, @@ -88,10 +88,10 @@ export function PullRequestList({ const rowActions = autoComplete ? { issueId, identifier, autoComplete } : null; if (isLoading) { - return

{t(($) => $.detail.pull_requests_loading)}

; + return

{t(($) => $.detail.pull_requests_loading)}

; } if (isError) { - return ; } @@ -125,7 +125,7 @@ export function PullRequestList({ )} {closed && ( -

+

{t(($) => $.wakeups.closed_hint)}

)} @@ -457,7 +457,7 @@ export function WakeupsSection({ type="button" aria-expanded={historyOpen} onClick={() => setHistoryOpen(!historyOpen)} - className="flex min-h-9 w-full items-center gap-1 rounded-md px-2 py-1 text-caption text-muted-foreground hover:bg-accent/50 focus-visible:outline-2 focus-visible:outline-ring" + className="flex min-h-9 w-full items-center gap-1 rounded-md px-2 py-1 text-label text-muted-foreground hover:bg-accent/50 focus-visible:outline-2 focus-visible:outline-ring" > , "children"> { - icon: LucideIcon; + icon: IconComponent; label: string; } @@ -117,7 +117,7 @@ export function CollectionPageHeaderAction({ type PageStateTone = "muted" | "destructive" | "warning"; interface CollectionPageStateProps { - icon: LucideIcon; + icon: IconComponent; title: ReactNode; description?: ReactNode; actions?: ReactNode; diff --git a/packages/views/layout/help-launcher.tsx b/packages/views/layout/help-launcher.tsx index e7b3dec70..c31b46017 100644 --- a/packages/views/layout/help-launcher.tsx +++ b/packages/views/layout/help-launcher.tsx @@ -7,7 +7,7 @@ import { Download, History, MessageCircle, -} from "lucide-react"; +} from "@multica/ui/icons"; import { DropdownMenu, DropdownMenuContent, diff --git a/packages/views/layout/join-discord-card.tsx b/packages/views/layout/join-discord-card.tsx index b84a2dc7a..2f14db8da 100644 --- a/packages/views/layout/join-discord-card.tsx +++ b/packages/views/layout/join-discord-card.tsx @@ -1,6 +1,6 @@ "use client"; -import { X } from "lucide-react"; +import { X } from "@multica/ui/icons"; import { useAuthStore } from "@multica/core/auth"; import { TooltipHint } from "@multica/ui/components/common/tooltip-hint"; import { DISCORD_URL, DiscordIcon } from "./discord"; diff --git a/packages/views/layout/page-header.test.tsx b/packages/views/layout/page-header.test.tsx index 023d4a6cd..892dcb86e 100644 --- a/packages/views/layout/page-header.test.tsx +++ b/packages/views/layout/page-header.test.tsx @@ -1,4 +1,4 @@ -import { ListTodo, Plus, Zap } from "lucide-react"; +import { ListTodo, Plus, Zap } from "@multica/ui/icons"; import { within } from "@testing-library/react"; import { describe, expect, it } from "vitest"; diff --git a/packages/views/layout/route-icon-components.test.tsx b/packages/views/layout/route-icon-components.test.tsx index cb306dd38..9a7f6f952 100644 --- a/packages/views/layout/route-icon-components.test.tsx +++ b/packages/views/layout/route-icon-components.test.tsx @@ -1,4 +1,5 @@ import { describe, it, expect } from "vitest"; +import { render } from "@testing-library/react"; import { paths, DEFAULT_ROUTE_ICON_NAME } from "@multica/core/paths"; import { ROUTE_ICON_COMPONENTS, routeIconForPath } from "./route-icon-components"; @@ -21,6 +22,13 @@ describe("routeIconForPath", () => { expect(routeIconForPath(p.autopilots())).not.toBe(routeIconForPath(p.issues())); }); + // The active sidebar item fills the glyph's `icon-body` solid; without one + // the active state loses its fill. + it.each(Object.entries(ROUTE_ICON_COMPONENTS))("%s marks a body for the solid active state", (_, Icon) => { + const { container } = render(); + expect(container.querySelector("svg .icon-body")).not.toBeNull(); + }); + it("returns the default component instead of undefined for an unknown route", () => { expect(routeIconForPath("/acme/not-a-route")).toBe( ROUTE_ICON_COMPONENTS[DEFAULT_ROUTE_ICON_NAME], diff --git a/packages/views/layout/route-icon-components.tsx b/packages/views/layout/route-icon-components.tsx index 0173bebf2..702e7592c 100644 --- a/packages/views/layout/route-icon-components.tsx +++ b/packages/views/layout/route-icon-components.tsx @@ -20,8 +20,8 @@ import { FileAudio, FileVideo, FileQuestion, - type LucideIcon, -} from "lucide-react"; + type IconComponent, +} from "@multica/ui/icons"; import { resolveRouteIconName, type RouteIconName } from "@multica/core/paths"; /** @@ -31,7 +31,7 @@ import { resolveRouteIconName, type RouteIconName } from "@multica/core/paths"; * Every {@link RouteIconName} must have an entry — the `Record` type makes a * missing key a compile error. */ -export const ROUTE_ICON_COMPONENTS: Record = { +export const ROUTE_ICON_COMPONENTS: Record = { Inbox, MessageSquare, CircleUser, @@ -67,6 +67,6 @@ export const ROUTE_ICON_COMPONENTS: Record = { * The sidebar nav and the desktop tab bar both call this, which is what keeps * a route's icon identical in both places. */ -export function routeIconForPath(path: string): LucideIcon { +export function routeIconForPath(path: string): IconComponent { return ROUTE_ICON_COMPONENTS[resolveRouteIconName(path)]; } diff --git a/packages/views/layout/tab-presentation.test.tsx b/packages/views/layout/tab-presentation.test.tsx index 3c0dd2467..867d15622 100644 --- a/packages/views/layout/tab-presentation.test.tsx +++ b/packages/views/layout/tab-presentation.test.tsx @@ -349,7 +349,7 @@ describe("ResourceLeadingVisual", () => { expect(getByTestId("actor-avatar").getAttribute("data-actor")).toBe("agent:ag1"); }); - it("renders a lucide icon for a plain icon visual", () => { + it("renders a route icon for a plain icon visual", () => { const { container } = render( , ); diff --git a/packages/views/members/member-detail-page.tsx b/packages/views/members/member-detail-page.tsx index 38fc64cdb..a00e1269a 100644 --- a/packages/views/members/member-detail-page.tsx +++ b/packages/views/members/member-detail-page.tsx @@ -1,6 +1,6 @@ "use client"; -import { ChevronRight, UserRound } from "lucide-react"; +import { ChevronRight, UserRound } from "@multica/ui/icons"; import { useQuery } from "@tanstack/react-query"; import type { MemberRole } from "@multica/core/types"; import { useWorkspaceId } from "@multica/core/hooks"; diff --git a/packages/views/modals/create-issue.tsx b/packages/views/modals/create-issue.tsx index 7646f3c69..1e1c2b2b9 100644 --- a/packages/views/modals/create-issue.tsx +++ b/packages/views/modals/create-issue.tsx @@ -22,7 +22,7 @@ import { Shapes, Tag, X as XIcon, -} from "lucide-react"; +} from "@multica/ui/icons"; import { cn } from "@multica/ui/lib/utils"; import { toast } from "sonner"; import type { diff --git a/packages/views/modals/create-project.tsx b/packages/views/modals/create-project.tsx index c369d09f7..fdd791a11 100644 --- a/packages/views/modals/create-project.tsx +++ b/packages/views/modals/create-project.tsx @@ -1,7 +1,7 @@ "use client"; import { useState, useRef } from "react"; -import { CalendarClock, CalendarDays, ChevronRight, FolderOpen, GitBranch, Maximize2, Minimize2, MoreHorizontal, Pencil, Search, X as XIcon, UserMinus } from "lucide-react"; +import { CalendarClock, CalendarDays, ChevronRight, FolderOpen, GitBranch, Maximize2, Minimize2, MoreHorizontal, Pencil, Search, X as XIcon, UserMinus } from "@multica/ui/icons"; /** * GitHub mark — lucide-react v1 dropped brand icons, so we inline the diff --git a/packages/views/modals/create-squad.tsx b/packages/views/modals/create-squad.tsx index 38197d1eb..132bf50b4 100644 --- a/packages/views/modals/create-squad.tsx +++ b/packages/views/modals/create-squad.tsx @@ -2,7 +2,7 @@ import { useMemo, useState } from "react"; import { useQuery, useQueryClient } from "@tanstack/react-query"; -import { ChevronDown, UserPlus, X } from "lucide-react"; +import { ChevronDown, UserPlus, X } from "@multica/ui/icons"; import { api } from "@multica/core/api"; import { useAuthStore } from "@multica/core/auth"; import { useWorkspaceId } from "@multica/core/hooks"; diff --git a/packages/views/modals/issue-limit-upgrade-dialog.tsx b/packages/views/modals/issue-limit-upgrade-dialog.tsx index ff0268107..4bd68c48f 100644 --- a/packages/views/modals/issue-limit-upgrade-dialog.tsx +++ b/packages/views/modals/issue-limit-upgrade-dialog.tsx @@ -2,7 +2,7 @@ import { useEffect, useRef, useState } from "react"; import { useQuery } from "@tanstack/react-query"; -import { Gauge, Loader2 } from "lucide-react"; +import { Gauge, Loader2 } from "@multica/ui/icons"; import { useCreateWorkspaceSubscriptionPortal, workspaceSubscriptionSummaryOptions, diff --git a/packages/views/modals/quick-create-issue.tsx b/packages/views/modals/quick-create-issue.tsx index 904ead1f6..5e7db2317 100644 --- a/packages/views/modals/quick-create-issue.tsx +++ b/packages/views/modals/quick-create-issue.tsx @@ -12,7 +12,7 @@ import { MoreHorizontal, Settings2, X as XIcon, -} from "lucide-react"; +} from "@multica/ui/icons"; import { useQuery } from "@tanstack/react-query"; import { toast } from "sonner"; import { DialogTitle } from "@multica/ui/components/ui/dialog"; diff --git a/packages/views/modals/source-context-preview.tsx b/packages/views/modals/source-context-preview.tsx index a66930039..8a5802ac8 100644 --- a/packages/views/modals/source-context-preview.tsx +++ b/packages/views/modals/source-context-preview.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { ChevronRight, Loader2, RefreshCw } from "lucide-react"; +import { ChevronRight, Loader2, RefreshCw } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { cn } from "@multica/ui/lib/utils"; import type { SourceContextPreview } from "@multica/core/types"; diff --git a/packages/views/my-issues/components/my-issues-header.tsx b/packages/views/my-issues/components/my-issues-header.tsx index b2f314622..aaac32247 100644 --- a/packages/views/my-issues/components/my-issues-header.tsx +++ b/packages/views/my-issues/components/my-issues-header.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useState } from "react"; -import { ChevronDown } from "lucide-react"; +import { ChevronDown } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { DropdownMenu, diff --git a/packages/views/my-issues/components/my-issues-page.tsx b/packages/views/my-issues/components/my-issues-page.tsx index 93df3f5b6..ed8806d8b 100644 --- a/packages/views/my-issues/components/my-issues-page.tsx +++ b/packages/views/my-issues/components/my-issues-page.tsx @@ -1,7 +1,7 @@ "use client"; import { useStore } from "zustand"; -import { ListTodo } from "lucide-react"; +import { ListTodo } from "@multica/ui/icons"; import { useAuthStore } from "@multica/core/auth"; import { myIssuesRelationFromScope, diff --git a/packages/views/onboarding/components/cloud-waitlist-expand.tsx b/packages/views/onboarding/components/cloud-waitlist-expand.tsx index 093d7ba27..2587eb27e 100644 --- a/packages/views/onboarding/components/cloud-waitlist-expand.tsx +++ b/packages/views/onboarding/components/cloud-waitlist-expand.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { ArrowRight, Check, Loader2 } from "lucide-react"; +import { ArrowRight, Check, Loader2 } from "@multica/ui/icons"; import { toast } from "sonner"; import { Button } from "@multica/ui/components/ui/button"; import { Input } from "@multica/ui/components/ui/input"; diff --git a/packages/views/onboarding/components/icon-option-card.tsx b/packages/views/onboarding/components/icon-option-card.tsx index a2be152a8..443c8aa5b 100644 --- a/packages/views/onboarding/components/icon-option-card.tsx +++ b/packages/views/onboarding/components/icon-option-card.tsx @@ -1,7 +1,7 @@ "use client"; import type { ReactNode } from "react"; -import { Check } from "lucide-react"; +import { Check } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { cn } from "@multica/ui/lib/utils"; @@ -9,7 +9,7 @@ const OTHER_INPUT_MAX_LENGTH = 80; /** * One option in a questionnaire card grid. `slug` is the persisted - * enum value; `icon` is a React node (lucide icon, brand SVG, or emoji + * enum value; `icon` is a React node (product icon, brand SVG, or emoji * span); `label` is the localized string already resolved by the * caller. `isOther` flips this card into a free-text input row. * diff --git a/packages/views/onboarding/components/onboarding-logout-button.tsx b/packages/views/onboarding/components/onboarding-logout-button.tsx index 17e5eed6e..1dff87187 100644 --- a/packages/views/onboarding/components/onboarding-logout-button.tsx +++ b/packages/views/onboarding/components/onboarding-logout-button.tsx @@ -1,6 +1,6 @@ "use client"; -import { LogOut } from "lucide-react"; +import { LogOut } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { cn } from "@multica/ui/lib/utils"; import { useLogout } from "../../auth"; diff --git a/packages/views/onboarding/components/step-sidebar.tsx b/packages/views/onboarding/components/step-sidebar.tsx index 580f0114d..4fc1537bd 100644 --- a/packages/views/onboarding/components/step-sidebar.tsx +++ b/packages/views/onboarding/components/step-sidebar.tsx @@ -1,7 +1,7 @@ "use client"; import type { CSSProperties, ReactNode } from "react"; -import { ArrowLeft, Check } from "lucide-react"; +import { ArrowLeft, Check } from "@multica/ui/icons"; import { ONBOARDING_STEP_ORDER, type OnboardingStep, diff --git a/packages/views/onboarding/source-backfill-modal.tsx b/packages/views/onboarding/source-backfill-modal.tsx index e7dd0ccf2..2a2208146 100644 --- a/packages/views/onboarding/source-backfill-modal.tsx +++ b/packages/views/onboarding/source-backfill-modal.tsx @@ -10,7 +10,7 @@ import { MoreHorizontal, Newspaper, Users, -} from "lucide-react"; +} from "@multica/ui/icons"; import { toast } from "sonner"; import { useAuthStore } from "@multica/core/auth"; import { diff --git a/packages/views/onboarding/steps/cli-install-instructions.tsx b/packages/views/onboarding/steps/cli-install-instructions.tsx index 43bd84407..9f6b0f5a6 100644 --- a/packages/views/onboarding/steps/cli-install-instructions.tsx +++ b/packages/views/onboarding/steps/cli-install-instructions.tsx @@ -1,7 +1,7 @@ "use client"; import { useState, type ReactNode } from "react"; -import { Check, Copy, Terminal } from "lucide-react"; +import { Check, Copy, Terminal } from "@multica/ui/icons"; import { Card, CardContent } from "@multica/ui/components/ui/card"; import { TooltipHint } from "@multica/ui/components/common/tooltip-hint"; import { CODE_LIGATURE_CLASS } from "@multica/ui/lib/code-style"; diff --git a/packages/views/onboarding/steps/step-about-you.tsx b/packages/views/onboarding/steps/step-about-you.tsx index 344b0e166..83ad73c62 100644 --- a/packages/views/onboarding/steps/step-about-you.tsx +++ b/packages/views/onboarding/steps/step-about-you.tsx @@ -16,7 +16,7 @@ import { Search, Settings2, User, -} from "lucide-react"; +} from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import type { QuestionnaireAnswers, Role, UseCase } from "@multica/core/onboarding"; import { diff --git a/packages/views/onboarding/steps/step-platform-fork.tsx b/packages/views/onboarding/steps/step-platform-fork.tsx index db83c4d9d..700b90b52 100644 --- a/packages/views/onboarding/steps/step-platform-fork.tsx +++ b/packages/views/onboarding/steps/step-platform-fork.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useState, type ReactNode } from "react"; -import { ArrowRight, Download, Loader2 } from "lucide-react"; +import { ArrowRight, Download, Loader2 } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { Dialog, diff --git a/packages/views/onboarding/steps/step-runtime-connect.tsx b/packages/views/onboarding/steps/step-runtime-connect.tsx index 4bc84c102..cab42fb3d 100644 --- a/packages/views/onboarding/steps/step-runtime-connect.tsx +++ b/packages/views/onboarding/steps/step-runtime-connect.tsx @@ -6,7 +6,7 @@ import { ArrowRight, Loader2, RefreshCw, -} from "lucide-react"; +} from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { cn } from "@multica/ui/lib/utils"; import { runtimeKeys } from "@multica/core/runtimes/queries"; diff --git a/packages/views/onboarding/steps/step-welcome.tsx b/packages/views/onboarding/steps/step-welcome.tsx index 2c4ed94c9..59ad2690f 100644 --- a/packages/views/onboarding/steps/step-welcome.tsx +++ b/packages/views/onboarding/steps/step-welcome.tsx @@ -2,7 +2,7 @@ import { statusCategoryOfKey } from "@multica/core/issues"; import { useState } from "react"; -import { ArrowRight, Download, Loader2 } from "lucide-react"; +import { ArrowRight, Download, Loader2 } from "@multica/ui/icons"; import { Button, buttonVariants } from "@multica/ui/components/ui/button"; import { MulticaIcon } from "@multica/ui/components/common/multica-icon"; import { cn } from "@multica/ui/lib/utils"; diff --git a/packages/views/onboarding/steps/step-workspace.tsx b/packages/views/onboarding/steps/step-workspace.tsx index 47c62eed1..7034d4247 100644 --- a/packages/views/onboarding/steps/step-workspace.tsx +++ b/packages/views/onboarding/steps/step-workspace.tsx @@ -1,7 +1,7 @@ "use client"; import { type ReactNode, useRef, useEffect, useState } from "react"; -import { Dices, Plus } from "lucide-react"; +import { Dices, Plus } from "@multica/ui/icons"; import { toast } from "sonner"; import { Button } from "@multica/ui/components/ui/button"; import { Input } from "@multica/ui/components/ui/input"; diff --git a/packages/views/package.json b/packages/views/package.json index a67f3bb72..74635305c 100644 --- a/packages/views/package.json +++ b/packages/views/package.json @@ -130,7 +130,6 @@ "@tanstack/react-query": "catalog:", "@tanstack/react-table": "catalog:", "i18next": "catalog:", - "lucide-react": "catalog:", "react": "catalog:", "react-dom": "catalog:", "react-i18next": "catalog:", diff --git a/packages/views/plugins/plugin-hook-actions.tsx b/packages/views/plugins/plugin-hook-actions.tsx index f67e81f88..de43bb5d0 100644 --- a/packages/views/plugins/plugin-hook-actions.tsx +++ b/packages/views/plugins/plugin-hook-actions.tsx @@ -2,7 +2,7 @@ import { useMemo, useState } from "react"; import { useQuery } from "@tanstack/react-query"; -import { Loader2, Plug } from "lucide-react"; +import { Loader2, Plug } from "@multica/ui/icons"; import { toast } from "sonner"; import { useFeatureEnabled } from "@multica/core/config"; import { PLUGINS_V1_FLAG } from "@multica/core/feature-flags"; diff --git a/packages/views/plugins/plugin-hook-activity.tsx b/packages/views/plugins/plugin-hook-activity.tsx index 014b9b92a..a0612919e 100644 --- a/packages/views/plugins/plugin-hook-activity.tsx +++ b/packages/views/plugins/plugin-hook-activity.tsx @@ -1,7 +1,7 @@ "use client"; import { useQuery } from "@tanstack/react-query"; -import { AlertTriangle } from "lucide-react"; +import { AlertTriangle } from "@multica/ui/icons"; import { pluginInvocationsOptions } from "@multica/core/plugins"; import type { PluginHook, PluginInvocation } from "@multica/core/types"; import { cn } from "@multica/ui/lib/utils"; diff --git a/packages/views/plugins/plugin-mcp-approval.tsx b/packages/views/plugins/plugin-mcp-approval.tsx index 57a233469..eedc4cfdb 100644 --- a/packages/views/plugins/plugin-mcp-approval.tsx +++ b/packages/views/plugins/plugin-mcp-approval.tsx @@ -2,7 +2,7 @@ import { useMemo, useState } from "react"; import { useQuery } from "@tanstack/react-query"; -import { AlertCircle, Loader2 } from "lucide-react"; +import { AlertCircle, Loader2 } from "@multica/ui/icons"; import { pluginMCPToolsOptions, useApprovePluginMCPTools } from "@multica/core/plugins"; import type { PluginHook, PluginMCPTool } from "@multica/core/types"; import { Alert, AlertDescription, AlertTitle } from "@multica/ui/components/ui/alert"; diff --git a/packages/views/plugins/plugin-modal-surface.tsx b/packages/views/plugins/plugin-modal-surface.tsx index 1fd85a1b3..780a16042 100644 --- a/packages/views/plugins/plugin-modal-surface.tsx +++ b/packages/views/plugins/plugin-modal-surface.tsx @@ -2,7 +2,7 @@ import { useMemo, useState } from "react"; import { useQuery } from "@tanstack/react-query"; -import { Plug } from "lucide-react"; +import { Plug } from "@multica/ui/icons"; import { useFeatureEnabled } from "@multica/core/config"; import { PLUGINS_V1_FLAG } from "@multica/core/feature-flags"; import { useCurrentWorkspace } from "@multica/core/paths"; diff --git a/packages/views/projects/components/github-ref-dialog.tsx b/packages/views/projects/components/github-ref-dialog.tsx index f18842407..aecc8c655 100644 --- a/packages/views/projects/components/github-ref-dialog.tsx +++ b/packages/views/projects/components/github-ref-dialog.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useState } from "react"; -import { TriangleAlert } from "lucide-react"; +import { TriangleAlert } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { Dialog, diff --git a/packages/views/projects/components/local-directory-hint.tsx b/packages/views/projects/components/local-directory-hint.tsx index e518a2959..f00711bdd 100644 --- a/packages/views/projects/components/local-directory-hint.tsx +++ b/packages/views/projects/components/local-directory-hint.tsx @@ -1,7 +1,7 @@ "use client"; import { useQuery } from "@tanstack/react-query"; -import { FolderOpen, GitBranch } from "lucide-react"; +import { FolderOpen, GitBranch } from "@multica/ui/icons"; import { projectResourcesOptions } from "@multica/core/projects"; import type { Agent, LocalDirectoryResourceRef, ProjectResource } from "@multica/core/types"; import { useWorkspaceId } from "@multica/core/hooks"; diff --git a/packages/views/projects/components/local-directory-mode-dialog.tsx b/packages/views/projects/components/local-directory-mode-dialog.tsx index c8cd3549d..a1e765131 100644 --- a/packages/views/projects/components/local-directory-mode-dialog.tsx +++ b/packages/views/projects/components/local-directory-mode-dialog.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useState } from "react"; -import { GitBranch, Pencil, TriangleAlert } from "lucide-react"; +import { GitBranch, Pencil, TriangleAlert } from "@multica/ui/icons"; import type { LocalDirectoryExecutionMode } from "@multica/core/types"; import { Button } from "@multica/ui/components/ui/button"; import { diff --git a/packages/views/projects/components/project-badge.tsx b/packages/views/projects/components/project-badge.tsx index 63facd1b3..067fcc1b7 100644 --- a/packages/views/projects/components/project-badge.tsx +++ b/packages/views/projects/components/project-badge.tsx @@ -1,6 +1,6 @@ "use client"; -import { Check } from "lucide-react"; +import { Check } from "@multica/ui/icons"; import { PROJECT_STATUS_CONFIG, PROJECT_STATUS_ORDER, diff --git a/packages/views/projects/components/project-detail.tsx b/packages/views/projects/components/project-detail.tsx index 61b147a5c..9bfe389a8 100644 --- a/packages/views/projects/components/project-detail.tsx +++ b/packages/views/projects/components/project-detail.tsx @@ -3,7 +3,7 @@ import { useMemo, useState, useCallback, useRef, useEffect } from "react"; import { useRegisterCommandBarContext } from "../../search/register-context"; import { useDefaultLayout, usePanelRef } from "react-resizable-panels"; -import { Check, ChevronRight, Link2, MoreHorizontal, PanelRight, Pin, PinOff, Trash2, UserMinus } from "lucide-react"; +import { Check, ChevronRight, Link2, MoreHorizontal, PanelRight, Pin, PinOff, Trash2, UserMinus } from "@multica/ui/icons"; import { useQuery } from "@tanstack/react-query"; import { cn } from "@multica/ui/lib/utils"; import { copyText } from "@multica/ui/lib/clipboard"; diff --git a/packages/views/projects/components/project-due-date-picker.tsx b/packages/views/projects/components/project-due-date-picker.tsx index 50cb159d9..2ee9847e7 100644 --- a/packages/views/projects/components/project-due-date-picker.tsx +++ b/packages/views/projects/components/project-due-date-picker.tsx @@ -1,6 +1,6 @@ "use client"; -import { CalendarDays } from "lucide-react"; +import { CalendarDays } from "@multica/ui/icons"; import type { UpdateProjectRequest } from "@multica/core/types"; import { DateOnlyPicker } from "../../common/date-only-picker"; import { useT } from "../../i18n"; diff --git a/packages/views/projects/components/project-lead-picker.tsx b/packages/views/projects/components/project-lead-picker.tsx index 505af2c12..78076ec8f 100644 --- a/packages/views/projects/components/project-lead-picker.tsx +++ b/packages/views/projects/components/project-lead-picker.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { UserMinus } from "lucide-react"; +import { UserMinus } from "@multica/ui/icons"; import { useQuery } from "@tanstack/react-query"; import { memberListOptions, agentListOptions } from "@multica/core/workspace/queries"; import { useWorkspaceId } from "@multica/core/hooks"; diff --git a/packages/views/projects/components/project-picker.tsx b/packages/views/projects/components/project-picker.tsx index 815b0fb6b..d4fd2d337 100644 --- a/packages/views/projects/components/project-picker.tsx +++ b/packages/views/projects/components/project-picker.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { FolderKanban } from "lucide-react"; +import { FolderKanban } from "@multica/ui/icons"; import { useQuery } from "@tanstack/react-query"; import { projectListOptions } from "@multica/core/projects/queries"; import { useWorkspaceId } from "@multica/core/hooks"; diff --git a/packages/views/projects/components/project-resources-section.tsx b/packages/views/projects/components/project-resources-section.tsx index 190b9911d..a73c90aa7 100644 --- a/packages/views/projects/components/project-resources-section.tsx +++ b/packages/views/projects/components/project-resources-section.tsx @@ -10,7 +10,7 @@ import { Plus, Search, Trash2, -} from "lucide-react"; +} from "@multica/ui/icons"; import { toast } from "sonner"; import { projectResourcesOptions, diff --git a/packages/views/projects/components/project-start-date-picker.tsx b/packages/views/projects/components/project-start-date-picker.tsx index b18124fea..c3066c631 100644 --- a/packages/views/projects/components/project-start-date-picker.tsx +++ b/packages/views/projects/components/project-start-date-picker.tsx @@ -1,6 +1,6 @@ "use client"; -import { CalendarClock } from "lucide-react"; +import { CalendarClock } from "@multica/ui/icons"; import type { UpdateProjectRequest } from "@multica/core/types"; import { DateOnlyPicker } from "../../common/date-only-picker"; import { useT } from "../../i18n"; diff --git a/packages/views/projects/components/projects-page.tsx b/packages/views/projects/components/projects-page.tsx index c67ee08a1..5a1b6c2ff 100644 --- a/packages/views/projects/components/projects-page.tsx +++ b/packages/views/projects/components/projects-page.tsx @@ -17,7 +17,7 @@ import { Search, Trash2, X, -} from "lucide-react"; +} from "@multica/ui/icons"; import { useQuery } from "@tanstack/react-query"; import { toast } from "sonner"; import { diff --git a/packages/views/quick-actions/components/quick-action-dialog.tsx b/packages/views/quick-actions/components/quick-action-dialog.tsx index 38b6bba07..062318a05 100644 --- a/packages/views/quick-actions/components/quick-action-dialog.tsx +++ b/packages/views/quick-actions/components/quick-action-dialog.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useMemo, useState } from "react"; -import { Globe, Info, Lock } from "lucide-react"; +import { Globe, Info, Lock } from "@multica/ui/icons"; import { toast } from "sonner"; import { useWorkspaceId } from "@multica/core/hooks"; import { useCurrentMember } from "@multica/core/permissions"; diff --git a/packages/views/rich-content/rich-code-block.tsx b/packages/views/rich-content/rich-code-block.tsx index 76d8e45d7..4f1f3720c 100644 --- a/packages/views/rich-content/rich-code-block.tsx +++ b/packages/views/rich-content/rich-code-block.tsx @@ -26,7 +26,7 @@ import { memo, useEffect, useMemo, useState, type ReactNode } from "react"; import { toHtml } from "hast-util-to-html"; -import { Check, Copy } from "lucide-react"; +import { Check, Copy } from "@multica/ui/icons"; import { cn } from "@multica/ui/lib/utils"; import { copyText } from "@multica/ui/lib/clipboard"; import { useT } from "../i18n"; diff --git a/packages/views/rich-content/rich-content-parity.test.tsx b/packages/views/rich-content/rich-content-parity.test.tsx index ed5f3bdfa..9a468d268 100644 --- a/packages/views/rich-content/rich-content-parity.test.tsx +++ b/packages/views/rich-content/rich-content-parity.test.tsx @@ -195,7 +195,7 @@ beforeEach(() => { /** * The Mermaid leaf's own container — NOT a bare `svg` query, which also matches - * the lucide icons in code-block chrome. + * the icons in code-block chrome. */ const mermaidLeaf = (container: HTMLElement): Element | null => container.querySelector(".mermaid-diagram"); diff --git a/packages/views/rich-content/rich-table-dialog.tsx b/packages/views/rich-content/rich-table-dialog.tsx index c59f68303..8f05bedcb 100644 --- a/packages/views/rich-content/rich-table-dialog.tsx +++ b/packages/views/rich-content/rich-table-dialog.tsx @@ -19,7 +19,7 @@ import { type Row, type SortingState, } from "@tanstack/react-table"; -import { Check, Copy, Search, X } from "lucide-react"; +import { Check, Copy, Search, X } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { IconButton } from "@multica/ui/components/common/icon-button"; import { DataTable } from "@multica/ui/components/ui/data-table"; diff --git a/packages/views/rich-content/rich-table.tsx b/packages/views/rich-content/rich-table.tsx index 98343deaa..0875aaf05 100644 --- a/packages/views/rich-content/rich-table.tsx +++ b/packages/views/rich-content/rich-table.tsx @@ -31,7 +31,7 @@ import { } from "react"; import { createPortal } from "react-dom"; import type { ExtraProps } from "react-markdown"; -import { Check, Copy, Maximize2, RotateCcw } from "lucide-react"; +import { Check, Copy, Maximize2, RotateCcw } from "@multica/ui/icons"; import { copyText } from "@multica/ui/lib/clipboard"; import { cn } from "@multica/ui/lib/utils"; import { useT } from "../i18n"; diff --git a/packages/views/runtimes/components/cloud-runtime-dialog.tsx b/packages/views/runtimes/components/cloud-runtime-dialog.tsx index 8372b1380..f98316198 100644 --- a/packages/views/runtimes/components/cloud-runtime-dialog.tsx +++ b/packages/views/runtimes/components/cloud-runtime-dialog.tsx @@ -3,7 +3,7 @@ import { useId, useMemo, useState } from "react"; import type { FormEvent, HTMLAttributes } from "react"; import { useQuery } from "@tanstack/react-query"; -import { Cloud, Loader2, RefreshCw, Rocket, Trash2 } from "lucide-react"; +import { Cloud, Loader2, RefreshCw, Rocket, Trash2 } from "@multica/ui/icons"; import { toast } from "sonner"; import type { CloudRuntimeNode } from "@multica/core/runtimes"; import { diff --git a/packages/views/runtimes/components/connect-remote-dialog.tsx b/packages/views/runtimes/components/connect-remote-dialog.tsx index 46aa50e39..120d6ae99 100644 --- a/packages/views/runtimes/components/connect-remote-dialog.tsx +++ b/packages/views/runtimes/components/connect-remote-dialog.tsx @@ -8,7 +8,7 @@ import { type ReactNode, } from "react"; import { AnimatePresence, motion, useReducedMotion } from "motion/react"; -import { Check, ChevronRight, Copy, Terminal } from "lucide-react"; +import { Check, ChevronRight, Copy, Terminal } from "@multica/ui/icons"; import { useQueryClient } from "@tanstack/react-query"; import { useWorkspaceId } from "@multica/core/hooks"; import { runtimeKeys } from "@multica/core/runtimes/queries"; diff --git a/packages/views/runtimes/components/custom-pricing-dialog.tsx b/packages/views/runtimes/components/custom-pricing-dialog.tsx index e1e1ab3c8..3a9bd3437 100644 --- a/packages/views/runtimes/components/custom-pricing-dialog.tsx +++ b/packages/views/runtimes/components/custom-pricing-dialog.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useState } from "react"; -import { Trash2 } from "lucide-react"; +import { Trash2 } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { IconButton } from "@multica/ui/components/common/icon-button"; import { diff --git a/packages/views/runtimes/components/delete-runtime-dialog.tsx b/packages/views/runtimes/components/delete-runtime-dialog.tsx index f69f82b20..5a12436ce 100644 --- a/packages/views/runtimes/components/delete-runtime-dialog.tsx +++ b/packages/views/runtimes/components/delete-runtime-dialog.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useMemo, useState } from "react"; -import { AlertTriangle, Globe, Info, Lock } from "lucide-react"; +import { AlertTriangle, Globe, Info, Lock } from "@multica/ui/icons"; import { toast } from "sonner"; import { useQuery } from "@tanstack/react-query"; import { ApiError } from "@multica/core/api"; diff --git a/packages/views/runtimes/components/delete-runtime-profile-dialog.tsx b/packages/views/runtimes/components/delete-runtime-profile-dialog.tsx index 2007d5fbe..b5b43920e 100644 --- a/packages/views/runtimes/components/delete-runtime-profile-dialog.tsx +++ b/packages/views/runtimes/components/delete-runtime-profile-dialog.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useState } from "react"; -import { AlertTriangle } from "lucide-react"; +import { AlertTriangle } from "@multica/ui/icons"; import { toast } from "sonner"; import type { RuntimeProfile } from "@multica/core/types"; import { diff --git a/packages/views/runtimes/components/provider-logo.tsx b/packages/views/runtimes/components/provider-logo.tsx index 979a4c107..47b3f09c9 100644 --- a/packages/views/runtimes/components/provider-logo.tsx +++ b/packages/views/runtimes/components/provider-logo.tsx @@ -1,5 +1,5 @@ import { useId } from "react"; -import { Monitor } from "lucide-react"; +import { Monitor } from "@multica/ui/icons"; import codeartsLogo from "./codearts-logo.svg"; import qwenLogo from "./qwen-logo.svg"; import reasonixLogo from "./reasonix-logo.svg"; diff --git a/packages/views/runtimes/components/qoder-connect-form.tsx b/packages/views/runtimes/components/qoder-connect-form.tsx index 5a47a9c37..78b9fb9c7 100644 --- a/packages/views/runtimes/components/qoder-connect-form.tsx +++ b/packages/views/runtimes/components/qoder-connect-form.tsx @@ -10,7 +10,7 @@ import { Plug, Settings2, ShieldCheck, -} from "lucide-react"; +} from "@multica/ui/icons"; import { MAX_CONCURRENCY, MAX_RUN_TIMEOUT, diff --git a/packages/views/runtimes/components/qoder-connection-cards.tsx b/packages/views/runtimes/components/qoder-connection-cards.tsx index 778159abd..50dcbb1b8 100644 --- a/packages/views/runtimes/components/qoder-connection-cards.tsx +++ b/packages/views/runtimes/components/qoder-connection-cards.tsx @@ -12,7 +12,7 @@ import { RefreshCw, ShieldCheck, Trash2, -} from "lucide-react"; +} from "@multica/ui/icons"; import { toast } from "sonner"; import { MAX_CONCURRENCY, diff --git a/packages/views/runtimes/components/qoder-detail-page.tsx b/packages/views/runtimes/components/qoder-detail-page.tsx index 71f55d2f9..9ef83d3de 100644 --- a/packages/views/runtimes/components/qoder-detail-page.tsx +++ b/packages/views/runtimes/components/qoder-detail-page.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { AlertCircle, Plus } from "lucide-react"; +import { AlertCircle, Plus } from "@multica/ui/icons"; import { toast } from "sonner"; import { useQuery } from "@tanstack/react-query"; import type { Agent, AgentRuntime } from "@multica/core/types"; diff --git a/packages/views/runtimes/components/revoke-runtime-access-dialog.tsx b/packages/views/runtimes/components/revoke-runtime-access-dialog.tsx index 3388a9557..77f7bf20d 100644 --- a/packages/views/runtimes/components/revoke-runtime-access-dialog.tsx +++ b/packages/views/runtimes/components/revoke-runtime-access-dialog.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useState } from "react"; -import { AlertTriangle } from "lucide-react"; +import { AlertTriangle } from "@multica/ui/icons"; import { toast } from "sonner"; import type { AgentRuntime } from "@multica/core/types"; import { ApiError, parseWithFallback } from "@multica/core/api"; diff --git a/packages/views/runtimes/components/runtime-access-editor.tsx b/packages/views/runtimes/components/runtime-access-editor.tsx index 2f083e5ea..8a30552a2 100644 --- a/packages/views/runtimes/components/runtime-access-editor.tsx +++ b/packages/views/runtimes/components/runtime-access-editor.tsx @@ -1,7 +1,7 @@ "use client"; import { useMemo, useState, type ComponentProps } from "react"; -import { Globe, Lock, Users } from "lucide-react"; +import { Globe, Lock, Users } from "@multica/ui/icons"; import { toast } from "sonner"; import { useQuery } from "@tanstack/react-query"; import type { AgentRuntime } from "@multica/core/types"; diff --git a/packages/views/runtimes/components/runtime-detail-page.tsx b/packages/views/runtimes/components/runtime-detail-page.tsx index 14bfcebc2..8b2ca2985 100644 --- a/packages/views/runtimes/components/runtime-detail-page.tsx +++ b/packages/views/runtimes/components/runtime-detail-page.tsx @@ -1,7 +1,7 @@ "use client"; import { useCallback, useEffect, useMemo, useState } from "react"; -import { AlertCircle, Cloud, Monitor, Pencil, Plus, Server } from "lucide-react"; +import { AlertCircle, Cloud, Monitor, Pencil, Plus, Server } from "@multica/ui/icons"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { useAuthStore } from "@multica/core/auth"; import { useWorkspaceId } from "@multica/core/hooks"; diff --git a/packages/views/runtimes/components/runtime-detail.tsx b/packages/views/runtimes/components/runtime-detail.tsx index 2f2dd4e20..914ccc653 100644 --- a/packages/views/runtimes/components/runtime-detail.tsx +++ b/packages/views/runtimes/components/runtime-detail.tsx @@ -6,7 +6,7 @@ import { ChevronRight, Cpu, Lock, -} from "lucide-react"; +} from "@multica/ui/icons"; import { toast } from "sonner"; import { useQuery } from "@tanstack/react-query"; import type { diff --git a/packages/views/runtimes/components/runtime-list.tsx b/packages/views/runtimes/components/runtime-list.tsx index d45b103c9..43d647b30 100644 --- a/packages/views/runtimes/components/runtime-list.tsx +++ b/packages/views/runtimes/components/runtime-list.tsx @@ -10,7 +10,7 @@ import { MoreHorizontal, Pencil, Trash2, -} from "lucide-react"; +} from "@multica/ui/icons"; import { toast } from "sonner"; import { useQuery } from "@tanstack/react-query"; import { CurrencyNumberFlow } from "@multica/ui/components/ui/number-flow"; diff --git a/packages/views/runtimes/components/runtime-profiles-dialog.tsx b/packages/views/runtimes/components/runtime-profiles-dialog.tsx index 42aad6aa8..092b1422d 100644 --- a/packages/views/runtimes/components/runtime-profiles-dialog.tsx +++ b/packages/views/runtimes/components/runtime-profiles-dialog.tsx @@ -12,7 +12,7 @@ import { Server, Trash2, X, -} from "lucide-react"; +} from "@multica/ui/icons"; import { toast } from "sonner"; import { useQuery } from "@tanstack/react-query"; import { ApiError } from "@multica/core/api"; diff --git a/packages/views/runtimes/components/runtime-settings-page.tsx b/packages/views/runtimes/components/runtime-settings-page.tsx index e4877b087..81dbde91c 100644 --- a/packages/views/runtimes/components/runtime-settings-page.tsx +++ b/packages/views/runtimes/components/runtime-settings-page.tsx @@ -1,6 +1,6 @@ "use client"; -import { Server } from "lucide-react"; +import { Server } from "@multica/ui/icons"; import { useQuery } from "@tanstack/react-query"; import type { AgentRuntime } from "@multica/core/types"; import { useWorkspaceId } from "@multica/core/hooks"; diff --git a/packages/views/runtimes/components/runtimes-page.tsx b/packages/views/runtimes/components/runtimes-page.tsx index 76f475c06..b6359358f 100644 --- a/packages/views/runtimes/components/runtimes-page.tsx +++ b/packages/views/runtimes/components/runtimes-page.tsx @@ -14,7 +14,7 @@ import { Search, Server, SquareTerminal, -} from "lucide-react"; +} from "@multica/ui/icons"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { toast } from "sonner"; import { useAuthStore } from "@multica/core/auth"; diff --git a/packages/views/runtimes/components/shared.tsx b/packages/views/runtimes/components/shared.tsx index a8e785a7c..31c426a27 100644 --- a/packages/views/runtimes/components/shared.tsx +++ b/packages/views/runtimes/components/shared.tsx @@ -1,4 +1,4 @@ -import { Cloud, Monitor, Wifi, WifiHigh, WifiOff } from "lucide-react"; +import { Cloud, Monitor, Wifi, WifiHigh, WifiOff } from "@multica/ui/icons"; import { Badge } from "@multica/ui/components/ui/badge"; import type { RuntimeHealth } from "@multica/core/runtimes"; import { ProviderLogo } from "./provider-logo"; diff --git a/packages/views/runtimes/components/update-section.tsx b/packages/views/runtimes/components/update-section.tsx index fd6aeac1a..c3a77cd93 100644 --- a/packages/views/runtimes/components/update-section.tsx +++ b/packages/views/runtimes/components/update-section.tsx @@ -6,7 +6,7 @@ import { ArrowUpCircle, Check, Lock, -} from "lucide-react"; +} from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { api } from "@multica/core/api"; import type { RuntimeUpdateStatus } from "@multica/core/types"; diff --git a/packages/views/runtimes/components/usage-section.tsx b/packages/views/runtimes/components/usage-section.tsx index 783b1c129..5dd2c7228 100644 --- a/packages/views/runtimes/components/usage-section.tsx +++ b/packages/views/runtimes/components/usage-section.tsx @@ -1,7 +1,7 @@ "use client"; import { useMemo, useState } from "react"; -import { BarChart3, ChevronRight, AlertCircle } from "lucide-react"; +import { BarChart3, ChevronRight, AlertCircle } from "@multica/ui/icons"; import { useQuery } from "@tanstack/react-query"; import { Skeleton } from "@multica/ui/components/ui/skeleton"; import { Button } from "@multica/ui/components/ui/button"; diff --git a/packages/views/search/commands/context-commands.tsx b/packages/views/search/commands/context-commands.tsx index b3543a982..d7ae2544b 100644 --- a/packages/views/search/commands/context-commands.tsx +++ b/packages/views/search/commands/context-commands.tsx @@ -16,7 +16,7 @@ import { Play, SquarePen, UserPlus, -} from "lucide-react"; +} from "@multica/ui/icons"; import { isAgentRuntimeBound } from "@multica/core/agents"; import { useAuthStore } from "@multica/core/auth"; import type { CommandBarContext } from "@multica/core/command-bar"; diff --git a/packages/views/search/commands/global-commands.tsx b/packages/views/search/commands/global-commands.tsx index 0054f4a35..474727d4e 100644 --- a/packages/views/search/commands/global-commands.tsx +++ b/packages/views/search/commands/global-commands.tsx @@ -11,7 +11,7 @@ import { Palette, SquarePen, Zap, -} from "lucide-react"; +} from "@multica/ui/icons"; import { useChatStore } from "@multica/core/chat"; import type { CommandBarContext } from "@multica/core/command-bar"; import { useArchiveAllReadInbox, useMarkAllInboxRead } from "@multica/core/inbox/mutations"; diff --git a/packages/views/search/commands/issue-commands.tsx b/packages/views/search/commands/issue-commands.tsx index b42c55f28..c7441eb58 100644 --- a/packages/views/search/commands/issue-commands.tsx +++ b/packages/views/search/commands/issue-commands.tsx @@ -24,7 +24,7 @@ import { Trash2, UserPlus, Zap, -} from "lucide-react"; +} from "@multica/ui/icons"; import { dispatchReasonCode } from "@multica/core/api"; import { useAuthStore } from "@multica/core/auth"; import { useWorkspaceId } from "@multica/core/hooks"; diff --git a/packages/views/search/delegate/delegate-group.tsx b/packages/views/search/delegate/delegate-group.tsx index 37aacff5e..b68d8e4b8 100644 --- a/packages/views/search/delegate/delegate-group.tsx +++ b/packages/views/search/delegate/delegate-group.tsx @@ -1,6 +1,6 @@ "use client"; -import { FolderOpen, Network, Sparkles, Users } from "lucide-react"; +import { FolderOpen, Network, Sparkles, Users } from "@multica/ui/icons"; import { Command as CommandPrimitive } from "cmdk"; import { createShortcutChord } from "@multica/core/shortcuts"; import { cn } from "@multica/ui/lib/utils"; diff --git a/packages/views/search/pages/issue-pages.tsx b/packages/views/search/pages/issue-pages.tsx index f4bc7c5d7..d44e155a9 100644 --- a/packages/views/search/pages/issue-pages.tsx +++ b/packages/views/search/pages/issue-pages.tsx @@ -3,7 +3,7 @@ import { useMemo } from "react"; import { useQuery } from "@tanstack/react-query"; import { toast } from "sonner"; -import { CalendarClock, CalendarX, FolderMinus, Lock, Network, UserMinus, Zap } from "lucide-react"; +import { CalendarClock, CalendarX, FolderMinus, Lock, Network, UserMinus, Zap } from "@multica/ui/icons"; import { Command as CommandPrimitive } from "cmdk"; import { dispatchReasonCode } from "@multica/core/api"; import { useWorkspaceId } from "@multica/core/hooks"; diff --git a/packages/views/search/pages/other-pages.tsx b/packages/views/search/pages/other-pages.tsx index 37a7b324a..50be5dc24 100644 --- a/packages/views/search/pages/other-pages.tsx +++ b/packages/views/search/pages/other-pages.tsx @@ -2,7 +2,7 @@ import { useQuery, useQueryClient } from "@tanstack/react-query"; import { toast } from "sonner"; -import { FolderMinus, Monitor, Moon, SquarePen, Sun } from "lucide-react"; +import { FolderMinus, Monitor, Moon, SquarePen, Sun } from "@multica/ui/icons"; import { Command as CommandPrimitive } from "cmdk"; import { useWorkspaceId } from "@multica/core/hooks"; import { useIssueStatuses } from "@multica/core/issue-statuses/hooks"; diff --git a/packages/views/search/result-rows.tsx b/packages/views/search/result-rows.tsx index 58c34d58b..1b23010fd 100644 --- a/packages/views/search/result-rows.tsx +++ b/packages/views/search/result-rows.tsx @@ -1,7 +1,7 @@ "use client"; import type { ReactNode } from "react"; -import { FileText, MessageSquare } from "lucide-react"; +import { FileText, MessageSquare } from "@multica/ui/icons"; import { Command as CommandPrimitive } from "cmdk"; import { useWorkspaceId } from "@multica/core/hooks"; import { issueStatusCategory } from "@multica/core/issues"; diff --git a/packages/views/search/root-view.tsx b/packages/views/search/root-view.tsx index 061f55405..1e4a60479 100644 --- a/packages/views/search/root-view.tsx +++ b/packages/views/search/root-view.tsx @@ -1,7 +1,7 @@ "use client"; import type { ReactNode } from "react"; -import { Clock, Loader2, MessageSquare, Sparkles, SquarePen, UserPlus, Zap, type LucideIcon } from "lucide-react"; +import { Clock, Loader2, MessageSquare, Sparkles, SquarePen, UserPlus, Zap, type IconComponent } from "@multica/ui/icons"; import { Command as CommandPrimitive } from "cmdk"; import { useQuery } from "@tanstack/react-query"; import { inboxUnreadSummaryOptions, unreadWorkspaceIds } from "@multica/core/inbox/queries"; @@ -434,7 +434,7 @@ function BestMatchGroups({ const p = useWorkspacePaths(); let row: ReactNode; - const actions: { id: string; label: string; icon: LucideIcon; run?: () => void }[] = []; + const actions: { id: string; label: string; icon: IconComponent; run?: () => void }[] = []; const subject = target ? target.kind === "single" ? target.issue.identifier diff --git a/packages/views/search/rows.tsx b/packages/views/search/rows.tsx index 65aeaecd8..133d0e11e 100644 --- a/packages/views/search/rows.tsx +++ b/packages/views/search/rows.tsx @@ -1,7 +1,7 @@ "use client"; import type { ReactNode } from "react"; -import { Check } from "lucide-react"; +import { Check } from "@multica/ui/icons"; import { Command as CommandPrimitive } from "cmdk"; import { cn } from "@multica/ui/lib/utils"; import { ShortcutKeycaps } from "../common/shortcut-keycaps"; diff --git a/packages/views/search/search-command.tsx b/packages/views/search/search-command.tsx index 947986af3..01e2d2c10 100644 --- a/packages/views/search/search-command.tsx +++ b/packages/views/search/search-command.tsx @@ -1,7 +1,7 @@ "use client"; import { Fragment, useCallback, useEffect, useMemo, useRef, useState } from "react"; -import { ChevronRight, SearchIcon, Sparkles } from "lucide-react"; +import { ChevronRight, SearchIcon, Sparkles } from "@multica/ui/icons"; import { Command as CommandPrimitive } from "cmdk"; import { selectCommandBarContexts, useCommandBarContextStore } from "@multica/core/command-bar"; import { createShortcutChord } from "@multica/core/shortcuts"; diff --git a/packages/views/search/search-trigger.tsx b/packages/views/search/search-trigger.tsx index 83b1bacd0..87fe87018 100644 --- a/packages/views/search/search-trigger.tsx +++ b/packages/views/search/search-trigger.tsx @@ -1,6 +1,6 @@ "use client"; -import { Search } from "lucide-react"; +import { Search } from "@multica/ui/icons"; import { SidebarMenuButton } from "@multica/ui/components/ui/sidebar"; import { useShortcut, diff --git a/packages/views/settings/components/billing-tab.tsx b/packages/views/settings/components/billing-tab.tsx index d1e5dcff8..3a67492bd 100644 --- a/packages/views/settings/components/billing-tab.tsx +++ b/packages/views/settings/components/billing-tab.tsx @@ -11,7 +11,7 @@ import { Loader2, Plus, RefreshCw, -} from "lucide-react"; +} from "@multica/ui/icons"; import { ApiError, errorCode } from "@multica/core/api"; import { autopilotQuotaUsageOptions } from "@multica/core/autopilots"; import { diff --git a/packages/views/settings/components/channels-tab.tsx b/packages/views/settings/components/channels-tab.tsx index 560860cd0..f717490cd 100644 --- a/packages/views/settings/components/channels-tab.tsx +++ b/packages/views/settings/components/channels-tab.tsx @@ -1,7 +1,7 @@ "use client"; import type { ReactNode } from "react"; -import { ChevronRight } from "lucide-react"; +import { ChevronRight } from "@multica/ui/icons"; import { useQuery } from "@tanstack/react-query"; import { useWorkspaceId } from "@multica/core/hooks"; import { useCurrentMember } from "@multica/core/permissions"; diff --git a/packages/views/settings/components/code-tab.tsx b/packages/views/settings/components/code-tab.tsx index 721337bcc..2c26038bd 100644 --- a/packages/views/settings/components/code-tab.tsx +++ b/packages/views/settings/components/code-tab.tsx @@ -3,7 +3,7 @@ import { useState } from "react"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { toast } from "sonner"; -import { MoreHorizontal, Pause, Play, Unplug } from "lucide-react"; +import { MoreHorizontal, Pause, Play, Unplug } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { IconButton } from "@multica/ui/components/common/icon-button"; import { Switch } from "@multica/ui/components/ui/switch"; diff --git a/packages/views/settings/components/code-vcs.tsx b/packages/views/settings/components/code-vcs.tsx index 2b290ed8e..bfac2efd6 100644 --- a/packages/views/settings/components/code-vcs.tsx +++ b/packages/views/settings/components/code-vcs.tsx @@ -3,7 +3,7 @@ import { useState } from "react"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { toast } from "sonner"; -import { Copy, FolderGit2, GitBranch, MoreHorizontal, RefreshCw, Unplug } from "lucide-react"; +import { Copy, FolderGit2, GitBranch, MoreHorizontal, RefreshCw, Unplug } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { IconButton } from "@multica/ui/components/common/icon-button"; import { Input } from "@multica/ui/components/ui/input"; diff --git a/packages/views/settings/components/composio-tab.tsx b/packages/views/settings/components/composio-tab.tsx index 871b11160..f6f598ac6 100644 --- a/packages/views/settings/components/composio-tab.tsx +++ b/packages/views/settings/components/composio-tab.tsx @@ -3,7 +3,7 @@ import { useEffect, useMemo, useRef, useState } from "react"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { toast } from "sonner"; -import { AlertTriangle, Check, Loader2, Plug, RefreshCw, Trash2 } from "lucide-react"; +import { AlertTriangle, Check, Loader2, Plug, RefreshCw, Trash2 } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { Card, CardContent } from "@multica/ui/components/ui/card"; import { Input } from "@multica/ui/components/ui/input"; diff --git a/packages/views/settings/components/dingtalk-tab.tsx b/packages/views/settings/components/dingtalk-tab.tsx index 23eab77a1..5fb565b9d 100644 --- a/packages/views/settings/components/dingtalk-tab.tsx +++ b/packages/views/settings/components/dingtalk-tab.tsx @@ -3,7 +3,7 @@ import { useState } from "react"; import { useInfiniteQuery, useQuery, useQueryClient } from "@tanstack/react-query"; import { toast } from "sonner"; -import { ChevronDown, ChevronRight, ExternalLink, Info, Trash2 } from "lucide-react"; +import { ChevronDown, ChevronRight, ExternalLink, Info, Trash2 } from "@multica/ui/icons"; import { cn } from "@multica/ui/lib/utils"; import { Button } from "@multica/ui/components/ui/button"; import { Card, CardContent } from "@multica/ui/components/ui/card"; diff --git a/packages/views/settings/components/issue-statuses-tab.test.tsx b/packages/views/settings/components/issue-statuses-tab.test.tsx index 00bd40597..4c57f0377 100644 --- a/packages/views/settings/components/issue-statuses-tab.test.tsx +++ b/packages/views/settings/components/issue-statuses-tab.test.tsx @@ -318,10 +318,10 @@ describe("IssueStatusesTab", () => { }).querySelector("svg")).not.toBeNull(); const category = within(dialog).getByRole("combobox"); // The chevron is a selector affordance, not a status glyph. - expect(category.querySelector("svg:not(.lucide-chevron-down)")).toBeNull(); + expect(category.querySelector("svg:not(.icon-chevron-down)")).toBeNull(); fireEvent.click(category); for (const option of await screen.findAllByRole("option")) { - expect(option.querySelector("svg:not(.lucide-check)")).toBeNull(); + expect(option.querySelector("svg:not(.icon-check)")).toBeNull(); } }); diff --git a/packages/views/settings/components/issue-statuses-tab.tsx b/packages/views/settings/components/issue-statuses-tab.tsx index 5bef50f53..c95fa2268 100644 --- a/packages/views/settings/components/issue-statuses-tab.tsx +++ b/packages/views/settings/components/issue-statuses-tab.tsx @@ -13,7 +13,7 @@ import { Pencil, Plus, Zap, -} from "lucide-react"; +} from "@multica/ui/icons"; import { toast } from "sonner"; import { DndContext, diff --git a/packages/views/settings/components/keyboard-shortcuts-tab.tsx b/packages/views/settings/components/keyboard-shortcuts-tab.tsx index 5ea156996..731320191 100644 --- a/packages/views/settings/components/keyboard-shortcuts-tab.tsx +++ b/packages/views/settings/components/keyboard-shortcuts-tab.tsx @@ -1,7 +1,7 @@ "use client"; import { useMemo, useState } from "react"; -import { Keyboard, RotateCcw, Search, X } from "lucide-react"; +import { Keyboard, RotateCcw, Search, X } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { IconButton } from "@multica/ui/components/common/icon-button"; import { Input } from "@multica/ui/components/ui/input"; diff --git a/packages/views/settings/components/lark-tab.tsx b/packages/views/settings/components/lark-tab.tsx index b7f0e523e..db77b6888 100644 --- a/packages/views/settings/components/lark-tab.tsx +++ b/packages/views/settings/components/lark-tab.tsx @@ -3,7 +3,7 @@ import { useEffect, useRef, useState } from "react"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { toast } from "sonner"; -import { ChevronRight, ExternalLink, RefreshCw, Trash2 } from "lucide-react"; +import { ChevronRight, ExternalLink, RefreshCw, Trash2 } from "@multica/ui/icons"; // Named import, NOT default: react-qr-code is CJS, and electron-vite's // dep-optimizer default-import interop handed back the module namespace // object instead of the component, throwing "Element type is invalid … diff --git a/packages/views/settings/components/mcp-tab.tsx b/packages/views/settings/components/mcp-tab.tsx index 8ffa100a0..d23439224 100644 --- a/packages/views/settings/components/mcp-tab.tsx +++ b/packages/views/settings/components/mcp-tab.tsx @@ -1,7 +1,7 @@ "use client"; import { useMemo, useState } from "react"; -import { ArrowRight, Blocks, Loader2, Plug, Plus, Server } from "lucide-react"; +import { ArrowRight, Blocks, Loader2, Plug, Plus, Server } from "@multica/ui/icons"; import { useQuery } from "@tanstack/react-query"; import { toast } from "sonner"; import { diff --git a/packages/views/settings/components/members-tab.tsx b/packages/views/settings/components/members-tab.tsx index e6d330834..378d4393d 100644 --- a/packages/views/settings/components/members-tab.tsx +++ b/packages/views/settings/components/members-tab.tsx @@ -15,7 +15,7 @@ import { User, UserMinus, X, -} from "lucide-react"; +} from "@multica/ui/icons"; import { ActorAvatar } from "../../common/actor-avatar"; import { AppLink, useOptionalNavigation } from "../../navigation"; import type { diff --git a/packages/views/settings/components/plugins-tab.tsx b/packages/views/settings/components/plugins-tab.tsx index 2bc44c67c..ee750fcee 100644 --- a/packages/views/settings/components/plugins-tab.tsx +++ b/packages/views/settings/components/plugins-tab.tsx @@ -2,7 +2,7 @@ import { useMemo, useRef, useState } from "react"; import { useQuery } from "@tanstack/react-query"; -import { AlertCircle, CalendarClock, Loader2, Trash2, Upload } from "lucide-react"; +import { AlertCircle, CalendarClock, Loader2, Trash2, Upload } from "@multica/ui/icons"; import { toast } from "sonner"; import { useCurrentMember } from "@multica/core/permissions"; import { diff --git a/packages/views/settings/components/pr-merge-status-row.tsx b/packages/views/settings/components/pr-merge-status-row.tsx index f488f0248..b44076efc 100644 --- a/packages/views/settings/components/pr-merge-status-row.tsx +++ b/packages/views/settings/components/pr-merge-status-row.tsx @@ -3,7 +3,7 @@ import { useState } from "react"; import { useQueryClient } from "@tanstack/react-query"; import { toast } from "sonner"; -import { CircleOff } from "lucide-react"; +import { CircleOff } from "@multica/ui/icons"; import { api } from "@multica/core/api"; import { derivePRMergeStatus, PR_MERGE_STATUS_NONE } from "@multica/core/github"; import { useWorkspaceId } from "@multica/core/hooks"; diff --git a/packages/views/settings/components/preferences-tab.tsx b/packages/views/settings/components/preferences-tab.tsx index dede6023a..186fe8371 100644 --- a/packages/views/settings/components/preferences-tab.tsx +++ b/packages/views/settings/components/preferences-tab.tsx @@ -1,7 +1,7 @@ "use client"; import { useMemo, useState } from "react"; -import { ChevronsUpDown } from "lucide-react"; +import { ChevronsUpDown } from "@multica/ui/icons"; import { toast } from "sonner"; import { Select, diff --git a/packages/views/settings/components/properties-tab.tsx b/packages/views/settings/components/properties-tab.tsx index d3365d085..84ae61028 100644 --- a/packages/views/settings/components/properties-tab.tsx +++ b/packages/views/settings/components/properties-tab.tsx @@ -12,7 +12,7 @@ import { Search, SlidersHorizontal, X, -} from "lucide-react"; +} from "@multica/ui/icons"; import { toast } from "sonner"; import { useAuthStore } from "@multica/core/auth"; import { useWorkspaceId } from "@multica/core/hooks"; diff --git a/packages/views/settings/components/quick-actions-tab.tsx b/packages/views/settings/components/quick-actions-tab.tsx index 5a540e710..65fe7d702 100644 --- a/packages/views/settings/components/quick-actions-tab.tsx +++ b/packages/views/settings/components/quick-actions-tab.tsx @@ -14,7 +14,7 @@ import { Trash2, TriangleAlert, Zap, -} from "lucide-react"; +} from "@multica/ui/icons"; import { toast } from "sonner"; import { useWorkspaceId } from "@multica/core/hooks"; import { diff --git a/packages/views/settings/components/repositories-section.tsx b/packages/views/settings/components/repositories-section.tsx index d1926b1d3..fc81db4cc 100644 --- a/packages/views/settings/components/repositories-section.tsx +++ b/packages/views/settings/components/repositories-section.tsx @@ -10,7 +10,7 @@ import { Plus, Search, Trash2, -} from "lucide-react"; +} from "@multica/ui/icons"; import { Input } from "@multica/ui/components/ui/input"; import { Label } from "@multica/ui/components/ui/label"; import { Button } from "@multica/ui/components/ui/button"; diff --git a/packages/views/settings/components/settings-layout.tsx b/packages/views/settings/components/settings-layout.tsx index 2f3f81c77..e8a1161c1 100644 --- a/packages/views/settings/components/settings-layout.tsx +++ b/packages/views/settings/components/settings-layout.tsx @@ -9,7 +9,7 @@ import { Laptop, Loader2, UserRound, -} from "lucide-react"; +} from "@multica/ui/icons"; import { useQuery } from "@tanstack/react-query"; import { Card, CardContent } from "@multica/ui/components/ui/card"; import { cn } from "@multica/ui/lib/utils"; diff --git a/packages/views/settings/components/settings-page.tsx b/packages/views/settings/components/settings-page.tsx index a5e7ca9df..808b2b7ea 100644 --- a/packages/views/settings/components/settings-page.tsx +++ b/packages/views/settings/components/settings-page.tsx @@ -24,7 +24,7 @@ import { X, Workflow, Zap, -} from "lucide-react"; +} from "@multica/ui/icons"; import { useAuthStore } from "@multica/core/auth"; import { useCurrentWorkspace } from "@multica/core/paths"; import { useFeatureEnabled } from "@multica/core/config"; diff --git a/packages/views/settings/components/slack-tab.tsx b/packages/views/settings/components/slack-tab.tsx index 530cf9b40..b49e18408 100644 --- a/packages/views/settings/components/slack-tab.tsx +++ b/packages/views/settings/components/slack-tab.tsx @@ -3,7 +3,7 @@ import { useState } from "react"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { toast } from "sonner"; -import { ChevronRight, ExternalLink, Trash2 } from "lucide-react"; +import { ChevronRight, ExternalLink, Trash2 } from "@multica/ui/icons"; import { SlackMark } from "./slack-mark"; import { cn } from "@multica/ui/lib/utils"; import { Button } from "@multica/ui/components/ui/button"; diff --git a/packages/views/settings/components/telegram-tab.tsx b/packages/views/settings/components/telegram-tab.tsx index cd047e60c..b401cdab8 100644 --- a/packages/views/settings/components/telegram-tab.tsx +++ b/packages/views/settings/components/telegram-tab.tsx @@ -3,7 +3,7 @@ import { useState } from "react"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { toast } from "sonner"; -import { ChevronRight, ExternalLink, Trash2 } from "lucide-react"; +import { ChevronRight, ExternalLink, Trash2 } from "@multica/ui/icons"; import { TelegramMark } from "./telegram-mark"; import { cn } from "@multica/ui/lib/utils"; import { Button } from "@multica/ui/components/ui/button"; diff --git a/packages/views/settings/components/tokens-tab.tsx b/packages/views/settings/components/tokens-tab.tsx index 840f6fabc..986c6c846 100644 --- a/packages/views/settings/components/tokens-tab.tsx +++ b/packages/views/settings/components/tokens-tab.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useState, useCallback } from "react"; -import { Trash2, Copy, Check, Info } from "lucide-react"; +import { Trash2, Copy, Check, Info } from "@multica/ui/icons"; import { Tooltip, TooltipTrigger, TooltipContent } from "@multica/ui/components/ui/tooltip"; import type { PersonalAccessToken } from "@multica/core/types"; import { Alert, AlertDescription } from "@multica/ui/components/ui/alert"; diff --git a/packages/views/settings/components/wecom-tab.tsx b/packages/views/settings/components/wecom-tab.tsx index 7eaa51fa7..6b050147e 100644 --- a/packages/views/settings/components/wecom-tab.tsx +++ b/packages/views/settings/components/wecom-tab.tsx @@ -3,7 +3,7 @@ import { useState } from "react"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { toast } from "sonner"; -import { ChevronRight, Trash2 } from "lucide-react"; +import { ChevronRight, Trash2 } from "@multica/ui/icons"; import { WecomMark } from "./wecom-mark"; import { cn } from "@multica/ui/lib/utils"; import { Button } from "@multica/ui/components/ui/button"; diff --git a/packages/views/settings/components/workspace-tab.tsx b/packages/views/settings/components/workspace-tab.tsx index 4824c7fdf..f6265a213 100644 --- a/packages/views/settings/components/workspace-tab.tsx +++ b/packages/views/settings/components/workspace-tab.tsx @@ -1,7 +1,7 @@ "use client"; import { useCallback, useEffect, useMemo, useState } from "react"; -import { Copy } from "lucide-react"; +import { Copy } from "@multica/ui/icons"; import { Input } from "@multica/ui/components/ui/input"; import { Textarea } from "@multica/ui/components/ui/textarea"; import { Button } from "@multica/ui/components/ui/button"; diff --git a/packages/views/skills/components/create-skill-dialog.tsx b/packages/views/skills/components/create-skill-dialog.tsx index b31195069..2866905b5 100644 --- a/packages/views/skills/components/create-skill-dialog.tsx +++ b/packages/views/skills/components/create-skill-dialog.tsx @@ -13,7 +13,7 @@ import { Pencil, Plus, X as XIcon, -} from "lucide-react"; +} from "@multica/ui/icons"; import { toast } from "sonner"; import { useQueryClient } from "@tanstack/react-query"; import { api } from "@multica/core/api"; diff --git a/packages/views/skills/components/file-tree.tsx b/packages/views/skills/components/file-tree.tsx index 647485fba..1e29bd2ed 100644 --- a/packages/views/skills/components/file-tree.tsx +++ b/packages/views/skills/components/file-tree.tsx @@ -12,7 +12,7 @@ import { Pencil, PencilLine, Trash2, -} from "lucide-react"; +} from "@multica/ui/icons"; import { Input } from "@multica/ui/components/ui/input"; import { DropdownMenu, diff --git a/packages/views/skills/components/refresh-skill-dialog.tsx b/packages/views/skills/components/refresh-skill-dialog.tsx index 0d5590a80..e033a338c 100644 --- a/packages/views/skills/components/refresh-skill-dialog.tsx +++ b/packages/views/skills/components/refresh-skill-dialog.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { Loader2, RotateCw } from "lucide-react"; +import { Loader2, RotateCw } from "@multica/ui/icons"; import { useQueryClient } from "@tanstack/react-query"; import { toast } from "sonner"; import type { Skill, SkillSummary } from "@multica/core/types"; diff --git a/packages/views/skills/components/runtime-local-skill-import-panel.tsx b/packages/views/skills/components/runtime-local-skill-import-panel.tsx index 00a492c76..c18eda705 100644 --- a/packages/views/skills/components/runtime-local-skill-import-panel.tsx +++ b/packages/views/skills/components/runtime-local-skill-import-panel.tsx @@ -14,7 +14,7 @@ import { Search, SkipForward, XCircle, -} from "lucide-react"; +} from "@multica/ui/icons"; import type { RuntimeLocalSkillImportConflict, RuntimeLocalSkillSummary, diff --git a/packages/views/skills/components/skill-detail-page.tsx b/packages/views/skills/components/skill-detail-page.tsx index 635f6b581..87f75f347 100644 --- a/packages/views/skills/components/skill-detail-page.tsx +++ b/packages/views/skills/components/skill-detail-page.tsx @@ -17,7 +17,7 @@ import { Trash2, UserPlus, Users, -} from "lucide-react"; +} from "@multica/ui/icons"; import { SkillIcon } from "../lib/skill-icon"; import type { Agent, diff --git a/packages/views/skills/components/skill-list-actions.tsx b/packages/views/skills/components/skill-list-actions.tsx index be5ea44ab..cad592eb7 100644 --- a/packages/views/skills/components/skill-list-actions.tsx +++ b/packages/views/skills/components/skill-list-actions.tsx @@ -12,7 +12,7 @@ import { Search, Trash2, X, -} from "lucide-react"; +} from "@multica/ui/icons"; import { useQueryClient } from "@tanstack/react-query"; import { toast } from "sonner"; import type { Agent, SkillSummary } from "@multica/core/types"; diff --git a/packages/views/skills/components/skill-list-toolbar.tsx b/packages/views/skills/components/skill-list-toolbar.tsx index a48e0a194..12540fd72 100644 --- a/packages/views/skills/components/skill-list-toolbar.tsx +++ b/packages/views/skills/components/skill-list-toolbar.tsx @@ -12,7 +12,7 @@ import { Search, Tags, X, -} from "lucide-react"; +} from "@multica/ui/icons"; import { useQuery } from "@tanstack/react-query"; import { useWorkspaceId } from "@multica/core/hooks"; import { labelListOptions } from "@multica/core/labels/queries"; diff --git a/packages/views/skills/components/skills-page.tsx b/packages/views/skills/components/skills-page.tsx index 620ef70a9..91d2f239b 100644 --- a/packages/views/skills/components/skills-page.tsx +++ b/packages/views/skills/components/skills-page.tsx @@ -9,7 +9,7 @@ import { Lock, Pencil, Plus, -} from "lucide-react"; +} from "@multica/ui/icons"; import { SkillIcon } from "../lib/skill-icon"; import type { Agent, diff --git a/packages/views/skills/lib/skill-icon.ts b/packages/views/skills/lib/skill-icon.ts index 7b15c1bc2..e1581add0 100644 --- a/packages/views/skills/lib/skill-icon.ts +++ b/packages/views/skills/lib/skill-icon.ts @@ -1,4 +1,4 @@ -import type { LucideIcon } from "lucide-react"; +import type { IconComponent } from "@multica/ui/icons"; import { WORKSPACE_PAGES } from "@multica/core/paths"; import { ROUTE_ICON_COMPONENTS } from "../../layout/route-icon-components"; @@ -14,5 +14,5 @@ import { ROUTE_ICON_COMPONENTS } from "../../layout/route-icon-components"; * This is for the skill *entity*. A file inside a skill is not a skill; those * keep the file-type icons in `file-tree.tsx`. */ -export const SkillIcon: LucideIcon = +export const SkillIcon: IconComponent = ROUTE_ICON_COMPONENTS[WORKSPACE_PAGES.skills.icon]; diff --git a/packages/views/squads/components/squad-detail-page.tsx b/packages/views/squads/components/squad-detail-page.tsx index ff35b4511..790cfae86 100644 --- a/packages/views/squads/components/squad-detail-page.tsx +++ b/packages/views/squads/components/squad-detail-page.tsx @@ -15,7 +15,7 @@ import { useNavigation } from "../../navigation"; import { AppLink } from "../../navigation"; import { BreadcrumbHeader } from "../../layout/breadcrumb-header"; import { PageHeader } from "../../layout/page-header"; -import { Users, Plus, Trash2, ArrowUpRight, Crown, Loader2, Pencil, FileText, Save } from "lucide-react"; +import { Users, Plus, Trash2, ArrowUpRight, Crown, Loader2, Pencil, FileText, Save } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { Input } from "@multica/ui/components/ui/input"; import { Label } from "@multica/ui/components/ui/label"; @@ -57,7 +57,7 @@ import { PickerSection, PickerEmpty, } from "../../issues/components/pickers/property-picker"; -import { ChevronDown, UserPlus } from "lucide-react"; +import { ChevronDown, UserPlus } from "@multica/ui/icons"; import { toast } from "sonner"; import type { Squad, SquadMember, SquadMemberStatus, SquadMemberStatusValue, Agent, MemberWithUser } from "@multica/core/types"; import { useT } from "../../i18n"; diff --git a/packages/views/squads/components/squads-page.tsx b/packages/views/squads/components/squads-page.tsx index b1918aa14..b03215bdd 100644 --- a/packages/views/squads/components/squads-page.tsx +++ b/packages/views/squads/components/squads-page.tsx @@ -13,7 +13,7 @@ import { Trash2, Users, X, -} from "lucide-react"; +} from "@multica/ui/icons"; import { useQuery, useQueryClient, useMutation } from "@tanstack/react-query"; import { toast } from "sonner"; import { useCurrentWorkspace, useWorkspacePaths } from "@multica/core/paths"; diff --git a/packages/views/workflows/column-handoff.tsx b/packages/views/workflows/column-handoff.tsx index f4cdc7ec6..6e2db03d9 100644 --- a/packages/views/workflows/column-handoff.tsx +++ b/packages/views/workflows/column-handoff.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { Plus, Workflow } from "lucide-react"; +import { Plus, Workflow } from "@multica/ui/icons"; import { useWorkspaceId } from "@multica/core/hooks"; import { statusAcceptsHandoff, workflowStep } from "@multica/core/issue-workflows"; import { useActorName } from "@multica/core/workspace/hooks"; diff --git a/packages/views/workflows/handoff-confirm-dialog.tsx b/packages/views/workflows/handoff-confirm-dialog.tsx index 55f62846d..3d0764dab 100644 --- a/packages/views/workflows/handoff-confirm-dialog.tsx +++ b/packages/views/workflows/handoff-confirm-dialog.tsx @@ -2,7 +2,7 @@ import { Fragment, useEffect, useState, type ReactNode } from "react"; import { useQuery } from "@tanstack/react-query"; -import { ArrowRight, ChevronDown, ChevronRight, TriangleAlert } from "lucide-react"; +import { ArrowRight, ChevronDown, ChevronRight, TriangleAlert } from "@multica/ui/icons"; import { useWorkspaceId } from "@multica/core/hooks"; import { useIssueStatuses } from "@multica/core/issue-statuses/hooks"; import { workflowHandoffPreviewOptions } from "@multica/core/issue-workflows"; diff --git a/packages/views/workflows/handoff-form.tsx b/packages/views/workflows/handoff-form.tsx index 9f6598860..336540dbf 100644 --- a/packages/views/workflows/handoff-form.tsx +++ b/packages/views/workflows/handoff-form.tsx @@ -27,7 +27,7 @@ import { import { Spinner } from "@multica/ui/components/ui/spinner"; import { Textarea } from "@multica/ui/components/ui/textarea"; import { cn } from "@multica/ui/lib/utils"; -import { ChevronDown } from "lucide-react"; +import { ChevronDown } from "@multica/ui/icons"; import { ActorAvatar } from "../common/actor-avatar"; import { PickerEmpty, PickerItem, PickerSection, PropertyPicker } from "../issues/components/pickers/property-picker"; import { StatusIcon } from "../issues/components/status-icon"; diff --git a/packages/views/workflows/issue-flow-card.tsx b/packages/views/workflows/issue-flow-card.tsx index 62f923fc7..5280720be 100644 --- a/packages/views/workflows/issue-flow-card.tsx +++ b/packages/views/workflows/issue-flow-card.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { Settings, Workflow } from "lucide-react"; +import { Settings, Workflow } from "@multica/ui/icons"; import { useWorkspaceId } from "@multica/core/hooks"; import { useIssueStatuses } from "@multica/core/issue-statuses/hooks"; import { useProjectWithWorkflow } from "@multica/core/issue-workflows"; diff --git a/packages/views/workflows/project-workflow-menu.tsx b/packages/views/workflows/project-workflow-menu.tsx index 6259f2de0..cae0fb282 100644 --- a/packages/views/workflows/project-workflow-menu.tsx +++ b/packages/views/workflows/project-workflow-menu.tsx @@ -2,7 +2,7 @@ import { useState } from "react"; import { useQuery } from "@tanstack/react-query"; -import { ChevronDown, ChevronRight, ListTree, Settings, Workflow } from "lucide-react"; +import { ChevronDown, ChevronRight, ListTree, Settings, Workflow } from "@multica/ui/icons"; import { useWorkspaceId } from "@multica/core/hooks"; import { useIssueStatuses } from "@multica/core/issue-statuses/hooks"; import { diff --git a/packages/views/workflows/project-workflow-row.tsx b/packages/views/workflows/project-workflow-row.tsx index 8b533d0af..f72d0cba1 100644 --- a/packages/views/workflows/project-workflow-row.tsx +++ b/packages/views/workflows/project-workflow-row.tsx @@ -2,7 +2,7 @@ import { useState, type ReactNode } from "react"; import { useQuery } from "@tanstack/react-query"; -import { Check, ChevronDown, Settings, Workflow } from "lucide-react"; +import { Check, ChevronDown, Settings, Workflow } from "@multica/ui/icons"; import { toast } from "sonner"; import { api, clientErrorMessage } from "@multica/core/api"; import { useWorkspaceId } from "@multica/core/hooks"; diff --git a/packages/views/workflows/timeline-handoff.tsx b/packages/views/workflows/timeline-handoff.tsx index e4d6be5ec..1af8998de 100644 --- a/packages/views/workflows/timeline-handoff.tsx +++ b/packages/views/workflows/timeline-handoff.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { CornerDownRight } from "lucide-react"; +import { CornerDownRight } from "@multica/ui/icons"; import { useActorName } from "@multica/core/workspace/hooks"; import { ActorAvatar } from "../common/actor-avatar"; import { useT } from "../i18n"; diff --git a/packages/views/workflows/workflow-editor-page.tsx b/packages/views/workflows/workflow-editor-page.tsx index b686582f5..c1803da63 100644 --- a/packages/views/workflows/workflow-editor-page.tsx +++ b/packages/views/workflows/workflow-editor-page.tsx @@ -30,7 +30,7 @@ import { Plus, Trash2, UserRound, -} from "lucide-react"; +} from "@multica/ui/icons"; import { toast } from "sonner"; import { ApiError, clientErrorMessage } from "@multica/core/api"; import { useWorkspaceId } from "@multica/core/hooks"; diff --git a/packages/views/workflows/workflow-mapping-dialog.tsx b/packages/views/workflows/workflow-mapping-dialog.tsx index ba6f2eae2..acee3024b 100644 --- a/packages/views/workflows/workflow-mapping-dialog.tsx +++ b/packages/views/workflows/workflow-mapping-dialog.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useState } from "react"; -import { ArrowRight, Check } from "lucide-react"; +import { ArrowRight, Check } from "@multica/ui/icons"; import { Button } from "@multica/ui/components/ui/button"; import { Dialog, diff --git a/packages/views/workflows/workflow-pill.tsx b/packages/views/workflows/workflow-pill.tsx index 96efad295..0dfda14f0 100644 --- a/packages/views/workflows/workflow-pill.tsx +++ b/packages/views/workflows/workflow-pill.tsx @@ -1,6 +1,6 @@ "use client"; -import { Check, Workflow } from "lucide-react"; +import { Check, Workflow } from "@multica/ui/icons"; import { useWorkspaceId } from "@multica/core/hooks"; import { useIssueWorkflows } from "@multica/core/issue-workflows"; import { diff --git a/packages/views/workflows/workflows-tab.tsx b/packages/views/workflows/workflows-tab.tsx index 3b6e74bc8..7e033505a 100644 --- a/packages/views/workflows/workflows-tab.tsx +++ b/packages/views/workflows/workflows-tab.tsx @@ -2,7 +2,7 @@ import { Fragment, useMemo } from "react"; import { useQuery } from "@tanstack/react-query"; -import { ChevronDown, ChevronRight, LayoutTemplate, Plus } from "lucide-react"; +import { ChevronDown, ChevronRight, LayoutTemplate, Plus } from "@multica/ui/icons"; import { useAuthStore } from "@multica/core/auth"; import { useWorkspaceId } from "@multica/core/hooks"; import { useIssueStatuses } from "@multica/core/issue-statuses/hooks"; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5e800afb9..7077103a3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -57,9 +57,6 @@ catalogs: katex: specifier: ^0.16.45 version: 0.16.45 - lucide-react: - specifier: ^1.0.1 - version: 1.0.1 mermaid: specifier: ^11.14.0 version: 11.14.0 @@ -203,9 +200,6 @@ importers: fix-path: specifier: ^5.0.0 version: 5.0.0 - lucide-react: - specifier: 'catalog:' - version: 1.0.1(react@19.2.3) motion: specifier: ^12.38.0 version: 12.38.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -293,16 +287,13 @@ importers: version: link:../../packages/ui fumadocs-core: specifier: ^16.17.8 - version: 16.17.8(@mdx-js/mdx@3.1.1)(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.14)(lucide-react@1.0.1(react@19.2.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(zod@4.6.7) + version: 16.17.8(@mdx-js/mdx@3.1.1)(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.14)(lucide-react@1.61.0(@types/react@19.2.14)(react@19.2.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(zod@4.6.7) fumadocs-mdx: specifier: ^15.4.10 - version: 15.4.10(@types/mdast@4.0.4)(@types/mdx@2.0.13)(@types/react@19.2.14)(fumadocs-core@16.17.8(@mdx-js/mdx@3.1.1)(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.14)(lucide-react@1.0.1(react@19.2.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(zod@4.6.7))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(vite@8.0.1(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.3)(@types/node@25.5.0)(jiti@2.7.0)(terser@5.47.1)(yaml@2.9.1)) + version: 15.4.10(@types/mdast@4.0.4)(@types/mdx@2.0.13)(@types/react@19.2.14)(fumadocs-core@16.17.8(@mdx-js/mdx@3.1.1)(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.14)(lucide-react@1.61.0(@types/react@19.2.14)(react@19.2.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(zod@4.6.7))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(vite@8.0.1(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.3)(@types/node@25.5.0)(jiti@2.7.0)(terser@5.47.1)(yaml@2.9.1)) fumadocs-ui: specifier: ^16.17.8 - version: 16.17.8(@types/mdx@2.0.13)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(fumadocs-core@16.17.8(@mdx-js/mdx@3.1.1)(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.14)(lucide-react@1.0.1(react@19.2.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(zod@4.6.7))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.2.2) - lucide-react: - specifier: 'catalog:' - version: 1.0.1(react@19.2.3) + version: 16.17.8(@types/mdx@2.0.13)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(fumadocs-core@16.17.8(@mdx-js/mdx@3.1.1)(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.14)(lucide-react@1.61.0(@types/react@19.2.14)(react@19.2.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(zod@4.6.7))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.2.2) mermaid: specifier: ^11.14.0 version: 11.14.0 @@ -578,9 +569,6 @@ importers: i18next: specifier: 'catalog:' version: 26.0.8(typescript@5.9.3) - lucide-react: - specifier: 'catalog:' - version: 1.0.1(react@19.2.3) react: specifier: 'catalog:' version: 19.2.3 @@ -659,13 +647,10 @@ importers: version: 17.4.1 fumadocs-core: specifier: ^15.5.2 - version: 15.8.5(@types/react@19.2.14)(lucide-react@1.0.1(react@19.2.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3) + version: 15.8.5(@types/react@19.2.14)(lucide-react@1.61.0(@types/react@19.2.14)(react@19.2.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3) fumadocs-mdx: specifier: ^12.0.3 - version: 12.0.3(fumadocs-core@15.8.5(@types/react@19.2.14)(lucide-react@1.0.1(react@19.2.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3) - lucide-react: - specifier: 'catalog:' - version: 1.0.1(react@19.2.3) + version: 12.0.3(fumadocs-core@15.8.5(@types/react@19.2.14)(lucide-react@1.61.0(@types/react@19.2.14)(react@19.2.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3) next: specifier: ^16.3.8 version: 16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -859,9 +844,6 @@ importers: linkify-it: specifier: ^5.0.0 version: 5.0.0 - lucide-react: - specifier: 'catalog:' - version: 1.0.1(react@19.2.3) next-themes: specifier: ^0.4.6 version: 0.4.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -1067,9 +1049,6 @@ importers: lowlight: specifier: ^3.3.0 version: 3.3.0 - lucide-react: - specifier: 'catalog:' - version: 1.0.1(react@19.2.3) mdast-util-from-markdown: specifier: ^2.0.3 version: 2.0.3 @@ -8585,11 +8564,6 @@ packages: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} - lucide-react@1.0.1: - resolution: {integrity: sha512-lih7tKEczCYOQjVEzpFuxEuNzlwf+1yhvlMlEkGWJM3va8Pugv8bYXc/pRtcjPncaP7k84X0Pt/71ufxvqEPtQ==} - peerDependencies: - react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 - lucide-react@1.61.0: resolution: {integrity: sha512-v2SQPPPNjnr+BlhL9Spuzmo5yR+hLkftfuE4E3jaxdNPgSH0hJKPcLJBP7yAta87jQNPsSERS59PJjCJ/CorBA==} peerDependencies: @@ -18581,7 +18555,7 @@ snapshots: fsevents@2.3.3: optional: true - fumadocs-core@15.8.5(@types/react@19.2.14)(lucide-react@1.0.1(react@19.2.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3): + fumadocs-core@15.8.5(@types/react@19.2.14)(lucide-react@1.61.0(@types/react@19.2.14)(react@19.2.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3): dependencies: '@formatjs/intl-localematcher': 0.6.2 '@orama/orama': 3.1.18 @@ -18603,7 +18577,7 @@ snapshots: unist-util-visit: 5.1.0 optionalDependencies: '@types/react': 19.2.14 - lucide-react: 1.0.1(react@19.2.3) + lucide-react: 1.61.0(@types/react@19.2.14)(react@19.2.3) next: 16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) react: 19.2.3 react-dom: 19.2.3(react@19.2.3) @@ -18611,7 +18585,7 @@ snapshots: transitivePeerDependencies: - supports-color - fumadocs-core@16.17.8(@mdx-js/mdx@3.1.1)(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.14)(lucide-react@1.0.1(react@19.2.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(zod@4.6.7): + fumadocs-core@16.17.8(@mdx-js/mdx@3.1.1)(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.14)(lucide-react@1.61.0(@types/react@19.2.14)(react@19.2.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(zod@4.6.7): dependencies: '@fumari/image-size': 0.1.1 estree-util-value-to-estree: 3.5.0 @@ -18638,7 +18612,7 @@ snapshots: '@types/hast': 3.0.5 '@types/mdast': 4.0.4 '@types/react': 19.2.14 - lucide-react: 1.0.1(react@19.2.3) + lucide-react: 1.61.0(@types/react@19.2.14)(react@19.2.3) next: 16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) react: 19.2.3 react-dom: 19.2.3(react@19.2.3) @@ -18647,14 +18621,14 @@ snapshots: transitivePeerDependencies: - supports-color - fumadocs-mdx@12.0.3(fumadocs-core@15.8.5(@types/react@19.2.14)(lucide-react@1.0.1(react@19.2.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3): + fumadocs-mdx@12.0.3(fumadocs-core@15.8.5(@types/react@19.2.14)(lucide-react@1.61.0(@types/react@19.2.14)(react@19.2.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3): dependencies: '@mdx-js/mdx': 3.1.1 '@standard-schema/spec': 1.1.0 chokidar: 4.0.3 esbuild: 0.25.12 estree-util-value-to-estree: 3.5.0 - fumadocs-core: 15.8.5(@types/react@19.2.14)(lucide-react@1.0.1(react@19.2.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3) + fumadocs-core: 15.8.5(@types/react@19.2.14)(lucide-react@1.61.0(@types/react@19.2.14)(react@19.2.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3) js-yaml: 4.1.1 lru-cache: 11.2.7 mdast-util-to-markdown: 2.1.2 @@ -18672,14 +18646,14 @@ snapshots: transitivePeerDependencies: - supports-color - fumadocs-mdx@15.4.10(@types/mdast@4.0.4)(@types/mdx@2.0.13)(@types/react@19.2.14)(fumadocs-core@16.17.8(@mdx-js/mdx@3.1.1)(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.14)(lucide-react@1.0.1(react@19.2.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(zod@4.6.7))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(vite@8.0.1(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.3)(@types/node@25.5.0)(jiti@2.7.0)(terser@5.47.1)(yaml@2.9.1)): + fumadocs-mdx@15.4.10(@types/mdast@4.0.4)(@types/mdx@2.0.13)(@types/react@19.2.14)(fumadocs-core@16.17.8(@mdx-js/mdx@3.1.1)(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.14)(lucide-react@1.61.0(@types/react@19.2.14)(react@19.2.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(zod@4.6.7))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(vite@8.0.1(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.3)(@types/node@25.5.0)(jiti@2.7.0)(terser@5.47.1)(yaml@2.9.1)): dependencies: '@mdx-js/mdx': 3.1.1 '@standard-schema/spec': 1.1.0 chokidar: 6.0.0 esbuild: 0.28.2 estree-util-value-to-estree: 3.5.0 - fumadocs-core: 16.17.8(@mdx-js/mdx@3.1.1)(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.14)(lucide-react@1.0.1(react@19.2.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(zod@4.6.7) + fumadocs-core: 16.17.8(@mdx-js/mdx@3.1.1)(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.14)(lucide-react@1.61.0(@types/react@19.2.14)(react@19.2.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(zod@4.6.7) github-slugger: 2.0.0 magic-string: 1.4.3 mdast-util-mdx: 3.0.0 @@ -18703,7 +18677,7 @@ snapshots: transitivePeerDependencies: - supports-color - fumadocs-ui@16.17.8(@types/mdx@2.0.13)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(fumadocs-core@16.17.8(@mdx-js/mdx@3.1.1)(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.14)(lucide-react@1.0.1(react@19.2.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(zod@4.6.7))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.2.2): + fumadocs-ui@16.17.8(@types/mdx@2.0.13)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(fumadocs-core@16.17.8(@mdx-js/mdx@3.1.1)(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.14)(lucide-react@1.61.0(@types/react@19.2.14)(react@19.2.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(zod@4.6.7))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.2.2): dependencies: '@fuma-translate/react': 1.0.2(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@fumadocs/tailwind': 0.1.4(tailwindcss@4.2.2) @@ -18719,7 +18693,7 @@ snapshots: '@radix-ui/react-tabs': 1.2.1(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) class-variance-authority: 0.7.1 cn: 0.5.0 - fumadocs-core: 16.17.8(@mdx-js/mdx@3.1.1)(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.14)(lucide-react@1.0.1(react@19.2.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(zod@4.6.7) + fumadocs-core: 16.17.8(@mdx-js/mdx@3.1.1)(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.14)(lucide-react@1.61.0(@types/react@19.2.14)(react@19.2.3))(next@16.3.8(@opentelemetry/api@1.9.1)(@playwright/test@1.58.2)(@types/node@25.5.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(zod@4.6.7) lucide-react: 1.61.0(@types/react@19.2.14)(react@19.2.3) motion: 14.6.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) next-themes: 0.4.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -19779,10 +19753,6 @@ snapshots: dependencies: yallist: 4.0.0 - lucide-react@1.0.1(react@19.2.3): - dependencies: - react: 19.2.3 - lucide-react@1.61.0(@types/react@19.2.14)(react@19.2.3): dependencies: react: 19.2.3 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index ac2b3bda9..0a9262e6f 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -22,7 +22,6 @@ catalog: i18next: ^26.0.8 jsdom: ^29.0.1 katex: ^0.16.45 - lucide-react: ^1.0.1 mermaid: ^11.14.0 postcss: ^8 posthog-js: ^1.176.1 diff --git a/server/internal/handler/property.go b/server/internal/handler/property.go index cfb29d294..8910780ca 100644 --- a/server/internal/handler/property.go +++ b/server/internal/handler/property.go @@ -54,8 +54,8 @@ const ( var validPropertyTypes = []string{"text", "number", "select", "multi_select", "date", "checkbox", "url", "actor", "multi_actor", "multi_text", "multi_url"} -// Property icons use stable catalog keys that the Web client maps to Lucide -// glyphs. Keeping this allowlist at the API boundary prevents arbitrary text +// Property icons use stable catalog keys that the Web client maps to its +// icon glyphs. Keeping this allowlist at the API boundary prevents arbitrary text // (including emoji) from leaking into every issue surface that renders icons. var validPropertyIcons = map[string]struct{}{ "circle-dot": {}, "signal-high": {}, "user-round": {}, "folder-kanban": {},