@coffer-org/web-ui 4.0.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/README.md +87 -0
- package/dist/Markdown.d.ts +4 -0
- package/dist/Markdown.js +13 -0
- package/dist/MarkdownEditor.d.ts +6 -0
- package/dist/MarkdownEditor.js +83 -0
- package/dist/actions/ActionButton.d.ts +7 -0
- package/dist/actions/ActionButton.js +54 -0
- package/dist/actions/PopupBody.d.ts +4 -0
- package/dist/actions/PopupBody.js +8 -0
- package/dist/actions/TemplateHost.d.ts +4 -0
- package/dist/actions/TemplateHost.js +36 -0
- package/dist/actions/registry.d.ts +20 -0
- package/dist/actions/registry.js +9 -0
- package/dist/components/ExtendReasonInfo.d.ts +6 -0
- package/dist/components/ExtendReasonInfo.js +12 -0
- package/dist/components/FavoriteButton.d.ts +8 -0
- package/dist/components/FavoriteButton.js +7 -0
- package/dist/components/Icon.d.ts +6 -0
- package/dist/components/Icon.js +12 -0
- package/dist/components/PageBody.d.ts +4 -0
- package/dist/components/PageBody.js +4 -0
- package/dist/components/RecordInline.d.ts +8 -0
- package/dist/components/RecordInline.js +29 -0
- package/dist/components/SaveStatus.d.ts +1 -0
- package/dist/components/SaveStatus.js +11 -0
- package/dist/components/Toolbar.d.ts +5 -0
- package/dist/components/Toolbar.js +4 -0
- package/dist/components/icons/color.d.ts +2 -0
- package/dist/components/icons/color.js +10 -0
- package/dist/components/icons/flag.d.ts +2 -0
- package/dist/components/icons/flag.js +6 -0
- package/dist/components/icons/lucide.d.ts +2 -0
- package/dist/components/icons/lucide.js +111 -0
- package/dist/components/icons/registry.d.ts +4 -0
- package/dist/components/icons/registry.js +22 -0
- package/dist/components/icons/simple.d.ts +2 -0
- package/dist/components/icons/simple.js +15 -0
- package/dist/components/icons/tabler.d.ts +2 -0
- package/dist/components/icons/tabler.js +11 -0
- package/dist/components/ui/FieldLabel.d.ts +9 -0
- package/dist/components/ui/FieldLabel.js +4 -0
- package/dist/components/ui/badge.d.ts +9 -0
- package/dist/components/ui/badge.js +19 -0
- package/dist/components/ui/button.d.ts +11 -0
- package/dist/components/ui/button.js +33 -0
- package/dist/components/ui/calendar.d.ts +8 -0
- package/dist/components/ui/calendar.js +72 -0
- package/dist/components/ui/card.d.ts +8 -0
- package/dist/components/ui/card.js +16 -0
- package/dist/components/ui/checkbox.d.ts +4 -0
- package/dist/components/ui/checkbox.js +8 -0
- package/dist/components/ui/chip-cls.d.ts +1 -0
- package/dist/components/ui/chip-cls.js +1 -0
- package/dist/components/ui/combobox.d.ts +24 -0
- package/dist/components/ui/combobox.js +58 -0
- package/dist/components/ui/confirm.d.ts +10 -0
- package/dist/components/ui/confirm.js +37 -0
- package/dist/components/ui/date-picker.d.ts +5 -0
- package/dist/components/ui/date-picker.js +16 -0
- package/dist/components/ui/dialog.d.ts +16 -0
- package/dist/components/ui/dialog.js +27 -0
- package/dist/components/ui/dropdown-menu.d.ts +15 -0
- package/dist/components/ui/dropdown-menu.js +18 -0
- package/dist/components/ui/input-group.d.ts +16 -0
- package/dist/components/ui/input-group.js +56 -0
- package/dist/components/ui/input.d.ts +3 -0
- package/dist/components/ui/input.js +6 -0
- package/dist/components/ui/label.d.ts +4 -0
- package/dist/components/ui/label.js +7 -0
- package/dist/components/ui/mask-input.d.ts +61 -0
- package/dist/components/ui/mask-input.js +1052 -0
- package/dist/components/ui/month-year-picker.d.ts +10 -0
- package/dist/components/ui/month-year-picker.js +46 -0
- package/dist/components/ui/option-icon.d.ts +15 -0
- package/dist/components/ui/option-icon.js +19 -0
- package/dist/components/ui/phone-input.d.ts +13 -0
- package/dist/components/ui/phone-input.js +53 -0
- package/dist/components/ui/popover.d.ts +11 -0
- package/dist/components/ui/popover.js +28 -0
- package/dist/components/ui/rating.d.ts +44 -0
- package/dist/components/ui/rating.js +501 -0
- package/dist/components/ui/scroll-area.d.ts +5 -0
- package/dist/components/ui/scroll-area.js +11 -0
- package/dist/components/ui/select-combobox.d.ts +25 -0
- package/dist/components/ui/select-combobox.js +36 -0
- package/dist/components/ui/select.d.ts +13 -0
- package/dist/components/ui/select.js +24 -0
- package/dist/components/ui/separator.d.ts +4 -0
- package/dist/components/ui/separator.js +7 -0
- package/dist/components/ui/switch.d.ts +4 -0
- package/dist/components/ui/switch.js +7 -0
- package/dist/components/ui/textarea.d.ts +3 -0
- package/dist/components/ui/textarea.js +6 -0
- package/dist/components/ui/time-picker.d.ts +84 -0
- package/dist/components/ui/time-picker.js +1258 -0
- package/dist/components/visually-hidden-input.d.ts +10 -0
- package/dist/components/visually-hidden-input.js +96 -0
- package/dist/hooks/use-as-ref.d.ts +3 -0
- package/dist/hooks/use-as-ref.js +10 -0
- package/dist/hooks/use-isomorphic-layout-effect.d.ts +3 -0
- package/dist/hooks/use-isomorphic-layout-effect.js +3 -0
- package/dist/hooks/use-lazy-ref.d.ts +3 -0
- package/dist/hooks/use-lazy-ref.js +9 -0
- package/dist/hooks/use-media-query.d.ts +3 -0
- package/dist/hooks/use-media-query.js +26 -0
- package/dist/host-services.d.ts +47 -0
- package/dist/host-services.js +35 -0
- package/dist/index.d.ts +70 -0
- package/dist/index.js +69 -0
- package/dist/layout.d.ts +29 -0
- package/dist/layout.js +323 -0
- package/dist/lib/cat-color.d.ts +1 -0
- package/dist/lib/cat-color.js +7 -0
- package/dist/lib/compose-refs.d.ts +5 -0
- package/dist/lib/compose-refs.js +38 -0
- package/dist/lib/date-format.d.ts +9 -0
- package/dist/lib/date-format.js +31 -0
- package/dist/lib/format.d.ts +14 -0
- package/dist/lib/format.js +34 -0
- package/dist/lib/json.d.ts +1 -0
- package/dist/lib/json.js +12 -0
- package/dist/lib/multi-value.d.ts +3 -0
- package/dist/lib/multi-value.js +22 -0
- package/dist/lib/record-option.d.ts +7 -0
- package/dist/lib/record-option.js +52 -0
- package/dist/lib/use-record-labels.d.ts +14 -0
- package/dist/lib/use-record-labels.js +130 -0
- package/dist/lib/utils.d.ts +2 -0
- package/dist/lib/utils.js +5 -0
- package/dist/list-view.d.ts +26 -0
- package/dist/list-view.js +11 -0
- package/dist/markdown/blocks.d.ts +10 -0
- package/dist/markdown/blocks.js +57 -0
- package/dist/markdown/extensions.d.ts +6 -0
- package/dist/markdown/extensions.js +25 -0
- package/dist/markdown/slash.d.ts +23 -0
- package/dist/markdown/slash.js +27 -0
- package/dist/markdown/toolbar.d.ts +13 -0
- package/dist/markdown/toolbar.js +119 -0
- package/dist/plugin-ui.d.ts +43 -0
- package/dist/plugin-ui.js +37 -0
- package/dist/registry.d.ts +26 -0
- package/dist/registry.js +169 -0
- package/dist/render/blocks/accordion.d.ts +1 -0
- package/dist/render/blocks/accordion.js +15 -0
- package/dist/render/blocks/aside.d.ts +1 -0
- package/dist/render/blocks/aside.js +14 -0
- package/dist/render/blocks/balance.d.ts +1 -0
- package/dist/render/blocks/balance.js +14 -0
- package/dist/render/blocks/bento.d.ts +1 -0
- package/dist/render/blocks/bento.js +24 -0
- package/dist/render/blocks/block-shell.d.ts +15 -0
- package/dist/render/blocks/block-shell.js +20 -0
- package/dist/render/blocks/calendar.d.ts +1 -0
- package/dist/render/blocks/calendar.js +142 -0
- package/dist/render/blocks/callout.d.ts +1 -0
- package/dist/render/blocks/callout.js +21 -0
- package/dist/render/blocks/chart.d.ts +1 -0
- package/dist/render/blocks/chart.js +46 -0
- package/dist/render/blocks/compare.d.ts +1 -0
- package/dist/render/blocks/compare.js +16 -0
- package/dist/render/blocks/countdown.d.ts +1 -0
- package/dist/render/blocks/countdown.js +36 -0
- package/dist/render/blocks/deck.d.ts +1 -0
- package/dist/render/blocks/deck.js +29 -0
- package/dist/render/blocks/epigraph.d.ts +1 -0
- package/dist/render/blocks/epigraph.js +13 -0
- package/dist/render/blocks/facets.d.ts +1 -0
- package/dist/render/blocks/facets.js +23 -0
- package/dist/render/blocks/figure.d.ts +1 -0
- package/dist/render/blocks/figure.js +13 -0
- package/dist/render/blocks/grid.d.ts +1 -0
- package/dist/render/blocks/grid.js +21 -0
- package/dist/render/blocks/heatmap.d.ts +1 -0
- package/dist/render/blocks/heatmap.js +135 -0
- package/dist/render/blocks/idcard.d.ts +1 -0
- package/dist/render/blocks/idcard.js +30 -0
- package/dist/render/blocks/identity.d.ts +1 -0
- package/dist/render/blocks/identity.js +46 -0
- package/dist/render/blocks/index.d.ts +40 -0
- package/dist/render/blocks/index.js +40 -0
- package/dist/render/blocks/journal.d.ts +1 -0
- package/dist/render/blocks/journal.js +50 -0
- package/dist/render/blocks/ledger.d.ts +1 -0
- package/dist/render/blocks/ledger.js +23 -0
- package/dist/render/blocks/manifest.d.ts +1 -0
- package/dist/render/blocks/manifest.js +50 -0
- package/dist/render/blocks/masthead.d.ts +1 -0
- package/dist/render/blocks/masthead.js +15 -0
- package/dist/render/blocks/meter.d.ts +1 -0
- package/dist/render/blocks/meter.js +32 -0
- package/dist/render/blocks/nutrition.d.ts +1 -0
- package/dist/render/blocks/nutrition.js +27 -0
- package/dist/render/blocks/people.d.ts +1 -0
- package/dist/render/blocks/people.js +35 -0
- package/dist/render/blocks/plaque.d.ts +1 -0
- package/dist/render/blocks/plaque.js +15 -0
- package/dist/render/blocks/properties.d.ts +1 -0
- package/dist/render/blocks/properties.js +22 -0
- package/dist/render/blocks/prose.d.ts +1 -0
- package/dist/render/blocks/prose.js +17 -0
- package/dist/render/blocks/receipt.d.ts +1 -0
- package/dist/render/blocks/receipt.js +23 -0
- package/dist/render/blocks/registry.d.ts +16 -0
- package/dist/render/blocks/registry.js +7 -0
- package/dist/render/blocks/relation-source.d.ts +2 -0
- package/dist/render/blocks/relation-source.js +6 -0
- package/dist/render/blocks/route.d.ts +1 -0
- package/dist/render/blocks/route.js +23 -0
- package/dist/render/blocks/score.d.ts +1 -0
- package/dist/render/blocks/score.js +15 -0
- package/dist/render/blocks/series.d.ts +23 -0
- package/dist/render/blocks/series.js +57 -0
- package/dist/render/blocks/specimen.d.ts +1 -0
- package/dist/render/blocks/specimen.js +19 -0
- package/dist/render/blocks/split.d.ts +1 -0
- package/dist/render/blocks/split.js +15 -0
- package/dist/render/blocks/spread.d.ts +1 -0
- package/dist/render/blocks/spread.js +15 -0
- package/dist/render/blocks/stack.d.ts +1 -0
- package/dist/render/blocks/stack.js +15 -0
- package/dist/render/blocks/stats.d.ts +1 -0
- package/dist/render/blocks/stats.js +23 -0
- package/dist/render/blocks/status.d.ts +1 -0
- package/dist/render/blocks/status.js +18 -0
- package/dist/render/blocks/table.d.ts +11 -0
- package/dist/render/blocks/table.js +136 -0
- package/dist/render/blocks/tabs.d.ts +1 -0
- package/dist/render/blocks/tabs.js +17 -0
- package/dist/render/blocks/terminal.d.ts +1 -0
- package/dist/render/blocks/terminal.js +18 -0
- package/dist/render/blocks/timeline.d.ts +1 -0
- package/dist/render/blocks/timeline.js +31 -0
- package/dist/render/box.d.ts +5 -0
- package/dist/render/box.js +23 -0
- package/dist/render/chrome.d.ts +64 -0
- package/dist/render/chrome.js +92 -0
- package/dist/render/core/amount.d.ts +1 -0
- package/dist/render/core/amount.js +19 -0
- package/dist/render/core/attachment.d.ts +29 -0
- package/dist/render/core/attachment.js +102 -0
- package/dist/render/core/choice.d.ts +1 -0
- package/dist/render/core/choice.js +40 -0
- package/dist/render/core/composite.d.ts +1 -0
- package/dist/render/core/composite.js +132 -0
- package/dist/render/core/datetime.d.ts +2 -0
- package/dist/render/core/datetime.js +215 -0
- package/dist/render/core/dimensions.d.ts +1 -0
- package/dist/render/core/dimensions.js +44 -0
- package/dist/render/core/embed.d.ts +11 -0
- package/dist/render/core/embed.js +99 -0
- package/dist/render/core/file.d.ts +12 -0
- package/dist/render/core/file.js +238 -0
- package/dist/render/core/illustrated.d.ts +39 -0
- package/dist/render/core/illustrated.js +113 -0
- package/dist/render/core/index.d.ts +23 -0
- package/dist/render/core/index.js +23 -0
- package/dist/render/core/layout-elements.d.ts +1 -0
- package/dist/render/core/layout-elements.js +78 -0
- package/dist/render/core/localpath.d.ts +6 -0
- package/dist/render/core/localpath.js +73 -0
- package/dist/render/core/money.d.ts +1 -0
- package/dist/render/core/money.js +39 -0
- package/dist/render/core/number.d.ts +17 -0
- package/dist/render/core/number.js +104 -0
- package/dist/render/core/period.d.ts +1 -0
- package/dist/render/core/period.js +60 -0
- package/dist/render/core/range.d.ts +1 -0
- package/dist/render/core/range.js +55 -0
- package/dist/render/core/reminder.d.ts +2 -0
- package/dist/render/core/reminder.js +56 -0
- package/dist/render/core/source.d.ts +3 -0
- package/dist/render/core/source.js +65 -0
- package/dist/render/core/stepper.d.ts +1 -0
- package/dist/render/core/stepper.js +81 -0
- package/dist/render/core/storage-group.d.ts +1 -0
- package/dist/render/core/storage-group.js +30 -0
- package/dist/render/core/text.d.ts +15 -0
- package/dist/render/core/text.js +370 -0
- package/dist/render/core/tristate.d.ts +1 -0
- package/dist/render/core/tristate.js +42 -0
- package/dist/render/core/weight.d.ts +4 -0
- package/dist/render/core/weight.js +38 -0
- package/dist/render/dispatch.d.ts +12 -0
- package/dist/render/dispatch.js +53 -0
- package/dist/render/display-override.d.ts +25 -0
- package/dist/render/display-override.js +23 -0
- package/dist/render/editor-mode.d.ts +4 -0
- package/dist/render/editor-mode.js +11 -0
- package/dist/render/field-address.d.ts +14 -0
- package/dist/render/field-address.js +10 -0
- package/dist/render/field-errors.d.ts +8 -0
- package/dist/render/field-errors.js +25 -0
- package/dist/render/field-frame.d.ts +20 -0
- package/dist/render/field-frame.js +78 -0
- package/dist/render/field-scope.d.ts +8 -0
- package/dist/render/field-scope.js +25 -0
- package/dist/render/field-width.d.ts +7 -0
- package/dist/render/field-width.js +12 -0
- package/dist/render/form-types.d.ts +12 -0
- package/dist/render/form-types.js +1 -0
- package/dist/render/hybrid-scope.d.ts +5 -0
- package/dist/render/hybrid-scope.js +9 -0
- package/dist/render/image.d.ts +64 -0
- package/dist/render/image.js +322 -0
- package/dist/render/live-kind.d.ts +7 -0
- package/dist/render/live-kind.js +104 -0
- package/dist/render/markdown-view.d.ts +5 -0
- package/dist/render/markdown-view.js +17 -0
- package/dist/render/multi.d.ts +10 -0
- package/dist/render/multi.js +26 -0
- package/dist/render/multiple-chips.d.ts +24 -0
- package/dist/render/multiple-chips.js +18 -0
- package/dist/render/option-list.d.ts +15 -0
- package/dist/render/option-list.js +47 -0
- package/dist/render/option-value.d.ts +20 -0
- package/dist/render/option-value.js +41 -0
- package/dist/render/picker-scrim.d.ts +7 -0
- package/dist/render/picker-scrim.js +32 -0
- package/dist/render/picker-surface.d.ts +5 -0
- package/dist/render/picker-surface.js +9 -0
- package/dist/render/popover-field.d.ts +16 -0
- package/dist/render/popover-field.js +153 -0
- package/dist/render/record-save-ctx.d.ts +11 -0
- package/dist/render/record-save-ctx.js +41 -0
- package/dist/render/shared.d.ts +92 -0
- package/dist/render/shared.js +182 -0
- package/dist/render/slot.d.ts +45 -0
- package/dist/render/slot.js +194 -0
- package/dist/render/sort-rows.d.ts +3 -0
- package/dist/render/sort-rows.js +38 -0
- package/dist/render/use-collection-rows.d.ts +10 -0
- package/dist/render/use-collection-rows.js +11 -0
- package/dist/render/use-field-edit.d.ts +28 -0
- package/dist/render/use-field-edit.js +50 -0
- package/dist/render/use-file-upload.d.ts +10 -0
- package/dist/render/use-file-upload.js +35 -0
- package/dist/render/use-form-bridge.d.ts +21 -0
- package/dist/render/use-form-bridge.js +53 -0
- package/dist/render/use-hybrid.d.ts +2 -0
- package/dist/render/use-hybrid.js +5 -0
- package/dist/render/widgets/attachment-group.d.ts +1 -0
- package/dist/render/widgets/attachment-group.js +35 -0
- package/dist/render/widgets/checklist-content.d.ts +15 -0
- package/dist/render/widgets/checklist-content.js +12 -0
- package/dist/render/widgets/checklist-group.d.ts +11 -0
- package/dist/render/widgets/checklist-group.js +47 -0
- package/dist/render/widgets/checklist-row.d.ts +14 -0
- package/dist/render/widgets/checklist-row.js +14 -0
- package/dist/render/widgets/display.d.ts +33 -0
- package/dist/render/widgets/display.js +97 -0
- package/dist/render/widgets/edit.d.ts +63 -0
- package/dist/render/widgets/edit.js +283 -0
- package/dist/render/widgets/fixed-collection.d.ts +11 -0
- package/dist/render/widgets/fixed-collection.js +34 -0
- package/dist/render/widgets/flow-row.d.ts +14 -0
- package/dist/render/widgets/flow-row.js +27 -0
- package/dist/render/widgets/group-edit.d.ts +9 -0
- package/dist/render/widgets/group-edit.js +23 -0
- package/dist/render/widgets/group-field.d.ts +9 -0
- package/dist/render/widgets/group-field.js +42 -0
- package/dist/render/widgets/group-widgets.d.ts +2 -0
- package/dist/render/widgets/group-widgets.js +41 -0
- package/dist/render/widgets/group.d.ts +26 -0
- package/dist/render/widgets/group.js +139 -0
- package/dist/render/widgets/illustrated-group.d.ts +1 -0
- package/dist/render/widgets/illustrated-group.js +41 -0
- package/dist/render/widgets/table-group.d.ts +11 -0
- package/dist/render/widgets/table-group.js +58 -0
- package/dist/render/widgets/two-cell-group.d.ts +21 -0
- package/dist/render/widgets/two-cell-group.js +42 -0
- package/dist/render/widgets/url-widget.d.ts +7 -0
- package/dist/render/widgets/url-widget.js +15 -0
- package/dist/render/widgets/weekday-grid.d.ts +13 -0
- package/dist/render/widgets/weekday-grid.js +47 -0
- package/dist/render/write.d.ts +5 -0
- package/dist/render/write.js +14 -0
- package/dist/schema-registry.d.ts +6 -0
- package/dist/schema-registry.js +25 -0
- package/dist/site-links.d.ts +13 -0
- package/dist/site-links.js +18 -0
- package/dist/strip-markdown.d.ts +1 -0
- package/dist/strip-markdown.js +11 -0
- package/dist/theme.css +189 -0
- package/dist/types.d.ts +84 -0
- package/dist/types.js +1 -0
- package/package.json +85 -0
package/README.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# @coffer-org/web-ui
|
|
2
|
+
|
|
3
|
+
The UI contract for Coffer plugin **web bundles**. A plugin's `dist/web.js` is
|
|
4
|
+
loaded at runtime by the host's federation loader; this package defines what that
|
|
5
|
+
bundle declares (`PluginUIBundle`) and the field-renderer registry it plugs into.
|
|
6
|
+
|
|
7
|
+
## What a web bundle exports
|
|
8
|
+
|
|
9
|
+
`web.js` **default-exports** a single `PluginUIBundle` — one bundle, not an array:
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
export default PluginUIBundle;
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Build one with `definePluginUI(bundle)`:
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import { definePluginUI } from '@coffer-org/web-ui';
|
|
19
|
+
|
|
20
|
+
export default definePluginUI({
|
|
21
|
+
// shelf?: { library, shelf, RecordView? } — only needed for a custom
|
|
22
|
+
// RecordView (replaces the generic RecordContent) tied to one shelf
|
|
23
|
+
// renderers?: FieldRenderer[] — own field-type renderers (each carries kinds[])
|
|
24
|
+
// listViews?: ListViewDef[] — own list-view kinds
|
|
25
|
+
// templates?: Record<string, TemplateImporter<any>> — action-result templates
|
|
26
|
+
// translations?: Partial<Record<'uk' | 'ru' | 'en', Record<string, unknown>>>
|
|
27
|
+
// slots?/routes?/nav?: contributions to the app shell (overlay, SPA routes, sidebar nav)
|
|
28
|
+
translations: { en: { 'myplugin.hello': 'Hello from myplugin' } },
|
|
29
|
+
});
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`definePluginUI` is the identity function — it exists so every plugin's `ui.tsx`
|
|
33
|
+
has one recognizable call, not three. There is no per-plugin choice to make: a
|
|
34
|
+
`ui.tsx` that only needs a `RecordView`, one that only needs `renderers`, and one
|
|
35
|
+
that only needs `slots` all call the same factory with the same type.
|
|
36
|
+
|
|
37
|
+
The host's federation loader applies the bundle once: `applyWebBundle`
|
|
38
|
+
(`packages/web/federation.ts`) forwards `slots`/`routes`/`nav` to `applyAppUI`
|
|
39
|
+
(this package) and itself registers `shelf.RecordView` for `shelf.library/shelf`,
|
|
40
|
+
calls `registerRenderer`/`registerListView` for `renderers`/`listViews`, and merges
|
|
41
|
+
`translations` into the global i18next instance.
|
|
42
|
+
|
|
43
|
+
## Vendor singleton model (importmap)
|
|
44
|
+
|
|
45
|
+
Plugin web bundles must **not** ship their own copy of React, i18next, or
|
|
46
|
+
`@coffer-org/web-ui` — they share the host's. The host publishes one vendor bundle
|
|
47
|
+
under `/vendor/*` and wires an [import map](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap)
|
|
48
|
+
so every bare specifier resolves to that single instance:
|
|
49
|
+
|
|
50
|
+
```html
|
|
51
|
+
<script type="importmap">
|
|
52
|
+
{
|
|
53
|
+
"imports": {
|
|
54
|
+
"react": "/vendor/react.js",
|
|
55
|
+
"react-dom": "/vendor/react-dom.js",
|
|
56
|
+
"i18next": "/vendor/i18next.js",
|
|
57
|
+
"@coffer-org/web-ui": "/vendor/web-ui.js"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
</script>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
This keeps a single React (so hooks/context work across bundles) and a single
|
|
64
|
+
i18next (so `addResourceBundle` merges into the one live instance). In dev, Vite
|
|
65
|
+
resolves these specifiers via its own aliases, so the import map is a prod-only
|
|
66
|
+
concern.
|
|
67
|
+
|
|
68
|
+
## Supported vendor majors
|
|
69
|
+
|
|
70
|
+
| Vendor | Range |
|
|
71
|
+
| --------------------- | ---------------------------- |
|
|
72
|
+
| `react` / `react-dom` | **19** (`>=19`) |
|
|
73
|
+
| `i18next` | **26** (23+ host-compatible) |
|
|
74
|
+
|
|
75
|
+
A scaffolded plugin declares these as **peer** dependencies (see
|
|
76
|
+
`create-coffer-plugin`'s `package.json` template), so it builds against the
|
|
77
|
+
host's instance instead of bundling its own.
|
|
78
|
+
|
|
79
|
+
## Mismatched vendor versions warn, don't block
|
|
80
|
+
|
|
81
|
+
The import map always resolves a plugin's `react` / `react-dom` / `i18next` /
|
|
82
|
+
`@coffer-org/web-ui` imports to the host's single instance — there is no runtime
|
|
83
|
+
version gate that refuses to load a bundle. A vendor-major mismatch surfaces as a
|
|
84
|
+
**peer-dependency warning at install/build time**, not a hard runtime failure: a
|
|
85
|
+
plugin built against an older major still loads against the host's instance and
|
|
86
|
+
runs as far as the shared API allows. Keep peers in range to avoid surprises; a
|
|
87
|
+
mismatch is a warning, not a block.
|
package/dist/Markdown.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { micromark } from 'micromark';
|
|
3
|
+
import { gfm, gfmHtml } from 'micromark-extension-gfm';
|
|
4
|
+
export function renderMarkdown(src) {
|
|
5
|
+
return micromark(src, {
|
|
6
|
+
allowDangerousHtml: true,
|
|
7
|
+
extensions: [gfm()],
|
|
8
|
+
htmlExtensions: [gfmHtml()],
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
export default function Markdown({ value }) {
|
|
12
|
+
return _jsx("div", { className: "md-static", dangerouslySetInnerHTML: { __html: renderMarkdown(value) } });
|
|
13
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
3
|
+
import { EditorContent, useEditor } from '@tiptap/react';
|
|
4
|
+
import { useTranslation } from 'react-i18next';
|
|
5
|
+
import { markdownExtensions } from "./markdown/extensions.js";
|
|
6
|
+
import { BLOCKS } from "./markdown/blocks.js";
|
|
7
|
+
import { Toolbar } from "./markdown/toolbar.js";
|
|
8
|
+
const markdownOf = (editor) => editor && !editor.isDestroyed ? editor.storage.markdown : undefined;
|
|
9
|
+
export default function MarkdownEditor({ value, onChange, placeholder, readonly, }) {
|
|
10
|
+
const { t } = useTranslation();
|
|
11
|
+
const [slash, setSlash] = useState(null);
|
|
12
|
+
const slashRef = useRef(null);
|
|
13
|
+
slashRef.current = slash;
|
|
14
|
+
const label = (key) => t(`form.md.${key}`);
|
|
15
|
+
const labelRef = useRef(label);
|
|
16
|
+
labelRef.current = label;
|
|
17
|
+
const handlers = useMemo(() => ({
|
|
18
|
+
filter: (query) => {
|
|
19
|
+
const q = query.trim().toLowerCase();
|
|
20
|
+
const items = BLOCKS.map((block) => ({
|
|
21
|
+
key: block.key,
|
|
22
|
+
run: ({ editor: e, range }) => block.run(e, range),
|
|
23
|
+
}));
|
|
24
|
+
if (!q)
|
|
25
|
+
return items;
|
|
26
|
+
return items.filter((item) => item.key.toLowerCase().includes(q) || labelRef.current(item.key).toLowerCase().includes(q));
|
|
27
|
+
},
|
|
28
|
+
open: ({ rect, items, pick }) => setSlash((prev) => ({ rect, items, pick, index: prev && prev.index < items.length ? prev.index : 0 })),
|
|
29
|
+
close: () => setSlash(null),
|
|
30
|
+
keyDown: (event) => {
|
|
31
|
+
const current = slashRef.current;
|
|
32
|
+
if (!current)
|
|
33
|
+
return false;
|
|
34
|
+
const last = current.items.length - 1;
|
|
35
|
+
if (event.key === 'ArrowDown') {
|
|
36
|
+
setSlash({ ...current, index: current.index >= last ? 0 : current.index + 1 });
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
if (event.key === 'ArrowUp') {
|
|
40
|
+
setSlash({ ...current, index: current.index <= 0 ? last : current.index - 1 });
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
if (event.key === 'Enter') {
|
|
44
|
+
const item = current.items[current.index];
|
|
45
|
+
if (!item)
|
|
46
|
+
return false;
|
|
47
|
+
current.pick(item);
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
if (event.key === 'Escape') {
|
|
51
|
+
setSlash(null);
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
return false;
|
|
55
|
+
},
|
|
56
|
+
}), []);
|
|
57
|
+
const editor = useEditor({
|
|
58
|
+
editable: !readonly,
|
|
59
|
+
extensions: markdownExtensions({ placeholder: readonly ? undefined : placeholder, slash: handlers }),
|
|
60
|
+
content: value,
|
|
61
|
+
autofocus: false,
|
|
62
|
+
onUpdate: ({ editor: e }) => {
|
|
63
|
+
const markdown = markdownOf(e);
|
|
64
|
+
if (markdown)
|
|
65
|
+
onChange?.(markdown.getMarkdown());
|
|
66
|
+
},
|
|
67
|
+
editorProps: { attributes: { class: 'md-static outline-none' } },
|
|
68
|
+
});
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
const markdown = markdownOf(editor);
|
|
71
|
+
if (!editor || !markdown)
|
|
72
|
+
return;
|
|
73
|
+
if (value === markdown.getMarkdown())
|
|
74
|
+
return;
|
|
75
|
+
editor.commands.setContent(value, { emitUpdate: false });
|
|
76
|
+
}, [editor, value]);
|
|
77
|
+
if (!editor || editor.isDestroyed)
|
|
78
|
+
return null;
|
|
79
|
+
return (_jsxs("div", { className: "flex min-h-0 min-w-0 flex-1 flex-col gap-1.5 md:gap-2", children: [!readonly && _jsx(Toolbar, { editor: editor }), _jsx(EditorContent, { editor: editor, className: "min-h-48 w-full min-w-0 max-w-full flex-1 overflow-y-auto rounded-lg border border-border bg-bg px-2 py-1.5 transition-colors focus-within:border-accent md:min-h-64 md:rounded-xl md:px-4 md:py-3" }), slash && slash.items.length > 0 && (_jsx("div", { role: "listbox", className: "fixed z-50 max-h-64 w-56 overflow-y-auto rounded-lg border border-border bg-surface p-1 shadow-lg", style: { top: (slash.rect?.bottom ?? 0) + 4, left: slash.rect?.left ?? 0 }, children: slash.items.map((item, i) => {
|
|
80
|
+
const Icon = BLOCKS.find((b) => b.key === item.key)?.icon;
|
|
81
|
+
return (_jsxs("button", { type: "button", role: "option", "aria-selected": i === slash.index, onMouseEnter: () => setSlash({ ...slash, index: i }), onClick: () => slash.pick(item), className: `flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm ${i === slash.index ? 'bg-elevated text-text' : 'text-muted'}`, children: [Icon && _jsx(Icon, { size: 15, className: "shrink-0" }), label(item.key)] }, item.key));
|
|
82
|
+
}) }))] }));
|
|
83
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ButtonEl } from '@coffer-org/sdk/fields';
|
|
2
|
+
import { type ActionContext } from './registry.ts';
|
|
3
|
+
export declare function ActionButton({ el, ctx, disabled }: {
|
|
4
|
+
el: ButtonEl;
|
|
5
|
+
ctx: ActionContext;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import { toast } from 'sonner';
|
|
5
|
+
import { Button } from "../components/ui/button.js";
|
|
6
|
+
import { Icon } from "../components/Icon.js";
|
|
7
|
+
import { Dialog, DialogContent, DialogHeader } from "../components/ui/dialog.js";
|
|
8
|
+
import { resolveAction } from "./registry.js";
|
|
9
|
+
import { TemplateHost } from "./TemplateHost.js";
|
|
10
|
+
import { PopupBody } from "./PopupBody.js";
|
|
11
|
+
export function ActionButton({ el, ctx, disabled }) {
|
|
12
|
+
const { t } = useTranslation();
|
|
13
|
+
const [loading, setLoading] = useState(false);
|
|
14
|
+
const [popup, setPopup] = useState(null);
|
|
15
|
+
const show = (ui) => {
|
|
16
|
+
if (ui.kind === 'popup') {
|
|
17
|
+
setPopup(ui);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const body = ui.component ? (_jsx(TemplateHost, { name: ui.component.name, data: ui.component.data })) : (t(ui.message ?? '', ui.params));
|
|
21
|
+
if (ui.variant === 'success')
|
|
22
|
+
toast.success(body);
|
|
23
|
+
else if (ui.variant === 'error')
|
|
24
|
+
toast.error(body);
|
|
25
|
+
else
|
|
26
|
+
toast(body);
|
|
27
|
+
};
|
|
28
|
+
const run = async () => {
|
|
29
|
+
const handler = resolveAction(el.value);
|
|
30
|
+
if (!handler) {
|
|
31
|
+
toast.error(t('actions.actionNotFound'));
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
setLoading(true);
|
|
35
|
+
try {
|
|
36
|
+
const res = await handler(ctx);
|
|
37
|
+
if (res)
|
|
38
|
+
show(res);
|
|
39
|
+
else
|
|
40
|
+
toast.success(t('actions.actionSuccess'));
|
|
41
|
+
}
|
|
42
|
+
catch (e) {
|
|
43
|
+
const ui = e.ui;
|
|
44
|
+
if (ui)
|
|
45
|
+
show(ui);
|
|
46
|
+
else
|
|
47
|
+
toast.error(e instanceof Error ? e.message : t('actions.actionError'));
|
|
48
|
+
}
|
|
49
|
+
finally {
|
|
50
|
+
setLoading(false);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
return (_jsxs(_Fragment, { children: [_jsxs(Button, { variant: el.variant ?? 'outline', onClick: run, disabled: disabled || loading, children: [loading ? (_jsx("span", { className: "animate-spin inline-block w-4 h-4 border-2 border-current/30 border-t-current rounded-full" })) : (el.icon && _jsx(Icon, { name: el.icon, size: 16 })), t(el.label)] }), _jsx(Dialog, { open: !!popup, onOpenChange: (o) => !o && setPopup(null), children: _jsx(DialogContent, { children: _jsx(DialogHeader, { children: popup && _jsx(PopupBody, { ui: popup }) }) }) })] }));
|
|
54
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { DialogTitle, DialogDescription } from "../components/ui/dialog.js";
|
|
4
|
+
import { TemplateHost } from "./TemplateHost.js";
|
|
5
|
+
export function PopupBody({ ui }) {
|
|
6
|
+
const { t } = useTranslation();
|
|
7
|
+
return (_jsxs(_Fragment, { children: [_jsx(DialogTitle, { children: ui.title ? t(ui.title, ui.params) : t('actions.notice') }), ui.component ? (_jsx(TemplateHost, { name: ui.component.name, data: ui.component.data })) : (_jsx(DialogDescription, { children: t(ui.message ?? '', ui.params) }))] }));
|
|
8
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { Component, lazy, Suspense } from 'react';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import { resolveTemplate } from "../registry.js";
|
|
5
|
+
const cache = new Map();
|
|
6
|
+
function lazyFor(name) {
|
|
7
|
+
const importer = resolveTemplate(name);
|
|
8
|
+
if (!importer)
|
|
9
|
+
return null;
|
|
10
|
+
let c = cache.get(name);
|
|
11
|
+
if (!c) {
|
|
12
|
+
c = lazy(importer);
|
|
13
|
+
cache.set(name, c);
|
|
14
|
+
}
|
|
15
|
+
return c;
|
|
16
|
+
}
|
|
17
|
+
class Boundary extends Component {
|
|
18
|
+
state = { failed: false };
|
|
19
|
+
static getDerivedStateFromError() {
|
|
20
|
+
return { failed: true };
|
|
21
|
+
}
|
|
22
|
+
render() {
|
|
23
|
+
return this.state.failed ? this.props.fallback : this.props.children;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const Spinner = () => (_jsx("span", { className: "animate-spin inline-block w-4 h-4 border-2 border-current/30 border-t-current rounded-full" }));
|
|
27
|
+
export function TemplateHost({ name, data }) {
|
|
28
|
+
const { t } = useTranslation();
|
|
29
|
+
const fallback = _jsx(_Fragment, { children: t('actions.notice') });
|
|
30
|
+
const Cmp = lazyFor(name);
|
|
31
|
+
if (!Cmp) {
|
|
32
|
+
console.warn(`[template] unknown '${name}'`);
|
|
33
|
+
return fallback;
|
|
34
|
+
}
|
|
35
|
+
return (_jsx(Boundary, { fallback: fallback, children: _jsx(Suspense, { fallback: _jsx(Spinner, {}), children: _jsx(Cmp, { data: data, t: t }) }) }));
|
|
36
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface ActionContext {
|
|
2
|
+
library: string;
|
|
3
|
+
shelf: string;
|
|
4
|
+
recordId: string;
|
|
5
|
+
}
|
|
6
|
+
export interface ActionUI {
|
|
7
|
+
kind: 'toast' | 'popup';
|
|
8
|
+
variant?: 'success' | 'error' | 'info';
|
|
9
|
+
title?: string;
|
|
10
|
+
message?: string;
|
|
11
|
+
params?: Record<string, string | number>;
|
|
12
|
+
component?: {
|
|
13
|
+
name: string;
|
|
14
|
+
data?: unknown;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export type ActionResult = void | ActionUI;
|
|
18
|
+
export type ActionHandler = (ctx: ActionContext) => Promise<ActionResult>;
|
|
19
|
+
export declare function registerAction(key: string, handler: ActionHandler): void;
|
|
20
|
+
export declare function resolveAction(key: string): ActionHandler | undefined;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
const registry = new Map();
|
|
2
|
+
export function registerAction(key, handler) {
|
|
3
|
+
if (registry.has(key))
|
|
4
|
+
throw new Error(`[actions] '${key}' already registered`);
|
|
5
|
+
registry.set(key, handler);
|
|
6
|
+
}
|
|
7
|
+
export function resolveAction(key) {
|
|
8
|
+
return registry.get(key);
|
|
9
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ExtendDef } from '@coffer-org/sdk/extend';
|
|
2
|
+
export declare function ExtendReasonInfo({ ext, fieldLabel, valueLabel, }: {
|
|
3
|
+
ext: ExtendDef;
|
|
4
|
+
fieldLabel: (key: string) => string;
|
|
5
|
+
valueLabel?: (key: string, value: string | number | boolean) => string;
|
|
6
|
+
}): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { describeCondition } from '@coffer-org/sdk/condition';
|
|
4
|
+
import { Icon } from "./Icon.js";
|
|
5
|
+
import { Popover, PopoverTrigger, PopoverContent } from "./ui/popover.js";
|
|
6
|
+
export function ExtendReasonInfo({ ext, fieldLabel, valueLabel, }) {
|
|
7
|
+
const { t } = useTranslation();
|
|
8
|
+
const clauses = describeCondition(ext.showWhen, fieldLabel, valueLabel);
|
|
9
|
+
if (clauses.length === 0)
|
|
10
|
+
return null;
|
|
11
|
+
return (_jsxs(Popover, { children: [_jsx(PopoverTrigger, { type: "button", "aria-label": t('extend.shownWhen'), className: "inline-flex items-center text-muted hover:text-text", children: _jsx(Icon, { name: "lucide:info", size: 14 }) }), _jsxs(PopoverContent, { align: "start", className: "w-auto max-w-xs text-sm", children: [_jsx("p", { className: "text-muted mb-1", children: t('extend.shownWhen') }), _jsx("p", { children: clauses.join('; ') })] })] }));
|
|
12
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function FavoriteButton({ favorite, busy, onClick, labelAdd, labelRemove, variant, }: {
|
|
2
|
+
favorite: boolean;
|
|
3
|
+
busy?: boolean;
|
|
4
|
+
onClick: () => void;
|
|
5
|
+
labelAdd: string;
|
|
6
|
+
labelRemove: string;
|
|
7
|
+
variant?: 'ghost' | 'outline';
|
|
8
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Star } from 'lucide-react';
|
|
3
|
+
import { Button } from './ui/button';
|
|
4
|
+
export function FavoriteButton({ favorite, busy = false, onClick, labelAdd, labelRemove, variant = 'ghost', }) {
|
|
5
|
+
const label = favorite ? labelRemove : labelAdd;
|
|
6
|
+
return (_jsx(Button, { variant: variant, size: "icon", type: "button", disabled: busy, "aria-label": label, "aria-pressed": favorite, title: label, onClick: onClick, className: favorite ? 'text-accent hover:text-accent' : 'text-muted hover:text-text', children: _jsx(Star, { "data-icon": "inline-start", size: 16, fill: favorite ? 'currentColor' : 'none' }) }));
|
|
7
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { HelpCircle } from 'lucide-react';
|
|
3
|
+
import { resolveIcon } from "./icons/registry.js";
|
|
4
|
+
export function Icon({ name, size = 16, className, strokeWidth, }) {
|
|
5
|
+
if (!name)
|
|
6
|
+
return null;
|
|
7
|
+
const node = resolveIcon(name, size, className, strokeWidth);
|
|
8
|
+
if (node !== undefined)
|
|
9
|
+
return _jsx(_Fragment, { children: node });
|
|
10
|
+
console.warn(`[Icon] unknown icon: ${name}`);
|
|
11
|
+
return _jsx(HelpCircle, { size: size, className: className, strokeWidth: strokeWidth });
|
|
12
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ShelfDef } from '@coffer-org/sdk/shelf';
|
|
2
|
+
export declare function RecordInline({ shelf, row, size, height, className, }: {
|
|
3
|
+
shelf: ShelfDef;
|
|
4
|
+
row: Record<string, unknown>;
|
|
5
|
+
size?: 'sm' | 'md';
|
|
6
|
+
height?: number;
|
|
7
|
+
className?: string;
|
|
8
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { inlineText, inlineImageKey } from '@coffer-org/sdk/shelf';
|
|
3
|
+
import { mediaUrl } from "../host-services.js";
|
|
4
|
+
import { OptionIconView } from "./ui/option-icon.js";
|
|
5
|
+
function firstImageName(value) {
|
|
6
|
+
if (typeof value !== 'string' || !value)
|
|
7
|
+
return undefined;
|
|
8
|
+
try {
|
|
9
|
+
const p = JSON.parse(value);
|
|
10
|
+
const first = Array.isArray(p) ? p[0] : p;
|
|
11
|
+
if (first && typeof first === 'object' && typeof first.name === 'string')
|
|
12
|
+
return first.name;
|
|
13
|
+
if (typeof first === 'string')
|
|
14
|
+
return first;
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export function RecordInline({ shelf, row, size = 'md', height, className, }) {
|
|
22
|
+
const text = inlineText(shelf, row);
|
|
23
|
+
const imgKey = inlineImageKey(shelf);
|
|
24
|
+
const imgName = imgKey ? firstImageName(row[imgKey]) : undefined;
|
|
25
|
+
const icon = imgName
|
|
26
|
+
? { kind: 'image', value: mediaUrl(imgName) }
|
|
27
|
+
: { kind: 'icon', value: shelf.icon ?? 'lucide:square' };
|
|
28
|
+
return (_jsxs("span", { className: `inline-flex min-w-0 items-center gap-2 ${className ?? ''}`, style: height ? { height, minHeight: height } : undefined, children: [imgKey && _jsx(OptionIconView, { icon: icon, size: size === 'sm' ? 'md' : 'lg', framed: true }), _jsx("span", { className: "truncate", children: text })] }));
|
|
29
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function SaveStatus(): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { Loader2 } from 'lucide-react';
|
|
4
|
+
import { useRecordSave } from "../render/record-save-ctx.js";
|
|
5
|
+
export function SaveStatus() {
|
|
6
|
+
const { t } = useTranslation();
|
|
7
|
+
const { saving } = useRecordSave();
|
|
8
|
+
if (!saving)
|
|
9
|
+
return null;
|
|
10
|
+
return (_jsxs("span", { className: "flex items-center gap-1.5 px-2 text-xs text-muted", "aria-live": "polite", children: [_jsx(Loader2, { size: 14, className: "animate-spin" }), _jsx("span", { className: "hidden sm:inline", children: t('save.saving') })] }));
|
|
11
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
export function Toolbar({ children, actions }) {
|
|
3
|
+
return (_jsxs("div", { "data-toolbar": true, className: "eink-solid sticky top-0 z-20 flex h-[52px] items-center justify-between gap-3 bg-bg/85 px-4 backdrop-blur md:px-6 border-b border-border2 shrink-0", children: [_jsx("div", { className: "flex items-center gap-2.5 min-w-0", children: children }), actions && (_jsx("div", { "data-toolbar-actions": true, className: "flex items-center gap-2 shrink-0", children: actions }))] }));
|
|
4
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { BASIC_COLORS } from '@coffer-org/sdk/color-names';
|
|
3
|
+
const BY_NAME = new Map(BASIC_COLORS.map((c) => [c.name, c.hex]));
|
|
4
|
+
const HEX_RE = /^#[0-9a-fA-F]{6}$/;
|
|
5
|
+
export function colorIcon(name, size, className) {
|
|
6
|
+
const hex = HEX_RE.test(name) ? name : BY_NAME.get(name);
|
|
7
|
+
if (!hex)
|
|
8
|
+
return null;
|
|
9
|
+
return (_jsx("span", { className: `shrink-0 inline-block rounded-full border border-border/60 ${className ?? ''}`, style: { width: size, height: size, backgroundColor: hex } }));
|
|
10
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
void import('flag-icons/css/flag-icons.min.css');
|
|
3
|
+
export function flagIcon(name, size, className) {
|
|
4
|
+
const code = name.toLowerCase();
|
|
5
|
+
return (_jsx("span", { className: `fi fi-${code} ${className ?? ''}`, style: { width: size, height: size * 0.75, display: 'inline-block', borderRadius: 2 } }));
|
|
6
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { IdCard, Antenna, Plane, Plus, Globe, Sprout, CookingPot, SlidersHorizontal, Ticket, Hospital, Hotel, User, Users, Pill, ClipboardList, Radio, RadioTower, Camera, Package, BatteryFull, Link, Monitor, Rocket, Bus, Shield, PlaneTakeoff, Satellite, FlaskConical, Stethoscope, Soup, Glasses, Puzzle, Settings, AlertTriangle, Hand, MapPin, Gauge, DoorOpen, PaintRoller, Zap, Calendar, Clock, CalendarClock, ArrowLeftRight, ArrowUp, ArrowDown, Bug, Check, Droplet, Folder, FolderOutput, Ghost, House, Info, Landmark, Layers, Play, Radar, Receipt, RefreshCw, Ruler, Square, Wallet, Wifi, X, Star, Minus, Activity, Bot, Search, LogOut, Trash2, Beaker, Bed, Box, CalendarDays, Carrot, Circle, Clapperboard, Code, CreditCard, HardDrive, Hash, Image, Key, Languages, List, ListChecks, MessageCircle, Network, NotebookPen, Route, Rows3, Server, ShieldCheck, ShoppingCart, Store, Tag, Terminal, Type, Upload, } from 'lucide-react';
|
|
3
|
+
const REGISTRY = {
|
|
4
|
+
'id-card': IdCard,
|
|
5
|
+
antenna: Antenna,
|
|
6
|
+
plane: Plane,
|
|
7
|
+
plus: Plus,
|
|
8
|
+
globe: Globe,
|
|
9
|
+
sprout: Sprout,
|
|
10
|
+
'cooking-pot': CookingPot,
|
|
11
|
+
'sliders-horizontal': SlidersHorizontal,
|
|
12
|
+
ticket: Ticket,
|
|
13
|
+
hospital: Hospital,
|
|
14
|
+
hotel: Hotel,
|
|
15
|
+
user: User,
|
|
16
|
+
users: Users,
|
|
17
|
+
pill: Pill,
|
|
18
|
+
'clipboard-list': ClipboardList,
|
|
19
|
+
radio: Radio,
|
|
20
|
+
'radio-tower': RadioTower,
|
|
21
|
+
camera: Camera,
|
|
22
|
+
package: Package,
|
|
23
|
+
'battery-full': BatteryFull,
|
|
24
|
+
link: Link,
|
|
25
|
+
monitor: Monitor,
|
|
26
|
+
rocket: Rocket,
|
|
27
|
+
bus: Bus,
|
|
28
|
+
shield: Shield,
|
|
29
|
+
'plane-takeoff': PlaneTakeoff,
|
|
30
|
+
satellite: Satellite,
|
|
31
|
+
'flask-conical': FlaskConical,
|
|
32
|
+
stethoscope: Stethoscope,
|
|
33
|
+
soup: Soup,
|
|
34
|
+
glasses: Glasses,
|
|
35
|
+
puzzle: Puzzle,
|
|
36
|
+
settings: Settings,
|
|
37
|
+
'alert-triangle': AlertTriangle,
|
|
38
|
+
hand: Hand,
|
|
39
|
+
'map-pin': MapPin,
|
|
40
|
+
gauge: Gauge,
|
|
41
|
+
'door-open': DoorOpen,
|
|
42
|
+
'paint-roller': PaintRoller,
|
|
43
|
+
zap: Zap,
|
|
44
|
+
calendar: Calendar,
|
|
45
|
+
clock: Clock,
|
|
46
|
+
'calendar-clock': CalendarClock,
|
|
47
|
+
'arrow-left-right': ArrowLeftRight,
|
|
48
|
+
'arrow-up': ArrowUp,
|
|
49
|
+
'arrow-down': ArrowDown,
|
|
50
|
+
bug: Bug,
|
|
51
|
+
check: Check,
|
|
52
|
+
droplet: Droplet,
|
|
53
|
+
folder: Folder,
|
|
54
|
+
'folder-output': FolderOutput,
|
|
55
|
+
ghost: Ghost,
|
|
56
|
+
house: House,
|
|
57
|
+
info: Info,
|
|
58
|
+
landmark: Landmark,
|
|
59
|
+
layers: Layers,
|
|
60
|
+
play: Play,
|
|
61
|
+
radar: Radar,
|
|
62
|
+
receipt: Receipt,
|
|
63
|
+
'refresh-cw': RefreshCw,
|
|
64
|
+
ruler: Ruler,
|
|
65
|
+
square: Square,
|
|
66
|
+
wallet: Wallet,
|
|
67
|
+
wifi: Wifi,
|
|
68
|
+
x: X,
|
|
69
|
+
star: Star,
|
|
70
|
+
minus: Minus,
|
|
71
|
+
activity: Activity,
|
|
72
|
+
bot: Bot,
|
|
73
|
+
search: Search,
|
|
74
|
+
'log-out': LogOut,
|
|
75
|
+
'trash-2': Trash2,
|
|
76
|
+
beaker: Beaker,
|
|
77
|
+
bed: Bed,
|
|
78
|
+
box: Box,
|
|
79
|
+
'calendar-days': CalendarDays,
|
|
80
|
+
carrot: Carrot,
|
|
81
|
+
circle: Circle,
|
|
82
|
+
clapperboard: Clapperboard,
|
|
83
|
+
code: Code,
|
|
84
|
+
'credit-card': CreditCard,
|
|
85
|
+
'hard-drive': HardDrive,
|
|
86
|
+
hash: Hash,
|
|
87
|
+
image: Image,
|
|
88
|
+
key: Key,
|
|
89
|
+
languages: Languages,
|
|
90
|
+
list: List,
|
|
91
|
+
'list-checks': ListChecks,
|
|
92
|
+
'message-circle': MessageCircle,
|
|
93
|
+
network: Network,
|
|
94
|
+
'notebook-pen': NotebookPen,
|
|
95
|
+
route: Route,
|
|
96
|
+
'rows-3': Rows3,
|
|
97
|
+
server: Server,
|
|
98
|
+
'shield-check': ShieldCheck,
|
|
99
|
+
'shopping-cart': ShoppingCart,
|
|
100
|
+
store: Store,
|
|
101
|
+
tag: Tag,
|
|
102
|
+
terminal: Terminal,
|
|
103
|
+
type: Type,
|
|
104
|
+
upload: Upload,
|
|
105
|
+
};
|
|
106
|
+
export function lucideIcon(name, size, className, strokeWidth) {
|
|
107
|
+
const Cmp = REGISTRY[name];
|
|
108
|
+
if (!Cmp)
|
|
109
|
+
return null;
|
|
110
|
+
return _jsx(Cmp, { size: size, className: className, strokeWidth: strokeWidth });
|
|
111
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
export type IconProvider = (name: string, size: number, className?: string, strokeWidth?: number) => ReactNode;
|
|
3
|
+
export declare const providers: Record<string, IconProvider>;
|
|
4
|
+
export declare function resolveIcon(raw: string, size: number, className?: string, strokeWidth?: number): ReactNode | undefined;
|