@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
@@ -83,6 +83,19 @@
83
83
  --kywi-editor-ease: 140ms cubic-bezier(0.2, 0.7, 0.2, 1);
84
84
  --kywi-editor-focus: 0 0 0 2px var(--kywi-editor-panel-bg), 0 0 0 4px var(--kywi-editor-accent-ring);
85
85
 
86
+ /* Linked components (kywi-cms#147).
87
+ Deliberately NOT derived from --kywi-editor-accent: "selected" is the accent
88
+ in both shells (indigo on the front end, green under admin.css's bridge —
89
+ kywi-cms#144), so a linked instance keyed off the accent would read as
90
+ selected in one theme and as nothing in particular in the other. A fixed
91
+ fuchsia is distinct from BOTH accents, which is the whole job of this
92
+ affordance, and it therefore needs no bridge entry in the (locked) admin.css
93
+ — the same colour means the same thing in both editors. */
94
+ --kywi-editor-linked: #c026d3;
95
+ --kywi-editor-linked-soft: rgba(192, 38, 211, 0.16);
96
+ --kywi-editor-linked-ring: rgba(192, 38, 211, 0.45);
97
+ --kywi-editor-on-linked: #ffffff;
98
+
86
99
  --kywi-editor-font: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
87
100
  --kywi-editor-panel-width-left: 232px;
88
101
  --kywi-editor-panel-width-right: 288px;
@@ -1658,12 +1671,40 @@ input[type="color"].kywi-token-raw-input { height: 34px; padding: 3px; cursor: p
1658
1671
  /* ============================================================================
1659
1672
  Front-of-site overlay editor (OverlayShell) + browse-mode toolbar.
1660
1673
  ========================================================================== */
1674
+
1675
+ /* The two front-of-site bar heights are TOKENS, not literals, because three
1676
+ different things have to agree on each number: the bar's own box, the
1677
+ document offset that clears it (`.kywi-frontend-edit--*` below), and JS
1678
+ arithmetic against live rects (`use-chrome-flip.ts`, `sticky-offset.ts`).
1679
+ They are also the numbers a THEME needs — a `position: sticky; top: 0`
1680
+ header is offset to `top: var(…)` for the length of an editing session
1681
+ (kywi-cms#146) — so they are published on `:root` and documented for theme
1682
+ authors in packages/core/README.md ("Sticky site headers …").
1683
+
1684
+ --kywi-browse-bar-height the browse-mode toolbar, `.kywi-edit-toolbar`
1685
+ (kywi-cms#93), declared here
1686
+ --kywi-overlay-bar-height the edit-mode bar, `.kywi-overlay-toolbar`,
1687
+ declared with the other in-place tokens further
1688
+ down (next to the rail widths)
1689
+
1690
+ Two declaration sites rather than one only because each sits with the block
1691
+ it belongs to; nothing else reads them positionally.
1692
+
1693
+ site/styles.css declares BOTH again, with the same values. Not redundancy for
1694
+ its own sake: this sheet is lazy-loaded in a generated app (behind
1695
+ `next/dynamic`, only when the overlay editor opens), so on a public page in
1696
+ BROWSE mode it is not in the document at all and these declarations do not
1697
+ exist — see the comment there. */
1698
+ :root {
1699
+ --kywi-browse-bar-height: 44px;
1700
+ }
1701
+
1661
1702
  .kywi-edit-toolbar {
1662
1703
  position: fixed;
1663
1704
  top: 0;
1664
1705
  left: 0;
1665
1706
  right: 0;
1666
- height: 44px;
1707
+ height: var(--kywi-browse-bar-height);
1667
1708
  /* Joins the --kywi-z-overlay tier contract (kywi-cms#124): this is the
1668
1709
  BROWSE-mode toolbar (#93), a different element from the fixed edit-mode
1669
1710
  .kywi-overlay-toolbar. It sits below every edit-mode tier — including
@@ -1739,7 +1780,15 @@ input[type="color"].kywi-token-raw-input { height: 34px; padding: 3px; cursor: p
1739
1780
  .kywi-edit-toolbar-done:hover,
1740
1781
  .kywi-edit-toolbar-publish:hover,
1741
1782
  .kywi-edit-toolbar-link:hover { filter: brightness(1.08); border-color: var(--kywi-editor-accent); }
1742
- .kywi-frontend-edit--browsing { padding-top: 44px; }
1783
+ /* Offsets the document while the browse bar is up. The SAME property on the
1784
+ SAME element as the copy in site/styles.css — the public stylesheet needs
1785
+ this rule for a host that mounts the browse toolbar without ever importing
1786
+ the editor — because two identical declarations collapse where two DIFFERENT
1787
+ ones add up. They used to differ (`html` here, `body` there), and a site that
1788
+ loaded both sheets was pushed down 88px for a 44px bar, which is the seam
1789
+ above the nav in kywi-cms#146(1): 44px of body background between the bar and
1790
+ the site header. Change one, change the other. */
1791
+ .kywi-frontend-edit--browsing { padding-top: var(--kywi-browse-bar-height); }
1743
1792
 
1744
1793
  /* ============================================================================
1745
1794
  In-place front-of-site editor (kywi-cms#94).
@@ -1754,6 +1803,11 @@ input[type="color"].kywi-token-raw-input { height: 34px; padding: 3px; cursor: p
1754
1803
  that paints over the page without displacing it (`.kywi-ip-*`).
1755
1804
  ========================================================================== */
1756
1805
 
1806
+ /* `--kywi-overlay-bar-height` is the edit-mode half of the pair documented at
1807
+ the top of this section (with `--kywi-browse-bar-height`): the fixed bar's
1808
+ own height, the document offset below, the `BAR_HEIGHT_PX` copy in
1809
+ use-chrome-flip.ts, and the `top` the sticky-offset detector hands to the
1810
+ site's own top-anchored elements (sticky-offset.ts) are all this number. */
1757
1811
  :root {
1758
1812
  --kywi-overlay-bar-height: 46px;
1759
1813
  --kywi-overlay-rail-left: var(--kywi-editor-panel-width-left);
@@ -1988,8 +2042,12 @@ input[type="color"].kywi-token-raw-input { height: 34px; padding: 3px; cursor: p
1988
2042
  Invisible AND click-through until its owner is hovered or selected, so the
1989
2043
  page never collects stray editor hit-targets.
1990
2044
 
1991
- Five-tier stacking contract, all keyed off one variable so the tiers can
1992
- never drift apart (kywi-cms#118, extended by #124):
2045
+ Stacking contract, all keyed off one variable so the tiers can never drift
2046
+ apart (kywi-cms#118, extended by #124 and #147):
2047
+ .kywi-editor-dialog-overlay (the editor's = var(--kywi-z-overlay, 1000) + 2 = 1002
2048
+ own modal — save-as-component, the save
2049
+ fork — which can be opened from inside
2050
+ any of the surfaces below it, #147)
1993
2051
  .kywi-editor-template-overlay (section- = var(--kywi-z-overlay, 1000) + 1 = 1001
1994
2052
  template picker modal)
1995
2053
  .kywi-overlay-toolbar (fixed edit bar) = var(--kywi-z-overlay, 1000) = 1000
@@ -2074,6 +2132,13 @@ input[type="color"].kywi-token-raw-input { height: 34px; padding: 3px; cursor: p
2074
2132
  bar has to be pushed DOWN from the owner's top edge to clear the fixed bar,
2075
2133
  publishes it as `--kywi-ip-chrome-clamp`, and adds this class.
2076
2134
 
2135
+ That strip grows by `--kywi-editor-sticky-offset` on a site whose own header
2136
+ is `position: sticky; top: 0` (kywi-cms#146): the editor re-pins that header
2137
+ directly under its bar for the session, so chrome that clears only the bar
2138
+ lands inside the site's nav instead. The detector (scope/sticky-offset.ts)
2139
+ publishes the band height; the hook adds it. Absent — a page with no
2140
+ top-anchored chrome — the arithmetic is unchanged.
2141
+
2077
2142
  The offset is a measured px value, not `top: 100%`: hanging the bar off the
2078
2143
  owner's BOTTOM edge was the first attempt, and for a section taller than the
2079
2144
  viewport it left the screen entirely (y=1684 in a 720px viewport on the
@@ -2095,6 +2160,43 @@ input[type="color"].kywi-token-raw-input { height: 34px; padding: 3px; cursor: p
2095
2160
  transform: none;
2096
2161
  border-radius: var(--kywi-editor-radius-sm);
2097
2162
  }
2163
+
2164
+ /* Chrome pushed RIGHT, out of the open module palette's footprint
2165
+ (kywi-cms#132). Same argument as the clamp above, one axis over: the left
2166
+ rail is FIXED to the viewport edge and sits one tier ABOVE chrome on purpose
2167
+ (999 vs 998, so an edge-adjacent section can never cover the palette), and a
2168
+ full-width section's chrome renders at the section's own `left: 0` — i.e.
2169
+ underneath it. The owner sees the grip, +Col, Personalize, A/B and × through
2170
+ nothing at all and cannot click any of them.
2171
+
2172
+ Positional again, and for the same reason the clamp is: the rail's width is a
2173
+ token this editor owns (`--kywi-overlay-rail-left`), so unlike the arbitrary
2174
+ SITE header the stacking contract above is written for, there is a number to
2175
+ move by. `useChromeFlip` measures the owner's left edge against it and
2176
+ publishes the difference as `--kywi-ip-chrome-left`.
2177
+
2178
+ Only the offset — no `transform`, no `border-radius` change: unlike the
2179
+ clamp this does not move the bar off its owner's top edge, so the base rule's
2180
+ above-position tab is still the right shape. It composes with the clamp when
2181
+ both apply (a full-width hero at the top of the page gets both classes).
2182
+
2183
+ Deliberately NOT transitioned, even though the rail it dodges slides. The
2184
+ same value is rewritten on every scroll frame while an owner is near the top
2185
+ strip, and a transition would make each of those writes an animation chasing
2186
+ the last one. The cost is a ~140ms window during a palette toggle where the
2187
+ bar has already moved and the rail is still sliding — which errs the safe
2188
+ way on the way in (the bar leaves before the rail arrives). */
2189
+ .kywi-ip-chrome.kywi-ip-chrome--rail-avoid {
2190
+ left: var(--kywi-ip-chrome-left, 0px);
2191
+ }
2192
+ /* The container bar wraps and already bounds itself to its owner; hold that
2193
+ promise once its left edge has moved, or a wide arm switcher would run off
2194
+ the band's right edge by exactly the distance it was pushed. The section bar
2195
+ is `white-space: nowrap` with shrinkable flex children, so it deliberately
2196
+ gets no max-width here — capping it would squash its buttons instead. */
2197
+ .kywi-ip-vc-chrome.kywi-ip-chrome--rail-avoid {
2198
+ max-width: calc(100% - var(--kywi-ip-chrome-left, 0px));
2199
+ }
2098
2200
  /* Chrome controls are always live once the bar itself is visible. */
2099
2201
  .kywi-ip-chrome .kywi-editor-section-toolbar-actions { opacity: 1; }
2100
2202
  .kywi-ip-chrome .kywi-editor-section-title,
@@ -2220,6 +2322,266 @@ input[type="color"].kywi-token-raw-input { height: 34px; padding: 3px; cursor: p
2220
2322
  .kywi-ip-vc:hover .kywi-ip-add-arm-section,
2221
2323
  .kywi-ip-vc--selected .kywi-ip-add-arm-section { opacity: 1; }
2222
2324
 
2325
+ /* ============================================================================
2326
+ Linked component instances (kywi-cms#147)
2327
+ A linked instance is ordinary-looking content that is shared with every other
2328
+ instance of the same component, so editing it is never a local act. Both
2329
+ editors therefore mark it two ways: a distinct OUTLINE (never a border — an
2330
+ affordance must not move the page by a pixel, see the in-place selection rules
2331
+ above) and a NAMED pill in whatever chrome already floats above the node.
2332
+
2333
+ The pill is always visible, unlike hover chrome: "which of these bands is
2334
+ shared?" has to be answerable before the owner reaches for one. It is also
2335
+ `pointer-events: none` — it is a label, not a control, and it must never take a
2336
+ click meant for the content underneath.
2337
+
2338
+ Selection still wins visually where the two meet: a selected linked node shows
2339
+ the accent outline (it is what the owner just clicked) with the pill still
2340
+ naming the component.
2341
+ ========================================================================== */
2342
+
2343
+ .kywi-editor-linked-pill {
2344
+ display: inline-flex;
2345
+ align-items: center;
2346
+ gap: 4px;
2347
+ height: 18px;
2348
+ padding: 0 8px;
2349
+ border-radius: var(--kywi-editor-radius-pill);
2350
+ background: var(--kywi-editor-linked);
2351
+ color: var(--kywi-editor-on-linked);
2352
+ font-family: var(--kywi-editor-font);
2353
+ font-size: 9.5px;
2354
+ font-weight: 700;
2355
+ letter-spacing: 0.04em;
2356
+ white-space: nowrap;
2357
+ max-width: 190px;
2358
+ overflow: hidden;
2359
+ text-overflow: ellipsis;
2360
+ }
2361
+ .kywi-editor-linked-pill svg { flex-shrink: 0; }
2362
+
2363
+ /* Artboard (admin Layout tab) */
2364
+ .kywi-editor-section--linked {
2365
+ outline: 1.5px solid var(--kywi-editor-linked);
2366
+ outline-offset: -1.5px;
2367
+ }
2368
+ .kywi-editor-vc--linked {
2369
+ outline: 1.5px solid var(--kywi-editor-linked);
2370
+ outline-offset: -1.5px;
2371
+ }
2372
+ .kywi-editor-module--linked {
2373
+ outline: 1.5px solid var(--kywi-editor-linked);
2374
+ outline-offset: 1px;
2375
+ }
2376
+ .kywi-editor-module-linked-tag {
2377
+ position: absolute;
2378
+ top: -10px;
2379
+ right: 10px;
2380
+ z-index: 3;
2381
+ pointer-events: none;
2382
+ }
2383
+
2384
+ /* In place (front-of-site overlay) */
2385
+ .kywi-ip-section--linked {
2386
+ outline: 1.5px solid var(--kywi-editor-linked);
2387
+ outline-offset: -1.5px;
2388
+ }
2389
+ .kywi-ip-section--linked.kywi-ip-section--selected,
2390
+ .kywi-ip-section--linked.kywi-ip-section--selected:hover {
2391
+ outline: 2px solid var(--kywi-editor-accent);
2392
+ outline-offset: -2px;
2393
+ }
2394
+ .kywi-ip-vc--linked {
2395
+ outline: 1.5px solid var(--kywi-editor-linked);
2396
+ outline-offset: 2px;
2397
+ }
2398
+ .kywi-ip-vc--linked.kywi-ip-vc--selected,
2399
+ .kywi-ip-vc--linked.kywi-ip-vc--selected:hover {
2400
+ outline: 2px solid var(--kywi-editor-accent);
2401
+ outline-offset: 2px;
2402
+ }
2403
+ .kywi-ip-module--linked {
2404
+ outline: 1.5px solid var(--kywi-editor-linked);
2405
+ outline-offset: 2px;
2406
+ }
2407
+ .kywi-ip-module--linked.kywi-ip-module--selected,
2408
+ .kywi-ip-module--linked.kywi-ip-module--selected:hover {
2409
+ outline: 2px solid var(--kywi-editor-accent);
2410
+ outline-offset: 2px;
2411
+ }
2412
+ /* Above the module, right-aligned: the type chip sits above-left and the action
2413
+ cluster inside top-right, so this collides with neither. Takes the page-flow
2414
+ chrome z-tier through its own rule rather than by joining
2415
+ `.kywi-ip-chrome, .kywi-ip-chip` — that shared rule also resets opacity and
2416
+ pointer-events, which is exactly what this must not inherit. */
2417
+ .kywi-ip-module-linked-tag {
2418
+ position: absolute;
2419
+ top: 0;
2420
+ right: 0;
2421
+ transform: translateY(-100%);
2422
+ z-index: calc(var(--kywi-z-overlay, 1000) - 2);
2423
+ pointer-events: none;
2424
+ }
2425
+
2426
+ /* ============================================================================
2427
+ Editor dialog (kywi-cms#147)
2428
+ The editor's own modal, used by "Save as component" and by the save fork. It
2429
+ renders in BOTH shells through a portal to `document.body`, wrapped in
2430
+ `.kywi-admin-shell.kywi-overlay-dialog-host` — so it is styled entirely from
2431
+ `--kywi-editor-*` tokens and comes out indigo on the front end and green in the
2432
+ admin Layout tab with no second rule set (kywi-cms#144).
2433
+ ========================================================================== */
2434
+
2435
+ .kywi-editor-dialog-overlay {
2436
+ position: fixed;
2437
+ inset: 0;
2438
+ /* One tier above the section-template modal's tier so a dialog opened from
2439
+ inside another surface is never painted under it. */
2440
+ z-index: calc(var(--kywi-z-overlay, 1000) + 2);
2441
+ display: flex;
2442
+ align-items: center;
2443
+ justify-content: center;
2444
+ padding: var(--kywi-editor-sp-4);
2445
+ background: rgba(8, 8, 20, 0.55);
2446
+ }
2447
+ .kywi-editor-dialog {
2448
+ width: 100%;
2449
+ max-width: 420px;
2450
+ box-sizing: border-box;
2451
+ background: var(--kywi-editor-panel-bg);
2452
+ border: 1px solid var(--kywi-editor-border-strong);
2453
+ border-radius: var(--kywi-editor-radius-lg);
2454
+ box-shadow: var(--kywi-editor-shadow-pop);
2455
+ color: var(--kywi-editor-panel-text);
2456
+ font-family: var(--kywi-editor-font);
2457
+ font-size: 13px;
2458
+ line-height: 1.45;
2459
+ overflow: hidden;
2460
+ }
2461
+ .kywi-editor-dialog-header {
2462
+ padding: var(--kywi-editor-sp-4) var(--kywi-editor-sp-5) 0;
2463
+ }
2464
+ .kywi-editor-dialog-title {
2465
+ font-size: 14.5px;
2466
+ font-weight: 700;
2467
+ color: var(--kywi-editor-text-strong);
2468
+ }
2469
+ .kywi-editor-dialog-body {
2470
+ padding: var(--kywi-editor-sp-3) var(--kywi-editor-sp-5) var(--kywi-editor-sp-2);
2471
+ }
2472
+ .kywi-editor-dialog-intro {
2473
+ margin: 0 0 var(--kywi-editor-sp-3);
2474
+ font-size: 12.5px;
2475
+ color: var(--kywi-editor-panel-muted);
2476
+ }
2477
+ /* "Component 1 of 2" — the save fork asks per component, so the owner needs to
2478
+ know a second question is coming (kywi-cms#147 T4). */
2479
+ .kywi-editor-dialog-step {
2480
+ margin: 0 0 var(--kywi-editor-sp-2);
2481
+ font-size: 10.5px;
2482
+ font-weight: 650;
2483
+ letter-spacing: 0.05em;
2484
+ text-transform: uppercase;
2485
+ color: var(--kywi-editor-panel-faint);
2486
+ }
2487
+ .kywi-editor-dialog-field { margin-bottom: var(--kywi-editor-sp-3); }
2488
+ .kywi-editor-dialog-label {
2489
+ display: block;
2490
+ margin-bottom: 5px;
2491
+ font-size: 10.5px;
2492
+ font-weight: 650;
2493
+ letter-spacing: 0.05em;
2494
+ text-transform: uppercase;
2495
+ color: var(--kywi-editor-panel-muted);
2496
+ }
2497
+ .kywi-editor-dialog-optional {
2498
+ margin-left: 6px;
2499
+ color: var(--kywi-editor-panel-faint);
2500
+ text-transform: none;
2501
+ letter-spacing: 0;
2502
+ font-weight: 500;
2503
+ }
2504
+ .kywi-editor-dialog-input {
2505
+ width: 100%;
2506
+ box-sizing: border-box;
2507
+ min-height: 32px;
2508
+ padding: 6px 9px;
2509
+ font-family: inherit;
2510
+ font-size: 12.5px;
2511
+ line-height: 1.4;
2512
+ color: var(--kywi-editor-panel-text);
2513
+ background: var(--kywi-editor-panel-raised-2);
2514
+ border: 1px solid var(--kywi-editor-border-strong);
2515
+ border-radius: var(--kywi-editor-radius-sm);
2516
+ }
2517
+ .kywi-editor-dialog-input:focus {
2518
+ outline: none;
2519
+ border-color: var(--kywi-editor-accent);
2520
+ box-shadow: 0 0 0 3px var(--kywi-editor-accent-ring);
2521
+ }
2522
+ .kywi-editor-dialog-textarea { resize: vertical; }
2523
+ /* A consequence of the save the owner has to know about before committing (a
2524
+ nested link that is about to be copied in) — informational, not an error. */
2525
+ .kywi-editor-dialog-notice {
2526
+ margin: 0 var(--kywi-editor-sp-5) var(--kywi-editor-sp-3);
2527
+ padding: var(--kywi-editor-sp-2) var(--kywi-editor-sp-3);
2528
+ border-left: 2px solid var(--kywi-editor-linked);
2529
+ border-radius: 0 var(--kywi-editor-radius-sm) var(--kywi-editor-radius-sm) 0;
2530
+ background: var(--kywi-editor-linked-soft);
2531
+ color: var(--kywi-editor-panel-text);
2532
+ font-size: 12px;
2533
+ }
2534
+ .kywi-editor-dialog-error {
2535
+ margin: 0 var(--kywi-editor-sp-5) var(--kywi-editor-sp-2);
2536
+ padding: var(--kywi-editor-sp-2) var(--kywi-editor-sp-3);
2537
+ border-radius: var(--kywi-editor-radius-sm);
2538
+ background: var(--kywi-editor-danger-soft);
2539
+ color: var(--kywi-editor-danger);
2540
+ font-size: 12px;
2541
+ }
2542
+ .kywi-editor-dialog-actions {
2543
+ display: flex;
2544
+ justify-content: flex-end;
2545
+ gap: var(--kywi-editor-sp-2);
2546
+ padding: var(--kywi-editor-sp-3) var(--kywi-editor-sp-5) var(--kywi-editor-sp-4);
2547
+ border-top: 1px solid var(--kywi-editor-hairline);
2548
+ }
2549
+ .kywi-editor-dialog-btn {
2550
+ min-height: 30px;
2551
+ padding: 0 14px;
2552
+ border-radius: var(--kywi-editor-radius-sm);
2553
+ border: 1px solid transparent;
2554
+ font-family: inherit;
2555
+ font-size: 12.5px;
2556
+ font-weight: 650;
2557
+ cursor: pointer;
2558
+ transition: background var(--kywi-editor-ease), border-color var(--kywi-editor-ease);
2559
+ }
2560
+ .kywi-editor-dialog-btn:disabled { opacity: 0.55; cursor: default; }
2561
+ .kywi-editor-dialog-btn--primary {
2562
+ background: var(--kywi-editor-accent);
2563
+ color: var(--kywi-editor-on-accent);
2564
+ }
2565
+ .kywi-editor-dialog-btn--primary:hover:not(:disabled) { background: var(--kywi-editor-accent-hover); }
2566
+ .kywi-editor-dialog-btn--secondary {
2567
+ background: var(--kywi-editor-panel-raised-solid);
2568
+ border-color: var(--kywi-editor-border-strong);
2569
+ color: var(--kywi-editor-panel-text);
2570
+ }
2571
+ .kywi-editor-dialog-btn--secondary:hover:not(:disabled) { background: var(--kywi-editor-panel-raised-2); }
2572
+ .kywi-editor-dialog-btn--danger {
2573
+ background: var(--kywi-editor-danger-strong);
2574
+ color: #fff;
2575
+ }
2576
+
2577
+ /* The linked note's second paragraph — the "what the canvas is showing you"
2578
+ aside — is subordinate to the first, not a second headline. */
2579
+ .kywi-editor-props-linked-aside {
2580
+ margin-top: var(--kywi-editor-sp-2);
2581
+ color: var(--kywi-editor-panel-muted);
2582
+ font-size: 12px;
2583
+ }
2584
+
2223
2585
  /* ============================================================================
2224
2586
  Admin-shell override guard.
2225
2587
  The admin design system (admin.css) sweeps `.kywi-editor-prop-input`,
@@ -2,7 +2,16 @@ export { LayoutEditor } from './layout-editor.js';
2
2
  export type { EditorState, EditorAction, VariantArmPatch, VariantContainerPatch, } from './editor-state.js';
3
3
  export { ModeToggle } from './mode-toggle.js';
4
4
  export { PagePropertiesPanel } from './page-properties.js';
5
- export { buildConnectedModuleNode, buildConnectedSectionNode, detachModuleFromComponent, detachSectionFromComponent, resolveSectionComponentDefinition, saveAsComponent, saveAsTemplate, cloneSection, cloneModule, copyToClipboard, pasteFromClipboard, type ComponentDefinitionInput, type SectionTemplateInput, type ClipboardPayload, } from './component-actions.js';
5
+ export { buildConnectedModuleNode, buildConnectedSectionNode, buildConnectedVariantContainerNode, flattenComponentLinks, countComponentLinksToFlatten, detachModuleFromComponent, detachSectionFromComponent, detachVariantContainerFromComponent, resolveSectionComponentDefinition, resolveVariantContainerComponentDefinition, saveAsComponent, saveAsTemplate, cloneSection, cloneModule, cloneVariantContainer, copyToClipboard, pasteFromClipboard, type ComponentDefinitionInput, type SaveAsComponentOptions, type SectionTemplateInput, type ClipboardPayload, } from './component-actions.js';
6
+ export { useComponentLibrary } from './use-component-library.js';
7
+ export type { ComponentLibrary, EditorComponent } from './use-component-library.js';
8
+ export { useComponentConnect } from './use-component-connect.js';
9
+ export type { ComponentConnect } from './use-component-connect.js';
10
+ export { findLinkedAncestor, hasLinkedAncestor } from './node-lookup.js';
11
+ export { LinkedComponentPill, linkedComponentName } from './linked-component.js';
12
+ export type { ComponentAffordances } from './linked-component.js';
13
+ export { EditorDialog, ComponentSaveDialog } from './editor-dialog.js';
14
+ export type { EditorDialogAction, ComponentSaveKind } from './editor-dialog.js';
6
15
  export { OverlayShell } from './overlay-shell.js';
7
16
  export type { OverlayShellProps, SaveAction, ResponsivePreview } from './overlay-shell.js';
8
17
  export { TokenColorInput, TokenSpacingInput, TokenTypographyInput, TokenPropField } from './token-inputs.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/admin/layout-editor/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,YAAY,EACV,WAAW,EACX,YAAY,EACZ,eAAe,EACf,qBAAqB,GACtB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,yBAAyB,EACzB,0BAA0B,EAC1B,iCAAiC,EACjC,eAAe,EACf,cAAc,EACd,YAAY,EACZ,WAAW,EACX,eAAe,EACf,kBAAkB,EAClB,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,GACtB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,YAAY,EAAE,iBAAiB,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAC1F,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/admin/layout-editor/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,YAAY,EACV,WAAW,EACX,YAAY,EACZ,eAAe,EACf,qBAAqB,GACtB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,kCAAkC,EAClC,qBAAqB,EACrB,4BAA4B,EAC5B,yBAAyB,EACzB,0BAA0B,EAC1B,mCAAmC,EACnC,iCAAiC,EACjC,0CAA0C,EAC1C,eAAe,EACf,cAAc,EACd,YAAY,EACZ,WAAW,EACX,qBAAqB,EACrB,eAAe,EACf,kBAAkB,EAClB,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,GACtB,MAAM,wBAAwB,CAAA;AAI/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AAChE,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAA;AACnF,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AAChE,YAAY,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAA;AAGlE,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AACxE,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAChF,YAAY,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AACjE,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACtE,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAC/E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,YAAY,EAAE,iBAAiB,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAC1F,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA"}
@@ -1,7 +1,17 @@
1
1
  export { LayoutEditor } from './layout-editor.js';
2
2
  export { ModeToggle } from './mode-toggle.js';
3
3
  export { PagePropertiesPanel } from './page-properties.js';
4
- export { buildConnectedModuleNode, buildConnectedSectionNode, detachModuleFromComponent, detachSectionFromComponent, resolveSectionComponentDefinition, saveAsComponent, saveAsTemplate, cloneSection, cloneModule, copyToClipboard, pasteFromClipboard, } from './component-actions.js';
4
+ export { buildConnectedModuleNode, buildConnectedSectionNode, buildConnectedVariantContainerNode, flattenComponentLinks, countComponentLinksToFlatten, detachModuleFromComponent, detachSectionFromComponent, detachVariantContainerFromComponent, resolveSectionComponentDefinition, resolveVariantContainerComponentDefinition, saveAsComponent, saveAsTemplate, cloneSection, cloneModule, cloneVariantContainer, copyToClipboard, pasteFromClipboard, } from './component-actions.js';
5
+ // Linked components in the editor (kywi-cms#147): the shared library/connect
6
+ // hooks both shells use, the canvas affordance contract, and the reusable dialog
7
+ // (which the save fork also renders).
8
+ export { useComponentLibrary } from './use-component-library.js';
9
+ export { useComponentConnect } from './use-component-connect.js';
10
+ // "Is this node inside somebody else's component?" — the question every component
11
+ // action is refused on (kywi-cms#147 T3 review, I1).
12
+ export { findLinkedAncestor, hasLinkedAncestor } from './node-lookup.js';
13
+ export { LinkedComponentPill, linkedComponentName } from './linked-component.js';
14
+ export { EditorDialog, ComponentSaveDialog } from './editor-dialog.js';
5
15
  export { OverlayShell } from './overlay-shell.js';
6
16
  export { TokenColorInput, TokenSpacingInput, TokenTypographyInput, TokenPropField } from './token-inputs.js';
7
17
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/admin/layout-editor/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAOjD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,yBAAyB,EACzB,0BAA0B,EAC1B,iCAAiC,EACjC,eAAe,EACf,cAAc,EACd,YAAY,EACZ,WAAW,EACX,eAAe,EACf,kBAAkB,GAInB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEjD,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/admin/layout-editor/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAOjD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,kCAAkC,EAClC,qBAAqB,EACrB,4BAA4B,EAC5B,yBAAyB,EACzB,0BAA0B,EAC1B,mCAAmC,EACnC,iCAAiC,EACjC,0CAA0C,EAC1C,eAAe,EACf,cAAc,EACd,YAAY,EACZ,WAAW,EACX,qBAAqB,EACrB,eAAe,EACf,kBAAkB,GAKnB,MAAM,wBAAwB,CAAA;AAC/B,6EAA6E;AAC7E,iFAAiF;AACjF,sCAAsC;AACtC,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AAEhE,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AAEhE,kFAAkF;AAClF,qDAAqD;AACrD,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AACxE,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAEhF,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAEtE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEjD,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA"}
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * inline-text.ts
3
- * Which modules can be text-edited directly on the page, and how to read the
4
- * edited value back out of the DOM (kywi-cms#94).
3
+ * Which modules can be text-edited directly on the page, WHICH ELEMENT each
4
+ * edit binds to, and how to read the edited value back out of the DOM
5
+ * (kywi-cms#94, kywi-cms#145).
5
6
  *
6
7
  * The front-of-site editor makes a text-bearing module's own rendered element
7
8
  * `contenteditable` — the real `<h2>`, `<p>` or rich-text `<div>` the visitor
@@ -17,6 +18,21 @@ export interface InlineTextProp {
17
18
  /** True when the prop holds HTML (rich text) rather than a plain string. */
18
19
  html: boolean;
19
20
  }
21
+ /**
22
+ * How an edit reached its element.
23
+ *
24
+ * `anchor` — the renderer marked the element with `data-kywi-prop`, so it holds
25
+ * that prop's copy and nothing else (see `useInlinePropAnchor`).
26
+ * `wrapper` — the legacy whole-module binding, allowed ONLY for a module with a
27
+ * single text prop (see `resolveInlineBinding` rule 3).
28
+ */
29
+ export type InlineBindingKind = 'anchor' | 'wrapper';
30
+ /** The element + prop one inline edit is bound to. */
31
+ export interface InlineTextBindingTarget {
32
+ prop: InlineTextProp;
33
+ element: HTMLElement;
34
+ kind: InlineBindingKind;
35
+ }
20
36
  /**
21
37
  * The module's *primary* text prop, or null when it has none.
22
38
  *
@@ -27,11 +43,47 @@ export interface InlineTextProp {
27
43
  * out of inline editing, where typing over the picture would be nonsense.
28
44
  */
29
45
  export declare function resolveInlineTextProp(config: ModuleConfig | null | undefined): InlineTextProp | null;
46
+ /**
47
+ * EVERY text-typed prop a module declares, in declaration order.
48
+ *
49
+ * This is the config-side half of the #145 safety guard: a module with more than
50
+ * one of these can never be bound at the wrapper, because the wrapper renders
51
+ * all of them and a commit would concatenate them into whichever one was bound.
52
+ */
53
+ export declare function listInlineTextProps(config: ModuleConfig | null | undefined): InlineTextProp[];
54
+ /**
55
+ * Which element + prop a double-click inside `wrapper` binds — or null when
56
+ * there is nothing safe to bind, in which case the caller routes the gesture to
57
+ * the props-rail fallback (kywi-cms#118) rather than to the wrapper.
58
+ *
59
+ * The rules, in order (kywi-cms#145):
60
+ *
61
+ * 1. The anchor the gesture actually landed in. Double-clicking a card's body
62
+ * edits the body, its footer edits the footer — the prop the owner pointed
63
+ * at, not "the module's first prop".
64
+ * 2. Otherwise, an unambiguous single anchor in the module: a gesture anywhere
65
+ * on a module with only one editable element can only have meant that one.
66
+ * Two or more anchors and a gesture that landed on neither is genuinely
67
+ * ambiguous → fallback.
68
+ * 3. Otherwise (a custom module with no anchors at all): the legacy whole-
69
+ * wrapper binding, and ONLY when the module declares exactly one text prop —
70
+ * the case where "everything the wrapper renders" and "the bound prop" cannot
71
+ * disagree. This is what keeps heading/text/richText/button working for
72
+ * module packs that never adopt the anchors.
73
+ *
74
+ * Anything else fails closed. A wrapper binding on a multi-text-prop module is
75
+ * the #145 corruption itself, so it is not reachable from here by any path.
76
+ */
77
+ export declare function resolveInlineBinding(config: ModuleConfig | null | undefined, wrapper: HTMLElement, target: Element | null): InlineTextBindingTarget | null;
30
78
  /**
31
79
  * Read the edited value back out of an editing host.
32
80
  *
33
- * The host is the module's wrapper element, which also carries the editor's own
34
- * floating chrome (type chip, action cluster). Chrome is marked with
81
+ * For an anchored host (`data-kywi-prop`) the host IS the prop's element — it
82
+ * renders that prop's copy and nothing else, editor chrome included so its
83
+ * content is the value, directly.
84
+ *
85
+ * For the legacy wrapper host the host also carries the editor's own floating
86
+ * chrome (type chip, action cluster). Chrome is marked with
35
87
  * `data-kywi-editor-chrome` and skipped, so the value comes from the module's
36
88
  * own rendered element — `innerHTML` for a rich-text prop, `textContent` for a
37
89
  * plain one.
@@ -1 +1 @@
1
- {"version":3,"file":"inline-text.d.ts","sourceRoot":"","sources":["../../../src/admin/layout-editor/inline-text.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAwB,MAAM,uBAAuB,CAAA;AAG/E,mDAAmD;AACnD,MAAM,WAAW,cAAc;IAC7B,sFAAsF;IACtF,IAAI,EAAE,MAAM,CAAA;IACZ,4EAA4E;IAC5E,IAAI,EAAE,OAAO,CAAA;CACd;AAaD;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,GAAG,SAAS,GAAG,cAAc,GAAG,IAAI,CASpG;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,CAS5E"}
1
+ {"version":3,"file":"inline-text.d.ts","sourceRoot":"","sources":["../../../src/admin/layout-editor/inline-text.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAwB,MAAM,uBAAuB,CAAA;AAI/E,mDAAmD;AACnD,MAAM,WAAW,cAAc;IAC7B,sFAAsF;IACtF,IAAI,EAAE,MAAM,CAAA;IACZ,4EAA4E;IAC5E,IAAI,EAAE,OAAO,CAAA;CACd;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,SAAS,CAAA;AAEpD,sDAAsD;AACtD,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,cAAc,CAAA;IACpB,OAAO,EAAE,WAAW,CAAA;IACpB,IAAI,EAAE,iBAAiB,CAAA;CACxB;AAuCD;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,GAAG,SAAS,GAAG,cAAc,GAAG,IAAI,CASpG;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,GAAG,SAAS,GAAG,cAAc,EAAE,CAO7F;AAiBD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,YAAY,GAAG,IAAI,GAAG,SAAS,EACvC,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,OAAO,GAAG,IAAI,GACrB,uBAAuB,GAAG,IAAI,CAoChC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,CAU5E"}