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,5 +1,4 @@
1
1
  import ColorPickerCombo from '@/components/fields/ColorPickerCombo';
2
- import type { BrandConfig } from '@/types/tractstack';
3
2
 
4
3
  export interface AiDesignConfig {
5
4
  harmony: string;
@@ -10,7 +9,6 @@ export interface AiDesignConfig {
10
9
  }
11
10
 
12
11
  interface AiDesignStepProps {
13
- config: BrandConfig;
14
12
  designConfig: AiDesignConfig;
15
13
  onDesignConfigChange: (newConfig: AiDesignConfig) => void;
16
14
  }
@@ -24,7 +22,6 @@ const harmonyOptions = [
24
22
  const themeOptions = ['Light', 'Dark', 'Bright', 'Muted', 'Pastel', 'Earthy'];
25
23
 
26
24
  export const AiDesignStep = ({
27
- config,
28
25
  designConfig,
29
26
  onDesignConfigChange,
30
27
  }: AiDesignStepProps) => {
@@ -71,7 +68,6 @@ export const AiDesignStep = ({
71
68
  <div>
72
69
  <ColorPickerCombo
73
70
  title="Base Color (Optional)"
74
- config={config}
75
71
  defaultColor={designConfig.baseColor}
76
72
  onColorChange={(color) => updateField('baseColor', color)}
77
73
  allowNull={true}
@@ -80,7 +76,6 @@ export const AiDesignStep = ({
80
76
  <div>
81
77
  <ColorPickerCombo
82
78
  title="Accent Color (Optional)"
83
- config={config}
84
79
  defaultColor={designConfig.accentColor}
85
80
  onColorChange={(color) => updateField('accentColor', color)}
86
81
  allowNull={true}
@@ -15,11 +15,12 @@ import { viewportKeyStore } from '@/stores/storykeep';
15
15
  import { createEmptyStorykeep } from '@/utils/compositor/nodesHelper';
16
16
  import { convertStorageToLiveTemplate } from '@/utils/compositor/designLibraryHelper';
17
17
  import type { StoragePane } from '@/types/compositorTypes';
18
- import type { BrandConfig, DesignLibraryEntry } from '@/types/tractstack';
18
+ import type { DesignLibraryEntry } from '@/types/tractstack';
19
19
  import {
20
20
  PaneSnapshotGenerator,
21
21
  type SnapshotData,
22
22
  } from '@/components/compositor/preview/PaneSnapshotGenerator';
23
+ import { brandConfigStore } from '@/stores/storykeep';
23
24
  import {
24
25
  PanesPreviewGenerator,
25
26
  type PanePreviewRequest,
@@ -32,7 +33,6 @@ const PAGE_SIZE = 12;
32
33
  // --- Sub-component for rendering a single preview item ---
33
34
  interface TemplatePreviewItemProps {
34
35
  storageTemplate: StoragePane;
35
- config: BrandConfig;
36
36
  onClick: () => void;
37
37
  title: string;
38
38
  category: string;
@@ -40,7 +40,6 @@ interface TemplatePreviewItemProps {
40
40
 
41
41
  const TemplatePreviewItem = ({
42
42
  storageTemplate,
43
- config,
44
43
  onClick,
45
44
  title,
46
45
  category,
@@ -113,7 +112,6 @@ const TemplatePreviewItem = ({
113
112
  id={liveTemplate.id}
114
113
  htmlString={previewState.htmlFragment}
115
114
  outputWidth={800}
116
- config={config}
117
115
  onComplete={(_id, data) => handleSnapshotComplete(data)}
118
116
  onError={(_id, err) =>
119
117
  setPreviewState((prev) =>
@@ -150,15 +148,11 @@ const TemplatePreviewItem = ({
150
148
 
151
149
  // --- Main component ---
152
150
  interface DesignLibraryStepProps {
153
- config: BrandConfig;
154
151
  onSelect: (entry: DesignLibraryEntry) => void;
155
152
  }
156
153
 
157
- export const DesignLibraryStep = ({
158
- config,
159
- onSelect,
160
- }: DesignLibraryStepProps) => {
161
- const designLibrary = config?.DESIGN_LIBRARY || [];
154
+ export const DesignLibraryStep = ({ onSelect }: DesignLibraryStepProps) => {
155
+ const designLibrary = brandConfigStore.get()?.DESIGN_LIBRARY || [];
162
156
  const viewport = useStore(viewportKeyStore).value;
163
157
 
164
158
  const [selectedCategory, setSelectedCategory] = useState<string>('all');
@@ -321,7 +315,6 @@ export const DesignLibraryStep = ({
321
315
  <TemplatePreviewItem
322
316
  key={entry.title}
323
317
  storageTemplate={entry.template}
324
- config={config}
325
318
  onClick={() => onSelect(entry)}
326
319
  title={entry.title}
327
320
  category={entry.category}
@@ -34,7 +34,7 @@ interface BreakNode extends FlatNode {
34
34
  bgColor: string;
35
35
  }
36
36
 
37
- const StyleBreakPanel = ({ node, parentNode, config }: BasePanelProps) => {
37
+ const StyleBreakPanel = ({ node, parentNode }: BasePanelProps) => {
38
38
  if (!node || !isBreakNode(node) || !parentNode || !isPaneNode(parentNode)) {
39
39
  return null;
40
40
  }
@@ -161,7 +161,6 @@ const StyleBreakPanel = ({ node, parentNode, config }: BasePanelProps) => {
161
161
  onColorChange={(color: string) =>
162
162
  setSettings((prev) => ({ ...prev, svgFill: color }))
163
163
  }
164
- config={config!}
165
164
  />
166
165
  <ColorPickerCombo
167
166
  title="Background Color"
@@ -169,7 +168,6 @@ const StyleBreakPanel = ({ node, parentNode, config }: BasePanelProps) => {
169
168
  onColorChange={(color: string) =>
170
169
  setSettings((prev) => ({ ...prev, bgColor: color }))
171
170
  }
172
- config={config!}
173
171
  allowNull={true}
174
172
  />
175
173
  </div>
@@ -19,14 +19,12 @@ import type {
19
19
  MarkdownPaneFragmentNode,
20
20
  GridLayoutNode,
21
21
  } from '@/types/compositorTypes';
22
- import type { BrandConfig } from '@/types/tractstack';
23
22
 
24
23
  export interface StyleElementUpdatePanelProps {
25
24
  node: FlatNode;
26
25
  parentNode: MarkdownPaneFragmentNode | GridLayoutNode;
27
26
  className: string;
28
27
  onTitleChange?: (title: string) => void;
29
- config?: BrandConfig | null;
30
28
  }
31
29
 
32
30
  const StyleElementUpdatePanel = ({
@@ -34,7 +32,6 @@ const StyleElementUpdatePanel = ({
34
32
  parentNode,
35
33
  className,
36
34
  onTitleChange,
37
- config,
38
35
  }: StyleElementUpdatePanelProps) => {
39
36
  if (
40
37
  !node ||
@@ -309,7 +306,6 @@ const StyleElementUpdatePanel = ({
309
306
  onFinalChange={handleFinalChange}
310
307
  values={values}
311
308
  viewport="mobile"
312
- config={config!}
313
309
  isInferred={false}
314
310
  />
315
311
  <ViewportComboBox
@@ -318,7 +314,6 @@ const StyleElementUpdatePanel = ({
318
314
  values={values}
319
315
  viewport="tablet"
320
316
  isInferred={!isOverridden && tabletValue === mobileValue}
321
- config={config!}
322
317
  />
323
318
  <ViewportComboBox
324
319
  value={desktopValue}
@@ -326,7 +321,6 @@ const StyleElementUpdatePanel = ({
326
321
  values={values}
327
322
  viewport="desktop"
328
323
  isInferred={!isOverridden && desktopValue === tabletValue}
329
- config={config!}
330
324
  />
331
325
  </div>
332
326
  </div>
@@ -28,7 +28,6 @@ const StyleImagePanel = ({
28
28
  outerContainerNode,
29
29
  parentNode,
30
30
  }: StyleImagePanelProps) => {
31
- console.log(`StyleImagePanel`, parentNode, node);
32
31
  const [altDescription, setAltDescription] = useState(node.alt || '');
33
32
 
34
33
  const imgDefaultClasses = parentNode.defaultClasses?.[node.tagName];
@@ -288,7 +288,6 @@ const StyleImageUpdatePanel = ({
288
288
  onFinalChange={handleFinalChange}
289
289
  values={values}
290
290
  viewport="mobile"
291
- config={config!}
292
291
  isInferred={false}
293
292
  />
294
293
  <ViewportComboBox
@@ -297,7 +296,6 @@ const StyleImageUpdatePanel = ({
297
296
  values={values}
298
297
  viewport="tablet"
299
298
  isInferred={!isOverridden && tabletValue === mobileValue}
300
- config={config!}
301
299
  />
302
300
  <ViewportComboBox
303
301
  value={desktopValue}
@@ -305,7 +303,6 @@ const StyleImageUpdatePanel = ({
305
303
  values={values}
306
304
  viewport="desktop"
307
305
  isInferred={!isOverridden && desktopValue === tabletValue}
308
- config={config!}
309
306
  />
310
307
  </div>
311
308
  </div>
@@ -18,7 +18,6 @@ const StyleLiElementUpdatePanel = ({
18
18
  node,
19
19
  parentNode,
20
20
  className,
21
- config,
22
21
  childId,
23
22
  }: BasePanelProps) => {
24
23
  if (
@@ -289,7 +288,6 @@ const StyleLiElementUpdatePanel = ({
289
288
  onFinalChange={handleFinalChange}
290
289
  values={values}
291
290
  viewport="mobile"
292
- config={config!}
293
291
  isInferred={false}
294
292
  />
295
293
  <ViewportComboBox
@@ -298,7 +296,6 @@ const StyleLiElementUpdatePanel = ({
298
296
  values={values}
299
297
  viewport="tablet"
300
298
  isInferred={!isOverridden && tabletValue === mobileValue}
301
- config={config!}
302
299
  />
303
300
  <ViewportComboBox
304
301
  value={desktopValue}
@@ -306,7 +303,6 @@ const StyleLiElementUpdatePanel = ({
306
303
  values={values}
307
304
  viewport="desktop"
308
305
  isInferred={!isOverridden && desktopValue === tabletValue}
309
- config={config!}
310
306
  />
311
307
  </div>
312
308
  </div>
@@ -4,19 +4,22 @@ import { getCtx } from '@/stores/nodes';
4
4
  import { cloneDeep } from '@/utils/helpers';
5
5
  import { lispLexer } from '@/utils/actions/lispLexer';
6
6
  import { preParseAction } from '@/utils/actions/preParse_Action';
7
- import { preParseBunny } from '@/utils/actions/preParse_Bunny';
8
7
  import ActionBuilderField from '@/components/form/ActionBuilderField';
8
+ import { brandConfigStore } from '@/stores/storykeep';
9
9
  import { GOTO_TARGETS } from '@/constants';
10
- import type { BrandConfig } from '@/types/tractstack';
11
10
  import type { FlatNode, LispToken } from '@/types/compositorTypes';
12
11
 
13
12
  interface StyleLinkConfigPanelProps {
14
13
  node: FlatNode;
15
- config: BrandConfig;
16
14
  }
17
15
 
18
- const StyleLinkConfigPanel = ({ node, config }: StyleLinkConfigPanelProps) => {
19
- if (!node?.tagName || (node.tagName !== 'a' && node.tagName !== 'button')) {
16
+ const StyleLinkConfigPanel = ({ node }: StyleLinkConfigPanelProps) => {
17
+ const config = brandConfigStore.get();
18
+ if (
19
+ !config ||
20
+ !node?.tagName ||
21
+ (node.tagName !== 'a' && node.tagName !== 'button')
22
+ ) {
20
23
  return null;
21
24
  }
22
25
 
@@ -7,7 +7,7 @@ import { tailwindClasses } from '@/utils/compositor/tailwindClasses';
7
7
  import ViewportComboBox from '@/components/fields/ViewportComboBox';
8
8
  import type { BasePanelProps, FlatNode } from '@/types/compositorTypes';
9
9
 
10
- const StyleLinkUpdatePanel = ({ node, className, config }: BasePanelProps) => {
10
+ const StyleLinkUpdatePanel = ({ node, className }: BasePanelProps) => {
11
11
  if (
12
12
  !node ||
13
13
  !className ||
@@ -99,7 +99,6 @@ const StyleLinkUpdatePanel = ({ node, className, config }: BasePanelProps) => {
99
99
  onFinalChange={(newValue) => handleFinalChange(newValue)}
100
100
  values={values}
101
101
  viewport="mobile"
102
- config={config!}
103
102
  isInferred={false}
104
103
  />
105
104
  </div>
@@ -53,7 +53,6 @@ const StyleParentPanel = ({
53
53
  node: initialNode,
54
54
  parentNode: paneNode,
55
55
  layer,
56
- config,
57
56
  }: ParentBasePanelProps) => {
58
57
  const [currentView, setCurrentView] = useState<PanelView>('summary');
59
58
  const [currentLayer, setCurrentLayer] = useState<number>(layer || 1);
@@ -322,7 +321,6 @@ const StyleParentPanel = ({
322
321
  title="Pane Background Color"
323
322
  defaultColor={paneNode.bgColour || ''}
324
323
  onColorChange={handleColorChange}
325
- config={config!}
326
324
  allowNull={true}
327
325
  />
328
326
  <div className="flex items-center justify-between border-t border-gray-200 pt-3">
@@ -599,7 +597,7 @@ const StyleParentPanel = ({
599
597
  const renderBackgroundImageVIew = () => (
600
598
  <div className="space-y-4">
601
599
  <BackButton />
602
- <BackgroundImageWrapper paneId={paneNode.id} config={config!} />
600
+ <BackgroundImageWrapper paneId={paneNode.id} />
603
601
  </div>
604
602
  );
605
603
 
@@ -1,5 +1,5 @@
1
1
  import { useState, useCallback, useMemo } from 'react';
2
- import { settingsPanelStore } from '@/stores/storykeep';
2
+ import { settingsPanelStore, brandConfigStore } from '@/stores/storykeep';
3
3
  import { getCtx } from '@/stores/nodes';
4
4
  import { tailwindClasses } from '@/utils/compositor/tailwindClasses';
5
5
  import { cloneDeep } from '@/utils/helpers';
@@ -32,10 +32,10 @@ const StyleParentPanelUpdate = ({
32
32
  layer,
33
33
  className,
34
34
  targetProperty,
35
- config,
36
35
  }: CustomPanelProps) => {
37
36
  const ctx = getCtx();
38
37
  const styleableNode = node as StyleableNode | null;
38
+ const config = brandConfigStore.get();
39
39
 
40
40
  if (
41
41
  !styleableNode ||
@@ -182,7 +182,6 @@ const StyleParentPanelUpdate = ({
182
182
  value={values.mobile}
183
183
  values={validTailwindValues}
184
184
  onFinalChange={handleUpdate}
185
- config={config}
186
185
  allowNegative={tailwindConfig.allowNegative}
187
186
  />
188
187
  <ViewportComboBox
@@ -190,7 +189,6 @@ const StyleParentPanelUpdate = ({
190
189
  value={values.tablet}
191
190
  values={validTailwindValues}
192
191
  onFinalChange={handleUpdate}
193
- config={config}
194
192
  allowNegative={tailwindConfig.allowNegative}
195
193
  />
196
194
  <ViewportComboBox
@@ -198,7 +196,6 @@ const StyleParentPanelUpdate = ({
198
196
  value={values.desktop}
199
197
  values={validTailwindValues}
200
198
  onFinalChange={handleUpdate}
201
- config={config}
202
199
  allowNegative={tailwindConfig.allowNegative}
203
200
  />
204
201
  </div>
@@ -13,14 +13,12 @@ import ToggleWidget from '@/components/edit/widgets/ToggleWidget';
13
13
  import YouTubeWidget from '@/components/edit/widgets/YouTubeWidget';
14
14
  import InteractiveDisclosureWidget from '@/components/edit/widgets/InteractiveDisclosureWidget';
15
15
  import type { FlatNode } from '@/types/compositorTypes';
16
- import type { BrandConfig } from '@/types/tractstack';
17
16
 
18
17
  interface StyleWidgetConfigPanelProps {
19
18
  node: FlatNode;
20
- config: BrandConfig;
21
19
  }
22
20
 
23
- function StyleWidgetConfigPanel({ node, config }: StyleWidgetConfigPanelProps) {
21
+ function StyleWidgetConfigPanel({ node }: StyleWidgetConfigPanelProps) {
24
22
  const [init, setInit] = useState(false);
25
23
 
26
24
  useEffect(() => {
@@ -97,11 +95,7 @@ function StyleWidgetConfigPanel({ node, config }: StyleWidgetConfigPanelProps) {
97
95
  toggle: () => <ToggleWidget node={node} onUpdate={handleParamUpdate} />,
98
96
  youtube: () => <YouTubeWidget node={node} onUpdate={handleParamUpdate} />,
99
97
  interactiveDisclosure: () => (
100
- <InteractiveDisclosureWidget
101
- node={node}
102
- onUpdate={handleParamUpdate}
103
- config={config}
104
- />
98
+ <InteractiveDisclosureWidget node={node} onUpdate={handleParamUpdate} />
105
99
  ),
106
100
  };
107
101
 
@@ -19,7 +19,6 @@ const StyleWidgetUpdatePanel = ({
19
19
  node,
20
20
  parentNode,
21
21
  className,
22
- config,
23
22
  childId,
24
23
  }: BasePanelProps) => {
25
24
  if (
@@ -285,7 +284,6 @@ const StyleWidgetUpdatePanel = ({
285
284
  onFinalChange={handleFinalChange}
286
285
  values={values}
287
286
  viewport="mobile"
288
- config={config!}
289
287
  isInferred={false}
290
288
  />
291
289
  <ViewportComboBox
@@ -294,7 +292,6 @@ const StyleWidgetUpdatePanel = ({
294
292
  values={values}
295
293
  viewport="tablet"
296
294
  isInferred={!isOverridden && tabletValue === mobileValue}
297
- config={config!}
298
295
  />
299
296
  <ViewportComboBox
300
297
  value={desktopValue}
@@ -302,7 +299,6 @@ const StyleWidgetUpdatePanel = ({
302
299
  values={values}
303
300
  viewport="desktop"
304
301
  isInferred={!isOverridden && desktopValue === tabletValue}
305
- config={config!}
306
302
  />
307
303
  </div>
308
304
  </div>
@@ -1,13 +1,11 @@
1
1
  import { useState, useMemo, useEffect } from 'react';
2
- import type { BrandConfig } from '@/types/tractstack';
2
+ import { CheckIcon } from '@heroicons/react/20/solid';
3
3
  import { savePaneToLibrary } from '@/utils/compositor/designLibraryHelper';
4
4
  import StringInput from '@/components/form/StringInput';
5
- import { CheckIcon } from '@heroicons/react/20/solid';
5
+ import { brandConfigStore } from '@/stores/storykeep';
6
6
 
7
7
  interface SaveToLibraryModalProps {
8
8
  paneId: string;
9
- config: BrandConfig;
10
- tenantId: string;
11
9
  onClose: () => void;
12
10
  }
13
11
 
@@ -37,8 +35,6 @@ const OTHER_CATEGORY = 'other';
37
35
 
38
36
  export function SaveToLibraryModal({
39
37
  paneId,
40
- config,
41
- tenantId,
42
38
  onClose,
43
39
  }: SaveToLibraryModalProps) {
44
40
  const [title, setTitle] = useState('');
@@ -48,13 +44,14 @@ export function SaveToLibraryModal({
48
44
  const [saveState, setSaveState] = useState<SaveState>('idle');
49
45
  const [error, setError] = useState('');
50
46
 
47
+ const designLibrary = brandConfigStore.get()?.DESIGN_LIBRARY || [];
51
48
  const categories = useMemo(() => {
52
49
  const cats =
53
- config.DESIGN_LIBRARY?.map((item) => item.category).filter(
54
- (v, i, a) => a.indexOf(v) === i
55
- ) || [];
50
+ designLibrary
51
+ .map((item) => item.category)
52
+ .filter((v, i, a) => a.indexOf(v) === i) || [];
56
53
  return [...cats, OTHER_CATEGORY];
57
- }, [config.DESIGN_LIBRARY]);
54
+ }, [designLibrary]);
58
55
 
59
56
  useEffect(() => {
60
57
  if (saveState === 'saved') {
@@ -80,14 +77,28 @@ export function SaveToLibraryModal({
80
77
  category: finalCategory,
81
78
  copyMode: copyMode,
82
79
  };
83
-
84
- const success = await savePaneToLibrary(paneId, tenantId, config, formData);
85
-
86
- if (success) {
87
- setSaveState('saved');
80
+ const brandConfig = brandConfigStore.get();
81
+
82
+ if (brandConfig) {
83
+ const newBrandConfig = await savePaneToLibrary(
84
+ paneId,
85
+ brandConfig.TENANT_ID,
86
+ brandConfig,
87
+ formData
88
+ );
89
+ if (newBrandConfig) {
90
+ brandConfigStore.set({
91
+ ...newBrandConfig,
92
+ TENANT_ID: brandConfig.TENANT_ID,
93
+ });
94
+ setSaveState('saved');
95
+ } else {
96
+ setSaveState('idle');
97
+ setError('Failed to save template. Please try again.');
98
+ }
88
99
  } else {
89
100
  setSaveState('idle');
90
- setError('Failed to save template. Please try again.');
101
+ setError('Failed to save template. Brand Config not found.');
91
102
  }
92
103
  };
93
104
 
@@ -18,20 +18,16 @@ import {
18
18
  hexToTailwind,
19
19
  findClosestTailwindColor,
20
20
  } from '@/utils/compositor/tailwindColors';
21
+ import { brandConfigStore } from '@/stores/storykeep';
21
22
  import { cloneDeep } from '@/utils/helpers';
22
- import type { FullContentMapItem, BrandConfig } from '@/types/tractstack';
23
+ import type { FullContentMapItem } from '@/types/tractstack';
23
24
  import {
24
25
  StoryFragmentMode,
25
26
  type StoryFragmentNode,
26
27
  } from '@/types/compositorTypes';
27
28
 
28
- const StoryFragmentConfigPanel = ({
29
- nodeId,
30
- config,
31
- }: {
32
- nodeId: string;
33
- config?: BrandConfig;
34
- }) => {
29
+ const StoryFragmentConfigPanel = ({ nodeId }: { nodeId: string }) => {
30
+ const brandColors = brandConfigStore.get()?.BRAND_COLOURS || '';
35
31
  const [isNodeAvailable, setIsNodeAvailable] = useState(false);
36
32
  const [storyfragmentNode, setStoryfragmentNode] =
37
33
  useState<StoryFragmentNode | null>(null);
@@ -156,7 +152,7 @@ const StoryFragmentConfigPanel = ({
156
152
  delete updatedNode.tailwindBgColour;
157
153
  } else {
158
154
  // Set the new background color
159
- const val = hexToTailwind(tempBgColor, config?.BRAND_COLOURS);
155
+ const val = hexToTailwind(tempBgColor, brandColors);
160
156
  const exactValPayload = val
161
157
  ? null
162
158
  : findClosestTailwindColor(tempBgColor);
@@ -178,23 +174,11 @@ const StoryFragmentConfigPanel = ({
178
174
  }
179
175
 
180
176
  if (mode === StoryFragmentMode.SLUG) {
181
- return (
182
- <StoryFragmentSlugPanel
183
- nodeId={nodeId}
184
- setMode={setMode}
185
- config={config!}
186
- />
187
- );
177
+ return <StoryFragmentSlugPanel nodeId={nodeId} setMode={setMode} />;
188
178
  } else if (mode === StoryFragmentMode.MENU) {
189
179
  return <StoryFragmentMenuPanel nodeId={nodeId} setMode={setMode} />;
190
180
  } else if (mode === StoryFragmentMode.OG) {
191
- return (
192
- <StoryFragmentOpenGraphPanel
193
- nodeId={nodeId}
194
- setMode={setMode}
195
- config={config}
196
- />
197
- );
181
+ return <StoryFragmentOpenGraphPanel nodeId={nodeId} setMode={setMode} />;
198
182
  }
199
183
 
200
184
  return (
@@ -253,7 +237,7 @@ const StoryFragmentConfigPanel = ({
253
237
  </>
254
238
  )}
255
239
 
256
- {config && (
240
+ {brandColors && (
257
241
  <div className="flex items-center gap-2">
258
242
  <div className="text-md">Background Colour:</div>
259
243
  <ColorPickerCombo
@@ -262,12 +246,11 @@ const StoryFragmentConfigPanel = ({
262
246
  storyfragmentNode.tailwindBgColour
263
247
  ? tailwindToHex(
264
248
  storyfragmentNode.tailwindBgColour,
265
- config?.BRAND_COLOURS || null
249
+ brandColors
266
250
  )
267
251
  : ''
268
252
  }
269
253
  onColorChange={handleBgColorChange}
270
- config={config}
271
254
  allowNull={true}
272
255
  />
273
256
  {tempBgColor !== null && (
@@ -28,11 +28,7 @@ import {
28
28
  getImageDimensions,
29
29
  type FileValidationOptions,
30
30
  } from '@/utils/api/fileHelpers';
31
- import type {
32
- FullContentMapItem,
33
- BrandConfig,
34
- Topic,
35
- } from '@/types/tractstack';
31
+ import type { FullContentMapItem, Topic } from '@/types/tractstack';
36
32
  import type { ImageDimensions } from '@/types/formTypes';
37
33
  import {
38
34
  StoryFragmentMode,
@@ -45,7 +41,6 @@ const TARGET_HEIGHT = 630;
45
41
  interface StoryFragmentOpenGraphPanelProps {
46
42
  nodeId: string;
47
43
  setMode: (mode: StoryFragmentMode) => void;
48
- config?: BrandConfig;
49
44
  }
50
45
 
51
46
  const hasSlug = (
@@ -58,7 +53,6 @@ const hasSlug = (
58
53
  const StoryFragmentOpenGraphPanel = ({
59
54
  nodeId,
60
55
  setMode,
61
- config,
62
56
  }: StoryFragmentOpenGraphPanelProps) => {
63
57
  const $contentMap = useStore(fullContentMapStore);
64
58
  const $storyFragmentTopics = useStore(storyFragmentTopicsStore);
@@ -691,15 +685,12 @@ const StoryFragmentOpenGraphPanel = ({
691
685
  </div>
692
686
  ) : (
693
687
  <>
694
- {config && (
695
- <OgImagePreview
696
- nodeId={nodeId}
697
- title={draftTitle}
698
- socialImagePath={draftImagePath}
699
- config={config}
700
- onColorChange={handleColorChange}
701
- />
702
- )}
688
+ <OgImagePreview
689
+ nodeId={nodeId}
690
+ title={draftTitle}
691
+ socialImagePath={draftImagePath}
692
+ onColorChange={handleColorChange}
693
+ />
703
694
  <div className="mt-4 flex space-x-4">
704
695
  <div
705
696
  className="relative w-64 overflow-hidden rounded-md bg-gray-100"
@@ -7,7 +7,7 @@ import { Switch } from '@ark-ui/react/switch';
7
7
  import { getCtx } from '@/stores/nodes';
8
8
  import { pendingHomePageSlugStore } from '@/stores/storykeep';
9
9
  import { cloneDeep } from '@/utils/helpers';
10
- import type { BrandConfig } from '@/types/tractstack';
10
+ import { brandConfigStore } from '@/stores/storykeep';
11
11
  import {
12
12
  StoryFragmentMode,
13
13
  type StoryFragmentNode,
@@ -16,13 +16,11 @@ import {
16
16
  interface StoryFragmentSlugPanelProps {
17
17
  nodeId: string;
18
18
  setMode: (mode: StoryFragmentMode) => void;
19
- config: BrandConfig;
20
19
  }
21
20
 
22
21
  const StoryFragmentSlugPanel = ({
23
22
  nodeId,
24
23
  setMode,
25
- config,
26
24
  }: StoryFragmentSlugPanelProps) => {
27
25
  const [slug, setSlug] = useState('');
28
26
  const [isValid, setIsValid] = useState(false);
@@ -30,7 +28,8 @@ const StoryFragmentSlugPanel = ({
30
28
  const [charCount, setCharCount] = useState(0);
31
29
  const [validationError, setValidationError] = useState<string | null>(null);
32
30
  const [canSave, setCanSave] = useState(false);
33
- const isHomeSlug = slug === config.HOME_SLUG;
31
+ const homeSlug = brandConfigStore.get()?.HOME_SLUG || `hello`;
32
+ const isHomeSlug = slug === homeSlug;
34
33
  const pendingHomePageSlug = useStore(pendingHomePageSlugStore);
35
34
  const isSetAsHomePage = pendingHomePageSlug === slug;
36
35
 
@@ -51,7 +50,7 @@ const StoryFragmentSlugPanel = ({
51
50
  setCharCount(length);
52
51
 
53
52
  // If it's the home slug, consider it valid but locked
54
- if (value === config.HOME_SLUG) {
53
+ if (value === homeSlug) {
55
54
  setIsValid(true);
56
55
  setCanSave(false);
57
56
  setValidationError(null);
@@ -92,7 +91,7 @@ const StoryFragmentSlugPanel = ({
92
91
  value: string
93
92
  ): { isValid: boolean; error?: string } => {
94
93
  // Don't allow saving if it's the home slug
95
- if (value === config.HOME_SLUG) {
94
+ if (value === homeSlug) {
96
95
  return {
97
96
  isValid: false,
98
97
  error: 'Cannot modify the home page slug',