@kywi-software/core 0.10.0 → 0.12.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 (248) hide show
  1. package/AGENT-PATTERNS.md +111 -23
  2. package/README.md +67 -0
  3. package/dist/admin/content-form.d.ts.map +1 -1
  4. package/dist/admin/content-form.js +97 -10
  5. package/dist/admin/content-form.js.map +1 -1
  6. package/dist/admin/layout-editor/component-actions.d.ts +219 -22
  7. package/dist/admin/layout-editor/component-actions.d.ts.map +1 -1
  8. package/dist/admin/layout-editor/component-actions.js +356 -36
  9. package/dist/admin/layout-editor/component-actions.js.map +1 -1
  10. package/dist/admin/layout-editor/component-fork.d.ts +224 -0
  11. package/dist/admin/layout-editor/component-fork.d.ts.map +1 -0
  12. package/dist/admin/layout-editor/component-fork.js +342 -0
  13. package/dist/admin/layout-editor/component-fork.js.map +1 -0
  14. package/dist/admin/layout-editor/editor-canvas.d.ts +28 -7
  15. package/dist/admin/layout-editor/editor-canvas.d.ts.map +1 -1
  16. package/dist/admin/layout-editor/editor-canvas.js +145 -32
  17. package/dist/admin/layout-editor/editor-canvas.js.map +1 -1
  18. package/dist/admin/layout-editor/editor-dialog.d.ts +164 -0
  19. package/dist/admin/layout-editor/editor-dialog.d.ts.map +1 -0
  20. package/dist/admin/layout-editor/editor-dialog.js +195 -0
  21. package/dist/admin/layout-editor/editor-dialog.js.map +1 -0
  22. package/dist/admin/layout-editor/editor-state.d.ts +76 -0
  23. package/dist/admin/layout-editor/editor-state.d.ts.map +1 -1
  24. package/dist/admin/layout-editor/editor-state.js +47 -1
  25. package/dist/admin/layout-editor/editor-state.js.map +1 -1
  26. package/dist/admin/layout-editor/editor.css +366 -4
  27. package/dist/admin/layout-editor/index.d.ts +10 -1
  28. package/dist/admin/layout-editor/index.d.ts.map +1 -1
  29. package/dist/admin/layout-editor/index.js +11 -1
  30. package/dist/admin/layout-editor/index.js.map +1 -1
  31. package/dist/admin/layout-editor/inline-text.d.ts +56 -4
  32. package/dist/admin/layout-editor/inline-text.d.ts.map +1 -1
  33. package/dist/admin/layout-editor/inline-text.js +134 -11
  34. package/dist/admin/layout-editor/inline-text.js.map +1 -1
  35. package/dist/admin/layout-editor/layout-editor.d.ts +58 -1
  36. package/dist/admin/layout-editor/layout-editor.d.ts.map +1 -1
  37. package/dist/admin/layout-editor/layout-editor.js +160 -190
  38. package/dist/admin/layout-editor/layout-editor.js.map +1 -1
  39. package/dist/admin/layout-editor/linked-component.d.ts +39 -0
  40. package/dist/admin/layout-editor/linked-component.d.ts.map +1 -0
  41. package/dist/admin/layout-editor/linked-component.js +42 -0
  42. package/dist/admin/layout-editor/linked-component.js.map +1 -0
  43. package/dist/admin/layout-editor/module-overlay.d.ts +36 -14
  44. package/dist/admin/layout-editor/module-overlay.d.ts.map +1 -1
  45. package/dist/admin/layout-editor/module-overlay.js +233 -25
  46. package/dist/admin/layout-editor/module-overlay.js.map +1 -1
  47. package/dist/admin/layout-editor/node-lookup.d.ts +35 -0
  48. package/dist/admin/layout-editor/node-lookup.d.ts.map +1 -1
  49. package/dist/admin/layout-editor/node-lookup.js +91 -0
  50. package/dist/admin/layout-editor/node-lookup.js.map +1 -1
  51. package/dist/admin/layout-editor/overlay-shell.d.ts.map +1 -1
  52. package/dist/admin/layout-editor/overlay-shell.js +150 -32
  53. package/dist/admin/layout-editor/overlay-shell.js.map +1 -1
  54. package/dist/admin/layout-editor/props-panel.d.ts +54 -1
  55. package/dist/admin/layout-editor/props-panel.d.ts.map +1 -1
  56. package/dist/admin/layout-editor/props-panel.js +119 -10
  57. package/dist/admin/layout-editor/props-panel.js.map +1 -1
  58. package/dist/admin/layout-editor/section-overlay.d.ts +16 -1
  59. package/dist/admin/layout-editor/section-overlay.d.ts.map +1 -1
  60. package/dist/admin/layout-editor/section-overlay.js +21 -11
  61. package/dist/admin/layout-editor/section-overlay.js.map +1 -1
  62. package/dist/admin/layout-editor/section-template-picker.d.ts +27 -1
  63. package/dist/admin/layout-editor/section-template-picker.d.ts.map +1 -1
  64. package/dist/admin/layout-editor/section-template-picker.js +71 -17
  65. package/dist/admin/layout-editor/section-template-picker.js.map +1 -1
  66. package/dist/admin/layout-editor/section-variant-container-config.js +5 -5
  67. package/dist/admin/layout-editor/section-variant-container-config.js.map +1 -1
  68. package/dist/admin/layout-editor/use-chrome-flip.d.ts +111 -11
  69. package/dist/admin/layout-editor/use-chrome-flip.d.ts.map +1 -1
  70. package/dist/admin/layout-editor/use-chrome-flip.js +233 -33
  71. package/dist/admin/layout-editor/use-chrome-flip.js.map +1 -1
  72. package/dist/admin/layout-editor/use-component-connect.d.ts +61 -0
  73. package/dist/admin/layout-editor/use-component-connect.d.ts.map +1 -0
  74. package/dist/admin/layout-editor/use-component-connect.js +292 -0
  75. package/dist/admin/layout-editor/use-component-connect.js.map +1 -0
  76. package/dist/admin/layout-editor/use-component-fork.d.ts +123 -0
  77. package/dist/admin/layout-editor/use-component-fork.d.ts.map +1 -0
  78. package/dist/admin/layout-editor/use-component-fork.js +346 -0
  79. package/dist/admin/layout-editor/use-component-fork.js.map +1 -0
  80. package/dist/admin/layout-editor/use-component-library.d.ts +94 -0
  81. package/dist/admin/layout-editor/use-component-library.d.ts.map +1 -0
  82. package/dist/admin/layout-editor/use-component-library.js +55 -0
  83. package/dist/admin/layout-editor/use-component-library.js.map +1 -0
  84. package/dist/admin/registry.d.ts +11 -2
  85. package/dist/admin/registry.d.ts.map +1 -1
  86. package/dist/admin/registry.js +40 -4
  87. package/dist/admin/registry.js.map +1 -1
  88. package/dist/admin/server.d.ts +1 -0
  89. package/dist/admin/server.d.ts.map +1 -1
  90. package/dist/admin/server.js +5 -0
  91. package/dist/admin/server.js.map +1 -1
  92. package/dist/admin/styles/admin.css +57 -1
  93. package/dist/admin/surfaces/components/component-edit.d.ts +3 -0
  94. package/dist/admin/surfaces/components/component-edit.d.ts.map +1 -0
  95. package/dist/admin/surfaces/components/component-edit.js +235 -0
  96. package/dist/admin/surfaces/components/component-edit.js.map +1 -0
  97. package/dist/admin/surfaces/components/components-data.d.ts +153 -0
  98. package/dist/admin/surfaces/components/components-data.d.ts.map +1 -0
  99. package/dist/admin/surfaces/components/components-data.js +154 -0
  100. package/dist/admin/surfaces/components/components-data.js.map +1 -0
  101. package/dist/admin/surfaces/components/components-list.d.ts +3 -0
  102. package/dist/admin/surfaces/components/components-list.d.ts.map +1 -0
  103. package/dist/admin/surfaces/components/components-list.js +196 -0
  104. package/dist/admin/surfaces/components/components-list.js.map +1 -0
  105. package/dist/admin/surfaces/components/definition-canvas.d.ts +73 -0
  106. package/dist/admin/surfaces/components/definition-canvas.d.ts.map +1 -0
  107. package/dist/admin/surfaces/components/definition-canvas.js +207 -0
  108. package/dist/admin/surfaces/components/definition-canvas.js.map +1 -0
  109. package/dist/admin/surfaces/layouts/layout-editor-client.d.ts.map +1 -1
  110. package/dist/admin/surfaces/layouts/layout-editor-client.js +14 -2
  111. package/dist/admin/surfaces/layouts/layout-editor-client.js.map +1 -1
  112. package/dist/admin/surfaces/layouts/layouts-data.d.ts +3 -14
  113. package/dist/admin/surfaces/layouts/layouts-data.d.ts.map +1 -1
  114. package/dist/admin/surfaces/layouts/layouts-data.js +4 -7
  115. package/dist/admin/surfaces/layouts/layouts-data.js.map +1 -1
  116. package/dist/admin/surfaces/layouts/layouts-list.d.ts.map +1 -1
  117. package/dist/admin/surfaces/layouts/layouts-list.js +16 -22
  118. package/dist/admin/surfaces/layouts/layouts-list.js.map +1 -1
  119. package/dist/admin/surfaces/settings/admin-features.d.ts.map +1 -1
  120. package/dist/admin/surfaces/settings/admin-features.js +1 -0
  121. package/dist/admin/surfaces/settings/admin-features.js.map +1 -1
  122. package/dist/api/bulk-routes.d.ts.map +1 -1
  123. package/dist/api/bulk-routes.js +25 -0
  124. package/dist/api/bulk-routes.js.map +1 -1
  125. package/dist/api/changeset-routes.d.ts.map +1 -1
  126. package/dist/api/changeset-routes.js +17 -3
  127. package/dist/api/changeset-routes.js.map +1 -1
  128. package/dist/api/component-routes.d.ts.map +1 -1
  129. package/dist/api/component-routes.js +228 -8
  130. package/dist/api/component-routes.js.map +1 -1
  131. package/dist/api/content-routes.d.ts.map +1 -1
  132. package/dist/api/content-routes.js +64 -0
  133. package/dist/api/content-routes.js.map +1 -1
  134. package/dist/api/feed-routes.d.ts +6 -6
  135. package/dist/api/graphql/resolvers.d.ts +4 -4
  136. package/dist/api/layout-routes.d.ts.map +1 -1
  137. package/dist/api/layout-routes.js +4 -17
  138. package/dist/api/layout-routes.js.map +1 -1
  139. package/dist/api/layout-write-guard.d.ts +80 -0
  140. package/dist/api/layout-write-guard.d.ts.map +1 -0
  141. package/dist/api/layout-write-guard.js +88 -0
  142. package/dist/api/layout-write-guard.js.map +1 -0
  143. package/dist/api/section-template-routes.d.ts.map +1 -1
  144. package/dist/api/section-template-routes.js +11 -0
  145. package/dist/api/section-template-routes.js.map +1 -1
  146. package/dist/api/translation-routes.d.ts.map +1 -1
  147. package/dist/api/translation-routes.js +8 -0
  148. package/dist/api/translation-routes.js.map +1 -1
  149. package/dist/api/version-routes.d.ts.map +1 -1
  150. package/dist/api/version-routes.js +20 -8
  151. package/dist/api/version-routes.js.map +1 -1
  152. package/dist/api/workflow-routes.d.ts.map +1 -1
  153. package/dist/api/workflow-routes.js +53 -8
  154. package/dist/api/workflow-routes.js.map +1 -1
  155. package/dist/db/analytics-queries.d.ts +3 -3
  156. package/dist/db/apply-snapshot.d.ts +75 -8
  157. package/dist/db/apply-snapshot.d.ts.map +1 -1
  158. package/dist/db/apply-snapshot.js +104 -8
  159. package/dist/db/apply-snapshot.js.map +1 -1
  160. package/dist/db/audit-queries.d.ts +12 -12
  161. package/dist/db/category-queries.d.ts +3 -3
  162. package/dist/db/changeset-audit-queries.d.ts +4 -4
  163. package/dist/db/changeset-queries.d.ts +7 -7
  164. package/dist/db/comment-queries.d.ts +8 -8
  165. package/dist/db/comment-subscription-queries.d.ts +2 -2
  166. package/dist/db/component-instance-queries.d.ts +197 -0
  167. package/dist/db/component-instance-queries.d.ts.map +1 -0
  168. package/dist/db/component-instance-queries.js +405 -0
  169. package/dist/db/component-instance-queries.js.map +1 -0
  170. package/dist/db/content-queries.d.ts.map +1 -1
  171. package/dist/db/content-queries.js +39 -2
  172. package/dist/db/content-queries.js.map +1 -1
  173. package/dist/db/extension-queries.d.ts +7 -7
  174. package/dist/db/feed-queries.d.ts +3 -3
  175. package/dist/db/index.d.ts +1 -0
  176. package/dist/db/index.d.ts.map +1 -1
  177. package/dist/db/index.js +1 -0
  178. package/dist/db/index.js.map +1 -1
  179. package/dist/db/layout-queries.d.ts +13 -1
  180. package/dist/db/layout-queries.d.ts.map +1 -1
  181. package/dist/db/layout-queries.js +52 -7
  182. package/dist/db/layout-queries.js.map +1 -1
  183. package/dist/db/locale-queries.d.ts.map +1 -1
  184. package/dist/db/locale-queries.js +0 -0
  185. package/dist/db/locale-queries.js.map +1 -1
  186. package/dist/db/media-queries.d.ts +12 -12
  187. package/dist/db/revision-queries.d.ts +3 -3
  188. package/dist/db/site-admin-queries.d.ts +2 -2
  189. package/dist/db/site-membership-queries.d.ts +3 -3
  190. package/dist/db/site-plugin-queries.d.ts +2 -2
  191. package/dist/db/site-queries.d.ts +6 -6
  192. package/dist/db/version-queries.d.ts +12 -12
  193. package/dist/db/webhook-queries.d.ts +11 -11
  194. package/dist/db/workflow-queries.d.ts +6 -6
  195. package/dist/db/workflow-queries.d.ts.map +1 -1
  196. package/dist/db/workflow-queries.js +11 -2
  197. package/dist/db/workflow-queries.js.map +1 -1
  198. package/dist/layout/comments-module.d.ts.map +1 -1
  199. package/dist/layout/comments-module.js +6 -2
  200. package/dist/layout/comments-module.js.map +1 -1
  201. package/dist/layout/component-refs.d.ts +465 -0
  202. package/dist/layout/component-refs.d.ts.map +1 -0
  203. package/dist/layout/component-refs.js +848 -0
  204. package/dist/layout/component-refs.js.map +1 -0
  205. package/dist/layout/index.d.ts +2 -1
  206. package/dist/layout/index.d.ts.map +1 -1
  207. package/dist/layout/index.js +1 -0
  208. package/dist/layout/index.js.map +1 -1
  209. package/dist/layout/module-permissions.d.ts +49 -1
  210. package/dist/layout/module-permissions.d.ts.map +1 -1
  211. package/dist/layout/module-permissions.js +117 -6
  212. package/dist/layout/module-permissions.js.map +1 -1
  213. package/dist/layout/module-render-context.d.ts +32 -0
  214. package/dist/layout/module-render-context.d.ts.map +1 -1
  215. package/dist/layout/module-render-context.js +32 -1
  216. package/dist/layout/module-render-context.js.map +1 -1
  217. package/dist/layout/modules-extended.d.ts.map +1 -1
  218. package/dist/layout/modules-extended.js +21 -11
  219. package/dist/layout/modules-extended.js.map +1 -1
  220. package/dist/layout/modules.d.ts.map +1 -1
  221. package/dist/layout/modules.js +15 -10
  222. package/dist/layout/modules.js.map +1 -1
  223. package/dist/layout/renderer.d.ts +51 -4
  224. package/dist/layout/renderer.d.ts.map +1 -1
  225. package/dist/layout/renderer.js +36 -38
  226. package/dist/layout/renderer.js.map +1 -1
  227. package/dist/layout/types.d.ts +42 -0
  228. package/dist/layout/types.d.ts.map +1 -1
  229. package/dist/layout/types.js +54 -11
  230. package/dist/layout/types.js.map +1 -1
  231. package/dist/schema/base.d.ts +1 -1
  232. package/dist/schema/components.d.ts +150 -0
  233. package/dist/schema/components.d.ts.map +1 -1
  234. package/dist/schema/components.js +50 -4
  235. package/dist/schema/components.js.map +1 -1
  236. package/dist/scope/inline-editing.d.ts.map +1 -1
  237. package/dist/scope/inline-editing.js +10 -0
  238. package/dist/scope/inline-editing.js.map +1 -1
  239. package/dist/scope/sticky-offset.d.ts +185 -0
  240. package/dist/scope/sticky-offset.d.ts.map +1 -0
  241. package/dist/scope/sticky-offset.js +432 -0
  242. package/dist/scope/sticky-offset.js.map +1 -0
  243. package/dist/site/styles.css +41 -3
  244. package/dist/versioning/scheduler.d.ts +8 -0
  245. package/dist/versioning/scheduler.d.ts.map +1 -1
  246. package/dist/versioning/scheduler.js +21 -7
  247. package/dist/versioning/scheduler.js.map +1 -1
  248. package/package.json +1 -1
@@ -1,21 +1,31 @@
1
1
  import React from 'react';
2
2
  import type { OverlayAction } from './section-overlay.js';
3
+ import type { InlineTextProp, InlineTextBindingTarget } from './inline-text.js';
3
4
  /**
4
- * Inline text editing for one module (kywi-cms#94). The overlay makes its own
5
- * wrapper which contains the module's real rendered element contenteditable
6
- * so the owner types on the page, in the page's styling. Commit reads the value
5
+ * Inline text editing for one module (kywi-cms#94, kywi-cms#145). The overlay
6
+ * makes the element that renders ONE prop contenteditablethe real `<h3>` a
7
+ * card's title is drawn in — so the owner types on the page, in the page's
8
+ * styling, and a commit can only ever write that prop. Commit reads the value
7
9
  * back out of the DOM (see `readInlineTextValue`); the parent turns that into an
8
10
  * `UPDATE_PROPS` dispatch, so the edit goes through history like any other.
11
+ *
12
+ * Which element that is is resolved per gesture rather than per module: see
13
+ * `resolveInlineBinding`, which the parent wires into `resolve` below.
9
14
  */
10
15
  export interface InlineTextBinding {
11
16
  /** True while THIS module is the one being text-edited. */
12
17
  active: boolean;
13
- /** Whether the bound prop holds HTML (Enter inserts a line break instead of committing). */
14
- html: boolean;
18
+ /**
19
+ * Resolve the element + prop a gesture at `target` binds, or null when there
20
+ * is nothing safe to bind — in which case the gesture falls through to
21
+ * `onInlineFallback` (the props rail) instead of editing anything
22
+ * (kywi-cms#145).
23
+ */
24
+ resolve: (wrapper: HTMLElement, target: Element | null) => InlineTextBindingTarget | null;
15
25
  /** Begin editing (double-click, or a click on an already-selected module). */
16
26
  onActivate: () => void;
17
- /** Commit the value currently in `host` and end the edit. */
18
- onCommit: (host: HTMLElement) => void;
27
+ /** Commit the value currently in `host` to `prop` and end the edit. */
28
+ onCommit: (host: HTMLElement, prop: InlineTextProp) => void;
19
29
  /** Abandon the edit and end it, leaving the stored props untouched. */
20
30
  onCancel: () => void;
21
31
  }
@@ -49,16 +59,28 @@ interface ModuleOverlayProps {
49
59
  /** Inline text editing binding, when this module carries a primary text prop. */
50
60
  inlineText?: InlineTextBinding | null;
51
61
  /**
52
- * Double-click fallback for a module with no primary text prop (kywi-cms#118).
53
- * Without a text prop to bind, double-click otherwise no-ops and reads as
54
- * "dead" this routes the gesture to the props rail instead: select the
55
- * module, then focus its first field there. Only meaningful in in-place mode
56
- * (see `inlineTextBindingFor`'s own `!inPlace` short-circuit); admin canvas
57
- * never carries `inlineEdit`, so it never gets this either.
62
+ * Double-click fallback for a gesture with nothing safe to bind
63
+ * (kywi-cms#118, widened by kywi-cms#145). That is a module with no text prop
64
+ * at all, and now also one whose text props the renderer does not anchor
65
+ * individually where the old wrapper binding was the corruption. Without it
66
+ * double-click no-ops and reads as "dead", so this routes the gesture to the
67
+ * props rail instead: select the module, then focus its first field there.
68
+ * Only meaningful in in-place mode (see `inlineTextBindingFor`'s own `!inPlace`
69
+ * short-circuit); admin canvas never carries `inlineEdit`, so it never gets
70
+ * this either.
58
71
  */
59
72
  onInlineFallback?: () => void;
73
+ /**
74
+ * The component this module is a linked instance of (kywi-cms#147). Stamps
75
+ * `data-component-id` (the same hook the public renderer emits), switches the
76
+ * wrapper to the linked outline, and names the component in a pill beside the
77
+ * type chip — a linked module is otherwise indistinguishable from an ordinary
78
+ * one, which is how an owner edits eleven pages by accident.
79
+ */
80
+ componentId?: string;
81
+ componentName?: string | null;
60
82
  children: React.ReactNode;
61
83
  }
62
- export declare function ModuleOverlay({ moduleId, instanceId, columnId, index, isSelected, onSelect, actions, typeLabel, inPlace, moduleType, inlineText, onInlineFallback, children, }: ModuleOverlayProps): import("react/jsx-runtime").JSX.Element;
84
+ export declare function ModuleOverlay({ moduleId, instanceId, columnId, index, isSelected, onSelect, actions, typeLabel, inPlace, moduleType, inlineText, onInlineFallback, componentId, componentName, children, }: ModuleOverlayProps): import("react/jsx-runtime").JSX.Element;
63
85
  export {};
64
86
  //# sourceMappingURL=module-overlay.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"module-overlay.d.ts","sourceRoot":"","sources":["../../../src/admin/layout-editor/module-overlay.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAGzD;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC,2DAA2D;IAC3D,MAAM,EAAE,OAAO,CAAA;IACf,4FAA4F;IAC5F,IAAI,EAAE,OAAO,CAAA;IACb,8EAA8E;IAC9E,UAAU,EAAE,MAAM,IAAI,CAAA;IACtB,6DAA6D;IAC7D,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAA;IACrC,uEAAuE;IACvE,QAAQ,EAAE,MAAM,IAAI,CAAA;CACrB;AAED,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB;;;;;sDAKkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,OAAO,CAAA;IACnB,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,OAAO,CAAC,EAAE,aAAa,EAAE,CAAA;IACzB,8EAA8E;IAC9E,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,yFAAyF;IACzF,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,iFAAiF;IACjF,UAAU,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAA;IACrC;;;;;;;OAOG;IACH,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAA;IAC7B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B;AAED,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,KAAK,EACL,UAAU,EACV,QAAQ,EACR,OAAO,EACP,SAAS,EACT,OAAe,EACf,UAAU,EACV,UAAU,EACV,gBAAgB,EAChB,QAAQ,GACT,EAAE,kBAAkB,2CA6MpB"}
1
+ {"version":3,"file":"module-overlay.d.ts","sourceRoot":"","sources":["../../../src/admin/layout-editor/module-overlay.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAA;AAI/E;;;;;;;;;;GAUG;AACH,MAAM,WAAW,iBAAiB;IAChC,2DAA2D;IAC3D,MAAM,EAAE,OAAO,CAAA;IACf;;;;;OAKG;IACH,OAAO,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,KAAK,uBAAuB,GAAG,IAAI,CAAA;IACzF,8EAA8E;IAC9E,UAAU,EAAE,MAAM,IAAI,CAAA;IACtB,uEAAuE;IACvE,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,cAAc,KAAK,IAAI,CAAA;IAC3D,uEAAuE;IACvE,QAAQ,EAAE,MAAM,IAAI,CAAA;CACrB;AAED,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB;;;;;sDAKkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,OAAO,CAAA;IACnB,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,OAAO,CAAC,EAAE,aAAa,EAAE,CAAA;IACzB,8EAA8E;IAC9E,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,yFAAyF;IACzF,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,iFAAiF;IACjF,UAAU,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAA;IACrC;;;;;;;;;;OAUG;IACH,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAA;IAC7B;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B;AAED,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,KAAK,EACL,UAAU,EACV,QAAQ,EACR,OAAO,EACP,SAAS,EACT,OAAe,EACf,UAAU,EACV,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,aAAa,EACb,QAAQ,GACT,EAAE,kBAAkB,2CAqapB"}
@@ -4,7 +4,8 @@ import React from 'react';
4
4
  import { useSortable } from '@dnd-kit/sortable';
5
5
  import { CSS } from '@dnd-kit/utilities';
6
6
  import { EditorIcon } from './editor-icons.js';
7
- export function ModuleOverlay({ moduleId, instanceId, columnId, index, isSelected, onSelect, actions, typeLabel, inPlace = false, moduleType, inlineText, onInlineFallback, children, }) {
7
+ import { LinkedComponentPill } from './linked-component.js';
8
+ export function ModuleOverlay({ moduleId, instanceId, columnId, index, isSelected, onSelect, actions, typeLabel, inPlace = false, moduleType, inlineText, onInlineFallback, componentId, componentName, children, }) {
8
9
  const { attributes, listeners, setNodeRef, transform, transition } = useSortable({
9
10
  id: moduleId,
10
11
  // `moduleType` (kywi-cms#139 review): without it, `useEditorDnd`'s
@@ -18,20 +19,131 @@ export function ModuleOverlay({ moduleId, instanceId, columnId, index, isSelecte
18
19
  // Escape must not commit: turning contenteditable off blurs the host, and the
19
20
  // blur handler would otherwise save the very edit the owner just abandoned.
20
21
  const cancellingRef = React.useRef(false);
22
+ /** The element + prop the CURRENT edit is bound to (kywi-cms#145). */
23
+ const boundRef = React.useRef(null);
24
+ // Read inside effects and event handlers, which must see the latest binding
25
+ // without re-running the editing effect (which would re-focus and re-place the
26
+ // caret) every time the parent re-creates the binding object.
27
+ const inlineTextRef = React.useRef(inlineText);
28
+ inlineTextRef.current = inlineText;
21
29
  const setRefs = React.useCallback((node) => {
22
30
  hostRef.current = node;
23
31
  setNodeRef(node);
24
32
  }, [setNodeRef]);
25
33
  const isEditing = Boolean(inlineText?.active);
26
- // Focus the editing host and drop the caret at the end of the text, so typing
27
- // continues the copy rather than replacing it.
34
+ /**
35
+ * Recovery counter for an edit whose element went away (kywi-cms#145 review).
36
+ * Bumping it re-runs the attach effect below against the DOM that is actually
37
+ * on the page now.
38
+ */
39
+ const [attachNonce, setAttachNonce] = React.useState(0);
40
+ const reattach = React.useCallback(() => setAttachNonce(n => n + 1), []);
41
+ /**
42
+ * Set once a session has failed to re-resolve and has asked to end. Without
43
+ * it the recovery effect and the attach effect would take turns forever on a
44
+ * module that genuinely has nothing left to bind.
45
+ */
46
+ const abandonedRef = React.useRef(false);
47
+ /**
48
+ * True when a live edit has no element on the page any more.
49
+ *
50
+ * The module's inner DOM can be replaced under an edit — undo emptying a
51
+ * heading swaps the renderer for the #134 empty state, a prop change re-keys
52
+ * a subtree. `contenteditable` is then sitting on a detached node: it can
53
+ * never fire `focusout`, so the edit can never commit, and the gesture
54
+ * handlers below would swallow every click as "already editing", leaving the
55
+ * module inert until a window-level Escape (kywi-cms#145 review).
56
+ */
57
+ function isOrphanedEdit() {
58
+ const bound = boundRef.current;
59
+ return !bound || !bound.element.isConnected;
60
+ }
61
+ /** Resolve + remember what a gesture at `target` would edit. */
62
+ function bind(target) {
63
+ const wrapper = hostRef.current;
64
+ const binding = inlineTextRef.current;
65
+ if (!wrapper || !binding)
66
+ return null;
67
+ const bound = binding.resolve(wrapper, target);
68
+ boundRef.current = bound;
69
+ return bound;
70
+ }
71
+ /**
72
+ * Take an orphaned session over with THIS gesture: re-resolve from where the
73
+ * pointer landed and re-attach. Returns false — and ends the session — when
74
+ * nothing resolves, so the gesture falls through to select/rail rather than
75
+ * being eaten by an edit that can no longer go anywhere.
76
+ *
77
+ * `bind` has already stored the answer by the time `reattach` runs, and the
78
+ * attach effect below is written to consume it (kywi-cms#145 review round 2):
79
+ * the pointer is the ONLY thing that can say which of a card's remaining
80
+ * anchors the owner meant, so losing it here would strand every recovery on a
81
+ * module with two or more of them.
82
+ */
83
+ function recoverOrphanedEdit(target) {
84
+ if (bind(target)) {
85
+ reattach();
86
+ return true;
87
+ }
88
+ inlineTextRef.current?.onCancel();
89
+ return false;
90
+ }
91
+ // Reset per session, ahead of the attach effect below (effects run in
92
+ // declaration order), so a session that ended in failure does not poison the
93
+ // next one.
94
+ React.useEffect(() => {
95
+ if (isEditing)
96
+ abandonedRef.current = false;
97
+ }, [isEditing]);
98
+ // Turn contenteditable on for the BOUND ELEMENT — not the wrapper, unless the
99
+ // wrapper is what resolution chose (kywi-cms#145) — then focus it and drop the
100
+ // caret at the end of the text, so typing continues the copy rather than
101
+ // replacing it. Imperative rather than a rendered `contentEditable` prop
102
+ // because the bound element belongs to the module's own renderer, not to this
103
+ // component's JSX.
28
104
  React.useEffect(() => {
29
- if (!isEditing)
105
+ if (!isEditing) {
106
+ // Where the binding is forgotten — deliberately NOT in the cleanup below
107
+ // (kywi-cms#145 review round 2). React runs a cleanup BEFORE the next
108
+ // effect body, so clearing it there also cleared it on an `attachNonce`
109
+ // re-run: `recoverOrphanedEdit` resolved a binding from the gesture, the
110
+ // cleanup threw it away, and this body fell back to resolving with no
111
+ // pointer at all — which returns null, and so CANCELS the session, on any
112
+ // module that still has two or more anchors (rule 2 is ambiguous there).
113
+ // This effect only re-runs on `isEditing`/`attachNonce`, and the nonce
114
+ // only moves while an edit is live, so reaching here means the session
115
+ // itself has ended.
116
+ boundRef.current = null;
30
117
  return;
31
- const host = hostRef.current;
32
- if (!host)
118
+ }
119
+ const wrapper = hostRef.current;
120
+ if (!wrapper)
121
+ return;
122
+ // An activation this component did not start (the parent set `editingId`
123
+ // directly) has no gesture to resolve from — resolve pointer-lessly. Same
124
+ // for a binding whose element has since left the document (kywi-cms#145
125
+ // review): re-resolve rather than attach to a node nobody can see. A
126
+ // binding a recovering gesture just resolved passes all three checks and is
127
+ // used as-is, which is the point of the recovery.
128
+ let bound = boundRef.current;
129
+ if (!bound ||
130
+ !bound.element.isConnected ||
131
+ (bound.element !== wrapper && !wrapper.contains(bound.element))) {
132
+ bound = inlineTextRef.current?.resolve(wrapper, null) ?? null;
133
+ boundRef.current = bound;
134
+ }
135
+ if (!bound) {
136
+ // Active with nothing bindable — the module re-rendered out from under an
137
+ // edit, say. End the session rather than leave the owner in an "editing"
138
+ // module that swallows nothing and cannot be typed in.
139
+ abandonedRef.current = true;
140
+ inlineTextRef.current?.onCancel();
33
141
  return;
142
+ }
143
+ const host = bound.element;
34
144
  cancellingRef.current = false;
145
+ host.setAttribute('contenteditable', 'true');
146
+ host.setAttribute('spellcheck', 'true');
35
147
  host.focus();
36
148
  const selection = window.getSelection?.();
37
149
  if (selection && typeof document.createRange === 'function') {
@@ -41,7 +153,61 @@ export function ModuleOverlay({ moduleId, instanceId, columnId, index, isSelecte
41
153
  selection.removeAllRanges();
42
154
  selection.addRange(range);
43
155
  }
44
- }, [isEditing]);
156
+ // A `<summary>` anchor — the accordion's title, the FAQ's question — keeps
157
+ // its activation behaviour while contenteditable (kywi-cms#145 review): in
158
+ // Chrome a click that only meant "put the caret here" also toggles the
159
+ // panel out from under the caret, and Space toggles as well as typing.
160
+ // Both reach the toggle as the CLICK event's default action (the keyboard
161
+ // ones through a synthesized click), so cancelling that one event stops the
162
+ // toggle while leaving caret placement (a mousedown default) and character
163
+ // insertion (a beforeinput default) alone. Deliberately not a keydown
164
+ // preventDefault: that would stop Space typing a space, which is the very
165
+ // behaviour this is here to preserve. Switching the anchor to an inner
166
+ // `<span>` is not an option — the published markup must stay byte-identical
167
+ // (layout/__tests__/inline-prop-anchors.test.tsx).
168
+ const suppressActivation = host.tagName === 'SUMMARY' ? (event) => event.preventDefault() : null;
169
+ if (suppressActivation)
170
+ host.addEventListener('click', suppressActivation);
171
+ return () => {
172
+ // Undo exactly what this run did to `host`, and nothing else. On a
173
+ // re-attach that means the OLD element goes back to being ordinary markup
174
+ // (suppressor and all, so a re-bind away from a `<summary>` stops
175
+ // swallowing its clicks) while the binding itself — which by then may be
176
+ // the new one a gesture resolved — is left alone; the session's binding is
177
+ // cleared by the `!isEditing` branch above instead.
178
+ if (suppressActivation)
179
+ host.removeEventListener('click', suppressActivation);
180
+ host.removeAttribute('contenteditable');
181
+ host.removeAttribute('spellcheck');
182
+ };
183
+ }, [isEditing, attachNonce]);
184
+ // The other half of the orphan recovery: no deps, so it runs after EVERY
185
+ // render (and after the attach effect above, which is declared first). A
186
+ // re-render that replaced the module's inner DOM lands here with a bound
187
+ // element that is no longer in the document — re-run the attach against what
188
+ // is there now (kywi-cms#145 review).
189
+ React.useEffect(() => {
190
+ if (!isEditing || abandonedRef.current)
191
+ return;
192
+ // …but only while this module is still IN the document. When the whole
193
+ // wrapper has been detached — the React tree is still mounted, its DOM is
194
+ // not: a host that removed the editor's container node, a test root whose
195
+ // container was taken out of `document.body` — then every element
196
+ // re-resolution could find lives inside that same detached wrapper, so it
197
+ // comes back disconnected too, this effect fires again on the render
198
+ // `reattach()` just caused, and the two effects ping-pong forever: an
199
+ // unbounded render loop that pins a core and exhausts the heap. Latent
200
+ // since kywi-cms#145 (it needs one render AFTER the detach to start, and
201
+ // nothing used to produce one); the component library loading in the shell
202
+ // is such a render, which is how kywi-cms#147 found it. There is nothing on
203
+ // screen to recover onto in that state anyway, and if the wrapper is
204
+ // re-attached the next render reaches the recovery again.
205
+ if (!hostRef.current?.isConnected)
206
+ return;
207
+ if (!isOrphanedEdit())
208
+ return;
209
+ reattach();
210
+ });
45
211
  const style = {
46
212
  transform: CSS.Transform.toString(transform),
47
213
  transition,
@@ -53,26 +219,48 @@ export function ModuleOverlay({ moduleId, instanceId, columnId, index, isSelecte
53
219
  // instead of following the link (kywi-cms#94).
54
220
  if (inPlace)
55
221
  e.preventDefault();
56
- if (isEditing)
222
+ // A live edit swallows clicks — but only a LIVE one. An orphaned session
223
+ // (see `isOrphanedEdit`) must let the gesture re-bind, or the module stays
224
+ // inert (kywi-cms#145 review).
225
+ if (isEditing) {
226
+ if (!isOrphanedEdit())
227
+ return;
228
+ if (recoverOrphanedEdit(e.target))
229
+ return;
230
+ onSelect();
57
231
  return;
232
+ }
58
233
  // A click on an already-selected, text-bearing module starts typing —
59
- // the second click of the "select, then edit" pattern (kywi-cms#94).
234
+ // the second click of the "select, then edit" pattern (kywi-cms#94). Which
235
+ // prop that is depends on where the click landed (kywi-cms#145); a click
236
+ // with nothing safe to bind just leaves the module selected, and the
237
+ // double-click that follows routes to the rail.
60
238
  if (inlineText && isSelected) {
61
- inlineText.onActivate();
239
+ if (bind(e.target))
240
+ inlineText.onActivate();
62
241
  return;
63
242
  }
64
243
  onSelect();
65
244
  }
66
245
  function handleDoubleClick(e) {
67
- if (isEditing)
68
- return;
69
- if (inlineText) {
246
+ if (isEditing) {
247
+ if (!isOrphanedEdit())
248
+ return;
249
+ if (recoverOrphanedEdit(e.target)) {
250
+ e.stopPropagation();
251
+ return;
252
+ }
253
+ // Nothing left to re-bind: the session has just ended, so fall through to
254
+ // the rail fallback below rather than eating the double-click.
255
+ }
256
+ if (inlineText && bind(e.target)) {
70
257
  e.stopPropagation();
71
258
  inlineText.onActivate();
72
259
  return;
73
260
  }
74
- // No primary text prop to bind (kywi-cms#118) — route the gesture to the
75
- // props rail instead of leaving it a silent no-op.
261
+ // Nothing safe to bind (kywi-cms#118, kywi-cms#145) — route the gesture to
262
+ // the props rail instead of leaving it a silent no-op, and never to the
263
+ // wrapper, which renders more than any one prop.
76
264
  if (onInlineFallback) {
77
265
  e.stopPropagation();
78
266
  onInlineFallback();
@@ -84,44 +272,57 @@ export function ModuleOverlay({ moduleId, instanceId, columnId, index, isSelecte
84
272
  if (e.key === 'Escape') {
85
273
  // Handled here rather than at the window: stopping propagation keeps the
86
274
  // shell's Escape handler (deselect) from also firing for the same press.
275
+ // Deliberately not gated on a resolved binding — Escape is the way out of
276
+ // an edit session however it got into trouble.
87
277
  e.preventDefault();
88
278
  e.stopPropagation();
89
279
  cancellingRef.current = true;
90
280
  inlineText.onCancel();
91
281
  return;
92
282
  }
93
- if (e.key === 'Enter' && !e.shiftKey && !inlineText.html) {
283
+ const bound = boundRef.current;
284
+ if (!bound)
285
+ return;
286
+ if (e.key === 'Enter' && !e.shiftKey && !bound.prop.html) {
94
287
  // A plain-text prop is a single line — Enter means "done", not a newline.
95
288
  e.preventDefault();
96
289
  e.stopPropagation();
97
- inlineText.onCommit(e.currentTarget);
290
+ inlineText.onCommit(bound.element, bound.prop);
98
291
  }
99
292
  }
100
293
  function handleBlur(e) {
101
- if (!isEditing || !inlineText)
294
+ const bound = boundRef.current;
295
+ if (!isEditing || !inlineText || !bound)
102
296
  return;
103
297
  // Focus moving to a child (an action button) is not leaving the edit.
298
+ // `currentTarget` is the wrapper: React's onBlur is focusout, which bubbles,
299
+ // so the edit's own element reports through here whatever it is bound to.
104
300
  if (e.relatedTarget && e.currentTarget.contains(e.relatedTarget))
105
301
  return;
106
302
  if (cancellingRef.current) {
107
303
  cancellingRef.current = false;
108
304
  return;
109
305
  }
110
- inlineText.onCommit(e.currentTarget);
306
+ inlineText.onCommit(bound.element, bound.prop);
111
307
  }
308
+ // No rendered `contentEditable` here: the edit is turned on imperatively, on
309
+ // the resolved element, by the effect above (kywi-cms#145).
112
310
  const editingProps = inlineText
113
311
  ? {
114
312
  onDoubleClick: handleDoubleClick,
115
313
  onKeyDown: handleKeyDown,
116
314
  onBlur: handleBlur,
117
- ...(isEditing
118
- ? { contentEditable: true, suppressContentEditableWarning: true, spellCheck: true }
119
- : {}),
120
315
  }
121
316
  : onInlineFallback
122
317
  ? { onDoubleClick: handleDoubleClick }
123
318
  : {};
124
- const chrome = (_jsxs(_Fragment, { children: [typeLabel && (_jsx("span", { className: inPlace ? 'kywi-ip-chip' : 'kywi-editor-module-type-chip', "data-kywi-editor-chrome": "", contentEditable: false, children: typeLabel })), _jsxs("div", { className: inPlace ? 'kywi-ip-chrome kywi-ip-module-actions' : 'kywi-editor-module-actions', "data-kywi-editor-chrome": "", contentEditable: false, children: [_jsx("button", { type: "button", className: "kywi-editor-module-action-btn kywi-editor-module-drag-handle", "aria-label": "Drag to reorder", title: "Drag to reorder", ...listeners, children: _jsx(EditorIcon, { name: "grip", size: 14 }) }), actions?.map((action, i) => (_jsx("button", { type: "button", className: "kywi-editor-module-action-btn", onClick: (e) => {
319
+ const chrome = (_jsxs(_Fragment, { children: [typeLabel && (_jsx("span", { className: inPlace ? 'kywi-ip-chip' : 'kywi-editor-module-type-chip', "data-kywi-editor-chrome": "", contentEditable: false, children: typeLabel })), componentId && (
320
+ // Deliberately NOT `.kywi-ip-chrome`: that class is invisible and
321
+ // click-through until its owner is hovered or selected, and a linked
322
+ // instance must announce itself BEFORE anyone reaches for it. It takes
323
+ // the same z-tier through its own rule, exactly as `.kywi-ip-insert-btn`
324
+ // does (see the stacking contract in editor.css).
325
+ _jsx("span", { className: inPlace ? 'kywi-ip-module-linked-tag' : 'kywi-editor-module-linked-tag', "data-kywi-editor-chrome": "", contentEditable: false, children: _jsx(LinkedComponentPill, { name: componentName }) })), _jsxs("div", { className: inPlace ? 'kywi-ip-chrome kywi-ip-module-actions' : 'kywi-editor-module-actions', "data-kywi-editor-chrome": "", contentEditable: false, children: [_jsx("button", { type: "button", className: "kywi-editor-module-action-btn kywi-editor-module-drag-handle", "aria-label": "Drag to reorder", title: "Drag to reorder", ...listeners, children: _jsx(EditorIcon, { name: "grip", size: 14 }) }), actions?.map((action, i) => (_jsx("button", { type: "button", className: "kywi-editor-module-action-btn", onClick: (e) => {
125
326
  e.stopPropagation();
126
327
  action.onClick();
127
328
  }, title: action.label, "aria-label": action.label, children: _jsx(EditorIcon, { name: action.icon, size: 14 }) }, i)))] })] }));
@@ -132,10 +333,17 @@ export function ModuleOverlay({ moduleId, instanceId, columnId, index, isSelecte
132
333
  'kywi-ip-module',
133
334
  isSelected ? 'kywi-ip-module--selected' : null,
134
335
  isEditing ? 'kywi-ip-module--editing' : null,
336
+ componentId ? 'kywi-ip-module--linked' : null,
135
337
  ]
136
338
  .filter(Boolean)
137
339
  .join(' ')
138
- : `kywi-editor-module${isSelected ? ' kywi-editor-module--selected' : ''}`;
139
- return (_jsxs("div", { ref: setRefs, className: className, style: style, onClick: handleClick, "data-module-id": moduleId, "data-kywi-module-slot": "", ...(inPlace ? { 'data-instance-id': instanceId } : {}), ...(inPlace && moduleType ? { 'data-kywi-module': moduleType } : {}), ...attributes, ...editingProps, children: [chrome, children] }));
340
+ : [
341
+ 'kywi-editor-module',
342
+ isSelected ? 'kywi-editor-module--selected' : null,
343
+ componentId ? 'kywi-editor-module--linked' : null,
344
+ ]
345
+ .filter(Boolean)
346
+ .join(' ');
347
+ return (_jsxs("div", { ref: setRefs, className: className, style: style, onClick: handleClick, "data-module-id": moduleId, "data-kywi-module-slot": "", ...(componentId ? { 'data-component-id': componentId } : {}), ...(inPlace ? { 'data-instance-id': instanceId } : {}), ...(inPlace && moduleType ? { 'data-kywi-module': moduleType } : {}), ...attributes, ...editingProps, children: [chrome, children] }));
140
348
  }
141
349
  //# sourceMappingURL=module-overlay.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"module-overlay.js","sourceRoot":"","sources":["../../../src/admin/layout-editor/module-overlay.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"module-overlay.js","sourceRoot":"","sources":["../../../src/admin/layout-editor/module-overlay.tsx"],"names":[],"mappings":"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"}
@@ -88,6 +88,41 @@ export declare function findColumnIn(regions: Record<string, RegionNode[]>, colu
88
88
  export declare function findModuleIn(regions: Record<string, RegionNode[]>, moduleId: string): ModuleLocation | null;
89
89
  /** Find a variant container by id. Containers only ever live at region level. */
90
90
  export declare function findVariantContainerIn(regions: Record<string, RegionNode[]>, containerId: string): VariantContainerLocation | null;
91
+ /**
92
+ * The `componentId` of the nearest ANCESTOR of `nodeId` that is itself a linked
93
+ * component instance, or null when every ancestor is ordinary content.
94
+ *
95
+ * WHY THIS EXISTS (kywi-cms#147 T3 review, I1). Connecting a node that lives
96
+ * inside an already-linked ancestor silently destroys data:
97
+ *
98
+ * - the connect writes the node as a CLEAN instance (`props: { componentId }`),
99
+ * replacing the content stored for it in the page's document — but that
100
+ * document is the ancestor's inline FALLBACK copy, so what was overwritten is
101
+ * the only thing the page can render when the ancestor's component cannot be
102
+ * resolved;
103
+ * - `collectComponentRefs` deliberately stops at a connected node, so the new
104
+ * link is invisible to the instance index, the usage counts and the delete
105
+ * gate, and the render-side placement pass strips it structurally;
106
+ * - so the moment the outer component becomes unresolvable, the inner node
107
+ * renders EMPTY, with nothing left to recover it from.
108
+ *
109
+ * A node's OWN `componentId` is deliberately not considered: this answers "is
110
+ * this node inside somebody ELSE's component?", which is the question both the
111
+ * chrome gating and the hard refusal in `useComponentConnect` ask. A linked
112
+ * SIBLING is not an ancestor and must not block anything.
113
+ */
114
+ export declare function findLinkedAncestor(regions: Record<string, RegionNode[]>, nodeId: string): string | null;
115
+ /**
116
+ * {@link findLinkedAncestor} as a yes/no, over a document's own regions.
117
+ *
118
+ * Regions only, exactly like the document readers below and for the same reason:
119
+ * the shells resolve their selection from `layout.regions` too, so a node living
120
+ * in a `pageVariants` / `abExperiments` region cannot be saved or linked through
121
+ * them at all (the lookup fails first). The canvas's own gating does not depend on
122
+ * this function — it threads `linkedAncestor` structurally, from where it is
123
+ * rendering — so variant regions are gated in the UI regardless.
124
+ */
125
+ export declare function hasLinkedAncestor(layout: LayoutDocument, nodeId: string): boolean;
91
126
  export declare function findModuleInDocument(layout: LayoutDocument, moduleId: string): ModuleNode | null;
92
127
  export declare function findSectionInDocument(layout: LayoutDocument, sectionId: string): LayoutSection | null;
93
128
  export declare function findVariantContainerInDocument(layout: LayoutDocument, containerId: string): VariantContainer | null;
@@ -1 +1 @@
1
- {"version":3,"file":"node-lookup.d.ts","sourceRoot":"","sources":["../../../src/admin/layout-editor/node-lookup.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"node-lookup.d.ts","sourceRoot":"","sources":["../../../src/admin/layout-editor/node-lookup.ts"],"names":[],"mappings":"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"}
@@ -125,6 +125,97 @@ export function findVariantContainerIn(regions, containerId) {
125
125
  }
126
126
  return null;
127
127
  }
128
+ // ── Linked ancestry (kywi-cms#147) ───────────────────────────────────────────
129
+ /**
130
+ * Search one array of sections for `nodeId`, carrying the link inherited from
131
+ * whatever holds those sections. Returns a WRAPPER so "found, no linked
132
+ * ancestor" (`{ value: null }`) stays distinguishable from "not here" (`null`).
133
+ */
134
+ function linkedAncestorInSections(sections, nodeId, inherited) {
135
+ for (const section of sections) {
136
+ if (!isLayoutSection(section))
137
+ continue;
138
+ // The section itself: its own componentId is not an ANCESTOR's.
139
+ if (section.id === nodeId)
140
+ return { value: inherited };
141
+ // Nearest first — a module inside a linked section reports that section,
142
+ // not the linked container two levels up.
143
+ const nearest = section.componentId ?? inherited ?? null;
144
+ for (const column of section.columns) {
145
+ if (column.id === nodeId)
146
+ return { value: nearest };
147
+ for (const module of column.nodes) {
148
+ if (module.id === nodeId)
149
+ return { value: nearest };
150
+ }
151
+ }
152
+ }
153
+ return null;
154
+ }
155
+ /**
156
+ * The `componentId` of the nearest ANCESTOR of `nodeId` that is itself a linked
157
+ * component instance, or null when every ancestor is ordinary content.
158
+ *
159
+ * WHY THIS EXISTS (kywi-cms#147 T3 review, I1). Connecting a node that lives
160
+ * inside an already-linked ancestor silently destroys data:
161
+ *
162
+ * - the connect writes the node as a CLEAN instance (`props: { componentId }`),
163
+ * replacing the content stored for it in the page's document — but that
164
+ * document is the ancestor's inline FALLBACK copy, so what was overwritten is
165
+ * the only thing the page can render when the ancestor's component cannot be
166
+ * resolved;
167
+ * - `collectComponentRefs` deliberately stops at a connected node, so the new
168
+ * link is invisible to the instance index, the usage counts and the delete
169
+ * gate, and the render-side placement pass strips it structurally;
170
+ * - so the moment the outer component becomes unresolvable, the inner node
171
+ * renders EMPTY, with nothing left to recover it from.
172
+ *
173
+ * A node's OWN `componentId` is deliberately not considered: this answers "is
174
+ * this node inside somebody ELSE's component?", which is the question both the
175
+ * chrome gating and the hard refusal in `useComponentConnect` ask. A linked
176
+ * SIBLING is not an ancestor and must not block anything.
177
+ */
178
+ export function findLinkedAncestor(regions, nodeId) {
179
+ for (const nodes of Object.values(regions)) {
180
+ for (const node of nodes) {
181
+ // Region level: a section or container sitting here has no ancestor at all.
182
+ if (node.id === nodeId)
183
+ return null;
184
+ if (isVariantContainer(node)) {
185
+ const containerLink = node.componentId ?? null;
186
+ const arms = [
187
+ node.defaultSections,
188
+ ...node.variants.map(variant => variant.sections),
189
+ ];
190
+ for (const arm of arms) {
191
+ const hit = linkedAncestorInSections(arm, nodeId, containerLink);
192
+ if (hit)
193
+ return hit.value;
194
+ }
195
+ continue;
196
+ }
197
+ if (isLayoutSection(node)) {
198
+ const hit = linkedAncestorInSections([node], nodeId, null);
199
+ if (hit)
200
+ return hit.value;
201
+ }
202
+ }
203
+ }
204
+ return null;
205
+ }
206
+ /**
207
+ * {@link findLinkedAncestor} as a yes/no, over a document's own regions.
208
+ *
209
+ * Regions only, exactly like the document readers below and for the same reason:
210
+ * the shells resolve their selection from `layout.regions` too, so a node living
211
+ * in a `pageVariants` / `abExperiments` region cannot be saved or linked through
212
+ * them at all (the lookup fails first). The canvas's own gating does not depend on
213
+ * this function — it threads `linkedAncestor` structurally, from where it is
214
+ * rendering — so variant regions are gated in the UI regardless.
215
+ */
216
+ export function hasLinkedAncestor(layout, nodeId) {
217
+ return findLinkedAncestor(layout.regions, nodeId) !== null;
218
+ }
128
219
  // ── Document-level readers ───────────────────────────────────────────────────
129
220
  //
130
221
  // Read-only convenience for the editor shells, which resolve the current