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
|
@@ -139,6 +139,8 @@ const AddPaneNewPanel = ({
|
|
|
139
139
|
const [copyMode, setCopyMode] = useState<CopyMode>('prompt');
|
|
140
140
|
const [promptValue, setPromptValue] = useState('');
|
|
141
141
|
const [copyValue, setCopyValue] = useState('');
|
|
142
|
+
const [selectedLibraryEntry, setSelectedLibraryEntry] =
|
|
143
|
+
useState<DesignLibraryEntry | null>(null);
|
|
142
144
|
const [aiDesignConfig, setAiDesignConfig] = useState<AiDesignConfig>({
|
|
143
145
|
harmony: 'Analogous',
|
|
144
146
|
baseColor: '',
|
|
@@ -153,27 +155,31 @@ const AddPaneNewPanel = ({
|
|
|
153
155
|
|
|
154
156
|
if (choice === 'blank') {
|
|
155
157
|
handleBlankSlate();
|
|
156
|
-
} else {
|
|
157
|
-
setStep('
|
|
158
|
+
} else if (choice === 'library') {
|
|
159
|
+
setStep('designLibrary');
|
|
160
|
+
} else if (choice === 'ai') {
|
|
161
|
+
setStep('aiDesign');
|
|
158
162
|
}
|
|
159
163
|
};
|
|
160
164
|
|
|
161
165
|
const handleBack = () => {
|
|
162
166
|
setError(null);
|
|
163
167
|
if (step === 'copyInput') {
|
|
164
|
-
|
|
168
|
+
if (initialChoice === 'library') {
|
|
169
|
+
setStep('designLibrary');
|
|
170
|
+
} else if (initialChoice === 'ai') {
|
|
171
|
+
setStep('aiDesign');
|
|
172
|
+
} else {
|
|
173
|
+
setStep('initial');
|
|
174
|
+
}
|
|
165
175
|
} else if (step === 'directInject') {
|
|
166
176
|
setStep('aiDesign');
|
|
167
|
-
} else if (
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
if (initialChoice === 'library') {
|
|
174
|
-
setStep('designLibrary');
|
|
175
|
-
} else if (initialChoice === 'ai') {
|
|
176
|
-
setStep('aiDesign');
|
|
177
|
+
} else if (
|
|
178
|
+
step === 'designLibrary' ||
|
|
179
|
+
step === 'aiDesign' ||
|
|
180
|
+
step === 'error'
|
|
181
|
+
) {
|
|
182
|
+
setStep('initial');
|
|
177
183
|
}
|
|
178
184
|
};
|
|
179
185
|
|
|
@@ -182,7 +188,7 @@ const AddPaneNewPanel = ({
|
|
|
182
188
|
id: '',
|
|
183
189
|
nodeType: 'Pane',
|
|
184
190
|
parentId: '',
|
|
185
|
-
title: '
|
|
191
|
+
title: '',
|
|
186
192
|
slug: '',
|
|
187
193
|
isDecorative: false,
|
|
188
194
|
markdown: {
|
|
@@ -199,130 +205,25 @@ const AddPaneNewPanel = ({
|
|
|
199
205
|
handleApplyTemplate(blankTemplate);
|
|
200
206
|
};
|
|
201
207
|
|
|
202
|
-
const handleDesignLibrarySelect =
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
mergeCopyIntoTemplate(entry.template, [])
|
|
206
|
-
);
|
|
207
|
-
if (liveTemplate.markdown) {
|
|
208
|
-
liveTemplate.markdown.markdownBody = copyValue;
|
|
209
|
-
}
|
|
210
|
-
handleApplyTemplate(liveTemplate);
|
|
211
|
-
return;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
if (copyMode === 'prompt') {
|
|
215
|
-
setError(null);
|
|
216
|
-
setStep('loading');
|
|
217
|
-
try {
|
|
218
|
-
const liveTemplate = convertStorageToLiveTemplate(entry.template);
|
|
219
|
-
if (!liveTemplate.markdown) {
|
|
220
|
-
throw new Error(
|
|
221
|
-
'The selected design library item is not compatible with this workflow as it has no markdown section.'
|
|
222
|
-
);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
const shellJson = convertTemplateToAIShell(liveTemplate);
|
|
226
|
-
if (!shellJson || shellJson === '{}') {
|
|
227
|
-
throw new Error(
|
|
228
|
-
'Could not generate a valid AI shell from this design.'
|
|
229
|
-
);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
const copyPromptDetails = prompts.aiPaneCopyPrompt;
|
|
233
|
-
const layout = 'Text Only';
|
|
234
|
-
const formattedCopyPrompt = copyPromptDetails.user_template
|
|
235
|
-
.replace('{{COPY_INPUT}}', promptValue)
|
|
236
|
-
.replace(
|
|
237
|
-
'{{DESIGN_INPUT}}',
|
|
238
|
-
"N/A - Use the provided Shell JSON's design."
|
|
239
|
-
)
|
|
240
|
-
.replace('{{LAYOUT_TYPE}}', layout)
|
|
241
|
-
.replace('{{SHELL_JSON}}', shellJson);
|
|
242
|
-
|
|
243
|
-
const copyResult = await callAskLemurAPI(
|
|
244
|
-
formattedCopyPrompt,
|
|
245
|
-
copyPromptDetails.system || '',
|
|
246
|
-
false,
|
|
247
|
-
isSandboxMode
|
|
248
|
-
);
|
|
249
|
-
|
|
250
|
-
const newNodes = parseAiCopyHtml(copyResult, liveTemplate.markdown.id);
|
|
251
|
-
|
|
252
|
-
const finalPane = cloneDeep(liveTemplate);
|
|
253
|
-
|
|
254
|
-
finalPane.markdown!.nodes = newNodes;
|
|
255
|
-
|
|
256
|
-
handleApplyTemplate(finalPane);
|
|
257
|
-
} catch (err: any) {
|
|
258
|
-
setError(err.message || 'Failed to generate AI copy for this design.');
|
|
259
|
-
setStep('error');
|
|
260
|
-
}
|
|
261
|
-
}
|
|
208
|
+
const handleDesignLibrarySelect = (entry: DesignLibraryEntry) => {
|
|
209
|
+
setSelectedLibraryEntry(entry);
|
|
210
|
+
setStep('copyInput');
|
|
262
211
|
};
|
|
263
212
|
|
|
264
|
-
const
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
let designInput = `Generate a design using a **${aiDesignConfig.harmony.toLowerCase()}** color scheme with a **${aiDesignConfig.theme.toLowerCase()}** theme.`;
|
|
269
|
-
if (aiDesignConfig.baseColor)
|
|
270
|
-
designInput += ` Base the colors around **${aiDesignConfig.baseColor}**.`;
|
|
271
|
-
if (aiDesignConfig.accentColor)
|
|
272
|
-
designInput += ` Use **${aiDesignConfig.accentColor}** as an accent color.`;
|
|
273
|
-
if (aiDesignConfig.additionalNotes)
|
|
274
|
-
designInput += ` Refine with these notes: "${aiDesignConfig.additionalNotes}"`;
|
|
275
|
-
|
|
276
|
-
try {
|
|
277
|
-
const shellPromptDetails = prompts.aiPaneShellPrompt;
|
|
278
|
-
const copyPromptDetails = prompts.aiPaneCopyPrompt;
|
|
279
|
-
const layout = 'Text Only';
|
|
280
|
-
|
|
281
|
-
const formattedShellPrompt = shellPromptDetails.user_template
|
|
282
|
-
.replace('{{DESIGN_INPUT}}', designInput)
|
|
283
|
-
.replace('{{LAYOUT_TYPE}}', layout);
|
|
284
|
-
|
|
285
|
-
const shellResult = await callAskLemurAPI(
|
|
286
|
-
formattedShellPrompt,
|
|
287
|
-
shellPromptDetails.system || '',
|
|
288
|
-
true,
|
|
289
|
-
isSandboxMode
|
|
290
|
-
);
|
|
291
|
-
|
|
292
|
-
const copyInputContent = copyMode === 'prompt' ? promptValue : copyValue;
|
|
293
|
-
const formattedCopyPrompt = copyPromptDetails.user_template
|
|
294
|
-
.replace('{{COPY_INPUT}}', copyInputContent)
|
|
295
|
-
.replace('{{DESIGN_INPUT}}', designInput)
|
|
296
|
-
.replace('{{LAYOUT_TYPE}}', layout)
|
|
297
|
-
.replace('{{SHELL_JSON}}', shellResult);
|
|
298
|
-
|
|
299
|
-
const copyResult = await callAskLemurAPI(
|
|
300
|
-
formattedCopyPrompt,
|
|
301
|
-
copyPromptDetails.system || '',
|
|
302
|
-
false,
|
|
303
|
-
isSandboxMode
|
|
304
|
-
);
|
|
305
|
-
|
|
306
|
-
const finalPane = parseAiPane(shellResult, copyResult, layout);
|
|
307
|
-
handleApplyTemplate(finalPane);
|
|
308
|
-
} catch (err: any) {
|
|
309
|
-
setError(err.message || 'Failed to generate AI pane.');
|
|
310
|
-
setStep('error');
|
|
311
|
-
}
|
|
312
|
-
}, [aiDesignConfig, copyMode, promptValue, copyValue, isSandboxMode]);
|
|
213
|
+
const handleAiDesignContinue = () => {
|
|
214
|
+
setStep('copyInput');
|
|
215
|
+
};
|
|
313
216
|
|
|
314
217
|
const handleApplyTemplate = async (template: TemplatePane) => {
|
|
315
|
-
console.log(template);
|
|
316
218
|
if (!ctx) return;
|
|
317
219
|
try {
|
|
318
220
|
const insertTemplate = cloneDeep(template);
|
|
319
|
-
insertTemplate.title = insertTemplate.title || 'New Pane';
|
|
320
|
-
insertTemplate.slug = insertTemplate.slug || '';
|
|
321
|
-
|
|
322
221
|
const ownerId =
|
|
323
222
|
isStoryFragment || isContextPane
|
|
324
223
|
? nodeId
|
|
325
224
|
: ctx.getClosestNodeTypeFromId(nodeId, 'StoryFragment');
|
|
225
|
+
insertTemplate.title = '';
|
|
226
|
+
insertTemplate.slug = '';
|
|
326
227
|
|
|
327
228
|
if (isContextPane) {
|
|
328
229
|
insertTemplate.isContextPane = true;
|
|
@@ -352,6 +253,127 @@ const AddPaneNewPanel = ({
|
|
|
352
253
|
}
|
|
353
254
|
};
|
|
354
255
|
|
|
256
|
+
const handleFinalGenerate = useCallback(async () => {
|
|
257
|
+
setError(null);
|
|
258
|
+
setStep('loading');
|
|
259
|
+
|
|
260
|
+
try {
|
|
261
|
+
if (initialChoice === 'library') {
|
|
262
|
+
if (!selectedLibraryEntry) {
|
|
263
|
+
throw new Error('No design library item was selected.');
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if (copyMode === 'raw') {
|
|
267
|
+
const liveTemplate = convertStorageToLiveTemplate(
|
|
268
|
+
mergeCopyIntoTemplate(selectedLibraryEntry.template, [])
|
|
269
|
+
);
|
|
270
|
+
if (liveTemplate.markdown) {
|
|
271
|
+
liveTemplate.markdown.markdownBody = copyValue;
|
|
272
|
+
}
|
|
273
|
+
handleApplyTemplate(liveTemplate);
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (copyMode === 'prompt') {
|
|
278
|
+
const liveTemplate = convertStorageToLiveTemplate(
|
|
279
|
+
selectedLibraryEntry.template
|
|
280
|
+
);
|
|
281
|
+
if (!liveTemplate.markdown) {
|
|
282
|
+
throw new Error(
|
|
283
|
+
'The selected design library item is not compatible with this workflow as it has no markdown section.'
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const shellJson = convertTemplateToAIShell(liveTemplate);
|
|
288
|
+
if (!shellJson || shellJson === '{}') {
|
|
289
|
+
throw new Error(
|
|
290
|
+
'Could not generate a valid AI shell from this design.'
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const copyPromptDetails = prompts.aiPaneCopyPrompt;
|
|
295
|
+
const layout = 'Text Only';
|
|
296
|
+
const formattedCopyPrompt = copyPromptDetails.user_template
|
|
297
|
+
.replace('{{COPY_INPUT}}', promptValue)
|
|
298
|
+
.replace(
|
|
299
|
+
'{{DESIGN_INPUT}}',
|
|
300
|
+
"N/A - Use the provided Shell JSON's design."
|
|
301
|
+
)
|
|
302
|
+
.replace('{{LAYOUT_TYPE}}', layout)
|
|
303
|
+
.replace('{{SHELL_JSON}}', shellJson);
|
|
304
|
+
|
|
305
|
+
const copyResult = await callAskLemurAPI(
|
|
306
|
+
formattedCopyPrompt,
|
|
307
|
+
copyPromptDetails.system || '',
|
|
308
|
+
false,
|
|
309
|
+
isSandboxMode
|
|
310
|
+
);
|
|
311
|
+
|
|
312
|
+
const newNodes = parseAiCopyHtml(
|
|
313
|
+
copyResult,
|
|
314
|
+
liveTemplate.markdown.id
|
|
315
|
+
);
|
|
316
|
+
const finalPane = cloneDeep(liveTemplate);
|
|
317
|
+
finalPane.markdown!.nodes = newNodes;
|
|
318
|
+
handleApplyTemplate(finalPane);
|
|
319
|
+
}
|
|
320
|
+
} else if (initialChoice === 'ai') {
|
|
321
|
+
let designInput = `Generate a design using a **${aiDesignConfig.harmony.toLowerCase()}** color scheme with a **${aiDesignConfig.theme.toLowerCase()}** theme.`;
|
|
322
|
+
if (aiDesignConfig.baseColor)
|
|
323
|
+
designInput += ` Base the colors around **${aiDesignConfig.baseColor}**.`;
|
|
324
|
+
if (aiDesignConfig.accentColor)
|
|
325
|
+
designInput += ` Use **${aiDesignConfig.accentColor}** as an accent color.`;
|
|
326
|
+
if (aiDesignConfig.additionalNotes)
|
|
327
|
+
designInput += ` Refine with these notes: "${aiDesignConfig.additionalNotes}"`;
|
|
328
|
+
|
|
329
|
+
const shellPromptDetails = prompts.aiPaneShellPrompt;
|
|
330
|
+
const copyPromptDetails = prompts.aiPaneCopyPrompt;
|
|
331
|
+
const layout = 'Text Only';
|
|
332
|
+
|
|
333
|
+
const formattedShellPrompt = shellPromptDetails.user_template
|
|
334
|
+
.replace('{{DESIGN_INPUT}}', designInput)
|
|
335
|
+
.replace('{{LAYOUT_TYPE}}', layout);
|
|
336
|
+
|
|
337
|
+
const shellResult = await callAskLemurAPI(
|
|
338
|
+
formattedShellPrompt,
|
|
339
|
+
shellPromptDetails.system || '',
|
|
340
|
+
true,
|
|
341
|
+
isSandboxMode
|
|
342
|
+
);
|
|
343
|
+
|
|
344
|
+
const copyInputContent =
|
|
345
|
+
copyMode === 'prompt' ? promptValue : copyValue;
|
|
346
|
+
const formattedCopyPrompt = copyPromptDetails.user_template
|
|
347
|
+
.replace('{{COPY_INPUT}}', copyInputContent)
|
|
348
|
+
.replace('{{DESIGN_INPUT}}', designInput)
|
|
349
|
+
.replace('{{LAYOUT_TYPE}}', layout)
|
|
350
|
+
.replace('{{SHELL_JSON}}', shellResult);
|
|
351
|
+
|
|
352
|
+
const copyResult = await callAskLemurAPI(
|
|
353
|
+
formattedCopyPrompt,
|
|
354
|
+
copyPromptDetails.system || '',
|
|
355
|
+
false,
|
|
356
|
+
isSandboxMode
|
|
357
|
+
);
|
|
358
|
+
|
|
359
|
+
const finalPane = parseAiPane(shellResult, copyResult, layout);
|
|
360
|
+
handleApplyTemplate(finalPane);
|
|
361
|
+
}
|
|
362
|
+
} catch (err: any) {
|
|
363
|
+
setError(err.message || 'Failed to generate AI pane.');
|
|
364
|
+
setStep('error');
|
|
365
|
+
}
|
|
366
|
+
}, [
|
|
367
|
+
aiDesignConfig,
|
|
368
|
+
copyMode,
|
|
369
|
+
promptValue,
|
|
370
|
+
copyValue,
|
|
371
|
+
isSandboxMode,
|
|
372
|
+
initialChoice,
|
|
373
|
+
selectedLibraryEntry,
|
|
374
|
+
handleApplyTemplate,
|
|
375
|
+
]);
|
|
376
|
+
|
|
355
377
|
const renderInitialStep = () => (
|
|
356
378
|
<div className="p-4">
|
|
357
379
|
<h3 className="font-action mb-4 text-center text-xl font-bold text-gray-800">
|
|
@@ -417,26 +439,15 @@ const AddPaneNewPanel = ({
|
|
|
417
439
|
← Back
|
|
418
440
|
</button>
|
|
419
441
|
<button
|
|
420
|
-
onClick={
|
|
442
|
+
onClick={handleFinalGenerate}
|
|
421
443
|
disabled={
|
|
422
444
|
copyMode === 'prompt' ? !promptValue.trim() : !copyValue.trim()
|
|
423
445
|
}
|
|
424
446
|
className="rounded-md bg-cyan-600 px-4 py-2 text-sm font-bold text-white shadow-sm hover:bg-cyan-700 disabled:cursor-not-allowed disabled:bg-gray-400"
|
|
425
447
|
>
|
|
426
|
-
|
|
448
|
+
✨ Generate Pane
|
|
427
449
|
</button>
|
|
428
450
|
</div>
|
|
429
|
-
{initialChoice === `ai` && !isSandboxMode && (
|
|
430
|
-
<div className="mt-6 text-center text-sm text-gray-600">
|
|
431
|
-
ADVANCED:{' '}
|
|
432
|
-
<button
|
|
433
|
-
onClick={() => setStep('directInject')}
|
|
434
|
-
className="font-bold text-cyan-700 underline hover:text-cyan-900 focus:outline-none"
|
|
435
|
-
>
|
|
436
|
-
Direct Inject
|
|
437
|
-
</button>
|
|
438
|
-
</div>
|
|
439
|
-
)}
|
|
440
451
|
</div>
|
|
441
452
|
);
|
|
442
453
|
|
|
@@ -447,7 +458,7 @@ const AddPaneNewPanel = ({
|
|
|
447
458
|
onClick={handleBack}
|
|
448
459
|
className="rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-bold text-gray-700 shadow-sm hover:bg-gray-50"
|
|
449
460
|
>
|
|
450
|
-
← Back to
|
|
461
|
+
← Back to Choice
|
|
451
462
|
</button>
|
|
452
463
|
</div>
|
|
453
464
|
<DesignLibraryStep
|
|
@@ -472,12 +483,23 @@ const AddPaneNewPanel = ({
|
|
|
472
483
|
← Back
|
|
473
484
|
</button>
|
|
474
485
|
<button
|
|
475
|
-
onClick={
|
|
486
|
+
onClick={handleAiDesignContinue}
|
|
476
487
|
className="rounded-md bg-cyan-600 px-4 py-2 text-sm font-bold text-white shadow-sm hover:bg-cyan-700"
|
|
477
488
|
>
|
|
478
|
-
|
|
489
|
+
Continue →
|
|
479
490
|
</button>
|
|
480
491
|
</div>
|
|
492
|
+
{initialChoice === `ai` && !isSandboxMode && (
|
|
493
|
+
<div className="mt-6 text-center text-sm text-gray-600">
|
|
494
|
+
ADVANCED:{' '}
|
|
495
|
+
<button
|
|
496
|
+
onClick={() => setStep('directInject')}
|
|
497
|
+
className="font-bold text-cyan-700 underline hover:text-cyan-900 focus:outline-none"
|
|
498
|
+
>
|
|
499
|
+
Direct Inject
|
|
500
|
+
</button>
|
|
501
|
+
</div>
|
|
502
|
+
)}
|
|
481
503
|
</div>
|
|
482
504
|
);
|
|
483
505
|
|
|
@@ -486,7 +508,7 @@ const AddPaneNewPanel = ({
|
|
|
486
508
|
);
|
|
487
509
|
|
|
488
510
|
const renderLoading = () => (
|
|
489
|
-
<div className="flex min-h-
|
|
511
|
+
<div className="flex min-h-80 flex-col items-center justify-center space-y-4 p-6">
|
|
490
512
|
<div className="h-8 w-8 animate-spin rounded-full border-b-2 border-cyan-600"></div>
|
|
491
513
|
<p className="text-sm text-gray-600">Generating AI Pane...</p>
|
|
492
514
|
<p className="text-xs text-gray-500">This may take a moment.</p>
|
|
@@ -550,7 +572,7 @@ const AddPaneNewPanel = ({
|
|
|
550
572
|
</>
|
|
551
573
|
)}
|
|
552
574
|
</div>
|
|
553
|
-
<div className="min-h-
|
|
575
|
+
<div className="min-h-96 rounded-md border bg-gray-50">
|
|
554
576
|
{renderStep()}
|
|
555
577
|
</div>
|
|
556
578
|
</div>
|
|
@@ -310,7 +310,7 @@ const AddPaneReUsePanel = ({
|
|
|
310
310
|
<style>{comboboxItemStyles}</style>
|
|
311
311
|
<div className="w-full rounded-md bg-white p-1.5">
|
|
312
312
|
<div className="flex flex-wrap items-center gap-2">
|
|
313
|
-
<div className="flex min-w-
|
|
313
|
+
<div className="flex min-w-48 flex-wrap items-center gap-2">
|
|
314
314
|
<button
|
|
315
315
|
onClick={() => setMode(PaneAddMode.DEFAULT)}
|
|
316
316
|
className="w-fit flex-none rounded bg-gray-100 px-3 py-1 text-sm text-gray-700 transition-colors hover:bg-gray-200 focus:bg-gray-200"
|
|
@@ -323,7 +323,7 @@ const AddPaneReUsePanel = ({
|
|
|
323
323
|
</div>
|
|
324
324
|
</div>
|
|
325
325
|
|
|
326
|
-
<div className="min-w-
|
|
326
|
+
<div className="min-w-72 flex-1">
|
|
327
327
|
<Combobox.Root
|
|
328
328
|
collection={collection}
|
|
329
329
|
value={[]}
|
|
@@ -9,11 +9,7 @@ import {
|
|
|
9
9
|
isContextPaneNode,
|
|
10
10
|
hasBeliefPayload,
|
|
11
11
|
} from '@/utils/compositor/typeGuards';
|
|
12
|
-
import {
|
|
13
|
-
settingsPanelStore,
|
|
14
|
-
viewportKeyStore,
|
|
15
|
-
fullContentMapStore,
|
|
16
|
-
} from '@/stores/storykeep';
|
|
12
|
+
import { settingsPanelStore, fullContentMapStore } from '@/stores/storykeep';
|
|
17
13
|
import { getCtx } from '@/stores/nodes';
|
|
18
14
|
import PaneTitlePanel from './PanePanel_title';
|
|
19
15
|
import PaneMagicPathPanel from './PanePanel_path';
|
|
@@ -34,8 +30,6 @@ const ConfigPanePanel = ({ nodeId }: ConfigPanePanelProps) => {
|
|
|
34
30
|
const isActiveMode =
|
|
35
31
|
activePaneMode.panel === 'settings' && activePaneMode.paneId === nodeId;
|
|
36
32
|
const $contentMap = useStore(fullContentMapStore);
|
|
37
|
-
const $viewportKey = useStore(viewportKeyStore);
|
|
38
|
-
const isMobile = $viewportKey.value === `mobile`;
|
|
39
33
|
|
|
40
34
|
const allNodes = ctx.allNodes.get();
|
|
41
35
|
const paneNode = allNodes.get(nodeId) as PaneNode;
|
|
@@ -200,7 +200,7 @@ const PaneImpressionPanel = ({ nodeId, setMode }: PaneImpressionPanelProps) => {
|
|
|
200
200
|
onChange={(e) => handleInputChange('body', e.target.value)}
|
|
201
201
|
onBlur={handleBlur}
|
|
202
202
|
placeholder="Enter impression body text"
|
|
203
|
-
className={`${commonInputClass} min-h-
|
|
203
|
+
className={`${commonInputClass} min-h-24`}
|
|
204
204
|
/>
|
|
205
205
|
</div>
|
|
206
206
|
|
|
@@ -130,7 +130,7 @@ const TemplatePreviewItem = ({
|
|
|
130
130
|
)}
|
|
131
131
|
</div>
|
|
132
132
|
<div className="p-3">
|
|
133
|
-
<h3 className="truncate font-
|
|
133
|
+
<h3 className="truncate font-bold" title={template.title}>
|
|
134
134
|
{template.title}
|
|
135
135
|
</h3>
|
|
136
136
|
<p className="text-sm text-gray-600">
|
|
@@ -404,9 +404,12 @@ export const RestylePaneModal = ({ config }: RestylePaneModalProps) => {
|
|
|
404
404
|
<Portal>
|
|
405
405
|
<Dialog.Backdrop className="z-103 fixed inset-0 bg-black/70" />
|
|
406
406
|
<Dialog.Positioner className="z-104 fixed inset-0 flex items-center justify-center">
|
|
407
|
-
<Dialog.Content
|
|
407
|
+
<Dialog.Content
|
|
408
|
+
className="flex flex-col rounded-lg bg-white shadow-2xl"
|
|
409
|
+
style={{ height: '90vw', width: '90vw' }}
|
|
410
|
+
>
|
|
408
411
|
<header className="flex items-center justify-between border-b p-4">
|
|
409
|
-
<Dialog.Title className="text-xl font-
|
|
412
|
+
<Dialog.Title className="text-xl font-bold">
|
|
410
413
|
Restyle Pane from Design Library
|
|
411
414
|
</Dialog.Title>
|
|
412
415
|
<Dialog.CloseTrigger
|
|
@@ -427,7 +430,7 @@ export const RestylePaneModal = ({ config }: RestylePaneModalProps) => {
|
|
|
427
430
|
className="w-48"
|
|
428
431
|
positioning={{ gutter: 4 }}
|
|
429
432
|
>
|
|
430
|
-
<Select.Label className="mb-1 text-sm font-
|
|
433
|
+
<Select.Label className="mb-1 text-sm font-bold">
|
|
431
434
|
Category
|
|
432
435
|
</Select.Label>
|
|
433
436
|
<Select.Control>
|
|
@@ -461,7 +464,7 @@ export const RestylePaneModal = ({ config }: RestylePaneModalProps) => {
|
|
|
461
464
|
className="flex-1"
|
|
462
465
|
positioning={{ gutter: 4 }}
|
|
463
466
|
>
|
|
464
|
-
<Combobox.Label className="mb-1 text-sm font-
|
|
467
|
+
<Combobox.Label className="mb-1 text-sm font-bold">
|
|
465
468
|
Filter by Title
|
|
466
469
|
</Combobox.Label>
|
|
467
470
|
<Combobox.Control>
|
|
@@ -37,11 +37,11 @@ export const AiDesignStep = ({
|
|
|
37
37
|
|
|
38
38
|
return (
|
|
39
39
|
<div className="space-y-6 rounded-lg bg-gray-50 p-4 shadow-inner">
|
|
40
|
-
<label className="block text-lg font-
|
|
40
|
+
<label className="block text-lg font-bold text-gray-800">
|
|
41
41
|
2. Configure AI Design
|
|
42
42
|
</label>
|
|
43
43
|
<div>
|
|
44
|
-
<label className="block text-base font-
|
|
44
|
+
<label className="block text-base font-bold text-gray-800">
|
|
45
45
|
Color Harmony
|
|
46
46
|
</label>
|
|
47
47
|
<div className="mt-2 flex flex-wrap gap-x-4 gap-y-2">
|
|
@@ -58,7 +58,7 @@ export const AiDesignStep = ({
|
|
|
58
58
|
/>
|
|
59
59
|
<label
|
|
60
60
|
htmlFor={`harmony-${option}`}
|
|
61
|
-
className="text-sm font-
|
|
61
|
+
className="text-sm font-bold text-gray-700"
|
|
62
62
|
>
|
|
63
63
|
{option}
|
|
64
64
|
</label>
|
|
@@ -89,7 +89,7 @@ export const AiDesignStep = ({
|
|
|
89
89
|
</div>
|
|
90
90
|
|
|
91
91
|
<div>
|
|
92
|
-
<label className="block text-base font-
|
|
92
|
+
<label className="block text-base font-bold text-gray-800">
|
|
93
93
|
Theme / Mood
|
|
94
94
|
</label>
|
|
95
95
|
<div className="mt-2 flex flex-wrap gap-x-4 gap-y-2">
|
|
@@ -106,7 +106,7 @@ export const AiDesignStep = ({
|
|
|
106
106
|
/>
|
|
107
107
|
<label
|
|
108
108
|
htmlFor={`theme-${option}`}
|
|
109
|
-
className="text-sm font-
|
|
109
|
+
className="text-sm font-bold text-gray-700"
|
|
110
110
|
>
|
|
111
111
|
{option}
|
|
112
112
|
</label>
|
|
@@ -118,7 +118,7 @@ export const AiDesignStep = ({
|
|
|
118
118
|
<div>
|
|
119
119
|
<label
|
|
120
120
|
htmlFor="additional-notes"
|
|
121
|
-
className="block text-base font-
|
|
121
|
+
className="block text-base font-bold text-gray-800"
|
|
122
122
|
>
|
|
123
123
|
Additional Design Notes (Optional)
|
|
124
124
|
</label>
|
|
@@ -30,7 +30,7 @@ export const CopyInputStep = ({
|
|
|
30
30
|
|
|
31
31
|
return (
|
|
32
32
|
<div className="space-y-4 rounded-lg bg-gray-50 p-4 shadow-inner">
|
|
33
|
-
<label className="block text-lg font-
|
|
33
|
+
<label className="block text-lg font-bold text-gray-800">
|
|
34
34
|
1. Provide Content
|
|
35
35
|
</label>
|
|
36
36
|
<div className="my-2 flex space-x-4">
|
|
@@ -46,7 +46,7 @@ export const CopyInputStep = ({
|
|
|
46
46
|
/>
|
|
47
47
|
<label
|
|
48
48
|
htmlFor="copy-prompt-mode"
|
|
49
|
-
className="text-sm font-
|
|
49
|
+
className="text-sm font-bold text-gray-700"
|
|
50
50
|
>
|
|
51
51
|
Write a prompt
|
|
52
52
|
</label>
|
|
@@ -63,7 +63,7 @@ export const CopyInputStep = ({
|
|
|
63
63
|
/>
|
|
64
64
|
<label
|
|
65
65
|
htmlFor="copy-raw-mode"
|
|
66
|
-
className="text-sm font-
|
|
66
|
+
className="text-sm font-bold text-gray-700"
|
|
67
67
|
>
|
|
68
68
|
Provide Copy (Markdown)
|
|
69
69
|
</label>
|
|
@@ -139,7 +139,7 @@ const TemplatePreviewItem = ({
|
|
|
139
139
|
</div>
|
|
140
140
|
</div>
|
|
141
141
|
<div className="flex-grow p-3">
|
|
142
|
-
<h3 className="truncate font-
|
|
142
|
+
<h3 className="truncate font-bold" title={title}>
|
|
143
143
|
{title}
|
|
144
144
|
</h3>
|
|
145
145
|
<p className="text-sm capitalize text-gray-600">{category}</p>
|
|
@@ -226,7 +226,7 @@ export const DesignLibraryStep = ({
|
|
|
226
226
|
|
|
227
227
|
return (
|
|
228
228
|
<div className="flex h-full flex-col space-y-4 rounded-lg bg-gray-50 p-4 shadow-inner">
|
|
229
|
-
<label className="block text-lg font-
|
|
229
|
+
<label className="block text-lg font-bold text-gray-800">
|
|
230
230
|
2. Choose a Design
|
|
231
231
|
</label>
|
|
232
232
|
|
|
@@ -241,7 +241,7 @@ export const DesignLibraryStep = ({
|
|
|
241
241
|
className="w-48"
|
|
242
242
|
positioning={{ gutter: 4 }}
|
|
243
243
|
>
|
|
244
|
-
<Select.Label className="mb-1 text-sm font-
|
|
244
|
+
<Select.Label className="mb-1 text-sm font-bold text-gray-700">
|
|
245
245
|
Category
|
|
246
246
|
</Select.Label>
|
|
247
247
|
<Select.Control>
|
|
@@ -280,7 +280,7 @@ export const DesignLibraryStep = ({
|
|
|
280
280
|
className="flex-1"
|
|
281
281
|
positioning={{ gutter: 4 }}
|
|
282
282
|
>
|
|
283
|
-
<Combobox.Label className="mb-1 text-sm font-
|
|
283
|
+
<Combobox.Label className="mb-1 text-sm font-bold text-gray-700">
|
|
284
284
|
Filter by Title
|
|
285
285
|
</Combobox.Label>
|
|
286
286
|
<Combobox.Control>
|
|
@@ -5,18 +5,22 @@ import {
|
|
|
5
5
|
settingsPanelStore,
|
|
6
6
|
} from '@/stores/storykeep';
|
|
7
7
|
import { StylesMemory } from '@/components/edit/state/StylesMemory';
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
isMarkdownPaneFragmentNode,
|
|
10
|
+
isGridLayoutNode,
|
|
11
|
+
} from '@/utils/compositor/typeGuards';
|
|
9
12
|
import SelectedTailwindClass from '@/components/fields/SelectedTailwindClass';
|
|
10
13
|
import { tagTitles } from '@/types/compositorTypes';
|
|
11
14
|
import type {
|
|
12
15
|
Tag,
|
|
13
16
|
FlatNode,
|
|
14
17
|
MarkdownPaneFragmentNode,
|
|
18
|
+
GridLayoutNode,
|
|
15
19
|
} from '@/types/compositorTypes';
|
|
16
20
|
|
|
17
|
-
interface StyleElementPanelProps {
|
|
21
|
+
export interface StyleElementPanelProps {
|
|
18
22
|
node: FlatNode;
|
|
19
|
-
parentNode: MarkdownPaneFragmentNode;
|
|
23
|
+
parentNode: MarkdownPaneFragmentNode | GridLayoutNode;
|
|
20
24
|
onTitleChange?: (title: string) => void;
|
|
21
25
|
}
|
|
22
26
|
|
|
@@ -25,7 +29,10 @@ const StyleElementPanel = ({
|
|
|
25
29
|
parentNode,
|
|
26
30
|
onTitleChange,
|
|
27
31
|
}: StyleElementPanelProps) => {
|
|
28
|
-
if (
|
|
32
|
+
if (
|
|
33
|
+
!node?.tagName ||
|
|
34
|
+
(!isMarkdownPaneFragmentNode(parentNode) && !isGridLayoutNode(parentNode))
|
|
35
|
+
) {
|
|
29
36
|
return null;
|
|
30
37
|
}
|
|
31
38
|
|