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.
@@ -211,7 +211,8 @@ export const RestylePaneModal = () => {
211
211
  (entry: DesignLibraryEntry) =>
212
212
  (selectedCategory === 'all' || entry.category === selectedCategory) &&
213
213
  entry.title.toLowerCase().includes(searchTerm.toLowerCase()) &&
214
- entry.markdownCount === targetMarkdownCount
214
+ entry.markdownCount === targetMarkdownCount &&
215
+ !entry.locked
215
216
  );
216
217
  }, [designLibrary, selectedCategory, searchTerm, targetMarkdownCount]);
217
218
 
@@ -350,14 +351,15 @@ export const RestylePaneModal = () => {
350
351
  <Dialog.Root
351
352
  open={isRestyleModalOpen}
352
353
  onOpenChange={handleDialogStateChange}
353
- modal={false}
354
+ modal={true}
355
+ preventScroll={true}
354
356
  >
355
- <Dialog.Backdrop className="z-103 fixed inset-0 bg-black/70" />
357
+ <Dialog.Backdrop className="z-103 fixed inset-0 bg-black bg-opacity-75" />
356
358
  <Dialog.Positioner className="z-104 fixed inset-0 flex items-center justify-center">
357
359
  <Dialog.Content
358
360
  ref={contentRef}
359
- className="flex flex-col rounded-lg bg-white shadow-2xl"
360
- style={{ maxHeight: '90vw', width: '90vw' }}
361
+ className="flex max-w-5xl flex-col rounded-lg bg-white shadow-2xl xl:max-w-7xl"
362
+ style={{ maxHeight: '90vh', width: '90vw' }}
361
363
  >
362
364
  <header className="flex items-center justify-between border-b p-4">
363
365
  <Dialog.Title className="text-xl font-bold">
@@ -33,10 +33,7 @@ export const AiDesignStep = ({
33
33
  };
34
34
 
35
35
  return (
36
- <div className="space-y-6 rounded-lg bg-gray-50 p-4 shadow-inner">
37
- <label className="block text-lg font-bold text-gray-800">
38
- 2. Configure AI Design
39
- </label>
36
+ <div className="space-y-6">
40
37
  <div>
41
38
  <label className="block text-base font-bold text-gray-800">
42
39
  Color Harmony
@@ -1,4 +1,3 @@
1
- import { useEffect } from 'react';
2
1
  import BooleanToggle from '@/components/form/BooleanToggle';
3
2
  import EnumSelect from '@/components/form/EnumSelect';
4
3
 
@@ -10,13 +9,32 @@ interface PromptOption {
10
9
  }
11
10
 
12
11
  interface CopyInputStepProps {
12
+ layoutChoice: 'standard' | 'grid';
13
13
  copyMode: CopyMode;
14
14
  onCopyModeChange: (mode: CopyMode) => void;
15
+
16
+ topic: string;
17
+ onTopicChange: (value: string) => void;
18
+
19
+ showAdvancedPrompts: boolean;
20
+ onShowAdvancedPromptsChange: (value: boolean) => void;
21
+
15
22
  promptValue: string;
16
23
  onPromptValueChange: (value: string) => void;
17
24
  copyValue: string;
18
25
  onCopyValueChange: (value: string) => void;
19
- defaultPrompt?: string;
26
+
27
+ overallPrompt: string;
28
+ onOverallPromptChange: (value: string) => void;
29
+ promptValueCol1: string;
30
+ onPromptValueCol1Change: (value: string) => void;
31
+ promptValueCol2: string;
32
+ onPromptValueCol2Change: (value: string) => void;
33
+ col1Copy: string;
34
+ onCol1CopyChange: (value: string) => void;
35
+ col2Copy: string;
36
+ onCol2CopyChange: (value: string) => void;
37
+
20
38
  hasRetainedContent?: boolean;
21
39
  promptOptions: PromptOption[];
22
40
  selectedPromptId: string;
@@ -27,13 +45,27 @@ interface CopyInputStepProps {
27
45
  }
28
46
 
29
47
  export const CopyInputStep = ({
48
+ layoutChoice,
30
49
  copyMode,
31
50
  onCopyModeChange,
51
+ topic,
52
+ onTopicChange,
53
+ showAdvancedPrompts,
54
+ onShowAdvancedPromptsChange,
32
55
  promptValue,
33
56
  onPromptValueChange,
34
57
  copyValue,
35
58
  onCopyValueChange,
36
- defaultPrompt,
59
+ overallPrompt,
60
+ onOverallPromptChange,
61
+ promptValueCol1,
62
+ onPromptValueCol1Change,
63
+ promptValueCol2,
64
+ onPromptValueCol2Change,
65
+ col1Copy,
66
+ onCol1CopyChange,
67
+ col2Copy,
68
+ onCol2CopyChange,
37
69
  hasRetainedContent = false,
38
70
  promptOptions,
39
71
  selectedPromptId,
@@ -42,77 +74,182 @@ export const CopyInputStep = ({
42
74
  onIsAiStylingChange,
43
75
  showStyleToggle = true,
44
76
  }: CopyInputStepProps) => {
45
- useEffect(() => {
46
- if (defaultPrompt && !promptValue) {
47
- onPromptValueChange(defaultPrompt);
48
- }
49
- }, [defaultPrompt, promptValue, onPromptValueChange]);
50
-
51
- return (
52
- <div className="space-y-4 rounded-lg bg-gray-50 p-4 shadow-inner">
53
- <label className="block text-lg font-bold text-gray-800">
54
- 1. Provide Content
55
- </label>
56
- <div className="my-2 flex flex-wrap gap-4">
77
+ const renderModeSelection = () => (
78
+ <div className="my-2 flex flex-wrap gap-4">
79
+ <div className="flex items-center space-x-2">
80
+ <input
81
+ type="radio"
82
+ id="copy-prompt-mode"
83
+ name="copyModeOptions"
84
+ value="prompt"
85
+ checked={copyMode === 'prompt'}
86
+ onChange={(e) => onCopyModeChange(e.target.value as CopyMode)}
87
+ className="h-4 w-4 border-gray-300 text-cyan-600 focus:ring-cyan-500"
88
+ />
89
+ <label
90
+ htmlFor="copy-prompt-mode"
91
+ className="text-sm font-bold text-gray-700"
92
+ >
93
+ Write a prompt
94
+ </label>
95
+ </div>
96
+ <div className="flex items-center space-x-2">
97
+ <input
98
+ type="radio"
99
+ id="copy-raw-mode"
100
+ name="copyModeOptions"
101
+ value="raw"
102
+ checked={copyMode === 'raw'}
103
+ onChange={(e) => onCopyModeChange(e.target.value as CopyMode)}
104
+ className="h-4 w-4 border-gray-300 text-cyan-600 focus:ring-cyan-500"
105
+ />
106
+ <label
107
+ htmlFor="copy-raw-mode"
108
+ className="text-sm font-bold text-gray-700"
109
+ >
110
+ Provide Copy (Markdown)
111
+ </label>
112
+ </div>
113
+ {hasRetainedContent && (
57
114
  <div className="flex items-center space-x-2">
58
115
  <input
59
116
  type="radio"
60
- id="copy-prompt-mode"
117
+ id="copy-original-mode"
61
118
  name="copyModeOptions"
62
- value="prompt"
63
- checked={copyMode === 'prompt'}
119
+ value="original"
120
+ checked={copyMode === 'original'}
64
121
  onChange={(e) => onCopyModeChange(e.target.value as CopyMode)}
65
122
  className="h-4 w-4 border-gray-300 text-cyan-600 focus:ring-cyan-500"
66
123
  />
67
124
  <label
68
- htmlFor="copy-prompt-mode"
125
+ htmlFor="copy-original-mode"
69
126
  className="text-sm font-bold text-gray-700"
70
127
  >
71
- Write a prompt
128
+ Use Original
72
129
  </label>
73
130
  </div>
74
- <div className="flex items-center space-x-2">
75
- <input
76
- type="radio"
77
- id="copy-raw-mode"
78
- name="copyModeOptions"
79
- value="raw"
80
- checked={copyMode === 'raw'}
81
- onChange={(e) => onCopyModeChange(e.target.value as CopyMode)}
82
- className="h-4 w-4 border-gray-300 text-cyan-600 focus:ring-cyan-500"
83
- />
84
- <label
85
- htmlFor="copy-raw-mode"
86
- className="text-sm font-bold text-gray-700"
87
- >
88
- Provide Copy (Markdown)
89
- </label>
131
+ )}
132
+ </div>
133
+ );
134
+
135
+ const renderPromptMode = () => (
136
+ <>
137
+ <div className="mb-4">
138
+ <EnumSelect
139
+ label="Section Type"
140
+ value={selectedPromptId}
141
+ onChange={onSelectedPromptIdChange}
142
+ options={promptOptions}
143
+ placeholder="Select a type..."
144
+ className="w-full"
145
+ />
146
+ </div>
147
+
148
+ <div className="mb-4">
149
+ <label className="mb-2 block text-sm font-bold text-gray-700">
150
+ Topic / Context
151
+ </label>
152
+ <textarea
153
+ value={topic}
154
+ onChange={(e) => onTopicChange(e.target.value)}
155
+ placeholder="e.g. a SaaS product for team collaboration"
156
+ rows={2}
157
+ className="block w-full rounded-md border-gray-300 p-2 shadow-sm focus:border-cyan-500 focus:ring-cyan-500 sm:text-sm"
158
+ />
159
+ </div>
160
+
161
+ <div className="mb-4 flex items-center">
162
+ <BooleanToggle
163
+ label="Advanced: Edit Full Prompts"
164
+ value={showAdvancedPrompts}
165
+ onChange={onShowAdvancedPromptsChange}
166
+ size="sm"
167
+ />
168
+ </div>
169
+
170
+ {showAdvancedPrompts && (
171
+ <div className="mt-4 space-y-4 rounded-md border border-gray-200 bg-white p-4">
172
+ {layoutChoice === 'standard' ? (
173
+ <div>
174
+ <label className="mb-2 block text-sm font-bold text-gray-700">
175
+ Full Prompt
176
+ </label>
177
+ <textarea
178
+ value={promptValue}
179
+ onChange={(e) => onPromptValueChange(e.target.value)}
180
+ rows={4}
181
+ className="block w-full rounded-md border-gray-300 p-2 shadow-sm focus:border-cyan-500 focus:ring-cyan-500 sm:text-sm"
182
+ />
183
+ <p className="mt-1 text-xs text-gray-500">
184
+ Leave [topic] as it will be replaced with your prompt.
185
+ </p>
186
+ </div>
187
+ ) : (
188
+ <>
189
+ <div>
190
+ <label className="mb-2 block text-sm font-bold text-gray-700">
191
+ Overall Component Brief
192
+ </label>
193
+ <textarea
194
+ value={overallPrompt}
195
+ onChange={(e) => onOverallPromptChange(e.target.value)}
196
+ rows={3}
197
+ className="block w-full rounded-md border-gray-300 p-2 shadow-sm focus:border-cyan-500 focus:ring-cyan-500 sm:text-sm"
198
+ />
199
+ </div>
200
+ <div className="grid grid-cols-1 gap-6 md:grid-cols-2">
201
+ <div>
202
+ <label className="mb-2 block text-sm font-bold text-gray-700">
203
+ Left Column Prompt
204
+ </label>
205
+ <textarea
206
+ value={promptValueCol1}
207
+ onChange={(e) => onPromptValueCol1Change(e.target.value)}
208
+ rows={4}
209
+ className="block w-full rounded-md border-gray-300 p-2 shadow-sm focus:border-cyan-500 focus:ring-cyan-500 sm:text-sm"
210
+ />
211
+ </div>
212
+ <div>
213
+ <label className="mb-2 block text-sm font-bold text-gray-700">
214
+ Right Column Prompt
215
+ </label>
216
+ <textarea
217
+ value={promptValueCol2}
218
+ onChange={(e) => onPromptValueCol2Change(e.target.value)}
219
+ rows={4}
220
+ className="block w-full rounded-md border-gray-300 p-2 shadow-sm focus:border-cyan-500 focus:ring-cyan-500 sm:text-sm"
221
+ />
222
+ </div>
223
+ </div>
224
+ </>
225
+ )}
90
226
  </div>
91
- {hasRetainedContent && (
92
- <div className="flex items-center space-x-2">
93
- <input
94
- type="radio"
95
- id="copy-original-mode"
96
- name="copyModeOptions"
97
- value="original"
98
- checked={copyMode === 'original'}
99
- onChange={(e) => onCopyModeChange(e.target.value as CopyMode)}
100
- className="h-4 w-4 border-gray-300 text-cyan-600 focus:ring-cyan-500"
227
+ )}
228
+ </>
229
+ );
230
+
231
+ const renderRawMode = () => (
232
+ <>
233
+ <div className="mb-2 flex items-center justify-between">
234
+ <p className="text-sm text-gray-500">
235
+ Provide your raw copy here. Use Markdown.
236
+ </p>
237
+ {showStyleToggle && (
238
+ <div className="flex items-center">
239
+ <BooleanToggle
240
+ label="Style with AI"
241
+ value={isAiStyling}
242
+ onChange={onIsAiStylingChange}
243
+ size="sm"
101
244
  />
102
- <label
103
- htmlFor="copy-original-mode"
104
- className="text-sm font-bold text-gray-700"
105
- >
106
- Use Original
107
- </label>
108
245
  </div>
109
246
  )}
110
247
  </div>
111
248
 
112
- {(copyMode === 'prompt' || (copyMode === 'raw' && isAiStyling)) && (
249
+ {isAiStyling && (
113
250
  <div className="mb-4">
114
251
  <EnumSelect
115
- label="Section Type"
252
+ label="Section Type (for Styling)"
116
253
  value={selectedPromptId}
117
254
  onChange={onSelectedPromptIdChange}
118
255
  options={promptOptions}
@@ -122,49 +259,54 @@ export const CopyInputStep = ({
122
259
  </div>
123
260
  )}
124
261
 
125
- {copyMode === 'prompt' && (
126
- <>
127
- <p className="mb-2 text-sm text-gray-500">
128
- Let the AI write the copy based on your prompt.
129
- </p>
130
- <textarea
131
- id="copy-prompt"
132
- value={promptValue}
133
- onChange={(e) => onPromptValueChange(e.target.value)}
134
- placeholder="e.g., A hero section for a SaaS product that helps teams collaborate..."
135
- rows={4}
136
- className="block w-full rounded-md border-gray-300 p-2 shadow-sm focus:border-cyan-500 focus:ring-cyan-500 sm:text-sm"
137
- />
138
- </>
139
- )}
140
-
141
- {copyMode === 'raw' && (
142
- <>
143
- <div className="mb-2 flex items-center justify-between">
144
- <p className="text-sm text-gray-500">
145
- Provide your raw copy here. Use Markdown.
146
- </p>
147
- {showStyleToggle && (
148
- <div className="flex items-center">
149
- <BooleanToggle
150
- label="Style with AI"
151
- value={isAiStyling}
152
- onChange={onIsAiStylingChange}
153
- size="sm"
154
- />
155
- </div>
156
- )}
262
+ {layoutChoice === 'standard' ? (
263
+ <textarea
264
+ id="raw-copy"
265
+ value={copyValue}
266
+ onChange={(e) => onCopyValueChange(e.target.value)}
267
+ placeholder="## My Awesome Headline..."
268
+ rows={6}
269
+ 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"
270
+ />
271
+ ) : (
272
+ <div className="grid grid-cols-1 gap-6 md:grid-cols-2">
273
+ <div>
274
+ <label className="mb-2 block text-sm font-bold text-gray-700">
275
+ Left Column Markdown
276
+ </label>
277
+ <textarea
278
+ value={col1Copy}
279
+ onChange={(e) => onCol1CopyChange(e.target.value)}
280
+ rows={8}
281
+ 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"
282
+ />
157
283
  </div>
158
- <textarea
159
- id="raw-copy"
160
- value={copyValue}
161
- onChange={(e) => onCopyValueChange(e.target.value)}
162
- placeholder="## My Awesome Headline..."
163
- rows={6}
164
- 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"
165
- />
166
- </>
284
+ <div>
285
+ <label className="mb-2 block text-sm font-bold text-gray-700">
286
+ Right Column Markdown
287
+ </label>
288
+ <textarea
289
+ value={col2Copy}
290
+ onChange={(e) => onCol2CopyChange(e.target.value)}
291
+ rows={8}
292
+ 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"
293
+ />
294
+ </div>
295
+ </div>
167
296
  )}
297
+ </>
298
+ );
299
+
300
+ return (
301
+ <>
302
+ <label className="block text-lg font-bold text-gray-800">
303
+ Content Configuration
304
+ </label>
305
+
306
+ {renderModeSelection()}
307
+
308
+ {copyMode === 'prompt' && renderPromptMode()}
309
+ {copyMode === 'raw' && renderRawMode()}
168
310
 
169
311
  {copyMode === 'original' && (
170
312
  <div className="rounded-md border border-blue-200 bg-blue-50 p-4 text-blue-700">
@@ -173,6 +315,6 @@ export const CopyInputStep = ({
173
315
  </p>
174
316
  </div>
175
317
  )}
176
- </div>
318
+ </>
177
319
  );
178
320
  };
@@ -46,30 +46,32 @@ const mainStylesUrl = isDev
46
46
  )
47
47
  }
48
48
 
49
- <script>
50
- (function initCleanSlate() {
51
- try {
52
- document.cookie =
53
- 'admin_auth=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax';
54
- document.cookie =
55
- 'editor_auth=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax';
56
- document.cookie =
57
- 'tractstack_session_id=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax';
49
+ <script is:inline>
50
+ if (typeof document !== 'undefined') {
51
+ (function initCleanSlate() {
52
+ try {
53
+ document.cookie =
54
+ 'admin_auth=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax';
55
+ document.cookie =
56
+ 'editor_auth=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax';
57
+ document.cookie =
58
+ 'tractstack_session_id=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax';
58
59
 
59
- const tractStackKeys = [];
60
- for (let i = 0; i < localStorage.length; i++) {
61
- const key = localStorage.key(i);
62
- if (key && key.startsWith('tractstack_')) {
63
- tractStackKeys.push(key);
60
+ const tractStackKeys = [];
61
+ for (let i = 0; i < localStorage.length; i++) {
62
+ const key = localStorage.key(i);
63
+ if (key && key.startsWith('tractstack_')) {
64
+ tractStackKeys.push(key);
65
+ }
64
66
  }
65
- }
66
- tractStackKeys.forEach((key) => localStorage.removeItem(key));
67
+ tractStackKeys.forEach((key) => localStorage.removeItem(key));
67
68
 
68
- console.log('TractStack: Clean slate initialization complete');
69
- } catch (error) {
70
- console.warn('TractStack: Error during clean slate init:', error);
71
- }
72
- })();
69
+ console.log('TractStack: Clean slate initialization complete');
70
+ } catch (error) {
71
+ console.warn('TractStack: Error during clean slate init:', error);
72
+ }
73
+ })();
74
+ }
73
75
  </script>
74
76
  </body>
75
77
  </html>