@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
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { uploadFile } from "../host-services.js";
|
|
3
|
+
export const MAX_UPLOAD_BYTES = 25 * 1024 * 1024;
|
|
4
|
+
export function useFileUpload() {
|
|
5
|
+
const [busy, setBusy] = useState(false);
|
|
6
|
+
const [progress, setProgress] = useState(0);
|
|
7
|
+
const [error, setError] = useState(null);
|
|
8
|
+
const [failedFile, setFailedFile] = useState(null);
|
|
9
|
+
async function upload(file) {
|
|
10
|
+
setError(null);
|
|
11
|
+
if (file.size > MAX_UPLOAD_BYTES) {
|
|
12
|
+
setFailedFile(null);
|
|
13
|
+
setError('upload.tooLarge');
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
setBusy(true);
|
|
17
|
+
setProgress(0);
|
|
18
|
+
const rec = await uploadFile(file, setProgress);
|
|
19
|
+
setBusy(false);
|
|
20
|
+
if (!rec) {
|
|
21
|
+
setFailedFile(file);
|
|
22
|
+
setError('upload.failed');
|
|
23
|
+
setProgress(0);
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
setFailedFile(null);
|
|
27
|
+
return rec;
|
|
28
|
+
}
|
|
29
|
+
async function retry() {
|
|
30
|
+
if (!failedFile || busy)
|
|
31
|
+
return null;
|
|
32
|
+
return upload(failedFile);
|
|
33
|
+
}
|
|
34
|
+
return { busy, error, progress, upload, retry, canRetry: failedFile !== null };
|
|
35
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type FieldMeta } from '@coffer-org/sdk/fields';
|
|
2
|
+
import type { FieldMode, RecordCtx } from '../types.ts';
|
|
3
|
+
import type { FormBridge } from './form-types.ts';
|
|
4
|
+
type Values = Record<string, unknown>;
|
|
5
|
+
export declare function useFormBridge(opts: {
|
|
6
|
+
fm: Record<string, FieldMeta>;
|
|
7
|
+
mode: FieldMode;
|
|
8
|
+
recordCtx: RecordCtx;
|
|
9
|
+
initial: Values | (() => Values);
|
|
10
|
+
hiddenFields?: string[];
|
|
11
|
+
}): {
|
|
12
|
+
values: Values;
|
|
13
|
+
setValues: React.Dispatch<React.SetStateAction<Values>>;
|
|
14
|
+
initial: Values;
|
|
15
|
+
errors: Record<string, string>;
|
|
16
|
+
setErrors: React.Dispatch<React.SetStateAction<Record<string, string>>>;
|
|
17
|
+
touched: Set<string>;
|
|
18
|
+
setTouched: React.Dispatch<React.SetStateAction<Set<string>>>;
|
|
19
|
+
bridge: FormBridge;
|
|
20
|
+
};
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { useMemo, useState } from 'react';
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { resolveFlag } from '@coffer-org/sdk/condition';
|
|
4
|
+
import { validateField } from '@coffer-org/sdk/fields';
|
|
5
|
+
import { makeIssueText } from "./field-errors.js";
|
|
6
|
+
export function useFormBridge(opts) {
|
|
7
|
+
const { fm, mode, recordCtx } = opts;
|
|
8
|
+
const { t } = useTranslation();
|
|
9
|
+
const issueText = makeIssueText(t);
|
|
10
|
+
const [initial] = useState(opts.initial);
|
|
11
|
+
const [values, setValues] = useState(initial);
|
|
12
|
+
const [errors, setErrors] = useState({});
|
|
13
|
+
const [touched, setTouched] = useState(() => new Set());
|
|
14
|
+
const hidden = useMemo(() => new Set(opts.hiddenFields ?? []), [opts.hiddenFields]);
|
|
15
|
+
const bridge = useMemo(() => ({
|
|
16
|
+
mode,
|
|
17
|
+
recordCtx,
|
|
18
|
+
values,
|
|
19
|
+
getValue: (k) => values[k],
|
|
20
|
+
setValue: (k, v) => {
|
|
21
|
+
setValues((s) => ({ ...s, [k]: v }));
|
|
22
|
+
if (touched.has(k)) {
|
|
23
|
+
const f = fm[k];
|
|
24
|
+
const issue = f ? validateField(f, v) : null;
|
|
25
|
+
setErrors((e) => {
|
|
26
|
+
const next = { ...e };
|
|
27
|
+
if (issue)
|
|
28
|
+
next[k] = issueText(issue.code, issue.params);
|
|
29
|
+
else
|
|
30
|
+
delete next[k];
|
|
31
|
+
return next;
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
touch: (k) => {
|
|
36
|
+
setTouched((s) => (s.has(k) ? s : new Set(s).add(k)));
|
|
37
|
+
const f = fm[k];
|
|
38
|
+
const issue = f ? validateField(f, values[k]) : null;
|
|
39
|
+
setErrors((e) => {
|
|
40
|
+
const next = { ...e };
|
|
41
|
+
if (issue)
|
|
42
|
+
next[k] = issueText(issue.code, issue.params);
|
|
43
|
+
else
|
|
44
|
+
delete next[k];
|
|
45
|
+
return next;
|
|
46
|
+
});
|
|
47
|
+
},
|
|
48
|
+
isHidden: (k) => hidden.has(k) || resolveFlag(fm[k]?.hidden, values),
|
|
49
|
+
requiredOf: (k) => resolveFlag(fm[k]?.required, values),
|
|
50
|
+
error: (k) => errors[k],
|
|
51
|
+
}), [values, errors, touched, hidden, fm, mode, recordCtx, issueText]);
|
|
52
|
+
return { values, setValues, initial, errors, setErrors, touched, setTouched, bridge };
|
|
53
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { registerRenderer } from "../../registry.js";
|
|
3
|
+
import { Input } from "../../components/ui/input.js";
|
|
4
|
+
import { Dash, compositeRoleValue } from "../shared.js";
|
|
5
|
+
import { twoCellGroupPage } from "./two-cell-group.js";
|
|
6
|
+
import { ReadOnlyFiles, SingleFileWidget } from "../core/file.js";
|
|
7
|
+
import { AttachmentBody, AttachmentStack, attachmentSlots, attachmentFileKind, attachmentRoleFixed, AttachmentFileCell, AttachmentLabelCell, } from "../core/attachment.js";
|
|
8
|
+
function AttachmentRowEdit({ meta, row, onChange }) {
|
|
9
|
+
const { lKey, fKey } = attachmentSlots(meta);
|
|
10
|
+
const kind = attachmentFileKind(meta);
|
|
11
|
+
const label = row[lKey];
|
|
12
|
+
const file = row[fKey];
|
|
13
|
+
const labelFixed = attachmentRoleFixed(meta, 'label');
|
|
14
|
+
const fileFixed = attachmentRoleFixed(meta, 'file');
|
|
15
|
+
return (_jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-2", children: [labelFixed ? (_jsx("p", { className: "text-[15px] text-muted", children: label != null && label !== '' ? String(label) : _jsx(Dash, {}) })) : (_jsx(Input, { value: label == null ? '' : String(label), onChange: (e) => onChange({ ...row, [lKey]: compositeRoleValue(e.target.value) }) })), fileFixed ? (_jsx(ReadOnlyFiles, { kind: kind, value: file ?? '' })) : (_jsx(SingleFileWidget, { kind: kind, value: file ?? '', onChange: (v) => onChange({ ...row, [fKey]: compositeRoleValue(v) }) }))] }));
|
|
16
|
+
}
|
|
17
|
+
function AttachmentRowLive({ meta, row, onChange }) {
|
|
18
|
+
const { lKey, fKey } = attachmentSlots(meta);
|
|
19
|
+
const kind = attachmentFileKind(meta);
|
|
20
|
+
const label = row[lKey];
|
|
21
|
+
const file = row[fKey];
|
|
22
|
+
const labelPart = meta.parts?.find((p) => p.role === 'label');
|
|
23
|
+
const labelFixed = attachmentRoleFixed(meta, 'label');
|
|
24
|
+
const fileFixed = attachmentRoleFixed(meta, 'file');
|
|
25
|
+
return (_jsx("div", { className: "min-w-0 flex-1", children: _jsx(AttachmentStack, { name: _jsx(AttachmentLabelCell, { label: label, fixed: labelFixed, meta: labelPart?.meta ?? meta, onChange: labelFixed ? undefined : (v) => onChange({ ...row, [lKey]: compositeRoleValue(v) }) }), file: _jsx(AttachmentFileCell, { file: file, fixed: fileFixed, kind: kind, onChange: fileFixed ? undefined : (v) => onChange({ ...row, [fKey]: compositeRoleValue(v) }) }) }) }));
|
|
26
|
+
}
|
|
27
|
+
const AttachmentGroupPage = twoCellGroupPage({
|
|
28
|
+
kind: 'attachment',
|
|
29
|
+
testid: 'attachment-list',
|
|
30
|
+
rowGap: 'gap-3',
|
|
31
|
+
RowEdit: AttachmentRowEdit,
|
|
32
|
+
RowLive: AttachmentRowLive,
|
|
33
|
+
Body: AttachmentBody,
|
|
34
|
+
});
|
|
35
|
+
registerRenderer({ kinds: ['attachmentList'], layout: 'block', Page: AttachmentGroupPage, editor: 'custom' });
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type FieldMeta, type RowSubField } from '@coffer-org/sdk/fields';
|
|
2
|
+
import type { RecordCtx } from '../../types.ts';
|
|
3
|
+
export type ChecklistContentField = {
|
|
4
|
+
key: string;
|
|
5
|
+
type: FieldMeta;
|
|
6
|
+
};
|
|
7
|
+
export declare function clientChecklistContentFields(fields: RowSubField[] | undefined): ChecklistContentField[];
|
|
8
|
+
export declare function ChecklistContent({ fields, row, editing, onChange, recordCtx, error, }: {
|
|
9
|
+
fields: ChecklistContentField[];
|
|
10
|
+
row: Record<string, unknown>;
|
|
11
|
+
editing: boolean;
|
|
12
|
+
onChange?: (key: string, value: unknown) => void;
|
|
13
|
+
recordCtx: RecordCtx;
|
|
14
|
+
error?: (key: string) => string | undefined;
|
|
15
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { clientToMeta } from '@coffer-org/sdk/fields';
|
|
3
|
+
import { Input } from "../../components/ui/input.js";
|
|
4
|
+
import { FieldSlot } from "../dispatch.js";
|
|
5
|
+
import { useHybridScope } from "../hybrid-scope.js";
|
|
6
|
+
export function clientChecklistContentFields(fields) {
|
|
7
|
+
return (fields ?? []).map((field) => ({ key: field.key, type: clientToMeta(field) }));
|
|
8
|
+
}
|
|
9
|
+
export function ChecklistContent({ fields, row, editing, onChange, recordCtx, error, }) {
|
|
10
|
+
const live = useHybridScope() && !editing;
|
|
11
|
+
return (_jsx("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: fields.map((field) => (_jsx("span", { className: "min-w-0 flex-1", children: field.type.kind === 'text' && editing ? (_jsx(Input, { value: String(row[field.key] ?? ''), onChange: (event) => onChange?.(field.key, event.target.value), className: "min-w-0 w-full" })) : (_jsx(FieldSlot, { field: field.type, fieldKey: live ? field.key : undefined, value: row[field.key] ?? '', mode: editing ? 'edit' : 'view', bare: !live, recordCtx: recordCtx, onChange: editing || live ? (value) => onChange?.(field.key, value) : undefined, error: error?.(field.key) })) }, field.key))) }));
|
|
12
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ContainerNode } from '@coffer-org/sdk/fields';
|
|
2
|
+
import type { RecordCtx, FieldMode } from '../../types.ts';
|
|
3
|
+
type Row = Record<string, unknown>;
|
|
4
|
+
export declare function ChecklistGroup({ group, value, onChange, recordCtx, mode, }: {
|
|
5
|
+
group: ContainerNode;
|
|
6
|
+
value: unknown;
|
|
7
|
+
onChange: (v: Row[]) => void;
|
|
8
|
+
recordCtx: RecordCtx;
|
|
9
|
+
mode: FieldMode;
|
|
10
|
+
}): import("react").JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { isNamedField } from '@coffer-org/sdk/fields';
|
|
4
|
+
import { AddBtn, CheckLegend, useRowIdentity } from "../shared.js";
|
|
5
|
+
import { useGroupDepth, GroupDepthProvider, groupScopeClass } from "../chrome.js";
|
|
6
|
+
import { useGroupEdit } from "./group-edit.js";
|
|
7
|
+
import { useHybridScope } from "../hybrid-scope.js";
|
|
8
|
+
import { ChecklistRow } from "./checklist-row.js";
|
|
9
|
+
import { ChecklistContent } from "./checklist-content.js";
|
|
10
|
+
import { PopoverField } from "../popover-field.js";
|
|
11
|
+
import { Checkbox } from "../../components/ui/checkbox.js";
|
|
12
|
+
export function ChecklistGroup({ group, value, onChange, recordCtx, mode, }) {
|
|
13
|
+
const { t } = useTranslation();
|
|
14
|
+
const depth = useGroupDepth();
|
|
15
|
+
const boolCols = group.fields.filter((f) => isNamedField(f) && /^check\d+$/.test(f.key));
|
|
16
|
+
const contentCols = group.fields.filter((f) => isNamedField(f) && !/^check\d+$/.test(f.key));
|
|
17
|
+
const contentFields = contentCols.map((field) => ({ key: field.key, type: field.type }));
|
|
18
|
+
const textCol = contentCols.find((f) => f.key === 'text');
|
|
19
|
+
const slots = boolCols.map((f) => f.type.label ?? '');
|
|
20
|
+
const g = useGroupEdit(mode, value, (v) => onChange(v));
|
|
21
|
+
const rows = Array.isArray(g.value) ? g.value : [];
|
|
22
|
+
const { rowId, updateRow, removeRow } = useRowIdentity(rows, g.onChange);
|
|
23
|
+
const controlled = g.mode !== 'view';
|
|
24
|
+
const live = useHybridScope() && mode === 'view';
|
|
25
|
+
const rowTools = controlled || live;
|
|
26
|
+
const toChecklistRow = (row) => ({
|
|
27
|
+
text: textCol ? String(row[textCol.key] ?? '') : '',
|
|
28
|
+
checks: boolCols.map((col) => row[col.key] === true),
|
|
29
|
+
});
|
|
30
|
+
const fromChecklistRow = (row, source) => {
|
|
31
|
+
const next = { ...source };
|
|
32
|
+
boolCols.forEach((col, i) => {
|
|
33
|
+
next[col.key] = row.checks[i] === true;
|
|
34
|
+
});
|
|
35
|
+
if (textCol)
|
|
36
|
+
next[textCol.key] = row.text;
|
|
37
|
+
return next;
|
|
38
|
+
};
|
|
39
|
+
const checkCell = (row, idx, col) => (_jsx(PopoverField, { field: { ...col.type, hints: { ...col.type.hints, noLabel: true } }, label: col.type.label ? t(col.type.label) : undefined, value: row[col.key] === true, geom: "none", width: "w-fit", view: (v, commit) => (_jsx(Checkbox, { checked: v === true, disabled: !commit, "aria-label": col.type.label ? t(col.type.label) : undefined, onCheckedChange: (c) => commit?.(c === true) })), edit: (v, set) => _jsx(Checkbox, { checked: v === true, onCheckedChange: (c) => set(c === true) }), onCommit: (v) => updateRow(idx, { ...row, [col.key]: v === true }) }, col.key));
|
|
40
|
+
const content = (_jsxs("div", { className: "flex flex-col gap-2 min-w-0", children: [_jsx("ul", { className: "flex flex-col gap-1.5", children: rows.map((row, idx) => {
|
|
41
|
+
const checklistRow = toChecklistRow(row);
|
|
42
|
+
return (_jsx("li", { children: _jsx(ChecklistRow, { row: checklistRow, slotCount: slots.length, editing: controlled, checkCells: live ? boolCols.map((col) => checkCell(row, idx, col)) : undefined, onChange: (next) => updateRow(idx, fromChecklistRow(next, row)), onRemove: rowTools ? () => removeRow(idx) : undefined, content: _jsx(ChecklistContent, { fields: contentFields, row: row, editing: controlled, onChange: (key, value) => updateRow(idx, { ...row, [key]: value }), recordCtx: recordCtx }) }) }, rowId(row)));
|
|
43
|
+
}) }), rowTools && _jsx(AddBtn, { onClick: () => g.onChange([...rows, {}]), children: t('form.addRow') }), _jsx(CheckLegend, { slots: slots })] }));
|
|
44
|
+
if (mode !== 'view')
|
|
45
|
+
return content;
|
|
46
|
+
return (_jsxs("section", { className: `${groupScopeClass(depth)} flex flex-col gap-1 min-w-0`, children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("h3", { className: "text-[13px] font-semibold text-accent", children: t(group.label) }), !live && g.actions && _jsx("span", { className: "ml-auto flex shrink-0 items-center gap-1.5", children: g.actions })] }), _jsx(GroupDepthProvider, { depth: depth + 1, children: content })] }));
|
|
47
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
export type ChecklistRowValue = {
|
|
3
|
+
text: string;
|
|
4
|
+
checks: boolean[];
|
|
5
|
+
};
|
|
6
|
+
export declare function ChecklistRow({ row, slotCount, editing, onChange, onRemove, checkCells, content, }: {
|
|
7
|
+
row: ChecklistRowValue;
|
|
8
|
+
slotCount: number;
|
|
9
|
+
editing?: boolean;
|
|
10
|
+
onChange?: (row: ChecklistRowValue) => void;
|
|
11
|
+
onRemove?: () => void;
|
|
12
|
+
checkCells?: ReactNode[];
|
|
13
|
+
content?: ReactNode;
|
|
14
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Trash2 } from 'lucide-react';
|
|
3
|
+
import { Button } from "../../components/ui/button.js";
|
|
4
|
+
import { Checkbox } from "../../components/ui/checkbox.js";
|
|
5
|
+
import { Input } from "../../components/ui/input.js";
|
|
6
|
+
import { useTranslation } from 'react-i18next';
|
|
7
|
+
import { checkNumbered, circledNum } from "../shared.js";
|
|
8
|
+
export function ChecklistRow({ row, slotCount, editing, onChange, onRemove, checkCells, content, }) {
|
|
9
|
+
const { t } = useTranslation();
|
|
10
|
+
const checks = Array.from({ length: slotCount }, (_, i) => Boolean(row.checks[i]));
|
|
11
|
+
const numbered = checkNumbered(slotCount);
|
|
12
|
+
return (_jsxs("div", { className: "flex items-center gap-3.5 min-h-9 text-sm min-w-0", children: [checks.map((checked, i) => (_jsxs("span", { className: "inline-flex items-center gap-0.5 shrink-0", children: [numbered && _jsx("span", { className: "text-[10px] text-muted tabular-nums", children: circledNum(i) }), editing ? (_jsx(Checkbox, { checked: checked, onCheckedChange: (next) => onChange?.({ ...row, checks: checks.map((value, j) => (j === i ? next === true : value)) }) })) : ((checkCells?.[i] ?? (_jsx(Checkbox, { checked: checked, disabled: true, tabIndex: -1, "aria-readonly": true, className: "pointer-events-none" }))))] }, i))), content ??
|
|
13
|
+
(editing ? (_jsx(Input, { value: row.text, onChange: (event) => onChange?.({ ...row, text: event.target.value }), className: "min-w-0 flex-1" })) : (_jsx("span", { className: "min-w-0 flex-1 truncate text-sm text-text", children: row.text || '—' }))), onRemove && (_jsx(Button, { type: "button", variant: "ghost", size: "iconSm", onClick: onRemove, title: t('actions.delete'), className: "h-5 w-5 shrink-0 rounded text-muted hover:text-danger", children: _jsx(Trash2, { size: 12 }) }))] }));
|
|
14
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { RecordCtx } from '../../types.ts';
|
|
2
|
+
import type { FieldMeta } from '@coffer-org/sdk/fields';
|
|
3
|
+
type TFn = (key: string, opts?: Record<string, unknown>) => string;
|
|
4
|
+
export declare function KeyValueList({ value, option, recordCtx, }: {
|
|
5
|
+
value: unknown;
|
|
6
|
+
option: FieldMeta;
|
|
7
|
+
recordCtx?: RecordCtx;
|
|
8
|
+
}): import("react").JSX.Element;
|
|
9
|
+
export declare function CheckDisplay({ value, slots, fields, recordCtx, }: {
|
|
10
|
+
value: unknown;
|
|
11
|
+
slots?: string[];
|
|
12
|
+
fields?: import('@coffer-org/sdk/fields').RowSubField[];
|
|
13
|
+
recordCtx?: RecordCtx;
|
|
14
|
+
}): import("react").JSX.Element;
|
|
15
|
+
export declare function MultiCheckDisplay({ value, slots }: {
|
|
16
|
+
value: unknown;
|
|
17
|
+
slots?: string[];
|
|
18
|
+
}): import("react").JSX.Element;
|
|
19
|
+
export declare function RelationValues({ field, value }: {
|
|
20
|
+
field: FieldMeta;
|
|
21
|
+
value: unknown;
|
|
22
|
+
}): import("react").JSX.Element;
|
|
23
|
+
export declare function measuredUnitLabel(field: FieldMeta, unit: string, t: TFn): string;
|
|
24
|
+
export declare function measuredSlots(field: FieldMeta): {
|
|
25
|
+
vKey: string;
|
|
26
|
+
uKey: string;
|
|
27
|
+
};
|
|
28
|
+
export declare function measuredChipContent(field: FieldMeta, t: TFn): (it: unknown) => import("react").JSX.Element;
|
|
29
|
+
export declare function MeasuredDisplay({ field, value }: {
|
|
30
|
+
field: FieldMeta;
|
|
31
|
+
value: unknown;
|
|
32
|
+
}): import("react").JSX.Element;
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Link } from 'react-router-dom';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import { partValueKeys } from '@coffer-org/sdk/fields';
|
|
5
|
+
import { resolveUnits } from '@coffer-org/sdk/units';
|
|
6
|
+
import { parseJSON } from "../../lib/json.js";
|
|
7
|
+
import { useRecordsByIds } from "../../lib/use-record-labels.js";
|
|
8
|
+
import { getShelf } from "../../schema-registry.js";
|
|
9
|
+
import { RecordInline } from "../../components/RecordInline.js";
|
|
10
|
+
import { Dash, hasValue, shortId, CheckLegend, colsToCheckRow } from "../shared.js";
|
|
11
|
+
import { FieldSlot } from "../dispatch.js";
|
|
12
|
+
import { FlowRow } from "./flow-row.js";
|
|
13
|
+
import { ChecklistRow } from "./checklist-row.js";
|
|
14
|
+
import { ChecklistContent, clientChecklistContentFields } from "./checklist-content.js";
|
|
15
|
+
export function KeyValueList({ value, option, recordCtx = { library: '', shelf: '', recordId: '' }, }) {
|
|
16
|
+
const list = parseJSON(value, []).filter((p) => p && p.key);
|
|
17
|
+
if (!list.length)
|
|
18
|
+
return _jsx(Dash, {});
|
|
19
|
+
return (_jsx(FlowRow, { items: list.map((p, i) => ({
|
|
20
|
+
key: String(i),
|
|
21
|
+
node: (_jsxs("div", { children: [_jsx("dt", { className: "text-[11px] font-semibold text-muted uppercase", children: p.key }), _jsx("dd", { className: "text-sm text-text break-all", children: _jsx(FieldSlot, { bare: true, field: option, value: p.value, mode: "view", recordCtx: recordCtx }) })] })),
|
|
22
|
+
})) }));
|
|
23
|
+
}
|
|
24
|
+
export function CheckDisplay({ value, slots = [], fields, recordCtx = { library: '', shelf: '', recordId: null }, }) {
|
|
25
|
+
const contentFields = clientChecklistContentFields(fields);
|
|
26
|
+
const data = parseJSON(value, {});
|
|
27
|
+
const row = contentFields.length
|
|
28
|
+
? {
|
|
29
|
+
text: String(data.text ?? ''),
|
|
30
|
+
checks: Array.from({ length: slots.length }, (_, i) => data['check' + i] === true),
|
|
31
|
+
}
|
|
32
|
+
: colsToCheckRow(value, slots.length);
|
|
33
|
+
const hasContent = contentFields.length
|
|
34
|
+
? contentFields.some((field) => hasValue(data[field.key]))
|
|
35
|
+
: Boolean(row.text);
|
|
36
|
+
if (!row.text && !hasContent && !row.checks.some(Boolean))
|
|
37
|
+
return (_jsx("div", { className: "flex text-sm", children: _jsx(Dash, {}) }));
|
|
38
|
+
return (_jsxs("div", { className: "flex flex-col gap-1", children: [_jsx("div", { className: "flex flex-col gap-1.5", children: _jsx(ChecklistRow, { row: row, slotCount: slots.length, content: contentFields.length ? (_jsx(ChecklistContent, { fields: contentFields, row: data, editing: false, recordCtx: recordCtx })) : undefined }) }), _jsx(CheckLegend, { slots: slots })] }));
|
|
39
|
+
}
|
|
40
|
+
export function MultiCheckDisplay({ value, slots = [] }) {
|
|
41
|
+
const rows = parseJSON(value, []).filter((r) => r && (r.text || (r.checks ?? []).some(Boolean)));
|
|
42
|
+
if (!rows.length)
|
|
43
|
+
return _jsx(Dash, {});
|
|
44
|
+
return (_jsxs("div", { className: "flex flex-col gap-1", children: [_jsx("div", { className: "flex flex-col gap-1.5", children: rows.map((row, i) => (_jsx(ChecklistRow, { row: row, slotCount: slots.length }, i))) }), _jsx(CheckLegend, { slots: slots })] }));
|
|
45
|
+
}
|
|
46
|
+
export function RelationValues({ field, value }) {
|
|
47
|
+
const library = field.relation?.library ?? '';
|
|
48
|
+
const shelf = field.relation?.shelf ?? '';
|
|
49
|
+
const multi = Boolean(field.hints['multi']);
|
|
50
|
+
const ids = multi ? parseJSON(value, []).map(String) : hasValue(value) ? [String(value)] : [];
|
|
51
|
+
const recordMap = useRecordsByIds(library, shelf, ids);
|
|
52
|
+
const m = getShelf(library, shelf);
|
|
53
|
+
if (!ids.length)
|
|
54
|
+
return _jsx(Dash, {});
|
|
55
|
+
return (_jsx("div", { className: "flex flex-wrap gap-2", children: ids.map((id) => {
|
|
56
|
+
const row = recordMap.get(id);
|
|
57
|
+
return (_jsx(Link, { to: `/${library}/${shelf}/${id}`, className: "inline-flex items-center gap-1.5 min-h-9 text-accent border border-transparent rounded-lg px-3 text-sm hover:text-accent2 transition-colors", children: m && row ? _jsx(RecordInline, { shelf: m, row: row, size: "sm", height: 28 }) : shortId(id) }, id));
|
|
58
|
+
}) }));
|
|
59
|
+
}
|
|
60
|
+
export function measuredUnitLabel(field, unit, t) {
|
|
61
|
+
const units = resolveUnits(field.hints['units']) ?? [];
|
|
62
|
+
const u = units.find((x) => x.value === unit);
|
|
63
|
+
return u ? t(u.label) : unit;
|
|
64
|
+
}
|
|
65
|
+
export function measuredSlots(field) {
|
|
66
|
+
const slots = partValueKeys((field.parts ?? []));
|
|
67
|
+
return { vKey: slots['value'] ?? 'value', uKey: slots['unit'] ?? 'unit' };
|
|
68
|
+
}
|
|
69
|
+
export function measuredChipContent(field, t) {
|
|
70
|
+
const { vKey, uKey } = measuredSlots(field);
|
|
71
|
+
const MeasuredChipContent = (it) => {
|
|
72
|
+
const o = it && typeof it === 'object'
|
|
73
|
+
? it
|
|
74
|
+
: (() => {
|
|
75
|
+
try {
|
|
76
|
+
return JSON.parse(String(it));
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
})();
|
|
82
|
+
if (o && typeof o === 'object' && vKey in o && uKey in o) {
|
|
83
|
+
const rec = o;
|
|
84
|
+
return _jsx("span", { className: "font-mono", children: `${rec[vKey]} ${measuredUnitLabel(field, String(rec[uKey]), t)}` });
|
|
85
|
+
}
|
|
86
|
+
return _jsx("span", { className: "font-mono", children: String(it) });
|
|
87
|
+
};
|
|
88
|
+
return MeasuredChipContent;
|
|
89
|
+
}
|
|
90
|
+
export function MeasuredDisplay({ field, value }) {
|
|
91
|
+
const { t } = useTranslation();
|
|
92
|
+
const { vKey, uKey } = measuredSlots(field);
|
|
93
|
+
const raw = parseJSON(value, null);
|
|
94
|
+
if (!raw || raw[vKey] == null)
|
|
95
|
+
return _jsx(Dash, {});
|
|
96
|
+
return (_jsxs("span", { className: "font-mono text-sm", children: [raw[vKey], ' ', _jsx("span", { className: "text-xs text-muted", children: measuredUnitLabel(field, String(raw[uKey] ?? ''), t) })] }));
|
|
97
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { TFunction } from 'i18next';
|
|
2
|
+
import type { FieldMeta } from '@coffer-org/sdk/fields';
|
|
3
|
+
import type { RecordCtx } from '../../types.ts';
|
|
4
|
+
import { type ChecklistRowValue } from './checklist-row.tsx';
|
|
5
|
+
export declare function RowWidget({ value, onChange, field, t, recordCtx, }: {
|
|
6
|
+
value: unknown;
|
|
7
|
+
onChange: (v: Record<string, string> | Record<string, string>[] | '') => void;
|
|
8
|
+
field: FieldMeta;
|
|
9
|
+
t: TFunction<'translation', undefined>;
|
|
10
|
+
recordCtx?: RecordCtx;
|
|
11
|
+
}): import("react").JSX.Element;
|
|
12
|
+
export declare function MeasuredWidget({ value, onChange, field, }: {
|
|
13
|
+
value: string | {
|
|
14
|
+
value: number | '';
|
|
15
|
+
unit: string;
|
|
16
|
+
} | '';
|
|
17
|
+
onChange: (v: {
|
|
18
|
+
value: number | '';
|
|
19
|
+
unit: string;
|
|
20
|
+
} | '') => void;
|
|
21
|
+
field: FieldMeta;
|
|
22
|
+
}): import("react").JSX.Element;
|
|
23
|
+
export declare function RelationPickerWidget({ field, value, onChange, excludeValues, }: {
|
|
24
|
+
field: FieldMeta;
|
|
25
|
+
value: unknown;
|
|
26
|
+
onChange: (v: string | string[]) => void;
|
|
27
|
+
excludeValues?: string[];
|
|
28
|
+
}): import("react").JSX.Element;
|
|
29
|
+
type CheckRow = ChecklistRowValue;
|
|
30
|
+
export declare function CheckWidget({ value, onChange, field, recordCtx, }: {
|
|
31
|
+
value: unknown;
|
|
32
|
+
onChange: (v: Record<string, unknown> | '') => void;
|
|
33
|
+
field: FieldMeta;
|
|
34
|
+
recordCtx?: RecordCtx;
|
|
35
|
+
}): import("react").JSX.Element;
|
|
36
|
+
export declare function MultiCheckInput({ value, onChange, field, }: {
|
|
37
|
+
value: unknown;
|
|
38
|
+
onChange: (v: CheckRow[] | '') => void;
|
|
39
|
+
field: FieldMeta;
|
|
40
|
+
}): import("react").JSX.Element;
|
|
41
|
+
interface KV {
|
|
42
|
+
key: string;
|
|
43
|
+
value: string;
|
|
44
|
+
}
|
|
45
|
+
export declare function KeyValueWidget({ value, onChange, multiple, option, keyLabel, valueLabel, recordCtx, }: {
|
|
46
|
+
value: unknown;
|
|
47
|
+
onChange: (v: KV[] | '') => void;
|
|
48
|
+
multiple?: boolean;
|
|
49
|
+
option: FieldMeta;
|
|
50
|
+
keyLabel?: string;
|
|
51
|
+
valueLabel?: string;
|
|
52
|
+
recordCtx?: RecordCtx;
|
|
53
|
+
}): import("react").JSX.Element;
|
|
54
|
+
type MeasuredItem = {
|
|
55
|
+
value: number | '';
|
|
56
|
+
unit: string;
|
|
57
|
+
};
|
|
58
|
+
export declare function MeasuredMultiInput({ field, value, onChange, }: {
|
|
59
|
+
field: FieldMeta;
|
|
60
|
+
value: unknown;
|
|
61
|
+
onChange: (v: MeasuredItem[] | '') => void;
|
|
62
|
+
}): import("react").JSX.Element;
|
|
63
|
+
export {};
|