astro-tractstack 2.0.42 → 2.0.44
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/Header.astro +0 -1
- package/templates/src/components/edit/pane/AddPanePanel_new.tsx +156 -343
- package/templates/src/components/edit/pane/RestylePaneModal.tsx +7 -5
- package/templates/src/components/edit/pane/steps/AiDesignStep.tsx +1 -4
- package/templates/src/components/edit/pane/steps/CopyInputStep.tsx +238 -96
- package/templates/src/pages/storykeep/init.astro +23 -21
- package/templates/src/utils/layout.ts +85 -75
package/package.json
CHANGED
|
@@ -22,16 +22,13 @@ import {
|
|
|
22
22
|
} from '@/utils/compositor/designLibraryHelper';
|
|
23
23
|
import { DirectInjectStep } from './steps/DirectInjectStep';
|
|
24
24
|
import BooleanToggle from '@/components/form/BooleanToggle';
|
|
25
|
-
import EnumSelect from '@/components/form/EnumSelect';
|
|
26
25
|
import type { StoryFragmentNode } from '@/types/compositorTypes';
|
|
27
26
|
import { TractStackAPI } from '@/utils/api';
|
|
28
27
|
|
|
29
28
|
type Step =
|
|
30
29
|
| 'initial'
|
|
31
|
-
| '
|
|
30
|
+
| 'dashboard'
|
|
32
31
|
| 'designLibrary'
|
|
33
|
-
| 'layoutChoice'
|
|
34
|
-
| 'aiDesign'
|
|
35
32
|
| 'loading'
|
|
36
33
|
| 'error'
|
|
37
34
|
| 'directInject';
|
|
@@ -63,7 +60,6 @@ const callAskLemurAPI = async (
|
|
|
63
60
|
let resultData: any;
|
|
64
61
|
|
|
65
62
|
if (isSandboxMode) {
|
|
66
|
-
// Sandbox mode still uses local fetch, but we pass the correct tenant ID
|
|
67
63
|
const response = await fetch(`/api/sandbox`, {
|
|
68
64
|
method: 'POST',
|
|
69
65
|
headers: { 'Content-Type': 'application/json', 'X-Tenant-ID': tenantId },
|
|
@@ -80,9 +76,8 @@ const callAskLemurAPI = async (
|
|
|
80
76
|
if (!json.success) {
|
|
81
77
|
throw new Error(json.error || 'Sandbox generation failed');
|
|
82
78
|
}
|
|
83
|
-
resultData = json.data;
|
|
79
|
+
resultData = json.data;
|
|
84
80
|
} else {
|
|
85
|
-
// Production mode: Use the robust API class
|
|
86
81
|
const response = await api.post('/api/v1/aai/askLemur', requestBody);
|
|
87
82
|
|
|
88
83
|
if (!response.success) {
|
|
@@ -90,9 +85,7 @@ const callAskLemurAPI = async (
|
|
|
90
85
|
response.error || 'Generation failed to return valid response.'
|
|
91
86
|
);
|
|
92
87
|
}
|
|
93
|
-
|
|
94
|
-
// TractStackAPI unwraps the 'data' field automatically
|
|
95
|
-
resultData = response.data; // { response: ... }
|
|
88
|
+
resultData = response.data;
|
|
96
89
|
}
|
|
97
90
|
|
|
98
91
|
if (!resultData?.response) {
|
|
@@ -137,6 +130,7 @@ const AddPaneNewPanel = ({
|
|
|
137
130
|
}: AddPaneNewPanelProps) => {
|
|
138
131
|
const ctx = providedCtx || getCtx();
|
|
139
132
|
const hasAssemblyAI = useStore(hasAssemblyAIStore);
|
|
133
|
+
|
|
140
134
|
const [step, setStep] = useState<Step>('initial');
|
|
141
135
|
const [initialChoice, setInitialChoice] = useState<InitialChoice | null>(
|
|
142
136
|
null
|
|
@@ -144,6 +138,10 @@ const AddPaneNewPanel = ({
|
|
|
144
138
|
const [layoutChoice, setLayoutChoice] = useState<LayoutChoice>('standard');
|
|
145
139
|
const [error, setError] = useState<string | null>(null);
|
|
146
140
|
|
|
141
|
+
const [topic, setTopic] = useState('');
|
|
142
|
+
const [showAdvancedPrompts, setShowAdvancedPrompts] = useState(false);
|
|
143
|
+
const [showStyles, setShowStyles] = useState(false);
|
|
144
|
+
|
|
147
145
|
const [selectedPromptId, setSelectedPromptId] = useState<string>('');
|
|
148
146
|
const [isAiStyling, setIsAiStyling] = useState(false);
|
|
149
147
|
|
|
@@ -151,15 +149,9 @@ const AddPaneNewPanel = ({
|
|
|
151
149
|
const [promptValue, setPromptValue] = useState('');
|
|
152
150
|
const [copyValue, setCopyValue] = useState('');
|
|
153
151
|
|
|
154
|
-
const [overallPrompt, setOverallPrompt] = useState(
|
|
155
|
-
|
|
156
|
-
);
|
|
157
|
-
const [promptValueCol1, setPromptValueCol1] = useState(
|
|
158
|
-
prompts.aiPaneCopyPrompt_2cols.presets.heroDefault.left.prompt
|
|
159
|
-
);
|
|
160
|
-
const [promptValueCol2, setPromptValueCol2] = useState(
|
|
161
|
-
prompts.aiPaneCopyPrompt_2cols.presets.heroDefault.right.prompt
|
|
162
|
-
);
|
|
152
|
+
const [overallPrompt, setOverallPrompt] = useState('');
|
|
153
|
+
const [promptValueCol1, setPromptValueCol1] = useState('');
|
|
154
|
+
const [promptValueCol2, setPromptValueCol2] = useState('');
|
|
163
155
|
const [col1Copy, setCol1Copy] = useState('');
|
|
164
156
|
const [col2Copy, setCol2Copy] = useState('');
|
|
165
157
|
|
|
@@ -206,18 +198,23 @@ const AddPaneNewPanel = ({
|
|
|
206
198
|
? activeConfig.variants[0]
|
|
207
199
|
: 'default';
|
|
208
200
|
|
|
201
|
+
const injectTopic = (template: string) => {
|
|
202
|
+
if (!template) return '';
|
|
203
|
+
return template.replace('[topic]', topic.trim() || '[topic]');
|
|
204
|
+
};
|
|
205
|
+
|
|
209
206
|
if (layoutChoice === 'standard') {
|
|
210
|
-
const
|
|
211
|
-
setPromptValue(
|
|
207
|
+
const baseText = copyPromptGroup[variant] || '';
|
|
208
|
+
setPromptValue(injectTopic(baseText));
|
|
212
209
|
} else if (layoutChoice === 'grid') {
|
|
213
210
|
const preset = copyPromptGroup.presets?.[variant];
|
|
214
211
|
if (preset) {
|
|
215
|
-
setOverallPrompt(preset.default || '');
|
|
212
|
+
setOverallPrompt(injectTopic(preset.default || ''));
|
|
216
213
|
setPromptValueCol1(preset.left?.prompt || '');
|
|
217
214
|
setPromptValueCol2(preset.right?.prompt || '');
|
|
218
215
|
}
|
|
219
216
|
}
|
|
220
|
-
}, [selectedPromptId, layoutChoice]);
|
|
217
|
+
}, [selectedPromptId, layoutChoice, topic]);
|
|
221
218
|
|
|
222
219
|
const handleInitialChoice = (choice: InitialChoice) => {
|
|
223
220
|
setInitialChoice(choice);
|
|
@@ -228,32 +225,22 @@ const AddPaneNewPanel = ({
|
|
|
228
225
|
} else if (choice === 'library') {
|
|
229
226
|
setStep('designLibrary');
|
|
230
227
|
} else if (choice === 'ai') {
|
|
231
|
-
setStep('
|
|
228
|
+
setStep('dashboard');
|
|
232
229
|
}
|
|
233
230
|
};
|
|
234
231
|
|
|
235
|
-
const handleLayoutChoice = (choice: LayoutChoice) => {
|
|
236
|
-
setLayoutChoice(choice);
|
|
237
|
-
setStep('aiDesign');
|
|
238
|
-
};
|
|
239
|
-
|
|
240
232
|
const handleBack = () => {
|
|
241
233
|
setError(null);
|
|
242
|
-
if (step === '
|
|
243
|
-
if (initialChoice === 'library') {
|
|
244
|
-
setStep('designLibrary');
|
|
245
|
-
} else if (initialChoice === 'ai') {
|
|
246
|
-
setStep('aiDesign');
|
|
247
|
-
} else {
|
|
248
|
-
setStep('initial');
|
|
249
|
-
}
|
|
250
|
-
} else if (step === 'aiDesign') {
|
|
251
|
-
setStep('layoutChoice');
|
|
252
|
-
} else if (step === 'directInject') {
|
|
253
|
-
setStep('aiDesign');
|
|
254
|
-
} else if (step === 'layoutChoice') {
|
|
234
|
+
if (step === 'dashboard') {
|
|
255
235
|
setStep('initial');
|
|
256
|
-
|
|
236
|
+
setTopic('');
|
|
237
|
+
setShowAdvancedPrompts(false);
|
|
238
|
+
setShowStyles(false);
|
|
239
|
+
} else if (
|
|
240
|
+
step === 'designLibrary' ||
|
|
241
|
+
step === 'error' ||
|
|
242
|
+
step === 'directInject'
|
|
243
|
+
) {
|
|
257
244
|
setStep('initial');
|
|
258
245
|
}
|
|
259
246
|
};
|
|
@@ -280,10 +267,6 @@ const AddPaneNewPanel = ({
|
|
|
280
267
|
handleApplyTemplate(blankTemplate);
|
|
281
268
|
};
|
|
282
269
|
|
|
283
|
-
const handleAiDesignContinue = () => {
|
|
284
|
-
setStep('copyInput');
|
|
285
|
-
};
|
|
286
|
-
|
|
287
270
|
const handleApplyTemplate = async (template: any) => {
|
|
288
271
|
if (!ctx) return;
|
|
289
272
|
try {
|
|
@@ -347,8 +330,7 @@ const AddPaneNewPanel = ({
|
|
|
347
330
|
} else {
|
|
348
331
|
setCopyMode('prompt');
|
|
349
332
|
}
|
|
350
|
-
|
|
351
|
-
setStep('copyInput');
|
|
333
|
+
setStep('dashboard');
|
|
352
334
|
};
|
|
353
335
|
|
|
354
336
|
const handleFinalGenerate = useCallback(async () => {
|
|
@@ -571,39 +553,47 @@ const AddPaneNewPanel = ({
|
|
|
571
553
|
isSandboxMode
|
|
572
554
|
);
|
|
573
555
|
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
for (const item of promptsToRun) {
|
|
587
|
-
const columnPreset = preset[item.presetKey];
|
|
588
|
-
const formattedCopyPrompt = copyPromptDetails.user_template
|
|
589
|
-
.replace('{{SHELL_JSON}}', shellResult)
|
|
590
|
-
.replace('{{COPY_INPUT}}', overallPrompt)
|
|
591
|
-
.replace('{{COLUMN_PROMPT}}', item.prompt)
|
|
592
|
-
.replace('{{DESIGN_INPUT}}', designInput)
|
|
593
|
-
.replace('{{LAYOUT_TYPE}}', layout)
|
|
594
|
-
.replace('{{COLUMN_EXAMPLE}}', columnPreset.example);
|
|
556
|
+
if (copyMode === 'raw') {
|
|
557
|
+
const rawContents = [col1Copy, col2Copy];
|
|
558
|
+
const finalPane = parseAiPane(shellResult, rawContents, layout);
|
|
559
|
+
handleApplyTemplate(finalPane);
|
|
560
|
+
} else {
|
|
561
|
+
const copyPromptKey = activeConfig.prompts.copy;
|
|
562
|
+
const copyPromptDetails = promptMap[copyPromptKey];
|
|
563
|
+
const preset =
|
|
564
|
+
copyPromptDetails.presets?.[activeConfig.variants[0]] ||
|
|
565
|
+
copyPromptDetails.presets?.heroDefault;
|
|
566
|
+
const copyResults: string[] = [];
|
|
595
567
|
|
|
596
|
-
const
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
568
|
+
const promptsToRun = [
|
|
569
|
+
{ prompt: promptValueCol1, presetKey: 'left' as ColumnPresetKey },
|
|
570
|
+
{
|
|
571
|
+
prompt: promptValueCol2,
|
|
572
|
+
presetKey: 'right' as ColumnPresetKey,
|
|
573
|
+
},
|
|
574
|
+
];
|
|
575
|
+
|
|
576
|
+
for (const item of promptsToRun) {
|
|
577
|
+
const columnPreset = preset[item.presetKey];
|
|
578
|
+
const formattedCopyPrompt = copyPromptDetails.user_template
|
|
579
|
+
.replace('{{SHELL_JSON}}', shellResult)
|
|
580
|
+
.replace('{{COPY_INPUT}}', overallPrompt)
|
|
581
|
+
.replace('{{COLUMN_PROMPT}}', item.prompt)
|
|
582
|
+
.replace('{{DESIGN_INPUT}}', designInput)
|
|
583
|
+
.replace('{{LAYOUT_TYPE}}', layout)
|
|
584
|
+
.replace('{{COLUMN_EXAMPLE}}', columnPreset.example);
|
|
585
|
+
|
|
586
|
+
const copyResult = await callAskLemurAPI(
|
|
587
|
+
formattedCopyPrompt,
|
|
588
|
+
copyPromptDetails.system || '',
|
|
589
|
+
false,
|
|
590
|
+
isSandboxMode
|
|
591
|
+
);
|
|
592
|
+
copyResults.push(copyResult);
|
|
593
|
+
}
|
|
594
|
+
const finalPane = parseAiPane(shellResult, copyResults, layout);
|
|
595
|
+
handleApplyTemplate(finalPane);
|
|
603
596
|
}
|
|
604
|
-
|
|
605
|
-
const finalPane = parseAiPane(shellResult, copyResults, layout);
|
|
606
|
-
handleApplyTemplate(finalPane);
|
|
607
597
|
}
|
|
608
598
|
}
|
|
609
599
|
} catch (err: any) {
|
|
@@ -671,235 +661,62 @@ const AddPaneNewPanel = ({
|
|
|
671
661
|
</div>
|
|
672
662
|
);
|
|
673
663
|
|
|
674
|
-
const
|
|
675
|
-
|
|
676
|
-
<
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
onClick={handleBack}
|
|
704
|
-
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"
|
|
705
|
-
>
|
|
706
|
-
← Back
|
|
707
|
-
</button>
|
|
708
|
-
</div>
|
|
709
|
-
</div>
|
|
710
|
-
);
|
|
711
|
-
|
|
712
|
-
const renderContentStep = () => {
|
|
713
|
-
if (layoutChoice === 'grid') {
|
|
714
|
-
const isGenerateDisabled =
|
|
715
|
-
copyMode === 'prompt'
|
|
716
|
-
? !overallPrompt.trim() ||
|
|
717
|
-
!promptValueCol1.trim() ||
|
|
718
|
-
!promptValueCol2.trim()
|
|
719
|
-
: copyMode === 'raw'
|
|
720
|
-
? !col1Copy.trim() || !col2Copy.trim()
|
|
721
|
-
: false;
|
|
722
|
-
|
|
723
|
-
return (
|
|
724
|
-
<div className="space-y-4 p-4">
|
|
725
|
-
<label className="block text-lg font-bold text-gray-800">
|
|
726
|
-
1. Provide Content
|
|
727
|
-
</label>
|
|
728
|
-
|
|
729
|
-
<div className="my-2 flex flex-wrap gap-4">
|
|
730
|
-
<div className="flex items-center space-x-2">
|
|
731
|
-
<input
|
|
732
|
-
type="radio"
|
|
733
|
-
checked={copyMode === 'prompt'}
|
|
734
|
-
onChange={() => setCopyMode('prompt')}
|
|
735
|
-
className="h-4 w-4 border-gray-300 text-cyan-600 focus:ring-cyan-500"
|
|
736
|
-
/>
|
|
737
|
-
<label className="text-sm font-bold text-gray-700">Prompt</label>
|
|
738
|
-
</div>
|
|
739
|
-
<div className="flex items-center space-x-2">
|
|
740
|
-
<input
|
|
741
|
-
type="radio"
|
|
742
|
-
checked={copyMode === 'raw'}
|
|
743
|
-
onChange={() => setCopyMode('raw')}
|
|
744
|
-
className="h-4 w-4 border-gray-300 text-cyan-600 focus:ring-cyan-500"
|
|
745
|
-
/>
|
|
746
|
-
<label className="text-sm font-bold text-gray-700">
|
|
747
|
-
Manual Markdown
|
|
748
|
-
</label>
|
|
749
|
-
</div>
|
|
750
|
-
{selectedLibraryEntry?.retain && (
|
|
751
|
-
<div className="flex items-center space-x-2">
|
|
752
|
-
<input
|
|
753
|
-
type="radio"
|
|
754
|
-
checked={copyMode === 'original'}
|
|
755
|
-
onChange={() => setCopyMode('original')}
|
|
756
|
-
className="h-4 w-4 border-gray-300 text-cyan-600 focus:ring-cyan-500"
|
|
757
|
-
/>
|
|
758
|
-
<label className="text-sm font-bold text-gray-700">
|
|
759
|
-
Use Original
|
|
760
|
-
</label>
|
|
761
|
-
</div>
|
|
762
|
-
)}
|
|
763
|
-
</div>
|
|
764
|
-
|
|
765
|
-
{copyMode === 'raw' && initialChoice === 'library' && (
|
|
766
|
-
<div className="mb-4 flex items-center justify-between rounded-lg border border-gray-100 bg-gray-50 p-2">
|
|
767
|
-
<span className="text-sm text-gray-600">
|
|
768
|
-
Style this content with AI?
|
|
769
|
-
</span>
|
|
770
|
-
<div className="flex items-center">
|
|
771
|
-
<BooleanToggle
|
|
772
|
-
label="AI Styles"
|
|
773
|
-
value={isAiStyling}
|
|
774
|
-
onChange={setIsAiStyling}
|
|
775
|
-
size="sm"
|
|
776
|
-
/>
|
|
777
|
-
</div>
|
|
778
|
-
</div>
|
|
779
|
-
)}
|
|
780
|
-
|
|
781
|
-
{copyMode === 'prompt' && (
|
|
782
|
-
<>
|
|
783
|
-
<div className="mb-4">
|
|
784
|
-
<EnumSelect
|
|
785
|
-
label="Section Type"
|
|
786
|
-
value={selectedPromptId}
|
|
787
|
-
onChange={setSelectedPromptId}
|
|
788
|
-
options={promptOptions}
|
|
789
|
-
placeholder="Select a section type..."
|
|
790
|
-
className="w-full"
|
|
791
|
-
/>
|
|
792
|
-
</div>
|
|
793
|
-
<div>
|
|
794
|
-
<label className="mb-2 block text-sm font-bold text-gray-700">
|
|
795
|
-
Overall Component Brief
|
|
796
|
-
</label>
|
|
797
|
-
<textarea
|
|
798
|
-
value={overallPrompt}
|
|
799
|
-
onChange={(e) => setOverallPrompt(e.target.value)}
|
|
800
|
-
rows={3}
|
|
801
|
-
className="block w-full rounded-md border-gray-300 p-2 shadow-sm focus:border-cyan-500 focus:ring-cyan-500 sm:text-sm"
|
|
802
|
-
/>
|
|
803
|
-
<p className="mt-1 text-xs text-gray-500">
|
|
804
|
-
This context is applied to both columns.
|
|
805
|
-
</p>
|
|
806
|
-
</div>
|
|
807
|
-
<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
|
|
808
|
-
<div>
|
|
809
|
-
<label className="mb-2 block text-sm font-bold text-gray-700">
|
|
810
|
-
Left Column Prompt
|
|
811
|
-
</label>
|
|
812
|
-
<textarea
|
|
813
|
-
value={promptValueCol1}
|
|
814
|
-
onChange={(e) => setPromptValueCol1(e.target.value)}
|
|
815
|
-
rows={4}
|
|
816
|
-
className="block w-full rounded-md border-gray-300 p-2 shadow-sm focus:border-cyan-500 focus:ring-cyan-500 sm:text-sm"
|
|
817
|
-
/>
|
|
818
|
-
</div>
|
|
819
|
-
<div>
|
|
820
|
-
<label className="mb-2 block text-sm font-bold text-gray-700">
|
|
821
|
-
Right Column Prompt
|
|
822
|
-
</label>
|
|
823
|
-
<textarea
|
|
824
|
-
value={promptValueCol2}
|
|
825
|
-
onChange={(e) => setPromptValueCol2(e.target.value)}
|
|
826
|
-
rows={4}
|
|
827
|
-
className="block w-full rounded-md border-gray-300 p-2 shadow-sm focus:border-cyan-500 focus:ring-cyan-500 sm:text-sm"
|
|
828
|
-
/>
|
|
829
|
-
</div>
|
|
830
|
-
</div>
|
|
831
|
-
</>
|
|
832
|
-
)}
|
|
833
|
-
|
|
834
|
-
{copyMode === 'raw' && (
|
|
835
|
-
<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
|
|
836
|
-
<div>
|
|
837
|
-
<label className="mb-2 block text-sm font-bold text-gray-700">
|
|
838
|
-
Left Column Markdown
|
|
839
|
-
</label>
|
|
840
|
-
<textarea
|
|
841
|
-
value={col1Copy}
|
|
842
|
-
onChange={(e) => setCol1Copy(e.target.value)}
|
|
843
|
-
rows={8}
|
|
844
|
-
className="block w-full rounded-md border-gray-300 p-2 font-mono text-sm shadow-sm focus:border-cyan-500 focus:ring-cyan-500"
|
|
845
|
-
/>
|
|
846
|
-
</div>
|
|
847
|
-
<div>
|
|
848
|
-
<label className="mb-2 block text-sm font-bold text-gray-700">
|
|
849
|
-
Right Column Markdown
|
|
850
|
-
</label>
|
|
851
|
-
<textarea
|
|
852
|
-
value={col2Copy}
|
|
853
|
-
onChange={(e) => setCol2Copy(e.target.value)}
|
|
854
|
-
rows={8}
|
|
855
|
-
className="block w-full rounded-md border-gray-300 p-2 font-mono text-sm shadow-sm focus:border-cyan-500 focus:ring-cyan-500"
|
|
856
|
-
/>
|
|
857
|
-
</div>
|
|
858
|
-
</div>
|
|
859
|
-
)}
|
|
860
|
-
|
|
861
|
-
{copyMode === 'original' && (
|
|
862
|
-
<div className="rounded-md border border-blue-200 bg-blue-50 p-4 text-blue-700">
|
|
863
|
-
<p className="text-sm">
|
|
864
|
-
The original text saved with this design will be used.
|
|
865
|
-
</p>
|
|
664
|
+
const renderDashboard = () => {
|
|
665
|
+
return (
|
|
666
|
+
<div className="space-y-6 p-4">
|
|
667
|
+
{/* Layout Selection */}
|
|
668
|
+
{initialChoice === 'ai' && (
|
|
669
|
+
<div className="flex justify-center border-b pb-4">
|
|
670
|
+
<div className="inline-flex rounded-lg bg-gray-100 p-1">
|
|
671
|
+
<button
|
|
672
|
+
onClick={() => setLayoutChoice('standard')}
|
|
673
|
+
className={`flex items-center space-x-2 rounded-md px-4 py-2 text-sm font-bold transition-all ${
|
|
674
|
+
layoutChoice === 'standard'
|
|
675
|
+
? 'bg-white text-cyan-700 shadow-sm'
|
|
676
|
+
: 'text-gray-500 hover:text-gray-900'
|
|
677
|
+
}`}
|
|
678
|
+
>
|
|
679
|
+
<DocumentIcon className="h-5 w-5" />
|
|
680
|
+
<span>Standard Layout</span>
|
|
681
|
+
</button>
|
|
682
|
+
<button
|
|
683
|
+
onClick={() => setLayoutChoice('grid')}
|
|
684
|
+
className={`flex items-center space-x-2 rounded-md px-4 py-2 text-sm font-bold transition-all ${
|
|
685
|
+
layoutChoice === 'grid'
|
|
686
|
+
? 'bg-white text-cyan-700 shadow-sm'
|
|
687
|
+
: 'text-gray-500 hover:text-gray-900'
|
|
688
|
+
}`}
|
|
689
|
+
>
|
|
690
|
+
<SquaresPlusIcon className="h-5 w-5" />
|
|
691
|
+
<span>2-Column Grid</span>
|
|
692
|
+
</button>
|
|
866
693
|
</div>
|
|
867
|
-
)}
|
|
868
|
-
|
|
869
|
-
<div className="flex justify-between">
|
|
870
|
-
<button
|
|
871
|
-
onClick={handleBack}
|
|
872
|
-
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"
|
|
873
|
-
>
|
|
874
|
-
← Back
|
|
875
|
-
</button>
|
|
876
|
-
<button
|
|
877
|
-
onClick={handleFinalGenerate}
|
|
878
|
-
disabled={isGenerateDisabled}
|
|
879
|
-
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"
|
|
880
|
-
>
|
|
881
|
-
✨ Generate Pane
|
|
882
|
-
</button>
|
|
883
694
|
</div>
|
|
884
|
-
|
|
885
|
-
);
|
|
886
|
-
}
|
|
695
|
+
)}
|
|
887
696
|
|
|
888
|
-
return (
|
|
889
|
-
<div className="space-y-4 p-4">
|
|
890
697
|
<CopyInputStep
|
|
698
|
+
layoutChoice={layoutChoice}
|
|
891
699
|
copyMode={copyMode}
|
|
892
700
|
onCopyModeChange={setCopyMode}
|
|
701
|
+
topic={topic}
|
|
702
|
+
onTopicChange={setTopic}
|
|
703
|
+
showAdvancedPrompts={showAdvancedPrompts}
|
|
704
|
+
onShowAdvancedPromptsChange={setShowAdvancedPrompts}
|
|
893
705
|
promptValue={promptValue}
|
|
894
706
|
onPromptValueChange={setPromptValue}
|
|
895
707
|
copyValue={copyValue}
|
|
896
708
|
onCopyValueChange={setCopyValue}
|
|
709
|
+
overallPrompt={overallPrompt}
|
|
710
|
+
onOverallPromptChange={setOverallPrompt}
|
|
711
|
+
promptValueCol1={promptValueCol1}
|
|
712
|
+
onPromptValueCol1Change={setPromptValueCol1}
|
|
713
|
+
promptValueCol2={promptValueCol2}
|
|
714
|
+
onPromptValueCol2Change={setPromptValueCol2}
|
|
715
|
+
col1Copy={col1Copy}
|
|
716
|
+
onCol1CopyChange={setCol1Copy}
|
|
717
|
+
col2Copy={col2Copy}
|
|
718
|
+
onCol2CopyChange={setCol2Copy}
|
|
897
719
|
hasRetainedContent={selectedLibraryEntry?.retain}
|
|
898
|
-
defaultPrompt={
|
|
899
|
-
first
|
|
900
|
-
? prompts.aiPaneCopyPrompt.heroDefault
|
|
901
|
-
: prompts.aiPaneCopyPrompt.contentDefault
|
|
902
|
-
}
|
|
903
720
|
promptOptions={promptOptions}
|
|
904
721
|
selectedPromptId={selectedPromptId}
|
|
905
722
|
onSelectedPromptIdChange={setSelectedPromptId}
|
|
@@ -907,27 +724,61 @@ const AddPaneNewPanel = ({
|
|
|
907
724
|
onIsAiStylingChange={setIsAiStyling}
|
|
908
725
|
showStyleToggle={initialChoice === 'library'}
|
|
909
726
|
/>
|
|
910
|
-
|
|
727
|
+
|
|
728
|
+
{initialChoice === 'ai' && (
|
|
729
|
+
<>
|
|
730
|
+
<div className="my-4 flex items-center">
|
|
731
|
+
<BooleanToggle
|
|
732
|
+
label="Customize Styles"
|
|
733
|
+
value={showStyles}
|
|
734
|
+
onChange={setShowStyles}
|
|
735
|
+
size="sm"
|
|
736
|
+
/>
|
|
737
|
+
</div>
|
|
738
|
+
|
|
739
|
+
{showStyles && (
|
|
740
|
+
<div className="rounded-lg border border-gray-100 bg-gray-50 p-4">
|
|
741
|
+
<AiDesignStep
|
|
742
|
+
designConfig={aiDesignConfig}
|
|
743
|
+
onDesignConfigChange={setAiDesignConfig}
|
|
744
|
+
/>
|
|
745
|
+
</div>
|
|
746
|
+
)}
|
|
747
|
+
</>
|
|
748
|
+
)}
|
|
749
|
+
|
|
750
|
+
<div className="flex justify-between pt-4">
|
|
911
751
|
<button
|
|
912
752
|
onClick={handleBack}
|
|
913
753
|
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"
|
|
914
754
|
>
|
|
915
|
-
|
|
755
|
+
Cancel
|
|
916
756
|
</button>
|
|
917
757
|
<button
|
|
918
758
|
onClick={handleFinalGenerate}
|
|
919
759
|
disabled={
|
|
920
760
|
copyMode === 'prompt'
|
|
921
|
-
? !promptValue.trim()
|
|
761
|
+
? !promptValue.trim() && !overallPrompt.trim()
|
|
922
762
|
: copyMode === 'raw'
|
|
923
|
-
? !copyValue.trim()
|
|
763
|
+
? !copyValue.trim() && (!col1Copy.trim() || !col2Copy.trim())
|
|
924
764
|
: false
|
|
925
765
|
}
|
|
926
|
-
className="rounded-md bg-cyan-600 px-
|
|
766
|
+
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"
|
|
927
767
|
>
|
|
928
768
|
✨ Generate Pane
|
|
929
769
|
</button>
|
|
930
770
|
</div>
|
|
771
|
+
|
|
772
|
+
{initialChoice === 'ai' && !isSandboxMode && (
|
|
773
|
+
<div className="text-center text-sm text-gray-600">
|
|
774
|
+
<button
|
|
775
|
+
onClick={() => setStep('directInject')}
|
|
776
|
+
className="font-bold text-cyan-700 underline hover:text-cyan-900 focus:outline-none"
|
|
777
|
+
>
|
|
778
|
+
Direct Inject
|
|
779
|
+
</button>
|
|
780
|
+
</div>
|
|
781
|
+
)}
|
|
931
782
|
</div>
|
|
932
783
|
);
|
|
933
784
|
};
|
|
@@ -946,40 +797,6 @@ const AddPaneNewPanel = ({
|
|
|
946
797
|
</div>
|
|
947
798
|
);
|
|
948
799
|
|
|
949
|
-
const renderAiDesignStep = () => (
|
|
950
|
-
<div className="space-y-4 p-4">
|
|
951
|
-
<AiDesignStep
|
|
952
|
-
designConfig={aiDesignConfig}
|
|
953
|
-
onDesignConfigChange={setAiDesignConfig}
|
|
954
|
-
/>
|
|
955
|
-
<div className="flex justify-between">
|
|
956
|
-
<button
|
|
957
|
-
onClick={handleBack}
|
|
958
|
-
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"
|
|
959
|
-
>
|
|
960
|
-
← Back
|
|
961
|
-
</button>
|
|
962
|
-
<button
|
|
963
|
-
onClick={handleAiDesignContinue}
|
|
964
|
-
className="rounded-md bg-cyan-600 px-4 py-2 text-sm font-bold text-white shadow-sm hover:bg-cyan-700"
|
|
965
|
-
>
|
|
966
|
-
Continue →
|
|
967
|
-
</button>
|
|
968
|
-
</div>
|
|
969
|
-
{initialChoice === `ai` && !isSandboxMode && (
|
|
970
|
-
<div className="mt-6 text-center text-sm text-gray-600">
|
|
971
|
-
ADVANCED:{' '}
|
|
972
|
-
<button
|
|
973
|
-
onClick={() => setStep('directInject')}
|
|
974
|
-
className="font-bold text-cyan-700 underline hover:text-cyan-900 focus:outline-none"
|
|
975
|
-
>
|
|
976
|
-
Direct Inject
|
|
977
|
-
</button>
|
|
978
|
-
</div>
|
|
979
|
-
)}
|
|
980
|
-
</div>
|
|
981
|
-
);
|
|
982
|
-
|
|
983
800
|
const renderDirectInjectStep = () => (
|
|
984
801
|
<DirectInjectStep
|
|
985
802
|
onBack={handleBack}
|
|
@@ -1013,14 +830,10 @@ const AddPaneNewPanel = ({
|
|
|
1013
830
|
switch (step) {
|
|
1014
831
|
case 'initial':
|
|
1015
832
|
return renderInitialStep();
|
|
1016
|
-
case '
|
|
1017
|
-
return
|
|
1018
|
-
case 'copyInput':
|
|
1019
|
-
return renderContentStep();
|
|
833
|
+
case 'dashboard':
|
|
834
|
+
return renderDashboard();
|
|
1020
835
|
case 'designLibrary':
|
|
1021
836
|
return renderDesignLibraryStep();
|
|
1022
|
-
case 'aiDesign':
|
|
1023
|
-
return renderAiDesignStep();
|
|
1024
837
|
case 'loading':
|
|
1025
838
|
return renderLoading();
|
|
1026
839
|
case 'directInject':
|