themelia-react-ui 2.0.4 → 2.0.5
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 +135 -0
- package/README.md +113 -18
- package/dist/{accordion-96o0pN62.js → accordion-B9MHG0cT.js} +11 -11
- package/dist/accordion-B9MHG0cT.js.map +1 -0
- package/dist/{action-menu-CHgs8vmj.js → action-menu-Dr8K-ghE.js} +48 -45
- package/dist/action-menu-Dr8K-ghE.js.map +1 -0
- package/dist/{affordance-geometry.generated-B8yGOr8-.js → affordance-geometry.generated-P-aVJisu.js} +36 -36
- package/dist/affordance-geometry.generated-P-aVJisu.js.map +1 -0
- package/dist/{ai-artifact-BZUGwBq6.js → ai-artifact-C58tQcBy.js} +210 -174
- package/dist/ai-artifact-C58tQcBy.js.map +1 -0
- package/dist/app-shell-B_IuNWOo.js +321 -0
- package/dist/app-shell-B_IuNWOo.js.map +1 -0
- package/dist/{attachment-DkoqHPPl.js → attachment-Dg_69lPS.js} +9 -9
- package/dist/{attachment-DkoqHPPl.js.map → attachment-Dg_69lPS.js.map} +1 -1
- package/dist/{auth-D2FVZ1MH.js → auth-DTkkshS8.js} +43 -46
- package/dist/auth-DTkkshS8.js.map +1 -0
- package/dist/{avatar-DWO_HHhB.js → avatar-CeZaFmNH.js} +8 -8
- package/dist/avatar-CeZaFmNH.js.map +1 -0
- package/dist/{badge-DErMA7ul.js → badge-xIiV_E7f.js} +5 -5
- package/dist/{badge-DErMA7ul.js.map → badge-xIiV_E7f.js.map} +1 -1
- 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 +1 -1
- package/dist/base/buttons.js +1 -1
- package/dist/base/cards.js +2 -2
- package/dist/base/carousel.js +3 -3
- package/dist/base/cascader.js +2 -372
- package/dist/base/chart.js +1 -1
- package/dist/base/choice-inputs.js +2 -2
- package/dist/base/code-block.js +1 -1
- package/dist/base/combobox.js +2 -2
- package/dist/base/command.js +1 -1
- package/dist/base/copyable.js +1 -1
- package/dist/base/date-pickers.js +2 -2
- package/dist/base/display.js +6 -6
- 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 +10 -10
- package/dist/base/item.js +1 -1
- package/dist/base/media-gallery.js +1 -1
- package/dist/base/metadata-list.js +1 -1
- 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 +12 -12
- package/dist/base/repeaters.js.map +1 -1
- package/dist/base/sheet.js +1 -1
- package/dist/base/sidebar.js +2 -2
- package/dist/base/signature-pad.js +7 -7
- package/dist/base/signature-pad.js.map +1 -1
- package/dist/base/skeleton.js +1 -1
- package/dist/base/spinner.js +4 -4
- 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 +36 -36
- package/dist/base/toaster.js.map +1 -1
- package/dist/base/tree.js +1 -1
- package/dist/base/upload-queue.js +1 -1
- package/dist/base/upload.js +3 -3
- package/dist/base/value-inputs.js +1 -1
- package/dist/{batch-action-bar-CdfIkCsV.js → batch-action-bar-Cb8cuvyy.js} +6 -6
- package/dist/batch-action-bar-Cb8cuvyy.js.map +1 -0
- package/dist/blocks/admin.js +21 -21
- package/dist/blocks/admin.js.map +1 -1
- package/dist/blocks/ai.js +230 -216
- package/dist/blocks/ai.js.map +1 -1
- package/dist/blocks/analytics/usage-card.js +1 -1
- package/dist/blocks/analytics.js +325 -306
- 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 +1259 -1184
- package/dist/blocks/commerce.js.map +1 -1
- package/dist/blocks/data-display.js +2 -2
- package/dist/blocks/onboarding.js +6 -6
- package/dist/blocks/onboarding.js.map +1 -1
- package/dist/blocks/planning.js +11 -11
- package/dist/blocks/timelines.js +1 -1
- package/dist/{breadcrumbs-B-WFKecD.js → breadcrumbs-J-K2kl4c.js} +6 -6
- package/dist/{breadcrumbs-B-WFKecD.js.map → breadcrumbs-J-K2kl4c.js.map} +1 -1
- package/dist/{button-DkmK-z8E.js → button-S2Cubiiz.js} +3 -3
- package/dist/button-S2Cubiiz.js.map +1 -0
- package/dist/{buttons-BbfzgczK.js → buttons-BedGfygC.js} +16 -16
- package/dist/buttons-BedGfygC.js.map +1 -0
- package/dist/cards-rNX1M4Xn.js +69 -0
- package/dist/cards-rNX1M4Xn.js.map +1 -0
- package/dist/cascader-B1MiqkBq.js +439 -0
- package/dist/cascader-B1MiqkBq.js.map +1 -0
- package/dist/chart-Darg_0Kv.js +162 -0
- package/dist/chart-Darg_0Kv.js.map +1 -0
- package/dist/{checkbox-CzYUTPeJ.js → checkbox-fflqmODR.js} +2 -2
- package/dist/{checkbox-CzYUTPeJ.js.map → checkbox-fflqmODR.js.map} +1 -1
- package/dist/{choice-inputs-JLtij2y4.js → choice-inputs-zUgBZfE4.js} +258 -257
- package/dist/choice-inputs-zUgBZfE4.js.map +1 -0
- package/dist/{code-block-CGNaUtAE.js → code-block-BzmM9Eig.js} +8 -8
- package/dist/code-block-BzmM9Eig.js.map +1 -0
- package/dist/{collapsible-Do4G0zcC.js → collapsible-BkAI_XD4.js} +5 -5
- package/dist/{collapsible-Do4G0zcC.js.map → collapsible-BkAI_XD4.js.map} +1 -1
- package/dist/{collection-content-C0e8SsTm.js → collection-content-gDh1v6O4.js} +3 -3
- package/dist/{collection-content-C0e8SsTm.js.map → collection-content-gDh1v6O4.js.map} +1 -1
- package/dist/combobox-BEx0vJgF.js +362 -0
- package/dist/combobox-BEx0vJgF.js.map +1 -0
- package/dist/{combobox-CBJDs6w_.js → combobox-BwzoXFSG.js} +254 -247
- package/dist/combobox-BwzoXFSG.js.map +1 -0
- package/dist/{command-D8NrBj-b.js → command-CrlPIL6m.js} +11 -11
- package/dist/command-CrlPIL6m.js.map +1 -0
- package/dist/{comments-Di4w0H_S.js → comments-Dmpp0YIc.js} +29 -29
- package/dist/{comments-Di4w0H_S.js.map → comments-Dmpp0YIc.js.map} +1 -1
- package/dist/components/base/action-menu/action-menu.d.ts +7 -1
- package/dist/components/base/buttons/button-group.recipes.d.ts +2 -2
- package/dist/components/base/cards/card.recipes.d.ts +6 -4
- package/dist/components/base/cards/partials/card-primitives.d.ts +9 -2
- package/dist/components/base/cards/partials/smart-card-header-row.d.ts +3 -1
- package/dist/components/base/cards/smart-card.types.d.ts +3 -4
- package/dist/components/base/cascader/cascader-panel.d.ts +76 -0
- package/dist/components/base/chart/chart.d.ts +6 -1
- package/dist/components/base/choice-inputs/choice-types.d.ts +1 -1
- package/dist/components/base/combobox/index.d.ts +4 -2
- package/dist/components/base/feedback/alert.d.ts +1 -1
- package/dist/components/base/forms/form-sizing.d.ts +7 -7
- package/dist/components/base/forms/workflow.d.ts +7 -1
- package/dist/components/base/forms-numeric/coordinates-input.d.ts +4 -0
- package/dist/components/base/metadata-list/metadata-list.d.ts +1 -1
- package/dist/components/base/navigation/dropdown-menu.d.ts +1 -1
- package/dist/components/base/navigation/page-header/page-header-commands.d.ts +14 -7
- package/dist/components/base/navigation/page-header/page-header.d.ts +10 -3
- package/dist/components/base/popover/popover.d.ts +3 -3
- package/dist/components/base/popover/popover.recipes.d.ts +10 -6
- package/dist/components/base/sheet/sheet.d.ts +2 -0
- package/dist/components/base/sidebar/index.d.ts +1 -1
- package/dist/components/base/sidebar/sidebar.d.ts +27 -5
- package/dist/components/base/toaster/index.d.ts +1 -0
- package/dist/components/blocks/ai/ai-file-tree/types.d.ts +1 -1
- package/dist/components/blocks/ai/ai-tool-call/types.d.ts +3 -1
- package/dist/components/blocks/ai/ai.strings.d.ts +2 -0
- package/dist/components/blocks/analytics/metric-comparison/metric-comparison.d.ts +2 -0
- package/dist/components/blocks/analytics/usage-card/usage-card.strings.d.ts +2 -0
- package/dist/components/blocks/commerce/cart-summary/cart-summary.d.ts +1 -1
- package/dist/components/blocks/commerce/cart-summary/types.d.ts +3 -1
- package/dist/components/blocks/commerce/discount-stack/discount-stack.d.ts +1 -1
- package/dist/components/blocks/commerce/discount-stack/types.d.ts +3 -1
- package/dist/components/blocks/commerce/fulfillment-group/fulfillment-group.d.ts +1 -1
- package/dist/components/blocks/commerce/fulfillment-group/types.d.ts +11 -2
- package/dist/components/blocks/commerce/index.d.ts +7 -6
- package/dist/components/blocks/commerce/inventory-section/inventory-section.d.ts +1 -1
- package/dist/components/blocks/commerce/inventory-section/types.d.ts +7 -2
- package/dist/components/blocks/commerce/invoice-header/index.d.ts +2 -1
- package/dist/components/blocks/commerce/invoice-header/invoice-header.d.ts +1 -1
- package/dist/components/blocks/commerce/invoice-header/types.d.ts +20 -6
- package/dist/components/blocks/commerce/invoice-line-items/invoice-line-items.d.ts +1 -1
- package/dist/components/blocks/commerce/invoice-line-items/types.d.ts +24 -7
- package/dist/components/blocks/commerce/invoice-mini/index.d.ts +2 -1
- package/dist/components/blocks/commerce/invoice-mini/types.d.ts +7 -1
- package/dist/components/blocks/commerce/order-customer/order-customer.d.ts +1 -1
- package/dist/components/blocks/commerce/order-customer/types.d.ts +9 -1
- package/dist/components/blocks/commerce/refund-status/refund-status.d.ts +1 -1
- package/dist/components/blocks/commerce/refund-status/types.d.ts +3 -1
- package/dist/components/blocks/commerce/shipment-tracking/shipment-tracking.d.ts +1 -1
- package/dist/components/blocks/commerce/shipment-tracking/types.d.ts +3 -1
- package/dist/components/blocks/commerce/tax-breakdown/tax-breakdown.d.ts +1 -1
- package/dist/components/blocks/commerce/tax-breakdown/types.d.ts +3 -1
- package/dist/components/features/activities/activities.types.d.ts +8 -2
- package/dist/components/features/activities/partials/activity-marker.d.ts +7 -3
- package/dist/components/features/activities/partials/activity-row.d.ts +24 -0
- package/dist/components/features/event-calendar/colors.d.ts +2 -2
- package/dist/components/features/event-calendar/event-calendar.types.d.ts +4 -0
- package/dist/components/features/filters/facets/select-facet.d.ts +2 -1
- package/dist/components/features/filters/filters.strings.d.ts +4 -0
- package/dist/components/features/filters/filters.types.d.ts +3 -0
- package/dist/components/features/filters/partials/filter-editor-header.d.ts +16 -0
- package/dist/components/features/filters/partials/filter-popover-content.d.ts +1 -1
- package/dist/components/features/filters/partials/nested-filter-options.d.ts +21 -0
- package/dist/components/features/filters/partials/regular-filter-content.d.ts +2 -1
- package/dist/components/features/filters/utils/filter-utils.d.ts +21 -3
- package/dist/components/features/global-search/global-search.types.d.ts +2 -0
- package/dist/components/features/global-search/partials/global-search-input.d.ts +10 -0
- package/dist/components/features/global-search/partials/global-search-result-row.d.ts +7 -1
- package/dist/components/features/media-library/media-library.strings.d.ts +2 -0
- package/dist/components/features/media-library/media-library.types.d.ts +14 -4
- package/dist/components/features/media-library/partials/media-library-partials.d.ts +1 -1
- package/dist/components/features/products/components/product-options-matrix.d.ts +1 -1
- package/dist/components/features/products/components/product-variant-editor.d.ts +1 -1
- package/dist/components/features/products/components/product-variants-manager.d.ts +1 -1
- package/dist/components/features/products/products.strings.d.ts +9 -1
- package/dist/components/features/products/products.types.d.ts +43 -6
- package/dist/components/features/resource/resource.d.ts +5 -1
- package/dist/components/features/resource/resource.types.d.ts +12 -1
- package/dist/components/features/rich-text-editor/partials/image-uploads.d.ts +1 -1
- package/dist/components/features/rich-text-editor/rich-text-editor.recipes.d.ts +12 -2
- package/dist/components/features/table/partials/resource-cell.d.ts +22 -5
- package/dist/components/features/table/table.types.d.ts +1 -1
- package/dist/components/layout/app-shell/app-shell.types.d.ts +35 -6
- package/dist/components/layout/app-shell/index.d.ts +1 -1
- package/dist/components/layout/app-shell/shell-regions.d.ts +27 -0
- package/dist/components/layout/app-shell/sidebar-inset-layout.d.ts +1 -1
- package/dist/components/layout/app-shell/stacked-layout.d.ts +1 -1
- package/dist/components/layout/app-shell/topbar-sidebar-layout.d.ts +1 -1
- package/dist/components/layout/containers/two-column-layout.d.ts +2 -0
- package/dist/components/layout/header/header.recipes.d.ts +6 -0
- package/dist/components/layout/header/header.types.d.ts +6 -6
- package/dist/components/layout/navigation/section-nav/section-nav.d.ts +5 -0
- package/dist/components/layout/page/index.d.ts +2 -1
- package/dist/components/layout/page/page.d.ts +1 -0
- package/dist/components/layout/page/page.strings.d.ts +11 -0
- package/dist/components/layout/page/page.types.d.ts +69 -17
- package/dist/components/layout/page/partials/page-header.d.ts +1 -1
- package/dist/components/layout/settings/settings.d.ts +9 -2
- package/dist/components/layout/sidebar/app-sidebar.d.ts +1 -1
- package/dist/components/layout/sidebar/components/sidebar-grouped-navigation.d.ts +1 -1
- package/dist/components/layout/sidebar/components/sidebar-navigation.d.ts +1 -1
- package/dist/components/layout/sidebar/index.d.ts +2 -1
- package/dist/components/layout/sidebar/sidebar-navigation-rail.d.ts +36 -0
- package/dist/components/layout/sidebar/sidebar.context.d.ts +5 -7
- package/dist/components/layout/sidebar/sidebar.types.d.ts +48 -10
- package/dist/components/layout/sidebar/sidebar.utils.d.ts +9 -1
- package/dist/components/layout/workspace/workspace.types.d.ts +8 -1
- package/dist/components/ui/alert-dialog.d.ts +2 -2
- package/dist/components/ui/combobox.d.ts +1 -1
- package/dist/components/ui/dialog.d.ts +2 -2
- package/dist/components/ui/overlay-layer.d.ts +18 -0
- package/dist/components/ui/sheet.d.ts +5 -1
- package/dist/components/ui/sidebar-state.d.ts +82 -0
- package/dist/components/ui/sidebar.d.ts +5 -17
- package/dist/{containers-CRmHf7GP.js → containers-CIxwbZt5.js} +26 -18
- package/dist/containers-CIxwbZt5.js.map +1 -0
- package/dist/{control-group-recipes-DBXmfh2E.js → control-group-recipes-fMuFo0H7.js} +6 -6
- package/dist/control-group-recipes-fMuFo0H7.js.map +1 -0
- package/dist/{copyable-CnGCZdX4.js → copyable-DIznBqiT.js} +7 -7
- package/dist/{copyable-CnGCZdX4.js.map → copyable-DIznBqiT.js.map} +1 -1
- package/dist/{data-display-D4oujtx0.js → data-display-BdgCAw8T.js} +268 -277
- package/dist/data-display-BdgCAw8T.js.map +1 -0
- package/dist/{date-Q7jnXxpk.js → date-Cq8ioE4o.js} +5 -5
- package/dist/{date-Q7jnXxpk.js.map → date-Cq8ioE4o.js.map} +1 -1
- package/dist/{date-picker-zOt1oNss.js → date-picker-RlIzKom_.js} +446 -437
- package/dist/date-picker-RlIzKom_.js.map +1 -0
- package/dist/{date-pickers-cj8IXbDC.js → date-pickers-DY-CpXS1.js} +12 -12
- package/dist/{date-pickers-cj8IXbDC.js.map → date-pickers-DY-CpXS1.js.map} +1 -1
- package/dist/{display-BB4BL_-K.js → display-KsZLw9Ov.js} +9 -9
- package/dist/{display-BB4BL_-K.js.map → display-KsZLw9Ov.js.map} +1 -1
- package/dist/dropdown-menu-CLs8Lihj.js +194 -0
- package/dist/dropdown-menu-CLs8Lihj.js.map +1 -0
- package/dist/features/activities.js +302 -253
- package/dist/features/activities.js.map +1 -1
- package/dist/features/ai-chat.js +15 -14
- package/dist/features/ai-chat.js.map +1 -1
- package/dist/features/appointment-calendar.js +22 -22
- package/dist/features/appointment-calendar.js.map +1 -1
- package/dist/features/async-preview.js +11 -10
- 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 +13 -13
- package/dist/features/data-view.js.map +1 -1
- package/dist/features/email-composer.js +237 -238
- package/dist/features/email-composer.js.map +1 -1
- package/dist/features/event-calendar.js +140 -146
- package/dist/features/event-calendar.js.map +1 -1
- package/dist/features/filters.js +1 -1
- package/dist/features/global-search.js +167 -138
- package/dist/features/global-search.js.map +1 -1
- package/dist/features/kanban.js +6 -7
- package/dist/features/kanban.js.map +1 -1
- package/dist/features/map.js +269 -260
- package/dist/features/map.js.map +1 -1
- package/dist/features/media-library.js +375 -326
- 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 +1266 -1193
- package/dist/features/products.js.map +1 -1
- package/dist/features/questionnaire.js +13 -13
- package/dist/features/questionnaire.js.map +1 -1
- package/dist/features/resource-assignment.js +8 -8
- package/dist/features/resource.js +69 -66
- package/dist/features/resource.js.map +1 -1
- package/dist/features/rich-text-editor.js +2 -2
- package/dist/features/schema-form.js +13 -13
- 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 +94 -95
- package/dist/features/theme-tweaker.js.map +1 -1
- package/dist/{feedback-DZNL5Lg1.js → feedback-Dm4izqFn.js} +80 -79
- package/dist/feedback-Dm4izqFn.js.map +1 -0
- package/dist/{field-affordance-recipes-DjwGx8eM.js → field-affordance-recipes-DWcNcOjh.js} +4 -4
- package/dist/field-affordance-recipes-DWcNcOjh.js.map +1 -0
- package/dist/{filters-BcT-uoFy.js → filters-DzgSJpMK.js} +693 -645
- package/dist/filters-DzgSJpMK.js.map +1 -0
- package/dist/{form-field-CsgRmdit.js → form-field-BriWAXyg.js} +6 -6
- package/dist/{form-field-CsgRmdit.js.map → form-field-BriWAXyg.js.map} +1 -1
- package/dist/{form-sizing-NXgjkmBG.js → form-sizing-Bs2qFUeE.js} +4 -4
- package/dist/form-sizing-Bs2qFUeE.js.map +1 -0
- package/dist/{forms-BV5m5aQF.js → forms-C0RGnJTe.js} +17 -13
- package/dist/forms-C0RGnJTe.js.map +1 -0
- package/dist/{forms-numeric-Cd33AKbD.js → forms-numeric-DIhghX1Q.js} +86 -82
- package/dist/forms-numeric-DIhghX1Q.js.map +1 -0
- package/dist/{header-BA697l4a.js → header-DMMxG__r.js} +67 -63
- package/dist/header-DMMxG__r.js.map +1 -0
- package/dist/header.recipes-BigdJjw1.js +6 -0
- package/dist/header.recipes-BigdJjw1.js.map +1 -0
- package/dist/{hooks-BQ-L7Uu2.js → hooks-DB6CJ4MR.js} +26 -14
- package/dist/hooks-DB6CJ4MR.js.map +1 -0
- package/dist/{icon-badge-COWbCCWu.js → icon-badge-DZF-YjQp.js} +4 -4
- package/dist/{icon-badge-COWbCCWu.js.map → icon-badge-DZF-YjQp.js.map} +1 -1
- package/dist/index.js +4 -5
- package/dist/{input-Cdw4k0fb.js → input-CvyDQlY7.js} +8 -8
- package/dist/{input-Cdw4k0fb.js.map → input-CvyDQlY7.js.map} +1 -1
- package/dist/input-DMBwAZmr.js +21 -0
- package/dist/input-DMBwAZmr.js.map +1 -0
- package/dist/{item-BvZ2DR_x.js → item-DjCcM18E.js} +16 -16
- package/dist/item-DjCcM18E.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 +2 -2
- package/dist/layout/settings.js +1 -1
- package/dist/layout/sidebar.js +3 -3
- package/dist/layout/workspace.js +1 -1
- package/dist/layout.js +11 -11
- package/dist/lib/affordance-geometry.generated.d.ts +35 -35
- package/dist/lib/control-group-recipes.d.ts +5 -5
- package/dist/lib/field-affordance-recipes.d.ts +2 -2
- package/dist/lib/motion-recipes.d.ts +3 -0
- package/dist/lib/navigation-row-recipes.d.ts +7 -7
- package/dist/lib/overlay-anatomy-recipes.d.ts +3 -3
- package/dist/lib/portal-recipes.d.ts +3 -0
- package/dist/lib/token-merge.generated.d.ts +13 -10
- package/dist/lib/utils.js +1 -1
- package/dist/map-demo-tile.svg +1 -1
- package/dist/{media-gallery-CSl5W1Fy.js → media-gallery-C-vChPmE.js} +6 -6
- package/dist/{media-gallery-CSl5W1Fy.js.map → media-gallery-C-vChPmE.js.map} +1 -1
- package/dist/{mentions-RKOQaaIB.js → mentions-0_4nWuI-.js} +10 -10
- package/dist/{mentions-RKOQaaIB.js.map → mentions-0_4nWuI-.js.map} +1 -1
- package/dist/{message-INU2xsxu.js → message-g8p7eVtN.js} +7 -7
- package/dist/message-g8p7eVtN.js.map +1 -0
- package/dist/{metadata-list-qVV7AVxa.js → metadata-list-C3MkU-Om.js} +64 -64
- package/dist/metadata-list-C3MkU-Om.js.map +1 -0
- package/dist/{motion-recipes-ChBg4HBq.js → motion-recipes-DitYv6P2.js} +10 -2
- package/dist/motion-recipes-DitYv6P2.js.map +1 -0
- package/dist/navigation-C90-oQFq.js +255 -0
- package/dist/navigation-C90-oQFq.js.map +1 -0
- package/dist/{navigation-BQNcg1jT.js → navigation-DaRjthVk.js} +101 -82
- package/dist/navigation-DaRjthVk.js.map +1 -0
- package/dist/{navigation-row-recipes-WZEs-hYo.js → navigation-row-recipes-BGVLvU_O.js} +9 -9
- package/dist/navigation-row-recipes-BGVLvU_O.js.map +1 -0
- package/dist/{number-E_OiIfJz.js → number-CRU3kGuk.js} +5 -5
- package/dist/{number-E_OiIfJz.js.map → number-CRU3kGuk.js.map} +1 -1
- package/dist/overflow-tab-bar-IVFVQFV6.js +172 -0
- package/dist/overflow-tab-bar-IVFVQFV6.js.map +1 -0
- package/dist/overlays-BSgCtM2v.js +1013 -0
- package/dist/overlays-BSgCtM2v.js.map +1 -0
- package/dist/page-DUUKDAjo.js +331 -0
- package/dist/page-DUUKDAjo.js.map +1 -0
- package/dist/page-header-commands-7P3sfE9u.js +193 -0
- package/dist/page-header-commands-7P3sfE9u.js.map +1 -0
- package/dist/{pagination-Ch8X_47u.js → pagination-CgCjElfu.js} +7 -7
- package/dist/{pagination-Ch8X_47u.js.map → pagination-CgCjElfu.js.map} +1 -1
- package/dist/popover-B85RenIl.js +201 -0
- package/dist/popover-B85RenIl.js.map +1 -0
- package/dist/{popover-menu-BYaCdFhf.js → popover-menu-DlnQ2zlR.js} +7 -7
- package/dist/{popover-menu-BYaCdFhf.js.map → popover-menu-DlnQ2zlR.js.map} +1 -1
- package/dist/{popover.recipes-D3j8R8Yp.js → popover.recipes-DdiEp0rd.js} +18 -11
- package/dist/popover.recipes-DdiEp0rd.js.map +1 -0
- package/dist/portal-recipes-BpsV_iRw.js +9 -0
- package/dist/portal-recipes-BpsV_iRw.js.map +1 -0
- package/dist/{primitives-Du64iDbb.js → primitives-ByWgGUgt.js} +5 -5
- package/dist/{primitives-Du64iDbb.js.map → primitives-ByWgGUgt.js.map} +1 -1
- package/dist/primitives.js +4 -4
- package/dist/{progress-BvF2oCdV.js → progress-BJhQP9WX.js} +9 -9
- package/dist/{progress-BvF2oCdV.js.map → progress-BJhQP9WX.js.map} +1 -1
- package/dist/{receipt-D789Jwyy.js → receipt-tOc7B3hw.js} +7 -7
- package/dist/receipt-tOc7B3hw.js.map +1 -0
- package/dist/{rich-text-CLJEf76s.js → rich-text-Dth5E882.js} +3 -3
- package/dist/{rich-text-CLJEf76s.js.map → rich-text-Dth5E882.js.map} +1 -1
- package/dist/{rich-text-editor-Cm1dpUpQ.js → rich-text-editor-C1fOjBTd.js} +429 -430
- package/dist/rich-text-editor-C1fOjBTd.js.map +1 -0
- package/dist/{rich-text-editor-toolbar-L__e4x47.js → rich-text-editor-toolbar-laT3tpBT.js} +32 -28
- package/dist/rich-text-editor-toolbar-laT3tpBT.js.map +1 -0
- package/dist/{scroll-area-La5RXsEk.js → scroll-area-B0dB2cBi.js} +2 -2
- package/dist/{scroll-area-La5RXsEk.js.map → scroll-area-B0dB2cBi.js.map} +1 -1
- package/dist/{separator-DAEV0w65.js → separator-Bb17I4pu.js} +2 -2
- package/dist/{separator-DAEV0w65.js.map → separator-Bb17I4pu.js.map} +1 -1
- package/dist/{separator-GNfPG-90.js → separator-Ct_WSWTJ.js} +3 -3
- package/dist/{separator-GNfPG-90.js.map → separator-Ct_WSWTJ.js.map} +1 -1
- package/dist/services/actions.js +1 -1
- package/dist/{settings-BA2iboic.js → settings-Bar5wiSo.js} +31 -38
- package/dist/settings-Bar5wiSo.js.map +1 -0
- package/dist/sheet-BGPERY55.js +250 -0
- package/dist/sheet-BGPERY55.js.map +1 -0
- package/dist/sidebar-D-JYMMbY.js +686 -0
- package/dist/sidebar-D-JYMMbY.js.map +1 -0
- package/dist/sidebar-f9gRWXIR.js +1001 -0
- package/dist/sidebar-f9gRWXIR.js.map +1 -0
- package/dist/skeleton-BapcJd9C.js +265 -0
- package/dist/skeleton-BapcJd9C.js.map +1 -0
- package/dist/smart-card-CW0hjetE.js +617 -0
- package/dist/smart-card-CW0hjetE.js.map +1 -0
- package/dist/{structure-C0V0_Fyf.js → structure-DuxKl954.js} +2 -2
- package/dist/{structure-C0V0_Fyf.js.map → structure-DuxKl954.js.map} +1 -1
- package/dist/style.css +1 -1
- package/dist/{table-CpvnzJn9.js → table-B4TE7iOV.js} +3 -3
- package/dist/{table-CpvnzJn9.js.map → table-B4TE7iOV.js.map} +1 -1
- package/dist/{table-DH7rozUv.js → table-CFOWY9pQ.js} +394 -388
- package/dist/table-CFOWY9pQ.js.map +1 -0
- package/dist/{tabs-eqVsJZWO.js → tabs-e7ko9S2o.js} +11 -11
- package/dist/tabs-e7ko9S2o.js.map +1 -0
- package/dist/{text-inputs-DXItiR0O.js → text-inputs-B1culiSK.js} +17 -17
- package/dist/text-inputs-B1culiSK.js.map +1 -0
- package/dist/theme.css +40 -37
- package/dist/{timelines-DmtztAY_.js → timelines-D3Sl9ueq.js} +13 -12
- package/dist/timelines-D3Sl9ueq.js.map +1 -0
- package/dist/tooltip-8wz5S_Zr.js +113 -0
- package/dist/tooltip-8wz5S_Zr.js.map +1 -0
- package/dist/{tree-CV11PURP.js → tree-CzUJHnFs.js} +8 -8
- package/dist/{tree-CV11PURP.js.map → tree-CzUJHnFs.js.map} +1 -1
- package/dist/typography/rich-text.js +1 -1
- package/dist/{typography-CSyJrh28.js → typography-BQnine1k.js} +12 -12
- package/dist/{typography-CSyJrh28.js.map → typography-BQnine1k.js.map} +1 -1
- package/dist/typography.js +1 -1
- package/dist/ui-provider-C-74NVLc.js +178 -0
- package/dist/ui-provider-C-74NVLc.js.map +1 -0
- package/dist/ui-provider.js +2 -3
- package/dist/{upload-C9SA0X-8.js → upload-BOW6U2tI.js} +25 -24
- package/dist/upload-BOW6U2tI.js.map +1 -0
- package/dist/{upload-queue-DhQJiSRc.js → upload-queue-qUXn1ykN.js} +16 -14
- package/dist/upload-queue-qUXn1ykN.js.map +1 -0
- package/dist/{usage-card-DVTRDmGz.js → usage-card-BeSLY0i0.js} +24 -17
- package/dist/usage-card-BeSLY0i0.js.map +1 -0
- package/dist/{utils-CF3c95Io.js → utils-B6kKb8jB.js} +237 -141
- package/dist/utils-B6kKb8jB.js.map +1 -0
- package/dist/value-inputs-skdVB2zh.js +980 -0
- package/dist/value-inputs-skdVB2zh.js.map +1 -0
- package/dist/{value-typography-ClupF0Gz.js → value-typography-uAmWUAL1.js} +2 -2
- package/dist/{value-typography-ClupF0Gz.js.map → value-typography-uAmWUAL1.js.map} +1 -1
- package/dist/{workspace-9EFVXUyk.js → workspace-DHeHv0qw.js} +50 -49
- package/dist/workspace-DHeHv0qw.js.map +1 -0
- package/docs/consumer-skill/SKILL.md +4 -3
- package/docs/consumer-skill/agents/themelia-ui-designer.md +96 -0
- package/docs/consumer-skill/examples/app-layout.tsx +52 -1
- package/docs/consumer-skill/examples/commerce-lines.tsx +271 -0
- package/docs/consumer-skill/examples/custom-composition.tsx +21 -0
- package/docs/consumer-skill/examples/detail.tsx +5 -4
- package/docs/consumer-skill/examples/editable-sections.tsx +38 -0
- package/docs/consumer-skill/examples/index-table.tsx +4 -4
- package/docs/consumer-skill/examples/manifest.json +38 -1
- package/docs/consumer-skill/examples/product-media.tsx +41 -0
- package/docs/consumer-skill/examples/product-parts.tsx +81 -0
- package/docs/consumer-skill/examples/rhf-edit-page.tsx +1 -1
- package/docs/consumer-skill/examples/rhf-overlay-form.tsx +24 -11
- package/docs/consumer-skill/examples/token-domain-structure.tsx +68 -0
- package/docs/consumer-skill/references/agents-md.md +19 -17
- package/docs/consumer-skill/references/analytics.md +18 -1
- package/docs/consumer-skill/references/commerce-composition.md +97 -0
- package/docs/consumer-skill/references/component-contracts.json +7131 -1754
- package/docs/consumer-skill/references/composition-mapping.md +17 -3
- package/docs/consumer-skill/references/composition.md +159 -31
- package/docs/consumer-skill/references/critique-rubric.md +98 -0
- package/docs/consumer-skill/references/custom-composition.md +261 -0
- package/docs/consumer-skill/references/data-reading.md +79 -0
- package/docs/consumer-skill/references/design-contract.md +11 -9
- package/docs/consumer-skill/references/discovery.md +27 -3
- package/docs/consumer-skill/references/domain-structures.md +124 -0
- package/docs/consumer-skill/references/installation.md +15 -4
- package/docs/consumer-skill/references/integration.md +35 -0
- package/docs/consumer-skill/references/product-composition.md +94 -0
- package/docs/consumer-skill/references/public-api.json +2881 -420
- package/docs/consumer-skill/references/review.md +39 -2
- package/docs/consumer-skill/references/rhf-workflows.md +7 -0
- package/docs/consumer-skill/references/screen-archetypes.md +19 -7
- package/docs/consumer-skill/references/screen-decisions.md +126 -0
- package/docs/consumer-skill/references/theming.md +17 -18
- package/docs/consumer-skill/references/tokens.json +9 -9
- package/docs/consumer-skill/references/view-craft.md +153 -0
- package/docs/consumer-skill/references/view-spec.md +73 -0
- package/docs/consumer-skill/references/workflows.md +7 -1
- package/docs/consumer-skill/scripts/composition-policy.mjs +39 -3
- package/docs/consumer-skill/scripts/composition-schema.mjs +1 -1
- package/docs/consumer-skill/scripts/composition.mjs +61 -5
- package/docs/consumer-skill/scripts/discovery.mjs +54 -0
- package/docs/consumer-skill/scripts/inspect-component.mjs +1 -1
- package/docs/consumer-skill/scripts/inspection.mjs +73 -18
- package/docs/consumer-skill/scripts/setup-skills.mjs +41 -6
- package/docs/consumer-skill/scripts/surface-policy.mjs +5 -5
- package/docs/consumer-skills/themelia-components/SKILL.md +14 -13
- package/docs/consumer-skills/themelia-composition/SKILL.md +16 -17
- package/docs/consumer-skills/themelia-design/SKILL.md +55 -0
- package/docs/consumer-skills/themelia-foundation/SKILL.md +2 -1
- package/docs/consumer-skills/themelia-tokenization/SKILL.md +24 -17
- package/package.json +1 -1
- package/dist/accordion-96o0pN62.js.map +0 -1
- package/dist/action-menu-CHgs8vmj.js.map +0 -1
- package/dist/affordance-geometry.generated-B8yGOr8-.js.map +0 -1
- package/dist/ai-artifact-BZUGwBq6.js.map +0 -1
- package/dist/app-shell-D63ATkIK.js +0 -237
- package/dist/app-shell-D63ATkIK.js.map +0 -1
- package/dist/auth-D2FVZ1MH.js.map +0 -1
- package/dist/avatar-DWO_HHhB.js.map +0 -1
- package/dist/base/cascader.js.map +0 -1
- package/dist/batch-action-bar-CdfIkCsV.js.map +0 -1
- package/dist/button-DkmK-z8E.js.map +0 -1
- package/dist/buttons-BbfzgczK.js.map +0 -1
- package/dist/cards-4JTWqvVe.js +0 -68
- package/dist/cards-4JTWqvVe.js.map +0 -1
- package/dist/chart-C19flDQb.js +0 -155
- package/dist/chart-C19flDQb.js.map +0 -1
- package/dist/choice-inputs-JLtij2y4.js.map +0 -1
- package/dist/code-block-CGNaUtAE.js.map +0 -1
- package/dist/combobox-CBJDs6w_.js.map +0 -1
- package/dist/combobox-hbhSS18O.js +0 -355
- package/dist/combobox-hbhSS18O.js.map +0 -1
- package/dist/command-D8NrBj-b.js.map +0 -1
- package/dist/containers-CRmHf7GP.js.map +0 -1
- package/dist/control-group-recipes-DBXmfh2E.js.map +0 -1
- package/dist/data-display-D4oujtx0.js.map +0 -1
- package/dist/date-picker-zOt1oNss.js.map +0 -1
- package/dist/dropdown-menu-CjY8Vt7W.js +0 -193
- package/dist/dropdown-menu-CjY8Vt7W.js.map +0 -1
- package/dist/feedback-DZNL5Lg1.js.map +0 -1
- package/dist/field-affordance-recipes-DjwGx8eM.js.map +0 -1
- package/dist/filters-BcT-uoFy.js.map +0 -1
- package/dist/form-sizing-NXgjkmBG.js.map +0 -1
- package/dist/forms-BV5m5aQF.js.map +0 -1
- package/dist/forms-numeric-Cd33AKbD.js.map +0 -1
- package/dist/header-BA697l4a.js.map +0 -1
- package/dist/hooks-BQ-L7Uu2.js.map +0 -1
- package/dist/input-DOPL5_QE.js +0 -21
- package/dist/input-DOPL5_QE.js.map +0 -1
- package/dist/item-BvZ2DR_x.js.map +0 -1
- package/dist/message-INU2xsxu.js.map +0 -1
- package/dist/metadata-list-qVV7AVxa.js.map +0 -1
- package/dist/motion-recipes-ChBg4HBq.js.map +0 -1
- package/dist/navigation-BQNcg1jT.js.map +0 -1
- package/dist/navigation-DLF3E1IC.js +0 -145
- package/dist/navigation-DLF3E1IC.js.map +0 -1
- package/dist/navigation-row-recipes-WZEs-hYo.js.map +0 -1
- package/dist/overflow-tab-bar-CrbqMteP.js +0 -284
- package/dist/overflow-tab-bar-CrbqMteP.js.map +0 -1
- package/dist/overlays-BlKynmde.js +0 -1004
- package/dist/overlays-BlKynmde.js.map +0 -1
- package/dist/page-CIwNUtGr.js +0 -227
- package/dist/page-CIwNUtGr.js.map +0 -1
- package/dist/page-header-commands-DFMlNYzN.js +0 -128
- package/dist/page-header-commands-DFMlNYzN.js.map +0 -1
- package/dist/popover-uwzX2vo7.js +0 -198
- package/dist/popover-uwzX2vo7.js.map +0 -1
- package/dist/popover.recipes-D3j8R8Yp.js.map +0 -1
- package/dist/receipt-D789Jwyy.js.map +0 -1
- package/dist/rich-text-editor-Cm1dpUpQ.js.map +0 -1
- package/dist/rich-text-editor-toolbar-L__e4x47.js.map +0 -1
- package/dist/settings-BA2iboic.js.map +0 -1
- package/dist/sheet-DoAxTb2J.js +0 -213
- package/dist/sheet-DoAxTb2J.js.map +0 -1
- package/dist/sidebar-ByqKR_W5.js +0 -512
- package/dist/sidebar-ByqKR_W5.js.map +0 -1
- package/dist/sidebar-D2iSnGJ7.js +0 -619
- package/dist/sidebar-D2iSnGJ7.js.map +0 -1
- package/dist/skeleton-CUj8O5Bd.js +0 -264
- package/dist/skeleton-CUj8O5Bd.js.map +0 -1
- package/dist/smart-card-CqkzQsK-.js +0 -614
- package/dist/smart-card-CqkzQsK-.js.map +0 -1
- package/dist/table-DH7rozUv.js.map +0 -1
- package/dist/tabs-eqVsJZWO.js.map +0 -1
- package/dist/text-inputs-DXItiR0O.js.map +0 -1
- package/dist/theme-scope-BJ6eE2xt.js +0 -50
- package/dist/theme-scope-BJ6eE2xt.js.map +0 -1
- package/dist/timelines-DmtztAY_.js.map +0 -1
- package/dist/tooltip-B4hjKtoV.js +0 -111
- package/dist/tooltip-B4hjKtoV.js.map +0 -1
- package/dist/ui-provider-CQCuCBcy.js +0 -136
- package/dist/ui-provider-CQCuCBcy.js.map +0 -1
- package/dist/upload-C9SA0X-8.js.map +0 -1
- package/dist/upload-queue-DhQJiSRc.js.map +0 -1
- package/dist/usage-card-DVTRDmGz.js.map +0 -1
- package/dist/use-mobile-vaLKwgyf.js +0 -15
- package/dist/use-mobile-vaLKwgyf.js.map +0 -1
- package/dist/utils-CF3c95Io.js.map +0 -1
- package/dist/value-inputs-C0o70p-U.js +0 -980
- package/dist/value-inputs-C0o70p-U.js.map +0 -1
- package/dist/workspace-9EFVXUyk.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-DHeHv0qw.js","names":["Icon","React","_Fragment","Text","DisplayLabel","Heading","headingRoleSizes","copyRoleProps","focusRecipes","Stack","toneRecipes","Progress","compositionRhythm","compositionClasses","interactionRecipes","Value","Badge","ItemMedia","ItemDescription","ItemActions","ItemGroup","ItemContent","Item","ItemTitle","hasPageHeaderCommands","PageHeaderCommands","useLayoutLinkRenderer","React$1","Fragment$1","defaultWorkspaceRecordHeaderStrings","defaultWorkspaceNavStrings","value","defaultWorkspaceLocaleStripStrings","CONTENT_WIDTH_CLASS","STATUS_ICON","Check","Circle","CircleAlert","STATUS_CLASS","clampPercent","DynamicWorkspaceIcon","icon","getStatus","item","active","WorkspaceLayout","props","hasSidebar","sidebar","hasRail","rail","ariaLabel","cn","contentWidth","className","header","headerClassName","bodyClassName","sidebarClassName","mainClassName","contentClassName","railClassName","isCommandList","WorkspaceRecordHeader","stringsProp","strings","useStrings","resolvedRenderLink","hasMetadata","metadata","secondaryCommands","secondaryActions","secondaryNodes","hasCommands","primaryAction","textGap","media","titleSlot","title","badges","status","description","index","actions","headerEnd","WorkspaceNav","groups","group","activeId","StatusIcon","completion","handleSelect","context","renderItem","rowContent","SecondaryValue","itemClassName","linkNode","footerSlot","WorkspaceLocaleStrip","handleLocaleClick","locale","onLocaleChange","locales","activeLocale","Button"],"sources":["../src/components/layout/workspace/workspace.strings.ts","../src/components/layout/workspace/workspace.tsx"],"sourcesContent":["export interface WorkspaceRecordHeaderStrings {\n\tmetadataLabel: string;\n\tactionsLabel: string;\n\tsecondaryActionsLabel: string;\n}\n\nexport const defaultWorkspaceRecordHeaderStrings: WorkspaceRecordHeaderStrings = {\n\tmetadataLabel: 'Record metadata',\n\tactionsLabel: 'Record actions',\n\tsecondaryActionsLabel: 'Secondary actions',\n};\n\nexport interface WorkspaceNavStrings {\n\tariaLabel: string;\n\tcompletionLabel: (value: number) => string;\n\tcurrentLabel: string;\n}\n\nexport const defaultWorkspaceNavStrings: WorkspaceNavStrings = {\n\tariaLabel: 'Workspace navigation',\n\tcompletionLabel: (value) => `${value}% complete`,\n\tcurrentLabel: 'Current',\n};\n\nexport interface WorkspaceLocaleStripStrings {\n\tariaLabel: string;\n\tactiveLabel: string;\n\tcompletionLabel: (value: number) => string;\n}\n\nexport const defaultWorkspaceLocaleStripStrings: WorkspaceLocaleStripStrings = {\n\tariaLabel: 'Workspace locales',\n\tactiveLabel: 'Active',\n\tcompletionLabel: (value) => `${value}% complete`,\n};\n","import * as React from 'react';\nimport {\n\tCheck,\n\tCircle,\n\tCircleAlert,\n\ttype LucideIcon,\n\t} from 'lucide-react';\n\nimport { Badge } from '../../base/badge';\nimport { Button } from '../../base/buttons';\nimport { Progress } from '../../base/feedback';\nimport {\n\tItem,\n\tItemActions,\n\tItemContent,\n\tItemDescription,\n\tItemGroup,\n\tItemMedia,\n\tItemTitle,\n} from '../../base/item';\nimport { Stack } from '../../base/structure';\nimport {compositionClasses, compositionRhythm} from '../../base/structure/composition.recipes';\nimport { SecondaryValue, Value } from '../../primitives';\nimport { DisplayLabel, Heading, Text } from '../../typography';\nimport {copyRoleProps, headingRoleSizes} from '../../typography/text.styles';\nimport { useStrings } from '../../../lib/strings';\nimport { cn } from '../../../lib/utils';\n\nimport { hasPageHeaderCommands, PageHeaderCommands, type PageHeaderAction } from '../../base/navigation/page-header/page-header-commands';\nimport { useLayoutLinkRenderer } from '../hooks';\nimport type { LayoutIconComponent } from '../layout.types';\nimport {\n\tdefaultWorkspaceLocaleStripStrings,\n\tdefaultWorkspaceNavStrings,\n\tdefaultWorkspaceRecordHeaderStrings,\n} from './workspace.strings';\nimport type {\n\tWorkspaceContentWidth,\n\tWorkspaceLayoutProps,\n\tWorkspaceLocaleItem,\n\tWorkspaceLocaleStripProps,\n\tWorkspaceNavItem,\n\tWorkspaceNavItemStatus,\n\tWorkspaceNavProps,\n\tWorkspaceRecordHeaderProps,\n} from './workspace.types';\nimport { focusRecipes } from '../../../lib/focus-recipes';\nimport { interactionRecipes } from '../../../lib/interaction-recipes';\nimport { toneRecipes } from '../../../lib/tone-recipes';\n\nconst CONTENT_WIDTH_CLASS: Record<WorkspaceContentWidth, string> = {\n\tdefault: '[--workspace-content-max-width:58rem]',\n\twide: '[--workspace-content-max-width:86rem]',\n\tfull: '[--workspace-content-max-width:none]',\n};\n\nconst STATUS_ICON: Record<WorkspaceNavItemStatus, LucideIcon> = {\n\tcomplete: Check,\n\tcurrent: Circle,\n\tattention: CircleAlert,\n\tdisabled: Circle,\n\tidle: Circle,\n};\n\nconst STATUS_CLASS: Record<WorkspaceNavItemStatus, string> = {\n\tcomplete: 'text-success',\n\tcurrent: 'text-primary-accent',\n\tattention: 'text-warning-accent',\n\t// Disabled dims like every disabled control rather than adding a fainter text tier.\n\tdisabled: 'text-muted-foreground opacity-50',\n\tidle: 'text-muted-foreground',\n};\n\nfunction clampPercent(value: number): number {\n\tif (!Number.isFinite(value)) return 0;\n\treturn Math.min(100, Math.max(0, Math.round(value)));\n}\n\nfunction DynamicWorkspaceIcon({\n\ticon,\n\tclassName,\n}: {\n\t/** Leading glyph. */\n\ticon?: LayoutIconComponent;\n\tclassName?: string;\n}) {\n\tif (!icon) return null;\n\tconst Icon = icon;\n\treturn <Icon className={className} aria-hidden=\"true\" />;\n}\n\nfunction getStatus(item: WorkspaceNavItem, active: boolean): WorkspaceNavItemStatus {\n\tif (item.disabled) return 'disabled';\n\tif (item.status) return item.status;\n\tif (item.warning) return 'attention';\n\tif (active) return 'current';\n\tif (item.completion !== undefined && clampPercent(item.completion) >= 100) return 'complete';\n\treturn 'idle';\n}\n\nexport const WorkspaceLayout = React.forwardRef<HTMLDivElement, WorkspaceLayoutProps>(function WorkspaceLayout({\n\theader,\n\tsidebar,\n\trail,\n\tchildren,\n\tcontentWidth = 'wide',\n\tclassName,\n\theaderClassName,\n\tbodyClassName,\n\tsidebarClassName,\n\tmainClassName,\n\tcontentClassName,\n\trailClassName,\n\tariaLabel,\n\tstyle,\n\t...props\n}, ref) {\n\tconst hasSidebar = !!sidebar;\n\tconst hasRail = !!rail;\n\n\treturn (\n\t\t<div\n\t\t\tref={ref}\n\t\t\taria-label={ariaLabel}\n\t\t\tclassName={cn(\n\t\t\t\t'workspace-layout--component @container/workspace-layout box-border flex h-full min-h-0 w-full flex-col overflow-y-auto overscroll-contain rounded-surface border border-border bg-background text-foreground',\n\t\t\t\t'[--workspace-sidebar-width:var(--shell-sidebar-width)] [--workspace-rail-width:20rem]',\n\t\t\t\tCONTENT_WIDTH_CLASS[contentWidth],\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\tstyle={style}\n\t\t\t{...props}\n\t\t>\n\t\t\t{!!header && (\n\t\t\t\t<header className={cn('workspace-layout--header shrink-0 border-b border-border bg-background', headerClassName)}>\n\t\t\t\t\t{header}\n\t\t\t\t</header>\n\t\t\t)}\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'workspace-layout--body grid min-h-0 flex-none grid-cols-1 bg-muted/30 @min-[80rem]/workspace-layout:flex-1',\n\t\t\t\t\thasSidebar && !hasRail && '@min-[80rem]/workspace-layout:grid-cols-[var(--workspace-sidebar-width)_minmax(0,1fr)]',\n\t\t\t\t\thasSidebar && hasRail && '@min-[80rem]/workspace-layout:grid-cols-[var(--workspace-sidebar-width)_minmax(0,1fr)] @min-[96rem]/workspace-layout:grid-cols-[var(--workspace-sidebar-width)_minmax(0,1fr)_var(--workspace-rail-width)]',\n\t\t\t\t\t!hasSidebar && hasRail && '@min-[96rem]/workspace-layout:grid-cols-[minmax(0,1fr)_var(--workspace-rail-width)]',\n\t\t\t\t\tbodyClassName,\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t{!!hasSidebar && (\n\t\t\t\t\t<aside\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'workspace-layout--sidebar hidden min-h-0 border-r border-border bg-background @min-[80rem]/workspace-layout:block',\n\t\t\t\t\t\t\tsidebarClassName,\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t<div className=\"h-full overflow-y-auto overscroll-contain p-space-lg\">\n\t\t\t\t\t\t\t{sidebar}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</aside>\n\t\t\t\t)}\n\t\t\t\t<main\n\t\t\t\t\ttabIndex={0}\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t`workspace-layout--main min-h-0 min-w-0 overflow-visible @min-[80rem]/workspace-layout:overflow-y-auto overscroll-contain focus-visible:outline-none ${focusRecipes.inset}`,\n\t\t\t\t\t\tmainClassName,\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'workspace-layout--content box-border mx-auto flex min-h-full w-full max-w-[var(--workspace-content-max-width)] flex-col p-surface-lg', compositionClasses.subjects,\n\t\t\t\t\t\t\tcontentWidth === 'full' && 'max-w-none',\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{children}\n\t\t\t\t\t</div>\n\t\t\t\t</main>\n\t\t\t\t{!!hasRail && (\n\t\t\t\t\t<aside\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'workspace-layout--rail hidden min-h-0 border-l border-border bg-background @min-[96rem]/workspace-layout:block',\n\t\t\t\t\t\t\trailClassName,\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t<div className=\"h-full overflow-y-auto overscroll-contain p-space-lg\">\n\t\t\t\t\t\t\t{rail}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</aside>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t);\n});\n\nWorkspaceLayout.displayName = 'WorkspaceLayout';\n\n/** Role-based command objects rather than rendered elements. */\nfunction isCommandList(value: unknown): value is readonly PageHeaderAction[] {\n\treturn Array.isArray(value) && value.every((item) =>\n\t\titem !== null && typeof item === 'object' && !React.isValidElement(item) && 'label' in item);\n}\n\nexport const WorkspaceRecordHeader = React.forwardRef<HTMLDivElement, WorkspaceRecordHeaderProps>(function WorkspaceRecordHeader({\n\ttitle,\n\tdescription,\n\ttextGap = 'dense',\n\tbadges,\n\tmetadata,\n\tactions,\n\tprimaryAction,\n\tsecondaryActions,\n\tmaxVisibleSecondaryActions,\n\tmoreActionsLabel = 'More actions',\n\trenderLink,\n\tstatus,\n\tmedia,\n\theaderEnd,\n\ttitleSlot,\n\tclassName,\n\tstrings: stringsProp,\n\t...props\n}, ref) {\n\tconst strings = useStrings(defaultWorkspaceRecordHeaderStrings, stringsProp);\n\tconst resolvedRenderLink = useLayoutLinkRenderer({ renderLink });\n\tconst hasMetadata = !!metadata?.length;\n\t// Command objects take the shared role-based row; elements keep the\n\t// previous free-form cluster.\n\tconst secondaryCommands = isCommandList(secondaryActions) ? secondaryActions : undefined;\n\tconst secondaryNodes = secondaryCommands ? undefined : (secondaryActions as React.ReactNode);\n\tconst hasCommands = hasPageHeaderCommands(primaryAction, secondaryCommands);\n\n\treturn (\n\t\t<Stack\n\t\t\tref={ref}\n\t\t\tdirection=\"horizontal\"\n\t\t\tgap=\"xl\"\n\t\t\talign=\"start\"\n\t\t\tjustify=\"between\"\n\t\t\twrap\n\t\t\tclassName={cn(\n\t\t\t\t'workspace-record-header--component p-surface-lg',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t\t<Stack gap={textGap} className=\"workspace-record-header--identity min-w-0 max-w-full flex-1 basis-64\">\n\t\t\t\t\t<Stack direction=\"horizontal\" gap=\"lg\" align=\"center\" wrap={false}>\n\t\t\t\t{!!media && (\n\t\t\t\t\t<div className=\"workspace-record-header--media flex size-12 shrink-0 items-center justify-center overflow-hidden rounded-radius border border-border bg-muted/30\">\n\t\t\t\t\t\t{media}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t\t\t\t<Stack direction=\"horizontal\" gap=\"md\" className=\"workspace-record-header--title-row min-w-0 flex-1\">\n\t\t\t\t\t\t{titleSlot ?? (\n\t\t\t\t\t\t\t<Heading tag=\"h4\" size={headingRoleSizes.subject} className=\"[overflow-wrap:anywhere]\">\n\t\t\t\t\t\t\t\t{title}\n\t\t\t\t\t\t\t</Heading>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{!!badges && <Stack direction=\"horizontal\" wrap align=\"center\" gap=\"sm\" className=\"workspace-record-header--badges\">{badges}</Stack>}\n\t\t\t\t\t\t\t{!!status && <div className=\"workspace-record-header--status\">{status}</div>}\n\t\t\t\t\t\t</Stack>\n\t\t\t\t\t</Stack>\n\t\t\t\t\t{!!description && (\n\t\t\t\t\t\t<Text {...copyRoleProps.structuralDescription} lineHeight=\"relaxed\" className=\"workspace-record-header--description max-w-4xl\">\n\t\t\t\t\t\t\t{description}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t)}\n\t\t\t\t\t{!!hasMetadata && (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\taria-label={strings.metadataLabel}\n\t\t\t\t\t\t\tclassName=\"workspace-record-header--metadata flex flex-wrap items-center gap-x-space-xl gap-y-space-xs\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{metadata.map((item, index) => (\n\t\t\t\t\t\t\t\t<div key={item.id ?? index} className=\"flex items-baseline gap-space-sm\">\n\t\t\t\t\t\t\t\t\t<DisplayLabel>\n\t\t\t\t\t\t\t\t\t\t{item.label}\n\t\t\t\t\t\t\t\t\t</DisplayLabel>\n\t\t\t\t\t\t\t\t\t<Value className=\"tabular-nums\">\n\t\t\t\t\t\t\t\t\t\t{item.value}\n\t\t\t\t\t\t\t\t\t</Value>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</Stack>\n\t\t\t{!!(actions || secondaryNodes || hasCommands || headerEnd) && (\n\t\t\t\t<div className={cn('workspace-record-header--actions flex max-w-full shrink-0 flex-wrap items-center justify-end', compositionClasses.commands)}>\n\t\t\t\t\t{!!secondaryNodes && (\n\t\t\t\t\t\t<Stack direction=\"horizontal\" wrap align=\"center\" gap={compositionRhythm.commands} aria-label={strings.secondaryActionsLabel}>\n\t\t\t\t\t\t\t{secondaryNodes}\n\t\t\t\t\t\t</Stack>\n\t\t\t\t\t)}\n\t\t\t\t\t{!!actions && (\n\t\t\t\t\t\t<Stack direction=\"horizontal\" wrap align=\"center\" gap={compositionRhythm.commands} aria-label={strings.actionsLabel}>\n\t\t\t\t\t\t\t{actions}\n\t\t\t\t\t\t</Stack>\n\t\t\t\t\t)}\n\t\t\t\t\t{hasCommands && (\n\t\t\t\t\t\t<PageHeaderCommands\n\t\t\t\t\t\t\tprimaryAction={primaryAction}\n\t\t\t\t\t\t\tsecondaryActions={secondaryCommands}\n\t\t\t\t\t\t\tmaxVisibleSecondaryActions={maxVisibleSecondaryActions}\n\t\t\t\t\t\t\tmoreActionsLabel={moreActionsLabel}\n\t\t\t\t\t\t\trenderLink={resolvedRenderLink}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t\t{!!headerEnd && <div className=\"workspace-record-header--end\">{headerEnd}</div>}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</Stack>\n\t);\n});\n\nWorkspaceRecordHeader.displayName = 'WorkspaceRecordHeader';\n\nexport const WorkspaceNav = React.forwardRef<HTMLElement, WorkspaceNavProps>(function WorkspaceNav({\n\tgroups,\n\tactiveId,\n\tonSelect,\n\trenderItem,\n\tfooterSlot,\n\trenderLink,\n\tclassName,\n\tstrings: stringsProp,\n\t...props\n}, ref) {\n\tconst strings = useStrings(defaultWorkspaceNavStrings, stringsProp);\n\tconst resolvedRenderLink = useLayoutLinkRenderer({ renderLink });\n\n\treturn (\n\t\t<Stack\n\t\t\trender={(\n\t\t\t\t<nav\n\t\t\t\t\tref={ref}\n\t\t\t\t\taria-label={props['aria-label'] ?? strings.ariaLabel}\n\t\t\t\t\t{...props}\n\t\t\t\t/>\n\t\t\t)}\n\t\t\tgap=\"xl\"\n\t\t\tclassName={cn('workspace-nav--component h-full', className)}\n\t\t>\n\t\t\t<Stack gap=\"xl\" className=\"workspace-nav--groups min-h-0 flex-1\">\n\t\t\t\t{groups.map((group) => (\n\t\t\t\t\t<Stack key={group.id} gap=\"md\" className=\"workspace-nav--group\">\n\t\t\t\t\t\t{!!group.label && (\n\t\t\t\t\t\t\t<Stack gap=\"dense\" className=\"workspace-nav--group-header px-space-xs\">\n\t\t\t\t\t\t\t\t<DisplayLabel>\n\t\t\t\t\t\t\t\t\t{group.label}\n\t\t\t\t\t\t\t\t</DisplayLabel>\n\t\t\t\t\t\t\t\t{!!group.description && (\n\t\t\t\t\t\t\t\t\t<Text size=\"xs\" type=\"secondary\">\n\t\t\t\t\t\t\t\t\t\t{group.description}\n\t\t\t\t\t\t\t\t\t</Text>\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)}\n\t\t\t\t\t\t<ItemGroup className=\"workspace-nav--items gap-space-xs\">\n\t\t\t\t\t\t\t{group.items.map((item, index) => {\n\t\t\t\t\t\t\t\tconst active = item.id === activeId;\n\t\t\t\t\t\t\t\tconst status = getStatus(item, active);\n\t\t\t\t\t\t\t\tconst StatusIcon = STATUS_ICON[status];\n\t\t\t\t\t\t\t\tconst completion = item.completion === undefined ? undefined : clampPercent(item.completion);\n\t\t\t\t\t\t\t\tconst handleSelect = (event: React.MouseEvent<HTMLElement>) => {\n\t\t\t\t\t\t\t\t\tif (item.disabled) {\n\t\t\t\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tonSelect?.(item);\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\tconst context = { active, group, index, onSelect: handleSelect };\n\n\t\t\t\t\t\t\t\tif (renderItem) {\n\t\t\t\t\t\t\t\t\treturn <React.Fragment key={item.id}>{renderItem(item, context)}</React.Fragment>;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tconst rowContent = (\n\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t<ItemMedia variant=\"icon\" className={cn(active && 'text-accent-foreground')}>\n\t\t\t\t\t\t\t\t\t\t\t{item.icon ? (\n\t\t\t\t\t\t\t\t\t\t\t\t<DynamicWorkspaceIcon icon={item.icon} className=\"size-icon\" />\n\t\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t\t<StatusIcon className={cn('size-icon-md', STATUS_CLASS[status])} aria-hidden=\"true\" />\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t</ItemMedia>\n\t\t\t\t\t\t\t\t\t\t<ItemContent>\n\t\t\t\t\t\t\t\t\t\t\t<div className=\"flex items-center gap-space-sm\">\n\t\t\t\t\t\t\t\t\t\t\t\t<ItemTitle>{item.label}</ItemTitle>\n\t\t\t\t\t\t\t\t\t\t\t\t{active && (\n\t\t\t\t\t\t\t\t\t\t\t<Text tag=\"span\" size=\"inherit\" className=\"sr-only\">{strings.currentLabel}</Text>\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t{!!item.description && <ItemDescription clamp={2}>{item.description}</ItemDescription>}\n\t\t\t\t\t\t\t\t\t\t\t{completion !== undefined && (\n\t\t\t\t\t\t\t\t\t\t\t\t<div className=\"mt-1.5 flex items-center gap-space-md\">\n\t\t\t\t\t\t\t\t\t\t\t<Progress\n\t\t\t\t\t\t\t\t\t\t\t\tvalue={completion}\n\t\t\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\t\t\t\taria-label={strings.completionLabel(completion)}\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"flex-1\"\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<SecondaryValue size=\"xs\" className=\"tabular-nums\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{strings.completionLabel(completion)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</SecondaryValue>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t</ItemContent>\n\t\t\t\t\t\t\t\t\t\t{!!item.badge && <ItemActions>{item.badge}</ItemActions>}\n\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t\tconst itemClassName = cn(\n\t\t\t\t\t\t\t\t\t'workspace-nav--item w-full border border-transparent px-row-x py-row-y text-left transition-colors',\n\t\t\t\t\t\t\t\t\tactive && interactionRecipes.rowCurrent,\n\t\t\t\t\t\t\t\t\titem.warning && !active && cn(toneRecipes.warning.edge, toneRecipes.warning.wash),\n\t\t\t\t\t\t\t\t\titem.disabled && 'pointer-events-none opacity-50',\n\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t\tif (item.href) {\n\t\t\t\t\t\t\t\t\tconst linkNode = resolvedRenderLink({\n\t\t\t\t\t\t\t\t\t\thref: item.href,\n\t\t\t\t\t\t\t\t\t\tchildren: rowContent,\n\t\t\t\t\t\t\t\t\t\tclassName: 'block',\n\t\t\t\t\t\t\t\t\t\tactive,\n\t\t\t\t\t\t\t\t\t\tdisabled: item.disabled,\n\t\t\t\t\t\t\t\t\t\texternal: item.external,\n\t\t\t\t\t\t\t\t\t\ttarget: item.target,\n\t\t\t\t\t\t\t\t\t\trel: item.rel,\n\t\t\t\t\t\t\t\t\t\tonClick: handleSelect as React.MouseEventHandler<HTMLAnchorElement>,\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t<Item key={item.id} size=\"md\" render={linkNode as React.ReactElement} className={itemClassName}>\n\t\t\t\t\t\t\t\t\t\t\t{rowContent}\n\t\t\t\t\t\t\t\t\t\t</Item>\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<Item\n\t\t\t\t\t\t\t\t\t\tkey={item.id}\n\t\t\t\t\t\t\t\t\t\tsize=\"md\"\n\t\t\t\t\t\t\t\t\t\trender={<button type=\"button\" onClick={handleSelect} disabled={item.disabled} />}\n\t\t\t\t\t\t\t\t\t\tclassName={itemClassName}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{rowContent}\n\t\t\t\t\t\t\t\t\t</Item>\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t</ItemGroup>\n\t\t\t\t\t</Stack>\n\t\t\t\t))}\n\t\t\t</Stack>\n\t\t\t{!!footerSlot && <div className=\"workspace-nav--footer shrink-0 border-t border-border pt-space-lg\">{footerSlot}</div>}\n\t\t</Stack>\n\t);\n});\n\nWorkspaceNav.displayName = 'WorkspaceNav';\n\nexport const WorkspaceLocaleStrip = React.forwardRef<HTMLDivElement, WorkspaceLocaleStripProps>(function WorkspaceLocaleStrip({\n\tlocales,\n\tactiveLocale,\n\tonLocaleChange,\n\tactions,\n\tstatus,\n\tclassName,\n\tstrings: stringsProp,\n\t...props\n}, ref) {\n\tconst strings = useStrings(defaultWorkspaceLocaleStripStrings, stringsProp);\n\n\tconst handleLocaleClick = (locale: WorkspaceLocaleItem) => {\n\t\tif (locale.disabled) return;\n\t\tonLocaleChange?.(locale);\n\t};\n\n\treturn (\n\t\t<div\n\t\t\tref={ref}\n\t\t\tclassName={cn('workspace-locale-strip--component flex flex-col gap-space-lg border-t border-border bg-muted/50 px-surface-lg py-surface min-[64rem]:flex-row min-[64rem]:items-center min-[64rem]:justify-between', className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{/* The active locale is a selection, not a command: it lifts on the shared\n\t\t\t segmented track, so the strip's own primary action stays the only solid one. */}\n\t\t\t<Stack direction=\"horizontal\" wrap align=\"center\" gap=\"2xs\" className=\"workspace-locale-strip--locales w-fit min-w-0 max-w-full rounded-radius bg-muted p-space-2xs\" role=\"group\" aria-label={strings.ariaLabel}>\n\t\t\t\t{locales.map((locale) => {\n\t\t\t\t\tconst active = locale.id === activeLocale;\n\t\t\t\t\tconst completion = locale.completion === undefined ? undefined : clampPercent(locale.completion);\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tkey={locale.id}\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\t\tbuttonStyle=\"ghost\"\n\t\t\t\t\t\t\tonClick={() => handleLocaleClick(locale)}\n\t\t\t\t\t\t\tdisabled={locale.disabled}\n\t\t\t\t\t\t\taria-pressed={active}\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t'workspace-locale-strip--item justify-start',\n\t\t\t\t\t\t\t\tactive ? interactionRecipes.segmentActiveButton : interactionRecipes.segmentInactiveButton,\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Stack direction=\"horizontal\" align=\"center\" gap=\"md\" render={<span />} className=\"min-w-0\">\n\t\t\t\t\t\t\t<Text tag=\"span\" size=\"inherit\" className=\"truncate text-inherit\">{locale.label}</Text>\n\t\t\t\t\t\t\t{active && <Text tag=\"span\" size=\"inherit\" className=\"sr-only\">{strings.activeLabel}</Text>}\n\t\t\t\t\t\t\t\t{completion !== undefined && (\n\t\t\t\t\t\t\t\t\t<Badge tone={completion >= 100 ? 'success' : 'secondary'} className=\"shrink-0\">\n\t\t\t\t\t\t\t\t\t\t{strings.completionLabel(completion)}\n\t\t\t\t\t\t\t\t\t</Badge>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t{!!locale.status && <span className=\"shrink-0\">{locale.status}</span>}\n\t\t\t\t\t\t\t</Stack>\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</Stack>\n\t\t\t{!!(status || actions) && (\n\t\t\t\t<Stack direction=\"horizontal\" wrap align=\"center\" gap={compositionRhythm.commands} className=\"workspace-locale-strip--actions shrink-0\">\n\t\t\t\t\t{!!status && <div className=\"workspace-locale-strip--status\">{status}</div>}\n\t\t\t\t\t{!!actions && <Stack direction=\"horizontal\" wrap align=\"center\" gap={compositionRhythm.commands}>{actions}</Stack>}\n\t\t\t\t</Stack>\n\t\t\t)}\n\t\t</div>\n\t);\n});\n\nWorkspaceLocaleStrip.displayName = 'WorkspaceLocaleStrip';\n"],"mappings":"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"}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: themelia-react-ui-consumer
|
|
3
|
-
description: Compatibility entrypoint to Themelia's components, tokenization and
|
|
3
|
+
description: Compatibility entrypoint to Themelia's components, tokenization, composition and design capabilities for building and delivering React UI; not library maintenance.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Themelia React UI consumer
|
|
7
7
|
|
|
8
|
-
Use the
|
|
8
|
+
Use the four canonical capabilities:
|
|
9
9
|
|
|
10
10
|
- [themelia-components](../consumer-skills/themelia-components/SKILL.md): installed setup, search, exact API inspection, typed forms/features and framework integration.
|
|
11
|
-
- [themelia-tokenization](../consumer-skills/themelia-tokenization/SKILL.md): semantic themes, typography,
|
|
11
|
+
- [themelia-tokenization](../consumer-skills/themelia-tokenization/SKILL.md): domain structures with public parts, semantic JSX and token-backed Tailwind; shared themes, typography, spacing/density and portals.
|
|
12
12
|
- [themelia-composition](../consumer-skills/themelia-composition/SKILL.md): business hierarchy, custom compositions, responsive regions, interaction review and app delivery.
|
|
13
|
+
- [themelia-design](../consumer-skills/themelia-design/SKILL.md): reading records for what matters, view specs, encodings and emphasis, and rubric-scored critique of rendered screens. Its [designer agent](agents/themelia-ui-designer.md) builds or reviews whole views.
|
|
13
14
|
|
|
14
15
|
They share this folder's API/token metadata, scripts, references and typed examples.
|
|
15
16
|
Use [installation](references/installation.md) to resolve the installed package and
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: themelia-ui-designer
|
|
3
|
+
description: Product designer for apps built with themelia-react-ui. Delegate a new view, a redesign, or a screen that works but reads poorly; it reads the real records, writes a view spec, builds with public owners, renders 390 and 1440 wide in light and dark, scores a critique rubric and fixes. Ask for review mode to get a read-only, independent critique of existing screens.
|
|
4
|
+
model: inherit
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Themelia UI designer
|
|
8
|
+
|
|
9
|
+
You are a product designer who builds. Your result is a view that lets its user
|
|
10
|
+
decide quickly from real records, built with themelia-react-ui public owners and
|
|
11
|
+
app markup over its tokens. You remove before you add, spend emphasis on
|
|
12
|
+
purpose, and judge rendered screens rather than source.
|
|
13
|
+
|
|
14
|
+
## Inputs
|
|
15
|
+
|
|
16
|
+
The parent names the mode (`design` or `review`, default `design`), the routes
|
|
17
|
+
or files, where the records live, the dev server URL when one runs, and any
|
|
18
|
+
constraints. Ask the parent only when a decision depends on something the
|
|
19
|
+
records, the brief and the code cannot tell you.
|
|
20
|
+
|
|
21
|
+
## Load first
|
|
22
|
+
|
|
23
|
+
- `node_modules/themelia-react-ui/docs/consumer-skills/themelia-design/SKILL.md`
|
|
24
|
+
- `node_modules/themelia-react-ui/docs/consumer-skill/references/data-reading.md`
|
|
25
|
+
- `node_modules/themelia-react-ui/docs/consumer-skill/references/view-spec.md`
|
|
26
|
+
- `node_modules/themelia-react-ui/docs/consumer-skill/references/view-craft.md`
|
|
27
|
+
- `node_modules/themelia-react-ui/docs/consumer-skill/references/critique-rubric.md`
|
|
28
|
+
- `node_modules/themelia-react-ui/docs/consumer-skills/themelia-composition/SKILL.md`
|
|
29
|
+
for owners, surfaces and insets
|
|
30
|
+
- The app's `AGENTS.md` or `CLAUDE.md`: its rules win over this file.
|
|
31
|
+
|
|
32
|
+
## Design mode
|
|
33
|
+
|
|
34
|
+
1. **Read the data.** Open the records (fixtures, mocks, types, API samples).
|
|
35
|
+
Read a typical, a large, an exceptional and an empty record. Write the data
|
|
36
|
+
brief.
|
|
37
|
+
2. **Baseline.** If the view exists, render it and score the rubric before
|
|
38
|
+
changing anything. Keep these screenshots for the report.
|
|
39
|
+
3. **Spec.** Write the view spec where the parent says, otherwise
|
|
40
|
+
`design/<view>.md`. Rank information, name the focal point, draw 390 and
|
|
41
|
+
1440 wireframes, choose an encoding per fact.
|
|
42
|
+
4. **Owners.** Find and verify owners before JSX:
|
|
43
|
+
- `node node_modules/themelia-react-ui/docs/consumer-skill/scripts/find-components.mjs <task nouns>`
|
|
44
|
+
- `node node_modules/themelia-react-ui/docs/consumer-skill/scripts/map-composition.mjs --pattern record-detail|collection|edit|analytics --main <need> --aside <need>`
|
|
45
|
+
- `node node_modules/themelia-react-ui/docs/consumer-skill/scripts/inspect-component.mjs <Symbol> --import <exact import> --prop <name>`
|
|
46
|
+
- `node node_modules/themelia-react-ui/docs/consumer-skill/scripts/inspect-tokens.mjs <role or root>`
|
|
47
|
+
5. **One subject first.** Build one representative subject and render it at
|
|
48
|
+
both widths before repeating it.
|
|
49
|
+
6. **Build the view.** Change only the app files in scope and new app
|
|
50
|
+
components. Never edit `node_modules` or the package.
|
|
51
|
+
7. **Render.** Use the browser tool you have (built-in browser, Chrome or the
|
|
52
|
+
app's Playwright). Capture 390×844 and 1440×900 in light and dark, plus the
|
|
53
|
+
opened, error and accepted states the view supports. Wait for rendered state
|
|
54
|
+
instead of fixed delays. Run the rubric's census at each width.
|
|
55
|
+
Without a browser tool, stop here: return the render checklist (routes,
|
|
56
|
+
widths, themes, states) and mark appearance unverified. Never claim visual
|
|
57
|
+
quality without screenshots.
|
|
58
|
+
8. **Critique.** Score the rubric as a reviewer who did not build the view.
|
|
59
|
+
Write findings in the rubric's format.
|
|
60
|
+
9. **Fix.** Repair the lowest-scoring criterion at its owner, render again and
|
|
61
|
+
score again. Stop after three rounds and report what remains.
|
|
62
|
+
10. **Check.** Run the app's typecheck, lint, tests and build, and
|
|
63
|
+
`node node_modules/themelia-react-ui/docs/consumer-skill/scripts/check-composition.mjs <changed files>`.
|
|
64
|
+
Execute the callbacks, validation, focus and error/retry paths your change
|
|
65
|
+
touched.
|
|
66
|
+
|
|
67
|
+
## Review mode
|
|
68
|
+
|
|
69
|
+
Read-only: do not edit files. Load the same references. Read the records and
|
|
70
|
+
write your own data brief, render the routes and form your five-second answers
|
|
71
|
+
before reading any design notes; then compare intent with result. Return the
|
|
72
|
+
scores, findings and screenshots.
|
|
73
|
+
|
|
74
|
+
## Rules
|
|
75
|
+
|
|
76
|
+
- Real records only. No invented figures, trends or states; data gaps stay
|
|
77
|
+
visible and are reported.
|
|
78
|
+
- Public imports only. No anatomy class overrides, new colours or tokens, blur,
|
|
79
|
+
decorative icons, filler cards or prose explaining the screen.
|
|
80
|
+
- Do not add navigation, cards or commands because a prop allows them.
|
|
81
|
+
- Keep existing behaviour: every command still works, explains why it is
|
|
82
|
+
disabled, or is removed with a reason.
|
|
83
|
+
- Report a library limit by owner and prop with the workaround used.
|
|
84
|
+
|
|
85
|
+
## Report
|
|
86
|
+
|
|
87
|
+
1. Rubric scores before and after, per criterion, width and theme.
|
|
88
|
+
2. Screenshot paths for each width, theme and state.
|
|
89
|
+
3. The decisions that changed the view and why, including what was removed.
|
|
90
|
+
4. Checks and interactions run, with results.
|
|
91
|
+
5. Library gaps: owner, prop, workaround.
|
|
92
|
+
6. Unverified: widths, themes, states or interactions not exercised.
|
|
93
|
+
|
|
94
|
+
Keep measurements and screenshots separate from judgement: "the census shows 9
|
|
95
|
+
text levels in Purchased goods" is evidence; "the view is clearer" is a claim
|
|
96
|
+
that needs it.
|
|
@@ -4,7 +4,7 @@ import { SidebarTrigger } from 'themelia-react-ui/base/sidebar';
|
|
|
4
4
|
import { AppLayout, type AppLayoutVariant } from 'themelia-react-ui/layout/app-shell';
|
|
5
5
|
import { HeaderUserMenu, type HeaderUserMenuProps } from 'themelia-react-ui/layout/header';
|
|
6
6
|
import { Page, type PageProps } from 'themelia-react-ui/layout/page';
|
|
7
|
-
import { AppSidebar, LayoutSidebarProvider, SidebarNavigationUser, type AppSidebarProps } from 'themelia-react-ui/layout/sidebar';
|
|
7
|
+
import { AppSidebar, LayoutSidebarProvider, SidebarNavigationUser, type AppSidebarProps, type LayoutSidebarProviderProps } from 'themelia-react-ui/layout/sidebar';
|
|
8
8
|
import type { UIConfig } from 'themelia-react-ui/ui-provider';
|
|
9
9
|
import { Text } from 'themelia-react-ui/typography';
|
|
10
10
|
|
|
@@ -51,6 +51,57 @@ export function WorkspaceLayout({ variant = 'inset', sidebar, navigationGroups =
|
|
|
51
51
|
</LayoutSidebarProvider>;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
export interface WorkspaceRegionsLayoutProps {
|
|
55
|
+
/** Supply SidebarNavigationRail for a persistent area rail. */
|
|
56
|
+
primaryNavigation?: ReactNode;
|
|
57
|
+
sidebarPresentation?: 'panel' | 'rail';
|
|
58
|
+
navigationGroups?: AppSidebarProps['navigationGroups'];
|
|
59
|
+
contextualNavigationGroups?: AppSidebarProps['navigationGroups'];
|
|
60
|
+
/** Independent of shell/rail presentation: minimize to icons, hide, or stay expanded. */
|
|
61
|
+
contextualCollapsible?: AppSidebarProps['collapsible'];
|
|
62
|
+
/** A defined replacement wins over contextual groups; null removes the region. */
|
|
63
|
+
secondarySidebar?: ReactNode;
|
|
64
|
+
currentUrl?: string;
|
|
65
|
+
renderLink?: AppSidebarProps['renderLink'];
|
|
66
|
+
secondarySidebarWidth?: string;
|
|
67
|
+
openPanels?: LayoutSidebarProviderProps['openPanels'];
|
|
68
|
+
defaultOpenPanels?: LayoutSidebarProviderProps['defaultOpenPanels'];
|
|
69
|
+
onOpenPanelsChange?: LayoutSidebarProviderProps['onOpenPanelsChange'];
|
|
70
|
+
mobilePanel?: LayoutSidebarProviderProps['mobilePanel'];
|
|
71
|
+
onMobilePanelChange?: LayoutSidebarProviderProps['onMobilePanelChange'];
|
|
72
|
+
user?: HeaderUserMenuProps['user'];
|
|
73
|
+
onLogout?: () => void;
|
|
74
|
+
children?: ReactNode;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** One provider coordinates the primary area and adjacent contextual navigation. */
|
|
78
|
+
export function WorkspaceRegionsLayout({ primaryNavigation, sidebarPresentation = 'panel',
|
|
79
|
+
navigationGroups = {}, contextualNavigationGroups, contextualCollapsible = 'icon', secondarySidebar,
|
|
80
|
+
currentUrl, renderLink, secondarySidebarWidth,
|
|
81
|
+
openPanels, defaultOpenPanels = ['primary', 'secondary'], onOpenPanelsChange,
|
|
82
|
+
mobilePanel, onMobilePanelChange, user, onLogout, children }: WorkspaceRegionsLayoutProps) {
|
|
83
|
+
const hasContextualNavigation = secondarySidebar !== undefined
|
|
84
|
+
? secondarySidebar != null && secondarySidebar !== false : contextualNavigationGroups !== undefined;
|
|
85
|
+
return <LayoutSidebarProvider adaptTo="container" className="min-h-0"
|
|
86
|
+
navigationPanel={hasContextualNavigation ? 'secondary' : 'primary'}
|
|
87
|
+
openPanels={openPanels} defaultOpenPanels={defaultOpenPanels} onOpenPanelsChange={onOpenPanelsChange}
|
|
88
|
+
mobilePanel={mobilePanel} onMobilePanelChange={onMobilePanelChange}>
|
|
89
|
+
<AppLayout variant="light-header" contentSurface="inset" className="h-svh min-h-0"
|
|
90
|
+
logo={<Text weight="semibold">Admin</Text>} sidebarTrigger={<SidebarTrigger />}
|
|
91
|
+
sidebarPresentation={sidebarPresentation}
|
|
92
|
+
mobileSidebarMode={sidebarPresentation === 'rail' ? 'inline' : 'drawer'}
|
|
93
|
+
secondarySidebarWidth={secondarySidebarWidth}
|
|
94
|
+
slots={{
|
|
95
|
+
headerEnd: user && <HeaderUserMenu user={user} onLogout={onLogout} />,
|
|
96
|
+
sidebar: primaryNavigation ?? <AppSidebar className="h-full" surface="transparent" menuDensity="comfortable"
|
|
97
|
+
navigationGroups={navigationGroups} currentUrl={currentUrl} renderLink={renderLink} />,
|
|
98
|
+
secondarySidebar: hasContextualNavigation ? secondarySidebar !== undefined ? secondarySidebar : <AppSidebar className="h-full" surface="transparent"
|
|
99
|
+
collapsible={contextualCollapsible} menuDensity="comfortable" searchable
|
|
100
|
+
navigationGroups={contextualNavigationGroups} currentUrl={currentUrl} renderLink={renderLink} /> : undefined,
|
|
101
|
+
}}>{children}</AppLayout>
|
|
102
|
+
</LayoutSidebarProvider>;
|
|
103
|
+
}
|
|
104
|
+
|
|
54
105
|
export interface WorkspaceExamplePageProps {
|
|
55
106
|
onCreate: () => void;
|
|
56
107
|
narrow?: boolean;
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import { CreditCard, FileText, Send } from 'lucide-react';
|
|
2
|
+
import { Badge } from 'themelia-react-ui/base/badge';
|
|
3
|
+
import { Card } from 'themelia-react-ui/base/cards';
|
|
4
|
+
import { Alert, AlertDescription, AlertTitle } from 'themelia-react-ui/base/feedback';
|
|
5
|
+
import { Stack } from 'themelia-react-ui/base/structure';
|
|
6
|
+
import {
|
|
7
|
+
AddressCard,
|
|
8
|
+
AmountRow,
|
|
9
|
+
FulfillmentGroup,
|
|
10
|
+
InvoiceHeader,
|
|
11
|
+
InvoiceLineItems,
|
|
12
|
+
OrderCustomer,
|
|
13
|
+
OrderLineItem,
|
|
14
|
+
OrderSummary,
|
|
15
|
+
OrderTimeline,
|
|
16
|
+
OrderTransactions,
|
|
17
|
+
PaymentTimeline,
|
|
18
|
+
ShipmentTracking,
|
|
19
|
+
SummaryPanel,
|
|
20
|
+
type InvoiceColumn,
|
|
21
|
+
type InvoiceLineItem,
|
|
22
|
+
} from 'themelia-react-ui/blocks/commerce';
|
|
23
|
+
import { Page } from 'themelia-react-ui/layout/page';
|
|
24
|
+
import { Money, Number as NumberValue } from 'themelia-react-ui/primitives';
|
|
25
|
+
import { Text } from 'themelia-react-ui/typography';
|
|
26
|
+
|
|
27
|
+
/** Mock accepted order values; the app owns tax, shipping and price calculations. */
|
|
28
|
+
export function SoldProductWithSummary() {
|
|
29
|
+
return (
|
|
30
|
+
<Card title="Items and totals">
|
|
31
|
+
<Stack gap="xl">
|
|
32
|
+
<OrderLineItem
|
|
33
|
+
id="mug-sand-350"
|
|
34
|
+
title="Ceramic mug"
|
|
35
|
+
variantTitle="350 ml / Sand"
|
|
36
|
+
sku="MUG-350-SAND"
|
|
37
|
+
unitPrice="€18.00"
|
|
38
|
+
quantity={2}
|
|
39
|
+
total="€36.00"
|
|
40
|
+
/>
|
|
41
|
+
<SummaryPanel>
|
|
42
|
+
<AmountRow label="Subtotal" amount="€36.00" />
|
|
43
|
+
<AmountRow label="Shipping" amount="€6.50" />
|
|
44
|
+
<AmountRow label="Tax" note="20%" amount="€8.50" />
|
|
45
|
+
<AmountRow label="Grand total" amount="€51.00" total rollup />
|
|
46
|
+
</SummaryPanel>
|
|
47
|
+
</Stack>
|
|
48
|
+
</Card>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Custom JSX values keep their roles: quiet regular breakdown, bold financial total. */
|
|
53
|
+
export function CustomServiceInvoice() {
|
|
54
|
+
// Custom columns replace the default four-column/mobile recipe with this two-column grid.
|
|
55
|
+
const serviceColumns: InvoiceColumn<InvoiceLineItem>[] = [
|
|
56
|
+
{
|
|
57
|
+
id: 'service',
|
|
58
|
+
header: 'Service',
|
|
59
|
+
width: 'minmax(0, 1fr)',
|
|
60
|
+
cell: (item) => (
|
|
61
|
+
<Stack gap="xs">
|
|
62
|
+
<Text type="inherit" className="wrap-anywhere">{item.description}</Text>
|
|
63
|
+
<Text tag="span" size="xs" type="secondary">
|
|
64
|
+
<NumberValue value={item.qty} /> × <Money amount={item.price} currency="EUR" />
|
|
65
|
+
</Text>
|
|
66
|
+
</Stack>
|
|
67
|
+
),
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
id: 'line-total',
|
|
71
|
+
header: 'Line total',
|
|
72
|
+
width: 'max-content',
|
|
73
|
+
align: 'right',
|
|
74
|
+
cell: (item) => <Money type="inherit" amount={item.total} currency="EUR" weight="regular" />,
|
|
75
|
+
},
|
|
76
|
+
];
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<InvoiceLineItems
|
|
80
|
+
items={[
|
|
81
|
+
{ description: 'Design services', qty: 1, price: 335, total: 335 },
|
|
82
|
+
{ description: 'Research workshop', qty: 2, price: 380, total: 760 },
|
|
83
|
+
{ description: 'Implementation support', qty: 3, price: 425, total: 1275 },
|
|
84
|
+
]}
|
|
85
|
+
columns={serviceColumns}
|
|
86
|
+
footerRows={[
|
|
87
|
+
{ label: 'Subtotal', value: <Money type="inherit" amount={2370} currency="EUR" weight="regular" /> },
|
|
88
|
+
{ label: 'VAT (20%)', value: <Money type="inherit" amount={474} currency="EUR" weight="regular" /> },
|
|
89
|
+
// emphasis controls the label/spacing; this React-node value owns its weight.
|
|
90
|
+
{ label: 'Invoice total', value: <Money type="inherit" amount={2844} currency="EUR" weight="bold" />, emphasis: 'total' },
|
|
91
|
+
]}
|
|
92
|
+
/>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export interface OrderFulfillmentDetailProps {
|
|
97
|
+
/** Requests fulfillment of the open group; the app accepts and reloads the order. */
|
|
98
|
+
onFulfill: () => void;
|
|
99
|
+
onPrintPackingSlip: () => void;
|
|
100
|
+
/** Opens the app's refund workflow, for example in an ActionDrawer. */
|
|
101
|
+
onRefund: () => void;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* One order route: Page owns the heading and commands, each subject is framed
|
|
106
|
+
* once, and the buyer and payment ledger sit in the aside. Mock accepted values.
|
|
107
|
+
*/
|
|
108
|
+
export function OrderFulfillmentDetail({ onFulfill, onPrintPackingSlip, onRefund }: OrderFulfillmentDetailProps) {
|
|
109
|
+
return (
|
|
110
|
+
<Page
|
|
111
|
+
header={{
|
|
112
|
+
title: 'Order #1042',
|
|
113
|
+
slots: { titleSuffix: <><Badge tone="warning">Partially fulfilled</Badge><Badge tone="success">Paid</Badge></> },
|
|
114
|
+
primaryAction: { label: 'Fulfill items', onClick: onFulfill },
|
|
115
|
+
secondaryActions: [{ label: 'Print packing slip', onClick: onPrintPackingSlip }, { label: 'Refund', onClick: onRefund }],
|
|
116
|
+
}}
|
|
117
|
+
aside={(
|
|
118
|
+
<>
|
|
119
|
+
<OrderCustomer
|
|
120
|
+
surface="card"
|
|
121
|
+
name="Ava Chen"
|
|
122
|
+
email="ava.chen@example.com"
|
|
123
|
+
orderCount={4}
|
|
124
|
+
shippingAddress={{ name: 'Ava Chen', line1: '18 Ermou Street', city: 'Athens', postalCode: '105 63', country: 'Greece' }}
|
|
125
|
+
billingSameAsShipping
|
|
126
|
+
/>
|
|
127
|
+
<OrderSummary
|
|
128
|
+
surface="card"
|
|
129
|
+
goods={[{ label: 'Subtotal', amount: '€104.00' }, { label: 'Shipping', amount: '€6.50' }]}
|
|
130
|
+
total={{ label: 'Total', amount: '€110.50' }}
|
|
131
|
+
payments={[{ label: 'Paid by card', amount: '€110.50' }]}
|
|
132
|
+
paymentStatus="paid"
|
|
133
|
+
/>
|
|
134
|
+
<OrderTransactions
|
|
135
|
+
surface="card"
|
|
136
|
+
transactions={[
|
|
137
|
+
{ id: 'auth', kind: 'authorization', status: 'success', amount: '€110.50', processedAt: '12 Oct, 09:14', method: 'Visa •••• 4242' },
|
|
138
|
+
{ id: 'capture', kind: 'capture', status: 'success', amount: '€110.50', processedAt: '12 Oct, 09:15', reference: 'ch_3PqL2x' },
|
|
139
|
+
]}
|
|
140
|
+
/>
|
|
141
|
+
</>
|
|
142
|
+
)}
|
|
143
|
+
>
|
|
144
|
+
<Alert tone="warning">
|
|
145
|
+
<AlertTitle>Confirm the delivery address</AlertTitle>
|
|
146
|
+
<AlertDescription>The courier flagged the postal code; confirm it with the customer before the Athens parcel ships.</AlertDescription>
|
|
147
|
+
</Alert>
|
|
148
|
+
<FulfillmentGroup
|
|
149
|
+
status="unfulfilled"
|
|
150
|
+
location="Athens warehouse"
|
|
151
|
+
items={[{ id: 'shirt', title: 'Linen overshirt', variantTitle: 'Navy / M', sku: 'LIN-OVR-NVY-M', unitPrice: '€68.00', quantity: 1, total: '€68.00' }]}
|
|
152
|
+
actions={[{ id: 'fulfill', label: 'Fulfill items', onClick: onFulfill }, { id: 'slip', label: 'Print packing slip', onClick: onPrintPackingSlip }]}
|
|
153
|
+
/>
|
|
154
|
+
<FulfillmentGroup
|
|
155
|
+
status="fulfilled"
|
|
156
|
+
location="Thessaloniki store"
|
|
157
|
+
items={[{ id: 'mug', title: 'Stoneware mug', variantTitle: 'Salt', sku: 'MUG-STW-SALT', unitPrice: '€18.00', quantity: 2, total: '€36.00' }]}
|
|
158
|
+
/>
|
|
159
|
+
<ShipmentTracking
|
|
160
|
+
surface="card"
|
|
161
|
+
carrier="ACS Courier"
|
|
162
|
+
trackingNumber="7781 2290 114"
|
|
163
|
+
status="in_transit"
|
|
164
|
+
steps={[
|
|
165
|
+
{ label: 'Label created', done: true, timestamp: '12 Oct, 11:02' },
|
|
166
|
+
{ label: 'Picked up', done: true, timestamp: '12 Oct, 16:40' },
|
|
167
|
+
{ label: 'Out for delivery', done: false },
|
|
168
|
+
{ label: 'Delivered', done: false },
|
|
169
|
+
]}
|
|
170
|
+
/>
|
|
171
|
+
{/* OrderTimeline owns its title; the Card only frames it. */}
|
|
172
|
+
<Card>
|
|
173
|
+
<OrderTimeline
|
|
174
|
+
title="History"
|
|
175
|
+
events={[
|
|
176
|
+
{ id: 'placed', title: 'Order placed', timestamp: '12 Oct, 09:14', status: 'completed' },
|
|
177
|
+
{ id: 'shipped', title: 'Mugs shipped from Thessaloniki', timestamp: '12 Oct, 16:40', status: 'completed' },
|
|
178
|
+
{ id: 'athens', title: 'Overshirt awaiting fulfillment', timestamp: 'Now', status: 'current' },
|
|
179
|
+
]}
|
|
180
|
+
/>
|
|
181
|
+
</Card>
|
|
182
|
+
</Page>
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export interface ReceivableInvoiceDetailProps {
|
|
187
|
+
onRecordPayment: () => void;
|
|
188
|
+
onSendReminder: () => void;
|
|
189
|
+
onApplyCredit: () => void;
|
|
190
|
+
onExportPdf: () => void;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* One invoice route: the document Card is the only frame around its header,
|
|
195
|
+
* flat line items and ledger; settlement and history are separate subjects.
|
|
196
|
+
* Long secondary labels stay in the More actions menu beside the primary command.
|
|
197
|
+
*/
|
|
198
|
+
export function ReceivableInvoiceDetail({ onRecordPayment, onSendReminder, onApplyCredit, onExportPdf }: ReceivableInvoiceDetailProps) {
|
|
199
|
+
return (
|
|
200
|
+
<Page
|
|
201
|
+
header={{
|
|
202
|
+
title: 'INV-2026-118',
|
|
203
|
+
slots: { titleSuffix: <Badge tone="destructive">Overdue</Badge> },
|
|
204
|
+
primaryAction: { label: 'Record payment', onClick: onRecordPayment },
|
|
205
|
+
secondaryActions: [
|
|
206
|
+
{ label: 'Send reminder', onClick: onSendReminder },
|
|
207
|
+
{ label: 'Apply approved credit', onClick: onApplyCredit },
|
|
208
|
+
{ label: 'Export PDF', onClick: onExportPdf },
|
|
209
|
+
],
|
|
210
|
+
maxVisibleSecondaryActions: 1,
|
|
211
|
+
}}
|
|
212
|
+
aside={(
|
|
213
|
+
<>
|
|
214
|
+
<Card title="Settlement">
|
|
215
|
+
<SummaryPanel>
|
|
216
|
+
<AmountRow label="Invoice total" amount="€2,199.76" />
|
|
217
|
+
<AmountRow label="Bank transfer, 14 Oct" amount="€1,000.00" deduction />
|
|
218
|
+
<AmountRow label="Balance due" amount="€1,199.76" total rollup />
|
|
219
|
+
</SummaryPanel>
|
|
220
|
+
</Card>
|
|
221
|
+
<AddressCard
|
|
222
|
+
surface="card"
|
|
223
|
+
kind="billing"
|
|
224
|
+
name="Kalliope Studio IKE"
|
|
225
|
+
line1="42 Tsimiski Street"
|
|
226
|
+
city="Thessaloniki"
|
|
227
|
+
postalCode="546 23"
|
|
228
|
+
country="Greece"
|
|
229
|
+
/>
|
|
230
|
+
</>
|
|
231
|
+
)}
|
|
232
|
+
>
|
|
233
|
+
<Card>
|
|
234
|
+
<Stack gap="2xl">
|
|
235
|
+
<InvoiceHeader
|
|
236
|
+
invoiceNumber="INV-2026-118"
|
|
237
|
+
status="overdue"
|
|
238
|
+
from={{ name: 'Ledgerline Accounting', location: 'Athens' }}
|
|
239
|
+
to={{ name: 'Kalliope Studio IKE', location: 'Thessaloniki' }}
|
|
240
|
+
issuedDate="12 Oct 2026"
|
|
241
|
+
dueDate="26 Oct 2026"
|
|
242
|
+
amount="€1,199.76"
|
|
243
|
+
/>
|
|
244
|
+
<InvoiceLineItems
|
|
245
|
+
surface="flat"
|
|
246
|
+
currency="EUR"
|
|
247
|
+
items={[
|
|
248
|
+
{ description: 'Quarterly bookkeeping retainer, July to September 2026', qty: 1, price: 1275, total: 1275 },
|
|
249
|
+
{ description: 'Payroll processing (per employee)', qty: 14, price: 18.5, total: 259 },
|
|
250
|
+
{ description: 'VAT return preparation', qty: 1, price: 240, total: 240 },
|
|
251
|
+
]}
|
|
252
|
+
footerRows={[
|
|
253
|
+
{ label: 'Subtotal', value: <Money type="inherit" amount={1774} currency="EUR" weight="regular" /> },
|
|
254
|
+
{ label: 'VAT (24%)', value: <Money type="inherit" amount={425.76} currency="EUR" weight="regular" /> },
|
|
255
|
+
{ label: 'Invoice total', value: <Money type="inherit" amount={2199.76} currency="EUR" weight="bold" />, emphasis: 'total' },
|
|
256
|
+
]}
|
|
257
|
+
/>
|
|
258
|
+
</Stack>
|
|
259
|
+
</Card>
|
|
260
|
+
<Card title="Payment history">
|
|
261
|
+
<PaymentTimeline
|
|
262
|
+
events={[
|
|
263
|
+
{ label: 'Invoice issued', date: '12 Oct', icon: FileText, done: true },
|
|
264
|
+
{ label: 'Partial payment received', date: '14 Oct', amount: '€1,000.00', icon: CreditCard, done: true },
|
|
265
|
+
{ label: 'Reminder due', date: '28 Oct', icon: Send, done: false },
|
|
266
|
+
]}
|
|
267
|
+
/>
|
|
268
|
+
</Card>
|
|
269
|
+
</Page>
|
|
270
|
+
);
|
|
271
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import { Stack } from 'themelia-react-ui/base/structure';
|
|
3
|
+
import { InlineStat } from 'themelia-react-ui/blocks/data-display';
|
|
4
|
+
import { Money } from 'themelia-react-ui/primitives';
|
|
5
|
+
|
|
6
|
+
/** Card-free app content: its parent owns the subject title and any surface. */
|
|
7
|
+
export function AssessmentComparison({declared, assessed, currency, labels, actions}: {
|
|
8
|
+
declared: number;
|
|
9
|
+
assessed: number;
|
|
10
|
+
currency: string;
|
|
11
|
+
labels: {declared: string; assessed: string};
|
|
12
|
+
actions?: ReactNode;
|
|
13
|
+
}) {
|
|
14
|
+
return <Stack gap="xl" className="@container min-w-0">
|
|
15
|
+
<div className="grid min-w-0 grid-cols-1 gap-space-xl @lg:grid-cols-2">
|
|
16
|
+
<InlineStat layout="stacked" label={labels.declared} value={<Money amount={declared} currency={currency} />} />
|
|
17
|
+
<InlineStat layout="stacked" label={labels.assessed} value={<Money amount={assessed} currency={currency} />} />
|
|
18
|
+
</div>
|
|
19
|
+
{actions && <Stack direction="horizontal" justify="end" gap="md">{actions}</Stack>}
|
|
20
|
+
</Stack>;
|
|
21
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useState, type ReactNode } from 'react';
|
|
2
|
+
import { Badge } from 'themelia-react-ui/base/badge';
|
|
2
3
|
import { Button } from 'themelia-react-ui/base/buttons';
|
|
3
4
|
import { Card } from 'themelia-react-ui/base/cards';
|
|
4
5
|
import { MetadataList } from 'themelia-react-ui/base/metadata-list';
|
|
@@ -21,7 +22,7 @@ export interface AccountDetailProps {
|
|
|
21
22
|
|
|
22
23
|
/** One framed subject for a drawer or dashboard: one quick control, no page chrome. */
|
|
23
24
|
export function AccountDetail({ account, onEdit }: AccountDetailProps) {
|
|
24
|
-
return <Card title={account.name}
|
|
25
|
+
return <Card title={account.name}
|
|
25
26
|
headerAction={<Button onClick={() => onEdit(account.id)}>Edit</Button>}>
|
|
26
27
|
<AccountFacts account={account}/>
|
|
27
28
|
</Card>;
|
|
@@ -52,9 +53,9 @@ export function AccountDetailPage({ account, onEdit, onBack, section, onSectionC
|
|
|
52
53
|
{ label: 'Send statement', onClick: () => onSendStatement(account.id) },
|
|
53
54
|
{ label: 'Delete account', destructive: true, onClick: () => { setError(undefined); deletion.show(); } },
|
|
54
55
|
];
|
|
55
|
-
return <Page header={{
|
|
56
|
+
return <Page narrow header={{
|
|
56
57
|
title: account.name, onBack, backLabel: 'Back to accounts',
|
|
57
|
-
|
|
58
|
+
slots: { titleSuffix: account.overdue ? <Badge tone="warning">Overdue</Badge> : null },
|
|
58
59
|
primaryAction: { label: 'Edit account', onClick: () => onEdit(account.id) },
|
|
59
60
|
secondaryActions: commands,
|
|
60
61
|
tabs: {
|
|
@@ -68,7 +69,7 @@ export function AccountDetailPage({ account, onEdit, onBack, section, onSectionC
|
|
|
68
69
|
},
|
|
69
70
|
}}>
|
|
70
71
|
{section === 'overview'
|
|
71
|
-
? <Card title="Contact and billing"
|
|
72
|
+
? <Card title="Contact and billing"><AccountFacts account={account}/></Card>
|
|
72
73
|
: children}
|
|
73
74
|
<ConfirmDialog {...deletion.overlayProps} destructive
|
|
74
75
|
title={`Delete ${account.name}?`} description="This permanently removes the account."
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from 'themelia-react-ui/base/accordion';
|
|
3
|
+
import { Badge } from 'themelia-react-ui/base/badge';
|
|
4
|
+
import { Stack } from 'themelia-react-ui/base/structure';
|
|
5
|
+
import { Heading, Text } from 'themelia-react-ui/typography';
|
|
6
|
+
|
|
7
|
+
export interface EditableSection {
|
|
8
|
+
id: string;
|
|
9
|
+
title: string;
|
|
10
|
+
content: ReactNode;
|
|
11
|
+
/** App-localized validation status, e.g. "2 errors"; omit when valid. */
|
|
12
|
+
validationMessage?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** Place inside the app's one form. Closing a panel retains the same field DOM. */
|
|
16
|
+
export function EditableSections({title, sections, openSections, onOpenSectionsChange}: {
|
|
17
|
+
title: string;
|
|
18
|
+
sections: EditableSection[];
|
|
19
|
+
openSections: string[];
|
|
20
|
+
onOpenSectionsChange: (values: string[]) => void;
|
|
21
|
+
}) {
|
|
22
|
+
return <Stack gap="xl">
|
|
23
|
+
<Heading tag="h2" size="base">{title}</Heading>
|
|
24
|
+
<Accordion multiple value={openSections} onValueChange={onOpenSectionsChange} aria-label={title}>
|
|
25
|
+
{sections.map(section => <AccordionItem key={section.id} value={section.id}>
|
|
26
|
+
<AccordionTrigger>
|
|
27
|
+
<Stack render={<span />} direction="horizontal" gap="md" className="min-w-0">
|
|
28
|
+
<Text tag="span" size="inherit" type="inherit" weight="medium">{section.title}</Text>
|
|
29
|
+
{section.validationMessage && <>{' '}<Badge tone="destructive">{section.validationMessage}</Badge></>}
|
|
30
|
+
</Stack>
|
|
31
|
+
</AccordionTrigger>
|
|
32
|
+
<AccordionContent keepMounted>
|
|
33
|
+
<Stack gap="xl">{section.content}</Stack>
|
|
34
|
+
</AccordionContent>
|
|
35
|
+
</AccordionItem>)}
|
|
36
|
+
</Accordion>
|
|
37
|
+
</Stack>;
|
|
38
|
+
}
|