themelia-ui 3.0.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/themelia-ui/SKILL.md +60 -33
- package/.agents/skills/themelia-ui/manifest.json +23 -0
- package/.agents/skills/themelia-ui/references/api-compatibility.md +5 -4
- package/.agents/skills/themelia-ui/references/blocks.md +123 -0
- package/.agents/skills/themelia-ui/references/composition-ladder.md +8 -8
- package/.agents/skills/themelia-ui/references/composition.md +100 -19
- package/.agents/skills/themelia-ui/references/forms.md +23 -3
- package/.agents/skills/themelia-ui/references/framework-wiring.md +41 -13
- package/.agents/skills/themelia-ui/references/i18n.md +4 -2
- package/.agents/skills/themelia-ui/references/imports.md +104 -104
- package/.agents/skills/themelia-ui/references/installation.md +60 -31
- package/.agents/skills/themelia-ui/references/migration.md +156 -5
- package/.agents/skills/themelia-ui/references/provider-and-scoping.md +37 -25
- package/.agents/skills/themelia-ui/references/reference-workflows.md +43 -0
- package/.agents/skills/themelia-ui/references/structure-and-spacing.md +147 -0
- package/.agents/skills/themelia-ui/references/theming.md +174 -131
- package/.agents/skills/themelia-ui/references/troubleshooting.md +88 -30
- package/.agents/skills/themelia-ui/references/verification.md +60 -5
- package/CHANGELOG.md +212 -0
- package/README.md +48 -60
- package/dist/accordion-CHuzMmWL.js +143 -0
- package/dist/{action-menu-BNLURfMK.js → action-menu-BwiL_F6I.js} +35 -33
- package/dist/{alert-dialog-BMVo6Z-8.js → alert-dialog-Cg2HhuBe.js} +1 -1
- package/dist/avatar-Dc_BNYfB.js +93 -0
- package/dist/badge-VlJVZjdm.js +45 -0
- package/dist/base/accordion.js +1 -1
- package/dist/base/action-menu.js +1 -1
- package/dist/base/alert-dialog.js +1 -1
- package/dist/base/aspect-ratio.js +3 -1
- package/dist/base/avatar.js +1 -1
- package/dist/base/badge.js +2 -2
- package/dist/base/batch-action-bar.js +1 -1
- package/dist/base/buttons.js +1 -1
- package/dist/base/cards.js +1 -1
- package/dist/base/carousel.js +6 -4
- package/dist/base/chart.js +1 -1
- package/dist/base/choice-inputs.js +1 -1
- package/dist/base/combobox.js +1 -1
- package/dist/base/command.js +1 -1
- package/dist/base/context-menu.js +22 -21
- package/dist/base/copyable.js +1 -1
- package/dist/base/date-pickers.js +1 -1
- package/dist/base/dialog.js +1 -1
- package/dist/base/display.js +1 -1
- package/dist/base/dropdown-menu.js +1 -1
- package/dist/base/feedback.js +1 -1
- package/dist/base/forms-numeric.js +1 -1
- package/dist/base/forms.js +1 -1
- package/dist/base/hover-card.js +26 -23
- package/dist/base/input-group.js +1 -1
- package/dist/base/item.js +1 -1
- package/dist/base/label.js +1 -1
- package/dist/base/menubar.js +20 -14
- package/dist/base/navigation-menu.js +47 -38
- package/dist/base/navigation.js +1 -1
- package/dist/base/otp-input.js +36 -30
- package/dist/base/overlay.js +1 -1
- package/dist/base/popover-menu.js +1 -1
- package/dist/base/popover.js +1 -1
- package/dist/base/qr-code.js +51 -47
- package/dist/base/repeaters.js +1 -1
- package/dist/base/resizable.js +2 -0
- package/dist/base/sheet.js +1 -1
- package/dist/base/sidebar.js +1 -1
- package/dist/base/skeleton.js +1 -1
- package/dist/base/spinner.js +1 -1
- package/dist/base/structure.js +1 -1
- package/dist/base/table.js +1 -1
- package/dist/base/text-inputs.js +1 -1
- package/dist/base/timeline.js +1 -1
- package/dist/base/toaster.js +1 -1
- package/dist/base/toggle.js +21 -15
- package/dist/base/toolbar.js +1 -1
- package/dist/base/tooltip.js +1 -1
- package/dist/base/typography.js +2 -2
- package/dist/base/upload.js +1 -1
- package/dist/base/value-inputs.js +1 -1
- package/dist/{batch-action-bar-BZYNKXdV.js → batch-action-bar-DZVMVW83.js} +11 -8
- package/dist/{admin/patterns → blocks/admin}/access.js +79 -76
- package/dist/blocks/admin/commerce.js +2493 -0
- package/dist/{patterns → blocks}/analytics.js +312 -303
- package/dist/{patterns → blocks}/onboarding.js +27 -23
- package/dist/{patterns → blocks}/timelines.js +1 -1
- package/dist/buttons-BX2JfL5X.js +173 -0
- package/dist/cards-Ddhz43Bz.js +279 -0
- package/dist/chart-BkK3Xm10.js +201 -0
- package/dist/choice-inputs-NwRxvmZN.js +694 -0
- package/dist/combobox-519ubijc.js +292 -0
- package/dist/command-JjApYFds.js +156 -0
- package/dist/comments-CCQ2QRaU.js +1443 -0
- package/dist/components/base/action-menu/action-menu.d.ts +1 -1
- package/dist/components/base/action-menu/action-menu.types.d.ts +2 -2
- package/dist/components/base/avatar/avatar.d.ts +5 -2
- package/dist/components/base/badge/badge.d.ts +10 -10
- package/dist/components/base/badge/badge.variants.d.ts +1 -2
- package/dist/components/base/badge/index.d.ts +1 -2
- package/dist/components/base/buttons/button.d.ts +9 -8
- package/dist/components/base/buttons/button.types.d.ts +2 -2
- package/dist/components/base/buttons/index.d.ts +1 -1
- package/dist/components/base/buttons/text-button.d.ts +1 -1
- package/dist/components/base/cards/card-actions.d.ts +1 -1
- package/dist/components/base/cards/card.d.ts +3 -1
- package/dist/components/base/cards/partials/card-header.d.ts +2 -1
- package/dist/components/base/choice-inputs/choice.types.d.ts +2 -2
- package/dist/components/base/choice-inputs/partials/choice-parts.d.ts +3 -3
- package/dist/components/base/command/command.d.ts +5 -2
- package/dist/components/base/display/icon-badge.d.ts +5 -3
- package/dist/components/base/display/index.d.ts +1 -1
- package/dist/components/base/display/metadata-list.d.ts +6 -6
- package/dist/components/base/display/metadata-value.d.ts +1 -1
- package/dist/components/base/display/separator.d.ts +2 -2
- package/dist/components/base/feedback/alert.d.ts +3 -2
- package/dist/components/base/feedback/empty.d.ts +5 -4
- package/dist/components/base/feedback/progress-circle.d.ts +2 -2
- package/dist/components/base/feedback/progress.d.ts +3 -1
- package/dist/components/base/forms/form-field.d.ts +2 -2
- package/dist/components/base/input-group/input-group.d.ts +8 -10
- package/dist/components/base/item/item.d.ts +2 -2
- package/dist/components/base/overlay/index.d.ts +1 -1
- package/dist/components/base/overlay/overlay.types.d.ts +7 -5
- package/dist/components/base/qr-code/qr-code.d.ts +4 -4
- package/dist/components/base/sheet/sheet.d.ts +1 -1
- package/dist/components/base/sidebar/sidebar.d.ts +9 -13
- package/dist/components/base/spinner/spinner.d.ts +2 -2
- package/dist/components/base/structure/adaptive-grid.d.ts +3 -3
- package/dist/components/base/structure/bleed.d.ts +4 -2
- package/dist/components/base/structure/grid.d.ts +10 -4
- package/dist/components/base/structure/index.d.ts +1 -1
- package/dist/components/base/structure/split.d.ts +4 -3
- package/dist/components/base/structure/stack.d.ts +5 -5
- package/dist/components/base/structure/structure.maps.d.ts +2 -1
- package/dist/components/base/structure/structure.types.d.ts +10 -4
- package/dist/components/base/toggle/toggle.d.ts +2 -2
- package/dist/components/base/toolbar/toolbar.d.ts +3 -3
- package/dist/components/base/typography/index.d.ts +2 -0
- package/dist/components/base/typography/rich-text/rich-text.variants.d.ts +9 -0
- package/dist/components/base/typography/text/index.d.ts +1 -0
- package/dist/components/base/typography/text/text.d.ts +15 -8
- package/dist/components/base/typography/text/text.variants.d.ts +41 -0
- package/dist/components/base/value-inputs/color-input.d.ts +1 -7
- package/dist/components/base/value-inputs/slider.d.ts +2 -7
- package/dist/components/{admin/patterns → blocks/admin}/commerce/vendor-profile.d.ts +2 -1
- package/dist/components/{patterns → blocks}/analytics/analytics.strings.d.ts +2 -5
- package/dist/components/features/actions/action-adapters.d.ts +3 -3
- package/dist/components/features/actions/actions.types.d.ts +3 -5
- package/dist/components/features/actions/index.d.ts +1 -1
- package/dist/components/features/activities/activities-feed.d.ts +1 -1
- package/dist/components/features/activities/activities.types.d.ts +4 -4
- package/dist/components/features/activities/activity-parts.d.ts +3 -3
- package/dist/components/features/activities/activity-row.d.ts +4 -4
- package/dist/components/features/activities/index.d.ts +1 -1
- package/dist/components/features/ai-chat/ai-chat.types.d.ts +10 -3
- package/dist/components/features/ai-chat/ai-message-surfaces.d.ts +1 -1
- package/dist/components/features/ai-chat/ai-work-surfaces.d.ts +1 -1
- package/dist/components/features/combobox/combobox.strings.d.ts +2 -2
- package/dist/components/features/combobox/fetching-combobox.d.ts +2 -1
- package/dist/components/features/combobox/resource-combobox.d.ts +3 -0
- package/dist/components/features/combobox/use-suggestions.d.ts +7 -0
- package/dist/components/features/event-calendar/event-calendar.types.d.ts +3 -0
- package/dist/components/features/media-library/index.d.ts +1 -1
- package/dist/components/features/media-library/media-library-parts.d.ts +4 -3
- package/dist/components/features/media-library/media-library-views.d.ts +4 -3
- package/dist/components/features/media-library/media-library.d.ts +1 -1
- package/dist/components/features/media-library/media-library.strings.d.ts +12 -13
- package/dist/components/features/media-library/media-library.types.d.ts +11 -9
- package/dist/components/features/media-library/media-resource-gallery.d.ts +1 -1
- package/dist/components/features/media-library/use-media-library.d.ts +1 -4
- package/dist/components/features/overlays/action-overlay-frame.d.ts +1 -1
- package/dist/components/features/overlays/index.d.ts +1 -1
- package/dist/components/features/overlays/overlay-parts.d.ts +3 -3
- package/dist/components/features/overlays/overlays.types.d.ts +8 -7
- package/dist/components/features/rich-text-editor/index.d.ts +0 -1
- package/dist/components/features/table/data-table-body.d.ts +1 -1
- package/dist/components/features/table/data-table-expanded-row.d.ts +27 -0
- package/dist/components/features/table/data-table-header.d.ts +1 -1
- package/dist/components/features/table/data-table-size.d.ts +1 -1
- package/dist/components/features/table/data-table.d.ts +1 -1
- package/dist/components/features/table/index.d.ts +1 -1
- package/dist/components/features/table/table-helpers.d.ts +9 -3
- package/dist/components/features/table/table.strings.d.ts +11 -0
- package/dist/components/features/table/table.types.d.ts +60 -2
- package/dist/components/features/theme-tweaker/index.d.ts +1 -1
- package/dist/components/features/theme-tweaker/theme-tweaker.strings.d.ts +1 -1
- package/dist/components/features/theme-tweaker/theme-tweaker.types.d.ts +6 -10
- package/dist/components/features/theme-tweaker/theme-tweaker.utils.d.ts +22 -6
- package/dist/components/layout/app-shell/topbar-sidebar-layout.d.ts +1 -1
- package/dist/components/layout/auth/auth.d.ts +1 -1
- package/dist/components/layout/auth/auth.types.d.ts +1 -1
- package/dist/components/primitives/value.d.ts +3 -1
- package/dist/containers-B8d8U9GS.js +2 -0
- package/dist/{copyable-H1TUEY-H.js → copyable-D9Okb1w6.js} +12 -11
- package/dist/core.css +2 -2
- package/dist/css/access.css +2 -1
- package/dist/css/accordion.css +2 -1
- package/dist/css/action-menu.css +2 -1
- package/dist/css/activities.css +2 -1
- package/dist/css/ai-chat.css +2 -1
- package/dist/css/analytics.css +2 -1
- package/dist/css/app-shell.css +2 -1
- package/dist/css/aspect-ratio.css +2 -1
- package/dist/css/async-preview.css +2 -1
- package/dist/css/auth.css +2 -1
- package/dist/css/avatar.css +2 -1
- package/dist/css/badge.css +2 -1
- package/dist/css/batch-action-bar.css +2 -1
- package/dist/css/buttons.css +2 -1
- package/dist/css/cards.css +2 -1
- package/dist/css/carousel.css +2 -1
- package/dist/css/chart.css +2 -1
- package/dist/css/choice-inputs.css +2 -1
- package/dist/css/combobox.css +2 -1
- package/dist/css/combobox2.css +2 -1
- package/dist/css/command.css +2 -1
- package/dist/css/comments.css +2 -1
- package/dist/css/commerce.css +2 -1
- package/dist/css/containers.css +2 -1
- package/dist/css/copyable.css +2 -1
- package/dist/css/data-view.css +2 -1
- package/dist/css/date-pickers.css +2 -1
- package/dist/css/display.css +2 -1
- package/dist/css/dropdown-menu.css +2 -1
- package/dist/css/event-calendar.css +2 -1
- package/dist/css/feedback.css +2 -1
- package/dist/css/filters.css +2 -1
- package/dist/css/forms-numeric.css +2 -1
- package/dist/css/forms.css +2 -1
- package/dist/css/global-search.css +2 -1
- package/dist/css/header.css +2 -1
- package/dist/css/hover-card.css +2 -1
- package/dist/css/input-group.css +2 -1
- package/dist/css/item.css +2 -1
- package/dist/css/kanban.css +2 -1
- package/dist/css/label.css +2 -1
- package/dist/css/map.css +2 -1
- package/dist/css/media-library.css +2 -1
- package/dist/css/mentions.css +2 -1
- package/dist/css/menubar.css +2 -1
- package/dist/css/navigation-menu.css +2 -1
- package/dist/css/navigation.css +2 -1
- package/dist/css/navigation2.css +2 -1
- package/dist/css/onboarding.css +2 -1
- package/dist/css/otp-input.css +2 -1
- package/dist/css/overlay.css +2 -1
- package/dist/css/overlays.css +2 -1
- package/dist/css/page.css +2 -1
- package/dist/css/popover-menu.css +2 -1
- package/dist/css/popover.css +2 -1
- package/dist/css/primitives.css +2 -1
- package/dist/css/products.css +2 -1
- package/dist/css/qr-code.css +2 -1
- package/dist/css/repeaters.css +2 -1
- package/dist/css/resizable.css +2 -1
- package/dist/css/resource-assignment.css +2 -1
- package/dist/css/resource.css +2 -1
- package/dist/css/rich-text-editor.css +2 -1
- package/dist/css/schema-form.css +2 -1
- package/dist/css/sidebar.css +2 -1
- package/dist/css/sidebar2.css +2 -1
- package/dist/css/skeleton.css +2 -1
- package/dist/css/spinner.css +2 -1
- package/dist/css/structure.css +2 -1
- package/dist/css/sync.css +2 -1
- package/dist/css/table.css +2 -1
- package/dist/css/table2.css +2 -1
- package/dist/css/text-inputs.css +2 -1
- package/dist/css/theme-tweaker.css +2 -1
- package/dist/css/timeline.css +2 -1
- package/dist/css/timelines.css +2 -1
- package/dist/css/toaster.css +2 -1
- package/dist/css/toggle.css +2 -1
- package/dist/css/toolbar.css +2 -1
- package/dist/css/tooltip.css +2 -1
- package/dist/css/typography.css +2 -1
- package/dist/css/upload.css +2 -1
- package/dist/css/value-inputs.css +2 -1
- package/dist/css/workspace.css +2 -1
- package/dist/css-graph.json +1027 -0
- package/dist/date-pickers-BwCwKIVM.js +685 -0
- package/dist/{dialog-CtFCuTUF.js → dialog-CAnwRNrm.js} +1 -1
- package/dist/display-a7AoX_u7.js +664 -0
- package/dist/dropdown-menu-Br8kvjrF.js +235 -0
- package/dist/empty.js +0 -0
- package/dist/features/actions.js +6 -6
- package/dist/features/activities.js +219 -216
- package/dist/features/ai-chat.js +593 -565
- package/dist/features/async-preview.js +105 -286
- package/dist/features/combobox.js +328 -314
- package/dist/features/comments.js +1 -1
- package/dist/features/data-view.js +56 -55
- package/dist/features/event-calendar.js +189 -185
- package/dist/features/filters.js +1 -1
- package/dist/features/global-search.js +259 -260
- package/dist/features/kanban.js +39 -37
- package/dist/features/map.js +357 -354
- package/dist/features/media-library.js +931 -931
- package/dist/features/mentions.js +1 -1
- package/dist/features/overlays.js +1 -1
- package/dist/features/products.js +950 -942
- package/dist/features/resource-assignment.js +39 -37
- package/dist/features/resource.js +70 -71
- package/dist/features/rich-text-editor.js +2 -2
- package/dist/features/schema-form.js +342 -338
- package/dist/features/sync.js +14 -12
- package/dist/features/table.js +1 -1
- package/dist/features/theme-tweaker.js +1002 -962
- package/dist/feedback-D4qVsKlD.js +430 -0
- package/dist/{filters-DOLKRSmb.js → filters-BhsTkWpZ.js} +386 -383
- package/dist/forms-C0WeNPFF.js +250 -0
- package/dist/forms-numeric-IwQ1ltNf.js +582 -0
- package/dist/hooks/use-native-dialog.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/input-group-HS_Z0Ei_.js +119 -0
- package/dist/item-M2pmpWXh.js +150 -0
- package/dist/{label-DumoMDm6.js → label-HOBXAscw.js} +7 -5
- package/dist/layout/app-shell.js +4 -2
- package/dist/layout/auth.js +102 -100
- package/dist/layout/header.js +190 -180
- package/dist/layout/navigation.js +1 -1
- package/dist/layout/page.js +18 -16
- package/dist/layout/settings.js +2 -2
- package/dist/layout/sidebar.js +50 -46
- package/dist/layout/workspace.js +71 -69
- package/dist/lib/action-presentation.d.ts +3 -3
- package/dist/lib/component-vocabulary.d.ts +2 -2
- package/dist/lib/css-length.d.ts +2 -0
- package/dist/lib/responsive.d.ts +1 -1
- package/dist/lib/theming/index.d.ts +1 -0
- package/dist/lib/theming/recipes.d.ts +2 -2
- package/dist/lib/theming/themes/dense.d.ts +3 -0
- package/dist/lib/theming/themes/editorial.d.ts +3 -0
- package/dist/lib/theming/themes/index.d.ts +8 -0
- package/dist/lib/theming/themes/pair.d.ts +7 -0
- package/dist/lib/theming/themes/sharp.d.ts +3 -0
- package/dist/lib/theming/themes/soft.d.ts +3 -0
- package/dist/lib/theming/themes/types.d.ts +12 -0
- package/dist/lib/ui-provider/index.d.ts +1 -1
- package/dist/lib/ui-provider/scope.d.ts +5 -8
- package/dist/lib/ui-provider/tokens.d.ts +11 -3
- package/dist/lib/ui-provider/tokens.generated.d.ts +6 -4
- package/dist/lib/ui-provider/types.d.ts +17 -19
- package/dist/lib/ui-provider/ui-scope.d.ts +1 -1
- package/dist/{mentions-BbsEHlcH.js → mentions-BOxbigwp.js} +113 -111
- package/dist/navigation-Bgu7Vc0M.js +622 -0
- package/dist/navigation-DiYACqpE.js +216 -0
- package/dist/overlay-BuQOl8aP.js +356 -0
- package/dist/{overlays-DvVoS3td.js → overlays-1sULyytH.js} +77 -75
- package/dist/popover-CA7SP_iz.js +127 -0
- package/dist/popover-menu-QXgQeWeG.js +192 -0
- package/dist/{primitives-D0bdDozz.js → primitives-BskKlf35.js} +181 -178
- package/dist/primitives.js +1 -1
- package/dist/profiles/admin.json +6 -36
- package/dist/profiles/general.json +6 -96
- package/dist/repeaters-CeH20dvr.js +445 -0
- package/dist/rich-text-editor-D_Ppm8yh.js +491 -0
- package/dist/{sheet-CKcmRbJ9.js → sheet-CJ1-OAla.js} +3 -3
- package/dist/sidebar-D8uGqxio.js +421 -0
- package/dist/skeleton-BTKNKTdj.js +173 -0
- package/dist/spinner-Tc1QCnxM.js +30 -0
- package/dist/{structure-D0WGQAP3.js → structure-CynEZ-OY.js} +15 -23
- package/dist/style.css +1 -1
- package/dist/styles/TOKENS.md +116 -275
- package/dist/styles/animation.css +114 -0
- package/dist/styles/base.css +7 -6
- package/dist/styles/fields.css +45 -63
- package/dist/styles/focus.css +12 -0
- package/dist/styles/forced-colors.css +11 -10
- package/dist/styles/index.css +23 -30
- package/dist/styles/map.css +45 -34
- package/dist/styles/mentions.css +14 -52
- package/dist/styles/overlays.css +7 -7
- package/dist/styles/tailwind.css +76 -127
- package/dist/styles/targets.css +3 -3
- package/dist/styles/theme/colour.css +86 -0
- package/dist/styles/theme/density.css +31 -0
- package/dist/styles/theme/elevation.css +9 -0
- package/dist/styles/theme/layout.css +18 -0
- package/dist/styles/theme/motion.css +18 -0
- package/dist/styles/theme/shape.css +12 -0
- package/dist/styles/theme/size.css +10 -0
- package/dist/styles/theme/spacing.css +11 -0
- package/dist/styles/theme/typography.css +20 -0
- package/dist/styles/tone.css +61 -0
- package/dist/table-B7dtIFUx.js +1262 -0
- package/dist/table-Ds_eO9av.js +191 -0
- package/dist/tailwind.css +76 -127
- package/dist/text-inputs-BboE77nZ.js +395 -0
- package/dist/theming-C5ygF5uf.js +292 -0
- package/dist/theming.js +2 -2
- package/dist/{timeline-BdaGRyj-.js → timeline-BR_jNgvz.js} +57 -49
- package/dist/{timelines-BB7550mz.js → timelines-DXG1BfIN.js} +69 -67
- package/dist/{toaster-bBMgXm8z.js → toaster-CXL8L7Mm.js} +106 -99
- package/dist/tokens.json +1027 -636
- package/dist/toolbar-DBK-c4yy.js +74 -0
- package/dist/tooltip-BPYP-jUm.js +76 -0
- package/dist/{typography-BkxEiwQ1.js → typography-DmeR05Er.js} +87 -53
- package/dist/{ui-provider-Cmoq6i_D.js → ui-provider-DpzLUD12.js} +117 -69
- package/dist/ui-provider.js +1 -1
- package/dist/upload-CYuoJykZ.js +968 -0
- package/dist/use-async-preview-BFwf9ElY.js +188 -0
- package/dist/value-inputs-ng8aVJJZ.js +728 -0
- package/docs/README.md +13 -3
- package/docs/build/browser-composition-fixture.ts +28 -0
- package/docs/build/recipes.md +11484 -10723
- package/docs/generated/component-index.json +9809 -9169
- package/docs/generated/components/INDEX.md +5 -5
- package/docs/generated/components/base--accordion.md +51 -2
- package/docs/generated/components/base--action-menu.md +14 -15
- package/docs/generated/components/base--alert-dialog.md +3 -4
- package/docs/generated/components/base--aspect-ratio.md +3 -4
- package/docs/generated/components/base--avatar.md +7 -7
- package/docs/generated/components/base--badge.md +159 -27
- package/docs/generated/components/base--batch-action-bar.md +6 -7
- package/docs/generated/components/base--buttons.md +151 -47
- package/docs/generated/components/base--cards.md +107 -14
- package/docs/generated/components/base--carousel.md +1 -2
- package/docs/generated/components/base--chart.md +44 -8
- package/docs/generated/components/base--choice-inputs.md +10 -11
- package/docs/generated/components/base--combobox.md +3 -4
- package/docs/generated/components/base--command.md +6 -6
- package/docs/generated/components/base--context-menu.md +1 -2
- package/docs/generated/components/base--copyable.md +6 -7
- package/docs/generated/components/base--date-pickers.md +6 -7
- package/docs/generated/components/base--dialog.md +6 -7
- package/docs/generated/components/base--direction.md +1 -1
- package/docs/generated/components/base--display.md +234 -54
- package/docs/generated/components/base--dropdown-menu.md +6 -7
- package/docs/generated/components/base--feedback.md +71 -18
- package/docs/generated/components/base--forms-numeric.md +6 -7
- package/docs/generated/components/base--forms.md +84 -14
- package/docs/generated/components/base--hover-card.md +3 -4
- package/docs/generated/components/base--input-group.md +27 -30
- package/docs/generated/components/base--item.md +8 -9
- package/docs/generated/components/base--label.md +2 -3
- package/docs/generated/components/base--menubar.md +2 -4
- package/docs/generated/components/base--navigation-menu.md +2 -3
- package/docs/generated/components/base--navigation.md +2 -3
- package/docs/generated/components/base--otp-input.md +3 -4
- package/docs/generated/components/base--overlay.md +56 -47
- package/docs/generated/components/base--popover-menu.md +7 -8
- package/docs/generated/components/base--popover.md +9 -10
- package/docs/generated/components/base--qr-code.md +7 -8
- package/docs/generated/components/base--repeaters.md +6 -7
- package/docs/generated/components/base--resizable.md +2 -3
- package/docs/generated/components/base--sheet.md +12 -13
- package/docs/generated/components/base--sidebar.md +9 -11
- package/docs/generated/components/base--skeleton.md +6 -7
- package/docs/generated/components/base--slot.md +1 -1
- package/docs/generated/components/base--spinner.md +5 -7
- package/docs/generated/components/base--structure.md +320 -70
- package/docs/generated/components/base--table.md +61 -3
- package/docs/generated/components/base--text-inputs.md +17 -18
- package/docs/generated/components/base--timeline.md +45 -4
- package/docs/generated/components/base--toaster.md +43 -12
- package/docs/generated/components/base--toggle.md +11 -12
- package/docs/generated/components/base--toolbar.md +7 -8
- package/docs/generated/components/base--tooltip.md +5 -6
- package/docs/generated/components/base--typography.md +317 -32
- package/docs/generated/components/base--upload.md +8 -9
- package/docs/generated/components/base--value-inputs.md +9 -38
- package/docs/generated/components/{admin--patterns--access.md → blocks--admin--access.md} +15 -6
- package/docs/generated/components/{admin--patterns--commerce.md → blocks--admin--commerce.md} +40 -41
- package/docs/generated/components/{patterns--analytics.md → blocks--analytics.md} +57 -14
- package/docs/generated/components/{patterns--onboarding.md → blocks--onboarding.md} +6 -7
- package/docs/generated/components/{patterns--timelines.md → blocks--timelines.md} +6 -7
- package/docs/generated/components/features--actions.md +8 -18
- package/docs/generated/components/features--activities.md +31 -32
- package/docs/generated/components/features--ai-chat.md +15 -15
- package/docs/generated/components/features--async-preview.md +5 -6
- package/docs/generated/components/features--combobox.md +71 -5
- package/docs/generated/components/features--comments.md +0 -1
- package/docs/generated/components/features--data-view.md +63 -8
- package/docs/generated/components/features--event-calendar.md +1 -2
- package/docs/generated/components/features--filters.md +11 -2
- package/docs/generated/components/features--global-search.md +1 -2
- package/docs/generated/components/features--kanban.md +1 -2
- package/docs/generated/components/features--map.md +1 -2
- package/docs/generated/components/features--media-library.md +105 -38
- package/docs/generated/components/features--mentions.md +7 -7
- package/docs/generated/components/features--overlays.md +75 -22
- package/docs/generated/components/features--products.md +10 -11
- package/docs/generated/components/features--resource-assignment.md +2 -3
- package/docs/generated/components/features--resource.md +3 -4
- package/docs/generated/components/features--rich-text-editor.md +42 -13
- package/docs/generated/components/features--schema-form.md +1 -2
- package/docs/generated/components/features--sync.md +2 -3
- package/docs/generated/components/features--table.md +162 -12
- package/docs/generated/components/features--theme-tweaker.md +30 -15
- package/docs/generated/components/forms.md +2 -2
- package/docs/generated/components/layout--app-shell.md +41 -11
- package/docs/generated/components/layout--auth.md +8 -9
- package/docs/generated/components/layout--containers.md +40 -1
- package/docs/generated/components/layout--header.md +2 -3
- package/docs/generated/components/layout--navigation.md +0 -1
- package/docs/generated/components/layout--page.md +33 -5
- package/docs/generated/components/layout--settings.md +0 -1
- package/docs/generated/components/layout--sidebar.md +47 -7
- package/docs/generated/components/layout--workspace.md +3 -4
- package/docs/generated/components/primitives.md +128 -17
- package/docs/generated/components/theming.md +147 -4
- package/docs/generated/components/ui-provider.md +96 -78
- package/docs/generated/composition-ladder.md +8 -8
- package/docs/generated/consumer-contract.json +5736 -0
- package/docs/generated/imports.md +104 -104
- package/docs/generated/migration-broad-imports.json +267 -90
- package/docs/generated/migration-broad-imports.md +266 -101
- package/docs/generated/migration-codemod.json +365 -70
- package/docs/generated/migration.md +665 -95
- package/docs/generated/profiles.md +27 -27
- package/docs/generated/public-api.md +104 -102
- package/docs/generated/recipes.json +755 -810
- package/docs/generated/workflows/communications-overview/analytics/communications-reference.tsx +19 -0
- package/docs/generated/workflows/index.json +691 -0
- package/docs/generated/workflows/media-picking/media-library/media-picking-reference.tsx +63 -0
- package/docs/generated/workflows/media-picking/media-library/reference-data.ts +3 -0
- package/docs/generated/workflows/multi-section-form/form-workflow/multi-section-reference.tsx +46 -0
- package/docs/generated/workflows/nested-action-flow/action-overlays/nested-action-reference.tsx +39 -0
- package/docs/generated/workflows/record-detail/page-layout/record-detail-reference.tsx +24 -0
- package/docs/generated/workflows/resource-index/data-view/resource-index-reference.tsx +51 -0
- package/docs/generated/workflows/scoped-resource-selection/combobox/scoped-resource-reference.tsx +50 -0
- package/docs/generated/workflows/website-content-editor/media-library/reference-data.ts +3 -0
- package/docs/generated/workflows/website-content-editor/rich-text-editor/website-content-reference.tsx +33 -0
- package/docs/generated/workflows/workspace-navigation/app-shell/workspace-navigation-reference.tsx +26 -0
- package/docs/learn/api-compatibility.md +5 -4
- package/docs/learn/blocks.md +123 -0
- package/docs/learn/composition.md +100 -19
- package/docs/learn/forms.md +23 -3
- package/docs/learn/framework-wiring.md +41 -13
- package/docs/learn/i18n.md +4 -2
- package/docs/learn/installation.md +60 -31
- package/docs/learn/migration.md +156 -5
- package/docs/learn/provider-and-scoping.md +37 -25
- package/docs/learn/reference-workflows.md +43 -0
- package/docs/learn/structure-and-spacing.md +147 -0
- package/docs/learn/theming.md +174 -131
- package/docs/learn/troubleshooting.md +88 -30
- package/docs/learn/verification.md +60 -5
- package/package.json +42 -473
- package/scripts/consumer/codemod.mjs +50 -32
- package/scripts/consumer/contract-reader.mjs +42 -0
- package/scripts/consumer/css-scan.mjs +51 -0
- package/scripts/consumer/diagnose.mjs +136 -0
- package/scripts/consumer/find-component.mjs +30 -17
- package/scripts/consumer/install-skill.mjs +93 -11
- package/src/styles/TOKENS.md +116 -275
- package/dist/accordion-6YPJ9XRO.js +0 -135
- package/dist/admin/patterns/access.css +0 -15
- package/dist/admin/patterns/commerce.css +0 -29
- package/dist/admin/patterns/commerce.js +0 -2493
- package/dist/avatar-CS7zow2q.js +0 -85
- package/dist/badge-CxOuTfVr.js +0 -63
- package/dist/base/accordion.css +0 -3
- package/dist/base/action-menu.css +0 -6
- package/dist/base/alert-dialog.css +0 -4
- package/dist/base/aspect-ratio.css +0 -2
- package/dist/base/avatar.css +0 -4
- package/dist/base/badge.css +0 -2
- package/dist/base/batch-action-bar.css +0 -5
- package/dist/base/buttons.css +0 -4
- package/dist/base/cards.css +0 -13
- package/dist/base/carousel.css +0 -5
- package/dist/base/chart.css +0 -2
- package/dist/base/choice-inputs.css +0 -10
- package/dist/base/combobox.css +0 -3
- package/dist/base/command.css +0 -9
- package/dist/base/context-menu.css +0 -2
- package/dist/base/copyable.css +0 -6
- package/dist/base/date-pickers.css +0 -11
- package/dist/base/dialog.css +0 -4
- package/dist/base/display.css +0 -8
- package/dist/base/dropdown-menu.css +0 -2
- package/dist/base/feedback.css +0 -5
- package/dist/base/forms-numeric.css +0 -12
- package/dist/base/forms.css +0 -14
- package/dist/base/hover-card.css +0 -2
- package/dist/base/input-group.css +0 -6
- package/dist/base/item.css +0 -9
- package/dist/base/label.css +0 -3
- package/dist/base/menubar.css +0 -2
- package/dist/base/navigation-menu.css +0 -2
- package/dist/base/navigation.css +0 -12
- package/dist/base/otp-input.css +0 -9
- package/dist/base/overlay.css +0 -4
- package/dist/base/popover-menu.css +0 -11
- package/dist/base/popover.css +0 -3
- package/dist/base/qr-code.css +0 -2
- package/dist/base/repeaters.css +0 -18
- package/dist/base/resizable.css +0 -2
- package/dist/base/sheet.css +0 -4
- package/dist/base/sidebar.css +0 -12
- package/dist/base/skeleton.css +0 -9
- package/dist/base/spinner.css +0 -2
- package/dist/base/structure.css +0 -2
- package/dist/base/table.css +0 -3
- package/dist/base/text-inputs.css +0 -2
- package/dist/base/timeline.css +0 -9
- package/dist/base/toaster.css +0 -2
- package/dist/base/toggle.css +0 -2
- package/dist/base/toolbar.css +0 -5
- package/dist/base/tooltip.css +0 -2
- package/dist/base/typography.css +0 -2
- package/dist/base/upload.css +0 -10
- package/dist/base/value-inputs.css +0 -14
- package/dist/buttons-CqXKWty3.js +0 -179
- package/dist/cards-C6Ulbkw7.js +0 -271
- package/dist/chart-nomhJ87z.js +0 -193
- package/dist/choice-inputs-OUDn0kQw.js +0 -680
- package/dist/combobox-C8oP92bT.js +0 -266
- package/dist/command-Bp3B6pUu.js +0 -143
- package/dist/comments-CAnDlyXO.js +0 -1438
- package/dist/components/admin/patterns/index.d.ts +0 -2
- package/dist/components/features/rich-text-editor/exec-command-engine.d.ts +0 -2
- package/dist/components/patterns/index.d.ts +0 -3
- package/dist/css/styles.css +0 -1
- package/dist/date-pickers-DOwIT-Nk.js +0 -661
- package/dist/display-B3Q17h5z.js +0 -645
- package/dist/dropdown-menu-TyNLCLML.js +0 -223
- package/dist/features/actions.css +0 -11
- package/dist/features/activities.css +0 -25
- package/dist/features/ai-chat.css +0 -14
- package/dist/features/async-preview.css +0 -10
- package/dist/features/combobox.css +0 -12
- package/dist/features/comments.css +0 -24
- package/dist/features/data-view.css +0 -31
- package/dist/features/event-calendar.css +0 -17
- package/dist/features/filters.css +0 -24
- package/dist/features/global-search.css +0 -19
- package/dist/features/kanban.css +0 -7
- package/dist/features/map.css +0 -15
- package/dist/features/media-library.css +0 -27
- package/dist/features/mentions.css +0 -17
- package/dist/features/overlays.css +0 -11
- package/dist/features/products.css +0 -29
- package/dist/features/resource-assignment.css +0 -14
- package/dist/features/resource.css +0 -15
- package/dist/features/rich-text-editor.css +0 -8
- package/dist/features/schema-form.css +0 -22
- package/dist/features/sync.css +0 -11
- package/dist/features/table.css +0 -20
- package/dist/features/theme-tweaker.css +0 -27
- package/dist/feedback-DRerHGuV.js +0 -469
- package/dist/forms-CPrGGif_.js +0 -242
- package/dist/forms-numeric-CPVsL7Vf.js +0 -569
- package/dist/index.css +0 -3
- package/dist/input-group-BYe0rhoB.js +0 -126
- package/dist/item-B3yQ26as.js +0 -146
- package/dist/layout/app-shell.css +0 -13
- package/dist/layout/auth.css +0 -14
- package/dist/layout/containers.css +0 -2
- package/dist/layout/header.css +0 -20
- package/dist/layout/navigation.css +0 -11
- package/dist/layout/page.css +0 -15
- package/dist/layout/settings.css +0 -16
- package/dist/layout/sidebar.css +0 -16
- package/dist/layout/workspace.css +0 -15
- package/dist/navigation-CsqTA16F.js +0 -614
- package/dist/navigation-DzxzPuwg.js +0 -202
- package/dist/overlay-WQOsLd69.js +0 -345
- package/dist/patterns/analytics.css +0 -15
- package/dist/patterns/onboarding.css +0 -11
- package/dist/patterns/timelines.css +0 -11
- package/dist/popover-DriLnIFc.js +0 -123
- package/dist/popover-menu-C2UCMAe7.js +0 -189
- package/dist/primitives.css +0 -3
- package/dist/repeaters-DuP1N0nw.js +0 -438
- package/dist/rich-text-editor-BQXFe9oN.js +0 -595
- package/dist/sidebar-D0N6ckJL.js +0 -412
- package/dist/skeleton-DGR9df28.js +0 -172
- package/dist/spinner-CUAVFecI.js +0 -52
- package/dist/styles/FACTORS.md +0 -36
- package/dist/styles/SCOPES.md +0 -86
- package/dist/styles/themes/default.css +0 -164
- package/dist/styles/theming/animation.css +0 -143
- package/dist/styles/theming/colors.css +0 -97
- package/dist/styles/theming/feedback.css +0 -17
- package/dist/styles/theming/field.css +0 -21
- package/dist/styles/theming/focus.css +0 -88
- package/dist/styles/theming/layers.css +0 -13
- package/dist/styles/theming/layout.css +0 -21
- package/dist/styles/theming/motion.css +0 -42
- package/dist/styles/theming/overlay.css +0 -52
- package/dist/styles/theming/sizing.css +0 -118
- package/dist/styles/theming/text.css +0 -30
- package/dist/styles/theming/typography.css +0 -26
- package/dist/styles/tokens/components.css +0 -22
- package/dist/styles/tokens/foundation.css +0 -80
- package/dist/styles/tokens/layout.css +0 -19
- package/dist/styles/tokens/palette.css +0 -88
- package/dist/styles/tokens/primitives.css +0 -18
- package/dist/styles/tokens/states.css +0 -77
- package/dist/table-BC4qqsUb.js +0 -180
- package/dist/table-BHDpjajL.js +0 -982
- package/dist/text-inputs-DF_lD7pA.js +0 -385
- package/dist/theming-D6KRU7hO.js +0 -104
- package/dist/toolbar-DWRywF0R.js +0 -68
- package/dist/tooltip-t1VQQ2tZ.js +0 -73
- package/dist/upload-B38YZeFJ.js +0 -938
- package/dist/value-inputs-Q4ymjXlV.js +0 -716
- package/src/styles/FACTORS.md +0 -36
- package/src/styles/SCOPES.md +0 -86
- /package/dist/components/{admin/patterns → blocks/admin}/access/admin.strings.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/access/credential-list.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/access/index.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/access/role-permissions.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/access/sensitive-action.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/account.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/address-lines.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/booking.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/cart.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/commerce.strings.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/commerce.types.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/format-amount.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/index.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/inventory-section.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/invoice.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/loyalty.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/order-customer.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/order-detail.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/order-line-item.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/order-transactions.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/order.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/seo-listing.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/seo-score.d.ts +0 -0
- /package/dist/components/{admin/patterns → blocks/admin}/commerce/summary-panel.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/analytics/activity-heatmap.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/analytics/analytics.types.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/analytics/chart-card.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/analytics/format-metric-value.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/analytics/index.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/analytics/metric-bar.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/analytics/metric-comparison.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/analytics/metric-gradient.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/analytics/metric-grid.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/analytics/metric-micro-grid.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/analytics/metric-skeleton.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/analytics/metric-trend-chip.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/analytics/metric.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/analytics/time-ruler.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/onboarding/checklist.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/onboarding/index.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/onboarding/onboarding.strings.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/timelines/changelog-timeline.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/timelines/index.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/timelines/milestones-timeline.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/timelines/steps.d.ts +0 -0
- /package/dist/components/{patterns → blocks}/timelines/timelines.strings.d.ts +0 -0
- /package/dist/styles/{theming/breakpoints.css → breakpoints.css} +0 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { useEffect, useMemo, useState } from "react"
|
|
2
|
+
import { Button } from "themelia-ui/base/buttons"
|
|
3
|
+
import { Stack } from "themelia-ui/base/structure"
|
|
4
|
+
import { Text } from "themelia-ui/base/typography"
|
|
5
|
+
import { MediaLibraryDialog, type MediaLibraryItem, type MediaLibraryFetcher } from "themelia-ui/features/media-library"
|
|
6
|
+
|
|
7
|
+
import { SAMPLE_MEDIA } from "./reference-data"
|
|
8
|
+
|
|
9
|
+
export default function MediaPickingReference() {
|
|
10
|
+
const [open, setOpen] = useState(false)
|
|
11
|
+
const [scope, setScope] = useState("site")
|
|
12
|
+
const [fail, setFail] = useState(false)
|
|
13
|
+
const [selected, setSelected] = useState<string[]>(["unavailable-id"])
|
|
14
|
+
const [pickerDraft, setPickerDraft] = useState(selected)
|
|
15
|
+
const [resolved, setResolved] = useState<{ scope: string; ids: string[]; items: MediaLibraryItem[] }>()
|
|
16
|
+
const [page, setPage] = useState(0)
|
|
17
|
+
const [query, setQuery] = useState("")
|
|
18
|
+
const [pending, setPending] = useState(true)
|
|
19
|
+
const [hasNext, setHasNext] = useState(false)
|
|
20
|
+
// A saved id is resolved separately from the current browser page, with scope access applied.
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
const controller = new AbortController()
|
|
23
|
+
const timer = setTimeout(() => {
|
|
24
|
+
if (!controller.signal.aborted) setResolved({ scope, ids: selected, items: SAMPLE_MEDIA.filter(item => selected.includes(item.id) && item.collection === scope) })
|
|
25
|
+
}, 150)
|
|
26
|
+
return () => { controller.abort(); clearTimeout(timer) }
|
|
27
|
+
}, [selected, scope])
|
|
28
|
+
const chosen = resolved?.scope === scope && resolved.ids === selected ? resolved.items : []
|
|
29
|
+
const unavailable = resolved?.scope === scope && resolved.ids === selected && chosen.length < selected.length
|
|
30
|
+
const changeOpen = (next: boolean) => {
|
|
31
|
+
if (next) setPickerDraft(selected)
|
|
32
|
+
setOpen(next)
|
|
33
|
+
}
|
|
34
|
+
const fetcher = useMemo<MediaLibraryFetcher>(() => async ({ query: search, signal }) => {
|
|
35
|
+
setPending(true)
|
|
36
|
+
try {
|
|
37
|
+
await new Promise(resolve => setTimeout(resolve, 200))
|
|
38
|
+
if (signal?.aborted) throw new DOMException("Aborted", "AbortError")
|
|
39
|
+
if (fail) throw new Error("Media lookup unavailable")
|
|
40
|
+
const matches = SAMPLE_MEDIA.filter(item => item.collection === scope && item.name.toLowerCase().includes(search.toLowerCase()))
|
|
41
|
+
const window = matches.slice(page, page + 2)
|
|
42
|
+
setHasNext(window.length > 1)
|
|
43
|
+
return { items: window.slice(0, 1) }
|
|
44
|
+
} finally { if (!signal?.aborted) setPending(false) }
|
|
45
|
+
}, [scope, fail, page])
|
|
46
|
+
return <Stack>
|
|
47
|
+
{unavailable && <Text role="alert">The saved asset is unavailable. Choose a replacement; the draft id is retained until then.</Text>}
|
|
48
|
+
<Stack direction="horizontal" gap="sm" wrap>
|
|
49
|
+
<MediaLibraryDialog open={open} trigger={<Button>Choose reference media</Button>} onOpenChange={changeOpen} fetcher={fetcher} value={pickerDraft} onValueChange={setPickerDraft} query={query} onQueryChange={next => { setQuery(next); setPage(0); setPending(true) }} selectionMode="single" allowUpload={false}
|
|
50
|
+
strings={{ showingCount: shown => `${shown} loaded on this page; total unknown` }}
|
|
51
|
+
slots={{ footer: <Stack direction="horizontal" gap="sm" wrap align="center">
|
|
52
|
+
<Text>Media page {page + 1}; total unknown</Text>
|
|
53
|
+
<Button disabled={pending || page === 0} onClick={() => { setPage(value => value - 1); setPending(true) }}>Previous media page</Button>
|
|
54
|
+
<Button disabled={pending || !hasNext} onClick={() => { setPage(value => value + 1); setPending(true) }}>Next media page</Button>
|
|
55
|
+
</Stack> }}
|
|
56
|
+
onConfirm={(items, ids) => { setSelected(ids); setResolved({ scope, ids, items }); setOpen(false) }} />
|
|
57
|
+
<Button tone="neutral" appearance="outline" onClick={() => setSelected(["image-2"])}>Load saved media draft</Button>
|
|
58
|
+
<Button tone="neutral" appearance="outline" onClick={() => { setScope(value => value === "site" ? "other" : "site"); setPage(0); setPending(true) }}>Switch media scope</Button>
|
|
59
|
+
<Button tone="neutral" appearance="outline" onClick={() => { setFail(value => !value); setPending(true) }}>Toggle media failure</Button>
|
|
60
|
+
</Stack>
|
|
61
|
+
<Text role="status">{chosen.length ? `Hydrated selection: ${chosen.map(item => `${item.name} — ${item.alt}`).join(", ")}` : `Saved draft ids: ${selected.join(", ")}`}</Text>
|
|
62
|
+
</Stack>
|
|
63
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { MediaLibraryItem } from "themelia-ui/features/media-library"
|
|
2
|
+
|
|
3
|
+
export const SAMPLE_MEDIA: MediaLibraryItem[] = [{ id: "image-1", name: "Garden exterior", type: "image", alt: "A garden with a stone path", collection: "site", public: true }, { id: "image-2", name: "Meeting room", type: "image", alt: "A meeting room with daylight", collection: "site", public: true }]
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { useRef, useState } from "react"
|
|
2
|
+
import { Card } from "themelia-ui/base/cards"
|
|
3
|
+
import { ContentBlock } from "themelia-ui/base/display"
|
|
4
|
+
import { FieldGroup, FormField, FormSection, FormActionsBar, SubmitStateButton } from "themelia-ui/base/forms"
|
|
5
|
+
import { Stack } from "themelia-ui/base/structure"
|
|
6
|
+
import { Input } from "themelia-ui/base/text-inputs"
|
|
7
|
+
import { Text } from "themelia-ui/base/typography"
|
|
8
|
+
import { useFormFieldBinding, useStateFormControl, type FormControl } from "themelia-ui/forms"
|
|
9
|
+
|
|
10
|
+
type Draft = { firstName: string; lastName: string; company: string }
|
|
11
|
+
function BoundField({ control, name, label, error }: { control: FormControl<Draft>; name: keyof Draft; label: string; error?: string }) {
|
|
12
|
+
const field = useFormFieldBinding<string, Draft>({ control, name })
|
|
13
|
+
return <FormField label={label} error={error} hint={name === "company" ? "The name shown on invoices." : undefined}><Input required value={field.value ?? ""} onChange={event => field.onValueChange(event.target.value)} onBlur={field.onBlur} /></FormField>
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default function MultiSectionReference() {
|
|
17
|
+
const control = useStateFormControl<Draft>({ firstName: "Alex", lastName: "Example", company: "Example team" })
|
|
18
|
+
const [pending, setPending] = useState(false)
|
|
19
|
+
const [error, setError] = useState<string>()
|
|
20
|
+
const [rootError, setRootError] = useState<string>()
|
|
21
|
+
const [saved, setSaved] = useState(0)
|
|
22
|
+
const running = useRef(false)
|
|
23
|
+
return <Stack>
|
|
24
|
+
<Card title="Account details" description="One outer surface, editable sections with retained region insets.">
|
|
25
|
+
<form onSubmit={async event => {
|
|
26
|
+
event.preventDefault(); if (running.current) return
|
|
27
|
+
running.current = true; setPending(true); setError(undefined); setRootError(undefined)
|
|
28
|
+
try {
|
|
29
|
+
await new Promise(resolve => setTimeout(resolve, 250))
|
|
30
|
+
if (control.values.company === "offline") throw new Error("Request failed. Your values remain here.")
|
|
31
|
+
if (control.values.company.length < 3) { setError("Company must have at least three characters."); return }
|
|
32
|
+
setSaved(count => count + 1)
|
|
33
|
+
} catch (failure) { setRootError((failure as Error).message) }
|
|
34
|
+
finally { running.current = false; setPending(false) }
|
|
35
|
+
}}>
|
|
36
|
+
<Stack gap="none">
|
|
37
|
+
{rootError && <Text role="alert" type="error">{rootError}</Text>}
|
|
38
|
+
<FormSection surface="flat" title="Contact"><FieldGroup legend="Legal name" disabled={pending}><BoundField control={control} name="firstName" label="First name" /><BoundField control={control} name="lastName" label="Last name" /></FieldGroup></FormSection>
|
|
39
|
+
<FormSection surface="flat" title="Billing"><fieldset disabled={pending} style={{ border: 0, padding: 0, margin: 0 }}><BoundField control={control} name="company" label="Company" error={error} /></fieldset></FormSection>
|
|
40
|
+
<FormActionsBar leading={<Text role="status">Successful submissions {saved}</Text>}><SubmitStateButton type="submit" state={pending ? "submitting" : "idle"} strings={{ idle: "Save account" }} /></FormActionsBar>
|
|
41
|
+
</Stack>
|
|
42
|
+
</form>
|
|
43
|
+
</Card>
|
|
44
|
+
<Card title="Preferences" description="A sibling subject owns its own surface."><ContentBlock surface="plain" title="Delivery instructions"><Text>Use ContentBlock for supporting prose; FieldGroup supplies fieldset semantics for related controls.</Text></ContentBlock></Card>
|
|
45
|
+
</Stack>
|
|
46
|
+
}
|
package/docs/generated/workflows/nested-action-flow/action-overlays/nested-action-reference.tsx
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { useRef, useState } from "react"
|
|
2
|
+
import { Button } from "themelia-ui/base/buttons"
|
|
3
|
+
import { FormField } from "themelia-ui/base/forms"
|
|
4
|
+
import { Stack } from "themelia-ui/base/structure"
|
|
5
|
+
import { Input } from "themelia-ui/base/text-inputs"
|
|
6
|
+
import { Text } from "themelia-ui/base/typography"
|
|
7
|
+
import { ActionDialog } from "themelia-ui/features/overlays"
|
|
8
|
+
|
|
9
|
+
export default function NestedActionReference() {
|
|
10
|
+
const [open, setOpen] = useState(false)
|
|
11
|
+
const [child, setChild] = useState(false)
|
|
12
|
+
const [name, setName] = useState("Draft record")
|
|
13
|
+
const [error, setError] = useState<string>()
|
|
14
|
+
const [saved, setSaved] = useState(0)
|
|
15
|
+
const session = useRef(0)
|
|
16
|
+
const changeOpen = (next: boolean) => { session.current++; setOpen(next); setChild(false) }
|
|
17
|
+
return <Stack>
|
|
18
|
+
<ActionDialog open={open} trigger={<Button>Inspect draft</Button>} onOpenChange={changeOpen} title="Record inspector" description="The draft remains here after cancellation, validation failure or transport failure." showConfirm={false}>
|
|
19
|
+
<Stack>
|
|
20
|
+
<FormField label="Record name" error={error} hint="Use at least three characters. Use offline to simulate a rejected request."><Input value={name} onChange={event => setName(event.target.value)} /></FormField>
|
|
21
|
+
<ActionDialog open={child} trigger={<Button>Review save</Button>} onOpenChange={setChild} title="Save this draft?" description="A resolved response can contain validation errors. Closure follows business success." closeOnAsyncComplete={false}
|
|
22
|
+
alertMessage={error} onError={() => setError("Could not save; your draft is still here.")}
|
|
23
|
+
onAsyncConfirm={async () => {
|
|
24
|
+
const attempt = session.current
|
|
25
|
+
await new Promise(resolve => setTimeout(resolve, 300))
|
|
26
|
+
if (attempt !== session.current) return
|
|
27
|
+
if (name === "offline") throw new Error("Unavailable")
|
|
28
|
+
if (name.trim().length < 3) { setError("Enter at least three characters."); return }
|
|
29
|
+
setError(undefined); setSaved(count => count + 1); changeOpen(false)
|
|
30
|
+
}}>
|
|
31
|
+
<Text>{name}</Text>
|
|
32
|
+
</ActionDialog>
|
|
33
|
+
{/* A native form can instead use formId: its submit handler owns validation and closure. */}
|
|
34
|
+
<Text size="xs" type="secondary">Confirmation {child ? "open" : "closed"}</Text>
|
|
35
|
+
</Stack>
|
|
36
|
+
</ActionDialog>
|
|
37
|
+
<Text role="status">Successful saves {saved}</Text>
|
|
38
|
+
</Stack>
|
|
39
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { useState } from "react"
|
|
2
|
+
import { Button } from "themelia-ui/base/buttons"
|
|
3
|
+
import { Card, CardContent, CardHeader } from "themelia-ui/base/cards"
|
|
4
|
+
import { ContentBlock, MetadataList } from "themelia-ui/base/display"
|
|
5
|
+
import { Stack } from "themelia-ui/base/structure"
|
|
6
|
+
import { Text } from "themelia-ui/base/typography"
|
|
7
|
+
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "themelia-ui/base/table"
|
|
8
|
+
import { Page } from "themelia-ui/layout/page"
|
|
9
|
+
|
|
10
|
+
export default function RecordDetailReference() {
|
|
11
|
+
const [activity, setActivity] = useState("No commands yet")
|
|
12
|
+
return <Page header={{ title: "Record R-104", description: "A record with independent subjects and related records.", actions: <Button onClick={() => setActivity("Route command: export R-104")}>Export record</Button> }}>
|
|
13
|
+
<Stack>
|
|
14
|
+
<Card title="Identity" titleLevel={2} headerAction={<Button tone="neutral" appearance="outline" onClick={() => setActivity("Identity command: edit R-104")}>Edit identity</Button>}>
|
|
15
|
+
<MetadataList items={[{ id: "owner", label: "Owner", value: "Example team" }, { id: "state", label: "State", value: "Active" }]} />
|
|
16
|
+
<ContentBlock title="Notes" surface="plain"><Text>A long description belongs to prose, while the name and status above are facts. Commands stay beside the subject they affect. Repeated records can each have their own headings without repeating the route heading.</Text></ContentBlock>
|
|
17
|
+
</Card>
|
|
18
|
+
<Card><CardHeader title="Related records" titleLevel={2} description="The header is composed from parts; omit Card title props when supplying it." /><CardContent>
|
|
19
|
+
<Table aria-label="Related records"><TableHeader><TableRow><TableHead>Record</TableHead><TableHead>Relationship</TableHead></TableRow></TableHeader><TableBody><TableRow><TableCell>R-105</TableCell><TableCell>Follow-up</TableCell></TableRow></TableBody></Table>
|
|
20
|
+
</CardContent></Card>
|
|
21
|
+
<Text role="status">{activity}</Text>
|
|
22
|
+
</Stack>
|
|
23
|
+
</Page>
|
|
24
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from "react"
|
|
2
|
+
import { Button } from "themelia-ui/base/buttons"
|
|
3
|
+
import { Stack } from "themelia-ui/base/structure"
|
|
4
|
+
import { Heading, Text } from "themelia-ui/base/typography"
|
|
5
|
+
import { DataView, type DataViewProps } from "themelia-ui/features/data-view"
|
|
6
|
+
import { FilterType, type ActiveFilter, type FilterConfig } from "themelia-ui/features/filters"
|
|
7
|
+
|
|
8
|
+
type RecordRow = { id: string; name: string; status: string; searchTerms: string }
|
|
9
|
+
const RECORDS: RecordRow[] = Array.from({ length: 6 }, (_, index) => ({ id: `r${index + 1}`, name: `Resource ${index + 1}`, status: index % 2 ? "Closed" : "Open", searchTerms: "hidden reference term" }))
|
|
10
|
+
const COLUMNS: DataViewProps<RecordRow>["columns"] = [{ accessorKey: "name", header: "Resource" }, { accessorKey: "status", header: "Status" }]
|
|
11
|
+
const FILTERS: FilterConfig[] = [{ key: "search", label: "Search hidden metadata and resource names", type: FilterType.SEARCH }, { key: "status", label: "Publication and review status with a long translated label", type: FilterType.SELECT, options: [{ value: "Open", label: "Open" }, { value: "Closed", label: "Closed" }] }]
|
|
12
|
+
|
|
13
|
+
export default function ResourceIndexReference() {
|
|
14
|
+
const [filters, setFilters] = useState<ActiveFilter[]>([])
|
|
15
|
+
const [page, setPage] = useState(0)
|
|
16
|
+
const [rows, setRows] = useState<RecordRow[]>([])
|
|
17
|
+
const [hasNext, setHasNext] = useState(false)
|
|
18
|
+
const [pending, setPending] = useState(true)
|
|
19
|
+
const [error, setError] = useState<string>()
|
|
20
|
+
const [refresh, setRefresh] = useState(0)
|
|
21
|
+
const [selection, setSelection] = useState<Record<string, true>>({})
|
|
22
|
+
const [answeredQuery, setAnsweredQuery] = useState("")
|
|
23
|
+
const [commands, setCommands] = useState("")
|
|
24
|
+
const failNext = useRef(false)
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
let active = true
|
|
27
|
+
async function load() {
|
|
28
|
+
setPending(true); setError(undefined)
|
|
29
|
+
await new Promise(resolve => setTimeout(resolve, 250))
|
|
30
|
+
if (!active) return
|
|
31
|
+
if (failNext.current) { failNext.current = false; setError("Refresh failed. Previous rows remain available."); setPending(false); return }
|
|
32
|
+
const search = filters.find(filter => filter.key === "search")?.value[0]?.toLowerCase() ?? ""
|
|
33
|
+
const status = filters.find(filter => filter.key === "status")?.value[0]
|
|
34
|
+
const matches = RECORDS.filter(row => `${row.name} ${row.searchTerms}`.toLowerCase().includes(search) && (!status || row.status === status))
|
|
35
|
+
setAnsweredQuery(search); setRows(matches.slice(page * 2, page * 2 + 2)); setHasNext(matches.length > page * 2 + 2); setPending(false)
|
|
36
|
+
}
|
|
37
|
+
void load()
|
|
38
|
+
return () => { active = false }
|
|
39
|
+
}, [filters, page, refresh])
|
|
40
|
+
return <div style={{ width: "100%", minWidth: 0, maxWidth: "48rem" }}>
|
|
41
|
+
<Stack>
|
|
42
|
+
<Heading level={3}>Resource index</Heading>
|
|
43
|
+
<Text type="secondary">Server matching includes fields absent from the visible columns. Totals are unknown; selection applies to the current page.</Text>
|
|
44
|
+
{error && <Text role="alert" type="error">{error}</Text>}
|
|
45
|
+
<DataView data={rows} columns={COLUMNS} filtering={{ filters: FILTERS, activeFilters: filters, onFilterChange: next => { setFilters(next); setPage(0); setSelection({}) }, filterRows: ({ data }) => [...data], isFiltering: pending }}
|
|
46
|
+
table={{ enableColumnVisibility: true, enableRowSelection: true, getRowId: row => row.id, rowSelection: selection, onRowSelectionChange: setSelection, bulkActions: ({ selectedRows }) => <Button onClick={() => setCommands(`Selected-page command: ${selectedRows.map(row => row.id).join(", ")}`)}>Archive selected page rows</Button> }}
|
|
47
|
+
slots={{ topbarEnd: <Stack direction="horizontal" gap="sm" wrap><Button tone="neutral" appearance="outline" disabled={pending} onClick={() => setRefresh(count => count + 1)}>Refresh</Button><Button tone="neutral" appearance="outline" onClick={() => { failNext.current = true; setRefresh(count => count + 1) }}>Fail next refresh</Button><Button tone="neutral" appearance="outline" onClick={() => setCommands(`Export current page: ${rows.map(row => row.id).join(", ")}`)}>Export page</Button></Stack>, footer: <Stack direction="horizontal" wrap align="center"><Text>Total unknown; page {page + 1}</Text><Button disabled={pending || page === 0} onClick={() => { setPage(value => value - 1); setSelection({}) }}>Previous page</Button><Button disabled={pending || !hasNext} onClick={() => { setPage(value => value + 1); setSelection({}) }}>Next page</Button></Stack> }} />
|
|
48
|
+
<Text role="status">{pending ? "Loading page" : `${rows.length} rows supplied by server; matched ${answeredQuery || "all"}`}{commands && `; ${commands}`}</Text>
|
|
49
|
+
</Stack>
|
|
50
|
+
</div>
|
|
51
|
+
}
|
package/docs/generated/workflows/scoped-resource-selection/combobox/scoped-resource-reference.tsx
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { useState } from "react"
|
|
2
|
+
import { Button } from "themelia-ui/base/buttons"
|
|
3
|
+
import { FormField } from "themelia-ui/base/forms"
|
|
4
|
+
import { Overlay, OverlayTrigger, OverlayContent, OverlayHeader, OverlayTitle, OverlayDescription, OverlayBody } from "themelia-ui/base/overlay"
|
|
5
|
+
import { Stack } from "themelia-ui/base/structure"
|
|
6
|
+
import { Text } from "themelia-ui/base/typography"
|
|
7
|
+
import { ResourceCombobox } from "themelia-ui/features/combobox"
|
|
8
|
+
|
|
9
|
+
type Resource = { id: string; label: string }
|
|
10
|
+
type Mode = "results" | "pending" | "empty" | "error"
|
|
11
|
+
|
|
12
|
+
export default function ScopedResourceReference() {
|
|
13
|
+
const [scope, setScope] = useState("A")
|
|
14
|
+
const [mode, setMode] = useState<Mode>("results")
|
|
15
|
+
const [query, setQuery] = useState("")
|
|
16
|
+
const [value, setValue] = useState<Resource | null>({ id: "A-1", label: "A project" })
|
|
17
|
+
const [selections, setSelections] = useState(0)
|
|
18
|
+
const [submissions, setSubmissions] = useState(0)
|
|
19
|
+
const [completions, setCompletions] = useState(0)
|
|
20
|
+
return <Overlay>
|
|
21
|
+
<OverlayTrigger render={<Button />}>Choose scoped resource</OverlayTrigger>
|
|
22
|
+
<OverlayContent>
|
|
23
|
+
<OverlayHeader><OverlayTitle>Assign resource</OverlayTitle><OverlayDescription>Lookup validity belongs to a workspace. The application decides whether a selected resource remains valid.</OverlayDescription></OverlayHeader>
|
|
24
|
+
<OverlayBody>
|
|
25
|
+
<form onSubmit={event => { event.preventDefault(); setSubmissions(count => count + 1) }}>
|
|
26
|
+
<Stack>
|
|
27
|
+
<Stack direction="horizontal" gap="sm" wrap>
|
|
28
|
+
{["A", "B"].map(key => <Button key={key} tone="neutral" appearance="outline" onClick={() => { setScope(key); setValue(null) }}>Workspace {key}</Button>)}
|
|
29
|
+
</Stack>
|
|
30
|
+
<Stack direction="horizontal" gap="sm" wrap>
|
|
31
|
+
{(["results", "pending", "empty", "error"] as const).map(key => <Button key={key} tone="neutral" appearance="ghost" onClick={() => setMode(key)}>{key}</Button>)}
|
|
32
|
+
</Stack>
|
|
33
|
+
<FormField label="Resource" hint={`Searching workspace ${scope}`}>
|
|
34
|
+
<ResourceCombobox<Resource> scopeKey={`${scope}:${mode}`} value={value} onValueChange={next => { setValue(next); setSelections(count => count + 1) }} searchValue={query} onSearchValueChange={setQuery} debounceMs={100} getKey={item => item.id} getLabel={item => item.label}
|
|
35
|
+
fetcher={async ({ query: search, signal }) => {
|
|
36
|
+
// The mock deliberately ignores abort; the picker must suppress its late answer.
|
|
37
|
+
void signal
|
|
38
|
+
await new Promise(resolve => setTimeout(resolve, mode === "pending" ? 2400 : scope === "A" ? 600 : 80))
|
|
39
|
+
if (mode === "error") throw new Error("Lookup unavailable")
|
|
40
|
+
return mode === "empty" || (search && !"project".includes(search.toLowerCase())) ? [] : [{ id: `${scope}-1`, label: `${scope} project` }]
|
|
41
|
+
}} onAfterFetch={() => setCompletions(count => count + 1)} />
|
|
42
|
+
</FormField>
|
|
43
|
+
<Button type="submit">Assign</Button>
|
|
44
|
+
<Text role="status">Selections {selections}; submissions {submissions}; completions {completions}</Text>
|
|
45
|
+
</Stack>
|
|
46
|
+
</form>
|
|
47
|
+
</OverlayBody>
|
|
48
|
+
</OverlayContent>
|
|
49
|
+
</Overlay>
|
|
50
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { MediaLibraryItem } from "themelia-ui/features/media-library"
|
|
2
|
+
|
|
3
|
+
export const SAMPLE_MEDIA: MediaLibraryItem[] = [{ id: "image-1", name: "Garden exterior", type: "image", alt: "A garden with a stone path", collection: "site", public: true }, { id: "image-2", name: "Meeting room", type: "image", alt: "A meeting room with daylight", collection: "site", public: true }]
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { useState } from "react"
|
|
2
|
+
import { Button } from "themelia-ui/base/buttons"
|
|
3
|
+
import { Card } from "themelia-ui/base/cards"
|
|
4
|
+
import { PillRadioGroup } from "themelia-ui/base/choice-inputs"
|
|
5
|
+
import { FormField } from "themelia-ui/base/forms"
|
|
6
|
+
import { Stack } from "themelia-ui/base/structure"
|
|
7
|
+
import { Input } from "themelia-ui/base/text-inputs"
|
|
8
|
+
import { RichText, Text } from "themelia-ui/base/typography"
|
|
9
|
+
import { MediaLibraryDialog, type MediaLibraryItem } from "themelia-ui/features/media-library"
|
|
10
|
+
import { RichTextEditor } from "themelia-ui/features/rich-text-editor"
|
|
11
|
+
import { SAMPLE_MEDIA } from "../media-library/reference-data"
|
|
12
|
+
|
|
13
|
+
export default function WebsiteContentReference() {
|
|
14
|
+
const [locale, setLocale] = useState("en")
|
|
15
|
+
const [drafts, setDrafts] = useState<Record<string, string>>({ en: "<p>Welcome to our workspace.</p>", ar: "<p>مرحباً بكم</p>" })
|
|
16
|
+
const [mediaOpen, setMediaOpen] = useState(false)
|
|
17
|
+
const [image, setImage] = useState<MediaLibraryItem>()
|
|
18
|
+
const [alt, setAlt] = useState("")
|
|
19
|
+
const [failed, setFailed] = useState(true)
|
|
20
|
+
const [pending, setPending] = useState(false)
|
|
21
|
+
const [message, setMessage] = useState("Drafts are local until saved")
|
|
22
|
+
return <Card title="Website content" description="Each locale owns a retained draft. Preview sanitizes HTML; the application also validates and sanitizes persisted content.">
|
|
23
|
+
<Stack>
|
|
24
|
+
<PillRadioGroup aria-label="Content locale" name="reference-content-locale" value={locale} onValueChange={value => value && setLocale(value)} options={[{ value: "en", label: "English" }, { value: "ar", label: "العربية" }]} />
|
|
25
|
+
<div dir={locale === "ar" ? "rtl" : "ltr"}><RichTextEditor value={drafts[locale] ?? ""} onValueChange={html => setDrafts(current => ({ ...current, [locale]: html }))} /></div>
|
|
26
|
+
<MediaLibraryDialog open={mediaOpen} trigger={<Button tone="neutral" appearance="outline">Choose hero media</Button>} onOpenChange={setMediaOpen} items={SAMPLE_MEDIA} selectionMode="single" confirmOnSelect allowUpload={false} onConfirm={items => { const item = items[0]; setImage(item); setAlt(item?.alt ?? ""); setMediaOpen(false) }} />
|
|
27
|
+
{image && <FormField label="Hero image alternative text" hint={image.name}><Input value={alt} onChange={event => setAlt(event.target.value)} /></FormField>}
|
|
28
|
+
<Stack direction="horizontal" wrap gap="sm"><Button disabled={pending} onClick={async () => { if (pending) return; setPending(true); await new Promise(resolve => setTimeout(resolve, 250)); setMessage(failed ? "Save failed. All locale drafts and image text remain here." : "Mock website save completed"); setPending(false) }}>Save website content</Button><Button tone="neutral" appearance="outline" onClick={() => setFailed(value => !value)}>Toggle save failure</Button></Stack>
|
|
29
|
+
<Text role="status">{message}</Text>
|
|
30
|
+
<RichText html={drafts[locale] ?? ""} />
|
|
31
|
+
</Stack>
|
|
32
|
+
</Card>
|
|
33
|
+
}
|
package/docs/generated/workflows/workspace-navigation/app-shell/workspace-navigation-reference.tsx
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { useState } from "react"
|
|
2
|
+
import { Text } from "themelia-ui/base/typography"
|
|
3
|
+
import { TopbarSidebarLayout } from "themelia-ui/layout/app-shell"
|
|
4
|
+
import { AppSidebar, type LinkRenderer } from "themelia-ui/layout/sidebar"
|
|
5
|
+
|
|
6
|
+
export default function WorkspaceNavigationReference() {
|
|
7
|
+
const [route, setRoute] = useState("/a/overview")
|
|
8
|
+
const [navigations, setNavigations] = useState(0)
|
|
9
|
+
const workspace = route.startsWith("/b/") ? "B" : "A"
|
|
10
|
+
const renderLink: LinkRenderer = ({ href, children, external, active, disabled, onClick, ...props }) => {
|
|
11
|
+
void active
|
|
12
|
+
if (disabled || !href) return <span {...props}>{children}</span>
|
|
13
|
+
return <a {...props} href={href} target={props.target ?? (external ? "_blank" : undefined)} rel={props.rel ?? (external ? "noopener noreferrer" : undefined)} onClick={event => {
|
|
14
|
+
onClick?.(event)
|
|
15
|
+
if (event.defaultPrevented || external || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return
|
|
16
|
+
event.preventDefault(); setRoute(href); setNavigations(count => count + 1)
|
|
17
|
+
}}>{children}</a>
|
|
18
|
+
}
|
|
19
|
+
return <div style={{ width: "100%", height: "28rem", minWidth: 0 }}>
|
|
20
|
+
<TopbarSidebarLayout contained contentRender={<div />} logo="Reference workspace" sidebarProviderProps={{ persist: false, keyboardShortcut: false }} sidebar={<AppSidebar logo={`Workspace ${workspace}`} renderLink={renderLink} currentUrl={route}
|
|
21
|
+
workspaceLinks={[{ label: "Workspace A home", url: "/a/overview", external: false }, { label: "Workspace B home", url: "/b/overview", external: false }, { label: "External workspace", url: "https://example.com" }]}
|
|
22
|
+
navigationGroups={{ "": [{ label: `${workspace} overview`, href: `/${workspace.toLowerCase()}/overview` }, { label: `${workspace} settings`, href: `/${workspace.toLowerCase()}/settings` }] }} />}>
|
|
23
|
+
<Text role="status">Workspace {workspace}; route {route}; navigations {navigations}</Text>
|
|
24
|
+
</TopbarSidebarLayout>
|
|
25
|
+
</div>
|
|
26
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# API compatibility
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Exact package subpaths, exported names, callable signatures, and
|
|
4
4
|
exported props/type members are compatibility surfaces. Public global theme tokens, documented
|
|
5
5
|
`data-slot` and BEM hooks, and the `strings` contracts are also consumer contracts.
|
|
6
6
|
|
|
@@ -15,9 +15,10 @@ exported props/type members are compatibility surfaces. Public global theme toke
|
|
|
15
15
|
| a documented default changes | behavioural change; release notes required |
|
|
16
16
|
| component token or hashed CSS Module name changes | internal unless documented as an extension point |
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
3.1 includes breaking changes despite its minor version number: it removes obsolete aliases
|
|
19
|
+
and adapters. Removed names do not stay available solely for an
|
|
20
|
+
upgrade window. A breaking release records the replacement in the migration reference and
|
|
21
|
+
the changelog; consumers pin the old version until they are ready to update.
|
|
21
22
|
|
|
22
23
|
A removal, a newly required member or an incompatible type change ships with a migration
|
|
23
24
|
record: the [migration reference](../generated/migration.md) names each one with its
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Choosing and composing blocks
|
|
2
|
+
|
|
3
|
+
A structural block arranges regions; a subject block renders a recognizable job such as
|
|
4
|
+
metrics, onboarding or an order summary. Use [Structure and spacing](./structure-and-spacing.md)
|
|
5
|
+
for page geometry, surfaces and gaps. Start with a ready subject block when its vocabulary
|
|
6
|
+
fits the product, then use its documented props, callbacks or parts. The application keeps
|
|
7
|
+
data, permission checks, routing, mutation and persistence.
|
|
8
|
+
|
|
9
|
+
## Published subject modules
|
|
10
|
+
|
|
11
|
+
| Job | Exact subpath and examples | Application owns | Optional peers |
|
|
12
|
+
| --- | --- | --- | --- |
|
|
13
|
+
| Quantities, changes and plots | `themelia-ui/blocks/analytics`: MetricGrid, Metric, MetricComparison, ChartCard, ActivityHeatmap | Measures, period, comparison meaning, loading/errors and metric actions | `recharts`, for the module even when the adopted block has no plot |
|
|
14
|
+
| Setup tasks completed over time | `themelia-ui/blocks/onboarding`: Checklist | Step status, content, submission and persistence | None |
|
|
15
|
+
| Milestones, changelog or linear progress | `themelia-ui/blocks/timelines`: MilestonesTimeline, ChangelogTimeline, Steps, StepsBar | Sequence, status, dates and navigation | None |
|
|
16
|
+
| Permissions and credential management | `themelia-ui/blocks/admin/access`: RolePermissions, CredentialList, SensitiveAction | Authorization, actual secrets, deletion confirmation and mutations | None |
|
|
17
|
+
| Orders, invoices, inventory and payment summaries | `themelia-ui/blocks/admin/commerce`: OrderSummary, InvoiceLineItems, InventorySection, PaymentTimeline | Commerce records, calculation policy, commands and transport | None |
|
|
18
|
+
|
|
19
|
+
These are modules, not broad barrels: there is no `themelia-ui/blocks` import. General and
|
|
20
|
+
admin profiles come from the same installation. Admin is presentation vocabulary rather
|
|
21
|
+
than an authorization layer; importing an admin block does not protect its actions or data.
|
|
22
|
+
The generated [import table](../generated/imports.md) is authoritative for optional peers.
|
|
23
|
+
Do not assume a symbol is peer-free because its own UI looks simple.
|
|
24
|
+
|
|
25
|
+
Open the selected API before JSX: [analytics](../generated/components/blocks--analytics.md),
|
|
26
|
+
[onboarding](../generated/components/blocks--onboarding.md),
|
|
27
|
+
[timelines](../generated/components/blocks--timelines.md),
|
|
28
|
+
[admin access](../generated/components/blocks--admin--access.md), or
|
|
29
|
+
[admin commerce](../generated/components/blocks--admin--commerce.md).
|
|
30
|
+
They list exact record shapes, defaults, strings, dependencies and preview recipes.
|
|
31
|
+
|
|
32
|
+
## Facts versus quantities
|
|
33
|
+
|
|
34
|
+
MetadataList owns label/value facts such as owner, status, address or a date. A numeric
|
|
35
|
+
identifier is still a fact. MetricGrid/Metric own measures such as delivered messages,
|
|
36
|
+
revenue or a conversion rate, with optional comparison and trend. Put prose facts beside
|
|
37
|
+
quantities rather than turning every value into a metric tile.
|
|
38
|
+
|
|
39
|
+
```tsx compile
|
|
40
|
+
import { ContentBlock, MetadataList } from "themelia-ui/base/display"
|
|
41
|
+
import { Stack } from "themelia-ui/base/structure"
|
|
42
|
+
import { MetricGrid, type MetricData } from "themelia-ui/blocks/analytics"
|
|
43
|
+
import { Page } from "themelia-ui/layout/page"
|
|
44
|
+
|
|
45
|
+
const metrics: MetricData[] = [
|
|
46
|
+
{ id: "delivered", label: "Delivered", value: 248 },
|
|
47
|
+
{ id: "opened", label: "Opened", value: null, subtitle: "Tracking unavailable" },
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
export function DeliveryOverview() {
|
|
51
|
+
return <Page header={{ title: "Delivery overview", description: "Current campaign" }}>
|
|
52
|
+
<Stack>
|
|
53
|
+
<MetricGrid metrics={metrics} variant="card" />
|
|
54
|
+
<ContentBlock title="Campaign details">
|
|
55
|
+
<MetadataList items={[
|
|
56
|
+
{ id: "owner", label: "Owner", value: "Alex" },
|
|
57
|
+
{ id: "status", label: "Status", value: "Sending" },
|
|
58
|
+
]} />
|
|
59
|
+
</ContentBlock>
|
|
60
|
+
</Stack>
|
|
61
|
+
</Page>
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Use `null` for an unavailable MetricData value; zero means a measured zero. MetricGrid's
|
|
66
|
+
loading contract is for initial loading. For error or refresh behavior, inspect the adopted
|
|
67
|
+
component's exact API rather than assuming every analytics block accepts the same props.
|
|
68
|
+
The [communications workflow](./reference-workflows.md) demonstrates retained figures,
|
|
69
|
+
failure feedback, retry, unknown tracking and a separate facts region.
|
|
70
|
+
|
|
71
|
+
## Compose without duplicating owners
|
|
72
|
+
|
|
73
|
+
Inspect whether a block already owns its title, surface, controls and responsive layout
|
|
74
|
+
before surrounding it with another Card or Grid. MetricGrid already arranges tiles;
|
|
75
|
+
ChartCard already owns its chart frame; FormSection already owns an editable section's
|
|
76
|
+
header and inset. Use a sibling surface for an independent subject and ContentBlock for
|
|
77
|
+
supporting prose inside one. [Composition](./composition.md#decide-the-owners-before-jsx)
|
|
78
|
+
describes the owners in detail.
|
|
79
|
+
|
|
80
|
+
Keep default typography and spacing with those owners. Do not invent `size`, `padding`,
|
|
81
|
+
`error` or `strings` props by analogy with another block. Use a documented slot or render
|
|
82
|
+
prop for one region; use public parts or an application composition when the arrangement
|
|
83
|
+
must differ. No block needs every extension seam. The [composition ladder](../generated/composition-ladder.md)
|
|
84
|
+
is a discovery aid; the selected API remains the contract.
|
|
85
|
+
|
|
86
|
+
## Compose your own subject
|
|
87
|
+
|
|
88
|
+
When the ready block's vocabulary cannot express the product, start from its public
|
|
89
|
+
lower-tier recipe rather than copying internals. The live block pages include these
|
|
90
|
+
compose-your-own examples; their source is also embedded in
|
|
91
|
+
[recipes.json](../generated/recipes.json) under the exact id below and in the
|
|
92
|
+
[recipe book](../build/recipes.md). The recipe imports identify the adopted modules and
|
|
93
|
+
their peer requirements; they do not require importing the corresponding ready block.
|
|
94
|
+
|
|
95
|
+
| Subject | Recipe id | Public building blocks |
|
|
96
|
+
| --- | --- | --- |
|
|
97
|
+
| A custom measure | `analytics-blueprint` | Card, Stack, Money, Badge, Sparkline |
|
|
98
|
+
| Setup checklist | `blocks-checklist-blueprint` | Progress, Accordion, IconBadge, Text, Button |
|
|
99
|
+
| Release timeline | `blocks-changelog-blueprint` | Timeline, MonoValue, Badge |
|
|
100
|
+
| Role/permission summary | `blocks-roles-blueprint` | Table, Badge, VisuallyHidden |
|
|
101
|
+
| Custom order summary | `cart-summary-blueprint` | Card, MetadataList, Money, Button, toast |
|
|
102
|
+
|
|
103
|
+
For example, retrieve the exact checklist source from the installed package:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
node <<'NODE'
|
|
107
|
+
const fs = require('node:fs')
|
|
108
|
+
const { recipes } = JSON.parse(fs.readFileSync('node_modules/themelia-ui/docs/generated/recipes.json', 'utf8'))
|
|
109
|
+
const recipe = recipes.find(item => item.id === 'blocks-checklist-blueprint')
|
|
110
|
+
if (!recipe) throw new Error('Recipe missing from this installed version')
|
|
111
|
+
process.stdout.write(recipe.code)
|
|
112
|
+
NODE
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
These examples establish presentation seams, with fixed sample data and mock callbacks.
|
|
116
|
+
Keep the application's real permission model, calculations and completion state in its
|
|
117
|
+
own component. Use the [complete workflows](./reference-workflows.md) when the task needs
|
|
118
|
+
submission, lookup, selection or retained-draft behavior beyond a presentation recipe.
|
|
119
|
+
|
|
120
|
+
For translated copy, use the selected module's typed strings and exported defaults. Product
|
|
121
|
+
labels and record content remain application copy. Test permissions, loading/empty/error
|
|
122
|
+
states, long labels, keyboard interaction, RTL and the adopted density in the real route;
|
|
123
|
+
the package's previews do not establish application acceptance.
|