astro-tractstack 2.0.18 → 2.0.20

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 (58) hide show
  1. package/dist/index.js +6 -32
  2. package/package.json +1 -1
  3. package/templates/src/components/codehooks/BunnyVideoSetup.tsx +1 -4
  4. package/templates/src/components/codehooks/FeaturedArticleSetup.tsx +0 -4
  5. package/templates/src/components/codehooks/ListContentSetup.tsx +1 -8
  6. package/templates/src/components/codehooks/ProductCardSetup.tsx +0 -2
  7. package/templates/src/components/codehooks/ProductGridSetup.tsx +0 -2
  8. package/templates/src/components/compositor/Compositor.tsx +3 -6
  9. package/templates/src/components/compositor/Node.tsx +13 -32
  10. package/templates/src/components/compositor/NodeWithGuid.tsx +49 -5
  11. package/templates/src/components/compositor/nodes/Pane.tsx +4 -21
  12. package/templates/src/components/compositor/nodes/Pane_DesignLibrary.tsx +27 -7
  13. package/templates/src/components/compositor/nodes/tagElements/NodeBasicTag.tsx +3 -1
  14. package/templates/src/components/compositor/preview/OgImagePreview.tsx +0 -5
  15. package/templates/src/components/compositor/preview/PaneSnapshotGenerator.tsx +5 -6
  16. package/templates/src/components/compositor/preview/PanesPreviewGenerator.tsx +1 -0
  17. package/templates/src/components/edit/PanelSwitch.tsx +3 -24
  18. package/templates/src/components/edit/SettingsPanel.tsx +0 -1
  19. package/templates/src/components/edit/ToolMode.tsx +6 -14
  20. package/templates/src/components/edit/pane/AddPanePanel.tsx +45 -25
  21. package/templates/src/components/edit/pane/AddPanePanel_new.tsx +277 -70
  22. package/templates/src/components/edit/pane/AddPanePanel_paste.tsx +111 -0
  23. package/templates/src/components/edit/pane/RestylePaneModal.tsx +7 -14
  24. package/templates/src/components/edit/pane/steps/AiDesignStep.tsx +0 -5
  25. package/templates/src/components/edit/pane/steps/DesignLibraryStep.tsx +4 -11
  26. package/templates/src/components/edit/panels/StyleBreakPanel.tsx +1 -3
  27. package/templates/src/components/edit/panels/StyleElementPanel_update.tsx +0 -6
  28. package/templates/src/components/edit/panels/StyleImagePanel.tsx +0 -1
  29. package/templates/src/components/edit/panels/StyleImagePanel_update.tsx +0 -3
  30. package/templates/src/components/edit/panels/StyleLiElementPanel_update.tsx +0 -4
  31. package/templates/src/components/edit/panels/StyleLinkPanel_config.tsx +8 -5
  32. package/templates/src/components/edit/panels/StyleLinkPanel_update.tsx +1 -2
  33. package/templates/src/components/edit/panels/StyleParentPanel.tsx +1 -3
  34. package/templates/src/components/edit/panels/StyleParentPanel_update.tsx +2 -5
  35. package/templates/src/components/edit/panels/StyleWidgetPanel_config.tsx +2 -8
  36. package/templates/src/components/edit/panels/StyleWidgetPanel_update.tsx +0 -4
  37. package/templates/src/components/edit/state/SaveToLibraryModal.tsx +27 -16
  38. package/templates/src/components/edit/storyfragment/StoryFragmentConfigPanel.tsx +9 -26
  39. package/templates/src/components/edit/storyfragment/StoryFragmentPanel_og.tsx +7 -16
  40. package/templates/src/components/edit/storyfragment/StoryFragmentPanel_slug.tsx +5 -6
  41. package/templates/src/components/edit/widgets/InteractiveDisclosureWidget.tsx +0 -5
  42. package/templates/src/components/fields/BackgroundImageWrapper.tsx +1 -7
  43. package/templates/src/components/fields/ColorPickerCombo.tsx +8 -12
  44. package/templates/src/components/fields/ViewportComboBox.tsx +4 -6
  45. package/templates/src/constants/prompts.json +22 -1
  46. package/templates/src/stores/nodes.ts +297 -222
  47. package/templates/src/stores/storykeep.ts +3 -3
  48. package/templates/src/types/compositorTypes.ts +21 -1
  49. package/templates/src/types/tractstack.ts +1 -0
  50. package/templates/src/utils/compositor/TemplatePanes.ts +0 -76
  51. package/templates/src/utils/compositor/aiPaneParser.ts +265 -83
  52. package/templates/src/utils/compositor/designLibraryHelper.ts +252 -26
  53. package/templates/src/utils/helpers.ts +5 -4
  54. package/utils/inject-files.ts +6 -32
  55. package/templates/src/components/compositor/preview/VisualBreakPreview.tsx +0 -154
  56. package/templates/src/components/edit/pane/PageGen_preview.tsx +0 -511
  57. package/templates/src/utils/compositor/processMarkdown.ts +0 -445
  58. package/templates/src/utils/compositor/templateMarkdownStyles.ts +0 -1273
@@ -1,6 +1,6 @@
1
1
  import { useEffect, useState } from 'react';
2
2
  import * as htmlToImage from 'html-to-image';
3
- import type { BrandConfig } from '@/types/tractstack';
3
+ import { brandConfigStore } from '@/stores/storykeep';
4
4
 
5
5
  export type SnapshotData = {
6
6
  imageData: string;
@@ -12,7 +12,6 @@ export interface PaneSnapshotGeneratorProps {
12
12
  htmlString: string;
13
13
  onComplete: (id: string, data: SnapshotData) => void;
14
14
  onError?: (id: string, error: string) => void;
15
- config?: BrandConfig;
16
15
  outputWidth?: number;
17
16
  }
18
17
 
@@ -33,7 +32,6 @@ export const PaneSnapshotGenerator = ({
33
32
  htmlString,
34
33
  onComplete,
35
34
  onError,
36
- config,
37
35
  outputWidth = 800,
38
36
  }: PaneSnapshotGeneratorProps) => {
39
37
  const [isGenerating, setIsGenerating] = useState(false);
@@ -80,7 +78,8 @@ export const PaneSnapshotGenerator = ({
80
78
  const customCssUrl = `${cssBasePath}/custom.css`;
81
79
  const storykeepCssUrl = `${cssBasePath}/storykeep.css`;
82
80
 
83
- const brandColors = config?.BRAND_COLOURS?.split(',') || [];
81
+ const brandColors =
82
+ brandConfigStore.get()?.BRAND_COLOURS?.split(',') || [];
84
83
 
85
84
  // Get all existing CSS links from current document
86
85
  const existingCssLinks = Array.from(
@@ -100,7 +99,7 @@ export const PaneSnapshotGenerator = ({
100
99
  <link rel="stylesheet" href="${storykeepCssUrl}">
101
100
  ${existingCssLinks.map((href) => `<link rel="stylesheet" href="${href}">`).join('\n')}
102
101
  ${
103
- config
102
+ brandColors
104
103
  ? `
105
104
  <style>
106
105
  :root {
@@ -203,7 +202,7 @@ export const PaneSnapshotGenerator = ({
203
202
  };
204
203
 
205
204
  generateSnapshot();
206
- }, [id, htmlString, isGenerating, onComplete, onError, config, outputWidth]);
205
+ }, [id, htmlString, isGenerating, onComplete, onError, outputWidth]);
207
206
 
208
207
  // Show spinner while generating
209
208
  if (isGenerating) {
@@ -62,6 +62,7 @@ export const PanesPreviewGenerator = ({
62
62
  request.ctx,
63
63
  actualPaneId
64
64
  );
65
+ console.log(previewPayload);
65
66
 
66
67
  previewPayloads.push(previewPayload);
67
68
  requestMap.set(previewPayload.id, request.id);
@@ -36,7 +36,6 @@ import StyleLiElementUpdatePanel from './panels/StyleLiElementPanel_update';
36
36
  import StyleLiElementRemovePanel from './panels/StyleLiElementPanel_remove';
37
37
  import StyleCodeHookPanel from './panels/StyleCodeHookPanel';
38
38
  import { getSettingsPanelTitle } from '@/utils/helpers';
39
- import type { BrandConfig } from '@/types/tractstack';
40
39
  import type {
41
40
  FlatNode,
42
41
  GridLayoutNode,
@@ -44,13 +43,11 @@ import type {
44
43
  } from '@/types/compositorTypes';
45
44
 
46
45
  interface SettingsPanelProps {
47
- config: BrandConfig;
48
46
  availableCodeHooks: string[];
49
47
  onTitleChange?: (title: string) => void;
50
48
  }
51
49
 
52
50
  const PanelSwitch = ({
53
- config,
54
51
  availableCodeHooks,
55
52
  onTitleChange,
56
53
  }: SettingsPanelProps) => {
@@ -101,13 +98,7 @@ const PanelSwitch = ({
101
98
  switch (signal.action) {
102
99
  case 'style-break':
103
100
  if (clickedNode && paneNode)
104
- return (
105
- <StyleBreakPanel
106
- config={config}
107
- node={clickedNode}
108
- parentNode={paneNode}
109
- />
110
- );
101
+ return <StyleBreakPanel node={clickedNode} parentNode={paneNode} />;
111
102
  break;
112
103
 
113
104
  case 'style-parent':
@@ -117,7 +108,6 @@ const PanelSwitch = ({
117
108
  node={markdownNode}
118
109
  parentNode={paneNode}
119
110
  layer={signal.layer || 0}
120
- config={config}
121
111
  />
122
112
  );
123
113
  else if (gridLayoutNode && paneNode)
@@ -126,7 +116,6 @@ const PanelSwitch = ({
126
116
  node={gridLayoutNode}
127
117
  parentNode={paneNode}
128
118
  layer={signal.layer || 0}
129
- config={config}
130
119
  />
131
120
  );
132
121
  break;
@@ -181,7 +170,6 @@ const PanelSwitch = ({
181
170
  node={clickedNode}
182
171
  layer={signal.layer || 0}
183
172
  className={signal.className}
184
- config={config}
185
173
  targetProperty={(signal as any).targetProperty}
186
174
  />
187
175
  );
@@ -215,7 +203,6 @@ const PanelSwitch = ({
215
203
  <StyleLinkUpdatePanel
216
204
  node={clickedNode}
217
205
  className={signal.className}
218
- config={config}
219
206
  />
220
207
  );
221
208
  break;
@@ -232,8 +219,7 @@ const PanelSwitch = ({
232
219
  break;
233
220
 
234
221
  case 'style-link-config':
235
- if (clickedNode)
236
- return <StyleLinkConfigPanel node={clickedNode} config={config} />;
222
+ if (clickedNode) return <StyleLinkConfigPanel node={clickedNode} />;
237
223
  break;
238
224
 
239
225
  case 'style-element':
@@ -280,7 +266,6 @@ const PanelSwitch = ({
280
266
  parentNode={styleContextNode}
281
267
  className={signal.className}
282
268
  onTitleChange={onTitleChange}
283
- config={config}
284
269
  />
285
270
  );
286
271
  break;
@@ -353,7 +338,6 @@ const PanelSwitch = ({
353
338
  parentNode={styleContextNode}
354
339
  className={signal.className}
355
340
  childId={signal.childId}
356
- config={config}
357
341
  />
358
342
  );
359
343
  break;
@@ -429,8 +413,7 @@ const PanelSwitch = ({
429
413
  }
430
414
 
431
415
  case 'style-code-config':
432
- if (clickedNode)
433
- return <StyleWidgetConfigPanel node={clickedNode} config={config} />;
416
+ if (clickedNode) return <StyleWidgetConfigPanel node={clickedNode} />;
434
417
  break;
435
418
 
436
419
  case 'style-code-add':
@@ -453,7 +436,6 @@ const PanelSwitch = ({
453
436
  node={clickedNode}
454
437
  parentNode={styleContextNode}
455
438
  className={signal.className}
456
- config={config}
457
439
  />
458
440
  );
459
441
  break;
@@ -467,7 +449,6 @@ const PanelSwitch = ({
467
449
  parentNode={styleContextNode}
468
450
  className={signal.className}
469
451
  childId={signal.childId}
470
- config={config}
471
452
  />
472
453
  );
473
454
  break;
@@ -541,7 +522,6 @@ const PanelSwitch = ({
541
522
  node={clickedNode}
542
523
  parentNode={styleContextNode}
543
524
  className={signal.className}
544
- config={config}
545
525
  />
546
526
  );
547
527
  break;
@@ -554,7 +534,6 @@ const PanelSwitch = ({
554
534
  parentNode={styleContextNode}
555
535
  className={signal.className}
556
536
  childId={signal.childId}
557
- config={config}
558
537
  />
559
538
  );
560
539
  break;
@@ -66,7 +66,6 @@ const SettingsPanel = ({ config, availableCodeHooks }: SettingsPanelProps) => {
66
66
  <div className="min-h-0 flex-1 space-y-4 overflow-y-auto p-1.5 pt-0 md:p-2.5 md:pt-0">
67
67
  <div className="rounded bg-gray-50 p-1.5 md:p-2.5">
68
68
  <PanelSwitch
69
- config={config}
70
69
  availableCodeHooks={availableCodeHooks}
71
70
  onTitleChange={setPanelTitle}
72
71
  />
@@ -52,6 +52,12 @@ const storykeepToolModes = [
52
52
  title: 'Design Library',
53
53
  description: 'Save pane to design library',
54
54
  },
55
+ {
56
+ key: 'debug' as const,
57
+ Icon: BugAntIcon,
58
+ title: 'Debug Mode',
59
+ description: 'Toggle node tree id reveal',
60
+ },
55
61
  ] as const;
56
62
 
57
63
  interface StoryKeepToolModeProps {
@@ -62,7 +68,6 @@ const StoryKeepToolMode = ({ isContext }: StoryKeepToolModeProps) => {
62
68
  const ctx = getCtx();
63
69
  const { value: toolModeVal } = useStore(ctx.toolModeValStore);
64
70
  const $selection = useStore(selectionStore);
65
- const showGuids = useStore(ctx.showGuids);
66
71
  const navRef = useRef<HTMLElement>(null);
67
72
 
68
73
  const hasTitle = useStore(ctx.hasTitle);
@@ -73,8 +78,6 @@ const StoryKeepToolMode = ({ isContext }: StoryKeepToolModeProps) => {
73
78
  const className =
74
79
  'w-8 h-8 py-1 rounded-xl bg-white text-myblue hover:bg-mygreen/20 hover:text-black hover:rotate-3 cursor-pointer transition-all';
75
80
  const classNameActive = 'w-8 h-8 py-1.5 rounded-md bg-myblue text-white';
76
- const classNameDebugActive =
77
- 'w-8 h-8 py-1.5 rounded-md bg-orange-500 text-white';
78
81
 
79
82
  const currentToolMode =
80
83
  storykeepToolModes.find((mode) => mode.key === toolModeVal) ??
@@ -86,11 +89,6 @@ const StoryKeepToolMode = ({ isContext }: StoryKeepToolModeProps) => {
86
89
  ctx.notifyNode('root');
87
90
  };
88
91
 
89
- const handleDebugToggle = () => {
90
- ctx.showGuids.set(!showGuids);
91
- ctx.notifyNode('root');
92
- };
93
-
94
92
  const handleStyleClick = () => {
95
93
  selectionStore.setKey('pendingAction', 'style');
96
94
  };
@@ -156,12 +154,6 @@ const StoryKeepToolMode = ({ isContext }: StoryKeepToolModeProps) => {
156
154
  )}
157
155
  </div>
158
156
  ))}
159
- <div title="Toggle debug node ids" key="debug">
160
- <BugAntIcon
161
- className={showGuids ? classNameDebugActive : className}
162
- onClick={handleDebugToggle}
163
- />
164
- </div>
165
157
  </div>
166
158
  )}
167
159
 
@@ -5,9 +5,9 @@ import AddPaneNewPanel from './AddPanePanel_new';
5
5
  import AddPaneBreakPanel from './AddPanePanel_break';
6
6
  import AddPaneReUsePanel from './AddPanePanel_reuse';
7
7
  import AddPaneCodeHookPanel from './AddPanePanel_codehook';
8
+ import AddPanePanel_paste from './AddPanePanel_paste';
8
9
  import { NodesContext, ROOT_NODE_NAME, getCtx } from '@/stores/nodes';
9
10
  import { PaneAddMode } from '@/types/compositorTypes';
10
- import type { BrandConfig } from '@/types/tractstack';
11
11
 
12
12
  interface AddPanePanelProps {
13
13
  nodeId: string;
@@ -15,7 +15,6 @@ interface AddPanePanelProps {
15
15
  ctx?: NodesContext;
16
16
  isStoryFragment?: boolean;
17
17
  isContextPane?: boolean;
18
- config?: BrandConfig;
19
18
  isSandboxMode?: boolean;
20
19
  }
21
20
 
@@ -25,16 +24,14 @@ const AddPanePanel = ({
25
24
  ctx,
26
25
  isStoryFragment = false,
27
26
  isContextPane = false,
28
- config,
29
27
  isSandboxMode = false,
30
28
  }: AddPanePanelProps) => {
31
29
  const [reset, setReset] = useState(false);
32
- const lookup = first ? `${nodeId}-0` : nodeId;
30
+ const [isExpanded, setIsExpanded] = useState(false);
33
31
 
34
- // Always get a valid context, either from props or the global getter
32
+ const lookup = first ? `${nodeId}-0` : nodeId;
35
33
  const nodesCtx = ctx || getCtx();
36
34
 
37
- // Use the guaranteed context to subscribe to stores
38
35
  const activePaneMode = useStore(nodesCtx.activePaneMode);
39
36
  const hasPanes = useStore(nodesCtx.hasPanes);
40
37
  const isTemplate = useStore(nodesCtx.isTemplate);
@@ -51,12 +48,14 @@ const AddPanePanel = ({
51
48
 
52
49
  const setMode = (newMode: PaneAddMode, reset?: boolean) => {
53
50
  setReset(true);
54
- nodesCtx.setPanelMode(lookup, 'add', newMode); // No longer needs optional chaining
51
+ nodesCtx.setPanelMode(lookup, 'add', newMode);
52
+ if (newMode === PaneAddMode.DEFAULT) {
53
+ setIsExpanded(false);
54
+ }
55
55
  if (reset) nodesCtx.notifyNode(ROOT_NODE_NAME);
56
56
  settingsPanelStore.set(null);
57
57
  };
58
58
 
59
- // Always render a stable container div for the intersection observer
60
59
  return (
61
60
  <div className="add-pane-panel-wrapper border-mydarkgrey border-b-2 border-t-2 border-dotted">
62
61
  {mode === PaneAddMode.NEW || (!hasPanes && first && !reset) ? (
@@ -67,7 +66,6 @@ const AddPanePanel = ({
67
66
  ctx={nodesCtx}
68
67
  isStoryFragment={isStoryFragment}
69
68
  isContextPane={isContextPane}
70
- config={config!}
71
69
  isSandboxMode={isSandboxMode}
72
70
  />
73
71
  ) : mode === PaneAddMode.BREAK && !isContextPane ? (
@@ -79,47 +77,60 @@ const AddPanePanel = ({
79
77
  isStoryFragment={isStoryFragment}
80
78
  />
81
79
  ) : mode === PaneAddMode.REUSE && !isContextPane ? (
82
- <AddPaneReUsePanel
80
+ <AddPaneReUsePanel nodeId={nodeId} first={first} setMode={setMode} />
81
+ ) : mode === PaneAddMode.CODEHOOK ? (
82
+ <AddPaneCodeHookPanel
83
83
  nodeId={nodeId}
84
84
  first={first}
85
85
  setMode={setMode}
86
- //ctx={nodesCtx}
86
+ isStoryFragment={isStoryFragment}
87
+ isContextPane={isContextPane}
87
88
  />
88
- ) : mode === PaneAddMode.CODEHOOK ? (
89
- <AddPaneCodeHookPanel
89
+ ) : mode === PaneAddMode.PASTE ? (
90
+ <AddPanePanel_paste
90
91
  nodeId={nodeId}
91
92
  first={first}
92
93
  setMode={setMode}
94
+ ctx={nodesCtx}
93
95
  isStoryFragment={isStoryFragment}
94
96
  isContextPane={isContextPane}
95
97
  />
96
- ) : (
98
+ ) : isExpanded ? (
97
99
  <div className="border-mylightgrey border-t border-dotted">
98
- <div className="group flex w-full gap-1 px-1.5 pb-0.5 pt-1.5">
99
- <div className="rounded-md bg-gray-200 px-2 py-1 text-sm text-gray-800">
100
- Insert Pane Here
101
- </div>
102
- <div className={`flex gap-1 transition-opacity`}>
100
+ <div className="group flex w-full flex-wrap items-center gap-2 px-1.5 pb-0.5 pt-1.5">
101
+ <button
102
+ onClick={() => setIsExpanded(false)}
103
+ className="rounded-md bg-gray-200 px-2 py-1 text-sm font-bold text-gray-800"
104
+ >
105
+ &lt; Cancel
106
+ </button>
107
+ <div className={`flex flex-wrap gap-1 transition-opacity`}>
103
108
  <button
104
109
  onClick={() => setMode(PaneAddMode.NEW)}
105
- className="rounded bg-white px-2 py-1 text-sm text-cyan-700 shadow-sm transition-colors hover:bg-cyan-700 hover:text-white focus:bg-cyan-700 focus:text-white"
110
+ className="rounded bg-white px-2 py-1 text-sm text-cyan-700 shadow-sm transition-colors hover:bg-cyan-700 hover:text-white"
106
111
  >
107
112
  + Design New
108
113
  </button>
114
+ <button
115
+ onClick={() => setMode(PaneAddMode.PASTE)}
116
+ className="rounded bg-white px-2 py-1 text-sm text-cyan-700 shadow-sm transition-colors hover:bg-cyan-700 hover:text-white"
117
+ >
118
+ + Paste Pane
119
+ </button>
109
120
  {!isContextPane && (
110
121
  <>
111
122
  <button
112
123
  onClick={() => setMode(PaneAddMode.BREAK)}
113
- className="rounded bg-white px-2 py-1 text-sm text-cyan-700 shadow-sm transition-colors hover:bg-cyan-700 hover:text-white focus:bg-cyan-700 focus:text-white"
124
+ className="rounded bg-white px-2 py-1 text-sm text-cyan-700 shadow-sm transition-colors hover:bg-cyan-700 hover:text-white"
114
125
  >
115
126
  + Visual Break
116
127
  </button>
117
128
  {!isTemplate && (
118
129
  <button
119
130
  onClick={() => setMode(PaneAddMode.REUSE)}
120
- className="rounded bg-white px-2 py-1 text-sm text-cyan-700 shadow-sm transition-colors hover:bg-cyan-700 hover:text-white focus:bg-cyan-700 focus:text-white"
131
+ className="rounded bg-white px-2 py-1 text-sm text-cyan-700 shadow-sm transition-colors hover:bg-cyan-700 hover:text-white"
121
132
  >
122
- + Re-use existing pane
133
+ + Re-use Pane
123
134
  </button>
124
135
  )}
125
136
  </>
@@ -127,14 +138,23 @@ const AddPanePanel = ({
127
138
  {!isTemplate && (
128
139
  <button
129
140
  onClick={() => setMode(PaneAddMode.CODEHOOK)}
130
- className="rounded bg-white px-2 py-1 text-sm text-cyan-700 shadow-sm transition-colors hover:bg-cyan-700 hover:text-white focus:bg-cyan-700 focus:text-white"
141
+ className="rounded bg-white px-2 py-1 text-sm text-cyan-700 shadow-sm transition-colors hover:bg-cyan-700 hover:text-white"
131
142
  >
132
- + Custom Code Hook
143
+ + Code Hook
133
144
  </button>
134
145
  )}
135
146
  </div>
136
147
  </div>
137
148
  </div>
149
+ ) : (
150
+ <div className="border-mylightgrey border-t border-dotted p-2">
151
+ <button
152
+ onClick={() => setIsExpanded(true)}
153
+ className="text-sm text-gray-500 underline decoration-dotted underline-offset-4 transition-colors hover:text-cyan-700"
154
+ >
155
+ Insert Pane Here
156
+ </button>
157
+ </div>
138
158
  )}
139
159
  </div>
140
160
  );