@kywi-software/core 0.6.2 → 0.6.4

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 (85) hide show
  1. package/AGENT-PATTERNS.md +221 -16
  2. package/README.md +23 -5
  3. package/dist/admin/layout-editor/column-overlay.d.ts +14 -1
  4. package/dist/admin/layout-editor/column-overlay.d.ts.map +1 -1
  5. package/dist/admin/layout-editor/column-overlay.js +5 -2
  6. package/dist/admin/layout-editor/column-overlay.js.map +1 -1
  7. package/dist/admin/layout-editor/editor-canvas.d.ts +34 -1
  8. package/dist/admin/layout-editor/editor-canvas.d.ts.map +1 -1
  9. package/dist/admin/layout-editor/editor-canvas.js +156 -16
  10. package/dist/admin/layout-editor/editor-canvas.js.map +1 -1
  11. package/dist/admin/layout-editor/editor-state.d.ts +57 -2
  12. package/dist/admin/layout-editor/editor-state.d.ts.map +1 -1
  13. package/dist/admin/layout-editor/editor-state.js +125 -53
  14. package/dist/admin/layout-editor/editor-state.js.map +1 -1
  15. package/dist/admin/layout-editor/editor.css +487 -44
  16. package/dist/admin/layout-editor/index.d.ts +1 -1
  17. package/dist/admin/layout-editor/index.d.ts.map +1 -1
  18. package/dist/admin/layout-editor/index.js.map +1 -1
  19. package/dist/admin/layout-editor/inline-text.d.ts +44 -0
  20. package/dist/admin/layout-editor/inline-text.d.ts.map +1 -0
  21. package/dist/admin/layout-editor/inline-text.js +67 -0
  22. package/dist/admin/layout-editor/inline-text.js.map +1 -0
  23. package/dist/admin/layout-editor/layout-editor.d.ts.map +1 -1
  24. package/dist/admin/layout-editor/layout-editor.js +23 -31
  25. package/dist/admin/layout-editor/layout-editor.js.map +1 -1
  26. package/dist/admin/layout-editor/module-overlay.d.ts +32 -1
  27. package/dist/admin/layout-editor/module-overlay.d.ts.map +1 -1
  28. package/dist/admin/layout-editor/module-overlay.js +108 -6
  29. package/dist/admin/layout-editor/module-overlay.js.map +1 -1
  30. package/dist/admin/layout-editor/node-lookup.d.ts +94 -0
  31. package/dist/admin/layout-editor/node-lookup.d.ts.map +1 -0
  32. package/dist/admin/layout-editor/node-lookup.js +142 -0
  33. package/dist/admin/layout-editor/node-lookup.js.map +1 -0
  34. package/dist/admin/layout-editor/overlay-shell.d.ts +19 -1
  35. package/dist/admin/layout-editor/overlay-shell.d.ts.map +1 -1
  36. package/dist/admin/layout-editor/overlay-shell.js +177 -69
  37. package/dist/admin/layout-editor/overlay-shell.js.map +1 -1
  38. package/dist/admin/layout-editor/props-panel.d.ts +9 -2
  39. package/dist/admin/layout-editor/props-panel.d.ts.map +1 -1
  40. package/dist/admin/layout-editor/props-panel.js +13 -5
  41. package/dist/admin/layout-editor/props-panel.js.map +1 -1
  42. package/dist/admin/layout-editor/region-overlay.d.ts +8 -1
  43. package/dist/admin/layout-editor/region-overlay.d.ts.map +1 -1
  44. package/dist/admin/layout-editor/region-overlay.js +4 -1
  45. package/dist/admin/layout-editor/region-overlay.js.map +1 -1
  46. package/dist/admin/layout-editor/section-insert-line.d.ts +7 -1
  47. package/dist/admin/layout-editor/section-insert-line.d.ts.map +1 -1
  48. package/dist/admin/layout-editor/section-insert-line.js +4 -1
  49. package/dist/admin/layout-editor/section-insert-line.js.map +1 -1
  50. package/dist/admin/layout-editor/section-overlay.d.ts +13 -1
  51. package/dist/admin/layout-editor/section-overlay.d.ts.map +1 -1
  52. package/dist/admin/layout-editor/section-overlay.js +24 -12
  53. package/dist/admin/layout-editor/section-overlay.js.map +1 -1
  54. package/dist/admin/layout-editor/section-variant-container-config.d.ts +29 -0
  55. package/dist/admin/layout-editor/section-variant-container-config.d.ts.map +1 -0
  56. package/dist/admin/layout-editor/section-variant-container-config.js +82 -0
  57. package/dist/admin/layout-editor/section-variant-container-config.js.map +1 -0
  58. package/dist/admin/styles/admin.css +5 -2
  59. package/dist/admin/surfaces/content/content-edit.d.ts.map +1 -1
  60. package/dist/admin/surfaces/content/content-edit.js +8 -1
  61. package/dist/admin/surfaces/content/content-edit.js.map +1 -1
  62. package/dist/db/content-queries.d.ts +35 -0
  63. package/dist/db/content-queries.d.ts.map +1 -1
  64. package/dist/db/content-queries.js +175 -36
  65. package/dist/db/content-queries.js.map +1 -1
  66. package/dist/layout/registry.d.ts +8 -1
  67. package/dist/layout/registry.d.ts.map +1 -1
  68. package/dist/layout/registry.js +8 -1
  69. package/dist/layout/registry.js.map +1 -1
  70. package/dist/nav/index.d.ts +1 -1
  71. package/dist/nav/index.d.ts.map +1 -1
  72. package/dist/nav/index.js +4 -1
  73. package/dist/nav/index.js.map +1 -1
  74. package/dist/nav/url-resolver.d.ts +27 -0
  75. package/dist/nav/url-resolver.d.ts.map +1 -1
  76. package/dist/nav/url-resolver.js +36 -1
  77. package/dist/nav/url-resolver.js.map +1 -1
  78. package/dist/scope/edit-mode-hooks.d.ts.map +1 -1
  79. package/dist/scope/edit-mode-hooks.js +27 -1
  80. package/dist/scope/edit-mode-hooks.js.map +1 -1
  81. package/dist/scope/inline-editing.d.ts.map +1 -1
  82. package/dist/scope/inline-editing.js +2 -1
  83. package/dist/scope/inline-editing.js.map +1 -1
  84. package/dist/site/styles.css +147 -4
  85. package/package.json +1 -1
@@ -1,9 +1,11 @@
1
1
  'use client';
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import React from 'react';
4
4
  import { SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable';
5
5
  import { useDroppable } from '@dnd-kit/core';
6
6
  import { isLayoutSection } from '../../layout/types.js';
7
+ import { resolveSectionStyle } from '../../layout/theme-css.js';
8
+ import { DEFAULT_ARM_ID, armSections, isVariantContainer, resolveArmSections } from './node-lookup.js';
7
9
  import { RegionOverlay } from './region-overlay.js';
8
10
  import { SectionOverlay } from './section-overlay.js';
9
11
  import { SectionInsertLine } from './section-insert-line.js';
@@ -34,6 +36,15 @@ function ModulePreview({ node, moduleComponents, resolveComponent, }) {
34
36
  : _jsxs("div", { className: "kywi-module kywi-module-unknown", children: ["Unknown: ", node.type] });
35
37
  }
36
38
  // ── Helpers ───────────────────────────────────────────────────────────────────
39
+ /**
40
+ * A region node the canvas knows how to draw. Anything else — a legacy or
41
+ * malformed node from an older document — is skipped rather than crashing the
42
+ * whole layout manager, which is how the old `filter(isLayoutSection)` behaved
43
+ * for everything that wasn't a plain section.
44
+ */
45
+ function isRenderableNode(node) {
46
+ return isLayoutSection(node) || isVariantContainer(node);
47
+ }
37
48
  function getRegions(state) {
38
49
  if (!state.activeVariant)
39
50
  return state.layout.regions;
@@ -47,8 +58,26 @@ function getRegions(state) {
47
58
  }
48
59
  return state.layout.regions;
49
60
  }
61
+ /**
62
+ * Build the inline-editing binding for one module, or null when the module has
63
+ * no primary text prop (or the canvas isn't in in-place mode).
64
+ */
65
+ function inlineTextBindingFor(nodeId, nodeType, inPlace, inlineEdit) {
66
+ if (!inPlace || !inlineEdit)
67
+ return null;
68
+ const prop = inlineEdit.resolveTextProp(nodeType);
69
+ if (!prop)
70
+ return null;
71
+ return {
72
+ active: inlineEdit.editingId === nodeId,
73
+ html: prop.html,
74
+ onActivate: () => inlineEdit.onActivate(nodeId),
75
+ onCommit: (host) => inlineEdit.onCommit(nodeId, host),
76
+ onCancel: () => inlineEdit.onCancel(),
77
+ };
78
+ }
50
79
  // ── DroppableColumn ───────────────────────────────────────────────────────────
51
- function DroppableColumn({ column, state, dispatch, moduleComponents, resolveComponent, }) {
80
+ function DroppableColumn({ column, state, dispatch, moduleComponents, resolveComponent, inPlace = false, inlineEdit, }) {
52
81
  // kywi-cms#20: this droppable represents the column's own (empty) space —
53
82
  // dropping directly there appends to the end of the column instead of always
54
83
  // inserting at the top, which `index: 0` (the old implicit default) would do
@@ -60,26 +89,137 @@ function DroppableColumn({ column, state, dispatch, moduleComponents, resolveCom
60
89
  data: { columnId: column.id, index: column.nodes.length },
61
90
  });
62
91
  const moduleIds = column.nodes.map(n => n.id);
63
- return (_jsx(ColumnOverlay, { columnId: column.id, width: column.width, children: _jsxs("div", { ref: setNodeRef, style: { minHeight: 40 }, children: [column.nodes.length === 0 && (_jsx("div", { className: "kywi-editor-column-empty", children: "Drag a module here" })), _jsx(SortableContext, { items: moduleIds, strategy: verticalListSortingStrategy, children: column.nodes.map((node, index) => {
64
- return (_jsx(ModuleOverlay, { moduleId: node.id, instanceId: node.instanceId, columnId: column.id, index: index, isSelected: state.selectedId === node.id, typeLabel: node.type, onSelect: () => dispatch({ type: 'SELECT', id: node.id, selectionType: 'module' }), children: _jsx(ModulePreview, { node: node, moduleComponents: moduleComponents, ...(resolveComponent ? { resolveComponent } : {}) }) }, node.id));
65
- }) })] }) }));
92
+ const content = (_jsxs(_Fragment, { children: [column.nodes.length === 0 && (_jsx("div", { className: inPlace ? 'kywi-ip-empty-column' : 'kywi-editor-column-empty', children: "Drag a module here" })), _jsx(SortableContext, { items: moduleIds, strategy: verticalListSortingStrategy, children: column.nodes.map((node, index) => {
93
+ const inlineText = inlineTextBindingFor(node.id, node.type, inPlace, inlineEdit);
94
+ // Re-key the preview after an edit session so contenteditable's DOM
95
+ // leftovers are replaced by a clean render from the stored props.
96
+ const previewKey = inlineEdit && inlineEdit.resetId === node.id ? `${node.id}:${inlineEdit.nonce}` : node.id;
97
+ return (_jsx(ModuleOverlay, { moduleId: node.id, instanceId: node.instanceId, columnId: column.id, index: index, isSelected: state.selectedId === node.id, typeLabel: node.type, inPlace: inPlace, moduleType: node.type, inlineText: inlineText, onSelect: () => dispatch({ type: 'SELECT', id: node.id, selectionType: 'module' }), children: _jsx(ModulePreview, { node: node, moduleComponents: moduleComponents, ...(resolveComponent ? { resolveComponent } : {}) }, previewKey) }, node.id));
98
+ }) })] }));
99
+ // In place the column element IS the drop zone: an extra wrapper div would
100
+ // sit between `.kywi-column` and the module wrappers and break the site's own
101
+ // child selectors. In the artboard the wrapper also carries a minimum height
102
+ // so an empty column stays a target.
103
+ return inPlace ? (_jsx(ColumnOverlay, { columnId: column.id, width: column.width, inPlace: true, rootRef: setNodeRef, children: content })) : (_jsx(ColumnOverlay, { columnId: column.id, width: column.width, children: _jsx("div", { ref: setNodeRef, style: { minHeight: 40 }, children: content }) }));
104
+ }
105
+ // ── SectionBlock ──────────────────────────────────────────────────────────────
106
+ /**
107
+ * One editable section: the overlay chrome plus its columns. Used both for a
108
+ * section sitting directly in a region and for a section inside a variant
109
+ * container arm (kywi-cms#92) — arm content is edited with exactly the same
110
+ * machinery, because the reducer's lookups are arm-aware.
111
+ */
112
+ function SectionBlock({ section, state, dispatch, moduleComponents, resolveComponent, inPlace = false, inlineEdit, }) {
113
+ // In place, the section carries its OWN resolved style exactly as the public
114
+ // SectionRenderer applies it (kywi-cms#94) — otherwise a section's background
115
+ // or padding would vanish the moment the owner started editing, which is the
116
+ // "I can't judge the real layout" complaint in miniature.
117
+ const resolved = inPlace
118
+ ? resolveSectionStyle(section.style, `[data-section-id="${section.id}"]`)
119
+ : null;
120
+ return (_jsx(SectionOverlay, { sectionId: section.id, isSelected: state.selectedId === section.id, inPlace: inPlace, ...(resolved ? { inPlaceStyle: resolved.base, responsiveCss: resolved.responsiveCss } : {}), onSelect: () => dispatch({ type: 'SELECT', id: section.id, selectionType: 'section' }), onAddColumn: () => dispatch({ type: 'ADD_COLUMN', sectionId: section.id }), onDelete: () => dispatch({ type: 'REMOVE_SECTION', sectionId: section.id }), children: section.columns.map((column, ci) => (_jsxs(React.Fragment, { children: [_jsx(DroppableColumn, { column: column, state: state, dispatch: dispatch, moduleComponents: moduleComponents, inPlace: inPlace, ...(inlineEdit ? { inlineEdit } : {}), ...(resolveComponent ? { resolveComponent } : {}) }), !inPlace && ci < section.columns.length - 1 && (_jsx(ColumnResizeHandle, { leftWidth: column.width, rightWidth: section.columns[ci + 1].width, onResize: (lw, rw) => {
121
+ const widths = section.columns.map((c, i) => i === ci ? lw : i === ci + 1 ? rw : c.width);
122
+ dispatch({ type: 'RESIZE_COLUMNS', sectionId: section.id, widths });
123
+ } }))] }, column.id))) }));
124
+ }
125
+ // ── VariantContainerBlock ─────────────────────────────────────────────────────
126
+ /** Human label for an arm: its own label, else its audience/arm key, else its position. */
127
+ function armLabel(entry, index) {
128
+ return entry.label || entry.audienceId || `Variant ${index + 1}`;
129
+ }
130
+ /** Section-level arm weights are 0..1 (module-level ones are 0-100) — show a percentage. */
131
+ function formatWeight(weight) {
132
+ return `${Math.round(weight * 1000) / 10}%`;
133
+ }
134
+ /**
135
+ * The Default / variant arm switcher. Rides inside the floating chrome in place
136
+ * and sits under the toolbar in the artboard, but is the same control either
137
+ * way — the canvas is showing whichever arm is selected here.
138
+ */
139
+ function ArmTabs({ arms, activeArm, isAbTest, onSelect, }) {
140
+ return (_jsx("div", { className: "kywi-editor-vc-arms", role: "tablist", "aria-label": "Variant arms", children: arms.map(arm => (_jsxs("button", { type: "button", role: "tab", "aria-selected": arm.id === activeArm, "data-arm-id": arm.id, className: `kywi-editor-vc-arm-btn${arm.id === activeArm ? ' kywi-editor-vc-arm-btn--active' : ''}`, onClick: (e) => {
141
+ e.stopPropagation();
142
+ onSelect(arm.id);
143
+ }, children: [arm.label, isAbTest && arm.weight !== null && (_jsx("span", { className: "kywi-editor-vc-arm-weight", children: formatWeight(arm.weight) }))] }, arm.id))) }));
144
+ }
145
+ /**
146
+ * The open arm's content. In the artboard it is a labelled box; in place it is
147
+ * nothing at all, so the arm's sections stay direct children of
148
+ * `.kywi-variant-container` the way the public renderer emits them.
149
+ */
150
+ function ArmBody({ inPlace, activeArm, children, }) {
151
+ if (inPlace)
152
+ return _jsx(_Fragment, { children: children });
153
+ return (_jsx("div", { className: "kywi-editor-vc-arm-body", "data-active-arm": activeArm, children: children }));
154
+ }
155
+ /**
156
+ * A section-level variant container rendered as a labelled block in document
157
+ * order (kywi-cms#92).
158
+ *
159
+ * Before this, the canvas filtered these nodes out entirely, so a personalized
160
+ * or A/B-tested band — typically the hero, the most-edited element on the page
161
+ * — simply did not exist in the layout manager. The block names what it is,
162
+ * lets the owner switch between the Default arm and each variant arm, and
163
+ * renders the open arm's sections with the ordinary section machinery so
164
+ * everything inside stays fully editable.
165
+ *
166
+ * In place (kywi-cms#94) the block becomes the public renderer's
167
+ * `.kywi-variant-container` and its badge/arm switcher floats above the band,
168
+ * so a personalized hero looks exactly like the hero while staying switchable.
169
+ */
170
+ function VariantContainerBlock({ container, state, dispatch, moduleComponents, resolveComponent, inPlace = false, inlineEdit, }) {
171
+ // Collapsed/expanded is presentation-only and per-block, so it stays local.
172
+ // Expanded by default: hiding arm content behind a disclosure would re-create
173
+ // the very "invisible in the editor" problem this block exists to fix.
174
+ const [expanded, setExpanded] = React.useState(true);
175
+ const isAbTest = container.mode === 'ab_test';
176
+ const isSelected = state.selectedId === container.id;
177
+ const requestedArm = state.activeArms[container.id] ?? DEFAULT_ARM_ID;
178
+ // A just-deleted arm can still be the requested one — fall back to Default.
179
+ const activeArm = armSections(container, requestedArm) ? requestedArm : DEFAULT_ARM_ID;
180
+ const sections = resolveArmSections(container, activeArm);
181
+ const arms = [
182
+ { id: DEFAULT_ARM_ID, label: 'Default', weight: null },
183
+ ...container.variants.map((v, i) => ({ id: v.id, label: armLabel(v, i), weight: v.weight })),
184
+ ];
185
+ const selectArm = (armId) => dispatch({ type: 'SET_VARIANT_ARM', containerId: container.id, armId });
186
+ const rootClassName = inPlace
187
+ ? `kywi-variant-container kywi-ip-vc${isSelected ? ' kywi-ip-vc--selected' : ''}`
188
+ : `kywi-editor-vc${isSelected ? ' kywi-editor-vc--selected' : ''}`;
189
+ return (_jsxs("div", { className: rootClassName, "data-variant-container-id": container.id, "data-vc-mode": container.mode, ...(inPlace ? { 'data-variant': activeArm } : {}), "data-testid": "editor-variant-container", children: [_jsxs("div", { className: inPlace ? 'kywi-ip-chrome kywi-ip-vc-chrome' : 'kywi-editor-vc-toolbar', ...(inPlace ? { 'data-kywi-editor-chrome': '', contentEditable: false } : {}), onClick: (e) => {
190
+ // Stop here so the canvas root doesn't immediately deselect.
191
+ e.stopPropagation();
192
+ dispatch({ type: 'SELECT', id: container.id, selectionType: 'variantContainer' });
193
+ }, children: [_jsx("span", { className: "kywi-editor-vc-badge", children: isAbTest ? 'A/B test' : 'Personalized' }), _jsx("span", { className: "kywi-editor-vc-title", children: isAbTest ? 'A/B tested section' : 'Personalized section' }), _jsxs("span", { className: "kywi-editor-vc-arm-count", children: [arms.length, " arm", arms.length === 1 ? '' : 's'] }), inPlace && expanded && (_jsx(ArmTabs, { arms: arms, activeArm: activeArm, isAbTest: isAbTest, onSelect: selectArm })), _jsx("div", { className: "kywi-editor-vc-toolbar-actions", children: _jsx("button", { type: "button", className: "kywi-editor-section-toolbar-btn", "data-action": "toggle-variant-container", "aria-expanded": expanded, onClick: (e) => { e.stopPropagation(); setExpanded(v => !v); }, children: expanded ? 'Collapse' : 'Expand' }) })] }), expanded && (_jsxs(_Fragment, { children: [!inPlace && (_jsx(ArmTabs, { arms: arms, activeArm: activeArm, isAbTest: isAbTest, onSelect: selectArm })), _jsxs(ArmBody, { inPlace: inPlace, activeArm: activeArm, children: [sections.length === 0 && (_jsx("p", { className: "kywi-editor-vc-arm-empty", children: "This arm renders nothing. Add a section so visitors in it see content." })), sections.map(section => (_jsx(SectionBlock, { section: section, state: state, dispatch: dispatch, moduleComponents: moduleComponents, inPlace: inPlace, ...(inlineEdit ? { inlineEdit } : {}), ...(resolveComponent ? { resolveComponent } : {}) }, section.id))), _jsx("button", { type: "button", className: inPlace ? 'kywi-ip-add-arm-section' : 'kywi-editor-vc-add-section', "data-action": "add-arm-section", ...(inPlace ? { 'data-kywi-editor-chrome': '' } : {}), onClick: (e) => {
194
+ e.stopPropagation();
195
+ dispatch({
196
+ type: 'ADD_ARM_SECTION',
197
+ containerId: container.id,
198
+ armId: activeArm,
199
+ columns: [12],
200
+ });
201
+ }, children: "+ Add section to this arm" })] })] }))] }));
66
202
  }
67
203
  // ── EditorCanvas ──────────────────────────────────────────────────────────────
68
- export function EditorCanvas({ state, dispatch, moduleComponents, onInsertSection, resolveComponent, overlayHandles = false, }) {
204
+ export function EditorCanvas({ state, dispatch, moduleComponents, onInsertSection, resolveComponent, overlayHandles = false, inPlace = false, inlineEdit, }) {
69
205
  const regions = getRegions(state);
70
- const canvasClassName = overlayHandles
71
- ? 'kywi-editor-canvas-content kywi-editor-canvas-content--overlay'
72
- : 'kywi-editor-canvas-content';
73
- // Total section count across every region — used to distinguish "no layout
206
+ // In place the canvas is NOT an artboard: it carries no background, padding
207
+ // or max-width of its own, so the page renders at its real width with its own
208
+ // styling and the editing chrome floats above it (kywi-cms#94).
209
+ const canvasClassName = inPlace
210
+ ? 'kywi-ip-canvas'
211
+ : overlayHandles
212
+ ? 'kywi-editor-canvas-content kywi-editor-canvas-content--overlay'
213
+ : 'kywi-editor-canvas-content';
214
+ // Total node count across every region — used to distinguish "no layout
74
215
  // document yet" from "regions exist but happen to render nothing" so the
75
216
  // canvas never looks like a rendering bug when it's really just empty.
76
- const totalSections = Object.values(regions).reduce((count, sections) => count + sections.filter(isLayoutSection).length, 0);
77
- return (_jsx(ModuleEditorContext.Provider, { value: true, children: _jsxs("div", { className: canvasClassName, onClick: () => dispatch({ type: 'DESELECT' }), children: [totalSections === 0 && (_jsxs("div", { className: "kywi-editor-canvas-empty", "data-testid": "editor-canvas-empty", children: [_jsx("p", { className: "kywi-editor-canvas-empty-title", children: "This page currently renders its body content." }), _jsx("p", { className: "kywi-editor-canvas-empty-copy", children: "Add a section to design it with the layout engine." }), _jsx("button", { type: "button", className: "kywi-editor-canvas-empty-cta", onClick: (event) => {
217
+ // Variant containers count (kywi-cms#92): a page whose regions hold only
218
+ // personalized / A-B'd bands has a real layout and must not be told it has none.
219
+ const totalNodes = Object.values(regions).reduce((count, nodes) => count + nodes.filter(isRenderableNode).length, 0);
220
+ return (_jsx(ModuleEditorContext.Provider, { value: true, children: _jsxs("div", { className: canvasClassName, onClick: () => dispatch({ type: 'DESELECT' }), children: [totalNodes === 0 && (_jsxs("div", { className: "kywi-editor-canvas-empty", "data-testid": "editor-canvas-empty", children: [_jsx("p", { className: "kywi-editor-canvas-empty-title", children: "This page currently renders its body content." }), _jsx("p", { className: "kywi-editor-canvas-empty-copy", children: "Add a section to design it with the layout engine." }), _jsx("button", { type: "button", className: "kywi-editor-canvas-empty-cta", onClick: (event) => {
78
221
  event.stopPropagation();
79
222
  onInsertSection(Object.keys(regions)[0] ?? 'main');
80
- }, children: "+ Add Section" })] })), Object.entries(regions).map(([regionName, sections]) => (_jsxs(RegionOverlay, { name: regionName, children: [sections.filter(isLayoutSection).map((section) => (_jsxs(React.Fragment, { children: [_jsx(SectionInsertLine, { onInsert: () => onInsertSection(regionName) }), _jsx(SectionOverlay, { sectionId: section.id, isSelected: state.selectedId === section.id, onSelect: () => dispatch({ type: 'SELECT', id: section.id, selectionType: 'section' }), onAddColumn: () => dispatch({ type: 'ADD_COLUMN', sectionId: section.id }), onDelete: () => dispatch({ type: 'REMOVE_SECTION', sectionId: section.id }), children: section.columns.map((column, ci) => (_jsxs(React.Fragment, { children: [_jsx(DroppableColumn, { column: column, state: state, dispatch: dispatch, moduleComponents: moduleComponents, ...(resolveComponent ? { resolveComponent } : {}) }), ci < section.columns.length - 1 && (_jsx(ColumnResizeHandle, { leftWidth: column.width, rightWidth: section.columns[ci + 1].width, onResize: (lw, rw) => {
81
- const widths = section.columns.map((c, i) => i === ci ? lw : i === ci + 1 ? rw : c.width);
82
- dispatch({ type: 'RESIZE_COLUMNS', sectionId: section.id, widths });
83
- } }))] }, column.id))) })] }, section.id))), _jsx(SectionInsertLine, { onInsert: () => onInsertSection(regionName) })] }, regionName)))] }) }));
223
+ }, children: "+ Add Section" })] })), Object.entries(regions).map(([regionName, nodes]) => (_jsxs(RegionOverlay, { name: regionName, inPlace: inPlace, children: [nodes.filter(isRenderableNode).map((node) => (_jsxs(React.Fragment, { children: [!inPlace && _jsx(SectionInsertLine, { onInsert: () => onInsertSection(regionName) }), isLayoutSection(node) ? (_jsx(SectionBlock, { section: node, state: state, dispatch: dispatch, moduleComponents: moduleComponents, inPlace: inPlace, ...(inlineEdit ? { inlineEdit } : {}), ...(resolveComponent ? { resolveComponent } : {}) })) : (_jsx(VariantContainerBlock, { container: node, state: state, dispatch: dispatch, moduleComponents: moduleComponents, inPlace: inPlace, ...(inlineEdit ? { inlineEdit } : {}), ...(resolveComponent ? { resolveComponent } : {}) }))] }, node.id))), _jsx(SectionInsertLine, { onInsert: () => onInsertSection(regionName), inPlace: inPlace })] }, regionName)))] }) }));
84
224
  }
85
225
  //# sourceMappingURL=editor-canvas.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"editor-canvas.js","sourceRoot":"","sources":["../../../src/admin/layout-editor/editor-canvas.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"editor-canvas.js","sourceRoot":"","sources":["../../../src/admin/layout-editor/editor-canvas.tsx"],"names":[],"mappings":"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"}
@@ -3,8 +3,34 @@
3
3
  * Core reducer for the Kywi layout overlay editor.
4
4
  * All editor components dispatch actions through this reducer.
5
5
  */
6
- import type { LayoutDocument, LayoutSection, ModuleNode } from '../../layout/types.js';
7
- export type SelectionType = 'module' | 'column' | 'section' | null;
6
+ import type { LayoutDocument, LayoutSection, ModuleNode, VariantContainer } from '../../layout/types.js';
7
+ export type SelectionType = 'module' | 'column' | 'section' | 'variantContainer' | null;
8
+ /**
9
+ * Arm metadata the props panel may rewrite.
10
+ *
11
+ * Deliberately carries no `sections`: the reducer keeps each surviving arm's
12
+ * own section content, matched by `id`, so relabelling or reweighting an arm
13
+ * can never revert (or alias) the content the canvas is editing. An `id` the
14
+ * container doesn't have yet is a new arm.
15
+ */
16
+ export interface VariantArmPatch {
17
+ id: string;
18
+ audienceId: string;
19
+ label: string;
20
+ weight: number;
21
+ }
22
+ /**
23
+ * Fields of a section-level variant container the props panel may rewrite.
24
+ * Absent keys are left untouched; `experimentId`/`winnerId` set to `''` clear
25
+ * the key entirely so the saved document never carries a meaningless empty id.
26
+ */
27
+ export interface VariantContainerPatch {
28
+ mode?: VariantContainer['mode'];
29
+ experimentId?: string;
30
+ winnerId?: string;
31
+ /** The complete arm list after the edit, in order. */
32
+ arms?: VariantArmPatch[];
33
+ }
8
34
  export interface DragState {
9
35
  isDragging: boolean;
10
36
  sourceType: 'palette' | 'canvas' | null;
@@ -20,6 +46,19 @@ export interface EditorState {
20
46
  history: LayoutDocument[];
21
47
  historyIndex: number;
22
48
  activeVariant: string | null;
49
+ /**
50
+ * Which arm of each section-level variant container the canvas is currently
51
+ * showing, keyed by container id (`DEFAULT_ARM_ID` for the Default arm).
52
+ *
53
+ * This is editor UI state, NOT document state — it lives beside `selectedId`
54
+ * and never enters `layout`, so it can't dirty the document, doesn't take
55
+ * part in undo/redo, and leaves round-trip byte-equivalence untouched. It
56
+ * lives in the reducer rather than in the canvas component so both editor
57
+ * shells (LayoutEditor and OverlayShell) read one source of truth and the
58
+ * open arm survives canvas re-mounts. Stale entries are harmless: a missing
59
+ * arm falls back to Default at render time.
60
+ */
61
+ activeArms: Record<string, string>;
23
62
  }
24
63
  export type EditorAction = {
25
64
  type: 'ADD_SECTION';
@@ -81,6 +120,22 @@ export type EditorAction = {
81
120
  } | {
82
121
  type: 'ADD_PAGE_VARIANT';
83
122
  audienceId: string;
123
+ } | {
124
+ type: 'SET_VARIANT_ARM';
125
+ containerId: string;
126
+ armId: string;
127
+ } | {
128
+ type: 'UPDATE_VARIANT_CONTAINER';
129
+ containerId: string;
130
+ patch: VariantContainerPatch;
131
+ } | {
132
+ type: 'REMOVE_VARIANT_CONTAINER';
133
+ containerId: string;
134
+ } | {
135
+ type: 'ADD_ARM_SECTION';
136
+ containerId: string;
137
+ armId: string;
138
+ columns: number[];
84
139
  } | {
85
140
  type: 'UNDO';
86
141
  } | {
@@ -1 +1 @@
1
- {"version":3,"file":"editor-state.d.ts","sourceRoot":"","sources":["../../../src/admin/layout-editor/editor-state.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"editor-state.d.ts","sourceRoot":"","sources":["../../../src/admin/layout-editor/editor-state.ts"],"names":[],"mappings":"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"}
@@ -6,6 +6,7 @@
6
6
  import { isLayoutSection } from '../../layout/types.js';
7
7
  import { generateId } from './drag-utils.js';
8
8
  import { cloneSection } from './component-actions.js';
9
+ import { armSections, findColumnIn, findModuleIn, findSectionIn, findVariantContainerIn, } from './node-lookup.js';
9
10
  // ── Helpers (internal) ───────────────────────────────────────────
10
11
  /**
11
12
  * If activeVariant is set, find the matching pageVariant or abExperiment
@@ -73,64 +74,45 @@ function commitToHistory(state, newLayout) {
73
74
  historyIndex: state.historyIndex + 1,
74
75
  };
75
76
  }
76
- /** Walk regions > sections > columns to find a column by ID. */
77
- function findColumn(regions, columnId) {
78
- for (const [regionName, nodes] of Object.entries(regions)) {
79
- for (const section of nodes) {
80
- if (!isLayoutSection(section))
81
- continue;
82
- for (const column of section.columns) {
83
- if (column.id === columnId) {
84
- return { regionName, region: nodes, section, column };
85
- }
86
- }
87
- }
88
- }
89
- return null;
90
- }
91
- /** Walk regions > sections > columns > modules to find a module by ID. */
92
- function findModule(regions, moduleId) {
93
- for (const [regionName, nodes] of Object.entries(regions)) {
94
- for (const section of nodes) {
95
- if (!isLayoutSection(section))
96
- continue;
97
- for (const column of section.columns) {
98
- for (let mi = 0; mi < column.nodes.length; mi++) {
99
- const module = column.nodes[mi];
100
- if (module !== undefined && module.id === moduleId) {
101
- return { regionName, region: nodes, section, column, module, moduleIndex: mi };
102
- }
103
- }
104
- }
105
- }
106
- }
107
- return null;
108
- }
109
- /** Find a section by ID across all regions. */
110
- function findSection(regions, sectionId) {
111
- for (const [regionName, nodes] of Object.entries(regions)) {
112
- for (const section of nodes) {
113
- if (isLayoutSection(section) && section.id === sectionId) {
114
- return { regionName, region: nodes, section };
115
- }
116
- }
117
- }
118
- return null;
77
+ /**
78
+ * Lookups are arm-aware (kywi-cms#92): a section, column or module living
79
+ * inside a section-level variant container's Default or variant arm is found
80
+ * exactly like one sitting directly in a region, so every existing section /
81
+ * column / module action edits arm content with no per-action special-casing.
82
+ * See `node-lookup.ts` for the traversal and the located shapes.
83
+ */
84
+ const findColumn = findColumnIn;
85
+ const findModule = findModuleIn;
86
+ const findSection = findSectionIn;
87
+ /** Deep-clone one section (columns, modules, module props/style). */
88
+ function cloneLayoutSection(section) {
89
+ return {
90
+ ...section,
91
+ columns: section.columns.map(col => ({
92
+ ...col,
93
+ nodes: col.nodes.map(n => ({ ...n, props: { ...n.props }, style: { ...n.style } })),
94
+ })),
95
+ };
119
96
  }
120
- /** Deep-clone regions immutably for safe mutation. Variant containers are
121
- * preserved (shallow-cloned) so section-only editor operations never drop them. */
97
+ /**
98
+ * Deep-clone regions immutably for safe mutation.
99
+ *
100
+ * Variant containers are cloned down to their arms (kywi-cms#92). They used to
101
+ * be shallow-cloned, which was safe only while arm content was unreachable: now
102
+ * that arm sections are editable, a shallow clone would alias the previous
103
+ * history entry's arrays and an arm edit would retroactively mutate every
104
+ * earlier snapshot, silently breaking undo.
105
+ */
122
106
  function cloneRegions(regions) {
123
107
  const result = {};
124
108
  for (const [name, nodes] of Object.entries(regions)) {
125
109
  result[name] = nodes.map(node => {
126
- if (!isLayoutSection(node))
127
- return { ...node };
110
+ if (isLayoutSection(node))
111
+ return cloneLayoutSection(node);
128
112
  return {
129
113
  ...node,
130
- columns: node.columns.map(col => ({
131
- ...col,
132
- nodes: col.nodes.map(n => ({ ...n, props: { ...n.props }, style: { ...n.style } })),
133
- })),
114
+ defaultSections: node.defaultSections.map(cloneLayoutSection),
115
+ variants: node.variants.map(v => ({ ...v, sections: v.sections.map(cloneLayoutSection) })),
134
116
  };
135
117
  });
136
118
  }
@@ -148,6 +130,7 @@ export function createInitialState(layout) {
148
130
  history: [layout],
149
131
  historyIndex: 0,
150
132
  activeVariant: null,
133
+ activeArms: {},
151
134
  };
152
135
  }
153
136
  export function editorReducer(state, action) {
@@ -170,6 +153,13 @@ export function editorReducer(state, action) {
170
153
  ...state,
171
154
  activeVariant: action.variantId,
172
155
  };
156
+ case 'SET_VARIANT_ARM':
157
+ // Which arm of a variant container the canvas shows — UI state only, so
158
+ // it never dirties the document or enters history (kywi-cms#92).
159
+ return {
160
+ ...state,
161
+ activeArms: { ...state.activeArms, [action.containerId]: action.armId },
162
+ };
173
163
  case 'UNDO': {
174
164
  if (state.historyIndex <= 0)
175
165
  return state;
@@ -258,7 +248,9 @@ export function editorReducer(state, action) {
258
248
  const hist = commitToHistory(state, layout);
259
249
  return { ...state, layout, ...hist, isDirty: true };
260
250
  }
261
- regions[found.regionName] = found.region.filter(sec => sec.id !== action.sectionId);
251
+ // Splice out of whichever array holds it — the region itself, or a
252
+ // variant container arm (kywi-cms#92).
253
+ found.holder.siblings.splice(found.index, 1);
262
254
  const layout = setActiveRegions(state, regions);
263
255
  const hist = commitToHistory(state, layout);
264
256
  return { ...state, layout, ...hist, isDirty: true };
@@ -275,7 +267,7 @@ export function editorReducer(state, action) {
275
267
  // for an edit that changed nothing (reviewer Minor, #69).
276
268
  if (!found)
277
269
  return state;
278
- regions[found.regionName] = found.region.map(node => node.id === action.sectionId ? action.section : node);
270
+ found.holder.siblings[found.index] = action.section;
279
271
  const layout = setActiveRegions(state, regions);
280
272
  const hist = commitToHistory(state, layout);
281
273
  return { ...state, layout, ...hist, isDirty: true };
@@ -432,6 +424,86 @@ export function editorReducer(state, action) {
432
424
  const hist = commitToHistory(state, layout);
433
425
  return { ...state, layout, ...hist, isDirty: true };
434
426
  }
427
+ // ── Section-level variant containers (kywi-cms#92) ────────────
428
+ //
429
+ // Only the container node itself needs bespoke actions. Everything INSIDE
430
+ // an arm (sections, columns, modules) is edited through the ordinary
431
+ // section/column/module actions above, because the lookups are arm-aware.
432
+ case 'UPDATE_VARIANT_CONTAINER': {
433
+ const regions = cloneRegions(getActiveRegions(state));
434
+ const found = findVariantContainerIn(regions, action.containerId);
435
+ if (!found)
436
+ return state;
437
+ const vc = found.container;
438
+ const { patch } = action;
439
+ if (patch.mode !== undefined)
440
+ vc.mode = patch.mode;
441
+ if (patch.experimentId !== undefined) {
442
+ if (patch.experimentId === '')
443
+ delete vc.experimentId;
444
+ else
445
+ vc.experimentId = patch.experimentId;
446
+ }
447
+ if (patch.winnerId !== undefined) {
448
+ if (patch.winnerId === '')
449
+ delete vc.winnerId;
450
+ else
451
+ vc.winnerId = patch.winnerId;
452
+ }
453
+ if (patch.arms !== undefined) {
454
+ const before = vc.variants;
455
+ vc.variants = patch.arms.map(arm => {
456
+ const existing = before.find(v => v.id === arm.id);
457
+ return {
458
+ id: arm.id,
459
+ audienceId: arm.audienceId,
460
+ label: arm.label,
461
+ weight: arm.weight,
462
+ // A brand-new arm is seeded with a copy of the Default arm (fresh
463
+ // ids via cloneSection) rather than starting empty: an empty arm
464
+ // ships a blank band to that slice of live traffic the moment it
465
+ // is saved. The owner edits the copy into the challenger.
466
+ sections: existing ? existing.sections : vc.defaultSections.map(cloneSection),
467
+ };
468
+ });
469
+ }
470
+ // `validateLayoutDocument` rejects an ab_test container with no
471
+ // experimentId, so switching mode seeds one instead of leaving the page
472
+ // silently unsaveable. The field stays editable in the props panel.
473
+ if (vc.mode === 'ab_test' && !vc.experimentId)
474
+ vc.experimentId = generateId();
475
+ const layout = setActiveRegions(state, regions);
476
+ const hist = commitToHistory(state, layout);
477
+ return { ...state, layout, ...hist, isDirty: true };
478
+ }
479
+ case 'REMOVE_VARIANT_CONTAINER': {
480
+ const regions = cloneRegions(getActiveRegions(state));
481
+ const found = findVariantContainerIn(regions, action.containerId);
482
+ if (!found)
483
+ return state;
484
+ found.region.splice(found.index, 1);
485
+ const layout = setActiveRegions(state, regions);
486
+ const hist = commitToHistory(state, layout);
487
+ return { ...state, layout, ...hist, isDirty: true };
488
+ }
489
+ case 'ADD_ARM_SECTION': {
490
+ const regions = cloneRegions(getActiveRegions(state));
491
+ const found = findVariantContainerIn(regions, action.containerId);
492
+ if (!found)
493
+ return state;
494
+ const sections = armSections(found.container, action.armId);
495
+ if (!sections)
496
+ return state;
497
+ sections.push({
498
+ id: generateId(),
499
+ type: 'section',
500
+ style: {},
501
+ columns: action.columns.map(width => ({ id: generateId(), width, nodes: [] })),
502
+ });
503
+ const layout = setActiveRegions(state, regions);
504
+ const hist = commitToHistory(state, layout);
505
+ return { ...state, layout, ...hist, isDirty: true };
506
+ }
435
507
  default:
436
508
  return state;
437
509
  }