@next-buildr/editor 2.0.1 → 3.0.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/UPGRADING.md +322 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/app/builder-editor.test.js +223 -18
- package/dist/app/config.d.ts +27 -4
- package/dist/app/config.d.ts.map +1 -1
- package/dist/app/config.js +4 -3
- package/dist/app/contracts.d.ts +40 -0
- package/dist/app/contracts.d.ts.map +1 -0
- package/dist/app/contracts.js +4 -0
- package/dist/app/editor-app.d.ts.map +1 -1
- package/dist/app/editor-app.js +316 -24
- package/dist/app/editor-app.test.js +144 -6
- package/dist/app/layout.d.ts +11 -2
- package/dist/app/layout.d.ts.map +1 -1
- package/dist/app/layout.js +170 -9
- package/dist/app/manifest.d.ts +7 -2
- package/dist/app/manifest.d.ts.map +1 -1
- package/dist/app/manifest.js +16 -4
- package/dist/app/shell-panels.d.ts +15 -0
- package/dist/app/shell-panels.d.ts.map +1 -1
- package/dist/app/small-screen.test.js +2 -2
- package/dist/app/stage-slots.d.ts +9 -0
- package/dist/app/stage-slots.d.ts.map +1 -0
- package/dist/app/stage-slots.js +10 -0
- package/dist/app/status-info.d.ts +2 -3
- package/dist/app/status-info.d.ts.map +1 -1
- package/dist/app/status-info.js +49 -16
- package/dist/canvas-host/canvas-frame.d.ts +13 -1
- package/dist/canvas-host/canvas-frame.d.ts.map +1 -1
- package/dist/canvas-host/canvas-frame.js +96 -8
- package/dist/canvas-host/canvas-frame.test.js +156 -3
- package/dist/canvas-host/host.d.ts +6 -0
- package/dist/canvas-host/host.d.ts.map +1 -1
- package/dist/canvas-host/host.js +116 -4
- package/dist/canvas-host/host.test.js +195 -6
- package/dist/clipboard/clipboard.d.ts +1 -1
- package/dist/clipboard/clipboard.d.ts.map +1 -1
- package/dist/clipboard/clipboard.js +5 -0
- package/dist/clipboard/clipboard.test.js +21 -1
- package/dist/clipboard/format.d.ts +3 -1
- package/dist/clipboard/format.d.ts.map +1 -1
- package/dist/clipboard/react.d.ts +1 -1
- package/dist/clipboard/react.d.ts.map +1 -1
- package/dist/clipboard/react.js +49 -3
- package/dist/dialogs/external-source.d.ts +15 -0
- package/dist/dialogs/external-source.d.ts.map +1 -0
- package/dist/dialogs/external-source.js +18 -0
- package/dist/dialogs/index.d.ts +4 -0
- package/dist/dialogs/index.d.ts.map +1 -1
- package/dist/dialogs/index.js +2 -0
- package/dist/dialogs/media-picker/index.d.ts +2 -2
- package/dist/dialogs/media-picker/index.d.ts.map +1 -1
- package/dist/dialogs/media-picker/index.js +1 -1
- package/dist/dialogs/media-picker/media-picker.d.ts +5 -0
- package/dist/dialogs/media-picker/media-picker.d.ts.map +1 -1
- package/dist/dialogs/media-picker/media-picker.js +67 -5
- package/dist/dialogs/media-picker/media-picker.test.js +72 -1
- package/dist/dialogs/media-picker/media-ref.d.ts +15 -0
- package/dist/dialogs/media-picker/media-ref.d.ts.map +1 -1
- package/dist/dialogs/media-picker/media-ref.js +29 -0
- package/dist/dialogs/remove-confirm.d.ts +14 -0
- package/dist/dialogs/remove-confirm.d.ts.map +1 -0
- package/dist/dialogs/remove-confirm.js +42 -0
- package/dist/dialogs/remove-confirm.test.d.ts +2 -0
- package/dist/dialogs/remove-confirm.test.d.ts.map +1 -0
- package/dist/dialogs/remove-confirm.test.js +118 -0
- package/dist/dnd/dnd-react.test.js +11 -2
- package/dist/dnd/dnd.test.js +23 -0
- package/dist/dnd/engine.d.ts +4 -2
- package/dist/dnd/engine.d.ts.map +1 -1
- package/dist/dnd/engine.js +6 -0
- package/dist/dnd/move-to-dialog.d.ts +4 -3
- package/dist/dnd/move-to-dialog.d.ts.map +1 -1
- package/dist/dnd/move-to-dialog.js +67 -10
- package/dist/dnd/react.d.ts.map +1 -1
- package/dist/dnd/react.js +5 -0
- package/dist/i18n/diagnostics.d.ts +22 -0
- package/dist/i18n/diagnostics.d.ts.map +1 -0
- package/dist/i18n/diagnostics.js +153 -0
- package/dist/i18n/diagnostics.test.d.ts +2 -0
- package/dist/i18n/diagnostics.test.d.ts.map +1 -0
- package/dist/i18n/diagnostics.test.js +74 -0
- package/dist/i18n/label-catalog.d.ts +20 -0
- package/dist/i18n/label-catalog.d.ts.map +1 -0
- package/dist/i18n/label-catalog.js +1 -0
- package/dist/i18n/locale-name.d.ts +7 -0
- package/dist/i18n/locale-name.d.ts.map +1 -0
- package/dist/i18n/locale-name.js +31 -0
- package/dist/i18n/localize-manifest.d.ts +11 -0
- package/dist/i18n/localize-manifest.d.ts.map +1 -0
- package/dist/i18n/localize-manifest.js +78 -0
- package/dist/i18n/localize-manifest.test.d.ts +2 -0
- package/dist/i18n/localize-manifest.test.d.ts.map +1 -0
- package/dist/i18n/localize-manifest.test.js +71 -0
- package/dist/messages/catalogs.test.d.ts +2 -0
- package/dist/messages/catalogs.test.d.ts.map +1 -0
- package/dist/messages/catalogs.test.js +80 -0
- package/dist/messages/en/app.d.ts +8 -0
- package/dist/messages/en/app.d.ts.map +1 -0
- package/dist/messages/en/app.js +7 -0
- package/dist/messages/en/blocks.d.ts +54 -0
- package/dist/messages/en/blocks.d.ts.map +1 -0
- package/dist/messages/en/blocks.js +53 -0
- package/dist/messages/en/canvas.d.ts +31 -0
- package/dist/messages/en/canvas.d.ts.map +1 -0
- package/dist/messages/en/canvas.js +30 -0
- package/dist/messages/en/clipboard.d.ts +13 -0
- package/dist/messages/en/clipboard.d.ts.map +1 -0
- package/dist/messages/en/clipboard.js +12 -0
- package/dist/messages/en/colorPicker.d.ts +20 -0
- package/dist/messages/en/colorPicker.d.ts.map +1 -0
- package/dist/messages/en/colorPicker.js +19 -0
- package/dist/messages/en/diagnostics.d.ts +40 -0
- package/dist/messages/en/diagnostics.d.ts.map +1 -0
- package/dist/messages/en/diagnostics.js +39 -0
- package/dist/messages/en/dialogs/common.d.ts +6 -0
- package/dist/messages/en/dialogs/common.d.ts.map +1 -0
- package/dist/messages/en/dialogs/common.js +5 -0
- package/dist/messages/en/dialogs/conflict.d.ts +15 -0
- package/dist/messages/en/dialogs/conflict.d.ts.map +1 -0
- package/dist/messages/en/dialogs/conflict.js +14 -0
- package/dist/messages/en/dialogs/delete.d.ts +19 -0
- package/dist/messages/en/dialogs/delete.d.ts.map +1 -0
- package/dist/messages/en/dialogs/delete.js +18 -0
- package/dist/messages/en/dialogs/pageOptions.d.ts +9 -0
- package/dist/messages/en/dialogs/pageOptions.d.ts.map +1 -0
- package/dist/messages/en/dialogs/pageOptions.js +8 -0
- package/dist/messages/en/dialogs/publish.d.ts +15 -0
- package/dist/messages/en/dialogs/publish.d.ts.map +1 -0
- package/dist/messages/en/dialogs/publish.js +14 -0
- package/dist/messages/en/dnd.d.ts +19 -0
- package/dist/messages/en/dnd.d.ts.map +1 -0
- package/dist/messages/en/dnd.js +18 -0
- package/dist/messages/en/editor.d.ts +30 -0
- package/dist/messages/en/editor.d.ts.map +1 -0
- package/dist/messages/en/editor.js +29 -0
- package/dist/messages/en/external.d.ts +6 -0
- package/dist/messages/en/external.d.ts.map +1 -0
- package/dist/messages/en/external.js +5 -0
- package/dist/messages/en/insert.d.ts +25 -0
- package/dist/messages/en/insert.d.ts.map +1 -0
- package/dist/messages/en/insert.js +24 -0
- package/dist/messages/en/inspector.d.ts +176 -0
- package/dist/messages/en/inspector.d.ts.map +1 -0
- package/dist/messages/en/inspector.js +175 -0
- package/dist/messages/en/issues.d.ts +36 -0
- package/dist/messages/en/issues.d.ts.map +1 -0
- package/dist/messages/en/issues.js +35 -0
- package/dist/messages/en/layers.d.ts +29 -0
- package/dist/messages/en/layers.d.ts.map +1 -0
- package/dist/messages/en/layers.js +28 -0
- package/dist/messages/en/leftPanel.d.ts +15 -0
- package/dist/messages/en/leftPanel.d.ts.map +1 -0
- package/dist/messages/en/leftPanel.js +14 -0
- package/dist/messages/en/list.d.ts +9 -0
- package/dist/messages/en/list.d.ts.map +1 -0
- package/dist/messages/en/list.js +8 -0
- package/dist/messages/en/locale.d.ts +4 -0
- package/dist/messages/en/locale.d.ts.map +1 -0
- package/dist/messages/en/locale.js +3 -0
- package/dist/messages/en/media.d.ts +51 -0
- package/dist/messages/en/media.d.ts.map +1 -0
- package/dist/messages/en/media.js +50 -0
- package/dist/messages/en/menu.d.ts +12 -0
- package/dist/messages/en/menu.d.ts.map +1 -0
- package/dist/messages/en/menu.js +11 -0
- package/dist/messages/en/patterns.d.ts +24 -0
- package/dist/messages/en/patterns.d.ts.map +1 -0
- package/dist/messages/en/patterns.js +23 -0
- package/dist/messages/en/preview.d.ts +8 -0
- package/dist/messages/en/preview.d.ts.map +1 -0
- package/dist/messages/en/preview.js +7 -0
- package/dist/messages/en/publish.d.ts +19 -0
- package/dist/messages/en/publish.d.ts.map +1 -0
- package/dist/messages/en/publish.js +18 -0
- package/dist/messages/en/richText.d.ts +21 -0
- package/dist/messages/en/richText.d.ts.map +1 -0
- package/dist/messages/en/richText.js +20 -0
- package/dist/messages/en/sample.d.ts +5 -0
- package/dist/messages/en/sample.d.ts.map +1 -0
- package/dist/messages/en/sample.js +4 -0
- package/dist/messages/en/save.d.ts +15 -0
- package/dist/messages/en/save.d.ts.map +1 -0
- package/dist/messages/en/save.js +14 -0
- package/dist/messages/en/shortcut.d.ts +36 -0
- package/dist/messages/en/shortcut.d.ts.map +1 -0
- package/dist/messages/en/shortcut.js +35 -0
- package/dist/messages/en/statusBar.d.ts +14 -0
- package/dist/messages/en/statusBar.d.ts.map +1 -0
- package/dist/messages/en/statusBar.js +13 -0
- package/dist/messages/en/structure.d.ts +28 -0
- package/dist/messages/en/structure.d.ts.map +1 -0
- package/dist/messages/en/structure.js +27 -0
- package/dist/messages/en/style.d.ts +168 -0
- package/dist/messages/en/style.d.ts.map +1 -0
- package/dist/messages/en/style.js +167 -0
- package/dist/messages/en/styleField.d.ts +301 -0
- package/dist/messages/en/styleField.d.ts.map +1 -0
- package/dist/messages/en/styleField.js +300 -0
- package/dist/messages/en/styleOption.d.ts +128 -0
- package/dist/messages/en/styleOption.d.ts.map +1 -0
- package/dist/messages/en/styleOption.js +127 -0
- package/dist/messages/en/styleSection.d.ts +16 -0
- package/dist/messages/en/styleSection.d.ts.map +1 -0
- package/dist/messages/en/styleSection.js +15 -0
- package/dist/messages/en/toast.d.ts +22 -0
- package/dist/messages/en/toast.d.ts.map +1 -0
- package/dist/messages/en/toast.js +21 -0
- package/dist/messages/en/toolbar.d.ts +47 -0
- package/dist/messages/en/toolbar.d.ts.map +1 -0
- package/dist/messages/en/toolbar.js +46 -0
- package/dist/messages/en/translation.d.ts +7 -0
- package/dist/messages/en/translation.d.ts.map +1 -0
- package/dist/messages/en/translation.js +6 -0
- package/dist/messages/en/ui.d.ts +4 -0
- package/dist/messages/en/ui.d.ts.map +1 -0
- package/dist/messages/en/ui.js +3 -0
- package/dist/messages/en/values.d.ts +45 -0
- package/dist/messages/en/values.d.ts.map +1 -0
- package/dist/messages/en/values.js +44 -0
- package/dist/messages/en.d.ts +1298 -202
- package/dist/messages/en.d.ts.map +1 -1
- package/dist/messages/en.js +82 -330
- package/dist/messages/index.d.ts +12 -0
- package/dist/messages/index.d.ts.map +1 -1
- package/dist/messages/index.js +28 -1
- package/dist/messages/pl/app.d.ts +8 -0
- package/dist/messages/pl/app.d.ts.map +1 -0
- package/dist/messages/pl/app.js +7 -0
- package/dist/messages/pl/blocks.d.ts +54 -0
- package/dist/messages/pl/blocks.d.ts.map +1 -0
- package/dist/messages/pl/blocks.js +53 -0
- package/dist/messages/pl/canvas.d.ts +31 -0
- package/dist/messages/pl/canvas.d.ts.map +1 -0
- package/dist/messages/pl/canvas.js +30 -0
- package/dist/messages/pl/clipboard.d.ts +13 -0
- package/dist/messages/pl/clipboard.d.ts.map +1 -0
- package/dist/messages/pl/clipboard.js +12 -0
- package/dist/messages/pl/colorPicker.d.ts +20 -0
- package/dist/messages/pl/colorPicker.d.ts.map +1 -0
- package/dist/messages/pl/colorPicker.js +19 -0
- package/dist/messages/pl/componentLabels.d.ts +9 -0
- package/dist/messages/pl/componentLabels.d.ts.map +1 -0
- package/dist/messages/pl/componentLabels.js +308 -0
- package/dist/messages/pl/diagnostics.d.ts +39 -0
- package/dist/messages/pl/diagnostics.d.ts.map +1 -0
- package/dist/messages/pl/diagnostics.js +38 -0
- package/dist/messages/pl/dialogs/common.d.ts +6 -0
- package/dist/messages/pl/dialogs/common.d.ts.map +1 -0
- package/dist/messages/pl/dialogs/common.js +5 -0
- package/dist/messages/pl/dialogs/conflict.d.ts +15 -0
- package/dist/messages/pl/dialogs/conflict.d.ts.map +1 -0
- package/dist/messages/pl/dialogs/conflict.js +14 -0
- package/dist/messages/pl/dialogs/delete.d.ts +19 -0
- package/dist/messages/pl/dialogs/delete.d.ts.map +1 -0
- package/dist/messages/pl/dialogs/delete.js +18 -0
- package/dist/messages/pl/dialogs/pageOptions.d.ts +9 -0
- package/dist/messages/pl/dialogs/pageOptions.d.ts.map +1 -0
- package/dist/messages/pl/dialogs/pageOptions.js +8 -0
- package/dist/messages/pl/dialogs/publish.d.ts +15 -0
- package/dist/messages/pl/dialogs/publish.d.ts.map +1 -0
- package/dist/messages/pl/dialogs/publish.js +14 -0
- package/dist/messages/pl/dnd.d.ts +19 -0
- package/dist/messages/pl/dnd.d.ts.map +1 -0
- package/dist/messages/pl/dnd.js +18 -0
- package/dist/messages/pl/editor.d.ts +30 -0
- package/dist/messages/pl/editor.d.ts.map +1 -0
- package/dist/messages/pl/editor.js +29 -0
- package/dist/messages/pl/external.d.ts +6 -0
- package/dist/messages/pl/external.d.ts.map +1 -0
- package/dist/messages/pl/external.js +5 -0
- package/dist/messages/pl/insert.d.ts +25 -0
- package/dist/messages/pl/insert.d.ts.map +1 -0
- package/dist/messages/pl/insert.js +24 -0
- package/dist/messages/pl/inspector.d.ts +176 -0
- package/dist/messages/pl/inspector.d.ts.map +1 -0
- package/dist/messages/pl/inspector.js +175 -0
- package/dist/messages/pl/issues.d.ts +36 -0
- package/dist/messages/pl/issues.d.ts.map +1 -0
- package/dist/messages/pl/issues.js +35 -0
- package/dist/messages/pl/layers.d.ts +29 -0
- package/dist/messages/pl/layers.d.ts.map +1 -0
- package/dist/messages/pl/layers.js +28 -0
- package/dist/messages/pl/leftPanel.d.ts +15 -0
- package/dist/messages/pl/leftPanel.d.ts.map +1 -0
- package/dist/messages/pl/leftPanel.js +14 -0
- package/dist/messages/pl/list.d.ts +9 -0
- package/dist/messages/pl/list.d.ts.map +1 -0
- package/dist/messages/pl/list.js +8 -0
- package/dist/messages/pl/locale.d.ts +4 -0
- package/dist/messages/pl/locale.d.ts.map +1 -0
- package/dist/messages/pl/locale.js +3 -0
- package/dist/messages/pl/media.d.ts +51 -0
- package/dist/messages/pl/media.d.ts.map +1 -0
- package/dist/messages/pl/media.js +50 -0
- package/dist/messages/pl/menu.d.ts +12 -0
- package/dist/messages/pl/menu.d.ts.map +1 -0
- package/dist/messages/pl/menu.js +11 -0
- package/dist/messages/pl/patterns.d.ts +24 -0
- package/dist/messages/pl/patterns.d.ts.map +1 -0
- package/dist/messages/pl/patterns.js +23 -0
- package/dist/messages/pl/preview.d.ts +8 -0
- package/dist/messages/pl/preview.d.ts.map +1 -0
- package/dist/messages/pl/preview.js +7 -0
- package/dist/messages/pl/publish.d.ts +19 -0
- package/dist/messages/pl/publish.d.ts.map +1 -0
- package/dist/messages/pl/publish.js +18 -0
- package/dist/messages/pl/richText.d.ts +21 -0
- package/dist/messages/pl/richText.d.ts.map +1 -0
- package/dist/messages/pl/richText.js +20 -0
- package/dist/messages/pl/sample.d.ts +5 -0
- package/dist/messages/pl/sample.d.ts.map +1 -0
- package/dist/messages/pl/sample.js +4 -0
- package/dist/messages/pl/save.d.ts +15 -0
- package/dist/messages/pl/save.d.ts.map +1 -0
- package/dist/messages/pl/save.js +14 -0
- package/dist/messages/pl/shortcut.d.ts +36 -0
- package/dist/messages/pl/shortcut.d.ts.map +1 -0
- package/dist/messages/pl/shortcut.js +35 -0
- package/dist/messages/pl/statusBar.d.ts +14 -0
- package/dist/messages/pl/statusBar.d.ts.map +1 -0
- package/dist/messages/pl/statusBar.js +13 -0
- package/dist/messages/pl/structure.d.ts +28 -0
- package/dist/messages/pl/structure.d.ts.map +1 -0
- package/dist/messages/pl/structure.js +27 -0
- package/dist/messages/pl/style.d.ts +168 -0
- package/dist/messages/pl/style.d.ts.map +1 -0
- package/dist/messages/pl/style.js +167 -0
- package/dist/messages/pl/styleField.d.ts +301 -0
- package/dist/messages/pl/styleField.d.ts.map +1 -0
- package/dist/messages/pl/styleField.js +300 -0
- package/dist/messages/pl/styleOption.d.ts +128 -0
- package/dist/messages/pl/styleOption.d.ts.map +1 -0
- package/dist/messages/pl/styleOption.js +127 -0
- package/dist/messages/pl/styleSection.d.ts +16 -0
- package/dist/messages/pl/styleSection.d.ts.map +1 -0
- package/dist/messages/pl/styleSection.js +15 -0
- package/dist/messages/pl/toast.d.ts +22 -0
- package/dist/messages/pl/toast.d.ts.map +1 -0
- package/dist/messages/pl/toast.js +21 -0
- package/dist/messages/pl/toolbar.d.ts +47 -0
- package/dist/messages/pl/toolbar.d.ts.map +1 -0
- package/dist/messages/pl/toolbar.js +46 -0
- package/dist/messages/pl/translation.d.ts +7 -0
- package/dist/messages/pl/translation.d.ts.map +1 -0
- package/dist/messages/pl/translation.js +6 -0
- package/dist/messages/pl/ui.d.ts +4 -0
- package/dist/messages/pl/ui.d.ts.map +1 -0
- package/dist/messages/pl/ui.js +3 -0
- package/dist/messages/pl/values.d.ts +45 -0
- package/dist/messages/pl/values.d.ts.map +1 -0
- package/dist/messages/pl/values.js +44 -0
- package/dist/messages/pl.d.ts.map +1 -1
- package/dist/messages/pl.js +82 -325
- package/dist/messages/plural.test.d.ts +2 -0
- package/dist/messages/plural.test.d.ts.map +1 -0
- package/dist/messages/plural.test.js +50 -0
- package/dist/panels/breadcrumbs/breadcrumbs.d.ts +1 -1
- package/dist/panels/breadcrumbs/breadcrumbs.d.ts.map +1 -1
- package/dist/panels/breadcrumbs/breadcrumbs.js +10 -3
- package/dist/panels/breadcrumbs/breadcrumbs.test.js +9 -2
- package/dist/panels/index.d.ts +3 -0
- package/dist/panels/index.d.ts.map +1 -1
- package/dist/panels/index.js +1 -0
- package/dist/panels/insert/catalog.d.ts +21 -1
- package/dist/panels/insert/catalog.d.ts.map +1 -1
- package/dist/panels/insert/catalog.js +85 -3
- package/dist/panels/insert/catalog.order.test.js +106 -1
- package/dist/panels/insert/index.d.ts +1 -0
- package/dist/panels/insert/index.d.ts.map +1 -1
- package/dist/panels/insert/insert-panel.d.ts +14 -4
- package/dist/panels/insert/insert-panel.d.ts.map +1 -1
- package/dist/panels/insert/insert-panel.js +128 -69
- package/dist/panels/insert/insert-panel.test.js +278 -37
- package/dist/panels/insert/target.d.ts +5 -1
- package/dist/panels/insert/target.d.ts.map +1 -1
- package/dist/panels/insert/target.js +11 -1
- package/dist/panels/inspector/author-fields.d.ts +21 -0
- package/dist/panels/inspector/author-fields.d.ts.map +1 -0
- package/dist/panels/inspector/author-fields.js +191 -0
- package/dist/panels/inspector/author-fields.test.d.ts +2 -0
- package/dist/panels/inspector/author-fields.test.d.ts.map +1 -0
- package/dist/panels/inspector/author-fields.test.js +237 -0
- package/dist/panels/inspector/controls/external-link.d.ts +24 -0
- package/dist/panels/inspector/controls/external-link.d.ts.map +1 -0
- package/dist/panels/inspector/controls/external-link.js +43 -0
- package/dist/panels/inspector/controls/external-link.test.d.ts +2 -0
- package/dist/panels/inspector/controls/external-link.test.d.ts.map +1 -0
- package/dist/panels/inspector/controls/external-link.test.js +105 -0
- package/dist/panels/inspector/controls/index.d.ts +1 -0
- package/dist/panels/inspector/controls/index.d.ts.map +1 -1
- package/dist/panels/inspector/controls/index.js +1 -0
- package/dist/panels/inspector/controls/media.d.ts +3 -1
- package/dist/panels/inspector/controls/media.d.ts.map +1 -1
- package/dist/panels/inspector/controls/media.js +8 -3
- package/dist/panels/inspector/controls/rich-text.d.ts.map +1 -1
- package/dist/panels/inspector/controls/rich-text.js +36 -6
- package/dist/panels/inspector/controls/textarea.d.ts +7 -2
- package/dist/panels/inspector/controls/textarea.d.ts.map +1 -1
- package/dist/panels/inspector/controls/textarea.js +37 -2
- package/dist/panels/inspector/default-hint.d.ts +13 -0
- package/dist/panels/inspector/default-hint.d.ts.map +1 -0
- package/dist/panels/inspector/default-hint.js +30 -0
- package/dist/panels/inspector/default-hint.test.d.ts +2 -0
- package/dist/panels/inspector/default-hint.test.d.ts.map +1 -0
- package/dist/panels/inspector/default-hint.test.js +46 -0
- package/dist/panels/inspector/index.d.ts +3 -3
- package/dist/panels/inspector/index.d.ts.map +1 -1
- package/dist/panels/inspector/index.js +2 -2
- package/dist/panels/inspector/inspector.d.ts +20 -2
- package/dist/panels/inspector/inspector.d.ts.map +1 -1
- package/dist/panels/inspector/inspector.js +246 -26
- package/dist/panels/inspector/inspector.test.js +276 -11
- package/dist/panels/inspector/props-panel.d.ts +36 -0
- package/dist/panels/inspector/props-panel.d.ts.map +1 -1
- package/dist/panels/inspector/props-panel.js +99 -17
- package/dist/panels/inspector/props-panel.test.d.ts +2 -0
- package/dist/panels/inspector/props-panel.test.d.ts.map +1 -0
- package/dist/panels/inspector/props-panel.test.js +17 -0
- package/dist/panels/inspector/scrub-label.d.ts +14 -0
- package/dist/panels/inspector/scrub-label.d.ts.map +1 -0
- package/dist/panels/inspector/scrub-label.js +75 -0
- package/dist/panels/inspector/scrub-label.test.d.ts +2 -0
- package/dist/panels/inspector/scrub-label.test.d.ts.map +1 -0
- package/dist/panels/inspector/scrub-label.test.js +132 -0
- package/dist/panels/inspector/styles/background-media.d.ts +28 -0
- package/dist/panels/inspector/styles/background-media.d.ts.map +1 -0
- package/dist/panels/inspector/styles/background-media.js +78 -0
- package/dist/panels/inspector/styles/box-model.d.ts +13 -16
- package/dist/panels/inspector/styles/box-model.d.ts.map +1 -1
- package/dist/panels/inspector/styles/box-model.js +10 -25
- package/dist/panels/inspector/styles/color-input.d.ts +3 -0
- package/dist/panels/inspector/styles/color-input.d.ts.map +1 -0
- package/dist/panels/inspector/styles/color-input.js +72 -0
- package/dist/panels/inspector/styles/gradient-fields.d.ts +9 -0
- package/dist/panels/inspector/styles/gradient-fields.d.ts.map +1 -0
- package/dist/panels/inspector/styles/gradient-fields.js +50 -0
- package/dist/panels/inspector/styles/index.d.ts +2 -0
- package/dist/panels/inspector/styles/index.d.ts.map +1 -1
- package/dist/panels/inspector/styles/index.js +2 -0
- package/dist/panels/inspector/styles/model.d.ts +27 -5
- package/dist/panels/inspector/styles/model.d.ts.map +1 -1
- package/dist/panels/inspector/styles/model.js +101 -3
- package/dist/panels/inspector/styles/motion-rows.d.ts +17 -0
- package/dist/panels/inspector/styles/motion-rows.d.ts.map +1 -0
- package/dist/panels/inspector/styles/motion-rows.js +117 -0
- package/dist/panels/inspector/styles/number-input.d.ts +4 -0
- package/dist/panels/inspector/styles/number-input.d.ts.map +1 -0
- package/dist/panels/inspector/styles/number-input.js +12 -0
- package/dist/panels/inspector/styles/option-label.d.ts +7 -0
- package/dist/panels/inspector/styles/option-label.d.ts.map +1 -0
- package/dist/panels/inspector/styles/option-label.js +9 -0
- package/dist/panels/inspector/styles/property-label.d.ts +9 -0
- package/dist/panels/inspector/styles/property-label.d.ts.map +1 -0
- package/dist/panels/inspector/styles/property-label.js +11 -0
- package/dist/panels/inspector/styles/section-state.d.ts +22 -0
- package/dist/panels/inspector/styles/section-state.d.ts.map +1 -0
- package/dist/panels/inspector/styles/section-state.js +96 -0
- package/dist/panels/inspector/styles/section.d.ts +25 -0
- package/dist/panels/inspector/styles/section.d.ts.map +1 -0
- package/dist/panels/inspector/styles/section.js +43 -0
- package/dist/panels/inspector/styles/sections-context.d.ts +13 -0
- package/dist/panels/inspector/styles/sections-context.d.ts.map +1 -0
- package/dist/panels/inspector/styles/sections-context.js +19 -0
- package/dist/panels/inspector/styles/sections-context.test.d.ts +2 -0
- package/dist/panels/inspector/styles/sections-context.test.d.ts.map +1 -0
- package/dist/panels/inspector/styles/sections-context.test.js +18 -0
- package/dist/panels/inspector/styles/sections-toggle.d.ts +6 -0
- package/dist/panels/inspector/styles/sections-toggle.d.ts.map +1 -0
- package/dist/panels/inspector/styles/sections-toggle.js +18 -0
- package/dist/panels/inspector/styles/segments.d.ts +3 -0
- package/dist/panels/inspector/styles/segments.d.ts.map +1 -1
- package/dist/panels/inspector/styles/segments.js +11 -4
- package/dist/panels/inspector/styles/sides-editor.d.ts +1 -1
- package/dist/panels/inspector/styles/sides-editor.d.ts.map +1 -1
- package/dist/panels/inspector/styles/sides-editor.js +33 -4
- package/dist/panels/inspector/styles/style-inspector.d.ts +3 -1
- package/dist/panels/inspector/styles/style-inspector.d.ts.map +1 -1
- package/dist/panels/inspector/styles/style-inspector.js +610 -42
- package/dist/panels/inspector/styles/style-inspector.test.js +694 -14
- package/dist/panels/inspector/styles/token-picker.d.ts +1 -1
- package/dist/panels/inspector/styles/token-picker.d.ts.map +1 -1
- package/dist/panels/inspector/styles/token-picker.js +10 -3
- package/dist/panels/inspector/styles/widgets.d.ts +116 -0
- package/dist/panels/inspector/styles/widgets.d.ts.map +1 -0
- package/dist/panels/inspector/styles/widgets.js +304 -0
- package/dist/panels/inspector/styles/widgets.test.d.ts +2 -0
- package/dist/panels/inspector/styles/widgets.test.d.ts.map +1 -0
- package/dist/panels/inspector/styles/widgets.test.js +247 -0
- package/dist/panels/inspector/values/value-editor.d.ts +1 -1
- package/dist/panels/inspector/values/value-editor.d.ts.map +1 -1
- package/dist/panels/inspector/values/value-editor.js +9 -8
- package/dist/panels/inspector/values/values.test.js +9 -3
- package/dist/panels/issues/collect.d.ts +2 -0
- package/dist/panels/issues/collect.d.ts.map +1 -1
- package/dist/panels/issues/collect.js +1 -0
- package/dist/panels/issues/index.d.ts +1 -0
- package/dist/panels/issues/index.d.ts.map +1 -1
- package/dist/panels/issues/index.js +1 -0
- package/dist/panels/issues/issues-panel.d.ts +4 -3
- package/dist/panels/issues/issues-panel.d.ts.map +1 -1
- package/dist/panels/issues/issues-panel.js +22 -35
- package/dist/panels/issues/path.d.ts +7 -0
- package/dist/panels/issues/path.d.ts.map +1 -0
- package/dist/panels/issues/path.js +21 -0
- package/dist/panels/layers/flatten.d.ts +16 -2
- package/dist/panels/layers/flatten.d.ts.map +1 -1
- package/dist/panels/layers/flatten.js +48 -4
- package/dist/panels/layers/layers-panel.d.ts +5 -2
- package/dist/panels/layers/layers-panel.d.ts.map +1 -1
- package/dist/panels/layers/layers-panel.js +177 -35
- package/dist/panels/layers/layers-panel.test.js +173 -15
- package/dist/panels/left-panel.d.ts +17 -0
- package/dist/panels/left-panel.d.ts.map +1 -0
- package/dist/panels/left-panel.js +47 -0
- package/dist/panels/left-panel.test.d.ts +2 -0
- package/dist/panels/left-panel.test.d.ts.map +1 -0
- package/dist/panels/left-panel.test.js +77 -0
- package/dist/persistence/persistence.test.js +9 -3
- package/dist/persistence/react.d.ts.map +1 -1
- package/dist/persistence/react.js +2 -2
- package/dist/preview/preview.d.ts +8 -0
- package/dist/preview/preview.d.ts.map +1 -1
- package/dist/preview/preview.js +21 -1
- package/dist/preview/preview.test.js +18 -1
- package/dist/shortcuts/actions.d.ts +13 -2
- package/dist/shortcuts/actions.d.ts.map +1 -1
- package/dist/shortcuts/actions.js +70 -15
- package/dist/shortcuts/help.d.ts +11 -0
- package/dist/shortcuts/help.d.ts.map +1 -0
- package/dist/shortcuts/help.js +77 -0
- package/dist/shortcuts/index.d.ts +5 -2
- package/dist/shortcuts/index.d.ts.map +1 -1
- package/dist/shortcuts/index.js +3 -1
- package/dist/shortcuts/map.d.ts +1 -1
- package/dist/shortcuts/map.d.ts.map +1 -1
- package/dist/shortcuts/map.js +14 -8
- package/dist/shortcuts/navigation.d.ts +13 -0
- package/dist/shortcuts/navigation.d.ts.map +1 -0
- package/dist/shortcuts/navigation.js +48 -0
- package/dist/shortcuts/shortcuts.d.ts +12 -1
- package/dist/shortcuts/shortcuts.d.ts.map +1 -1
- package/dist/shortcuts/shortcuts.js +61 -14
- package/dist/shortcuts/shortcuts.test.js +206 -5
- package/dist/store/create-store.d.ts.map +1 -1
- package/dist/store/create-store.js +19 -1
- package/dist/store/index.d.ts +4 -1
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js +3 -1
- package/dist/store/react.d.ts +4 -0
- package/dist/store/react.d.ts.map +1 -1
- package/dist/store/react.js +7 -0
- package/dist/store/store.test.js +24 -0
- package/dist/store/structure-lock.d.ts +16 -0
- package/dist/store/structure-lock.d.ts.map +1 -0
- package/dist/store/structure-lock.js +43 -0
- package/dist/store/structure-lock.test.d.ts +2 -0
- package/dist/store/structure-lock.test.d.ts.map +1 -0
- package/dist/store/structure-lock.test.js +49 -0
- package/dist/store/types.d.ts +9 -0
- package/dist/store/types.d.ts.map +1 -1
- package/dist/store/view.d.ts +20 -0
- package/dist/store/view.d.ts.map +1 -0
- package/dist/store/view.js +17 -0
- package/dist/store/view.test.d.ts +2 -0
- package/dist/store/view.test.d.ts.map +1 -0
- package/dist/store/view.test.js +103 -0
- package/dist/styles/tokens.test.js +88 -9
- package/dist/styles.css +4112 -586
- package/dist/toolbar/brand.d.ts +2 -2
- package/dist/toolbar/brand.d.ts.map +1 -1
- package/dist/toolbar/brand.js +4 -4
- package/dist/toolbar/breakpoint-control.d.ts +4 -0
- package/dist/toolbar/breakpoint-control.d.ts.map +1 -1
- package/dist/toolbar/breakpoint-control.js +11 -4
- package/dist/toolbar/editable-title.d.ts +4 -1
- package/dist/toolbar/editable-title.d.ts.map +1 -1
- package/dist/toolbar/editable-title.js +2 -2
- package/dist/toolbar/editable-title.test.js +10 -0
- package/dist/toolbar/locale-chip.d.ts +10 -0
- package/dist/toolbar/locale-chip.d.ts.map +1 -0
- package/dist/toolbar/locale-chip.js +27 -0
- package/dist/toolbar/locale-switcher.d.ts.map +1 -1
- package/dist/toolbar/locale-switcher.js +4 -1
- package/dist/toolbar/more-menu.d.ts +26 -4
- package/dist/toolbar/more-menu.d.ts.map +1 -1
- package/dist/toolbar/more-menu.js +60 -13
- package/dist/toolbar/page-chip.d.ts +10 -0
- package/dist/toolbar/page-chip.d.ts.map +1 -0
- package/dist/toolbar/page-chip.js +12 -0
- package/dist/toolbar/page-options-dialog.d.ts +16 -0
- package/dist/toolbar/page-options-dialog.d.ts.map +1 -0
- package/dist/toolbar/page-options-dialog.js +13 -0
- package/dist/toolbar/panel-toggles.d.ts +3 -2
- package/dist/toolbar/panel-toggles.d.ts.map +1 -1
- package/dist/toolbar/panel-toggles.js +9 -4
- package/dist/toolbar/publish-dialog.d.ts +3 -0
- package/dist/toolbar/publish-dialog.d.ts.map +1 -1
- package/dist/toolbar/publish-dialog.js +34 -7
- package/dist/toolbar/publish.test.js +63 -19
- package/dist/toolbar/safe-history.d.ts +3 -0
- package/dist/toolbar/safe-history.d.ts.map +1 -0
- package/dist/toolbar/safe-history.js +5 -0
- package/dist/toolbar/sample-picker.d.ts +24 -4
- package/dist/toolbar/sample-picker.d.ts.map +1 -1
- package/dist/toolbar/sample-picker.js +42 -18
- package/dist/toolbar/toolbar-centre.d.ts +3 -11
- package/dist/toolbar/toolbar-centre.d.ts.map +1 -1
- package/dist/toolbar/toolbar-centre.js +4 -5
- package/dist/toolbar/toolbar-left.d.ts +4 -7
- package/dist/toolbar/toolbar-left.d.ts.map +1 -1
- package/dist/toolbar/toolbar-left.js +13 -11
- package/dist/toolbar/toolbar-right.d.ts +21 -6
- package/dist/toolbar/toolbar-right.d.ts.map +1 -1
- package/dist/toolbar/toolbar-right.js +28 -14
- package/dist/toolbar/toolbar.d.ts +23 -17
- package/dist/toolbar/toolbar.d.ts.map +1 -1
- package/dist/toolbar/toolbar.js +28 -11
- package/dist/toolbar/toolbar.test.js +238 -23
- package/dist/toolbar/use-overflow-level.d.ts +2 -1
- package/dist/toolbar/use-overflow-level.d.ts.map +1 -1
- package/dist/toolbar/use-overflow-level.js +9 -3
- package/dist/toolbar/zoom-menu.d.ts +5 -1
- package/dist/toolbar/zoom-menu.d.ts.map +1 -1
- package/dist/toolbar/zoom-menu.js +3 -2
- package/dist/ui/icon.d.ts +53 -0
- package/dist/ui/icon.d.ts.map +1 -1
- package/dist/ui/icon.js +58 -1
- package/dist/ui/icon.test.js +101 -3
- package/dist/ui/index.d.ts +4 -3
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +3 -2
- package/dist/ui/primitives.d.ts +97 -14
- package/dist/ui/primitives.d.ts.map +1 -1
- package/dist/ui/primitives.js +108 -22
- package/dist/ui/primitives.test.js +204 -3
- package/dist/ui/structure-locked.d.ts +9 -0
- package/dist/ui/structure-locked.d.ts.map +1 -0
- package/dist/ui/structure-locked.js +28 -0
- package/dist/ui/toast.d.ts +3 -1
- package/dist/ui/toast.d.ts.map +1 -1
- package/dist/ui/toast.js +21 -5
- package/dist/ui/toast.test.js +34 -0
- package/package.json +5 -4
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
// @vitest-environment jsdom
|
|
3
|
-
import { createRegistryMeta, createSeededIdGenerator, defaultTheme, getStyleProperty, toManifest, } from '@next-buildr/core';
|
|
4
|
-
import { act } from 'react';
|
|
3
|
+
import { createRegistryMeta, createSeededIdGenerator, defaultTheme, getStyleProperty, p, toManifest, } from '@next-buildr/core';
|
|
4
|
+
import { act, useState } from 'react';
|
|
5
5
|
import { createRoot } from 'react-dom/client';
|
|
6
|
-
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
6
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
7
7
|
import { axe } from 'vitest-axe';
|
|
8
8
|
import * as matchers from 'vitest-axe/matchers';
|
|
9
9
|
import { ManifestProvider } from '../../../app/manifest.js';
|
|
10
10
|
import { MessagesProvider } from '../../../messages/index.js';
|
|
11
11
|
import { createEditorStore, EditorStoreProvider, useEditorState } from '../../../store/index.js';
|
|
12
|
-
import {
|
|
12
|
+
import { SearchField } from '../../../ui/index.js';
|
|
13
|
+
import { boundsOf, checkStyleInput } from './model.js';
|
|
14
|
+
import { StyleSectionsProvider } from './sections-context.js';
|
|
15
|
+
import { SectionsToggle } from './sections-toggle.js';
|
|
13
16
|
import { StyleInspector } from './style-inspector.js';
|
|
14
17
|
expect.extend(matchers);
|
|
15
18
|
globalThis.IS_REACT_ACT_ENVIRONMENT = true;
|
|
@@ -58,6 +61,9 @@ beforeEach(() => {
|
|
|
58
61
|
};
|
|
59
62
|
Element.prototype.scrollIntoView ??= () => { };
|
|
60
63
|
Element.prototype.hasPointerCapture ??= () => false;
|
|
64
|
+
localStorage.clear();
|
|
65
|
+
Element.prototype.setPointerCapture ??= () => { };
|
|
66
|
+
Element.prototype.releasePointerCapture ??= () => { };
|
|
61
67
|
container = document.createElement('div');
|
|
62
68
|
document.body.append(container);
|
|
63
69
|
root = createRoot(container);
|
|
@@ -66,21 +72,38 @@ afterEach(() => {
|
|
|
66
72
|
act(() => root.unmount());
|
|
67
73
|
document.body.innerHTML = '';
|
|
68
74
|
});
|
|
69
|
-
async function mount(breakpoint) {
|
|
75
|
+
async function mount(breakpoint, groups, readOnly = false, props) {
|
|
76
|
+
const custom = groups !== undefined || props !== undefined;
|
|
77
|
+
const activeRegistry = custom
|
|
78
|
+
? createRegistryMeta({
|
|
79
|
+
components: [
|
|
80
|
+
page,
|
|
81
|
+
{ ...box, styles: { groups: groups ?? box.styles.groups }, props: props ?? box.props },
|
|
82
|
+
],
|
|
83
|
+
})
|
|
84
|
+
: registry;
|
|
85
|
+
const activeManifest = custom ? toManifest(activeRegistry) : manifest;
|
|
70
86
|
const store = createEditorStore({
|
|
71
87
|
doc: fixture(),
|
|
72
|
-
registry,
|
|
88
|
+
registry: activeRegistry,
|
|
89
|
+
readOnly,
|
|
73
90
|
generateId: createSeededIdGenerator(3),
|
|
74
91
|
validationDelayMs: null,
|
|
75
92
|
});
|
|
76
93
|
store.select('box0000001');
|
|
77
94
|
const View = () => {
|
|
78
|
-
const node = useEditorState((state) => state.doc.nodes[
|
|
95
|
+
const node = useEditorState((state) => state.anchorId === null ? undefined : state.doc.nodes[state.anchorId]);
|
|
96
|
+
const [query, setQuery] = useState('');
|
|
97
|
+
const [lastId, setLastId] = useState(node?.id);
|
|
98
|
+
if (node?.id !== lastId) {
|
|
99
|
+
setLastId(node?.id);
|
|
100
|
+
setQuery('');
|
|
101
|
+
}
|
|
79
102
|
if (node === undefined)
|
|
80
103
|
return null;
|
|
81
|
-
return _jsx(StyleInspector, { node: node, ...(breakpoint !== undefined ? { breakpoint } : {}) });
|
|
104
|
+
return (_jsxs(StyleSectionsProvider, { children: [_jsx(SectionsToggle, {}), _jsx(SearchField, { className: "bd-inspector-search", label: "Search", clearLabel: "Clear", value: query, onChange: setQuery }), _jsx(StyleInspector, { node: node, query: query, ...(breakpoint !== undefined ? { breakpoint } : {}) })] }));
|
|
82
105
|
};
|
|
83
|
-
await act(async () => root.render(_jsx(MessagesProvider, { locale: "en", children: _jsx(ManifestProvider, { manifest:
|
|
106
|
+
await act(async () => root.render(_jsx(MessagesProvider, { locale: "en", children: _jsx(ManifestProvider, { manifest: activeManifest, children: _jsx(EditorStoreProvider, { store: store, children: _jsx(View, {}) }) }) })));
|
|
84
107
|
return store;
|
|
85
108
|
}
|
|
86
109
|
const styles = (store) => store.getState().doc.nodes['box0000001']?.styles;
|
|
@@ -89,7 +112,42 @@ const type = (element, value) => act(async () => {
|
|
|
89
112
|
Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value')?.set?.call(element, value);
|
|
90
113
|
element.dispatchEvent(new Event('input', { bubbles: true }));
|
|
91
114
|
});
|
|
115
|
+
describe('layout disclosures and alignment (PB-157)', () => {
|
|
116
|
+
it('expands the main-axis alignment on click', async () => {
|
|
117
|
+
await mount(undefined, ['layout']);
|
|
118
|
+
const toggle = container.querySelector('.bd-layout-more__toggle');
|
|
119
|
+
if (toggle === null)
|
|
120
|
+
throw new Error('disclosure missing');
|
|
121
|
+
expect(toggle.getAttribute('aria-expanded')).toBe('false');
|
|
122
|
+
await act(async () => toggle.click());
|
|
123
|
+
expect(toggle.getAttribute('aria-expanded')).toBe('true');
|
|
124
|
+
expect(document.getElementById(toggle.getAttribute('aria-controls') ?? '')?.hidden).toBe(false);
|
|
125
|
+
});
|
|
126
|
+
it('shows the alignment pad when the component prop makes it a flex container', async () => {
|
|
127
|
+
await mount(undefined, ['layout'], false, {
|
|
128
|
+
display: p.select({ options: ['flex', 'grid', 'block'], default: 'flex' }),
|
|
129
|
+
});
|
|
130
|
+
expect(container.querySelector('.bd-alignment-pad')).not.toBeNull();
|
|
131
|
+
await mount(undefined, ['layout'], false, {
|
|
132
|
+
display: p.select({ options: ['flex', 'grid', 'block'], default: 'grid' }),
|
|
133
|
+
});
|
|
134
|
+
expect(container.querySelector('.bd-alignment-pad')).toBeNull();
|
|
135
|
+
});
|
|
136
|
+
it('names keywords in words, not CSS', async () => {
|
|
137
|
+
await mount(undefined, ['layout']);
|
|
138
|
+
expect(container.textContent).not.toMatch(/flex-start|space-between|nowrap/);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
92
141
|
describe('checkStyleInput', () => {
|
|
142
|
+
it('uses the grammar bounds for each scrubbed notation', () => {
|
|
143
|
+
const lineHeight = getStyleProperty('typography', 'lineHeight');
|
|
144
|
+
const columns = getStyleProperty('layout', 'columns');
|
|
145
|
+
if (lineHeight === undefined || columns === undefined)
|
|
146
|
+
throw new Error('property missing');
|
|
147
|
+
expect(boundsOf(lineHeight, '1')).toEqual({ min: 0.5, max: 5 });
|
|
148
|
+
expect(boundsOf(lineHeight, '24px')).toEqual({ min: 0 });
|
|
149
|
+
expect(boundsOf(columns, '2')).toEqual({ min: 1, max: 12 });
|
|
150
|
+
});
|
|
93
151
|
const gap = getStyleProperty('layout', 'gap');
|
|
94
152
|
const opacity = getStyleProperty('effects', 'opacity');
|
|
95
153
|
it('accepts tokens the theme has and lengths', () => {
|
|
@@ -119,6 +177,27 @@ describe('StyleInspector', () => {
|
|
|
119
177
|
const groups = [...container.querySelectorAll('[data-group]')].map((g) => g.getAttribute('data-group'));
|
|
120
178
|
expect(groups).toEqual(['layout', 'spacing', 'visibility']);
|
|
121
179
|
});
|
|
180
|
+
it('shows Typography and Colours, with a hinted text colour, when the component allows typography', async () => {
|
|
181
|
+
await mount(undefined, ['spacing', 'typography', 'effects']);
|
|
182
|
+
const groups = [...container.querySelectorAll('[data-group]')].map((g) => g.getAttribute('data-group'));
|
|
183
|
+
expect(groups).toEqual(['spacing', 'typography', 'colors', 'shadow', 'effects']);
|
|
184
|
+
const color = container.querySelector('[data-path="typography.color"] input.bd-wcolor__hex');
|
|
185
|
+
expect(color?.getAttribute('placeholder')).toBe(defaultTheme.tokens.color['text']);
|
|
186
|
+
});
|
|
187
|
+
it('labels every effect control and folds the rarely used ones away', async () => {
|
|
188
|
+
await mount(undefined, ['effects']);
|
|
189
|
+
const effects = container.querySelector('[data-group="effects"]');
|
|
190
|
+
const toggles = [...effects.querySelectorAll('.bd-layout-more__toggle')];
|
|
191
|
+
expect(toggles.length).toBeGreaterThanOrEqual(3);
|
|
192
|
+
expect(toggles.every((toggle) => toggle.getAttribute('aria-expanded') === 'false')).toBe(true);
|
|
193
|
+
for (const control of effects.querySelectorAll('input, select')) {
|
|
194
|
+
if (control.closest('[hidden]') !== null)
|
|
195
|
+
continue;
|
|
196
|
+
const named = control.getAttribute('aria-label') !== null ||
|
|
197
|
+
(control.id !== '' && effects.querySelector(`label[for="${control.id}"]`) !== null);
|
|
198
|
+
expect(named, control.outerHTML).toBe(true);
|
|
199
|
+
}
|
|
200
|
+
});
|
|
122
201
|
it('writes to desktop with no breakpoint', async () => {
|
|
123
202
|
const store = await mount();
|
|
124
203
|
await type(inputAt('layout.gap'), '2rem');
|
|
@@ -135,7 +214,7 @@ describe('StyleInspector', () => {
|
|
|
135
214
|
const field = container.querySelector('[data-path="layout.gap"]');
|
|
136
215
|
expect(field.textContent).toContain('from desktop');
|
|
137
216
|
const pressed = container.querySelector('[data-style-prop="layout.display"] [aria-pressed=true]');
|
|
138
|
-
expect(pressed?.
|
|
217
|
+
expect(pressed?.getAttribute('aria-label')).toBe('Grid');
|
|
139
218
|
});
|
|
140
219
|
it('does not save a value outside the grammar and says why', async () => {
|
|
141
220
|
const store = await mount();
|
|
@@ -223,11 +302,11 @@ describe('style inspector controls (PB-128)', () => {
|
|
|
223
302
|
});
|
|
224
303
|
it('writes the same command as typing when a segment is pressed, and unsets on a second press', async () => {
|
|
225
304
|
const store = await mount();
|
|
226
|
-
await act(async () => buttonNamed('
|
|
305
|
+
await act(async () => buttonNamed('Vertical').click());
|
|
227
306
|
expect(styles(store)?.base?.layout?.direction).toBe('column');
|
|
228
307
|
const group = container.querySelector('[data-style-prop="layout.direction"] fieldset');
|
|
229
|
-
expect(group?.querySelector('[aria-pressed=true]')?.getAttribute('aria-label')).toBe('
|
|
230
|
-
await act(async () => buttonNamed('
|
|
308
|
+
expect(group?.querySelector('[aria-pressed=true]')?.getAttribute('aria-label')).toBe('Vertical');
|
|
309
|
+
await act(async () => buttonNamed('Vertical').click());
|
|
231
310
|
expect(styles(store)?.base?.layout?.direction).toBeUndefined();
|
|
232
311
|
});
|
|
233
312
|
it('keeps keywords without a segment reachable through the other-values menu', async () => {
|
|
@@ -263,3 +342,604 @@ describe('style inspector controls (PB-128)', () => {
|
|
|
263
342
|
expect(await axe(container)).toHaveNoViolations();
|
|
264
343
|
});
|
|
265
344
|
});
|
|
345
|
+
describe('template v2 inspector controls', () => {
|
|
346
|
+
it('remembers a collapsed unused style section after unmount, without changing the document', async () => {
|
|
347
|
+
const store = await mount();
|
|
348
|
+
const initial = store.getState().doc;
|
|
349
|
+
const toggle = container.querySelector('[data-group="spacing"] .bd-sec__head');
|
|
350
|
+
expect(toggle?.getAttribute('aria-expanded')).toBe('true');
|
|
351
|
+
await act(async () => toggle?.click());
|
|
352
|
+
expect(toggle?.getAttribute('aria-expanded')).toBe('false');
|
|
353
|
+
expect(store.getState().doc).toBe(initial);
|
|
354
|
+
await act(async () => root.render(null));
|
|
355
|
+
await mount();
|
|
356
|
+
expect(container
|
|
357
|
+
.querySelector('[data-group="spacing"] .bd-sec__head')
|
|
358
|
+
?.getAttribute('aria-expanded')).toBe('false');
|
|
359
|
+
});
|
|
360
|
+
it('ignores malformed stored preferences and searches localized property labels', async () => {
|
|
361
|
+
localStorage.setItem('buildr.editor.inspector.styles', '{"layout":"invalid"}');
|
|
362
|
+
const store = await mount();
|
|
363
|
+
const initial = store.getState().doc;
|
|
364
|
+
const search = container.querySelector('.bd-inspector-search input');
|
|
365
|
+
if (search === null)
|
|
366
|
+
throw new Error('search missing');
|
|
367
|
+
await type(search, 'gap');
|
|
368
|
+
expect(container.querySelector('[data-style-prop="layout.gap"]')).not.toBeNull();
|
|
369
|
+
expect(container.querySelector('[data-style-prop="layout.display"]')).toBeNull();
|
|
370
|
+
expect(container.querySelector('[data-group="spacing"]')).toBeNull();
|
|
371
|
+
await type(search, 'no such setting');
|
|
372
|
+
expect(container.textContent).toContain('No settings “no such setting”');
|
|
373
|
+
expect(store.getState().doc).toBe(initial);
|
|
374
|
+
});
|
|
375
|
+
it('uses two existing style commands for the flex pad, one undo step, and redo', async () => {
|
|
376
|
+
const store = await mount();
|
|
377
|
+
await act(async () => buttonNamed('Flex').click());
|
|
378
|
+
const dispatch = vi.spyOn(store, 'dispatchBatch');
|
|
379
|
+
const pad = container.querySelector('[aria-label="Content alignment"]');
|
|
380
|
+
const pick = pad?.querySelector('[aria-label="bottom right"]');
|
|
381
|
+
await act(async () => pick?.click());
|
|
382
|
+
expect(dispatch).toHaveBeenCalledWith([
|
|
383
|
+
{
|
|
384
|
+
type: 'node.setStyle',
|
|
385
|
+
payload: {
|
|
386
|
+
id: 'box0000001',
|
|
387
|
+
layer: {},
|
|
388
|
+
group: 'layout',
|
|
389
|
+
property: 'justify',
|
|
390
|
+
value: 'flex-end',
|
|
391
|
+
},
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
type: 'node.setStyle',
|
|
395
|
+
payload: {
|
|
396
|
+
id: 'box0000001',
|
|
397
|
+
layer: {},
|
|
398
|
+
group: 'layout',
|
|
399
|
+
property: 'align',
|
|
400
|
+
value: 'flex-end',
|
|
401
|
+
},
|
|
402
|
+
},
|
|
403
|
+
], { label: 'Content alignment' });
|
|
404
|
+
expect(styles(store)?.base?.layout).toMatchObject({ justify: 'flex-end', align: 'flex-end' });
|
|
405
|
+
await act(async () => {
|
|
406
|
+
store.undo();
|
|
407
|
+
});
|
|
408
|
+
expect(styles(store)?.base?.layout?.justify).toBeUndefined();
|
|
409
|
+
expect(styles(store)?.base?.layout?.align).toBeUndefined();
|
|
410
|
+
expect(styles(store)?.base?.layout?.display).toBe('flex');
|
|
411
|
+
await act(async () => {
|
|
412
|
+
store.redo();
|
|
413
|
+
});
|
|
414
|
+
expect(styles(store)?.base?.layout?.justify).toBe('flex-end');
|
|
415
|
+
});
|
|
416
|
+
it('scrubs validated lengths through node.setStyle and rejects negative padding', async () => {
|
|
417
|
+
const store = await mount();
|
|
418
|
+
await type(inputAt('layout.gap'), '10px');
|
|
419
|
+
const dispatch = vi.spyOn(store, 'dispatch');
|
|
420
|
+
const label = container.querySelector('[data-style-prop="layout.gap"] label.bd-scrub-label');
|
|
421
|
+
if (label === null)
|
|
422
|
+
throw new Error('scrub label missing');
|
|
423
|
+
await act(async () => {
|
|
424
|
+
label.dispatchEvent(new MouseEvent('pointerdown', { bubbles: true, button: 0, clientX: 10 }));
|
|
425
|
+
label.dispatchEvent(new MouseEvent('pointermove', { bubbles: true, clientX: 19 }));
|
|
426
|
+
label.dispatchEvent(new MouseEvent('pointerup', { bubbles: true }));
|
|
427
|
+
});
|
|
428
|
+
expect(dispatch).toHaveBeenCalledWith({
|
|
429
|
+
type: 'node.setStyle',
|
|
430
|
+
payload: { id: 'box0000001', layer: {}, group: 'layout', property: 'gap', value: '13px' },
|
|
431
|
+
});
|
|
432
|
+
const before = styles(store)?.base?.spacing;
|
|
433
|
+
await type(inputAt('spacing.padding.top'), '-5px');
|
|
434
|
+
expect(styles(store)?.base?.spacing).toEqual(before);
|
|
435
|
+
});
|
|
436
|
+
it('writes linked and unlinked corners and borders through commands at the active device', async () => {
|
|
437
|
+
const store = await mount('mobile', ['border']);
|
|
438
|
+
const dispatch = vi.spyOn(store, 'dispatch');
|
|
439
|
+
await type(inputAt('border.radius.topLeft'), '8px');
|
|
440
|
+
expect(styles(store)?.bp?.['mobile']?.border?.radius).toEqual({
|
|
441
|
+
topLeft: '8px',
|
|
442
|
+
topRight: '8px',
|
|
443
|
+
bottomRight: '8px',
|
|
444
|
+
bottomLeft: '8px',
|
|
445
|
+
});
|
|
446
|
+
await act(async () => {
|
|
447
|
+
store.undo();
|
|
448
|
+
});
|
|
449
|
+
expect(styles(store)?.bp?.['mobile']?.border?.radius).toBeUndefined();
|
|
450
|
+
await act(async () => {
|
|
451
|
+
store.redo();
|
|
452
|
+
});
|
|
453
|
+
expect(styles(store)?.bp?.['mobile']?.border?.radius?.bottomRight).toBe('8px');
|
|
454
|
+
await act(async () => buttonNamed('Border: Link sides').click());
|
|
455
|
+
await type(inputAt('border.width.left'), '2px');
|
|
456
|
+
expect(styles(store)?.bp?.['mobile']?.border?.width).toEqual({ left: '2px' });
|
|
457
|
+
expect(dispatch).toHaveBeenCalledWith({
|
|
458
|
+
type: 'node.setStyle',
|
|
459
|
+
payload: {
|
|
460
|
+
id: 'box0000001',
|
|
461
|
+
layer: { bp: 'mobile' },
|
|
462
|
+
group: 'border',
|
|
463
|
+
property: 'width',
|
|
464
|
+
side: 'left',
|
|
465
|
+
value: '2px',
|
|
466
|
+
},
|
|
467
|
+
});
|
|
468
|
+
expect(container
|
|
469
|
+
.querySelector('[data-style-prop="border.width"] .bd-device-indicator')
|
|
470
|
+
?.getAttribute('data-override')).toBe('true');
|
|
471
|
+
await act(async () => buttonNamed('Restore default: Border').click());
|
|
472
|
+
expect(styles(store)?.bp?.['mobile']?.border?.width).toBeUndefined();
|
|
473
|
+
});
|
|
474
|
+
it('uses only theme shadow tokens and validates colour edits before dispatch', async () => {
|
|
475
|
+
const store = await mount('mobile', ['effects', 'background']);
|
|
476
|
+
const dispatch = vi.spyOn(store, 'dispatch');
|
|
477
|
+
const preset = container.querySelector('.bd-shadow-presets button:nth-child(2)');
|
|
478
|
+
await act(async () => preset?.click());
|
|
479
|
+
const token = `$shadow.${Object.keys(defaultTheme.tokens.shadow)[0]}`;
|
|
480
|
+
expect(styles(store)?.bp?.['mobile']?.effects?.shadow).toBe(token);
|
|
481
|
+
expect(dispatch).toHaveBeenCalledWith({
|
|
482
|
+
type: 'node.setStyle',
|
|
483
|
+
payload: {
|
|
484
|
+
id: 'box0000001',
|
|
485
|
+
layer: { bp: 'mobile' },
|
|
486
|
+
group: 'effects',
|
|
487
|
+
property: 'shadow',
|
|
488
|
+
value: token,
|
|
489
|
+
},
|
|
490
|
+
});
|
|
491
|
+
const color = container.querySelector('[data-style-prop="background.color"] .bd-color-trigger');
|
|
492
|
+
await act(async () => color?.click());
|
|
493
|
+
const input = document.querySelector('.bd-color-hex input');
|
|
494
|
+
if (input === null)
|
|
495
|
+
throw new Error('colour field missing');
|
|
496
|
+
dispatch.mockClear();
|
|
497
|
+
await type(input, 'url(https://example.com)');
|
|
498
|
+
expect(dispatch).not.toHaveBeenCalled();
|
|
499
|
+
await type(input, '#12345680');
|
|
500
|
+
expect(styles(store)?.bp?.['mobile']?.background?.color).toBe('#12345680');
|
|
501
|
+
expect(dispatch).toHaveBeenCalledWith({
|
|
502
|
+
type: 'node.setStyle',
|
|
503
|
+
payload: {
|
|
504
|
+
id: 'box0000001',
|
|
505
|
+
layer: { bp: 'mobile' },
|
|
506
|
+
group: 'background',
|
|
507
|
+
property: 'color',
|
|
508
|
+
value: '#12345680',
|
|
509
|
+
},
|
|
510
|
+
});
|
|
511
|
+
await act(async () => {
|
|
512
|
+
store.undo();
|
|
513
|
+
});
|
|
514
|
+
expect(styles(store)?.bp?.['mobile']?.background?.color).toBeUndefined();
|
|
515
|
+
});
|
|
516
|
+
it('keeps the hue slider controlled and undoes a whole drag in one step', async () => {
|
|
517
|
+
const store = await mount('mobile', ['background']);
|
|
518
|
+
const trigger = container.querySelector('[data-style-prop="background.color"] .bd-color-trigger');
|
|
519
|
+
await act(async () => trigger?.click());
|
|
520
|
+
const hue = document.querySelector('input.bd-style-hue');
|
|
521
|
+
if (hue === null)
|
|
522
|
+
throw new Error('hue slider missing');
|
|
523
|
+
await type(hue, '40');
|
|
524
|
+
await type(hue, '120');
|
|
525
|
+
await type(hue, '200');
|
|
526
|
+
expect(hue.value).toBe('200');
|
|
527
|
+
expect(styles(store)?.bp?.['mobile']?.background?.color).toBe('hsl(200 100% 50%)');
|
|
528
|
+
await act(async () => {
|
|
529
|
+
store.undo();
|
|
530
|
+
});
|
|
531
|
+
expect(styles(store)?.bp?.['mobile']?.background?.color).toBeUndefined();
|
|
532
|
+
});
|
|
533
|
+
it('does not allow writes to a readonly document and exposes accessible supported widgets', async () => {
|
|
534
|
+
await mount('mobile', ['effects', 'border', 'background'], true);
|
|
535
|
+
for (const toggle of container.querySelectorAll('.bd-sec__head[aria-expanded=false]')) {
|
|
536
|
+
await act(async () => toggle.click());
|
|
537
|
+
}
|
|
538
|
+
for (const control of container.querySelectorAll('[data-style-prop] input, [data-style-prop] button, [data-style-prop] select')) {
|
|
539
|
+
expect(control.disabled).toBe(true);
|
|
540
|
+
}
|
|
541
|
+
expect(await axe(container)).toHaveNoViolations();
|
|
542
|
+
});
|
|
543
|
+
});
|
|
544
|
+
describe('template gradient and image position widgets', () => {
|
|
545
|
+
it('writes a linear gradient and image position through validated style commands', async () => {
|
|
546
|
+
const store = await mount('mobile', ['background']);
|
|
547
|
+
await act(async () => [...container.querySelectorAll('button')]
|
|
548
|
+
.find((button) => button.textContent === 'Gradient')
|
|
549
|
+
?.click());
|
|
550
|
+
const dispatch = vi.spyOn(store, 'dispatch');
|
|
551
|
+
const angle = container.querySelector('.bd-gradient-angle input:not([type=range])');
|
|
552
|
+
if (angle === null)
|
|
553
|
+
throw new Error('gradient angle missing');
|
|
554
|
+
await type(angle, '90');
|
|
555
|
+
const names = Object.keys(defaultTheme.tokens.color);
|
|
556
|
+
const gradient = `linear-gradient(90deg, $color.${names[0]}, $color.${names[1] ?? names[0]})`;
|
|
557
|
+
expect(styles(store)?.bp?.['mobile']?.background?.gradient).toBe(gradient);
|
|
558
|
+
expect(dispatch).toHaveBeenCalledWith({
|
|
559
|
+
type: 'node.setStyle',
|
|
560
|
+
payload: {
|
|
561
|
+
id: 'box0000001',
|
|
562
|
+
layer: { bp: 'mobile' },
|
|
563
|
+
group: 'background',
|
|
564
|
+
property: 'gradient',
|
|
565
|
+
value: gradient,
|
|
566
|
+
},
|
|
567
|
+
});
|
|
568
|
+
const pad = container.querySelector('[data-style-prop="background.imagePosition"] .bd-alignment-pad');
|
|
569
|
+
await act(async () => pad?.querySelector('[aria-label="top left"]')?.click());
|
|
570
|
+
expect(styles(store)?.bp?.['mobile']?.background?.imagePosition).toBe('top left');
|
|
571
|
+
await act(async () => {
|
|
572
|
+
store.undo();
|
|
573
|
+
});
|
|
574
|
+
expect(styles(store)?.bp?.['mobile']?.background?.imagePosition).toBeUndefined();
|
|
575
|
+
expect(styles(store)?.bp?.['mobile']?.background?.gradient).toBe(gradient);
|
|
576
|
+
await act(async () => {
|
|
577
|
+
store.redo();
|
|
578
|
+
});
|
|
579
|
+
expect(styles(store)?.bp?.['mobile']?.background?.imagePosition).toBe('top left');
|
|
580
|
+
});
|
|
581
|
+
it('keeps a gradient with more than two stops editable without silently simplifying it', async () => {
|
|
582
|
+
const store = await mount(undefined, ['background']);
|
|
583
|
+
await act(async () => [...container.querySelectorAll('button')]
|
|
584
|
+
.find((button) => button.textContent === 'Gradient')
|
|
585
|
+
?.click());
|
|
586
|
+
const gradient = 'linear-gradient(180deg, #123456, #456789, #abcdef)';
|
|
587
|
+
await type(inputAt('background.gradient'), gradient);
|
|
588
|
+
expect(styles(store)?.base?.background?.gradient).toBe(gradient);
|
|
589
|
+
expect(container.querySelector('.bd-gradient-fields')).toBeNull();
|
|
590
|
+
});
|
|
591
|
+
});
|
|
592
|
+
describe('template width modes', () => {
|
|
593
|
+
it('writes existing width values for automatic and full width, while Custom focuses the input', async () => {
|
|
594
|
+
const store = await mount(undefined, ['size']);
|
|
595
|
+
const mode = container.querySelector('[aria-label="Width mode"]');
|
|
596
|
+
const pick = async (value) => act(async () => {
|
|
597
|
+
[...(mode?.querySelectorAll('button') ?? [])]
|
|
598
|
+
.find((button) => button.textContent === value)
|
|
599
|
+
?.click();
|
|
600
|
+
});
|
|
601
|
+
await pick('Full');
|
|
602
|
+
expect(styles(store)?.base?.size?.width).toBe('100%');
|
|
603
|
+
await pick('Auto');
|
|
604
|
+
expect(styles(store)?.base?.size?.width).toBe('auto');
|
|
605
|
+
expect([...(mode?.querySelectorAll('button') ?? [])]
|
|
606
|
+
.find((button) => button.textContent === 'Auto')
|
|
607
|
+
?.getAttribute('aria-pressed')).toBe('true');
|
|
608
|
+
await type(inputAt('size.width'), 'fit-content');
|
|
609
|
+
expect([...(mode?.querySelectorAll('button') ?? [])]
|
|
610
|
+
.find((button) => button.textContent === 'Auto')
|
|
611
|
+
?.getAttribute('aria-pressed')).toBe('false');
|
|
612
|
+
await pick('Custom');
|
|
613
|
+
expect(document.activeElement).toBe(inputAt('size.width'));
|
|
614
|
+
await type(inputAt('size.width'), '340px');
|
|
615
|
+
expect(styles(store)?.base?.size?.width).toBe('340px');
|
|
616
|
+
});
|
|
617
|
+
});
|
|
618
|
+
describe('template hover styles', () => {
|
|
619
|
+
it('resets state and search on selection, restores accordion preferences, and opens used sections', async () => {
|
|
620
|
+
const store = await mount(undefined, [
|
|
621
|
+
'layout',
|
|
622
|
+
'background',
|
|
623
|
+
'effects',
|
|
624
|
+
'spacing',
|
|
625
|
+
'visibility',
|
|
626
|
+
]);
|
|
627
|
+
const sectionButton = (name) => container.querySelector(`[data-group="${name}"] .bd-sec__head`);
|
|
628
|
+
await act(async () => sectionButton('layout')?.click());
|
|
629
|
+
await act(async () => sectionButton('spacing')?.click());
|
|
630
|
+
await act(async () => {
|
|
631
|
+
store.dispatch({
|
|
632
|
+
type: 'node.setStyle',
|
|
633
|
+
payload: { id: 'root', layer: {}, group: 'layout', property: 'display', value: 'flex' },
|
|
634
|
+
});
|
|
635
|
+
});
|
|
636
|
+
await act(async () => buttonNamed('Hover').click());
|
|
637
|
+
await type(container.querySelector('.bd-inspector-search input'), 'color');
|
|
638
|
+
await act(async () => store.select('root'));
|
|
639
|
+
expect(container.querySelector('.bd-styles')?.getAttribute('data-layer')).toBe('base');
|
|
640
|
+
expect(container.querySelector('.bd-inspector-search input')?.value).toBe('');
|
|
641
|
+
expect(sectionButton('layout')?.getAttribute('aria-expanded')).toBe('true');
|
|
642
|
+
expect(sectionButton('spacing')?.getAttribute('aria-expanded')).toBe('false');
|
|
643
|
+
await act(async () => sectionButton('visibility')?.click());
|
|
644
|
+
expect(sectionButton('visibility')?.getAttribute('aria-expanded')).toBe('true');
|
|
645
|
+
await act(async () => store.select('box0000001'));
|
|
646
|
+
expect(sectionButton('visibility')?.getAttribute('aria-expanded')).toBe('true');
|
|
647
|
+
});
|
|
648
|
+
it('translates the source of values in every pseudo-state', async () => {
|
|
649
|
+
await mount(undefined, ['effects']);
|
|
650
|
+
for (const label of ['Hover', 'Focus', 'Pressed']) {
|
|
651
|
+
await act(async () => buttonNamed(label).click());
|
|
652
|
+
const select = container.querySelector('[data-style-prop="effects.cursor"] select');
|
|
653
|
+
if (select === null)
|
|
654
|
+
throw new Error('cursor select missing');
|
|
655
|
+
await act(async () => {
|
|
656
|
+
select.value = 'pointer';
|
|
657
|
+
select.dispatchEvent(new Event('change', { bubbles: true }));
|
|
658
|
+
});
|
|
659
|
+
expect(select.textContent).toContain(`Pointer (${label})`);
|
|
660
|
+
expect(select.textContent).not.toContain('state:');
|
|
661
|
+
}
|
|
662
|
+
});
|
|
663
|
+
it('stores the selected palette token for colors and gradient stops', async () => {
|
|
664
|
+
const store = await mount(undefined, ['background']);
|
|
665
|
+
const name = Object.keys(defaultTheme.tokens.color)[0];
|
|
666
|
+
const token = `$color.${name}`;
|
|
667
|
+
const trigger = container.querySelector('[data-style-prop="background.color"] .bd-color-trigger');
|
|
668
|
+
await act(async () => trigger?.click());
|
|
669
|
+
// The newest popover: the previous one may still be closing.
|
|
670
|
+
const pick = () => [
|
|
671
|
+
...document.querySelectorAll(`.bd-color-palette button[aria-label^="${name}:"]`),
|
|
672
|
+
].at(-1);
|
|
673
|
+
await act(async () => pick()?.click());
|
|
674
|
+
expect(styles(store)?.base?.background?.color).toBe(token);
|
|
675
|
+
await act(async () => document
|
|
676
|
+
.querySelector('.bd-color-popover')
|
|
677
|
+
?.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true })));
|
|
678
|
+
await act(async () => new Promise((resolve) => setTimeout(resolve, 50)));
|
|
679
|
+
await act(async () => [...container.querySelectorAll('button')]
|
|
680
|
+
.find((button) => button.textContent === 'Gradient')
|
|
681
|
+
?.click());
|
|
682
|
+
const stops = container.querySelectorAll('.bd-gradient-stop .bd-color-trigger');
|
|
683
|
+
expect(stops).toHaveLength(2);
|
|
684
|
+
await act(async () => stops[1]?.click());
|
|
685
|
+
await act(async () => pick()?.click());
|
|
686
|
+
expect(styles(store)?.base?.background?.gradient).toBe(`linear-gradient(180deg, ${token}, ${token})`);
|
|
687
|
+
});
|
|
688
|
+
it('edits allowed visual properties through existing state-layer commands, with undo and redo', async () => {
|
|
689
|
+
const store = await mount('mobile', ['layout', 'effects', 'background']);
|
|
690
|
+
const dispatch = vi.spyOn(store, 'dispatch');
|
|
691
|
+
await act(async () => buttonNamed('Hover').click());
|
|
692
|
+
expect(container.querySelector('[data-group="layout"]')).toBeNull();
|
|
693
|
+
expect(container.querySelector('[data-style-prop="effects.cursor"]')).not.toBeNull();
|
|
694
|
+
await type(inputAt('background.color'), '#123456');
|
|
695
|
+
expect(dispatch).toHaveBeenCalledWith({
|
|
696
|
+
type: 'node.setStyle',
|
|
697
|
+
payload: {
|
|
698
|
+
id: 'box0000001',
|
|
699
|
+
layer: { state: 'hover' },
|
|
700
|
+
group: 'background',
|
|
701
|
+
property: 'color',
|
|
702
|
+
value: '#123456',
|
|
703
|
+
},
|
|
704
|
+
});
|
|
705
|
+
expect(styles(store)?.state?.hover?.background?.color).toBe('#123456');
|
|
706
|
+
expect(styles(store)?.bp?.['mobile']?.background?.color).toBeUndefined();
|
|
707
|
+
await act(async () => {
|
|
708
|
+
store.undo();
|
|
709
|
+
});
|
|
710
|
+
expect(styles(store)?.state?.hover?.background?.color).toBeUndefined();
|
|
711
|
+
await act(async () => {
|
|
712
|
+
store.redo();
|
|
713
|
+
});
|
|
714
|
+
expect(styles(store)?.state?.hover?.background?.color).toBe('#123456');
|
|
715
|
+
await act(async () => buttonNamed('Restore default: Color').click());
|
|
716
|
+
expect(styles(store)?.state?.hover?.background?.color).toBeUndefined();
|
|
717
|
+
});
|
|
718
|
+
});
|
|
719
|
+
describe('style sections chrome (PB-157 WP5a)', () => {
|
|
720
|
+
const head = (name) => container.querySelector(`[data-group="${name}"] .bd-sec__head`);
|
|
721
|
+
it('highlights the matched label text and shows a no-results state', async () => {
|
|
722
|
+
await mount();
|
|
723
|
+
const search = container.querySelector('.bd-inspector-search input');
|
|
724
|
+
if (search === null)
|
|
725
|
+
throw new Error('search missing');
|
|
726
|
+
await type(search, 'GAP');
|
|
727
|
+
expect(container.querySelector('[data-style-prop="layout.gap"] .bd-field-label mark')?.textContent).toBe('Gap');
|
|
728
|
+
await type(search, 'zzz');
|
|
729
|
+
expect(container.querySelector('.bd-empty strong')?.textContent).toContain('zzz');
|
|
730
|
+
expect(container.querySelector('[data-group]')).toBeNull();
|
|
731
|
+
});
|
|
732
|
+
it('keeps the remembered state when storage is corrupt or refuses writes', async () => {
|
|
733
|
+
localStorage.setItem('buildr.editor.inspector.styles', 'not json {');
|
|
734
|
+
await mount();
|
|
735
|
+
expect(head('spacing')?.getAttribute('aria-expanded')).toBe('true');
|
|
736
|
+
expect(head('visibility')?.getAttribute('aria-expanded')).toBe('false');
|
|
737
|
+
const set = vi.spyOn(Storage.prototype, 'setItem').mockImplementation(() => {
|
|
738
|
+
throw new Error('full');
|
|
739
|
+
});
|
|
740
|
+
await act(async () => head('spacing')?.click());
|
|
741
|
+
expect(head('spacing')?.getAttribute('aria-expanded')).toBe('false');
|
|
742
|
+
set.mockRestore();
|
|
743
|
+
});
|
|
744
|
+
it('counts the values set only at the breakpoint being edited', async () => {
|
|
745
|
+
await mount('tablet');
|
|
746
|
+
const chip = container.querySelector('[data-group="layout"] .bd-ovr');
|
|
747
|
+
expect(chip?.textContent).toBe('1');
|
|
748
|
+
expect(chip?.getAttribute('aria-label')).toContain('tablet');
|
|
749
|
+
expect(container.querySelector('[data-group="spacing"] .bd-ovr')).toBeNull();
|
|
750
|
+
expect(container.querySelector('.bd-note--ovr')?.textContent).toContain('tablet');
|
|
751
|
+
});
|
|
752
|
+
it('resets a section with unset commands only, as one undo step', async () => {
|
|
753
|
+
const store = await mount('tablet');
|
|
754
|
+
await act(async () => {
|
|
755
|
+
store.dispatch({
|
|
756
|
+
type: 'node.setStyle',
|
|
757
|
+
payload: {
|
|
758
|
+
id: 'box0000001',
|
|
759
|
+
layer: { bp: 'tablet' },
|
|
760
|
+
group: 'layout',
|
|
761
|
+
property: 'gap',
|
|
762
|
+
value: '8px',
|
|
763
|
+
},
|
|
764
|
+
});
|
|
765
|
+
});
|
|
766
|
+
expect(container.querySelector('[data-group="layout"] .bd-ovr')?.textContent).toBe('2');
|
|
767
|
+
const dispatch = vi.spyOn(store, 'dispatch');
|
|
768
|
+
const reset = container.querySelector('[data-group="layout"] .bd-sec__foot button');
|
|
769
|
+
await act(async () => reset?.click());
|
|
770
|
+
const types = dispatch.mock.calls.map(([command]) => command.type);
|
|
771
|
+
expect(types.length).toBe(2);
|
|
772
|
+
expect(new Set(types)).toEqual(new Set(['node.unsetStyle']));
|
|
773
|
+
expect(styles(store)?.bp?.['tablet']?.layout).toBeUndefined();
|
|
774
|
+
expect(styles(store)?.base?.layout?.gap).toBe('$space.4');
|
|
775
|
+
expect(container.querySelector('[data-group="layout"] .bd-sec__foot')).toBeNull();
|
|
776
|
+
await act(async () => {
|
|
777
|
+
store.undo();
|
|
778
|
+
});
|
|
779
|
+
expect(styles(store)?.bp?.['tablet']?.layout?.display).toBe('grid');
|
|
780
|
+
expect(styles(store)?.bp?.['tablet']?.layout?.gap).toBe('8px');
|
|
781
|
+
});
|
|
782
|
+
it('expands and collapses every section from SectionsToggle', async () => {
|
|
783
|
+
const store = await mount(undefined, ['layout', 'spacing', 'visibility']);
|
|
784
|
+
const initial = store.getState().doc;
|
|
785
|
+
await act(async () => buttonNamed('Expand all sections').click());
|
|
786
|
+
for (const name of ['layout', 'spacing', 'visibility'])
|
|
787
|
+
expect(head(name)?.getAttribute('aria-expanded')).toBe('true');
|
|
788
|
+
expect(JSON.parse(localStorage.getItem('buildr.editor.inspector.styles') ?? '{}')).toEqual({
|
|
789
|
+
layout: true,
|
|
790
|
+
spacing: true,
|
|
791
|
+
visibility: true,
|
|
792
|
+
});
|
|
793
|
+
await act(async () => buttonNamed('Collapse all sections').click());
|
|
794
|
+
for (const name of ['layout', 'spacing', 'visibility'])
|
|
795
|
+
expect(head(name)?.getAttribute('aria-expanded')).toBe('false');
|
|
796
|
+
expect(store.getState().doc).toBe(initial);
|
|
797
|
+
});
|
|
798
|
+
it('hides min and max dimensions behind a disclosure', async () => {
|
|
799
|
+
await mount(undefined, ['size']);
|
|
800
|
+
expect(container.querySelector('[data-style-prop="size.minWidth"]')).toBeNull();
|
|
801
|
+
await act(async () => buttonNamed('Min. and max. dimensions').click());
|
|
802
|
+
expect(container.querySelector('[data-style-prop="size.minWidth"]')).not.toBeNull();
|
|
803
|
+
});
|
|
804
|
+
});
|
|
805
|
+
describe('motion section (ADR-027)', () => {
|
|
806
|
+
const presetButton = (name) => [...container.querySelectorAll('.bd-motion-presets button')].find((b) => b.textContent === name);
|
|
807
|
+
it('offers ready effects and hides the entrance details until one is chosen', async () => {
|
|
808
|
+
await mount(undefined, ['motion']);
|
|
809
|
+
expect(container.querySelector('.bd-motion-presets')).not.toBeNull();
|
|
810
|
+
expect(container.querySelector('[data-style-prop="motion.entranceDuration"]')).toBeNull();
|
|
811
|
+
expect(container.querySelector('[data-style-prop="motion.entranceDirection"]')).toBeNull();
|
|
812
|
+
});
|
|
813
|
+
it('writes a preset as one undo step and shows its controls', async () => {
|
|
814
|
+
const store = await mount(undefined, ['motion']);
|
|
815
|
+
const slide = container.querySelector('.bd-motion-presets button:nth-child(3)');
|
|
816
|
+
await act(async () => slide.click());
|
|
817
|
+
expect(styles(store)?.base?.['motion']).toMatchObject({
|
|
818
|
+
entrance: 'slide',
|
|
819
|
+
entranceDirection: 'up',
|
|
820
|
+
});
|
|
821
|
+
expect(container.querySelector('[data-style-prop="motion.entranceDuration"]')).not.toBeNull();
|
|
822
|
+
expect(container.querySelector('[data-style-prop="motion.entranceDirection"]')).not.toBeNull();
|
|
823
|
+
expect(container.querySelector('.bd-motion-curve')).not.toBeNull();
|
|
824
|
+
store.undo();
|
|
825
|
+
expect(styles(store)?.base?.['motion']).toBeUndefined();
|
|
826
|
+
expect(presetButton('None')).toBeDefined();
|
|
827
|
+
});
|
|
828
|
+
});
|
|
829
|
+
describe('background media (PB-157)', () => {
|
|
830
|
+
const mediaProps = {
|
|
831
|
+
backgroundImage: p.media({ label: 'Background image', accept: ['image'] }),
|
|
832
|
+
backgroundVideo: p.media({ label: 'Background video', accept: ['video'] }),
|
|
833
|
+
backgroundPoster: p.media({ label: 'Video poster', accept: ['image'] }),
|
|
834
|
+
};
|
|
835
|
+
const kindButton = (name) => [...container.querySelectorAll('.bd-bg-kind button')].find((b) => b.textContent === name);
|
|
836
|
+
const click = (element) => act(async () => element.click());
|
|
837
|
+
const propOf = (store, name) => store.getState().doc.nodes['box0000001']?.props?.[name];
|
|
838
|
+
const setMedia = (store, prop, url) => store.dispatch({
|
|
839
|
+
type: 'node.setProp',
|
|
840
|
+
payload: {
|
|
841
|
+
id: 'box0000001',
|
|
842
|
+
prop,
|
|
843
|
+
value: { kind: 'static', value: { external: true, url } },
|
|
844
|
+
},
|
|
845
|
+
});
|
|
846
|
+
const field = (prop) => container.querySelector(`[data-prop=${prop}]`);
|
|
847
|
+
it('keeps Image and Video off, with a reason, for a component without those props', async () => {
|
|
848
|
+
await mount(undefined, ['background']);
|
|
849
|
+
expect(kindButton('Image')?.disabled).toBe(true);
|
|
850
|
+
expect(kindButton('Video')?.disabled).toBe(true);
|
|
851
|
+
expect(container.textContent).toContain('This component has no image or video background.');
|
|
852
|
+
});
|
|
853
|
+
it('enables Image and Video for a component that has the props and shows their fields', async () => {
|
|
854
|
+
await mount(undefined, ['background'], false, mediaProps);
|
|
855
|
+
expect(kindButton('Image')?.disabled).toBe(false);
|
|
856
|
+
expect(kindButton('Video')?.disabled).toBe(false);
|
|
857
|
+
expect(container.textContent).not.toContain('has no image or video');
|
|
858
|
+
await click(kindButton('Image'));
|
|
859
|
+
expect(field('backgroundImage')).not.toBeNull();
|
|
860
|
+
expect(field('backgroundVideo')).toBeNull();
|
|
861
|
+
await click(kindButton('Video'));
|
|
862
|
+
expect(field('backgroundVideo')).not.toBeNull();
|
|
863
|
+
expect(field('backgroundPoster')).not.toBeNull();
|
|
864
|
+
expect(field('backgroundImage')).toBeNull();
|
|
865
|
+
});
|
|
866
|
+
it('shows the kind the component already holds', async () => {
|
|
867
|
+
const store = await mount(undefined, ['background'], false, mediaProps);
|
|
868
|
+
expect(kindButton('Video')?.getAttribute('aria-pressed')).toBe('false');
|
|
869
|
+
await act(async () => void setMedia(store, 'backgroundVideo', 'https://cdn.example.com/a.mp4'));
|
|
870
|
+
expect(kindButton('Video')?.getAttribute('aria-pressed')).toBe('true');
|
|
871
|
+
expect(field('backgroundVideo')).not.toBeNull();
|
|
872
|
+
});
|
|
873
|
+
it('clears the other media when the kind changes, as one undo step', async () => {
|
|
874
|
+
const store = await mount(undefined, ['background'], false, mediaProps);
|
|
875
|
+
await act(async () => void setMedia(store, 'backgroundImage', 'https://cdn.example.com/a.jpg'));
|
|
876
|
+
expect(kindButton('Image')?.getAttribute('aria-pressed')).toBe('true');
|
|
877
|
+
await click(kindButton('Video'));
|
|
878
|
+
expect(propOf(store, 'backgroundImage')).toBeUndefined();
|
|
879
|
+
await act(async () => {
|
|
880
|
+
store.undo();
|
|
881
|
+
});
|
|
882
|
+
expect(propOf(store, 'backgroundImage')).toBeDefined();
|
|
883
|
+
expect(kindButton('Image')?.getAttribute('aria-pressed')).toBe('true');
|
|
884
|
+
});
|
|
885
|
+
it('clears the video and its poster when switching to Image, and one undo restores both', async () => {
|
|
886
|
+
const store = await mount(undefined, ['background'], false, mediaProps);
|
|
887
|
+
await act(async () => {
|
|
888
|
+
setMedia(store, 'backgroundVideo', 'https://cdn.example.com/a.mp4');
|
|
889
|
+
setMedia(store, 'backgroundPoster', 'https://cdn.example.com/p.jpg');
|
|
890
|
+
});
|
|
891
|
+
await click(kindButton('Image'));
|
|
892
|
+
expect(propOf(store, 'backgroundVideo')).toBeUndefined();
|
|
893
|
+
expect(propOf(store, 'backgroundPoster')).toBeUndefined();
|
|
894
|
+
await act(async () => {
|
|
895
|
+
store.undo();
|
|
896
|
+
});
|
|
897
|
+
expect(propOf(store, 'backgroundVideo')).toBeDefined();
|
|
898
|
+
expect(propOf(store, 'backgroundPoster')).toBeDefined();
|
|
899
|
+
expect(kindButton('Video')?.getAttribute('aria-pressed')).toBe('true');
|
|
900
|
+
});
|
|
901
|
+
it('clears all media when switching to None, and one undo restores them', async () => {
|
|
902
|
+
const store = await mount(undefined, ['background'], false, mediaProps);
|
|
903
|
+
await act(async () => {
|
|
904
|
+
setMedia(store, 'backgroundVideo', 'https://cdn.example.com/a.mp4');
|
|
905
|
+
setMedia(store, 'backgroundPoster', 'https://cdn.example.com/p.jpg');
|
|
906
|
+
});
|
|
907
|
+
await click(kindButton('None'));
|
|
908
|
+
expect(propOf(store, 'backgroundVideo')).toBeUndefined();
|
|
909
|
+
expect(propOf(store, 'backgroundPoster')).toBeUndefined();
|
|
910
|
+
await act(async () => {
|
|
911
|
+
store.undo();
|
|
912
|
+
});
|
|
913
|
+
expect(propOf(store, 'backgroundVideo')).toBeDefined();
|
|
914
|
+
expect(propOf(store, 'backgroundPoster')).toBeDefined();
|
|
915
|
+
});
|
|
916
|
+
it('rolls back and says so when a switch fails', async () => {
|
|
917
|
+
const store = await mount(undefined, ['background'], false, mediaProps);
|
|
918
|
+
await act(async () => {
|
|
919
|
+
setMedia(store, 'backgroundImage', 'https://cdn.example.com/a.jpg');
|
|
920
|
+
});
|
|
921
|
+
const dispatch = store.dispatch.bind(store);
|
|
922
|
+
vi.spyOn(store, 'dispatch').mockImplementation((command, options) => command.type === 'node.unsetProp'
|
|
923
|
+
? { ok: false, error: { code: 'x', message: 'refused' } }
|
|
924
|
+
: dispatch(command, options));
|
|
925
|
+
await click(kindButton('Video'));
|
|
926
|
+
expect(propOf(store, 'backgroundImage')).toBeDefined();
|
|
927
|
+
expect(container.querySelector('.bd-inspector-notice')?.textContent).toBe('The background could not be changed. Nothing was removed.');
|
|
928
|
+
});
|
|
929
|
+
it('keeps the colour and gradient choices working on a device layer that holds media', async () => {
|
|
930
|
+
const store = await mount('tablet', ['background'], false, mediaProps);
|
|
931
|
+
await act(async () => void setMedia(store, 'backgroundVideo', 'https://cdn.example.com/a.mp4'));
|
|
932
|
+
expect(kindButton('Video')?.getAttribute('aria-pressed')).toBe('false');
|
|
933
|
+
await click(kindButton('Gradient'));
|
|
934
|
+
expect(kindButton('Gradient')?.getAttribute('aria-pressed')).toBe('true');
|
|
935
|
+
expect(container.querySelector('[data-style-prop="background.gradient"]')).not.toBeNull();
|
|
936
|
+
await click(kindButton('Colour'));
|
|
937
|
+
expect(container.querySelector('[data-style-prop="background.color"]')).not.toBeNull();
|
|
938
|
+
expect(propOf(store, 'backgroundVideo')).toBeDefined();
|
|
939
|
+
});
|
|
940
|
+
it('does not offer media while a device is being edited', async () => {
|
|
941
|
+
await mount('tablet', ['background'], false, mediaProps);
|
|
942
|
+
expect(kindButton('Image')?.disabled).toBe(true);
|
|
943
|
+
expect(container.textContent).toContain('belong to the whole component');
|
|
944
|
+
});
|
|
945
|
+
});
|