@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,23 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { registerRenderer } from "../../registry.js";
|
|
4
|
+
import { Slot, useSlots } from "../slot.js";
|
|
5
|
+
import { BlockShell, fieldLabel } from "./block-shell.js";
|
|
6
|
+
function FacetsPage({ el }) {
|
|
7
|
+
const g = el;
|
|
8
|
+
const { t } = useTranslation();
|
|
9
|
+
const slots = useSlots();
|
|
10
|
+
const body = (_jsx("div", { className: "flex flex-wrap gap-2", "data-testid": "facets", children: slots.map((s, i) => {
|
|
11
|
+
if (s.handle.hidden)
|
|
12
|
+
return null;
|
|
13
|
+
return (_jsx("div", { className: "min-w-0 rounded-full border border-border px-3 py-1 text-sm", "data-testid": `facets-pill-${i}`, children: _jsx(Slot, { name: s.name, ownLabel: true, render: (handle, defaultDisplay) => (_jsxs("span", { className: "inline-flex min-w-0 items-baseline gap-1.5", "data-testid": "facets-pair", children: [_jsx("span", { className: "shrink-0", children: fieldLabel(handle, t) }), _jsx("span", { className: "min-w-0 font-semibold text-text", children: defaultDisplay })] })) }) }, s.name));
|
|
14
|
+
}) }));
|
|
15
|
+
return (_jsx(BlockShell, { label: g.label, icon: g.icon, children: body }));
|
|
16
|
+
}
|
|
17
|
+
registerRenderer({
|
|
18
|
+
kinds: ['facets'],
|
|
19
|
+
layout: 'block',
|
|
20
|
+
editor: 'custom',
|
|
21
|
+
Page: FacetsPage,
|
|
22
|
+
childWidth: 'w-fit',
|
|
23
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { registerRenderer } from "../../registry.js";
|
|
3
|
+
import { Slot, useSlots } from "../slot.js";
|
|
4
|
+
import { findSlot } from "./block-shell.js";
|
|
5
|
+
function FigurePage({ el }) {
|
|
6
|
+
const g = el;
|
|
7
|
+
const imageName = g.view?.image;
|
|
8
|
+
const captionName = g.view?.caption;
|
|
9
|
+
const slots = useSlots();
|
|
10
|
+
const caption = findSlot(slots, captionName);
|
|
11
|
+
return (_jsxs("figure", { className: "min-w-0", "data-testid": "figure", children: [_jsx("div", { className: "min-w-0", "data-testid": "figure-image", children: _jsx(Slot, { name: imageName }) }), caption && !caption.handle.hidden && (_jsx("figcaption", { className: "mt-2 min-w-0 text-sm text-muted italic", "data-testid": "figure-caption", children: _jsx(Slot, { name: captionName }) }))] }));
|
|
12
|
+
}
|
|
13
|
+
registerRenderer({ kinds: ['figure'], layout: 'block', editor: 'custom', Page: FigurePage });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { registerRenderer } from "../../registry.js";
|
|
3
|
+
import { Slot, useSlots } from "../slot.js";
|
|
4
|
+
import { BlockShell } from "./block-shell.js";
|
|
5
|
+
const COLS = {
|
|
6
|
+
2: 'grid-cols-1 sm:grid-cols-2',
|
|
7
|
+
3: 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3',
|
|
8
|
+
4: 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-4',
|
|
9
|
+
};
|
|
10
|
+
function GridPage({ el }) {
|
|
11
|
+
const g = el;
|
|
12
|
+
const columns = g.view?.columns ?? 3;
|
|
13
|
+
const slots = useSlots();
|
|
14
|
+
const body = (_jsx("div", { className: `grid gap-3 ${COLS[columns] ?? COLS[3]}`, children: slots.map((s, i) => {
|
|
15
|
+
if (s.handle.hidden)
|
|
16
|
+
return null;
|
|
17
|
+
return (_jsx("div", { className: "min-w-0", "data-testid": `grid-item-${i}`, children: _jsx(Slot, { name: s.name }) }, s.name));
|
|
18
|
+
}) }));
|
|
19
|
+
return (_jsx(BlockShell, { label: g.label, icon: g.icon, children: body }));
|
|
20
|
+
}
|
|
21
|
+
registerRenderer({ kinds: ['grid'], layout: 'block', editor: 'custom', Page: GridPage });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { registerRenderer } from "../../registry.js";
|
|
4
|
+
import { groupScopeClass, useGroupDepth, GroupDepthProvider } from "../chrome.js";
|
|
5
|
+
import { useGroupEdit } from "../widgets/group-edit.js";
|
|
6
|
+
import { GroupField } from "../widgets/group-field.js";
|
|
7
|
+
import { useSlot } from "../slot.js";
|
|
8
|
+
import { parseSeriesDate } from "./series.js";
|
|
9
|
+
import { partField } from "../use-collection-rows.js";
|
|
10
|
+
const DAY_MS = 86_400_000;
|
|
11
|
+
const LEVELS = 4;
|
|
12
|
+
const MAX_WEEKS = 260;
|
|
13
|
+
function densityLevel(count, min, max) {
|
|
14
|
+
if (!Number.isFinite(count) || count <= 0)
|
|
15
|
+
return 0;
|
|
16
|
+
if (max === min)
|
|
17
|
+
return Math.ceil(LEVELS / 2);
|
|
18
|
+
return Math.min(LEVELS, Math.max(1, Math.ceil((count / max) * LEVELS)));
|
|
19
|
+
}
|
|
20
|
+
function toDay(t) {
|
|
21
|
+
return Math.floor(t / DAY_MS) * DAY_MS;
|
|
22
|
+
}
|
|
23
|
+
function dayKey(day) {
|
|
24
|
+
return new Date(day).toISOString().slice(0, 10);
|
|
25
|
+
}
|
|
26
|
+
function weekdayIndex(day) {
|
|
27
|
+
return (new Date(day).getUTCDay() + 6) % 7;
|
|
28
|
+
}
|
|
29
|
+
function weekStart(day) {
|
|
30
|
+
return day - weekdayIndex(day) * DAY_MS;
|
|
31
|
+
}
|
|
32
|
+
function weekEnd(day) {
|
|
33
|
+
return day + (6 - weekdayIndex(day)) * DAY_MS;
|
|
34
|
+
}
|
|
35
|
+
function dayGrid(counts) {
|
|
36
|
+
if (counts.size === 0)
|
|
37
|
+
return undefined;
|
|
38
|
+
const sorted = [...counts.keys()].sort((a, b) => a - b);
|
|
39
|
+
let from = sorted[0];
|
|
40
|
+
let to = sorted[sorted.length - 1];
|
|
41
|
+
const weeks = Math.round((weekEnd(to) - weekStart(from) + DAY_MS) / (DAY_MS * 7));
|
|
42
|
+
if (weeks > MAX_WEEKS) {
|
|
43
|
+
const window = busiestWindow(sorted, counts);
|
|
44
|
+
from = window.from;
|
|
45
|
+
to = window.to;
|
|
46
|
+
}
|
|
47
|
+
let clipped = 0;
|
|
48
|
+
for (const [day, n] of counts)
|
|
49
|
+
if (day < from || day > to)
|
|
50
|
+
clipped += n;
|
|
51
|
+
const start = weekStart(from);
|
|
52
|
+
const end = weekEnd(to);
|
|
53
|
+
const days = [];
|
|
54
|
+
for (let d = start; d <= end; d += DAY_MS)
|
|
55
|
+
days.push(d);
|
|
56
|
+
return { days, from, to, clipped };
|
|
57
|
+
}
|
|
58
|
+
function busiestWindow(sorted, counts) {
|
|
59
|
+
const width = (MAX_WEEKS * 7 - 1) * DAY_MS;
|
|
60
|
+
let lo = 0;
|
|
61
|
+
let hi = 0;
|
|
62
|
+
let rows = 0;
|
|
63
|
+
let bestRows = -1;
|
|
64
|
+
let bestStart = weekStart(sorted[0]);
|
|
65
|
+
for (const day of sorted) {
|
|
66
|
+
const start = weekStart(day);
|
|
67
|
+
const end = start + width;
|
|
68
|
+
while (hi < sorted.length && sorted[hi] <= end)
|
|
69
|
+
rows += counts.get(sorted[hi++]);
|
|
70
|
+
while (lo < sorted.length && sorted[lo] < start)
|
|
71
|
+
rows -= counts.get(sorted[lo++]);
|
|
72
|
+
if (rows >= bestRows) {
|
|
73
|
+
bestRows = rows;
|
|
74
|
+
bestStart = start;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const inside = sorted.filter((d) => d >= bestStart && d <= bestStart + width);
|
|
78
|
+
return { from: inside[0], to: inside[inside.length - 1] };
|
|
79
|
+
}
|
|
80
|
+
const WEEKDAYS = ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'];
|
|
81
|
+
function HeatmapPage({ el, value, recordCtx, mode }) {
|
|
82
|
+
const { t } = useTranslation();
|
|
83
|
+
const depth = useGroupDepth();
|
|
84
|
+
const { write } = useSlot();
|
|
85
|
+
const group = el;
|
|
86
|
+
const dateKey = group.view?.['date'];
|
|
87
|
+
const dateFld = partField(group, dateKey);
|
|
88
|
+
const g = useGroupEdit(mode, value, (v) => write(v));
|
|
89
|
+
const rows = Array.isArray(g.value) ? g.value : [];
|
|
90
|
+
const editing = g.mode !== 'view';
|
|
91
|
+
if (!dateKey || !dateFld) {
|
|
92
|
+
return (_jsx(GroupField, { group: { ...group, kind: undefined }, value: value, onChange: (v) => void write(v), recordCtx: recordCtx, mode: mode }));
|
|
93
|
+
}
|
|
94
|
+
const counts = new Map();
|
|
95
|
+
let undated = 0;
|
|
96
|
+
for (const row of rows) {
|
|
97
|
+
const t0 = parseSeriesDate(row[dateKey]);
|
|
98
|
+
if (t0 === undefined) {
|
|
99
|
+
undated += 1;
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
const day = toDay(t0);
|
|
103
|
+
counts.set(day, (counts.get(day) ?? 0) + 1);
|
|
104
|
+
}
|
|
105
|
+
const grid = dayGrid(counts);
|
|
106
|
+
const active = grid ? [...counts.entries()].filter(([d]) => d >= grid.from && d <= grid.to).map(([, c]) => c) : [];
|
|
107
|
+
const max = active.length ? Math.max(...active) : 0;
|
|
108
|
+
const min = active.length ? Math.min(...active) : 0;
|
|
109
|
+
const offGrid = undated + (grid?.clipped ?? 0);
|
|
110
|
+
const editor = (_jsx(GroupField, { group: { ...group, kind: undefined }, value: g.value, onChange: (v) => g.onChange(v), recordCtx: recordCtx, mode: "edit" }));
|
|
111
|
+
const monthLabels = grid
|
|
112
|
+
? Array.from({ length: grid.days.length / 7 }, (_, w) => {
|
|
113
|
+
const monday = grid.days[w * 7];
|
|
114
|
+
const prev = w > 0 ? grid.days[(w - 1) * 7] : undefined;
|
|
115
|
+
const month = new Date(monday).getUTCMonth();
|
|
116
|
+
const show = prev === undefined || new Date(prev).getUTCMonth() !== month;
|
|
117
|
+
return (_jsx("div", { className: "h-3 whitespace-nowrap", children: show ? new Date(monday).toLocaleDateString(undefined, { month: 'short', timeZone: 'UTC' }) : '' }, w));
|
|
118
|
+
})
|
|
119
|
+
: [];
|
|
120
|
+
const cells = (grid?.days ?? []).map((day) => {
|
|
121
|
+
if (day < grid.from || day > grid.to) {
|
|
122
|
+
return _jsx("div", { className: "h-4 w-4", "data-testid": "heatmap-pad" }, day);
|
|
123
|
+
}
|
|
124
|
+
const count = counts.get(day) ?? 0;
|
|
125
|
+
const level = densityLevel(count, min, max);
|
|
126
|
+
const key = dayKey(day);
|
|
127
|
+
return (_jsxs("div", { "data-testid": `heatmap-day-${key}`, "data-count": count, "data-level": level, title: `${key} · ${count}`, className: `relative h-4 w-4 overflow-hidden rounded-[3px] border ${count > 0 ? 'border-accent/30' : 'border-border'}`, children: [level > 0 && (_jsx("span", { "aria-hidden": true, className: "absolute inset-x-0 bottom-0 bg-accent/15", style: { height: `${Math.round((level / LEVELS) * 100)}%` } })), count > 0 && _jsx("span", { className: "sr-only", children: `${key} · ${count}` })] }, day));
|
|
128
|
+
});
|
|
129
|
+
const map = grid === undefined ? (_jsx("p", { className: "py-1 text-sm text-muted", "data-testid": "heatmap-empty", children: t('form.noDates', 'No dated entries yet') })) : (_jsx("div", { className: "max-w-full overflow-x-auto", "data-testid": "heatmap-body", children: _jsxs("div", { className: "inline-flex flex-col gap-1", children: [_jsxs("div", { className: "flex gap-1", children: [_jsx("div", { className: "w-5 shrink-0" }), _jsx("div", { className: "grid grid-flow-col auto-cols-[1rem] gap-1 text-[9px] leading-3 text-muted", children: monthLabels })] }), _jsxs("div", { className: "flex gap-1", children: [_jsx("div", { className: "grid w-5 shrink-0 grid-rows-7 gap-1 text-[9px] leading-4 text-muted", children: WEEKDAYS.map((wd, i) => (_jsx("div", { children: i % 2 === 0 ? wd : '' }, wd))) }), _jsx("div", { className: "grid grid-rows-7 grid-flow-col auto-cols-[1rem] gap-1", "data-testid": "heatmap-grid", children: cells })] })] }) }));
|
|
130
|
+
const content = editing ? (editor) : (_jsxs("div", { className: "flex flex-col gap-1.5", children: [map, offGrid > 0 && (_jsx("p", { className: "text-[11px] text-muted", "data-testid": "heatmap-offgrid", children: t('form.offGrid', { n: offGrid, defaultValue: '{{n}} not on the grid' }) }))] }));
|
|
131
|
+
if (mode !== 'view')
|
|
132
|
+
return content;
|
|
133
|
+
return (_jsxs("section", { className: `${groupScopeClass(depth)} flex flex-col gap-1 min-w-0`, "data-testid": "heatmap", children: [group.label && (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("h3", { className: "text-[13px] font-semibold text-accent", children: t(group.label) }), 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 })] }));
|
|
134
|
+
}
|
|
135
|
+
registerRenderer({ kinds: ['heatmap'], layout: 'block', Page: HeatmapPage, editor: 'custom' });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { registerRenderer } from "../../registry.js";
|
|
3
|
+
import { Slot, useSlots } from "../slot.js";
|
|
4
|
+
import { findSlot, findSlots } from "./block-shell.js";
|
|
5
|
+
function groupedNumber(raw) {
|
|
6
|
+
const compact = raw.replace(/\s+/g, '');
|
|
7
|
+
if (!compact)
|
|
8
|
+
return '';
|
|
9
|
+
const groups = [];
|
|
10
|
+
for (let i = 0; i < compact.length; i += 4)
|
|
11
|
+
groups.push(compact.slice(i, i + 4));
|
|
12
|
+
return groups.join(' ');
|
|
13
|
+
}
|
|
14
|
+
function IdcardPage({ el }) {
|
|
15
|
+
const g = el;
|
|
16
|
+
const numberName = g.view?.number;
|
|
17
|
+
const overlineName = g.view?.overline;
|
|
18
|
+
const metaNames = g.view?.meta ?? [];
|
|
19
|
+
const slots = useSlots();
|
|
20
|
+
const overline = findSlot(slots, overlineName);
|
|
21
|
+
const metaVisible = findSlots(slots, metaNames).filter((s) => !s.handle.hidden);
|
|
22
|
+
return (_jsxs("div", { className: "space-y-1", "data-testid": "idcard", children: [overline && !overline.handle.hidden && (_jsx("div", { className: "min-w-0 text-xs font-medium uppercase tracking-widest text-muted", "data-testid": "idcard-overline", children: _jsx(Slot, { name: overlineName }) })), _jsx("div", { className: "min-w-0", children: _jsx(Slot, { name: numberName, render: (handle, defaultDisplay) => {
|
|
23
|
+
const raw = typeof handle.value === 'string' || typeof handle.value === 'number' ? String(handle.value) : '';
|
|
24
|
+
const grouped = groupedNumber(raw);
|
|
25
|
+
if (!grouped)
|
|
26
|
+
return defaultDisplay;
|
|
27
|
+
return (_jsx("span", { className: "font-mono text-2xl font-semibold tracking-widest tabular-nums", "data-testid": "idcard-number", children: grouped }));
|
|
28
|
+
} }) }), metaVisible.length > 0 && (_jsx("div", { className: "flex flex-wrap items-center gap-x-1 border-t border-b border-border py-1.5 text-sm text-muted", "data-testid": "idcard-meta", children: metaVisible.map((s, i) => (_jsx("span", { className: `inline-flex min-w-0 items-center ${i > 0 ? "before:mr-2 before:text-muted before:content-['·']" : ''}`, "data-testid": `idcard-meta-${i}`, children: _jsx(Slot, { name: s.name }) }, s.name))) }))] }));
|
|
29
|
+
}
|
|
30
|
+
registerRenderer({ kinds: ['idcard'], layout: 'block', editor: 'custom', Page: IdcardPage });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Phone, Mail, Link as LinkIcon } from 'lucide-react';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import { registerRenderer } from "../../registry.js";
|
|
5
|
+
import { Slot, useSlots } from "../slot.js";
|
|
6
|
+
import { BlockShell, fieldLabel, findSlot, findSlots } from "./block-shell.js";
|
|
7
|
+
const linkHrefOf = (s) => (/^[a-z][a-z0-9+.-]*:\/\//i.test(s) ? s : `https://${s}`);
|
|
8
|
+
function channelHref(field, value) {
|
|
9
|
+
if (field.kind === 'tel') {
|
|
10
|
+
const s = String(value ?? '').trim();
|
|
11
|
+
return s ? `tel:${s}` : undefined;
|
|
12
|
+
}
|
|
13
|
+
if (field.kind === 'email') {
|
|
14
|
+
const s = String(value ?? '').trim();
|
|
15
|
+
return s ? `mailto:${s}` : undefined;
|
|
16
|
+
}
|
|
17
|
+
if (field.kind === 'link') {
|
|
18
|
+
const s = String(value ?? '').trim();
|
|
19
|
+
return s ? linkHrefOf(s) : undefined;
|
|
20
|
+
}
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
const CHANNEL_ICON = { tel: Phone, email: Mail, link: LinkIcon };
|
|
24
|
+
function IdentityPage({ el }) {
|
|
25
|
+
const g = el;
|
|
26
|
+
const { t } = useTranslation();
|
|
27
|
+
const avatarName = g.view?.avatar;
|
|
28
|
+
const nameName = g.view?.name;
|
|
29
|
+
const roleName = g.view?.role;
|
|
30
|
+
const channelNames = g.view?.channels ?? [];
|
|
31
|
+
const slots = useSlots();
|
|
32
|
+
const avatar = findSlot(slots, avatarName);
|
|
33
|
+
const role = findSlot(slots, roleName);
|
|
34
|
+
const channels = findSlots(slots, channelNames);
|
|
35
|
+
const visibleChannels = channels.filter((c) => !c.handle.hidden);
|
|
36
|
+
const body = (_jsxs("div", { className: "flex items-center gap-3", "data-testid": "identity", children: [avatar && !avatar.handle.hidden && (_jsx("div", { className: "shrink-0", "data-testid": "identity-avatar", children: _jsx(Slot, { name: avatarName }) })), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "min-w-0 text-lg font-semibold", "data-testid": "identity-name", children: _jsx(Slot, { name: nameName }) }), role && !role.handle.hidden && (_jsx("div", { className: "min-w-0 text-sm text-muted", "data-testid": "identity-role", children: _jsx(Slot, { name: roleName }) }))] }), visibleChannels.length > 0 && (_jsx("div", { className: "flex shrink-0 items-center gap-1.5", "data-testid": "identity-channels", children: channels.map((c) => c.handle.hidden ? null : (_jsx("span", { children: _jsx(Slot, { name: c.name, ownLabel: true, render: (handle, defaultDisplay) => {
|
|
37
|
+
const field = handle.field.type;
|
|
38
|
+
const href = channelHref(field, handle.value);
|
|
39
|
+
if (!href)
|
|
40
|
+
return defaultDisplay;
|
|
41
|
+
const Ico = CHANNEL_ICON[field.kind] ?? LinkIcon;
|
|
42
|
+
return (_jsx("a", { href: href, "aria-label": fieldLabel(handle, t), className: "inline-flex h-9 w-9 items-center justify-center rounded-lg border border-border text-muted transition-colors hover:border-accent hover:text-accent", children: _jsx(Ico, { size: 16 }) }));
|
|
43
|
+
} }) }, c.name))) }))] }));
|
|
44
|
+
return (_jsx(BlockShell, { label: g.label, icon: g.icon, children: body }));
|
|
45
|
+
}
|
|
46
|
+
registerRenderer({ kinds: ['identity'], layout: 'block', editor: 'custom', Page: IdentityPage });
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import './grid.tsx';
|
|
2
|
+
import './bento.tsx';
|
|
3
|
+
import './split.tsx';
|
|
4
|
+
import './aside.tsx';
|
|
5
|
+
import './spread.tsx';
|
|
6
|
+
import './tabs.tsx';
|
|
7
|
+
import './accordion.tsx';
|
|
8
|
+
import './ledger.tsx';
|
|
9
|
+
import './stats.tsx';
|
|
10
|
+
import './facets.tsx';
|
|
11
|
+
import './prose.tsx';
|
|
12
|
+
import './epigraph.tsx';
|
|
13
|
+
import './terminal.tsx';
|
|
14
|
+
import './plaque.tsx';
|
|
15
|
+
import './figure.tsx';
|
|
16
|
+
import './compare.tsx';
|
|
17
|
+
import './callout.tsx';
|
|
18
|
+
import './masthead.tsx';
|
|
19
|
+
import './score.tsx';
|
|
20
|
+
import './status.tsx';
|
|
21
|
+
import './meter.tsx';
|
|
22
|
+
import './balance.tsx';
|
|
23
|
+
import './countdown.tsx';
|
|
24
|
+
import './deck.tsx';
|
|
25
|
+
import './people.tsx';
|
|
26
|
+
import './identity.tsx';
|
|
27
|
+
import './timeline.tsx';
|
|
28
|
+
import './receipt.tsx';
|
|
29
|
+
import './idcard.tsx';
|
|
30
|
+
import './route.tsx';
|
|
31
|
+
import './specimen.tsx';
|
|
32
|
+
import './nutrition.tsx';
|
|
33
|
+
import './calendar.tsx';
|
|
34
|
+
import './journal.tsx';
|
|
35
|
+
import './manifest.tsx';
|
|
36
|
+
import './table.tsx';
|
|
37
|
+
import './properties.tsx';
|
|
38
|
+
import './stack.tsx';
|
|
39
|
+
import './chart.tsx';
|
|
40
|
+
import './heatmap.tsx';
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import "./grid.js";
|
|
2
|
+
import "./bento.js";
|
|
3
|
+
import "./split.js";
|
|
4
|
+
import "./aside.js";
|
|
5
|
+
import "./spread.js";
|
|
6
|
+
import "./tabs.js";
|
|
7
|
+
import "./accordion.js";
|
|
8
|
+
import "./ledger.js";
|
|
9
|
+
import "./stats.js";
|
|
10
|
+
import "./facets.js";
|
|
11
|
+
import "./prose.js";
|
|
12
|
+
import "./epigraph.js";
|
|
13
|
+
import "./terminal.js";
|
|
14
|
+
import "./plaque.js";
|
|
15
|
+
import "./figure.js";
|
|
16
|
+
import "./compare.js";
|
|
17
|
+
import "./callout.js";
|
|
18
|
+
import "./masthead.js";
|
|
19
|
+
import "./score.js";
|
|
20
|
+
import "./status.js";
|
|
21
|
+
import "./meter.js";
|
|
22
|
+
import "./balance.js";
|
|
23
|
+
import "./countdown.js";
|
|
24
|
+
import "./deck.js";
|
|
25
|
+
import "./people.js";
|
|
26
|
+
import "./identity.js";
|
|
27
|
+
import "./timeline.js";
|
|
28
|
+
import "./receipt.js";
|
|
29
|
+
import "./idcard.js";
|
|
30
|
+
import "./route.js";
|
|
31
|
+
import "./specimen.js";
|
|
32
|
+
import "./nutrition.js";
|
|
33
|
+
import "./calendar.js";
|
|
34
|
+
import "./journal.js";
|
|
35
|
+
import "./manifest.js";
|
|
36
|
+
import "./table.js";
|
|
37
|
+
import "./properties.js";
|
|
38
|
+
import "./stack.js";
|
|
39
|
+
import "./chart.js";
|
|
40
|
+
import "./heatmap.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { isNamedField, isStorageGroup } from '@coffer-org/sdk/fields';
|
|
4
|
+
import { registerRenderer } from "../../registry.js";
|
|
5
|
+
import { AddBtn } from "../shared.js";
|
|
6
|
+
import { RemoveBtn } from "../multiple-chips.js";
|
|
7
|
+
import { STACK, Rail, groupScopeClass, useGroupDepth, GroupDepthProvider } from "../chrome.js";
|
|
8
|
+
import { useGroupEdit } from "../widgets/group-edit.js";
|
|
9
|
+
import { useHybridScope } from "../hybrid-scope.js";
|
|
10
|
+
import { FieldSlot } from "../dispatch.js";
|
|
11
|
+
import { GroupField } from "../widgets/group-field.js";
|
|
12
|
+
import { ChecklistContent } from "../widgets/checklist-content.js";
|
|
13
|
+
import { useFieldErrors } from "../field-errors.js";
|
|
14
|
+
import { useCollectionRows, partField } from "../use-collection-rows.js";
|
|
15
|
+
import { useSlot } from "../slot.js";
|
|
16
|
+
function cellNode(f, row, key, editing, live, onCommit, recordCtx, error) {
|
|
17
|
+
if (editing) {
|
|
18
|
+
return (_jsx(FieldSlot, { el: f, field: f.type, fieldKey: key, value: row[key] ?? '', onChange: onCommit, mode: "edit", bare: true, recordCtx: recordCtx, error: error }));
|
|
19
|
+
}
|
|
20
|
+
return (_jsx(FieldSlot, { el: f, field: f.type, fieldKey: live ? key : undefined, value: row[key] ?? '', mode: "view", bare: !live, recordCtx: recordCtx, onChange: live ? onCommit : undefined, error: error }));
|
|
21
|
+
}
|
|
22
|
+
function JournalPage({ el, value, recordCtx, mode }) {
|
|
23
|
+
const { t } = useTranslation();
|
|
24
|
+
const depth = useGroupDepth();
|
|
25
|
+
const errorAt = useFieldErrors();
|
|
26
|
+
const { write } = useSlot();
|
|
27
|
+
const group = el;
|
|
28
|
+
const dateKey = group.view?.['date'];
|
|
29
|
+
const textKey = group.view?.['text'];
|
|
30
|
+
const dateFld = partField(group, dateKey);
|
|
31
|
+
const textFld = partField(group, textKey);
|
|
32
|
+
const g = useGroupEdit(mode, value, (v) => write(v));
|
|
33
|
+
const rows = Array.isArray(g.value) ? g.value : [];
|
|
34
|
+
const editing = g.mode !== 'view';
|
|
35
|
+
const live = useHybridScope() && mode === 'view';
|
|
36
|
+
const rowTools = editing || live;
|
|
37
|
+
const { rowId, updateRow, removeRow, addRow } = useCollectionRows(rows, (v) => g.onChange(v));
|
|
38
|
+
if (!dateFld || !textFld || !dateKey || !textKey) {
|
|
39
|
+
return (_jsx(GroupField, { group: { ...group, kind: undefined }, value: value, onChange: (v) => void write(v), recordCtx: recordCtx, mode: mode }));
|
|
40
|
+
}
|
|
41
|
+
const restFields = group.fields
|
|
42
|
+
.filter((f) => isNamedField(f) && f.key !== dateKey && f.key !== textKey)
|
|
43
|
+
.map((f) => ({ key: f.key, type: f.type }));
|
|
44
|
+
const errorFor = (idx, key) => isStorageGroup(group) ? errorAt([group.key, idx, key]) : undefined;
|
|
45
|
+
const content = (_jsxs("div", { className: `flex flex-col ${STACK}`, children: [rows.map((row, idx) => (_jsx(Rail, { children: _jsxs("div", { className: "flex items-start gap-3", "data-testid": `journal-entry-${idx}`, children: [_jsx("div", { className: "w-20 shrink-0 text-xs text-muted tabular-nums", "data-testid": `journal-date-${idx}`, children: cellNode(dateFld, row, dateKey, editing, live, (v) => updateRow(idx, dateKey, v), recordCtx, errorFor(idx, dateKey)) }), _jsx("div", { className: "min-w-0 flex-1 text-sm", "data-testid": `journal-text-${idx}`, children: cellNode(textFld, row, textKey, editing, live, (v) => updateRow(idx, textKey, v), recordCtx, errorFor(idx, textKey)) }), restFields.length > 0 && (_jsx(ChecklistContent, { fields: restFields, row: row, editing: editing, onChange: (key, v) => updateRow(idx, key, v), recordCtx: recordCtx, error: (key) => errorFor(idx, key) })), rowTools && _jsx(RemoveBtn, { className: "mt-0.5", onClick: () => removeRow(idx) })] }) }, rowId(row)))), rowTools && _jsx(AddBtn, { onClick: addRow, children: t('form.addRow') })] }));
|
|
46
|
+
if (mode !== 'view')
|
|
47
|
+
return content;
|
|
48
|
+
return (_jsxs("section", { className: `${groupScopeClass(depth)} flex flex-col gap-1 min-w-0`, "data-testid": "journal", children: [group.label && (_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 })] }));
|
|
49
|
+
}
|
|
50
|
+
registerRenderer({ kinds: ['journal'], layout: 'block', Page: JournalPage, editor: 'custom' });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { registerRenderer } from "../../registry.js";
|
|
4
|
+
import { Slot, useSlots } from "../slot.js";
|
|
5
|
+
import { BlockShell, fieldLabel } from "./block-shell.js";
|
|
6
|
+
function LedgerPage({ el }) {
|
|
7
|
+
const g = el;
|
|
8
|
+
const { t } = useTranslation();
|
|
9
|
+
const slots = useSlots();
|
|
10
|
+
const body = (_jsx("div", { className: "flex flex-col divide-y divide-border", "data-testid": "ledger", children: slots.map((s, i) => {
|
|
11
|
+
if (s.handle.hidden)
|
|
12
|
+
return null;
|
|
13
|
+
return (_jsx("div", { className: "min-w-0 py-2", "data-testid": `ledger-row-${i}`, children: _jsx(Slot, { name: s.name, ownLabel: true, render: (handle, defaultDisplay) => (_jsxs("span", { className: "flex w-full min-w-0 items-baseline gap-2", "data-testid": "ledger-leader", children: [_jsx("span", { className: "shrink-0", children: fieldLabel(handle, t) }), _jsx("span", { className: "min-w-0 flex-1 border-b border-dotted border-border", "data-testid": "ledger-dots" }), _jsx("span", { className: "shrink-0 text-right font-medium tabular-nums", children: defaultDisplay })] })) }) }, s.name));
|
|
14
|
+
}) }));
|
|
15
|
+
return (_jsx(BlockShell, { label: g.label, icon: g.icon, children: body }));
|
|
16
|
+
}
|
|
17
|
+
registerRenderer({
|
|
18
|
+
kinds: ['ledger'],
|
|
19
|
+
layout: 'block',
|
|
20
|
+
editor: 'custom',
|
|
21
|
+
Page: LedgerPage,
|
|
22
|
+
childWidth: 'w-full',
|
|
23
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { isNamedField, isStorageGroup } from '@coffer-org/sdk/fields';
|
|
4
|
+
import { registerRenderer } from "../../registry.js";
|
|
5
|
+
import { AddBtn } from "../shared.js";
|
|
6
|
+
import { RemoveBtn } from "../multiple-chips.js";
|
|
7
|
+
import { STACK, Rail, groupScopeClass, useGroupDepth, GroupDepthProvider } from "../chrome.js";
|
|
8
|
+
import { useGroupEdit } from "../widgets/group-edit.js";
|
|
9
|
+
import { useHybridScope } from "../hybrid-scope.js";
|
|
10
|
+
import { FieldSlot } from "../dispatch.js";
|
|
11
|
+
import { GroupField } from "../widgets/group-field.js";
|
|
12
|
+
import { ChecklistContent } from "../widgets/checklist-content.js";
|
|
13
|
+
import { useFieldErrors } from "../field-errors.js";
|
|
14
|
+
import { useCollectionRows, partField } from "../use-collection-rows.js";
|
|
15
|
+
import { useSlot } from "../slot.js";
|
|
16
|
+
function cellNode(f, row, key, editing, live, onCommit, recordCtx, error) {
|
|
17
|
+
if (editing) {
|
|
18
|
+
return (_jsx(FieldSlot, { el: f, field: f.type, fieldKey: key, value: row[key] ?? '', onChange: onCommit, mode: "edit", bare: true, recordCtx: recordCtx, error: error }));
|
|
19
|
+
}
|
|
20
|
+
return (_jsx(FieldSlot, { el: f, field: f.type, fieldKey: live ? key : undefined, value: row[key] ?? '', mode: "view", bare: !live, recordCtx: recordCtx, onChange: live ? onCommit : undefined, error: error }));
|
|
21
|
+
}
|
|
22
|
+
function ManifestPage({ el, value, recordCtx, mode }) {
|
|
23
|
+
const { t } = useTranslation();
|
|
24
|
+
const depth = useGroupDepth();
|
|
25
|
+
const errorAt = useFieldErrors();
|
|
26
|
+
const { write } = useSlot();
|
|
27
|
+
const group = el;
|
|
28
|
+
const qtyKey = group.view?.['quantity'];
|
|
29
|
+
const itemKey = group.view?.['item'];
|
|
30
|
+
const qtyFld = partField(group, qtyKey);
|
|
31
|
+
const itemFld = partField(group, itemKey);
|
|
32
|
+
const g = useGroupEdit(mode, value, (v) => write(v));
|
|
33
|
+
const rows = Array.isArray(g.value) ? g.value : [];
|
|
34
|
+
const editing = g.mode !== 'view';
|
|
35
|
+
const live = useHybridScope() && mode === 'view';
|
|
36
|
+
const rowTools = editing || live;
|
|
37
|
+
const { rowId, updateRow, removeRow, addRow } = useCollectionRows(rows, (v) => g.onChange(v));
|
|
38
|
+
if (!qtyFld || !itemFld || !qtyKey || !itemKey) {
|
|
39
|
+
return (_jsx(GroupField, { group: { ...group, kind: undefined }, value: value, onChange: (v) => void write(v), recordCtx: recordCtx, mode: mode }));
|
|
40
|
+
}
|
|
41
|
+
const restFields = group.fields
|
|
42
|
+
.filter((f) => isNamedField(f) && f.key !== qtyKey && f.key !== itemKey)
|
|
43
|
+
.map((f) => ({ key: f.key, type: f.type }));
|
|
44
|
+
const errorFor = (idx, key) => isStorageGroup(group) ? errorAt([group.key, idx, key]) : undefined;
|
|
45
|
+
const content = (_jsxs("div", { className: `flex flex-col ${STACK}`, children: [rows.map((row, idx) => (_jsx(Rail, { children: _jsxs("div", { className: "flex items-center gap-3", "data-testid": `manifest-row-${idx}`, children: [_jsx("div", { className: "w-12 shrink-0 text-right text-sm tabular-nums", "data-testid": `manifest-quantity-${idx}`, children: cellNode(qtyFld, row, qtyKey, editing, live, (v) => updateRow(idx, qtyKey, v), recordCtx, errorFor(idx, qtyKey)) }), _jsx("div", { className: "min-w-0 flex-1 text-sm", "data-testid": `manifest-item-${idx}`, children: cellNode(itemFld, row, itemKey, editing, live, (v) => updateRow(idx, itemKey, v), recordCtx, errorFor(idx, itemKey)) }), restFields.length > 0 && (_jsx(ChecklistContent, { fields: restFields, row: row, editing: editing, onChange: (key, v) => updateRow(idx, key, v), recordCtx: recordCtx, error: (key) => errorFor(idx, key) })), rowTools && _jsx(RemoveBtn, { onClick: () => removeRow(idx) })] }) }, rowId(row)))), rowTools && _jsx(AddBtn, { onClick: addRow, children: t('form.addRow') })] }));
|
|
46
|
+
if (mode !== 'view')
|
|
47
|
+
return content;
|
|
48
|
+
return (_jsxs("section", { className: `${groupScopeClass(depth)} flex flex-col gap-1 min-w-0`, "data-testid": "manifest", children: [group.label && (_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 })] }));
|
|
49
|
+
}
|
|
50
|
+
registerRenderer({ kinds: ['manifest'], layout: 'block', Page: ManifestPage, editor: 'custom' });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { registerRenderer } from "../../registry.js";
|
|
3
|
+
import { Slot, useSlots } from "../slot.js";
|
|
4
|
+
import { findSlot, findSlots } from "./block-shell.js";
|
|
5
|
+
function MastheadPage({ el }) {
|
|
6
|
+
const g = el;
|
|
7
|
+
const titleName = g.view?.title;
|
|
8
|
+
const overlineName = g.view?.overline;
|
|
9
|
+
const metaNames = g.view?.meta ?? [];
|
|
10
|
+
const slots = useSlots();
|
|
11
|
+
const overline = findSlot(slots, overlineName);
|
|
12
|
+
const metaVisible = findSlots(slots, metaNames).filter((s) => !s.handle.hidden);
|
|
13
|
+
return (_jsxs("div", { className: "space-y-1", "data-testid": "masthead", children: [overline && !overline.handle.hidden && (_jsx("div", { className: "min-w-0 text-xs font-medium uppercase tracking-widest text-muted", "data-testid": "masthead-overline", children: _jsx(Slot, { name: overlineName }) })), _jsx("div", { className: "min-w-0 text-2xl leading-tight font-bold", "data-testid": "masthead-title", children: _jsx(Slot, { name: titleName }) }), metaVisible.length > 0 && (_jsx("div", { className: "flex flex-wrap items-center gap-x-1 border-t border-b border-border py-1.5 text-sm text-muted", "data-testid": "masthead-meta", children: metaVisible.map((s, i) => (_jsx("span", { className: `inline-flex min-w-0 items-center ${i > 0 ? "before:mr-2 before:text-muted before:content-['·']" : ''}`, "data-testid": `masthead-meta-${i}`, children: _jsx(Slot, { name: s.name }) }, s.name))) }))] }));
|
|
14
|
+
}
|
|
15
|
+
registerRenderer({ kinds: ['masthead'], layout: 'block', editor: 'custom', Page: MastheadPage });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { registerRenderer } from "../../registry.js";
|
|
3
|
+
import { Slot, useSlots } from "../slot.js";
|
|
4
|
+
import { BlockShell, findSlot } from "./block-shell.js";
|
|
5
|
+
function resolveRange(view, field) {
|
|
6
|
+
const min = Number(view?.min ?? field.hints['min'] ?? 0);
|
|
7
|
+
const maxRaw = view?.max ?? field.hints['max'];
|
|
8
|
+
const max = maxRaw != null ? Number(maxRaw) : min + 1;
|
|
9
|
+
return { min: Number.isFinite(min) ? min : 0, max: Number.isFinite(max) && max > min ? max : min + 1 };
|
|
10
|
+
}
|
|
11
|
+
function magnitudeOf(value) {
|
|
12
|
+
if (value != null && typeof value === 'object' && 'value' in value) {
|
|
13
|
+
return Number(value['value']);
|
|
14
|
+
}
|
|
15
|
+
return Number(value);
|
|
16
|
+
}
|
|
17
|
+
function MeterPage({ el }) {
|
|
18
|
+
const g = el;
|
|
19
|
+
const sourceName = g.view?.source;
|
|
20
|
+
const ofName = g.view?.of;
|
|
21
|
+
const view = g.view;
|
|
22
|
+
const slots = useSlots();
|
|
23
|
+
const of = findSlot(slots, ofName);
|
|
24
|
+
const body = (_jsxs("div", { className: "flex flex-wrap items-end gap-3", "data-testid": "meter", children: [_jsx("div", { className: "min-w-0 flex-1", children: _jsx(Slot, { name: sourceName, render: (handle, defaultDisplay) => {
|
|
25
|
+
const { min, max } = resolveRange(view, handle.field.type);
|
|
26
|
+
const n = magnitudeOf(handle.value);
|
|
27
|
+
const ratio = Number.isFinite(n) ? Math.max(0, Math.min(1, (n - min) / (max - min))) : 0;
|
|
28
|
+
return (_jsxs("span", { className: "flex min-w-0 flex-col gap-1", "data-testid": "meter-figure", children: [_jsx("span", { className: "text-2xl font-semibold tabular-nums", children: defaultDisplay }), _jsx("span", { role: "progressbar", "aria-valuemin": min, "aria-valuemax": max, "aria-valuenow": Number.isFinite(n) ? Math.max(min, Math.min(max, n)) : min, className: "h-2 w-full overflow-hidden rounded-full bg-border", "data-testid": "meter-bar", children: _jsx("span", { className: "block h-full rounded-full bg-accent transition-[width]", style: { width: `${ratio * 100}%` }, "data-testid": "meter-fill" }) })] }));
|
|
29
|
+
} }) }), of && !of.handle.hidden && (_jsx("div", { className: "min-w-0 text-sm text-muted", "data-testid": "meter-of", children: _jsx(Slot, { name: ofName }) }))] }));
|
|
30
|
+
return (_jsx(BlockShell, { label: g.label, icon: g.icon, children: body }));
|
|
31
|
+
}
|
|
32
|
+
registerRenderer({ kinds: ['meter'], layout: 'block', editor: 'custom', Page: MeterPage });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { registerRenderer } from "../../registry.js";
|
|
4
|
+
import { Slot, useSlots } from "../slot.js";
|
|
5
|
+
import { BlockShell, fieldLabel, findSlot, findSlots } from "./block-shell.js";
|
|
6
|
+
function NutritionPage({ el }) {
|
|
7
|
+
const g = el;
|
|
8
|
+
const { t } = useTranslation();
|
|
9
|
+
const energyName = g.view?.energy;
|
|
10
|
+
const fieldNames = g.view?.fields ?? [];
|
|
11
|
+
const slots = useSlots();
|
|
12
|
+
const energy = findSlot(slots, energyName);
|
|
13
|
+
const rows = findSlots(slots, fieldNames);
|
|
14
|
+
const energyVisible = energy !== undefined && !energy.handle.hidden;
|
|
15
|
+
const visibleRows = rows.filter((r) => !r.handle.hidden);
|
|
16
|
+
if (!energyVisible && visibleRows.length === 0)
|
|
17
|
+
return (_jsx(BlockShell, { label: g.label, icon: g.icon, children: null }));
|
|
18
|
+
const body = (_jsxs("div", { className: "w-full max-w-xs border-2 border-text p-3", "data-testid": "nutrition", children: [energyVisible && (_jsx("div", { className: "mb-2 border-b-4 border-text pb-2", "data-testid": "nutrition-energy-row", children: _jsx(Slot, { name: energyName, ownLabel: true, render: (handle, defaultDisplay) => (_jsxs("span", { className: "flex w-full min-w-0 items-baseline justify-between gap-3", "data-testid": "nutrition-energy", children: [_jsx("span", { className: "min-w-0 text-base font-bold uppercase tracking-wide", children: fieldLabel(handle, t) }), _jsx("span", { className: "shrink-0 text-2xl font-black tabular-nums", children: defaultDisplay })] })) }) })), _jsx("div", { className: "flex flex-col divide-y divide-border", children: rows.map((r, i) => r.handle.hidden ? null : (_jsx("div", { className: "min-w-0 py-1", "data-testid": `nutrition-row-${i}`, children: _jsx(Slot, { name: r.name, ownLabel: true, render: (handle, defaultDisplay) => (_jsxs("span", { className: "flex w-full min-w-0 items-baseline justify-between gap-3 text-sm", children: [_jsx("span", { className: "min-w-0", children: fieldLabel(handle, t) }), _jsx("span", { className: "shrink-0 text-right font-medium tabular-nums", children: defaultDisplay })] })) }) }, r.name))) })] }));
|
|
19
|
+
return (_jsx(BlockShell, { label: g.label, icon: g.icon, children: body }));
|
|
20
|
+
}
|
|
21
|
+
registerRenderer({
|
|
22
|
+
kinds: ['nutrition'],
|
|
23
|
+
layout: 'block',
|
|
24
|
+
editor: 'custom',
|
|
25
|
+
Page: NutritionPage,
|
|
26
|
+
childWidth: 'w-full',
|
|
27
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|