themelia-react-ui 1.0.2 → 2.0.1
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/CHANGELOG.md +632 -1
- package/README.md +31 -13
- package/dist/accordion-B6a3vVgA.js +207 -0
- package/dist/accordion-B6a3vVgA.js.map +1 -0
- package/dist/action-menu-TzCoSlwL.js +280 -0
- package/dist/action-menu-TzCoSlwL.js.map +1 -0
- package/dist/{affordance-geometry.generated-CL84ZN9A.js → affordance-geometry.generated-B5iu-Mkr.js} +9 -3
- package/dist/affordance-geometry.generated-B5iu-Mkr.js.map +1 -0
- package/dist/{ai-artifact-DLVdK0Py.js → ai-artifact-BMJdv-6q.js} +389 -391
- package/dist/ai-artifact-BMJdv-6q.js.map +1 -0
- package/dist/{app-shell-C_fKpljx.js → app-shell-ZK5RWdo6.js} +4 -4
- package/dist/{app-shell-C_fKpljx.js.map → app-shell-ZK5RWdo6.js.map} +1 -1
- package/dist/attachment-BtfhGm8i.js +245 -0
- package/dist/attachment-BtfhGm8i.js.map +1 -0
- package/dist/{auth-CAQcasMV.js → auth-CYxKfo69.js} +239 -237
- package/dist/auth-CYxKfo69.js.map +1 -0
- package/dist/{avatar-Bu2HhitA.js → avatar-BBnEJIx8.js} +71 -68
- package/dist/avatar-BBnEJIx8.js.map +1 -0
- package/dist/badge-MrKVNzW9.js +93 -0
- package/dist/badge-MrKVNzW9.js.map +1 -0
- package/dist/base/accordion.js +1 -1
- package/dist/base/action-menu.js +1 -1
- package/dist/base/attachment.js +1 -1
- package/dist/base/avatar.js +1 -1
- package/dist/base/badge.js +1 -1
- package/dist/base/batch-action-bar.js +3 -0
- package/dist/base/buttons.js +2 -3
- package/dist/base/cards.js +2 -2
- package/dist/base/carousel.js +19 -19
- package/dist/base/carousel.js.map +1 -1
- package/dist/base/cascader.js +234 -224
- package/dist/base/cascader.js.map +1 -1
- package/dist/base/chart.js +1 -1
- package/dist/base/choice-inputs.js +3 -3
- package/dist/base/code-block.js +1 -1
- package/dist/base/combobox.js +1 -1
- package/dist/base/command.js +1 -1
- package/dist/base/copyable.js +1 -1
- package/dist/base/date-pickers.js +2 -2
- package/dist/base/display.js +7 -7
- package/dist/base/feedback.js +3 -3
- package/dist/base/forms-numeric.js +1 -1
- package/dist/base/forms.js +2 -2
- package/dist/base/inline-edit.js +81 -76
- package/dist/base/inline-edit.js.map +1 -1
- package/dist/base/item.js +1 -1
- package/dist/base/media-gallery.js +1 -1
- package/dist/base/metadata-list.js +3 -0
- package/dist/base/navigation.js +7 -7
- package/dist/base/popover-menu.js +1 -1
- package/dist/base/popover.js +1 -1
- package/dist/base/qr-code.js +7 -4
- package/dist/base/qr-code.js.map +1 -1
- package/dist/base/repeaters.js +175 -174
- package/dist/base/repeaters.js.map +1 -1
- package/dist/base/sheet.js +1 -1
- package/dist/base/sidebar.js +1 -1
- package/dist/base/signature-pad.js +148 -138
- package/dist/base/signature-pad.js.map +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 +2 -2
- package/dist/base/toaster.js +4 -4
- package/dist/base/toaster.js.map +1 -1
- package/dist/base/tree.js +1 -1
- package/dist/base/upload-queue.js +1 -1
- package/dist/base/upload.js +3 -3
- package/dist/base/value-inputs.js +2 -2
- package/dist/batch-action-bar-BZGDG-Si.js +104 -0
- package/dist/batch-action-bar-BZGDG-Si.js.map +1 -0
- package/dist/blocks/admin.js +264 -253
- package/dist/blocks/admin.js.map +1 -1
- package/dist/blocks/ai.js +293 -323
- package/dist/blocks/ai.js.map +1 -1
- package/dist/blocks/analytics/usage-card.js +1 -1
- package/dist/blocks/analytics.js +596 -587
- package/dist/blocks/analytics.js.map +1 -1
- package/dist/blocks/collaboration.js +1 -1
- package/dist/blocks/commerce/receipt.js +1 -1
- package/dist/blocks/commerce.js +2246 -1693
- package/dist/blocks/commerce.js.map +1 -1
- package/dist/blocks/data-display.js +3 -2
- package/dist/blocks/onboarding.js +50 -49
- package/dist/blocks/onboarding.js.map +1 -1
- package/dist/blocks/planning.js +82 -91
- package/dist/blocks/planning.js.map +1 -1
- package/dist/blocks/timelines.js +1 -1
- package/dist/breadcrumbs-D5t7I023.js +129 -0
- package/dist/breadcrumbs-D5t7I023.js.map +1 -0
- package/dist/{button-BZyfTvwm.js → button-QYwiyhD2.js} +15 -14
- package/dist/button-QYwiyhD2.js.map +1 -0
- package/dist/buttons-SbIcm1HJ.js +661 -0
- package/dist/buttons-SbIcm1HJ.js.map +1 -0
- package/dist/{cards-qGSErLw_.js → cards-CiiHpKYd.js} +8 -8
- package/dist/cards-CiiHpKYd.js.map +1 -0
- package/dist/{chart-Bsc5BICK.js → chart-QfrARkXl.js} +17 -15
- package/dist/chart-QfrARkXl.js.map +1 -0
- package/dist/checkbox-DhB6K0bK.js +36 -0
- package/dist/checkbox-DhB6K0bK.js.map +1 -0
- package/dist/choice-inputs-t6w3ATNz.js +766 -0
- package/dist/choice-inputs-t6w3ATNz.js.map +1 -0
- package/dist/code-block-Dgbu-CU3.js +185 -0
- package/dist/code-block-Dgbu-CU3.js.map +1 -0
- package/dist/{collapsible-ClvC7Bj3.js → collapsible-D8AEGU1-.js} +4 -4
- package/dist/{collapsible-ClvC7Bj3.js.map → collapsible-D8AEGU1-.js.map} +1 -1
- package/dist/{collection-content-D6S8cv_n.js → collection-content-uK16Grv0.js} +3 -3
- package/dist/{collection-content-D6S8cv_n.js.map → collection-content-uK16Grv0.js.map} +1 -1
- package/dist/{combobox-BFnbJJp3.js → combobox-2Ic8N9bL.js} +103 -98
- package/dist/combobox-2Ic8N9bL.js.map +1 -0
- package/dist/combobox-DLl0bfiq.js +867 -0
- package/dist/combobox-DLl0bfiq.js.map +1 -0
- package/dist/{command-BnmSchli.js → command-kNR20o7x.js} +34 -30
- package/dist/command-kNR20o7x.js.map +1 -0
- package/dist/{comments-u5L0OGip.js → comments-BpDuCUUu.js} +304 -301
- package/dist/comments-BpDuCUUu.js.map +1 -0
- package/dist/components/base/accordion/accordion-variants.d.ts +3 -3
- package/dist/components/base/action-menu/action-menu.d.ts +27 -5
- package/dist/components/base/action-menu/action-menu.recipes.d.ts +21 -0
- package/dist/components/base/action-menu/index.d.ts +1 -0
- package/dist/components/base/avatar/stacked-avatars.d.ts +5 -4
- package/dist/components/base/badge/badge.d.ts +1 -1
- package/dist/components/base/badge/badge.recipes.d.ts +6 -6
- package/dist/components/base/batch-action-bar/batch-action-bar.d.ts +50 -0
- package/dist/components/base/batch-action-bar/batch-action-bar.strings.d.ts +20 -0
- package/dist/components/base/batch-action-bar/index.d.ts +8 -0
- package/dist/components/base/buttons/base-button.d.ts +7 -0
- package/dist/components/base/buttons/button-group.recipes.d.ts +2 -2
- package/dist/components/base/buttons/button.recipes.d.ts +2 -2
- package/dist/components/base/buttons/button.variants.d.ts +1 -0
- package/dist/components/base/buttons/loader-button.d.ts +3 -1
- package/dist/components/base/buttons/text-button.d.ts +2 -2
- package/dist/components/base/carousel/carousel.d.ts +3 -1
- package/dist/components/base/chart/chart.d.ts +7 -7
- package/dist/components/base/choice-inputs/checkbox.d.ts +6 -7
- package/dist/components/base/choice-inputs/choice-types.d.ts +24 -3
- package/dist/components/base/choice-inputs/pill-radio-group.d.ts +9 -0
- package/dist/components/base/choice-inputs/select-popup.d.ts +9 -1
- package/dist/components/base/choice-inputs/switch-card.d.ts +1 -1
- package/dist/components/base/date-pickers/date-picker-field.d.ts +23 -0
- package/dist/components/base/date-pickers/datepicker.types.d.ts +13 -3
- package/dist/components/base/display/alert-dialog.d.ts +10 -3
- package/dist/components/base/display/content-block.d.ts +4 -2
- package/dist/components/base/display/date-block.d.ts +1 -1
- package/dist/components/base/display/dialog.d.ts +8 -5
- package/dist/components/base/display/icon-badge/icon-badge.d.ts +1 -1
- package/dist/components/base/display/surface-title.d.ts +6 -1
- package/dist/components/base/feedback/alert.d.ts +1 -1
- package/dist/components/base/feedback/state-display.d.ts +5 -4
- package/dist/components/base/forms/form-sizing.d.ts +43 -8
- package/dist/components/base/forms/workflow.d.ts +2 -0
- package/dist/components/base/forms-numeric/coordinates-input.d.ts +3 -0
- package/dist/components/base/forms-numeric/rounding-mode-select.d.ts +4 -1
- package/dist/components/base/metadata-list/index.d.ts +12 -0
- package/dist/components/{blocks/data-display/metadata → base/metadata-list}/metadata-list.d.ts +28 -25
- package/dist/components/{blocks/data-display/metadata → base/metadata-list}/metadata-value.d.ts +2 -2
- package/dist/components/base/navigation/dropdown-menu.d.ts +2 -2
- package/dist/components/base/navigation/index.d.ts +1 -1
- package/dist/components/base/navigation/language-switcher.d.ts +4 -1
- package/dist/components/base/navigation/overflow-tab-bar.d.ts +7 -0
- package/dist/components/base/navigation/page-header/index.d.ts +1 -0
- package/dist/components/base/navigation/page-header/page-header-commands.d.ts +73 -0
- package/dist/components/base/navigation/page-header/page-header.d.ts +30 -4
- package/dist/components/base/qr-code/qr-code.d.ts +2 -0
- package/dist/components/base/sheet/index.d.ts +29 -1
- package/dist/components/base/sheet/sheet.d.ts +10 -5
- package/dist/components/base/signature-pad/signature-pad.types.d.ts +5 -1
- package/dist/components/base/signature-pad/signature-pad.utils.d.ts +11 -3
- package/dist/components/base/spinner/spinner.d.ts +3 -2
- package/dist/components/base/structure/structure.types.d.ts +1 -1
- package/dist/components/base/text-inputs/field-clear-button.d.ts +6 -0
- package/dist/components/base/text-inputs/input-group.d.ts +2 -2
- package/dist/components/base/upload/upload.recipes.d.ts +33 -0
- package/dist/components/base/value-inputs/date-time-input.d.ts +4 -2
- package/dist/components/base/value-inputs/index.d.ts +5 -5
- package/dist/components/base/value-inputs/tags-input.d.ts +38 -12
- package/dist/components/blocks/admin/api-key-list/api-key-list.types.d.ts +1 -1
- package/dist/components/blocks/analytics/format-metric-value.d.ts +11 -1
- package/dist/components/blocks/analytics/index.d.ts +1 -1
- package/dist/components/blocks/analytics/use-metric-format-options.d.ts +3 -0
- package/dist/components/blocks/commerce/address-card/address-card.d.ts +1 -1
- package/dist/components/blocks/commerce/address-card/types.d.ts +4 -1
- package/dist/components/blocks/commerce/booking-calendar-event-card/booking-calendar-event-card.d.ts +4 -0
- package/dist/components/blocks/commerce/booking-calendar-event-card/booking-calendar-event-card.types.d.ts +2 -2
- package/dist/components/blocks/commerce/cart-summary/cart-summary.d.ts +3 -1
- package/dist/components/blocks/commerce/cart-summary/index.d.ts +2 -2
- package/dist/components/blocks/commerce/cart-summary/types.d.ts +6 -1
- package/dist/components/blocks/commerce/discount-stack/discount-stack.d.ts +3 -1
- package/dist/components/blocks/commerce/discount-stack/index.d.ts +2 -2
- package/dist/components/blocks/commerce/discount-stack/types.d.ts +16 -4
- package/dist/components/blocks/commerce/fulfillment-group/fulfillment-group.d.ts +5 -0
- package/dist/components/blocks/commerce/fulfillment-group/index.d.ts +2 -0
- package/dist/components/blocks/commerce/fulfillment-group/types.d.ts +43 -0
- package/dist/components/blocks/commerce/index.d.ts +13 -5
- package/dist/components/blocks/commerce/inventory-section/types.d.ts +4 -1
- package/dist/components/blocks/commerce/invoice-header/invoice-header.d.ts +1 -1
- package/dist/components/blocks/commerce/invoice-header/types.d.ts +4 -2
- package/dist/components/blocks/commerce/invoice-mini/invoice-mini.d.ts +1 -1
- package/dist/components/blocks/commerce/invoice-mini/types.d.ts +2 -1
- package/dist/components/blocks/commerce/loyalty-points/types.d.ts +1 -1
- package/dist/components/blocks/commerce/order-customer/index.d.ts +2 -0
- package/dist/components/blocks/commerce/order-customer/order-customer.d.ts +5 -0
- package/dist/components/blocks/commerce/order-customer/types.d.ts +48 -0
- package/dist/components/blocks/commerce/order-header/index.d.ts +2 -0
- package/dist/components/blocks/commerce/order-header/order-header.d.ts +5 -0
- package/dist/components/blocks/commerce/order-header/types.d.ts +37 -0
- package/dist/components/blocks/commerce/order-line-item/index.d.ts +2 -0
- package/dist/components/blocks/commerce/order-line-item/order-line-item.d.ts +5 -0
- package/dist/components/blocks/commerce/order-line-item/types.d.ts +46 -0
- package/dist/components/blocks/commerce/order-status/types.d.ts +4 -0
- package/dist/components/blocks/commerce/order-summary/index.d.ts +2 -0
- package/dist/components/blocks/commerce/order-summary/order-summary.d.ts +5 -0
- package/dist/components/blocks/commerce/order-summary/types.d.ts +42 -0
- package/dist/components/blocks/commerce/order-transactions/index.d.ts +2 -0
- package/dist/components/blocks/commerce/order-transactions/order-transactions.d.ts +5 -0
- package/dist/components/blocks/commerce/order-transactions/types.d.ts +46 -0
- package/dist/components/blocks/commerce/payment-method/index.d.ts +2 -2
- package/dist/components/blocks/commerce/payment-method/payment-method.d.ts +9 -1
- package/dist/components/blocks/commerce/payment-method/types.d.ts +14 -1
- package/dist/components/blocks/commerce/refund-status/index.d.ts +2 -2
- package/dist/components/blocks/commerce/refund-status/refund-status.d.ts +3 -1
- package/dist/components/blocks/commerce/refund-status/types.d.ts +6 -3
- package/dist/components/blocks/commerce/seo-listing/seo-listing-card.d.ts +1 -1
- package/dist/components/blocks/commerce/seo-listing/types.d.ts +3 -1
- package/dist/components/blocks/commerce/shared/address-lines.d.ts +21 -0
- package/dist/components/blocks/commerce/shared/line-thumbnail.d.ts +9 -0
- package/dist/components/blocks/commerce/shared/order-status.d.ts +51 -0
- package/dist/components/blocks/commerce/shipment-tracking/shipment-tracking.d.ts +1 -1
- package/dist/components/blocks/commerce/shipment-tracking/types.d.ts +27 -6
- package/dist/components/blocks/commerce/summary-panel/amount-row.d.ts +2 -0
- package/dist/components/blocks/commerce/summary-panel/index.d.ts +3 -0
- package/dist/components/blocks/commerce/summary-panel/summary-panel.d.ts +2 -0
- package/dist/components/blocks/commerce/summary-panel/types.d.ts +26 -0
- package/dist/components/blocks/commerce/tax-breakdown/tax-breakdown.d.ts +1 -1
- package/dist/components/blocks/commerce/tax-breakdown/types.d.ts +2 -1
- package/dist/components/blocks/commerce/vendor-profile/types.d.ts +4 -1
- package/dist/components/blocks/data-display/dense-info-card/dense-info.strings.d.ts +4 -1
- package/dist/components/blocks/data-display/inline-stat/inline-stat.d.ts +4 -1
- package/dist/components/blocks/data-display/metadata/index.d.ts +30 -4
- package/dist/components/features/activities/partials/activity-row.d.ts +6 -2
- package/dist/components/features/activities/partials/tone-tokens.d.ts +0 -6
- package/dist/components/features/global-search/partials/global-search-group-heading.d.ts +15 -0
- package/dist/components/features/global-search/partials/global-search-idle-state.d.ts +1 -1
- package/dist/components/features/global-search/partials/tone-palettes.d.ts +0 -5
- package/dist/components/features/kanban/kanban.d.ts +1 -1
- package/dist/components/features/kanban/kanban.strings.d.ts +1 -1
- package/dist/components/features/kanban/kanban.types.d.ts +2 -2
- package/dist/components/features/media-library/hooks/use-media-library.d.ts +1 -1
- package/dist/components/features/media-library/index.d.ts +1 -1
- package/dist/components/features/media-library/media-library.d.ts +1 -1
- package/dist/components/features/media-library/media-library.strings.d.ts +4 -0
- package/dist/components/features/media-library/media-library.types.d.ts +74 -1
- package/dist/components/features/media-library/partials/media-library-partials.d.ts +3 -3
- package/dist/components/features/mentions/partials/mention-kind-toggles.d.ts +16 -0
- package/dist/components/features/overlays/alert-dialog.d.ts +1 -1
- package/dist/components/features/overlays/dialog.d.ts +1 -1
- package/dist/components/features/overlays/drawer.d.ts +1 -1
- package/dist/components/features/overlays/hooks/use-overlay-actions.d.ts +2 -2
- package/dist/components/features/overlays/hooks/use-overlay-visibility.d.ts +11 -4
- package/dist/components/features/overlays/index.d.ts +1 -1
- package/dist/components/features/overlays/overlay-tone-icon.d.ts +37 -0
- package/dist/components/features/overlays/overlays.types.d.ts +62 -19
- package/dist/components/features/products/components/product-contract-overview.d.ts +5 -0
- package/dist/components/features/products/components/product-details-card.d.ts +5 -0
- package/dist/components/features/products/components/product-operations-card.d.ts +5 -0
- package/dist/components/features/products/components/product-option-action-menu.d.ts +5 -0
- package/dist/components/features/products/components/product-options-summary.d.ts +5 -0
- package/dist/components/features/products/components/product-policies-card.d.ts +5 -0
- package/dist/components/features/products/components/product-quote-preview-card.d.ts +5 -0
- package/dist/components/features/products/components/product-readiness-card.d.ts +5 -0
- package/dist/components/features/products/components/product-structure-card.d.ts +5 -0
- package/dist/components/features/products/components/product-variant-action-menu.d.ts +23 -1
- package/dist/components/features/products/components/product-variants-manager.d.ts +1 -1
- package/dist/components/features/products/partials/index.d.ts +1 -1
- package/dist/components/features/products/partials/product-metric-tile.d.ts +6 -0
- package/dist/components/features/products/partials/product-tone.d.ts +11 -1
- package/dist/components/features/products/products.types.d.ts +11 -3
- package/dist/components/features/resource/index.d.ts +1 -1
- package/dist/components/features/resource/resource.d.ts +1 -1
- package/dist/components/features/resource/resource.types.d.ts +34 -6
- package/dist/components/features/rich-text-editor/index.d.ts +2 -1
- package/dist/components/features/rich-text-editor/partials/image-nodes.d.ts +13 -0
- package/dist/components/features/rich-text-editor/partials/image-uploads.d.ts +66 -0
- package/dist/components/features/rich-text-editor/partials/inline-reference-node.d.ts +19 -0
- package/dist/components/features/rich-text-editor/rich-text-editor.recipes.d.ts +1 -1
- package/dist/components/features/rich-text-editor/rich-text-editor.strings.d.ts +14 -0
- package/dist/components/features/rich-text-editor/rich-text-editor.types.d.ts +45 -0
- package/dist/components/features/rich-text-editor/use-rich-text-images.d.ts +18 -0
- package/dist/components/features/sync/index.d.ts +26 -3
- package/dist/components/features/table/data-table.d.ts +1 -1
- package/dist/components/features/table/partials/cell-renderers.d.ts +1 -1
- package/dist/components/features/table/table.types.d.ts +32 -7
- package/dist/components/layout/page/index.d.ts +1 -1
- package/dist/components/layout/page/page.types.d.ts +51 -4
- package/dist/components/layout/page/partials/page-actions.d.ts +1 -0
- package/dist/components/layout/page/partials/page-header.d.ts +1 -1
- package/dist/components/layout/settings/settings.d.ts +16 -2
- package/dist/components/layout/workspace/workspace.types.d.ts +21 -4
- package/dist/components/primitives/date.d.ts +16 -3
- package/dist/components/primitives/dimensions.d.ts +6 -0
- package/dist/components/primitives/duration.d.ts +6 -0
- package/dist/components/primitives/file-size.d.ts +6 -0
- package/dist/components/primitives/index.d.ts +1 -1
- package/dist/components/primitives/initials.d.ts +11 -2
- package/dist/components/primitives/link.d.ts +7 -0
- package/dist/components/primitives/money.d.ts +29 -7
- package/dist/components/primitives/number.d.ts +17 -0
- package/dist/components/primitives/value-typography.d.ts +54 -0
- package/dist/components/primitives/value.d.ts +31 -6
- package/dist/components/typography/heading.d.ts +9 -1
- package/dist/components/typography/label.d.ts +3 -0
- package/dist/components/typography/rich-text/index.d.ts +1 -1
- package/dist/components/typography/rich-text/rich-text-tree.d.ts +19 -0
- package/dist/components/typography/rich-text/rich-text.d.ts +16 -0
- package/dist/components/typography/running-text.d.ts +12 -0
- package/dist/components/typography/text-link.d.ts +24 -1
- package/dist/components/typography/text.d.ts +12 -0
- package/dist/components/typography/text.styles.d.ts +35 -13
- package/dist/components/ui/button.d.ts +1 -1
- package/dist/components/ui/checkbox.d.ts +6 -0
- package/dist/components/ui/overlay.recipes.d.ts +6 -2
- package/dist/components/ui/select.d.ts +3 -1
- package/dist/components/ui/switch.d.ts +5 -0
- package/dist/{containers-DqB-bSYE.js → containers-DmWiJa2I.js} +36 -35
- package/dist/containers-DmWiJa2I.js.map +1 -0
- package/dist/{copyable-BTSByfmq.js → copyable-B3Gwgdqc.js} +6 -6
- package/dist/{copyable-BTSByfmq.js.map → copyable-B3Gwgdqc.js.map} +1 -1
- package/dist/data-display-DafIvCl5.js +960 -0
- package/dist/data-display-DafIvCl5.js.map +1 -0
- package/dist/date-BgK3bTdo.js +144 -0
- package/dist/date-BgK3bTdo.js.map +1 -0
- package/dist/date-picker-CF-DtUpF.js +1529 -0
- package/dist/date-picker-CF-DtUpF.js.map +1 -0
- package/dist/date-pickers-BmzxJl5l.js +174 -0
- package/dist/date-pickers-BmzxJl5l.js.map +1 -0
- package/dist/{display-CS6Hbk18.js → display-DsQTVzMz.js} +88 -87
- package/dist/display-DsQTVzMz.js.map +1 -0
- package/dist/{dropdown-menu-D-boNgGO.js → dropdown-menu-E2qmdC7o.js} +23 -16
- package/dist/dropdown-menu-E2qmdC7o.js.map +1 -0
- package/dist/features/activities.js +437 -521
- package/dist/features/activities.js.map +1 -1
- package/dist/features/ai-chat.js +174 -172
- package/dist/features/ai-chat.js.map +1 -1
- package/dist/features/async-preview.js +8 -8
- package/dist/features/async-preview.js.map +1 -1
- package/dist/features/combobox.js +1 -1
- package/dist/features/comments.js +1 -1
- package/dist/features/data-view.js +139 -138
- package/dist/features/data-view.js.map +1 -1
- package/dist/features/email-composer/engine.js +1 -1
- package/dist/features/email-composer.js +353 -352
- package/dist/features/email-composer.js.map +1 -1
- package/dist/features/event-calendar.js +262 -269
- package/dist/features/event-calendar.js.map +1 -1
- package/dist/features/filters.js +1 -1
- package/dist/features/global-search.js +307 -310
- package/dist/features/global-search.js.map +1 -1
- package/dist/features/kanban.js +95 -97
- package/dist/features/kanban.js.map +1 -1
- package/dist/features/map.js +56 -57
- package/dist/features/map.js.map +1 -1
- package/dist/features/media-library.js +914 -824
- package/dist/features/media-library.js.map +1 -1
- package/dist/features/mentions.js +1 -1
- package/dist/features/overlays.js +1 -1
- package/dist/features/products.js +1272 -1311
- package/dist/features/products.js.map +1 -1
- package/dist/features/questionnaire.js +204 -194
- package/dist/features/questionnaire.js.map +1 -1
- package/dist/features/resource-assignment.js +103 -95
- package/dist/features/resource-assignment.js.map +1 -1
- package/dist/features/resource.js +77 -69
- package/dist/features/resource.js.map +1 -1
- package/dist/features/rich-text-editor.js +30 -11
- package/dist/features/rich-text-editor.js.map +1 -1
- package/dist/features/schema-form.js +193 -189
- package/dist/features/schema-form.js.map +1 -1
- package/dist/features/suggestions.js +3 -3
- package/dist/features/sync.js +7 -7
- package/dist/features/sync.js.map +1 -1
- package/dist/features/table.js +1 -1
- package/dist/features/theme-tweaker.js +455 -455
- package/dist/features/theme-tweaker.js.map +1 -1
- package/dist/feedback-qNuMBtRH.js +233 -0
- package/dist/feedback-qNuMBtRH.js.map +1 -0
- package/dist/field-affordance-recipes-qQeIf4lG.js +48 -0
- package/dist/field-affordance-recipes-qQeIf4lG.js.map +1 -0
- package/dist/field-state-recipes-BVA2CWHo.js +12 -0
- package/dist/field-state-recipes-BVA2CWHo.js.map +1 -0
- package/dist/{filters-D6FF8L6s.js → filters-BkHH53uv.js} +414 -412
- package/dist/filters-BkHH53uv.js.map +1 -0
- package/dist/focus-recipes-B653VaLq.js +12 -0
- package/dist/focus-recipes-B653VaLq.js.map +1 -0
- package/dist/{form-field-CZwrkP7m.js → form-field-DUt4UxSV.js} +7 -7
- package/dist/{form-field-CZwrkP7m.js.map → form-field-DUt4UxSV.js.map} +1 -1
- package/dist/form-sizing-By94KzXE.js +130 -0
- package/dist/form-sizing-By94KzXE.js.map +1 -0
- package/dist/{forms-B5NCbkSC.js → forms-Bzha-Y3B.js} +25 -25
- package/dist/forms-Bzha-Y3B.js.map +1 -0
- package/dist/forms-numeric-C0bvjRPZ.js +906 -0
- package/dist/forms-numeric-C0bvjRPZ.js.map +1 -0
- package/dist/{header-kxruN3RM.js → header-BOefOKd1.js} +38 -41
- package/dist/header-BOefOKd1.js.map +1 -0
- package/dist/{hooks-BrlnCwQd.js → hooks-9k_TtmKh.js} +2 -2
- package/dist/{hooks-BrlnCwQd.js.map → hooks-9k_TtmKh.js.map} +1 -1
- package/dist/{http-CdEIHyQf.js → http-D_6rOnzU.js} +2 -2
- package/dist/{http-CdEIHyQf.js.map → http-D_6rOnzU.js.map} +1 -1
- package/dist/icon-badge-CAuKupo9.js +55 -0
- package/dist/icon-badge-CAuKupo9.js.map +1 -0
- package/dist/index.js +7 -7
- package/dist/input-DWhBBBww.js +262 -0
- package/dist/input-DWhBBBww.js.map +1 -0
- package/dist/{input-vxcaNCYC.js → input-Ddi_LSYv.js} +3 -3
- package/dist/{input-vxcaNCYC.js.map → input-Ddi_LSYv.js.map} +1 -1
- package/dist/interaction-recipes-CHr0dJUs.js +24 -0
- package/dist/interaction-recipes-CHr0dJUs.js.map +1 -0
- package/dist/item-DEmDiTlD.js +265 -0
- package/dist/item-DEmDiTlD.js.map +1 -0
- package/dist/layer-recipes-CCpklYME.js +13 -0
- package/dist/layer-recipes-CCpklYME.js.map +1 -0
- package/dist/layout/app-shell.js +1 -1
- package/dist/layout/auth.js +1 -1
- package/dist/layout/containers.js +1 -1
- package/dist/layout/header.js +1 -1
- package/dist/layout/hooks.js +1 -1
- package/dist/layout/navigation.js +1 -1
- package/dist/layout/page.js +1 -1
- package/dist/layout/settings.js +1 -1
- package/dist/layout/sidebar.js +2 -2
- package/dist/layout/workspace.js +1 -1
- package/dist/layout.js +10 -10
- package/dist/lib/affordance-geometry.generated.d.ts +7 -1
- package/dist/lib/field-affordance-recipes.d.ts +41 -1
- package/dist/lib/field-state-recipes.d.ts +9 -6
- package/dist/lib/focus-recipes.d.ts +24 -0
- package/dist/lib/format.d.ts +9 -0
- package/dist/lib/interaction-recipes.d.ts +35 -0
- package/dist/lib/layer-recipes.d.ts +19 -0
- package/dist/lib/money-format.d.ts +30 -0
- package/dist/lib/motion-recipes.d.ts +1 -0
- package/dist/lib/overlay-anatomy-recipes.d.ts +2 -1
- package/dist/lib/safe-image-src.d.ts +10 -0
- package/dist/lib/sanitize-html.d.ts +15 -3
- package/dist/lib/surface-recipes.d.ts +48 -6
- package/dist/lib/token-merge.generated.d.ts +17 -14
- package/dist/lib/tone-recipes.d.ts +79 -0
- package/dist/lib/track-recipes.d.ts +1 -1
- package/dist/lib/ui-provider/hooks.d.ts +2 -1
- package/dist/lib/ui-provider/index.d.ts +2 -2
- package/dist/lib/ui-provider/provider.d.ts +7 -2
- package/dist/lib/ui-provider/store.d.ts +6 -2
- package/dist/lib/ui-provider/types.d.ts +14 -2
- package/dist/lib/utils.js +1 -1
- package/dist/media-gallery-DcTtAaeC.js +203 -0
- package/dist/media-gallery-DcTtAaeC.js.map +1 -0
- package/dist/mentions-D-uyCh01.js +568 -0
- package/dist/mentions-D-uyCh01.js.map +1 -0
- package/dist/{message-SZUNB1eX.js → message-CdHgIWKf.js} +5 -5
- package/dist/{message-SZUNB1eX.js.map → message-CdHgIWKf.js.map} +1 -1
- package/dist/metadata-list-X5rYAKSB.js +394 -0
- package/dist/metadata-list-X5rYAKSB.js.map +1 -0
- package/dist/{motion-recipes-B6jKXEcN.js → motion-recipes-ChBg4HBq.js} +3 -2
- package/dist/{motion-recipes-B6jKXEcN.js.map → motion-recipes-ChBg4HBq.js.map} +1 -1
- package/dist/navigation-D3KwXmaq.js +145 -0
- package/dist/navigation-D3KwXmaq.js.map +1 -0
- package/dist/navigation-HJf5zxlH.js +268 -0
- package/dist/navigation-HJf5zxlH.js.map +1 -0
- package/dist/{navigation-row-recipes-DQEXQcqY.js → navigation-row-recipes-BVowojQw.js} +2 -2
- package/dist/{navigation-row-recipes-DQEXQcqY.js.map → navigation-row-recipes-BVowojQw.js.map} +1 -1
- package/dist/number-DMhe-Vsk.js +352 -0
- package/dist/number-DMhe-Vsk.js.map +1 -0
- package/dist/overflow-tab-bar-sQHXLlwQ.js +280 -0
- package/dist/overflow-tab-bar-sQHXLlwQ.js.map +1 -0
- package/dist/overlay.recipes-8GHqmlb4.js +6 -0
- package/dist/overlay.recipes-8GHqmlb4.js.map +1 -0
- package/dist/overlays-I0axtYA6.js +999 -0
- package/dist/overlays-I0axtYA6.js.map +1 -0
- package/dist/{page-hGmT4nWK.js → page-B5dTH9gE.js} +79 -68
- package/dist/page-B5dTH9gE.js.map +1 -0
- package/dist/page-header-commands-DjzFEq3E.js +126 -0
- package/dist/page-header-commands-DjzFEq3E.js.map +1 -0
- package/dist/{pagination-NLGqRirf.js → pagination-3bPA_a6K.js} +19 -19
- package/dist/{pagination-NLGqRirf.js.map → pagination-3bPA_a6K.js.map} +1 -1
- package/dist/{popover-CghIYdQf.js → popover-Di55PyAI.js} +8 -8
- package/dist/popover-Di55PyAI.js.map +1 -0
- package/dist/{popover-menu-B4PoWhRl.js → popover-menu-B71Tn2Qz.js} +6 -6
- package/dist/{popover-menu-B4PoWhRl.js.map → popover-menu-B71Tn2Qz.js.map} +1 -1
- package/dist/{popover.recipes-QlD4JenO.js → popover.recipes-Bdyhj2db.js} +2 -2
- package/dist/{popover.recipes-QlD4JenO.js.map → popover.recipes-Bdyhj2db.js.map} +1 -1
- package/dist/primitives-B-CkiEMU.js +379 -0
- package/dist/primitives-B-CkiEMU.js.map +1 -0
- package/dist/primitives.js +5 -5
- package/dist/{progress-BroqrAyV.js → progress-rnS8-uAW.js} +11 -11
- package/dist/progress-rnS8-uAW.js.map +1 -0
- package/dist/{receipt-BuJynLgf.js → receipt-D0oswZ0p.js} +6 -6
- package/dist/{receipt-BuJynLgf.js.map → receipt-D0oswZ0p.js.map} +1 -1
- package/dist/rich-text-DvGulsNJ.js +78 -0
- package/dist/rich-text-DvGulsNJ.js.map +1 -0
- package/dist/rich-text-editor-sMU_Scqm.js +1204 -0
- package/dist/rich-text-editor-sMU_Scqm.js.map +1 -0
- package/dist/rich-text-editor.recipes-CadiF_Uu.js +88 -0
- package/dist/rich-text-editor.recipes-CadiF_Uu.js.map +1 -0
- package/dist/rich-text-editor.strings-CB59ekH2.js +38 -0
- package/dist/rich-text-editor.strings-CB59ekH2.js.map +1 -0
- package/dist/safe-image-src-C6kQSMBZ.js +17 -0
- package/dist/safe-image-src-C6kQSMBZ.js.map +1 -0
- package/dist/sanitize-html-DsQmI48u.js +92 -0
- package/dist/sanitize-html-DsQmI48u.js.map +1 -0
- package/dist/scroll-area-Bt_vXY2b.js +48 -0
- package/dist/scroll-area-Bt_vXY2b.js.map +1 -0
- package/dist/{separator-BNIgG3au.js → separator-C8DlRGwF.js} +4 -4
- package/dist/separator-C8DlRGwF.js.map +1 -0
- package/dist/{separator-BhtFyo4x.js → separator-CYHnjsAb.js} +2 -2
- package/dist/{separator-BhtFyo4x.js.map → separator-CYHnjsAb.js.map} +1 -1
- package/dist/services/actions/action-adapters.d.ts +22 -0
- package/dist/services/actions/index.d.ts +1 -1
- package/dist/services/actions.js +23 -6
- package/dist/services/actions.js.map +1 -1
- package/dist/settings-CQW3b-Cu.js +170 -0
- package/dist/settings-CQW3b-Cu.js.map +1 -0
- package/dist/sheet-4SEvVYzA.js +210 -0
- package/dist/sheet-4SEvVYzA.js.map +1 -0
- package/dist/{sidebar-CyR4XKwR.js → sidebar-C7WWR29L.js} +181 -180
- package/dist/sidebar-C7WWR29L.js.map +1 -0
- package/dist/sidebar-d7Dg80ln.js +511 -0
- package/dist/sidebar-d7Dg80ln.js.map +1 -0
- package/dist/{skeleton-3F0uhYn3.js → skeleton-Cz890JZF.js} +10 -10
- package/dist/skeleton-Cz890JZF.js.map +1 -0
- package/dist/smart-card-lFKxn5Hu.js +595 -0
- package/dist/smart-card-lFKxn5Hu.js.map +1 -0
- package/dist/{spinner-Cpf7oRkF.js → spinner-fa3h1Aif.js} +10 -8
- package/dist/spinner-fa3h1Aif.js.map +1 -0
- package/dist/{structure-CRdqVawd.js → structure-DC2dygdA.js} +3 -3
- package/dist/{structure-CRdqVawd.js.map → structure-DC2dygdA.js.map} +1 -1
- package/dist/{structure.recipes-Bqhf9oIh.js → structure.recipes-EPz60cU8.js} +37 -19
- package/dist/structure.recipes-EPz60cU8.js.map +1 -0
- package/dist/style.css +1 -1
- package/dist/surface-recipes-BKRVW8Os.js +43 -0
- package/dist/surface-recipes-BKRVW8Os.js.map +1 -0
- package/dist/table-CIKyLUsy.js +163 -0
- package/dist/table-CIKyLUsy.js.map +1 -0
- package/dist/{table-CcRDZiLP.js → table-CrcLN9Io.js} +544 -530
- package/dist/table-CrcLN9Io.js.map +1 -0
- package/dist/tabs-DwBJfjxX.js +190 -0
- package/dist/tabs-DwBJfjxX.js.map +1 -0
- package/dist/{text-inputs-DsR56TR-.js → text-inputs-aaK9wcDT.js} +151 -155
- package/dist/text-inputs-aaK9wcDT.js.map +1 -0
- package/dist/{text.styles-Q4sGAIgA.js → text.styles-g4He6UIW.js} +17 -14
- package/dist/text.styles-g4He6UIW.js.map +1 -0
- package/dist/theme.css +16 -12
- package/dist/themes/green.css +24 -0
- package/dist/{timelines-D1pkt3se.js → timelines-C_SBwHNP.js} +154 -164
- package/dist/timelines-C_SBwHNP.js.map +1 -0
- package/dist/tone-recipes-CPoExcTE.js +70 -0
- package/dist/tone-recipes-CPoExcTE.js.map +1 -0
- package/dist/tooltip-CsfgrfS7.js +111 -0
- package/dist/tooltip-CsfgrfS7.js.map +1 -0
- package/dist/track-recipes-CDcKmndW.js +10 -0
- package/dist/track-recipes-CDcKmndW.js.map +1 -0
- package/dist/{tree-BtmYyMZV.js → tree-BiKhg8AY.js} +72 -70
- package/dist/tree-BiKhg8AY.js.map +1 -0
- package/dist/typography/rich-text.js +1 -1
- package/dist/typography-DTRkE9zL.js +117 -0
- package/dist/typography-DTRkE9zL.js.map +1 -0
- package/dist/typography.js +2 -2
- package/dist/{ui-provider-DRPn3qNl.js → ui-provider-1D_NSYzO.js} +30 -23
- package/dist/ui-provider-1D_NSYzO.js.map +1 -0
- package/dist/ui-provider.js +3 -3
- package/dist/{upload-CDbYw1WN.js → upload-BO8-CLN6.js} +294 -293
- package/dist/upload-BO8-CLN6.js.map +1 -0
- package/dist/{upload-queue-CNd_hH_a.js → upload-queue-EOC8g1gf.js} +133 -138
- package/dist/upload-queue-EOC8g1gf.js.map +1 -0
- package/dist/upload.recipes-BbxTqrCT.js +61 -0
- package/dist/upload.recipes-BbxTqrCT.js.map +1 -0
- package/dist/{usage-card-VyJLUwRr.js → usage-card-obRaBskq.js} +42 -43
- package/dist/{usage-card-VyJLUwRr.js.map → usage-card-obRaBskq.js.map} +1 -1
- package/dist/{utils-BvH9PSmq.js → utils-l5LpDw2z.js} +264 -62
- package/dist/utils-l5LpDw2z.js.map +1 -0
- package/dist/value-inputs-TAYMX111.js +947 -0
- package/dist/value-inputs-TAYMX111.js.map +1 -0
- package/dist/value-typography-b8wpz1eX.js +116 -0
- package/dist/value-typography-b8wpz1eX.js.map +1 -0
- package/dist/workspace-DH0v0KcB.js +407 -0
- package/dist/workspace-DH0v0KcB.js.map +1 -0
- package/docs/consumer-skill/SKILL.md +62 -50
- package/docs/consumer-skill/examples/app-layout.tsx +3 -5
- package/docs/consumer-skill/examples/composition.tsx +3 -3
- package/docs/consumer-skill/examples/detail.tsx +59 -13
- package/docs/consumer-skill/examples/edit.tsx +2 -2
- package/docs/consumer-skill/examples/layout-blocks.tsx +20 -0
- package/docs/consumer-skill/examples/manifest.json +28 -6
- package/docs/consumer-skill/examples/receipt.tsx +2 -2
- package/docs/consumer-skill/examples/scoped-directory.tsx +3 -3
- package/docs/consumer-skill/examples/website.tsx +1 -1
- package/docs/consumer-skill/references/agents-md.md +33 -0
- package/docs/consumer-skill/references/analytics.md +1 -1
- package/docs/consumer-skill/references/composition.md +139 -24
- package/docs/consumer-skill/references/design-contract.md +12 -3
- package/docs/consumer-skill/references/discovery.md +4 -0
- package/docs/consumer-skill/references/installation.md +33 -1
- package/docs/consumer-skill/references/integration.md +32 -1
- package/docs/consumer-skill/references/public-api.json +1051 -610
- package/docs/consumer-skill/references/review.md +44 -8
- package/docs/consumer-skill/references/theming.md +14 -4
- package/docs/consumer-skill/references/tokens.json +5 -2
- package/docs/consumer-skill/references/workflows.md +30 -9
- package/docs/consumer-skill/scripts/composition-policy.mjs +127 -6
- package/docs/consumer-skill/scripts/discovery.mjs +11 -3
- package/docs/consumer-skill/scripts/pin-button-defaults.mjs +95 -0
- package/docs/consumer-skill/scripts/surface-policy.mjs +139 -5
- package/package.json +13 -3
- package/dist/accordion-BRTcsp8J.js +0 -205
- package/dist/accordion-BRTcsp8J.js.map +0 -1
- package/dist/action-menu-Drxw_vJk.js +0 -265
- package/dist/action-menu-Drxw_vJk.js.map +0 -1
- package/dist/affordance-geometry.generated-CL84ZN9A.js.map +0 -1
- package/dist/ai-artifact-DLVdK0Py.js.map +0 -1
- package/dist/attachment-DbjUWsP0.js +0 -244
- package/dist/attachment-DbjUWsP0.js.map +0 -1
- package/dist/auth-CAQcasMV.js.map +0 -1
- package/dist/avatar-Bu2HhitA.js.map +0 -1
- package/dist/badge-CzId1Wlm.js +0 -92
- package/dist/badge-CzId1Wlm.js.map +0 -1
- package/dist/breadcrumbs-BuYz5SDU.js +0 -128
- package/dist/breadcrumbs-BuYz5SDU.js.map +0 -1
- package/dist/button-BZDasD04.js +0 -651
- package/dist/button-BZDasD04.js.map +0 -1
- package/dist/button-BZyfTvwm.js.map +0 -1
- package/dist/buttons-D_6KJvEE.js +0 -99
- package/dist/buttons-D_6KJvEE.js.map +0 -1
- package/dist/cards-qGSErLw_.js.map +0 -1
- package/dist/chart-Bsc5BICK.js.map +0 -1
- package/dist/checkbox-BQNDjUCh.js +0 -34
- package/dist/checkbox-BQNDjUCh.js.map +0 -1
- package/dist/choice-inputs-Mk3iWbhr.js +0 -725
- package/dist/choice-inputs-Mk3iWbhr.js.map +0 -1
- package/dist/code-block-DzHKRybS.js +0 -183
- package/dist/code-block-DzHKRybS.js.map +0 -1
- package/dist/combobox-BFnbJJp3.js.map +0 -1
- package/dist/combobox-hozNwUcc.js +0 -847
- package/dist/combobox-hozNwUcc.js.map +0 -1
- package/dist/command-BnmSchli.js.map +0 -1
- package/dist/comments-u5L0OGip.js.map +0 -1
- package/dist/containers-DqB-bSYE.js.map +0 -1
- package/dist/data-display-Bihs9Ven.js +0 -1342
- package/dist/data-display-Bihs9Ven.js.map +0 -1
- package/dist/date-DOKhJPu7.js +0 -140
- package/dist/date-DOKhJPu7.js.map +0 -1
- package/dist/date-picker-DzP5HQq7.js +0 -1541
- package/dist/date-picker-DzP5HQq7.js.map +0 -1
- package/dist/date-pickers-BpgGz7S-.js +0 -196
- package/dist/date-pickers-BpgGz7S-.js.map +0 -1
- package/dist/display-CS6Hbk18.js.map +0 -1
- package/dist/dropdown-menu-D-boNgGO.js.map +0 -1
- package/dist/feedback-CJkUAapr.js +0 -233
- package/dist/feedback-CJkUAapr.js.map +0 -1
- package/dist/field-affordance-recipes-uKY4MsZ_.js +0 -25
- package/dist/field-affordance-recipes-uKY4MsZ_.js.map +0 -1
- package/dist/field-state-recipes-DQQpiLWC.js +0 -11
- package/dist/field-state-recipes-DQQpiLWC.js.map +0 -1
- package/dist/filters-D6FF8L6s.js.map +0 -1
- package/dist/form-sizing-QP8aIRaW.js +0 -103
- package/dist/form-sizing-QP8aIRaW.js.map +0 -1
- package/dist/format-iamDSqs2.js +0 -110
- package/dist/format-iamDSqs2.js.map +0 -1
- package/dist/forms-B5NCbkSC.js.map +0 -1
- package/dist/forms-numeric-Crrm80Lm.js +0 -867
- package/dist/forms-numeric-Crrm80Lm.js.map +0 -1
- package/dist/header-kxruN3RM.js.map +0 -1
- package/dist/icon-badge-Btc6pQrp.js +0 -53
- package/dist/icon-badge-Btc6pQrp.js.map +0 -1
- package/dist/input-SX9V0AL3.js +0 -255
- package/dist/input-SX9V0AL3.js.map +0 -1
- package/dist/item-DE4YnuJx.js +0 -258
- package/dist/item-DE4YnuJx.js.map +0 -1
- package/dist/media-gallery-DLp3HAz0.js +0 -201
- package/dist/media-gallery-DLp3HAz0.js.map +0 -1
- package/dist/mentions-Cl0Kt_Pd.js +0 -565
- package/dist/mentions-Cl0Kt_Pd.js.map +0 -1
- package/dist/navigation-DnQSNMT0.js +0 -276
- package/dist/navigation-DnQSNMT0.js.map +0 -1
- package/dist/navigation-DyytsLRB.js +0 -265
- package/dist/navigation-DyytsLRB.js.map +0 -1
- package/dist/number-DasMFWEG.js +0 -269
- package/dist/number-DasMFWEG.js.map +0 -1
- package/dist/overlay.recipes-BxW5FIfK.js +0 -6
- package/dist/overlay.recipes-BxW5FIfK.js.map +0 -1
- package/dist/overlays-DUbs1KEi.js +0 -1011
- package/dist/overlays-DUbs1KEi.js.map +0 -1
- package/dist/page-hGmT4nWK.js.map +0 -1
- package/dist/page-header-D8nERkn5.js +0 -112
- package/dist/page-header-D8nERkn5.js.map +0 -1
- package/dist/popover-CghIYdQf.js.map +0 -1
- package/dist/primitives-C7ff0QaI.js +0 -337
- package/dist/primitives-C7ff0QaI.js.map +0 -1
- package/dist/progress-BroqrAyV.js.map +0 -1
- package/dist/rich-text-DlxDOtf4.js +0 -32
- package/dist/rich-text-DlxDOtf4.js.map +0 -1
- package/dist/rich-text-editor-BKyG7rWz.js +0 -574
- package/dist/rich-text-editor-BKyG7rWz.js.map +0 -1
- package/dist/rich-text-editor.recipes-B72Nfuze.js +0 -81
- package/dist/rich-text-editor.recipes-B72Nfuze.js.map +0 -1
- package/dist/rich-text-editor.strings-BpnIQgMl.js +0 -25
- package/dist/rich-text-editor.strings-BpnIQgMl.js.map +0 -1
- package/dist/sanitize-html-BG9FGe-j.js +0 -64
- package/dist/sanitize-html-BG9FGe-j.js.map +0 -1
- package/dist/scroll-area-D-pIhEKl.js +0 -47
- package/dist/scroll-area-D-pIhEKl.js.map +0 -1
- package/dist/separator-BNIgG3au.js.map +0 -1
- package/dist/settings-DOTOzeZ2.js +0 -161
- package/dist/settings-DOTOzeZ2.js.map +0 -1
- package/dist/sheet-BFhrNehm.js +0 -205
- package/dist/sheet-BFhrNehm.js.map +0 -1
- package/dist/sidebar-CyR4XKwR.js.map +0 -1
- package/dist/sidebar-SvGJ0Zwi.js +0 -506
- package/dist/sidebar-SvGJ0Zwi.js.map +0 -1
- package/dist/skeleton-3F0uhYn3.js.map +0 -1
- package/dist/smart-card-DjGVV2xr.js +0 -584
- package/dist/smart-card-DjGVV2xr.js.map +0 -1
- package/dist/spinner-Cpf7oRkF.js.map +0 -1
- package/dist/structure.recipes-Bqhf9oIh.js.map +0 -1
- package/dist/surface-recipes-Dd__PD-w.js +0 -28
- package/dist/surface-recipes-Dd__PD-w.js.map +0 -1
- package/dist/table-CLtJTxoR.js +0 -147
- package/dist/table-CLtJTxoR.js.map +0 -1
- package/dist/table-CcRDZiLP.js.map +0 -1
- package/dist/tabs-BNgu7g0u.js +0 -188
- package/dist/tabs-BNgu7g0u.js.map +0 -1
- package/dist/text-inputs-DsR56TR-.js.map +0 -1
- package/dist/text.styles-Q4sGAIgA.js.map +0 -1
- package/dist/timelines-D1pkt3se.js.map +0 -1
- package/dist/track-recipes-LLPNVwFg.js +0 -10
- package/dist/track-recipes-LLPNVwFg.js.map +0 -1
- package/dist/tree-BtmYyMZV.js.map +0 -1
- package/dist/typography-BxQgiZyw.js +0 -96
- package/dist/typography-BxQgiZyw.js.map +0 -1
- package/dist/ui-provider-DRPn3qNl.js.map +0 -1
- package/dist/upload-CDbYw1WN.js.map +0 -1
- package/dist/upload-queue-CNd_hH_a.js.map +0 -1
- package/dist/use-file-drop-target-BX7GnhoQ.js +0 -39
- package/dist/use-file-drop-target-BX7GnhoQ.js.map +0 -1
- package/dist/utils-BvH9PSmq.js.map +0 -1
- package/dist/value-inputs-D0KCrfVC.js +0 -840
- package/dist/value-inputs-D0KCrfVC.js.map +0 -1
- package/dist/workspace-CcR8r-Nt.js +0 -395
- package/dist/workspace-CcR8r-Nt.js.map +0 -1
- /package/dist/components/{blocks/data-display/metadata → base/metadata-list}/metadata-list.strings.d.ts +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Composition review and checks
|
|
2
2
|
|
|
3
|
-
Use after selecting owners,
|
|
4
|
-
workflow/declarations; this is
|
|
3
|
+
Use after selecting owners, when auditing a screen, and before handing back UI
|
|
4
|
+
work. Read only the relevant workflow/declarations; this is not a new design system.
|
|
5
5
|
|
|
6
6
|
## Review the task and hierarchy
|
|
7
7
|
|
|
@@ -19,9 +19,28 @@ workflow/declarations; this is a review aid, not a new design system.
|
|
|
19
19
|
empty/missing values and narrow parent width? Zero and unavailable differ.
|
|
20
20
|
|
|
21
21
|
These criteria allow different product layouts. Do not impose a universal card
|
|
22
|
-
count, row-line limit
|
|
22
|
+
count, row-line limit or one-column form rule. Emphasis is the exception: keep
|
|
23
|
+
one solid primary command per page or surface, so the next action stays obvious.
|
|
23
24
|
|
|
24
|
-
##
|
|
25
|
+
## Done means
|
|
26
|
+
|
|
27
|
+
UI work is done when the source checker below reports no errors on the files you
|
|
28
|
+
changed, and the app's typecheck, lint and tests then pass. Run the checker, fix
|
|
29
|
+
the owner or prop each finding names, and run it again; after three rounds, stop
|
|
30
|
+
and report what remains. Warnings are review findings: fix each one or keep it
|
|
31
|
+
with a reason. This is the agent's completion condition, not the build's; app CI
|
|
32
|
+
may stay non-blocking on warnings. The [project instructions
|
|
33
|
+
block](agents-md.md) states the same condition in the app's `AGENTS.md`.
|
|
34
|
+
|
|
35
|
+
Hand back five lines, so a skipped check is visible:
|
|
36
|
+
|
|
37
|
+
1. Owners used for the route, its commands and each data region.
|
|
38
|
+
2. Checker: run or not run, with its error and warning counts.
|
|
39
|
+
3. Typecheck, lint and tests: each run or not run, and why.
|
|
40
|
+
4. Kept warnings, each with file:line and its reason.
|
|
41
|
+
5. States covered or missing: loading, empty, error, disabled and validation.
|
|
42
|
+
|
|
43
|
+
## Source checker
|
|
25
44
|
|
|
26
45
|
The package ships a read-only script, not an npm bin/global CLI. It needs the
|
|
27
46
|
consumer's TypeScript development dependency and Node matching the package engine:
|
|
@@ -40,12 +59,29 @@ Errors cover unknown package entrypoints/symbols and statically detected overrid
|
|
|
40
59
|
of protected Card/popup insets, Card badges in headerAction/headerStart rather
|
|
41
60
|
than titleSuffix, control geometry/typography, fixed DisplayLabel/Badge
|
|
42
61
|
roles, cross-role shell/inner radius replacements, display-copy margins, or
|
|
43
|
-
|
|
62
|
+
redrawn focus indicators (another ring width, offset or halo strength) on imported controls. Intentional nested bodies,
|
|
44
63
|
circular owners and joined-edge corner resets retain their roles. Import ownership
|
|
45
|
-
follows lexical bindings, preserving locally shadowed application components.
|
|
46
|
-
|
|
47
|
-
warnings; warnings alone do not fail CI. Messages
|
|
64
|
+
follows lexical bindings, preserving locally shadowed application components. Imports of
|
|
65
|
+
symbols the public index marks deprecated, nested framed subjects and repeated
|
|
66
|
+
literal headings produce review warnings; warnings alone do not fail CI. Messages
|
|
67
|
+
identify the owner and remedy. Dialog-like UI outside the overlay owners warns
|
|
68
|
+
too: native elements with `role="dialog"`/`"alertdialog"` or `aria-modal`, a
|
|
69
|
+
`fixed inset-0` layer, and imports of another modal library.
|
|
48
70
|
Standalone compact Cards and Page gutter removal also produce review warnings.
|
|
71
|
+
Buttons placed in a Page or PageHeader `actions` region warn as well: pass
|
|
72
|
+
commands as `primaryAction` and ordered `secondaryActions` so the header owns
|
|
73
|
+
their emphasis, size and overflow. Non-command controls stay valid there.
|
|
74
|
+
A Page with more than one solid primary command, counting `header.primaryAction`
|
|
75
|
+
and every Button with `tone="primary"` and no other style, warns as well. Overlays own
|
|
76
|
+
their own primary command and are not counted. Raw palette classes such as
|
|
77
|
+
`bg-blue-500`, `text-gray-600` or `border-white` warn on any element; use a
|
|
78
|
+
semantic surface/foreground pair or a status tone. A Card title icon and an icon on
|
|
79
|
+
more than one MetadataList fact warn as decoration; keep a glyph only when it
|
|
80
|
+
encodes state or a brand. Native `<button>` and
|
|
81
|
+
`<h1>`–`<h6>` elements warn in favour of Button/TextButton and Heading, which
|
|
82
|
+
own focus, loading and disabled states or margins and the heading scale. A
|
|
83
|
+
native button passed as a package owner's `render`, such as an Item row
|
|
84
|
+
rendered as a button, is that owner's root and does not warn.
|
|
49
85
|
Verified Card-owning Metric/card-grid, UsageCard and TaskCard compositions also
|
|
50
86
|
participate in nested-surface and peer-gap review. Metric without its card variant,
|
|
51
87
|
compact MetricGrid, flat TaskCard, ChartCard and Receipt do not establish a frame.
|
|
@@ -4,7 +4,7 @@ The [design contract](design-contract.md) records which geometry changes togethe
|
|
|
4
4
|
and which variant choices remain independent. Retheme shared responsibilities;
|
|
5
5
|
avoid overriding individual components to imitate another density or inset.
|
|
6
6
|
|
|
7
|
-
Use shadcn semantic surfaces/foregrounds: background, card, popover, primary, secondary, muted, accent, destructive, border, input, ring, charts and sidebar. Central success/info/warning foreground pairs express states; never overload primary or statuses as decoration.
|
|
7
|
+
Use shadcn semantic surfaces/foregrounds: background, card, popover, primary, secondary, muted, accent, destructive, border, input, ring, charts and sidebar. Central success/info/warning foreground pairs express states; never overload primary or statuses as decoration. `--input` is the one control boundary: fields, select and date triggers, checkboxes, radios, switch tracks and outline buttons all draw it, so adjoining controls read as one family. It is deliberately soft and translucent, reading the same on every surface; focus and invalid edges carry the 3:1 contrast. `--border` is for dividers and surface edges. Keep that split when rebranding.
|
|
8
8
|
|
|
9
9
|
tokens.json distinguishes 23 structural roots, advanced typography/status settings, and derived utility spellings. A utility is not another public variable. Keep overrides in one stylesheet at root or ThemeScope, without copying computed CSS into JavaScript.
|
|
10
10
|
|
|
@@ -63,6 +63,12 @@ control heights and copy gaps keep their independent roots.
|
|
|
63
63
|
|
|
64
64
|
Use discrete inset, density and size props for the component responsibility described in [composition](composition.md). CSS scales are independent continuous theme settings. Primary row text does not shrink to xs merely because a density is compact. Public Input and Command search retain normal desktop editable text; coarse-pointer devices use text-base at mobile and tablet widths. Typography components remain margin-free.
|
|
65
65
|
|
|
66
|
+
The default primary is near-black so success and other status colors never compete
|
|
67
|
+
with it. `themelia-react-ui/themes/green.css`, imported after `style.css`, is the
|
|
68
|
+
opt-in Themelia green brand (primary, its foreground, the dark accent and the first
|
|
69
|
+
chart series). Rebrand by setting `--primary` and `--primary-foreground` in both
|
|
70
|
+
`:root` and `.dark`; keep the brand hue clear of the status hues and check 4.5:1.
|
|
71
|
+
|
|
66
72
|
Root overrides reach body portals. Scoped themes use ThemeScope from ui-provider. Advanced editing uses the theme-tweaker public API, editing CSS rather than adding another JavaScript styling system.
|
|
67
73
|
|
|
68
74
|
Explicit portal containers take precedence over the nearest ThemeScope. Place those containers inside the intended theme boundary; a portal deliberately moved outside it cannot inherit that boundary automatically. Test the opened popup, not only its trigger.
|
|
@@ -71,9 +77,13 @@ Apps using semantic utilities in their own JSX process themelia-react-ui/theme.c
|
|
|
71
77
|
|
|
72
78
|
The package class merger recognizes token overrides only for advertised utilities and exact class spellings emitted by the library stylesheet, including their negative, important and responsive forms. A valid Tailwind alias such as `m-space-2xl` can still be absent from that stylesheet. Unshipped aliases preserve existing fallback classes; they do not receive package override semantics merely because an app's separate Tailwind build can generate them. Use the app's own merge configuration for additional app-compiled aliases.
|
|
73
79
|
|
|
74
|
-
`ring` and `sidebar-ring` are focus roles
|
|
75
|
-
|
|
76
|
-
|
|
80
|
+
`ring` and `sidebar-ring` are the focus roles. Every focused element draws one
|
|
81
|
+
indicator: a 1px edge in the role at full strength (the control's own border, an
|
|
82
|
+
inset edge on borderless rows, or an outline just outside link text) inside a
|
|
83
|
+
soft 3px halo of the role at 50%. The edge carries the tested 3:1 contrast
|
|
84
|
+
against adjacent surfaces, so keep the root color at that strength when
|
|
85
|
+
overriding the theme; the halo makes focus stand out without reading as a
|
|
86
|
+
heavier border.
|
|
77
87
|
|
|
78
88
|
## Extend without drift
|
|
79
89
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"package": "themelia-react-ui",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"structural": [
|
|
5
5
|
{
|
|
6
6
|
"name": "--space-scale",
|
|
@@ -121,7 +121,7 @@
|
|
|
121
121
|
"radius": {
|
|
122
122
|
"name": "--radius",
|
|
123
123
|
"default": "0.75rem",
|
|
124
|
-
"purpose": "Shared
|
|
124
|
+
"purpose": "Shared 12px outer corners; inner control/row corners derive from this root and stay rectangular.",
|
|
125
125
|
"defaultUtility": "rounded-radius",
|
|
126
126
|
"innerUtility": "rounded-inner",
|
|
127
127
|
"innerFormula": "min(calc(var(--radius) * 0.75), calc(min(var(--height-action), var(--height-control)) * var(--density-scale) / 4))"
|
|
@@ -209,6 +209,7 @@
|
|
|
209
209
|
"gap-space-lg",
|
|
210
210
|
"gap-space-xl",
|
|
211
211
|
"gap-space-2xl",
|
|
212
|
+
"gap-space-3xl",
|
|
212
213
|
"gap-x-space-2xs",
|
|
213
214
|
"gap-x-space-xs",
|
|
214
215
|
"gap-x-space-sm",
|
|
@@ -216,6 +217,7 @@
|
|
|
216
217
|
"gap-x-space-lg",
|
|
217
218
|
"gap-x-space-xl",
|
|
218
219
|
"gap-x-space-2xl",
|
|
220
|
+
"gap-x-space-3xl",
|
|
219
221
|
"gap-y-space-2xs",
|
|
220
222
|
"gap-y-space-xs",
|
|
221
223
|
"gap-y-space-sm",
|
|
@@ -223,6 +225,7 @@
|
|
|
223
225
|
"gap-y-space-lg",
|
|
224
226
|
"gap-y-space-xl",
|
|
225
227
|
"gap-y-space-2xl",
|
|
228
|
+
"gap-y-space-3xl",
|
|
226
229
|
"p-space-2xs",
|
|
227
230
|
"p-space-xs",
|
|
228
231
|
"p-space-sm",
|
|
@@ -28,9 +28,23 @@ Reset/removal aborts pending uploads; the app owns transport and persistence.
|
|
|
28
28
|
|
|
29
29
|
## Detail and framing
|
|
30
30
|
|
|
31
|
-
[
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
[The detail recipe](../examples/detail.tsx) exports two owners.
|
|
32
|
+
`AccountDetailPage` is the record route: Page owns the title, one status badge,
|
|
33
|
+
the commands and the section tabs. `primaryAction` is Edit account,
|
|
34
|
+
`secondaryActions` holds Send statement and a `destructive` Delete account that
|
|
35
|
+
opens ConfirmDialog, and `header.tabs` carries Overview, Invoices with its count
|
|
36
|
+
badge, and Activity. The header renders `[secondary…] [primary] [⋯]`; destructive
|
|
37
|
+
and overflow commands live in the More actions menu. `AccountDetail` is the same
|
|
38
|
+
facts as one framed subject for a drawer or dashboard, with Edit as its one quick
|
|
39
|
+
`headerAction`. Name, Email, Date, Money and Value own formatting and
|
|
40
|
+
missing-value fallbacks; `balanceMinor` uses `Money unit="minor"`.
|
|
41
|
+
|
|
42
|
+
No optional peers are needed. The app supplies the loaded record, the section
|
|
43
|
+
content and the delete transport, and owns navigation, locale/provider defaults
|
|
44
|
+
and permissions (`visible: false` hides a command). Verify missing
|
|
45
|
+
email/date/balance, a rejected delete that keeps the confirmation open, tab
|
|
46
|
+
selection with keyboard arrows, the narrow layout where secondary commands
|
|
47
|
+
collapse into the menu, and light/dark themes.
|
|
34
48
|
|
|
35
49
|
## Scoped directory
|
|
36
50
|
|
|
@@ -79,12 +93,16 @@ definitions; the app then chooses appropriate destination focus.
|
|
|
79
93
|
|
|
80
94
|
## Single resource page
|
|
81
95
|
|
|
82
|
-
Use `Page
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
96
|
+
Use `Page` from `themelia-react-ui/layout/page` for the record route's identity,
|
|
97
|
+
back navigation, content bounds, commands and section tabs. Pass the record's
|
|
98
|
+
main command as `header.primaryAction`, supporting commands as
|
|
99
|
+
`header.secondaryActions` and sections as `header.tabs`; one status badge goes in
|
|
100
|
+
`header.titleBadges`. `PageHeader` serves a custom shell; `PageActions` is
|
|
101
|
+
deprecated. The [layout recipe](../examples/app-layout.tsx) demonstrates that
|
|
102
|
+
route boundary; the [detail recipe](../examples/detail.tsx) demonstrates the
|
|
103
|
+
record route and an independently framed subject with MetadataList and value
|
|
104
|
+
primitives. Decide whether the record needs that independent Card before nesting
|
|
105
|
+
it under Page. Avoid repeating the
|
|
88
106
|
route heading just to frame the same facts. Page owns gutters; PageViewport owns
|
|
89
107
|
scrolling only. App navigation, record loading/missing/error/retry, permissions,
|
|
90
108
|
edit and delete callbacks remain application responsibilities.
|
|
@@ -92,6 +110,9 @@ edit and delete callbacks remain application responsibilities.
|
|
|
92
110
|
Use `WorkspaceLayout` from `themelia-react-ui/layout/workspace` when independently composed record header,
|
|
93
111
|
sidebar/main/rail regions are needed; inspect `features/resource` for complete
|
|
94
112
|
resource coordination. A single record does not automatically need either.
|
|
113
|
+
Their headers (`WorkspaceRecordHeader`, `ResourceHeader` and the resource shells)
|
|
114
|
+
take the same `primaryAction` and `secondaryActions` as Page; keep their
|
|
115
|
+
`actions` for non-command controls.
|
|
95
116
|
Read [layout composition](composition.md#application-layouts) for boundary and
|
|
96
117
|
parent-width behavior, then the exact selected declaration for its current props.
|
|
97
118
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { surfaceParts, surfaceForwarders, paddingClass, paddingProperty, utility,
|
|
1
|
+
import { surfaceParts, surfaceForwarders, paddingClass, paddingProperty, utility, focusRingDrift, fadedText, sharedCornerParts, displayNames, nativeDisplayNames, marginProperty, radiusProperty, replacesSharedRadius, cornerRole, addsCopyMargin } from './surface-policy.mjs';
|
|
2
2
|
|
|
3
3
|
const controlNames = /^(?:Base)?(?:Button|ButtonLink|IconButton)$|^(Input|InputGroup|InputGroupInput|InputGroupTextarea|Textarea|PasswordInput|Select|SelectTrigger|ComboboxInput|ComboboxInputTrigger|ComboboxTrigger)$/;
|
|
4
4
|
const controlFamilies = new Set(['buttons', 'text-inputs', 'choice-inputs', 'combobox']);
|
|
@@ -9,6 +9,9 @@ const textStyle = /^(fontSize|fontWeight|fontFamily|lineHeight|letterSpacing)$/;
|
|
|
9
9
|
const smallPeerGaps = new Set(['none', 'normal', 'dense', '2xs', 'xs', 'sm', 'md']);
|
|
10
10
|
const structureDefaults = { Stack: 'md', Grid: 'xl', AdaptiveGrid: 'xl' };
|
|
11
11
|
const breakpoints = ['base', 'sm', 'md', 'lg', 'xl', '2xl'];
|
|
12
|
+
const paletteHues = 'slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose|mauve|olive|mist|taupe';
|
|
13
|
+
const rawPaletteClass = new RegExp(`^!?(?:bg|text|border(?:-[xytrblse])?|ring|ring-offset|outline|fill|stroke|from|via|to|divide|decoration|caret|accent|placeholder)-(?:(?:${paletteHues})-(?:50|[1-9]00|950)|black|white)(?:/\\d{1,3})?$`);
|
|
14
|
+
const overlayOwners = ['ActionDialog', 'ConfirmDialog', 'ActionDrawer'];
|
|
12
15
|
|
|
13
16
|
/** Bind this source only; never resolve imports, read libraries or run app code. */
|
|
14
17
|
export function sourceBindings(source, ts) {
|
|
@@ -24,6 +27,16 @@ export function sourceBindings(source, ts) {
|
|
|
24
27
|
}
|
|
25
28
|
|
|
26
29
|
/** Small static review: TypeScript is supplied by the app, never a runtime peer. */
|
|
30
|
+
const overlayRemedy = 'Use ActionDialog, ConfirmDialog or ActionDrawer with useOverlayVisibility from themelia-react-ui/features/overlays; they own focus, dismissal, pending state and portal theming.';
|
|
31
|
+
const modalLibrary = /^(?:@radix-ui\/react-(?:alert-)?dialog|react-modal|vaul|@base-ui(?:-components)?\/react\/(?:alert-)?dialog)$/;
|
|
32
|
+
const modalExports = { '@headlessui/react': /^(?:Dialog|DialogPanel)$/, 'react-aria-components': /^(?:Dialog|Modal|ModalOverlay)$/ };
|
|
33
|
+
const importsModal = (node, ts) => {
|
|
34
|
+
const specifier = node.moduleSpecifier.text;
|
|
35
|
+
if (modalLibrary.test(specifier)) return true;
|
|
36
|
+
const names = node.importClause?.namedBindings;
|
|
37
|
+
return !!modalExports[specifier] && !!names && ts.isNamedImports(names) && names.elements.some(item => modalExports[specifier].test((item.propertyName ?? item.name).text));
|
|
38
|
+
};
|
|
39
|
+
|
|
27
40
|
export function analyzeComposition(text, { filename, index, ts }) {
|
|
28
41
|
const kind = /\.jsx?$/.test(filename) ? ts.ScriptKind.JSX : filename.endsWith('.tsx') ? ts.ScriptKind.TSX : ts.ScriptKind.TS;
|
|
29
42
|
const source = ts.createSourceFile(filename, text, ts.ScriptTarget.Latest, true, kind);
|
|
@@ -116,11 +129,13 @@ export function analyzeComposition(text, { filename, index, ts }) {
|
|
|
116
129
|
for (const item of elements) {
|
|
117
130
|
const symbol = (item.propertyName ?? item.name).text;
|
|
118
131
|
if (!family.symbols.includes(symbol)) add(item, 'public-symbol', 'error', `${specifier} does not export ${symbol}; inspect its declaration.`);
|
|
132
|
+
else if (family.deprecated?.[symbol]) add(item, 'deprecated-owner', 'warning', `${symbol} is deprecated: ${family.deprecated[symbol]}`);
|
|
119
133
|
if (ts.isImportDeclaration(node)) bindings.set(symbolFor(item.name), { symbol, import: specifier });
|
|
120
134
|
}
|
|
121
135
|
if (names && ts.isNamespaceImport(names)) namespaces.set(symbolFor(names.name), specifier);
|
|
122
136
|
}
|
|
123
137
|
function gather(node) {
|
|
138
|
+
if (ts.isImportDeclaration(node) && ts.isStringLiteralLike(node.moduleSpecifier) && importsModal(node, ts)) add(node, 'raw-overlay-primitive', 'warning', `${node.moduleSpecifier.text} builds a second dialog system. ${overlayRemedy}`);
|
|
124
139
|
if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name) && node.initializer) declarations.set(symbolFor(node.name), node.initializer);
|
|
125
140
|
if ((ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) && node.moduleSpecifier && ts.isStringLiteralLike(node.moduleSpecifier)) importOwner(node, node.moduleSpecifier.text);
|
|
126
141
|
if (ts.isImportTypeNode(node) && ts.isLiteralTypeNode(node.argument) && ts.isStringLiteralLike(node.argument.literal)) importOwner(node, node.argument.literal.text);
|
|
@@ -185,6 +200,67 @@ export function analyzeComposition(text, { filename, index, ts }) {
|
|
|
185
200
|
if (ts.isJsxExpression(node)) return slotBadge(node.expression);
|
|
186
201
|
return false;
|
|
187
202
|
};
|
|
203
|
+
// Buttons, command rows and command menus placed directly, conditionally or
|
|
204
|
+
// inside a passive row of a page header's actions region. Unknown local
|
|
205
|
+
// components are custom controls.
|
|
206
|
+
const commandButtons = expression => {
|
|
207
|
+
const node = resolve(expression);
|
|
208
|
+
if (!node) return false;
|
|
209
|
+
if (ts.isJsxElement(node) || ts.isJsxSelfClosingElement(node)) {
|
|
210
|
+
const opening = ts.isJsxElement(node) ? node.openingElement : node;
|
|
211
|
+
const owner = ownerFor(opening.tagName);
|
|
212
|
+
if (isOwner(owner, 'base/buttons', ['Button', 'TextButton', 'BaseButton', 'BaseButtonLink']) || isOwner(owner, 'base/forms', ['SubmitStateButton']) || isOwner(owner, 'base/action-menu', ['ActionMenu', 'ActionButtons']) || isOwner(owner, 'layout/page', ['PageActions']) || isOwner(owner, 'layout', ['PageActions']) || opening.tagName.getText(source) === 'button') return true;
|
|
213
|
+
if (!/^(div|span)$/.test(opening.tagName.getText(source)) && !isOwner(owner, 'base/structure', ['Stack', 'Grid'])) return false;
|
|
214
|
+
return ts.isJsxElement(node) && node.children.some(commandButtons);
|
|
215
|
+
}
|
|
216
|
+
if (ts.isJsxFragment(node)) return node.children.some(commandButtons);
|
|
217
|
+
if (ts.isJsxExpression(node)) return commandButtons(node.expression);
|
|
218
|
+
if (ts.isConditionalExpression(node)) return commandButtons(node.whenTrue) || commandButtons(node.whenFalse);
|
|
219
|
+
if (ts.isBinaryExpression(node) && [ts.SyntaxKind.AmpersandAmpersandToken, ts.SyntaxKind.BarBarToken, ts.SyntaxKind.QuestionQuestionToken].includes(node.operatorToken.kind)) return commandButtons(node.right);
|
|
220
|
+
return false;
|
|
221
|
+
};
|
|
222
|
+
// Static class tokens only; dynamic parts are skipped rather than reported.
|
|
223
|
+
const staticClasses = (expression, visited = new Set()) => {
|
|
224
|
+
const node = resolve(expression);
|
|
225
|
+
if (!node || visited.has(node)) return [];
|
|
226
|
+
visited.add(node);
|
|
227
|
+
if (ts.isStringLiteralLike(node)) return [node.text];
|
|
228
|
+
if (ts.isTemplateExpression(node)) return [node.head.text, ...node.templateSpans.map(span => span.literal.text)];
|
|
229
|
+
if (ts.isConditionalExpression(node)) return [...staticClasses(node.whenTrue, visited), ...staticClasses(node.whenFalse, visited)];
|
|
230
|
+
if (ts.isBinaryExpression(node) && [ts.SyntaxKind.AmpersandAmpersandToken, ts.SyntaxKind.BarBarToken, ts.SyntaxKind.QuestionQuestionToken].includes(node.operatorToken.kind)) return staticClasses(node.right, visited);
|
|
231
|
+
if (ts.isArrayLiteralExpression(node)) return node.elements.flatMap(item => staticClasses(item, visited));
|
|
232
|
+
if (ts.isCallExpression(node) && /^(cn|clsx|classNames|twMerge)$/.test(node.expression.getText(source))) return node.arguments.flatMap(item => staticClasses(item, visited));
|
|
233
|
+
return [];
|
|
234
|
+
};
|
|
235
|
+
const classTokens = opening => {
|
|
236
|
+
const attribute = opening.attributes.properties.find(property => ts.isJsxAttribute(property) && property.name.getText(source) === 'className');
|
|
237
|
+
if (!attribute?.initializer) return [];
|
|
238
|
+
const expression = ts.isJsxExpression(attribute.initializer) ? attribute.initializer.expression : attribute.initializer;
|
|
239
|
+
// Template chunks may split a token; keep only complete-looking words.
|
|
240
|
+
return staticClasses(expression).flatMap(value => value.split(/\s+/)).filter(token => token && !token.startsWith('-') && !token.endsWith('-')).map(utility);
|
|
241
|
+
};
|
|
242
|
+
// tone="primary" is solid unless a buttonStyle says otherwise; untoned Buttons are neutral.
|
|
243
|
+
const solidPrimary = (opening, owner) => {
|
|
244
|
+
if (!isOwner(owner, 'base/buttons', ['Button'])) return false;
|
|
245
|
+
const props = new Map(attributes(opening));
|
|
246
|
+
const style = props.has('buttonStyle') ? literal(props.get('buttonStyle')) : 'solid';
|
|
247
|
+
return literal(props.get('tone')) === 'primary' && style === 'solid';
|
|
248
|
+
};
|
|
249
|
+
// Overlays are separate surfaces with their own primary command.
|
|
250
|
+
const solidPrimaryCount = root => {
|
|
251
|
+
let count = 0;
|
|
252
|
+
const walk = child => {
|
|
253
|
+
if (ts.isJsxElement(child) || ts.isJsxSelfClosingElement(child)) {
|
|
254
|
+
const opening = ts.isJsxElement(child) ? child.openingElement : child;
|
|
255
|
+
const owner = ownerFor(opening.tagName);
|
|
256
|
+
if (isOwner(owner, 'features/overlays', overlayOwners)) return;
|
|
257
|
+
if (solidPrimary(opening, owner)) count++;
|
|
258
|
+
}
|
|
259
|
+
ts.forEachChild(child, walk);
|
|
260
|
+
};
|
|
261
|
+
ts.forEachChild(root, walk);
|
|
262
|
+
return count;
|
|
263
|
+
};
|
|
188
264
|
const peerCards = element => {
|
|
189
265
|
if (!ts.isJsxElement(element.parent)) return new Set();
|
|
190
266
|
const cards = [];
|
|
@@ -239,10 +315,31 @@ export function analyzeComposition(text, { filename, index, ts }) {
|
|
|
239
315
|
if (ts.isJsxSelfClosingElement(node)) inspect(node, parents);
|
|
240
316
|
ts.forEachChild(node, child => visit(child, parents));
|
|
241
317
|
}
|
|
318
|
+
// A native element passed as a package owner's `render` is that owner's root, such as
|
|
319
|
+
// an Item row rendered as a button; the owner keeps its focus, hover and row anatomy.
|
|
320
|
+
const renderRoots = new Set();
|
|
321
|
+
const collectRenderRoots = expression => {
|
|
322
|
+
if (!expression) return;
|
|
323
|
+
if (ts.isJsxSelfClosingElement(expression)) renderRoots.add(expression);
|
|
324
|
+
else if (ts.isJsxElement(expression)) renderRoots.add(expression.openingElement);
|
|
325
|
+
else if (ts.isParenthesizedExpression(expression) || ts.isAsExpression(expression)) collectRenderRoots(expression.expression);
|
|
326
|
+
else if (ts.isConditionalExpression(expression)) { collectRenderRoots(expression.whenTrue); collectRenderRoots(expression.whenFalse); }
|
|
327
|
+
else if (ts.isBinaryExpression(expression)) collectRenderRoots(expression.right);
|
|
328
|
+
else if (ts.isArrowFunction(expression) && !ts.isBlock(expression.body)) collectRenderRoots(expression.body);
|
|
329
|
+
};
|
|
242
330
|
function inspect(node, parents) {
|
|
243
331
|
const owner = ownerFor(node.tagName);
|
|
332
|
+
const render = owner && node.attributes.properties.find(attribute => ts.isJsxAttribute(attribute) && attribute.name.getText(source) === 'render');
|
|
333
|
+
if (render?.initializer) collectRenderRoots(ts.isJsxExpression(render.initializer) ? render.initializer.expression : render.initializer);
|
|
334
|
+
if (classTokens(node).some(token => rawPaletteClass.test(token))) add(node, 'raw-palette-color', 'warning', 'Raw palette colors bypass the theme and dark mode. Use semantic classes such as bg-primary, bg-muted, text-muted-foreground, border-border or a status tone (text-destructive, bg-success/10).');
|
|
244
335
|
if (!owner) {
|
|
245
|
-
|
|
336
|
+
const tag = node.tagName.getText(source);
|
|
337
|
+
if (tag === 'button' && !renderRoots.has(node)) add(node, 'raw-button', 'warning', 'Use Button or TextButton from themelia-react-ui/base/buttons: they own size, focus ring, loading and disabled states.');
|
|
338
|
+
if (/^h[1-6]$/.test(tag)) add(node, 'raw-heading', 'warning', 'Use Heading from themelia-react-ui/typography (tag for the level, size for emphasis): it resets native margins and keeps the shared heading scale.');
|
|
339
|
+
const nativeProps = new Map(attributes(node));
|
|
340
|
+
const modalRole = /^(?:dialog|alertdialog)$/.test(literal(nativeProps.get('role')) ?? '') || nativeProps.has('aria-modal');
|
|
341
|
+
const scrim = classTokens(node).includes('fixed') && classTokens(node).includes('inset-0');
|
|
342
|
+
if (modalRole || scrim) add(node, 'raw-overlay-primitive', 'warning', `A hand-rolled ${modalRole ? 'dialog' : 'full-screen layer'} must own focus, dismissal, pending state and theming itself. ${overlayRemedy}`);
|
|
246
343
|
if (/^(?:input|textarea)$/.test(node.tagName.getText(source))) {
|
|
247
344
|
const props = new Map(attributes(node));
|
|
248
345
|
if (props.has('className') && classStrings(props.get('className')).flatMap(value=>value.split(/\s+/)).some(value=>replacesSharedRadius(value,'inner'))) add(node,'shared-radius','error','Native editable controls follow bounded rounded-inner; change the global theme root, not per-field corners.');
|
|
@@ -272,12 +369,15 @@ export function analyzeComposition(text, { filename, index, ts }) {
|
|
|
272
369
|
const badge = family === 'badge' && owner.symbol === 'Badge';
|
|
273
370
|
for (const name of ['className', 'headerClassName', 'contentClassName', 'footerClassName', 'subHeadingClassName']) {
|
|
274
371
|
if (!props.has(name)) continue;
|
|
275
|
-
const
|
|
372
|
+
const tokens = classStrings(props.get(name)).flatMap(value => value.split(/\s+/)).filter(Boolean);
|
|
373
|
+
const classes = tokens.map(utility);
|
|
374
|
+
const focusDrift = focusRingDrift(tokens);
|
|
276
375
|
if ((anatomy || forwarder && name === 'contentClassName') && classes.some(value => paddingClass.test(value))) add(node, 'surface-padding', 'error', `${owner.symbol}: use inset/type/density and public regions; padding overrides replace owned anatomy.`);
|
|
277
376
|
if (control && name === 'className' && classes.some(value => fixedControlClass.test(value))) add(node, 'control-anatomy', 'error', `${owner.symbol}: use its size/variant props; preserve shared control height, inset, corners and typography.`);
|
|
278
377
|
if ((name === 'className' && (control || sharedCorners) || name === 'contentClassName' && forwarder) && classes.some(value=>replacesSharedRadius(value, control && name === 'className' ? 'inner' : cornerRole(family,owner.symbol)))) add(node,'shared-radius','error',`${owner.symbol}: outer shells use rounded-radius; controls and collection rows use bounded rounded-inner. Preserve the owning role and joined-edge resets.`);
|
|
279
378
|
if (display && classes.some(addsCopyMargin)) add(node,'copy-margin','error',`${owner.symbol}: typography is margin-free; use textGap on the headed owner or gap on Stack/Grid.`);
|
|
280
|
-
if (
|
|
379
|
+
if (display && name === 'className' && tokens.some(fadedText)) add(node,'faded-text','error',`${owner.symbol}: use its type prop (main, secondary) instead of ${[...new Set(tokens.filter(fadedText))].join(', ')}; an opacity-faded text role falls under 4.5:1.`);
|
|
380
|
+
if ((control || family === 'buttons' && owner.symbol === 'TextButton') && name === 'className' && focusDrift.length) add(node, 'focus-ring-recipe', 'error', `${owner.symbol}: keep the shared focus indicator (a ring-3 halo of ring-ring/50 around a full-strength ring edge); ${[...new Set(focusDrift)].join(', ')} redraws it.`);
|
|
281
381
|
if (fixedText && name === 'className' && classes.some(value => fixedTextClass.test(value) || badge && /^rounded(?:-|$)/.test(value))) add(node, 'fixed-text-role', 'error', `${owner.symbol}: preserve its shared typography${badge ? ' and radius' : ''}; use its public variants and className for placement.`);
|
|
282
382
|
}
|
|
283
383
|
if (props.has('style')) for (const [name,value] of properties(props.get('style'))) {
|
|
@@ -287,7 +387,9 @@ export function analyzeComposition(text, { filename, index, ts }) {
|
|
|
287
387
|
if (display && marginProperty.test(name) && !/^['"]?0(?:px|rem|em|%)?['"]?$/.test(resolve(value)?.getText(source)??'')) add(node,'copy-margin','error',`${owner.symbol}: typography is margin-free; the surrounding structure owns its copy gap.`);
|
|
288
388
|
if (fixedText && (textStyle.test(name) || badge && /^border.*Radius$/.test(name))) add(node, 'fixed-text-role', 'error', `${owner.symbol}: ${name} replaces its shared text/radius recipe.`);
|
|
289
389
|
}
|
|
290
|
-
if (['SmartCard', 'ContentBlock'].
|
|
390
|
+
if ((isOwner(owner, 'base/cards', ['Card', 'SmartCard']) || isOwner(owner, 'base/display', ['ContentBlock'])) && props.get('icon')) add(node, 'decorative-icon', 'warning', `${owner.symbol}: a title icon is decoration unless it encodes state or a brand; let the title name the subject.`);
|
|
391
|
+
const facts = isOwner(owner, 'base/metadata-list', ['MetadataList']) || isOwner(owner, 'blocks/data-display', ['MetadataList']) ? resolve(props.get('items')) : undefined;
|
|
392
|
+
if (facts && ts.isArrayLiteralExpression(facts) && facts.elements.filter(item => properties(item, false).some(([name]) => name === 'icon')).length > 1) add(node, 'decorative-icon', 'warning', 'MetadataList: an icon on every fact repeats what its label says; keep labels and drop the icons.');
|
|
291
393
|
const framed = framedOwner(owner, props);
|
|
292
394
|
if (isOwner(owner, 'base/cards', ['Card', 'SmartCard'])) {
|
|
293
395
|
for (const slot of ['headerAction', 'headerStart']) if (slotBadge(props.get(slot))) add(node, 'card-badge-placement', 'error', `${owner.symbol}: put status/count/version badges in titleSuffix; ${slot} owns ${slot === 'headerAction' ? 'commands' : 'pre-title context'}.`);
|
|
@@ -296,7 +398,7 @@ export function analyzeComposition(text, { filename, index, ts }) {
|
|
|
296
398
|
const valueHeading = contents.some(item => role(item, ['Heading']) && /[$€£¥]|\d/.test(renderedText(item.element)));
|
|
297
399
|
if (valueHeading && contents.some(item => role(item, ['Text', 'DisplayLabel'])) && contents.some(item => isOwner(item.owner, 'base/badge', ['Badge']) && /[%+−-]|\d/.test(renderedText(item.element)))) add(node, 'reinvented-metric-card', 'warning', 'This label/value/change composition resembles a KPI. Compare Metric/MetricGrid from blocks/analytics or InlineStat from blocks/data-display; retain a custom subject when their metric lifecycle does not fit.');
|
|
298
400
|
const factRows = contents.filter(item => isOwner(item.owner, 'base/structure', ['Stack']) && literal(item.props.get('direction')) === 'horizontal' && literal(item.props.get('justify')) === 'between' && contentElements(item.opening).filter(child => role(child, ['Text', 'DisplayLabel'])).length >= 2);
|
|
299
|
-
if (factRows.length >= 2) add(node, 'reinvented-metadata-list', 'warning', 'Repeated label/value rows resemble record facts. Compare MetadataList or InlineStat from blocks/data-display; preserve custom rows when they own distinct interactions or content.');
|
|
401
|
+
if (factRows.length >= 2) add(node, 'reinvented-metadata-list', 'warning', 'Repeated label/value rows resemble record facts. Compare MetadataList from base/metadata-list or InlineStat from blocks/data-display; preserve custom rows when they own distinct interactions or content.');
|
|
300
402
|
if (contents.some(item => role(item, ['Heading']) && /^(?:no\b|nothing\b|empty\b)/i.test(renderedText(item.element))) && contents.some(item => isOwner(item.owner, 'base/structure', ['Stack']) && literal(item.props.get('align')) === 'center') && contents.some(item => isOwner(item.owner, 'base/buttons', ['Button', 'ButtonLink']))) add(node, 'reinvented-empty-state', 'warning', 'This centered empty region may fit EmptyState from blocks/data-display, with media, title, description and actions. Review the product state before choosing the complete owner.');
|
|
301
403
|
}
|
|
302
404
|
if (isOwner(owner, 'base/feedback', ['Empty'])) add(node, 'reinvented-empty-state', 'warning', 'Empty exposes lower-level anatomy. Compare EmptyState from blocks/data-display for a routine no-data/no-results region; keep Empty when custom anatomy is required.');
|
|
@@ -307,6 +409,25 @@ export function analyzeComposition(text, { filename, index, ts }) {
|
|
|
307
409
|
if (framed && (!props.has('surface') || literal(props.get('surface')) === 'framed') && peers?.cards.size > 1 && peers.cards.has(node) && peers.smallGap) add(node, 'card-peer-gap', 'warning', 'Small peer gaps can be consumed by framed Card rings. Use lg/xl for independent surfaces and inspect visible edge clearance; tighter grouping needs an intentional surface policy.');
|
|
308
410
|
if (framed && parents.some(parent => parent.framed)) add(node, 'nested-surface', 'warning', `${owner.symbol} is inside a framed owner. Review subject boundaries; use surface="flat" when the parent owns the frame.`);
|
|
309
411
|
const header = properties(props.get('header'), false);
|
|
412
|
+
const pageOwner = owner.import === `${index.package}/layout/page` || owner.import === `${index.package}/layout`;
|
|
413
|
+
// Every header owner takes role-based commands; its free-form regions hold
|
|
414
|
+
// non-command controls only.
|
|
415
|
+
const commandHeader = (pageOwner && owner.symbol === 'PageHeader') || isOwner(owner, 'base/navigation', ['PageHeading']) || isOwner(owner, 'features/resource', ['ResourceHeader', 'ResourceIndexShell', 'ResourceShowShell', 'TabbedResourceShell']) || isOwner(owner, 'layout/settings', ['SettingsShell', 'AsideNavShell']) || isOwner(owner, 'layout', ['SettingsShell', 'AsideNavShell']) || isOwner(owner, 'layout/workspace', ['WorkspaceRecordHeader']);
|
|
416
|
+
const headerActions = pageOwner && owner.symbol === 'Page' ? new Map(header).get('actions') : commandHeader ? props.get('actions') : undefined;
|
|
417
|
+
const elementSecondary = isOwner(owner, 'layout/workspace', ['WorkspaceRecordHeader']) ? props.get('secondaryActions') : undefined;
|
|
418
|
+
if (pageOwner && owner.symbol === 'Page') {
|
|
419
|
+
const primaries = solidPrimaryCount(ts.isJsxSelfClosingElement(node) ? node : node.parent) + (new Map(header).has('primaryAction') ? 1 : 0);
|
|
420
|
+
if (primaries > 1) add(node, 'multiple-primary-commands', 'warning', `Page has ${primaries} solid primary commands. Keep one primary per page as header.primaryAction; leave other commands untoned (the neutral button) or list them in secondaryActions.`);
|
|
421
|
+
}
|
|
422
|
+
if ((headerActions && commandButtons(headerActions)) || (elementSecondary && commandButtons(elementSecondary))) add(node, 'page-command-roles', 'warning', `${owner.symbol}: buttons, command rows and menus in the header actions region choose their own emphasis, order and overflow. Pass commands as primaryAction (one) and ordered secondaryActions; keep actions for non-command controls.`);
|
|
423
|
+
const headerProps = pageOwner && owner.symbol === 'Page' ? new Map(header) : pageOwner && owner.symbol === 'PageHeader' ? props : undefined;
|
|
424
|
+
if (headerProps) {
|
|
425
|
+
if (headerProps.has('titleIcon') && !headerProps.has('titleIconHref') && !headerProps.has('onTitleIconClick')) add(headerProps.get('titleIcon') ?? node, 'decorative-icon', 'warning', `${owner.symbol}: titleIcon decorates the page title; let the title name the page, or link the icon with titleIconHref.`);
|
|
426
|
+
const hasIcon = action => properties(action, false).some(([name]) => name === 'icon');
|
|
427
|
+
const secondary = resolve(headerProps.get('secondaryActions'));
|
|
428
|
+
const iconCommands = (headerProps.has('primaryAction') && hasIcon(headerProps.get('primaryAction')) ? 1 : 0) + (secondary && ts.isArrayLiteralExpression(secondary) ? secondary.elements.filter(hasIcon).length : 0);
|
|
429
|
+
if (iconCommands > 1) add(headerProps.get('secondaryActions') ?? node, 'decorative-icon', 'warning', `${owner.symbol}: ${iconCommands} page commands carry icons that repeat their labels. Keep the labels; reserve an icon for + on an add command or an external link.`);
|
|
430
|
+
}
|
|
310
431
|
const title = literal(props.get('title')) ?? literal(new Map(header).get('title'));
|
|
311
432
|
if (title && parents.some(parent => parent.title === title)) add(node, 'duplicate-heading', 'warning', `The heading "${title}" repeats its ancestor. Keep one route/subject title unless a distinct task warrants repetition.`);
|
|
312
433
|
const structure = owner.import === `${index.package}/base/structure` && Object.hasOwn(structureDefaults, owner.symbol);
|
|
@@ -21,6 +21,7 @@ export function validateIndex(index) {
|
|
|
21
21
|
requireFormat(text(family.declaration) && /^dist\/[\w./-]+\.d\.ts$/.test(family.declaration) && !family.declaration.split('/').includes('..'), `invalid declaration ${family.declaration}`);
|
|
22
22
|
requireFormat(layers.includes(family.layer) && text(family.responsibility), `missing layer/responsibility for ${family.import}`);
|
|
23
23
|
for (const field of ['symbols', 'jobs', 'tags', 'aliases', 'sections', 'optionalPeers']) requireFormat(stringList(family[field]), `invalid ${field} for ${family.import}`);
|
|
24
|
+
if (family.deprecated !== undefined) requireFormat(family.deprecated !== null && typeof family.deprecated === 'object' && !Array.isArray(family.deprecated) && Object.entries(family.deprecated).every(([symbol, note]) => family.symbols.includes(symbol) && text(note)), `invalid deprecated symbols for ${family.import}`);
|
|
24
25
|
if (family.references !== undefined) requireFormat(stringList(family.references) && family.references.every(file => /^references\/[\w/-]+\.md(?:#[\w-]+)?$/.test(file) && !file.split('/').includes('..')), `invalid focused references for ${family.import}`);
|
|
25
26
|
requireFormat(family.optionalPeers.every(peer => index.peers?.some(owner => owner.name === peer && owner.optional)), `unknown optional peer for ${family.import}`);
|
|
26
27
|
if (family.recipes !== undefined) {
|
|
@@ -117,11 +118,18 @@ export function findComponents(index, { query, layer = null, limit = 5 }) {
|
|
|
117
118
|
const score = exactImport ? 10000 : matchedSymbols.length ? 9000 + Number(documentedSymbol) : exactFamily ? 8500 : exactIntent ? 8000 : focusedSymbols.length ? 7100 + 1 / Math.min(...focusedSymbols.map(symbol => words(symbol).length)) : terms.reduce((sum, term) => sum + (family.guidance.some(guide => containsTerms(guide.title, [term])) ? 20 : family.tags.some(tag => containsTerms(tag, [term])) ? 10 : 1), 0);
|
|
118
119
|
const selectedSymbols = matchedSymbols.length ? matchedSymbols : focusedSymbols;
|
|
119
120
|
const guidance = relevantGuidance(family, needle, terms, exactOwners.length ? selectedSymbols : [], exactImport);
|
|
120
|
-
const
|
|
121
|
+
const candidateSymbols = exactImport ? family.symbols : exactOwners.length || matchedSymbols.length ? selectedSymbols : [...new Set([...selectedSymbols, ...guidance.flatMap(guide => guideSymbols(guide, family))])];
|
|
122
|
+
// Intent searches recommend current names only. Exact queries keep the
|
|
123
|
+
// requested symbol; either way the result reports deprecated candidates.
|
|
124
|
+
const lifecycle = family.deprecated ?? {};
|
|
125
|
+
const relevantSymbols = exactImport || matchedSymbols.length ? candidateSymbols : candidateSymbols.filter(symbol => !Object.hasOwn(lifecycle, symbol));
|
|
126
|
+
const deprecated = Object.fromEntries(candidateSymbols.filter(symbol => Object.hasOwn(lifecycle, symbol)).map(symbol => [symbol, lifecycle[symbol]]));
|
|
121
127
|
const candidates = (family.recipes ?? []).filter(recipe => recipe.symbols.some(symbol => relevantSymbols.includes(symbol)));
|
|
122
128
|
const recipeText = recipe => normalized([recipe.file, ...recipe.exports, ...recipe.references].join(' ')).replace(/[-/#]/g, ' ');
|
|
123
129
|
const taskRecipes = matchedSymbols.length || exactImport ? [] : candidates.filter(recipe => terms.every(term => recipeText(recipe).includes(term)));
|
|
124
|
-
|
|
130
|
+
// Retain related task synonyms without routing through an unrelated alias
|
|
131
|
+
// on the same broad family (for example, website versus main/aside layout).
|
|
132
|
+
const aliases = guidance.flatMap(guide => guide.aliases.filter(alias => terms.some(term => containsTerms(alias, [term]))).map(alias => normalized(alias).split(/\s+/)));
|
|
125
133
|
const aliasRecipes = matchedSymbols.length || exactImport ? [] : candidates.filter(recipe => aliases.some(intent => intent.every(term => recipeText(recipe).includes(term))));
|
|
126
134
|
const recipes = taskRecipes.length ? taskRecipes : aliasRecipes.length ? aliasRecipes : candidates;
|
|
127
135
|
const nextReads = {
|
|
@@ -129,7 +137,7 @@ export function findComponents(index, { query, layer = null, limit = 5 }) {
|
|
|
129
137
|
references: [...new Set([...(family.references ?? []), ...recipes.flatMap(recipe => recipe.references)])].sort(compare),
|
|
130
138
|
examples: recipes.map(({ file, exports, symbols, optionalPeers = [] }) => ({ file, exports, symbols: symbols.filter(symbol => relevantSymbols.includes(symbol)), optionalPeers })),
|
|
131
139
|
};
|
|
132
|
-
ranked.push({ score, import: family.import, declaration: family.declaration, layer: family.layer, responsibility: family.responsibility, optionalPeers: family.optionalPeers, match: exactImport ? 'import' : matchedSymbols.length ? 'symbol' : 'intent', matchedSymbols, relevantSymbols, nextReads, guidance });
|
|
140
|
+
ranked.push({ score, import: family.import, declaration: family.declaration, layer: family.layer, responsibility: family.responsibility, optionalPeers: family.optionalPeers, match: exactImport ? 'import' : matchedSymbols.length ? 'symbol' : 'intent', matchedSymbols, relevantSymbols, ...(Object.keys(deprecated).length ? { deprecated } : {}), nextReads, guidance });
|
|
133
141
|
}
|
|
134
142
|
ranked.sort((a, b) => b.score - a.score || compare(a.import, b.import));
|
|
135
143
|
return { package: index.package, version: index.version, query, layer, limit, total: ranked.length, results: ranked.slice(0, limit) };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { createRequire } from 'node:module';
|
|
4
|
+
import { pathToFileURL } from 'node:url';
|
|
5
|
+
import { sourceBindings } from './composition-policy.mjs';
|
|
6
|
+
|
|
7
|
+
// An untoned Button now renders as the secondary outline, and a Button with a
|
|
8
|
+
// tone but no buttonStyle keeps that tone's solid treatment. Writing the old
|
|
9
|
+
// default tone onto untoned Buttons therefore keeps an existing screen's look.
|
|
10
|
+
// It edits only with --write; otherwise it reports what it would change.
|
|
11
|
+
// --solid-only pins only Buttons that also set no buttonStyle, so untoned
|
|
12
|
+
// outline and ghost Buttons (often brand-coloured by accident) turn neutral.
|
|
13
|
+
const usage = 'Usage: pin-button-defaults.mjs [--write] [--solid-only] [--tone=primary] [--source-root=<dir>] <files or directories>';
|
|
14
|
+
const owners = new Set(['Button', 'BaseButton', 'BaseButtonLink']);
|
|
15
|
+
const packageImports = new Set(['themelia-react-ui', 'themelia-react-ui/base/buttons']);
|
|
16
|
+
|
|
17
|
+
export function pinButtonDefaults(text, { filename, ts, tone = 'primary', solidOnly = false, sourceRoot }) {
|
|
18
|
+
const kind = /\.jsx?$/.test(filename) ? ts.ScriptKind.JSX : filename.endsWith('.tsx') ? ts.ScriptKind.TSX : ts.ScriptKind.TS;
|
|
19
|
+
const source = ts.createSourceFile(filename, text, ts.ScriptTarget.Latest, true, kind);
|
|
20
|
+
const symbolFor = sourceBindings(source, ts);
|
|
21
|
+
// Library maintainers pass --source-root so relative imports of the buttons family count too.
|
|
22
|
+
const buttonsDir = sourceRoot && path.resolve(sourceRoot, 'components/base/buttons');
|
|
23
|
+
const isButtonsImport = specifier => packageImports.has(specifier)
|
|
24
|
+
|| (!!buttonsDir && specifier.startsWith('.') && `${path.resolve(path.dirname(filename), specifier)}/`.startsWith(`${buttonsDir}/`));
|
|
25
|
+
const named = new Set();
|
|
26
|
+
const namespaces = new Set();
|
|
27
|
+
for (const statement of source.statements) {
|
|
28
|
+
if (!ts.isImportDeclaration(statement) || !ts.isStringLiteral(statement.moduleSpecifier) || !isButtonsImport(statement.moduleSpecifier.text)) continue;
|
|
29
|
+
const bindings = statement.importClause?.namedBindings;
|
|
30
|
+
if (bindings && ts.isNamespaceImport(bindings)) namespaces.add(symbolFor(bindings.name));
|
|
31
|
+
if (bindings && ts.isNamedImports(bindings)) for (const item of bindings.elements) {
|
|
32
|
+
if (!item.isTypeOnly && owners.has((item.propertyName ?? item.name).text)) named.add(symbolFor(item.name));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const isOwner = tag => (ts.isIdentifier(tag) && named.has(symbolFor(tag)))
|
|
36
|
+
|| (ts.isPropertyAccessExpression(tag) && ts.isIdentifier(tag.expression) && namespaces.has(symbolFor(tag.expression)) && owners.has(tag.name.text));
|
|
37
|
+
const edits = [];
|
|
38
|
+
const pinned = [];
|
|
39
|
+
const unresolved = [];
|
|
40
|
+
const line = node => source.getLineAndCharacterOfPosition(node.getStart(source)).line + 1;
|
|
41
|
+
const visit = node => {
|
|
42
|
+
if ((ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) && isOwner(node.tagName)) {
|
|
43
|
+
const props = node.attributes.properties;
|
|
44
|
+
const has = name => props.some(attribute => ts.isJsxAttribute(attribute) && attribute.name.getText(source) === name);
|
|
45
|
+
const toned = has('tone') || (solidOnly && has('buttonStyle'));
|
|
46
|
+
if (!toned && props.some(ts.isJsxSpreadAttribute)) {
|
|
47
|
+
// A spread may already carry tone; leave it to review.
|
|
48
|
+
unresolved.push({ file: filename, line: line(node) });
|
|
49
|
+
} else if (!toned) {
|
|
50
|
+
edits.push({ at: (node.typeArguments ?? node.tagName).end, text: ` tone="${tone}"` });
|
|
51
|
+
pinned.push({ file: filename, line: line(node), tone });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
ts.forEachChild(node, visit);
|
|
55
|
+
};
|
|
56
|
+
visit(source);
|
|
57
|
+
let output = text;
|
|
58
|
+
for (const edit of edits.sort((a, b) => b.at - a.at)) output = output.slice(0, edit.at) + edit.text + output.slice(edit.at);
|
|
59
|
+
return { output, pinned, unresolved };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function collect(target, files) {
|
|
63
|
+
const info = fs.lstatSync(target);
|
|
64
|
+
if (info.isSymbolicLink()) throw new Error(`Use a real source path instead of a symlink: ${target}`);
|
|
65
|
+
if (info.isDirectory()) {
|
|
66
|
+
for (const entry of fs.readdirSync(target).sort()) if (!['node_modules', '.git', 'dist', 'build'].includes(entry)) collect(path.join(target, entry), files);
|
|
67
|
+
} else if (/\.[jt]sx?$/.test(target) && !/\.d\.ts$/.test(target)) files.add(path.resolve(target));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href) {
|
|
71
|
+
try {
|
|
72
|
+
const args = process.argv.slice(2);
|
|
73
|
+
const option = name => args.find(arg => arg.startsWith(`--${name}=`))?.slice(name.length + 3);
|
|
74
|
+
const targets = args.filter(arg => !arg.startsWith('--'));
|
|
75
|
+
const unknown = args.filter(arg => arg.startsWith('--') && !/^--(?:write|solid-only|tone=.+|source-root=.+)$/.test(arg));
|
|
76
|
+
if (!targets.length || unknown.length) throw new Error(unknown.length ? `Unknown option: ${unknown.join(', ')}\n${usage}` : usage);
|
|
77
|
+
const ts = createRequire(path.join(process.cwd(), 'package.json'))('typescript');
|
|
78
|
+
const files = new Set();
|
|
79
|
+
targets.forEach(target => collect(target, files));
|
|
80
|
+
if (!files.size) throw new Error('No supported source files found in the supplied paths.');
|
|
81
|
+
const write = args.includes('--write');
|
|
82
|
+
const sourceRoot = option('source-root') && path.resolve(option('source-root'));
|
|
83
|
+
const results = [...files].sort().map(filename => {
|
|
84
|
+
const text = fs.readFileSync(filename, 'utf8');
|
|
85
|
+
const result = pinButtonDefaults(text, { filename, ts, tone: option('tone'), solidOnly: args.includes('--solid-only'), sourceRoot });
|
|
86
|
+
if (write && result.output !== text) fs.writeFileSync(filename, result.output);
|
|
87
|
+
return result;
|
|
88
|
+
});
|
|
89
|
+
const pinned = results.flatMap(result => result.pinned);
|
|
90
|
+
process.stdout.write(JSON.stringify({ mode: write ? 'write' : 'dry-run', files: files.size, pinned: pinned.length, changedFiles: new Set(pinned.map(item => item.file)).size, unresolved: results.flatMap(result => result.unresolved), details: pinned }, null, 2) + '\n');
|
|
91
|
+
} catch (error) {
|
|
92
|
+
process.stderr.write(`pin-button-defaults: ${error.message}\nRun from the consumer app with its TypeScript development dependency installed.\n`);
|
|
93
|
+
process.exitCode = 1;
|
|
94
|
+
}
|
|
95
|
+
}
|