@webjsdev/ui 0.3.16 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +71 -10
- package/THIRD_PARTY_NOTICES.md +349 -0
- package/package.json +4 -2
- package/packages/registry/blocks/_shared/placeholder.svg +1 -0
- package/packages/registry/blocks/charts/chart-area-axes.ts +72 -0
- package/packages/registry/blocks/charts/chart-area-default.ts +64 -0
- package/packages/registry/blocks/charts/chart-area-gradient.ts +82 -0
- package/packages/registry/blocks/charts/chart-area-icons.ts +77 -0
- package/packages/registry/blocks/charts/chart-area-interactive.ts +204 -0
- package/packages/registry/blocks/charts/chart-area-legend.ts +72 -0
- package/packages/registry/blocks/charts/chart-area-linear.ts +64 -0
- package/packages/registry/blocks/charts/chart-area-stacked-expand.ts +77 -0
- package/packages/registry/blocks/charts/chart-area-stacked.ts +71 -0
- package/packages/registry/blocks/charts/chart-area-step.ts +68 -0
- package/packages/registry/blocks/charts/chart-bar-active.ts +93 -0
- package/packages/registry/blocks/charts/chart-bar-default.ts +60 -0
- package/packages/registry/blocks/charts/chart-bar-horizontal.ts +62 -0
- package/packages/registry/blocks/charts/chart-bar-interactive.ts +185 -0
- package/packages/registry/blocks/charts/chart-bar-label-custom.ts +78 -0
- package/packages/registry/blocks/charts/chart-bar-label.ts +66 -0
- package/packages/registry/blocks/charts/chart-bar-mixed.ts +87 -0
- package/packages/registry/blocks/charts/chart-bar-multiple.ts +67 -0
- package/packages/registry/blocks/charts/chart-bar-negative.ts +61 -0
- package/packages/registry/blocks/charts/chart-bar-stacked.ts +68 -0
- package/packages/registry/blocks/charts/chart-line-default.ts +61 -0
- package/packages/registry/blocks/charts/chart-line-dots-colors.ts +86 -0
- package/packages/registry/blocks/charts/chart-line-dots-custom.ts +75 -0
- package/packages/registry/blocks/charts/chart-line-dots.ts +65 -0
- package/packages/registry/blocks/charts/chart-line-interactive.ts +185 -0
- package/packages/registry/blocks/charts/chart-line-label-custom.ts +94 -0
- package/packages/registry/blocks/charts/chart-line-label.ts +73 -0
- package/packages/registry/blocks/charts/chart-line-linear.ts +61 -0
- package/packages/registry/blocks/charts/chart-line-multiple.ts +71 -0
- package/packages/registry/blocks/charts/chart-line-step.ts +61 -0
- package/packages/registry/blocks/charts/chart-pie-donut-active.ts +86 -0
- package/packages/registry/blocks/charts/chart-pie-donut-text.ts +89 -0
- package/packages/registry/blocks/charts/chart-pie-donut.ts +77 -0
- package/packages/registry/blocks/charts/chart-pie-interactive.ts +120 -0
- package/packages/registry/blocks/charts/chart-pie-label-custom.ts +82 -0
- package/packages/registry/blocks/charts/chart-pie-label-list.ts +86 -0
- package/packages/registry/blocks/charts/chart-pie-label.ts +77 -0
- package/packages/registry/blocks/charts/chart-pie-legend.ts +79 -0
- package/packages/registry/blocks/charts/chart-pie-separator-none.ts +77 -0
- package/packages/registry/blocks/charts/chart-pie-simple.ts +77 -0
- package/packages/registry/blocks/charts/chart-pie-stacked.ts +99 -0
- package/packages/registry/blocks/charts/chart-radar-default.ts +61 -0
- package/packages/registry/blocks/charts/chart-radar-dots.ts +61 -0
- package/packages/registry/blocks/charts/chart-radar-grid-circle-fill.ts +61 -0
- package/packages/registry/blocks/charts/chart-radar-grid-circle-no-lines.ts +61 -0
- package/packages/registry/blocks/charts/chart-radar-grid-circle.ts +61 -0
- package/packages/registry/blocks/charts/chart-radar-grid-custom.ts +61 -0
- package/packages/registry/blocks/charts/chart-radar-grid-fill.ts +61 -0
- package/packages/registry/blocks/charts/chart-radar-grid-none.ts +60 -0
- package/packages/registry/blocks/charts/chart-radar-icons.ts +76 -0
- package/packages/registry/blocks/charts/chart-radar-label-custom.ts +77 -0
- package/packages/registry/blocks/charts/chart-radar-legend.ts +70 -0
- package/packages/registry/blocks/charts/chart-radar-lines-only.ts +68 -0
- package/packages/registry/blocks/charts/chart-radar-multiple.ts +68 -0
- package/packages/registry/blocks/charts/chart-radar-radius.ts +68 -0
- package/packages/registry/blocks/charts/chart-radial-grid.ts +80 -0
- package/packages/registry/blocks/charts/chart-radial-label.ts +85 -0
- package/packages/registry/blocks/charts/chart-radial-shape.ts +81 -0
- package/packages/registry/blocks/charts/chart-radial-simple.ts +79 -0
- package/packages/registry/blocks/charts/chart-radial-stacked.ts +69 -0
- package/packages/registry/blocks/charts/chart-radial-text.ts +82 -0
- package/packages/registry/blocks/charts/chart-tooltip-advanced.ts +84 -0
- package/packages/registry/blocks/charts/chart-tooltip-default.ts +62 -0
- package/packages/registry/blocks/charts/chart-tooltip-formatter.ts +75 -0
- package/packages/registry/blocks/charts/chart-tooltip-icons.ts +68 -0
- package/packages/registry/blocks/charts/chart-tooltip-indicator-line.ts +62 -0
- package/packages/registry/blocks/charts/chart-tooltip-indicator-none.ts +62 -0
- package/packages/registry/blocks/charts/chart-tooltip-label-custom.ts +65 -0
- package/packages/registry/blocks/charts/chart-tooltip-label-formatter.ts +66 -0
- package/packages/registry/blocks/charts/chart-tooltip-label-none.ts +62 -0
- package/packages/registry/blocks/dashboard-01/components/app-sidebar.ts +108 -0
- package/packages/registry/blocks/dashboard-01/components/chart-area-interactive.ts +276 -0
- package/packages/registry/blocks/dashboard-01/components/dashboard-data.ts +89 -0
- package/packages/registry/blocks/dashboard-01/components/data-table.ts +637 -0
- package/packages/registry/blocks/dashboard-01/components/nav-documents.ts +65 -0
- package/packages/registry/blocks/dashboard-01/components/nav-main.ts +61 -0
- package/packages/registry/blocks/dashboard-01/components/nav-secondary.ts +40 -0
- package/packages/registry/blocks/dashboard-01/components/nav-user.ts +66 -0
- package/packages/registry/blocks/dashboard-01/components/section-cards.ts +59 -0
- package/packages/registry/blocks/dashboard-01/components/site-header.ts +52 -0
- package/packages/registry/blocks/dashboard-01/page.ts +39 -0
- package/packages/registry/blocks/login-01/components/login-form.ts +70 -0
- package/packages/registry/blocks/login-01/page.ts +19 -0
- package/packages/registry/blocks/login-02/components/login-form.ts +68 -0
- package/packages/registry/blocks/login-02/page.ts +36 -0
- package/packages/registry/blocks/login-03/components/login-form.ts +89 -0
- package/packages/registry/blocks/login-03/page.ts +28 -0
- package/packages/registry/blocks/login-04/components/login-form.ts +91 -0
- package/packages/registry/blocks/login-04/page.ts +20 -0
- package/packages/registry/blocks/login-05/components/login-form.ts +75 -0
- package/packages/registry/blocks/login-05/page.ts +19 -0
- package/packages/registry/blocks/preview/cards/activate-agent-dialog.ts +77 -0
- package/packages/registry/blocks/preview/cards/analytics-card.ts +64 -0
- package/packages/registry/blocks/preview/cards/anomaly-alert.ts +35 -0
- package/packages/registry/blocks/preview/cards/bar-chart-card.ts +91 -0
- package/packages/registry/blocks/preview/cards/book-appointment.ts +51 -0
- package/packages/registry/blocks/preview/cards/codespaces-card.ts +172 -0
- package/packages/registry/blocks/preview/cards/contributions-activity.ts +63 -0
- package/packages/registry/blocks/preview/cards/contributors.ts +51 -0
- package/packages/registry/blocks/preview/cards/environment-variables.ts +47 -0
- package/packages/registry/blocks/preview/cards/feedback-form.ts +61 -0
- package/packages/registry/blocks/preview/cards/file-upload.ts +51 -0
- package/packages/registry/blocks/preview/cards/github-profile.ts +66 -0
- package/packages/registry/blocks/preview/cards/icon-preview-grid.ts +47 -0
- package/packages/registry/blocks/preview/cards/invite-team.ts +78 -0
- package/packages/registry/blocks/preview/cards/invoice.ts +91 -0
- package/packages/registry/blocks/preview/cards/live-waveform.ts +330 -0
- package/packages/registry/blocks/preview/cards/no-team-members.ts +61 -0
- package/packages/registry/blocks/preview/cards/not-found.ts +46 -0
- package/packages/registry/blocks/preview/cards/observability-card.ts +44 -0
- package/packages/registry/blocks/preview/cards/pie-chart-card.ts +84 -0
- package/packages/registry/blocks/preview/cards/report-bug.ts +71 -0
- package/packages/registry/blocks/preview/cards/shipping-address.ts +79 -0
- package/packages/registry/blocks/preview/cards/shortcuts.ts +57 -0
- package/packages/registry/blocks/preview/cards/skeleton-loading.ts +37 -0
- package/packages/registry/blocks/preview/cards/sleep-report.ts +85 -0
- package/packages/registry/blocks/preview/cards/style-overview.ts +64 -0
- package/packages/registry/blocks/preview/cards/typography-specimen.ts +107 -0
- package/packages/registry/blocks/preview/cards/ui-elements.ts +164 -0
- package/packages/registry/blocks/preview/cards/usage-card.ts +63 -0
- package/packages/registry/blocks/preview/cards/visitors.ts +71 -0
- package/packages/registry/blocks/preview/cards/weekly-fitness-summary.ts +54 -0
- package/packages/registry/blocks/preview/page.ts +103 -0
- package/packages/registry/blocks/preview-02/cards/account-access.ts +70 -0
- package/packages/registry/blocks/preview-02/cards/card-overview.ts +75 -0
- package/packages/registry/blocks/preview-02/cards/claimable-balance.ts +54 -0
- package/packages/registry/blocks/preview-02/cards/contribution-history.ts +80 -0
- package/packages/registry/blocks/preview-02/cards/cover-art.ts +41 -0
- package/packages/registry/blocks/preview-02/cards/dividend-income.ts +76 -0
- package/packages/registry/blocks/preview-02/cards/empty-connect-bank.ts +38 -0
- package/packages/registry/blocks/preview-02/cards/empty-distribute-track.ts +38 -0
- package/packages/registry/blocks/preview-02/cards/empty-explore-catalog.ts +39 -0
- package/packages/registry/blocks/preview-02/cards/faq.ts +79 -0
- package/packages/registry/blocks/preview-02/cards/front-door.ts +40 -0
- package/packages/registry/blocks/preview-02/cards/index-investing.ts +31 -0
- package/packages/registry/blocks/preview-02/cards/kitchen-island.ts +90 -0
- package/packages/registry/blocks/preview-02/cards/loading-card.ts +34 -0
- package/packages/registry/blocks/preview-02/cards/new-milestone.ts +53 -0
- package/packages/registry/blocks/preview-02/cards/notification-settings.ts +126 -0
- package/packages/registry/blocks/preview-02/cards/payments.ts +88 -0
- package/packages/registry/blocks/preview-02/cards/payout-threshold.ts +92 -0
- package/packages/registry/blocks/preview-02/cards/power-usage.ts +84 -0
- package/packages/registry/blocks/preview-02/cards/preferences.ts +89 -0
- package/packages/registry/blocks/preview-02/cards/qr-connect.ts +54 -0
- package/packages/registry/blocks/preview-02/cards/receiving-method.ts +89 -0
- package/packages/registry/blocks/preview-02/cards/recent-transactions.ts +101 -0
- package/packages/registry/blocks/preview-02/cards/release-catalog.ts +73 -0
- package/packages/registry/blocks/preview-02/cards/roller-shades.ts +110 -0
- package/packages/registry/blocks/preview-02/cards/savings-progress.ts +68 -0
- package/packages/registry/blocks/preview-02/cards/savings-targets.ts +132 -0
- package/packages/registry/blocks/preview-02/cards/sidebar-nav.ts +88 -0
- package/packages/registry/blocks/preview-02/cards/social-links.ts +57 -0
- package/packages/registry/blocks/preview-02/cards/stock-performance.ts +106 -0
- package/packages/registry/blocks/preview-02/cards/syncing-state.ts +37 -0
- package/packages/registry/blocks/preview-02/cards/transfer-funds.ts +111 -0
- package/packages/registry/blocks/preview-02/cards/upcoming-payments.ts +69 -0
- package/packages/registry/blocks/preview-02/page.ts +111 -0
- package/packages/registry/blocks/preview-03/cards/files-chat.ts +75 -0
- package/packages/registry/blocks/preview-03/cards/group-chat.ts +114 -0
- package/packages/registry/blocks/preview-03/cards/reasoning-chat.ts +88 -0
- package/packages/registry/blocks/preview-03/cards/simple-chat.ts +53 -0
- package/packages/registry/blocks/preview-03/components/chat-card.ts +126 -0
- package/packages/registry/blocks/preview-03/components/chat-player.ts +174 -0
- package/packages/registry/blocks/preview-03/components/part-file.ts +77 -0
- package/packages/registry/blocks/preview-03/components/part-reasoning.ts +25 -0
- package/packages/registry/blocks/preview-03/components/part-source.ts +48 -0
- package/packages/registry/blocks/preview-03/components/part-text.ts +69 -0
- package/packages/registry/blocks/preview-03/components/part-tool.ts +71 -0
- package/packages/registry/blocks/preview-03/components/prompt-input.ts +86 -0
- package/packages/registry/blocks/preview-03/page.ts +39 -0
- package/packages/registry/blocks/sidebar-01/components/app-sidebar.ts +113 -0
- package/packages/registry/blocks/sidebar-01/components/search-form.ts +33 -0
- package/packages/registry/blocks/sidebar-01/components/version-switcher.ts +50 -0
- package/packages/registry/blocks/sidebar-01/page.ts +58 -0
- package/packages/registry/blocks/sidebar-02/components/app-sidebar.ts +131 -0
- package/packages/registry/blocks/sidebar-02/components/search-form.ts +33 -0
- package/packages/registry/blocks/sidebar-02/components/version-switcher.ts +50 -0
- package/packages/registry/blocks/sidebar-02/page.ts +53 -0
- package/packages/registry/blocks/sidebar-03/components/app-sidebar.ts +134 -0
- package/packages/registry/blocks/sidebar-03/page.ts +60 -0
- package/packages/registry/blocks/sidebar-04/components/app-sidebar.ts +136 -0
- package/packages/registry/blocks/sidebar-04/page.ts +58 -0
- package/packages/registry/blocks/sidebar-05/components/app-sidebar.ts +147 -0
- package/packages/registry/blocks/sidebar-05/components/search-form.ts +33 -0
- package/packages/registry/blocks/sidebar-05/page.ts +58 -0
- package/packages/registry/blocks/sidebar-06/components/app-sidebar.ts +105 -0
- package/packages/registry/blocks/sidebar-06/components/nav-main.ts +56 -0
- package/packages/registry/blocks/sidebar-06/components/sidebar-opt-in-form.ts +44 -0
- package/packages/registry/blocks/sidebar-06/page.ts +57 -0
- package/packages/registry/blocks/sidebar-07/components/app-sidebar.ts +108 -0
- package/packages/registry/blocks/sidebar-07/components/nav-main.ts +61 -0
- package/packages/registry/blocks/sidebar-07/components/nav-projects.ts +65 -0
- package/packages/registry/blocks/sidebar-07/components/nav-user.ts +70 -0
- package/packages/registry/blocks/sidebar-07/components/team-switcher.ts +66 -0
- package/packages/registry/blocks/sidebar-07/page.ts +59 -0
- package/packages/registry/blocks/sidebar-08/components/app-sidebar.ts +122 -0
- package/packages/registry/blocks/sidebar-08/components/nav-main.ts +68 -0
- package/packages/registry/blocks/sidebar-08/components/nav-projects.ts +65 -0
- package/packages/registry/blocks/sidebar-08/components/nav-secondary.ts +40 -0
- package/packages/registry/blocks/sidebar-08/components/nav-user.ts +70 -0
- package/packages/registry/blocks/sidebar-08/page.ts +59 -0
- package/packages/registry/blocks/sidebar-09/components/app-sidebar.ts +213 -0
- package/packages/registry/blocks/sidebar-09/components/nav-user.ts +70 -0
- package/packages/registry/blocks/sidebar-09/page.ts +52 -0
- package/packages/registry/blocks/sidebar-10/components/app-sidebar.ts +125 -0
- package/packages/registry/blocks/sidebar-10/components/nav-actions.ts +84 -0
- package/packages/registry/blocks/sidebar-10/components/nav-favorites.ts +66 -0
- package/packages/registry/blocks/sidebar-10/components/nav-main.ts +37 -0
- package/packages/registry/blocks/sidebar-10/components/nav-secondary.ts +43 -0
- package/packages/registry/blocks/sidebar-10/components/nav-workspaces.ts +78 -0
- package/packages/registry/blocks/sidebar-10/components/team-switcher.ts +63 -0
- package/packages/registry/blocks/sidebar-10/page.ts +46 -0
- package/packages/registry/blocks/sidebar-11/components/app-sidebar.ts +114 -0
- package/packages/registry/blocks/sidebar-11/page.ts +63 -0
- package/packages/registry/blocks/sidebar-12/components/app-sidebar.ts +63 -0
- package/packages/registry/blocks/sidebar-12/components/calendars.ts +53 -0
- package/packages/registry/blocks/sidebar-12/components/date-picker.ts +26 -0
- package/packages/registry/blocks/sidebar-12/components/nav-user.ts +70 -0
- package/packages/registry/blocks/sidebar-12/page.ts +43 -0
- package/packages/registry/blocks/sidebar-13/components/settings-dialog.ts +114 -0
- package/packages/registry/blocks/sidebar-13/page.ts +21 -0
- package/packages/registry/blocks/sidebar-14/components/app-sidebar.ts +120 -0
- package/packages/registry/blocks/sidebar-14/page.ts +55 -0
- package/packages/registry/blocks/sidebar-15/components/calendars.ts +53 -0
- package/packages/registry/blocks/sidebar-15/components/date-picker.ts +26 -0
- package/packages/registry/blocks/sidebar-15/components/nav-favorites.ts +66 -0
- package/packages/registry/blocks/sidebar-15/components/nav-main.ts +35 -0
- package/packages/registry/blocks/sidebar-15/components/nav-secondary.ts +43 -0
- package/packages/registry/blocks/sidebar-15/components/nav-user.ts +70 -0
- package/packages/registry/blocks/sidebar-15/components/nav-workspaces.ts +75 -0
- package/packages/registry/blocks/sidebar-15/components/sidebar-left.ts +126 -0
- package/packages/registry/blocks/sidebar-15/components/sidebar-right.ts +62 -0
- package/packages/registry/blocks/sidebar-15/components/team-switcher.ts +63 -0
- package/packages/registry/blocks/sidebar-15/page.ts +47 -0
- package/packages/registry/blocks/sidebar-16/components/app-sidebar.ts +124 -0
- package/packages/registry/blocks/sidebar-16/components/nav-main.ts +67 -0
- package/packages/registry/blocks/sidebar-16/components/nav-projects.ts +65 -0
- package/packages/registry/blocks/sidebar-16/components/nav-secondary.ts +40 -0
- package/packages/registry/blocks/sidebar-16/components/nav-user.ts +70 -0
- package/packages/registry/blocks/sidebar-16/components/search-form.ts +27 -0
- package/packages/registry/blocks/sidebar-16/components/site-header.ts +42 -0
- package/packages/registry/blocks/sidebar-16/page.ts +38 -0
- package/packages/registry/blocks/signup-01/components/signup-form.ts +78 -0
- package/packages/registry/blocks/signup-01/page.ts +19 -0
- package/packages/registry/blocks/signup-02/components/signup-form.ts +78 -0
- package/packages/registry/blocks/signup-02/page.ts +36 -0
- package/packages/registry/blocks/signup-03/components/signup-form.ts +79 -0
- package/packages/registry/blocks/signup-03/page.ts +28 -0
- package/packages/registry/blocks/signup-04/components/signup-form.ts +100 -0
- package/packages/registry/blocks/signup-04/page.ts +20 -0
- package/packages/registry/blocks/signup-05/components/signup-form.ts +75 -0
- package/packages/registry/blocks/signup-05/page.ts +20 -0
- package/packages/registry/components/accordion.ts +20 -7
- package/packages/registry/components/alert-dialog.ts +58 -13
- package/packages/registry/components/alert.ts +11 -6
- package/packages/registry/components/attachment.ts +119 -0
- package/packages/registry/components/avatar.ts +17 -8
- package/packages/registry/components/badge.ts +16 -9
- package/packages/registry/components/breadcrumb.ts +6 -6
- package/packages/registry/components/bubble.ts +95 -0
- package/packages/registry/components/button-group.ts +73 -0
- package/packages/registry/components/button.ts +35 -25
- package/packages/registry/components/calendar.ts +566 -0
- package/packages/registry/components/card.ts +8 -8
- package/packages/registry/components/carousel.ts +352 -0
- package/packages/registry/components/chart-element.ts +547 -0
- package/packages/registry/components/chart-geometry.ts +457 -0
- package/packages/registry/components/chart.ts +932 -0
- package/packages/registry/components/checkbox.ts +22 -84
- package/packages/registry/components/code-block.ts +191 -0
- package/packages/registry/components/collapsible.ts +5 -2
- package/packages/registry/components/combobox.ts +802 -0
- package/packages/registry/components/command.ts +618 -0
- package/packages/registry/components/context-menu.ts +302 -0
- package/packages/registry/components/dialog.ts +156 -45
- package/packages/registry/components/direction.ts +43 -0
- package/packages/registry/components/drawer.ts +226 -0
- package/packages/registry/components/dropdown-menu.ts +262 -83
- package/packages/registry/components/empty.ts +88 -0
- package/packages/registry/components/field.ts +165 -0
- package/packages/registry/components/floating.ts +124 -0
- package/packages/registry/components/hover-card.ts +19 -8
- package/packages/registry/components/input-group.ts +118 -0
- package/packages/registry/components/input-otp.ts +365 -0
- package/packages/registry/components/input.ts +3 -3
- package/packages/registry/components/item.ts +134 -0
- package/packages/registry/components/kbd.ts +2 -2
- package/packages/registry/components/label.ts +1 -1
- package/packages/registry/components/marker.ts +63 -0
- package/packages/registry/components/menubar.ts +388 -0
- package/packages/registry/components/message-scroller.ts +470 -0
- package/packages/registry/components/message.ts +69 -0
- package/packages/registry/components/native-select.ts +5 -5
- package/packages/registry/components/navigation-menu.ts +564 -0
- package/packages/registry/components/pagination.ts +5 -5
- package/packages/registry/components/popover.ts +30 -84
- package/packages/registry/components/progress.ts +7 -3
- package/packages/registry/components/questionnaire.ts +840 -0
- package/packages/registry/components/radio-group.ts +18 -73
- package/packages/registry/components/resizable.ts +330 -0
- package/packages/registry/components/scroll-area.ts +46 -0
- package/packages/registry/components/select.ts +650 -0
- package/packages/registry/components/separator.ts +1 -1
- package/packages/registry/components/sheet.ts +128 -0
- package/packages/registry/components/sidebar.ts +457 -0
- package/packages/registry/components/skeleton.ts +1 -1
- package/packages/registry/components/slider.ts +333 -0
- package/packages/registry/components/sonner.ts +74 -7
- package/packages/registry/components/spinner.ts +66 -0
- package/packages/registry/components/switch.ts +117 -9
- package/packages/registry/components/table.ts +11 -9
- package/packages/registry/components/tabs.ts +76 -25
- package/packages/registry/components/textarea.ts +1 -1
- package/packages/registry/components/toggle-group.ts +30 -11
- package/packages/registry/components/toggle.ts +20 -13
- package/packages/registry/components/tooltip.ts +68 -7
- package/packages/registry/components/trace.ts +75 -0
- package/packages/registry/lib/icons-hugeicons.ts +955 -0
- package/packages/registry/lib/icons-phosphor.ts +955 -0
- package/packages/registry/lib/icons-remixicon.ts +955 -0
- package/packages/registry/lib/icons-tabler.ts +955 -0
- package/packages/registry/lib/icons.ts +768 -0
- package/packages/registry/lib/utils.ts +49 -4
- package/packages/registry/registry.json +4092 -60
- package/packages/registry/styles/shadcn-tailwind.css +654 -0
- package/packages/registry/styles/style-luma.css +1987 -0
- package/packages/registry/styles/style-lyra.css +1965 -0
- package/packages/registry/styles/style-maia.css +1987 -0
- package/packages/registry/styles/style-mira.css +1992 -0
- package/packages/registry/styles/style-new-york.css +1597 -0
- package/packages/registry/styles/style-nova.css +1990 -0
- package/packages/registry/styles/style-rhea.css +1987 -0
- package/packages/registry/styles/style-sera.css +1977 -0
- package/packages/registry/styles/style-vega.css +1990 -0
- package/packages/registry/styles/supplement.json +54 -0
- package/packages/registry/styles/tw-animate.css +6 -0
- package/packages/registry/themes/base-colors.js +8 -2
- package/packages/registry/themes/fonts.js +120 -0
- package/packages/registry/themes/index.css +2 -0
- package/packages/registry/themes/items.js +61 -0
- package/packages/registry/themes/preset.js +302 -0
- package/packages/registry/themes/themes.js +1193 -0
- package/src/commands/add.js +236 -12
- package/src/commands/diff.js +34 -20
- package/src/commands/info.js +7 -0
- package/src/commands/init.js +125 -8
- package/src/commands/list.js +43 -11
- package/src/commands/view.js +33 -5
- package/src/registry/extract.js +192 -2
- package/src/registry/icons.js +31 -0
- package/src/registry/local.js +15 -1
- package/src/registry/schema.js +13 -0
- package/src/registry/style-bake.js +506 -0
- package/src/utils/theme.js +110 -21
|
@@ -0,0 +1,618 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command: a searchable list of actions, the menu behind a command palette.
|
|
3
|
+
* Tier-2. It is cmdk's model, built on the platform: typing in the input
|
|
4
|
+
* filters and ranks the items, the arrow keys move a selection while focus
|
|
5
|
+
* stays in the input, and Enter runs the selected item. `<ui-command-dialog>`
|
|
6
|
+
* puts the same command in a native modal `<dialog>`.
|
|
7
|
+
*
|
|
8
|
+
* shadcn parity:
|
|
9
|
+
* Command (label, shouldFilter, loop)
|
|
10
|
+
* → <ui-command label should-filter="false" loop>
|
|
11
|
+
* CommandInput placeholder → <ui-command-input placeholder>
|
|
12
|
+
* CommandList → <ui-command-list>
|
|
13
|
+
* CommandEmpty → <ui-command-empty>No results.</ui-command-empty>
|
|
14
|
+
* CommandGroup heading → <ui-command-group heading="Suggestions">
|
|
15
|
+
* CommandItem (value, keywords, disabled, onSelect)
|
|
16
|
+
* → <ui-command-item value keywords="a b" disabled>, firing `ui-select`
|
|
17
|
+
* CommandShortcut → <ui-command-shortcut>
|
|
18
|
+
* CommandSeparator → <ui-command-separator>
|
|
19
|
+
* CommandDialog (open, title, description, showCloseButton)
|
|
20
|
+
* → <ui-command-dialog open title description show-close-button>
|
|
21
|
+
* around a <ui-command>
|
|
22
|
+
* onValueChange (Command) → `ui-value-change` ({ detail: { value } }) as the selection moves
|
|
23
|
+
* onValueChange (Input) → `ui-search-change` ({ detail: { search } })
|
|
24
|
+
*
|
|
25
|
+
* An item's value is its `value` attribute, else its text. A search ranks
|
|
26
|
+
* items by how well the value and `keywords` match (a prefix beats a word
|
|
27
|
+
* start beats a substring beats letters in order), hides the rest, hides a
|
|
28
|
+
* group left empty and every separator, and shows `<ui-command-empty>` when
|
|
29
|
+
* nothing matches. `should-filter="false"` leaves filtering to you (a list a
|
|
30
|
+
* server action returns). Activating an item that holds a link follows it.
|
|
31
|
+
*
|
|
32
|
+
* Keyboard (as cmdk's): ArrowDown / ArrowUp (and Ctrl+N / Ctrl+P, Ctrl+J /
|
|
33
|
+
* Ctrl+K) move the selection, `loop` wraps it, Home / End jump to the ends,
|
|
34
|
+
* Enter runs the selected item. Pointing at an item selects it.
|
|
35
|
+
*
|
|
36
|
+
* A11y (handled by the element, plus your part): the input is a
|
|
37
|
+
* `role="combobox"` controlling a `role="listbox"` and pointing at the
|
|
38
|
+
* selected `role="option"` through `aria-activedescendant`, so focus never
|
|
39
|
+
* leaves it. Groups are named by their heading and a disabled item is
|
|
40
|
+
* announced and skipped. Your part: name the command (`label`, read by a
|
|
41
|
+
* screen reader only), since a placeholder is not a name.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```html
|
|
45
|
+
* <ui-command label="Command menu" class="rounded-lg border shadow-md md:min-w-[450px]">
|
|
46
|
+
* <ui-command-input placeholder="Type a command or search"></ui-command-input>
|
|
47
|
+
* <ui-command-list>
|
|
48
|
+
* <ui-command-empty>No results found.</ui-command-empty>
|
|
49
|
+
* <ui-command-group heading="Suggestions">
|
|
50
|
+
* <ui-command-item>Calendar</ui-command-item>
|
|
51
|
+
* <ui-command-item keywords="emoji smiley">Search Emoji</ui-command-item>
|
|
52
|
+
* <ui-command-item disabled>Calculator</ui-command-item>
|
|
53
|
+
* </ui-command-group>
|
|
54
|
+
* <ui-command-separator></ui-command-separator>
|
|
55
|
+
* <ui-command-group heading="Settings">
|
|
56
|
+
* <ui-command-item>Profile<ui-command-shortcut>⌘P</ui-command-shortcut></ui-command-item>
|
|
57
|
+
* </ui-command-group>
|
|
58
|
+
* </ui-command-list>
|
|
59
|
+
* </ui-command>
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
import { WebComponent, html, prop, signal, nothing } from '@webjsdev/core';
|
|
63
|
+
import { cn, takeAuthoredClass } from '../lib/utils.ts';
|
|
64
|
+
import { inputGroupClass, inputGroupAddonClass } from './input-group.ts';
|
|
65
|
+
import { UiDialog, UiDialogContent } from './dialog.ts';
|
|
66
|
+
|
|
67
|
+
/** The command's classes (the element applies them). */
|
|
68
|
+
export const commandClass = (): string => 'cn-command flex size-full flex-col overflow-hidden';
|
|
69
|
+
/** The command dialog's panel classes (the element applies them). */
|
|
70
|
+
export const commandDialogClass = (): string => 'cn-command-dialog top-1/3 translate-y-0 overflow-hidden p-0';
|
|
71
|
+
/** The input's wrapper (the element applies them). */
|
|
72
|
+
export const commandInputWrapperClass = (): string => 'cn-command-input-wrapper';
|
|
73
|
+
/** The input group around the input (the element applies them). */
|
|
74
|
+
export const commandInputGroupClass = (): string => 'cn-command-input-group';
|
|
75
|
+
/** The input's classes (the element applies them). */
|
|
76
|
+
export const commandInputClass = (): string =>
|
|
77
|
+
'cn-command-input outline-hidden disabled:cursor-not-allowed disabled:opacity-50';
|
|
78
|
+
/** The search icon. */
|
|
79
|
+
export const commandInputIconClass = (): string => 'cn-command-input-icon';
|
|
80
|
+
/** The list's classes (the element applies them). */
|
|
81
|
+
export const commandListClass = (): string => 'cn-command-list flex flex-col overflow-x-hidden overflow-y-auto';
|
|
82
|
+
/** The empty state's classes (the element applies them). */
|
|
83
|
+
export const commandEmptyClass = (): string => 'cn-command-empty';
|
|
84
|
+
/** A group's classes (the element applies them). */
|
|
85
|
+
export const commandGroupClass = (): string => 'cn-command-group';
|
|
86
|
+
/** A separator's classes (the element applies them). */
|
|
87
|
+
export const commandSeparatorClass = (): string => 'cn-command-separator';
|
|
88
|
+
/** An item's classes (the element applies them). */
|
|
89
|
+
export const commandItemClass = (): string =>
|
|
90
|
+
'cn-command-item group/command-item data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0';
|
|
91
|
+
/** A checked item's check mark. */
|
|
92
|
+
export const commandItemIndicatorClass = (): string =>
|
|
93
|
+
'cn-command-item-indicator ms-auto opacity-0 group-has-data-[slot=command-shortcut]/command-item:hidden group-data-[checked=true]/command-item:opacity-100';
|
|
94
|
+
/** A keyboard shortcut hint's classes. */
|
|
95
|
+
export const commandShortcutClass = (): string => 'cn-command-shortcut';
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* How well `search` matches `text`, 0 for no match: a prefix scores highest,
|
|
99
|
+
* then a match at a word start, then a substring, then the letters in order.
|
|
100
|
+
* Shorter texts win ties, as in cmdk's command-score.
|
|
101
|
+
*/
|
|
102
|
+
export function commandScore(text: string, search: string): number {
|
|
103
|
+
const t = text.toLowerCase();
|
|
104
|
+
const s = search.trim().toLowerCase();
|
|
105
|
+
if (!s) return 1;
|
|
106
|
+
if (!t) return 0;
|
|
107
|
+
const brevity = 1 / (1 + t.length / 100);
|
|
108
|
+
if (t.startsWith(s)) return 0.9 + 0.09 * brevity;
|
|
109
|
+
const at = t.indexOf(s);
|
|
110
|
+
if (at > 0) {
|
|
111
|
+
const wordStart = /[\s\-_/.:]/.test(t[at - 1]);
|
|
112
|
+
return (wordStart ? 0.7 : 0.5) + 0.09 * brevity;
|
|
113
|
+
}
|
|
114
|
+
let i = 0;
|
|
115
|
+
for (const ch of t) {
|
|
116
|
+
if (ch === s[i]) i++;
|
|
117
|
+
if (i === s.length) return 0.1 + 0.09 * brevity;
|
|
118
|
+
}
|
|
119
|
+
return 0;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const ROOT = 'ui-command';
|
|
123
|
+
let uid = 0;
|
|
124
|
+
|
|
125
|
+
// shadcn's className on each Command part lands on the element that part
|
|
126
|
+
// renders (the command, its input, list, empty state, groups and items), so a
|
|
127
|
+
// class written on the host moves there, read once at first render. The
|
|
128
|
+
// hosts stay boxes rather than display: contents, since a group, an item and
|
|
129
|
+
// the empty state hide themselves through the hidden attribute, which a
|
|
130
|
+
// display utility on the host would override.
|
|
131
|
+
function takeAuthored(part: HTMLElement): string | null {
|
|
132
|
+
return takeAuthoredClass(part, null);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
type ItemState = { visible: boolean; selected: boolean; order: number };
|
|
136
|
+
|
|
137
|
+
export class UiCommand extends WebComponent({
|
|
138
|
+
label: String,
|
|
139
|
+
shouldFilter: prop(String, { attribute: 'should-filter' }),
|
|
140
|
+
loop: Boolean,
|
|
141
|
+
// The selected item's value.
|
|
142
|
+
value: prop(String, { reflect: true }),
|
|
143
|
+
}) {
|
|
144
|
+
readonly #search = signal('');
|
|
145
|
+
_id = '';
|
|
146
|
+
|
|
147
|
+
constructor() {
|
|
148
|
+
super();
|
|
149
|
+
this.label = '';
|
|
150
|
+
this.shouldFilter = 'true';
|
|
151
|
+
this.loop = false;
|
|
152
|
+
this.value = '';
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
connectedCallback(): void {
|
|
156
|
+
super.connectedCallback?.();
|
|
157
|
+
this._id ||= `ui-command-${++uid}`;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// The ids exist once the root has connected. The server never connects an
|
|
161
|
+
// element, so it serves none rather than a `-list` every box would share;
|
|
162
|
+
// hydration renders them in.
|
|
163
|
+
get listId(): string | null {
|
|
164
|
+
return this._id ? `${this._id}-list` : null;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
get labelId(): string | null {
|
|
168
|
+
return this._id ? `${this._id}-label` : null;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// The root never hides itself, so its host can be display: contents: the
|
|
172
|
+
// command box is then the flex item of whatever holds it, and a `max-w-sm`
|
|
173
|
+
// with the box's `size-full` sizes against that parent, as shadcn's does.
|
|
174
|
+
// The host's box is turned off through its style, which the server serves.
|
|
175
|
+
render() {
|
|
176
|
+
const authored = takeAuthored(this);
|
|
177
|
+
if (typeof this.getAttribute === 'function' && !this.getAttribute('style')) this.setAttribute('style', 'display: contents');
|
|
178
|
+
return html`<div data-slot="command" cmdk-root="" class=${cn(commandClass(), authored)} @keydown=${this._onKeyDown}>${this.label
|
|
179
|
+
? html`<label id=${this.labelId || nothing} cmdk-label="" class="sr-only">${this.label}</label>`
|
|
180
|
+
: ''}<slot></slot></div>`;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// The parts that belong to this command, not to a command nested in it.
|
|
184
|
+
_own<T extends Element>(selector: string): T[] {
|
|
185
|
+
if (typeof this.querySelectorAll !== 'function') return [];
|
|
186
|
+
return Array.from(this.querySelectorAll<T>(selector)).filter((el) => el.closest(ROOT) === this);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/** The items currently shown, in the order they are shown. */
|
|
190
|
+
visibleItems(): UiCommandItem[] {
|
|
191
|
+
return this._own<UiCommandItem>(`${ROOT}-item`)
|
|
192
|
+
.filter((i) => i.state?.get().visible)
|
|
193
|
+
.sort((a, b) => a.state?.get().order - b.state?.get().order);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/** Set the search text, as typing does. */
|
|
197
|
+
setSearch(search: string): void {
|
|
198
|
+
if (search === this.#search.get()) return;
|
|
199
|
+
this.#search.set(search);
|
|
200
|
+
this.dispatchEvent(new CustomEvent('ui-search-change', { bubbles: true, detail: { search } }));
|
|
201
|
+
this.refresh(true);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Re-rank and redraw the items. A new search selects the best match; a
|
|
206
|
+
* redraw otherwise keeps the selection where it is when it is still shown.
|
|
207
|
+
*/
|
|
208
|
+
refresh(reselect = false): void {
|
|
209
|
+
const filter = this.shouldFilter !== 'false';
|
|
210
|
+
const search = this.#search.get();
|
|
211
|
+
const items = this._own<UiCommandItem>(`${ROOT}-item`);
|
|
212
|
+
const scored = items.map((item, dom) => ({
|
|
213
|
+
item,
|
|
214
|
+
dom,
|
|
215
|
+
score: filter ? commandScore(`${item.itemValue} ${item.keywords ?? ''}`, search) : 1,
|
|
216
|
+
}));
|
|
217
|
+
const ranked = search && filter
|
|
218
|
+
? scored.filter((s) => s.score > 0).sort((a, b) => b.score - a.score || a.dom - b.dom)
|
|
219
|
+
: scored;
|
|
220
|
+
const rank = new Map(ranked.map((s, i) => [s.item, i]));
|
|
221
|
+
// A group sits where its best item ranks.
|
|
222
|
+
const groups = this._own<UiCommandGroup>(`${ROOT}-group`);
|
|
223
|
+
const groupRank = new Map<UiCommandGroup, number>();
|
|
224
|
+
for (const g of groups) {
|
|
225
|
+
const ranks = items.filter((i) => i.closest(`${ROOT}-group`) === g && rank.has(i)).map((i) => rank.get(i) as number);
|
|
226
|
+
groupRank.set(g, ranks.length ? Math.min(...ranks) : Infinity);
|
|
227
|
+
}
|
|
228
|
+
const sorting = !!search && filter;
|
|
229
|
+
const visible = ranked.map((s) => s.item);
|
|
230
|
+
const enabled = visible.filter((i) => !i.disabled);
|
|
231
|
+
let selected = items.find((i) => i.itemValue === this.value && rank.has(i) && !i.disabled) ?? null;
|
|
232
|
+
if (reselect || !selected) {
|
|
233
|
+
selected = sorting
|
|
234
|
+
? enabled[0] ?? null
|
|
235
|
+
: enabled.slice().sort((a, b) => items.indexOf(a) - items.indexOf(b))[0] ?? null;
|
|
236
|
+
}
|
|
237
|
+
for (const item of items) {
|
|
238
|
+
const r = rank.get(item);
|
|
239
|
+
item.state?.set({ visible: r !== undefined, selected: item === selected, order: sorting && r !== undefined ? r : items.indexOf(item) });
|
|
240
|
+
}
|
|
241
|
+
for (const g of groups) {
|
|
242
|
+
const r = groupRank.get(g) ?? Infinity;
|
|
243
|
+
g.shown?.set(r !== Infinity);
|
|
244
|
+
g.order?.set(sorting && r !== Infinity ? r : 0);
|
|
245
|
+
}
|
|
246
|
+
for (const sep of this._own<UiCommandSeparator>(`${ROOT}-separator`)) sep.shown?.set(!search);
|
|
247
|
+
for (const empty of this._own<UiCommandEmpty>(`${ROOT}-empty`)) empty.shown?.set(visible.length === 0);
|
|
248
|
+
this._select(selected);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
_select(item: UiCommandItem | null): void {
|
|
252
|
+
const value = item?.itemValue ?? '';
|
|
253
|
+
for (const i of this._own<UiCommandItem>(`${ROOT}-item`)) {
|
|
254
|
+
if (i.state?.get().selected !== (i === item)) i.state?.set({ ...i.state?.get(), selected: i === item });
|
|
255
|
+
}
|
|
256
|
+
const input = this._own<UiCommandInput>(`${ROOT}-input`)[0];
|
|
257
|
+
if (input) input.activeId?.set(item?.optionId ?? '');
|
|
258
|
+
item?.scrollIntoViewIfShown?.();
|
|
259
|
+
if (value !== this.value) {
|
|
260
|
+
this.value = value;
|
|
261
|
+
this.dispatchEvent(new CustomEvent('ui-value-change', { bubbles: true, detail: { value } }));
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/** Move the selection to an item (used by pointing). */
|
|
266
|
+
selectItem(item: UiCommandItem): void {
|
|
267
|
+
if (item.disabled || !item.state?.get().visible) return;
|
|
268
|
+
this._select(item);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/** Run an item: fire its ui-select, and follow a link it holds. */
|
|
272
|
+
run(item: UiCommandItem | null): void {
|
|
273
|
+
if (!item || item.disabled) return;
|
|
274
|
+
const ok = item.dispatchEvent(new CustomEvent('ui-select', { bubbles: true, cancelable: true, detail: { value: item.itemValue } }));
|
|
275
|
+
if (!ok) return;
|
|
276
|
+
item.querySelector<HTMLAnchorElement>('a[href]')?.click();
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
_move(by: number | 'first' | 'last'): void {
|
|
280
|
+
const enabled = this.visibleItems().filter((i) => !i.disabled);
|
|
281
|
+
if (!enabled.length) return;
|
|
282
|
+
const at = enabled.findIndex((i) => i.state?.get().selected);
|
|
283
|
+
let next: number;
|
|
284
|
+
if (by === 'first') next = 0;
|
|
285
|
+
else if (by === 'last') next = enabled.length - 1;
|
|
286
|
+
else {
|
|
287
|
+
next = at + by;
|
|
288
|
+
if (this.loop) next = (next + enabled.length) % enabled.length;
|
|
289
|
+
else next = Math.max(0, Math.min(enabled.length - 1, next));
|
|
290
|
+
}
|
|
291
|
+
this._select(enabled[next]);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
_onKeyDown = (e: KeyboardEvent): void => {
|
|
295
|
+
if (e.isComposing) return;
|
|
296
|
+
const ctrl = e.ctrlKey && !e.metaKey && !e.altKey;
|
|
297
|
+
if (e.key === 'ArrowDown' || (ctrl && (e.key === 'n' || e.key === 'j'))) { e.preventDefault(); this._move(1); }
|
|
298
|
+
else if (e.key === 'ArrowUp' || (ctrl && (e.key === 'p' || e.key === 'k'))) { e.preventDefault(); this._move(-1); }
|
|
299
|
+
else if (e.key === 'Home') { e.preventDefault(); this._move('first'); }
|
|
300
|
+
else if (e.key === 'End') { e.preventDefault(); this._move('last'); }
|
|
301
|
+
else if (e.key === 'Enter') {
|
|
302
|
+
e.preventDefault();
|
|
303
|
+
this.run(this.visibleItems().find((i) => i.state?.get().selected) ?? null);
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
// Parts connected after the first render (a client render appends children
|
|
308
|
+
// in order) are ranked once they are all in place.
|
|
309
|
+
_partConnected(): void {
|
|
310
|
+
if (this._queued) return;
|
|
311
|
+
this._queued = true;
|
|
312
|
+
queueMicrotask(() => { this._queued = false; this.refresh(); });
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
_queued = false;
|
|
316
|
+
}
|
|
317
|
+
UiCommand.register('ui-command');
|
|
318
|
+
|
|
319
|
+
// --------------------------------------------------------------------------
|
|
320
|
+
// <ui-command-input>
|
|
321
|
+
// --------------------------------------------------------------------------
|
|
322
|
+
|
|
323
|
+
export class UiCommandInput extends WebComponent({
|
|
324
|
+
placeholder: String,
|
|
325
|
+
}) {
|
|
326
|
+
readonly activeId = signal('');
|
|
327
|
+
constructor() {
|
|
328
|
+
super();
|
|
329
|
+
this.placeholder = '';
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
connectedCallback(): void {
|
|
333
|
+
super.connectedCallback?.();
|
|
334
|
+
this._root()?._partConnected();
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
_root(): UiCommand | null {
|
|
338
|
+
return this.closest(ROOT) as UiCommand | null;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
render() {
|
|
342
|
+
const root = this._root();
|
|
343
|
+
const named = root?.label ? root.labelId || nothing : nothing;
|
|
344
|
+
return html`<div data-slot="command-input-wrapper" cmdk-input-wrapper="" class=${commandInputWrapperClass()}><div
|
|
345
|
+
data-slot="input-group" class=${cn(inputGroupClass(), commandInputGroupClass())}
|
|
346
|
+
><input
|
|
347
|
+
data-slot="command-input"
|
|
348
|
+
cmdk-input=""
|
|
349
|
+
type="text"
|
|
350
|
+
role="combobox"
|
|
351
|
+
autocomplete="off"
|
|
352
|
+
autocorrect="off"
|
|
353
|
+
spellcheck="false"
|
|
354
|
+
aria-autocomplete="list"
|
|
355
|
+
aria-expanded="true"
|
|
356
|
+
aria-controls=${root?.listId || nothing}
|
|
357
|
+
aria-labelledby=${named}
|
|
358
|
+
aria-label=${named ? nothing : this.getAttribute?.('aria-label') || this.placeholder || nothing}
|
|
359
|
+
aria-activedescendant=${this.activeId.get() || nothing}
|
|
360
|
+
placeholder=${this.placeholder || nothing}
|
|
361
|
+
class=${cn(commandInputClass(), takeAuthored(this))}
|
|
362
|
+
@input=${this._onInput}
|
|
363
|
+
><div data-slot="input-group-addon" data-align="inline-start" class=${inputGroupAddonClass()}><svg
|
|
364
|
+
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"
|
|
365
|
+
class=${commandInputIconClass()}
|
|
366
|
+
><circle cx="11" cy="11" r="8"></circle><path d="m21 21-4.3-4.3"></path></svg></div></div></div>`;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
_onInput = (e: Event): void => {
|
|
370
|
+
this._root()?.setSearch((e.target as HTMLInputElement).value);
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
UiCommandInput.register('ui-command-input');
|
|
374
|
+
|
|
375
|
+
// --------------------------------------------------------------------------
|
|
376
|
+
// <ui-command-list>
|
|
377
|
+
// --------------------------------------------------------------------------
|
|
378
|
+
|
|
379
|
+
export class UiCommandList extends WebComponent {
|
|
380
|
+
render() {
|
|
381
|
+
const root = this.closest?.(ROOT) as UiCommand | null;
|
|
382
|
+
return html`<div
|
|
383
|
+
data-slot="command-list"
|
|
384
|
+
cmdk-list=""
|
|
385
|
+
role="listbox"
|
|
386
|
+
id=${root?.listId || nothing}
|
|
387
|
+
aria-label=${this.getAttribute?.('aria-label') || 'Suggestions'}
|
|
388
|
+
class=${cn(commandListClass(), takeAuthored(this))}
|
|
389
|
+
><slot></slot></div>`;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
UiCommandList.register('ui-command-list');
|
|
393
|
+
|
|
394
|
+
// --------------------------------------------------------------------------
|
|
395
|
+
// <ui-command-empty>
|
|
396
|
+
// --------------------------------------------------------------------------
|
|
397
|
+
|
|
398
|
+
export class UiCommandEmpty extends WebComponent {
|
|
399
|
+
readonly shown = signal(false);
|
|
400
|
+
constructor() {
|
|
401
|
+
super();
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
connectedCallback(): void {
|
|
405
|
+
super.connectedCallback?.();
|
|
406
|
+
(this.closest(ROOT) as UiCommand | null)?._partConnected();
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
render() {
|
|
410
|
+
return html`<div data-slot="command-empty" cmdk-empty="" role="presentation" ?hidden=${!this.shown.get()} class=${cn(commandEmptyClass(), takeAuthored(this))}><slot></slot></div>`;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
UiCommandEmpty.register('ui-command-empty');
|
|
414
|
+
|
|
415
|
+
// --------------------------------------------------------------------------
|
|
416
|
+
// <ui-command-group>
|
|
417
|
+
// --------------------------------------------------------------------------
|
|
418
|
+
|
|
419
|
+
export class UiCommandGroup extends WebComponent({
|
|
420
|
+
heading: String,
|
|
421
|
+
}) {
|
|
422
|
+
readonly shown = signal(true);
|
|
423
|
+
readonly order = signal(0);
|
|
424
|
+
_id = '';
|
|
425
|
+
|
|
426
|
+
constructor() {
|
|
427
|
+
super();
|
|
428
|
+
this.heading = '';
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
connectedCallback(): void {
|
|
432
|
+
super.connectedCallback?.();
|
|
433
|
+
this._id ||= `ui-command-group-${++uid}`;
|
|
434
|
+
(this.closest(ROOT) as UiCommand | null)?._partConnected();
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
updated(changedProperties: Map<string, unknown>): void {
|
|
438
|
+
super.updated?.(changedProperties);
|
|
439
|
+
this.style.order = this.order.get() ? String(this.order.get()) : '';
|
|
440
|
+
this.hidden = !this.shown.get();
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
render() {
|
|
444
|
+
// No id before connect (the server never connects an element), so the
|
|
445
|
+
// served group is named by aria-label instead of a shared `-heading` id.
|
|
446
|
+
const headingId = this.heading && this._id ? `${this._id}-heading` : nothing;
|
|
447
|
+
return html`<div data-slot="command-group" cmdk-group="" role="presentation" class=${cn(commandGroupClass(), takeAuthored(this))}>${this.heading
|
|
448
|
+
? html`<div cmdk-group-heading="" aria-hidden="true" id=${headingId}>${this.heading}</div>`
|
|
449
|
+
: ''}<div cmdk-group-items="" role="group" aria-labelledby=${headingId} aria-label=${this.heading && !headingId ? this.heading : nothing} class="flex flex-col"><slot></slot></div></div>`;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
UiCommandGroup.register('ui-command-group');
|
|
453
|
+
|
|
454
|
+
// --------------------------------------------------------------------------
|
|
455
|
+
// <ui-command-separator>
|
|
456
|
+
// --------------------------------------------------------------------------
|
|
457
|
+
|
|
458
|
+
export class UiCommandSeparator extends WebComponent {
|
|
459
|
+
readonly shown = signal(true);
|
|
460
|
+
constructor() {
|
|
461
|
+
super();
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
connectedCallback(): void {
|
|
465
|
+
super.connectedCallback?.();
|
|
466
|
+
(this.closest(ROOT) as UiCommand | null)?._partConnected();
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
render() {
|
|
470
|
+
return html`<div data-slot="command-separator" cmdk-separator="" role="separator" ?hidden=${!this.shown.get()} class=${commandSeparatorClass()}></div>`;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
UiCommandSeparator.register('ui-command-separator');
|
|
474
|
+
|
|
475
|
+
// --------------------------------------------------------------------------
|
|
476
|
+
// <ui-command-item>
|
|
477
|
+
// --------------------------------------------------------------------------
|
|
478
|
+
|
|
479
|
+
export class UiCommandItem extends WebComponent({
|
|
480
|
+
value: String,
|
|
481
|
+
keywords: String,
|
|
482
|
+
disabled: Boolean,
|
|
483
|
+
checked: Boolean,
|
|
484
|
+
}) {
|
|
485
|
+
readonly state = signal<ItemState>({ visible: true, selected: false, order: 0 });
|
|
486
|
+
_id = '';
|
|
487
|
+
|
|
488
|
+
constructor() {
|
|
489
|
+
super();
|
|
490
|
+
this.value = '';
|
|
491
|
+
this.keywords = '';
|
|
492
|
+
this.disabled = false;
|
|
493
|
+
this.checked = false;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
connectedCallback(): void {
|
|
497
|
+
super.connectedCallback?.();
|
|
498
|
+
this._id ||= `ui-command-item-${++uid}`;
|
|
499
|
+
(this.closest(ROOT) as UiCommand | null)?._partConnected();
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
get optionId(): string {
|
|
503
|
+
return `${this._id}-option`;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/** The item's value: its `value` attribute, else its text. */
|
|
507
|
+
get itemValue(): string {
|
|
508
|
+
if (this.value) return this.value;
|
|
509
|
+
const text = this.querySelector?.('[data-slot="command-item"]')?.textContent ?? this.textContent ?? '';
|
|
510
|
+
return text.trim();
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
scrollIntoViewIfShown(): void {
|
|
514
|
+
const option = this.querySelector?.<HTMLElement>('[data-slot="command-item"]');
|
|
515
|
+
if (option && typeof option.scrollIntoView === 'function') option.scrollIntoView({ block: 'nearest' });
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
updated(changedProperties: Map<string, unknown>): void {
|
|
519
|
+
super.updated?.(changedProperties);
|
|
520
|
+
const { order, visible } = this.state.get();
|
|
521
|
+
this.style.order = order ? String(order) : '';
|
|
522
|
+
this.hidden = !visible;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
render() {
|
|
526
|
+
const s = this.state.get();
|
|
527
|
+
return html`<div
|
|
528
|
+
data-slot="command-item"
|
|
529
|
+
cmdk-item=""
|
|
530
|
+
role="option"
|
|
531
|
+
id=${this._id ? this.optionId : nothing}
|
|
532
|
+
aria-selected=${s.selected ? 'true' : 'false'}
|
|
533
|
+
data-selected=${s.selected ? 'true' : 'false'}
|
|
534
|
+
aria-disabled=${this.disabled ? 'true' : nothing}
|
|
535
|
+
data-disabled=${this.disabled ? 'true' : 'false'}
|
|
536
|
+
data-checked=${this.checked ? 'true' : nothing}
|
|
537
|
+
data-value=${this.value || nothing}
|
|
538
|
+
class=${cn(commandItemClass(), takeAuthored(this))}
|
|
539
|
+
@pointermove=${this._onPointerMove}
|
|
540
|
+
@click=${this._onClick}
|
|
541
|
+
><slot></slot><svg
|
|
542
|
+
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"
|
|
543
|
+
class=${commandItemIndicatorClass()}
|
|
544
|
+
><path d="M20 6 9 17l-5-5"></path></svg></div>`;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
_onPointerMove = (): void => {
|
|
548
|
+
if (this.state.get().selected) return;
|
|
549
|
+
(this.closest(ROOT) as UiCommand | null)?.selectItem(this);
|
|
550
|
+
};
|
|
551
|
+
|
|
552
|
+
_onClick = (e: Event): void => {
|
|
553
|
+
// A click on a link inside follows it natively; run the item's event too.
|
|
554
|
+
const root = this.closest(ROOT) as UiCommand | null;
|
|
555
|
+
if (!root || this.disabled) return;
|
|
556
|
+
const onLink = (e.target as Element).closest('a[href]');
|
|
557
|
+
const ok = this.dispatchEvent(new CustomEvent('ui-select', { bubbles: true, cancelable: true, detail: { value: this.itemValue } }));
|
|
558
|
+
if (!ok && onLink) e.preventDefault();
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
UiCommandItem.register('ui-command-item');
|
|
562
|
+
|
|
563
|
+
// --------------------------------------------------------------------------
|
|
564
|
+
// <ui-command-shortcut>
|
|
565
|
+
// --------------------------------------------------------------------------
|
|
566
|
+
|
|
567
|
+
export class UiCommandShortcut extends WebComponent {
|
|
568
|
+
// The span is the item's flex item, as shadcn's CommandShortcut is, so the
|
|
569
|
+
// styles' `ml-auto` pushes it to the end of the row. A shortcut never hides
|
|
570
|
+
// itself, so unlike the other parts its host can be display: contents,
|
|
571
|
+
// turned off through its style, which the server serves.
|
|
572
|
+
render() {
|
|
573
|
+
const authored = takeAuthored(this);
|
|
574
|
+
if (typeof this.getAttribute === 'function' && !this.getAttribute('style')) this.setAttribute('style', 'display: contents');
|
|
575
|
+
return html`<span data-slot="command-shortcut" class=${cn(commandShortcutClass(), authored)}><slot></slot></span>`;
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
UiCommandShortcut.register('ui-command-shortcut');
|
|
579
|
+
|
|
580
|
+
// --------------------------------------------------------------------------
|
|
581
|
+
// <ui-command-dialog>
|
|
582
|
+
// --------------------------------------------------------------------------
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* A command in a native modal dialog: a `<ui-dialog>` whose content the
|
|
586
|
+
* element renders itself, with a screen-reader title and description, around
|
|
587
|
+
* the `<ui-command>` you put inside, as in shadcn's CommandDialog.
|
|
588
|
+
*/
|
|
589
|
+
export class UiCommandDialog extends UiDialog {
|
|
590
|
+
static rootTag = 'ui-command-dialog';
|
|
591
|
+
static contentTag = 'ui-command-dialog-content';
|
|
592
|
+
static slotPrefix = 'dialog';
|
|
593
|
+
|
|
594
|
+
// shadcn's CommandDialog passes its className to the DialogContent, so the
|
|
595
|
+
// class written on this host goes to the content, which puts it on the panel.
|
|
596
|
+
_authored: string | null = null;
|
|
597
|
+
|
|
598
|
+
render() {
|
|
599
|
+
this._authored = takeAuthoredClass(this, null);
|
|
600
|
+
const title = this.getAttribute?.('title') || 'Command Palette';
|
|
601
|
+
const description = this.getAttribute?.('description') || 'Search for a command to run...';
|
|
602
|
+
const close = this.getAttribute?.('show-close-button') ?? 'false';
|
|
603
|
+
return html`<div data-slot="dialog" data-state=${this.open ? 'open' : 'closed'}><ui-command-dialog-content
|
|
604
|
+
show-close-button=${close} class=${this._authored}><h2 data-slot="dialog-title" class="sr-only">${title}</h2><p
|
|
605
|
+
data-slot="dialog-description" class="sr-only">${description}</p><slot></slot></ui-command-dialog-content></div>`;
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
UiCommandDialog.register('ui-command-dialog');
|
|
609
|
+
|
|
610
|
+
export class UiCommandDialogContent extends UiDialogContent {
|
|
611
|
+
static rootTag = 'ui-command-dialog';
|
|
612
|
+
static slotPrefix = 'dialog';
|
|
613
|
+
|
|
614
|
+
_panelClass(): string {
|
|
615
|
+
return cn(super._panelClass(), commandDialogClass());
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
UiCommandDialogContent.register('ui-command-dialog-content');
|