efficient-easel 22.0.0 → 23.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/README.md +38 -23
  2. package/dist/{CanvasDragLayer-B6Yn9S8T.d.ts → CanvasDragLayer-NZpaX6aq.d.ts} +15 -4
  3. package/dist/{ScreenDocumentContext-BIK3uWtF.d.ts → ScreenDocumentContext-BDLUYzlM.d.ts} +4 -4
  4. package/dist/blocks/index.d.ts +11 -11
  5. package/dist/canvas/index.d.ts +21 -9
  6. package/dist/canvas/index.js +1 -1
  7. package/dist/{canvas-typing-Be4FO4q7.d.ts → canvas-typing-DOBx8dD3.d.ts} +12 -2
  8. package/dist/{chunk-XWKQP6AE.js → chunk-3P735WOM.js} +4 -4
  9. package/dist/{chunk-KWLHKKZO.js → chunk-4YUC7B7E.js} +1 -1
  10. package/dist/chunk-6F5GO337.js +1 -0
  11. package/dist/{chunk-3S5N4HLJ.js → chunk-6NJHYXJM.js} +1 -1
  12. package/dist/{chunk-BTDI7JAA.js → chunk-A6ZP5II4.js} +2 -2
  13. package/dist/{chunk-IWCKVZHS.js → chunk-AGWKB77Q.js} +1 -1
  14. package/dist/chunk-AT4DDMJS.js +1 -0
  15. package/dist/chunk-FF54HWSE.js +8 -0
  16. package/dist/{chunk-IROEWITG.js → chunk-FOOK54T2.js} +1 -1
  17. package/dist/{chunk-SWBADIQT.js → chunk-G3HAKQUF.js} +1 -1
  18. package/dist/{chunk-ZOSEBPAI.js → chunk-GKG3M5QK.js} +1 -1
  19. package/dist/chunk-GXRS52JD.js +5 -0
  20. package/dist/{chunk-YC6KLSW3.js → chunk-HLMQ34GP.js} +1 -1
  21. package/dist/chunk-HZSZT3BE.js +7 -0
  22. package/dist/{chunk-EB6NI2VK.js → chunk-IYHO4XQX.js} +1 -1
  23. package/dist/chunk-IZGFJWH4.js +1 -0
  24. package/dist/chunk-KXM6YRG2.js +1 -0
  25. package/dist/chunk-KXTXYINN.js +16 -0
  26. package/dist/chunk-LN43DP2A.js +18 -0
  27. package/dist/{chunk-YHFKWV7H.js → chunk-MXECWHRJ.js} +10 -10
  28. package/dist/chunk-OXZDSOZV.js +1 -0
  29. package/dist/{chunk-BSHIQIZC.js → chunk-RPMSET77.js} +1 -1
  30. package/dist/{chunk-K7BTCBWD.js → chunk-TGZCD6IP.js} +1 -1
  31. package/dist/chunk-VZUXOZGP.js +64 -0
  32. package/dist/{chunk-RY5AWQ63.js → chunk-XJ23ULBP.js} +1 -1
  33. package/dist/{chunk-TLN5ZT76.js → chunk-YHEYJKQL.js} +1 -1
  34. package/dist/chunk-YU3WHLGI.js +1 -0
  35. package/dist/copy/index.d.ts +20 -6
  36. package/dist/copy/index.js +29 -29
  37. package/dist/data/index.d.ts +30 -22
  38. package/dist/data/index.js +1 -1
  39. package/dist/drag/drag.css +10 -1
  40. package/dist/drag/index.d.ts +5 -5
  41. package/dist/drag/index.js +1 -1
  42. package/dist/draw/index.d.ts +1 -1
  43. package/dist/easel/easel.css +12 -5
  44. package/dist/easel/index.d.ts +90 -53
  45. package/dist/easel/index.js +1 -1
  46. package/dist/edit-lock/index.d.ts +5 -5
  47. package/dist/fields/fields.css +1 -1
  48. package/dist/fields/index.d.ts +15 -15
  49. package/dist/fields/index.js +1 -1
  50. package/dist/node-ops/index.d.ts +3 -3
  51. package/dist/node-ops/index.js +1 -1
  52. package/dist/panel/index.d.ts +1 -1
  53. package/dist/panel/panel.css +6 -1
  54. package/dist/pick/index.d.ts +5 -5
  55. package/dist/{plan-CRUh2kVK.d.ts → plan-D0DgSLnY.d.ts} +5 -5
  56. package/dist/render/index.d.ts +13 -13
  57. package/dist/render/index.js +1 -1
  58. package/dist/{resolve-AJ6WF4EL.d.ts → resolve-Bz4mszpL.d.ts} +5 -5
  59. package/dist/screen/components/AddBlockRow.js +1 -1
  60. package/dist/screen/components/AddSidePanel.d.ts +2 -2
  61. package/dist/screen/components/AddSidePanel.js +1 -1
  62. package/dist/screen/components/NodeContextMenu.d.ts +17 -20
  63. package/dist/screen/components/NodeContextMenu.js +1 -1
  64. package/dist/screen/components/PageEditGuardNotices.js +1 -1
  65. package/dist/screen/components/PreviewDeviceContext.d.ts +1 -1
  66. package/dist/screen/components/PreviewPartsContext.d.ts +2 -2
  67. package/dist/screen/components/SaveControls.d.ts +8 -8
  68. package/dist/screen/components/ScreenChrome.js +1 -1
  69. package/dist/screen/components/ScreenDocumentContext.d.ts +5 -5
  70. package/dist/screen/components/ScreenDocumentContext.js +1 -1
  71. package/dist/screen/components/ScreenMount.d.ts +8 -8
  72. package/dist/screen/components/ScreenMount.js +1 -1
  73. package/dist/screen/components/ScreenStoreProvider.d.ts +12 -12
  74. package/dist/screen/components/ScreenStoreProvider.js +1 -1
  75. package/dist/screen/components/SectionScreenShell.js +17 -17
  76. package/dist/screen/components/usePartBridge.d.ts +10 -10
  77. package/dist/screen/components/usePartBridge.js +1 -1
  78. package/dist/screen/index.d.ts +8 -8
  79. package/dist/screen/index.js +1 -1
  80. package/dist/screen/lib/admin-bridge.d.ts +4 -4
  81. package/dist/screen/lib/document/block-types-in.d.ts +2 -1
  82. package/dist/screen/lib/document/block-types-in.js +1 -1
  83. package/dist/screen/lib/document/content-tree.d.ts +8 -8
  84. package/dist/screen/lib/document/device-fields.d.ts +7 -7
  85. package/dist/screen/lib/document/device-fields.js +1 -1
  86. package/dist/screen/lib/document/field-markers.d.ts +4 -4
  87. package/dist/screen/lib/document/palette-sections.d.ts +5 -5
  88. package/dist/screen/lib/document/panel-fields.d.ts +5 -5
  89. package/dist/screen/lib/document/panel-no-control-mark.d.ts +3 -3
  90. package/dist/screen/lib/document/part-id.d.ts +1 -1
  91. package/dist/screen/lib/document/preview-events.d.ts +2 -2
  92. package/dist/screen/lib/document/preview-selection-context.d.ts +2 -2
  93. package/dist/screen/lib/document/section-doc.d.ts +5 -5
  94. package/dist/screen/lib/document/section-doc.js +1 -1
  95. package/dist/screen/lib/document/slot-child-name.d.ts +1 -1
  96. package/dist/screen/lib/document/slot-section-spec.d.ts +1 -1
  97. package/dist/screen/lib/document/style-clipboard.d.ts +8 -8
  98. package/dist/screen/lib/document/style-clipboard.js +1 -1
  99. package/dist/screen/lib/document/tree-reveal.d.ts +4 -4
  100. package/dist/screen/lib/document/use-section-ops.d.ts +6 -6
  101. package/dist/screen/lib/document/use-section-ops.js +1 -1
  102. package/dist/screen/lib/document-addressing.d.ts +5 -5
  103. package/dist/screen/lib/document-hooks.d.ts +4 -4
  104. package/dist/screen/lib/host.d.ts +5 -5
  105. package/dist/screen/lib/key-scope.d.ts +1 -1
  106. package/dist/screen/lib/key-scope.js +1 -1
  107. package/dist/screen/lib/media-panel.d.ts +5 -5
  108. package/dist/screen/lib/media-picker.d.ts +6 -6
  109. package/dist/screen/lib/page-lock.d.ts +4 -4
  110. package/dist/screen/lib/screen-parts.d.ts +22 -10
  111. package/dist/screen/lib/screen-parts.js +1 -1
  112. package/dist/screen/lib/section-templates.d.ts +4 -4
  113. package/dist/screen/lib/session-context.d.ts +4 -4
  114. package/dist/screen/lib/session.d.ts +5 -5
  115. package/dist/screen/lib/shared-sections.d.ts +4 -4
  116. package/dist/screen/screen.css +14 -14
  117. package/dist/screen/words.d.ts +4 -3
  118. package/dist/screen/words.js +1 -1
  119. package/dist/{session-CrWwDt7Z.d.ts → session-EsjORLQ0.d.ts} +1 -1
  120. package/dist/shell/shell.css +2 -2
  121. package/dist/strings/index.d.ts +2 -2
  122. package/dist/strings/index.js +2 -2
  123. package/dist/style-clipboard/index.d.ts +2 -2
  124. package/dist/text-styles/index.d.ts +3 -3
  125. package/dist/text-styles/model.d.ts +1 -1
  126. package/dist/{types-BFd8FqQw.d.ts → types-BIytwvvH.d.ts} +2 -2
  127. package/dist/{types-DFxBChE3.d.ts → types-BljCVdzR.d.ts} +17 -17
  128. package/dist/{types-DlQIM1YO.d.ts → types-Dq180WRV.d.ts} +8 -8
  129. package/dist/{useNodeOps-C_nisDHh.d.ts → useNodeOps-igxrnEhq.d.ts} +2 -2
  130. package/dist/{watch-D0bNZRtU.d.ts → watch-Unf6SfUf.d.ts} +3 -3
  131. package/dist/{words-gIDCeRv3.d.ts → words-B5Gb7KFq.d.ts} +1 -1
  132. package/dist/{words-BpTjCfqO.d.ts → words-Cf5VT2Ic.d.ts} +2 -2
  133. package/package.json +1 -1
  134. package/dist/chunk-4LGROS5L.js +0 -1
  135. package/dist/chunk-BDSLF5BR.js +0 -1
  136. package/dist/chunk-CPL43ZLJ.js +0 -1
  137. package/dist/chunk-CUZQ2HMA.js +0 -18
  138. package/dist/chunk-GHBK7BKL.js +0 -1
  139. package/dist/chunk-IYYE7VJN.js +0 -65
  140. package/dist/chunk-KN2TIXUT.js +0 -1
  141. package/dist/chunk-L55YIXDC.js +0 -1
  142. package/dist/chunk-MZ5GSSZ3.js +0 -7
  143. package/dist/chunk-SJMS247S.js +0 -5
  144. package/dist/chunk-TXR7GC5A.js +0 -8
  145. package/dist/chunk-WJSEWAWK.js +0 -15
package/README.md CHANGED
@@ -425,14 +425,14 @@ unknown pastes only between two components of the same type. An empty
425
425
  ## The document — `efficient-easel/data`
426
426
 
427
427
  `efficient-easel/data` (added in 0.67.0) is the bottom layer of the engine that
428
- replaces the old editor (the blueprint's step 1.1): the saved document as pure
428
+ replaces the old library (the blueprint's step 1.1): the saved document as pure
429
429
  functions. It imports nothing and touches no browser global, so the editor's
430
430
  store, a Next server component, a Node script and a test all call the same
431
431
  code.
432
432
 
433
433
  **The format does not change.** A document is exactly what Puck 0.20 saves —
434
434
  `{ root: { props }, content: [...], zones: {} }`, with a block's children
435
- inline in its slot props — so no campaign or page migrates when the old editor goes.
435
+ inline in its slot props — so no campaign or page migrates when the old library goes.
436
436
 
437
437
  ```ts
438
438
  import { normalizeData, find, insert, move, remove, duplicate, setProps, setRoot, createNode, walk, ROOT_LIST } from 'efficient-easel/data';
@@ -447,15 +447,16 @@ next = setProps(next, config, id, { level: 3 });
447
447
 
448
448
  | Export | Notes |
449
449
  |---|---|
450
- | `normalizeData(data, config)` | the old editor's load: missing top-level slots become `[]`, `zones` becomes `{}`, the root's `defaultProps` fill what is missing. Older formats (props written on `root`, children parked in `zones`) are converted the way the old editor's `migrate()` converts them. **A document already in shape comes back as the same object.** |
450
+ | `normalizeData(data, config)` | the old library's load: missing top-level slots become `[]`, `zones` becomes `{}`, the root's `defaultProps` fill what is missing. Older formats (props written on `root`, children parked in `zones`) are converted the way the old library's `migrate()` converts them. **A document already in shape comes back as the same object.** |
451
451
  | `find`, `walk`, `slotsOf`, `getList` | Read. `walk` visits parent before children, slots in declaration order; returning a node from the visitor replaces it. |
452
- | `insert`, `move`, `remove`, `duplicate` | Change the tree. `move` within one list takes the index AFTER the move (the old editor's rule). |
452
+ | `isNode`, `isNodeList` | Shape checks. `isNode`: a string `type` and a `props` object. `isNodeList`: a slot's array — non-empty, every item a node; a list field (stats rows) is not one. The one answer for the easel and every host; do not write your own. |
453
+ | `insert`, `move`, `remove`, `duplicate` | Change the tree. `move` within one list takes the index AFTER the move (the old library's rule). |
453
454
  | `setProps`, `setRoot` | Merge props. A key keeps its place; a patch that changes nothing returns the same document. |
454
455
  | `createNode(config, type, props?)`, `newId(type)` | A new block the way the Add panel makes one: `{ ...defaultProps, id }`, ids `<Type>-<uuid>`. |
455
- | `zoneKey`, `parseZoneKey`, `ROOT_LIST` | A place is `{ parentId, slot, index }`; the top-level list is `{ parentId: 'root', slot: 'default-zone' }` — the two halves of the old editor's zone key. |
456
+ | `zoneKey`, `parseZoneKey`, `ROOT_LIST` | A place is `{ parentId, slot, index }`; the top-level list is `{ parentId: 'root', slot: 'default-zone' }` — the two halves of the old library's zone key. |
456
457
 
457
458
  `config` is the app's block config: only `fields` (which props are slots, including
458
- slots inside `object` / `array` fields) and `defaultProps` are read, so an old editor
459
+ slots inside `object` / `array` fields) and `defaultProps` are read, so an old library
459
460
  `Config` works as it is. A type the config does not know is kept whole.
460
461
 
461
462
  Every edit copies only the path to the change, so an untouched block is the
@@ -566,11 +567,11 @@ base words under a translation, markers on untranslated rows). Routing and
566
567
  `efficient-easel/blocks` (added in 0.92.0) holds the types a block is written
567
568
  with: Puck 0.20's `Config`, `ComponentConfig`, `Fields`, `Field`,
568
569
  `CustomField`, `ComponentData`, `Data`, `Slot` and `SlotComponent`, with the
569
- same generics. An app that typed its blocks with the old editor's imports them from here
570
+ same generics. An app that typed its blocks with the old library's imports them from here
570
571
  instead, and no block changes. It is types only: nothing in it exists at
571
572
  runtime. One key is the engine's own: `translatable` on a field (0.97.0),
572
573
  which says whether the prop is written again per language (the translation
573
- overlay, above). It is optional, so a field written for the old editor is still a field.
574
+ overlay, above). It is optional, so a field written for the old library is still a field.
574
575
 
575
576
  ```ts
576
577
  import type { Config, CustomField, Slot } from 'efficient-easel/blocks';
@@ -591,9 +592,9 @@ const config: Config<{ Hero: HeroProps }> = {
591
592
  ## The published renderer — `efficient-easel/render`
592
593
 
593
594
  `efficient-easel/render` (added in 0.68.0) draws a saved document the way the
594
- published site does — the drop-in for the old editor's `<Render>` (the blueprint's step
595
+ published site does — the drop-in for the old library's `<Render>` (the blueprint's step
595
596
  1.2). Same config, same document, **the same HTML**: the specs hold it to
596
- Puck 0.20.2's markup, recorded from the old editor's own `<Render>`, byte for byte.
597
+ Puck 0.20.2's markup, recorded from the old library's own `<Render>`, byte for byte.
597
598
 
598
599
  ```tsx
599
600
  import { Render } from 'efficient-easel/render';
@@ -603,18 +604,18 @@ import { Render } from 'efficient-easel/render';
603
604
 
604
605
  It is a plain function: **no hook, no context, no `'use client'`**. It runs in a
605
606
  server component, a client component or a script, and `Render(props)` called
606
- directly returns the element tree. (The old editor's reads the document from a context
607
+ directly returns the element tree. (The old library's reads the document from a context
607
608
  and builds props in hooks, so it only runs as a client component.) Whether the
608
609
  blocks themselves can run on the server is up to the blocks.
609
610
 
610
- The block authoring shape is the old editor's, so an app passes the config it has: a
611
+ The block authoring shape is the old library's, so an app passes the config it has: a
611
612
  block's `render` gets its props, `editor`, and each slot as a component —
612
613
  `render: ({ content: Content }) => <Content className="grid" />` — which draws
613
614
  `<div className style>` around its blocks. The top-level list is wrapped in one
614
- plain `<div>`, and `editor` carries exactly what the old editor's client `<Render>` gave
615
+ plain `<div>`, and `editor` carries exactly what the old library's client `<Render>` gave
615
616
  a block at each level. A type the config does not know draws nothing.
616
617
 
617
- **The old editor's name is gone (22.0.0).** The block prop is `editor`, the
618
+ **The old library's name is gone (22.0.0).** The block prop is `editor`, the
618
619
  canvas markup `data-easel-*`, the subpaths `screen/lib/document/*`, the
619
620
  inspector mode `{ kind: "selection" }` and the root's id `page-root`. What was
620
621
  removed, and what replaces each name, is in the CHANGELOG under 22.0.0.
@@ -638,7 +639,7 @@ always has it.
638
639
 
639
640
  `className` (0.95.0) is an opt-in class for that top-level wrapper, for a host
640
641
  whose stylesheet has to reach it: `<Render … className="page" />`. Left out,
641
- the wrapper is bare and the markup is the old editor's.
642
+ the wrapper is bare and the markup is the old library's.
642
643
 
643
644
  ## What a block draws with — `efficient-easel/draw`, `efficient-easel/draw/client`
644
645
 
@@ -690,7 +691,7 @@ graph to an exact list of files and imports.
690
691
 
691
692
  `efficient-easel/canvas` (added in 0.70.0, blueprint step 2.1) is the one way
692
693
  into the editor's canvas iframe — `#preview-frame`, the engine's own
693
- same-origin canvas frame (the old editor's, until the editors left it). It replaces the
694
+ same-origin canvas frame (the old library's, until the editors left it). It replaces the
694
695
  editors' own polling loops, host-head style injection and hand-written
695
696
  coordinate maths.
696
697
 
@@ -707,7 +708,7 @@ const tick = useCanvasLayout(canvas); // re-m
707
708
  |---|---|
708
709
  | `useCanvasFrame(rootRef, { selector?, readySelector? })` | `{ frame, document, window }` or `null`. Found by a MutationObserver and the frame's `load` event — never a timer. `readySelector` waits for the canvas to be drawn in a loaded-but-empty document. |
709
710
  | `useCanvasEvent(canvas, type, handler, { on?, capture? })` | A listener on the canvas document (or window) that moves to a replacement document and always calls the latest handler, without re-binding on every render. |
710
- | `useCanvasStyle(canvas, key, css)` | A `<style>` in the canvas document's head only — re-injected into a replacement, put back if something empties the head (the old editor's AutoFrame does, once), removed on unmount, never written to the host page. |
711
+ | `useCanvasStyle(canvas, key, css)` | A `<style>` in the canvas document's head only — re-injected into a replacement, put back if something empties the head (the old library's AutoFrame does, once), removed on unmount, never written to the host page. |
711
712
  | `useCanvasLayout(canvas)` | A number that changes when the canvas scrolls, resizes, is replaced, or the host scrolls or resizes (plus two settle passes). |
712
713
  | `frameRectToHost`, `framePointToHost`, `frameScale` | A box or point measured inside the frame, on the host page — through the frame's SCALE (a phone view drawn small). |
713
714
  | `fitCanvas({ available, width, maxScale })` | The canvas width and the scale that fits it into the pane. |
@@ -787,7 +788,19 @@ A host's PARTS join the chain (W0): through `CanvasPartsContext` (a
787
788
  host says which part of the innermost block is under the pointer, and
788
789
  `clickPickPart` puts it after its block: a container's part is one more rung, a
789
790
  block with no lists is picked with its part at once. The hover outline draws
790
- the part (`is-hover-part`); Escape lets a part go before it climbs.
791
+ the part (`is-hover-part`); Escape lets a part go before it climbs. One box per text (Lewis 2026-10-26): a part gets a box of its own
792
+ (`is-hover-part`; with the host's `selectedPart(doc)`, the selected rectangle
793
+ `is-selected is-selected-part` while the block's selected box stands down),
794
+ unless it is its block's only part (`CanvasPart.whole`, a Text block's words)
795
+ in a block with no lists: then the block and its words are one rung and share
796
+ the block box, where the drag handle's label is. With no `whole`, a block with
797
+ no lists is read as that one rung. Without `selectedPart`, the block box as
798
+ before. The LABEL names what is selected (Lewis 2026-10-26):
799
+ while a part with a box of its own is open, the screen hands the drag layer a
800
+ `tag` (`CanvasPart.label`, the Layers name) drawn on the part's box like the
801
+ handle but with no drag dots, and the block's handle is not drawn; to drag
802
+ the block, select the block first or drag its Layers row (`partHasOwnBox` is
803
+ the one rule for the box and the label).
791
804
 
792
805
  ## Autosave — `efficient-easel/autosave`
793
806
 
@@ -997,7 +1010,7 @@ const easel = createEasel<EaselConfig>({ config, data, onChange: (doc) => autosa
997
1010
  - `bindUndoKeys(target, editor, { leaveTyping: true })` (0.106.0) leaves a
998
1011
  press where a person types — a text field, a textarea, an editable
999
1012
  region — to that field's own undo. Left out, a press there undoes the
1000
- easel's step, as the old editor's did; the provider and the canvas bind so.
1013
+ easel's step, as the old library's did; the provider and the canvas bind so.
1001
1014
  - **Two tabs since 4.0.0: Design and Animation.** A field's `bucket` is one
1002
1015
  of `SETTINGS_BUCKETS`; anything else (the 3.x `Content`, `Style`, `Layout`)
1003
1016
  is ignored, so the rows stay in the tab above them. Inside Design the host
@@ -1026,8 +1039,8 @@ const easel = createEasel<EaselConfig>({ config, data, onChange: (doc) => autosa
1026
1039
  the slot's name has a bucket. Filter `row.field.type !== 'slot'` before
1027
1040
  drawing or counting rows of your own.
1028
1041
  - **Inserting a block runs no resolver; `easel.resolveNode` does.** The
1029
- `insert` action puts the block in with its `defaultProps`, as the old editor's reducer
1030
- did. What ran a new block's `resolveData` in the old editor was its own drop from the
1042
+ `insert` action puts the block in with its `defaultProps`, as the old library's reducer
1043
+ did. What ran a new block's `resolveData` in the old library was its own drop from the
1031
1044
  component list, and the engine has no drop of its own: the Add list's click
1032
1045
  and the drag's drop are the host's. So follow an insert with it:
1033
1046
 
@@ -1212,7 +1225,7 @@ words, its marks and buttons of the layer's own are `blockLook.rowName`,
1212
1225
  `rowPreview`, `rowMarks` and `rowActions`. A block config's
1213
1226
  `permissions.delete` / `duplicate` set to `false` takes the action off the
1214
1227
  block's rows and its menu, and the inspector is handed the answer for its
1215
- head (`nodeActions`). The frame's words (Page settings, the pinned labels,
1228
+ head (`nodeActions`). The frame's words (the pinned labels,
1216
1229
  the band's) are `screen` words too.
1217
1230
 
1218
1231
  Its canvas can be a mail preview's (0.105.0). `devices.fit: "shrink"` draws a
@@ -1330,7 +1343,9 @@ layer, Copy, Copy style). Inside another app's page (`ownsDocument` false) ⌘Z
1330
1343
  editor's ground (its root takes focus, never a tab stop), and never in a text
1331
1344
  field or an editable region, where they are the field's own. A row's
1332
1345
  right-click is that row's: a pinned node's row opens its node's menu, a rung's
1333
- row opens none, and the ground's "Page settings" is `screen.pageSettings`.
1346
+ row opens none, and the ground's "This page" (`screen.pageStyles`) is the
1347
+ layer's `ScreenBridges.openPageStyles`, drawn only where the layer hands one.
1348
+ The tree has no row for the document's own settings (23.0.0).
1334
1349
  And `blockRules.stripCopy(node)` cleans every copy the screen makes — the
1335
1350
  menu's Duplicate and Paste, ⌘V, a saved section put in from Add — of what
1336
1351
  only its original may hold (the campaign designer's baked picture).
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
- import { C as CanvasTarget$1 } from './watch-D0bNZRtU.js';
3
- import { S as SlotAddress, P as Place } from './types-DlQIM1YO.js';
4
- import { D as DragSession } from './session-CrWwDt7Z.js';
2
+ import { C as CanvasTarget$1 } from './watch-Unf6SfUf.js';
3
+ import { S as SlotAddress, P as Place } from './types-Dq180WRV.js';
4
+ import { D as DragSession } from './session-EsjORLQ0.js';
5
5
  import { D as DragWords } from './words-SD4neL0n.js';
6
6
 
7
7
  /**
@@ -196,6 +196,17 @@ type CanvasDragLayerProps<I> = {
196
196
  /** What the outline says the drop does ("Replace image"). */
197
197
  label?: (item: I, source: CanvasSource<I>) => string;
198
198
  };
199
+ /**
200
+ * The NAME of what is selected when it is a part with a box of its own (a
201
+ * section's scrolling bar; Lewis 2026-10-26: the label says what is
202
+ * selected, on the corner of its box). Drawn as the handle is drawn, on the
203
+ * part's top-left corner, with no drag dots: a part does not drag. The host
204
+ * leaves the block's handle off meanwhile (`choose`). Absent: no tag.
205
+ */
206
+ tag?: {
207
+ element: Element;
208
+ label: string;
209
+ } | null;
199
210
  /** The handle CLICKED, not dragged: select what it names. Absent: a click does nothing. */
200
211
  onPick?: (item: I) => void;
201
212
  /** "+ Add section" in a seam: open the Add panel at that place. */
@@ -207,7 +218,7 @@ type CanvasDragLayerProps<I> = {
207
218
  readOnly?: boolean;
208
219
  /** Re-measure when this changes — the document's revision. Layout changes re-measure by themselves. */
209
220
  revision?: unknown;
210
- /** How the canvas is measured. Default: the old editor's markers (./measure). */
221
+ /** How the canvas is measured. Default: the old library's markers (./measure). */
211
222
  measure?: (canvas: CanvasTarget$1, layer: Element) => MeasuredCanvas;
212
223
  /**
213
224
  * The layer's own words in the host's language:
@@ -621,15 +621,15 @@ type ScreenDocumentValue = {
621
621
  * editing right now. Null while loading and between retargets, so it also
622
622
  * keys any once-per-document work (e.g. the pinned-chrome seed). */
623
623
  docId: string | null;
624
- /** The document exactly as it was LOADED from the backend: the old editor's initial
624
+ /** The document exactly as it was LOADED from the backend: the old library's initial
625
625
  * state, and the persisted snapshot a load-time seed must measure itself
626
- * against. Null while loading. Edits live in the old editor's own store, so this does
626
+ * against. Null while loading. Edits live in the old library's own store, so this does
627
627
  * NOT track them — it stays the last-loaded layout for the whole session. */
628
628
  data: Data | null;
629
629
  /** The freshest layout the merchant is actually viewing — the latest edit made
630
630
  * since load (tracked on every onChange, even after the autosave settles), else
631
631
  * the last-loaded `data`. Lets a feature snapshot the live view (e.g. the
632
- * read-only origin backdrop in footer focus) without reaching into the old editor's store.
632
+ * read-only origin backdrop in footer focus) without reaching into the old library's store.
633
633
  * Lean accessor (ISP) — never exposes the ref. */
634
634
  getLiveData: () => Data | null;
635
635
  error: string | null;
@@ -659,7 +659,7 @@ type ScreenDocumentValue = {
659
659
  /** "Retry now": a failed save goes again at once instead of waiting out its
660
660
  * backoff. */
661
661
  retrySave: () => void;
662
- /** Autosave — hand every the old editor onChange to this. */
662
+ /** Autosave — hand every the old library onChange to this. */
663
663
  onChange: (next: Data) => void;
664
664
  /** Persist the pending edit immediately; resolves to whether nothing is left
665
665
  * unsaved. */
@@ -1,17 +1,17 @@
1
1
  import { ReactElement, FC, CSSProperties, ReactNode, JSX } from 'react';
2
- import { P as Permissions, A as AppState } from '../types-DFxBChE3.js';
2
+ import { P as Permissions, A as AppState } from '../types-BljCVdzR.js';
3
3
  import '../data/index.js';
4
- import '../types-DlQIM1YO.js';
5
- import '../resolve-AJ6WF4EL.js';
6
- import '../plan-CRUh2kVK.js';
4
+ import '../types-Dq180WRV.js';
5
+ import '../resolve-Bz4mszpL.js';
6
+ import '../plan-D0DgSLnY.js';
7
7
 
8
8
  /**
9
9
  * efficient-easel/blocks — how a block is WRITTEN: its config, its fields, the
10
10
  * props its `render` receives and the document it lands in.
11
11
  *
12
- * Blueprint default #3 keeps the old editor's block writing, so the ~119 blocks both apps
12
+ * Blueprint default #3 keeps the old library's block writing, so the ~119 blocks both apps
13
13
  * wrote move onto the engine without a line changed. Until 6.1 those blocks were
14
- * typed by importing the old editor's own types, which kept the old editor package in both apps'
14
+ * typed by importing the old library's own types, which kept the old library's package in both apps'
15
15
  * dependencies after nothing ran it any more. These are the same shapes, written
16
16
  * here — Puck 0.20's `Config`, `ComponentConfig`, `Fields`, `Field`,
17
17
  * `CustomField`, `ComponentData`, `Data`, `Slot` and `SlotComponent` — so an app
@@ -20,7 +20,7 @@ import '../plan-CRUh2kVK.js';
20
20
  * WHAT IS LEFT OUT, ON PURPOSE:
21
21
  * - the `ConfigParams` form of `Config<{ components, root, fields }>` and the
22
22
  * user field-type extension it carries (neither app uses it);
23
- * - everything about the old editor's own app — its store, overrides, plugins and
23
+ * - everything about the old library's own app — its store, overrides, plugins and
24
24
  * history. Those are the engine's now (`efficient-easel/easel`).
25
25
  *
26
26
  * The `editor` prop is what every block's `render` destructures
@@ -49,7 +49,7 @@ type BaseField = {
49
49
  metadata?: Metadata;
50
50
  visible?: boolean;
51
51
  /**
52
- * NOT THE OLD EDITOR'S — the engine's (0.97.0). Whether this prop is written again in
52
+ * NOT THE OLD LIBRARY'S — the engine's (0.97.0). Whether this prop is written again in
53
53
  * each language of a multilingual page (`efficient-easel/data`, the
54
54
  * translation overlay). Left out, a `text` or `textarea` field is and every
55
55
  * other type is not, so a `custom` field that edits words, or a picture with
@@ -104,7 +104,7 @@ type ObjectField<Props = AnyRecord> = BaseField & {
104
104
  [SubPropName in keyof Props]: Field<Props[SubPropName]>;
105
105
  };
106
106
  };
107
- /** A custom field's drawing: called with the old editor's six props, as both apps wrote them. */
107
+ /** A custom field's drawing: called with the old library's six props, as both apps wrote them. */
108
108
  type CustomFieldRender<Value> = (props: {
109
109
  field: CustomField<Value>;
110
110
  name: string;
@@ -124,9 +124,9 @@ type SlotField = BaseField & {
124
124
  disallow?: string[];
125
125
  };
126
126
  /**
127
- * The old editor's `external` field: a value picked from a list the app fetches. Neither
127
+ * The old library's `external` field: a value picked from a list the app fetches. Neither
128
128
  * app has one and the Inspector does not draw it — it is in the union only so
129
- * the union is the old editor's, and a function that takes `Fields` takes the old editor's too.
129
+ * the union is the old library's, and a function that takes `Fields` takes the old library's too.
130
130
  */
131
131
  type ExternalField<Props = AnyRecord> = BaseField & {
132
132
  type: 'external';
@@ -1,6 +1,6 @@
1
1
  import { RefObject } from 'react';
2
- import { C as CanvasTarget, W as WatchOptions } from '../watch-D0bNZRtU.js';
3
- export { B as BLOCK_SELECTOR, a as CANVAS_SELECTOR, L as LIST_SELECTOR, i as isFrameReady, w as watchCanvasFrame } from '../watch-D0bNZRtU.js';
2
+ import { C as CanvasTarget, W as WatchOptions } from '../watch-Unf6SfUf.js';
3
+ export { B as BLOCK_SELECTOR, a as CANVAS_SELECTOR, L as LIST_SELECTOR, i as isFrameReady, w as watchCanvasFrame } from '../watch-Unf6SfUf.js';
4
4
  export { R as REPEAT_ATTRIBUTE, a as REPEAT_INDEX_ATTRIBUTE, i as isRepeatCopy, m as mainCopyOf, q as queryAllCopies, b as queryMainCopy } from '../repeat-D65bJS8d.js';
5
5
 
6
6
  /**
@@ -38,10 +38,19 @@ declare function nodeIdAt(target: EventTarget | null, attribute?: string): strin
38
38
  * the canvas's wrapper, and the wrapper's own box is the answer. A block whose
39
39
  * drawing leaves the wrapper's flow (the website's header bar is
40
40
  * `position: fixed`) leaves the wrapper with no height; then the union of what
41
- * it drew, its child elements, is the box. Never null: a wrapper with nothing
42
- * drawn is its own empty box.
41
+ * it drew is the box: each child element with a box of its own, and inside a
42
+ * child with none (a host's own wrapper divs round the bar), what that child
43
+ * drew, the same way. Never null: a wrapper with nothing drawn is its own empty
44
+ * box.
43
45
  */
44
46
  declare function drawnBox(el: Element): Box;
47
+ /** Whether one element holds the other (or is it): the same words, however the host stamps them. */
48
+ declare function related(a: Element, b: Element): boolean;
49
+ /** How far the box round typed or selected words stands clear of them, in px
50
+ * (Lewis 2026-10-14). The one home: the canvas sets `--es-words-clear` from
51
+ * it (`.is-typing`, `.is-selected.is-words` read that, easel.css) and the
52
+ * drag layer measures the handle's corner from it. */
53
+ declare const WORDS_CLEAR = 4;
45
54
  interface Box {
46
55
  left: number;
47
56
  top: number;
@@ -134,10 +143,10 @@ declare function removeCanvasStyle(doc: Document, key: string): void;
134
143
  /**
135
144
  * efficient-easel/canvas — the one way into the editor's canvas frame.
136
145
  *
137
- * Step 2.1 of the engine that replaces the old editor (blueprint "From The Ground Up
146
+ * Step 2.1 of the engine that replaces the old library (blueprint "From The Ground Up
138
147
  * For Efficient Editor", 2026-09-29). Both editors draw their canvas in an
139
- * iframe — the old editor's `#preview-frame` today, the engine's own same-origin
140
- * CanvasFrame once the editors leave the old editor — and each reached into it its own
148
+ * iframe — the old library's `#preview-frame` today, the engine's own same-origin
149
+ * CanvasFrame once the editors leave the old library — and each reached into it its own
141
150
  * way: eight polling loops with eight intervals, stylesheets pushed into the
142
151
  * host `<head>` hoping to be mirrored, key listeners re-bound on a one-second
143
152
  * timer, coordinate conversions that forgot the frame's scale. This module is
@@ -180,10 +189,13 @@ type CanvasTypingEvent = CustomEvent<{
180
189
  * can and are not being typed, else null. The layer over the canvas says how
181
190
  * to start — "Double-click to edit" — on that block (Lewis 2026-10-20: one
182
191
  * click on a Text block looked like typing, and nothing said it needs two).
192
+ * `words`: the selected words when they wear the typing box (Lewis 2026-10-26,
193
+ * option B), for the layer's handle and hint to sit on that box's corners.
183
194
  */
184
195
  declare const CANVAS_TYPABLE_EVENT = "easel:canvas-typable";
185
196
  type CanvasTypableEvent = CustomEvent<{
186
197
  id: string | null;
198
+ words?: Element;
187
199
  }>;
188
200
  type CanvasEventMap = DocumentEventMap & WindowEventMap & {
189
201
  [CANVAS_TYPING_EVENT]: CanvasTypingEvent;
@@ -212,7 +224,7 @@ declare function useCanvasTyping(canvas: CanvasTarget | null): boolean;
212
224
  * back in a replacement document, and take it out on unmount. An empty string
213
225
  * removes it. Nothing is written to the host page.
214
226
  *
215
- * "Keep" means it comes back if something else takes it out. The old editor's AutoFrame
227
+ * "Keep" means it comes back if something else takes it out. The old library's AutoFrame
216
228
  * empties the frame's `<head>` once, when the host styles it mirrors have
217
229
  * loaded (`doc.head.innerHTML = ""` in CopyHostStyles), and nothing orders that
218
230
  * after the canvas is published — so a sheet written first would silently go.
@@ -234,4 +246,4 @@ declare function useCanvasLayout(canvas: CanvasTarget | null, { settle }?: {
234
246
  settle?: readonly number[];
235
247
  }): number;
236
248
 
237
- export { BLOCK_ATTRIBUTE, type Box, CANVAS_TYPABLE_EVENT, CANVAS_TYPING_EVENT, type CanvasFit, CanvasTarget, type CanvasTypableEvent, type CanvasTypingEvent, WatchOptions, clientPointToLayer, drawnBox, elementScale, fitCanvas, framePointToHost, frameRectToHost, frameRectToLayer, frameScale, isTypingTarget, nodeIdAt, removeCanvasStyle, setCanvasNonce, upsertCanvasStyle, useCanvasEvent, useCanvasFrame, useCanvasLayout, useCanvasStyle, useCanvasTyping };
249
+ export { BLOCK_ATTRIBUTE, type Box, CANVAS_TYPABLE_EVENT, CANVAS_TYPING_EVENT, type CanvasFit, CanvasTarget, type CanvasTypableEvent, type CanvasTypingEvent, WORDS_CLEAR, WatchOptions, clientPointToLayer, drawnBox, elementScale, fitCanvas, framePointToHost, frameRectToHost, frameRectToLayer, frameScale, isTypingTarget, nodeIdAt, related, removeCanvasStyle, setCanvasNonce, upsertCanvasStyle, useCanvasEvent, useCanvasFrame, useCanvasLayout, useCanvasStyle, useCanvasTyping };
@@ -1 +1 @@
1
- export{BLOCK_ATTRIBUTE,BLOCK_SELECTOR,CANVAS_SELECTOR,CANVAS_TYPABLE_EVENT,CANVAS_TYPING_EVENT,LIST_SELECTOR,clientPointToLayer,drawnBox,elementScale,fitCanvas,framePointToHost,frameRectToHost,frameRectToLayer,frameScale,isFrameReady,isTypingTarget,nodeIdAt,removeCanvasStyle,setCanvasNonce,upsertCanvasStyle,useCanvasEvent,useCanvasFrame,useCanvasLayout,useCanvasStyle,useCanvasTyping,watchCanvasFrame}from"../chunk-GHBK7BKL.js";export{REPEAT_ATTRIBUTE,REPEAT_INDEX_ATTRIBUTE,isRepeatCopy,mainCopyOf,queryAllCopies,queryMainCopy}from"../chunk-LF3FUSCQ.js";
1
+ export{BLOCK_ATTRIBUTE,BLOCK_SELECTOR,CANVAS_SELECTOR,CANVAS_TYPABLE_EVENT,CANVAS_TYPING_EVENT,LIST_SELECTOR,WORDS_CLEAR,clientPointToLayer,drawnBox,elementScale,fitCanvas,framePointToHost,frameRectToHost,frameRectToLayer,frameScale,isFrameReady,isTypingTarget,nodeIdAt,related,removeCanvasStyle,setCanvasNonce,upsertCanvasStyle,useCanvasEvent,useCanvasFrame,useCanvasLayout,useCanvasStyle,useCanvasTyping,watchCanvasFrame}from"../chunk-YU3WHLGI.js";export{REPEAT_ATTRIBUTE,REPEAT_INDEX_ATTRIBUTE,isRepeatCopy,mainCopyOf,queryAllCopies,queryMainCopy}from"../chunk-LF3FUSCQ.js";
@@ -2,7 +2,7 @@ import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
3
  import { MarkStyle, WrapResult, InlineRule, MarkupTool } from 'efficient-shell/markup';
4
4
  import { TextAlign, TextToolbarCase, TextToolbarMark } from 'efficient-shell/ui';
5
- import { C as CopyWords } from './words-BpTjCfqO.js';
5
+ import { C as CopyWords } from './words-Cf5VT2Ic.js';
6
6
 
7
7
  type CellWords = NonNullable<CopyWords['cells']>;
8
8
  interface CopyCell {
@@ -53,7 +53,7 @@ interface CopyThemeColor {
53
53
  }
54
54
  /**
55
55
  * The colour the toolbar's A shows for `current` (a theme colour's name or a
56
- * hex): the hex itself, or the theme colour's value. One rule for every bar
56
+ * hex): the hex itself, or theme colour's value. One rule for every bar
57
57
  * that opens this window — the panel's text box and the canvas typing bar.
58
58
  */
59
59
  declare function colorRunOf(current: string | null, colors: readonly CopyThemeColor[] | undefined): string | undefined;
@@ -381,6 +381,9 @@ interface CanvasTypingSession {
381
381
  /** The colour the selection wears (a theme colour's name or a hex, a
382
382
  * pending one included), or null: the colour window shows it. */
383
383
  color: string | null;
384
+ /** Whether the selected words wear a mark or a colour that Clear
385
+ * formatting would take off (a link stays): the button shows only then. */
386
+ clearable: boolean;
384
387
  };
385
388
  /** A mark button pressed (B, I, U, S, superscript, subscript): on the
386
389
  * selected words, or for the words typed next — `markPress`, as the panel
@@ -424,6 +427,13 @@ interface CanvasTypingSession {
424
427
  * window stays open, so the focus is not moved.
425
428
  */
426
429
  color: (color: string | null) => void;
430
+ /**
431
+ * Clear formatting (Lewis 2026-10-26): every mark and colour off the
432
+ * selected words, back to the text's own style (`clearStyle`, which keeps a
433
+ * link). One edit step; the words stay selected. At a bare caret, the whole
434
+ * text (`clearRangeOf`, the one rule the panel box and the field bar share).
435
+ */
436
+ clear: () => void;
427
437
  }
428
438
  /** Start typing in the words `element()` drew, or `null` where they are not the string's. */
429
439
  declare function startCanvasTyping(o: CanvasTypingOptions): CanvasTypingSession | null;
@@ -1,7 +1,7 @@
1
- import{clientOnly as r}from"./chunk-GXQCZJOP.js";import{ScreenChrome as n}from"./chunk-IYYE7VJN.js";import{ScreenStoreProvider as e}from"./chunk-RY5AWQ63.js";import{ScreenDocumentProvider as i,useScreenDocument as a}from"./chunk-BTDI7JAA.js";import{DEFAULT_SCREEN_WORDS as o}from"./chunk-EB6NI2VK.js";import{documentPermissions as s}from"./chunk-THWO5YVZ.js";import{useWords as c}from"./chunk-MFIRYGHW.js";import{useMemo as t,useState as d,useRef as l,useEffect as m,useCallback as g}from"react";import{Dialog as h,Button as f}from"efficient-shell/ui";import{jsx as u,jsxs as p,Fragment as v}from"react/jsx-runtime";var k=r(e),N=r(n);function C({onCancel:r,onDiscard:n,onSave:e}){const i=c("screen",o).leave,[a,s]=d(!1),t=l(!0);m(()=>(t.current=!0,()=>{t.current=!1}),[]);const k=g(async()=>{s(!0);try{await e()}finally{t.current&&s(!1)}},[e]);/* @__PURE__ */
1
+ import{clientOnly as r}from"./chunk-GXQCZJOP.js";import{ScreenChrome as n}from"./chunk-VZUXOZGP.js";import{ScreenStoreProvider as e}from"./chunk-XJ23ULBP.js";import{ScreenDocumentProvider as i,useScreenDocument as a}from"./chunk-A6ZP5II4.js";import{DEFAULT_SCREEN_WORDS as o}from"./chunk-IYHO4XQX.js";import{documentPermissions as s}from"./chunk-THWO5YVZ.js";import{useWords as c}from"./chunk-MFIRYGHW.js";import{useMemo as t,useState as d,useRef as l,useEffect as m,useCallback as g}from"react";import{Dialog as h,Button as f}from"efficient-shell/ui";import{jsx as u,jsxs as p,Fragment as v}from"react/jsx-runtime";var k=r(e),C=r(n);function j({onCancel:r,onDiscard:n,onSave:e}){const i=c("screen",o).leave,[a,s]=d(!1),t=l(!0);m(()=>(t.current=!0,()=>{t.current=!1}),[]);const k=g(async()=>{s(!0);try{await e()}finally{t.current&&s(!1)}},[e]);/* @__PURE__ */
2
2
  return u(h,{open:!0,role:"alertdialog",size:"sm",title:i.title,onClose:r,footer:/* @__PURE__ */p(v,{children:[
3
3
  /* @__PURE__ */u(f,{variant:"secondary",onClick:r,children:i.cancel}),
4
4
  /* @__PURE__ */u(f,{variant:"ghost-danger",onClick:n,children:i.discard}),
5
- /* @__PURE__ */u(f,{variant:"primary",loading:a,onClick:()=>{k()},children:i.save})]}),children:i.body})}function j({target:r,addressing:n,onHostMessage:e,children:a}){/* @__PURE__ */
6
- return u(i,{target:r,addressing:n,onHostMessage:e,children:a})}var y=(r,n)=>/* @__PURE__ */p(v,{children:[r,n]});function A({config:r,parts:n,wrap:e=y}){const{data:i,error:d,redirecting:l,ready:m,readOnly:g,onChange:h,pendingNav:f,cancelPendingNav:p,discardAndNavigate:v,saveAndNavigate:j}=a(),A=t(()=>s(!g),[g]),Y=c("screen",o);return l?/* @__PURE__ */u("div",{className:"sf-msg",children:Y.loading}):d?/* @__PURE__ */u("div",{className:"sf-msg sf-msg--error",children:d}):m?i?e(
7
- /* @__PURE__ */u(k,{config:r,data:i,onChange:h,permissions:A,parts:n,children:/* @__PURE__ */u(N,{})}),f&&/* @__PURE__ */u(C,{onCancel:p,onDiscard:v,onSave:j})):/* @__PURE__ */u("div",{className:"sf-msg",children:Y.loading}):/* @__PURE__ */u("div",{className:"sf-msg",children:Y.waitingForAuthorization})}export{A as DocumentScreen,j as ScreenMount};
5
+ /* @__PURE__ */u(f,{variant:"primary",loading:a,onClick:()=>{k()},children:i.save})]}),children:i.body})}function y({target:r,addressing:n,onHostMessage:e,children:a}){/* @__PURE__ */
6
+ return u(i,{target:r,addressing:n,onHostMessage:e,children:a})}var N=(r,n)=>/* @__PURE__ */p(v,{children:[r,n]});function H({config:r,parts:n,wrap:e=N}){const{data:i,error:d,redirecting:l,ready:m,readOnly:g,onChange:h,pendingNav:f,cancelPendingNav:p,discardAndNavigate:v,saveAndNavigate:y}=a(),H=t(()=>s(!g),[g]),O=c("screen",o);return l?/* @__PURE__ */u("div",{className:"sf-msg",children:O.loading}):d?/* @__PURE__ */u("div",{className:"sf-msg sf-msg--error",children:d}):m?i?e(
7
+ /* @__PURE__ */u(k,{config:r,data:i,onChange:h,permissions:H,parts:n,children:/* @__PURE__ */u(C,{})}),f&&/* @__PURE__ */u(j,{onCancel:p,onDiscard:v,onSave:y})):/* @__PURE__ */u("div",{className:"sf-msg",children:O.loading}):/* @__PURE__ */u("div",{className:"sf-msg",children:O.waitingForAuthorization})}export{H as DocumentScreen,y as ScreenMount};
@@ -1,2 +1,2 @@
1
- import{noControlField as e}from"./chunk-INRERJU4.js";import{DEFAULT_SCREEN_WORDS as n}from"./chunk-EB6NI2VK.js";import{useWords as r}from"./chunk-MFIRYGHW.js";import{usePreviewDevice as t}from"./chunk-BSPCSC45.js";import{jsx as o}from"react/jsx-runtime";function i(e){return"mobile"===e?"mobile":"desktop"}var c={desktop:null,tablet:n.deviceNote.tablet,mobile:n.deviceNote.mobile},u="data-sf-device-hidden";function d(){/* @__PURE__ */
1
+ import{noControlField as e}from"./chunk-INRERJU4.js";import{DEFAULT_SCREEN_WORDS as n}from"./chunk-IYHO4XQX.js";import{useWords as r}from"./chunk-MFIRYGHW.js";import{usePreviewDevice as t}from"./chunk-BSPCSC45.js";import{jsx as o}from"react/jsx-runtime";function i(e){return"mobile"===e?"mobile":"desktop"}var c={desktop:null,tablet:n.deviceNote.tablet,mobile:n.deviceNote.mobile},u="data-sf-device-hidden";function d(){/* @__PURE__ */
2
2
  return o("span",{hidden:!0,[u]:""})}function s({tier:e,render:n,...r}){return i(t())===e?/* @__PURE__ */o(n,{...r}):/* @__PURE__ */o(d,{})}var m="__device";function f(e){const n=e?.[m];return n??null}function l(e){return f(e)?.inner??e}function a(e,n){const r=n.render;return{...n,[m]:{tier:e,inner:n},render:n=>/* @__PURE__ */o(s,{tier:e,render:r,...n})}}function p(){const e=r("screen",n).deviceNote,i=t(),c="desktop"===i?null:e[i];return c?/* @__PURE__ */o("div",{className:"sf-device-scope",children:c}):/* @__PURE__ */o(d,{})}function v(){return e({type:"custom",render:()=>/* @__PURE__ */o(p,{})},"always")}export{m as DEVICE_FIELD_MARKER,u as DEVICE_HIDDEN_ATTR,c as DEVICE_NOTE,a as deviceField,f as deviceMetaOf,v as deviceNote,i as shownTier,l as withoutDeviceGate};
@@ -0,0 +1 @@
1
+ import{useSectionOps as o}from"./chunk-FOOK54T2.js";import{SELECTION_MODE as e}from"./chunk-GXRS52JD.js";import{decodePartId as r,encodePartId as t}from"./chunk-R4AUZVA3.js";import{useEasel as n}from"./chunk-KXTXYINN.js";import{usePreviewParts as p}from"./chunk-467WWV4I.js";import{useCallback as d,useEffect as c}from"react";var s=o=>"part"===o.kind;function m({mode:m,setMode:i,onOpenPart:a}){const{getSelectorForId:u}=n(o=>o),I=o(),{setSelectedPartId:f,setSelectHandler:k}=p(),l=d(o=>{const t=r(o);if(!t)return;const{nodeId:n,propKey:p}=t;p?(i(o=>s(o)&&o.nodeId===n&&o.propKey===p?o:{kind:"part",nodeId:n,propKey:p}),a?.(n)):i(o=>"part"===o.kind?e:o)},[i,a]);c(()=>{k(l)},[k,l]);const K=s(m)?t(m.nodeId,m.propKey):null;c(()=>{f(K)},[K,f]);return{selectNode:d(o=>{i(()=>e);const r=u(o);r&&I.select(r)},[i,u,I]),openPartId:K}}export{m as usePartBridge};
@@ -1 +1 @@
1
- import{zoneKey as e}from"./chunk-K7BTCBWD.js";import{useRef as t,useEffect as n,useState as r,useSyncExternalStore as o,useCallback as i}from"react";var l=56,c=16;function a(e){const t=Math.max(e,0);return t>=l?0:Math.ceil(16*(1-t/l))}function u(e,t,n){if(e<t-l||e>n+l)return 0;const r=e-t,o=n-e;return r<l&&r<=o?-a(r):o<l?a(o):0}function s(e){const t=e?.ownerDocument?.defaultView;for(let n=e?.parentElement??null;n;n=n.parentElement){const e=t?.getComputedStyle(n).overflowY;if(("auto"===e||"scroll"===e)&&n.scrollHeight>n.clientHeight)return n}return null}function f(e){const t=e?.ownerDocument?.defaultView?.getComputedStyle(e).overflowY;return e&&("auto"===t||"scroll"===t)&&e.scrollHeight>e.clientHeight?e:s(e)}function d(e){const t=e.scrollingElement??e.documentElement;return t&&t.scrollHeight>t.clientHeight?t:null}function g(e,t=e){const n=t.ownerDocument,r=n.defaultView;if(!r)return()=>{};let o=null,i=0;const l=e=>{o=e.clientY},c=()=>{if(null!==o){const n=t.getBoundingClientRect(),r=u(o,n.top,n.bottom);r&&(e.scrollTop+=r)}i=r.requestAnimationFrame(c)};return n.addEventListener("dragover",l,!0),i=r.requestAnimationFrame(c),()=>{n.removeEventListener("dragover",l,!0),r.cancelAnimationFrame(i)}}function p(e){return/move|all|uninitialized/i.test(e)?"move":"copy"}function m(){let e=null,t=null;const n=/* @__PURE__ */new Set,r=()=>{if(t!==e){t=e;for(const e of[...n])e()}};return{get:()=>e,shown:()=>t,start(t){e=t,globalThis.setTimeout(r,0)},end(){null===e&&null===t||(e=null,r())},subscribe:e=>(n.add(e),()=>{n.delete(e)})}}function v(e,t,n,r){if(e.into)return{side:"into",to:e.into};return"first"===e.pinned||"last"!==e.pinned&&t>n+r/2?{side:"after",to:{...e.place,index:e.place.index+1}}:{side:"before",to:{...e.place,index:e.place.index}}}var D=(t,n)=>e(t)===e(n);function w(e,t){return D(e,t)&&(t.index===e.index||t.index===e.index+1)}function y(e,t){return D(e,t)&&e.index<t.index?t.index-1:t.index}function x(e,t){return{...e,index:t<0?e.index-1:e.index+2}}function h(e,t){if(!t)return e;const n={...t,...e};for(const[r,o]of Object.entries(e)){const e=t[r];"function"==typeof o&&"function"==typeof e&&(n[r]=t=>{o(t),e(t)})}return n}function T(l){const c=t(l);n(()=>{c.current=l});const[a]=r(()=>m()),u=l.session??a,d=o(u.subscribe,u.shown,u.shown),[D,y]=r(null),x=t(null),T=i(()=>{x.current?.(),x.current=null},[]),b=i(()=>{T(),u.end(),y(null)},[u,T]);n(()=>u.subscribe(()=>{u.get()||(T(),y(null))}),[u,T]),n(()=>T,[T]);const k=i((e,t)=>{y(n=>n&&n.key===e&&n.side===t?n:{key:e,side:t})},[]),E=i(e=>{y(t=>t&&t.key===e?null:t)},[]),A=(e,t,n,r)=>!("into"===n?r===e.key:void 0!==e.from&&w(e.from,t))&&c.current.canDrop(e.item,t);return{dragging:d?.item??null,row:(e,t)=>{const{keyOf:n,readOnly:r}=c.current,o=n(e.item),i=!r&&!e.pinned&&!1!==e.canDrag,l=t=>{const n=t.currentTarget.getBoundingClientRect();return v(e,t.clientY,n.top,n.height)},a={draggable:i||void 0,onDragStart:i?t=>{const n=t.currentTarget;u.start({key:o,item:e.item,from:e.place}),t.dataTransfer.effectAllowed="move";try{t.dataTransfer.setData("text/plain",o)}catch{}n.classList.add("is-lifting");const r=n.getBoundingClientRect();t.dataTransfer.setDragImage?.(n,t.clientX-r.left,t.clientY-r.top),n.ownerDocument.defaultView?.setTimeout(()=>n.classList.remove("is-lifting"),0);const i=s(n);T(),x.current=i?g(i):null}:void 0,onDragEnd:i?()=>b():void 0,onDragOver:e=>{const t=u.get();if(!t)return;const n=l(e);A(t,n.to,n.side,o)?(e.preventDefault(),e.dataTransfer.dropEffect=p(e.dataTransfer.effectAllowed),k(o,n.side)):E(o)},onDrop:e=>{const t=u.get();if(!t)return;const n=l(e);A(t,n.to,n.side,o)&&(e.preventDefault(),b(),c.current.onDrop(t.item,n.to))},onKeyDown:t=>{if("ArrowUp"!==t.key&&"ArrowDown"!==t.key)return;if(!t.altKey||t.ctrlKey||t.metaKey||t.shiftKey)return;if(t.preventDefault(),t.repeat||!i)return;const{onStep:n,canStep:r}=c.current,o="ArrowUp"===t.key?-1:1;n&&!1!==r?.(e.item,o)&&n(e.item,o)}};return{draggable:i,dragging:d?.key===o,drop:D?.key===o?D.side:void 0,rowProps:h(a,t)}},seam:(t,n)=>{const r=(o=t.place,`seam:${e(o)}:${o.index}`);var o;const i={onDragOver:e=>{const n=u.get();n&&(A(n,t.place,"before",r)?(e.preventDefault(),e.dataTransfer.dropEffect=p(e.dataTransfer.effectAllowed),k(r,"before")):E(r))},onDrop:e=>{const n=u.get();n&&A(n,t.place,"before",r)&&(e.preventDefault(),b(),c.current.onDrop(n.item,t.place))}};return{drop:D?.key===r,seamProps:h(i,n)}},rootProps:e=>h({onDragEnter:e=>{if(!u.get()||x.current)return;const t=f(e.currentTarget);x.current=t?g(t):null},onDragLeave:e=>{const t=e.relatedTarget;t&&e.currentTarget.contains(t)||y(null)}},e)}}export{l as AUTO_SCROLL_EDGE,c as AUTO_SCROLL_MAX_SPEED,u as autoScrollDelta,a as autoScrollSpeed,m as createDragSession,p as dropEffectFor,v as dropOnRow,d as frameScrollBox,y as gapToMoveIndex,w as isNoOpDrop,f as scrollBoxOf,s as scrollParent,g as startAutoScroll,x as stepGap,T as useTreeDrag};
1
+ import{zoneKey as e}from"./chunk-TGZCD6IP.js";import{useRef as t,useEffect as n,useState as r,useSyncExternalStore as o,useCallback as i}from"react";var l=56,c=16;function a(e){const t=Math.max(e,0);return t>=l?0:Math.ceil(16*(1-t/l))}function u(e,t,n){if(e<t-l||e>n+l)return 0;const r=e-t,o=n-e;return r<l&&r<=o?-a(r):o<l?a(o):0}function s(e){const t=e?.ownerDocument?.defaultView;for(let n=e?.parentElement??null;n;n=n.parentElement){const e=t?.getComputedStyle(n).overflowY;if(("auto"===e||"scroll"===e)&&n.scrollHeight>n.clientHeight)return n}return null}function f(e){const t=e?.ownerDocument?.defaultView?.getComputedStyle(e).overflowY;return e&&("auto"===t||"scroll"===t)&&e.scrollHeight>e.clientHeight?e:s(e)}function d(e){const t=e.scrollingElement??e.documentElement;return t&&t.scrollHeight>t.clientHeight?t:null}function g(e,t=e){const n=t.ownerDocument,r=n.defaultView;if(!r)return()=>{};let o=null,i=0;const l=e=>{o=e.clientY},c=()=>{if(null!==o){const n=t.getBoundingClientRect(),r=u(o,n.top,n.bottom);r&&(e.scrollTop+=r)}i=r.requestAnimationFrame(c)};return n.addEventListener("dragover",l,!0),i=r.requestAnimationFrame(c),()=>{n.removeEventListener("dragover",l,!0),r.cancelAnimationFrame(i)}}function p(e){return/move|all|uninitialized/i.test(e)?"move":"copy"}function m(){let e=null,t=null;const n=/* @__PURE__ */new Set,r=()=>{if(t!==e){t=e;for(const e of[...n])e()}};return{get:()=>e,shown:()=>t,start(t){e=t,globalThis.setTimeout(r,0)},end(){null===e&&null===t||(e=null,r())},subscribe:e=>(n.add(e),()=>{n.delete(e)})}}function v(e,t,n,r){if(e.into)return{side:"into",to:e.into};return"first"===e.pinned||"last"!==e.pinned&&t>n+r/2?{side:"after",to:{...e.place,index:e.place.index+1}}:{side:"before",to:{...e.place,index:e.place.index}}}var D=(t,n)=>e(t)===e(n);function w(e,t){return D(e,t)&&(t.index===e.index||t.index===e.index+1)}function y(e,t){return D(e,t)&&e.index<t.index?t.index-1:t.index}function x(e,t){return{...e,index:t<0?e.index-1:e.index+2}}function h(e,t){if(!t)return e;const n={...t,...e};for(const[r,o]of Object.entries(e)){const e=t[r];"function"==typeof o&&"function"==typeof e&&(n[r]=t=>{o(t),e(t)})}return n}function T(l){const c=t(l);n(()=>{c.current=l});const[a]=r(()=>m()),u=l.session??a,d=o(u.subscribe,u.shown,u.shown),[D,y]=r(null),x=t(null),T=i(()=>{x.current?.(),x.current=null},[]),b=i(()=>{T(),u.end(),y(null)},[u,T]);n(()=>u.subscribe(()=>{u.get()||(T(),y(null))}),[u,T]),n(()=>T,[T]);const k=i((e,t)=>{y(n=>n&&n.key===e&&n.side===t?n:{key:e,side:t})},[]),E=i(e=>{y(t=>t&&t.key===e?null:t)},[]),A=(e,t,n,r)=>!("into"===n?r===e.key:void 0!==e.from&&w(e.from,t))&&c.current.canDrop(e.item,t);return{dragging:d?.item??null,row:(e,t)=>{const{keyOf:n,readOnly:r}=c.current,o=n(e.item),i=!r&&!e.pinned&&!1!==e.canDrag,l=t=>{const n=t.currentTarget.getBoundingClientRect();return v(e,t.clientY,n.top,n.height)},a={draggable:i||void 0,onDragStart:i?t=>{const n=t.currentTarget;u.start({key:o,item:e.item,from:e.place}),t.dataTransfer.effectAllowed="move";try{t.dataTransfer.setData("text/plain",o)}catch{}n.classList.add("is-lifting");const r=n.getBoundingClientRect();t.dataTransfer.setDragImage?.(n,t.clientX-r.left,t.clientY-r.top),n.ownerDocument.defaultView?.setTimeout(()=>n.classList.remove("is-lifting"),0);const i=s(n);T(),x.current=i?g(i):null}:void 0,onDragEnd:i?()=>b():void 0,onDragOver:e=>{const t=u.get();if(!t)return;const n=l(e);A(t,n.to,n.side,o)?(e.preventDefault(),e.dataTransfer.dropEffect=p(e.dataTransfer.effectAllowed),k(o,n.side)):E(o)},onDrop:e=>{const t=u.get();if(!t)return;const n=l(e);A(t,n.to,n.side,o)&&(e.preventDefault(),b(),c.current.onDrop(t.item,n.to))},onKeyDown:t=>{if("ArrowUp"!==t.key&&"ArrowDown"!==t.key)return;if(!t.altKey||t.ctrlKey||t.metaKey||t.shiftKey)return;if(t.preventDefault(),t.repeat||!i)return;const{onStep:n,canStep:r}=c.current,o="ArrowUp"===t.key?-1:1;n&&!1!==r?.(e.item,o)&&n(e.item,o)}};return{draggable:i,dragging:d?.key===o,drop:D?.key===o?D.side:void 0,rowProps:h(a,t)}},seam:(t,n)=>{const r=(o=t.place,`seam:${e(o)}:${o.index}`);var o;const i={onDragOver:e=>{const n=u.get();n&&(A(n,t.place,"before",r)?(e.preventDefault(),e.dataTransfer.dropEffect=p(e.dataTransfer.effectAllowed),k(r,"before")):E(r))},onDrop:e=>{const n=u.get();n&&A(n,t.place,"before",r)&&(e.preventDefault(),b(),c.current.onDrop(n.item,t.place))}};return{drop:D?.key===r,seamProps:h(i,n)}},rootProps:e=>h({onDragEnter:e=>{if(!u.get()||x.current)return;const t=f(e.currentTarget);x.current=t?g(t):null},onDragLeave:e=>{const t=e.relatedTarget;t&&e.currentTarget.contains(t)||y(null)}},e)}}export{l as AUTO_SCROLL_EDGE,c as AUTO_SCROLL_MAX_SPEED,u as autoScrollDelta,a as autoScrollSpeed,m as createDragSession,p as dropEffectFor,v as dropOnRow,d as frameScrollBox,y as gapToMoveIndex,w as isNoOpDrop,f as scrollBoxOf,s as scrollParent,g as startAutoScroll,x as stepGap,T as useTreeDrag};
@@ -1,2 +1,2 @@
1
- import{routeSharedHostMessage as e}from"./chunk-77IWWW6X.js";import{describeLoadFailure as r,hostLoadRefusal as n}from"./chunk-ERR437B5.js";import{editLockOf as t}from"./chunk-GMCZXMOV.js";import{NO_DOCUMENT_ADDRESSING as o}from"./chunk-RLBXE4EU.js";import{saveStatusOf as u,resetForDocumentSwitch as a}from"./chunk-HNKB2ZYR.js";import{isExpiredSession as s,readEaselFailure as i}from"./chunk-CLOS6SSX.js";import{useAdminBridge as l}from"./chunk-BIK3AO2V.js";import{STATUS_UNREACHABLE as c}from"./chunk-KCOBHPN6.js";import{useEaselSession as d}from"./chunk-YM4UEGBV.js";import{backendOf as f,setSessionDocumentSite as m}from"./chunk-SNF5764Q.js";import{useEaselHost as k}from"./chunk-MQA7OFRA.js";import{DEFAULT_SCREEN_WORDS as v}from"./chunk-EB6NI2VK.js";import{useAutosave as g}from"./chunk-NDRZP6YR.js";import{canWriteDocument as p,newEaselClientId as h,reloadIfVersionMoved as y,openUnansweredClaim as w,FAIL_OPEN_RETRY_MS as b,CLAIM_FAIL_OPEN_MS as S,holderOf as I}from"./chunk-THWO5YVZ.js";import{useWords as P}from"./chunk-MFIRYGHW.js";import{createContext as j,useContext as B,useState as R,useMemo as E,useCallback as O,useEffect as H,useRef as A}from"react";import{jsx as C}from"react/jsx-runtime";var M={content:[],root:{},zones:{}};var N=j(null);function T(){const e=B(N);if(!e)throw new Error("useStorefrontDocument must be used within StorefrontDocumentProvider");return e}function V({target:j,addressing:B=o,onHostMessage:T,children:V}){const F=B,{homeSlug:D,entryMayBounce:L,entryBounce:W,onSwitch:Y,tellsHost:K,adapterFor:U,migrateRenamedProps:X,describeMissing:Z,onLoadFailed:x}=F,[G,Q]=R(j),z=k(),_=d(),q=E(()=>f(_),[_]),J=E(()=>t(_),[_]),$="template"===G.kind,ee="template"===G.kind?G.id:null,re="template"===G.kind?G.pageSlug??D??"":"document"===G.kind?G.slug??"":G.slug,ne="page"===G.kind?G.siteId??null:null,te=_.blocks,oe=E(()=>U(G,q,te),[U,q,te,G.kind,"template"===G.kind?G.id:"document"===G.kind?G.record:G.siteId]),ue=oe.capabilities,ae=O(e=>_.documentHooks?.stored?.(e)??e,[_]);H(()=>{m(_,ne)},[_,ne]);const se=A(G);H(()=>{se.current=G},[G]);const{token:ie,tokenRef:le,capabilities:ce}=l({onMessage:r=>{if(T?.(r)||e(r))return;const n=r;if("storefront-editor:navigate"===n?.type){const e=r;e?.target&&Rr(e.target)}}}),de=!_.usesBridgedToken||null!==ie,fe=oe.lock,me=Boolean(q.lock),[ke,ve]=R(null),[ge,pe]=R(null),[he,ye]=R(null),[we,be]=R(null),Se=P("screen",v),Ie=we?function(e,r){if(null!==e.sentence)return e.sentence;if(!e.missing)return r.loadFailed({cause:e.cause});switch(e.target.kind){case"template":return r.missingTemplatePage;case"document":return r.missingDocument;default:return r.missingPage({slug:e.slug})}}(we,Se):null,[Pe,je]=R(null),Be=A(null),Re=A(null),[Ee,Oe]=R(!1),He=A(null),[Ae,Ce]=R(null),Me=A(null),[Ne,Te]=R(null),[Ve,Fe]=R(!1),De=A(null);H(()=>{De.current=Ne},[Ne]);const[Le,We]=R(ue.hasEditLock?{kind:"checking"}:{kind:"editing"}),Ye=A(Le);H(()=>{Ye.current=Le},[Le]);const Ke=A(()=>Promise.resolve(!1)),Ue=O(e=>{Re.current=e,Oe(!0)},[]),Xe=g({save:async({id:e,data:r})=>{if(p(Ye.current)){if(!await Ke.current(e,r)){if(!p(Ye.current))return void Ue({id:e,data:r});throw new Error("page save did not land")}}else Ue({id:e,data:r})},onFailure:(e,r)=>{0===r&&z.send("storefront-editor:save-failed")}}),{state:Ze,push:xe,flush:Ge,pause:Qe,resume:ze,stop:_e,reset:qe,retryNow:Je,hasPending:$e}=Xe,er=A(Ze);H(()=>{er.current=Ze},[Ze]);const rr=u(Ze),nr=O(()=>{const e=Re.current;e&&(Re.current=null,Oe(!1),xe(e))},[xe]),tr=A("");tr.current||(tr.current=h());const[or,ur]=R(0),ar=A(!1),[sr,ir]=R(L(j)),lr=A(!1);H(()=>{if(lr.current)return;lr.current=!0;const e=z.address.search(),r=W(j,e);r?z.address.load(r):L(j)&&ir(!1)},[j,z]);const cr=z.send;H(()=>{if(!de)return;let e=!1;const t=se.current,o=oe.resolve(re),u=_.documentHooks?.opening?.({slug:re,isTemplate:$,capabilities:ue});return o.then(async r=>{if(e)return;if(!r)return"page"===t.kind&&null!==D&&re!==D?void z.address.load({kind:"page",slug:D,siteId:ne??void 0}):(be({target:t,slug:re,missing:!0,sentence:Z?.(t)??null}),void x?.(t,null));const n=r.readOnlyReason?r.readOnlyReason:null;Be.current=n,je(n),ve(r.id),pe(r.kind??null),Me.current=r.version??null;const o=r.layout,a=o&&Object.keys(o).length?o:M,s=X(a),i=u?await u(s):s;e||ye(i)}).catch(o=>{e||(console.error("[storefront-editor] document load failed",o),be({target:t,slug:re,missing:!1,sentence:n(o,{slug:re},_),cause:r(o,_)}),x?.(t,o))}),()=>{e=!0}},[de,ie,$,oe,re]);const dr=O(e=>new Promise(r=>{const n=Date.now(),t=setInterval(()=>{const o=le.current;o&&o!==e?(clearInterval(t),r(o)):Date.now()-n>6e3&&(clearInterval(t),r(null))},200)}),[]),fr=O(async e=>{const r=le.current;if(!r&&_.usesBridgedToken)return{ok:!1,error:new Error("no editor token")};try{return{ok:!0,value:await e(r??"")}}catch(n){if(s(n,_)){cr("storefront-editor:auth-expired");const n=r?await dr(r):null;if(n)try{return{ok:!0,value:await e(n)}}catch(e){return{ok:!1,error:e}}}return{ok:!1,error:n}}},[cr,dr,_]),mr=O(async e=>{const r=le.current?await fr(e):{ok:!1};return r.ok||cr("storefront-editor:save-failed"),r.ok},[cr,fr]),kr=O(async(e,r,n=!1)=>{if(null!==Be.current)return!1;if(!p(Ye.current))return!1;if(De.current)return!1;const t=await fr(()=>oe.saveLayout(e,r,Me.current,tr.current));if(t.ok)return Me.current=t.value.version??Me.current,Fe(!1),!0;const o=J.readLockTaken(t.error);if(o){const e={kind:"takenover",holder:o};return Ye.current=e,We(e),!1}const u=J.readSaveConflict(t.error);if(u){if(u.savedByYou&&!n&&oe.rereadVersion){const n=await fr(()=>oe.rereadVersion(e));if(n.ok&&n.value)return Me.current=n.value,Ke.current(e,r,!0)}_e(),De.current=u,Te(u)}return Fe(i(t.error,_)?.status===c),!1},[oe,fr,_e,_]);H(()=>{Ke.current=kr},[kr]);const vr=O(e=>{if(null!==Be.current)return;if(cr("storefront-editor:dirty"),!ke)return;const r=ae(e);He.current=r,p(Ye.current)?xe({id:ke,data:r}):Ue({id:ke,data:r})},[ke,cr,Ue,xe,ae]),gr=O(async()=>{p(Ye.current)&&nr();return await Ge()&&null==Re.current},[nr,Ge]),pr=A(gr);H(()=>{pr.current=gr},[gr]);const hr=A(fr);H(()=>{hr.current=fr},[fr]);const yr=O(()=>{z.address.reload()},[z]),wr=A(()=>Promise.resolve(!1));H(()=>{wr.current=()=>{const e=oe.rereadVersion;return ke&&e?y({ours:Me.current,stored:async()=>{const r=await hr.current(()=>e(ke));return r.ok?r.value:null},hasPending:()=>null!=Re.current||$e(),reload:yr}):Promise.resolve(!1)}},[oe,ke,$e,yr]);const br=null!==Pe;H(()=>{if(!fe||!ke||!de||br)return;let e=!1,r=null,n=null;const t=tr.current,o={claim:async e=>{const r=await hr.current(()=>fe.claim(ke,t,e));if(r.ok)return{heartbeat_seconds:r.value.heartbeatSeconds};throw r.error},cancelled:()=>e,currentAccess:()=>Ye.current,heldWrite:()=>({pending:null!=Re.current||$e(),autoSaveEnabled:!er.current.paused,saveConflict:null!=De.current}),setAccess:e=>{Ye.current=e,We(e)},releaseHeldWrite:()=>{pr.current()},startHeartbeat:e=>{r&&clearInterval(r),r=setInterval(()=>{u(!1)},e)},stopHeartbeat:()=>{r&&(clearInterval(r),r=null)},reloadIfMoved:()=>{wr.current()}},u=J.makeClaimBeat(o),a=ar.current;return ar.current=!1,a||(We({kind:"checking"}),n=setTimeout(()=>{n=null,w(o)&&o.startHeartbeat(b)},S)),u(a).finally(()=>{n&&clearTimeout(n),n=null}),()=>{e=!0,n&&clearTimeout(n),r&&clearInterval(r),fe.release(ke,t).catch(()=>{})}},[ke,fe,de,ie,or,br]);const Sr=O(()=>{fe&&ke&&(ar.current=!0,ur(e=>e+1))},[ke,fe]),Ir=O(()=>{We(e=>{const r="blocked"===e.kind||"takenover"===e.kind?e.holder:null;return r?{kind:"readonly",holder:r}:e})},[]),Pr=O(()=>{er.current.paused?(p(Ye.current)&&nr(),ze()):Qe()},[nr,Qe,ze]),jr=O(()=>{Je()},[Je]),Br=O(e=>{He.current=null,a("template"!==e.kind&&me,{resetAutosave:()=>{qe(),Re.current=null,Oe(!1)},setVersion:e=>{Me.current=e},setSaveConflict:Te,setAccess:We}),Y(e),Q(e),Be.current=null,je(null),ve(null),pe(null),ye(null),be(null),z.address.show(e),"document"!==e.kind&&K(e)&&z.send("storefront-editor:navigated",{target:e})},[qe,z,me,Y,K]),Rr=O(e=>{if(function(e,r,n){if(e.kind!==r.kind)return!1;if("template"===e.kind){const t=r;return e.id===t.id&&(e.pageSlug??n)===(t.pageSlug??n)}if("document"===e.kind){const n=r;return e.record===n.record&&(e.slug??"")===(n.slug??"")}const t=r;return e.slug===t.slug&&e.siteId===t.siteId}(e,se.current,D))return;const r=null!=Re.current;if(!r&&!$e())return void Br(e);const n=er.current;r||n.paused||n.failed||n.stopped?Ce(e):Ge().then(r=>{r?Br(e):Ce(e)})},[Br,$e,Ge,D]),Er=O(()=>Ce(null),[]),Or=O(()=>{Ce(e=>(e&&Br(e),null))},[Br]),Hr=O(async()=>{const e=Ae;if(!e)return;await gr()&&(Ce(null),Br(e))},[Ae,gr,Br]),Ar=O(async e=>{if(null!==Be.current)return;if(!ke)return;if(!p(Ye.current)||De.current)return;const r=ae(e);if(!await kr(ke,r))return void(De.current||cr("storefront-editor:save-failed"));const n=oe.publish;if(!ue.canPublish||!n)return void cr("storefront-editor:saved");const t=await fr(()=>n(ke,Me.current??void 0));if(!t.ok){const{error:e}=t;return void cr("storefront-editor:publish-failed",{reason:e instanceof Error&&e.message?e.message:null})}Me.current=t.value.version??Me.current,cr("storefront-editor:published")},[ke,oe,ue.canPublish,cr,kr,fr,ae]);/* @__PURE__ */
2
- return C(N.Provider,{value:{target:G,adapter:oe,capabilities:ue,templateId:ee,currentSlug:re,currentKind:ge,siteId:ne,ready:de,token:ie,tokenRef:le,notifyParent:cr,bridgeCapabilities:ce,runAuthed:mr,docId:ke,data:he,getLiveData:()=>He.current??he,error:Ie,redirecting:sr,saveStatus:rr,saveState:Ze,autoSaveEnabled:!Ze.paused,autoSaveStoppedByConflict:Ze.stopped,hasUnsavedEdits:Ze.pending||Ee,toggleAutoSave:Pr,retrySave:jr,onChange:vr,flushSave:gr,onPublish:Ar,access:Le,readOnly:null!==I(Le)||null!==Pe||null!==Ne,readOnlyReason:Pe,takeOverEditing:Sr,viewReadOnly:Ir,saveConflict:Ne,saveUnreachable:Ve,reloadFromServer:yr,navigate:Rr,pendingNav:Ae,cancelPendingNav:Er,discardAndNavigate:Or,saveAndNavigate:Hr},children:V})}export{N as ScreenDocumentContext,V as ScreenDocumentProvider,T as useScreenDocument};
1
+ import{routeSharedHostMessage as e}from"./chunk-77IWWW6X.js";import{describeLoadFailure as r,hostLoadRefusal as n}from"./chunk-ERR437B5.js";import{editLockOf as t}from"./chunk-GMCZXMOV.js";import{NO_DOCUMENT_ADDRESSING as o}from"./chunk-RLBXE4EU.js";import{saveStatusOf as u,resetForDocumentSwitch as a}from"./chunk-HNKB2ZYR.js";import{isExpiredSession as s,readEaselFailure as i}from"./chunk-CLOS6SSX.js";import{useAdminBridge as l}from"./chunk-BIK3AO2V.js";import{STATUS_UNREACHABLE as c}from"./chunk-KCOBHPN6.js";import{useEaselSession as d}from"./chunk-YM4UEGBV.js";import{backendOf as f,setSessionDocumentSite as m}from"./chunk-SNF5764Q.js";import{useEaselHost as k}from"./chunk-MQA7OFRA.js";import{DEFAULT_SCREEN_WORDS as v}from"./chunk-IYHO4XQX.js";import{useAutosave as g}from"./chunk-NDRZP6YR.js";import{canWriteDocument as p,newEaselClientId as h,reloadIfVersionMoved as y,openUnansweredClaim as w,FAIL_OPEN_RETRY_MS as b,CLAIM_FAIL_OPEN_MS as S,holderOf as I}from"./chunk-THWO5YVZ.js";import{useWords as P}from"./chunk-MFIRYGHW.js";import{createContext as j,useContext as R,useState as B,useMemo as O,useCallback as E,useEffect as H,useRef as A}from"react";import{jsx as C}from"react/jsx-runtime";var M={content:[],root:{},zones:{}};var N=j(null);function T(){const e=R(N);if(!e)throw new Error("useStorefrontDocument must be used within StorefrontDocumentProvider");return e}function F({target:j,addressing:R=o,onHostMessage:T,children:F}){const V=R,{homeSlug:D,entryMayBounce:L,entryBounce:W,onSwitch:Y,tellsHost:X,adapterFor:K,migrateRenamedProps:U,describeMissing:Z,onLoadFailed:x}=V,[G,Q]=B(j),z=k(),_=d(),q=O(()=>f(_),[_]),J=O(()=>t(_),[_]),$="template"===G.kind,ee="template"===G.kind?G.id:null,re="template"===G.kind?G.pageSlug??D??"":"document"===G.kind?G.slug??"":G.slug,ne="page"===G.kind?G.siteId??null:null,te=_.blocks,oe=O(()=>K(G,q,te),[K,q,te,G.kind,"template"===G.kind?G.id:"document"===G.kind?G.record:G.siteId]),ue=oe.capabilities,ae=E(e=>_.documentHooks?.stored?.(e)??e,[_]);H(()=>{m(_,ne)},[_,ne]);const se=A(G);H(()=>{se.current=G},[G]);const{token:ie,tokenRef:le,capabilities:ce}=l({onMessage:r=>{if(T?.(r)||e(r))return;const n=r;if("storefront-editor:navigate"===n?.type){const e=r;e?.target&&Br(e.target)}}}),de=!_.usesBridgedToken||null!==ie,fe=oe.lock,me=Boolean(q.lock),[ke,ve]=B(null),[ge,pe]=B(null),[he,ye]=B(null),[we,be]=B(null),Se=P("screen",v),Ie=we?function(e,r){if(null!==e.sentence)return e.sentence;if(!e.missing)return r.loadFailed({cause:e.cause});switch(e.target.kind){case"template":return r.missingTemplatePage;case"document":return r.missingDocument;default:return r.missingPage({slug:e.slug})}}(we,Se):null,[Pe,je]=B(null),Re=A(null),Be=A(null),[Oe,Ee]=B(!1),He=A(null),[Ae,Ce]=B(null),Me=A(null),[Ne,Te]=B(null),[Fe,Ve]=B(!1),De=A(null);H(()=>{De.current=Ne},[Ne]);const[Le,We]=B(ue.hasEditLock?{kind:"checking"}:{kind:"editing"}),Ye=A(Le);H(()=>{Ye.current=Le},[Le]);const Xe=A(()=>Promise.resolve(!1)),Ke=E(e=>{Be.current=e,Ee(!0)},[]),Ue=g({save:async({id:e,data:r})=>{if(p(Ye.current)){if(!await Xe.current(e,r)){if(!p(Ye.current))return void Ke({id:e,data:r});throw new Error("page save did not land")}}else Ke({id:e,data:r})},onFailure:(e,r)=>{0===r&&z.send("storefront-editor:save-failed")}}),{state:Ze,push:xe,flush:Ge,pause:Qe,resume:ze,stop:_e,reset:qe,retryNow:Je,hasPending:$e}=Ue,er=A(Ze);H(()=>{er.current=Ze},[Ze]);const rr=u(Ze),nr=E(()=>{const e=Be.current;e&&(Be.current=null,Ee(!1),xe(e))},[xe]),tr=A("");tr.current||(tr.current=h());const[or,ur]=B(0),ar=A(!1),[sr,ir]=B(L(j)),lr=A(!1);H(()=>{if(lr.current)return;lr.current=!0;const e=z.address.search(),r=W(j,e);r?z.address.load(r):L(j)&&ir(!1)},[j,z]);const cr=z.send;H(()=>{if(!de)return;let e=!1;const t=se.current,o=oe.resolve(re),u=_.documentHooks?.opening?.({slug:re,isTemplate:$,capabilities:ue});return o.then(async r=>{if(e)return;if(!r)return"page"===t.kind&&null!==D&&re!==D?void z.address.load({kind:"page",slug:D,siteId:ne??void 0}):(be({target:t,slug:re,missing:!0,sentence:Z?.(t)??null}),void x?.(t,null));const n=r.readOnlyReason?r.readOnlyReason:null;Re.current=n,je(n),ve(r.id),pe(r.kind??null),Me.current=r.version??null;const o=r.layout,a=o&&Object.keys(o).length?o:M,s=U(a),i=u?await u(s):s;e||ye(i)}).catch(o=>{e||(console.error("[storefront-editor] document load failed",o),be({target:t,slug:re,missing:!1,sentence:n(o,{slug:re},_),cause:r(o,_)}),x?.(t,o))}),()=>{e=!0}},[de,ie,$,oe,re]);const dr=E(e=>new Promise(r=>{const n=Date.now(),t=setInterval(()=>{const o=le.current;o&&o!==e?(clearInterval(t),r(o)):Date.now()-n>6e3&&(clearInterval(t),r(null))},200)}),[]),fr=E(async e=>{const r=le.current;if(!r&&_.usesBridgedToken)return{ok:!1,error:new Error("no editor token")};try{return{ok:!0,value:await e(r??"")}}catch(n){if(s(n,_)){cr("storefront-editor:auth-expired");const n=r?await dr(r):null;if(n)try{return{ok:!0,value:await e(n)}}catch(e){return{ok:!1,error:e}}}return{ok:!1,error:n}}},[cr,dr,_]),mr=E(async e=>{const r=le.current?await fr(e):{ok:!1};return r.ok||cr("storefront-editor:save-failed"),r.ok},[cr,fr]),kr=E(async(e,r,n=!1)=>{if(null!==Re.current)return!1;if(!p(Ye.current))return!1;if(De.current)return!1;const t=await fr(()=>oe.saveLayout(e,r,Me.current,tr.current));if(t.ok)return Me.current=t.value.version??Me.current,Ve(!1),!0;const o=J.readLockTaken(t.error);if(o){const e={kind:"takenover",holder:o};return Ye.current=e,We(e),!1}const u=J.readSaveConflict(t.error);if(u){if(u.savedByYou&&!n&&oe.rereadVersion){const n=await fr(()=>oe.rereadVersion(e));if(n.ok&&n.value)return Me.current=n.value,Xe.current(e,r,!0)}_e(),De.current=u,Te(u)}return Ve(i(t.error,_)?.status===c),!1},[oe,fr,_e,_]);H(()=>{Xe.current=kr},[kr]);const vr=E(e=>{if(null!==Re.current)return;if(cr("storefront-editor:dirty"),!ke)return;const r=ae(e);He.current=r,p(Ye.current)?xe({id:ke,data:r}):Ke({id:ke,data:r})},[ke,cr,Ke,xe,ae]),gr=E(async()=>{p(Ye.current)&&nr();return await Ge()&&null==Be.current},[nr,Ge]),pr=A(gr);H(()=>{pr.current=gr},[gr]);const hr=A(fr);H(()=>{hr.current=fr},[fr]);const yr=E(()=>{z.address.reload()},[z]),wr=A(()=>Promise.resolve(!1));H(()=>{wr.current=()=>{const e=oe.rereadVersion;return ke&&e?y({ours:Me.current,stored:async()=>{const r=await hr.current(()=>e(ke));return r.ok?r.value:null},hasPending:()=>null!=Be.current||$e(),reload:yr}):Promise.resolve(!1)}},[oe,ke,$e,yr]);const br=null!==Pe;H(()=>{if(!fe||!ke||!de||br)return;let e=!1,r=null,n=null;const t=tr.current,o={claim:async e=>{const r=await hr.current(()=>fe.claim(ke,t,e));if(r.ok)return{heartbeat_seconds:r.value.heartbeatSeconds};throw r.error},cancelled:()=>e,currentAccess:()=>Ye.current,heldWrite:()=>({pending:null!=Be.current||$e(),autoSaveEnabled:!er.current.paused,saveConflict:null!=De.current}),setAccess:e=>{Ye.current=e,We(e)},releaseHeldWrite:()=>{pr.current()},startHeartbeat:e=>{r&&clearInterval(r),r=setInterval(()=>{u(!1)},e)},stopHeartbeat:()=>{r&&(clearInterval(r),r=null)},reloadIfMoved:()=>{wr.current()}},u=J.makeClaimBeat(o),a=ar.current;return ar.current=!1,a||(We({kind:"checking"}),n=setTimeout(()=>{n=null,w(o)&&o.startHeartbeat(b)},S)),u(a).finally(()=>{n&&clearTimeout(n),n=null}),()=>{e=!0,n&&clearTimeout(n),r&&clearInterval(r),fe.release(ke,t).catch(()=>{})}},[ke,fe,de,ie,or,br]);const Sr=E(()=>{fe&&ke&&(ar.current=!0,ur(e=>e+1))},[ke,fe]),Ir=E(()=>{We(e=>{const r="blocked"===e.kind||"takenover"===e.kind?e.holder:null;return r?{kind:"readonly",holder:r}:e})},[]),Pr=E(()=>{er.current.paused?(p(Ye.current)&&nr(),ze()):Qe()},[nr,Qe,ze]),jr=E(()=>{Je()},[Je]),Rr=E(e=>{He.current=null,a("template"!==e.kind&&me,{resetAutosave:()=>{qe(),Be.current=null,Ee(!1)},setVersion:e=>{Me.current=e},setSaveConflict:Te,setAccess:We}),Y(e),Q(e),Re.current=null,je(null),ve(null),pe(null),ye(null),be(null),z.address.show(e),"document"!==e.kind&&X(e)&&z.send("storefront-editor:navigated",{target:e})},[qe,z,me,Y,X]),Br=E(e=>{if(function(e,r,n){if(e.kind!==r.kind)return!1;if("template"===e.kind){const t=r;return e.id===t.id&&(e.pageSlug??n)===(t.pageSlug??n)}if("document"===e.kind){const n=r;return e.record===n.record&&(e.slug??"")===(n.slug??"")}const t=r;return e.slug===t.slug&&e.siteId===t.siteId}(e,se.current,D))return;const r=null!=Be.current;if(!r&&!$e())return void Rr(e);const n=er.current;r||n.paused||n.failed||n.stopped?Ce(e):Ge().then(r=>{r?Rr(e):Ce(e)})},[Rr,$e,Ge,D]),Or=E(()=>Ce(null),[]),Er=E(()=>{Ce(e=>(e&&Rr(e),null))},[Rr]),Hr=E(async()=>{const e=Ae;if(!e)return;await gr()&&(Ce(null),Rr(e))},[Ae,gr,Rr]),Ar=E(async e=>{if(null!==Re.current)return;if(!ke)return;if(!p(Ye.current)||De.current)return;const r=ae(e);if(!await kr(ke,r))return void(De.current||cr("storefront-editor:save-failed"));const n=oe.publish;if(!ue.canPublish||!n)return void cr("storefront-editor:saved");const t=await fr(()=>n(ke,Me.current??void 0));if(!t.ok){const{error:e}=t;return void cr("storefront-editor:publish-failed",{reason:e instanceof Error&&e.message?e.message:null})}Me.current=t.value.version??Me.current,cr("storefront-editor:published")},[ke,oe,ue.canPublish,cr,kr,fr,ae]);/* @__PURE__ */
2
+ return C(N.Provider,{value:{target:G,adapter:oe,capabilities:ue,templateId:ee,currentSlug:re,currentKind:ge,siteId:ne,ready:de,token:ie,tokenRef:le,notifyParent:cr,bridgeCapabilities:ce,runAuthed:mr,docId:ke,data:he,getLiveData:()=>He.current??he,error:Ie,redirecting:sr,saveStatus:rr,saveState:Ze,autoSaveEnabled:!Ze.paused,autoSaveStoppedByConflict:Ze.stopped,hasUnsavedEdits:Ze.pending||Oe,toggleAutoSave:Pr,retrySave:jr,onChange:vr,flushSave:gr,onPublish:Ar,access:Le,readOnly:null!==I(Le)||null!==Pe||null!==Ne,readOnlyReason:Pe,takeOverEditing:Sr,viewReadOnly:Ir,saveConflict:Ne,saveUnreachable:Fe,reloadFromServer:yr,navigate:Br,pendingNav:Ae,cancelPendingNav:Or,discardAndNavigate:Er,saveAndNavigate:Hr},children:F})}export{N as ScreenDocumentContext,F as ScreenDocumentProvider,T as useScreenDocument};
@@ -1 +1 @@
1
- import{changedProps as e}from"./chunk-K7BTCBWD.js";import{useState as t,useRef as r,useEffect as n}from"react";function i({id:i,node:l,block:d,parent:o=null,appState:a=null}){const u=d?.fields??{},[s,c]=t(()=>({id:i,fields:u,loading:!1})),p=r(null),f=r(null),g=r({parent:o,appState:a,id:i});return g.current={parent:o,appState:a,id:i},n(()=>{if(!l||!d)return;const t=f.current!==i;f.current=i;let r=s.fields;t&&(r=u,p.current=null,c({id:i,fields:u,loading:!1}));const n=d.resolveFields;if(!n)return void(t||c(e=>({...e,fields:u})));let o=!1;const a=p.current&&(p.current.props?.id??"root")===(l.props?.id??"root")?p.current:null,m=setTimeout(()=>{o||c(e=>e.id===i?{...e,loading:!0}:e)},50);return Promise.resolve(n(l,{changed:e(l,a),fields:u,lastFields:r,lastData:a,appState:g.current.appState,parent:g.current.parent})).then(e=>{clearTimeout(m),o||g.current.id!==i||(p.current=l,c({id:i,fields:e,loading:!1}))}),()=>{o=!0,clearTimeout(m)}},[i,l,d]),s.id===i?{fields:s.fields,loading:s.loading}:{fields:u,loading:!1}}export{i as useResolvedFields};
1
+ import{changedProps as e}from"./chunk-TGZCD6IP.js";import{useState as t,useRef as r,useEffect as n}from"react";function i({id:i,node:l,block:d,parent:o=null,appState:a=null}){const u=d?.fields??{},[s,c]=t(()=>({id:i,fields:u,loading:!1})),p=r(null),f=r(null),g=r({parent:o,appState:a,id:i});return g.current={parent:o,appState:a,id:i},n(()=>{if(!l||!d)return;const t=f.current!==i;f.current=i;let r=s.fields;t&&(r=u,p.current=null,c({id:i,fields:u,loading:!1}));const n=d.resolveFields;if(!n)return void(t||c(e=>({...e,fields:u})));let o=!1;const a=p.current&&(p.current.props?.id??"root")===(l.props?.id??"root")?p.current:null,m=setTimeout(()=>{o||c(e=>e.id===i?{...e,loading:!0}:e)},50);return Promise.resolve(n(l,{changed:e(l,a),fields:u,lastFields:r,lastData:a,appState:g.current.appState,parent:g.current.parent})).then(e=>{clearTimeout(m),o||g.current.id!==i||(p.current=l,c({id:i,fields:e,loading:!1}))}),()=>{o=!0,clearTimeout(m)}},[i,l,d]),s.id===i?{fields:s.fields,loading:s.loading}:{fields:u,loading:!1}}export{i as useResolvedFields};
@@ -0,0 +1 @@
1
+ import{useEaselSession as e}from"./chunk-YM4UEGBV.js";import{useHostEscape as n}from"./chunk-MQA7OFRA.js";import{DEFAULT_SCREEN_WORDS as t}from"./chunk-IYHO4XQX.js";import{styleMenuItems as o}from"./chunk-V7U33NF2.js";import{ROOT_ZONE as l}from"./chunk-TCAAOYQY.js";import{easelMenuEntries as r,menuLabel as i}from"./chunk-FIVU2COQ.js";import{createNodeClipboard as c,nodeMenuItems as s}from"./chunk-P5VYGWYO.js";import{DEFAULT_NODE_MENU_WORDS as a}from"./chunk-WK3AFPXY.js";import{isTypingTarget as u,useCanvasEvent as d,framePointToHost as p}from"./chunk-YU3WHLGI.js";import{zoneKey as f,ROOT_SLOT as m,ROOT_ID as y}from"./chunk-TGZCD6IP.js";import{useState as h,useCallback as k,useRef as b,useEffect as v}from"react";import{ContextMenu as g}from"efficient-shell/ui";import{UndoIcon as w,RedoIcon as x,PasteIcon as C,StylesIcon as O,LayersIcon as z,CopyIcon as P}from"efficient-shell/icons/efficient";import{jsx as A}from"react/jsx-runtime";function Y(e,n){const t=[],o=/* @__PURE__ */new Set;let r={zone:n.zone,index:n.index};for(;r;){const n=e.nodeAt(r.zone,r.index);if(!n||o.has(n.props.id))break;if(o.add(n.props.id),t.push({zone:r.zone,index:r.index,node:n,parentType:null}),r.zone===l)break;const i=r.zone.lastIndexOf(":");if(i<=0)break;r=e.locate(r.zone.slice(0,i))}for(let e=0;e<t.length-1;e+=1)t[e].parentType=t[e+1].node.type;return t}var j=c(),D=/* @__PURE__ */new WeakMap;function M(e){if(e.claimsPage)return j;const n=e.registry;if(!n)return e.cache("easel:node-clipboard",c);let t=D.get(n);return t||(t=c(),D.set(n,t)),t}function I(){return M(e())}function K(e,n,t){if(n===l){const{floor:n,cap:o}=e.sectionBand();return{parentId:y,slot:m,index:Math.min(Math.max(t,n),o)}}const o=n.lastIndexOf(":");return{parentId:n.slice(0,o),slot:n.slice(o+1),index:t}}function T(e,n,t){const o=e.isPinned(n,t),l=!o&&!e.isLocked(n)&&!e.duplicateBlocked(n),r=e.permits?.(n)??{duplicate:!0,delete:!0};return{copy:!o&&r.duplicate,cut:l&&r.duplicate&&r.delete,delete:l&&r.delete}}function S(e,n,t){const o=e.canPasteAt;if(!o)return f(n.from)===t.zone?K(e,t.zone,t.index+1):null;for(const l of Y(e,t)){const t=K(e,l.zone,l.index+1);if(o(n,t))return t}return null}function X(e){if(e.defaultPrevented||e.altKey||e.shiftKey)return null;if(u(e.target))return null;const n=e.target,t=n&&"ownerDocument"in n?n.ownerDocument??n:null,o=t?.getSelection?.();if(o&&!o.isCollapsed&&o.toString().trim())return null;if(!e.metaKey&&!e.ctrlKey)return"Delete"===e.key?"delete":null;const l=e.code||(1===e.key.length?`Key${e.key.toUpperCase()}`:"");return"KeyC"===l?"copy":"KeyX"===l?"cut":"KeyV"===l?"paste":null}function E(e,n,t,o){const l=e.nodeAt(t.zone,t.index);if(!l)return null;const r=l.props.id,i=e.labelOf(l.type,t.zone),c=T(e,l,t.zone);if("copy"===n)return c.copy?(e.nodeOps.copy(r,i),{done:"copied",name:i}):null;if(o.readOnly)return null;if("cut"===n)return c.cut?(e.nodeOps.cut(r,i),{done:"cut",name:i}):null;if("delete"===n)return c.delete?(e.nodeOps.remove(r),{done:"deleted",name:i}):null;const s=o.held;if(!s)return null;const a=e.isPinned(l,t.zone)?null:S(e,s,t);return a?(e.nodeOps.paste(a),{done:"pasted",name:s.label}):(e.onPasteRefused(s),{done:"refused",name:s.label})}function L(e,n){const{zone:t,index:r}=n,i=e.nodeAt(t,r);if(!i)return[];const c=i.props.id,a=e.labelOf(i.type,t),u=Boolean(i.props._hidden),d=e.nodeOps,p=e.isPinned(i,t),f=e.isLocked(i),m=!p&&!f&&!e.duplicateBlocked(i),y=e.permits?.(i)??{duplicate:!0,delete:!0},h=T(e,i,t),k=Y(e,n),b=d.held,v=b&&!p?S(e,b,n):null,g=!e.readOnly,w=e.style?o({held:g?e.style.held():null,canCopy:e.style.canCopy(i,t),onCopy:()=>e.style?.copy(i,t),onPaste:()=>e.style?.paste(t,r,i),words:e.words?.styleClipboard}):[];return s({title:a,words:e.words?.menu,layer:{group:"pick",items:k.flatMap((n,t)=>{const o={label:e.rowNameOf(n.node,n.zone),checked:0===t,onClick:()=>e.selectAt(n.zone,n.index,n.node.props.id,n.parentType)},r=n.zone===l?null:e.slotRung?.(n.zone)??null;return r?[o,{label:r.label,checked:!1,onClick:r.select}]:[o]})},actions:{duplicate:g&&m&&y.duplicate?()=>d.duplicate(c):void 0,...R(g&&!p,e=>d.canStep(c,e),e=>d.step(c,e)),copy:h.copy?()=>d.copy(c,a):void 0,cut:g&&h.cut?()=>d.cut(c,a):void 0,paste:g&&b&&v?{label:b.label,run:()=>d.paste(v)}:void 0,rename:g&&e.renamePropOf(i,t)?()=>e.beginRename(t,r):void 0,hide:!g||f||p?void 0:{hidden:u,run:()=>d.setProps(c,{_hidden:!u})},delete:g&&m&&y.delete?()=>d.remove(c):void 0},style:w,extras:e.menuRows?.(i,t,r)??void 0,pinnedLine:p?U(e).pinned:void 0})}function R(e,n,t){return e?{moveUp:n(-1)?()=>t(-1):null,moveDown:n(1)?()=>t(1):null}:{}}var U=e=>e.words?.screen??t.menu;function V(e){const n=U(e),o=!e.readOnly,r=[];o&&e.history.hasPast&&r.push({label:n.undo,icon:/* @__PURE__ */A(w,{}),shortcut:"⌘Z",onClick:e.history.back}),o&&e.history.hasFuture&&r.push({label:n.redo,icon:/* @__PURE__ */A(x,{}),shortcut:"⇧⌘Z",onClick:e.history.forward});const i=[],c=e.nodeOps.held,s=K(e,l,e.sectionBand().cap);if(o&&c&&(e.canPasteAt?e.canPasteAt(c,s):f(c.from)===l)){const n=s,t=e.words?.menu??a;i.push({label:t.pasteNamed({paste:t.paste,label:c.label}),icon:/* @__PURE__ */A(C,{}),shortcut:"⌘V",onClick:()=>e.nodeOps.paste(n)})}const u=[r,i,[...e.openPageStyles?[{label:e.pageStylesLabel??t.pageStyles,icon:/* @__PURE__ */A(O,{}),onClick:e.openPageStyles}]:[],{label:n.collapseAll,icon:/* @__PURE__ */A(z,{}),onClick:e.collapseAll}]].filter(e=>e.length>0),d={label:"—",onClick:()=>{}};return u.flatMap((e,n)=>n?[d,...e]:e)}function B(e,n){const t=n.selectionStart??0,o=n.selectionEnd??0,l=n.value.slice(t,o),r=e=>{n.focus(),n.setRangeText(e,t,o,"end"),n.dispatchEvent(new Event("input",{bubbles:!0}))},i=e.words?.menu??a,c=U(e),s=[];l&&(s.push({label:i.copy,icon:/* @__PURE__ */A(P,{}),shortcut:"⌘C",onClick:()=>navigator.clipboard?.writeText(l)}),s.push({label:i.cut,icon:/* @__PURE__ */A(P,{}),shortcut:"⌘X",onClick:()=>{navigator.clipboard?.writeText(l),r("")}})),s.push({label:i.paste,icon:/* @__PURE__ */A(C,{}),shortcut:"⌘V",onClick:()=>{navigator.clipboard?.readText().then(e=>{e&&r(e)}).catch(()=>e.onPasteRefused())}});const u=[s,n.value?[{label:c.selectAll,shortcut:"⌘A",onClick:()=>{n.focus(),n.select()}}]:[]].filter(e=>e.length>0),d={label:"—",onClick:()=>{}};return u.flatMap((e,n)=>n?[d,...e]:e)}function F(e){return e.shiftKey}function N(e,t){const[o,l]=h(null),r=k(()=>l(null),[]);n(null!==o,r);const i=b(e);i.current=e;const c=k(e=>{const n=i.current,t=n.keys;if(!t)return;const o=X(e);if(!o)return;const l=t.selected();if(!l)return;const r=E(n,o,l,{readOnly:t.readOnly,held:t.held()});r&&(e.preventDefault(),t.onDone?.(r))},[]),s=e.keys?.target??null;v(()=>{if(!s)return;const e=e=>c(e);return s.addEventListener("keydown",e),()=>s.removeEventListener("keydown",e)},[s,c]),d(t,"keydown",c);const a=k(n=>{if(F(n))return;const t=n.target;if(t?.closest?.("[data-slot-zone]"))return n.preventDefault(),void l(null);const o=function(e){const n=e?.closest?.("input, textarea");return n&&("INPUT"!==n.tagName||["text","search","url","email","tel","number",""].includes(n.type))?n:null}(t);if(o)return n.preventDefault(),void l({kind:"input",x:n.clientX,y:n.clientY,el:o,owner:t});const r=t?.closest?.("[data-node-id]")?.getAttribute("data-node-id"),i=r?e.locate(r):null;n.preventDefault(),l(i?{kind:"node",x:n.clientX,y:n.clientY,...i,owner:t}:{kind:"empty",x:n.clientX,y:n.clientY,owner:t})},[e]);d(t,"contextmenu",n=>{if(F(n)||!t)return;const o=n.target?.closest?.("[data-easel-block]")??null,r=o?.getAttribute("data-easel-block"),i=r?e.locate(r):null;n.preventDefault();const c=p(t.frame,n.clientX,n.clientY),s=t.frame;l(i?{kind:"node",...c,...i,owner:s}:{kind:"empty",...c,owner:s})}),d(t,"mousedown",r),d(t,"scroll",r,{on:"window"});return{onEditorContextMenu:a,menu:o?/* @__PURE__ */A(G,{host:e,target:o,onClose:r}):null,closeMenu:r}}function G({host:e,target:n,onClose:t}){const o="node"===n.kind?L(e,n):"input"===n.kind?B(e,n.el):V(e);return 0===o.length?null:/* @__PURE__ */A(g,{at:{x:n.x,y:n.y},owner:n.owner??null,onClose:t,"aria-label":i(o),items:r(o)})}export{j as EASEL_NODE_CLIPBOARD,Y as ancestorChain,M as nodeClipboardOf,T as nodeClipboardRules,L as nodeMenuItems,X as nodeShortcut,V as pageMenuItems,S as pastePlace,E as runNodeShortcut,B as textMenuItems,I as useNodeClipboard,N as useNodeContextMenu};
@@ -0,0 +1,8 @@
1
+ import{buildPaletteSections as e,pinnedSection as t,categoryLabel as n}from"./chunk-VKPOH6MK.js";import{blockTypesIn as o}from"./chunk-IZGFJWH4.js";import{sectionTemplatesOf as l}from"./chunk-N7E6264U.js";import{sharedSectionsOf as r}from"./chunk-N3MJOHAG.js";import{SidePanelHead as i,PanelModeExit as s}from"./chunk-SINAM2IT.js";import{blockRuns as c}from"./chunk-RUQOIQWI.js";import{useScreenBlockLook as a,useScreenBlockRules as d,useScreenPinned as p}from"./chunk-GXRS52JD.js";import{useEaselSession as m}from"./chunk-YM4UEGBV.js";import{DEFAULT_SCREEN_WORDS as f}from"./chunk-IYHO4XQX.js";import{useEasel as u}from"./chunk-KXTXYINN.js";import{easelMenuEntries as y}from"./chunk-FIVU2COQ.js";import{useWords as h}from"./chunk-MFIRYGHW.js";import{AddPanel as k}from"./chunk-LN43DP2A.js";import{DEFAULT_DRAG_WORDS as g}from"./chunk-TQ5Y6S2X.js";import{useState as b,useEffect as v,useMemo as j,useRef as I}from"react";import{SharedIcon as w,AddIcon as C}from"efficient-shell/icons/efficient";import{ContextMenu as O,toast as M,Dialog as N,Button as T}from"efficient-shell/ui";import{jsx as $,jsxs as x,Fragment as E}from"react/jsx-runtime";function F({name:e,pages:t,onDelete:n,onCancel:o}){const l=h("screen",f).shared,[r,i]=b(!1),s=I(null);/* @__PURE__ */
2
+ return $(N,{open:!0,role:"alertdialog",size:"sm",title:l.deleteTitle({name:e}),onClose:o,initialFocus:s,footer:/* @__PURE__ */x(E,{children:[
3
+ /* @__PURE__ */$(T,{ref:s,variant:"secondary",onClick:o,children:l.cancel}),
4
+ /* @__PURE__ */$(T,{variant:"danger",loading:r,onClick:()=>{(async()=>{i(!0);try{await n()}finally{i(!1)}})()},children:l.deleteShared})]}),children:l.deleteMessage({count:t})})}var H=e=>`section:${e}`,S=e=>`block:${e}`,A=e=>`template:${e}`,X=e=>`shared:${e}`;function D({at:I,placeBlocks:N,canTake:T,onPick:D,itemFor:G,session:L,siteWide:Q,onClose:W,onHide:Y,readOnly:z}){const B=u(e=>e.config),P=a(),{labelAtLevel:R,categoryLabel:U,firstSection:J,Icon:K,Thumbnail:V}=P,{blockIsOffered:_,canAddTo:Z}=d(),q=h("screen",f).add,ee=h("drag",g).add,te=m(),[ne,oe]=b([]);v(()=>{let e=!1;const t=e=>_(e,te);return l(te).list().then(n=>{if(e)return;const l=B.components;oe(n.filter(e=>e.node?.type&&l[e.node.type]&&o(e.node).every(t)))}).catch(()=>{}),()=>{e=!0}},[B,te]);const le=p().shared,re=h("screen",f).shared,[ie,se]=b([]),[ce,ae]=b(0);v(()=>{if(!le)return;let e=!1;const t=e=>_(e,te);return r(te).list().then(n=>{if(e)return;const l=B.components;se(n.filter(e=>e.node?.type&&l[e.node.type]&&o(e.node).every(t)))}).catch(()=>{}),()=>{e=!0}},[B,te,ce]);const[de,pe]=b(null),[me,fe]=b(null),ue=j(()=>e(B,P),[B]),ye=e=>R(e,"section",B.components[e]?.label??e),he=e=>({type:H(e.type),label:e.name,cover:/* @__PURE__ */$(V,{type:e.type}),title:e.desc?`${e.name} — ${e.desc}`:q.tile({name:e.name}),keywords:[e.alias??"",e.desc,e.type,e.catLabel].filter(Boolean)}),ke=e=>{const t=e.indexOf(":"),n=e.slice(0,t),o=e.slice(t+1);if("section"===n)return{kind:"section",type:o};if("block"===n)return{kind:"block",type:o};if("template"===n){const e=ne.find(e=>e.id===o);return e?{kind:"template",template:e}:null}if("shared"===n){const e=ie.find(e=>e.id===o);return e?{kind:"shared",section:e}:null}return null},ge=e=>/* @__PURE__ */$("span",{className:"es-add-glyph-cover",children:/* @__PURE__ */$(K,{type:e,size:26})}),be=j(()=>{const e=t(ue,J),o=/* @__PURE__ */new Map,l=e=>{e.retired||o.has(e.type)||!_(e.type,te)||o.set(e.type,e)};for(const t of e?[e]:ue){const e=Z(t.type)?.choices??[];e.forEach(l),e.forEach(e=>Z(e.type,1)?.choices?.forEach(l))}N?.forEach(l);const r=new Set(ue.map(e=>e.type)),i=[...o.values()].filter(e=>!r.has(e.type)),s=e=>({type:S(e.type),label:e.label,cover:ge(e.type),title:q.tile({name:e.label}),keywords:[e.group??"",e.type].filter(Boolean)}),a=e=>o.has(e.type)?{...he(e),cover:ge(e.type)}:he(e),d=[];ie.length>0&&d.push({key:"shared",title:re.group,tiles:ie.map(e=>({type:X(e.id),label:e.title,cover:/* @__PURE__ */$(V,{type:e.node.type}),mark:/* @__PURE__ */$(w,{size:12}),title:re.onPages({count:e.used_on.length}),keywords:[ye(e.node.type),e.node.type]}))}),ne.length>0&&d.push({key:"templates",title:q.templates,tiles:ne.map(e=>({type:A(e.id),label:e.name,cover:/* @__PURE__ */$(V,{type:e.node.type}),keywords:[ye(e.node.type),e.node.type]}))});const p=i.filter(e=>!e.group);let m=!1;for(const t of Object.keys(B.categories??{})){const o=ue.filter(e=>e.cat===t);if(0===o.length)continue;const l=e&&o.some(t=>t.type===e.type)?e:null,r=(l?[l,...o.filter(e=>e.type!==l.type)]:o).map(a);l&&!m&&(r.splice(1,0,...p.map(s)),m=!0),d.push({key:`category:${t}`,title:n(B,t,U),tiles:r})}const f=d.find(e=>e.key?.startsWith("category:"));if(!m&&f&&p.length>0&&(f.tiles=[...f.tiles,...p.map(s)],m=!0),c(i.filter(e=>e.group||!m)).forEach((e,t)=>{d.push({key:`blocks:${t}`,title:e.group??"",tiles:e.items.map(s)})}),!T)return d;const u=d.map(e=>({...e,tiles:e.tiles.map(e=>{const t=ke(e.type),n=t?T(t):null;return n?{...e,disabled:!0,disabledReason:n}:e})})),y=e=>e.tiles.some(e=>!e.disabled);return[...u.filter(y),...u.filter(e=>!y(e))]},[ne,ie,re,ue,B,q,T,N,te]);/* @__PURE__ */
5
+ return x(E,{children:[
6
+ /* @__PURE__ */$(i,{icon:/* @__PURE__ */$(C,{size:15}),title:q.title,context:q.contextAll,actions:/* @__PURE__ */$(s,{label:q.done,description:q.doneDescription,onClick:W}),onHide:Y}),
7
+ /* @__PURE__ */x("div",{className:"sf-addside sf-scroll",children:[
8
+ /* @__PURE__ */$(k,{groups:be,session:L,itemFor:e=>G(ke(e)??{kind:"section",type:e}),onInsert:D?e=>{const t=ke(e);t&&D(t)}:void 0,onTileMenu:(e,t)=>{const n=ke(e);return"shared"===n?.kind&&!z&&(pe({section:n.section,...t}),!0)},at:I,hint:q.hint,searchLabel:q.search,readOnly:z,words:ee}),Q??null]}),de?/* @__PURE__ */$(O,{at:{x:de.x,y:de.y},owner:de.owner,onClose:()=>pe(null),"aria-label":de.section.title,items:y([{label:re.deleteShared,danger:!0,onClick:()=>{fe(de.section),pe(null)}}])}):null,me?/* @__PURE__ */$(F,{name:me.title,pages:me.used_on.length,onDelete:()=>(async e=>{try{await r(te).remove(e.id)}catch{return void M.error(re.deleteFailed)}fe(null),le?.removed?.(e),se(t=>t.filter(t=>t.id!==e.id)),ae(e=>e+1)})(me),onCancel:()=>fe(null)}):null]})}export{D as AddSidePanel,S as blockKey,H as sectionKey,X as sharedKey,A as templateKey};