efficient-easel 20.2.1 → 21.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (266) hide show
  1. package/README.md +30 -9
  2. package/dist/{CanvasDragLayer-ARfaivCu.d.ts → CanvasDragLayer-CFUcBbgc.d.ts} +2 -2
  3. package/dist/{ScreenDocumentContext-CFJeqqKk.d.ts → ScreenDocumentContext-1RgtGKWR.d.ts} +4 -0
  4. package/dist/blocks/index.d.ts +5 -3
  5. package/dist/{buckets-Tj-nkBpg.d.ts → buckets-Sw94ll9I.d.ts} +1 -1
  6. package/dist/canvas/index.d.ts +8 -6
  7. package/dist/canvas/index.js +1 -1
  8. package/dist/chunk-2C7W64S5.js +8 -0
  9. package/dist/chunk-2L6KWUBC.js +1 -0
  10. package/dist/chunk-467WWV4I.js +1 -0
  11. package/dist/chunk-4FD7TAOE.js +1 -0
  12. package/dist/chunk-67HCYOW4.js +1 -0
  13. package/dist/chunk-A2VVB4RH.js +0 -0
  14. package/dist/{chunk-2GVCAIPX.js → chunk-BDSLF5BR.js} +1 -1
  15. package/dist/{chunk-U66YKDAR.js → chunk-BIK3AO2V.js} +1 -1
  16. package/dist/chunk-BTDI7JAA.js +2 -0
  17. package/dist/chunk-DDH2DYQP.js +1 -0
  18. package/dist/{chunk-I7BROL77.js → chunk-DNQ7AF6K.js} +1 -1
  19. package/dist/{chunk-HK6I3NVO.js → chunk-E52W3M5I.js} +1 -1
  20. package/dist/chunk-EB6NI2VK.js +1 -0
  21. package/dist/chunk-FM6JO4WF.js +2 -0
  22. package/dist/{chunk-JQXD3TDE.js → chunk-GWYNMSIP.js} +1 -1
  23. package/dist/{chunk-7YVEYQDE.js → chunk-I67UW5UG.js} +3 -3
  24. package/dist/chunk-JACEEVVF.js +1 -0
  25. package/dist/{chunk-QAJAEWCZ.js → chunk-KFWNGPW3.js} +5 -5
  26. package/dist/{chunk-FGYJ5DJY.js → chunk-KWLHKKZO.js} +1 -1
  27. package/dist/chunk-MLQKNED6.js +1 -0
  28. package/dist/chunk-MZ5GSSZ3.js +7 -0
  29. package/dist/{chunk-43AEUUNQ.js → chunk-N3MJOHAG.js} +1 -1
  30. package/dist/{chunk-BVN33R76.js → chunk-N7E6264U.js} +1 -1
  31. package/dist/chunk-OHZHYROJ.js +5 -0
  32. package/dist/chunk-PFFH7ASD.js +21 -0
  33. package/dist/chunk-PRHBWA5V.js +0 -0
  34. package/dist/chunk-S3DUFDQ6.js +6 -0
  35. package/dist/chunk-SNF5764Q.js +1 -0
  36. package/dist/chunk-SSRYU3YG.js +1 -0
  37. package/dist/chunk-SWBADIQT.js +1 -0
  38. package/dist/{chunk-GOTN2KY4.js → chunk-TIAWIOGD.js} +1 -1
  39. package/dist/chunk-TQ5Y6S2X.js +1 -0
  40. package/dist/chunk-TUXLORVR.js +15 -0
  41. package/dist/{chunk-FGNR22NY.js → chunk-U5DNBT63.js} +1 -1
  42. package/dist/chunk-U7TFWHST.js +5 -0
  43. package/dist/chunk-WHS6Y55E.js +10 -0
  44. package/dist/chunk-WJJ7H42G.js +18 -0
  45. package/dist/{chunk-ZOBSIXRD.js → chunk-Y2T3JX7K.js} +1 -1
  46. package/dist/chunk-YIUE4US7.js +0 -0
  47. package/dist/{chunk-O7Q4DDJT.js → chunk-YM4UEGBV.js} +1 -1
  48. package/dist/chunk-YVFYWAYU.js +65 -0
  49. package/dist/{chunk-UJ46J7QW.js → chunk-ZOSEBPAI.js} +1 -1
  50. package/dist/copy/index.d.ts +2 -2
  51. package/dist/copy/index.js +13 -13
  52. package/dist/drag/drag.css +3 -9
  53. package/dist/drag/index.d.ts +3 -3
  54. package/dist/drag/index.js +1 -1
  55. package/dist/draw/client.d.ts +1 -1
  56. package/dist/draw/client.js +1 -1
  57. package/dist/draw/index.d.ts +9 -9
  58. package/dist/draw/index.js +1 -1
  59. package/dist/easel/easel.css +3 -1
  60. package/dist/easel/index.d.ts +2 -2
  61. package/dist/easel/index.js +1 -1
  62. package/dist/fields/fields.css +2 -2
  63. package/dist/fields/index.d.ts +5 -5
  64. package/dist/fields/index.js +1 -1
  65. package/dist/panel/index.d.ts +39 -140
  66. package/dist/panel/index.js +15 -15
  67. package/dist/panel/panel.css +53 -347
  68. package/dist/render/index.d.ts +2 -2
  69. package/dist/render/index.js +5 -5
  70. package/dist/{repeat-Czi-6zPX.d.ts → repeat-BNgSq2Nw.d.ts} +1 -1
  71. package/dist/screen/components/AddBlockRow.d.ts +1 -1
  72. package/dist/screen/components/AddBlockRow.js +1 -1
  73. package/dist/screen/components/AddSidePanel.d.ts +2 -2
  74. package/dist/screen/components/AddSidePanel.js +1 -1
  75. package/dist/screen/components/NodeContextMenu.d.ts +15 -15
  76. package/dist/screen/components/NodeContextMenu.js +1 -1
  77. package/dist/screen/components/PageEditGuardNotices.js +1 -1
  78. package/dist/screen/components/PreviewPartsContext.d.ts +2 -2
  79. package/dist/screen/components/PreviewPartsContext.js +1 -1
  80. package/dist/screen/components/SaveControls.d.ts +9 -9
  81. package/dist/screen/components/ScreenChrome.js +1 -1
  82. package/dist/screen/components/ScreenDocumentContext.d.ts +2 -2
  83. package/dist/screen/components/ScreenDocumentContext.js +1 -1
  84. package/dist/screen/components/ScreenMount.d.ts +9 -9
  85. package/dist/screen/components/ScreenMount.js +1 -1
  86. package/dist/screen/components/ScreenStoreProvider.d.ts +9 -9
  87. package/dist/screen/components/ScreenStoreProvider.js +1 -1
  88. package/dist/screen/components/SectionScreenShell.js +17 -17
  89. package/dist/screen/components/SlotChildActionsContext.d.ts +1 -1
  90. package/dist/screen/components/usePartBridge.d.ts +9 -9
  91. package/dist/screen/components/usePartBridge.js +1 -1
  92. package/dist/screen/index.d.ts +10 -10
  93. package/dist/screen/index.js +1 -1
  94. package/dist/screen/lib/admin-bridge.d.ts +1 -1
  95. package/dist/screen/lib/admin-bridge.js +1 -1
  96. package/dist/screen/lib/content/view-tiers.d.ts +15 -3
  97. package/dist/screen/lib/content/view-tiers.js +1 -1
  98. package/dist/screen/lib/document/add-target-types.d.ts +55 -0
  99. package/dist/screen/lib/document/add-target-types.js +1 -0
  100. package/dist/screen/lib/document/block-choice.d.ts +64 -0
  101. package/dist/screen/lib/document/block-choice.js +1 -0
  102. package/dist/screen/lib/document/block-types-in.d.ts +39 -0
  103. package/dist/screen/lib/document/block-types-in.js +1 -0
  104. package/dist/screen/lib/document/content-tree.d.ts +222 -0
  105. package/dist/screen/lib/document/content-tree.js +1 -0
  106. package/dist/screen/lib/document/device-fields.d.ts +128 -0
  107. package/dist/screen/lib/document/device-fields.js +1 -0
  108. package/dist/screen/lib/document/field-buckets.d.ts +36 -0
  109. package/dist/screen/lib/document/field-buckets.js +1 -0
  110. package/dist/screen/lib/document/field-markers.d.ts +205 -0
  111. package/dist/screen/lib/document/field-markers.js +1 -0
  112. package/dist/screen/lib/document/hidable.d.ts +44 -0
  113. package/dist/screen/lib/document/hidable.js +1 -0
  114. package/dist/screen/lib/document/palette-sections.d.ts +103 -0
  115. package/dist/screen/lib/document/palette-sections.js +1 -0
  116. package/dist/screen/lib/document/panel-fields.d.ts +47 -0
  117. package/dist/screen/lib/document/panel-fields.js +1 -0
  118. package/dist/screen/lib/document/panel-no-control-mark.d.ts +74 -0
  119. package/dist/screen/lib/document/panel-no-control-mark.js +1 -0
  120. package/dist/screen/lib/document/part-id.d.ts +23 -0
  121. package/dist/screen/lib/document/part-id.js +1 -0
  122. package/dist/screen/lib/document/preview-click.d.ts +49 -0
  123. package/dist/screen/lib/document/preview-click.js +1 -0
  124. package/dist/screen/lib/document/preview-dom.d.ts +8 -0
  125. package/dist/screen/lib/document/preview-dom.js +1 -0
  126. package/dist/screen/lib/document/preview-events.d.ts +25 -0
  127. package/dist/screen/lib/document/preview-events.js +1 -0
  128. package/dist/screen/lib/document/preview-selection-context.d.ts +72 -0
  129. package/dist/screen/lib/document/preview-selection-context.js +1 -0
  130. package/dist/screen/lib/document/section-doc.d.ts +24 -0
  131. package/dist/screen/lib/document/section-doc.js +1 -0
  132. package/dist/screen/lib/document/slot-child-name.d.ts +225 -0
  133. package/dist/screen/lib/document/slot-child-name.js +1 -0
  134. package/dist/screen/lib/document/slot-heal.d.ts +5 -0
  135. package/dist/screen/lib/document/slot-heal.js +1 -0
  136. package/dist/screen/lib/document/slot-section-spec.d.ts +96 -0
  137. package/dist/screen/lib/document/slot-section-spec.js +1 -0
  138. package/dist/screen/lib/document/style-clipboard.d.ts +144 -0
  139. package/dist/screen/lib/document/style-clipboard.js +1 -0
  140. package/dist/screen/lib/document/text-control-kinds.d.ts +71 -0
  141. package/dist/screen/lib/document/text-control-kinds.js +1 -0
  142. package/dist/screen/lib/document/tree-reveal.d.ts +62 -0
  143. package/dist/screen/lib/document/tree-reveal.js +1 -0
  144. package/dist/screen/lib/document/use-section-ops.d.ts +110 -0
  145. package/dist/screen/lib/document/use-section-ops.js +1 -0
  146. package/dist/screen/lib/document-addressing.d.ts +2 -2
  147. package/dist/screen/lib/document-switch.d.ts +1 -1
  148. package/dist/screen/lib/host.d.ts +2 -2
  149. package/dist/screen/lib/key-scope.d.ts +1 -1
  150. package/dist/screen/lib/key-scope.js +1 -1
  151. package/dist/screen/lib/media-panel.d.ts +2 -2
  152. package/dist/screen/lib/media-picker.d.ts +2 -2
  153. package/dist/screen/lib/page-lock.d.ts +1 -1
  154. package/dist/screen/lib/puck/add-target-types.d.ts +3 -55
  155. package/dist/screen/lib/puck/add-target-types.js +1 -0
  156. package/dist/screen/lib/puck/block-choice.d.ts +1 -64
  157. package/dist/screen/lib/puck/block-choice.js +1 -1
  158. package/dist/screen/lib/puck/block-types-in.d.ts +1 -39
  159. package/dist/screen/lib/puck/block-types-in.js +1 -1
  160. package/dist/screen/lib/puck/content-tree.d.ts +1 -222
  161. package/dist/screen/lib/puck/content-tree.js +1 -1
  162. package/dist/screen/lib/puck/device-fields.d.ts +3 -127
  163. package/dist/screen/lib/puck/device-fields.js +1 -1
  164. package/dist/screen/lib/puck/field-buckets.d.ts +2 -36
  165. package/dist/screen/lib/puck/field-buckets.js +1 -1
  166. package/dist/screen/lib/puck/field-markers.d.ts +2 -205
  167. package/dist/screen/lib/puck/field-markers.js +1 -1
  168. package/dist/screen/lib/puck/hidable.d.ts +1 -44
  169. package/dist/screen/lib/puck/hidable.js +1 -1
  170. package/dist/screen/lib/puck/palette-sections.d.ts +2 -97
  171. package/dist/screen/lib/puck/palette-sections.js +1 -1
  172. package/dist/screen/lib/puck/panel-fields.d.ts +1 -47
  173. package/dist/screen/lib/puck/panel-fields.js +1 -1
  174. package/dist/screen/lib/puck/panel-no-control-mark.d.ts +2 -74
  175. package/dist/screen/lib/puck/panel-no-control-mark.js +1 -1
  176. package/dist/screen/lib/puck/part-id.d.ts +1 -23
  177. package/dist/screen/lib/puck/part-id.js +1 -1
  178. package/dist/screen/lib/puck/preview-click.d.ts +1 -49
  179. package/dist/screen/lib/puck/preview-click.js +1 -1
  180. package/dist/screen/lib/puck/preview-dom.d.ts +1 -8
  181. package/dist/screen/lib/puck/preview-dom.js +1 -1
  182. package/dist/screen/lib/puck/preview-events.d.ts +1 -25
  183. package/dist/screen/lib/puck/preview-events.js +1 -1
  184. package/dist/screen/lib/puck/preview-selection-context.d.ts +2 -72
  185. package/dist/screen/lib/puck/preview-selection-context.js +1 -1
  186. package/dist/screen/lib/puck/section-doc.d.ts +3 -18
  187. package/dist/screen/lib/puck/section-doc.js +1 -1
  188. package/dist/screen/lib/puck/slot-child-name.d.ts +1 -225
  189. package/dist/screen/lib/puck/slot-child-name.js +1 -1
  190. package/dist/screen/lib/puck/slot-heal.d.ts +2 -5
  191. package/dist/screen/lib/puck/slot-heal.js +1 -1
  192. package/dist/screen/lib/puck/slot-section-spec.d.ts +1 -96
  193. package/dist/screen/lib/puck/slot-section-spec.js +1 -0
  194. package/dist/screen/lib/puck/style-clipboard.d.ts +14 -116
  195. package/dist/screen/lib/puck/style-clipboard.js +1 -1
  196. package/dist/screen/lib/puck/text-control-kinds.d.ts +1 -71
  197. package/dist/screen/lib/puck/text-control-kinds.js +1 -1
  198. package/dist/screen/lib/puck/tree-reveal.d.ts +1 -62
  199. package/dist/screen/lib/puck/tree-reveal.js +1 -1
  200. package/dist/screen/lib/puck/use-section-ops.d.ts +4 -105
  201. package/dist/screen/lib/puck/use-section-ops.js +1 -1
  202. package/dist/screen/lib/screen-parts.d.ts +27 -20
  203. package/dist/screen/lib/screen-parts.js +1 -1
  204. package/dist/screen/lib/section-template-types.d.ts +1 -1
  205. package/dist/screen/lib/section-templates.d.ts +1 -1
  206. package/dist/screen/lib/section-templates.js +1 -1
  207. package/dist/screen/lib/session-context.d.ts +1 -1
  208. package/dist/screen/lib/session-context.js +1 -1
  209. package/dist/screen/lib/session.d.ts +3 -3
  210. package/dist/screen/lib/session.js +1 -1
  211. package/dist/screen/lib/shared-section-types.d.ts +1 -1
  212. package/dist/screen/lib/shared-sections.d.ts +1 -1
  213. package/dist/screen/lib/shared-sections.js +1 -1
  214. package/dist/screen/screen.css +5 -9
  215. package/dist/screen/words.d.ts +4 -0
  216. package/dist/screen/words.js +1 -1
  217. package/dist/strings/index.d.ts +4 -4
  218. package/dist/strings/index.js +2 -2
  219. package/dist/text-styles/index.js +33 -33
  220. package/dist/tree/index.d.ts +5 -5
  221. package/dist/tree/index.js +1 -1
  222. package/dist/{types-CDX6vd6A.d.ts → types-B8NwXKlE.d.ts} +1 -1
  223. package/dist/{types-Bqq6ya0y.d.ts → types-DBy3L69b.d.ts} +11 -4
  224. package/dist/{watch-BTYOJpQU.d.ts → watch-D8xZow3y.d.ts} +2 -2
  225. package/dist/{words-vhnV8sM7.d.ts → words-CFkb8XtN.d.ts} +5 -0
  226. package/dist/{words-BeX5eGq7.d.ts → words-CmEnDoOe.d.ts} +1 -1
  227. package/dist/{words-CvwYvkJm.d.ts → words-SD4neL0n.d.ts} +6 -0
  228. package/package.json +156 -12
  229. package/dist/chunk-23DYNW6S.js +0 -1
  230. package/dist/chunk-23VM4PMV.js +0 -7
  231. package/dist/chunk-276MBG5P.js +0 -2
  232. package/dist/chunk-6FWAE2RN.js +0 -1
  233. package/dist/chunk-7LYKFL3Q.js +0 -21
  234. package/dist/chunk-A6Z4SD3I.js +0 -10
  235. package/dist/chunk-BHRC3ASL.js +0 -1
  236. package/dist/chunk-EFHV56BO.js +0 -15
  237. package/dist/chunk-I54UCYOU.js +0 -1
  238. package/dist/chunk-JBOSEHIX.js +0 -1
  239. package/dist/chunk-KAML3KQH.js +0 -1
  240. package/dist/chunk-L2Y3PF2R.js +0 -4
  241. package/dist/chunk-LQV5FZTQ.js +0 -18
  242. package/dist/chunk-MEHLY5Q4.js +0 -1
  243. package/dist/chunk-PAOZMXEI.js +0 -5
  244. package/dist/chunk-QIDRJH3S.js +0 -1
  245. package/dist/chunk-R5KEFI55.js +0 -8
  246. package/dist/chunk-RC25EGHD.js +0 -5
  247. package/dist/chunk-RSCMJIWS.js +0 -1
  248. package/dist/chunk-TNGOL65V.js +0 -1
  249. package/dist/chunk-VANKQVOW.js +0 -8
  250. package/dist/chunk-WEIE2FBC.js +0 -1
  251. package/dist/chunk-WRFD4EXD.js +0 -1
  252. package/dist/chunk-XJ2WXGFJ.js +0 -65
  253. /package/dist/{chunk-MQNBD6AB.js → chunk-3QB2ZQXK.js} +0 -0
  254. /package/dist/{chunk-LER7RKTO.js → chunk-5XL2RXFU.js} +0 -0
  255. /package/dist/{chunk-6W7WLPZH.js → chunk-6UAEFOJ4.js} +0 -0
  256. /package/dist/{chunk-26OOWIJJ.js → chunk-7OCEPOEJ.js} +0 -0
  257. /package/dist/{chunk-IQ5TA7AM.js → chunk-AJ2SUSET.js} +0 -0
  258. /package/dist/{chunk-DUVRZ456.js → chunk-ANPOR6EY.js} +0 -0
  259. /package/dist/{chunk-5ZBY24K7.js → chunk-CPL43ZLJ.js} +0 -0
  260. /package/dist/{chunk-PIND6KE7.js → chunk-I6SK6ZDT.js} +0 -0
  261. /package/dist/{chunk-7F52SZOI.js → chunk-INRERJU4.js} +0 -0
  262. /package/dist/{chunk-R5L2E7JX.js → chunk-MGVI67QV.js} +0 -0
  263. /package/dist/{chunk-IYT6NN2J.js → chunk-R4AUZVA3.js} +0 -0
  264. /package/dist/{chunk-M2Z775ZC.js → chunk-RUQOIQWI.js} +0 -0
  265. /package/dist/{chunk-PLVEGYK6.js → chunk-TCAAOYQY.js} +0 -0
  266. /package/dist/{chunk-PA3PNTVV.js → chunk-VKPOH6MK.js} +0 -0
@@ -0,0 +1,25 @@
1
+ /**
2
+ * lib/document/preview-events.ts — events the editor's screen sends INTO the preview.
3
+ *
4
+ * Moved from components/HeroSection (which re-exports them) so the screen's
5
+ * preview bridge (lib/document/preview-dom) can send them without importing a
6
+ * section, and moves into efficient-easel with the screen (doc/adr/0004). A
7
+ * section listens for its own; the name is the contract between the two.
8
+ */
9
+ /**
10
+ * Event the editor chrome dispatches INTO the preview iframe to jump a Hero's
11
+ * slider to a slide by index. The chrome (section tree + "Add slide") lives
12
+ * outside this iframe and can't reach the slider's React state, and Puck's
13
+ * selection overlay is portaled to the iframe `<body>` (not inside `.hero-track`),
14
+ * so selection alone can't be observed from here — this is the explicit bridge.
15
+ * See {@link ScreenChrome} `selectChild` / `addChild`.
16
+ */
17
+ declare const HERO_SLIDER_GOTO_EVENT = "hero-slider:goto";
18
+ interface HeroSliderGotoDetail {
19
+ /** Target Hero's stable Puck id (`data-easel-block`); omit to hit all Heroes. */
20
+ id?: string;
21
+ /** Zero-based slide index to show. */
22
+ index: number;
23
+ }
24
+
25
+ export { HERO_SLIDER_GOTO_EVENT, type HeroSliderGotoDetail };
@@ -0,0 +1 @@
1
+ export{HERO_SLIDER_GOTO_EVENT}from"../../../chunk-AJ2SUSET.js";
@@ -0,0 +1,72 @@
1
+ import * as react from 'react';
2
+ import { ReactNode } from 'react';
3
+
4
+ /**
5
+ * Shared machinery for the editor preview's "selection bridges" — the click-to-
6
+ * select plumbing every piece of site CHROME needs because it is NOT a Puck node
7
+ * and so can't route through Puck's own selection. The header, the chat bubble,
8
+ * and a Hero's ticker / background / text overlay each expose the SAME two-way
9
+ * bridge, and all built it by hand until this file:
10
+ *
11
+ * - `select(…)` / `setSelectHandler(fn)` — a ref-backed handler the chrome
12
+ * registers (it opens the matching inspector panel), invoked from inside the
13
+ * portaled preview iframe when the element is clicked. It lives behind a ref so
14
+ * the chrome can re-register without re-rendering the preview; `select` itself
15
+ * stays stable. See {@link useSelectHandler}.
16
+ * - a mirrored SELECTION the preview reads to draw its own "selected" outline.
17
+ *
18
+ * Two entry points reuse the bridge:
19
+ * - {@link useSelectHandler} — just the ref-backed `select` / `setSelectHandler`
20
+ * pair, for the header + chat bridges. They keep a plain boolean `selected` and
21
+ * layer their own live-config state around it, so they compose this hook rather
22
+ * than the whole context factory.
23
+ * - {@link createPreviewSelectionContext} — a whole context + provider + hook for
24
+ * an ID-SCOPED bridge (a Hero's ticker / background / text), where the mirrored
25
+ * selection is "which sibling id is selected" (`selected<Thing>Id`), scoped by
26
+ * id so sibling heroes never cross-select. The three such contexts differ ONLY
27
+ * in that field's name, so they are each one call to this factory.
28
+ */
29
+ /**
30
+ * The ref-backed `select` / `setSelectHandler` pair shared by every selection
31
+ * bridge. `Args` is the click payload the chrome's handler receives — `[]` for a
32
+ * lone toggle (header / chat) or `[id: string]` for an id-scoped bridge (ticker /
33
+ * hero media / hero text). `select` is stable across renders; registering a new
34
+ * handler never re-renders the portaled preview.
35
+ */
36
+ declare function useSelectHandler<Args extends unknown[]>(): {
37
+ select: (...args: Args) => void;
38
+ setSelectHandler: (fn: (...args: Args) => void) => void;
39
+ };
40
+ /**
41
+ * The context value of an id-scoped selection bridge, keyed by the id field's
42
+ * name `Key` (e.g. `"selectedHeroId"`): the mirrored id + its `set…` setter, plus
43
+ * the shared `select(id)` / `setSelectHandler` pair. Keeping the field name in the
44
+ * type is what lets one factory reproduce each context's exact public API.
45
+ */
46
+ type PreviewIdSelection<Key extends string> = {
47
+ [P in Key]: string | null;
48
+ } & {
49
+ [P in Key as `set${Capitalize<P>}`]: (id: string | null) => void;
50
+ } & {
51
+ select: (id: string) => void;
52
+ setSelectHandler: (fn: (id: string) => void) => void;
53
+ };
54
+ /**
55
+ * Build a complete id-scoped selection-bridge context — the shared body of
56
+ * PreviewTickerContext / PreviewHeroMediaContext / PreviewHeroTextContext, which
57
+ * differ only in the id field's NAME. Pass that field name and the returned
58
+ * `Provider` + `useSelection` expose exactly `{ [idKey], set<IdKey>, select,
59
+ * setSelectHandler }`, so each context's existing consumers read unchanged.
60
+ *
61
+ * @example
62
+ * export const { Provider: PreviewTickerProvider, useSelection: usePreviewTicker } =
63
+ * createPreviewSelectionContext("selectedHeroId");
64
+ */
65
+ declare function createPreviewSelectionContext<Key extends string>(idKey: Key): {
66
+ Provider: ({ children }: {
67
+ children: ReactNode;
68
+ }) => react.JSX.Element;
69
+ useSelection: () => PreviewIdSelection<Key>;
70
+ };
71
+
72
+ export { type PreviewIdSelection, createPreviewSelectionContext, useSelectHandler };
@@ -0,0 +1 @@
1
+ export{createPreviewSelectionContext,useSelectHandler}from"../../../chunk-TIAWIOGD.js";import"../../../chunk-MGVI67QV.js";
@@ -0,0 +1,24 @@
1
+ import { Data } from '../../../blocks/index.js';
2
+ import { TreeItem } from './content-tree.js';
3
+ import 'react';
4
+ import '../../../types-Cq53lL8d.js';
5
+ import '../../../data/index.js';
6
+ import '../../../types-41704JE4.js';
7
+ import '../../../resolve-D68pb3Bx.js';
8
+ import '../../../plan-CZS902DV.js';
9
+
10
+ declare function nodeToDoc(node: TreeItem): Data;
11
+ declare function docToNode(data: Data): TreeItem | null;
12
+ /**
13
+ * Deep-copy a stored section node with FRESH ids — the node's own and every
14
+ * inline slot child's, recursively — so inserting the same template twice never
15
+ * lands two nodes with colliding ids (Puck keys selection/replace on id, and
16
+ * React keys render on it).
17
+ *
18
+ * `strip` (0.106.0) sees each copied node once its children are copied, and
19
+ * answers it as the copy should hold it — the layer's `blockRules.stripCopy`,
20
+ * which takes out what only an original may hold. It keeps the fresh id.
21
+ */
22
+ declare function cloneNodeWithFreshIds(node: TreeItem, strip?: (node: TreeItem) => TreeItem): TreeItem;
23
+
24
+ export { cloneNodeWithFreshIds, docToNode, nodeToDoc };
@@ -0,0 +1 @@
1
+ export{cloneNodeWithFreshIds,docToNode,nodeToDoc}from"../../../chunk-BDSLF5BR.js";import"../../../chunk-TCAAOYQY.js";
@@ -0,0 +1,225 @@
1
+ /**
2
+ * What a slot child is CALLED — the ONE rule, and the only place it is written
3
+ * (card 66194).
4
+ *
5
+ * A slot-backed section (Hero Slideshow, Collections, Product Grid, Customer
6
+ * Photo Grid, Gallery) keeps its children on its own props, and three surfaces
7
+ * have to put a word on each of them: the page editor's Sections tree
8
+ * (`ScreenChrome`), the standalone section editor's tree
9
+ * (`SectionScreenShell`) — which also feeds the list drawn inside the section's
10
+ * own settings panel through `SlotChildActionsContext` — and `CollectionCard`'s
11
+ * own render, which puts the SAME word on the published card.
12
+ *
13
+ * Before this card the rule was written out three times. Card 66186 wrote the
14
+ * second copy, card 66190 had to edit both to add the Collection Card step and
15
+ * discovered the third while doing it. Three copies of a five-rung precedence is
16
+ * a rule that looks right until the day two of them disagree — and a merchant
17
+ * would meet that as a tree row and a card that name the same thing differently.
18
+ *
19
+ * ── THE PRECEDENCE, most specific first ──────────────────────────────────────
20
+ * 1. `props.name` an explicit identifier the author typed (Hero Slide's
21
+ * "Slide name", Gallery Item's "Heading").
22
+ * 2. `props.altName` a card-local override of the name below it
23
+ * (Collection Card's "Alt name").
24
+ * 3. `props.collection` the LINKED category's snapshot name — the source the
25
+ * override above overrides.
26
+ * 3b. `props.source` the LINKED post's snapshot headline (Post card). The
27
+ * SAME rung as `collection` and deliberately beside it:
28
+ * both are "the thing this block is linked to, named by
29
+ * its own snapshot", and both are overridable by the two
30
+ * rungs above. A Post card is the first slot child that
31
+ * links to a post — Featured cover and Long read link to
32
+ * one too, but they are top-level sections and never
33
+ * reach this rule — so without it four cards in a Box
34
+ * all read "Post card" and a merchant cannot tell which
35
+ * one they are dragging.
36
+ * 4. `props.code` a catalog slug (Product Ref stores only this), resolved
37
+ * through `wheelName` when a caller supplies one.
38
+ * 5. the caller's own fallback — see {@link slotChildRowName}.
39
+ *
40
+ * `name` and `altName` may be hidable values (`{text,hidden}`) rather than bare
41
+ * strings, so both read through `hidableText`: an object reaching a tree row
42
+ * crashes it ("Objects are not valid as a React child").
43
+ *
44
+ * Rungs 1–3 are authored copy and may carry the shop's editorial marks. A TREE
45
+ * ROW unwraps them ({@link slotChildRowName}); the published card does not, and
46
+ * must not — that rung's own comment carries the reasoning (card 66202). How a
47
+ * mark is unwrapped is the grammar's, so the row is handed the function that
48
+ * does it, as it is handed the catalog: this module goes into efficient-easel
49
+ * with the screen (doc/adr/0004), and the grammar is the layer's.
50
+ *
51
+ * ── WHY THE CATALOG RESOLVER IS AN ARGUMENT ──────────────────────────────────
52
+ * The two trees genuinely differ at rung 4, and always have: the page editor has
53
+ * the product catalog loaded and shows a Product Ref as "Turbine II", while the
54
+ * standalone shell has no catalog and shows the raw slug `turbine-ii`. That
55
+ * asymmetry shipped with card 66186 and is real behaviour, NOT a defect this
56
+ * module quietly repairs. Taking the resolver as a parameter makes it an
57
+ * explicit argument instead of an accident: the shell passes none, so it shows
58
+ * the slug, and a reader sees that on the call line rather than discovering it.
59
+ * (Same reasoning as `content-tree.ts`, which takes the config as an argument
60
+ * rather than importing it.)
61
+ *
62
+ * `scripts/test-slot-child-name.tsx` pins the behaviour — the precedence, the
63
+ * resolver contract, and that every existing row name is unchanged.
64
+ * `scripts/test-slot-child-lists.tsx` §5 pins that this stays the ONE home.
65
+ */
66
+ /**
67
+ * A Puck content node as this rule reads it. Deliberately looser than
68
+ * `TreeItem` (no required `id`): `CollectionCard.render` names itself from the
69
+ * props it was handed, and never has a node in hand.
70
+ */
71
+ type SlotChild = {
72
+ type: string;
73
+ props: Record<string, unknown>;
74
+ };
75
+ /**
76
+ * The name a slot child carries in its OWN data — rungs 1–4 above — or `""` when
77
+ * it carries none.
78
+ *
79
+ * `wheelName` resolves a `props.code` catalog slug to a wheel's design name; a
80
+ * caller with no catalog omits it and the slug stands.
81
+ *
82
+ * Callers that need a word for an unnamed child add their own last rung; they do
83
+ * not agree on what it should be, which is exactly why it is not in here. The
84
+ * two trees fall back to the component's label ({@link slotChildRowName}), while
85
+ * `CollectionCard.render` falls back to an editor-only placeholder — an unlinked
86
+ * card must not publish the words "Collection Card".
87
+ */
88
+ declare function slotChildName(child: SlotChild, wheelName?: (code: string) => string | undefined): string;
89
+ /**
90
+ * The full five-rung rule as a TREE ROW reads it: {@link slotChildName} with its
91
+ * markup unwrapped, else the component's friendly label. `compLabel` is the
92
+ * host's own config-backed lookup (`config.components[type].label ?? type`) —
93
+ * passed in, because this module has no config and importing one would make the
94
+ * editor's naming rule a dependency of the config that describes it.
95
+ *
96
+ * `plainText` unwraps the markup: the plain words of authored copy in the
97
+ * layer's grammar, which the screen holds as `ScreenBlockLook.plainText`
98
+ * (lib/screen-parts). The website's is lib/markup `stripMarkup`. Passed in for
99
+ * the reason `compLabel` is: the grammar is the layer's, and an email's is not
100
+ * a website's.
101
+ *
102
+ * ── WHY THE STRIP IS HERE AND NOT ONE RUNG DOWN (card 66202) ─────────────────
103
+ * A slot child's name is AUTHORED COPY. Rungs 1–3 are boxes a merchant types
104
+ * into, so they may carry any mark in the shop's grammar, and a tree row printed
105
+ * them verbatim: `Precision== Forged==` in a list that is plain text end to end.
106
+ * It reads as broken, and it is expensive — `.sf-subtree` costs 25px a nesting
107
+ * level, so a depth-2 row has roughly 172px of a 288px panel to spell a name in
108
+ * and truncates. Four delimiters come out of that budget before a word does.
109
+ *
110
+ * `slotChildName` deliberately does NOT strip, and that asymmetry is the whole
111
+ * point of putting this on the row rung instead. Its third caller is
112
+ * `CollectionCard.render`, which puts the word on a customer's LIVE page, where
113
+ * `<CollectionCard/>` routes `name` through `renderHeadline` — so `==phrase==`
114
+ * there is the merchant's accent colour, not noise. Stripping one rung lower
115
+ * would have flattened it on every published card that uses one. A tree row is
116
+ * the surface that cannot draw a mark; it is the surface that drops it.
117
+ *
118
+ * Through the grammar's own stripper (the website's `stripMarkup`), never by
119
+ * deleting delimiter characters: that unwraps a PAIR and leaves a lone
120
+ * delimiter exactly where the renderer leaves it, so a half-typed name — which
121
+ * is what mid-edit data actually looks like — keeps its whole line. It also
122
+ * means a mark the grammar grows is handled here with no edit, because this
123
+ * file names no delimiter of its own.
124
+ *
125
+ * The fallback still fires only for a genuinely nameless child: the grammar
126
+ * needs at least one character between a pair, so a name that is non-empty
127
+ * cannot strip to nothing and be renamed into its component's label.
128
+ */
129
+ declare function slotChildRowName<N extends SlotChild>(child: N, compLabel: (type: string) => string, plainText: (copy: string) => string, wheelName?: (code: string) => string | undefined, rowName?: RowNameRule<N>): string;
130
+ /**
131
+ * THE LAYER'S LAST WORD (0.103.0) — `ScreenBlockLook.rowName`
132
+ * (lib/screen-parts), the rung a layer may stand above the whole precedence:
133
+ * handed the node, the level it is named at and what the rule here answered,
134
+ * it answers the row's name. The campaign designer names its rows by its own
135
+ * labels, and needs none of the website's rungs.
136
+ *
137
+ * An argument and not a rung written here, for the reason the grammar and the
138
+ * catalog are: this module has no layer. Absent, the rule here is the name, as
139
+ * it was before the member existed.
140
+ */
141
+ type RowNameRule<N extends SlotChild = SlotChild> = (node: N, level: "section" | "block", fallback: string) => string;
142
+ /**
143
+ * WHICH PROP A RENAME WRITES — the write side of the rule above, and here for
144
+ * the reason the read side is: naming a slot child has ONE home (card 66194).
145
+ * A rename that picked its own prop would be a sixth opinion about what a child
146
+ * is called, and the day it disagreed a merchant would rename a row and watch
147
+ * the row not change.
148
+ *
149
+ * Returns the prop key, or `null` when this component has no name to write —
150
+ * and a `null` is what takes `Rename` out of the menu, rather than a menu item
151
+ * that does nothing.
152
+ *
153
+ * ── ONLY A DECLARED IDENTIFIER, AND THIS IS THE WHOLE TRAP ───────────────────
154
+ * `GalleryItem.name` is keyed `name`, it IS what its Layers row says, and it is
155
+ * an ordinary `Heading` a merchant writes — copy, printed on the page. A rename
156
+ * keyed on the prop NAME would quietly rewrite that heading from a menu item
157
+ * called "Rename". So the field must DECLARE itself an identifier
158
+ * (`withIdentifier`, see `lib/document/controls`), which is the same declaration the
159
+ * settings panel reads to keep these rows out of the copy list.
160
+ *
161
+ * `fields` is taken as an argument rather than imported, exactly like the
162
+ * `wheelName` resolver above: this module has no config, and importing one would
163
+ * make the editor's naming rule a dependency of the config that describes it.
164
+ *
165
+ * The order matches {@link slotChildName}'s precedence, so the prop a rename
166
+ * writes is the prop the row then reads. `altName` before `name` cannot happen
167
+ * in today's config — no component declares both — and the order is written out
168
+ * anyway so the answer does not depend on that staying true.
169
+ */
170
+ declare function slotChildRenameProp(fields: Record<string, unknown> | undefined): "name" | "altName" | null;
171
+ /**
172
+ * WHICH PROP A SECTION'S RENAME WRITES (0.105.0) — the write side of
173
+ * {@link rootRowName} below, as {@link slotChildRenameProp} is the write side of
174
+ * a slot child's name, and here for the same reason: one home for what a node
175
+ * is called.
176
+ *
177
+ * Owner ruling R11 (Victor Mau, 2026-10-09): Rename works on top-level sections
178
+ * in both editors. A section's row reads rung 1 and nothing below it — its own
179
+ * `name`, else its type's label — so `name` is what a rename writes, and the row
180
+ * then reads it back. Until the ruling a root node had no Rename at all: its row
181
+ * was taken to say only its type, which stopped being true the day the row
182
+ * started reading the `name` the presets seed ("Brand Text", a split's
183
+ * "<Section> section"), and that name had no way to be changed.
184
+ *
185
+ * ── `name` IS WRITTEN UNLESS IT IS COPY — the slot child's trap, at the root ──
186
+ * A section whose fields do not declare `name` carries it only as the editor's
187
+ * label for it: the presets write it, the Layers row reads it, and no page draws
188
+ * it. One that declares it an identifier (`withIdentifier`) is the same. But a
189
+ * field keyed `name` that is ordinary copy — `GalleryItem.name` is a Heading
190
+ * printed on the page — is not a name, and a menu item called "Rename" must not
191
+ * rewrite it: null, and the section gets no Rename. No section of the website's
192
+ * registry declares `name` at all today, so every one of them is renamed.
193
+ */
194
+ declare function sectionRenameProp(fields: Record<string, unknown> | undefined): "name" | null;
195
+ /**
196
+ * What a ROOT-level node is called in the trees — rung 1 of the same precedence
197
+ * above, and nothing below it.
198
+ *
199
+ * A root node is not a slot child: it has no linked collection, no card-local
200
+ * override and no catalog slug, so four of the five rungs have nothing to say
201
+ * about it. What it CAN carry is rung 1 — an explicit name the author (or the
202
+ * seeding) wrote — and before this function nothing at the root read it.
203
+ *
204
+ * ⚠️ THE DEFECT THAT PUT THIS HERE. `addSection` seeds a split pair as a Box
205
+ * carrying `name: "<Section> section"`, and the comment beside that line says
206
+ * the rename seam reads `name`. At the root both trees named a node by its TYPE
207
+ * alone, and a Box's type name at section level is the literal "Blank section" —
208
+ * so every pair a merchant added arrived in Layers as "Blank section", with the
209
+ * stored name read by nobody. A value written and never read is the same defect
210
+ * as a control that reaches nothing.
211
+ *
212
+ * It lives HERE, beside the rule it is a rung of, rather than in the chrome that
213
+ * calls it: two files deciding what a node is called is exactly what card 66194
214
+ * collapsed into this module, and a root rule written in the component would be
215
+ * the fourth copy.
216
+ *
217
+ * `fallback` is the caller's type-level label (`sectionLabel(type)`), which is
218
+ * what every published page reads today and what an unnamed node keeps reading.
219
+ *
220
+ * `rowName` is the layer's last word ({@link RowNameRule}), asked at the
221
+ * SECTION level with what this rung answered.
222
+ */
223
+ declare function rootRowName<N extends SlotChild>(node: N, fallback: string, rowName?: RowNameRule<N>): string;
224
+
225
+ export { type RowNameRule, type SlotChild, rootRowName, sectionRenameProp, slotChildName, slotChildRenameProp, slotChildRowName };
@@ -0,0 +1 @@
1
+ export{rootRowName,sectionRenameProp,slotChildName,slotChildRenameProp,slotChildRowName}from"../../../chunk-SSRYU3YG.js";import"../../../chunk-ANPOR6EY.js";import"../../../chunk-6UAEFOJ4.js";
@@ -0,0 +1,5 @@
1
+ import { TreeItem } from './content-tree.js';
2
+
3
+ declare function dedupeSlotChildren(item: TreeItem, slots: string[]): TreeItem["props"] | null;
4
+
5
+ export { dedupeSlotChildren };
@@ -0,0 +1 @@
1
+ export{dedupeSlotChildren}from"../../../chunk-7OCEPOEJ.js";
@@ -0,0 +1,96 @@
1
+ /**
2
+ * A component type's own `defaultProps`, looked up in the Puck config.
3
+ *
4
+ * Handed IN rather than imported: `lib/document/config` imports the seed
5
+ * registry's neighbours, and a seed registry that reached back into the config
6
+ * would close the loop. Both callers of `seeds()` already hold the config
7
+ * (`components/ScreenChrome`, `components/StandaloneSectionEditor`),
8
+ * so the lookup travels the short way.
9
+ *
10
+ * ⚠️ IT IS OPTIONAL, AND THE FIVE SPECS THAT PREDATE IT IGNORE IT. They
11
+ * seed ONE flat child whose every field is content, so a missing default changes
12
+ * nothing they draw. Image & Text Columns seeds a Box holding blocks, and a Box
13
+ * without its `direction` / `justify` / `align` / `wrap` is a different shape on
14
+ * the page — see `boxColumnSeed` in lib/document/slot-specs.
15
+ */
16
+ type NodeDefaults = (type: string) => Record<string, unknown>;
17
+ interface SlotSectionSpec {
18
+ /** The primary slot field on the section (e.g. Hero's `slides`). */
19
+ slot: string;
20
+ /** The child component type the slot holds. */
21
+ childType: string;
22
+ /** The "Add …" affordance label. */
23
+ addLabel: string;
24
+ /**
25
+ * The children ARE the section, and no surface offers to add one.
26
+ *
27
+ * ⚠️ NOT THE SAME THING AS `addBlocked`, AND THE DIFFERENCE IS WHY IT EXISTS.
28
+ * `addBlocked` is a reason adding is impossible RIGHT NOW — a hero anchor
29
+ * already holds four — so the row stays, greyed, with the sentence on it, and
30
+ * the merchant can act on it (re-place a group and Add comes back). A fixed
31
+ * set has no such state: the row would be permanently dead furniture, and
32
+ * `NodeContextMenu`'s own rule says it plainest — a row must never be a button
33
+ * that does nothing.
34
+ *
35
+ * Both surfaces that draw an Add row read this. `addBlocked` is still declared
36
+ * beside it, because the DROP path asks that one and never this.
37
+ */
38
+ fixed?: boolean;
39
+ /** Children render as a HORIZONTAL slider (selection must advance it). */
40
+ slider?: boolean;
41
+ /**
42
+ * Prop bags for the default children a fresh section is seeded with.
43
+ *
44
+ * `defaultsFor` is {@link NodeDefaults} — present when the caller holds the
45
+ * config, absent otherwise, and every spec that seeds a plain content child
46
+ * simply declines it.
47
+ */
48
+ seeds: (defaultsFor?: NodeDefaults) => Record<string, unknown>[];
49
+ /**
50
+ * Convert a section's LEGACY props (an older inline-array field) into slot
51
+ * children at load-time — the chrome-only migration for pages saved before the
52
+ * field became a slot. Returns [] when there's nothing to migrate, in which
53
+ * case the seeder falls back to `seeds()`.
54
+ */
55
+ legacy?: (props: Record<string, unknown>) => Record<string, unknown>[];
56
+ /**
57
+ * Why this section cannot take another child right now — a sentence the
58
+ * merchant reads — or `null` when it can (card 66189).
59
+ *
60
+ * Optional, and only the Hero slide answers it today: a group is placed on one
61
+ * of nine anchors, an anchor stacks at most four, and a fifth would be drawn
62
+ * ON TOP of the fourth. The rule lives on the SPEC rather than inside
63
+ * `SlotChildRows` because the list is shared by five sections and this is one
64
+ * section's arithmetic — the list asks, the spec answers.
65
+ */
66
+ addBlocked?: (children: readonly unknown[], incoming?: unknown) => string | null;
67
+ /**
68
+ * Why this section must NOT be seeded at all, read off its OWN stored props.
69
+ *
70
+ * The seeder's existing guard is "the slot already has children" — right for a
71
+ * section whose only shape is the slot, and blind to a section that still
72
+ * carries an OLDER one. Image & Text Columns is the first of those: its
73
+ * columns used to be a `steps` ARRAY, the owner ruled on 2026-09-05 that
74
+ * nothing is migrated, and a stored page therefore has a full `steps` and an
75
+ * empty `boxes`. Without this the seeder would drop three fresh Boxes into a
76
+ * published page that already draws three columns, and the merchant would find
77
+ * six.
78
+ *
79
+ * Deliberately a question about the PARENT'S props, not about the slot — the
80
+ * slot is what the existing guard already reads, and answering "is there an
81
+ * older shape here" from the same place is what makes this a second question
82
+ * rather than a second opinion on the first.
83
+ */
84
+ skipSeed?: (props: Record<string, unknown>) => boolean;
85
+ /**
86
+ * What the list says about the children it ALREADY holds, or `null`.
87
+ *
88
+ * The counterpart to `addBlocked`, and deliberately a second question rather
89
+ * than a second answer from the first: `addBlocked` is about a group that has
90
+ * not arrived yet, this is about the ones that are already here and cannot all
91
+ * be drawn. A section that cannot get into that state simply declares neither.
92
+ */
93
+ notice?: (children: readonly unknown[]) => string | null;
94
+ }
95
+
96
+ export type { NodeDefaults, SlotSectionSpec };
@@ -0,0 +1 @@
1
+ import"../../../chunk-A2VVB4RH.js";
@@ -0,0 +1,144 @@
1
+ import { StyleRow } from '../../../style-clipboard/index.js';
2
+ import { S as StyleClipboardWords } from '../../../words-CnnHb9jo.js';
3
+ import { ScreenStyleDocument, ScreenNode, ScreenStylePastePlan, ScreenStyleClipboard } from '../screen-parts.js';
4
+ import { panelFieldsOf } from './panel-fields.js';
5
+ import '../../../types-BbOBWXMP.js';
6
+ import 'react';
7
+ import '../../../blocks/index.js';
8
+ import '../../../types-Cq53lL8d.js';
9
+ import '../../../data/index.js';
10
+ import '../../../types-41704JE4.js';
11
+ import '../../../resolve-D68pb3Bx.js';
12
+ import '../../../plan-CZS902DV.js';
13
+ import '../../../watch-D8xZow3y.js';
14
+ import '../../../types-B3iSHX-w.js';
15
+ import '../../../types-Cy7rdmXt.js';
16
+ import '../../../wordFit-7XpmhcaW.js';
17
+ import '../../../edit-lock/index.js';
18
+ import '../../../panelWidths-DgQXiPXU.js';
19
+ import '../../../CanvasDragLayer-CFUcBbgc.js';
20
+ import '../../../session-DSQFmIvx.js';
21
+ import '../../../words-SD4neL0n.js';
22
+ import '../../../types-DBy3L69b.js';
23
+ import 'efficient-shell/ui';
24
+ import '../../../words-Cl9xMUYY.js';
25
+ import '../../components/AddSidePanel.js';
26
+ import '../section-template-types.js';
27
+ import './content-tree.js';
28
+ import '../shared-section-types.js';
29
+ import './block-choice.js';
30
+ import '../../../ScreenDocumentContext-1RgtGKWR.js';
31
+ import '../document-contract.js';
32
+ import '../document-switch.js';
33
+ import '../../../engine-CvXpFE86.js';
34
+ import '../admin-bridge.js';
35
+ import '../session.js';
36
+ import '../backend-error.js';
37
+ import '../host-chrome.js';
38
+ import '../links/link-filters.js';
39
+ import '../document-hooks.js';
40
+ import './add-target-types.js';
41
+ import './slot-section-spec.js';
42
+
43
+ /**
44
+ * lib/document/style-clipboard.ts — COPY STYLE / PASTE STYLE in the website editor
45
+ * (card [ADD] Copy Style And Paste Style, owner 2026-09-19).
46
+ *
47
+ * The clipboard, the matching rule, the menu rows, the words and the shortcut
48
+ * test are `efficient-easel/style-clipboard`'s — written once for both editors;
49
+ * the campaign designer draws the same two rows from the same module. This file
50
+ * answers only the two questions that are the website editor's own:
51
+ *
52
+ * 1. WHICH ROWS of a node are its look — {@link nodeStyleRows};
53
+ * 2. WHAT KIND each row is — {@link shopFieldKind}.
54
+ *
55
+ * ── WHICH ROWS ──────────────────────────────────────────────────────────────
56
+ * Owner's rule 3 was "the Style and Layout tabs, never Content". Since 4.0.0
57
+ * the panel has two tabs, Design and Animation (owner, final 2026-10-10), and
58
+ * what was the Content tab sits at the top of Design — so the rule is read off
59
+ * the Design GROUPS instead of the tabs: the rows under Size, Design, Layout or
60
+ * Position are a look and are copied. Never the Content group (its
61
+ * `_dContent` marker, and every row of Design before the first group heading),
62
+ * never Anchor, never Animation.
63
+ *
64
+ * The panel after `assignSectionGroups` is a flat list in which each bucket
65
+ * header (`BUCKET_KEY`) opens its run — the same reading the tab strip hides
66
+ * rows by — and inside Design each group heading (`DESIGN_GROUP_KEY`) opens
67
+ * its own; a row belongs to the headers above it. A group heading counts only
68
+ * inside Design.
69
+ *
70
+ * Left out even in those groups (the list GG approved on 2026-09-19):
71
+ * · every picture (`__media`) — Media folded into Style on 2026-09-14, and a
72
+ * picture is Content;
73
+ * · words and links (`__text`, `__link`);
74
+ * · headings, bucket headers and notes — `__fold`, and every `_`-key (the
75
+ * panel's own furniture, as in the campaign designer) — which store nothing;
76
+ * · the Anchor rows — a deep-link id must be unique on the page;
77
+ * · slots (Boxes, children) — structure, not a look;
78
+ * · a picture's focal point (`focal`, `imageFocal`) — a point ON ONE picture,
79
+ * meaningless on another, like the campaign logo's colour map.
80
+ * A text part's own look (`partStyles`) is no row at all, so it is never read.
81
+ *
82
+ * ── THE PHONE VALUE ─────────────────────────────────────────────────────────
83
+ * Stored as its own row (`<key>Phone`, ./phone-override), on the same tab, so it
84
+ * travels like any row. It is not COUNTED: the merchant sees one row per
85
+ * device, and the number is the rows they see.
86
+ */
87
+
88
+ type Props = Record<string, unknown>;
89
+ type NodeLike = {
90
+ type: string;
91
+ props: Props;
92
+ };
93
+ type ConfigLike = Parameters<typeof panelFieldsOf>[0];
94
+ /** The clipboard's scope: one site (GG, 2026-09-19) — across its pages. */
95
+ declare function siteStyleScope(siteId: string | null | undefined): string;
96
+ /**
97
+ * The kind of one website-editor row.
98
+ *
99
+ * · a tag (a shared builder's `section:<key>`, ../controls `sharedStyleKinds`)
100
+ * wins, on the gate or on the control it wraps;
101
+ * · a CHOICE row (it declares `options`) is `choice:` plus its sorted values;
102
+ * · anything else is the shell's reading, which answers `null` for an
103
+ * untagged custom control: it pastes only onto the same section type.
104
+ */
105
+ declare function shopFieldKind(field: unknown): string | null;
106
+ /** A node's look, as rows the shell's clipboard can hold and match. */
107
+ declare function nodeStyleRows(config: ConfigLike, node: NodeLike): StyleRow[];
108
+ /** Copy one node's look into the site's clipboard. */
109
+ declare function copyNodeStyle(config: ConfigLike, scope: string, node: NodeLike, label: string): void;
110
+ /**
111
+ * What a paste onto this node would do: the new props, and the words the
112
+ * merchant reads. Null when nothing is held for this site. The caller writes
113
+ * `props` through its one replace op only when `changed`, and always shows
114
+ * `message` — "nothing matched" is an answer, not a silence.
115
+ */
116
+ declare function planNodePaste(config: ConfigLike, scope: string, node: NodeLike, label: string, words?: StyleClipboardWords): {
117
+ props: Props;
118
+ changed: boolean;
119
+ pasted: number;
120
+ message: string;
121
+ } | null;
122
+ /** A style clipboard with every member answered: the screen's reading of a
123
+ * layer's {@link ScreenStyleClipboard}. */
124
+ interface ResolvedStyleClipboard {
125
+ scope: (doc: ScreenStyleDocument) => string;
126
+ rows: (config: unknown, node: ScreenNode) => StyleRow[];
127
+ copy: (scope: string, node: ScreenNode, label: string, config: unknown) => void;
128
+ plan: (scope: string, node: ScreenNode, label: string, config: unknown) => ScreenStylePastePlan | null;
129
+ }
130
+ /**
131
+ * COPY STYLE / PASTE STYLE AS THE SCREEN RUNS THEM (0.105.0): a layer's
132
+ * clipboard (lib/screen-parts `styleClipboard`) with every member it left out
133
+ * answered the website's way. A layer's `copy` and `plan`, where it hands none,
134
+ * read the rows it handed (`rows`), so a layer with its own look and nothing
135
+ * else still copies and pastes. With no layer's: exactly the website's —
136
+ * `siteStyleScope(siteId)`, `nodeStyleRows`, `copyNodeStyle`, `planNodePaste`.
137
+ */
138
+ declare function styleClipboardOf(part: ScreenStyleClipboard | null | undefined,
139
+ /** What the screen's own `plan` says after a paste, in the host's language
140
+ * (`EaselStrings.styleClipboard`, 3.1.0). A layer's own `plan` says its own
141
+ * words. Left out: English. */
142
+ words?: StyleClipboardWords): ResolvedStyleClipboard;
143
+
144
+ export { type ResolvedStyleClipboard, copyNodeStyle, nodeStyleRows, planNodePaste, shopFieldKind, siteStyleScope, styleClipboardOf };
@@ -0,0 +1 @@
1
+ export{copyNodeStyle,nodeStyleRows,planNodePaste,shopFieldKind,siteStyleScope,styleClipboardOf}from"../../../chunk-SWBADIQT.js";import"../../../chunk-5XL2RXFU.js";import"../../../chunk-KWLHKKZO.js";import"../../../chunk-INRERJU4.js";import"../../../chunk-3QB2ZQXK.js";import"../../../chunk-EB6NI2VK.js";import"../../../chunk-V7U33NF2.js";import"../../../chunk-6WY6ZXJG.js";import"../../../chunk-ANPOR6EY.js";import"../../../chunk-BPXEFVSQ.js";import"../../../chunk-MFIRYGHW.js";import"../../../chunk-BSPCSC45.js";