astro-tractstack 2.2.1 → 2.2.3
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/package.json +1 -1
- package/templates/src/components/codehooks/BunnyVideoSetup.tsx +0 -1
- package/templates/src/components/codehooks/FeaturedArticleSetup.tsx +0 -1
- package/templates/src/components/codehooks/ListContentSetup.tsx +0 -1
- package/templates/src/components/codehooks/ProductCardSetup.tsx +0 -1
- package/templates/src/components/codehooks/ProductGridSetup.tsx +0 -1
- package/templates/src/components/compositor/Compositor.tsx +0 -1
- package/templates/src/components/compositor/Node.tsx +157 -133
- package/templates/src/components/compositor/nodes/tagElements/NodeBasicTag.tsx +2 -4
- package/templates/src/components/edit/Header.tsx +2 -6
- package/templates/src/components/edit/context/ContextPaneConfig_slug.tsx +1 -1
- package/templates/src/components/edit/context/ContextPaneConfig_title.tsx +0 -1
- package/templates/src/components/edit/pane/AddPanePanel_break.tsx +1 -0
- package/templates/src/components/edit/pane/AddPanePanel_new.tsx +8 -12
- package/templates/src/components/edit/pane/AddPanePanel_reuse.tsx +9 -6
- package/templates/src/components/edit/pane/AiRestylePaneModal.tsx +7 -69
- package/templates/src/components/edit/pane/ConfigPanePanel.tsx +2 -2
- package/templates/src/components/edit/pane/PanePanel_impression.tsx +0 -4
- package/templates/src/components/edit/pane/PanePanel_path.tsx +0 -1
- package/templates/src/components/edit/pane/PanePanel_title.tsx +1 -2
- package/templates/src/components/edit/pane/RestylePaneModal.tsx +1 -4
- package/templates/src/components/edit/pane/steps/AiCreativeDesignStep.tsx +0 -3
- package/templates/src/components/edit/pane/steps/AiRefineDesignStep.tsx +2 -2
- package/templates/src/components/edit/pane/steps/AiStandardDesignStep.tsx +173 -80
- package/templates/src/components/edit/pane/steps/CreativeInjectStep.tsx +0 -5
- package/templates/src/components/edit/pane/steps/DesignLibraryStep.tsx +2 -1
- package/templates/src/components/edit/panels/StyleBreakPanel.tsx +1 -4
- package/templates/src/components/edit/panels/StyleCodeHookPanel.tsx +0 -1
- package/templates/src/components/edit/panels/StyleElementPanel.tsx +1 -1
- package/templates/src/components/edit/panels/StyleElementPanel_remove.tsx +1 -4
- package/templates/src/components/edit/panels/StyleElementPanel_update.tsx +3 -3
- package/templates/src/components/edit/panels/StyleImagePanel.tsx +3 -3
- package/templates/src/components/edit/panels/StyleImagePanel_remove.tsx +1 -4
- package/templates/src/components/edit/panels/StyleImagePanel_update.tsx +3 -4
- package/templates/src/components/edit/panels/StyleLiElementPanel_remove.tsx +1 -4
- package/templates/src/components/edit/panels/StyleLiElementPanel_update.tsx +3 -3
- package/templates/src/components/edit/panels/StyleLinkPanel.tsx +1 -1
- package/templates/src/components/edit/panels/StyleLinkPanel_config.tsx +1 -1
- package/templates/src/components/edit/panels/StyleLinkPanel_remove.tsx +1 -1
- package/templates/src/components/edit/panels/StyleLinkPanel_update.tsx +1 -1
- package/templates/src/components/edit/panels/StyleParentPanel.tsx +0 -7
- package/templates/src/components/edit/panels/StyleParentPanel_deleteLayer.tsx +0 -2
- package/templates/src/components/edit/panels/StyleParentPanel_remove.tsx +0 -2
- package/templates/src/components/edit/panels/StyleParentPanel_update.tsx +0 -2
- package/templates/src/components/edit/panels/StyleWidgetPanel_config.tsx +0 -3
- package/templates/src/components/edit/panels/StyleWidgetPanel_remove.tsx +1 -4
- package/templates/src/components/edit/panels/StyleWidgetPanel_update.tsx +3 -4
- package/templates/src/components/edit/panels/StyleWordCarouselPanel.tsx +0 -2
- package/templates/src/components/edit/state/StylesMemory.tsx +3 -9
- package/templates/src/components/edit/storyfragment/StoryFragmentConfigPanel.tsx +0 -1
- package/templates/src/components/edit/storyfragment/StoryFragmentPanel_menu.tsx +0 -2
- package/templates/src/components/edit/storyfragment/StoryFragmentPanel_og.tsx +0 -2
- package/templates/src/components/edit/storyfragment/StoryFragmentPanel_slug.tsx +0 -1
- package/templates/src/components/edit/storyfragment/StoryFragmentPanel_title.tsx +0 -1
- package/templates/src/components/fields/ArtpackImage.tsx +0 -7
- package/templates/src/components/fields/BackgroundImage.tsx +0 -14
- package/templates/src/components/fields/BackgroundImageWrapper.tsx +0 -5
- package/templates/src/components/fields/ImageUpload.tsx +0 -3
- package/templates/src/pages/[...slug]/edit.astro +0 -1
- package/templates/src/pages/sandbox.astro +0 -1
- package/templates/src/stores/nodes.ts +278 -312
- package/templates/src/stores/nodesHistory.ts +59 -24
- package/templates/src/utils/api/setupHelpers.ts +1 -1
- package/templates/src/utils/compositor/aiPaneParser.ts +57 -0
- package/templates/src/utils/compositor/designLibraryHelper.ts +1 -3
- package/templates/src/utils/compositor/htmlAst.ts +109 -2
- package/templates/src/utils/compositor/nodesHelper.ts +1 -9
- package/templates/src/utils/compositor/savePipeline.ts +1 -4
package/package.json
CHANGED
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
isTopLevelBlockNode,
|
|
9
9
|
parseCodeHook,
|
|
10
10
|
} from '@/utils/compositor/nodesHelper';
|
|
11
|
-
import { isPaneNode, isGridLayoutNode } from '@/utils/compositor/typeGuards';
|
|
12
11
|
import { PaneAddMode } from '@/types/compositorTypes';
|
|
13
12
|
import { NodeOverlay } from './tools/NodeOverlay';
|
|
14
13
|
import PanelVisibilityWrapper from '@/components/compositor/PanelVisibilityWrapper';
|
|
@@ -59,70 +58,32 @@ export const Node = memo((props: NodeProps) => {
|
|
|
59
58
|
const ctx = getCtx(props);
|
|
60
59
|
const node = ctx.allNodes.get().get(props.nodeId);
|
|
61
60
|
const viewport = useStore(viewportKeyStore).value;
|
|
62
|
-
const isPreview = ctx.rootNodeId.get() === `tmp
|
|
61
|
+
const isPreview = ctx.rootNodeId.get() === `tmp` || ctx.isTemplate.get();
|
|
63
62
|
const hasPanes = useStore(ctx.hasPanes);
|
|
64
63
|
|
|
65
64
|
if (!node) return null;
|
|
66
65
|
|
|
67
66
|
let element: ReactNode = null;
|
|
68
67
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
68
|
+
switch (node.nodeType) {
|
|
69
|
+
case 'StoryFragment': {
|
|
70
|
+
const sf = node as StoryFragmentNode;
|
|
71
|
+
if (!isPreview) ctx.hasTitle.set(!(!sf.slug || !sf.title));
|
|
73
72
|
|
|
74
|
-
|
|
75
|
-
return (
|
|
76
|
-
<div
|
|
77
|
-
className="fixed inset-0 overflow-y-auto bg-black bg-opacity-75"
|
|
78
|
-
style={{ zIndex: 9005 }}
|
|
79
|
-
>
|
|
80
|
-
<div className="flex min-h-screen items-center justify-center p-1.5">
|
|
81
|
-
<div
|
|
82
|
-
className="fixed inset-0 bg-black opacity-65"
|
|
83
|
-
onClick={() => (window.location.href = '/storykeep')}
|
|
84
|
-
/>
|
|
85
|
-
<div className="relative w-full max-w-4xl rounded-lg bg-white shadow-xl">
|
|
86
|
-
<div className="p-6">
|
|
87
|
-
<StoryFragmentTitlePanel nodeId={props.nodeId} />
|
|
88
|
-
</div>
|
|
89
|
-
</div>
|
|
90
|
-
</div>
|
|
91
|
-
</div>
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if (!hasPanes && !isPreview) {
|
|
96
|
-
return <EmptyPageHandler {...props} />;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
return (
|
|
100
|
-
<>
|
|
101
|
-
<StoryFragmentConfigPanel
|
|
102
|
-
nodeId={props.nodeId}
|
|
103
|
-
isSandboxMode={props.isSandboxMode || false}
|
|
104
|
-
/>
|
|
105
|
-
<StoryFragment {...props} />
|
|
106
|
-
</>
|
|
107
|
-
);
|
|
108
|
-
} else if (isPaneNode(node)) {
|
|
109
|
-
const paneNode = node as PaneNode;
|
|
110
|
-
const isHtmlAstPane = !!paneNode.htmlAst;
|
|
111
|
-
const paneNodes = ctx.getChildNodeIDs(node.id);
|
|
112
|
-
|
|
113
|
-
if (paneNode.isContextPane) {
|
|
114
|
-
if (!isPreview) ctx.hasTitle.set(!(!paneNode.slug || !paneNode.title));
|
|
115
|
-
|
|
116
|
-
if (!isPreview && !(paneNode.slug && paneNode.title)) {
|
|
73
|
+
if (!(sf.slug && sf.title)) {
|
|
117
74
|
return (
|
|
118
75
|
<div
|
|
119
76
|
className="fixed inset-0 overflow-y-auto bg-black bg-opacity-75"
|
|
120
77
|
style={{ zIndex: 9005 }}
|
|
121
78
|
>
|
|
122
79
|
<div className="flex min-h-screen items-center justify-center p-1.5">
|
|
80
|
+
<div
|
|
81
|
+
className="fixed inset-0 bg-black opacity-65"
|
|
82
|
+
onClick={() => (window.location.href = '/storykeep')}
|
|
83
|
+
/>
|
|
123
84
|
<div className="relative w-full max-w-4xl rounded-lg bg-white shadow-xl">
|
|
124
85
|
<div className="p-6">
|
|
125
|
-
<
|
|
86
|
+
<StoryFragmentTitlePanel nodeId={props.nodeId} />
|
|
126
87
|
</div>
|
|
127
88
|
</div>
|
|
128
89
|
</div>
|
|
@@ -130,96 +91,159 @@ export const Node = memo((props: NodeProps) => {
|
|
|
130
91
|
);
|
|
131
92
|
}
|
|
132
93
|
|
|
133
|
-
if (!
|
|
134
|
-
|
|
135
|
-
|
|
94
|
+
if (!hasPanes && !isPreview) {
|
|
95
|
+
return <EmptyPageHandler {...props} />;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return (
|
|
99
|
+
<>
|
|
100
|
+
<StoryFragmentConfigPanel
|
|
101
|
+
nodeId={props.nodeId}
|
|
102
|
+
isSandboxMode={props.isSandboxMode || false}
|
|
103
|
+
/>
|
|
104
|
+
<StoryFragment {...props} />
|
|
105
|
+
</>
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
case 'Pane':
|
|
109
|
+
{
|
|
110
|
+
const paneNode = node as PaneNode;
|
|
111
|
+
const storyfragmentNodeId = ctx.getClosestNodeTypeFromId(
|
|
112
|
+
node.id,
|
|
113
|
+
'StoryFragment'
|
|
114
|
+
);
|
|
115
|
+
const storyfragmentNode = ctx.allNodes
|
|
116
|
+
.get()
|
|
117
|
+
.get(storyfragmentNodeId) as StoryFragmentNode;
|
|
118
|
+
const first = paneNode.id === storyfragmentNode.paneIds?.[0];
|
|
119
|
+
const isHtmlAstPane = !!paneNode.htmlAst;
|
|
120
|
+
const paneNodes = ctx.getChildNodeIDs(node.id);
|
|
121
|
+
|
|
122
|
+
if (paneNode.isContextPane) {
|
|
123
|
+
if (!isPreview)
|
|
124
|
+
ctx.hasTitle.set(!(!paneNode.slug || !paneNode.title));
|
|
125
|
+
|
|
126
|
+
if (!isPreview && !(paneNode.slug && paneNode.title)) {
|
|
127
|
+
return (
|
|
128
|
+
<div
|
|
129
|
+
className="fixed inset-0 overflow-y-auto bg-black bg-opacity-75"
|
|
130
|
+
style={{ zIndex: 9005 }}
|
|
131
|
+
>
|
|
132
|
+
<div className="flex min-h-screen items-center justify-center p-1.5">
|
|
133
|
+
<div className="relative w-full max-w-4xl rounded-lg bg-white shadow-xl">
|
|
134
|
+
<div className="p-6">
|
|
135
|
+
<ContextPaneTitlePanel nodeId={props.nodeId} />
|
|
136
|
+
</div>
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
139
|
+
</div>
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (!isPreview && !paneNodes.length) {
|
|
144
|
+
return (
|
|
145
|
+
<>
|
|
146
|
+
<ContextPanePanel nodeId={node.id} />
|
|
147
|
+
<PanelVisibilityWrapper
|
|
148
|
+
nodeId={node.id}
|
|
149
|
+
panelType="add"
|
|
150
|
+
ctx={ctx}
|
|
151
|
+
>
|
|
152
|
+
<Pane {...props} />
|
|
153
|
+
</PanelVisibilityWrapper>
|
|
154
|
+
<AddPanePanel
|
|
155
|
+
nodeId={node.id}
|
|
156
|
+
first={true}
|
|
157
|
+
ctx={ctx}
|
|
158
|
+
isContextPane={true}
|
|
159
|
+
/>
|
|
160
|
+
</>
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const content = isHtmlAstPane ? (
|
|
166
|
+
<CreativePane nodeId={props.nodeId} htmlAst={paneNode.htmlAst!} />
|
|
167
|
+
) : (
|
|
168
|
+
<Pane {...props} />
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
element = (
|
|
136
172
|
<>
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
173
|
+
{first && (
|
|
174
|
+
<AddPanePanel nodeId={props.nodeId} first={true} ctx={ctx} />
|
|
175
|
+
)}
|
|
176
|
+
<div className="py-0.5">
|
|
177
|
+
<ConfigPanePanel
|
|
178
|
+
nodeId={props.nodeId}
|
|
179
|
+
isHtmlAstPane={isHtmlAstPane}
|
|
180
|
+
isSandboxMode={props.isSandboxMode || false}
|
|
181
|
+
/>
|
|
182
|
+
<PanelVisibilityWrapper
|
|
183
|
+
nodeId={props.nodeId}
|
|
184
|
+
panelType="settings"
|
|
185
|
+
ctx={ctx}
|
|
186
|
+
>
|
|
187
|
+
{content}
|
|
188
|
+
</PanelVisibilityWrapper>
|
|
189
|
+
</div>
|
|
190
|
+
<AddPanePanel nodeId={props.nodeId} first={false} ctx={ctx} />
|
|
147
191
|
</>
|
|
148
192
|
);
|
|
149
193
|
}
|
|
150
|
-
|
|
194
|
+
break;
|
|
151
195
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
) : (
|
|
156
|
-
<Pane {...props} />
|
|
157
|
-
);
|
|
196
|
+
case 'BgPane':
|
|
197
|
+
element = <BgPaneWrapper {...props} />;
|
|
198
|
+
break;
|
|
158
199
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
{...props}
|
|
206
|
-
hook={hookData.hook}
|
|
207
|
-
value1={hookData.value1}
|
|
208
|
-
value2={hookData.value2}
|
|
209
|
-
value3={hookData.value3}
|
|
210
|
-
/>
|
|
211
|
-
) : null;
|
|
212
|
-
break;
|
|
200
|
+
case 'Markdown':
|
|
201
|
+
element = <Markdown {...props} />;
|
|
202
|
+
break;
|
|
203
|
+
|
|
204
|
+
case 'GridLayoutNode':
|
|
205
|
+
element = <GridLayout {...props} />;
|
|
206
|
+
break;
|
|
207
|
+
|
|
208
|
+
case 'TagElement': {
|
|
209
|
+
const flatNode = node as FlatNode;
|
|
210
|
+
|
|
211
|
+
switch (flatNode.tagName) {
|
|
212
|
+
case 'text':
|
|
213
|
+
element = <NodeText {...props} />;
|
|
214
|
+
break;
|
|
215
|
+
case 'img':
|
|
216
|
+
element = <NodeImg {...props} />;
|
|
217
|
+
break;
|
|
218
|
+
case 'a':
|
|
219
|
+
element = <NodeA {...props} />;
|
|
220
|
+
break;
|
|
221
|
+
case 'button':
|
|
222
|
+
element = <NodeButton {...props} />;
|
|
223
|
+
break;
|
|
224
|
+
case 'code': {
|
|
225
|
+
const hookData = parseCodeHook(node);
|
|
226
|
+
element = hookData ? (
|
|
227
|
+
<Widget
|
|
228
|
+
{...props}
|
|
229
|
+
hook={hookData.hook}
|
|
230
|
+
value1={hookData.value1}
|
|
231
|
+
value2={hookData.value2}
|
|
232
|
+
value3={hookData.value3}
|
|
233
|
+
/>
|
|
234
|
+
) : null;
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
default:
|
|
238
|
+
element = (
|
|
239
|
+
<NodeBasicTag
|
|
240
|
+
{...props}
|
|
241
|
+
tagName={flatNode.tagName as keyof JSX.IntrinsicElements}
|
|
242
|
+
isSelectableText={true}
|
|
243
|
+
/>
|
|
244
|
+
);
|
|
245
|
+
break;
|
|
213
246
|
}
|
|
214
|
-
default:
|
|
215
|
-
element = (
|
|
216
|
-
<NodeBasicTag
|
|
217
|
-
{...props}
|
|
218
|
-
tagName={flatNode.tagName as keyof JSX.IntrinsicElements}
|
|
219
|
-
isSelectableText={true}
|
|
220
|
-
/>
|
|
221
|
-
);
|
|
222
|
-
break;
|
|
223
247
|
}
|
|
224
248
|
}
|
|
225
249
|
|
|
@@ -497,7 +497,6 @@ export const NodeBasicTag = (props: NodeTagProps) => {
|
|
|
497
497
|
const updatedNode = {
|
|
498
498
|
...cloneDeep(node),
|
|
499
499
|
isPlaceholder: false,
|
|
500
|
-
isChanged: true,
|
|
501
500
|
};
|
|
502
501
|
ctx.modifyNodes([updatedNode]);
|
|
503
502
|
}
|
|
@@ -507,7 +506,7 @@ export const NodeBasicTag = (props: NodeTagProps) => {
|
|
|
507
506
|
const paneNode = cloneDeep(
|
|
508
507
|
ctx.allNodes.get().get(paneNodeId)
|
|
509
508
|
) as PaneNode;
|
|
510
|
-
ctx.modifyNodes([
|
|
509
|
+
ctx.modifyNodes([paneNode]);
|
|
511
510
|
}
|
|
512
511
|
}
|
|
513
512
|
} catch (error) {
|
|
@@ -573,7 +572,6 @@ export const NodeBasicTag = (props: NodeTagProps) => {
|
|
|
573
572
|
const updatedNode = {
|
|
574
573
|
...cloneDeep(node),
|
|
575
574
|
isPlaceholder: false,
|
|
576
|
-
isChanged: true,
|
|
577
575
|
};
|
|
578
576
|
ctx.modifyNodes([updatedNode]);
|
|
579
577
|
}
|
|
@@ -591,7 +589,7 @@ export const NodeBasicTag = (props: NodeTagProps) => {
|
|
|
591
589
|
const paneNode = cloneDeep(
|
|
592
590
|
ctx.allNodes.get().get(paneNodeId)
|
|
593
591
|
) as PaneNode;
|
|
594
|
-
ctx.modifyNodes([
|
|
592
|
+
ctx.modifyNodes([paneNode]);
|
|
595
593
|
}
|
|
596
594
|
|
|
597
595
|
ctx.clearEditLock();
|
|
@@ -34,7 +34,6 @@ const StoryKeepHeader = ({
|
|
|
34
34
|
const viewport = useStore(viewportModeStore);
|
|
35
35
|
const pendingHomePageSlug = useStore(pendingHomePageSlugStore);
|
|
36
36
|
const ctx = getCtx();
|
|
37
|
-
const showSaveBypass = useStore(ctx.showSaveBypass);
|
|
38
37
|
const hasTitle = useStore(ctx.hasTitle);
|
|
39
38
|
const hasPanes = useStore(ctx.hasPanes);
|
|
40
39
|
const [canUndo, setCanUndo] = useState(false);
|
|
@@ -124,7 +123,7 @@ const StoryKeepHeader = ({
|
|
|
124
123
|
];
|
|
125
124
|
|
|
126
125
|
// Show save button if there are undo changes OR pending home page change
|
|
127
|
-
const shouldShowSave = canUndo || pendingHomePageSlug
|
|
126
|
+
const shouldShowSave = canUndo || pendingHomePageSlug;
|
|
128
127
|
|
|
129
128
|
if (!hasTitle && !hasPanes) return null;
|
|
130
129
|
|
|
@@ -203,12 +202,9 @@ const StoryKeepHeader = ({
|
|
|
203
202
|
console.log('Total Nodes in Store:', allNodesArray.length);
|
|
204
203
|
console.log('Full Nodes Map:', allNodesMap);
|
|
205
204
|
|
|
206
|
-
// Specifically audit Creative Panes for large htmlAst payloads
|
|
207
|
-
// Using type guards/property checks to handle the BaseNode vs PaneNode distinction
|
|
208
205
|
const creativePanes = allNodesArray.filter(
|
|
209
206
|
(n) => n.nodeType === 'Pane' && 'htmlAst' in n
|
|
210
207
|
);
|
|
211
|
-
|
|
212
208
|
if (creativePanes.length > 0) {
|
|
213
209
|
console.group('Creative Panes Detail (htmlAst Audit)');
|
|
214
210
|
creativePanes.forEach((pane) => {
|
|
@@ -229,7 +225,7 @@ const StoryKeepHeader = ({
|
|
|
229
225
|
}}
|
|
230
226
|
className="rounded-md bg-myblue px-3.5 py-1.5 font-action font-bold text-white hover:bg-myorange"
|
|
231
227
|
>
|
|
232
|
-
|
|
228
|
+
Nodes Dump
|
|
233
229
|
</button>
|
|
234
230
|
)}
|
|
235
231
|
|
|
@@ -57,7 +57,7 @@ const PaneSlugPanel = ({ nodeId, setMode }: PaneSlugPanelProps) => {
|
|
|
57
57
|
if (slug.length >= 3) {
|
|
58
58
|
// Only update if meets minimum length
|
|
59
59
|
const ctx = getCtx();
|
|
60
|
-
const updatedNode = { ...cloneDeep(paneNode), slug
|
|
60
|
+
const updatedNode = { ...cloneDeep(paneNode), slug };
|
|
61
61
|
ctx.modifyNodes([updatedNode]);
|
|
62
62
|
}
|
|
63
63
|
};
|
|
@@ -114,6 +114,7 @@ const AddPaneBreakPanel = ({
|
|
|
114
114
|
useEffect(() => {
|
|
115
115
|
const newPreviews = filteredVariants.map((variant, index: number) => {
|
|
116
116
|
const ctx = new NodesContext();
|
|
117
|
+
ctx.isTemplate.set(true);
|
|
117
118
|
ctx.addNode(createEmptyStorykeep('tmp'));
|
|
118
119
|
const template = templateCategory.getTemplatesByVariant(variant)[0];
|
|
119
120
|
ctx.addTemplatePane('tmp', template);
|
|
@@ -134,22 +134,18 @@ const AddPaneNewPanel = ({
|
|
|
134
134
|
|
|
135
135
|
if (isContextPane) {
|
|
136
136
|
insertTemplate.isContextPane = true;
|
|
137
|
-
|
|
138
|
-
tmpCtx.addContextTemplatePane(ownerId, insertTemplate);
|
|
139
|
-
});
|
|
137
|
+
ctx.addContextTemplatePane(ownerId, insertTemplate);
|
|
140
138
|
} else {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
);
|
|
148
|
-
});
|
|
139
|
+
ctx.addTemplatePane(
|
|
140
|
+
ownerId,
|
|
141
|
+
insertTemplate,
|
|
142
|
+
nodeId,
|
|
143
|
+
first ? 'before' : 'after'
|
|
144
|
+
);
|
|
149
145
|
const storyFragment = cloneDeep(
|
|
150
146
|
ctx.allNodes.get().get(ownerId)
|
|
151
147
|
) as StoryFragmentNode;
|
|
152
|
-
ctx.modifyNodes([{ ...storyFragment
|
|
148
|
+
ctx.modifyNodes([{ ...storyFragment }]);
|
|
153
149
|
}
|
|
154
150
|
ctx.notifyNode(`root`);
|
|
155
151
|
setParentMode(PaneAddMode.DEFAULT, false);
|
|
@@ -91,11 +91,15 @@ const AddPaneReUsePanel = ({
|
|
|
91
91
|
pane.slug.toLowerCase().includes(query.toLowerCase())
|
|
92
92
|
);
|
|
93
93
|
|
|
94
|
-
const newPreviews = filteredPanes.map((pane, index) =>
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
94
|
+
const newPreviews = filteredPanes.map((pane, index) => {
|
|
95
|
+
const previewCtx = new NodesContext();
|
|
96
|
+
previewCtx.isTemplate.set(true);
|
|
97
|
+
return {
|
|
98
|
+
ctx: previewCtx,
|
|
99
|
+
pane,
|
|
100
|
+
index,
|
|
101
|
+
};
|
|
102
|
+
});
|
|
99
103
|
|
|
100
104
|
setPreviews(newPreviews);
|
|
101
105
|
setCurrentPage(0);
|
|
@@ -194,7 +198,6 @@ const AddPaneReUsePanel = ({
|
|
|
194
198
|
);
|
|
195
199
|
}
|
|
196
200
|
}
|
|
197
|
-
storyFragmentNode.isChanged = true;
|
|
198
201
|
|
|
199
202
|
ctx.addNode(templateData.paneNode);
|
|
200
203
|
ctx.linkChildToParent(
|
|
@@ -7,75 +7,13 @@ import SparklesIcon from '@heroicons/react/24/outline/SparklesIcon';
|
|
|
7
7
|
import { getCtx } from '@/stores/nodes';
|
|
8
8
|
import { selectionStore } from '@/stores/selection';
|
|
9
9
|
import { renderedPreviews } from '@/stores/previews';
|
|
10
|
-
import { sandboxTokenStore } from '@/stores/storykeep';
|
|
11
10
|
import { AiDesignStep, type AiDesignConfig } from './steps/AiDesignStep';
|
|
12
11
|
import { AiRefineDesignStep } from './steps/AiRefineDesignStep';
|
|
13
12
|
import prompts from '@/constants/prompts.json';
|
|
14
|
-
import { TractStackAPI } from '@/utils/api';
|
|
15
13
|
import { parseAiPane } from '@/utils/compositor/aiPaneParser';
|
|
14
|
+
import { callAskLemurAPI } from '@/utils/compositor/aiGeneration';
|
|
16
15
|
import type { PaneNode, TemplatePane } from '@/types/compositorTypes';
|
|
17
16
|
|
|
18
|
-
const callAskLemurAPI = async (
|
|
19
|
-
prompt: string,
|
|
20
|
-
context: string,
|
|
21
|
-
expectJson: boolean,
|
|
22
|
-
isSandboxMode: boolean
|
|
23
|
-
): Promise<string> => {
|
|
24
|
-
const tenantId =
|
|
25
|
-
(window as any).TRACTSTACK_CONFIG?.tenantId ||
|
|
26
|
-
import.meta.env.PUBLIC_TENANTID ||
|
|
27
|
-
'default';
|
|
28
|
-
const api = new TractStackAPI(tenantId);
|
|
29
|
-
|
|
30
|
-
const requestBody = {
|
|
31
|
-
prompt,
|
|
32
|
-
input_text: context,
|
|
33
|
-
final_model: '',
|
|
34
|
-
temperature: 0.5,
|
|
35
|
-
max_tokens: 10000,
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
let resultData: any;
|
|
39
|
-
|
|
40
|
-
if (isSandboxMode) {
|
|
41
|
-
const token = sandboxTokenStore.get();
|
|
42
|
-
const response = await fetch(`/api/sandbox`, {
|
|
43
|
-
method: 'POST',
|
|
44
|
-
headers: {
|
|
45
|
-
'Content-Type': 'application/json',
|
|
46
|
-
'X-Tenant-ID': tenantId,
|
|
47
|
-
'X-Sandbox-Token': token || '',
|
|
48
|
-
},
|
|
49
|
-
credentials: 'include',
|
|
50
|
-
body: JSON.stringify({ action: 'askLemur', payload: requestBody }),
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
if (!response.ok) {
|
|
54
|
-
const errorText = await response.text();
|
|
55
|
-
throw new Error(`Sandbox API failed: ${response.status} ${errorText}`);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const json = await response.json();
|
|
59
|
-
if (!json.success) {
|
|
60
|
-
throw new Error(json.error || 'Sandbox generation failed');
|
|
61
|
-
}
|
|
62
|
-
resultData = json.data;
|
|
63
|
-
} else {
|
|
64
|
-
const response = await api.post('/api/v1/aai/askLemur', requestBody);
|
|
65
|
-
if (!response.success || !response.data?.response) {
|
|
66
|
-
throw new Error(response.error || 'AI generation failed');
|
|
67
|
-
}
|
|
68
|
-
resultData = response.data;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
let raw = resultData.response;
|
|
72
|
-
if (typeof raw === 'string') {
|
|
73
|
-
if (raw.startsWith('```json')) raw = raw.slice(7, -3).trim();
|
|
74
|
-
}
|
|
75
|
-
if (expectJson && typeof raw === 'object') return JSON.stringify(raw);
|
|
76
|
-
return raw;
|
|
77
|
-
};
|
|
78
|
-
|
|
79
17
|
interface AiRestylePaneModalProps {
|
|
80
18
|
isSandboxMode?: boolean;
|
|
81
19
|
}
|
|
@@ -149,12 +87,12 @@ export const AiRestylePaneModal = ({
|
|
|
149
87
|
.replace('{{COPY_INPUT}}', 'A generic content section')
|
|
150
88
|
.replace('{{LAYOUT_TYPE}}', 'Text Only');
|
|
151
89
|
|
|
152
|
-
const resultStr = await callAskLemurAPI(
|
|
153
|
-
formattedPrompt,
|
|
154
|
-
shellPromptDetails.system || '',
|
|
155
|
-
true,
|
|
156
|
-
isSandboxMode
|
|
157
|
-
);
|
|
90
|
+
const resultStr = await callAskLemurAPI({
|
|
91
|
+
prompt: formattedPrompt,
|
|
92
|
+
context: shellPromptDetails.system || '',
|
|
93
|
+
expectJson: true,
|
|
94
|
+
isSandboxMode,
|
|
95
|
+
});
|
|
158
96
|
|
|
159
97
|
let dummyCopy: string | string[] = '';
|
|
160
98
|
if (isGrid) {
|
|
@@ -252,7 +252,7 @@ const ConfigPanePanel = ({
|
|
|
252
252
|
</div>
|
|
253
253
|
|
|
254
254
|
{/* Design Library Tools (Right Aligned) */}
|
|
255
|
-
<div className="ml-auto flex items-center gap-2 border-l border-gray-300
|
|
255
|
+
<div className="ml-auto flex items-center gap-2 border-l border-gray-300 px-2">
|
|
256
256
|
{!isHtmlAstPane && !isSandboxMode && (
|
|
257
257
|
<button
|
|
258
258
|
title="Save Pane to Design Library"
|
|
@@ -280,7 +280,7 @@ const ConfigPanePanel = ({
|
|
|
280
280
|
<ArrowPathRoundedSquareIcon className="h-4 w-4 text-white" />
|
|
281
281
|
</button>
|
|
282
282
|
)}
|
|
283
|
-
{import.meta.env.DEV && (
|
|
283
|
+
{import.meta.env.DEV && !isHtmlAstPane && (
|
|
284
284
|
<button
|
|
285
285
|
title="Copy Pane Design to Clipboard"
|
|
286
286
|
onClick={handleCopyToClipboard}
|