themelia-react-ui 2.0.0 → 2.0.2
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 +527 -0
- package/README.md +47 -14
- package/THIRD_PARTY_NOTICES.md +13 -0
- package/dist/accordion-Cjb6sx0G.js +208 -0
- package/dist/accordion-Cjb6sx0G.js.map +1 -0
- package/dist/action-menu-CllU52Mm.js +280 -0
- package/dist/action-menu-CllU52Mm.js.map +1 -0
- package/dist/affordance-geometry.generated-tF36bREk.js +140 -0
- package/dist/affordance-geometry.generated-tF36bREk.js.map +1 -0
- package/dist/ai-artifact-DvTwDVyL.js +1148 -0
- package/dist/ai-artifact-DvTwDVyL.js.map +1 -0
- package/dist/{app-shell-BE_j8-AT.js → app-shell-C4FhvCqF.js} +5 -5
- package/dist/{app-shell-BE_j8-AT.js.map → app-shell-C4FhvCqF.js.map} +1 -1
- package/dist/attachment-BxDfL2mw.js +246 -0
- package/dist/attachment-BxDfL2mw.js.map +1 -0
- package/dist/{auth-M3vGMgDR.js → auth-ax2BqjrI.js} +241 -235
- package/dist/auth-ax2BqjrI.js.map +1 -0
- package/dist/{avatar-djdaaQ_s.js → avatar-DAPlDvhJ.js} +67 -66
- package/dist/avatar-DAPlDvhJ.js.map +1 -0
- package/dist/badge-HpFqoqSY.js +93 -0
- package/dist/badge-HpFqoqSY.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 +50 -46
- package/dist/base/carousel.js.map +1 -1
- package/dist/base/cascader.js +69 -81
- 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 +2 -2
- 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 +20 -20
- 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 +1 -1
- package/dist/base/repeaters.js +216 -220
- 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 +147 -137
- package/dist/base/signature-pad.js.map +1 -1
- package/dist/base/skeleton.js +1 -1
- package/dist/base/spinner.js +79 -2
- package/dist/base/spinner.js.map +1 -0
- 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 +46 -45
- 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-DnUJ21NQ.js +105 -0
- package/dist/batch-action-bar-DnUJ21NQ.js.map +1 -0
- package/dist/blocks/admin.js +171 -169
- package/dist/blocks/admin.js.map +1 -1
- package/dist/blocks/ai.js +308 -285
- package/dist/blocks/ai.js.map +1 -1
- package/dist/blocks/analytics/usage-card.js +1 -1
- package/dist/blocks/analytics.js +626 -589
- 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 +2051 -1329
- package/dist/blocks/commerce.js.map +1 -1
- package/dist/blocks/data-display.js +3 -2
- package/dist/blocks/onboarding.js +68 -58
- package/dist/blocks/onboarding.js.map +1 -1
- package/dist/blocks/planning.js +27 -26
- package/dist/blocks/planning.js.map +1 -1
- package/dist/blocks/timelines.js +1 -1
- package/dist/breadcrumbs-C-oqs1sQ.js +129 -0
- package/dist/breadcrumbs-C-oqs1sQ.js.map +1 -0
- package/dist/{button-R9CCoH7A.js → button-DVzspB_G.js} +15 -14
- package/dist/button-DVzspB_G.js.map +1 -0
- package/dist/{button-BS3KDg00.js → buttons-DPZekJFu.js} +208 -216
- package/dist/buttons-DPZekJFu.js.map +1 -0
- package/dist/cards-BaBZR-AU.js +68 -0
- package/dist/cards-BaBZR-AU.js.map +1 -0
- package/dist/{chart-DwYRKKc-.js → chart-ZOYyK2xG.js} +58 -55
- package/dist/chart-ZOYyK2xG.js.map +1 -0
- package/dist/checkbox-AWIhNhmo.js +36 -0
- package/dist/checkbox-AWIhNhmo.js.map +1 -0
- package/dist/choice-inputs-CNHvARCJ.js +770 -0
- package/dist/choice-inputs-CNHvARCJ.js.map +1 -0
- package/dist/code-block-DeneBJR_.js +185 -0
- package/dist/code-block-DeneBJR_.js.map +1 -0
- package/dist/{collapsible-oMUGM4tr.js → collapsible-C-_l4hpy.js} +4 -4
- package/dist/{collapsible-oMUGM4tr.js.map → collapsible-C-_l4hpy.js.map} +1 -1
- package/dist/{collection-content-Ys-OZOkY.js → collection-content-By56pLog.js} +3 -3
- package/dist/{collection-content-Ys-OZOkY.js.map → collection-content-By56pLog.js.map} +1 -1
- package/dist/combobox-C0EQW6dr.js +875 -0
- package/dist/combobox-C0EQW6dr.js.map +1 -0
- package/dist/combobox-xCQ2RMNE.js +309 -0
- package/dist/combobox-xCQ2RMNE.js.map +1 -0
- package/dist/{command-kPMPjIxJ.js → command-C25VMRII.js} +7 -7
- package/dist/{command-kPMPjIxJ.js.map → command-C25VMRII.js.map} +1 -1
- package/dist/{comments-You0Bzbr.js → comments-BYYlTA8E.js} +390 -379
- package/dist/comments-BYYlTA8E.js.map +1 -0
- package/dist/components/base/action-menu/action-menu.d.ts +21 -4
- 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/badge/badge.recipes.d.ts +5 -5
- 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/button-group.recipes.d.ts +1 -1
- package/dist/components/base/buttons/button.recipes.d.ts +2 -2
- package/dist/components/base/buttons/loader-button.d.ts +2 -1
- package/dist/components/base/cards/card.recipes.d.ts +2 -3
- package/dist/components/base/cards/partials/smart-card-skeleton.d.ts +3 -13
- package/dist/components/base/cards/smart-card.types.d.ts +11 -4
- package/dist/components/base/chart/chart.d.ts +2 -5
- package/dist/components/base/choice-inputs/checkbox.d.ts +2 -2
- package/dist/components/base/choice-inputs/choice-types.d.ts +18 -6
- package/dist/components/base/combobox/combobox.strings.d.ts +7 -0
- package/dist/components/base/combobox/index.d.ts +30 -4
- package/dist/components/base/display/alert-dialog.d.ts +6 -5
- package/dist/components/base/display/dialog.d.ts +4 -8
- package/dist/components/base/display/icon-badge/icon-badge.d.ts +1 -1
- package/dist/components/base/forms/form-sizing.d.ts +26 -15
- 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/index.d.ts +1 -1
- 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 +26 -3
- package/dist/components/base/navigation/pagination.d.ts +5 -2
- package/dist/components/base/popover/popover.recipes.d.ts +15 -1
- package/dist/components/base/sheet/sheet.d.ts +4 -8
- 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/table/index.d.ts +9 -2
- 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 +25 -3
- package/dist/components/base/value-inputs/index.d.ts +5 -5
- package/dist/components/base/value-inputs/tags-input.d.ts +36 -12
- package/dist/components/blocks/ai/ai-shimmer/ai-shimmer.d.ts +1 -1
- package/dist/components/blocks/ai/ai-shimmer/types.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 +2 -1
- 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 +45 -0
- package/dist/components/blocks/commerce/index.d.ts +13 -5
- 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/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-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 +12 -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/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/data-display/inline-stat/inline-stat.d.ts +16 -8
- package/dist/components/blocks/data-display/metadata/index.d.ts +30 -4
- package/dist/components/features/activities/partials/activity-marker.d.ts +6 -3
- 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/appointment-calendar/appointment-calendar.d.ts +5 -0
- package/dist/components/features/appointment-calendar/appointment-calendar.types.d.ts +220 -0
- package/dist/components/features/appointment-calendar/appointment-calendar.utils.d.ts +41 -0
- package/dist/components/features/appointment-calendar/index.d.ts +3 -0
- package/dist/components/features/appointment-calendar/partials/appointment-agenda.d.ts +32 -0
- package/dist/components/features/appointment-calendar/partials/appointment-month.d.ts +13 -0
- package/dist/components/features/combobox/combobox.strings.d.ts +15 -1
- package/dist/components/features/combobox/types.d.ts +4 -0
- package/dist/components/features/global-search/partials/global-search-group-heading.d.ts +15 -0
- 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 +6 -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/index.d.ts +1 -1
- package/dist/components/features/overlays/overlay-tone-icon.d.ts +3 -3
- package/dist/components/features/overlays/overlays.types.d.ts +20 -0
- 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/products.types.d.ts +9 -2
- 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 +7 -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 +54 -1
- 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/table-header.d.ts +1 -1
- package/dist/components/features/table/table.strings.d.ts +55 -1
- package/dist/components/features/table/table.types.d.ts +49 -11
- package/dist/components/features/theme-tweaker/theme-tweaker.types.d.ts +5 -0
- package/dist/components/layout/page/index.d.ts +1 -1
- package/dist/components/layout/page/page.types.d.ts +33 -36
- 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/number.d.ts +4 -2
- package/dist/components/primitives/value.d.ts +3 -1
- 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/text-link.d.ts +8 -3
- package/dist/components/ui/checkbox.d.ts +4 -3
- package/dist/components/ui/combobox.d.ts +6 -2
- package/dist/components/ui/item.d.ts +8 -8
- package/dist/components/ui/overlay.recipes.d.ts +0 -9
- package/dist/components/ui/switch.d.ts +2 -2
- package/dist/components/ui/tabs.d.ts +1 -1
- package/dist/{containers-D_L4mTVb.js → containers-Mu1LMGV1.js} +36 -35
- package/dist/containers-Mu1LMGV1.js.map +1 -0
- package/dist/{copyable-DDjTeW_j.js → copyable-ClBuk_UK.js} +6 -6
- package/dist/{copyable-DDjTeW_j.js.map → copyable-ClBuk_UK.js.map} +1 -1
- package/dist/data-display-DT_khPl_.js +971 -0
- package/dist/data-display-DT_khPl_.js.map +1 -0
- package/dist/{date-uf3z37Nm.js → date-DCrsDTZc.js} +5 -5
- package/dist/{date-uf3z37Nm.js.map → date-DCrsDTZc.js.map} +1 -1
- package/dist/date-picker-ay0Pha_a.js +1530 -0
- package/dist/date-picker-ay0Pha_a.js.map +1 -0
- package/dist/date-pickers-Ccw8DL2b.js +175 -0
- package/dist/date-pickers-Ccw8DL2b.js.map +1 -0
- package/dist/display-hAc1HjpI.js +344 -0
- package/dist/display-hAc1HjpI.js.map +1 -0
- package/dist/dropdown-menu-Cl4X7L5S.js +193 -0
- package/dist/dropdown-menu-Cl4X7L5S.js.map +1 -0
- package/dist/editable-text-recipe-Cn61kEcv.js +10 -0
- package/dist/editable-text-recipe-Cn61kEcv.js.map +1 -0
- package/dist/features/activities.js +478 -542
- package/dist/features/activities.js.map +1 -1
- package/dist/features/ai-chat.js +209 -199
- package/dist/features/ai-chat.js.map +1 -1
- package/dist/features/appointment-calendar.js +683 -0
- package/dist/features/appointment-calendar.js.map +1 -0
- package/dist/features/async-preview.js +109 -107
- 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 +30 -29
- package/dist/features/data-view.js.map +1 -1
- package/dist/features/email-composer/engine.js +1 -1
- package/dist/features/email-composer.js +285 -283
- package/dist/features/email-composer.js.map +1 -1
- package/dist/features/event-calendar.js +282 -273
- package/dist/features/event-calendar.js.map +1 -1
- package/dist/features/filters.js +1 -1
- package/dist/features/global-search.js +318 -318
- package/dist/features/global-search.js.map +1 -1
- package/dist/features/kanban.js +146 -147
- package/dist/features/kanban.js.map +1 -1
- package/dist/features/map.js +269 -268
- package/dist/features/map.js.map +1 -1
- package/dist/features/media-library.js +970 -863
- 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 +1137 -1124
- package/dist/features/products.js.map +1 -1
- package/dist/features/questionnaire.js +206 -194
- package/dist/features/questionnaire.js.map +1 -1
- package/dist/features/resource-assignment.js +24 -21
- 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 +35 -33
- package/dist/features/schema-form.js.map +1 -1
- package/dist/features/suggestions.js +3 -3
- package/dist/features/sync.js +11 -5
- package/dist/features/sync.js.map +1 -1
- package/dist/features/table.js +1 -1
- package/dist/features/theme-tweaker.js +501 -496
- package/dist/features/theme-tweaker.js.map +1 -1
- package/dist/feedback-BYIhtitP.js +239 -0
- package/dist/feedback-BYIhtitP.js.map +1 -0
- package/dist/field-affordance-recipes-DZhnIL_Y.js +41 -0
- package/dist/field-affordance-recipes-DZhnIL_Y.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-Da-gNPsE.js → filters-BGfvjP4d.js} +483 -472
- package/dist/filters-BGfvjP4d.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-VZRULhUK.js → form-field-CwH9y77i.js} +6 -5
- package/dist/form-field-CwH9y77i.js.map +1 -0
- package/dist/{form-sizing-uWP4lzVh.js → form-sizing-BdP_Mf5p.js} +45 -46
- package/dist/form-sizing-BdP_Mf5p.js.map +1 -0
- package/dist/{forms-DDeEnXSY.js → forms-B9G_xwzi.js} +22 -22
- package/dist/{forms-DDeEnXSY.js.map → forms-B9G_xwzi.js.map} +1 -1
- package/dist/forms-numeric-B_jraJaQ.js +906 -0
- package/dist/forms-numeric-B_jraJaQ.js.map +1 -0
- package/dist/{header-2ycNqGOR.js → header-CGXuhcRm.js} +164 -161
- package/dist/header-CGXuhcRm.js.map +1 -0
- package/dist/{hooks-DQ5SPwZw.js → hooks-Dkz0K2WT.js} +2 -2
- package/dist/{hooks-DQ5SPwZw.js.map → hooks-Dkz0K2WT.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-DYKIwvOV.js +55 -0
- package/dist/icon-badge-DYKIwvOV.js.map +1 -0
- package/dist/index.js +7 -7
- package/dist/input-CZw8iU99.js +21 -0
- package/dist/input-CZw8iU99.js.map +1 -0
- package/dist/input-DQdEd0YD.js +263 -0
- package/dist/input-DQdEd0YD.js.map +1 -0
- package/dist/interaction-recipes-XR9ZpVYL.js +25 -0
- package/dist/interaction-recipes-XR9ZpVYL.js.map +1 -0
- package/dist/item-K5_ghvze.js +275 -0
- package/dist/item-K5_ghvze.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 +72 -0
- package/dist/lib/editable-text-recipe.d.ts +4 -4
- package/dist/lib/field-affordance-recipes.d.ts +8 -3
- package/dist/lib/field-state-recipes.d.ts +9 -8
- package/dist/lib/focus-recipes.d.ts +24 -0
- package/dist/lib/interaction-recipes.d.ts +40 -0
- package/dist/lib/layer-recipes.d.ts +19 -0
- package/dist/lib/motion-recipes.d.ts +1 -0
- package/dist/lib/overlay-anatomy-recipes.d.ts +1 -0
- 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 +47 -7
- package/dist/lib/theme-mode-css.d.ts +7 -0
- package/dist/lib/token-merge.generated.d.ts +9 -6
- package/dist/lib/tone-recipes.d.ts +87 -0
- 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/types.d.ts +11 -2
- package/dist/lib/utils.js +1 -1
- package/dist/media-gallery-3zIVLMWH.js +203 -0
- package/dist/media-gallery-3zIVLMWH.js.map +1 -0
- package/dist/mentions-utuUvH1K.js +570 -0
- package/dist/mentions-utuUvH1K.js.map +1 -0
- package/dist/{message-YfFmbXNP.js → message-DZ_ruyUV.js} +7 -6
- package/dist/message-DZ_ruyUV.js.map +1 -0
- package/dist/metadata-list-8N16ZMW_.js +405 -0
- package/dist/metadata-list-8N16ZMW_.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-Bnotn4AQ.js +145 -0
- package/dist/navigation-Bnotn4AQ.js.map +1 -0
- package/dist/navigation-BzhHI3lo.js +269 -0
- package/dist/navigation-BzhHI3lo.js.map +1 -0
- package/dist/{navigation-row-recipes-DlU-4QYO.js → navigation-row-recipes-BFLCk_Aq.js} +2 -2
- package/dist/{navigation-row-recipes-DlU-4QYO.js.map → navigation-row-recipes-BFLCk_Aq.js.map} +1 -1
- package/dist/{number-CKRBYmZK.js → number-DbV1Dija.js} +36 -34
- package/dist/{number-CKRBYmZK.js.map → number-DbV1Dija.js.map} +1 -1
- package/dist/overflow-tab-bar-CWY7Nogn.js +282 -0
- package/dist/overflow-tab-bar-CWY7Nogn.js.map +1 -0
- package/dist/overlay.recipes-8GHqmlb4.js +6 -0
- package/dist/overlay.recipes-8GHqmlb4.js.map +1 -0
- package/dist/overlays-DNWmZrJ4.js +1001 -0
- package/dist/overlays-DNWmZrJ4.js.map +1 -0
- package/dist/page-Bgl1F560.js +224 -0
- package/dist/page-Bgl1F560.js.map +1 -0
- package/dist/page-header-commands-DOb6WsfD.js +126 -0
- package/dist/page-header-commands-DOb6WsfD.js.map +1 -0
- package/dist/pagination-BL25hu2s.js +158 -0
- package/dist/pagination-BL25hu2s.js.map +1 -0
- package/dist/{popover-Dcv_9jxr.js → popover-7_m66eYW.js} +11 -10
- package/dist/popover-7_m66eYW.js.map +1 -0
- package/dist/popover-menu-B9WWygpa.js +100 -0
- package/dist/popover-menu-B9WWygpa.js.map +1 -0
- package/dist/{popover.recipes-wmbvL8Ah.js → popover.recipes-D3j8R8Yp.js} +18 -11
- package/dist/popover.recipes-D3j8R8Yp.js.map +1 -0
- package/dist/{primitives-BHrwQXFC.js → primitives-BFK08r9M.js} +45 -44
- package/dist/primitives-BFK08r9M.js.map +1 -0
- package/dist/primitives.js +4 -4
- package/dist/{progress-Br9WTFya.js → progress-B1VnCT0K.js} +9 -9
- package/dist/{progress-Br9WTFya.js.map → progress-B1VnCT0K.js.map} +1 -1
- package/dist/{receipt-CV89q1fs.js → receipt-BVSOH3Xo.js} +9 -6
- package/dist/{receipt-CV89q1fs.js.map → receipt-BVSOH3Xo.js.map} +1 -1
- package/dist/rich-text-GOUyKQ-s.js +78 -0
- package/dist/rich-text-GOUyKQ-s.js.map +1 -0
- package/dist/rich-text-editor-cRLC-eBK.js +1196 -0
- package/dist/rich-text-editor-cRLC-eBK.js.map +1 -0
- package/dist/rich-text-editor-toolbar-DfXg0-VC.js +94 -0
- package/dist/rich-text-editor-toolbar-DfXg0-VC.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-DcI-M1UT.js +48 -0
- package/dist/scroll-area-DcI-M1UT.js.map +1 -0
- package/dist/{separator-Do5GWDYi.js → separator-BDV-Y648.js} +3 -3
- package/dist/{separator-Do5GWDYi.js.map → separator-BDV-Y648.js.map} +1 -1
- package/dist/{separator-BMEvwnSX.js → separator-Bom7NsGO.js} +2 -2
- package/dist/{separator-BMEvwnSX.js.map → separator-Bom7NsGO.js.map} +1 -1
- package/dist/services/actions/action-adapters.d.ts +18 -0
- package/dist/services/actions/index.d.ts +1 -1
- package/dist/services/actions.js +16 -4
- package/dist/services/actions.js.map +1 -1
- package/dist/settings-ybnjVwbd.js +171 -0
- package/dist/settings-ybnjVwbd.js.map +1 -0
- package/dist/sheet-CGpB3omz.js +211 -0
- package/dist/sheet-CGpB3omz.js.map +1 -0
- package/dist/{sidebar-Cb8WzOvE.js → sidebar-A0ElHINE.js} +17 -16
- package/dist/sidebar-A0ElHINE.js.map +1 -0
- package/dist/{sidebar-Crc9M9JV.js → sidebar-CPx_7YBa.js} +205 -203
- package/dist/sidebar-CPx_7YBa.js.map +1 -0
- package/dist/{skeleton-DVMXr15h.js → skeleton-Byjnt7qr.js} +9 -9
- package/dist/{skeleton-DVMXr15h.js.map → skeleton-Byjnt7qr.js.map} +1 -1
- package/dist/smart-card-DiC5aac3.js +604 -0
- package/dist/smart-card-DiC5aac3.js.map +1 -0
- package/dist/{structure-hzCW-XsV.js → structure-BmisBK-3.js} +2 -2
- package/dist/{structure-hzCW-XsV.js.map → structure-BmisBK-3.js.map} +1 -1
- 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-BweFy_P9.js +1530 -0
- package/dist/table-BweFy_P9.js.map +1 -0
- package/dist/table-DsfzoUia.js +175 -0
- package/dist/table-DsfzoUia.js.map +1 -0
- package/dist/tabs-CDocW5D1.js +191 -0
- package/dist/tabs-CDocW5D1.js.map +1 -0
- package/dist/text-inputs-f9Ia-aCi.js +353 -0
- package/dist/text-inputs-f9Ia-aCi.js.map +1 -0
- package/dist/theme-mode-css-BB-_RYab.js +14 -0
- package/dist/theme-mode-css-BB-_RYab.js.map +1 -0
- package/dist/theme-scope-BJ6eE2xt.js +50 -0
- package/dist/theme-scope-BJ6eE2xt.js.map +1 -0
- package/dist/theme.css +285 -228
- package/dist/themes/green.css +16 -12
- package/dist/timelines-CwM_9IhD.js +457 -0
- package/dist/timelines-CwM_9IhD.js.map +1 -0
- package/dist/tone-recipes-BPsRAvhu.js +73 -0
- package/dist/tone-recipes-BPsRAvhu.js.map +1 -0
- package/dist/tooltip-yiRJUFjp.js +111 -0
- package/dist/tooltip-yiRJUFjp.js.map +1 -0
- package/dist/{tree-BotPlyiD.js → tree-WnKQzwbq.js} +69 -67
- package/dist/tree-WnKQzwbq.js.map +1 -0
- package/dist/typography/rich-text.js +1 -1
- package/dist/typography-UTnveOEy.js +117 -0
- package/dist/typography-UTnveOEy.js.map +1 -0
- package/dist/typography.js +2 -2
- package/dist/{ui-provider-D2_TeLqw.js → ui-provider-C_U0Xma4.js} +13 -5
- package/dist/ui-provider-C_U0Xma4.js.map +1 -0
- package/dist/ui-provider.js +3 -3
- package/dist/{upload-B0WHW7ak.js → upload-CXyxmQBP.js} +210 -209
- package/dist/upload-CXyxmQBP.js.map +1 -0
- package/dist/{upload-queue-BHZ_wBfd.js → upload-queue-Boscubn9.js} +111 -111
- package/dist/upload-queue-Boscubn9.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-U0YBLTNT.js → usage-card-BhO5eqkX.js} +45 -29
- package/dist/usage-card-BhO5eqkX.js.map +1 -0
- package/dist/{utils-Cospvlj1.js → utils-BRhFDwuU.js} +114 -67
- package/dist/utils-BRhFDwuU.js.map +1 -0
- package/dist/value-inputs-DXPDjvBU.js +963 -0
- package/dist/value-inputs-DXPDjvBU.js.map +1 -0
- package/dist/{value-typography-Deb3yQZg.js → value-typography-BP8OG6h5.js} +2 -2
- package/dist/{value-typography-Deb3yQZg.js.map → value-typography-BP8OG6h5.js.map} +1 -1
- package/dist/workspace-Cdrg7k9f.js +408 -0
- package/dist/workspace-Cdrg7k9f.js.map +1 -0
- package/docs/consumer-skill/SKILL.md +21 -22
- package/docs/consumer-skill/examples/app-layout.tsx +1 -1
- package/docs/consumer-skill/examples/composition.tsx +3 -3
- package/docs/consumer-skill/examples/detail.tsx +59 -12
- package/docs/consumer-skill/examples/edit.tsx +1 -1
- package/docs/consumer-skill/examples/receipt.tsx +2 -2
- package/docs/consumer-skill/examples/scoped-directory.tsx +1 -1
- 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 +58 -13
- package/docs/consumer-skill/references/design-contract.md +12 -3
- package/docs/consumer-skill/references/installation.md +11 -1
- package/docs/consumer-skill/references/integration.md +4 -3
- package/docs/consumer-skill/references/public-api.json +956 -453
- package/docs/consumer-skill/references/review.md +32 -5
- package/docs/consumer-skill/references/theming.md +78 -9
- package/docs/consumer-skill/references/tokens.json +1 -1
- package/docs/consumer-skill/references/workflows.md +54 -10
- package/docs/consumer-skill/scripts/composition-policy.mjs +42 -11
- package/docs/consumer-skill/scripts/surface-policy.mjs +150 -5
- package/package.json +17 -5
- package/dist/accordion-CQXVcd7Q.js +0 -205
- package/dist/accordion-CQXVcd7Q.js.map +0 -1
- package/dist/action-menu-BTpyPWJ2.js +0 -264
- package/dist/action-menu-BTpyPWJ2.js.map +0 -1
- package/dist/affordance-geometry.generated-CCIXb2A1.js +0 -68
- package/dist/affordance-geometry.generated-CCIXb2A1.js.map +0 -1
- package/dist/ai-artifact-2PQ2fItc.js +0 -1112
- package/dist/ai-artifact-2PQ2fItc.js.map +0 -1
- package/dist/attachment-q69dlt5Y.js +0 -244
- package/dist/attachment-q69dlt5Y.js.map +0 -1
- package/dist/auth-M3vGMgDR.js.map +0 -1
- package/dist/avatar-djdaaQ_s.js.map +0 -1
- package/dist/badge-0tATj-tW.js +0 -92
- package/dist/badge-0tATj-tW.js.map +0 -1
- package/dist/breadcrumbs-BG_FfMK4.js +0 -128
- package/dist/breadcrumbs-BG_FfMK4.js.map +0 -1
- package/dist/button-BS3KDg00.js.map +0 -1
- package/dist/button-R9CCoH7A.js.map +0 -1
- package/dist/buttons-DS0ZIwJ_.js +0 -99
- package/dist/buttons-DS0ZIwJ_.js.map +0 -1
- package/dist/cards-QoJ4syG9.js +0 -66
- package/dist/cards-QoJ4syG9.js.map +0 -1
- package/dist/chart-DwYRKKc-.js.map +0 -1
- package/dist/checkbox-B7ygNTYp.js +0 -35
- package/dist/checkbox-B7ygNTYp.js.map +0 -1
- package/dist/choice-inputs-DrJ17tpL.js +0 -752
- package/dist/choice-inputs-DrJ17tpL.js.map +0 -1
- package/dist/code-block-CD0B7M93.js +0 -183
- package/dist/code-block-CD0B7M93.js.map +0 -1
- package/dist/combobox-6dvVny2q.js +0 -272
- package/dist/combobox-6dvVny2q.js.map +0 -1
- package/dist/combobox-CB7039j7.js +0 -865
- package/dist/combobox-CB7039j7.js.map +0 -1
- package/dist/comments-You0Bzbr.js.map +0 -1
- package/dist/components/layout/page/partials/page-header-commands.d.ts +0 -13
- package/dist/containers-D_L4mTVb.js.map +0 -1
- package/dist/data-display-3xWQUnMA.js +0 -1335
- package/dist/data-display-3xWQUnMA.js.map +0 -1
- package/dist/date-picker-DrDFj8Lo.js +0 -1527
- package/dist/date-picker-DrDFj8Lo.js.map +0 -1
- package/dist/date-pickers-CnFCb0n2.js +0 -174
- package/dist/date-pickers-CnFCb0n2.js.map +0 -1
- package/dist/display-DrdvPwF0.js +0 -343
- package/dist/display-DrdvPwF0.js.map +0 -1
- package/dist/dropdown-menu-CURh59jb.js +0 -193
- package/dist/dropdown-menu-CURh59jb.js.map +0 -1
- package/dist/editable-text-recipe-Bkm6wKHp.js +0 -10
- package/dist/editable-text-recipe-Bkm6wKHp.js.map +0 -1
- package/dist/feedback-C7nR0UtT.js +0 -232
- package/dist/feedback-C7nR0UtT.js.map +0 -1
- package/dist/field-affordance-recipes-CkOCdE2y.js +0 -46
- package/dist/field-affordance-recipes-CkOCdE2y.js.map +0 -1
- package/dist/field-state-recipes-C-MFBX_8.js +0 -11
- package/dist/field-state-recipes-C-MFBX_8.js.map +0 -1
- package/dist/filters-Da-gNPsE.js.map +0 -1
- package/dist/form-field-VZRULhUK.js.map +0 -1
- package/dist/form-sizing-uWP4lzVh.js.map +0 -1
- package/dist/forms-numeric-D3CO60IF.js +0 -905
- package/dist/forms-numeric-D3CO60IF.js.map +0 -1
- package/dist/header-2ycNqGOR.js.map +0 -1
- package/dist/icon-badge-DKlaKXoo.js +0 -53
- package/dist/icon-badge-DKlaKXoo.js.map +0 -1
- package/dist/input-BoLm9Hks.js +0 -20
- package/dist/input-BoLm9Hks.js.map +0 -1
- package/dist/input-DhQdBnV3.js +0 -255
- package/dist/input-DhQdBnV3.js.map +0 -1
- package/dist/item-xzh8Df65.js +0 -264
- package/dist/item-xzh8Df65.js.map +0 -1
- package/dist/media-gallery-DQUQ0m3O.js +0 -201
- package/dist/media-gallery-DQUQ0m3O.js.map +0 -1
- package/dist/mentions-DwnO1hh4.js +0 -564
- package/dist/mentions-DwnO1hh4.js.map +0 -1
- package/dist/message-YfFmbXNP.js.map +0 -1
- package/dist/navigation-Cbp5V8gG.js +0 -264
- package/dist/navigation-Cbp5V8gG.js.map +0 -1
- package/dist/navigation-Cs1npsPm.js +0 -300
- package/dist/navigation-Cs1npsPm.js.map +0 -1
- package/dist/overlay.recipes-CNO2S9V6.js +0 -34
- package/dist/overlay.recipes-CNO2S9V6.js.map +0 -1
- package/dist/overlays-DhZO7N-I.js +0 -994
- package/dist/overlays-DhZO7N-I.js.map +0 -1
- package/dist/page-C6R_8jFt.js +0 -325
- package/dist/page-C6R_8jFt.js.map +0 -1
- package/dist/page-header-hUTzcRZX.js +0 -112
- package/dist/page-header-hUTzcRZX.js.map +0 -1
- package/dist/pagination-Cm0jqa3I.js +0 -149
- package/dist/pagination-Cm0jqa3I.js.map +0 -1
- package/dist/popover-Dcv_9jxr.js.map +0 -1
- package/dist/popover-menu-DnRFKnHP.js +0 -99
- package/dist/popover-menu-DnRFKnHP.js.map +0 -1
- package/dist/popover.recipes-wmbvL8Ah.js.map +0 -1
- package/dist/primitives-BHrwQXFC.js.map +0 -1
- package/dist/rich-text-editor-CF8QYt5p.js +0 -574
- package/dist/rich-text-editor-CF8QYt5p.js.map +0 -1
- package/dist/rich-text-editor.recipes-CnrbmTS1.js +0 -81
- package/dist/rich-text-editor.recipes-CnrbmTS1.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/rich-text-j-FGAeZW.js +0 -32
- package/dist/rich-text-j-FGAeZW.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-DRdr16Pt.js +0 -47
- package/dist/scroll-area-DRdr16Pt.js.map +0 -1
- package/dist/settings-DHk0L2MF.js +0 -161
- package/dist/settings-DHk0L2MF.js.map +0 -1
- package/dist/sheet-DRFNY1_D.js +0 -207
- package/dist/sheet-DRFNY1_D.js.map +0 -1
- package/dist/sidebar-Cb8WzOvE.js.map +0 -1
- package/dist/sidebar-Crc9M9JV.js.map +0 -1
- package/dist/smart-card-Bek-TwUp.js +0 -599
- package/dist/smart-card-Bek-TwUp.js.map +0 -1
- package/dist/spinner-CmTAbEp0.js +0 -80
- package/dist/spinner-CmTAbEp0.js.map +0 -1
- package/dist/surface-recipes-DOdoBXGm.js +0 -28
- package/dist/surface-recipes-DOdoBXGm.js.map +0 -1
- package/dist/table-D6zKeYQX.js +0 -162
- package/dist/table-D6zKeYQX.js.map +0 -1
- package/dist/table-Dn4XSrSB.js +0 -1444
- package/dist/table-Dn4XSrSB.js.map +0 -1
- package/dist/tabs-Dk8E_knt.js +0 -189
- package/dist/tabs-Dk8E_knt.js.map +0 -1
- package/dist/text-inputs-BFpku0Qd.js +0 -331
- package/dist/text-inputs-BFpku0Qd.js.map +0 -1
- package/dist/theme-scope-kStaAer0.js +0 -39
- package/dist/theme-scope-kStaAer0.js.map +0 -1
- package/dist/timelines-CxuAFIc2.js +0 -439
- package/dist/timelines-CxuAFIc2.js.map +0 -1
- package/dist/tree-BotPlyiD.js.map +0 -1
- package/dist/typography-CAr3dQhX.js +0 -116
- package/dist/typography-CAr3dQhX.js.map +0 -1
- package/dist/ui-provider-D2_TeLqw.js.map +0 -1
- package/dist/upload-B0WHW7ak.js.map +0 -1
- package/dist/upload-queue-BHZ_wBfd.js.map +0 -1
- package/dist/usage-card-U0YBLTNT.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-Cospvlj1.js.map +0 -1
- package/dist/value-inputs-CjfzGMsN.js +0 -854
- package/dist/value-inputs-CjfzGMsN.js.map +0 -1
- package/dist/workspace-YoFjXi6i.js +0 -394
- package/dist/workspace-YoFjXi6i.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
|
|
|
@@ -22,7 +22,25 @@ These criteria allow different product layouts. Do not impose a universal card
|
|
|
22
22
|
count, row-line limit or one-column form rule. Emphasis is the exception: keep
|
|
23
23
|
one solid primary command per page or surface, so the next action stays obvious.
|
|
24
24
|
|
|
25
|
-
##
|
|
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
|
|
26
44
|
|
|
27
45
|
The package ships a read-only script, not an npm bin/global CLI. It needs the
|
|
28
46
|
consumer's TypeScript development dependency and Node matching the package engine:
|
|
@@ -41,7 +59,7 @@ Errors cover unknown package entrypoints/symbols and statically detected overrid
|
|
|
41
59
|
of protected Card/popup insets, Card badges in headerAction/headerStart rather
|
|
42
60
|
than titleSuffix, control geometry/typography, fixed DisplayLabel/Badge
|
|
43
61
|
roles, cross-role shell/inner radius replacements, display-copy margins, or
|
|
44
|
-
|
|
62
|
+
redrawn focus indicators (another ring width, offset or halo strength) on imported controls. Intentional nested bodies,
|
|
45
63
|
circular owners and joined-edge corner resets retain their roles. Import ownership
|
|
46
64
|
follows lexical bindings, preserving locally shadowed application components. Imports of
|
|
47
65
|
symbols the public index marks deprecated, nested framed subjects and repeated
|
|
@@ -49,6 +67,13 @@ literal headings produce review warnings; warnings alone do not fail CI. Message
|
|
|
49
67
|
identify the owner and remedy. Dialog-like UI outside the overlay owners warns
|
|
50
68
|
too: native elements with `role="dialog"`/`"alertdialog"` or `aria-modal`, a
|
|
51
69
|
`fixed inset-0` layer, and imports of another modal library.
|
|
70
|
+
|
|
71
|
+
The checker also rejects faded semantic text colors and partial opacity on
|
|
72
|
+
imported typography/value primitives, including aliases and namespace imports.
|
|
73
|
+
Use the shared secondary/status role. Presence endpoints (0/100) and the shared
|
|
74
|
+
disabled 50% treatment remain valid; component disabled props keep that dimming
|
|
75
|
+
with its owner.
|
|
76
|
+
|
|
52
77
|
Standalone compact Cards and Page gutter removal also produce review warnings.
|
|
53
78
|
Buttons placed in a Page or PageHeader `actions` region warn as well: pass
|
|
54
79
|
commands as `primaryAction` and ordered `secondaryActions` so the header owns
|
|
@@ -61,7 +86,9 @@ semantic surface/foreground pair or a status tone. A Card title icon and an icon
|
|
|
61
86
|
more than one MetadataList fact warn as decoration; keep a glyph only when it
|
|
62
87
|
encodes state or a brand. Native `<button>` and
|
|
63
88
|
`<h1>`–`<h6>` elements warn in favour of Button/TextButton and Heading, which
|
|
64
|
-
own focus, loading and disabled states or margins and the heading scale.
|
|
89
|
+
own focus, loading and disabled states or margins and the heading scale. A
|
|
90
|
+
native button passed as a package owner's `render`, such as an Item row
|
|
91
|
+
rendered as a button, is that owner's root and does not warn.
|
|
65
92
|
Verified Card-owning Metric/card-grid, UsageCard and TaskCard compositions also
|
|
66
93
|
participate in nested-surface and peer-gap review. Metric without its card variant,
|
|
67
94
|
compact MetricGrid, flat TaskCard, ChartCard and Receipt do not establish a frame.
|
|
@@ -4,10 +4,20 @@ 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. `--input` is the control boundary and
|
|
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 resting 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 provides at least 3:1 contrast on the declared background, card, popover, muted, accent and secondary surfaces in both modes. Focus and invalid edges retain their separate 3:1 contract. `--border` is for quieter dividers and surface edges. When rebranding, check resting controls as well as focused controls, including the outside edge of fields with their own fill.
|
|
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
|
|
|
11
|
+
Pair each painted surface with its intended ink: `bg-card text-card-foreground`
|
|
12
|
+
and `bg-popover text-popover-foreground` are matching pairs. Flat sections inherit
|
|
13
|
+
the containing surface. For app-owned primary copy in a differently colored
|
|
14
|
+
surface, use Text/Value `type="inherit"` and Label `className="text-inherit"`;
|
|
15
|
+
standalone typography keeps its documented defaults. Keep secondary, link, status
|
|
16
|
+
and inverse roles explicit, and use a secondary text role instead of fading text
|
|
17
|
+
with opacity. Component disabled props own dimming; an extra faded wrapper can
|
|
18
|
+
multiply it. Brand colors alone do not guarantee input/focus contrast: retain the
|
|
19
|
+
central `--input`/`--ring` roles or verify their replacements on every host surface.
|
|
20
|
+
|
|
11
21
|
The default `--radius` is 0.75rem (12px). One public root drives two shared
|
|
12
22
|
roles; component owners choose the role, so ordinary callers add no radius class.
|
|
13
23
|
|
|
@@ -47,6 +57,14 @@ replacing individual components' owned corners.
|
|
|
47
57
|
|
|
48
58
|
Action and editable-control heights are separate roles; keep roots equal for adjoining alignment. `--space-scale` multiplies structural gaps, inline insets and surface padding. `--density-scale` multiplies action/control height and collection block padding. Roots are unscaled measurements; do not pre-multiply and then apply the utility again.
|
|
49
59
|
|
|
60
|
+
Control heights are nominal floors when custom typography needs more room.
|
|
61
|
+
Native fields, Select and InputGroup frames fit their editable line plus the
|
|
62
|
+
border, and cap vertical padding to the space remaining in the nominal height.
|
|
63
|
+
The default 32/36/40px sizes and radius roles stay unchanged. Text actions grow
|
|
64
|
+
under their intentionally tighter leading, so independently enlarged type can
|
|
65
|
+
produce different fitted heights even with equal action/control roots. Check
|
|
66
|
+
type size, leading and height roots together when exact custom pairing matters.
|
|
67
|
+
|
|
50
68
|
Both surface roots default to 1.25rem. At a 16px root font and space-scale 1,
|
|
51
69
|
ordinary surface insets are 20px, compact insets are 10px and large insets are
|
|
52
70
|
36px. Page's default large gutters inherit that same recipe. Row insets,
|
|
@@ -65,11 +83,58 @@ Use discrete inset, density and size props for the component responsibility desc
|
|
|
65
83
|
|
|
66
84
|
The default primary is near-black so success and other status colors never compete
|
|
67
85
|
with it. `themelia-react-ui/themes/green.css`, imported after `style.css`, is the
|
|
68
|
-
opt-in Themelia green brand (primary, its foreground
|
|
69
|
-
chart series). Rebrand by setting `--primary` and
|
|
70
|
-
`:root` and `.dark`;
|
|
86
|
+
opt-in Themelia green brand (primary, its foreground and the dark accent; the first
|
|
87
|
+
chart series is already that green). Rebrand by setting `--primary` and
|
|
88
|
+
`--primary-foreground` in both `:root` and `.dark`; the sidebar's primary follows
|
|
89
|
+
them in both modes. Keep the brand hue clear of the status hues and check 4.5:1.
|
|
90
|
+
|
|
91
|
+
Root overrides reach body portals. Scoped themes use ThemeScope from ui-provider.
|
|
92
|
+
The nearest explicit `.light` or `.dark` boundary governs the palette and dark
|
|
93
|
+
utilities, including repeated nesting and scoped portals. This uses inherited
|
|
94
|
+
custom-property container style queries, supported in Chromium 111+, Safari 18.1+
|
|
95
|
+
and Firefox 151+. The internal mode marker is state derived from those classes;
|
|
96
|
+
it is not another customization setting.
|
|
97
|
+
|
|
98
|
+
When ThemeScope's `style` supplies `--primary`, its default `--primary-accent`
|
|
99
|
+
and `--sidebar-primary` references resolve at that scope. The same applies to
|
|
100
|
+
`--primary-foreground` / `--sidebar-primary-foreground`, `--foreground` /
|
|
101
|
+
`--popover-foreground`, and `--font-sans` / `--font-heading`. Explicit local role
|
|
102
|
+
overrides in CSS or `style` win. A child scope with no new source override
|
|
103
|
+
inherits independent roles unchanged. Mode-dependent roles such as the elevated
|
|
104
|
+
dark `--popover` stay owned by the palette.
|
|
105
|
+
|
|
106
|
+
Package defaults and these alias references live in the `theme` cascade layer.
|
|
107
|
+
Explicit Tailwind utility overrides therefore win on plain scopes and scopes
|
|
108
|
+
with a mode class, as do unlayered consumer CSS and inline overrides. Keep the
|
|
109
|
+
standard `theme, base, components, utilities` layer order when composing your
|
|
110
|
+
application stylesheet.
|
|
111
|
+
|
|
112
|
+
CSS class themes declare their source roots and dependent aliases together:
|
|
113
|
+
CSS resolves aliases at their declaration boundary, and a scope cannot infer
|
|
114
|
+
which declarations an arbitrary consumer stylesheet supplied.
|
|
115
|
+
|
|
116
|
+
```css
|
|
117
|
+
.tenant-theme {
|
|
118
|
+
--primary: oklch(0.45 0.12 250);
|
|
119
|
+
--primary-accent: var(--primary);
|
|
120
|
+
--sidebar-primary: var(--primary);
|
|
121
|
+
--primary-foreground: oklch(0.99 0 0);
|
|
122
|
+
--sidebar-primary-foreground: var(--primary-foreground);
|
|
123
|
+
--font-sans: Georgia, serif;
|
|
124
|
+
--font-heading: var(--font-sans);
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Advanced editing uses the theme-tweaker public API, editing CSS rather than
|
|
129
|
+
adding another JavaScript styling system.
|
|
71
130
|
|
|
72
|
-
|
|
131
|
+
For tenant exports, pass the whole result of
|
|
132
|
+
`createScopedAdminUIThemeSelectors(scopeSelector)` to `serializeAdminUITheme`.
|
|
133
|
+
Its additive `modeScope` metadata selects light/dark values by the nearest mode
|
|
134
|
+
boundary, including complex selector lists. The existing `shared`, `light` and
|
|
135
|
+
`dark` strings remain available; manually supplied selectors without `modeScope`
|
|
136
|
+
are emitted literally. Mode-specific ChartStyle series use the same boundary
|
|
137
|
+
policy, while a fixed single-color series remains independent of mode.
|
|
73
138
|
|
|
74
139
|
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.
|
|
75
140
|
|
|
@@ -77,9 +142,13 @@ Apps using semantic utilities in their own JSX process themelia-react-ui/theme.c
|
|
|
77
142
|
|
|
78
143
|
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.
|
|
79
144
|
|
|
80
|
-
`ring` and `sidebar-ring` are focus roles
|
|
81
|
-
|
|
82
|
-
|
|
145
|
+
`ring` and `sidebar-ring` are the focus roles. Every focused element draws one
|
|
146
|
+
indicator: a 1px edge in the role at full strength (the control's own border, an
|
|
147
|
+
inset edge on borderless rows, or an outline just outside link text) inside a
|
|
148
|
+
soft 3px halo of the role at 50%. The edge carries the tested 3:1 contrast
|
|
149
|
+
against adjacent surfaces, so keep the root color at that strength when
|
|
150
|
+
overriding the theme; the halo makes focus stand out without reading as a
|
|
151
|
+
heavier border.
|
|
83
152
|
|
|
84
153
|
## Extend without drift
|
|
85
154
|
|
|
@@ -104,4 +173,4 @@ heights. `--icon` and `--avatar` set media dimensions independently. Component
|
|
|
104
173
|
Test these choices separately and in combination. Tables follow row insets,
|
|
105
174
|
Cards and code/message bodies follow surfaces, and image containment uses generic
|
|
106
175
|
spacing. Foundation directional spacing utilities ship with style.css and use
|
|
107
|
-
the same
|
|
176
|
+
the same eight steps as gaps; generated spellings are not new theme roots.
|
|
@@ -18,6 +18,14 @@ and explicit maximums from your column definitions. The table owns its one named
|
|
|
18
18
|
scroll region. Verify grouped widths, sticky header rows and first-column behavior
|
|
19
19
|
with real overflow in both directions, rather than adding another focusable wrapper.
|
|
20
20
|
|
|
21
|
+
## Media selection
|
|
22
|
+
|
|
23
|
+
For a browsing `MediaLibrary` with `bulkActions`, localize the selected-assets
|
|
24
|
+
region through `strings.batchActionsLabel` (English default: `Batch actions`).
|
|
25
|
+
The visible selection summary and Clear action stay in
|
|
26
|
+
`strings.footer.selectedCount` and `strings.footer.clear`. The native
|
|
27
|
+
`BatchActionBar` owns the region and its dismissal/focus behavior.
|
|
28
|
+
|
|
21
29
|
## Comment attachments
|
|
22
30
|
|
|
23
31
|
`Comments` and `CommentComposer` announce attachment validation/upload errors.
|
|
@@ -28,9 +36,23 @@ Reset/removal aborts pending uploads; the app owns transport and persistence.
|
|
|
28
36
|
|
|
29
37
|
## Detail and framing
|
|
30
38
|
|
|
31
|
-
[
|
|
32
|
-
|
|
33
|
-
|
|
39
|
+
[The detail recipe](../examples/detail.tsx) exports two owners.
|
|
40
|
+
`AccountDetailPage` is the record route: Page owns the title, one status badge,
|
|
41
|
+
the commands and the section tabs. `primaryAction` is Edit account,
|
|
42
|
+
`secondaryActions` holds Send statement and a `destructive` Delete account that
|
|
43
|
+
opens ConfirmDialog, and `header.tabs` carries Overview, Invoices with its count
|
|
44
|
+
badge, and Activity. The header renders `[secondary…] [primary] [⋯]`; destructive
|
|
45
|
+
and overflow commands live in the More actions menu. `AccountDetail` is the same
|
|
46
|
+
facts as one framed subject for a drawer or dashboard, with Edit as its one quick
|
|
47
|
+
`headerAction`. Name, Email, Date, Money and Value own formatting and
|
|
48
|
+
missing-value fallbacks; `balanceMinor` uses `Money unit="minor"`.
|
|
49
|
+
|
|
50
|
+
No optional peers are needed. The app supplies the loaded record, the section
|
|
51
|
+
content and the delete transport, and owns navigation, locale/provider defaults
|
|
52
|
+
and permissions (`visible: false` hides a command). Verify missing
|
|
53
|
+
email/date/balance, a rejected delete that keeps the confirmation open, tab
|
|
54
|
+
selection with keyboard arrows, the narrow layout where secondary commands
|
|
55
|
+
collapse into the menu, and light/dark themes.
|
|
34
56
|
|
|
35
57
|
## Scoped directory
|
|
36
58
|
|
|
@@ -58,6 +80,23 @@ in pagination URLs. A criteria-driven business selector would be a different
|
|
|
58
80
|
product contract. The recipe's English labels are example copy: adapt labels,
|
|
59
81
|
criteria and component `strings` for app translation and permissions.
|
|
60
82
|
|
|
83
|
+
DataTable accessibility copy also belongs to `strings`: use
|
|
84
|
+
`accessibility.sortColumn(columnLabel)` and `accessibility.resizeColumn(columnLabel)`
|
|
85
|
+
for column controls, `emptyState.ariaLabel` for the empty-result status and
|
|
86
|
+
`selection.label` for the selected-row action region. Partial overrides preserve
|
|
87
|
+
the other English defaults.
|
|
88
|
+
|
|
89
|
+
For searchable selection, `Combobox` uses `strings.clear` and `strings.toggle`;
|
|
90
|
+
both single and multiple recipes use `strings.dismiss` for the two screen-reader
|
|
91
|
+
dismissal controls. `MultiCombobox` uses `strings.removeSelection(itemLabel)` for
|
|
92
|
+
each removal button.
|
|
93
|
+
Custom base anatomy exposes `ComboboxInputTrigger` strings `{ clear, toggle }`,
|
|
94
|
+
`ComboboxClear` strings `{ clear }` and `ComboboxChip` strings `{ remove }`.
|
|
95
|
+
`ComboboxRoot` preserves the supported upstream `dismissLabel` prop. This private
|
|
96
|
+
build requires the companion Base UI `1.8.0-kpo.2` archive. It includes that public seam
|
|
97
|
+
and preserves an existing focus target inside a parent popup during nested
|
|
98
|
+
popup dismissal.
|
|
99
|
+
|
|
61
100
|
Strict imported declarations require the manifest's optional peers. DataTable
|
|
62
101
|
sorting is disabled because the app's server owns query order. Loading/error
|
|
63
102
|
feedback occupies the empty result region while query context remains mounted;
|
|
@@ -80,13 +119,15 @@ definitions; the app then chooses appropriate destination focus.
|
|
|
80
119
|
## Single resource page
|
|
81
120
|
|
|
82
121
|
Use `Page` from `themelia-react-ui/layout/page` for the record route's identity,
|
|
83
|
-
back navigation, content bounds and
|
|
84
|
-
`header.primaryAction
|
|
85
|
-
`
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
122
|
+
back navigation, content bounds, commands and section tabs. Pass the record's
|
|
123
|
+
main command as `header.primaryAction`, supporting commands as
|
|
124
|
+
`header.secondaryActions` and sections as `header.tabs`; one status badge goes in
|
|
125
|
+
`header.titleBadges`. `PageHeader` serves a custom shell; `PageActions` is
|
|
126
|
+
deprecated. The [layout recipe](../examples/app-layout.tsx) demonstrates that
|
|
127
|
+
route boundary; the [detail recipe](../examples/detail.tsx) demonstrates the
|
|
128
|
+
record route and an independently framed subject with MetadataList and value
|
|
129
|
+
primitives. Decide whether the record needs that independent Card before nesting
|
|
130
|
+
it under Page. Avoid repeating the
|
|
90
131
|
route heading just to frame the same facts. Page owns gutters; PageViewport owns
|
|
91
132
|
scrolling only. App navigation, record loading/missing/error/retry, permissions,
|
|
92
133
|
edit and delete callbacks remain application responsibilities.
|
|
@@ -94,6 +135,9 @@ edit and delete callbacks remain application responsibilities.
|
|
|
94
135
|
Use `WorkspaceLayout` from `themelia-react-ui/layout/workspace` when independently composed record header,
|
|
95
136
|
sidebar/main/rail regions are needed; inspect `features/resource` for complete
|
|
96
137
|
resource coordination. A single record does not automatically need either.
|
|
138
|
+
Their headers (`WorkspaceRecordHeader`, `ResourceHeader` and the resource shells)
|
|
139
|
+
take the same `primaryAction` and `secondaryActions` as Page; keep their
|
|
140
|
+
`actions` for non-command controls.
|
|
97
141
|
Read [layout composition](composition.md#application-layouts) for boundary and
|
|
98
142
|
parent-width behavior, then the exact selected declaration for its current props.
|
|
99
143
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { surfaceParts, surfaceForwarders, paddingClass, paddingProperty, utility,
|
|
1
|
+
import { surfaceParts, surfaceForwarders, paddingClass, paddingProperty, utility, focusRingDrift, fadedText, textOpacityDrift, textContentNames, 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']);
|
|
@@ -200,15 +200,16 @@ export function analyzeComposition(text, { filename, index, ts }) {
|
|
|
200
200
|
if (ts.isJsxExpression(node)) return slotBadge(node.expression);
|
|
201
201
|
return false;
|
|
202
202
|
};
|
|
203
|
-
// Buttons
|
|
204
|
-
// header's actions region. Unknown local
|
|
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.
|
|
205
206
|
const commandButtons = expression => {
|
|
206
207
|
const node = resolve(expression);
|
|
207
208
|
if (!node) return false;
|
|
208
209
|
if (ts.isJsxElement(node) || ts.isJsxSelfClosingElement(node)) {
|
|
209
210
|
const opening = ts.isJsxElement(node) ? node.openingElement : node;
|
|
210
211
|
const owner = ownerFor(opening.tagName);
|
|
211
|
-
if (isOwner(owner, 'base/buttons', ['Button', 'TextButton', 'BaseButton', 'BaseButtonLink']) || isOwner(owner, 'base/forms', ['SubmitStateButton']) || opening.tagName.getText(source) === 'button') return true;
|
|
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;
|
|
212
213
|
if (!/^(div|span)$/.test(opening.tagName.getText(source)) && !isOwner(owner, 'base/structure', ['Stack', 'Grid'])) return false;
|
|
213
214
|
return ts.isJsxElement(node) && node.children.some(commandButtons);
|
|
214
215
|
}
|
|
@@ -314,12 +315,26 @@ export function analyzeComposition(text, { filename, index, ts }) {
|
|
|
314
315
|
if (ts.isJsxSelfClosingElement(node)) inspect(node, parents);
|
|
315
316
|
ts.forEachChild(node, child => visit(child, parents));
|
|
316
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
|
+
};
|
|
317
330
|
function inspect(node, parents) {
|
|
318
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);
|
|
319
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).');
|
|
320
335
|
if (!owner) {
|
|
321
336
|
const tag = node.tagName.getText(source);
|
|
322
|
-
if (tag === 'button') add(node, 'raw-button', 'warning', 'Use Button or TextButton from themelia-react-ui/base/buttons: they own size, focus ring, loading and disabled states.');
|
|
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.');
|
|
323
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.');
|
|
324
339
|
const nativeProps = new Map(attributes(node));
|
|
325
340
|
const modalRole = /^(?:dialog|alertdialog)$/.test(literal(nativeProps.get('role')) ?? '') || nativeProps.has('aria-modal');
|
|
@@ -350,16 +365,20 @@ export function analyzeComposition(text, { filename, index, ts }) {
|
|
|
350
365
|
const control = controlFamilies.has(family) && controlNames.test(owner.symbol);
|
|
351
366
|
const sharedCorners = sharedCornerParts[family]?.test(owner.symbol);
|
|
352
367
|
const display = owner.import === `${index.package}/typography` && displayNames.test(owner.symbol);
|
|
368
|
+
const textContent = display || owner.import === `${index.package}/primitives` && textContentNames.test(owner.symbol);
|
|
353
369
|
const fixedText = owner.import === `${index.package}/typography` && owner.symbol === 'DisplayLabel' || family === 'badge' && owner.symbol === 'Badge';
|
|
354
370
|
const badge = family === 'badge' && owner.symbol === 'Badge';
|
|
355
371
|
for (const name of ['className', 'headerClassName', 'contentClassName', 'footerClassName', 'subHeadingClassName']) {
|
|
356
372
|
if (!props.has(name)) continue;
|
|
357
|
-
const
|
|
373
|
+
const tokens = classStrings(props.get(name)).flatMap(value => value.split(/\s+/)).filter(Boolean);
|
|
374
|
+
const classes = tokens.map(utility);
|
|
375
|
+
const focusDrift = focusRingDrift(tokens);
|
|
358
376
|
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.`);
|
|
359
377
|
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.`);
|
|
360
378
|
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.`);
|
|
361
379
|
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.`);
|
|
362
|
-
if (
|
|
380
|
+
if (textContent && name === 'className' && tokens.some(token=>fadedText(token)||textOpacityDrift(token))) add(node,'faded-text','error',`${owner.symbol}: use its semantic type instead of adding an opacity tier to the text. Presence endpoints and shared disabled state remain valid.`);
|
|
381
|
+
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.`);
|
|
363
382
|
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.`);
|
|
364
383
|
}
|
|
365
384
|
if (props.has('style')) for (const [name,value] of properties(props.get('style'))) {
|
|
@@ -370,7 +389,7 @@ export function analyzeComposition(text, { filename, index, ts }) {
|
|
|
370
389
|
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.`);
|
|
371
390
|
}
|
|
372
391
|
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.`);
|
|
373
|
-
const facts = isOwner(owner, 'blocks/data-display', ['MetadataList']) ? resolve(props.get('items')) : undefined;
|
|
392
|
+
const facts = isOwner(owner, 'base/metadata-list', ['MetadataList']) || isOwner(owner, 'blocks/data-display', ['MetadataList']) ? resolve(props.get('items')) : undefined;
|
|
374
393
|
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.');
|
|
375
394
|
const framed = framedOwner(owner, props);
|
|
376
395
|
if (isOwner(owner, 'base/cards', ['Card', 'SmartCard'])) {
|
|
@@ -380,7 +399,7 @@ export function analyzeComposition(text, { filename, index, ts }) {
|
|
|
380
399
|
const valueHeading = contents.some(item => role(item, ['Heading']) && /[$€£¥]|\d/.test(renderedText(item.element)));
|
|
381
400
|
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.');
|
|
382
401
|
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);
|
|
383
|
-
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.');
|
|
402
|
+
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.');
|
|
384
403
|
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.');
|
|
385
404
|
}
|
|
386
405
|
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.');
|
|
@@ -392,12 +411,24 @@ export function analyzeComposition(text, { filename, index, ts }) {
|
|
|
392
411
|
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.`);
|
|
393
412
|
const header = properties(props.get('header'), false);
|
|
394
413
|
const pageOwner = owner.import === `${index.package}/layout/page` || owner.import === `${index.package}/layout`;
|
|
395
|
-
|
|
414
|
+
// Every header owner takes role-based commands; its free-form regions hold
|
|
415
|
+
// non-command controls only.
|
|
416
|
+
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']);
|
|
417
|
+
const headerActions = pageOwner && owner.symbol === 'Page' ? new Map(header).get('actions') : commandHeader ? props.get('actions') : undefined;
|
|
418
|
+
const elementSecondary = isOwner(owner, 'layout/workspace', ['WorkspaceRecordHeader']) ? props.get('secondaryActions') : undefined;
|
|
396
419
|
if (pageOwner && owner.symbol === 'Page') {
|
|
397
420
|
const primaries = solidPrimaryCount(ts.isJsxSelfClosingElement(node) ? node : node.parent) + (new Map(header).has('primaryAction') ? 1 : 0);
|
|
398
421
|
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.`);
|
|
399
422
|
}
|
|
400
|
-
if (headerActions && commandButtons(headerActions)) add(node, 'page-command-roles', 'warning', `${owner.symbol}: buttons in the header actions region choose their own emphasis,
|
|
423
|
+
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.`);
|
|
424
|
+
const headerProps = pageOwner && owner.symbol === 'Page' ? new Map(header) : pageOwner && owner.symbol === 'PageHeader' ? props : undefined;
|
|
425
|
+
if (headerProps) {
|
|
426
|
+
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.`);
|
|
427
|
+
const hasIcon = action => properties(action, false).some(([name]) => name === 'icon');
|
|
428
|
+
const secondary = resolve(headerProps.get('secondaryActions'));
|
|
429
|
+
const iconCommands = (headerProps.has('primaryAction') && hasIcon(headerProps.get('primaryAction')) ? 1 : 0) + (secondary && ts.isArrayLiteralExpression(secondary) ? secondary.elements.filter(hasIcon).length : 0);
|
|
430
|
+
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.`);
|
|
431
|
+
}
|
|
401
432
|
const title = literal(props.get('title')) ?? literal(new Map(header).get('title'));
|
|
402
433
|
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.`);
|
|
403
434
|
const structure = owner.import === `${index.package}/base/structure` && Object.hasOwn(structureDefaults, owner.symbol);
|
|
@@ -25,6 +25,7 @@ export const sharedCornerParts = {
|
|
|
25
25
|
sheet: /^SheetContent$/,
|
|
26
26
|
};
|
|
27
27
|
export const displayNames = /^(?:Text|Heading|DisplayLabel|Label|TextLink)$/;
|
|
28
|
+
export const textContentNames = /^(?:Value|SecondaryValue|MutedValue|MonoValue|EmptyValue|Number|Percent|Money|Date|DateTime|Time|Duration|Name|Email|Phone|Link|FileSize|Dimensions|DateRange|RelativeTime|Url|Initials)$/;
|
|
28
29
|
export const nativeDisplayNames = /^(?:p|h[1-6])$/;
|
|
29
30
|
export const marginProperty = /^margin(?:Inline|Block)?(?:Start|End)?$|^margin(?:Top|Right|Bottom|Left)$|^margin-(?:(?:inline|block)(?:-(?:start|end))?|top|right|bottom|left)$/;
|
|
30
31
|
export const radiusProperty = /^border(?:(?:Top|Bottom)(?:Left|Right)|(?:Start|End)(?:Start|End))?Radius$|^border-(?:(?:top|bottom)-(?:left|right)-|(?:start|end)-(?:start|end)-)?radius$/;
|
|
@@ -57,10 +58,154 @@ export function utility(token) {
|
|
|
57
58
|
return token.slice(start).replace(/^!|!$/g, '');
|
|
58
59
|
}
|
|
59
60
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
export function variants(token) {
|
|
62
|
+
return token.slice(0, token.length - utility(token).length - (/!$/.test(token) ? 1 : 0)).replace(/!$/, '');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Text and icon colours are typography roles. Opacity on a role adds a tier under
|
|
66
|
+
// the tested 4.5:1, so only the sidebar keeps its one secondary tier.
|
|
67
|
+
const textRole = /^text-(?:foreground|muted-foreground|card-foreground|popover-foreground|accent-foreground|secondary-foreground|primary-foreground|primary-accent|warning-accent|link-color|success|info|warning|destructive|sidebar-foreground|sidebar-accent-foreground|sidebar-primary-foreground)\/.+$/;
|
|
68
|
+
export function fadedText(token) {
|
|
69
|
+
const value = utility(token);
|
|
70
|
+
return value !== 'text-sidebar-foreground/70' && textRole.test(value);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Separate opacity on an owned text node changes its semantic ink as well. */
|
|
74
|
+
export function textOpacityDrift(token) {
|
|
75
|
+
const value = utility(token);
|
|
76
|
+
const match = value.match(/^opacity-(?:(\d+(?:\.\d+)?)|\[(\d*\.?\d+)(%)?\])$/);
|
|
63
77
|
if (!match) return false;
|
|
64
|
-
const opacity = Number(match[1]
|
|
65
|
-
|
|
78
|
+
const opacity = match[1] !== undefined ? Number(match[1]) : Number(match[2]) * (match[3] ? 1 : 100);
|
|
79
|
+
if (!(opacity > 0 && opacity < 100)) return false;
|
|
80
|
+
return !(opacity === 50 && variantSegments(variants(token)).some(segment => disabledSegment.test(segment)));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Interaction fills come from one recipe owner: accent for rows, muted for toggle
|
|
84
|
+
// hover, a lifted card segment and the table ladder. A neutral fill with opacity or
|
|
85
|
+
// a primary tint under hover, highlight, selection, current or pressed state is a
|
|
86
|
+
// second definition of that state.
|
|
87
|
+
const interactionSegment = /^(?:group-|peer-)?(?:hover|focus|focus-visible|focus-within|active|data-highlighted|data-selected|data-active|data-current|data-pressed|aria-selected|aria-current|aria-pressed|aria-checked|data-\[(?:highlighted|selected|active|current|pressed|checked|state=[^\]]+)[^\]]*\])(?:\/[\w-]+)?$/;
|
|
88
|
+
function variantSegments(variant) {
|
|
89
|
+
const segments = [];
|
|
90
|
+
let depth = 0, start = 0;
|
|
91
|
+
for (let i = 0; i < variant.length; i++) {
|
|
92
|
+
if ('[('.includes(variant[i])) depth++;
|
|
93
|
+
else if ('])'.includes(variant[i])) depth--;
|
|
94
|
+
else if (variant[i] === ':' && depth === 0) { segments.push(variant.slice(start, i)); start = i + 1; }
|
|
95
|
+
}
|
|
96
|
+
return segments;
|
|
97
|
+
}
|
|
98
|
+
export function interactionFillDrift(token) {
|
|
99
|
+
if (!variantSegments(variants(token)).some(segment => interactionSegment.test(segment))) return false;
|
|
100
|
+
const match = utility(token).match(/^bg-(muted|accent|card|background|foreground|secondary|popover|sidebar-accent|primary)\/(.+)$/);
|
|
101
|
+
return !!match && !(match[1] === 'muted' && match[2] === '50');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Neutral fills have one strength per role (neutralFillRecipes in
|
|
105
|
+
// src/lib/surface-recipes.ts): a wash at muted/30, a band at muted/50, a chip at
|
|
106
|
+
// foreground/8, the inverse chip at background/10 and the idle marker at
|
|
107
|
+
// muted-foreground/40. Opaque fills are always available; interaction states belong
|
|
108
|
+
// to interaction-fill.
|
|
109
|
+
const neutralTint = /^bg-(muted|muted-foreground|foreground|background|card|popover|secondary|accent|sidebar(?:-[a-z]+)*)\/(.+)$/;
|
|
110
|
+
const neutralScale = new Set(['muted/30', 'muted/50', 'foreground/8', 'background/10', 'muted-foreground/40']);
|
|
111
|
+
export function neutralFillDrift(token) {
|
|
112
|
+
const match = utility(token).match(neutralTint);
|
|
113
|
+
if (!match || neutralScale.has(`${match[1]}/${match[2]}`)) return false;
|
|
114
|
+
return !variantSegments(variants(token)).some(segment => interactionSegment.test(segment));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Elevation takes one theme shadow per role (elevationRecipes in
|
|
118
|
+
// src/lib/surface-recipes.ts): xs resting, sm card, md raised and anchored, lg lifted
|
|
119
|
+
// and xl modal; shadow-none clears it. A box-shadow divider line that draws
|
|
120
|
+
// var(--border) is divider mechanics, not elevation.
|
|
121
|
+
export function elevationDrift(token) {
|
|
122
|
+
const value = utility(token);
|
|
123
|
+
if (!/^shadow(?:-|$)/.test(value)) return false;
|
|
124
|
+
return !/^shadow-(?:none|xs|sm|md|lg|xl)$/.test(value) && !/^shadow-\[.*var\(--border\).*\]$/.test(value);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Dividers have two strengths: a surface edge draws the full border role and an
|
|
128
|
+
// inner divider (one side, divide, separator) draws it at 60%. The control boundary
|
|
129
|
+
// has one strength. Only src/lib/surface-recipes.ts owns other strengths (the modal
|
|
130
|
+
// shell and the framed Card ring).
|
|
131
|
+
export function dividerStrengthDrift(token) {
|
|
132
|
+
const match = utility(token).match(/^(?:border(?:-[trblxyse]|-bs|-be)?|divide(?:-[xy])?|ring|inset-ring|outline|bg)-(border|sidebar-border|input)\/(.+)$/);
|
|
133
|
+
return !!match && !(match[1] === 'border' && match[2] === '60');
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Status and emphasis tints have one scale, src/lib/tone-recipes.ts: a wash, tint,
|
|
137
|
+
// edge, halo and line strength per tone, which the contrast contract tests. A
|
|
138
|
+
// translucent tone spelled anywhere else is a second scale. The invalid state's
|
|
139
|
+
// destructive halo belongs to the field-state and focus recipes.
|
|
140
|
+
const toneTint = /^(?:bg|border(?:-[trblxyse]|-bs|-be)?|ring|inset-ring|outline|divide(?:-[xy])?)-(?:info|success|warning|destructive|primary)(?:-accent)?\/.+$/;
|
|
141
|
+
export function statusTintDrift(token) {
|
|
142
|
+
return toneTint.test(utility(token)) && !/invalid|focus/.test(variants(token));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// State changes (colour, border and shadow) share one timing: Tailwind's default
|
|
146
|
+
// 150ms transition and easing. Presence and geometry motion (enter, exit, expand,
|
|
147
|
+
// slide) comes from src/lib/motion-recipes.ts. Returns the timing tokens that
|
|
148
|
+
// retime a paint-only transition.
|
|
149
|
+
const paintProperties = new Set(['color', 'background-color', 'background', 'border-color', 'box-shadow', 'outline-color', 'text-decoration-color', 'fill', 'stroke']);
|
|
150
|
+
function paintTransition(token) {
|
|
151
|
+
const value = utility(token);
|
|
152
|
+
if (value === 'transition-colors' || value === 'transition-shadow') return true;
|
|
153
|
+
const list = value.match(/^transition-\[(.+)\]$/)?.[1];
|
|
154
|
+
return !!list && list.split(',').every(property => paintProperties.has(property.trim()));
|
|
155
|
+
}
|
|
156
|
+
export function stateMotionDrift(classes) {
|
|
157
|
+
const resting = classes.filter(token => variants(token) === '');
|
|
158
|
+
if (!resting.some(paintTransition) || resting.some(token => /^transition(?:-|$)/.test(utility(token)) && !paintTransition(token))) return [];
|
|
159
|
+
return resting.filter(token => /^duration-(?!150$|0$)/.test(utility(token)) || /^ease-/.test(utility(token)));
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Corners take a role derived from --radius: rounded-radius (outer shells) and
|
|
163
|
+
// rounded-inner (controls, rows, nested bodies), plus rounded-full, rounded-none
|
|
164
|
+
// and the root-derived rounded-radius-* steps. Bare rounded is a fixed 4px that
|
|
165
|
+
// ignores the theme root, and the t-shirt steps are a second scale.
|
|
166
|
+
export function radiusRoleDrift(token) {
|
|
167
|
+
return /^rounded(?:-(?:[trblse]|tl|tr|br|bl|ss|se|es|ee))?(?:-(?:xs|sm|md|lg|xl|2xl|3xl|4xl))?$/.test(utility(token));
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// One stacking scale (src/lib/layer-recipes.ts): z-10 raised, z-20 sticky, z-30
|
|
171
|
+
// sticky over sticky, z-40 app chrome, z-50 popups and modal layers. Local
|
|
172
|
+
// ordering may also use z-0, z-[1] and z-[-1].
|
|
173
|
+
export function layerScaleDrift(token) {
|
|
174
|
+
const match = utility(token).replace(/^-/, '').match(/^z-(?:(\d+)|\[(-?\d+)\])$/);
|
|
175
|
+
if (!match) return false;
|
|
176
|
+
if (match[2] !== undefined) return Math.abs(Number(match[2])) > 1;
|
|
177
|
+
return ![0, 10, 20, 30, 40, 50].includes(Number(match[1]));
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Disabled content dims once, at 50%; a child of a dimmed owner resets to 100%.
|
|
181
|
+
const disabledSegment = /^(?:group-|peer-)?(?:disabled|data-disabled|aria-disabled|data-\[disabled[^\]]*\]|aria-\[disabled[^\]]*\])(?:\/[\w-]+)?$/;
|
|
182
|
+
export function disabledDimmingDrift(token) {
|
|
183
|
+
if (!variantSegments(variants(token)).some(segment => disabledSegment.test(segment))) return false;
|
|
184
|
+
const match = utility(token).match(/^opacity-(\d+)$/);
|
|
185
|
+
return !!match && !['50', '100'].includes(match[1]);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const focusState = /focus|focused/;
|
|
189
|
+
const ringWidth = /^ring(?:-\d+(?:\.\d+)?|-\[(?:\d+(?:\.\d+)?)(?:px|rem|em)\])?$/;
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Every focus indicator is one recipe: a 3px halo of the ring role at 50% around
|
|
193
|
+
* a full-strength 1px edge (the control's own `border-ring`, or `inset-ring-ring`
|
|
194
|
+
* on a borderless element). Returns the tokens that draw focus any other way:
|
|
195
|
+
* another focus ring width, an offset ring, a halo at another strength, an
|
|
196
|
+
* attenuated edge, or an unscoped ring colour that a focus-only width turns into
|
|
197
|
+
* a full-strength halo. Status tints (invalid, selected) keep their own colours.
|
|
198
|
+
*/
|
|
199
|
+
export function focusRingDrift(classes) {
|
|
200
|
+
const focused = token => focusState.test(variants(token));
|
|
201
|
+
const focusWidth = classes.some(token => focused(token) && ringWidth.test(utility(token)) && utility(token) !== 'ring-0');
|
|
202
|
+
return classes.filter(token => {
|
|
203
|
+
const value = utility(token);
|
|
204
|
+
if (!focused(token)) return focusWidth && variants(token) === '' && /^ring-(?:ring|sidebar-ring)$/.test(value);
|
|
205
|
+
if (/^ring-offset-/.test(value)) return true;
|
|
206
|
+
if (ringWidth.test(value)) return !/^ring-[03]$/.test(value);
|
|
207
|
+
const halo = value.match(/^ring-(?:ring|sidebar-ring)(?:\/(.+))?$/);
|
|
208
|
+
if (halo) return halo[1] !== '50';
|
|
209
|
+
return /^(?:border|inset-ring|outline)-(?:ring|sidebar-ring)\/.+$/.test(value);
|
|
210
|
+
});
|
|
66
211
|
}
|