@syntrologie/adapt-content 0.0.0-semantically-released → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cdn.d.ts ADDED
@@ -0,0 +1,35 @@
1
+ /**
2
+ * CDN Entry Point for Adaptive Content
3
+ *
4
+ * This module is bundled for CDN delivery and self-registers with the global
5
+ * SynOS app registry when loaded dynamically via the AppLoader.
6
+ */
7
+ /**
8
+ * App manifest for registry registration.
9
+ * Follows the AppManifest interface expected by AppLoader/AppRegistry.
10
+ */
11
+ export declare const manifest: {
12
+ id: string;
13
+ version: string;
14
+ name: string;
15
+ description: string;
16
+ runtime: {
17
+ actions: {
18
+ kind: "content:insertHtml" | "content:setText" | "content:setAttr" | "content:addClass" | "content:removeClass" | "content:setStyle";
19
+ executor: import("./types").ActionExecutor<import("./types").InsertHtmlAction> | import("./types").ActionExecutor<import("./types").SetTextAction> | import("./types").ActionExecutor<import("./types").SetAttrAction> | import("./types").ActionExecutor<import("./types").AddClassAction> | import("./types").ActionExecutor<import("./types").RemoveClassAction> | import("./types").ActionExecutor<import("./types").SetStyleAction>;
20
+ }[];
21
+ };
22
+ editor: {
23
+ panel: {
24
+ title: string;
25
+ icon: string;
26
+ description: string;
27
+ };
28
+ component: typeof import("./editor").ContentEditor;
29
+ };
30
+ metadata: {
31
+ isBuiltIn: boolean;
32
+ };
33
+ };
34
+ export default manifest;
35
+ //# sourceMappingURL=cdn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cdn.d.ts","sourceRoot":"","sources":["../src/cdn.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH;;;GAGG;AACH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;CAepB,CAAC;AAaF,eAAe,QAAQ,CAAC"}
package/dist/cdn.js ADDED
@@ -0,0 +1,39 @@
1
+ /**
2
+ * CDN Entry Point for Adaptive Content
3
+ *
4
+ * This module is bundled for CDN delivery and self-registers with the global
5
+ * SynOS app registry when loaded dynamically via the AppLoader.
6
+ */
7
+ import { editor } from './editor';
8
+ import { executors, runtime } from './runtime';
9
+ /**
10
+ * App manifest for registry registration.
11
+ * Follows the AppManifest interface expected by AppLoader/AppRegistry.
12
+ */
13
+ export const manifest = {
14
+ id: runtime.id,
15
+ version: runtime.version,
16
+ name: runtime.name,
17
+ description: runtime.description,
18
+ runtime: {
19
+ actions: executors.map(({ kind, executor }) => ({
20
+ kind,
21
+ executor,
22
+ })),
23
+ },
24
+ editor,
25
+ metadata: {
26
+ isBuiltIn: true,
27
+ },
28
+ };
29
+ /**
30
+ * Self-register with global registry if available.
31
+ * This happens when loaded via script tag (UMD).
32
+ */
33
+ if (typeof window !== 'undefined') {
34
+ const registry = window.SynOS?.appRegistry;
35
+ if (registry && typeof registry.register === 'function') {
36
+ registry.register(manifest);
37
+ }
38
+ }
39
+ export default manifest;
package/dist/editor.d.ts CHANGED
@@ -1,13 +1,12 @@
1
1
  /**
2
- * Adaptive Content - Editor Module
2
+ * Adaptive Content - Editor Component
3
3
  *
4
- * Editor panel for configuring content modifications.
4
+ * Review & tweak editor for AI-generated content modifications.
5
+ * Displays a scannable list of one-liner change summaries.
6
+ * Clicking a card navigates to the element and shows a floating edit panel.
5
7
  */
6
8
  import type { EditorPanelProps } from './types';
7
- /**
8
- * Content editor panel component.
9
- */
10
- export declare function ContentEditor({ config: _config, onChange: _onChange, editor: _editor, }: EditorPanelProps): import("react/jsx-runtime").JSX.Element;
9
+ export declare function ContentEditor({ config, onChange, editor }: EditorPanelProps): import("react/jsx-runtime").JSX.Element;
11
10
  /**
12
11
  * Editor module configuration.
13
12
  */
@@ -19,4 +18,10 @@ export declare const editor: {
19
18
  };
20
19
  component: typeof ContentEditor;
21
20
  };
21
+ export declare const editorPanel: {
22
+ title: string;
23
+ icon: string;
24
+ description: string;
25
+ };
26
+ export default ContentEditor;
22
27
  //# sourceMappingURL=editor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../src/editor.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD;;GAEG;AACH,wBAAgB,aAAa,CAAC,EAC5B,MAAM,EAAE,OAAO,EACf,QAAQ,EAAE,SAAS,EACnB,MAAM,EAAE,OAAO,GAChB,EAAE,gBAAgB,2CAOlB;AAED;;GAEG;AACH,eAAO,MAAM,MAAM;;;;;;;CAOlB,CAAC"}
1
+ {"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../src/editor.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAqXhD,wBAAgB,aAAa,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,gBAAgB,2CAsa3E;AAED;;GAEG;AACH,eAAO,MAAM,MAAM;;;;;;;CAOlB,CAAC;AAEF,eAAO,MAAM,WAAW;;;;CAAe,CAAC;AAExC,eAAe,aAAa,CAAC"}
package/dist/editor.js CHANGED
@@ -1,9 +1,510 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  /**
3
- * Content editor panel component.
3
+ * Adaptive Content - Editor Component
4
+ *
5
+ * Review & tweak editor for AI-generated content modifications.
6
+ * Displays a scannable list of one-liner change summaries.
7
+ * Clicking a card navigates to the element and shows a floating edit panel.
4
8
  */
5
- export function ContentEditor({ config: _config, onChange: _onChange, editor: _editor, }) {
6
- return (_jsxs("div", { className: "syntro-content-editor", children: [_jsx("p", { children: "Content editor coming soon..." }), _jsx("p", { children: "Configure text replacements, attribute changes, and style modifications." })] }));
9
+ import { useState, useCallback, useEffect, useRef } from 'react';
10
+ import { summarizeContentChange } from './summarize';
11
+ function itemKey(section, index) {
12
+ return `${section}:${index}`;
13
+ }
14
+ function parseItemKey(key) {
15
+ const [section, indexStr] = key.split(':');
16
+ return { section: section, index: Number(indexStr) };
17
+ }
18
+ // ============================================================================
19
+ // Section Config
20
+ // ============================================================================
21
+ const SECTION_ICONS = {
22
+ textReplacements: '\u{1f4dd}',
23
+ attributeChanges: '\u{1f3f7}\u{fe0f}',
24
+ styleChanges: '\u{1f3a8}',
25
+ htmlInsertions: '\u{1f4c4}',
26
+ classAdditions: '\u{2795}',
27
+ classRemovals: '\u{2796}',
28
+ };
29
+ // ============================================================================
30
+ // Styles
31
+ // ============================================================================
32
+ const styles = {
33
+ container: {
34
+ display: 'flex',
35
+ flexDirection: 'column',
36
+ height: '100%',
37
+ fontFamily: 'system-ui, -apple-system, sans-serif',
38
+ },
39
+ header: {
40
+ padding: '16px',
41
+ borderBottom: '1px solid #334155',
42
+ display: 'flex',
43
+ alignItems: 'center',
44
+ gap: '12px',
45
+ },
46
+ backButton: {
47
+ padding: '6px 12px',
48
+ borderRadius: '6px',
49
+ border: 'none',
50
+ backgroundColor: 'rgba(255,255,255,0.05)',
51
+ color: '#94a3b8',
52
+ fontSize: '13px',
53
+ cursor: 'pointer',
54
+ },
55
+ title: {
56
+ margin: 0,
57
+ fontSize: '15px',
58
+ fontWeight: 600,
59
+ color: '#f8fafc',
60
+ },
61
+ subtitle: {
62
+ margin: '2px 0 0 0',
63
+ fontSize: '11px',
64
+ color: '#64748b',
65
+ },
66
+ body: {
67
+ flex: 1,
68
+ overflow: 'auto',
69
+ padding: '16px',
70
+ },
71
+ groupHeader: {
72
+ fontSize: '11px',
73
+ fontWeight: 700,
74
+ color: '#64748b',
75
+ textTransform: 'uppercase',
76
+ letterSpacing: '0.06em',
77
+ padding: '4px 0 8px 0',
78
+ display: 'flex',
79
+ alignItems: 'center',
80
+ justifyContent: 'space-between',
81
+ },
82
+ groupCount: {
83
+ fontSize: '10px',
84
+ color: '#475569',
85
+ backgroundColor: 'rgba(255,255,255,0.06)',
86
+ padding: '2px 6px',
87
+ borderRadius: '8px',
88
+ },
89
+ card: {
90
+ display: 'flex',
91
+ alignItems: 'center',
92
+ gap: '8px',
93
+ padding: '8px 10px',
94
+ borderRadius: '6px',
95
+ border: '1px solid rgba(255,255,255,0.06)',
96
+ background: 'rgba(255,255,255,0.02)',
97
+ marginBottom: '4px',
98
+ cursor: 'pointer',
99
+ fontSize: '13px',
100
+ color: '#e2e8f0',
101
+ },
102
+ cardIcon: {
103
+ fontSize: '13px',
104
+ flexShrink: 0,
105
+ },
106
+ cardText: {
107
+ flex: 1,
108
+ overflow: 'hidden',
109
+ textOverflow: 'ellipsis',
110
+ whiteSpace: 'nowrap',
111
+ },
112
+ dismissButton: {
113
+ padding: '2px 6px',
114
+ borderRadius: '4px',
115
+ border: 'none',
116
+ background: 'transparent',
117
+ color: '#64748b',
118
+ fontSize: '14px',
119
+ cursor: 'pointer',
120
+ flexShrink: 0,
121
+ lineHeight: 1,
122
+ },
123
+ dismissedSection: {
124
+ marginTop: '16px',
125
+ cursor: 'pointer',
126
+ userSelect: 'none',
127
+ },
128
+ dismissedHeader: {
129
+ fontSize: '11px',
130
+ fontWeight: 600,
131
+ color: '#475569',
132
+ display: 'flex',
133
+ alignItems: 'center',
134
+ gap: '6px',
135
+ },
136
+ dismissedCard: {
137
+ display: 'flex',
138
+ alignItems: 'center',
139
+ gap: '8px',
140
+ padding: '6px 10px',
141
+ borderRadius: '6px',
142
+ border: '1px solid rgba(255,255,255,0.03)',
143
+ background: 'transparent',
144
+ marginBottom: '3px',
145
+ cursor: 'pointer',
146
+ fontSize: '12px',
147
+ color: '#475569',
148
+ opacity: 0.6,
149
+ },
150
+ emptyState: {
151
+ textAlign: 'center',
152
+ padding: '32px 16px',
153
+ color: '#64748b',
154
+ fontSize: '13px',
155
+ },
156
+ footer: {
157
+ padding: '12px 16px',
158
+ borderTop: '1px solid #334155',
159
+ display: 'flex',
160
+ gap: '8px',
161
+ },
162
+ saveButton: {
163
+ flex: 1,
164
+ padding: '10px',
165
+ borderRadius: '8px',
166
+ border: 'none',
167
+ background: 'rgba(59, 130, 246, 0.15)',
168
+ color: '#3b82f6',
169
+ fontSize: '13px',
170
+ fontWeight: 600,
171
+ cursor: 'pointer',
172
+ },
173
+ publishButton: {
174
+ flex: 1,
175
+ padding: '10px',
176
+ borderRadius: '8px',
177
+ border: 'none',
178
+ background: '#22c55e',
179
+ color: 'white',
180
+ fontSize: '13px',
181
+ fontWeight: 600,
182
+ cursor: 'pointer',
183
+ },
184
+ // Edit form styles
185
+ editForm: {
186
+ padding: '4px 0',
187
+ },
188
+ editHeader: {
189
+ display: 'flex',
190
+ alignItems: 'center',
191
+ gap: '8px',
192
+ marginBottom: '12px',
193
+ fontSize: '13px',
194
+ fontWeight: 600,
195
+ color: '#e2e8f0',
196
+ },
197
+ editTarget: {
198
+ fontSize: '11px',
199
+ fontFamily: 'monospace',
200
+ color: '#94a3b8',
201
+ padding: '4px 8px',
202
+ background: 'rgba(255,255,255,0.04)',
203
+ borderRadius: '4px',
204
+ marginBottom: '12px',
205
+ },
206
+ editLabel: {
207
+ fontSize: '11px',
208
+ fontWeight: 600,
209
+ color: '#64748b',
210
+ marginBottom: '4px',
211
+ display: 'block',
212
+ },
213
+ editInput: {
214
+ width: '100%',
215
+ padding: '6px 8px',
216
+ borderRadius: '4px',
217
+ border: '1px solid rgba(255,255,255,0.1)',
218
+ background: 'rgba(255,255,255,0.04)',
219
+ color: '#e2e8f0',
220
+ fontSize: '12px',
221
+ fontFamily: 'inherit',
222
+ marginBottom: '8px',
223
+ boxSizing: 'border-box',
224
+ },
225
+ editTextarea: {
226
+ width: '100%',
227
+ padding: '6px 8px',
228
+ borderRadius: '4px',
229
+ border: '1px solid rgba(255,255,255,0.1)',
230
+ background: 'rgba(255,255,255,0.04)',
231
+ color: '#e2e8f0',
232
+ fontSize: '12px',
233
+ fontFamily: 'inherit',
234
+ marginBottom: '8px',
235
+ resize: 'vertical',
236
+ minHeight: '60px',
237
+ boxSizing: 'border-box',
238
+ },
239
+ editSelect: {
240
+ width: '100%',
241
+ padding: '6px 8px',
242
+ borderRadius: '4px',
243
+ border: '1px solid rgba(255,255,255,0.1)',
244
+ background: 'rgba(255,255,255,0.04)',
245
+ color: '#e2e8f0',
246
+ fontSize: '12px',
247
+ marginBottom: '8px',
248
+ },
249
+ };
250
+ // ============================================================================
251
+ // Helpers
252
+ // ============================================================================
253
+ /** Build a flat list of all items across all section types. */
254
+ function flattenItems(config) {
255
+ const items = [];
256
+ const sections = Object.keys(SECTION_ICONS);
257
+ for (const section of sections) {
258
+ const arr = config[section] || [];
259
+ arr.forEach((item, i) => {
260
+ const rec = item;
261
+ items.push({
262
+ key: itemKey(section, i),
263
+ section,
264
+ index: i,
265
+ icon: SECTION_ICONS[section],
266
+ summary: summarizeContentChange(section, rec),
267
+ anchorId: rec.anchorId || '',
268
+ });
269
+ });
270
+ }
271
+ return items;
272
+ }
273
+ /** Remove items by key set from a config, returning a new config. */
274
+ function filterConfig(config, dismissedKeys) {
275
+ const result = { ...config };
276
+ const sections = Object.keys(SECTION_ICONS);
277
+ for (const section of sections) {
278
+ const arr = config[section] || [];
279
+ const filtered = arr.filter((_, i) => !dismissedKeys.has(itemKey(section, i)));
280
+ if (filtered.length > 0 || config[section] !== undefined) {
281
+ result[section] = filtered;
282
+ }
283
+ }
284
+ return result;
285
+ }
286
+ function useAnchorDetection(items) {
287
+ const [detectionMap, setDetectionMap] = useState(new Map());
288
+ const itemsRef = useRef(items);
289
+ itemsRef.current = items;
290
+ useEffect(() => {
291
+ const runDetection = () => {
292
+ const map = new Map();
293
+ for (const item of itemsRef.current) {
294
+ if (!item.anchorId) {
295
+ map.set(item.key, { found: false, element: null });
296
+ continue;
297
+ }
298
+ try {
299
+ const el = document.querySelector(item.anchorId);
300
+ map.set(item.key, { found: el !== null, element: el });
301
+ }
302
+ catch {
303
+ map.set(item.key, { found: false, element: null });
304
+ }
305
+ }
306
+ setDetectionMap(map);
307
+ };
308
+ runDetection();
309
+ const interval = setInterval(runDetection, 2000);
310
+ return () => clearInterval(interval);
311
+ }, []);
312
+ return detectionMap;
313
+ }
314
+ function DetectionBadge({ found }) {
315
+ return (_jsx("span", { style: {
316
+ width: '8px',
317
+ height: '8px',
318
+ borderRadius: '50%',
319
+ backgroundColor: found ? '#22c55e' : '#475569',
320
+ flexShrink: 0,
321
+ display: 'inline-block',
322
+ }, title: found ? 'Found on this page' : 'Not found on this page' }));
323
+ }
324
+ // ============================================================================
325
+ // ContentEditor Component
326
+ // ============================================================================
327
+ export function ContentEditor({ config, onChange, editor }) {
328
+ const typedConfig = config;
329
+ const [dismissedKeys, setDismissedKeys] = useState(new Set());
330
+ const [dismissedOpen, setDismissedOpen] = useState(false);
331
+ const [editingKey, setEditingKey] = useState(null);
332
+ const [previewMode, setPreviewMode] = useState('after');
333
+ // Consume initialEditKey from accordion navigation on mount
334
+ const initialConsumed = useRef(false);
335
+ useEffect(() => {
336
+ if (editor.initialEditKey != null && !initialConsumed.current) {
337
+ initialConsumed.current = true;
338
+ // Map flat action index to internal section:index key.
339
+ // The flat index refers to the position within this app's actions only
340
+ // (after actionsToAppConfig transformation), so we walk sections in order.
341
+ const allFlat = flattenItems(typedConfig);
342
+ const targetIdx = Number(editor.initialEditKey);
343
+ if (targetIdx >= 0 && targetIdx < allFlat.length) {
344
+ const target = allFlat[targetIdx];
345
+ setEditingKey(target.key);
346
+ if (target.anchorId) {
347
+ editor.highlightElement(target.anchorId);
348
+ }
349
+ }
350
+ editor.clearInitialState?.();
351
+ }
352
+ else if (editor.initialCreate && !initialConsumed.current) {
353
+ initialConsumed.current = true;
354
+ editor.clearInitialState?.();
355
+ }
356
+ }, [editor, typedConfig]);
357
+ const allItems = flattenItems(typedConfig);
358
+ const activeItems = allItems.filter((item) => !dismissedKeys.has(item.key));
359
+ const dismissedItems = allItems.filter((item) => dismissedKeys.has(item.key));
360
+ const totalChanges = activeItems.length;
361
+ const [_hoveredKey, setHoveredKey] = useState(null);
362
+ const detectionMap = useAnchorDetection(allItems);
363
+ const foundCount = activeItems.filter((item) => detectionMap.get(item.key)?.found).length;
364
+ const handleDismiss = useCallback((key) => {
365
+ setDismissedKeys((prev) => {
366
+ const next = new Set(prev);
367
+ next.add(key);
368
+ return next;
369
+ });
370
+ if (editingKey === key)
371
+ setEditingKey(null);
372
+ }, [editingKey]);
373
+ const handleRestore = useCallback((key) => {
374
+ setDismissedKeys((prev) => {
375
+ const next = new Set(prev);
376
+ next.delete(key);
377
+ return next;
378
+ });
379
+ }, []);
380
+ const handleCardClick = useCallback((item) => {
381
+ if (item.anchorId) {
382
+ editor.highlightElement(item.anchorId);
383
+ }
384
+ setEditingKey(item.key);
385
+ }, [editor]);
386
+ const handleBackToList = useCallback(() => {
387
+ setEditingKey(null);
388
+ setPreviewMode('after');
389
+ editor.previewConfig(config);
390
+ editor.clearHighlight();
391
+ }, [editor, config]);
392
+ const handleBeforeAfter = useCallback((mode) => {
393
+ setPreviewMode(mode);
394
+ if (mode === 'before') {
395
+ const filtered = filterConfig(typedConfig, new Set([editingKey]));
396
+ editor.previewConfig(filtered);
397
+ }
398
+ else {
399
+ editor.previewConfig(config);
400
+ }
401
+ }, [typedConfig, editingKey, editor, config]);
402
+ const handleFieldChange = useCallback((section, index, field, value) => {
403
+ const arr = (typedConfig[section] || []).slice();
404
+ const item = { ...arr[index] };
405
+ item[field] = value;
406
+ arr[index] = item;
407
+ const updated = { ...typedConfig, [section]: arr };
408
+ onChange(updated);
409
+ editor.setDirty(true);
410
+ }, [typedConfig, onChange, editor]);
411
+ const handlePublish = useCallback(() => {
412
+ // Filter dismissed items before publishing
413
+ if (dismissedKeys.size > 0) {
414
+ const filtered = filterConfig(typedConfig, dismissedKeys);
415
+ onChange(filtered);
416
+ }
417
+ editor.publish();
418
+ }, [dismissedKeys, typedConfig, onChange, editor]);
419
+ const handleCardHover = useCallback((item) => {
420
+ setHoveredKey(item.key);
421
+ if (item.anchorId) {
422
+ editor.highlightElement(item.anchorId);
423
+ }
424
+ }, [editor]);
425
+ const handleCardLeave = useCallback(() => {
426
+ setHoveredKey(null);
427
+ editor.clearHighlight();
428
+ }, [editor]);
429
+ // ---- Edit form renderers per section type ----
430
+ const renderEditFields = (section, index) => {
431
+ const arr = typedConfig[section] || [];
432
+ const item = arr[index];
433
+ if (!item)
434
+ return null;
435
+ const anchorId = item.anchorId || '';
436
+ switch (section) {
437
+ case 'textReplacements':
438
+ return (_jsxs("div", { style: styles.editForm, children: [_jsx("div", { style: styles.editTarget, children: anchorId }), _jsx("label", { style: styles.editLabel, children: "Text" }), _jsx("textarea", { style: styles.editTextarea, value: item.text || '', onChange: (e) => handleFieldChange(section, index, 'text', e.target.value) })] }));
439
+ case 'attributeChanges':
440
+ return (_jsxs("div", { style: styles.editForm, children: [_jsx("div", { style: styles.editTarget, children: anchorId }), _jsx("label", { style: styles.editLabel, children: "Attribute" }), _jsx("input", { style: styles.editInput, value: item.attr || '', onChange: (e) => handleFieldChange(section, index, 'attr', e.target.value) }), _jsx("label", { style: styles.editLabel, children: "Value" }), _jsx("input", { style: styles.editInput, value: item.value || '', onChange: (e) => handleFieldChange(section, index, 'value', e.target.value) })] }));
441
+ case 'styleChanges': {
442
+ const styleObj = item.styles || {};
443
+ return (_jsxs("div", { style: styles.editForm, children: [_jsx("div", { style: styles.editTarget, children: anchorId }), _jsx("label", { style: styles.editLabel, children: "Styles" }), Object.entries(styleObj).map(([prop, val]) => (_jsxs("div", { style: { display: 'flex', gap: '4px', marginBottom: '4px' }, children: [_jsx("input", { style: { ...styles.editInput, flex: 1, marginBottom: 0 }, value: prop, readOnly: true }), _jsx("input", { style: { ...styles.editInput, flex: 1, marginBottom: 0 }, value: val, onChange: (e) => {
444
+ const newStyles = { ...styleObj, [prop]: e.target.value };
445
+ handleFieldChange(section, index, 'styles', newStyles);
446
+ } })] }, prop)))] }));
447
+ }
448
+ case 'htmlInsertions':
449
+ return (_jsxs("div", { style: styles.editForm, children: [_jsx("div", { style: styles.editTarget, children: anchorId }), _jsx("label", { style: styles.editLabel, children: "Position" }), _jsxs("select", { style: styles.editSelect, value: item.position || 'after', onChange: (e) => handleFieldChange(section, index, 'position', e.target.value), children: [_jsx("option", { value: "before", children: "Before" }), _jsx("option", { value: "after", children: "After" }), _jsx("option", { value: "prepend", children: "Prepend" }), _jsx("option", { value: "append", children: "Append" }), _jsx("option", { value: "replace", children: "Replace" })] }), _jsx("label", { style: styles.editLabel, children: "HTML" }), _jsx("textarea", { style: { ...styles.editTextarea, fontFamily: 'monospace' }, value: item.html || '', onChange: (e) => handleFieldChange(section, index, 'html', e.target.value) })] }));
450
+ case 'classAdditions':
451
+ case 'classRemovals':
452
+ return (_jsxs("div", { style: styles.editForm, children: [_jsx("div", { style: styles.editTarget, children: anchorId }), _jsx("label", { style: styles.editLabel, children: "Class Name" }), _jsx("input", { style: styles.editInput, value: item.className || '', onChange: (e) => handleFieldChange(section, index, 'className', e.target.value) })] }));
453
+ default:
454
+ return null;
455
+ }
456
+ };
457
+ return (_jsxs("div", { style: styles.container, children: [_jsxs("div", { style: styles.header, children: [_jsx("button", { onClick: () => (editingKey !== null ? handleBackToList() : editor.navigateHome()), style: styles.backButton, children: "\u2190 Back" }), _jsxs("div", { children: [_jsx("h2", { style: styles.title, children: "Review Changes" }), _jsxs("p", { style: styles.subtitle, children: [totalChanges, " change", totalChanges !== 1 ? 's' : '', totalChanges > 0 && ` (${foundCount} found on this page)`] })] })] }), _jsx("div", { style: styles.body, children: editingKey !== null ? (
458
+ /* ---- Edit mode ---- */
459
+ (() => {
460
+ const ref = parseItemKey(editingKey);
461
+ const editItem = allItems.find((it) => it.key === editingKey);
462
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { style: styles.editHeader, children: [_jsx("span", { children: editItem?.icon }), _jsx("span", { children: editItem?.summary })] }), _jsxs("div", { style: {
463
+ display: 'flex',
464
+ gap: '0',
465
+ marginBottom: '12px',
466
+ borderRadius: '6px',
467
+ overflow: 'hidden',
468
+ border: '1px solid rgba(255,255,255,0.1)',
469
+ }, children: [_jsx("button", { onClick: () => handleBeforeAfter('before'), style: {
470
+ flex: 1,
471
+ padding: '6px 12px',
472
+ border: 'none',
473
+ fontSize: '12px',
474
+ fontWeight: 600,
475
+ cursor: 'pointer',
476
+ background: previewMode === 'before' ? 'rgba(59,130,246,0.2)' : 'transparent',
477
+ color: previewMode === 'before' ? '#3b82f6' : '#64748b',
478
+ }, children: "Before" }), _jsx("button", { onClick: () => handleBeforeAfter('after'), style: {
479
+ flex: 1,
480
+ padding: '6px 12px',
481
+ border: 'none',
482
+ borderLeft: '1px solid rgba(255,255,255,0.1)',
483
+ fontSize: '12px',
484
+ fontWeight: 600,
485
+ cursor: 'pointer',
486
+ background: previewMode === 'after' ? 'rgba(59,130,246,0.2)' : 'transparent',
487
+ color: previewMode === 'after' ? '#3b82f6' : '#64748b',
488
+ }, children: "After" })] }), renderEditFields(ref.section, ref.index)] }));
489
+ })()) : (
490
+ /* ---- List mode ---- */
491
+ _jsxs(_Fragment, { children: [allItems.length === 0 && (_jsx("div", { style: styles.emptyState, children: "No content changes configured." })), activeItems.length > 0 && (_jsxs(_Fragment, { children: [_jsxs("div", { style: styles.groupHeader, children: [_jsx("span", { children: "CONTENT" }), _jsx("span", { style: styles.groupCount, children: activeItems.length })] }), activeItems.map((item) => {
492
+ const detection = detectionMap.get(item.key);
493
+ return (_jsxs("div", { style: styles.card, "data-item-key": item.key, onMouseEnter: () => handleCardHover(item), onMouseLeave: handleCardLeave, children: [_jsx(DetectionBadge, { found: detection?.found ?? false }), _jsx("span", { style: styles.cardIcon, onClick: (e) => {
494
+ e.stopPropagation();
495
+ handleCardClick(item);
496
+ }, children: item.icon }), _jsx("span", { style: styles.cardText, onClick: () => handleCardClick(item), children: item.summary }), _jsx("button", { style: styles.dismissButton, onClick: (e) => {
497
+ e.stopPropagation();
498
+ handleDismiss(item.key);
499
+ }, title: "Dismiss this change", children: "\u00D7" })] }, item.key));
500
+ })] })), dismissedItems.length > 0 && (_jsxs("div", { style: styles.dismissedSection, children: [_jsxs("div", { style: { ...styles.dismissedHeader, cursor: 'pointer' }, onClick: () => setDismissedOpen(!dismissedOpen), children: [_jsx("span", { children: dismissedOpen ? '\u25be' : '\u25b8' }), _jsxs("span", { children: ["Dismissed (", dismissedItems.length, ")"] })] }), dismissedOpen && (_jsx("div", { style: { marginTop: '6px' }, children: dismissedItems.map((item) => (_jsxs("div", { style: styles.dismissedCard, children: [_jsx("span", { style: styles.cardIcon, children: item.icon }), _jsx("span", { style: { ...styles.cardText, textDecoration: 'line-through' }, children: item.summary }), _jsx("button", { style: {
501
+ ...styles.dismissButton,
502
+ color: '#3b82f6',
503
+ fontSize: '11px',
504
+ }, onClick: (e) => {
505
+ e.stopPropagation();
506
+ handleRestore(item.key);
507
+ }, children: "Restore" })] }, item.key))) }))] }))] })) }), _jsxs("div", { style: styles.footer, children: [_jsx("button", { onClick: () => editor.save(), style: styles.saveButton, children: "Save Draft" }), _jsx("button", { onClick: handlePublish, style: styles.publishButton, children: "Publish" })] })] }));
7
508
  }
8
509
  /**
9
510
  * Editor module configuration.
@@ -11,8 +512,10 @@ export function ContentEditor({ config: _config, onChange: _onChange, editor: _e
11
512
  export const editor = {
12
513
  panel: {
13
514
  title: 'Content',
14
- icon: '📝',
515
+ icon: '\u{1f4dd}',
15
516
  description: 'Text and attribute modifications',
16
517
  },
17
518
  component: ContentEditor,
18
519
  };
520
+ export const editorPanel = editor.panel;
521
+ export default ContentEditor;
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,cAAc,EACd,iBAAiB,EACjB,cAAc,EAEd,cAAc,EACf,MAAM,SAAS,CAAC;AAOjB;;GAEG;AACH,eAAO,MAAM,iBAAiB,EAAE,cAAc,CAAC,gBAAgB,CAmE9D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,cAAc,CAAC,aAAa,CA+BxD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,cAAc,CAAC,aAAa,CA2CxD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,cAAc,CAAC,cAAc,CA8B1D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,cAAc,CAAC,iBAAiB,CA8BhE,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,cAAc,CAAC,cAAc,CA+C1D,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;EAOZ,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;CAMnB,CAAC"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EACV,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,cAAc,EACd,iBAAiB,EACjB,cAAc,EAEd,cAAc,EACf,MAAM,SAAS,CAAC;AAMjB;;GAEG;AACH,eAAO,MAAM,iBAAiB,EAAE,cAAc,CAAC,gBAAgB,CAmE9D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,cAAc,CAAC,aAAa,CA+BxD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,cAAc,CAAC,aAAa,CA2CxD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,cAAc,CAAC,cAAc,CA8B1D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,cAAc,CAAC,iBAAiB,CA8BhE,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,cAAc,CAAC,cAAc,CA+C1D,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;EAOZ,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;CAMnB,CAAC"}
package/dist/schema.d.ts CHANGED
@@ -12,127 +12,157 @@ export declare const configSchema: z.ZodObject<{
12
12
  /** Text replacements */
13
13
  textReplacements: z.ZodOptional<z.ZodArray<z.ZodObject<{
14
14
  anchorId: z.ZodString;
15
+ summary: z.ZodString;
15
16
  text: z.ZodString;
16
17
  }, "strip", z.ZodTypeAny, {
17
18
  anchorId: string;
19
+ summary: string;
18
20
  text: string;
19
21
  }, {
20
22
  anchorId: string;
23
+ summary: string;
21
24
  text: string;
22
25
  }>, "many">>;
23
26
  /** Attribute modifications */
24
27
  attributeChanges: z.ZodOptional<z.ZodArray<z.ZodObject<{
25
28
  anchorId: z.ZodString;
29
+ summary: z.ZodString;
26
30
  attr: z.ZodString;
27
31
  value: z.ZodString;
28
32
  }, "strip", z.ZodTypeAny, {
33
+ value: string;
29
34
  anchorId: string;
35
+ summary: string;
30
36
  attr: string;
31
- value: string;
32
37
  }, {
38
+ value: string;
33
39
  anchorId: string;
40
+ summary: string;
34
41
  attr: string;
35
- value: string;
36
42
  }>, "many">>;
37
43
  /** Style modifications */
38
44
  styleChanges: z.ZodOptional<z.ZodArray<z.ZodObject<{
39
45
  anchorId: z.ZodString;
46
+ summary: z.ZodString;
40
47
  styles: z.ZodRecord<z.ZodString, z.ZodString>;
41
48
  }, "strip", z.ZodTypeAny, {
42
49
  anchorId: string;
50
+ summary: string;
43
51
  styles: Record<string, string>;
44
52
  }, {
45
53
  anchorId: string;
54
+ summary: string;
46
55
  styles: Record<string, string>;
47
56
  }>, "many">>;
48
57
  /** HTML insertions */
49
58
  htmlInsertions: z.ZodOptional<z.ZodArray<z.ZodObject<{
50
59
  anchorId: z.ZodString;
60
+ summary: z.ZodString;
51
61
  html: z.ZodString;
52
62
  position: z.ZodEnum<["before", "after", "prepend", "append", "replace"]>;
53
63
  }, "strip", z.ZodTypeAny, {
54
64
  anchorId: string;
65
+ summary: string;
55
66
  html: string;
56
67
  position: "before" | "after" | "prepend" | "append" | "replace";
57
68
  }, {
58
69
  anchorId: string;
70
+ summary: string;
59
71
  html: string;
60
72
  position: "before" | "after" | "prepend" | "append" | "replace";
61
73
  }>, "many">>;
62
74
  /** Class additions */
63
75
  classAdditions: z.ZodOptional<z.ZodArray<z.ZodObject<{
64
76
  anchorId: z.ZodString;
77
+ summary: z.ZodString;
65
78
  className: z.ZodString;
66
79
  }, "strip", z.ZodTypeAny, {
67
80
  anchorId: string;
81
+ summary: string;
68
82
  className: string;
69
83
  }, {
70
84
  anchorId: string;
85
+ summary: string;
71
86
  className: string;
72
87
  }>, "many">>;
73
88
  /** Class removals */
74
89
  classRemovals: z.ZodOptional<z.ZodArray<z.ZodObject<{
75
90
  anchorId: z.ZodString;
91
+ summary: z.ZodString;
76
92
  className: z.ZodString;
77
93
  }, "strip", z.ZodTypeAny, {
78
94
  anchorId: string;
95
+ summary: string;
79
96
  className: string;
80
97
  }, {
81
98
  anchorId: string;
99
+ summary: string;
82
100
  className: string;
83
101
  }>, "many">>;
84
102
  }, "strip", z.ZodTypeAny, {
85
103
  textReplacements?: {
86
104
  anchorId: string;
105
+ summary: string;
87
106
  text: string;
88
107
  }[] | undefined;
89
108
  attributeChanges?: {
109
+ value: string;
90
110
  anchorId: string;
111
+ summary: string;
91
112
  attr: string;
92
- value: string;
93
113
  }[] | undefined;
94
114
  styleChanges?: {
95
115
  anchorId: string;
116
+ summary: string;
96
117
  styles: Record<string, string>;
97
118
  }[] | undefined;
98
119
  htmlInsertions?: {
99
120
  anchorId: string;
121
+ summary: string;
100
122
  html: string;
101
123
  position: "before" | "after" | "prepend" | "append" | "replace";
102
124
  }[] | undefined;
103
125
  classAdditions?: {
104
126
  anchorId: string;
127
+ summary: string;
105
128
  className: string;
106
129
  }[] | undefined;
107
130
  classRemovals?: {
108
131
  anchorId: string;
132
+ summary: string;
109
133
  className: string;
110
134
  }[] | undefined;
111
135
  }, {
112
136
  textReplacements?: {
113
137
  anchorId: string;
138
+ summary: string;
114
139
  text: string;
115
140
  }[] | undefined;
116
141
  attributeChanges?: {
142
+ value: string;
117
143
  anchorId: string;
144
+ summary: string;
118
145
  attr: string;
119
- value: string;
120
146
  }[] | undefined;
121
147
  styleChanges?: {
122
148
  anchorId: string;
149
+ summary: string;
123
150
  styles: Record<string, string>;
124
151
  }[] | undefined;
125
152
  htmlInsertions?: {
126
153
  anchorId: string;
154
+ summary: string;
127
155
  html: string;
128
156
  position: "before" | "after" | "prepend" | "append" | "replace";
129
157
  }[] | undefined;
130
158
  classAdditions?: {
131
159
  anchorId: string;
160
+ summary: string;
132
161
  className: string;
133
162
  }[] | undefined;
134
163
  classRemovals?: {
135
164
  anchorId: string;
165
+ summary: string;
136
166
  className: string;
137
167
  }[] | undefined;
138
168
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;GAGG;AACH,eAAO,MAAM,YAAY;IACvB,wBAAwB;;;;;;;;;;;IAUxB,8BAA8B;;;;;;;;;;;;;;IAW9B,0BAA0B;;;;;;;;;;;IAU1B,sBAAsB;;;;;;;;;;;;;;IAWtB,sBAAsB;;;;;;;;;;;IAUtB,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EASrB,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;GAGG;AACH,eAAO,MAAM,YAAY;IACvB,wBAAwB;;;;;;;;;;;;;;IAWxB,8BAA8B;;;;;;;;;;;;;;;;;IAY9B,0BAA0B;;;;;;;;;;;;;;IAW1B,sBAAsB;;;;;;;;;;;;;;;;;IAYtB,sBAAsB;;;;;;;;;;;;;;IAWtB,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAUrB,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC"}
package/dist/schema.js CHANGED
@@ -13,6 +13,7 @@ export const configSchema = z.object({
13
13
  textReplacements: z
14
14
  .array(z.object({
15
15
  anchorId: z.string(),
16
+ summary: z.string(),
16
17
  text: z.string(),
17
18
  }))
18
19
  .optional(),
@@ -20,6 +21,7 @@ export const configSchema = z.object({
20
21
  attributeChanges: z
21
22
  .array(z.object({
22
23
  anchorId: z.string(),
24
+ summary: z.string(),
23
25
  attr: z.string(),
24
26
  value: z.string(),
25
27
  }))
@@ -28,6 +30,7 @@ export const configSchema = z.object({
28
30
  styleChanges: z
29
31
  .array(z.object({
30
32
  anchorId: z.string(),
33
+ summary: z.string(),
31
34
  styles: z.record(z.string()),
32
35
  }))
33
36
  .optional(),
@@ -35,6 +38,7 @@ export const configSchema = z.object({
35
38
  htmlInsertions: z
36
39
  .array(z.object({
37
40
  anchorId: z.string(),
41
+ summary: z.string(),
38
42
  html: z.string(),
39
43
  position: z.enum(['before', 'after', 'prepend', 'append', 'replace']),
40
44
  }))
@@ -43,6 +47,7 @@ export const configSchema = z.object({
43
47
  classAdditions: z
44
48
  .array(z.object({
45
49
  anchorId: z.string(),
50
+ summary: z.string(),
46
51
  className: z.string(),
47
52
  }))
48
53
  .optional(),
@@ -50,6 +55,7 @@ export const configSchema = z.object({
50
55
  classRemovals: z
51
56
  .array(z.object({
52
57
  anchorId: z.string(),
58
+ summary: z.string(),
53
59
  className: z.string(),
54
60
  }))
55
61
  .optional(),
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Human-readable summary generation for content config changes.
3
+ *
4
+ * Pure functions — no DOM access, just string formatting from config data.
5
+ */
6
+ import type { ContentConfig } from './schema';
7
+ /**
8
+ * Convert a CSS selector into a human-friendly element description.
9
+ */
10
+ export declare function describeSelector(selector: string): string;
11
+ /**
12
+ * Generate a human-readable one-liner for a content config change.
13
+ */
14
+ export declare function summarizeContentChange(type: keyof ContentConfig, item: Record<string, unknown>): string;
15
+ //# sourceMappingURL=summarize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summarize.d.ts","sourceRoot":"","sources":["../src/summarize.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAI9C;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAwBzD;AAYD;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,aAAa,EACzB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,MAAM,CAiCR"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Human-readable summary generation for content config changes.
3
+ *
4
+ * Pure functions — no DOM access, just string formatting from config data.
5
+ */
6
+ const MAX_TEXT_LEN = 40;
7
+ /**
8
+ * Convert a CSS selector into a human-friendly element description.
9
+ */
10
+ export function describeSelector(selector) {
11
+ if (!selector)
12
+ return '(no target)';
13
+ // ID selector: strip # and common prefixes
14
+ if (selector.startsWith('#')) {
15
+ let name = selector.slice(1);
16
+ const prefixes = ['hero-', 'main-', 'page-', 'app-', 'section-'];
17
+ for (const prefix of prefixes) {
18
+ if (name.startsWith(prefix)) {
19
+ name = name.slice(prefix.length);
20
+ break;
21
+ }
22
+ }
23
+ return truncate(name, 50);
24
+ }
25
+ // data-testid selector
26
+ const testIdMatch = selector.match(/\[data-testid="([^"]+)"\]/);
27
+ if (testIdMatch) {
28
+ return `${testIdMatch[1]} element`;
29
+ }
30
+ // Class selector or complex selector: keep as-is
31
+ return truncate(selector, 50);
32
+ }
33
+ function truncate(text, max) {
34
+ if (text.length <= max)
35
+ return text;
36
+ return `${text.slice(0, max)}...`;
37
+ }
38
+ function truncateQuoted(text, max) {
39
+ if (text.length <= max)
40
+ return `"${text}"`;
41
+ return `"${text.slice(0, max)}..."`;
42
+ }
43
+ /**
44
+ * Generate a human-readable one-liner for a content config change.
45
+ */
46
+ export function summarizeContentChange(type, item) {
47
+ const desc = describeSelector(item.anchorId || '');
48
+ switch (type) {
49
+ case 'textReplacements': {
50
+ const text = item.text || '';
51
+ return `Change ${desc} to ${truncateQuoted(text, MAX_TEXT_LEN)}`;
52
+ }
53
+ case 'attributeChanges': {
54
+ const attr = item.attr || '';
55
+ const value = item.value || '';
56
+ return `Set ${desc} ${attr} to ${truncateQuoted(value, MAX_TEXT_LEN)}`;
57
+ }
58
+ case 'styleChanges': {
59
+ const styles = item.styles || {};
60
+ const count = Object.keys(styles).length;
61
+ return `Restyle ${desc} (${count} ${count === 1 ? 'property' : 'properties'})`;
62
+ }
63
+ case 'htmlInsertions': {
64
+ const position = item.position || 'append';
65
+ return `Insert HTML ${position} ${desc}`;
66
+ }
67
+ case 'classAdditions': {
68
+ const className = item.className || '';
69
+ return `Add class "${className}" to ${desc}`;
70
+ }
71
+ case 'classRemovals': {
72
+ const className = item.className || '';
73
+ return `Remove class "${className}" from ${desc}`;
74
+ }
75
+ default:
76
+ return `Unknown change on ${desc}`;
77
+ }
78
+ }
package/dist/types.d.ts CHANGED
@@ -12,6 +12,22 @@ export interface EditorPanelProps {
12
12
  navigateHome: () => Promise<boolean>;
13
13
  save: () => Promise<void>;
14
14
  publish: (captureScreenshot?: boolean) => Promise<void>;
15
+ /** Navigate the target page to a different route (preserves editor params). */
16
+ navigateTo: (route: string) => Promise<void>;
17
+ /** Show a persistent blue highlight on the element matching this selector. */
18
+ highlightElement: (selector: string) => void;
19
+ /** Remove the persistent element highlight. */
20
+ clearHighlight: () => void;
21
+ /** Get the current page route (pathname). */
22
+ getCurrentRoute: () => string;
23
+ /** Push a temporary config to the live page preview without saving to state. */
24
+ previewConfig: (config: Record<string, unknown>) => void;
25
+ /** Flat action index to open in edit mode (from accordion navigation). */
26
+ initialEditKey?: string;
27
+ /** Open the editor in create mode. */
28
+ initialCreate?: boolean;
29
+ /** Clear the initial navigation state (call after consuming). */
30
+ clearInitialState?: () => void;
15
31
  };
16
32
  platformClient?: unknown;
17
33
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACpD,MAAM,EAAE;QACN,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;QACnC,YAAY,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;QACrC,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;QAC1B,OAAO,EAAE,CAAC,iBAAiB,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KACzD,CAAC;IACF,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAMD,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEnF,UAAU,UAAU;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAiB,SAAQ,UAAU;IAClD,IAAI,EAAE,oBAAoB,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,cAAc,CAAC;CAC1B;AAED,MAAM,WAAW,aAAc,SAAQ,UAAU;IAC/C,IAAI,EAAE,iBAAiB,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAc,SAAQ,UAAU;IAC/C,IAAI,EAAE,iBAAiB,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAe,SAAQ,UAAU;IAChD,IAAI,EAAE,kBAAkB,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAkB,SAAQ,UAAU;IACnD,IAAI,EAAE,qBAAqB,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAe,SAAQ,UAAU;IAChD,IAAI,EAAE,kBAAkB,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAMD,MAAM,MAAM,eAAe,GAAG,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AACzD,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAExF,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,eAAe,CAAC;IACzB,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,WAAW,CAAC;IACzB,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,WAAW,GAAG,IAAI,CAAC;IACxD,UAAU,EAAE,MAAM,MAAM,CAAC;IACzB,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACtE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,eAAe,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@syntrologie/adapt-content",
3
- "version": "0.0.0-semantically-released",
3
+ "version": "1.0.0",
4
4
  "description": "Adaptive Content app - DOM manipulation actions for text, attributes, and styles",
5
5
  "license": "Proprietary",
6
6
  "private": false,
@@ -33,7 +33,9 @@
33
33
  ],
34
34
  "scripts": {
35
35
  "build": "tsc",
36
- "clean": "rm -rf dist"
36
+ "clean": "rm -rf dist",
37
+ "test": "vitest run",
38
+ "test:watch": "vitest"
37
39
  },
38
40
  "peerDependencies": {
39
41
  "@syntrologie/runtime-sdk": "^2.0.0",
@@ -42,9 +44,15 @@
42
44
  "zod": "^3.0.0"
43
45
  },
44
46
  "devDependencies": {
45
- "@floating-ui/dom": "^1.6.0",
46
- "@types/react": "^18.0.0",
47
- "typescript": "^5.0.0",
48
- "zod": "^3.25.0"
47
+ "@floating-ui/dom": "^1.7.5",
48
+ "@testing-library/react": "^16.3.2",
49
+ "@types/react": "^19.1.0",
50
+ "@types/react-dom": "^19.2.3",
51
+ "jsdom": "^25.0.1",
52
+ "react": "^19.2.4",
53
+ "react-dom": "^19.2.4",
54
+ "typescript": "^5.7.3",
55
+ "vitest": "^2.1.9",
56
+ "zod": "^3.25.76"
49
57
  }
50
58
  }