@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,470 @@
|
|
|
1
|
+
import { flattenBlocks, hasBlockDescendant } from "./normalize.js";
|
|
2
|
+
|
|
3
|
+
export const RICHCLAY_SELECTOR = "[data-richclay], [richclay], [editable], [clay-editable]";
|
|
4
|
+
|
|
5
|
+
// The names that say "richclay" and nothing else. `editable` is deliberately not
|
|
6
|
+
// among them: it is the friendly spelling, and it is also a name other people use.
|
|
7
|
+
const RICHCLAY_OPT_IN = "[data-richclay], [richclay], [clay-editable]";
|
|
8
|
+
|
|
9
|
+
// Both spellings of the option-carrying attribute, in the order they are consulted.
|
|
10
|
+
// `clay-editable` is the escape hatch for a page whose custom element already owns
|
|
11
|
+
// the bare name, so it has to behave identically down to the token list: a spelling
|
|
12
|
+
// that mounts a different editor is worse than no escape hatch at all.
|
|
13
|
+
const EDITABLE_ATTRS = ["editable", "clay-editable"];
|
|
14
|
+
|
|
15
|
+
const singleLineSelector = ':is([editable~="single-line"], [clay-editable~="single-line"])';
|
|
16
|
+
|
|
17
|
+
// A custom element's tag name always contains a hyphen, and `editable` is a common
|
|
18
|
+
// boolean property on one: Lit reflects `@property({ type: Boolean }) editable`
|
|
19
|
+
// straight to this attribute, where it means whatever that component decided and
|
|
20
|
+
// never rich text. Mounting an editor on such an element makes its rendered output
|
|
21
|
+
// typeable and writes that output into the author's saved file, which is damage the
|
|
22
|
+
// author cannot see until they open the file. A custom element that does want
|
|
23
|
+
// richclay asks by name.
|
|
24
|
+
export function isRichClayHost(el) {
|
|
25
|
+
if (!el || typeof el.matches !== "function") return false;
|
|
26
|
+
if (!el.tagName.includes("-")) return true;
|
|
27
|
+
return el.matches(RICHCLAY_OPT_IN);
|
|
28
|
+
}
|
|
29
|
+
export const CHROME_SELECTOR =
|
|
30
|
+
"[data-richclay-toolbar], [data-richclay-menu], [data-richclay-dialog], [data-richclay-live], [data-richclay-float]";
|
|
31
|
+
|
|
32
|
+
const runtimeClasses = [
|
|
33
|
+
"richclay-editor",
|
|
34
|
+
"richclay-inline",
|
|
35
|
+
"richclay-active",
|
|
36
|
+
"richclay-empty",
|
|
37
|
+
"richclay-focused"
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
const installedWindows = new WeakSet();
|
|
41
|
+
const armedWindows = new WeakSet();
|
|
42
|
+
|
|
43
|
+
// Both clients dispatch the same moment under different names.
|
|
44
|
+
const PLATFORM_READY = ["clay:ready", "hyperclay:ready"];
|
|
45
|
+
|
|
46
|
+
function platformReadyPromise(win) {
|
|
47
|
+
return (
|
|
48
|
+
[win.clay?.ready, win.hyperclay?.ready].find(
|
|
49
|
+
ready => ready && typeof ready.then === "function"
|
|
50
|
+
) || null
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function platformEditMode(win) {
|
|
55
|
+
if (typeof win.clay?.isEditMode === "boolean") return win.clay.isEditMode;
|
|
56
|
+
if (typeof win.hyperclay?.isEditMode === "boolean") return win.hyperclay.isEditMode;
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// A bare namespace object proves nothing: every clayjs satellite creates
|
|
61
|
+
// window.clay for its own bookkeeping, and <div id="clay"> makes one via named
|
|
62
|
+
// window access. What distinguishes a real core is its lifecycle contract.
|
|
63
|
+
function hasPlatformLifecycle(win) {
|
|
64
|
+
const modules = win.hyperclayModules;
|
|
65
|
+
const legacyHyperclayLoader =
|
|
66
|
+
win.__hyperclayNoAutoExport === false &&
|
|
67
|
+
modules &&
|
|
68
|
+
typeof modules === "object" &&
|
|
69
|
+
typeof modules.nodeType !== "number";
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
platformEditMode(win) !== null ||
|
|
73
|
+
Boolean(platformReadyPromise(win)) ||
|
|
74
|
+
Boolean(legacyHyperclayLoader)
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Two clients provide this API and they spell three things differently. hyperclayjs
|
|
79
|
+
// owns window.hyperclay; clayjs owns window.clay and renamed the save transform to
|
|
80
|
+
// addDocumentTransform. Reading `clay ?? hyperclay` as one namespace would resolve to
|
|
81
|
+
// clay and then find no beforeSave, so richclay would silently stop stripping its own
|
|
82
|
+
// chrome and every save would write toolbars into the author's file. Hence per
|
|
83
|
+
// capability rather than per namespace.
|
|
84
|
+
function platformDocumentTransform(win) {
|
|
85
|
+
return win.clay?.addDocumentTransform || win.hyperclay?.beforeSave || null;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// onSnapshot runs on EVERY snapshot, save and live sync alike; the document
|
|
89
|
+
// transform runs only on the save branch, after the sync frame has already been
|
|
90
|
+
// dispatched. Registering only on the latter meant every live-sync frame carried
|
|
91
|
+
// contenteditable, the active classes and the runtime data-richclay to every
|
|
92
|
+
// other browser, whose own watcher subscribes to data-richclay and mounted an
|
|
93
|
+
// editor on it. Prefer the snapshot hook; fall back for a client too old to have
|
|
94
|
+
// one.
|
|
95
|
+
function platformSnapshotTransform(win) {
|
|
96
|
+
return win.clay?.onSnapshot || win.hyperclay?.onSnapshot || null;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// richclay's stylesheet carries save-remove, so no rule in richclay.css reaches
|
|
100
|
+
// the saved file. A <pre> has `white-space: pre` and never wraps, so without
|
|
101
|
+
// containment one long line runs off the side of the published page. These four
|
|
102
|
+
// declarations are the only ones that have to outlive edit mode, so they ride the
|
|
103
|
+
// markup instead of the stylesheet.
|
|
104
|
+
const PRE_CONTAINMENT = {
|
|
105
|
+
boxSizing: "border-box",
|
|
106
|
+
minWidth: "100%",
|
|
107
|
+
overflow: "auto",
|
|
108
|
+
width: "0"
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export function shouldUseHyperclay(options = {}, win = window) {
|
|
112
|
+
if (options.hyperclay === false) return false;
|
|
113
|
+
if (options.hyperclay === true) return true;
|
|
114
|
+
return Boolean(hasPlatformLifecycle(win) || hasEditmodeSignal(win));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function isHyperclayEditMode(win = window) {
|
|
118
|
+
const fromQuery = readEditmodeParam(win);
|
|
119
|
+
if (fromQuery !== null) return fromQuery;
|
|
120
|
+
|
|
121
|
+
if (typeof win.__hyperclayEditMode === "boolean") {
|
|
122
|
+
return win.__hyperclayEditMode;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const fromPlatform = platformEditMode(win);
|
|
126
|
+
if (fromPlatform !== null) return fromPlatform;
|
|
127
|
+
|
|
128
|
+
return readEditmodeCookie(win);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function shouldActivateEditor(options = {}, win = window) {
|
|
132
|
+
if (options.readOnly) return false;
|
|
133
|
+
if (!shouldUseHyperclay(options, win)) return true;
|
|
134
|
+
return isHyperclayEditMode(win);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// The editable attribute's value is a space-separated token list, like class.
|
|
138
|
+
// Unknown tokens are ignored for forward compatibility.
|
|
139
|
+
export function parseEditableOptions(element) {
|
|
140
|
+
const name = EDITABLE_ATTRS.find(attr => element.hasAttribute(attr));
|
|
141
|
+
if (!name) return null;
|
|
142
|
+
const tokens = new Set(
|
|
143
|
+
(element.getAttribute(name) || "").trim().split(/\s+/).filter(Boolean)
|
|
144
|
+
);
|
|
145
|
+
const options = {
|
|
146
|
+
inline: true,
|
|
147
|
+
singleLine: tokens.has("single-line"),
|
|
148
|
+
toolbarOnSelect: tokens.has("toolbar-on-select")
|
|
149
|
+
};
|
|
150
|
+
if (tokens.has("no-toolbar")) options.toolbar = false;
|
|
151
|
+
return options;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export function installHyperclayBridge(win = window) {
|
|
155
|
+
if (installedWindows.has(win)) return;
|
|
156
|
+
const register = platformSnapshotTransform(win) || platformDocumentTransform(win);
|
|
157
|
+
if (typeof register !== "function") {
|
|
158
|
+
armBridgeRetry(win);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
register(docElem => stripRichClayFromClone(docElem));
|
|
163
|
+
installedWindows.add(win);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// hyperclayjs publishes the transform from deep in its core waterfall while
|
|
167
|
+
// richclay arrives as one flat vendor bundle, and a flat bundle always resolves
|
|
168
|
+
// before a multi-level waterfall, so this first read reliably misses. Nothing
|
|
169
|
+
// constructs a region again afterwards, so with no retry the bridge never installs
|
|
170
|
+
// and every save writes richclay's chrome into the author's file. clayjs is immune
|
|
171
|
+
// by construction, assembling addDocumentTransform before any plugin import; the
|
|
172
|
+
// readiness pair is the signal hyperclayjs added for exactly this handshake.
|
|
173
|
+
function armBridgeRetry(win) {
|
|
174
|
+
if (armedWindows.has(win)) return;
|
|
175
|
+
const doc = win.document;
|
|
176
|
+
const ready = platformReadyPromise(win);
|
|
177
|
+
if (!doc && !ready) return;
|
|
178
|
+
armedWindows.add(win);
|
|
179
|
+
|
|
180
|
+
const retry = () => {
|
|
181
|
+
installHyperclayBridge(win);
|
|
182
|
+
if (installedWindows.has(win)) disarm();
|
|
183
|
+
};
|
|
184
|
+
const disarm = () => {
|
|
185
|
+
if (!doc) return;
|
|
186
|
+
PLATFORM_READY.forEach(name => doc.removeEventListener(name, retry));
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
if (doc) PLATFORM_READY.forEach(name => doc.addEventListener(name, retry));
|
|
190
|
+
// A loader that never settles must not surface as an unhandled rejection.
|
|
191
|
+
if (ready) ready.then(retry, () => {});
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export function stripRichClayFromClone(docElem) {
|
|
195
|
+
docElem.querySelectorAll?.(CHROME_SELECTOR).forEach(node => node.remove());
|
|
196
|
+
|
|
197
|
+
docElem.querySelectorAll?.(RICHCLAY_SELECTOR).forEach(region => {
|
|
198
|
+
// richclay only cleans up after itself. A region it never took ownership of,
|
|
199
|
+
// because it refused the root or was never activated, is the author's markup
|
|
200
|
+
// and has to come through the save byte for byte. setupEditorAttributes sets
|
|
201
|
+
// this marker in the same breath as every other runtime attribute, so its
|
|
202
|
+
// absence means there is nothing here to strip and nothing here to repair.
|
|
203
|
+
if (region.getAttribute("data-richclay-active") !== "true") return;
|
|
204
|
+
removeRuntimeState(region, "save");
|
|
205
|
+
// The only place this has to be right. Damage happens when markup reaches the
|
|
206
|
+
// file, so a flatten here sits downstream of every Squire route: setHTML,
|
|
207
|
+
// clear formatting, the image resizer, shortcuts, paste, and whatever a future
|
|
208
|
+
// Squire adds. Three rounds of chasing entry points end here.
|
|
209
|
+
//
|
|
210
|
+
// It cannot destroy the author's own blocks, which is what round 3b's version
|
|
211
|
+
// did: a block inside a region with a <p> ancestor cannot have come from their
|
|
212
|
+
// file, because the parser would have ejected it before richclay ever saw it.
|
|
213
|
+
// And it runs on a clone, so it cannot disturb the caret or the undo stack.
|
|
214
|
+
if (needsFlattening(region)) {
|
|
215
|
+
const doc = region.ownerDocument;
|
|
216
|
+
const singleLine = Boolean(region.matches?.(singleLineSelector));
|
|
217
|
+
flattenBlocks(region, () =>
|
|
218
|
+
singleLine ? doc.createTextNode(" ") : doc.createElement("br")
|
|
219
|
+
);
|
|
220
|
+
// flattenBlocks only unwraps blocks, so it cannot repair <a> inside <a>. Same
|
|
221
|
+
// idea, one tag: keep the text, drop the nested duplicate.
|
|
222
|
+
region.querySelectorAll(region.localName).forEach(nested => {
|
|
223
|
+
while (nested.firstChild) nested.parentNode.insertBefore(nested.firstChild, nested);
|
|
224
|
+
nested.remove();
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
if (region.matches?.(singleLineSelector)) unwrapLoneSingleLineBlock(region);
|
|
228
|
+
region.querySelectorAll("#squire-selection-start, #squire-selection-end").forEach(node => {
|
|
229
|
+
node.remove();
|
|
230
|
+
});
|
|
231
|
+
region.querySelectorAll(".squire-image-resize-container").forEach(node => node.remove());
|
|
232
|
+
stripZeroWidthArtifacts(region);
|
|
233
|
+
// PRE_CONTAINMENT keeps a long line from running off the side of the published
|
|
234
|
+
// page, where richclay's stylesheet has been stripped by save-remove. It has to
|
|
235
|
+
// ride the markup for that reason. It must not ride an author's own <pre>: those
|
|
236
|
+
// are theirs, their CSS already handles them, and writing width: 0 into a file
|
|
237
|
+
// that was only opened breaks the byte-identical-on-open invariant everything
|
|
238
|
+
// else here defends. Only a <pre> richclay made gets contained.
|
|
239
|
+
const codeBlocks = (region.matches?.("pre")
|
|
240
|
+
? [region, ...region.querySelectorAll("pre")]
|
|
241
|
+
: Array.from(region.querySelectorAll("pre"))
|
|
242
|
+
).filter(pre => pre.hasAttribute("data-richclay-pre"));
|
|
243
|
+
|
|
244
|
+
codeBlocks.forEach(pre => {
|
|
245
|
+
Object.entries(PRE_CONTAINMENT).forEach(([property, value]) => {
|
|
246
|
+
if (!pre.style[property]) pre.style[property] = value;
|
|
247
|
+
});
|
|
248
|
+
pre.removeAttribute("data-richclay-pre");
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
// Squire leaves its selection bookmarks wherever the command was operating,
|
|
253
|
+
// which is not always inside a region. Sweeping the document costs one query and
|
|
254
|
+
// cannot leave one behind.
|
|
255
|
+
docElem
|
|
256
|
+
.querySelectorAll?.("#squire-selection-start, #squire-selection-end")
|
|
257
|
+
.forEach(node => node.remove());
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// The region's nearest block ancestor is the smallest subtree whose serialization
|
|
261
|
+
// reproduces the ejection, for `p > span > span editable` as well as for
|
|
262
|
+
// `div > h2 editable`. Deliberately no BODY: a region with no block ancestor at
|
|
263
|
+
// all reparses correctly on its own, and scoping to BODY would serialize the
|
|
264
|
+
// whole page on every save.
|
|
265
|
+
const BLOCK_SCOPE =
|
|
266
|
+
"p, td, th, li, dl, dt, dd, table, blockquote, div, section, article, aside, main, header, footer, figure, figcaption";
|
|
267
|
+
const MEASURE_ATTR = "data-richclay-measure";
|
|
268
|
+
|
|
269
|
+
// Round trip the region through the real parser and see whether it still owns its
|
|
270
|
+
// own content. This cannot be wrong about the parser, because it is the parser: it
|
|
271
|
+
// covers the <p> rule, the whole implicitly-closes family (heading in heading, li
|
|
272
|
+
// in li, a in a, dt/dd, td in td, button, form), and anything a future spec adds,
|
|
273
|
+
// with no list to maintain and no list to get wrong for a fourth time.
|
|
274
|
+
//
|
|
275
|
+
// It also draws the line the old structural predicate could not see. A <ul> pasted
|
|
276
|
+
// into an <h2 editable> is stable, so it measures clean and is left alone; an <h3>
|
|
277
|
+
// pasted into the same region ejects, so it is flattened. The hook no longer has to
|
|
278
|
+
// know the difference between markup that is merely invalid and markup that is
|
|
279
|
+
// doomed, because it can watch which one happens.
|
|
280
|
+
function ejectsOnReload(region) {
|
|
281
|
+
const doc = region.ownerDocument;
|
|
282
|
+
const scope = region.closest(BLOCK_SCOPE) || region;
|
|
283
|
+
region.setAttribute(MEASURE_ATTR, "");
|
|
284
|
+
const probe = doc.createElement("div");
|
|
285
|
+
try {
|
|
286
|
+
probe.innerHTML = scope.outerHTML;
|
|
287
|
+
} finally {
|
|
288
|
+
region.removeAttribute(MEASURE_ATTR);
|
|
289
|
+
}
|
|
290
|
+
const reparsed = probe.querySelector(`[${MEASURE_ATTR}]`);
|
|
291
|
+
return !reparsed || reparsed.textContent !== region.textContent;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// A region can also lose content to an element of its own tag: the parser closes
|
|
295
|
+
// the outer one when the inner start tag arrives. Asking the region which tag it is
|
|
296
|
+
// keeps this out of list territory.
|
|
297
|
+
const selfNests = region => Boolean(region.querySelector(region.localName));
|
|
298
|
+
|
|
299
|
+
// hasBlockDescendant first, and not only as an optimisation: a region with no block
|
|
300
|
+
// in it has nothing this hook could flatten, so measuring it would be work with no
|
|
301
|
+
// possible outcome. Measured on an 8-paragraph region: the check is 0.02 ms and the
|
|
302
|
+
// reparse it skips is 0.43 ms, so an ordinary save pays almost nothing.
|
|
303
|
+
const needsFlattening = region =>
|
|
304
|
+
Boolean(region.matches?.(singleLineSelector)) ||
|
|
305
|
+
((hasBlockDescendant(region) || selfNests(region)) && ejectsOnReload(region));
|
|
306
|
+
|
|
307
|
+
// Shared runtime-state removal used by both the save strip (on the cloned
|
|
308
|
+
// document) and destroy() (on the live element). The contenteditable marker
|
|
309
|
+
// records provenance: "true" means richclay added the attribute; any other
|
|
310
|
+
// value is the author's original non-"true" value; no marker with the
|
|
311
|
+
// attribute present means the author wrote contenteditable="true" themselves.
|
|
312
|
+
export function removeRuntimeState(region, mode) {
|
|
313
|
+
const origin = region.getAttribute("data-richclay-runtime-contenteditable");
|
|
314
|
+
|
|
315
|
+
if (region.hasAttribute("contenteditable")) {
|
|
316
|
+
if (origin === "true") {
|
|
317
|
+
region.removeAttribute("contenteditable");
|
|
318
|
+
} else if (origin) {
|
|
319
|
+
if (mode === "destroy") {
|
|
320
|
+
region.setAttribute("contenteditable", origin);
|
|
321
|
+
} else {
|
|
322
|
+
region.setAttribute("inert-contenteditable", origin);
|
|
323
|
+
region.removeAttribute("contenteditable");
|
|
324
|
+
}
|
|
325
|
+
} else if (mode === "save") {
|
|
326
|
+
region.setAttribute("inert-contenteditable", region.getAttribute("contenteditable"));
|
|
327
|
+
region.removeAttribute("contenteditable");
|
|
328
|
+
}
|
|
329
|
+
// destroy with no marker: the author wrote contenteditable; leave it.
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
runtimeClasses.forEach(className => region.classList.remove(className));
|
|
333
|
+
if (region.getAttribute("class") === "") region.removeAttribute("class");
|
|
334
|
+
|
|
335
|
+
removeRuntimeAttribute(region, "role", "data-richclay-runtime-role");
|
|
336
|
+
removeRuntimeAttribute(region, "aria-multiline", "data-richclay-runtime-aria-multiline");
|
|
337
|
+
removeRuntimeAttribute(region, "no-undo", "data-richclay-runtime-no-undo");
|
|
338
|
+
if (region.getAttribute("data-richclay-runtime-display") === "true") {
|
|
339
|
+
region.style.removeProperty("display");
|
|
340
|
+
if (region.getAttribute("style") === "") region.removeAttribute("style");
|
|
341
|
+
}
|
|
342
|
+
removeRuntimeDescribedBy(region);
|
|
343
|
+
|
|
344
|
+
region.removeAttribute("data-richclay-active");
|
|
345
|
+
region.removeAttribute("data-richclay-placeholder");
|
|
346
|
+
region.removeAttribute("data-richclay-pre");
|
|
347
|
+
region.removeAttribute("data-richclay-runtime-role");
|
|
348
|
+
region.removeAttribute("data-richclay-runtime-aria-multiline");
|
|
349
|
+
region.removeAttribute("data-richclay-runtime-no-undo");
|
|
350
|
+
region.removeAttribute("data-richclay-runtime-describedby");
|
|
351
|
+
region.removeAttribute("data-richclay-runtime-contenteditable");
|
|
352
|
+
region.removeAttribute("data-richclay-runtime-display");
|
|
353
|
+
|
|
354
|
+
// Only a marker richclay invented comes off; an authored data-richclay has no
|
|
355
|
+
// provenance attribute and survives byte for byte. Note this list is an
|
|
356
|
+
// explicit enumeration, not a prefix sweep, so a new runtime attribute is only
|
|
357
|
+
// removed if it is named here.
|
|
358
|
+
if (region.getAttribute("data-richclay-runtime-marker") === "true") {
|
|
359
|
+
region.removeAttribute("data-richclay");
|
|
360
|
+
}
|
|
361
|
+
region.removeAttribute("data-richclay-runtime-marker");
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function stripZeroWidthArtifacts(region) {
|
|
365
|
+
const zwsp = String.fromCharCode(0x200b);
|
|
366
|
+
const stack = [region];
|
|
367
|
+
while (stack.length) {
|
|
368
|
+
const node = stack.pop();
|
|
369
|
+
node.childNodes.forEach(child => {
|
|
370
|
+
if (child.nodeType === 3) {
|
|
371
|
+
if (child.nodeValue.includes(zwsp)) {
|
|
372
|
+
child.nodeValue = child.nodeValue.split(zwsp).join("");
|
|
373
|
+
}
|
|
374
|
+
} else if (child.nodeType === 1) {
|
|
375
|
+
stack.push(child);
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
// Drop inline wrappers Squire left empty once the caret placeholder is gone.
|
|
380
|
+
region.querySelectorAll("b, i, u, s, em, strong, code, sub, sup, span").forEach(el => {
|
|
381
|
+
if (el.children.length === 0 && (el.textContent || "") === "" && el.attributes.length === 0) {
|
|
382
|
+
el.remove();
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// Safety net for single-line regions: with the fidelity-first attach Squire
|
|
388
|
+
// never wraps the content, but if a lone bare <P> wrapper ever appears, the
|
|
389
|
+
// saved file must not contain it.
|
|
390
|
+
function unwrapLoneSingleLineBlock(region) {
|
|
391
|
+
const meaningful = Array.from(region.childNodes).filter(
|
|
392
|
+
node => node.nodeType !== 3 || (node.nodeValue || "").trim() !== ""
|
|
393
|
+
);
|
|
394
|
+
if (meaningful.length !== 1) return;
|
|
395
|
+
const block = meaningful[0];
|
|
396
|
+
if (block.nodeType !== 1 || block.nodeName !== "P" || block.attributes.length > 0) return;
|
|
397
|
+
while (block.firstChild) region.insertBefore(block.firstChild, block);
|
|
398
|
+
block.remove();
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
export function consumeInertContenteditable(element) {
|
|
402
|
+
if (!element.hasAttribute("inert-contenteditable")) return null;
|
|
403
|
+
|
|
404
|
+
let value = element.getAttribute("inert-contenteditable");
|
|
405
|
+
if (!["false", "plaintext-only"].includes(value)) value = "true";
|
|
406
|
+
element.setAttribute("contenteditable", value);
|
|
407
|
+
element.removeAttribute("inert-contenteditable");
|
|
408
|
+
if (value === "true") {
|
|
409
|
+
// Self-heal: a saved inert "true" is redundant with what activation
|
|
410
|
+
// re-adds. Mark it runtime so the next save drops it from the file
|
|
411
|
+
// instead of round-tripping it forever.
|
|
412
|
+
element.setAttribute("data-richclay-runtime-contenteditable", "true");
|
|
413
|
+
}
|
|
414
|
+
return value;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
export function markChrome(element) {
|
|
418
|
+
// snapshot-remove drops it from every Hyperclay snapshot (save, live-sync, and
|
|
419
|
+
// dirty comparison). no-watch additionally keeps the mutation observer from
|
|
420
|
+
// walking this high-churn subtree at all. Both stay out of the saved file.
|
|
421
|
+
element.setAttribute("snapshot-remove", "");
|
|
422
|
+
element.setAttribute("no-watch", "");
|
|
423
|
+
return element;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
function readEditmodeParam(win) {
|
|
427
|
+
try {
|
|
428
|
+
const params = new URLSearchParams(win.location?.search || "");
|
|
429
|
+
if (params.get("editmode") === "true") return true;
|
|
430
|
+
if (params.get("editmode") === "false") return false;
|
|
431
|
+
} catch {
|
|
432
|
+
return null;
|
|
433
|
+
}
|
|
434
|
+
return null;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
function hasEditmodeSignal(win) {
|
|
438
|
+
return readEditmodeParam(win) !== null || typeof win.__hyperclayEditMode === "boolean";
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
function readEditmodeCookie(win) {
|
|
442
|
+
// Hyperclay signals an owner's edit session with the isAdminOfCurrentResource
|
|
443
|
+
// cookie (see hyperclayjs isAdminOfCurrentResource.js); any non-empty value
|
|
444
|
+
// means the logged-in owner is editing. Read it directly so richclay stays
|
|
445
|
+
// standalone and never imports hyperclayjs.
|
|
446
|
+
const cookie = win.document?.cookie || "";
|
|
447
|
+
const match = cookie.match(/(?:^|;\s*)isAdminOfCurrentResource=([^;]*)/);
|
|
448
|
+
return Boolean(match && match[1] !== "");
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
function removeRuntimeAttribute(region, attribute, marker) {
|
|
452
|
+
if (!region.hasAttribute(marker)) return;
|
|
453
|
+
region.removeAttribute(attribute);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
function removeRuntimeDescribedBy(region) {
|
|
457
|
+
const id = region.getAttribute("data-richclay-runtime-describedby");
|
|
458
|
+
if (!id) return;
|
|
459
|
+
|
|
460
|
+
const ids = (region.getAttribute("aria-describedby") || "")
|
|
461
|
+
.split(/\s+/)
|
|
462
|
+
.filter(Boolean)
|
|
463
|
+
.filter(value => value !== id);
|
|
464
|
+
|
|
465
|
+
if (ids.length) {
|
|
466
|
+
region.setAttribute("aria-describedby", ids.join(" "));
|
|
467
|
+
} else {
|
|
468
|
+
region.removeAttribute("aria-describedby");
|
|
469
|
+
}
|
|
470
|
+
}
|