@webjsdev/ui 0.3.17 → 0.5.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 +67 -8
- 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 +644 -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 +8 -8
- package/packages/registry/components/field.ts +20 -18
- 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 +7 -4
- 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/dom.ts +3 -4
- 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 +52 -8
- package/packages/registry/registry.json +4056 -72
- 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 +266 -14
- package/src/commands/diff.js +34 -20
- package/src/commands/info.js +7 -0
- package/src/commands/init.js +127 -10
- package/src/commands/list.js +43 -11
- package/src/commands/view.js +33 -5
- package/src/lint/rules/no-restyle.js +1 -1
- package/src/registry/extract.js +194 -5
- 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
package/src/registry/local.js
CHANGED
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
BASE_OVERRIDES,
|
|
33
33
|
mergeThemeCss,
|
|
34
34
|
} from '../../packages/registry/themes/base-colors.js';
|
|
35
|
+
import { designSystemItem, designSystemItems } from '../../packages/registry/themes/items.js';
|
|
35
36
|
|
|
36
37
|
/** Absolute path to the packaged registry root (`packages/ui/packages/registry`). */
|
|
37
38
|
export const REGISTRY_ROOT = resolve(
|
|
@@ -136,6 +137,14 @@ export function loadRegistryItem(name) {
|
|
|
136
137
|
}
|
|
137
138
|
}
|
|
138
139
|
|
|
140
|
+
// The accent themes and the font items, built from data (#1666).
|
|
141
|
+
const data = designSystemItem(name);
|
|
142
|
+
if (data) {
|
|
143
|
+
const composed = { $schema: SCHEMA, ...data };
|
|
144
|
+
itemCache.set(name, composed);
|
|
145
|
+
return composed;
|
|
146
|
+
}
|
|
147
|
+
|
|
139
148
|
return null;
|
|
140
149
|
}
|
|
141
150
|
|
|
@@ -147,10 +156,14 @@ export function loadRegistryItem(name) {
|
|
|
147
156
|
*/
|
|
148
157
|
export function loadRegistryIndex() {
|
|
149
158
|
if (indexCache) return indexCache;
|
|
159
|
+
// `title` and `categories` ride along so a block or chart can be listed and
|
|
160
|
+
// grouped without loading its files (D18).
|
|
150
161
|
const fromManifest = readManifest().items.map((item) => ({
|
|
151
162
|
name: item.name,
|
|
152
163
|
type: item.type,
|
|
164
|
+
title: item.title,
|
|
153
165
|
description: item.description,
|
|
166
|
+
categories: item.categories,
|
|
154
167
|
dependencies: item.dependencies,
|
|
155
168
|
registryDependencies: item.registryDependencies,
|
|
156
169
|
}));
|
|
@@ -162,7 +175,8 @@ export function loadRegistryIndex() {
|
|
|
162
175
|
type: 'registry:theme',
|
|
163
176
|
description: BASE_DESCRIPTIONS[color],
|
|
164
177
|
}));
|
|
165
|
-
|
|
178
|
+
const data = designSystemItems().map(({ name, type, title, description }) => ({ name, type, title, description }));
|
|
179
|
+
indexCache = [...fromManifest, ...synthesized, ...data];
|
|
166
180
|
return indexCache;
|
|
167
181
|
}
|
|
168
182
|
|
package/src/registry/schema.js
CHANGED
|
@@ -62,6 +62,18 @@ const cssValueSchema = z.lazy(() =>
|
|
|
62
62
|
export const registryItemCssSchema = z.record(z.string(), cssValueSchema);
|
|
63
63
|
export const registryItemEnvVarsSchema = z.record(z.string(), z.string());
|
|
64
64
|
|
|
65
|
+
/** A `registry:font` item's face (shadcn's `registryItemFontSchema`, #1666). */
|
|
66
|
+
export const registryItemFontSchema = z.object({
|
|
67
|
+
family: z.string(),
|
|
68
|
+
provider: z.literal('google'),
|
|
69
|
+
import: z.string(),
|
|
70
|
+
variable: z.string(),
|
|
71
|
+
weight: z.array(z.string()).optional(),
|
|
72
|
+
subsets: z.array(z.string()).optional(),
|
|
73
|
+
selector: z.string().optional(),
|
|
74
|
+
dependency: z.string().optional(),
|
|
75
|
+
});
|
|
76
|
+
|
|
65
77
|
export const registryItemCommonSchema = z.object({
|
|
66
78
|
$schema: z.string().optional(),
|
|
67
79
|
extends: z.string().optional(),
|
|
@@ -80,6 +92,7 @@ export const registryItemCommonSchema = z.object({
|
|
|
80
92
|
meta: z.record(z.string(), z.any()).optional(),
|
|
81
93
|
docs: z.string().optional(),
|
|
82
94
|
categories: z.array(z.string()).optional(),
|
|
95
|
+
font: registryItemFontSchema.optional(),
|
|
83
96
|
});
|
|
84
97
|
|
|
85
98
|
/** A rule's severity. Absent from `lint.rules` means `off`. */
|
|
@@ -0,0 +1,506 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The style bake (#1666, D8): turn a registry component written in BASE FORM
|
|
3
|
+
* into plain Tailwind for one chosen style.
|
|
4
|
+
*
|
|
5
|
+
* A base-form component carries shadcn's semantic class names alongside the
|
|
6
|
+
* layout classes it keeps inline, the way shadcn's own
|
|
7
|
+
* `registry/bases/radix/ui/*.tsx` does:
|
|
8
|
+
*
|
|
9
|
+
* const BASE = 'cn-button group/button inline-flex shrink-0 items-center ...';
|
|
10
|
+
*
|
|
11
|
+
* A STYLE is a file of nested rules that map each of those names to Tailwind
|
|
12
|
+
* through `@apply`, all under one `.style-<name>` wrapper:
|
|
13
|
+
*
|
|
14
|
+
* .style-nova { .cn-button { @apply rounded-lg border text-sm ...; } }
|
|
15
|
+
*
|
|
16
|
+
* The bake replaces each `cn-*` name with the classes its style maps it to,
|
|
17
|
+
* ahead of the classes already in the string, and drops the name. It runs
|
|
18
|
+
* wherever an app or an agent READS code: `add` and `diff` (through
|
|
19
|
+
* `transformForProject`), `webjs ui view`, and the MCP `ui` tool. So an
|
|
20
|
+
* installed file, and anything an agent copies, is plain readable Tailwind
|
|
21
|
+
* with no `cn-*` name in it, and `cn()` merging keeps working on it.
|
|
22
|
+
*
|
|
23
|
+
* This is a port of shadcn's `createStyleMap` and `transformStyle`
|
|
24
|
+
* (`packages/shadcn/src/styles/` in the shadcn repo), written without postcss
|
|
25
|
+
* or ts-morph so the CLI gains no dependency. Two deliberate differences:
|
|
26
|
+
*
|
|
27
|
+
* - shadcn inlines a name only at its FIRST occurrence in a file. Here every
|
|
28
|
+
* occurrence is inlined, because a Tier-2 template can render the same part
|
|
29
|
+
* in two branches and both must be styled.
|
|
30
|
+
* - shadcn merges with tailwind-merge. Here the mapped classes are placed
|
|
31
|
+
* BEFORE the string's own classes with exact duplicates dropped, and the
|
|
32
|
+
* component's runtime `cn()` (or the class attribute as written) resolves
|
|
33
|
+
* the rest. Placing them first is what lets an inline layout class win a
|
|
34
|
+
* conflict, the same precedence `twMerge(mapped, original)` gives.
|
|
35
|
+
*
|
|
36
|
+
* A `cn-*` name must sit in static text: a string literal, or the static part
|
|
37
|
+
* of a `class="..."` attribute in an `html` template. A name produced inside a
|
|
38
|
+
* `${...}` hole is never seen and never baked.
|
|
39
|
+
*/
|
|
40
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
41
|
+
import { join } from 'node:path';
|
|
42
|
+
import { REGISTRY_ROOT } from './local.js';
|
|
43
|
+
|
|
44
|
+
const CN_PREFIX = 'cn-';
|
|
45
|
+
const CN_TOKEN = /^cn-[\w-]+$/;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Names that survive the bake, because they are hooks rather than styles: a
|
|
49
|
+
* selector elsewhere targets them, or the CLI rewrites them at install time.
|
|
50
|
+
* shadcn's own list (`ALLOWLIST` in transform-style-map.ts).
|
|
51
|
+
*/
|
|
52
|
+
export const CN_ALLOWLIST = new Set([
|
|
53
|
+
'cn-menu-target',
|
|
54
|
+
'cn-menu-translucent',
|
|
55
|
+
'cn-logical-sides',
|
|
56
|
+
'cn-rtl-flip',
|
|
57
|
+
'cn-font-heading',
|
|
58
|
+
]);
|
|
59
|
+
|
|
60
|
+
/** The styles the kit ships, in the order a picker lists them. `new-york` is the default. */
|
|
61
|
+
export const STYLE_NAMES = ['new-york', 'vega', 'nova', 'maia', 'lyra', 'mira', 'luma', 'sera', 'rhea'];
|
|
62
|
+
export const DEFAULT_STYLE = 'new-york';
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Normalise a `components.json` `style` value to a style the kit ships.
|
|
66
|
+
* `'default'` (the schema's default) and an absent value mean `new-york`.
|
|
67
|
+
* @param {string | undefined | null} style
|
|
68
|
+
*/
|
|
69
|
+
export function resolveStyleName(style) {
|
|
70
|
+
if (!style || style === 'default') return DEFAULT_STYLE;
|
|
71
|
+
return STYLE_NAMES.includes(style) ? style : DEFAULT_STYLE;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
// Style map: CSS with @apply rules -> { 'cn-x': 'tailwind classes' }
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Build the style map from a style file's CSS. Mirrors shadcn's
|
|
80
|
+
* `createStyleMap`: every rule whose body holds `@apply` contributes its
|
|
81
|
+
* classes to the LAST `cn-*` class of each selector in its selector list,
|
|
82
|
+
* with `&` removed; a later rule for the same name is PREPENDED to what the
|
|
83
|
+
* earlier ones gave it. A rule with no `@apply` contributes nothing.
|
|
84
|
+
*
|
|
85
|
+
* @param {string} css
|
|
86
|
+
* @returns {Record<string, string>}
|
|
87
|
+
*/
|
|
88
|
+
export function createStyleMap(css) {
|
|
89
|
+
/** @type {Record<string, string>} */
|
|
90
|
+
const result = {};
|
|
91
|
+
const src = stripCssComments(css);
|
|
92
|
+
/** @type {string[][]} */
|
|
93
|
+
const stack = []; // selector lists of the enclosing rules (unused for the subject, kept for clarity)
|
|
94
|
+
let i = 0;
|
|
95
|
+
let buf = '';
|
|
96
|
+
/** @type {{ selectors: string[], applies: string[] }[]} */
|
|
97
|
+
const frames = [];
|
|
98
|
+
while (i < src.length) {
|
|
99
|
+
const ch = src[i];
|
|
100
|
+
if (ch === '{') {
|
|
101
|
+
const prelude = buf.trim();
|
|
102
|
+
buf = '';
|
|
103
|
+
const selectors = prelude.startsWith('@') ? [] : splitSelectors(prelude);
|
|
104
|
+
frames.push({ selectors, applies: [] });
|
|
105
|
+
stack.push(selectors);
|
|
106
|
+
i++;
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
if (ch === '}') {
|
|
110
|
+
const frame = frames.pop();
|
|
111
|
+
stack.pop();
|
|
112
|
+
buf = '';
|
|
113
|
+
if (frame && frame.applies.length) {
|
|
114
|
+
const classes = frame.applies.join(' ');
|
|
115
|
+
for (const sel of frame.selectors) {
|
|
116
|
+
const subject = subjectClass(sel.replace(/\s*&\s*/g, '').trim());
|
|
117
|
+
if (!subject) continue;
|
|
118
|
+
result[subject] = result[subject] ? `${classes} ${result[subject]}` : classes;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
i++;
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
if (ch === ';') {
|
|
125
|
+
const decl = buf.trim();
|
|
126
|
+
buf = '';
|
|
127
|
+
const m = /^@apply\s+([\s\S]+)$/.exec(decl);
|
|
128
|
+
if (m && frames.length) {
|
|
129
|
+
const value = m[1].trim().replace(/\s+/g, ' ');
|
|
130
|
+
if (value) frames[frames.length - 1].applies.push(value);
|
|
131
|
+
}
|
|
132
|
+
i++;
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
buf += ch;
|
|
136
|
+
i++;
|
|
137
|
+
}
|
|
138
|
+
return result;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** @param {string} css */
|
|
142
|
+
function stripCssComments(css) {
|
|
143
|
+
return css.replace(/\/\*[\s\S]*?\*\//g, ' ');
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/** Split a selector list on top-level commas (not inside () or []). */
|
|
147
|
+
function splitSelectors(prelude) {
|
|
148
|
+
const out = [];
|
|
149
|
+
let depth = 0;
|
|
150
|
+
let cur = '';
|
|
151
|
+
for (const ch of prelude) {
|
|
152
|
+
if (ch === '(' || ch === '[') depth++;
|
|
153
|
+
else if (ch === ')' || ch === ']') depth--;
|
|
154
|
+
if (ch === ',' && depth === 0) { out.push(cur.trim()); cur = ''; continue; }
|
|
155
|
+
cur += ch;
|
|
156
|
+
}
|
|
157
|
+
if (cur.trim()) out.push(cur.trim());
|
|
158
|
+
return out;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** The last `.cn-*` class in a selector, ignoring anything inside [] or (). */
|
|
162
|
+
function subjectClass(selector) {
|
|
163
|
+
let depth = 0;
|
|
164
|
+
let last = null;
|
|
165
|
+
for (let i = 0; i < selector.length; i++) {
|
|
166
|
+
const ch = selector[i];
|
|
167
|
+
if (ch === '(' || ch === '[') { depth++; continue; }
|
|
168
|
+
if (ch === ')' || ch === ']') { depth--; continue; }
|
|
169
|
+
if (depth === 0 && ch === '.' && selector.startsWith(CN_PREFIX, i + 1)) {
|
|
170
|
+
const m = /^[\w-]+/.exec(selector.slice(i + 1));
|
|
171
|
+
if (m) last = m[0];
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return last;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** @type {Map<string, Record<string, string>>} */
|
|
178
|
+
const MAP_CACHE = new Map();
|
|
179
|
+
|
|
180
|
+
/** Absolute path of a shipped style file. */
|
|
181
|
+
export function styleFilePath(name) {
|
|
182
|
+
return join(REGISTRY_ROOT, 'styles', `style-${name}.css`);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* The style map for one shipped style, read from the packaged registry and
|
|
187
|
+
* cached. An unknown or missing style yields an empty map, which bakes every
|
|
188
|
+
* `cn-*` name away to nothing rather than leaking it.
|
|
189
|
+
* @param {string | undefined | null} style
|
|
190
|
+
*/
|
|
191
|
+
export function loadStyleMap(style) {
|
|
192
|
+
const name = resolveStyleName(style);
|
|
193
|
+
const cached = MAP_CACHE.get(name);
|
|
194
|
+
if (cached) return cached;
|
|
195
|
+
const file = styleFilePath(name);
|
|
196
|
+
const map = existsSync(file) ? createStyleMap(readFileSync(file, 'utf8')) : {};
|
|
197
|
+
MAP_CACHE.set(name, map);
|
|
198
|
+
return map;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// ---------------------------------------------------------------------------
|
|
202
|
+
// Class segments: where in a JS/TS source a class list can sit
|
|
203
|
+
// ---------------------------------------------------------------------------
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* @typedef {{ start: number, end: number, quote: "'" | '"' | '`' | 'attr' }} Segment
|
|
207
|
+
* `start` / `end` delimit the RAW source text of the segment (between the
|
|
208
|
+
* quotes, or the static run of a class attribute). `quote` is the delimiter
|
|
209
|
+
* the text must stay legal inside.
|
|
210
|
+
*/
|
|
211
|
+
|
|
212
|
+
const REGEX_PRECEDERS = new Set(['(', ',', '=', ':', '[', '!', '&', '|', '?', '{', '}', ';', '+', '-', '*', '%', '<', '>', '~', '^']);
|
|
213
|
+
const REGEX_KEYWORDS = new Set(['return', 'typeof', 'case', 'do', 'else', 'in', 'of', 'new', 'delete', 'void', 'throw', 'yield', 'await']);
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Find every string literal in a JS/TS source, plus every static run of a
|
|
217
|
+
* `class="..."` attribute inside an `html` tagged template. This one function
|
|
218
|
+
* is what the bake rewrites, what the fixture records and what the snapshot
|
|
219
|
+
* test compares, so the three cannot disagree about which strings carry
|
|
220
|
+
* classes. Comments and regex literals are skipped. A template literal with
|
|
221
|
+
* no holes is a plain string; a template with holes contributes nothing of
|
|
222
|
+
* its own unless it is an `html` template, where only class attribute text
|
|
223
|
+
* counts.
|
|
224
|
+
*
|
|
225
|
+
* @param {string} src
|
|
226
|
+
* @returns {Segment[]}
|
|
227
|
+
*/
|
|
228
|
+
export function classSegments(src) {
|
|
229
|
+
/** @type {Segment[]} */
|
|
230
|
+
const segs = [];
|
|
231
|
+
let i = 0;
|
|
232
|
+
let prevSig = ''; // last significant code char, for regex detection
|
|
233
|
+
let prevWord = '';
|
|
234
|
+
/** @type {{ html: boolean, inClass: boolean, attrQuote: string, runStart: number }[]} */
|
|
235
|
+
const tpl = []; // open template literals (innermost last)
|
|
236
|
+
/** @type {number[]} */
|
|
237
|
+
const holeDepth = []; // brace depth inside each open ${ } hole
|
|
238
|
+
|
|
239
|
+
const n = src.length;
|
|
240
|
+
const inCode = () => tpl.length === 0 || holeDepth.length === tpl.length;
|
|
241
|
+
|
|
242
|
+
while (i < n) {
|
|
243
|
+
if (!inCode()) {
|
|
244
|
+
// Inside the static text of the innermost template.
|
|
245
|
+
const t = tpl[tpl.length - 1];
|
|
246
|
+
const ch = src[i];
|
|
247
|
+
if (ch === '\\') { i += 2; continue; }
|
|
248
|
+
if (ch === '`') {
|
|
249
|
+
if (t.html && t.inClass && i > t.runStart) segs.push({ start: t.runStart, end: i, quote: 'attr' });
|
|
250
|
+
tpl.pop();
|
|
251
|
+
i++;
|
|
252
|
+
prevSig = ')';
|
|
253
|
+
prevWord = '';
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
if (ch === '$' && src[i + 1] === '{') {
|
|
257
|
+
if (t.html && t.inClass && i > t.runStart) segs.push({ start: t.runStart, end: i, quote: 'attr' });
|
|
258
|
+
holeDepth.push(0);
|
|
259
|
+
i += 2;
|
|
260
|
+
prevSig = '{';
|
|
261
|
+
prevWord = '';
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
if (t.html) {
|
|
265
|
+
if (t.inClass) {
|
|
266
|
+
if (ch === t.attrQuote) {
|
|
267
|
+
if (i > t.runStart) segs.push({ start: t.runStart, end: i, quote: 'attr' });
|
|
268
|
+
t.inClass = false;
|
|
269
|
+
}
|
|
270
|
+
} else {
|
|
271
|
+
const m = /^class=(["'])/.exec(src.slice(i, i + 7));
|
|
272
|
+
if (m && /[\s<]/.test(src[i - 1] || ' ')) {
|
|
273
|
+
t.inClass = true;
|
|
274
|
+
t.attrQuote = m[1];
|
|
275
|
+
i += 7;
|
|
276
|
+
t.runStart = i;
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
i++;
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Code.
|
|
286
|
+
const ch = src[i];
|
|
287
|
+
if (ch === '/' && src[i + 1] === '/') { const e = src.indexOf('\n', i); i = e < 0 ? n : e; continue; }
|
|
288
|
+
if (ch === '/' && src[i + 1] === '*') { const e = src.indexOf('*/', i + 2); i = e < 0 ? n : e + 2; continue; }
|
|
289
|
+
if (ch === "'" || ch === '"') {
|
|
290
|
+
const start = i + 1;
|
|
291
|
+
let j = start;
|
|
292
|
+
while (j < n && src[j] !== ch) { if (src[j] === '\\') j++; if (src[j] === '\n') break; j++; }
|
|
293
|
+
segs.push({ start, end: j, quote: ch });
|
|
294
|
+
i = j + 1;
|
|
295
|
+
prevSig = ')';
|
|
296
|
+
prevWord = '';
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
if (ch === '`') {
|
|
300
|
+
// A template with no holes is a plain string. Decide by scanning ahead.
|
|
301
|
+
const isHtml = /\bhtml\s*$/.test(src.slice(Math.max(0, i - 12), i));
|
|
302
|
+
let j = i + 1;
|
|
303
|
+
let hasHole = false;
|
|
304
|
+
while (j < n && src[j] !== '`') {
|
|
305
|
+
if (src[j] === '\\') { j += 2; continue; }
|
|
306
|
+
if (src[j] === '$' && src[j + 1] === '{') { hasHole = true; break; }
|
|
307
|
+
j++;
|
|
308
|
+
}
|
|
309
|
+
if (!hasHole && !isHtml) {
|
|
310
|
+
segs.push({ start: i + 1, end: j, quote: '`' });
|
|
311
|
+
i = j + 1;
|
|
312
|
+
prevSig = ')';
|
|
313
|
+
prevWord = '';
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
tpl.push({ html: isHtml, inClass: false, attrQuote: '"', runStart: 0 });
|
|
317
|
+
i++;
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
if (ch === '/' ) {
|
|
321
|
+
const regexAllowed = !prevSig || REGEX_PRECEDERS.has(prevSig) || REGEX_KEYWORDS.has(prevWord);
|
|
322
|
+
if (regexAllowed) {
|
|
323
|
+
let j = i + 1;
|
|
324
|
+
let inClassSet = false;
|
|
325
|
+
while (j < n) {
|
|
326
|
+
const c = src[j];
|
|
327
|
+
if (c === '\\') { j += 2; continue; }
|
|
328
|
+
if (c === '\n') break;
|
|
329
|
+
if (inClassSet) { if (c === ']') inClassSet = false; }
|
|
330
|
+
else if (c === '[') inClassSet = true;
|
|
331
|
+
else if (c === '/') break;
|
|
332
|
+
j++;
|
|
333
|
+
}
|
|
334
|
+
j++;
|
|
335
|
+
while (j < n && /[a-z]/i.test(src[j])) j++;
|
|
336
|
+
i = j;
|
|
337
|
+
prevSig = ')';
|
|
338
|
+
prevWord = '';
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
if (holeDepth.length && holeDepth.length === tpl.length) {
|
|
343
|
+
if (ch === '{') holeDepth[holeDepth.length - 1]++;
|
|
344
|
+
else if (ch === '}') {
|
|
345
|
+
if (holeDepth[holeDepth.length - 1] === 0) {
|
|
346
|
+
holeDepth.pop();
|
|
347
|
+
const t = tpl[tpl.length - 1];
|
|
348
|
+
i++;
|
|
349
|
+
t.runStart = i; // a class attribute continues after the hole
|
|
350
|
+
continue;
|
|
351
|
+
}
|
|
352
|
+
holeDepth[holeDepth.length - 1]--;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
if (/[A-Za-z_$]/.test(ch)) {
|
|
356
|
+
let j = i;
|
|
357
|
+
while (j < n && /[\w$]/.test(src[j])) j++;
|
|
358
|
+
prevWord = src.slice(i, j);
|
|
359
|
+
prevSig = 'a';
|
|
360
|
+
i = j;
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
363
|
+
if (!/\s/.test(ch)) { prevSig = ch; prevWord = ''; }
|
|
364
|
+
i++;
|
|
365
|
+
}
|
|
366
|
+
return segs;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* The cooked value of a segment: what the string MEANS at runtime, with its
|
|
371
|
+
* escapes resolved. Class attribute text is taken as written.
|
|
372
|
+
* @param {string} src
|
|
373
|
+
* @param {Segment} seg
|
|
374
|
+
*/
|
|
375
|
+
export function segmentValue(src, seg) {
|
|
376
|
+
const raw = src.slice(seg.start, seg.end);
|
|
377
|
+
if (seg.quote === 'attr') return raw;
|
|
378
|
+
return raw.replace(/\\(u\{[0-9a-fA-F]+\}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{2}|[\s\S])/g, (_, e) => {
|
|
379
|
+
if (e[0] === 'u' && e[1] === '{') return String.fromCodePoint(parseInt(e.slice(2, -1), 16));
|
|
380
|
+
if (e[0] === 'u' && e.length === 5) return String.fromCharCode(parseInt(e.slice(1), 16));
|
|
381
|
+
if (e[0] === 'x' && e.length === 3) return String.fromCharCode(parseInt(e.slice(1), 16));
|
|
382
|
+
return { n: '\n', t: '\t', r: '\r', b: '\b', f: '\f', v: '\v', 0: '\0' }[e] ?? e;
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Write a cooked value back inside the delimiter it sits in.
|
|
388
|
+
*
|
|
389
|
+
* The result must read right TWICE: as JavaScript (or an HTML attribute), and
|
|
390
|
+
* as the raw text Tailwind's scanner reads, which never unescapes anything. So
|
|
391
|
+
* a quote is never escaped with a backslash or an entity if it can be helped:
|
|
392
|
+
* `[class*=\'size-\']` is valid JavaScript, but Tailwind compiles the
|
|
393
|
+
* backslashes into the selector and the rule never matches. bakeSource()
|
|
394
|
+
* avoids it for a JS string by changing the string's delimiter (see there).
|
|
395
|
+
* In an HTML attribute a double quote becomes a single one, which means the
|
|
396
|
+
* same in a CSS string or attribute value. Escaping is the last resort, for a
|
|
397
|
+
* value carrying both quotes, which no style emits.
|
|
398
|
+
*/
|
|
399
|
+
function escapeFor(value, quote) {
|
|
400
|
+
if (quote === 'attr') {
|
|
401
|
+
if (!value.includes('"')) return value;
|
|
402
|
+
return value.includes("'") ? value.replace(/"/g, '"') : value.replace(/"/g, "'");
|
|
403
|
+
}
|
|
404
|
+
let out = value.replace(/\\/g, '\\\\');
|
|
405
|
+
if (quote === '`') return out.replace(/`/g, '\\`').replace(/\$\{/g, '\\${');
|
|
406
|
+
return out.replace(new RegExp(quote, 'g'), `\\${quote}`);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// ---------------------------------------------------------------------------
|
|
410
|
+
// The bake
|
|
411
|
+
// ---------------------------------------------------------------------------
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Bake one class list. Every `cn-*` name is replaced by the classes the map
|
|
415
|
+
* gives it (none, when the map has no entry), the mapped classes go FIRST,
|
|
416
|
+
* the allowlisted hooks stay, and exact duplicates are dropped.
|
|
417
|
+
*
|
|
418
|
+
* @param {string} value a cooked class list
|
|
419
|
+
* @param {Record<string, string>} styleMap
|
|
420
|
+
*/
|
|
421
|
+
export function bakeClassList(value, styleMap) {
|
|
422
|
+
const tokens = value.split(/\s+/).filter(Boolean);
|
|
423
|
+
if (!tokens.some((t) => CN_TOKEN.test(t))) return value;
|
|
424
|
+
const mapped = [];
|
|
425
|
+
const rest = [];
|
|
426
|
+
for (const t of tokens) {
|
|
427
|
+
if (CN_TOKEN.test(t)) {
|
|
428
|
+
if (CN_ALLOWLIST.has(t)) rest.push(t);
|
|
429
|
+
else if (styleMap[t]) mapped.push(...styleMap[t].split(/\s+/).filter(Boolean));
|
|
430
|
+
} else {
|
|
431
|
+
rest.push(t);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
const seen = new Set();
|
|
435
|
+
const out = [];
|
|
436
|
+
for (const t of [...mapped, ...rest]) {
|
|
437
|
+
if (seen.has(t)) continue;
|
|
438
|
+
seen.add(t);
|
|
439
|
+
out.push(t);
|
|
440
|
+
}
|
|
441
|
+
// Keep the original's leading / trailing whitespace, so a class list that
|
|
442
|
+
// was concatenated into a longer string still has its separators.
|
|
443
|
+
const lead = /^\s*/.exec(value)[0];
|
|
444
|
+
const trail = /\s*$/.exec(value)[0];
|
|
445
|
+
return out.length ? lead + out.join(' ') + trail : (lead || trail ? ' ' : '');
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Bake a whole source file for one style map. A file with no `cn-*` name
|
|
450
|
+
* comes back unchanged, byte for byte.
|
|
451
|
+
*
|
|
452
|
+
* @param {string} src
|
|
453
|
+
* @param {Record<string, string>} styleMap
|
|
454
|
+
*/
|
|
455
|
+
export function bakeSource(src, styleMap) {
|
|
456
|
+
if (!src.includes(CN_PREFIX)) return src;
|
|
457
|
+
const segs = classSegments(src);
|
|
458
|
+
let out = '';
|
|
459
|
+
let last = 0;
|
|
460
|
+
for (const seg of segs) {
|
|
461
|
+
const value = segmentValue(src, seg);
|
|
462
|
+
if (!/(^|\s)cn-[\w-]/.test(value)) continue;
|
|
463
|
+
const baked = bakeClassList(value, styleMap);
|
|
464
|
+
// A class that carries the string's own quote (the styles' `[class*='size-']`
|
|
465
|
+
// inside a single-quoted string) moves the string to the other quote, the
|
|
466
|
+
// way a person writes it, rather than escaping: Tailwind reads the raw
|
|
467
|
+
// text and would keep the backslashes.
|
|
468
|
+
const q = seg.quote;
|
|
469
|
+
const other = q === "'" ? '"' : q === '"' ? "'" : '';
|
|
470
|
+
if (other && baked.includes(q) && !baked.includes(other)) {
|
|
471
|
+
out += src.slice(last, seg.start - 1) + other + escapeFor(baked, other) + other;
|
|
472
|
+
last = seg.end + 1;
|
|
473
|
+
continue;
|
|
474
|
+
}
|
|
475
|
+
out += src.slice(last, seg.start) + escapeFor(baked, q);
|
|
476
|
+
last = seg.end;
|
|
477
|
+
}
|
|
478
|
+
return out + src.slice(last);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Bake for a project: the style named in its `components.json`, `new-york`
|
|
483
|
+
* when there is none. This is the entry `transformForProject` and the kit
|
|
484
|
+
* projector call.
|
|
485
|
+
*
|
|
486
|
+
* @param {string} src
|
|
487
|
+
* @param {string | undefined | null} style
|
|
488
|
+
*/
|
|
489
|
+
export function bakeForStyle(src, style) {
|
|
490
|
+
return bakeSource(src, loadStyleMap(style));
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* Every `cn-*` name left in a baked source outside the allowlist. A test uses
|
|
495
|
+
* it to prove nothing an app or agent reads ever carries one.
|
|
496
|
+
* @param {string} src
|
|
497
|
+
*/
|
|
498
|
+
export function leftoverCnNames(src) {
|
|
499
|
+
const names = new Set();
|
|
500
|
+
for (const seg of classSegments(src)) {
|
|
501
|
+
for (const t of segmentValue(src, seg).split(/\s+/)) {
|
|
502
|
+
if (CN_TOKEN.test(t) && !CN_ALLOWLIST.has(t)) names.add(t);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
return [...names];
|
|
506
|
+
}
|