astro-tractstack 2.2.2 → 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 -134
- package/templates/src/components/compositor/nodes/tagElements/NodeBasicTag.tsx +2 -4
- package/templates/src/components/edit/Header.tsx +1 -2
- 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/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
|
@@ -4,7 +4,7 @@ import CheckIcon from '@heroicons/react/24/outline/CheckIcon';
|
|
|
4
4
|
import XMarkIcon from '@heroicons/react/24/outline/XMarkIcon';
|
|
5
5
|
import ArrowPathRoundedSquareIcon from '@heroicons/react/24/outline/ArrowPathRoundedSquareIcon';
|
|
6
6
|
import prompts from '@/constants/prompts.json';
|
|
7
|
-
import { htmlToHtmlAst } from '@/utils/compositor/htmlAst';
|
|
7
|
+
import { htmlToHtmlAst, cleanHtml } from '@/utils/compositor/htmlAst';
|
|
8
8
|
import { callAskLemurAPI } from '@/utils/compositor/aiGeneration';
|
|
9
9
|
import type { TemplatePane } from '@/types/compositorTypes';
|
|
10
10
|
|
|
@@ -51,7 +51,7 @@ export const AiRefineDesignStep = ({
|
|
|
51
51
|
|
|
52
52
|
userPrompt = userPrompt.replace('{{DESIGN_NOTES}}', prompt);
|
|
53
53
|
userPrompt = userPrompt.replace('{{CSS_INPUT}}', initialCss);
|
|
54
|
-
userPrompt = userPrompt.replace('{{HTML_INPUT}}', initialHtml);
|
|
54
|
+
userPrompt = userPrompt.replace('{{HTML_INPUT}}', cleanHtml(initialHtml));
|
|
55
55
|
|
|
56
56
|
// 1. Get RAW output from AI
|
|
57
57
|
const resultHtml = await callAskLemurAPI({
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { useState, useCallback, useMemo, useEffect } from 'react';
|
|
2
2
|
import prompts from '@/constants/prompts.json';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
parseAiPane,
|
|
5
|
+
createDefaultShell,
|
|
6
|
+
} from '@/utils/compositor/aiPaneParser';
|
|
4
7
|
import { callAskLemurAPI } from '@/utils/compositor/aiGeneration';
|
|
8
|
+
import { markdownToHtml } from '@/utils/compositor/htmlAst';
|
|
5
9
|
import { CopyInputStep, type CopyMode } from './CopyInputStep';
|
|
6
10
|
import { AiDesignStep, type AiDesignConfig } from './AiDesignStep';
|
|
7
11
|
import BooleanToggle from '@/components/form/BooleanToggle';
|
|
@@ -43,10 +47,13 @@ export const AiStandardDesignStep = ({
|
|
|
43
47
|
const [col1Copy, setCol1Copy] = useState('');
|
|
44
48
|
const [col2Copy, setCol2Copy] = useState('');
|
|
45
49
|
|
|
50
|
+
// Prompts State
|
|
46
51
|
const [masterShellSystem, setMasterShellSystem] = useState('');
|
|
47
52
|
const [masterShellUser, setMasterShellUser] = useState('');
|
|
48
53
|
const [masterCopySystem, setMasterCopySystem] = useState('');
|
|
49
54
|
const [masterCopyUser, setMasterCopyUser] = useState('');
|
|
55
|
+
const [masterStyleSystem, setMasterStyleSystem] = useState('');
|
|
56
|
+
const [masterStyleUser, setMasterStyleUser] = useState('');
|
|
50
57
|
|
|
51
58
|
const [aiDesignConfig, setAiDesignConfig] = useState<AiDesignConfig>({
|
|
52
59
|
harmony: 'Analogous',
|
|
@@ -75,6 +82,7 @@ export const AiStandardDesignStep = ({
|
|
|
75
82
|
}
|
|
76
83
|
}, [promptOptions, selectedPromptId]);
|
|
77
84
|
|
|
85
|
+
// Load Prompt Templates
|
|
78
86
|
useEffect(() => {
|
|
79
87
|
if (!selectedPromptId) return;
|
|
80
88
|
|
|
@@ -85,8 +93,11 @@ export const AiStandardDesignStep = ({
|
|
|
85
93
|
|
|
86
94
|
const promptKey = activeConfig.prompts.copy;
|
|
87
95
|
const shellKey = activeConfig.prompts.shell;
|
|
96
|
+
const styleKey = activeConfig.prompts.style; // New: Load style prompt key
|
|
97
|
+
|
|
88
98
|
const copyPromptGroup = (prompts as any)[promptKey];
|
|
89
99
|
const shellPromptGroup = (prompts as any)[shellKey];
|
|
100
|
+
const stylePromptGroup = (prompts as any)[styleKey];
|
|
90
101
|
|
|
91
102
|
if (shellPromptGroup) {
|
|
92
103
|
setMasterShellSystem(shellPromptGroup.system || '');
|
|
@@ -96,6 +107,10 @@ export const AiStandardDesignStep = ({
|
|
|
96
107
|
setMasterCopySystem(copyPromptGroup.system || '');
|
|
97
108
|
setMasterCopyUser(copyPromptGroup.user_template || '');
|
|
98
109
|
}
|
|
110
|
+
if (stylePromptGroup) {
|
|
111
|
+
setMasterStyleSystem(stylePromptGroup.system || '');
|
|
112
|
+
setMasterStyleUser(stylePromptGroup.user_template || '');
|
|
113
|
+
}
|
|
99
114
|
|
|
100
115
|
if (!copyPromptGroup) return;
|
|
101
116
|
|
|
@@ -126,65 +141,128 @@ export const AiStandardDesignStep = ({
|
|
|
126
141
|
);
|
|
127
142
|
if (!activeConfig) throw new Error('Selected prompt type not found.');
|
|
128
143
|
|
|
129
|
-
let designInput = `Generate a design using a **${aiDesignConfig.harmony.toLowerCase()}** color scheme with a **${aiDesignConfig.theme.toLowerCase()}** theme.`;
|
|
130
|
-
if (aiDesignConfig.baseColor)
|
|
131
|
-
designInput += ` Base the colors around **${aiDesignConfig.baseColor}**.`;
|
|
132
|
-
if (aiDesignConfig.accentColor)
|
|
133
|
-
designInput += ` Use **${aiDesignConfig.accentColor}** as an accent color.`;
|
|
134
|
-
if (additionalNotes)
|
|
135
|
-
designInput += ` Refine with these notes: "${additionalNotes}"`;
|
|
136
|
-
|
|
137
144
|
const layoutType = 'Text Only';
|
|
138
145
|
const promptMap = prompts as any;
|
|
139
146
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
let formattedShellPrompt = masterShellUser
|
|
145
|
-
.replace('{{DESIGN_INPUT}}', designInput)
|
|
146
|
-
.replace('{{LAYOUT_TYPE}}', layoutType);
|
|
147
|
+
// --- 1. Shell Generation ---
|
|
148
|
+
let shellResult = '';
|
|
147
149
|
|
|
148
|
-
if (
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
)
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
prompt: formattedShellPrompt,
|
|
158
|
-
context: masterShellSystem,
|
|
159
|
-
expectJson: true,
|
|
160
|
-
isSandboxMode,
|
|
161
|
-
});
|
|
150
|
+
if (isAiStyling) {
|
|
151
|
+
// AI Path: Generate Shell via AskLemur
|
|
152
|
+
let designInput = `Generate a design using a **${aiDesignConfig.harmony.toLowerCase()}** color scheme with a **${aiDesignConfig.theme.toLowerCase()}** theme.`;
|
|
153
|
+
if (aiDesignConfig.baseColor)
|
|
154
|
+
designInput += ` Base the colors around **${aiDesignConfig.baseColor}**.`;
|
|
155
|
+
if (aiDesignConfig.accentColor)
|
|
156
|
+
designInput += ` Use **${aiDesignConfig.accentColor}** as an accent color.`;
|
|
157
|
+
if (additionalNotes)
|
|
158
|
+
designInput += ` Refine with these notes: "${additionalNotes}"`;
|
|
162
159
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
160
|
+
const injectTopic = (text: string) => {
|
|
161
|
+
return text.replace('{{TOPIC}}', topic.trim());
|
|
162
|
+
};
|
|
166
163
|
|
|
167
|
-
|
|
168
|
-
.replace('{{COPY_INPUT}}', copyInputContent)
|
|
164
|
+
let formattedShellPrompt = masterShellUser
|
|
169
165
|
.replace('{{DESIGN_INPUT}}', designInput)
|
|
170
|
-
.replace('{{LAYOUT_TYPE}}', layoutType)
|
|
171
|
-
|
|
166
|
+
.replace('{{LAYOUT_TYPE}}', layoutType);
|
|
167
|
+
|
|
168
|
+
if (layoutChoice === 'grid') {
|
|
169
|
+
const finalOverallPrompt = injectTopic(overallPrompt);
|
|
170
|
+
formattedShellPrompt = formattedShellPrompt.replace(
|
|
171
|
+
'{{COPY_INPUT}}',
|
|
172
|
+
finalOverallPrompt
|
|
173
|
+
);
|
|
174
|
+
}
|
|
172
175
|
|
|
173
|
-
|
|
174
|
-
prompt:
|
|
175
|
-
context:
|
|
176
|
-
expectJson:
|
|
176
|
+
shellResult = await callAskLemurAPI({
|
|
177
|
+
prompt: formattedShellPrompt,
|
|
178
|
+
context: masterShellSystem,
|
|
179
|
+
expectJson: true,
|
|
177
180
|
isSandboxMode,
|
|
178
181
|
});
|
|
182
|
+
} else {
|
|
183
|
+
// No AI Path: Use Default Shell
|
|
184
|
+
shellResult = JSON.stringify(createDefaultShell(layoutChoice));
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const designInputForCopy = isAiStyling
|
|
188
|
+
? `Using a **${aiDesignConfig.harmony.toLowerCase()}** color scheme.`
|
|
189
|
+
: 'Use the provided default classes.';
|
|
190
|
+
|
|
191
|
+
// --- 2. Content Generation ---
|
|
192
|
+
if (layoutChoice === 'standard') {
|
|
193
|
+
let finalHtml = '';
|
|
194
|
+
|
|
195
|
+
if (copyMode === 'prompt') {
|
|
196
|
+
// A. Prompt Mode: AI writes copy
|
|
197
|
+
const injectTopic = (text: string) =>
|
|
198
|
+
text.replace('{{TOPIC}}', topic.trim());
|
|
199
|
+
const copyInputContent = injectTopic(promptValue);
|
|
200
|
+
|
|
201
|
+
const formattedCopyPrompt = masterCopyUser
|
|
202
|
+
.replace('{{COPY_INPUT}}', copyInputContent)
|
|
203
|
+
.replace('{{DESIGN_INPUT}}', designInputForCopy)
|
|
204
|
+
.replace('{{LAYOUT_TYPE}}', layoutType)
|
|
205
|
+
.replace('{{SHELL_JSON}}', shellResult);
|
|
206
|
+
|
|
207
|
+
finalHtml = await callAskLemurAPI({
|
|
208
|
+
prompt: formattedCopyPrompt,
|
|
209
|
+
context: masterCopySystem,
|
|
210
|
+
expectJson: false,
|
|
211
|
+
isSandboxMode,
|
|
212
|
+
});
|
|
213
|
+
} else {
|
|
214
|
+
// B. Raw Mode: User provided markdown
|
|
215
|
+
if (isAiStyling) {
|
|
216
|
+
// Style with AI: Use the 'style' prompt to format markdown
|
|
217
|
+
const formattedStylePrompt = masterStyleUser
|
|
218
|
+
.replace('{{SHELL_JSON}}', shellResult)
|
|
219
|
+
.replace('{{COPY_INPUT}}', copyValue);
|
|
220
|
+
|
|
221
|
+
finalHtml = await callAskLemurAPI({
|
|
222
|
+
prompt: formattedStylePrompt,
|
|
223
|
+
context: masterStyleSystem,
|
|
224
|
+
expectJson: false,
|
|
225
|
+
isSandboxMode,
|
|
226
|
+
});
|
|
227
|
+
} else {
|
|
228
|
+
// No AI: Local conversion
|
|
229
|
+
finalHtml = markdownToHtml(copyValue);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
179
232
|
|
|
180
|
-
const finalPane = parseAiPane(shellResult,
|
|
233
|
+
const finalPane = parseAiPane(shellResult, finalHtml, layoutType);
|
|
181
234
|
onCreatePane(finalPane);
|
|
182
235
|
} else if (layoutChoice === 'grid') {
|
|
236
|
+
// --- Grid Layout Path ---
|
|
183
237
|
if (copyMode === 'raw') {
|
|
238
|
+
// B. Raw Mode (Grid)
|
|
184
239
|
const rawContents = [col1Copy, col2Copy];
|
|
185
|
-
|
|
240
|
+
let finalContents: string[] = [];
|
|
241
|
+
|
|
242
|
+
if (isAiStyling) {
|
|
243
|
+
// Style with AI: Loop through columns and style each
|
|
244
|
+
for (const content of rawContents) {
|
|
245
|
+
const formattedStylePrompt = masterStyleUser
|
|
246
|
+
.replace('{{SHELL_JSON}}', shellResult)
|
|
247
|
+
.replace('{{COPY_INPUT}}', content);
|
|
248
|
+
|
|
249
|
+
const styledHtml = await callAskLemurAPI({
|
|
250
|
+
prompt: formattedStylePrompt,
|
|
251
|
+
context: masterStyleSystem,
|
|
252
|
+
expectJson: false,
|
|
253
|
+
isSandboxMode,
|
|
254
|
+
});
|
|
255
|
+
finalContents.push(styledHtml);
|
|
256
|
+
}
|
|
257
|
+
} else {
|
|
258
|
+
// No AI: Local conversion
|
|
259
|
+
finalContents = rawContents.map(markdownToHtml);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const finalPane = parseAiPane(shellResult, finalContents, layoutType);
|
|
186
263
|
onCreatePane(finalPane);
|
|
187
264
|
} else {
|
|
265
|
+
// A. Prompt Mode (Grid): AI writes copy
|
|
188
266
|
const copyPromptKey = activeConfig.prompts.copy;
|
|
189
267
|
const copyPromptDetails = promptMap[copyPromptKey];
|
|
190
268
|
const preset =
|
|
@@ -192,6 +270,9 @@ export const AiStandardDesignStep = ({
|
|
|
192
270
|
copyPromptDetails.presets?.heroDefault;
|
|
193
271
|
const copyResults: string[] = [];
|
|
194
272
|
|
|
273
|
+
const injectTopic = (text: string) =>
|
|
274
|
+
text.replace('{{TOPIC}}', topic.trim());
|
|
275
|
+
|
|
195
276
|
const promptsToRun = [
|
|
196
277
|
{ prompt: promptValueCol1, presetKey: 'left' as ColumnPresetKey },
|
|
197
278
|
{ prompt: promptValueCol2, presetKey: 'right' as ColumnPresetKey },
|
|
@@ -204,7 +285,7 @@ export const AiStandardDesignStep = ({
|
|
|
204
285
|
.replace('{{SHELL_JSON}}', shellResult)
|
|
205
286
|
.replace('{{COPY_INPUT}}', injectTopic(overallPrompt))
|
|
206
287
|
.replace('{{COLUMN_PROMPT}}', item.prompt)
|
|
207
|
-
.replace('{{DESIGN_INPUT}}',
|
|
288
|
+
.replace('{{DESIGN_INPUT}}', designInputForCopy)
|
|
208
289
|
.replace('{{LAYOUT_TYPE}}', layoutType)
|
|
209
290
|
.replace('{{COLUMN_EXAMPLE}}', columnPreset.example);
|
|
210
291
|
|
|
@@ -245,16 +326,25 @@ export const AiStandardDesignStep = ({
|
|
|
245
326
|
masterShellSystem,
|
|
246
327
|
masterCopyUser,
|
|
247
328
|
masterCopySystem,
|
|
329
|
+
masterStyleUser,
|
|
330
|
+
masterStyleSystem,
|
|
248
331
|
topic,
|
|
332
|
+
isAiStyling, // Added dependency
|
|
249
333
|
]);
|
|
250
334
|
|
|
251
335
|
if (isGenerating) {
|
|
252
336
|
return (
|
|
253
337
|
<div className="flex min-h-96 flex-col items-center justify-center space-y-4 p-6">
|
|
254
338
|
<div className="h-8 w-8 animate-spin rounded-full border-b-2 border-cyan-600"></div>
|
|
255
|
-
<p className="text-sm text-gray-600">
|
|
339
|
+
<p className="text-sm text-gray-600">
|
|
340
|
+
{isAiStyling
|
|
341
|
+
? 'Generating Design & Content...'
|
|
342
|
+
: 'Processing Content...'}
|
|
343
|
+
</p>
|
|
256
344
|
<p className="text-xs text-gray-500">
|
|
257
|
-
|
|
345
|
+
{isAiStyling
|
|
346
|
+
? 'Creating a unique layout from scratch.'
|
|
347
|
+
: 'Applying standard formatting.'}
|
|
258
348
|
</p>
|
|
259
349
|
</div>
|
|
260
350
|
);
|
|
@@ -301,42 +391,45 @@ export const AiStandardDesignStep = ({
|
|
|
301
391
|
masterCopyUser={masterCopyUser}
|
|
302
392
|
setMasterCopyUser={setMasterCopyUser}
|
|
303
393
|
>
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
<BooleanToggle
|
|
324
|
-
label="Customize Colors"
|
|
325
|
-
value={showColors}
|
|
326
|
-
onChange={setShowColors}
|
|
327
|
-
size="sm"
|
|
328
|
-
/>
|
|
329
|
-
</div>
|
|
394
|
+
{/* Style config is only relevant if AI Styling is ON */}
|
|
395
|
+
{isAiStyling && (
|
|
396
|
+
<div className="border-t pt-4">
|
|
397
|
+
<div>
|
|
398
|
+
<label
|
|
399
|
+
htmlFor="dashboard-notes"
|
|
400
|
+
className="block text-sm font-bold text-gray-700"
|
|
401
|
+
>
|
|
402
|
+
Design Notes
|
|
403
|
+
</label>
|
|
404
|
+
<textarea
|
|
405
|
+
id="dashboard-notes"
|
|
406
|
+
rows={2}
|
|
407
|
+
className="mt-1 block w-full rounded-md border-gray-300 px-3 py-2 text-sm shadow-sm focus:border-cyan-500 focus:ring-cyan-500"
|
|
408
|
+
placeholder="e.g. Clean, minimal, high contrast..."
|
|
409
|
+
value={additionalNotes}
|
|
410
|
+
onChange={(e) => setAdditionalNotes(e.target.value)}
|
|
411
|
+
/>
|
|
412
|
+
</div>
|
|
330
413
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
414
|
+
<div className="my-4 flex items-center">
|
|
415
|
+
<BooleanToggle
|
|
416
|
+
label="Customize Colors"
|
|
417
|
+
value={showColors}
|
|
418
|
+
onChange={setShowColors}
|
|
419
|
+
size="sm"
|
|
336
420
|
/>
|
|
337
421
|
</div>
|
|
338
|
-
|
|
339
|
-
|
|
422
|
+
|
|
423
|
+
{showColors && (
|
|
424
|
+
<div className="rounded-lg border border-gray-100 bg-gray-50 p-4">
|
|
425
|
+
<AiDesignStep
|
|
426
|
+
designConfig={aiDesignConfig}
|
|
427
|
+
onDesignConfigChange={setAiDesignConfig}
|
|
428
|
+
/>
|
|
429
|
+
</div>
|
|
430
|
+
)}
|
|
431
|
+
</div>
|
|
432
|
+
)}
|
|
340
433
|
</CopyInputStep>
|
|
341
434
|
|
|
342
435
|
{error && (
|
|
@@ -363,7 +456,7 @@ export const AiStandardDesignStep = ({
|
|
|
363
456
|
}
|
|
364
457
|
className="rounded-md bg-cyan-600 px-6 py-2 text-sm font-bold text-white shadow-sm hover:bg-cyan-700 disabled:cursor-not-allowed disabled:bg-gray-400"
|
|
365
458
|
>
|
|
366
|
-
✨ Generate Pane
|
|
459
|
+
{isAiStyling ? '✨ Generate Pane' : 'Create Pane'}
|
|
367
460
|
</button>
|
|
368
461
|
</div>
|
|
369
462
|
</div>
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { useState } from 'react';
|
|
2
|
-
import { getCtx } from '@/stores/nodes';
|
|
3
2
|
import { htmlToHtmlAst } from '@/utils/compositor/htmlAst';
|
|
4
3
|
import type { TemplatePane } from '@/types/compositorTypes';
|
|
5
4
|
|
|
@@ -28,7 +27,6 @@ export const CreativeInjectStep = ({
|
|
|
28
27
|
|
|
29
28
|
try {
|
|
30
29
|
const htmlAst = await htmlToHtmlAst(html, css);
|
|
31
|
-
|
|
32
30
|
const template: TemplatePane = {
|
|
33
31
|
id: '',
|
|
34
32
|
nodeType: 'Pane',
|
|
@@ -48,10 +46,7 @@ export const CreativeInjectStep = ({
|
|
|
48
46
|
nodes: [],
|
|
49
47
|
},
|
|
50
48
|
};
|
|
51
|
-
|
|
52
49
|
onCreatePane(template);
|
|
53
|
-
const ctx = getCtx();
|
|
54
|
-
ctx.showSaveBypass.set(true);
|
|
55
50
|
} catch (err: any) {
|
|
56
51
|
console.error('Compiler Error:', err);
|
|
57
52
|
setError(`Compilation failed: ${err.message}`);
|
|
@@ -56,8 +56,9 @@ const TemplatePreviewItem = ({
|
|
|
56
56
|
);
|
|
57
57
|
|
|
58
58
|
const fragmentRequest = useMemo((): PanePreviewRequest[] => {
|
|
59
|
-
// This preview logic
|
|
59
|
+
// This preview logic creates a *temporary* context.
|
|
60
60
|
const ctx = new NodesContext();
|
|
61
|
+
ctx.isTemplate.set(true);
|
|
61
62
|
ctx.addNode(createEmptyStorykeep('tmp'));
|
|
62
63
|
ctx.addTemplatePane('tmp', liveTemplate);
|
|
63
64
|
return [{ id: liveTemplate.id, ctx }];
|
|
@@ -104,10 +104,7 @@ const StyleBreakPanel = ({ node, parentNode }: BasePanelProps) => {
|
|
|
104
104
|
}
|
|
105
105
|
});
|
|
106
106
|
|
|
107
|
-
const updatedNodes = [
|
|
108
|
-
{ ...breakNode, isChanged: true },
|
|
109
|
-
{ ...paneNode, isChanged: true },
|
|
110
|
-
];
|
|
107
|
+
const updatedNodes = [{ ...breakNode }, { ...paneNode }];
|
|
111
108
|
ctx.modifyNodes(updatedNodes);
|
|
112
109
|
}, [settings, node, parentNode, ctx, allNodes]);
|
|
113
110
|
|
|
@@ -100,10 +100,7 @@ const StyleElementRemovePanel = ({
|
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
ctx.modifyNodes([
|
|
104
|
-
{ ...elementNode, isChanged: true },
|
|
105
|
-
{ ...markdownNode, isChanged: true },
|
|
106
|
-
]);
|
|
103
|
+
ctx.modifyNodes([{ ...elementNode }, { ...markdownNode }]);
|
|
107
104
|
resetStore();
|
|
108
105
|
};
|
|
109
106
|
|
|
@@ -131,7 +131,7 @@ const StyleElementUpdatePanel = ({
|
|
|
131
131
|
break;
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
ctx.modifyNodes([{ ...elementNode
|
|
134
|
+
ctx.modifyNodes([{ ...elementNode }]);
|
|
135
135
|
} else {
|
|
136
136
|
// Update default classes
|
|
137
137
|
const markdownNode = cloneDeep(
|
|
@@ -170,7 +170,7 @@ const StyleElementUpdatePanel = ({
|
|
|
170
170
|
break;
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
-
ctx.modifyNodes([{ ...markdownNode
|
|
173
|
+
ctx.modifyNodes([{ ...markdownNode }]);
|
|
174
174
|
}
|
|
175
175
|
|
|
176
176
|
setPendingUpdate(null);
|
|
@@ -251,7 +251,7 @@ const StyleElementUpdatePanel = ({
|
|
|
251
251
|
}
|
|
252
252
|
}
|
|
253
253
|
|
|
254
|
-
ctx.modifyNodes([{ ...elementNode
|
|
254
|
+
ctx.modifyNodes([{ ...elementNode }]);
|
|
255
255
|
setIsOverridden(checked);
|
|
256
256
|
},
|
|
257
257
|
[node, className, parentNode]
|
|
@@ -269,7 +269,7 @@ const StyleImagePanel = ({
|
|
|
269
269
|
const imgNode = cloneDeep(allNodes.get(node.id)) as FlatNode;
|
|
270
270
|
if (!imgNode) return;
|
|
271
271
|
imgNode.alt = newAlt;
|
|
272
|
-
ctx.modifyNodes([{ ...imgNode
|
|
272
|
+
ctx.modifyNodes([{ ...imgNode }]);
|
|
273
273
|
};
|
|
274
274
|
|
|
275
275
|
const handleImageUpdate = (params: ImageParams) => {
|
|
@@ -285,7 +285,7 @@ const StyleImagePanel = ({
|
|
|
285
285
|
params.altDescription || '!!This is requires a description!!'
|
|
286
286
|
);
|
|
287
287
|
if (params.srcSet) imgNode.srcSet = params.srcSet;
|
|
288
|
-
ctx.modifyNodes([{ ...imgNode
|
|
288
|
+
ctx.modifyNodes([{ ...imgNode }]);
|
|
289
289
|
};
|
|
290
290
|
|
|
291
291
|
const handleImageRemove = () => {
|
|
@@ -297,7 +297,7 @@ const StyleImagePanel = ({
|
|
|
297
297
|
imgNode.src = `/static.jpg`;
|
|
298
298
|
if (typeof imgNode.srcSet === `string`) delete imgNode.srcSet;
|
|
299
299
|
imgNode.alt = `This is a placeholder for an image that hasn't yet been uploaded`;
|
|
300
|
-
ctx.modifyNodes([{ ...imgNode
|
|
300
|
+
ctx.modifyNodes([{ ...imgNode }]);
|
|
301
301
|
};
|
|
302
302
|
|
|
303
303
|
if (
|
|
@@ -109,10 +109,7 @@ const StyleImageRemovePanel = ({
|
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
ctx.modifyNodes([
|
|
113
|
-
{ ...targetNode, isChanged: true },
|
|
114
|
-
{ ...parentNodeClone, isChanged: true },
|
|
115
|
-
]);
|
|
112
|
+
ctx.modifyNodes([{ ...targetNode }, { ...parentNodeClone }]);
|
|
116
113
|
resetStore();
|
|
117
114
|
};
|
|
118
115
|
|
|
@@ -18,7 +18,6 @@ const StyleImageUpdatePanel = ({
|
|
|
18
18
|
node,
|
|
19
19
|
parentNode,
|
|
20
20
|
className,
|
|
21
|
-
config,
|
|
22
21
|
childId,
|
|
23
22
|
}: BasePanelProps) => {
|
|
24
23
|
if (
|
|
@@ -119,7 +118,7 @@ const StyleImageUpdatePanel = ({
|
|
|
119
118
|
break;
|
|
120
119
|
}
|
|
121
120
|
|
|
122
|
-
ctx.modifyNodes([{ ...targetNode
|
|
121
|
+
ctx.modifyNodes([{ ...targetNode }]);
|
|
123
122
|
} else {
|
|
124
123
|
const markdownNode = cloneDeep(
|
|
125
124
|
allNodes.get(parentNode.id)
|
|
@@ -158,7 +157,7 @@ const StyleImageUpdatePanel = ({
|
|
|
158
157
|
break;
|
|
159
158
|
}
|
|
160
159
|
|
|
161
|
-
ctx.modifyNodes([{ ...markdownNode
|
|
160
|
+
ctx.modifyNodes([{ ...markdownNode }]);
|
|
162
161
|
}
|
|
163
162
|
|
|
164
163
|
setPendingUpdate(null);
|
|
@@ -240,7 +239,7 @@ const StyleImageUpdatePanel = ({
|
|
|
240
239
|
}
|
|
241
240
|
}
|
|
242
241
|
|
|
243
|
-
ctx.modifyNodes([{ ...targetNode
|
|
242
|
+
ctx.modifyNodes([{ ...targetNode }]);
|
|
244
243
|
setIsOverridden(checked);
|
|
245
244
|
},
|
|
246
245
|
[node, className, parentNode, childId, isImage]
|
|
@@ -115,7 +115,7 @@ const StyleLiElementUpdatePanel = ({
|
|
|
115
115
|
break;
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
ctx.modifyNodes([{ ...targetNode
|
|
118
|
+
ctx.modifyNodes([{ ...targetNode }]);
|
|
119
119
|
} else {
|
|
120
120
|
const markdownNode = cloneDeep(
|
|
121
121
|
allNodes.get(parentNode.id)
|
|
@@ -150,7 +150,7 @@ const StyleLiElementUpdatePanel = ({
|
|
|
150
150
|
break;
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
ctx.modifyNodes([{ ...markdownNode
|
|
153
|
+
ctx.modifyNodes([{ ...markdownNode }]);
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
setPendingUpdate(null);
|
|
@@ -240,7 +240,7 @@ const StyleLiElementUpdatePanel = ({
|
|
|
240
240
|
}
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
-
ctx.modifyNodes([{ ...targetNode
|
|
243
|
+
ctx.modifyNodes([{ ...targetNode }]);
|
|
244
244
|
setIsOverridden(checked);
|
|
245
245
|
},
|
|
246
246
|
[node, className, parentNode, childId, isContainer]
|
|
@@ -256,7 +256,7 @@ const StyleLinkPanel = ({ node }: BasePanelProps) => {
|
|
|
256
256
|
callbackPayload: linkNode.buttonPayload?.callbackPayload || '',
|
|
257
257
|
};
|
|
258
258
|
|
|
259
|
-
ctx.modifyNodes([{ ...linkNode
|
|
259
|
+
ctx.modifyNodes([{ ...linkNode }]);
|
|
260
260
|
|
|
261
261
|
settingsPanelStore.set({
|
|
262
262
|
action: 'style-link',
|
|
@@ -109,7 +109,7 @@ const StyleLinkConfigPanel = ({ node }: StyleLinkConfigPanelProps) => {
|
|
|
109
109
|
});
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
ctx.modifyNodes([{ ...linkNode
|
|
112
|
+
ctx.modifyNodes([{ ...linkNode }]);
|
|
113
113
|
} catch (error) {
|
|
114
114
|
console.error('Error in updateNode:', error);
|
|
115
115
|
}
|
|
@@ -48,7 +48,7 @@ const StyleLinkRemovePanel = ({ node, className }: BasePanelProps) => {
|
|
|
48
48
|
delete linkNode.buttonPayload.buttonClasses[className];
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
|
-
ctx.modifyNodes([{ ...linkNode
|
|
51
|
+
ctx.modifyNodes([{ ...linkNode }]);
|
|
52
52
|
resetStore();
|
|
53
53
|
};
|
|
54
54
|
|