@panphora/bevel 0.1.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/LICENSE +16 -0
- package/README.md +226 -0
- package/bevel-fonts.css +16 -0
- package/bevel.css +3075 -0
- package/bevel.js +2126 -0
- package/dist/react/components/activity-feed.d.ts +89 -0
- package/dist/react/components/activity-feed.js +54 -0
- package/dist/react/components/alert-dialog.d.ts +14 -0
- package/dist/react/components/alert-dialog.js +19 -0
- package/dist/react/components/app-shell.d.ts +98 -0
- package/dist/react/components/app-shell.js +86 -0
- package/dist/react/components/app-toolbar.d.ts +19 -0
- package/dist/react/components/app-toolbar.js +22 -0
- package/dist/react/components/avatar-group.d.ts +67 -0
- package/dist/react/components/avatar-group.js +49 -0
- package/dist/react/components/badge-and-pill.d.ts +34 -0
- package/dist/react/components/badge-and-pill.js +12 -0
- package/dist/react/components/breadcrumbs.d.ts +56 -0
- package/dist/react/components/breadcrumbs.js +44 -0
- package/dist/react/components/bulk-bar.d.ts +22 -0
- package/dist/react/components/bulk-bar.js +59 -0
- package/dist/react/components/button.d.ts +15 -0
- package/dist/react/components/button.js +20 -0
- package/dist/react/components/callout-and-hint.d.ts +17 -0
- package/dist/react/components/callout-and-hint.js +8 -0
- package/dist/react/components/checkbox.d.ts +5 -0
- package/dist/react/components/checkbox.js +13 -0
- package/dist/react/components/chip.d.ts +149 -0
- package/dist/react/components/chip.js +29 -0
- package/dist/react/components/code-block.d.ts +50 -0
- package/dist/react/components/code-block.js +77 -0
- package/dist/react/components/code-editor.d.ts +122 -0
- package/dist/react/components/code-editor.js +695 -0
- package/dist/react/components/column-manager.d.ts +28 -0
- package/dist/react/components/column-manager.js +85 -0
- package/dist/react/components/combobox.d.ts +32 -0
- package/dist/react/components/combobox.js +37 -0
- package/dist/react/components/data-grid.d.ts +108 -0
- package/dist/react/components/data-grid.js +159 -0
- package/dist/react/components/data-table.d.ts +2 -0
- package/dist/react/components/data-table.js +6 -0
- package/dist/react/components/date.d.ts +23 -0
- package/dist/react/components/date.js +11 -0
- package/dist/react/components/details.d.ts +13 -0
- package/dist/react/components/details.js +20 -0
- package/dist/react/components/dialog.d.ts +74 -0
- package/dist/react/components/dialog.js +31 -0
- package/dist/react/components/diff-view.d.ts +73 -0
- package/dist/react/components/diff-view.js +68 -0
- package/dist/react/components/documents.d.ts +70 -0
- package/dist/react/components/documents.js +10 -0
- package/dist/react/components/drawer.d.ts +45 -0
- package/dist/react/components/drawer.js +35 -0
- package/dist/react/components/editable-grid-cells.d.ts +32 -0
- package/dist/react/components/editable-grid-cells.js +116 -0
- package/dist/react/components/eyebrow-kicker-lede-pull-quote.d.ts +39 -0
- package/dist/react/components/eyebrow-kicker-lede-pull-quote.js +12 -0
- package/dist/react/components/field.d.ts +32 -0
- package/dist/react/components/field.js +27 -0
- package/dist/react/components/file-tree.d.ts +75 -0
- package/dist/react/components/file-tree.js +247 -0
- package/dist/react/components/file.d.ts +43 -0
- package/dist/react/components/file.js +73 -0
- package/dist/react/components/files-table.d.ts +174 -0
- package/dist/react/components/files-table.js +237 -0
- package/dist/react/components/filter-builder.d.ts +37 -0
- package/dist/react/components/filter-builder.js +109 -0
- package/dist/react/components/form-error-summary.d.ts +16 -0
- package/dist/react/components/form-error-summary.js +49 -0
- package/dist/react/components/icon-button.d.ts +8 -0
- package/dist/react/components/icon-button.js +14 -0
- package/dist/react/components/icon.d.ts +7 -0
- package/dist/react/components/icon.js +15 -0
- package/dist/react/components/image.d.ts +72 -0
- package/dist/react/components/image.js +24 -0
- package/dist/react/components/inline-edit.d.ts +70 -0
- package/dist/react/components/inline-edit.js +149 -0
- package/dist/react/components/input.d.ts +29 -0
- package/dist/react/components/input.js +20 -0
- package/dist/react/components/kanban-board.d.ts +140 -0
- package/dist/react/components/kanban-board.js +374 -0
- package/dist/react/components/layout.d.ts +51 -0
- package/dist/react/components/layout.js +28 -0
- package/dist/react/components/list.d.ts +28 -0
- package/dist/react/components/list.js +6 -0
- package/dist/react/components/masthead-and-verdict.d.ts +60 -0
- package/dist/react/components/masthead-and-verdict.js +8 -0
- package/dist/react/components/menu.d.ts +26 -0
- package/dist/react/components/menu.js +31 -0
- package/dist/react/components/multi-select-picker.d.ts +49 -0
- package/dist/react/components/multi-select-picker.js +20 -0
- package/dist/react/components/note.d.ts +33 -0
- package/dist/react/components/note.js +8 -0
- package/dist/react/components/number-field.d.ts +16 -0
- package/dist/react/components/number-field.js +17 -0
- package/dist/react/components/pagination.d.ts +45 -0
- package/dist/react/components/pagination.js +87 -0
- package/dist/react/components/persistent-action-banner.d.ts +71 -0
- package/dist/react/components/persistent-action-banner.js +39 -0
- package/dist/react/components/popconfirm.d.ts +42 -0
- package/dist/react/components/popconfirm.js +59 -0
- package/dist/react/components/popover.d.ts +16 -0
- package/dist/react/components/popover.js +21 -0
- package/dist/react/components/progress-and-gauge.d.ts +44 -0
- package/dist/react/components/progress-and-gauge.js +19 -0
- package/dist/react/components/radio.d.ts +7 -0
- package/dist/react/components/radio.js +13 -0
- package/dist/react/components/rich-text-toolbar.d.ts +26 -0
- package/dist/react/components/rich-text-toolbar.js +64 -0
- package/dist/react/components/rows-and-card.d.ts +88 -0
- package/dist/react/components/rows-and-card.js +10 -0
- package/dist/react/components/save-status-indicator.d.ts +11 -0
- package/dist/react/components/save-status-indicator.js +33 -0
- package/dist/react/components/segmented-control.d.ts +21 -0
- package/dist/react/components/segmented-control.js +15 -0
- package/dist/react/components/select.d.ts +29 -0
- package/dist/react/components/select.js +29 -0
- package/dist/react/components/selectable-cards.d.ts +30 -0
- package/dist/react/components/selectable-cards.js +29 -0
- package/dist/react/components/settings-rows.d.ts +51 -0
- package/dist/react/components/settings-rows.js +8 -0
- package/dist/react/components/sidebar-nav.d.ts +77 -0
- package/dist/react/components/sidebar-nav.js +41 -0
- package/dist/react/components/skeleton-and-empty.d.ts +51 -0
- package/dist/react/components/skeleton-and-empty.js +14 -0
- package/dist/react/components/slider.d.ts +19 -0
- package/dist/react/components/slider.js +17 -0
- package/dist/react/components/small-charts.d.ts +60 -0
- package/dist/react/components/small-charts.js +76 -0
- package/dist/react/components/sortable.d.ts +30 -0
- package/dist/react/components/sortable.js +85 -0
- package/dist/react/components/split-button.d.ts +38 -0
- package/dist/react/components/split-button.js +43 -0
- package/dist/react/components/split-panes.d.ts +35 -0
- package/dist/react/components/split-panes.js +102 -0
- package/dist/react/components/stat-tiles.d.ts +54 -0
- package/dist/react/components/stat-tiles.js +8 -0
- package/dist/react/components/steps.d.ts +11 -0
- package/dist/react/components/steps.js +13 -0
- package/dist/react/components/switch.d.ts +6 -0
- package/dist/react/components/switch.js +13 -0
- package/dist/react/components/table.d.ts +61 -0
- package/dist/react/components/table.js +6 -0
- package/dist/react/components/tabs.d.ts +7 -0
- package/dist/react/components/tabs.js +13 -0
- package/dist/react/components/tags.d.ts +33 -0
- package/dist/react/components/tags.js +83 -0
- package/dist/react/components/textarea.d.ts +10 -0
- package/dist/react/components/textarea.js +6 -0
- package/dist/react/components/toast.d.ts +35 -0
- package/dist/react/components/toast.js +90 -0
- package/dist/react/components/tooltip-and-key.d.ts +20 -0
- package/dist/react/components/tooltip-and-key.js +20 -0
- package/dist/react/components/tree-view.d.ts +34 -0
- package/dist/react/components/tree-view.js +118 -0
- package/dist/react/components/upload-dropzone.d.ts +92 -0
- package/dist/react/components/upload-dropzone.js +116 -0
- package/dist/react/components/wizard-shell.d.ts +78 -0
- package/dist/react/components/wizard-shell.js +176 -0
- package/dist/react/fonts.css.d.ts +1 -0
- package/dist/react/index.d.ts +76 -0
- package/dist/react/index.js +77 -0
- package/dist/react/integrations/quickcrop.d.ts +58 -0
- package/dist/react/integrations/quickcrop.js +137 -0
- package/dist/react/integrations/richclay.d.ts +43 -0
- package/dist/react/integrations/richclay.js +129 -0
- package/dist/react/internal/classes.d.ts +3 -0
- package/dist/react/internal/classes.js +10 -0
- package/dist/react/internal/close-mark.d.ts +1 -0
- package/dist/react/internal/close-mark.js +10 -0
- package/dist/react/internal/controllable-state.d.ts +9 -0
- package/dist/react/internal/controllable-state.js +22 -0
- package/dist/react/internal/drop-effect.d.ts +28 -0
- package/dist/react/internal/drop-effect.js +8 -0
- package/dist/react/internal/form-reset.d.ts +2 -0
- package/dist/react/internal/form-reset.js +22 -0
- package/dist/react/internal/format.d.ts +1 -0
- package/dist/react/internal/format.js +14 -0
- package/dist/react/internal/link.d.ts +2 -0
- package/dist/react/internal/link.js +8 -0
- package/dist/react/internal/part.d.ts +20 -0
- package/dist/react/internal/part.js +47 -0
- package/dist/react/internal/pointer-session.d.ts +8 -0
- package/dist/react/internal/pointer-session.js +60 -0
- package/dist/react/internal/refs.d.ts +2 -0
- package/dist/react/internal/refs.js +22 -0
- package/dist/react/internal/rich-text.d.ts +28 -0
- package/dist/react/internal/rich-text.js +4 -0
- package/dist/react/internal/table-context.d.ts +39 -0
- package/dist/react/internal/table-context.js +12 -0
- package/dist/react/internal/use-object-url.d.ts +1 -0
- package/dist/react/internal/use-object-url.js +15 -0
- package/dist/react/layout.css +274 -0
- package/dist/react/layout.css.d.ts +1 -0
- package/dist/react/models/filter.d.ts +31 -0
- package/dist/react/models/filter.js +79 -0
- package/dist/react/models/kanban.d.ts +51 -0
- package/dist/react/models/kanban.js +35 -0
- package/dist/react/models/reorder.d.ts +9 -0
- package/dist/react/models/reorder.js +23 -0
- package/dist/react/models/table.d.ts +85 -0
- package/dist/react/models/table.js +144 -0
- package/dist/react/models/tree.d.ts +16 -0
- package/dist/react/models/tree.js +26 -0
- package/dist/react/provider.d.ts +18 -0
- package/dist/react/provider.js +31 -0
- package/dist/react/recipes/context-hypercms.d.ts +17 -0
- package/dist/react/recipes/context-hypercms.js +71 -0
- package/dist/react/recipes/context-quickcrop.d.ts +8 -0
- package/dist/react/recipes/context-quickcrop.js +49 -0
- package/dist/react/theme.css +8004 -0
- package/dist/react/theme.css.d.ts +1 -0
- package/examples/README.md +34 -0
- package/examples/components/activity-feed.html +28 -0
- package/examples/components/app-shell.html +12 -0
- package/examples/components/app-toolbar.html +38 -0
- package/examples/components/avatar-group.html +27 -0
- package/examples/components/breadcrumbs.html +26 -0
- package/examples/components/bulk-bar.html +22 -0
- package/examples/components/code-block.html +12 -0
- package/examples/components/code-editor.html +25 -0
- package/examples/components/column-manager.html +9 -0
- package/examples/components/combobox.html +13 -0
- package/examples/components/context-hypercms.css +41 -0
- package/examples/components/context-hypercms.html +40 -0
- package/examples/components/context-hypercms.js +62 -0
- package/examples/components/context-quickcrop.html +137 -0
- package/examples/components/diff-view.html +9 -0
- package/examples/components/drawer.html +11 -0
- package/examples/components/editable-grid-cells.html +9 -0
- package/examples/components/file-browser.html +53 -0
- package/examples/components/file-tree.html +34 -0
- package/examples/components/files-table.html +80 -0
- package/examples/components/filter-builder.html +11 -0
- package/examples/components/form-error-summary.html +11 -0
- package/examples/components/index.html +51 -0
- package/examples/components/inline-edit.html +42 -0
- package/examples/components/kanban-board.html +42 -0
- package/examples/components/manifest.json +3279 -0
- package/examples/components/modal.html +11 -0
- package/examples/components/multi-select-picker.html +13 -0
- package/examples/components/pagination.html +32 -0
- package/examples/components/persistent-action-banner.html +23 -0
- package/examples/components/popconfirm.html +13 -0
- package/examples/components/popover-menu.html +13 -0
- package/examples/components/reference/baseline/DECISIONS.md +85 -0
- package/examples/components/reference/baseline/README.md +58 -0
- package/examples/components/reference/baseline/bevel-fonts.css +16 -0
- package/examples/components/reference/baseline/bevel.css +1339 -0
- package/examples/components/reference/baseline/bevel.js +496 -0
- package/examples/components/reference/baseline/fonts/LICENSE-ibm-plex-mono.txt +93 -0
- package/examples/components/reference/baseline/fonts/LICENSE-ibm-plex-sans.txt +93 -0
- package/examples/components/reference/baseline/fonts/LICENSE-newsreader.txt +93 -0
- package/examples/components/reference/baseline/fonts/ibm-plex-mono-latin-400-normal.woff2 +0 -0
- package/examples/components/reference/baseline/fonts/ibm-plex-mono-latin-500-normal.woff2 +0 -0
- package/examples/components/reference/baseline/fonts/ibm-plex-mono-latin-600-normal.woff2 +0 -0
- package/examples/components/reference/baseline/fonts/ibm-plex-sans-latin-400-italic.woff2 +0 -0
- package/examples/components/reference/baseline/fonts/ibm-plex-sans-latin-400-normal.woff2 +0 -0
- package/examples/components/reference/baseline/fonts/ibm-plex-sans-latin-500-normal.woff2 +0 -0
- package/examples/components/reference/baseline/fonts/ibm-plex-sans-latin-600-normal.woff2 +0 -0
- package/examples/components/reference/baseline/fonts/newsreader-latin-opsz-italic.woff2 +0 -0
- package/examples/components/reference/baseline/fonts/newsreader-latin-opsz-normal.woff2 +0 -0
- package/examples/components/reference/fable/IMPROVEMENTS.md +106 -0
- package/examples/components/reference/fable/PARENT-REPAIRS.md +17 -0
- package/examples/components/reference/fable/__pycache__/build_repairs.cpython-311.pyc +0 -0
- package/examples/components/reference/fable/__pycache__/kanban.cpython-311.pyc +0 -0
- package/examples/components/reference/fable/as-authored/IMPROVEMENTS-completed.md +106 -0
- package/examples/components/reference/fable/as-authored/base-astra.css +17 -0
- package/examples/components/reference/fable/as-authored/base-parent.css +416 -0
- package/examples/components/reference/fable/as-authored/build.py +858 -0
- package/examples/components/reference/fable/as-authored/fable.css +823 -0
- package/examples/components/reference/fable/as-authored/kanban-completed.css +235 -0
- package/examples/components/reference/fable/as-authored/kanban-completed.html +53 -0
- package/examples/components/reference/fable/as-authored/kanban-completed.py +212 -0
- package/examples/components/reference/fable/as-authored/kanban.py +207 -0
- package/examples/components/reference/fable/base-astra.css +17 -0
- package/examples/components/reference/fable/base-parent.css +416 -0
- package/examples/components/reference/fable/build.py +858 -0
- package/examples/components/reference/fable/build_repairs.py +25 -0
- package/examples/components/reference/fable/components/activity-feed.html +3 -0
- package/examples/components/reference/fable/components/app-toolbar.html +3 -0
- package/examples/components/reference/fable/components/avatar-group.html +4 -0
- package/examples/components/reference/fable/components/breadcrumbs.html +3 -0
- package/examples/components/reference/fable/components/code-block.html +9 -0
- package/examples/components/reference/fable/components/column-manager.html +3 -0
- package/examples/components/reference/fable/components/combobox.html +6 -0
- package/examples/components/reference/fable/components/context-hypercms.html +3 -0
- package/examples/components/reference/fable/components/context-quickcrop.html +4 -0
- package/examples/components/reference/fable/components/diff-view.html +13 -0
- package/examples/components/reference/fable/components/drawer.html +3 -0
- package/examples/components/reference/fable/components/editable-grid-cells.html +3 -0
- package/examples/components/reference/fable/components/filter-builder.html +3 -0
- package/examples/components/reference/fable/components/form-error-summary.html +4 -0
- package/examples/components/reference/fable/components/inline-edit.html +3 -0
- package/examples/components/reference/fable/components/kanban-board.html +53 -0
- package/examples/components/reference/fable/components/modal.html +3 -0
- package/examples/components/reference/fable/components/multi-select-picker.html +5 -0
- package/examples/components/reference/fable/components/pagination.html +3 -0
- package/examples/components/reference/fable/components/persistent-action-banner.html +4 -0
- package/examples/components/reference/fable/components/popconfirm.html +5 -0
- package/examples/components/reference/fable/components/popover-menu.html +3 -0
- package/examples/components/reference/fable/components/rich-text-toolbar.html +3 -0
- package/examples/components/reference/fable/components/save-status-indicator.html +2 -0
- package/examples/components/reference/fable/components/selectable-cards.html +3 -0
- package/examples/components/reference/fable/components/settings-rows.html +3 -0
- package/examples/components/reference/fable/components/sidebar-nav.html +4 -0
- package/examples/components/reference/fable/components/small-charts.html +5 -0
- package/examples/components/reference/fable/components/split-button.html +4 -0
- package/examples/components/reference/fable/components/split-panes.html +8 -0
- package/examples/components/reference/fable/components/stat-tiles.html +3 -0
- package/examples/components/reference/fable/components/toast-stack.html +5 -0
- package/examples/components/reference/fable/components/tree-view.html +4 -0
- package/examples/components/reference/fable/components/upload-dropzone.html +6 -0
- package/examples/components/reference/fable/components/wizard-shell.html +3 -0
- package/examples/components/reference/fable/coverage.json +414 -0
- package/examples/components/reference/fable/fable.css +823 -0
- package/examples/components/reference/fable/index.html +5 -0
- package/examples/components/reference/fable/kanban.css +237 -0
- package/examples/components/reference/fable/kanban.py +212 -0
- package/examples/components/reference/fable/parent-repairs.css +9 -0
- package/examples/components/reference/fixtures/data.json +102 -0
- package/examples/components/reference/fixtures/host.js +47 -0
- package/examples/components/reference/fixtures/static-host.js +39 -0
- package/examples/components/reference/fixtures/workspace.jpg +0 -0
- package/examples/components/reference/parent/CHANGES.md +179 -0
- package/examples/components/reference/parent/__pycache__/kanban.cpython-311.pyc +0 -0
- package/examples/components/reference/parent/base-astra.css +17 -0
- package/examples/components/reference/parent/base-parent.css +416 -0
- package/examples/components/reference/parent/build.py +148 -0
- package/examples/components/reference/parent/components/activity-feed.html +2 -0
- package/examples/components/reference/parent/components/app-toolbar.html +2 -0
- package/examples/components/reference/parent/components/avatar-group.html +4 -0
- package/examples/components/reference/parent/components/breadcrumbs.html +2 -0
- package/examples/components/reference/parent/components/code-block.html +8 -0
- package/examples/components/reference/parent/components/column-manager.html +2 -0
- package/examples/components/reference/parent/components/combobox.html +6 -0
- package/examples/components/reference/parent/components/context-hypercms.html +2 -0
- package/examples/components/reference/parent/components/context-quickcrop.html +4 -0
- package/examples/components/reference/parent/components/diff-view.html +4 -0
- package/examples/components/reference/parent/components/drawer.html +2 -0
- package/examples/components/reference/parent/components/editable-grid-cells.html +2 -0
- package/examples/components/reference/parent/components/filter-builder.html +2 -0
- package/examples/components/reference/parent/components/form-error-summary.html +2 -0
- package/examples/components/reference/parent/components/inline-edit.html +2 -0
- package/examples/components/reference/parent/components/kanban-board.html +84 -0
- package/examples/components/reference/parent/components/modal.html +2 -0
- package/examples/components/reference/parent/components/multi-select-picker.html +5 -0
- package/examples/components/reference/parent/components/pagination.html +2 -0
- package/examples/components/reference/parent/components/persistent-action-banner.html +4 -0
- package/examples/components/reference/parent/components/popconfirm.html +5 -0
- package/examples/components/reference/parent/components/popover-menu.html +2 -0
- package/examples/components/reference/parent/components/rich-text-toolbar.html +2 -0
- package/examples/components/reference/parent/components/save-status-indicator.html +2 -0
- package/examples/components/reference/parent/components/selectable-cards.html +2 -0
- package/examples/components/reference/parent/components/settings-rows.html +2 -0
- package/examples/components/reference/parent/components/sidebar-nav.html +4 -0
- package/examples/components/reference/parent/components/small-charts.html +2 -0
- package/examples/components/reference/parent/components/split-button.html +5 -0
- package/examples/components/reference/parent/components/split-panes.html +8 -0
- package/examples/components/reference/parent/components/stat-tiles.html +2 -0
- package/examples/components/reference/parent/components/toast-stack.html +5 -0
- package/examples/components/reference/parent/components/tree-view.html +4 -0
- package/examples/components/reference/parent/components/upload-dropzone.html +6 -0
- package/examples/components/reference/parent/components/wizard-shell.html +2 -0
- package/examples/components/reference/parent/coverage.json +414 -0
- package/examples/components/reference/parent/index.html +1 -0
- package/examples/components/reference/parent/kanban.css +114 -0
- package/examples/components/reference/parent/kanban.py +55 -0
- package/examples/components/reference/parent/refinement.css +53 -0
- package/examples/components/reference/selected/build.py +70 -0
- package/examples/components/reference/selected/components/activity-feed.html +3 -0
- package/examples/components/reference/selected/components/app-toolbar.html +3 -0
- package/examples/components/reference/selected/components/avatar-group.html +4 -0
- package/examples/components/reference/selected/components/breadcrumbs.html +3 -0
- package/examples/components/reference/selected/components/code-block.html +9 -0
- package/examples/components/reference/selected/components/column-manager.html +3 -0
- package/examples/components/reference/selected/components/combobox.html +6 -0
- package/examples/components/reference/selected/components/context-hypercms.html +3 -0
- package/examples/components/reference/selected/components/context-quickcrop.html +4 -0
- package/examples/components/reference/selected/components/diff-view.html +13 -0
- package/examples/components/reference/selected/components/drawer.html +3 -0
- package/examples/components/reference/selected/components/editable-grid-cells.html +3 -0
- package/examples/components/reference/selected/components/filter-builder.html +3 -0
- package/examples/components/reference/selected/components/form-error-summary.html +4 -0
- package/examples/components/reference/selected/components/inline-edit.html +3 -0
- package/examples/components/reference/selected/components/kanban-board.html +53 -0
- package/examples/components/reference/selected/components/modal.html +2 -0
- package/examples/components/reference/selected/components/multi-select-picker.html +5 -0
- package/examples/components/reference/selected/components/pagination.html +3 -0
- package/examples/components/reference/selected/components/persistent-action-banner.html +4 -0
- package/examples/components/reference/selected/components/popconfirm.html +5 -0
- package/examples/components/reference/selected/components/popover-menu.html +3 -0
- package/examples/components/reference/selected/components/rich-text-toolbar.html +3 -0
- package/examples/components/reference/selected/components/save-status-indicator.html +2 -0
- package/examples/components/reference/selected/components/selectable-cards.html +3 -0
- package/examples/components/reference/selected/components/settings-rows.html +3 -0
- package/examples/components/reference/selected/components/sidebar-nav.html +4 -0
- package/examples/components/reference/selected/components/small-charts.html +5 -0
- package/examples/components/reference/selected/components/split-button.html +4 -0
- package/examples/components/reference/selected/components/split-panes.html +8 -0
- package/examples/components/reference/selected/components/stat-tiles.html +3 -0
- package/examples/components/reference/selected/components/toast-stack.html +5 -0
- package/examples/components/reference/selected/components/tree-view.html +4 -0
- package/examples/components/reference/selected/components/upload-dropzone.html +6 -0
- package/examples/components/reference/selected/components/wizard-shell.html +3 -0
- package/examples/components/reference/selected/corrections.css +11 -0
- package/examples/components/reference/selected/coverage.json +413 -0
- package/examples/components/reference/selected/gallery-build.mjs +49 -0
- package/examples/components/reference/selected/gallery-spec.json +12 -0
- package/examples/components/reference/selected/index.html +1 -0
- package/examples/components/reference/selected/kanban-comparison.json +6 -0
- package/examples/components/reference/selected/manifest.json +476 -0
- package/examples/components/reference/sha256.json +142 -0
- package/examples/components/reference/sources/diagonal-close.svg +1 -0
- package/examples/components/reference/sources/hyperclay/public-assets/css/hyperclay-app-source.css +614 -0
- package/examples/components/reference/sources/hyperclay/public-assets/js/app.js +94 -0
- package/examples/components/reference/sources/hyperclayjs/src/ui/theModal.js +897 -0
- package/examples/components/reference/sources/hypercms/scripts/build-theme.js +203 -0
- package/examples/components/reference/sources/hypercms/src/anchor.js +24 -0
- package/examples/components/reference/sources/hypercms/src/apply-loop.js +167 -0
- package/examples/components/reference/sources/hypercms/src/diagnostics.js +44 -0
- package/examples/components/reference/sources/hypercms/src/enhance.js +173 -0
- package/examples/components/reference/sources/hypercms/src/events.js +955 -0
- package/examples/components/reference/sources/hypercms/src/form-builder.js +518 -0
- package/examples/components/reference/sources/hypercms/src/form-rules.js +208 -0
- package/examples/components/reference/sources/hypercms/src/hooks.js +100 -0
- package/examples/components/reference/sources/hypercms/src/hypercms-bundle.js +10 -0
- package/examples/components/reference/sources/hypercms/src/hypercms.js +347 -0
- package/examples/components/reference/sources/hypercms/src/morph.js +10 -0
- package/examples/components/reference/sources/hypercms/src/path.js +61 -0
- package/examples/components/reference/sources/hypercms/src/place.js +131 -0
- package/examples/components/reference/sources/hypercms/src/platform.js +131 -0
- package/examples/components/reference/sources/hypercms/src/refresh.js +87 -0
- package/examples/components/reference/sources/hypercms/src/richclay-bridge.js +140 -0
- package/examples/components/reference/sources/hypercms/src/row-identity.js +111 -0
- package/examples/components/reference/sources/hypercms/src/scaffold.js +10 -0
- package/examples/components/reference/sources/hypercms/src/session.js +303 -0
- package/examples/components/reference/sources/hypercms/src/shell.js +248 -0
- package/examples/components/reference/sources/hypercms/src/styles.css +298 -0
- package/examples/components/reference/sources/hypercms/src/targets.js +144 -0
- package/examples/components/reference/sources/hypercms/src/templates.js +656 -0
- package/examples/components/reference/sources/hypercms/src/theme/pixel-quiet.overrides.css +761 -0
- package/examples/components/reference/sources/hypercms/src/theme.generated.css +1772 -0
- package/examples/components/reference/sources/hypercms/src/toggle.js +666 -0
- package/examples/components/reference/sources/hypercms/src/unresolved.js +211 -0
- package/examples/components/reference/sources/hypercms/src/vendor/mirk.vendor.js +212 -0
- package/examples/components/reference/sources/hypercms/src/views/inline-layer.js +421 -0
- package/examples/components/reference/sources/hypercms/src/views/inline.js +1072 -0
- package/examples/components/reference/sources/hypercms/src/views/sidebar.js +97 -0
- package/examples/components/reference/sources/modal-reference.html +301 -0
- package/examples/components/reference/sources/quickcrop/quickcrop.css +124 -0
- package/examples/components/reference/sources/quickcrop/quickcrop.js +400 -0
- package/examples/components/reference/sources/richclay/richclay.css +416 -0
- package/examples/components/reference/sources/richclay/richclay.js +2962 -0
- package/examples/components/reference/sources/richclay/src/a11y.js +67 -0
- package/examples/components/reference/sources/richclay/src/browser-global.js +7 -0
- package/examples/components/reference/sources/richclay/src/buttons.js +254 -0
- package/examples/components/reference/sources/richclay/src/hyperclay.js +470 -0
- package/examples/components/reference/sources/richclay/src/normalize.js +380 -0
- package/examples/components/reference/sources/richclay/src/richclay.js +1356 -0
- package/examples/components/reference/sources/richclay/src/sanitize.js +189 -0
- package/examples/components/reference/sources/richclay/src/styles.js +23 -0
- package/examples/components/reference/sources/richclay/src/toolbar-float.js +175 -0
- package/examples/components/reference/sources/richclay/src/toolbar.js +394 -0
- package/examples/components/reference/sources/richclay/src/vendor-bundle.js +15 -0
- package/examples/components/reference/sources/richclay/vendor/DOMPURIFY-LICENSE +202 -0
- package/examples/components/reference/sources/richclay/vendor/DOMPURIFY-LICENSE-MPL +373 -0
- package/examples/components/reference/sources/richclay/vendor/SQUIRE-LICENSE +21 -0
- package/examples/components/reference/sources/richclay/vendor/purify.es.mjs +2249 -0
- package/examples/components/reference/sources/richclay/vendor/purify.min.js +3 -0
- package/examples/components/reference/sources/richclay/vendor/squire.js +22 -0
- package/examples/components/reference/sources/richclay/vendor/squire.mjs +22 -0
- package/examples/components/reference/sources/richclay/vendor/squire.provenance.json +19 -0
- package/examples/components/rich-text-toolbar.html +43 -0
- package/examples/components/save-status-indicator.html +11 -0
- package/examples/components/selectable-cards.html +9 -0
- package/examples/components/settings-rows.html +10 -0
- package/examples/components/sidebar-nav.html +9 -0
- package/examples/components/small-charts.html +21 -0
- package/examples/components/split-button.html +13 -0
- package/examples/components/split-panes-editor.html +6 -0
- package/examples/components/split-panes.html +9 -0
- package/examples/components/stat-tiles.html +23 -0
- package/examples/components/toast-stack.html +21 -0
- package/examples/components/tree-view.html +9 -0
- package/examples/components/upload-dropzone.html +88 -0
- package/examples/components/wizard-shell.html +50 -0
- package/examples/datastar/index.html +38 -0
- package/examples/datastar/server.mjs +31 -0
- package/examples/fixtures/field-guide.pdf +14 -0
- package/examples/fixtures/workspace.jpg +0 -0
- package/examples/setup-peers.mjs +35 -0
- package/fonts/LICENSE-ibm-plex-mono.txt +93 -0
- package/fonts/LICENSE-ibm-plex-sans.txt +93 -0
- package/fonts/LICENSE-newsreader.txt +93 -0
- package/fonts/ibm-plex-mono-latin-400-normal.woff2 +0 -0
- package/fonts/ibm-plex-mono-latin-500-normal.woff2 +0 -0
- package/fonts/ibm-plex-mono-latin-600-normal.woff2 +0 -0
- package/fonts/ibm-plex-sans-latin-400-italic.woff2 +0 -0
- package/fonts/ibm-plex-sans-latin-400-normal.woff2 +0 -0
- package/fonts/ibm-plex-sans-latin-500-normal.woff2 +0 -0
- package/fonts/ibm-plex-sans-latin-600-normal.woff2 +0 -0
- package/fonts/newsreader-latin-opsz-italic.woff2 +0 -0
- package/fonts/newsreader-latin-opsz-normal.woff2 +0 -0
- package/icons/LICENSE +21 -0
- package/icons/house.json +71 -0
- package/icons/icons.d.ts +17 -0
- package/icons/icons.js +648 -0
- package/icons/icons.svg +126 -0
- package/icons/marks/build-tray.source.mjs +45 -0
- package/icons/marks/hyperclay-local.svg +11 -0
- package/icons/phosphor.json +53 -0
- package/icons/round.json +8 -0
- package/integrations/datastar.js +202 -0
- package/integrations/quickcrop.css +26 -0
- package/integrations/quickcrop.js +56 -0
- package/integrations/richclay.css +100 -0
- package/integrations/richclay.js +131 -0
- package/package.json +630 -0
- package/react/README.md +244 -0
- package/src/README.md +83 -0
- package/vendor/datastar/datastar-1.0.3.js +10 -0
- package/vendor/datastar/provenance.json +6 -0
- package/vendor/floating-ui/LICENSE-core +20 -0
- package/vendor/floating-ui/LICENSE-dom +20 -0
- package/vendor/floating-ui/floating-ui.core.umd.min.js +1 -0
- package/vendor/floating-ui/floating-ui.dom.umd.min.js +1 -0
- package/vendor/floating-ui/provenance.json +17 -0
- package/vendor/richclay/LICENSE +16 -0
- package/vendor/richclay/THIRD-PARTY-NOTICES.md +45 -0
- package/vendor/richclay/provenance.json +17 -0
- package/vendor/richclay/richclay.css +404 -0
- package/vendor/richclay/richclay.js +2940 -0
- package/vendor/richclay/vendor/DOMPURIFY-LICENSE +202 -0
- package/vendor/richclay/vendor/DOMPURIFY-LICENSE-MPL +373 -0
- package/vendor/richclay/vendor/SQUIRE-LICENSE +21 -0
- package/vendor/richclay/vendor/purify.min.js +3 -0
- package/vendor/richclay/vendor/squire.js +22 -0
- package/vendor/richclay/vendor/squire.provenance.json +30 -0
|
@@ -0,0 +1,656 @@
|
|
|
1
|
+
import { ruleAttrIndex } from 'hyper-html-api/engine'
|
|
2
|
+
import { getRuleAtPath } from './path.js'
|
|
3
|
+
|
|
4
|
+
export function humanize(key) {
|
|
5
|
+
return key
|
|
6
|
+
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
7
|
+
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')
|
|
8
|
+
.replace(/[-_]/g, ' ')
|
|
9
|
+
.replace(/\s+/g, ' ')
|
|
10
|
+
.trim()
|
|
11
|
+
.replace(/^./, (c) => c.toUpperCase())
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// The default templates emit real mirk-interface markup so the generated form
|
|
15
|
+
// renders in the Pixel Quiet look out of the box. Every data-hcms-* hook
|
|
16
|
+
// (shape, label, field, action, the .hcms-array-items / .hcms-card-fields slots,
|
|
17
|
+
// the .hcms-error inline slots) is preserved exactly, so the engine, events,
|
|
18
|
+
// add/remove/reorder, and inline-error placement bind unchanged. The CSS that
|
|
19
|
+
// dresses these lives in src/theme.generated.css (scoped mirk + pixel-quiet).
|
|
20
|
+
const SORTABLE_GRIP = `<div class="hcms-drag-handle mirk-sortable__grip" aria-hidden="true"><div class="mirk-sortable__dots"><span class="mirk-sortable__dot"></span><span class="mirk-sortable__dot"></span><span class="mirk-sortable__dot"></span><span class="mirk-sortable__dot"></span><span class="mirk-sortable__dot"></span><span class="mirk-sortable__dot"></span><span class="mirk-sortable__dot"></span><span class="mirk-sortable__dot"></span></div></div>`
|
|
21
|
+
|
|
22
|
+
// Crisp-line × (square caps + crispEdges): a plain pixel-sharp close glyph that
|
|
23
|
+
// stays hard-edged inside the small square corner button on object-array cards.
|
|
24
|
+
const CLOSE_ICON = `<svg class="hcms-x" viewBox="0 0 16 16" shape-rendering="crispEdges" aria-hidden="true"><path d="M4 4 L12 12 M12 4 L4 12" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="square"></path></svg>`
|
|
25
|
+
|
|
26
|
+
const DEFAULT_TEMPLATES = {
|
|
27
|
+
// The default scalar is a one-row auto-growing textarea, not an <input>:
|
|
28
|
+
// page copy is prose and routinely wraps. Growth comes from field-sizing:
|
|
29
|
+
// content in the theme, with a scrollHeight fallback (enhance.js).
|
|
30
|
+
'@scalar': `
|
|
31
|
+
<label class="hcms-field" data-hcms-shape="scalar">
|
|
32
|
+
<span class="hcms-label" data-hcms-label></span>
|
|
33
|
+
<textarea class="mirk-textarea" rows="1" data-hcms-field></textarea>
|
|
34
|
+
<div class="hcms-error" hidden></div>
|
|
35
|
+
</label>
|
|
36
|
+
`,
|
|
37
|
+
'@object': `
|
|
38
|
+
<section class="hcms-object" data-hcms-shape="object">
|
|
39
|
+
<h3 class="hcms-object-title" data-hcms-label></h3>
|
|
40
|
+
<div class="hcms-object-fields"></div>
|
|
41
|
+
<div class="hcms-error" hidden></div>
|
|
42
|
+
</section>
|
|
43
|
+
`,
|
|
44
|
+
'@scalar-array': `
|
|
45
|
+
<section class="hcms-array hcms-scalar-array" data-hcms-shape="scalar-array">
|
|
46
|
+
<header class="hcms-array-header">
|
|
47
|
+
<h3 class="hcms-array-title" data-hcms-label></h3>
|
|
48
|
+
</header>
|
|
49
|
+
<ul class="hcms-array-items"></ul>
|
|
50
|
+
<div class="hcms-error" hidden></div>
|
|
51
|
+
<button type="button" class="hcms-add mirk-button mirk-button--small" data-hcms-action="add"><span class="mirk-button__label">+ Add</span></button>
|
|
52
|
+
</section>
|
|
53
|
+
`,
|
|
54
|
+
'@scalar-array-item': `
|
|
55
|
+
<li class="hcms-array-item" draggable="true">
|
|
56
|
+
<input class="mirk-input" data-hcms-field />
|
|
57
|
+
<button type="button" class="hcms-move hcms-move-up hcms-sr-only" data-hcms-action="move-up" aria-label="Move up">↑</button>
|
|
58
|
+
<button type="button" class="hcms-move hcms-move-down hcms-sr-only" data-hcms-action="move-down" aria-label="Move down">↓</button>
|
|
59
|
+
<button type="button" class="hcms-remove" data-hcms-action="remove" aria-label="Remove">×</button>
|
|
60
|
+
<div class="hcms-error" hidden></div>
|
|
61
|
+
</li>
|
|
62
|
+
`,
|
|
63
|
+
'@object-array': `
|
|
64
|
+
<section class="hcms-array hcms-object-array hcms-array--cards" data-hcms-shape="object-array">
|
|
65
|
+
<header class="hcms-array-header">
|
|
66
|
+
<h3 class="hcms-array-title" data-hcms-label></h3>
|
|
67
|
+
</header>
|
|
68
|
+
<div class="hcms-array-items"></div>
|
|
69
|
+
<div class="hcms-error" hidden></div>
|
|
70
|
+
<button type="button" class="hcms-add mirk-button mirk-button--small" data-hcms-action="add"><span class="mirk-button__label">+ Add</span></button>
|
|
71
|
+
</section>
|
|
72
|
+
`,
|
|
73
|
+
'@object-array-item': `
|
|
74
|
+
<article class="hcms-card mirk-sortable__item" draggable="true">
|
|
75
|
+
${SORTABLE_GRIP}
|
|
76
|
+
<div class="hcms-card-body mirk-sortable__body">
|
|
77
|
+
<div class="hcms-card-fields"></div>
|
|
78
|
+
<div class="hcms-card-controls">
|
|
79
|
+
<button type="button" class="hcms-move hcms-move-up hcms-sr-only" data-hcms-action="move-up" aria-label="Move up">↑</button>
|
|
80
|
+
<button type="button" class="hcms-move hcms-move-down hcms-sr-only" data-hcms-action="move-down" aria-label="Move down">↓</button>
|
|
81
|
+
<button type="button" class="hcms-remove hcms-remove--card" data-hcms-action="remove" aria-label="Remove">${CLOSE_ICON}</button>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
<div class="hcms-error" hidden></div>
|
|
85
|
+
</article>
|
|
86
|
+
`,
|
|
87
|
+
// Opt-in upload components. Built on the kit's consolidated mirk chrome (all
|
|
88
|
+
// themed in theme.generated.css), with interactive hooks kept on data-hcms-*
|
|
89
|
+
// so the vendored mirk runtime (which keys off .mirk-*__input / .mirk-*__remove)
|
|
90
|
+
// never double-handles a CMS field. The bound value is the leaf's URL: the
|
|
91
|
+
// <a href> for @file, the <img src> for @image. Empty/filled chrome is driven
|
|
92
|
+
// by that attribute in CSS (.hcms-upload* in pixel-quiet.overrides.css), no JS.
|
|
93
|
+
'@file': `
|
|
94
|
+
<div class="hcms-field hcms-upload hcms-upload--file" data-hcms-shape="scalar">
|
|
95
|
+
<span class="hcms-label" data-hcms-label></span>
|
|
96
|
+
<div class="mirk-file mirk-file--compact mirk-file--round">
|
|
97
|
+
<label class="mirk-button mirk-button--round mirk-button--small">
|
|
98
|
+
<input type="file" data-hcms-upload />
|
|
99
|
+
<span class="mirk-button__label">Choose</span>
|
|
100
|
+
</label>
|
|
101
|
+
<a class="mirk-file__name" data-hcms-field></a>
|
|
102
|
+
<button type="button" class="hcms-upload-clear" data-hcms-action="clear-upload" aria-label="Remove file">${CLOSE_ICON}</button>
|
|
103
|
+
</div>
|
|
104
|
+
<div class="hcms-error" hidden></div>
|
|
105
|
+
</div>
|
|
106
|
+
`,
|
|
107
|
+
'@image': `
|
|
108
|
+
<div class="hcms-field hcms-upload hcms-upload--image" data-hcms-shape="scalar">
|
|
109
|
+
<span class="hcms-label" data-hcms-label></span>
|
|
110
|
+
<div class="mirk-image mirk-image--compact mirk-image--rounded">
|
|
111
|
+
<label class="mirk-button mirk-button--small mirk-image__upload">
|
|
112
|
+
<input type="file" accept="image/*" data-hcms-upload />
|
|
113
|
+
<span class="mirk-button__label">Upload image</span>
|
|
114
|
+
</label>
|
|
115
|
+
<figure class="mirk-image__thumb">
|
|
116
|
+
<span class="mirk-image__frame"><img class="mirk-image__preview" data-hcms-field alt="" /></span>
|
|
117
|
+
<button type="button" class="hcms-upload-clear hcms-upload-clear--badge" data-hcms-action="clear-upload" aria-label="Remove image">${CLOSE_ICON}</button>
|
|
118
|
+
</figure>
|
|
119
|
+
</div>
|
|
120
|
+
<div class="hcms-error" hidden></div>
|
|
121
|
+
</div>
|
|
122
|
+
`,
|
|
123
|
+
// Named built-in controls, opt-in via data-hcms-component on the page element
|
|
124
|
+
// a rule points at. Promoted from the demo custom templates (mirk chrome,
|
|
125
|
+
// already themed in theme.generated.css), so the easy path needs no template
|
|
126
|
+
// authoring. @checkbox/@toggle bind the same input[type=checkbox]@checked
|
|
127
|
+
// machinery; @select/@radio get their entries from data-hcms-options (the
|
|
128
|
+
// form-builder populates the empty <select> / clones the radio prototype).
|
|
129
|
+
'@checkbox': `
|
|
130
|
+
<div class="hcms-field hcms-field--row" data-hcms-shape="scalar">
|
|
131
|
+
<span class="hcms-label" data-hcms-label></span>
|
|
132
|
+
<label class="mirk-checkbox">
|
|
133
|
+
<input type="checkbox" class="mirk-sr-only" data-hcms-field />
|
|
134
|
+
<span class="mirk-checkbox__box"><span class="mirk-checkbox__mark"></span></span>
|
|
135
|
+
</label>
|
|
136
|
+
<div class="hcms-error" hidden></div>
|
|
137
|
+
</div>
|
|
138
|
+
`,
|
|
139
|
+
'@toggle': `
|
|
140
|
+
<div class="hcms-field hcms-field--row" data-hcms-shape="scalar">
|
|
141
|
+
<span class="hcms-label" data-hcms-label></span>
|
|
142
|
+
<label class="mirk-toggle">
|
|
143
|
+
<input type="checkbox" role="switch" class="mirk-sr-only" data-hcms-field />
|
|
144
|
+
<span class="mirk-toggle__track"><span class="mirk-toggle__thumb"></span></span>
|
|
145
|
+
</label>
|
|
146
|
+
<div class="hcms-error" hidden></div>
|
|
147
|
+
</div>
|
|
148
|
+
`,
|
|
149
|
+
'@select': `
|
|
150
|
+
<label class="hcms-field" data-hcms-shape="scalar">
|
|
151
|
+
<span class="hcms-label" data-hcms-label></span>
|
|
152
|
+
<div class="mirk-select">
|
|
153
|
+
<select class="mirk-select__field" data-hcms-field></select>
|
|
154
|
+
<span aria-hidden="true" class="mirk-select__chevron">›</span>
|
|
155
|
+
</div>
|
|
156
|
+
<div class="hcms-error" hidden></div>
|
|
157
|
+
</label>
|
|
158
|
+
`,
|
|
159
|
+
'@radio': `
|
|
160
|
+
<div class="hcms-field" data-hcms-shape="scalar">
|
|
161
|
+
<span class="hcms-label" data-hcms-label></span>
|
|
162
|
+
<div class="hcms-radio-row">
|
|
163
|
+
<label class="mirk-radio">
|
|
164
|
+
<input type="radio" class="mirk-sr-only" data-hcms-field />
|
|
165
|
+
<span class="mirk-radio__ring"><span class="mirk-radio__fill"></span><span class="mirk-radio__dot"></span></span>
|
|
166
|
+
<span class="mirk-radio__label"></span>
|
|
167
|
+
</label>
|
|
168
|
+
</div>
|
|
169
|
+
<div class="hcms-error" hidden></div>
|
|
170
|
+
</div>
|
|
171
|
+
`,
|
|
172
|
+
'@textarea': `
|
|
173
|
+
<label class="hcms-field" data-hcms-shape="scalar">
|
|
174
|
+
<span class="hcms-label" data-hcms-label></span>
|
|
175
|
+
<textarea class="mirk-textarea" rows="3" data-hcms-field></textarea>
|
|
176
|
+
<div class="hcms-error" hidden></div>
|
|
177
|
+
</label>
|
|
178
|
+
`,
|
|
179
|
+
// Rich-text surface for @innerHTML-bound rules: a contenteditable div whose
|
|
180
|
+
// value interface is innerHTML (fieldPropertyFor), so links and inline
|
|
181
|
+
// formatting survive the round-trip. richclay mounts on it when the host
|
|
182
|
+
// page ships it (enhance.js); otherwise it stays a plain contenteditable.
|
|
183
|
+
'@richtext': `
|
|
184
|
+
<div class="hcms-field" data-hcms-shape="scalar">
|
|
185
|
+
<span class="hcms-label" data-hcms-label></span>
|
|
186
|
+
<div class="mirk-textarea hcms-richtext" contenteditable="true" data-hcms-field></div>
|
|
187
|
+
<div class="hcms-error" hidden></div>
|
|
188
|
+
</div>
|
|
189
|
+
`,
|
|
190
|
+
'@number': `
|
|
191
|
+
<label class="hcms-field" data-hcms-shape="scalar">
|
|
192
|
+
<span class="hcms-label" data-hcms-label></span>
|
|
193
|
+
<input class="mirk-input" type="number" data-hcms-field />
|
|
194
|
+
<div class="hcms-error" hidden></div>
|
|
195
|
+
</label>
|
|
196
|
+
`,
|
|
197
|
+
'@chips': `
|
|
198
|
+
<div class="hcms-field hcms-chips" data-hcms-shape="scalar-array">
|
|
199
|
+
<span class="hcms-label" data-hcms-label></span>
|
|
200
|
+
<div class="mirk-tags hcms-array-items"></div>
|
|
201
|
+
<button type="button" class="hcms-add mirk-button mirk-button--small" data-hcms-action="add"><span class="mirk-button__label">+ Add</span></button>
|
|
202
|
+
<div class="hcms-error" hidden></div>
|
|
203
|
+
</div>
|
|
204
|
+
`,
|
|
205
|
+
'@chips-item': `
|
|
206
|
+
<span class="mirk-tags__chip" data-hcms-array-item>
|
|
207
|
+
<input class="hcms-chip-field" data-hcms-field aria-label="Item" placeholder="…" />
|
|
208
|
+
<button type="button" class="hcms-remove" data-hcms-action="remove" aria-label="Remove">×</button>
|
|
209
|
+
</span>
|
|
210
|
+
`,
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Shape templates fill-the-gaps on every managed page. The opt-in components
|
|
214
|
+
// (@file/@image uploads + the named controls) are injected on demand the first
|
|
215
|
+
// time a field selects them (the Slice-2 component seam), so pages using none
|
|
216
|
+
// stay clean.
|
|
217
|
+
const ALWAYS_INJECT_KEYS = [
|
|
218
|
+
'@scalar',
|
|
219
|
+
'@object',
|
|
220
|
+
'@scalar-array',
|
|
221
|
+
'@scalar-array-item',
|
|
222
|
+
'@object-array',
|
|
223
|
+
'@object-array-item',
|
|
224
|
+
]
|
|
225
|
+
|
|
226
|
+
export function injectDefaults(doc) {
|
|
227
|
+
const head = doc.head || doc.documentElement
|
|
228
|
+
if (!head) return
|
|
229
|
+
for (const key of ALWAYS_INJECT_KEYS) injectTemplate(doc, head, key)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Inject one opt-in component template if the page hasn't already defined its
|
|
233
|
+
// own. Called by the component-selection seam the first time a field resolves
|
|
234
|
+
// to a component.
|
|
235
|
+
export function injectComponentTemplate(doc, key) {
|
|
236
|
+
if (!DEFAULT_TEMPLATES[key]) return null
|
|
237
|
+
const head = doc && (doc.head || doc.documentElement)
|
|
238
|
+
if (!head) return null
|
|
239
|
+
return injectTemplate(doc, head, key)
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Named-component selection. Explicit beats inferred: a data-hcms-component
|
|
243
|
+
// attribute on the page element a rule points at wins over the @prop-suffix
|
|
244
|
+
// inference, so a checked-bound field can still opt into the @toggle look.
|
|
245
|
+
// Inference stays narrow: @src means image upload (the dominant image-CMS
|
|
246
|
+
// workflow) and @checked means checkbox (a text input showing the literal word
|
|
247
|
+
// "true" helps nobody). @href is NOT inferred: editing a link/URL is far more
|
|
248
|
+
// common than uploading a file, so an a@href rule stays a plain URL field and
|
|
249
|
+
// the file upload is opt-in. Suffix is split like the engine (ruleAttrIndex,
|
|
250
|
+
// see engine/extract.js). Returns a DEFAULT_TEMPLATES key.
|
|
251
|
+
const PROP_TO_COMPONENT = { src: '@image', checked: '@checkbox', innerHTML: '@richtext' }
|
|
252
|
+
// data-hcms-component values for scalar rules. "chips" is array-only (below).
|
|
253
|
+
const SCALAR_COMPONENT_BY_NAME = {
|
|
254
|
+
image: '@image',
|
|
255
|
+
file: '@file',
|
|
256
|
+
checkbox: '@checkbox',
|
|
257
|
+
toggle: '@toggle',
|
|
258
|
+
select: '@select',
|
|
259
|
+
radio: '@radio',
|
|
260
|
+
textarea: '@textarea',
|
|
261
|
+
number: '@number',
|
|
262
|
+
richtext: '@richtext',
|
|
263
|
+
}
|
|
264
|
+
// Every opt-in component injects on demand; only the 6 shape templates are
|
|
265
|
+
// always present.
|
|
266
|
+
const ON_DEMAND_COMPONENT_KEYS = new Set([
|
|
267
|
+
...Object.values(SCALAR_COMPONENT_BY_NAME),
|
|
268
|
+
'@chips',
|
|
269
|
+
'@chips-item',
|
|
270
|
+
])
|
|
271
|
+
|
|
272
|
+
export function componentForScalarRule(rule, doc, pathArr, pageRules) {
|
|
273
|
+
if (typeof rule !== 'string') return '@scalar'
|
|
274
|
+
const at = ruleAttrIndex(rule)
|
|
275
|
+
const host = hostSelectorOf(rule, at, pathArr, pageRules)
|
|
276
|
+
const override = readElementAttr(host, doc, 'data-hcms-component')
|
|
277
|
+
if (override && SCALAR_COMPONENT_BY_NAME[override]) {
|
|
278
|
+
const key = SCALAR_COMPONENT_BY_NAME[override]
|
|
279
|
+
// Value guards check exactly the elements the engine binds: under an array
|
|
280
|
+
// the same rule binds one element per item (every match votes), while a
|
|
281
|
+
// plain scalar binds only the FIRST match — a decorative second element
|
|
282
|
+
// sharing the selector must not veto the control.
|
|
283
|
+
const multi = Array.isArray(pathArr) && pathArr.some((s) => s === '*' || typeof s === 'number')
|
|
284
|
+
if (key === '@number' && !currentScalarValues(rule, at, doc, multi, host).every(numberInputCanHold)) {
|
|
285
|
+
return '@scalar'
|
|
286
|
+
}
|
|
287
|
+
if (
|
|
288
|
+
(key === '@checkbox' || key === '@toggle') &&
|
|
289
|
+
(at < 0 || rule.slice(at + 1) !== 'checked') &&
|
|
290
|
+
!currentScalarValues(rule, at, doc, multi, host).every(checkboxCanHold)
|
|
291
|
+
) {
|
|
292
|
+
return '@scalar'
|
|
293
|
+
}
|
|
294
|
+
return key
|
|
295
|
+
}
|
|
296
|
+
if (at >= 0) {
|
|
297
|
+
const prop = rule.slice(at + 1)
|
|
298
|
+
if (PROP_TO_COMPONENT[prop]) return PROP_TO_COMPONENT[prop]
|
|
299
|
+
}
|
|
300
|
+
return '@scalar'
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// The data-hcms-component key the page element explicitly declares for this
|
|
304
|
+
// rule, or null (absent / unknown name / value-guard fallback). Lets the
|
|
305
|
+
// builder tell "author asked for this" apart from suffix inference when
|
|
306
|
+
// logging shadowing notices.
|
|
307
|
+
export function declaredComponentKey(rule, doc, pathArr, pageRules) {
|
|
308
|
+
if (typeof rule !== 'string') return null
|
|
309
|
+
const at = ruleAttrIndex(rule)
|
|
310
|
+
const name = readElementAttr(hostSelectorOf(rule, at, pathArr, pageRules), doc, 'data-hcms-component')
|
|
311
|
+
return (name && SCALAR_COMPONENT_BY_NAME[name]) || null
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// A number input physically rejects any value that isn't a plain number — it
|
|
315
|
+
// reads back '' — and the whole-form commit would then blank the page value on
|
|
316
|
+
// the next edit of ANY field. When any bound value isn't number-shaped, fall
|
|
317
|
+
// back to the plain text control. This runs inside componentForScalarRule so
|
|
318
|
+
// the builder and deriveFormRules stay in lockstep (both call it).
|
|
319
|
+
const NUMBER_VALUE_RE = /^-?\d+(\.\d+)?([eE][+-]?\d+)?$/
|
|
320
|
+
|
|
321
|
+
function numberInputCanHold(value) {
|
|
322
|
+
if (value == null || value === '') return true
|
|
323
|
+
return NUMBER_VALUE_RE.test(String(value))
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// A checkbox/toggle extracts its checked property — 'true' or 'false' — so any
|
|
327
|
+
// other bound value ("yes", "on", "1") would be clobbered to 'false' on the
|
|
328
|
+
// next whole-form commit. @checked projections are exempt in the caller: they
|
|
329
|
+
// round-trip the checked state faithfully by construction.
|
|
330
|
+
function checkboxCanHold(value) {
|
|
331
|
+
return value == null || value === '' || value === 'true' || value === 'false'
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// Read the page values the rule binds, the way the engine extracts them:
|
|
335
|
+
// trimmed textContent for text projections (adapter.text trims), the live
|
|
336
|
+
// property for @value, the raw attribute otherwise. Mirrors extraction's
|
|
337
|
+
// skips: cms-template seeds and the shell are never extracted, so their
|
|
338
|
+
// values don't get a vote. `multi` mirrors the engine's binding: all matches
|
|
339
|
+
// under an array (one element per item), only the first match otherwise.
|
|
340
|
+
function currentScalarValues(rule, at, doc, multi, selector) {
|
|
341
|
+
if (!doc || !doc.querySelectorAll) return []
|
|
342
|
+
if (!selector || selector === '.') return []
|
|
343
|
+
let els = null
|
|
344
|
+
try {
|
|
345
|
+
els = doc.querySelectorAll(selector)
|
|
346
|
+
} catch {
|
|
347
|
+
return []
|
|
348
|
+
}
|
|
349
|
+
const prop = at >= 0 ? rule.slice(at + 1) : null
|
|
350
|
+
const out = []
|
|
351
|
+
for (const el of els) {
|
|
352
|
+
if (el.closest && el.closest('[cms-template], [data-hcms-shell]')) continue
|
|
353
|
+
if (prop) {
|
|
354
|
+
if (prop === 'value' && 'value' in el) out.push(el.value)
|
|
355
|
+
else out.push(el.getAttribute ? el.getAttribute(prop) : null)
|
|
356
|
+
} else {
|
|
357
|
+
out.push((el.textContent || '').trim())
|
|
358
|
+
}
|
|
359
|
+
if (!multi) break
|
|
360
|
+
}
|
|
361
|
+
return out
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// Array-level component selection: data-hcms-component="chips" on the list
|
|
365
|
+
// container (or any ancestor of the items) swaps the scalar-array chrome for
|
|
366
|
+
// the chip list. Resolved through the first item the rule's selector matches,
|
|
367
|
+
// then closest(), so the natural authoring spot — the <ul> — works even though
|
|
368
|
+
// the selector targets the items. Growable-from-zero lists carry a cms-template
|
|
369
|
+
// item, so the item selector always has something to match.
|
|
370
|
+
export function componentForScalarArrayRule(rule, doc) {
|
|
371
|
+
if (typeof rule !== 'string' || !rule.endsWith('[]')) return null
|
|
372
|
+
if (!doc || !doc.querySelector) return null
|
|
373
|
+
const selector = rule.slice(0, -2).trim()
|
|
374
|
+
if (!selector) return null
|
|
375
|
+
let item = null
|
|
376
|
+
try {
|
|
377
|
+
item = doc.querySelector(selector)
|
|
378
|
+
} catch {
|
|
379
|
+
return null
|
|
380
|
+
}
|
|
381
|
+
const host = item && item.closest ? item.closest('[data-hcms-component]') : null
|
|
382
|
+
const name = host && host.getAttribute ? host.getAttribute('data-hcms-component') : null
|
|
383
|
+
if (name === 'chips') return { array: '@chips', item: '@chips-item' }
|
|
384
|
+
return null
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// Template resolution shared by the builder and deriveFormRules: a custom
|
|
388
|
+
// template at the exact path wins, then a wildcard-path one, then the default.
|
|
389
|
+
export function resolveTemplate(pathArr, defaultKey, doc) {
|
|
390
|
+
const pathStr = pathArr.join('.')
|
|
391
|
+
const wildcardKey = pathArr.map((s) => (typeof s === 'number' ? '*' : s)).join('.')
|
|
392
|
+
return (
|
|
393
|
+
(pathStr && findTemplate(doc, pathStr)) ||
|
|
394
|
+
(wildcardKey && wildcardKey !== pathStr && findTemplate(doc, wildcardKey)) ||
|
|
395
|
+
findTemplate(doc, defaultKey)
|
|
396
|
+
)
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// The declared array component, but only when its array template actually
|
|
400
|
+
// wins at this path — a custom path/wildcard template that shadows it returns
|
|
401
|
+
// null. The form-builder (item chrome) and deriveFormRules (item leaf
|
|
402
|
+
// selector) MUST share this verdict: if they diverge, the derived selector
|
|
403
|
+
// stops matching the rendered item leaf, every item extracts null, and the
|
|
404
|
+
// whole-form commit writes those nulls back over real page data.
|
|
405
|
+
export function winningScalarArrayComponent(rule, pathArr, doc) {
|
|
406
|
+
const comp = componentForScalarArrayRule(rule, doc)
|
|
407
|
+
if (!comp) return null
|
|
408
|
+
const winner = resolveTemplate(pathArr, comp.array, doc)
|
|
409
|
+
if (winner && winner.getAttribute('data-hcms-tpl') === comp.array) return comp
|
|
410
|
+
return null
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// Option list for @select/@radio: data-hcms-options="low medium high" on the
|
|
414
|
+
// same page element as data-hcms-component. Space-separated value tokens (the
|
|
415
|
+
// data-rules-name idiom); labels derive via humanize() like every other label.
|
|
416
|
+
export function readOptionsOverride(rule, doc, pathArr, pageRules) {
|
|
417
|
+
if (typeof rule !== 'string') return null
|
|
418
|
+
const at = ruleAttrIndex(rule)
|
|
419
|
+
const raw = readElementAttr(hostSelectorOf(rule, at, pathArr, pageRules), doc, 'data-hcms-options')
|
|
420
|
+
if (raw == null) return null
|
|
421
|
+
const tokens = raw.trim().split(/\s+/).filter(Boolean)
|
|
422
|
+
return tokens.length ? tokens : null
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// Crop opt-in for @image: data-hcms-crop="1:1" | "16:9" | "free" on the page
|
|
426
|
+
// element. The form-builder copies it onto the built field so the upload path
|
|
427
|
+
// reads it without a second page lookup.
|
|
428
|
+
export function readCropOverride(rule, doc, pathArr, pageRules) {
|
|
429
|
+
if (typeof rule !== 'string') return null
|
|
430
|
+
const at = ruleAttrIndex(rule)
|
|
431
|
+
return readElementAttr(hostSelectorOf(rule, at, pathArr, pageRules), doc, 'data-hcms-crop')
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
function scalarSelectorOf(rule, at) {
|
|
435
|
+
return at >= 0 ? rule.slice(0, at) : rule
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// The page element that carries this rule's authoring attributes
|
|
439
|
+
// (data-hcms-component / -options / -crop), and whose values the guards read.
|
|
440
|
+
//
|
|
441
|
+
// A rule that binds its own context element — a lone "." or a leading "@attr" —
|
|
442
|
+
// has no selector of its own: scalarSelectorOf yields "" or ".". Inside a list
|
|
443
|
+
// that context element IS the row, so the element to read is the row, and the
|
|
444
|
+
// row selector is the enclosing array's item selector. That is the "state is
|
|
445
|
+
// content" case (data-status on the card), and without this it can never carry
|
|
446
|
+
// a named control. Outside any list the context is the document root, so there
|
|
447
|
+
// is still no element to read and we return "" — readElementAttr and
|
|
448
|
+
// currentScalarValues both treat that as "nothing declared", exactly as before.
|
|
449
|
+
//
|
|
450
|
+
// The component is chosen per RULE, not per row, so any ONE matching row
|
|
451
|
+
// answers the question; readElementAttr's querySelector taking the first match
|
|
452
|
+
// is correct rather than a shortcut.
|
|
453
|
+
function hostSelectorOf(rule, at, pathArr, pageRules) {
|
|
454
|
+
const own = scalarSelectorOf(rule, at)
|
|
455
|
+
if (own && own !== '.') return own
|
|
456
|
+
return enclosingArraySelector(pageRules, pathArr)
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// The descendant-joined item selectors of every array rule crossed on the way
|
|
460
|
+
// to pathArr, or "" when the path crosses none (or does not resolve). Mirrors
|
|
461
|
+
// the scope chain hyperclay's resolveControl builds for the same path, so the
|
|
462
|
+
// generator stamps the attribute on exactly the elements read back here.
|
|
463
|
+
function enclosingArraySelector(pageRules, pathArr) {
|
|
464
|
+
if (pageRules == null || !Array.isArray(pathArr)) return ''
|
|
465
|
+
const scope = []
|
|
466
|
+
let node = pageRules
|
|
467
|
+
for (const seg of pathArr) {
|
|
468
|
+
if (node == null || typeof node === 'string') break
|
|
469
|
+
if (Array.isArray(node)) {
|
|
470
|
+
if (typeof node[0] !== 'string') return ''
|
|
471
|
+
if (seg !== '*' && typeof seg !== 'number') return ''
|
|
472
|
+
scope.push(node[0])
|
|
473
|
+
node = node[1]
|
|
474
|
+
continue
|
|
475
|
+
}
|
|
476
|
+
if (typeof node !== 'object') return ''
|
|
477
|
+
if (!Object.prototype.hasOwnProperty.call(node, seg)) return ''
|
|
478
|
+
node = node[seg]
|
|
479
|
+
}
|
|
480
|
+
return scope.join(' ')
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// The only branch that reads the page DOM during selection.
|
|
484
|
+
function readElementAttr(selector, doc, attrName) {
|
|
485
|
+
if (!doc || !doc.querySelector) return null
|
|
486
|
+
if (!selector || selector === '.') return null
|
|
487
|
+
let el = null
|
|
488
|
+
try {
|
|
489
|
+
el = doc.querySelector(selector)
|
|
490
|
+
} catch {
|
|
491
|
+
return null
|
|
492
|
+
}
|
|
493
|
+
return el && el.getAttribute ? el.getAttribute(attrName) : null
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
// Pre-inject the component templates this page's rules actually select, so
|
|
497
|
+
// both deriveFormRules (selectors) and buildForm (DOM) resolve them. Walks the
|
|
498
|
+
// same rule shapes as buildTemplateMap; idempotent and author-template-safe.
|
|
499
|
+
export function injectComponents(doc, pageRules) {
|
|
500
|
+
if (!doc || pageRules == null) return
|
|
501
|
+
walk(pageRules, [])
|
|
502
|
+
|
|
503
|
+
// The path is carried so componentForScalarRule can resolve a context leaf
|
|
504
|
+
// ("." / "@attr") against its enclosing row, the same way the builder does.
|
|
505
|
+
// Without it a row-level named control resolves to @scalar here, its template
|
|
506
|
+
// is never injected, and buildScalar then throws on the missing template.
|
|
507
|
+
function walk(rule, pathArr) {
|
|
508
|
+
const kind = shapeKindOf(rule)
|
|
509
|
+
if (kind === 'scalar') {
|
|
510
|
+
const key = componentForScalarRule(rule, doc, pathArr, pageRules)
|
|
511
|
+
if (ON_DEMAND_COMPONENT_KEYS.has(key)) injectComponentTemplate(doc, key)
|
|
512
|
+
return
|
|
513
|
+
}
|
|
514
|
+
if (kind === 'scalar-array') {
|
|
515
|
+
const comp = componentForScalarArrayRule(rule, doc)
|
|
516
|
+
if (comp) {
|
|
517
|
+
injectComponentTemplate(doc, comp.array)
|
|
518
|
+
injectComponentTemplate(doc, comp.item)
|
|
519
|
+
}
|
|
520
|
+
return
|
|
521
|
+
}
|
|
522
|
+
if (kind === 'object') {
|
|
523
|
+
for (const [k, child] of Object.entries(rule)) walk(child, [...pathArr, k])
|
|
524
|
+
return
|
|
525
|
+
}
|
|
526
|
+
if (kind === 'object-array') {
|
|
527
|
+
const itemShape = rule[1]
|
|
528
|
+
const itemPath = [...pathArr, '*']
|
|
529
|
+
if (itemShape && typeof itemShape === 'object' && !Array.isArray(itemShape)) {
|
|
530
|
+
for (const [k, child] of Object.entries(itemShape)) walk(child, [...itemPath, k])
|
|
531
|
+
} else {
|
|
532
|
+
walk(itemShape, itemPath)
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
function injectTemplate(doc, head, key) {
|
|
539
|
+
const existing = findTemplate(doc, key)
|
|
540
|
+
if (existing) return existing
|
|
541
|
+
const tpl = doc.createElement('template')
|
|
542
|
+
tpl.setAttribute('data-hcms-tpl', key)
|
|
543
|
+
tpl.setAttribute('save-remove', '')
|
|
544
|
+
tpl.innerHTML = DEFAULT_TEMPLATES[key].trim()
|
|
545
|
+
head.appendChild(tpl)
|
|
546
|
+
return tpl
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
export function findTemplate(doc, key) {
|
|
550
|
+
if (!doc || !doc.querySelector) return null
|
|
551
|
+
return doc.querySelector(`template[data-hcms-tpl="${cssEscape(key)}"]`)
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
function cssEscape(value) {
|
|
555
|
+
if (typeof CSS !== 'undefined' && CSS.escape) return CSS.escape(value)
|
|
556
|
+
return String(value).replace(/[^a-zA-Z0-9_\-.*]/g, (c) => '\\' + c)
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
export function shapeKindOf(rule) {
|
|
560
|
+
if (typeof rule === 'string') {
|
|
561
|
+
return rule.endsWith('[]') ? 'scalar-array' : 'scalar'
|
|
562
|
+
}
|
|
563
|
+
if (Array.isArray(rule)) return 'object-array'
|
|
564
|
+
if (typeof rule === 'object' && rule !== null) return 'object'
|
|
565
|
+
return 'scalar'
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
const SHAPE_TO_DEFAULT_KEY = {
|
|
569
|
+
scalar: '@scalar',
|
|
570
|
+
object: '@object',
|
|
571
|
+
'scalar-array': '@scalar-array',
|
|
572
|
+
'object-array': '@object-array',
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
const SHAPE_TO_ITEM_KEY = {
|
|
576
|
+
'scalar-array': '@scalar-array-item',
|
|
577
|
+
'object-array': '@object-array-item',
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
export function templateKeyForPath(pathArr, pageRules) {
|
|
581
|
+
const rule = getRuleAtPath(pageRules, pathArr)
|
|
582
|
+
const shape = shapeKindOf(rule)
|
|
583
|
+
return SHAPE_TO_DEFAULT_KEY[shape] || '@scalar'
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
export function itemTemplateKeyForArrayPath(pathArr, pageRules) {
|
|
587
|
+
const rule = getRuleAtPath(pageRules, pathArr)
|
|
588
|
+
const shape = shapeKindOf(rule)
|
|
589
|
+
return SHAPE_TO_ITEM_KEY[shape] || null
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
export function buildTemplateMap(pageRules, doc) {
|
|
593
|
+
const map = new Map()
|
|
594
|
+
walk([], pageRules)
|
|
595
|
+
return map
|
|
596
|
+
|
|
597
|
+
function walk(pathArr, rule) {
|
|
598
|
+
const pathStr = pathArr.join('.')
|
|
599
|
+
const wildcardKey = pathArr.map((s) => (typeof s === 'number' ? '*' : s)).join('.')
|
|
600
|
+
const shape = shapeKindOf(rule)
|
|
601
|
+
const arrayComp = shape === 'scalar-array' ? componentForScalarArrayRule(rule, doc) : null
|
|
602
|
+
// Items follow the WINNING component (a shadowed chips array renders
|
|
603
|
+
// default items), matching buildScalarArray.
|
|
604
|
+
const winningComp = shape === 'scalar-array' ? winningScalarArrayComponent(rule, pathArr, doc) : null
|
|
605
|
+
const defaultKey =
|
|
606
|
+
shape === 'scalar'
|
|
607
|
+
? componentForScalarRule(rule, doc, pathArr)
|
|
608
|
+
: (arrayComp && arrayComp.array) || SHAPE_TO_DEFAULT_KEY[shape] || '@scalar'
|
|
609
|
+
|
|
610
|
+
let tpl =
|
|
611
|
+
(pathStr && findTemplate(doc, pathStr)) ||
|
|
612
|
+
(wildcardKey && wildcardKey !== pathStr && findTemplate(doc, wildcardKey)) ||
|
|
613
|
+
findTemplate(doc, defaultKey)
|
|
614
|
+
|
|
615
|
+
map.set(pathStr, tpl)
|
|
616
|
+
|
|
617
|
+
if (shape === 'object') {
|
|
618
|
+
for (const [k, child] of Object.entries(rule)) walk([...pathArr, k], child)
|
|
619
|
+
} else if (shape === 'object-array' || shape === 'scalar-array') {
|
|
620
|
+
const itemPath = [...pathArr, '*']
|
|
621
|
+
const itemKey = itemPath.map((s) => (typeof s === 'number' ? '*' : s)).join('.')
|
|
622
|
+
const itemShape = shape === 'object-array' ? 'object-array-item' : 'scalar-array-item'
|
|
623
|
+
const itemTpl =
|
|
624
|
+
findTemplate(doc, itemKey) ||
|
|
625
|
+
(winningComp && findTemplate(doc, winningComp.item)) ||
|
|
626
|
+
findTemplate(doc, '@' + itemShape)
|
|
627
|
+
map.set(itemKey, itemTpl)
|
|
628
|
+
if (shape === 'object-array') {
|
|
629
|
+
const itemRule = rule[1]
|
|
630
|
+
if (itemRule && typeof itemRule === 'object' && !Array.isArray(itemRule)) {
|
|
631
|
+
for (const [k, child] of Object.entries(itemRule)) walk([...itemPath, k], child)
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
export function isInlineTemplate(tplEl) {
|
|
639
|
+
if (!tplEl) return false
|
|
640
|
+
const root = tplEl.content || tplEl
|
|
641
|
+
return !!root.querySelector('[data-hcms-field]')
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
export function slotSelectorFor(kind) {
|
|
645
|
+
switch (kind) {
|
|
646
|
+
case 'object':
|
|
647
|
+
return '.hcms-object-fields'
|
|
648
|
+
case 'object-array-item':
|
|
649
|
+
return '.hcms-card-fields'
|
|
650
|
+
case 'scalar-array':
|
|
651
|
+
case 'object-array':
|
|
652
|
+
return '.hcms-array-items'
|
|
653
|
+
default:
|
|
654
|
+
return null
|
|
655
|
+
}
|
|
656
|
+
}
|