themelia-ui 3.0.0 → 3.2.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/.agents/skills/themelia-ui/SKILL.md +60 -33
- package/.agents/skills/themelia-ui/manifest.json +23 -0
- package/.agents/skills/themelia-ui/references/api-compatibility.md +5 -4
- package/.agents/skills/themelia-ui/references/blocks.md +123 -0
- package/.agents/skills/themelia-ui/references/composition-ladder.md +8 -8
- package/.agents/skills/themelia-ui/references/composition.md +100 -19
- package/.agents/skills/themelia-ui/references/forms.md +23 -3
- package/.agents/skills/themelia-ui/references/framework-wiring.md +41 -13
- package/.agents/skills/themelia-ui/references/i18n.md +4 -2
- package/.agents/skills/themelia-ui/references/imports.md +104 -104
- package/.agents/skills/themelia-ui/references/installation.md +60 -31
- package/.agents/skills/themelia-ui/references/migration.md +156 -5
- package/.agents/skills/themelia-ui/references/provider-and-scoping.md +37 -25
- package/.agents/skills/themelia-ui/references/reference-workflows.md +43 -0
- package/.agents/skills/themelia-ui/references/structure-and-spacing.md +147 -0
- package/.agents/skills/themelia-ui/references/theming.md +174 -131
- package/.agents/skills/themelia-ui/references/troubleshooting.md +88 -30
- package/.agents/skills/themelia-ui/references/verification.md +60 -5
- package/CHANGELOG.md +212 -0
- package/README.md +48 -60
- package/dist/accordion-CHuzMmWL.js +143 -0
- package/dist/{action-menu-BNLURfMK.js → action-menu-BwiL_F6I.js} +35 -33
- package/dist/{alert-dialog-BMVo6Z-8.js → alert-dialog-Cg2HhuBe.js} +1 -1
- package/dist/avatar-Dc_BNYfB.js +93 -0
- package/dist/badge-VlJVZjdm.js +45 -0
- package/dist/base/accordion.js +1 -1
- package/dist/base/action-menu.js +1 -1
- package/dist/base/alert-dialog.js +1 -1
- package/dist/base/aspect-ratio.js +3 -1
- package/dist/base/avatar.js +1 -1
- package/dist/base/badge.js +2 -2
- package/dist/base/batch-action-bar.js +1 -1
- package/dist/base/buttons.js +1 -1
- package/dist/base/cards.js +1 -1
- package/dist/base/carousel.js +6 -4
- package/dist/base/chart.js +1 -1
- package/dist/base/choice-inputs.js +1 -1
- package/dist/base/combobox.js +1 -1
- package/dist/base/command.js +1 -1
- package/dist/base/context-menu.js +22 -21
- package/dist/base/copyable.js +1 -1
- package/dist/base/date-pickers.js +1 -1
- package/dist/base/dialog.js +1 -1
- package/dist/base/display.js +1 -1
- package/dist/base/dropdown-menu.js +1 -1
- package/dist/base/feedback.js +1 -1
- package/dist/base/forms-numeric.js +1 -1
- package/dist/base/forms.js +1 -1
- package/dist/base/hover-card.js +26 -23
- package/dist/base/input-group.js +1 -1
- package/dist/base/item.js +1 -1
- package/dist/base/label.js +1 -1
- package/dist/base/menubar.js +20 -14
- package/dist/base/navigation-menu.js +47 -38
- package/dist/base/navigation.js +1 -1
- package/dist/base/otp-input.js +36 -30
- package/dist/base/overlay.js +1 -1
- package/dist/base/popover-menu.js +1 -1
- package/dist/base/popover.js +1 -1
- package/dist/base/qr-code.js +51 -47
- package/dist/base/repeaters.js +1 -1
- package/dist/base/resizable.js +2 -0
- package/dist/base/sheet.js +1 -1
- package/dist/base/sidebar.js +1 -1
- package/dist/base/skeleton.js +1 -1
- package/dist/base/spinner.js +1 -1
- package/dist/base/structure.js +1 -1
- package/dist/base/table.js +1 -1
- package/dist/base/text-inputs.js +1 -1
- package/dist/base/timeline.js +1 -1
- package/dist/base/toaster.js +1 -1
- package/dist/base/toggle.js +21 -15
- package/dist/base/toolbar.js +1 -1
- package/dist/base/tooltip.js +1 -1
- package/dist/base/typography.js +2 -2
- package/dist/base/upload.js +1 -1
- package/dist/base/value-inputs.js +1 -1
- package/dist/{batch-action-bar-BZYNKXdV.js → batch-action-bar-DZVMVW83.js} +11 -8
- package/dist/{admin/patterns → blocks/admin}/access.js +79 -76
- package/dist/blocks/admin/commerce.js +2493 -0
- package/dist/{patterns → blocks}/analytics.js +312 -303
- package/dist/{patterns → blocks}/onboarding.js +27 -23
- package/dist/{patterns → blocks}/timelines.js +1 -1
- package/dist/buttons-BX2JfL5X.js +173 -0
- package/dist/cards-Ddhz43Bz.js +279 -0
- package/dist/chart-BkK3Xm10.js +201 -0
- package/dist/choice-inputs-NwRxvmZN.js +694 -0
- package/dist/combobox-519ubijc.js +292 -0
- package/dist/command-JjApYFds.js +156 -0
- package/dist/comments-CCQ2QRaU.js +1443 -0
- package/dist/components/base/action-menu/action-menu.d.ts +1 -1
- package/dist/components/base/action-menu/action-menu.types.d.ts +2 -2
- package/dist/components/base/avatar/avatar.d.ts +5 -2
- package/dist/components/base/badge/badge.d.ts +10 -10
- package/dist/components/base/badge/badge.variants.d.ts +1 -2
- package/dist/components/base/badge/index.d.ts +1 -2
- package/dist/components/base/buttons/button.d.ts +9 -8
- package/dist/components/base/buttons/button.types.d.ts +2 -2
- package/dist/components/base/buttons/index.d.ts +1 -1
- package/dist/components/base/buttons/text-button.d.ts +1 -1
- package/dist/components/base/cards/card-actions.d.ts +1 -1
- package/dist/components/base/cards/card.d.ts +3 -1
- package/dist/components/base/cards/partials/card-header.d.ts +2 -1
- package/dist/components/base/choice-inputs/choice.types.d.ts +2 -2
- package/dist/components/base/choice-inputs/partials/choice-parts.d.ts +3 -3
- package/dist/components/base/command/command.d.ts +5 -2
- package/dist/components/base/display/icon-badge.d.ts +5 -3
- package/dist/components/base/display/index.d.ts +1 -1
- package/dist/components/base/display/metadata-list.d.ts +6 -6
- package/dist/components/base/display/metadata-value.d.ts +1 -1
- package/dist/components/base/display/separator.d.ts +2 -2
- package/dist/components/base/feedback/alert.d.ts +3 -2
- package/dist/components/base/feedback/empty.d.ts +5 -4
- package/dist/components/base/feedback/progress-circle.d.ts +2 -2
- package/dist/components/base/feedback/progress.d.ts +3 -1
- package/dist/components/base/forms/form-field.d.ts +2 -2
- package/dist/components/base/input-group/input-group.d.ts +8 -10
- package/dist/components/base/item/item.d.ts +2 -2
- package/dist/components/base/overlay/index.d.ts +1 -1
- package/dist/components/base/overlay/overlay.types.d.ts +7 -5
- package/dist/components/base/qr-code/qr-code.d.ts +4 -4
- package/dist/components/base/sheet/sheet.d.ts +1 -1
- package/dist/components/base/sidebar/sidebar.d.ts +9 -13
- package/dist/components/base/spinner/spinner.d.ts +2 -2
- package/dist/components/base/structure/adaptive-grid.d.ts +3 -3
- package/dist/components/base/structure/bleed.d.ts +4 -2
- package/dist/components/base/structure/grid.d.ts +10 -4
- package/dist/components/base/structure/index.d.ts +1 -1
- package/dist/components/base/structure/split.d.ts +4 -3
- package/dist/components/base/structure/stack.d.ts +5 -5
- package/dist/components/base/structure/structure.maps.d.ts +2 -1
- package/dist/components/base/structure/structure.types.d.ts +10 -4
- package/dist/components/base/toggle/toggle.d.ts +2 -2
- package/dist/components/base/toolbar/toolbar.d.ts +3 -3
- package/dist/components/base/typography/index.d.ts +2 -0
- package/dist/components/base/typography/rich-text/rich-text.variants.d.ts +9 -0
- package/dist/components/base/typography/text/index.d.ts +1 -0
- package/dist/components/base/typography/text/text.d.ts +15 -8
- package/dist/components/base/typography/text/text.variants.d.ts +41 -0
- package/dist/components/base/value-inputs/color-input.d.ts +1 -7
- package/dist/components/base/value-inputs/slider.d.ts +2 -7
- package/dist/components/{admin/patterns → blocks/admin}/commerce/vendor-profile.d.ts +2 -1
- package/dist/components/{patterns → blocks}/analytics/analytics.strings.d.ts +2 -5
- package/dist/components/features/actions/action-adapters.d.ts +3 -3
- package/dist/components/features/actions/actions.types.d.ts +3 -5
- package/dist/components/features/actions/index.d.ts +1 -1
- package/dist/components/features/activities/activities-feed.d.ts +1 -1
- package/dist/components/features/activities/activities.types.d.ts +4 -4
- package/dist/components/features/activities/activity-parts.d.ts +3 -3
- package/dist/components/features/activities/activity-row.d.ts +4 -4
- package/dist/components/features/activities/index.d.ts +1 -1
- package/dist/components/features/ai-chat/ai-chat.types.d.ts +10 -3
- package/dist/components/features/ai-chat/ai-message-surfaces.d.ts +1 -1
- package/dist/components/features/ai-chat/ai-work-surfaces.d.ts +1 -1
- package/dist/components/features/combobox/combobox.strings.d.ts +2 -2
- package/dist/components/features/combobox/fetching-combobox.d.ts +2 -1
- package/dist/components/features/combobox/resource-combobox.d.ts +3 -0
- package/dist/components/features/combobox/use-suggestions.d.ts +7 -0
- package/dist/components/features/event-calendar/event-calendar.types.d.ts +3 -0
- package/dist/components/features/media-library/index.d.ts +1 -1
- package/dist/components/features/media-library/media-library-parts.d.ts +4 -3
- package/dist/components/features/media-library/media-library-views.d.ts +4 -3
- package/dist/components/features/media-library/media-library.d.ts +1 -1
- package/dist/components/features/media-library/media-library.strings.d.ts +12 -13
- package/dist/components/features/media-library/media-library.types.d.ts +11 -9
- package/dist/components/features/media-library/media-resource-gallery.d.ts +1 -1
- package/dist/components/features/media-library/use-media-library.d.ts +1 -4
- package/dist/components/features/overlays/action-overlay-frame.d.ts +1 -1
- package/dist/components/features/overlays/index.d.ts +1 -1
- package/dist/components/features/overlays/overlay-parts.d.ts +3 -3
- package/dist/components/features/overlays/overlays.types.d.ts +8 -7
- package/dist/components/features/rich-text-editor/index.d.ts +0 -1
- package/dist/components/features/table/data-table-body.d.ts +1 -1
- package/dist/components/features/table/data-table-expanded-row.d.ts +27 -0
- package/dist/components/features/table/data-table-header.d.ts +1 -1
- package/dist/components/features/table/data-table-size.d.ts +1 -1
- package/dist/components/features/table/data-table.d.ts +1 -1
- package/dist/components/features/table/index.d.ts +1 -1
- package/dist/components/features/table/table-helpers.d.ts +9 -3
- package/dist/components/features/table/table.strings.d.ts +11 -0
- package/dist/components/features/table/table.types.d.ts +60 -2
- package/dist/components/features/theme-tweaker/index.d.ts +1 -1
- package/dist/components/features/theme-tweaker/theme-tweaker.strings.d.ts +1 -1
- package/dist/components/features/theme-tweaker/theme-tweaker.types.d.ts +6 -10
- package/dist/components/features/theme-tweaker/theme-tweaker.utils.d.ts +22 -6
- package/dist/components/layout/app-shell/topbar-sidebar-layout.d.ts +1 -1
- package/dist/components/layout/auth/auth.d.ts +1 -1
- package/dist/components/layout/auth/auth.types.d.ts +1 -1
- package/dist/components/primitives/value.d.ts +3 -1
- package/dist/containers-B8d8U9GS.js +2 -0
- package/dist/{copyable-H1TUEY-H.js → copyable-D9Okb1w6.js} +12 -11
- package/dist/core.css +2 -2
- package/dist/css/access.css +2 -1
- package/dist/css/accordion.css +2 -1
- package/dist/css/action-menu.css +2 -1
- package/dist/css/activities.css +2 -1
- package/dist/css/ai-chat.css +2 -1
- package/dist/css/analytics.css +2 -1
- package/dist/css/app-shell.css +2 -1
- package/dist/css/aspect-ratio.css +2 -1
- package/dist/css/async-preview.css +2 -1
- package/dist/css/auth.css +2 -1
- package/dist/css/avatar.css +2 -1
- package/dist/css/badge.css +2 -1
- package/dist/css/batch-action-bar.css +2 -1
- package/dist/css/buttons.css +2 -1
- package/dist/css/cards.css +2 -1
- package/dist/css/carousel.css +2 -1
- package/dist/css/chart.css +2 -1
- package/dist/css/choice-inputs.css +2 -1
- package/dist/css/combobox.css +2 -1
- package/dist/css/combobox2.css +2 -1
- package/dist/css/command.css +2 -1
- package/dist/css/comments.css +2 -1
- package/dist/css/commerce.css +2 -1
- package/dist/css/containers.css +2 -1
- package/dist/css/copyable.css +2 -1
- package/dist/css/data-view.css +2 -1
- package/dist/css/date-pickers.css +2 -1
- package/dist/css/display.css +2 -1
- package/dist/css/dropdown-menu.css +2 -1
- package/dist/css/event-calendar.css +2 -1
- package/dist/css/feedback.css +2 -1
- package/dist/css/filters.css +2 -1
- package/dist/css/forms-numeric.css +2 -1
- package/dist/css/forms.css +2 -1
- package/dist/css/global-search.css +2 -1
- package/dist/css/header.css +2 -1
- package/dist/css/hover-card.css +2 -1
- package/dist/css/input-group.css +2 -1
- package/dist/css/item.css +2 -1
- package/dist/css/kanban.css +2 -1
- package/dist/css/label.css +2 -1
- package/dist/css/map.css +2 -1
- package/dist/css/media-library.css +2 -1
- package/dist/css/mentions.css +2 -1
- package/dist/css/menubar.css +2 -1
- package/dist/css/navigation-menu.css +2 -1
- package/dist/css/navigation.css +2 -1
- package/dist/css/navigation2.css +2 -1
- package/dist/css/onboarding.css +2 -1
- package/dist/css/otp-input.css +2 -1
- package/dist/css/overlay.css +2 -1
- package/dist/css/overlays.css +2 -1
- package/dist/css/page.css +2 -1
- package/dist/css/popover-menu.css +2 -1
- package/dist/css/popover.css +2 -1
- package/dist/css/primitives.css +2 -1
- package/dist/css/products.css +2 -1
- package/dist/css/qr-code.css +2 -1
- package/dist/css/repeaters.css +2 -1
- package/dist/css/resizable.css +2 -1
- package/dist/css/resource-assignment.css +2 -1
- package/dist/css/resource.css +2 -1
- package/dist/css/rich-text-editor.css +2 -1
- package/dist/css/schema-form.css +2 -1
- package/dist/css/sidebar.css +2 -1
- package/dist/css/sidebar2.css +2 -1
- package/dist/css/skeleton.css +2 -1
- package/dist/css/spinner.css +2 -1
- package/dist/css/structure.css +2 -1
- package/dist/css/sync.css +2 -1
- package/dist/css/table.css +2 -1
- package/dist/css/table2.css +2 -1
- package/dist/css/text-inputs.css +2 -1
- package/dist/css/theme-tweaker.css +2 -1
- package/dist/css/timeline.css +2 -1
- package/dist/css/timelines.css +2 -1
- package/dist/css/toaster.css +2 -1
- package/dist/css/toggle.css +2 -1
- package/dist/css/toolbar.css +2 -1
- package/dist/css/tooltip.css +2 -1
- package/dist/css/typography.css +2 -1
- package/dist/css/upload.css +2 -1
- package/dist/css/value-inputs.css +2 -1
- package/dist/css/workspace.css +2 -1
- package/dist/css-graph.json +1027 -0
- package/dist/date-pickers-BwCwKIVM.js +685 -0
- package/dist/{dialog-CtFCuTUF.js → dialog-CAnwRNrm.js} +1 -1
- package/dist/display-a7AoX_u7.js +664 -0
- package/dist/dropdown-menu-Br8kvjrF.js +235 -0
- package/dist/empty.js +0 -0
- package/dist/features/actions.js +6 -6
- package/dist/features/activities.js +219 -216
- package/dist/features/ai-chat.js +593 -565
- package/dist/features/async-preview.js +105 -286
- package/dist/features/combobox.js +328 -314
- package/dist/features/comments.js +1 -1
- package/dist/features/data-view.js +56 -55
- package/dist/features/event-calendar.js +189 -185
- package/dist/features/filters.js +1 -1
- package/dist/features/global-search.js +259 -260
- package/dist/features/kanban.js +39 -37
- package/dist/features/map.js +357 -354
- package/dist/features/media-library.js +931 -931
- package/dist/features/mentions.js +1 -1
- package/dist/features/overlays.js +1 -1
- package/dist/features/products.js +950 -942
- package/dist/features/resource-assignment.js +39 -37
- package/dist/features/resource.js +70 -71
- package/dist/features/rich-text-editor.js +2 -2
- package/dist/features/schema-form.js +342 -338
- package/dist/features/sync.js +14 -12
- package/dist/features/table.js +1 -1
- package/dist/features/theme-tweaker.js +1002 -962
- package/dist/feedback-D4qVsKlD.js +430 -0
- package/dist/{filters-DOLKRSmb.js → filters-BhsTkWpZ.js} +386 -383
- package/dist/forms-C0WeNPFF.js +250 -0
- package/dist/forms-numeric-IwQ1ltNf.js +582 -0
- package/dist/hooks/use-native-dialog.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/input-group-HS_Z0Ei_.js +119 -0
- package/dist/item-M2pmpWXh.js +150 -0
- package/dist/{label-DumoMDm6.js → label-HOBXAscw.js} +7 -5
- package/dist/layout/app-shell.js +4 -2
- package/dist/layout/auth.js +102 -100
- package/dist/layout/header.js +190 -180
- package/dist/layout/navigation.js +1 -1
- package/dist/layout/page.js +18 -16
- package/dist/layout/settings.js +2 -2
- package/dist/layout/sidebar.js +50 -46
- package/dist/layout/workspace.js +71 -69
- package/dist/lib/action-presentation.d.ts +3 -3
- package/dist/lib/component-vocabulary.d.ts +2 -2
- package/dist/lib/css-length.d.ts +2 -0
- package/dist/lib/responsive.d.ts +1 -1
- package/dist/lib/theming/index.d.ts +1 -0
- package/dist/lib/theming/recipes.d.ts +2 -2
- package/dist/lib/theming/themes/dense.d.ts +3 -0
- package/dist/lib/theming/themes/editorial.d.ts +3 -0
- package/dist/lib/theming/themes/index.d.ts +8 -0
- package/dist/lib/theming/themes/pair.d.ts +7 -0
- package/dist/lib/theming/themes/sharp.d.ts +3 -0
- package/dist/lib/theming/themes/soft.d.ts +3 -0
- package/dist/lib/theming/themes/types.d.ts +12 -0
- package/dist/lib/ui-provider/index.d.ts +1 -1
- package/dist/lib/ui-provider/scope.d.ts +5 -8
- package/dist/lib/ui-provider/tokens.d.ts +11 -3
- package/dist/lib/ui-provider/tokens.generated.d.ts +6 -4
- package/dist/lib/ui-provider/types.d.ts +17 -19
- package/dist/lib/ui-provider/ui-scope.d.ts +1 -1
- package/dist/{mentions-BbsEHlcH.js → mentions-BOxbigwp.js} +113 -111
- package/dist/navigation-Bgu7Vc0M.js +622 -0
- package/dist/navigation-DiYACqpE.js +216 -0
- package/dist/overlay-BuQOl8aP.js +356 -0
- package/dist/{overlays-DvVoS3td.js → overlays-1sULyytH.js} +77 -75
- package/dist/popover-CA7SP_iz.js +127 -0
- package/dist/popover-menu-QXgQeWeG.js +192 -0
- package/dist/{primitives-D0bdDozz.js → primitives-BskKlf35.js} +181 -178
- package/dist/primitives.js +1 -1
- package/dist/profiles/admin.json +6 -36
- package/dist/profiles/general.json +6 -96
- package/dist/repeaters-CeH20dvr.js +445 -0
- package/dist/rich-text-editor-D_Ppm8yh.js +491 -0
- package/dist/{sheet-CKcmRbJ9.js → sheet-CJ1-OAla.js} +3 -3
- package/dist/sidebar-D8uGqxio.js +421 -0
- package/dist/skeleton-BTKNKTdj.js +173 -0
- package/dist/spinner-Tc1QCnxM.js +30 -0
- package/dist/{structure-D0WGQAP3.js → structure-CynEZ-OY.js} +15 -23
- package/dist/style.css +1 -1
- package/dist/styles/TOKENS.md +116 -275
- package/dist/styles/animation.css +114 -0
- package/dist/styles/base.css +7 -6
- package/dist/styles/fields.css +45 -63
- package/dist/styles/focus.css +12 -0
- package/dist/styles/forced-colors.css +11 -10
- package/dist/styles/index.css +23 -30
- package/dist/styles/map.css +45 -34
- package/dist/styles/mentions.css +14 -52
- package/dist/styles/overlays.css +7 -7
- package/dist/styles/tailwind.css +76 -127
- package/dist/styles/targets.css +3 -3
- package/dist/styles/theme/colour.css +86 -0
- package/dist/styles/theme/density.css +31 -0
- package/dist/styles/theme/elevation.css +9 -0
- package/dist/styles/theme/layout.css +18 -0
- package/dist/styles/theme/motion.css +18 -0
- package/dist/styles/theme/shape.css +12 -0
- package/dist/styles/theme/size.css +10 -0
- package/dist/styles/theme/spacing.css +11 -0
- package/dist/styles/theme/typography.css +20 -0
- package/dist/styles/tone.css +61 -0
- package/dist/table-B7dtIFUx.js +1262 -0
- package/dist/table-Ds_eO9av.js +191 -0
- package/dist/tailwind.css +76 -127
- package/dist/text-inputs-BboE77nZ.js +395 -0
- package/dist/theming-C5ygF5uf.js +292 -0
- package/dist/theming.js +2 -2
- package/dist/{timeline-BdaGRyj-.js → timeline-BR_jNgvz.js} +57 -49
- package/dist/{timelines-BB7550mz.js → timelines-DXG1BfIN.js} +69 -67
- package/dist/{toaster-bBMgXm8z.js → toaster-CXL8L7Mm.js} +106 -99
- package/dist/tokens.json +1027 -636
- package/dist/toolbar-DBK-c4yy.js +74 -0
- package/dist/tooltip-BPYP-jUm.js +76 -0
- package/dist/{typography-BkxEiwQ1.js → typography-DmeR05Er.js} +87 -53
- package/dist/{ui-provider-Cmoq6i_D.js → ui-provider-DpzLUD12.js} +117 -69
- package/dist/ui-provider.js +1 -1
- package/dist/upload-CYuoJykZ.js +968 -0
- package/dist/use-async-preview-BFwf9ElY.js +188 -0
- package/dist/value-inputs-ng8aVJJZ.js +728 -0
- package/docs/README.md +13 -3
- package/docs/build/browser-composition-fixture.ts +28 -0
- package/docs/build/recipes.md +11484 -10723
- package/docs/generated/component-index.json +9809 -9169
- package/docs/generated/components/INDEX.md +5 -5
- package/docs/generated/components/base--accordion.md +51 -2
- package/docs/generated/components/base--action-menu.md +14 -15
- package/docs/generated/components/base--alert-dialog.md +3 -4
- package/docs/generated/components/base--aspect-ratio.md +3 -4
- package/docs/generated/components/base--avatar.md +7 -7
- package/docs/generated/components/base--badge.md +159 -27
- package/docs/generated/components/base--batch-action-bar.md +6 -7
- package/docs/generated/components/base--buttons.md +151 -47
- package/docs/generated/components/base--cards.md +107 -14
- package/docs/generated/components/base--carousel.md +1 -2
- package/docs/generated/components/base--chart.md +44 -8
- package/docs/generated/components/base--choice-inputs.md +10 -11
- package/docs/generated/components/base--combobox.md +3 -4
- package/docs/generated/components/base--command.md +6 -6
- package/docs/generated/components/base--context-menu.md +1 -2
- package/docs/generated/components/base--copyable.md +6 -7
- package/docs/generated/components/base--date-pickers.md +6 -7
- package/docs/generated/components/base--dialog.md +6 -7
- package/docs/generated/components/base--direction.md +1 -1
- package/docs/generated/components/base--display.md +234 -54
- package/docs/generated/components/base--dropdown-menu.md +6 -7
- package/docs/generated/components/base--feedback.md +71 -18
- package/docs/generated/components/base--forms-numeric.md +6 -7
- package/docs/generated/components/base--forms.md +84 -14
- package/docs/generated/components/base--hover-card.md +3 -4
- package/docs/generated/components/base--input-group.md +27 -30
- package/docs/generated/components/base--item.md +8 -9
- package/docs/generated/components/base--label.md +2 -3
- package/docs/generated/components/base--menubar.md +2 -4
- package/docs/generated/components/base--navigation-menu.md +2 -3
- package/docs/generated/components/base--navigation.md +2 -3
- package/docs/generated/components/base--otp-input.md +3 -4
- package/docs/generated/components/base--overlay.md +56 -47
- package/docs/generated/components/base--popover-menu.md +7 -8
- package/docs/generated/components/base--popover.md +9 -10
- package/docs/generated/components/base--qr-code.md +7 -8
- package/docs/generated/components/base--repeaters.md +6 -7
- package/docs/generated/components/base--resizable.md +2 -3
- package/docs/generated/components/base--sheet.md +12 -13
- package/docs/generated/components/base--sidebar.md +9 -11
- package/docs/generated/components/base--skeleton.md +6 -7
- package/docs/generated/components/base--slot.md +1 -1
- package/docs/generated/components/base--spinner.md +5 -7
- package/docs/generated/components/base--structure.md +320 -70
- package/docs/generated/components/base--table.md +61 -3
- package/docs/generated/components/base--text-inputs.md +17 -18
- package/docs/generated/components/base--timeline.md +45 -4
- package/docs/generated/components/base--toaster.md +43 -12
- package/docs/generated/components/base--toggle.md +11 -12
- package/docs/generated/components/base--toolbar.md +7 -8
- package/docs/generated/components/base--tooltip.md +5 -6
- package/docs/generated/components/base--typography.md +317 -32
- package/docs/generated/components/base--upload.md +8 -9
- package/docs/generated/components/base--value-inputs.md +9 -38
- package/docs/generated/components/{admin--patterns--access.md → blocks--admin--access.md} +15 -6
- package/docs/generated/components/{admin--patterns--commerce.md → blocks--admin--commerce.md} +40 -41
- package/docs/generated/components/{patterns--analytics.md → blocks--analytics.md} +57 -14
- package/docs/generated/components/{patterns--onboarding.md → blocks--onboarding.md} +6 -7
- package/docs/generated/components/{patterns--timelines.md → blocks--timelines.md} +6 -7
- package/docs/generated/components/features--actions.md +8 -18
- package/docs/generated/components/features--activities.md +31 -32
- package/docs/generated/components/features--ai-chat.md +15 -15
- package/docs/generated/components/features--async-preview.md +5 -6
- package/docs/generated/components/features--combobox.md +71 -5
- package/docs/generated/components/features--comments.md +0 -1
- package/docs/generated/components/features--data-view.md +63 -8
- package/docs/generated/components/features--event-calendar.md +1 -2
- package/docs/generated/components/features--filters.md +11 -2
- package/docs/generated/components/features--global-search.md +1 -2
- package/docs/generated/components/features--kanban.md +1 -2
- package/docs/generated/components/features--map.md +1 -2
- package/docs/generated/components/features--media-library.md +105 -38
- package/docs/generated/components/features--mentions.md +7 -7
- package/docs/generated/components/features--overlays.md +75 -22
- package/docs/generated/components/features--products.md +10 -11
- package/docs/generated/components/features--resource-assignment.md +2 -3
- package/docs/generated/components/features--resource.md +3 -4
- package/docs/generated/components/features--rich-text-editor.md +42 -13
- package/docs/generated/components/features--schema-form.md +1 -2
- package/docs/generated/components/features--sync.md +2 -3
- package/docs/generated/components/features--table.md +162 -12
- package/docs/generated/components/features--theme-tweaker.md +30 -15
- package/docs/generated/components/forms.md +2 -2
- package/docs/generated/components/layout--app-shell.md +41 -11
- package/docs/generated/components/layout--auth.md +8 -9
- package/docs/generated/components/layout--containers.md +40 -1
- package/docs/generated/components/layout--header.md +2 -3
- package/docs/generated/components/layout--navigation.md +0 -1
- package/docs/generated/components/layout--page.md +33 -5
- package/docs/generated/components/layout--settings.md +0 -1
- package/docs/generated/components/layout--sidebar.md +47 -7
- package/docs/generated/components/layout--workspace.md +3 -4
- package/docs/generated/components/primitives.md +128 -17
- package/docs/generated/components/theming.md +147 -4
- package/docs/generated/components/ui-provider.md +96 -78
- package/docs/generated/composition-ladder.md +8 -8
- package/docs/generated/consumer-contract.json +5736 -0
- package/docs/generated/imports.md +104 -104
- package/docs/generated/migration-broad-imports.json +267 -90
- package/docs/generated/migration-broad-imports.md +266 -101
- package/docs/generated/migration-codemod.json +365 -70
- package/docs/generated/migration.md +665 -95
- package/docs/generated/profiles.md +27 -27
- package/docs/generated/public-api.md +104 -102
- package/docs/generated/recipes.json +755 -810
- package/docs/generated/workflows/communications-overview/analytics/communications-reference.tsx +19 -0
- package/docs/generated/workflows/index.json +691 -0
- package/docs/generated/workflows/media-picking/media-library/media-picking-reference.tsx +63 -0
- package/docs/generated/workflows/media-picking/media-library/reference-data.ts +3 -0
- package/docs/generated/workflows/multi-section-form/form-workflow/multi-section-reference.tsx +46 -0
- package/docs/generated/workflows/nested-action-flow/action-overlays/nested-action-reference.tsx +39 -0
- package/docs/generated/workflows/record-detail/page-layout/record-detail-reference.tsx +24 -0
- package/docs/generated/workflows/resource-index/data-view/resource-index-reference.tsx +51 -0
- package/docs/generated/workflows/scoped-resource-selection/combobox/scoped-resource-reference.tsx +50 -0
- package/docs/generated/workflows/website-content-editor/media-library/reference-data.ts +3 -0
- package/docs/generated/workflows/website-content-editor/rich-text-editor/website-content-reference.tsx +33 -0
- package/docs/generated/workflows/workspace-navigation/app-shell/workspace-navigation-reference.tsx +26 -0
- package/docs/learn/api-compatibility.md +5 -4
- package/docs/learn/blocks.md +123 -0
- package/docs/learn/composition.md +100 -19
- package/docs/learn/forms.md +23 -3
- package/docs/learn/framework-wiring.md +41 -13
- package/docs/learn/i18n.md +4 -2
- package/docs/learn/installation.md +60 -31
- package/docs/learn/migration.md +156 -5
- package/docs/learn/provider-and-scoping.md +37 -25
- package/docs/learn/reference-workflows.md +43 -0
- package/docs/learn/structure-and-spacing.md +147 -0
- package/docs/learn/theming.md +174 -131
- package/docs/learn/troubleshooting.md +88 -30
- package/docs/learn/verification.md +60 -5
- package/package.json +42 -473
- package/scripts/consumer/codemod.mjs +50 -32
- package/scripts/consumer/contract-reader.mjs +42 -0
- package/scripts/consumer/css-scan.mjs +51 -0
- package/scripts/consumer/diagnose.mjs +136 -0
- package/scripts/consumer/find-component.mjs +30 -17
- package/scripts/consumer/install-skill.mjs +93 -11
- package/src/styles/TOKENS.md +116 -275
- package/dist/accordion-6YPJ9XRO.js +0 -135
- package/dist/admin/patterns/access.css +0 -15
- package/dist/admin/patterns/commerce.css +0 -29
- package/dist/admin/patterns/commerce.js +0 -2493
- package/dist/avatar-CS7zow2q.js +0 -85
- package/dist/badge-CxOuTfVr.js +0 -63
- package/dist/base/accordion.css +0 -3
- package/dist/base/action-menu.css +0 -6
- package/dist/base/alert-dialog.css +0 -4
- package/dist/base/aspect-ratio.css +0 -2
- package/dist/base/avatar.css +0 -4
- package/dist/base/badge.css +0 -2
- package/dist/base/batch-action-bar.css +0 -5
- package/dist/base/buttons.css +0 -4
- package/dist/base/cards.css +0 -13
- package/dist/base/carousel.css +0 -5
- package/dist/base/chart.css +0 -2
- package/dist/base/choice-inputs.css +0 -10
- package/dist/base/combobox.css +0 -3
- package/dist/base/command.css +0 -9
- package/dist/base/context-menu.css +0 -2
- package/dist/base/copyable.css +0 -6
- package/dist/base/date-pickers.css +0 -11
- package/dist/base/dialog.css +0 -4
- package/dist/base/display.css +0 -8
- package/dist/base/dropdown-menu.css +0 -2
- package/dist/base/feedback.css +0 -5
- package/dist/base/forms-numeric.css +0 -12
- package/dist/base/forms.css +0 -14
- package/dist/base/hover-card.css +0 -2
- package/dist/base/input-group.css +0 -6
- package/dist/base/item.css +0 -9
- package/dist/base/label.css +0 -3
- package/dist/base/menubar.css +0 -2
- package/dist/base/navigation-menu.css +0 -2
- package/dist/base/navigation.css +0 -12
- package/dist/base/otp-input.css +0 -9
- package/dist/base/overlay.css +0 -4
- package/dist/base/popover-menu.css +0 -11
- package/dist/base/popover.css +0 -3
- package/dist/base/qr-code.css +0 -2
- package/dist/base/repeaters.css +0 -18
- package/dist/base/resizable.css +0 -2
- package/dist/base/sheet.css +0 -4
- package/dist/base/sidebar.css +0 -12
- package/dist/base/skeleton.css +0 -9
- package/dist/base/spinner.css +0 -2
- package/dist/base/structure.css +0 -2
- package/dist/base/table.css +0 -3
- package/dist/base/text-inputs.css +0 -2
- package/dist/base/timeline.css +0 -9
- package/dist/base/toaster.css +0 -2
- package/dist/base/toggle.css +0 -2
- package/dist/base/toolbar.css +0 -5
- package/dist/base/tooltip.css +0 -2
- package/dist/base/typography.css +0 -2
- package/dist/base/upload.css +0 -10
- package/dist/base/value-inputs.css +0 -14
- package/dist/buttons-CqXKWty3.js +0 -179
- package/dist/cards-C6Ulbkw7.js +0 -271
- package/dist/chart-nomhJ87z.js +0 -193
- package/dist/choice-inputs-OUDn0kQw.js +0 -680
- package/dist/combobox-C8oP92bT.js +0 -266
- package/dist/command-Bp3B6pUu.js +0 -143
- package/dist/comments-CAnDlyXO.js +0 -1438
- package/dist/components/admin/patterns/index.d.ts +0 -2
- package/dist/components/features/rich-text-editor/exec-command-engine.d.ts +0 -2
- package/dist/components/patterns/index.d.ts +0 -3
- package/dist/css/styles.css +0 -1
- package/dist/date-pickers-DOwIT-Nk.js +0 -661
- package/dist/display-B3Q17h5z.js +0 -645
- package/dist/dropdown-menu-TyNLCLML.js +0 -223
- package/dist/features/actions.css +0 -11
- package/dist/features/activities.css +0 -25
- package/dist/features/ai-chat.css +0 -14
- package/dist/features/async-preview.css +0 -10
- package/dist/features/combobox.css +0 -12
- package/dist/features/comments.css +0 -24
- package/dist/features/data-view.css +0 -31
- package/dist/features/event-calendar.css +0 -17
- package/dist/features/filters.css +0 -24
- package/dist/features/global-search.css +0 -19
- package/dist/features/kanban.css +0 -7
- package/dist/features/map.css +0 -15
- package/dist/features/media-library.css +0 -27
- package/dist/features/mentions.css +0 -17
- package/dist/features/overlays.css +0 -11
- package/dist/features/products.css +0 -29
- package/dist/features/resource-assignment.css +0 -14
- package/dist/features/resource.css +0 -15
- package/dist/features/rich-text-editor.css +0 -8
- package/dist/features/schema-form.css +0 -22
- package/dist/features/sync.css +0 -11
- package/dist/features/table.css +0 -20
- package/dist/features/theme-tweaker.css +0 -27
- package/dist/feedback-DRerHGuV.js +0 -469
- package/dist/forms-CPrGGif_.js +0 -242
- package/dist/forms-numeric-CPVsL7Vf.js +0 -569
- package/dist/index.css +0 -3
- package/dist/input-group-BYe0rhoB.js +0 -126
- package/dist/item-B3yQ26as.js +0 -146
- package/dist/layout/app-shell.css +0 -13
- package/dist/layout/auth.css +0 -14
- package/dist/layout/containers.css +0 -2
- package/dist/layout/header.css +0 -20
- package/dist/layout/navigation.css +0 -11
- package/dist/layout/page.css +0 -15
- package/dist/layout/settings.css +0 -16
- package/dist/layout/sidebar.css +0 -16
- package/dist/layout/workspace.css +0 -15
- package/dist/navigation-CsqTA16F.js +0 -614
- package/dist/navigation-DzxzPuwg.js +0 -202
- package/dist/overlay-WQOsLd69.js +0 -345
- package/dist/patterns/analytics.css +0 -15
- package/dist/patterns/onboarding.css +0 -11
- package/dist/patterns/timelines.css +0 -11
- package/dist/popover-DriLnIFc.js +0 -123
- package/dist/popover-menu-C2UCMAe7.js +0 -189
- package/dist/primitives.css +0 -3
- package/dist/repeaters-DuP1N0nw.js +0 -438
- package/dist/rich-text-editor-BQXFe9oN.js +0 -595
- package/dist/sidebar-D0N6ckJL.js +0 -412
- package/dist/skeleton-DGR9df28.js +0 -172
- package/dist/spinner-CUAVFecI.js +0 -52
- package/dist/styles/FACTORS.md +0 -36
- package/dist/styles/SCOPES.md +0 -86
- package/dist/styles/themes/default.css +0 -164
- package/dist/styles/theming/animation.css +0 -143
- package/dist/styles/theming/colors.css +0 -97
- package/dist/styles/theming/feedback.css +0 -17
- package/dist/styles/theming/field.css +0 -21
- package/dist/styles/theming/focus.css +0 -88
- package/dist/styles/theming/layers.css +0 -13
- package/dist/styles/theming/layout.css +0 -21
- package/dist/styles/theming/motion.css +0 -42
- package/dist/styles/theming/overlay.css +0 -52
- package/dist/styles/theming/sizing.css +0 -118
- package/dist/styles/theming/text.css +0 -30
- package/dist/styles/theming/typography.css +0 -26
- package/dist/styles/tokens/components.css +0 -22
- package/dist/styles/tokens/foundation.css +0 -80
- package/dist/styles/tokens/layout.css +0 -19
- package/dist/styles/tokens/palette.css +0 -88
- package/dist/styles/tokens/primitives.css +0 -18
- package/dist/styles/tokens/states.css +0 -77
- package/dist/table-BC4qqsUb.js +0 -180
- package/dist/table-BHDpjajL.js +0 -982
- package/dist/text-inputs-DF_lD7pA.js +0 -385
- package/dist/theming-D6KRU7hO.js +0 -104
- package/dist/toolbar-DWRywF0R.js +0 -68
- package/dist/tooltip-t1VQQ2tZ.js +0 -73
- package/dist/upload-B38YZeFJ.js +0 -938
- package/dist/value-inputs-Q4ymjXlV.js +0 -716
- package/src/styles/FACTORS.md +0 -36
- package/src/styles/SCOPES.md +0 -86
- /package/dist/components/{admin/patterns → blocks/admin}/access/admin.strings.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/access/credential-list.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/access/index.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/access/role-permissions.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/access/sensitive-action.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/account.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/address-lines.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/booking.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/cart.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/commerce.strings.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/commerce.types.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/format-amount.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/index.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/inventory-section.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/invoice.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/loyalty.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/order-customer.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/order-detail.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/order-line-item.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/order-transactions.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/order.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/seo-listing.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/seo-score.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/summary-panel.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/analytics/activity-heatmap.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/analytics/analytics.types.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/analytics/chart-card.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/analytics/format-metric-value.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/analytics/index.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/analytics/metric-bar.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/analytics/metric-comparison.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/analytics/metric-gradient.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/analytics/metric-grid.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/analytics/metric-micro-grid.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/analytics/metric-skeleton.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/analytics/metric-trend-chip.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/analytics/metric.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/analytics/time-ruler.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/onboarding/checklist.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/onboarding/index.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/onboarding/onboarding.strings.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/timelines/changelog-timeline.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/timelines/index.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/timelines/milestones-timeline.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/timelines/steps.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/timelines/timelines.strings.d.ts +0 -0
- /package/dist/styles/{theming/breakpoints.css → breakpoints.css} +0 -0
|
@@ -3,13 +3,16 @@
|
|
|
3
3
|
* Rewrites a consumer's source for a themelia-ui upgrade, from the migration maps shipped in
|
|
4
4
|
* docs/generated/. Preview with --dry-run, then apply (in this repo: `npm run codemod`):
|
|
5
5
|
* node node_modules/themelia-ui/scripts/consumer/codemod.mjs [--dry-run] src/
|
|
6
|
-
* Rewrites moved subpaths, removed-barrel imports, renamed tokens and utility classes
|
|
6
|
+
* Rewrites moved subpaths, removed-barrel imports, renamed tokens and utility classes, and
|
|
7
|
+
* removes obsolete kit stylesheet imports, which components now bring themselves.
|
|
7
8
|
* Reports without editing: removed tokens, overrides where old names merged (so one rule
|
|
8
|
-
* may now set --radius twice), utilities whose meaning changed, ambiguous symbols
|
|
9
|
+
* may now set --radius twice), utilities whose meaning changed, ambiguous symbols, and kit
|
|
10
|
+
* stylesheet references requiring manual review.
|
|
9
11
|
*/
|
|
10
12
|
import { existsSync, readFileSync, readdirSync, realpathSync, statSync, writeFileSync } from 'node:fs'
|
|
11
|
-
import { dirname, join,
|
|
13
|
+
import { dirname, join, resolve } from 'node:path'
|
|
12
14
|
import { fileURLToPath } from 'node:url'
|
|
15
|
+
import { loadMigrationMaps } from './contract-reader.mjs'
|
|
13
16
|
|
|
14
17
|
const HERE = dirname(fileURLToPath(import.meta.url))
|
|
15
18
|
const GENERATED = resolve(HERE, '..', '..', 'docs', 'generated')
|
|
@@ -21,33 +24,7 @@ const MARKUP = /\.(?:html|vue|svelte|astro|mdx)$/
|
|
|
21
24
|
const escape = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
22
25
|
|
|
23
26
|
/** The two published maps, indexed for the rewrites below. */
|
|
24
|
-
export
|
|
25
|
-
const read = (file) => {
|
|
26
|
-
const path = resolve(dir, file)
|
|
27
|
-
if (!existsSync(path)) throw new Error(`the packaged migration map is missing at ${path}`)
|
|
28
|
-
return JSON.parse(readFileSync(path, 'utf8'))
|
|
29
|
-
}
|
|
30
|
-
const codemod = read('migration-codemod.json')
|
|
31
|
-
const broad = read('migration-broad-imports.json')
|
|
32
|
-
const pkg = JSON.parse(readFileSync(resolve(dir, '..', '..', 'package.json'), 'utf8'))
|
|
33
|
-
/* A moved family's stylesheet moves with it, where the new one is published. */
|
|
34
|
-
const sheets = new Map()
|
|
35
|
-
for (const [from, to] of Object.entries(codemod.moves ?? {})) {
|
|
36
|
-
const subpath = `.${to.slice(pkg.name.length)}.css`
|
|
37
|
-
if (from.startsWith(`${pkg.name}/`) && pkg.exports?.[subpath]) sheets.set(`${from}.css`, `${to}.css`)
|
|
38
|
-
}
|
|
39
|
-
return {
|
|
40
|
-
/* Where a reader finds the rest, as a path from wherever the codemod was run. */
|
|
41
|
-
doc: relative(process.cwd(), resolve(dir, 'migration.md')),
|
|
42
|
-
moves: new Map([...Object.entries(codemod.moves ?? {}), ...sheets]),
|
|
43
|
-
tokens: new Map(Object.entries(codemod.tokens ?? {})),
|
|
44
|
-
classes: new Map(Object.entries(codemod.classes ?? {})),
|
|
45
|
-
reviewClasses: new Map(Object.entries(codemod.reviewClasses ?? {})),
|
|
46
|
-
broad: new Set([...(broad.removedSubpaths ?? [])]),
|
|
47
|
-
owner: broad.symbols ?? {},
|
|
48
|
-
ambiguous: new Set(Object.keys(broad.ambiguous ?? {})),
|
|
49
|
-
}
|
|
50
|
-
}
|
|
27
|
+
export const loadMaps = (dir = GENERATED) => loadMigrationMaps(dir)
|
|
51
28
|
|
|
52
29
|
/*
|
|
53
30
|
* A whole property name: the lookbehind keeps `i--` and `a--b` out; greedy, so a name
|
|
@@ -100,6 +77,38 @@ export function rewriteSource(text, file, maps) {
|
|
|
100
77
|
}
|
|
101
78
|
}
|
|
102
79
|
|
|
80
|
+
/*
|
|
81
|
+
* Components bring their own CSS in a bundler. Side-effect script imports go; module CSS
|
|
82
|
+
* paths are no longer published, so plain CSS @imports go too. A directly linked page uses
|
|
83
|
+
* style.css instead. Complex references are reported for manual review.
|
|
84
|
+
*/
|
|
85
|
+
const sheet = `${escape(maps.name)}/(?!core\\.css["']|tailwind\\.css["'])[^"']+\\.css`
|
|
86
|
+
const moduleSheet = `${escape(maps.name)}/(?:primitives|(?:base|layout|features|blocks|patterns|admin)/[^"']+)\\.css`
|
|
87
|
+
if (isScript) {
|
|
88
|
+
next = next.replace(new RegExp(`^[ \\t]*import\\s*(["'])(${sheet})\\1;?[ \\t]*\\r?\\n?`, 'gm'), (line, quote, specifier) => {
|
|
89
|
+
changes.push(`stylesheet ${file} removed ${specifier} — components bring their own CSS`)
|
|
90
|
+
return ''
|
|
91
|
+
})
|
|
92
|
+
for (const match of next.matchAll(new RegExp(`(["'])(${moduleSheet})\\1`, 'g'))) {
|
|
93
|
+
notes.push(`stylesheet ${file} ${match[2]} — this module stylesheet is no longer published; remove the import`)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (isStyle) {
|
|
97
|
+
next = next.replace(new RegExp(`^[ \\t]*@import\\s*(["'])(${moduleSheet})\\1\\s*;?[ \\t]*(?:\\r?\\n|$)`, 'gm'), (line, quote, specifier) => {
|
|
98
|
+
changes.push(`stylesheet ${file} removed ${specifier} — module CSS is no longer published`)
|
|
99
|
+
notes.push(`stylesheet ${file} if this page has no bundler, link ${maps.name}/style.css instead`)
|
|
100
|
+
return ''
|
|
101
|
+
})
|
|
102
|
+
}
|
|
103
|
+
if (isStyle || isMarkup) {
|
|
104
|
+
for (const match of next.matchAll(new RegExp(`(["'])(${sheet})\\1`, 'g'))) {
|
|
105
|
+
notes.push(`stylesheet ${file} ${match[2]} — in a bundled app this loads CSS twice; direct links without a bundler use ${maps.name}/style.css`)
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (isStyle && new RegExp(`@import\\s*(["'])${escape(maps.name)}/core\\.css\\1`).test(next)) {
|
|
109
|
+
notes.push(`stylesheet ${file} ${maps.name}/core.css — the components import core.css themselves; an @import here inlines a second copy`)
|
|
110
|
+
}
|
|
111
|
+
|
|
103
112
|
if (isScript) {
|
|
104
113
|
/* A named import from a removed barrel becomes one import per owning subpath. */
|
|
105
114
|
next = next.replace(
|
|
@@ -215,7 +224,11 @@ export function runCodemod(argv = process.argv.slice(2), { maps = loadMaps(), lo
|
|
|
215
224
|
|
|
216
225
|
const changes = []
|
|
217
226
|
const notes = []
|
|
218
|
-
|
|
227
|
+
/* A listed path the project does not have is reported, so one command can cover several layouts. */
|
|
228
|
+
const found = targets.filter((target) => existsSync(target))
|
|
229
|
+
for (const target of targets.filter((target) => !existsSync(target))) log(` not found ${target} — skipped`)
|
|
230
|
+
if (!found.length) return 1
|
|
231
|
+
for (const file of found.flatMap((target) => walk(target))) {
|
|
219
232
|
const original = readFileSync(file, 'utf8')
|
|
220
233
|
const result = rewriteSource(original, file, maps)
|
|
221
234
|
changes.push(...result.changes)
|
|
@@ -226,10 +239,15 @@ export function runCodemod(argv = process.argv.slice(2), { maps = loadMaps(), lo
|
|
|
226
239
|
const uniqueNotes = [...new Set(notes)].sort()
|
|
227
240
|
for (const line of changes.sort()) log(` ${line}`)
|
|
228
241
|
for (const line of uniqueNotes) log(` ${line}`)
|
|
242
|
+
const removedSheets = changes.some((line) => line.startsWith('stylesheet'))
|
|
229
243
|
log(
|
|
230
244
|
`\n${dryRun ? 'would apply' : 'applied'} ${changes.length} rewrite(s)` +
|
|
231
245
|
(uniqueNotes.length ? `, left ${uniqueNotes.length} for you` : '') +
|
|
232
|
-
`.\n\nNot attempted: \`asChild\` → \`render
|
|
246
|
+
`.\n\nNot attempted: \`asChild\` → \`render\` and the provider changes. See\n${maps.doc}.` +
|
|
247
|
+
(removedSheets
|
|
248
|
+
? '\n\nComponents now bring their own CSS. If the app renders on the server with Vite (Astro, React Router,\n' +
|
|
249
|
+
'TanStack Start, Vike), add themelia-ui to `ssr.noExternal`, or the server render has no kit CSS.'
|
|
250
|
+
: ''),
|
|
233
251
|
)
|
|
234
252
|
return 0
|
|
235
253
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
2
|
+
import { relative, resolve } from 'node:path'
|
|
3
|
+
|
|
4
|
+
export function loadMigrationMaps(dir) {
|
|
5
|
+
const read = (file) => {
|
|
6
|
+
const path = resolve(dir, file)
|
|
7
|
+
if (!existsSync(path)) throw new Error(`the packaged migration map is missing at ${path}`)
|
|
8
|
+
return JSON.parse(readFileSync(path, 'utf8'))
|
|
9
|
+
}
|
|
10
|
+
const codemod = read('migration-codemod.json')
|
|
11
|
+
const broad = read('migration-broad-imports.json')
|
|
12
|
+
const root = resolve(dir, '..', '..')
|
|
13
|
+
const pkg = JSON.parse(readFileSync(resolve(root, 'package.json'), 'utf8'))
|
|
14
|
+
return {
|
|
15
|
+
/* Where a reader finds the rest, as a path from wherever the codemod was run. */
|
|
16
|
+
doc: relative(process.cwd(), resolve(dir, 'migration.md')),
|
|
17
|
+
name: pkg.name,
|
|
18
|
+
moves: new Map(Object.entries(codemod.moves ?? {})),
|
|
19
|
+
tokens: new Map(Object.entries(codemod.tokens ?? {})),
|
|
20
|
+
classes: new Map(Object.entries(codemod.classes ?? {})),
|
|
21
|
+
reviewClasses: new Map(Object.entries(codemod.reviewClasses ?? {})),
|
|
22
|
+
broad: new Set([...(broad.removedSubpaths ?? [])]),
|
|
23
|
+
owner: broad.symbols ?? {},
|
|
24
|
+
ambiguous: new Set(Object.keys(broad.ambiguous ?? {})),
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
/** Read generated package facts; absent or incompatible metadata is an incomplete analysis. */
|
|
30
|
+
export function loadConsumerContract(packageRoot) {
|
|
31
|
+
const pkg=JSON.parse(readFileSync(resolve(packageRoot,'package.json'),'utf8'))
|
|
32
|
+
const metadata=resolve(packageRoot,'docs/generated/consumer-contract.json')
|
|
33
|
+
if(!existsSync(metadata)) throw new Error(`consumer contract is missing at ${metadata}`)
|
|
34
|
+
const contract=JSON.parse(readFileSync(metadata,'utf8'))
|
|
35
|
+
if(contract.schemaVersion!==1 || !contract.publicExports || !contract.privateStyleNames || !Array.isArray(contract.privateStyleNames.variables) || !Array.isArray(contract.privateStyleNames.classes)) throw new Error('unsupported consumer contract schema')
|
|
36
|
+
if(contract.packageVersion!==pkg.version) throw new Error('consumer contract version differs from installed package')
|
|
37
|
+
for(const [specifier,entry] of Object.entries(contract.publicExports)) {
|
|
38
|
+
if(!(specifier===pkg.name||specifier.startsWith(`${pkg.name}/`)) || !['javascript','stylesheet','json'].includes(entry.kind) || !Array.isArray(entry.symbols)) throw new Error('invalid public export metadata')
|
|
39
|
+
if(entry.targets?.some(target=>!target.startsWith('./')||target.split('/').includes('..')||!existsSync(resolve(packageRoot,target)))) throw new Error(`installed package export target is missing: ${specifier}`)
|
|
40
|
+
}
|
|
41
|
+
return {...contract,name:pkg.name,packageRoot,migration:loadMigrationMaps(resolve(packageRoot,'docs/generated'))}
|
|
42
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/** Bounded plain-CSS observations. Unsupported input is explicit, never a regex pass. */
|
|
2
|
+
const decodeEscapes = value => value
|
|
3
|
+
.replace(/\\(?:\r\n|[\n\r\f])/g, '')
|
|
4
|
+
.replace(/\\([0-9a-fA-F]{1,6})(?:\r\n|[ \n\r\t\f])?|\\(.)/g, (_, hex, char) => {
|
|
5
|
+
if (!hex) return char
|
|
6
|
+
const point = parseInt(hex, 16)
|
|
7
|
+
return point === 0 || point > 0x10ffff || (point >= 0xd800 && point <= 0xdfff) ? '\uFFFD' : String.fromCodePoint(point)
|
|
8
|
+
})
|
|
9
|
+
export function scanCss(source, file = 'input.css') {
|
|
10
|
+
const classes = [], variables = [], imports = [], unsupported = []
|
|
11
|
+
const locate = at => { const before=source.slice(0,at); return { line:before.split('\n').length,column:at-(before.lastIndexOf('\n')+1)+1 } }
|
|
12
|
+
if (!file.endsWith('.css')) return { classes, variables, imports, unsupported:[{...locate(0),reason:'Only plain CSS is supported'}] }
|
|
13
|
+
const chars=source.split('')
|
|
14
|
+
for(let i=0;i<source.length;i++) {
|
|
15
|
+
if(source.slice(i,i+2)==='/*') {
|
|
16
|
+
const end=source.indexOf('*/',i+2)
|
|
17
|
+
if(end<0) { unsupported.push({...locate(i),reason:'Unclosed comment'}); break }
|
|
18
|
+
for(let j=i;j<end+2;j++) if(chars[j]!=='\n') chars[j]=' '
|
|
19
|
+
i=end+1
|
|
20
|
+
} else if(source[i]==='"'||source[i]==="'") {
|
|
21
|
+
const start=i, quote=source[i]; let closed=false
|
|
22
|
+
for(i++;i<source.length;i++) { if(source[i]==='\\') {i++;continue} if(source[i]===quote) {closed=true;break} }
|
|
23
|
+
if(!closed) unsupported.push({...locate(start),reason:'Unclosed string'})
|
|
24
|
+
const value=source.slice(start+1,i)
|
|
25
|
+
if(/@import\s+(?:url\(\s*)?$/i.test(chars.slice(0,start).join(''))) imports.push({specifier:decodeEscapes(value),...locate(start)})
|
|
26
|
+
for(let j=start;j<=i && j<chars.length;j++) if(chars[j]!=='\n') chars[j]=' '
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const clean=chars.join(''); let from=0, depth=0
|
|
30
|
+
for (const hit of clean.matchAll(/@import\s+url\(\s*([^\s)][^)]*?)\s*\)/gi)) {
|
|
31
|
+
const value=decodeEscapes(hit[1])
|
|
32
|
+
imports.push({specifier:value,...locate(hit.index)})
|
|
33
|
+
}
|
|
34
|
+
for(let i=0;i<clean.length;i++) {
|
|
35
|
+
if(clean[i]==='{') {
|
|
36
|
+
const prelude=clean.slice(from,i)
|
|
37
|
+
for(const hit of prelude.matchAll(/\.((?:\\[0-9a-fA-F]{1,6}\s?|\\.|[\w-])+)/g)) {
|
|
38
|
+
const name=decodeEscapes(hit[1])
|
|
39
|
+
classes.push({name,...locate(from+hit.index)})
|
|
40
|
+
}
|
|
41
|
+
depth++;from=i+1
|
|
42
|
+
} else if(clean[i]===';'||clean[i]==='}') { if(clean[i]==='}') depth--;from=i+1 }
|
|
43
|
+
}
|
|
44
|
+
if(depth!==0) unsupported.push({...locate(source.length),reason:'Unbalanced CSS blocks'})
|
|
45
|
+
for(const hit of clean.matchAll(/--[A-Za-z_][\w-]*/g)) {
|
|
46
|
+
const after=clean.slice(hit.index+hit[0].length), before=clean.slice(0,hit.index)
|
|
47
|
+
if(/^\s*:/.test(after)||/var\(\s*$/.test(before)) variables.push({name:hit[0],kind:/^\s*:/.test(after)?'declaration':'read',...locate(hit.index)})
|
|
48
|
+
}
|
|
49
|
+
if(/(?:^|[;{}])\s*\$|@(?:mixin|include|extend)\b/.test(clean)) unsupported.push({...locate(0),reason:'Preprocessor syntax is unsupported'})
|
|
50
|
+
return { classes, variables, imports, unsupported }
|
|
51
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/** Read-only observations of explicit consumer files against the installed package. */
|
|
3
|
+
import { existsSync, lstatSync, readFileSync, readdirSync, realpathSync } from 'node:fs'
|
|
4
|
+
import { createRequire } from 'node:module'
|
|
5
|
+
import { dirname, relative, resolve } from 'node:path'
|
|
6
|
+
import { fileURLToPath } from 'node:url'
|
|
7
|
+
import { loadConsumerContract } from './contract-reader.mjs'
|
|
8
|
+
import { scanCss } from './css-scan.mjs'
|
|
9
|
+
import { checkSkill } from './install-skill.mjs'
|
|
10
|
+
|
|
11
|
+
const DOC='node_modules/themelia-ui/docs/learn/'
|
|
12
|
+
const SCRIPT=/\.(?:[cm]?[jt]sx?)$/
|
|
13
|
+
const EXCLUDED=new Set(['node_modules','.git','dist','build'])
|
|
14
|
+
const inside=(root,path)=>{const rel=relative(root,path);return rel!== '..'&&!rel.startsWith('../')&&!rel.startsWith('..\\')}
|
|
15
|
+
export async function diagnoseProject({project='.',paths=[],contract,checkSkills=true}={}) {
|
|
16
|
+
const root=realpathSync(resolve(project)), require=createRequire(resolve(root,'package.json'))
|
|
17
|
+
const report={schemaVersion:1,packageVersion:null,checkedRules:[],skippedChecks:[],checkedFiles:[],skippedFiles:[],findings:[]}
|
|
18
|
+
const skip=(ruleId,reason)=>report.skippedChecks.push({ruleId,reason})
|
|
19
|
+
if(!contract) {
|
|
20
|
+
try {contract=loadConsumerContract(dirname(require.resolve('themelia-ui/package.json')))}
|
|
21
|
+
catch(error) {skip('package-contract',error.message);return {...report,exitCode:2}}
|
|
22
|
+
}
|
|
23
|
+
report.packageVersion=contract.packageVersion
|
|
24
|
+
const files=new Set()
|
|
25
|
+
const skipped=(file,reason)=>report.skippedFiles.push({file:relative(root,file),reason})
|
|
26
|
+
const walk=path=>{
|
|
27
|
+
if(!inside(root,path)||relative(root,path).split(/[\\/]/).some(part=>EXCLUDED.has(part))) {skipped(path,'Outside explicit project source boundary');return}
|
|
28
|
+
if(!existsSync(path)) {skipped(path,'Missing path');return}
|
|
29
|
+
if(!inside(root,realpathSync(path))) {skipped(path,'Resolved path escapes the project through a symlink');return}
|
|
30
|
+
const stat=lstatSync(path)
|
|
31
|
+
if(stat.isSymbolicLink()) {skipped(path,'Symlinks are not followed');return}
|
|
32
|
+
if(stat.isDirectory()) {for(const entry of readdirSync(path).sort()) if(!EXCLUDED.has(entry)) walk(resolve(path,entry));return}
|
|
33
|
+
if(SCRIPT.test(path)||/\.(?:css|scss|sass|less|vue|svelte|astro|mdx)$/.test(path)) files.add(path)
|
|
34
|
+
else skipped(path,'Unsupported source format')
|
|
35
|
+
}
|
|
36
|
+
if(!paths.length) skip('explicit-paths','Supply explicit source paths to analyze')
|
|
37
|
+
for(const path of paths) walk(resolve(root,path))
|
|
38
|
+
const scripts=[...files].filter(path=>SCRIPT.test(path))
|
|
39
|
+
let ts, program, checker
|
|
40
|
+
if(scripts.length) {
|
|
41
|
+
try {ts=require('typescript');program=ts.createProgram(scripts,{noResolve:true,noLib:true,types:[],target:ts.ScriptTarget.Latest,jsx:ts.JsxEmit.Preserve});checker=program.getTypeChecker()}
|
|
42
|
+
catch(error) {skip('script-parser',`Install TypeScript in this consumer project: ${error.message}`)}
|
|
43
|
+
}
|
|
44
|
+
const finding=(ruleId,severity,file,location,evidence,explanation,documentation='troubleshooting.md')=>report.findings.push({ruleId,severity,file:relative(root,file),line:location.line,column:location.column,evidence,explanation,documentation:DOC+documentation})
|
|
45
|
+
const exportEntry=specifier=>contract.publicExports[specifier]
|
|
46
|
+
const imports=(specifier,names,file,loc)=>{
|
|
47
|
+
if(!(specifier===contract.name||specifier.startsWith(`${contract.name}/`))) return
|
|
48
|
+
const entry=exportEntry(specifier)
|
|
49
|
+
if(!entry) {
|
|
50
|
+
const moved=contract.migration?.moves?.get(specifier)
|
|
51
|
+
const alternatives=names.map(name=>contract.migration?.owner?.[name]).filter(Boolean)
|
|
52
|
+
finding('unpublished-import','error',file,loc,specifier,`This exact import is not published.${moved?` Use ${moved}.`:alternatives.length?` Use ${[...new Set(alternatives)].join(', ')}.`:/\.css$/.test(specifier)?' Components bring their own CSS; remove obsolete module stylesheet imports.':' Consult the exact import catalogue.'}`,'composition.md');return
|
|
53
|
+
}
|
|
54
|
+
if(entry.kind==='javascript') for(const name of names) if(!entry.symbols.includes(name)) finding('missing-symbol','error',file,loc,`${specifier}: ${name}`,'This symbol is absent from the installed public declaration; consult the module API.','composition.md')
|
|
55
|
+
}
|
|
56
|
+
if(ts) report.checkedRules.push('unpublished-import','missing-symbol','duplicate-owner','nested-surface')
|
|
57
|
+
for(const file of scripts) {
|
|
58
|
+
if(!ts) {skipped(file,'TypeScript parser unavailable');continue}
|
|
59
|
+
const source=program.getSourceFile(file)
|
|
60
|
+
if(!source || source.parseDiagnostics.length) {skipped(file,'Source parse failed');continue}
|
|
61
|
+
report.checkedFiles.push(relative(root,file));const bindings=new Map(), namespaces=new Map()
|
|
62
|
+
const loc=node=>{const p=source.getLineAndCharacterOfPosition(node.getStart(source));return {line:p.line+1,column:p.character+1}}
|
|
63
|
+
const bind=(node,symbol,specifier)=>{const identity=checker.getSymbolAtLocation(node);if(identity) bindings.set(identity,{symbol,specifier})}
|
|
64
|
+
for(const node of source.statements) {
|
|
65
|
+
if(ts.isImportDeclaration(node)&&ts.isStringLiteral(node.moduleSpecifier)) {
|
|
66
|
+
const specifier=node.moduleSpecifier.text, clause=node.importClause, names=[]
|
|
67
|
+
if(clause?.name) {names.push('default');bind(clause.name,'default',specifier)}
|
|
68
|
+
const named=clause?.namedBindings
|
|
69
|
+
if(named&&ts.isNamedImports(named)) for(const element of named.elements) {const name=element.propertyName?.text??element.name.text;names.push(name);bind(element.name,name,specifier)}
|
|
70
|
+
if(named&&ts.isNamespaceImport(named)) namespaces.set(checker.getSymbolAtLocation(named.name),specifier)
|
|
71
|
+
imports(specifier,names,file,loc(node.moduleSpecifier))
|
|
72
|
+
} else if(ts.isExportDeclaration(node)&&node.moduleSpecifier&&ts.isStringLiteral(node.moduleSpecifier)) imports(node.moduleSpecifier.text,node.exportClause&&ts.isNamedExports(node.exportClause)?node.exportClause.elements.map(item=>item.propertyName?.text??item.name.text):[],file,loc(node.moduleSpecifier))
|
|
73
|
+
}
|
|
74
|
+
const owner=tag=>{
|
|
75
|
+
if(ts.isIdentifier(tag)) return bindings.get(checker.getSymbolAtLocation(tag))
|
|
76
|
+
if(ts.isPropertyAccessExpression(tag)) {const specifier=namespaces.get(checker.getSymbolAtLocation(tag.expression));if(specifier) return {specifier,symbol:tag.name.text}}
|
|
77
|
+
}
|
|
78
|
+
const native=tag=>{const value=owner(tag.tagName);return value&&exportEntry(value.specifier)?.symbols.includes(value.symbol)?value.symbol:null}
|
|
79
|
+
const title=tag=>{const attr=tag.attributes.properties.find(item=>ts.isJsxAttribute(item)&&['title','label'].includes(item.name.getText(source)));return attr?.initializer&&ts.isStringLiteral(attr.initializer)?attr.initializer.text:undefined}
|
|
80
|
+
const visit=node=>{
|
|
81
|
+
if(ts.isCallExpression(node)&&node.arguments[0]&&ts.isStringLiteral(node.arguments[0])&&(node.expression.kind===ts.SyntaxKind.ImportKeyword||(ts.isIdentifier(node.expression)&&node.expression.text==='require'&&!checker.getSymbolAtLocation(node.expression)))) imports(node.arguments[0].text,[],file,loc(node.arguments[0]))
|
|
82
|
+
const member=ts.isPropertyAccessExpression(node)?{base:node.expression,name:node.name.text}
|
|
83
|
+
:ts.isQualifiedName(node)?{base:node.left,name:node.right.text}
|
|
84
|
+
:ts.isElementAccessExpression(node)&&node.argumentExpression&&(ts.isStringLiteral(node.argumentExpression)||ts.isNoSubstitutionTemplateLiteral(node.argumentExpression))?{base:node.expression,name:node.argumentExpression.text}:null
|
|
85
|
+
if(member) {
|
|
86
|
+
const specifier=namespaces.get(checker.getSymbolAtLocation(member.base))
|
|
87
|
+
if(specifier) imports(specifier,[member.name],file,loc(node))
|
|
88
|
+
}
|
|
89
|
+
const tag=ts.isJsxElement(node)?node.openingElement:ts.isJsxSelfClosingElement(node)?node:null
|
|
90
|
+
if(tag) {
|
|
91
|
+
const symbol=native(tag)
|
|
92
|
+
if(symbol) for(let ancestor=node.parent;ancestor;ancestor=ancestor.parent) {
|
|
93
|
+
if(!ts.isJsxElement(ancestor)) continue
|
|
94
|
+
const parent=native(ancestor.openingElement);if(!parent) continue
|
|
95
|
+
if(title(tag)&&title(tag)===title(ancestor.openingElement)) finding('duplicate-owner','warning',file,loc(tag),`${parent} / ${symbol}: ${title(tag)}`,'Repeated literal names may duplicate a subject or field owner. Confirm distinct subjects and accessible names.','composition.md')
|
|
96
|
+
if(symbol==='Card'&&parent==='Card') finding('nested-surface','warning',file,loc(tag),'Card inside Card','Confirm the child is an independent subject. ContentBlock or flat FormSection may express an existing-surface region.','composition.md')
|
|
97
|
+
break
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
ts.forEachChild(node,visit)
|
|
101
|
+
};visit(source)
|
|
102
|
+
}
|
|
103
|
+
report.checkedRules.push('private-variable','private-selector','migration-token','stylesheet-import')
|
|
104
|
+
for(const file of [...files].filter(path=>!SCRIPT.test(path))) {
|
|
105
|
+
const observations=scanCss(readFileSync(file,'utf8'),file)
|
|
106
|
+
if(observations.unsupported.length) {skipped(file,observations.unsupported.map(item=>item.reason).join('; '));continue}
|
|
107
|
+
report.checkedFiles.push(relative(root,file))
|
|
108
|
+
for(const item of observations.imports) imports(item.specifier,[],file,item)
|
|
109
|
+
for(const item of observations.classes) if(contract.privateStyleNames.classes.includes(item.name)) finding('private-selector','warning',file,item,item.name,'This selector matches a verified CSS Module hash in this package build. Use documented hooks or public tokens.')
|
|
110
|
+
for(const item of observations.variables) {
|
|
111
|
+
if(contract.privateStyleNames.variables.includes(item.name)) finding('private-variable','warning',file,item,item.name,'This package-private variable is not a supported override. Use a documented public token.')
|
|
112
|
+
if(contract.migration?.tokens?.has(item.name)) finding('migration-token','warning',file,item,item.name,`Historical token; ${contract.migration.tokens.get(item.name)?`review ${contract.migration.tokens.get(item.name)}`:'no successor is declared'}.`,'migration.md')
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if(checkSkills) {
|
|
116
|
+
if(!contract.packageRoot) skip('skill-freshness','Installed package root unavailable')
|
|
117
|
+
else {
|
|
118
|
+
const freshness=checkSkill({project:root,source:resolve(contract.packageRoot,'.agents/skills/themelia-ui')})
|
|
119
|
+
if(freshness.exitCode===2) skip('skill-freshness',freshness.error)
|
|
120
|
+
else {report.checkedRules.push('skill-freshness');for(const target of freshness.targets) if(target.status!=='current') finding('skill-freshness','warning',resolve(root,`.${target.target==='agents'?'agents':'claude'}/skills/themelia-ui/SKILL.md`),{line:1,column:1},`${target.target}: ${target.status}; installed ${target.installedVersion??'unknown'}, expected ${freshness.packageVersion}`,`Review modified content and preserve application policy. Run install-skill.mjs --check --json, then reinstall only the generated copy you intend to replace. Unmanaged skills are never overwritten.`,'verification.md')}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
const incomplete=report.skippedChecks.length||report.skippedFiles.length
|
|
124
|
+
return {...report,exitCode:incomplete?2:report.findings.some(item=>item.severity==='error')?1:0}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export async function runDiagnoseCli(args=process.argv.slice(2),io=console) {
|
|
128
|
+
let project='.',json=false;const paths=[]
|
|
129
|
+
for(const arg of args) {if(arg==='--json') json=true;else if(arg.startsWith('--project=')) project=arg.slice(10);else if(arg.startsWith('--')) {io.error('usage: diagnose.mjs --project=<directory> [--json] <paths...>');return 2}else paths.push(arg)}
|
|
130
|
+
let result
|
|
131
|
+
try {result=await diagnoseProject({project,paths})} catch(error) {io.error(`Incomplete diagnosis: ${error.message}`);return 2}
|
|
132
|
+
if(json) io.log(JSON.stringify(result,null,2))
|
|
133
|
+
else {io.log(`themelia-ui ${result.packageVersion??'unknown'}: ${result.checkedFiles.length} files, ${result.findings.length} findings`);for(const item of result.findings) io.log(`${item.severity} ${item.file}:${item.line}:${item.column} ${item.ruleId}: ${item.explanation}`);for(const item of [...result.skippedChecks,...result.skippedFiles]) io.log(`incomplete ${item.ruleId??item.file}: ${item.reason}`)}
|
|
134
|
+
return result.exitCode
|
|
135
|
+
}
|
|
136
|
+
if(process.argv[1]&&realpathSync(process.argv[1])===realpathSync(fileURLToPath(import.meta.url))) process.exitCode=await runDiagnoseCli()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/*
|
|
3
|
-
* Finds which themelia-ui component to use, with its exact
|
|
3
|
+
* Finds which themelia-ui component to use, with its exact import, from the
|
|
4
4
|
* catalogue shipped in this package (offline). `--help` lists the filters.
|
|
5
5
|
* node node_modules/themelia-ui/scripts/consumer/find-component.mjs "bulk selection"
|
|
6
6
|
* node node_modules/themelia-ui/scripts/consumer/find-component.mjs --tier=base --json
|
|
@@ -11,6 +11,7 @@ import { fileURLToPath } from 'node:url'
|
|
|
11
11
|
|
|
12
12
|
const HERE = dirname(fileURLToPath(import.meta.url))
|
|
13
13
|
export const INDEX_PATH = resolve(HERE, '..', '..', 'docs/generated/component-index.json')
|
|
14
|
+
export const CONTEXTS = ['existing-surface', 'editable', 'read-only', 'server-collection', 'nested-overlay', 'changing-scope']
|
|
14
15
|
|
|
15
16
|
/** One catalogue entry in the shape the finder searches and `--json` prints. */
|
|
16
17
|
const toRecord = (entry) => ({
|
|
@@ -19,7 +20,6 @@ const toRecord = (entry) => ({
|
|
|
19
20
|
profile: entry.profile,
|
|
20
21
|
status: entry.status,
|
|
21
22
|
publicImport: entry.import,
|
|
22
|
-
cssImport: entry.css,
|
|
23
23
|
publicSymbols: entry.symbols,
|
|
24
24
|
components: entry.components,
|
|
25
25
|
componentGuidance: entry.componentGuidance,
|
|
@@ -37,7 +37,9 @@ const toRecord = (entry) => ({
|
|
|
37
37
|
|
|
38
38
|
export function loadIndex(path = INDEX_PATH) {
|
|
39
39
|
if (!existsSync(path)) throw new Error(`the packaged component index is missing at ${path}`)
|
|
40
|
-
|
|
40
|
+
const index = JSON.parse(readFileSync(path, 'utf8'))
|
|
41
|
+
if (!Number.isInteger(index.schemaVersion) || index.schemaVersion < 1 || index.schemaVersion > 4 || !index.modules) throw new Error('unsupported component index schema; use the finder shipped with the installed package')
|
|
42
|
+
return Object.values(index.modules).map(toRecord)
|
|
41
43
|
}
|
|
42
44
|
|
|
43
45
|
const text = (value) => (Array.isArray(value) ? value.join(' ') : String(value ?? ''))
|
|
@@ -88,9 +90,11 @@ const STOPWORDS = new Set([
|
|
|
88
90
|
* which beats positive guidance and recipes. `avoidWhen` text never counts as a match.
|
|
89
91
|
*/
|
|
90
92
|
export function findComponents(modules, query, filters = {}) {
|
|
93
|
+
const contexts = filters.context ?? []
|
|
94
|
+
if (!Array.isArray(contexts) || contexts.some(value => !CONTEXTS.includes(value))) throw new Error(`unknown context; expected ${CONTEXTS.join(', ')}`)
|
|
91
95
|
const needle = query.trim().toLowerCase()
|
|
92
96
|
const hasFilter = ['tier', 'profile', 'status', 'module', 'peer', 'route', 'symbol']
|
|
93
|
-
.some((name) => Boolean(filters[name]))
|
|
97
|
+
.some((name) => Boolean(filters[name])) || contexts.length > 0
|
|
94
98
|
if (!needle && !hasFilter) return []
|
|
95
99
|
|
|
96
100
|
const scored = []
|
|
@@ -105,7 +109,7 @@ export function findComponents(modules, query, filters = {}) {
|
|
|
105
109
|
const symbols = (record.publicSymbols ?? []).map((s) => String(s).toLowerCase())
|
|
106
110
|
if (filters.symbol && !symbols.includes(filters.symbol.toLowerCase())) continue
|
|
107
111
|
|
|
108
|
-
if (!needle) {
|
|
112
|
+
if (!needle && !contexts.length) {
|
|
109
113
|
scored.push({ record, score: 0 })
|
|
110
114
|
continue
|
|
111
115
|
}
|
|
@@ -124,8 +128,8 @@ export function findComponents(modules, query, filters = {}) {
|
|
|
124
128
|
)
|
|
125
129
|
if (normalizedSymbols.includes(phrase)) score = 100
|
|
126
130
|
else if (normalizedModule === phrase) score = 90
|
|
127
|
-
else if (normalizedSymbols.some((symbol) => symbol.includes(phrase))) score = 75
|
|
128
|
-
else if (normalizedModule.includes(phrase)) score = 70
|
|
131
|
+
else if (phrase && normalizedSymbols.some((symbol) => symbol.includes(phrase))) score = 75
|
|
132
|
+
else if (phrase && normalizedModule.includes(phrase)) score = 70
|
|
129
133
|
else if (queryTerms.length > 1 && identityWholeMatch) score = 65
|
|
130
134
|
else {
|
|
131
135
|
const positive = [
|
|
@@ -152,16 +156,17 @@ export function findComponents(modules, query, filters = {}) {
|
|
|
152
156
|
}
|
|
153
157
|
for (const entry of record.componentGuidance ?? []) {
|
|
154
158
|
const curated = entry.guidanceSource === 'component'
|
|
155
|
-
const
|
|
159
|
+
const matchedContexts = contexts.filter(value => entry.contexts?.includes(value))
|
|
160
|
+
const corpus = [entry.symbol, entry.description, curated ? entry.chooseWhen : '', ...(entry.capabilities ?? []), ...matchedContexts].join(' ')
|
|
156
161
|
const hits = termHits(queryTerms, corpus)
|
|
157
162
|
const exact = normalizedWords(entry.symbol).join(' ') === phrase
|
|
158
|
-
if (exact || (queryTerms.length && hits * 2 >= queryTerms.length)) {
|
|
159
|
-
const componentScore = exact ? 100 : Math.min(curated ?
|
|
160
|
-
componentMatches.push({ ...entry, score: componentScore, matchedTerms: queryTerms.filter((term) => termHits([term], corpus)) })
|
|
163
|
+
if (exact || (queryTerms.length && hits * 2 >= queryTerms.length) || (!needle && matchedContexts.length)) {
|
|
164
|
+
const componentScore = exact ? 100 : Math.min(curated ? 74 : 34, (curated ? 39 : 10) + (queryTerms.length ? Math.round(25 * hits / queryTerms.length) : 0) + matchedContexts.length * 5)
|
|
165
|
+
componentMatches.push({ ...entry, score: componentScore, matchedContexts, contextCoverage: entry.contexts ? 'curated' : 'unknown', matchedTerms: queryTerms.filter((term) => termHits([term], corpus)) })
|
|
161
166
|
score = Math.max(score, componentScore)
|
|
162
167
|
}
|
|
163
168
|
}
|
|
164
|
-
if (score > 0) scored.push({ record: filters.explain ? { ...record, match: { score, components: componentMatches.sort((a, b) => b.score - a.score), reason: componentMatches.length ? 'Public component name, description
|
|
169
|
+
if (score > 0 || !needle) scored.push({ record: filters.explain ? { ...record, match: { score, contexts, contextCoverage: (record.componentGuidance ?? []).some(entry => entry.contexts) ? 'curated' : 'unknown', components: componentMatches.sort((a, b) => b.score - a.score), reason: componentMatches.length ? 'Public component name, description, positive usage guidance or applicable context' : 'Module identity, positive guidance or attributed recipe; uncurated contexts remain unknown' } } : record, score })
|
|
165
170
|
}
|
|
166
171
|
|
|
167
172
|
return scored
|
|
@@ -181,6 +186,7 @@ Options:
|
|
|
181
186
|
--symbol=<Name> exact public export name
|
|
182
187
|
--peer=<package> modules that require this optional peer
|
|
183
188
|
--route=</path> modules represented on this live preview route
|
|
189
|
+
--context=<context> repeatable: ${CONTEXTS.join(', ')}
|
|
184
190
|
--limit=<N> return at most N matches (default 8)
|
|
185
191
|
--explain include matched components, reasons and API anchors
|
|
186
192
|
--json emit complete machine-readable records
|
|
@@ -188,7 +194,7 @@ Options:
|
|
|
188
194
|
|
|
189
195
|
A text query is optional when at least one catalogue filter is present.`
|
|
190
196
|
|
|
191
|
-
const VALUE_FLAGS = new Set(['tier', 'profile', 'status', 'module', 'symbol', 'peer', 'route', 'limit'])
|
|
197
|
+
const VALUE_FLAGS = new Set(['tier', 'profile', 'status', 'module', 'symbol', 'peer', 'route', 'limit', 'context'])
|
|
192
198
|
const BOOLEAN_FLAGS = new Set(['json', 'help', 'explain'])
|
|
193
199
|
|
|
194
200
|
export function parseFinderArgs(args) {
|
|
@@ -208,7 +214,10 @@ export function parseFinderArgs(args) {
|
|
|
208
214
|
if (!VALUE_FLAGS.has(rawName)) throw new Error(`unknown option --${rawName}`)
|
|
209
215
|
const value = rest.join('=')
|
|
210
216
|
if (!value) throw new Error(`--${rawName} requires a value written as --${rawName}=...`)
|
|
211
|
-
|
|
217
|
+
if (rawName === 'context') {
|
|
218
|
+
if (!CONTEXTS.includes(value)) throw new Error(`unknown context ${value}; expected ${CONTEXTS.join(', ')}`)
|
|
219
|
+
options.context = [...(options.context ?? []), value]
|
|
220
|
+
} else options[rawName] = value
|
|
212
221
|
}
|
|
213
222
|
const limit = options.limit === undefined ? 8 : Number(options.limit)
|
|
214
223
|
if (!Number.isInteger(limit) || limit < 1 || limit > 100) {
|
|
@@ -230,7 +239,7 @@ export function runFinderCli(args = process.argv.slice(2), io = console) {
|
|
|
230
239
|
return 0
|
|
231
240
|
}
|
|
232
241
|
const filters = Object.fromEntries(
|
|
233
|
-
['tier', 'profile', 'status', 'module', 'symbol', 'peer', 'route']
|
|
242
|
+
['tier', 'profile', 'status', 'module', 'symbol', 'peer', 'route', 'context']
|
|
234
243
|
.filter((name) => parsed.options[name])
|
|
235
244
|
.map((name) => [name, parsed.options[name]]),
|
|
236
245
|
)
|
|
@@ -257,16 +266,20 @@ export function renderMatch(record) {
|
|
|
257
266
|
`${record.module} (${record.tier} · ${record.profile}${record.status ? ` · ${record.status}` : ''})`,
|
|
258
267
|
` import ${record.publicImport}`,
|
|
259
268
|
]
|
|
260
|
-
if (record.cssImport ?? record.css) lines.push(` css ${record.cssImport ?? record.css}`)
|
|
261
269
|
if (record.apiDoc) lines.push(` api node_modules/themelia-ui/docs/generated/${record.apiDoc}`)
|
|
262
270
|
if (record.chooseWhen) lines.push(` choose ${text(record.chooseWhen)}`)
|
|
263
271
|
if (record.avoidWhen) lines.push(` avoid ${text(record.avoidWhen)}`)
|
|
264
|
-
if (record.composeWith?.length) lines.push(` with ${text(record.composeWith)} — import
|
|
272
|
+
if (record.composeWith?.length) lines.push(` with ${text(record.composeWith)} — import it too`)
|
|
265
273
|
if (record.alternatives?.length) lines.push(` instead ${text(record.alternatives)}`)
|
|
266
274
|
if (record.match) {
|
|
267
275
|
lines.push(` match ${record.match.reason}`)
|
|
268
276
|
for (const entry of record.match.components.slice(0, 3)) {
|
|
269
277
|
lines.push(` ${entry.symbol} — ${entry.chooseWhen}`, ` api ${entry.apiDoc}`, ` compose ${entry.composition}`)
|
|
278
|
+
lines.push(` guidance ${entry.guidanceSource === 'component' ? 'component' : 'module fallback'}`)
|
|
279
|
+
lines.push(` context ${entry.contextCoverage ?? 'unknown'}${entry.matchedContexts?.length ? `: ${entry.matchedContexts.join(', ')}` : ''}`)
|
|
280
|
+
const unmatched = (record.match.contexts ?? []).filter(context => !entry.matchedContexts?.includes(context))
|
|
281
|
+
if (unmatched.length) lines.push(` unmatched ${unmatched.join(', ')}`)
|
|
282
|
+
for (const workflow of entry.workflows ?? []) lines.push(` source node_modules/themelia-ui/docs/generated/${workflow.source}`)
|
|
270
283
|
}
|
|
271
284
|
}
|
|
272
285
|
return lines.join('\n')
|