themelia-react-ui 2.0.0 → 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 +351 -0
- package/README.md +26 -13
- package/dist/{accordion-CQXVcd7Q.js → accordion-B6a3vVgA.js} +84 -82
- 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-CCIXb2A1.js → affordance-geometry.generated-B5iu-Mkr.js} +3 -2
- package/dist/affordance-geometry.generated-B5iu-Mkr.js.map +1 -0
- package/dist/{ai-artifact-2PQ2fItc.js → ai-artifact-BMJdv-6q.js} +379 -376
- package/dist/ai-artifact-BMJdv-6q.js.map +1 -0
- package/dist/{app-shell-BE_j8-AT.js → app-shell-ZK5RWdo6.js} +4 -4
- package/dist/{app-shell-BE_j8-AT.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-M3vGMgDR.js → auth-CYxKfo69.js} +237 -235
- package/dist/auth-CYxKfo69.js.map +1 -0
- package/dist/{avatar-djdaaQ_s.js → avatar-BBnEJIx8.js} +66 -65
- 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 +13 -13
- package/dist/base/carousel.js.map +1 -1
- package/dist/base/cascader.js +103 -115
- 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 +17 -17
- 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 +171 -170
- 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 +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 +2 -2
- 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 +173 -171
- package/dist/blocks/admin.js.map +1 -1
- package/dist/blocks/ai.js +266 -263
- package/dist/blocks/ai.js.map +1 -1
- package/dist/blocks/analytics/usage-card.js +1 -1
- package/dist/blocks/analytics.js +440 -438
- 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 +1945 -1266
- 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 +25 -25
- 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-R9CCoH7A.js → button-QYwiyhD2.js} +15 -14
- package/dist/button-QYwiyhD2.js.map +1 -0
- package/dist/{button-BS3KDg00.js → buttons-SbIcm1HJ.js} +200 -213
- package/dist/buttons-SbIcm1HJ.js.map +1 -0
- package/dist/{cards-QoJ4syG9.js → cards-CiiHpKYd.js} +8 -8
- package/dist/cards-CiiHpKYd.js.map +1 -0
- package/dist/{chart-DwYRKKc-.js → chart-QfrARkXl.js} +5 -5
- package/dist/{chart-DwYRKKc-.js.map → chart-QfrARkXl.js.map} +1 -1
- 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-oMUGM4tr.js → collapsible-D8AEGU1-.js} +4 -4
- package/dist/{collapsible-oMUGM4tr.js.map → collapsible-D8AEGU1-.js.map} +1 -1
- package/dist/{collection-content-Ys-OZOkY.js → collection-content-uK16Grv0.js} +3 -3
- package/dist/{collection-content-Ys-OZOkY.js.map → collection-content-uK16Grv0.js.map} +1 -1
- package/dist/{combobox-6dvVny2q.js → combobox-2Ic8N9bL.js} +74 -68
- package/dist/combobox-2Ic8N9bL.js.map +1 -0
- package/dist/{combobox-CB7039j7.js → combobox-DLl0bfiq.js} +307 -305
- package/dist/combobox-DLl0bfiq.js.map +1 -0
- package/dist/{command-kPMPjIxJ.js → command-kNR20o7x.js} +7 -7
- package/dist/{command-kPMPjIxJ.js.map → command-kNR20o7x.js.map} +1 -1
- package/dist/{comments-You0Bzbr.js → comments-BpDuCUUu.js} +341 -339
- package/dist/comments-BpDuCUUu.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 +4 -4
- 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/choice-inputs/checkbox.d.ts +2 -2
- package/dist/components/base/choice-inputs/choice-types.d.ts +18 -6
- 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 +15 -12
- 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/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/text-inputs/field-clear-button.d.ts +6 -0
- 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/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 +43 -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/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/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/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 +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/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 +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/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 +4 -3
- package/dist/components/ui/checkbox.d.ts +4 -3
- package/dist/components/ui/overlay.recipes.d.ts +0 -9
- package/dist/components/ui/switch.d.ts +2 -2
- package/dist/{containers-D_L4mTVb.js → containers-DmWiJa2I.js} +36 -35
- package/dist/containers-DmWiJa2I.js.map +1 -0
- package/dist/{copyable-DDjTeW_j.js → copyable-B3Gwgdqc.js} +6 -6
- package/dist/{copyable-DDjTeW_j.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-uf3z37Nm.js → date-BgK3bTdo.js} +5 -5
- package/dist/{date-uf3z37Nm.js.map → date-BgK3bTdo.js.map} +1 -1
- package/dist/date-picker-CF-DtUpF.js +1529 -0
- package/dist/date-picker-CF-DtUpF.js.map +1 -0
- package/dist/{date-pickers-CnFCb0n2.js → date-pickers-BmzxJl5l.js} +19 -19
- package/dist/{date-pickers-CnFCb0n2.js.map → date-pickers-BmzxJl5l.js.map} +1 -1
- package/dist/{display-DrdvPwF0.js → display-DsQTVzMz.js} +88 -87
- package/dist/display-DsQTVzMz.js.map +1 -0
- package/dist/{dropdown-menu-CURh59jb.js → dropdown-menu-E2qmdC7o.js} +7 -7
- package/dist/{dropdown-menu-CURh59jb.js.map → dropdown-menu-E2qmdC7o.js.map} +1 -1
- package/dist/features/activities.js +414 -501
- package/dist/features/activities.js.map +1 -1
- package/dist/features/ai-chat.js +170 -169
- 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 +73 -71
- package/dist/features/email-composer.js.map +1 -1
- package/dist/features/event-calendar.js +278 -275
- 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 +918 -825
- 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 +1115 -1122
- package/dist/features/products.js.map +1 -1
- package/dist/features/questionnaire.js +202 -194
- package/dist/features/questionnaire.js.map +1 -1
- package/dist/features/resource-assignment.js +25 -25
- 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 +33 -33
- package/dist/features/schema-form.js.map +1 -1
- package/dist/features/suggestions.js +3 -3
- package/dist/features/sync.js +3 -3
- package/dist/features/table.js +1 -1
- package/dist/features/theme-tweaker.js +397 -396
- package/dist/features/theme-tweaker.js.map +1 -1
- package/dist/{feedback-C7nR0UtT.js → feedback-qNuMBtRH.js} +84 -83
- package/dist/feedback-qNuMBtRH.js.map +1 -0
- package/dist/{field-affordance-recipes-CkOCdE2y.js → field-affordance-recipes-qQeIf4lG.js} +8 -6
- 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-Da-gNPsE.js → filters-BkHH53uv.js} +565 -563
- 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-VZRULhUK.js → form-field-DUt4UxSV.js} +4 -4
- package/dist/{form-field-VZRULhUK.js.map → form-field-DUt4UxSV.js.map} +1 -1
- package/dist/{form-sizing-uWP4lzVh.js → form-sizing-By94KzXE.js} +19 -15
- package/dist/form-sizing-By94KzXE.js.map +1 -0
- package/dist/{forms-DDeEnXSY.js → forms-Bzha-Y3B.js} +22 -22
- package/dist/{forms-DDeEnXSY.js.map → forms-Bzha-Y3B.js.map} +1 -1
- package/dist/{forms-numeric-D3CO60IF.js → forms-numeric-C0bvjRPZ.js} +265 -264
- package/dist/forms-numeric-C0bvjRPZ.js.map +1 -0
- package/dist/{header-2ycNqGOR.js → header-BOefOKd1.js} +47 -51
- package/dist/header-BOefOKd1.js.map +1 -0
- package/dist/{hooks-DQ5SPwZw.js → hooks-9k_TtmKh.js} +2 -2
- package/dist/{hooks-DQ5SPwZw.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-BoLm9Hks.js → input-Ddi_LSYv.js} +3 -3
- package/dist/{input-BoLm9Hks.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-xzh8Df65.js → item-DEmDiTlD.js} +98 -97
- 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 +1 -0
- package/dist/lib/field-affordance-recipes.d.ts +6 -1
- 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 +35 -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/token-merge.generated.d.ts +9 -6
- package/dist/lib/tone-recipes.d.ts +79 -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 +9 -0
- 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-YfFmbXNP.js → message-CdHgIWKf.js} +5 -5
- package/dist/{message-YfFmbXNP.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-DlU-4QYO.js → navigation-row-recipes-BVowojQw.js} +2 -2
- package/dist/{navigation-row-recipes-DlU-4QYO.js.map → navigation-row-recipes-BVowojQw.js.map} +1 -1
- package/dist/{number-CKRBYmZK.js → number-DMhe-Vsk.js} +5 -5
- package/dist/{number-CKRBYmZK.js.map → number-DMhe-Vsk.js.map} +1 -1
- 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-B5dTH9gE.js +224 -0
- 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-Cm0jqa3I.js → pagination-3bPA_a6K.js} +15 -15
- package/dist/{pagination-Cm0jqa3I.js.map → pagination-3bPA_a6K.js.map} +1 -1
- package/dist/{popover-Dcv_9jxr.js → popover-Di55PyAI.js} +8 -8
- package/dist/popover-Di55PyAI.js.map +1 -0
- package/dist/{popover-menu-DnRFKnHP.js → popover-menu-B71Tn2Qz.js} +6 -6
- package/dist/{popover-menu-DnRFKnHP.js.map → popover-menu-B71Tn2Qz.js.map} +1 -1
- package/dist/{popover.recipes-wmbvL8Ah.js → popover.recipes-Bdyhj2db.js} +2 -2
- package/dist/{popover.recipes-wmbvL8Ah.js.map → popover.recipes-Bdyhj2db.js.map} +1 -1
- package/dist/{primitives-BHrwQXFC.js → primitives-B-CkiEMU.js} +5 -5
- package/dist/{primitives-BHrwQXFC.js.map → primitives-B-CkiEMU.js.map} +1 -1
- package/dist/primitives.js +4 -4
- package/dist/{progress-Br9WTFya.js → progress-rnS8-uAW.js} +9 -9
- package/dist/{progress-Br9WTFya.js.map → progress-rnS8-uAW.js.map} +1 -1
- package/dist/{receipt-CV89q1fs.js → receipt-D0oswZ0p.js} +6 -6
- package/dist/{receipt-CV89q1fs.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-Do5GWDYi.js → separator-C8DlRGwF.js} +3 -3
- package/dist/{separator-Do5GWDYi.js.map → separator-C8DlRGwF.js.map} +1 -1
- package/dist/{separator-BMEvwnSX.js → separator-CYHnjsAb.js} +2 -2
- package/dist/{separator-BMEvwnSX.js.map → separator-CYHnjsAb.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-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-Crc9M9JV.js → sidebar-C7WWR29L.js} +180 -179
- package/dist/sidebar-C7WWR29L.js.map +1 -0
- package/dist/{sidebar-Cb8WzOvE.js → sidebar-d7Dg80ln.js} +16 -16
- package/dist/sidebar-d7Dg80ln.js.map +1 -0
- package/dist/{skeleton-DVMXr15h.js → skeleton-Cz890JZF.js} +9 -9
- package/dist/{skeleton-DVMXr15h.js.map → skeleton-Cz890JZF.js.map} +1 -1
- package/dist/smart-card-lFKxn5Hu.js +595 -0
- package/dist/smart-card-lFKxn5Hu.js.map +1 -0
- package/dist/{spinner-CmTAbEp0.js → spinner-fa3h1Aif.js} +7 -7
- package/dist/{spinner-CmTAbEp0.js.map → spinner-fa3h1Aif.js.map} +1 -1
- package/dist/{structure-hzCW-XsV.js → structure-DC2dygdA.js} +2 -2
- package/dist/{structure-hzCW-XsV.js.map → structure-DC2dygdA.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-D6zKeYQX.js → table-CIKyLUsy.js} +59 -58
- package/dist/table-CIKyLUsy.js.map +1 -0
- package/dist/table-CrcLN9Io.js +1458 -0
- package/dist/table-CrcLN9Io.js.map +1 -0
- package/dist/{tabs-Dk8E_knt.js → tabs-DwBJfjxX.js} +58 -57
- package/dist/tabs-DwBJfjxX.js.map +1 -0
- package/dist/{text-inputs-BFpku0Qd.js → text-inputs-aaK9wcDT.js} +74 -79
- package/dist/text-inputs-aaK9wcDT.js.map +1 -0
- package/dist/theme.css +3 -3
- package/dist/{timelines-CxuAFIc2.js → timelines-C_SBwHNP.js} +153 -150
- 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/{tree-BotPlyiD.js → tree-BiKhg8AY.js} +68 -66
- 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 +1 -1
- package/dist/{ui-provider-D2_TeLqw.js → ui-provider-1D_NSYzO.js} +11 -3
- package/dist/ui-provider-1D_NSYzO.js.map +1 -0
- package/dist/ui-provider.js +3 -3
- package/dist/{upload-B0WHW7ak.js → upload-BO8-CLN6.js} +209 -209
- package/dist/upload-BO8-CLN6.js.map +1 -0
- package/dist/{upload-queue-BHZ_wBfd.js → upload-queue-EOC8g1gf.js} +109 -111
- 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-U0YBLTNT.js → usage-card-obRaBskq.js} +46 -46
- package/dist/{usage-card-U0YBLTNT.js.map → usage-card-obRaBskq.js.map} +1 -1
- package/dist/{utils-Cospvlj1.js → utils-l5LpDw2z.js} +56 -24
- 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-Deb3yQZg.js → value-typography-b8wpz1eX.js} +2 -2
- package/dist/{value-typography-Deb3yQZg.js.map → value-typography-b8wpz1eX.js.map} +1 -1
- package/dist/workspace-DH0v0KcB.js +407 -0
- package/dist/workspace-DH0v0KcB.js.map +1 -0
- package/docs/consumer-skill/SKILL.md +19 -20
- 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 +51 -8
- package/docs/consumer-skill/references/design-contract.md +12 -3
- package/docs/consumer-skill/references/installation.md +11 -1
- package/docs/consumer-skill/references/public-api.json +847 -447
- package/docs/consumer-skill/references/review.md +25 -5
- package/docs/consumer-skill/references/theming.md +8 -4
- package/docs/consumer-skill/references/tokens.json +1 -1
- package/docs/consumer-skill/references/workflows.md +29 -10
- package/docs/consumer-skill/scripts/composition-policy.mjs +41 -11
- package/docs/consumer-skill/scripts/surface-policy.mjs +139 -5
- package/package.json +10 -2
- 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.map +0 -1
- 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.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.map +0 -1
- 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/display-DrdvPwF0.js.map +0 -1
- package/dist/feedback-C7nR0UtT.js.map +0 -1
- 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-sizing-uWP4lzVh.js.map +0 -1
- 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-DhQdBnV3.js +0 -255
- package/dist/input-DhQdBnV3.js.map +0 -1
- 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/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/popover-Dcv_9jxr.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/surface-recipes-DOdoBXGm.js +0 -28
- package/dist/surface-recipes-DOdoBXGm.js.map +0 -1
- 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.map +0 -1
- package/dist/text-inputs-BFpku0Qd.js.map +0 -1
- 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/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
|
|
@@ -61,7 +79,9 @@ semantic surface/foreground pair or a status tone. A Card title icon and an icon
|
|
|
61
79
|
more than one MetadataList fact warn as decoration; keep a glyph only when it
|
|
62
80
|
encodes state or a brand. Native `<button>` and
|
|
63
81
|
`<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.
|
|
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.
|
|
65
85
|
Verified Card-owning Metric/card-grid, UsageCard and TaskCard compositions also
|
|
66
86
|
participate in nested-surface and peer-gap review. Metric without its card variant,
|
|
67
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. `--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 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
|
|
|
@@ -77,9 +77,13 @@ Apps using semantic utilities in their own JSX process themelia-react-ui/theme.c
|
|
|
77
77
|
|
|
78
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.
|
|
79
79
|
|
|
80
|
-
`ring` and `sidebar-ring` are focus roles
|
|
81
|
-
|
|
82
|
-
|
|
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.
|
|
83
87
|
|
|
84
88
|
## Extend without drift
|
|
85
89
|
|
|
@@ -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
|
|
|
@@ -80,13 +94,15 @@ definitions; the app then chooses appropriate destination focus.
|
|
|
80
94
|
## Single resource page
|
|
81
95
|
|
|
82
96
|
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
|
-
|
|
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
|
|
90
106
|
route heading just to frame the same facts. Page owns gutters; PageViewport owns
|
|
91
107
|
scrolling only. App navigation, record loading/missing/error/retry, permissions,
|
|
92
108
|
edit and delete callbacks remain application responsibilities.
|
|
@@ -94,6 +110,9 @@ edit and delete callbacks remain application responsibilities.
|
|
|
94
110
|
Use `WorkspaceLayout` from `themelia-react-ui/layout/workspace` when independently composed record header,
|
|
95
111
|
sidebar/main/rail regions are needed; inspect `features/resource` for complete
|
|
96
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.
|
|
97
116
|
Read [layout composition](composition.md#application-layouts) for boundary and
|
|
98
117
|
parent-width behavior, then the exact selected declaration for its current props.
|
|
99
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']);
|
|
@@ -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');
|
|
@@ -354,12 +369,15 @@ export function analyzeComposition(text, { filename, index, ts }) {
|
|
|
354
369
|
const badge = family === 'badge' && owner.symbol === 'Badge';
|
|
355
370
|
for (const name of ['className', 'headerClassName', 'contentClassName', 'footerClassName', 'subHeadingClassName']) {
|
|
356
371
|
if (!props.has(name)) continue;
|
|
357
|
-
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);
|
|
358
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.`);
|
|
359
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.`);
|
|
360
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.`);
|
|
361
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.`);
|
|
362
|
-
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.`);
|
|
363
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.`);
|
|
364
382
|
}
|
|
365
383
|
if (props.has('style')) for (const [name,value] of properties(props.get('style'))) {
|
|
@@ -370,7 +388,7 @@ export function analyzeComposition(text, { filename, index, ts }) {
|
|
|
370
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.`);
|
|
371
389
|
}
|
|
372
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.`);
|
|
373
|
-
const facts = isOwner(owner, 'blocks/data-display', ['MetadataList']) ? resolve(props.get('items')) : undefined;
|
|
391
|
+
const facts = isOwner(owner, 'base/metadata-list', ['MetadataList']) || isOwner(owner, 'blocks/data-display', ['MetadataList']) ? resolve(props.get('items')) : undefined;
|
|
374
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.');
|
|
375
393
|
const framed = framedOwner(owner, props);
|
|
376
394
|
if (isOwner(owner, 'base/cards', ['Card', 'SmartCard'])) {
|
|
@@ -380,7 +398,7 @@ export function analyzeComposition(text, { filename, index, ts }) {
|
|
|
380
398
|
const valueHeading = contents.some(item => role(item, ['Heading']) && /[$€£¥]|\d/.test(renderedText(item.element)));
|
|
381
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.');
|
|
382
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);
|
|
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.');
|
|
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.');
|
|
384
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.');
|
|
385
403
|
}
|
|
386
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.');
|
|
@@ -392,12 +410,24 @@ export function analyzeComposition(text, { filename, index, ts }) {
|
|
|
392
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.`);
|
|
393
411
|
const header = properties(props.get('header'), false);
|
|
394
412
|
const pageOwner = owner.import === `${index.package}/layout/page` || owner.import === `${index.package}/layout`;
|
|
395
|
-
|
|
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;
|
|
396
418
|
if (pageOwner && owner.symbol === 'Page') {
|
|
397
419
|
const primaries = solidPrimaryCount(ts.isJsxSelfClosingElement(node) ? node : node.parent) + (new Map(header).has('primaryAction') ? 1 : 0);
|
|
398
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.`);
|
|
399
421
|
}
|
|
400
|
-
if (headerActions && commandButtons(headerActions)) add(node, 'page-command-roles', 'warning', `${owner.symbol}: buttons in the header actions region choose their own emphasis,
|
|
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
|
+
}
|
|
401
431
|
const title = literal(props.get('title')) ?? literal(new Map(header).get('title'));
|
|
402
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.`);
|
|
403
433
|
const structure = owner.import === `${index.package}/base/structure` && Object.hasOwn(structureDefaults, owner.symbol);
|
|
@@ -57,10 +57,144 @@ export function utility(token) {
|
|
|
57
57
|
return token.slice(start).replace(/^!|!$/g, '');
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
export function variants(token) {
|
|
61
|
+
return token.slice(0, token.length - utility(token).length - (/!$/.test(token) ? 1 : 0)).replace(/!$/, '');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Text and icon colours are typography roles. Opacity on a role adds a tier under
|
|
65
|
+
// the tested 4.5:1, so only the sidebar keeps its one secondary tier.
|
|
66
|
+
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)\/.+$/;
|
|
67
|
+
export function fadedText(token) {
|
|
68
|
+
const value = utility(token);
|
|
69
|
+
return value !== 'text-sidebar-foreground/70' && textRole.test(value);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Interaction fills come from one recipe owner: accent for rows, muted for toggle
|
|
73
|
+
// hover, a lifted card segment and the table ladder. A neutral fill with opacity or
|
|
74
|
+
// a primary tint under hover, highlight, selection, current or pressed state is a
|
|
75
|
+
// second definition of that state.
|
|
76
|
+
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-]+)?$/;
|
|
77
|
+
function variantSegments(variant) {
|
|
78
|
+
const segments = [];
|
|
79
|
+
let depth = 0, start = 0;
|
|
80
|
+
for (let i = 0; i < variant.length; i++) {
|
|
81
|
+
if ('[('.includes(variant[i])) depth++;
|
|
82
|
+
else if ('])'.includes(variant[i])) depth--;
|
|
83
|
+
else if (variant[i] === ':' && depth === 0) { segments.push(variant.slice(start, i)); start = i + 1; }
|
|
84
|
+
}
|
|
85
|
+
return segments;
|
|
86
|
+
}
|
|
87
|
+
export function interactionFillDrift(token) {
|
|
88
|
+
if (!variantSegments(variants(token)).some(segment => interactionSegment.test(segment))) return false;
|
|
89
|
+
const match = utility(token).match(/^bg-(muted|accent|card|background|foreground|secondary|popover|sidebar-accent|primary)\/(.+)$/);
|
|
90
|
+
return !!match && !(match[1] === 'muted' && match[2] === '50');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Neutral fills have one strength per role (neutralFillRecipes in
|
|
94
|
+
// src/lib/surface-recipes.ts): a wash at muted/30, a band at muted/50, a chip at
|
|
95
|
+
// foreground/8, the inverse chip at background/10 and the idle marker at
|
|
96
|
+
// muted-foreground/40. Opaque fills are always available; interaction states belong
|
|
97
|
+
// to interaction-fill.
|
|
98
|
+
const neutralTint = /^bg-(muted|muted-foreground|foreground|background|card|popover|secondary|accent|sidebar(?:-[a-z]+)*)\/(.+)$/;
|
|
99
|
+
const neutralScale = new Set(['muted/30', 'muted/50', 'foreground/8', 'background/10', 'muted-foreground/40']);
|
|
100
|
+
export function neutralFillDrift(token) {
|
|
101
|
+
const match = utility(token).match(neutralTint);
|
|
102
|
+
if (!match || neutralScale.has(`${match[1]}/${match[2]}`)) return false;
|
|
103
|
+
return !variantSegments(variants(token)).some(segment => interactionSegment.test(segment));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Elevation takes one theme shadow per role (elevationRecipes in
|
|
107
|
+
// src/lib/surface-recipes.ts): xs resting, sm card, md raised and anchored, lg lifted
|
|
108
|
+
// and xl modal; shadow-none clears it. A box-shadow divider line that draws
|
|
109
|
+
// var(--border) is divider mechanics, not elevation.
|
|
110
|
+
export function elevationDrift(token) {
|
|
111
|
+
const value = utility(token);
|
|
112
|
+
if (!/^shadow(?:-|$)/.test(value)) return false;
|
|
113
|
+
return !/^shadow-(?:none|xs|sm|md|lg|xl)$/.test(value) && !/^shadow-\[.*var\(--border\).*\]$/.test(value);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Dividers have two strengths: a surface edge draws the full border role and an
|
|
117
|
+
// inner divider (one side, divide, separator) draws it at 60%. The control boundary
|
|
118
|
+
// has one strength. Only src/lib/surface-recipes.ts owns other strengths (the modal
|
|
119
|
+
// shell and the framed Card ring).
|
|
120
|
+
export function dividerStrengthDrift(token) {
|
|
121
|
+
const match = utility(token).match(/^(?:border(?:-[trblxyse]|-bs|-be)?|divide(?:-[xy])?|ring|inset-ring|outline|bg)-(border|sidebar-border|input)\/(.+)$/);
|
|
122
|
+
return !!match && !(match[1] === 'border' && match[2] === '60');
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Status and emphasis tints have one scale, src/lib/tone-recipes.ts: a wash, tint,
|
|
126
|
+
// edge, halo and line strength per tone, which the contrast contract tests. A
|
|
127
|
+
// translucent tone spelled anywhere else is a second scale. The invalid state's
|
|
128
|
+
// destructive halo belongs to the field-state and focus recipes.
|
|
129
|
+
const toneTint = /^(?:bg|border(?:-[trblxyse]|-bs|-be)?|ring|inset-ring|outline|divide(?:-[xy])?)-(?:info|success|warning|destructive|primary)(?:-accent)?\/.+$/;
|
|
130
|
+
export function statusTintDrift(token) {
|
|
131
|
+
return toneTint.test(utility(token)) && !/invalid|focus/.test(variants(token));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// State changes (colour, border and shadow) share one timing: Tailwind's default
|
|
135
|
+
// 150ms transition and easing. Presence and geometry motion (enter, exit, expand,
|
|
136
|
+
// slide) comes from src/lib/motion-recipes.ts. Returns the timing tokens that
|
|
137
|
+
// retime a paint-only transition.
|
|
138
|
+
const paintProperties = new Set(['color', 'background-color', 'background', 'border-color', 'box-shadow', 'outline-color', 'text-decoration-color', 'fill', 'stroke']);
|
|
139
|
+
function paintTransition(token) {
|
|
140
|
+
const value = utility(token);
|
|
141
|
+
if (value === 'transition-colors' || value === 'transition-shadow') return true;
|
|
142
|
+
const list = value.match(/^transition-\[(.+)\]$/)?.[1];
|
|
143
|
+
return !!list && list.split(',').every(property => paintProperties.has(property.trim()));
|
|
144
|
+
}
|
|
145
|
+
export function stateMotionDrift(classes) {
|
|
146
|
+
const resting = classes.filter(token => variants(token) === '');
|
|
147
|
+
if (!resting.some(paintTransition) || resting.some(token => /^transition(?:-|$)/.test(utility(token)) && !paintTransition(token))) return [];
|
|
148
|
+
return resting.filter(token => /^duration-(?!150$|0$)/.test(utility(token)) || /^ease-/.test(utility(token)));
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Corners take a role derived from --radius: rounded-radius (outer shells) and
|
|
152
|
+
// rounded-inner (controls, rows, nested bodies), plus rounded-full, rounded-none
|
|
153
|
+
// and the root-derived rounded-radius-* steps. Bare rounded is a fixed 4px that
|
|
154
|
+
// ignores the theme root, and the t-shirt steps are a second scale.
|
|
155
|
+
export function radiusRoleDrift(token) {
|
|
156
|
+
return /^rounded(?:-(?:[trblse]|tl|tr|br|bl|ss|se|es|ee))?(?:-(?:xs|sm|md|lg|xl|2xl|3xl|4xl))?$/.test(utility(token));
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// One stacking scale (src/lib/layer-recipes.ts): z-10 raised, z-20 sticky, z-30
|
|
160
|
+
// sticky over sticky, z-40 app chrome, z-50 popups and modal layers. Local
|
|
161
|
+
// ordering may also use z-0, z-[1] and z-[-1].
|
|
162
|
+
export function layerScaleDrift(token) {
|
|
163
|
+
const match = utility(token).replace(/^-/, '').match(/^z-(?:(\d+)|\[(-?\d+)\])$/);
|
|
63
164
|
if (!match) return false;
|
|
64
|
-
|
|
65
|
-
return
|
|
165
|
+
if (match[2] !== undefined) return Math.abs(Number(match[2])) > 1;
|
|
166
|
+
return ![0, 10, 20, 30, 40, 50].includes(Number(match[1]));
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Disabled content dims once, at 50%; a child of a dimmed owner resets to 100%.
|
|
170
|
+
const disabledSegment = /^(?:group-|peer-)?(?:disabled|data-disabled|aria-disabled|data-\[disabled[^\]]*\]|aria-\[disabled[^\]]*\])(?:\/[\w-]+)?$/;
|
|
171
|
+
export function disabledDimmingDrift(token) {
|
|
172
|
+
if (!variantSegments(variants(token)).some(segment => disabledSegment.test(segment))) return false;
|
|
173
|
+
const match = utility(token).match(/^opacity-(\d+)$/);
|
|
174
|
+
return !!match && !['50', '100'].includes(match[1]);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const focusState = /focus|focused/;
|
|
178
|
+
const ringWidth = /^ring(?:-\d+(?:\.\d+)?|-\[(?:\d+(?:\.\d+)?)(?:px|rem|em)\])?$/;
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Every focus indicator is one recipe: a 3px halo of the ring role at 50% around
|
|
182
|
+
* a full-strength 1px edge (the control's own `border-ring`, or `inset-ring-ring`
|
|
183
|
+
* on a borderless element). Returns the tokens that draw focus any other way:
|
|
184
|
+
* another focus ring width, an offset ring, a halo at another strength, an
|
|
185
|
+
* attenuated edge, or an unscoped ring colour that a focus-only width turns into
|
|
186
|
+
* a full-strength halo. Status tints (invalid, selected) keep their own colours.
|
|
187
|
+
*/
|
|
188
|
+
export function focusRingDrift(classes) {
|
|
189
|
+
const focused = token => focusState.test(variants(token));
|
|
190
|
+
const focusWidth = classes.some(token => focused(token) && ringWidth.test(utility(token)) && utility(token) !== 'ring-0');
|
|
191
|
+
return classes.filter(token => {
|
|
192
|
+
const value = utility(token);
|
|
193
|
+
if (!focused(token)) return focusWidth && variants(token) === '' && /^ring-(?:ring|sidebar-ring)$/.test(value);
|
|
194
|
+
if (/^ring-offset-/.test(value)) return true;
|
|
195
|
+
if (ringWidth.test(value)) return !/^ring-[03]$/.test(value);
|
|
196
|
+
const halo = value.match(/^ring-(?:ring|sidebar-ring)(?:\/(.+))?$/);
|
|
197
|
+
if (halo) return halo[1] !== '50';
|
|
198
|
+
return /^(?:border|inset-ring|outline)-(?:ring|sidebar-ring)\/.+$/.test(value);
|
|
199
|
+
});
|
|
66
200
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "themelia-react-ui",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "A composable React UI library for modern admin applications, built on Base UI and Tailwind with shadcn-compatible themes, shared design tokens, reusable layouts, blocks and workflows.",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
@@ -99,6 +99,10 @@
|
|
|
99
99
|
"types": "./dist/components/base/badge/index.d.ts",
|
|
100
100
|
"import": "./dist/base/badge.js"
|
|
101
101
|
},
|
|
102
|
+
"./base/batch-action-bar": {
|
|
103
|
+
"types": "./dist/components/base/batch-action-bar/index.d.ts",
|
|
104
|
+
"import": "./dist/base/batch-action-bar.js"
|
|
105
|
+
},
|
|
102
106
|
"./base/cards": {
|
|
103
107
|
"types": "./dist/components/base/cards/index.d.ts",
|
|
104
108
|
"import": "./dist/base/cards.js"
|
|
@@ -163,6 +167,10 @@
|
|
|
163
167
|
"types": "./dist/components/base/media-gallery/index.d.ts",
|
|
164
168
|
"import": "./dist/base/media-gallery.js"
|
|
165
169
|
},
|
|
170
|
+
"./base/metadata-list": {
|
|
171
|
+
"types": "./dist/components/base/metadata-list/index.d.ts",
|
|
172
|
+
"import": "./dist/base/metadata-list.js"
|
|
173
|
+
},
|
|
166
174
|
"./base/navigation": {
|
|
167
175
|
"types": "./dist/components/base/navigation/index.d.ts",
|
|
168
176
|
"import": "./dist/base/navigation.js"
|
|
@@ -465,7 +473,7 @@
|
|
|
465
473
|
"check:maps": "node scripts/test-client-boundaries.mjs --built",
|
|
466
474
|
"build:docs": "node scripts/build-static-docs.mjs",
|
|
467
475
|
"check:static-docs": "node scripts/check-static-docs.mjs",
|
|
468
|
-
"check:agent": "node --test scripts/test-consumer-discovery.mjs scripts/test-consumer-composition.mjs scripts/test-button-codemod.mjs scripts/test-consumer-skill-assets.mjs scripts/test-static-docs.mjs scripts/test-fixture-install.mjs && npm run check:skill",
|
|
476
|
+
"check:agent": "node --test scripts/test-consumer-discovery.mjs scripts/test-consumer-composition.mjs scripts/test-consumer-evals.mjs scripts/test-button-codemod.mjs scripts/test-consumer-skill-assets.mjs scripts/test-static-docs.mjs scripts/test-fixture-install.mjs && npm run check:skill",
|
|
469
477
|
"check:release": "npm run check:all && npm run check:agent && npm run build:docs && npm run check:static-docs"
|
|
470
478
|
},
|
|
471
479
|
"peerDependencies": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"accordion-CQXVcd7Q.js","names":["Accordion","AccordionPrimitive","AccordionItem","AccordionTrigger","AccordionContent","Accordion","React","PrimitiveAccordion","PrimitiveAccordionItem","PrimitiveAccordionTrigger","PrimitiveAccordionContent","Accordion","Text","motionRecipes","Stack","DisclosurePanelElement","IconBadge","React$1","Accordion$2","props","Accordion","cn","className","AccordionItem$1","AccordionTrigger$1","children","ChevronDownIcon","AccordionContent$1","panelProps","Accordion$1","AccordionItem","AccordionTrigger","isSimpleText","AccordionContent","ACCORDION_ROOT_VARIANT_CLASS","ACCORDION_ITEM_VARIANT_CLASS","ACCORDION_TRIGGER_BASE","ACCORDION_CONTENT_PADDING","defaultSmartAccordionStrings","SmartAccordion","forwardRef","stringsProp","strings","useStrings","hasIconColumn","iconStyle","items","item","contentPadding","triggerGridClass","onValueChange","next","variant","itemClassName","triggerClassName","SmartAccordionIcon","isSimpleContent","contentClassName","content","reserveSpace","icon"],"sources":["../src/components/ui/accordion.tsx","../src/components/base/accordion/accordion.tsx","../src/components/base/accordion/accordion-variants.ts","../src/components/base/accordion/accordion.strings.ts","../src/components/base/accordion/smart-accordion.tsx"],"sourcesContent":["import { DisclosurePanelElement } from './disclosure-panel';\nimport { motionRecipes } from '../../lib/motion-recipes';\nimport { Accordion as AccordionPrimitive } from \"@base-ui/react/accordion\"\n\nimport { cn } from \"../../lib/utils\"\nimport { ChevronDownIcon } from \"lucide-react\"\n\nfunction Accordion({ className, ...props }: AccordionPrimitive.Root.Props) {\n return (\n <AccordionPrimitive.Root\n data-slot=\"accordion\"\n className={cn(\"border-border accordion--component flex w-full flex-col border box-border overflow-hidden\", className)}\n {...props}\n />\n )\n}\n\nfunction AccordionItem({ className, ...props }: AccordionPrimitive.Item.Props) {\n return (\n <AccordionPrimitive.Item\n data-slot=\"accordion-item\"\n className={cn(\"border-border accordion-item--component border-b last:border-b-0\", className)}\n {...props}\n />\n )\n}\n\nfunction AccordionTrigger({\n className,\n children,\n ...props\n}: AccordionPrimitive.Trigger.Props) {\n return (\n <AccordionPrimitive.Header className=\"accordion-header m-0\">\n <AccordionPrimitive.Trigger\n data-slot=\"accordion-trigger\"\n className={cn(\"accordion-trigger--component flex w-full items-center justify-between border-0 bg-transparent outline-none cursor-pointer box-border\", className)}\n {...props}\n >\n {children}\n <ChevronDownIcon data-slot=\"accordion-trigger-icon\" className={cn(\"accordion-trigger--icon size-icon text-muted-foreground shrink-0 [[aria-expanded=true]_&]:rotate-180\", motionRecipes.chevron)} />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n )\n}\n\nfunction AccordionContent({\n className,\n children,\n render,\n ...props\n}: AccordionPrimitive.Panel.Props) {\n return (\n <AccordionPrimitive.Panel\n data-slot=\"accordion-content\"\n className={cn(\"accordion-content--component box-border text-foreground h-(--accordion-panel-height)\", motionRecipes.disclosure, className)}\n {...props}\n render={(panelProps, state) => <DisclosurePanelElement props={panelProps} state={state} render={render} heightVariable=\"--accordion-panel-height\" />}\n >\n {children}\n </AccordionPrimitive.Panel>\n )\n}\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent }\n\n","/**\n * Accordion — tokenized base wrapper around the shadcn/Base UI primitive.\n *\n * The internal primitive intentionally keeps shadcn's roomy defaults. This\n * public layer calibrates them for admin surfaces: radius tokens, 12px row\n * insets, density-aware vertical rhythm, quiet hover/focus treatments, and\n * matching trigger/content columns. Consumers retain the complete compound\n * API and can override any treatment with `className`.\n */\nimport * as React from 'react';\n\nimport {\n\tAccordion as PrimitiveAccordion,\n\tAccordionContent as PrimitiveAccordionContent,\n\tAccordionItem as PrimitiveAccordionItem,\n\tAccordionTrigger as PrimitiveAccordionTrigger,\n} from '../../ui/accordion';\nimport { Text } from '../../typography';\nimport { cn } from '../../../lib/utils';\n\nexport type AccordionProps = React.ComponentPropsWithoutRef<typeof PrimitiveAccordion>;\nexport type AccordionItemProps = React.ComponentPropsWithoutRef<typeof PrimitiveAccordionItem>;\nexport type AccordionTriggerProps = React.ComponentPropsWithoutRef<typeof PrimitiveAccordionTrigger>;\nexport type AccordionContentProps = React.ComponentPropsWithoutRef<typeof PrimitiveAccordionContent>;\n\nconst Accordion = React.forwardRef<React.ElementRef<typeof PrimitiveAccordion>, AccordionProps>(\n\tfunction Accordion({ className, ...props }, ref) {\n\t\treturn (\n\t\t\t<PrimitiveAccordion\n\t\t\t\tref={ref}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'accordion--component rounded-radius border-border bg-card',\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nAccordion.displayName = 'Accordion';\n\nconst AccordionItem = React.forwardRef<React.ElementRef<typeof PrimitiveAccordionItem>, AccordionItemProps>(\n\tfunction AccordionItem({ className, ...props }, ref) {\n\t\treturn (\n\t\t\t<PrimitiveAccordionItem\n\t\t\t\tref={ref}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'accordion-item--component border-border',\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nAccordionItem.displayName = 'AccordionItem';\n\nconst AccordionTrigger = React.forwardRef<React.ElementRef<typeof PrimitiveAccordionTrigger>, AccordionTriggerProps>(\n\tfunction AccordionTrigger({ className, children, ...props }, ref) {\n\t\tconst isSimpleText = typeof children === 'string' || typeof children === 'number' || typeof children === 'bigint';\n\t\treturn (\n\t\t\t<PrimitiveAccordionTrigger\n\t\t\t\tref={ref}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'accordion-trigger--component min-h-action items-center gap-space-lg px-row-x py-row-y',\n\t\t\t\t\t'text-start text-sm font-medium transition-colors hover:bg-muted/40 hover:no-underline',\n\t\t\t\t\t// Inset: the shell clips its rounded corners, so an outer ring was cut off.\n\t\t\t\t\t'focus-visible:z-10 focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring',\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{isSimpleText ? (\n\t\t\t\t\t<Text tag=\"span\" size=\"inherit\" weight=\"medium\" lineHeight=\"tight\" className=\"text-inherit\">\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</Text>\n\t\t\t\t) : children}\n\t\t\t</PrimitiveAccordionTrigger>\n\t\t);\n\t},\n);\nAccordionTrigger.displayName = 'AccordionTrigger';\n\nconst AccordionContent = React.forwardRef<React.ElementRef<typeof PrimitiveAccordionContent>, AccordionContentProps>(\n\tfunction AccordionContent({ className, children, ...props }, ref) {\n\t\tconst isSimpleText = typeof children === 'string' || typeof children === 'number' || typeof children === 'bigint';\n\t\treturn (\n\t\t\t<PrimitiveAccordionContent\n\t\t\t\tref={ref}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'accordion-content--component px-row-x pb-space-lg text-sm',\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{isSimpleText ? (\n\t\t\t\t\t<Text tag=\"div\" size=\"inherit\" lineHeight=\"relaxed\" className=\"text-inherit\">\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</Text>\n\t\t\t\t) : children}\n\t\t\t</PrimitiveAccordionContent>\n\t\t);\n\t},\n);\nAccordionContent.displayName = 'AccordionContent';\n\nexport {\n\tAccordion,\n\tAccordionItem,\n\tAccordionTrigger,\n\tAccordionContent,\n};\n","/**\n * Shared accordion-shell variant classes — used by both `SmartAccordion`\n * and any blocks surface that builds on `base/accordion` directly\n * (e.g. `blocks/onboarding/checklist`).\n *\n * Exported because two consumers already keep it in lockstep; a third\n * one will copy this exact map. Centralising means a future tweak\n * (e.g. tighten `card` items to `border-border/70`) propagates.\n *\n * Padding tokens for trigger / content live alongside so the rhythm\n * is shared too:\n *\n * - Trigger: `gap-space-lg px-row-x py-row-y` — density-driven,\n * `<UIProvider>`\n * override flows through.\n * - Content padding accounts for the base panel's `px-row-x`.\n * Medallion and inline rows use shared media/spacing tokens, and\n * no-icon rows add no extra left padding so body copy tracks the\n * trigger text column instead of drifting.\n */\nimport type { DisclosureSurface } from '../../../lib/component-vocabulary';\n\nexport type AccordionShellVariant = DisclosureSurface;\n\nexport const ACCORDION_ROOT_VARIANT_CLASS: Record<AccordionShellVariant, string> = {\n\tcard: 'gap-space-md border-0 rounded-none bg-transparent overflow-visible',\n\tbordered: 'rounded-radius border border-border bg-card overflow-hidden',\n\tflat: 'border-0 rounded-none bg-transparent overflow-visible',\n};\n\n// The chevron and the revealed panel carry the open state; an open item is not\n// tinted into a box. Rounded items clip their trigger so its inset focus ring and\n// hover fill follow the item's corners.\nexport const ACCORDION_ITEM_VARIANT_CLASS: Record<AccordionShellVariant, string> = {\n\tcard: 'border border-border bg-card rounded-radius overflow-hidden',\n\tbordered: 'bg-transparent not-last:border-b border-border',\n\tflat: 'border-0 not-last:border-b-0 bg-transparent rounded-radius overflow-hidden',\n};\n\nexport const ACCORDION_TRIGGER_BASE =\n\t'items-center gap-space-lg px-row-x py-row-y text-start hover:no-underline';\n\n/**\n * Content-padding presets keyed off the leading-icon width. Use\n * `withMedallion` when the trigger renders a default `IconBadge`\n * plus the shared row gap so body text aligns under the title at every\n * consumer density.\n */\nexport const ACCORDION_CONTENT_PADDING = {\n\t// Composed from root tokens so a scoped density/space boundary applies (the\n\t// `--spacing-*` aliases resolve once at :root inside arbitrary values).\n\twithMedallion: 'ps-[calc(var(--row-x)*var(--space-scale)+var(--avatar)+0.75rem*var(--space-scale))] pe-row-x pt-0',\n\twithInline: 'ps-[calc(var(--row-x)*var(--space-scale)+var(--icon)*1.25+0.75rem*var(--space-scale))] pe-row-x pt-0',\n\twithoutIcon: 'px-row-x pt-0',\n} as const;\n","/**\n * Strings for `SmartAccordion`. There aren't many — Radix handles the\n * trigger ARIA states automatically, so the only library-owned copy is\n * the optional landmark label on the wrapping nav region. Consumers\n * override per-item `title` / `badge` / `content` directly via\n * `SmartAccordionItem` props (the strings live in the data, not here).\n */\nexport interface SmartAccordionStrings {\n\t/**\n\t * Sets `aria-label` on the wrapping element so screen readers can name\n\t * the accordion region. Optional — when absent, no aria-label is set.\n\t */\n\tregionAriaLabel?: string;\n}\n\nexport const defaultSmartAccordionStrings: SmartAccordionStrings = {\n\tregionAriaLabel: undefined,\n};\n","/**\n * SmartAccordion — the canonical \"icon + title + optional badge + body\"\n * accordion pattern, with three visual variants for the surface chrome\n * (`card` | `bordered` | `flat`) and three icon framings (`medallion` |\n * `inline` | `none`).\n *\n * Composes the wrapped `base/accordion` parts (rule 2 — blocks-style\n * convenience built from re-exports, not the raw shadcn primitive).\n *\n * For richer rows (multi-line metadata, custom layouts), drop down to\n * the compound API:\n *\n * import { Accordion, AccordionItem, AccordionTrigger, AccordionContent }\n * from '.';\n */\nimport { forwardRef, type ReactNode } from 'react';\n\nimport { IconBadge } from '../display/icon-badge';\nimport { Stack } from '../structure';\nimport { Text } from '../../typography';\nimport { useStrings } from '../../../lib/strings';\nimport { cn } from '../../../lib/utils';\n\nimport { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from './accordion';\nimport {\n\tACCORDION_CONTENT_PADDING,\n\tACCORDION_ITEM_VARIANT_CLASS,\n\tACCORDION_ROOT_VARIANT_CLASS,\n\tACCORDION_TRIGGER_BASE,\n} from './accordion-variants';\nimport { defaultSmartAccordionStrings } from './accordion.strings';\nimport type {\n\tSmartAccordionIconStyle,\n\tSmartAccordionProps,\n} from './accordion.types';\n\n/**\n * Bounded accordion composition for repeated icon, title, description, badge,\n * and body sections. Use the compound Accordion parts when row structure or\n * per-item presentation differs.\n */\nexport const SmartAccordion = forwardRef<HTMLDivElement, SmartAccordionProps>(function SmartAccordion({\n\titems,\n\tmultiple = false,\n\tdefaultValue,\n\tvalue,\n\tonValueChange,\n\tvariant = 'bordered',\n\ticonStyle = 'inline',\n\tclassName,\n\titemClassName,\n\ttriggerClassName,\n\tcontentClassName,\n\tstrings: stringsProp,\n}, ref) {\n\tconst strings = useStrings(defaultSmartAccordionStrings, stringsProp);\n\tconst hasIconColumn = iconStyle !== 'none' && items.some((item) => item.icon != null);\n\tconst contentPadding =\n\t\t!hasIconColumn\n\t\t\t? ACCORDION_CONTENT_PADDING.withoutIcon\n\t\t\t: iconStyle === 'medallion'\n\t\t\t? ACCORDION_CONTENT_PADDING.withMedallion\n\t\t\t: ACCORDION_CONTENT_PADDING.withInline;\n\tconst triggerGridClass = !hasIconColumn\n\t\t? 'grid-cols-[minmax(0,1fr)]'\n\t\t: 'grid-cols-[auto_minmax(0,1fr)]';\n\treturn (\n\t\t<Accordion\n\t\t\tref={ref}\n\t\t\tmultiple={multiple}\n\t\t\tdefaultValue={defaultValue}\n\t\t\tvalue={value}\n\t\t\tonValueChange={\n\t\t\t\tonValueChange\n\t\t\t\t\t? (next) => onValueChange(next as string[])\n\t\t\t\t\t: undefined\n\t\t\t}\n\t\t\taria-label={strings.regionAriaLabel}\n\t\t\tdata-variant={variant}\n\t\t\tdata-icon-style={iconStyle}\n\t\t\tclassName={cn('smart-accordion--component', ACCORDION_ROOT_VARIANT_CLASS[variant], className)}\n\t\t>\n\t\t\t{items.map((item) => (\n\t\t\t\t<AccordionItem\n\t\t\t\t\tkey={item.value}\n\t\t\t\t\tvalue={item.value}\n\t\t\t\t\tclassName={cn('smart-accordion--item', ACCORDION_ITEM_VARIANT_CLASS[variant], itemClassName)}\n\t\t\t\t>\n\t\t\t\t\t<AccordionTrigger\n\t\t\t\t\t\tclassName={cn('smart-accordion--trigger', ACCORDION_TRIGGER_BASE, triggerClassName)}\n\t\t\t\t\t\tdisabled={item.disabled}\n\t\t\t\t\t>\n\t\t\t\t\t\t<div className={cn('grid min-w-0 flex-1 items-center gap-x-space-lg', triggerGridClass)}>\n\t\t\t\t\t\t\t<SmartAccordionIcon\n\t\t\t\t\t\t\t\ticonStyle={iconStyle}\n\t\t\t\t\t\t\t\ticon={item.icon}\n\t\t\t\t\t\t\t\treserveSpace={hasIconColumn}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<Stack render={<span />} gap=\"dense\" className=\"smart-accordion--heading flex-1\">\n\t\t\t\t\t\t\t\t<span className=\"flex min-w-0 flex-wrap items-center gap-x-space-md gap-y-space-xs\">\n\t\t\t\t\t\t\t\t\t{isSimpleContent(item.title) ? (\n\t\t\t\t\t\t\t\t\t\t<Text tag=\"span\" weight=\"semibold\" className=\"smart-accordion--title min-w-0\">\n\t\t\t\t\t\t\t\t\t\t\t{item.title}\n\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t) : item.title}\n\t\t\t\t\t\t\t\t\t{item.badge != null && (\n\t\t\t\t\t\t\t\t\t\t<span className=\"smart-accordion--badge inline-flex shrink-0\">{item.badge}</span>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t{!!item.description && (\n\t\t\t\t\t\t\t\t\tisSimpleContent(item.description) ? (\n\t\t\t\t\t\t\t\t\t\t<Text tag=\"span\" type=\"secondary\" className=\"smart-accordion--description min-w-0\">\n\t\t\t\t\t\t\t\t\t\t\t{item.description}\n\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t) : item.description\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</Stack>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</AccordionTrigger>\n\t\t\t\t\t<AccordionContent\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'smart-accordion--content',\n\t\t\t\t\t\t\tcontentPadding,\n\t\t\t\t\t\t\tcontentClassName,\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{isSimpleContent(item.content) ? (\n\t\t\t\t\t\t\t<Text tag=\"div\" type=\"secondary\" lineHeight=\"relaxed\">\n\t\t\t\t\t\t\t\t{item.content}\n\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t) : item.content}\n\t\t\t\t\t</AccordionContent>\n\t\t\t\t</AccordionItem>\n\t\t\t))}\n\t\t</Accordion>\n\t);\n});\n\nSmartAccordion.displayName = 'SmartAccordion';\n\nfunction isSimpleContent(content: ReactNode): content is string | number | bigint {\n\treturn typeof content === 'string' || typeof content === 'number' || typeof content === 'bigint';\n}\n\nfunction SmartAccordionIcon({\n\ticonStyle,\n\ticon,\n\treserveSpace,\n}: {\n\ticonStyle: SmartAccordionIconStyle;\n\ticon?: ReactNode;\n\treserveSpace: boolean;\n}) {\n\tif (iconStyle === 'none' || !reserveSpace) return null;\n\tif (!icon) {\n\t\treturn (\n\t\t\t<span\n\t\t\t\taria-hidden=\"true\"\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'smart-accordion--icon inline-flex shrink-0',\n\t\t\t\t\ticonStyle === 'inline' ? 'size-icon-lg' : 'size-avatar',\n\t\t\t\t)}\n\t\t\t/>\n\t\t);\n\t}\n\tif (iconStyle === 'inline') {\n\t\treturn (\n\t\t\t<span\n\t\t\t\taria-hidden=\"true\"\n\t\t\t\tclassName=\"smart-accordion--icon inline-flex size-icon-lg shrink-0 self-center text-muted-foreground [&>svg]:size-icon\"\n\t\t\t>\n\t\t\t\t{icon}\n\t\t\t</span>\n\t\t);\n\t}\n\treturn (\n\t\t<IconBadge size=\"md\" tone=\"neutral\" shape=\"circle\" aria-hidden=\"true\" className=\"smart-accordion--icon self-center\">\n\t\t\t{icon}\n\t\t</IconBadge>\n\t);\n}\n"],"mappings":"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"}
|