astro-tractstack 2.0.17 → 2.0.18
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/index.js +18 -0
- package/package.json +1 -1
- package/templates/src/components/codehooks/FeaturedArticleSetup.tsx +1 -1
- package/templates/src/components/codehooks/ListContentSetup.tsx +1 -1
- package/templates/src/components/compositor/Compositor.tsx +1 -0
- package/templates/src/components/compositor/Node.tsx +41 -17
- package/templates/src/components/compositor/nodes/GhostInsertBlock.tsx +9 -6
- package/templates/src/components/compositor/nodes/GridLayout.tsx +124 -0
- package/templates/src/components/compositor/nodes/GridLayout_eraser.tsx +33 -0
- package/templates/src/components/compositor/nodes/Markdown.tsx +67 -37
- package/templates/src/components/compositor/nodes/Markdown_eraser.tsx +56 -0
- package/templates/src/components/compositor/preview/FeaturedArticlePreview.tsx +8 -2
- package/templates/src/components/edit/PanelSwitch.tsx +232 -75
- package/templates/src/components/edit/SettingsPanel.tsx +0 -1
- package/templates/src/components/edit/pane/AddPanePanel_codehook.tsx +3 -3
- package/templates/src/components/edit/pane/AddPanePanel_new.tsx +167 -145
- package/templates/src/components/edit/pane/AddPanePanel_reuse.tsx +2 -2
- package/templates/src/components/edit/pane/ConfigPanePanel.tsx +1 -7
- package/templates/src/components/edit/pane/PanePanel_impression.tsx +1 -1
- package/templates/src/components/edit/pane/RestylePaneModal.tsx +8 -5
- package/templates/src/components/edit/pane/steps/AiDesignStep.tsx +6 -6
- package/templates/src/components/edit/pane/steps/CopyInputStep.tsx +3 -3
- package/templates/src/components/edit/pane/steps/DesignLibraryStep.tsx +4 -4
- package/templates/src/components/edit/panels/StyleElementPanel.tsx +11 -4
- package/templates/src/components/edit/panels/StyleElementPanel_add.tsx +8 -8
- package/templates/src/components/edit/panels/StyleElementPanel_remove.tsx +14 -4
- package/templates/src/components/edit/panels/StyleElementPanel_update.tsx +16 -4
- package/templates/src/components/edit/panels/StyleImagePanel.tsx +8 -3
- package/templates/src/components/edit/panels/StyleImagePanel_add.tsx +9 -2
- package/templates/src/components/edit/panels/StyleImagePanel_remove.tsx +5 -2
- package/templates/src/components/edit/panels/StyleImagePanel_update.tsx +5 -2
- package/templates/src/components/edit/panels/StyleLiElementPanel.tsx +7 -3
- package/templates/src/components/edit/panels/StyleLiElementPanel_add.tsx +9 -2
- package/templates/src/components/edit/panels/StyleLiElementPanel_remove.tsx +5 -2
- package/templates/src/components/edit/panels/StyleLiElementPanel_update.tsx +5 -2
- package/templates/src/components/edit/panels/StyleParentPanel.tsx +530 -171
- package/templates/src/components/edit/panels/StyleParentPanel_add.tsx +77 -42
- package/templates/src/components/edit/panels/StyleParentPanel_deleteLayer.tsx +38 -22
- package/templates/src/components/edit/panels/StyleParentPanel_remove.tsx +171 -66
- package/templates/src/components/edit/panels/StyleParentPanel_update.tsx +166 -98
- package/templates/src/components/edit/panels/StyleWidgetPanel.tsx +7 -3
- package/templates/src/components/edit/panels/StyleWidgetPanel_add.tsx +9 -2
- package/templates/src/components/edit/panels/StyleWidgetPanel_remove.tsx +5 -2
- package/templates/src/components/edit/panels/StyleWidgetPanel_update.tsx +6 -2
- package/templates/src/components/edit/state/SaveModal.tsx +10 -2
- package/templates/src/components/edit/state/SaveToLibraryModal.tsx +6 -6
- package/templates/src/components/fields/PaneBreakShapeSelector.tsx +1 -1
- package/templates/src/components/widgets/ImpressionWrapper.tsx +4 -1
- package/templates/src/constants/prompts.json +1 -1
- package/templates/src/stores/nodes.ts +110 -33
- package/templates/src/stores/storykeep.ts +3 -1
- package/templates/src/types/compositorTypes.ts +37 -2
- package/templates/src/utils/compositor/TemplateNodes.ts +8 -0
- package/templates/src/utils/compositor/nodesHelper.ts +229 -0
- package/templates/src/utils/compositor/reduceNodesClassNames.ts +40 -1
- package/templates/src/utils/compositor/typeGuards.ts +7 -0
- package/templates/src/utils/etl/extractor.ts +1 -5
- package/templates/src/utils/etl/index.ts +1 -0
- package/templates/src/utils/etl/transformer.ts +70 -25
- package/utils/inject-files.ts +18 -0
|
@@ -75,6 +75,7 @@ export interface OptionsPayload {
|
|
|
75
75
|
| undefined;
|
|
76
76
|
parentClasses?: any | undefined;
|
|
77
77
|
parentCss?: string[] | undefined;
|
|
78
|
+
gridCss?: string | undefined;
|
|
78
79
|
hiddenViewportMobile?: boolean | undefined;
|
|
79
80
|
hiddenViewportTablet?: boolean | undefined;
|
|
80
81
|
hiddenViewportDesktop?: boolean | undefined;
|
|
@@ -11,6 +11,7 @@ import type {
|
|
|
11
11
|
ArtpackImageNode,
|
|
12
12
|
BgImageNode,
|
|
13
13
|
StoryFragmentNode,
|
|
14
|
+
GridLayoutNode,
|
|
14
15
|
} from '@/types/compositorTypes';
|
|
15
16
|
import type {
|
|
16
17
|
OptionsPayload,
|
|
@@ -21,7 +22,9 @@ import {
|
|
|
21
22
|
isBreakNode,
|
|
22
23
|
isArtpackImageNode,
|
|
23
24
|
isBgImageNode,
|
|
25
|
+
isGridLayoutNode,
|
|
24
26
|
} from '@/utils/compositor/typeGuards';
|
|
27
|
+
import { processClassesForViewports } from '@/utils/compositor/reduceNodesClassNames';
|
|
25
28
|
|
|
26
29
|
const VERBOSE = false;
|
|
27
30
|
|
|
@@ -42,7 +45,6 @@ export function transformToOptionsPayload(
|
|
|
42
45
|
})),
|
|
43
46
|
});
|
|
44
47
|
|
|
45
|
-
// 1. Generate flattened nodes array with computed CSS
|
|
46
48
|
const flattenedNodes = subtree.allChildNodes
|
|
47
49
|
.map((node) => {
|
|
48
50
|
if (VERBOSE)
|
|
@@ -58,11 +60,8 @@ export function transformToOptionsPayload(
|
|
|
58
60
|
parentId: node.parentId,
|
|
59
61
|
};
|
|
60
62
|
|
|
61
|
-
// Add type-specific fields based on node type
|
|
62
63
|
if (node.nodeType === 'TagElement') {
|
|
63
64
|
const flatNode = node as FlatNode;
|
|
64
|
-
|
|
65
|
-
// Compute CSS using existing NodesContext methods
|
|
66
65
|
let computedCSS: string | undefined;
|
|
67
66
|
try {
|
|
68
67
|
computedCSS = ctx.getNodeClasses(node.id, 'auto', 0);
|
|
@@ -91,10 +90,55 @@ export function transformToOptionsPayload(
|
|
|
91
90
|
return transformedNode;
|
|
92
91
|
}
|
|
93
92
|
|
|
93
|
+
if (isGridLayoutNode(node)) {
|
|
94
|
+
const gridLayoutNode = node as GridLayoutNode;
|
|
95
|
+
let gridCss = '';
|
|
96
|
+
if (gridLayoutNode.gridColumns) {
|
|
97
|
+
const { mobile, tablet, desktop } = gridLayoutNode.gridColumns;
|
|
98
|
+
gridCss = `grid grid-cols-${mobile}`;
|
|
99
|
+
if (tablet !== mobile) {
|
|
100
|
+
gridCss += ` md:grid-cols-${tablet}`;
|
|
101
|
+
}
|
|
102
|
+
if (desktop !== tablet) {
|
|
103
|
+
gridCss += ` xl:grid-cols-${desktop}`;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
let parentCss: string[] | undefined;
|
|
108
|
+
if (gridLayoutNode.parentClasses) {
|
|
109
|
+
try {
|
|
110
|
+
parentCss = gridLayoutNode.parentClasses.map((_, index) =>
|
|
111
|
+
ctx.getNodeClasses(node.id, 'auto', index)
|
|
112
|
+
);
|
|
113
|
+
} catch (error) {
|
|
114
|
+
console.warn(
|
|
115
|
+
`Failed to compute parent CSS for grid node ${node.id}:`,
|
|
116
|
+
error
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const transformedNode = {
|
|
122
|
+
...baseNode,
|
|
123
|
+
type: gridLayoutNode.type,
|
|
124
|
+
gridCss: gridCss,
|
|
125
|
+
gridColumns: gridLayoutNode.gridColumns,
|
|
126
|
+
parentClasses: gridLayoutNode.parentClasses,
|
|
127
|
+
parentCss: parentCss,
|
|
128
|
+
defaultClasses: gridLayoutNode.defaultClasses,
|
|
129
|
+
hiddenViewportMobile: gridLayoutNode.hiddenViewportMobile,
|
|
130
|
+
hiddenViewportTablet: gridLayoutNode.hiddenViewportTablet,
|
|
131
|
+
hiddenViewportDesktop: gridLayoutNode.hiddenViewportDesktop,
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
if (VERBOSE)
|
|
135
|
+
console.log('✅ TRANSFORMER - GridLayout result:', transformedNode);
|
|
136
|
+
return transformedNode;
|
|
137
|
+
}
|
|
138
|
+
|
|
94
139
|
if (node.nodeType === 'Markdown') {
|
|
95
140
|
const markdownNode = node as MarkdownPaneFragmentNode;
|
|
96
141
|
|
|
97
|
-
// Compute parentCss if parentClasses exist
|
|
98
142
|
let parentCss: string[] | undefined;
|
|
99
143
|
if (markdownNode.parentClasses) {
|
|
100
144
|
try {
|
|
@@ -109,6 +153,25 @@ export function transformToOptionsPayload(
|
|
|
109
153
|
}
|
|
110
154
|
}
|
|
111
155
|
|
|
156
|
+
let gridCss: string | undefined;
|
|
157
|
+
if (markdownNode.gridClasses) {
|
|
158
|
+
try {
|
|
159
|
+
const [allClasses] = processClassesForViewports(
|
|
160
|
+
markdownNode.gridClasses,
|
|
161
|
+
{},
|
|
162
|
+
1
|
|
163
|
+
);
|
|
164
|
+
if (allClasses && allClasses.length > 0) {
|
|
165
|
+
gridCss = allClasses[0];
|
|
166
|
+
}
|
|
167
|
+
} catch (error) {
|
|
168
|
+
console.warn(
|
|
169
|
+
`Failed to compute grid CSS for markdown node ${node.id}:`,
|
|
170
|
+
error
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
112
175
|
const transformedNode = {
|
|
113
176
|
...baseNode,
|
|
114
177
|
type: markdownNode.type,
|
|
@@ -119,6 +182,8 @@ export function transformToOptionsPayload(
|
|
|
119
182
|
hiddenViewportMobile: markdownNode.hiddenViewportMobile,
|
|
120
183
|
hiddenViewportTablet: markdownNode.hiddenViewportTablet,
|
|
121
184
|
hiddenViewportDesktop: markdownNode.hiddenViewportDesktop,
|
|
185
|
+
gridClasses: markdownNode.gridClasses,
|
|
186
|
+
...(gridCss && { gridCss: gridCss }),
|
|
122
187
|
};
|
|
123
188
|
|
|
124
189
|
if (VERBOSE)
|
|
@@ -127,7 +192,6 @@ export function transformToOptionsPayload(
|
|
|
127
192
|
}
|
|
128
193
|
|
|
129
194
|
if (node.nodeType === 'BgPane') {
|
|
130
|
-
// Handle different BgPane types
|
|
131
195
|
if (isBreakNode(node as FlatNode)) {
|
|
132
196
|
const breakNode = node as VisualBreakNode;
|
|
133
197
|
const transformedNode = {
|
|
@@ -188,20 +252,15 @@ export function transformToOptionsPayload(
|
|
|
188
252
|
);
|
|
189
253
|
return transformedNode;
|
|
190
254
|
}
|
|
191
|
-
|
|
192
|
-
// Fallback for unknown BgPane types
|
|
193
255
|
if (VERBOSE)
|
|
194
256
|
console.warn('⚠️ TRANSFORMER - Unknown BgPane type:', node);
|
|
195
257
|
return baseNode;
|
|
196
258
|
}
|
|
197
|
-
|
|
198
|
-
// Unknown node type - return base node
|
|
199
259
|
if (VERBOSE) console.warn('⚠️ TRANSFORMER - Unknown node type:', node);
|
|
200
260
|
return baseNode;
|
|
201
261
|
})
|
|
202
262
|
.filter((node) => node !== null);
|
|
203
263
|
|
|
204
|
-
// 2. Build final OptionsPayload
|
|
205
264
|
const optionsPayload: OptionsPayload = {
|
|
206
265
|
bgColour: subtree.paneNode.bgColour,
|
|
207
266
|
isDecorative: subtree.paneNode.isDecorative,
|
|
@@ -230,11 +289,9 @@ export async function transformStoryFragmentForSave(
|
|
|
230
289
|
const node = ctx.allNodes.get().get(fragmentId) as StoryFragmentNode;
|
|
231
290
|
const seoData = storyFragmentTopicsStore.get()[fragmentId];
|
|
232
291
|
|
|
233
|
-
// Get brand config from store to find default tractstack
|
|
234
292
|
const brandConfig = await getBrandConfig(tenantId);
|
|
235
293
|
const defaultTractStackSlug =
|
|
236
294
|
brandConfig?.TRACTSTACK_HOME_SLUG || 'tractstack';
|
|
237
|
-
// Find the default tractstack ID from content map
|
|
238
295
|
const contentMap = fullContentMapStore.get();
|
|
239
296
|
const defaultTractStack = contentMap.find(
|
|
240
297
|
(item) => item.type === 'TractStack' && item.slug === defaultTractStackSlug
|
|
@@ -244,12 +301,10 @@ export async function transformStoryFragmentForSave(
|
|
|
244
301
|
|
|
245
302
|
const payload = {
|
|
246
303
|
...node,
|
|
247
|
-
// Add deferred SEO data if available
|
|
248
304
|
...(seoData && {
|
|
249
305
|
topics: seoData.topics?.map((t) => t.title) || [],
|
|
250
306
|
description: seoData.description || '',
|
|
251
307
|
}),
|
|
252
|
-
// Ensure tractStackId is set for new StoryFragments
|
|
253
308
|
tractStackId: finalTractStackId,
|
|
254
309
|
};
|
|
255
310
|
|
|
@@ -261,13 +316,8 @@ export function transformLivePaneForSave(
|
|
|
261
316
|
paneId: string,
|
|
262
317
|
isContext?: boolean
|
|
263
318
|
): BackendSavePayload {
|
|
264
|
-
// 1. Extract distributed state
|
|
265
319
|
const subtree = extractPaneSubtree(ctx, paneId);
|
|
266
|
-
|
|
267
|
-
// 2. Transform to flattened OptionsPayload using existing NodesContext methods
|
|
268
320
|
const optionsPayload = transformToOptionsPayload(ctx, subtree);
|
|
269
|
-
|
|
270
|
-
// 3. Format for save endpoint
|
|
271
321
|
return formatForSave(subtree.paneNode, optionsPayload, isContext);
|
|
272
322
|
}
|
|
273
323
|
|
|
@@ -275,12 +325,7 @@ export function transformLivePaneForPreview(
|
|
|
275
325
|
ctx: NodesContext,
|
|
276
326
|
paneId: string
|
|
277
327
|
): BackendPreviewPayload {
|
|
278
|
-
// 1. Extract distributed state
|
|
279
328
|
const subtree = extractPaneSubtree(ctx, paneId);
|
|
280
|
-
|
|
281
|
-
// 2. Transform to flattened OptionsPayload using existing NodesContext methods
|
|
282
329
|
const optionsPayload = transformToOptionsPayload(ctx, subtree);
|
|
283
|
-
|
|
284
|
-
// 3. Format for preview endpoint
|
|
285
330
|
return formatForPreview(subtree.paneNode, optionsPayload);
|
|
286
331
|
}
|
package/utils/inject-files.ts
CHANGED
|
@@ -105,6 +105,18 @@ export async function injectTemplateFiles(
|
|
|
105
105
|
),
|
|
106
106
|
dest: 'src/components/compositor/nodes/RenderChildren.tsx',
|
|
107
107
|
},
|
|
108
|
+
{
|
|
109
|
+
src: resolve(
|
|
110
|
+
'../templates/src/components/compositor/nodes/GridLayout.tsx'
|
|
111
|
+
),
|
|
112
|
+
dest: 'src/components/compositor/nodes/GridLayout.tsx',
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
src: resolve(
|
|
116
|
+
'../templates/src/components/compositor/nodes/GridLayout_eraser.tsx'
|
|
117
|
+
),
|
|
118
|
+
dest: 'src/components/compositor/nodes/GridLayout_eraser.tsx',
|
|
119
|
+
},
|
|
108
120
|
{
|
|
109
121
|
src: resolve(
|
|
110
122
|
'../templates/src/components/compositor/nodes/GhostInsertBlock.tsx'
|
|
@@ -155,6 +167,12 @@ export async function injectTemplateFiles(
|
|
|
155
167
|
src: resolve('../templates/src/components/compositor/nodes/Markdown.tsx'),
|
|
156
168
|
dest: 'src/components/compositor/nodes/Markdown.tsx',
|
|
157
169
|
},
|
|
170
|
+
{
|
|
171
|
+
src: resolve(
|
|
172
|
+
'../templates/src/components/compositor/nodes/Markdown_eraser.tsx'
|
|
173
|
+
),
|
|
174
|
+
dest: 'src/components/compositor/nodes/Markdown_eraser.tsx',
|
|
175
|
+
},
|
|
158
176
|
{
|
|
159
177
|
src: resolve(
|
|
160
178
|
'../templates/src/components/compositor/nodes/BgPaneWrapper.tsx'
|