@alpaca-editor/core 1.0.3902 → 1.0.3904

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.
Files changed (98) hide show
  1. package/dist/components/ui/CardConnector.d.ts +2 -1
  2. package/dist/components/ui/CardConnector.js +3 -3
  3. package/dist/components/ui/CardConnector.js.map +1 -1
  4. package/dist/components/ui/button.js +1 -1
  5. package/dist/components/ui/button.js.map +1 -1
  6. package/dist/components/ui/card.d.ts +7 -1
  7. package/dist/components/ui/card.js +71 -3
  8. package/dist/components/ui/card.js.map +1 -1
  9. package/dist/config/config.js +4 -2
  10. package/dist/config/config.js.map +1 -1
  11. package/dist/config/types.d.ts +1 -0
  12. package/dist/editor/MobileLayout.js +1 -1
  13. package/dist/editor/MobileLayout.js.map +1 -1
  14. package/dist/editor/PictureEditor.js +13 -5
  15. package/dist/editor/PictureEditor.js.map +1 -1
  16. package/dist/editor/client/EditorClient.js +2 -2
  17. package/dist/editor/client/EditorClient.js.map +1 -1
  18. package/dist/editor/client/editContext.d.ts +14 -1
  19. package/dist/editor/client/editContext.js.map +1 -1
  20. package/dist/editor/client/operations.js +1 -1
  21. package/dist/editor/client/operations.js.map +1 -1
  22. package/dist/editor/page-editor-chrome/CommentHighlighting.js +4 -1
  23. package/dist/editor/page-editor-chrome/CommentHighlighting.js.map +1 -1
  24. package/dist/editor/ui/Splitter.js +3 -1
  25. package/dist/editor/ui/Splitter.js.map +1 -1
  26. package/dist/page-wizard/WizardBoxConnector.d.ts +2 -1
  27. package/dist/page-wizard/WizardBoxConnector.js +3 -3
  28. package/dist/page-wizard/WizardBoxConnector.js.map +1 -1
  29. package/dist/page-wizard/WizardSteps.js +63 -17
  30. package/dist/page-wizard/WizardSteps.js.map +1 -1
  31. package/dist/page-wizard/service.d.ts +1 -1
  32. package/dist/page-wizard/service.js +1 -1
  33. package/dist/page-wizard/service.js.map +1 -1
  34. package/dist/page-wizard/steps/CollectStep.js +11 -17
  35. package/dist/page-wizard/steps/CollectStep.js.map +1 -1
  36. package/dist/page-wizard/steps/ComponentTypesSelector.d.ts +1 -0
  37. package/dist/page-wizard/steps/ComponentTypesSelector.js +53 -78
  38. package/dist/page-wizard/steps/ComponentTypesSelector.js.map +1 -1
  39. package/dist/page-wizard/steps/ContentStep.d.ts +2 -0
  40. package/dist/page-wizard/steps/ContentStep.js +403 -0
  41. package/dist/page-wizard/steps/ContentStep.js.map +1 -0
  42. package/dist/page-wizard/steps/Generate.js +1 -1
  43. package/dist/page-wizard/steps/Generate.js.map +1 -1
  44. package/dist/page-wizard/steps/ImagesStep.js +16 -13
  45. package/dist/page-wizard/steps/ImagesStep.js.map +1 -1
  46. package/dist/page-wizard/steps/SelectStep.js +1 -1
  47. package/dist/page-wizard/steps/SelectStep.js.map +1 -1
  48. package/dist/page-wizard/steps/SetupPageStep.d.ts +2 -0
  49. package/dist/page-wizard/steps/SetupPageStep.js +152 -0
  50. package/dist/page-wizard/steps/SetupPageStep.js.map +1 -0
  51. package/dist/page-wizard/steps/usePageCreator.js +4 -4
  52. package/dist/page-wizard/steps/usePageCreator.js.map +1 -1
  53. package/dist/page-wizard/usePageWizard.d.ts +17 -3
  54. package/dist/page-wizard/usePageWizard.js +62 -2
  55. package/dist/page-wizard/usePageWizard.js.map +1 -1
  56. package/dist/revision.d.ts +2 -2
  57. package/dist/revision.js +2 -2
  58. package/dist/splash-screen/NewPage.js +10 -10
  59. package/dist/splash-screen/NewPage.js.map +1 -1
  60. package/dist/splash-screen/SplashScreen.js +3 -3
  61. package/dist/splash-screen/SplashScreen.js.map +1 -1
  62. package/dist/styles.css +184 -68
  63. package/package.json +1 -1
  64. package/src/components/ui/CardConnector.tsx +50 -15
  65. package/src/components/ui/button.tsx +1 -1
  66. package/src/components/ui/card.tsx +331 -15
  67. package/src/config/config.tsx +4 -2
  68. package/src/config/types.ts +3 -0
  69. package/src/editor/MobileLayout.tsx +7 -9
  70. package/src/editor/PictureEditor.tsx +16 -10
  71. package/src/editor/client/EditorClient.tsx +3 -5
  72. package/src/editor/client/editContext.ts +23 -1
  73. package/src/editor/client/operations.ts +1 -1
  74. package/src/editor/page-editor-chrome/CommentHighlighting.tsx +6 -1
  75. package/src/editor/ui/Splitter.tsx +10 -1
  76. package/src/page-wizard/WizardBoxConnector.tsx +50 -15
  77. package/src/page-wizard/WizardSteps.tsx +163 -34
  78. package/src/page-wizard/service.ts +2 -2
  79. package/src/page-wizard/steps/CollectStep.tsx +95 -141
  80. package/src/page-wizard/steps/ComponentTypesSelector.tsx +225 -245
  81. package/src/page-wizard/steps/ContentStep.tsx +648 -0
  82. package/src/page-wizard/steps/Generate.tsx +3 -3
  83. package/src/page-wizard/steps/ImagesStep.tsx +20 -15
  84. package/src/page-wizard/steps/SelectStep.tsx +4 -4
  85. package/src/page-wizard/steps/SetupPageStep.tsx +329 -0
  86. package/src/page-wizard/steps/usePageCreator.ts +4 -4
  87. package/src/page-wizard/usePageWizard.ts +69 -4
  88. package/src/revision.ts +2 -2
  89. package/src/splash-screen/NewPage.tsx +22 -16
  90. package/src/splash-screen/SplashScreen.tsx +3 -1
  91. package/dist/page-wizard/steps/CreatePage.d.ts +0 -12
  92. package/dist/page-wizard/steps/CreatePage.js +0 -149
  93. package/dist/page-wizard/steps/CreatePage.js.map +0 -1
  94. package/dist/page-wizard/steps/CreatePageAndLayoutStep.d.ts +0 -2
  95. package/dist/page-wizard/steps/CreatePageAndLayoutStep.js +0 -235
  96. package/dist/page-wizard/steps/CreatePageAndLayoutStep.js.map +0 -1
  97. package/src/page-wizard/steps/CreatePage.tsx +0 -329
  98. package/src/page-wizard/steps/CreatePageAndLayoutStep.tsx +0 -430
@@ -1,21 +1,56 @@
1
1
  import { cn } from "../lib/utils";
2
2
 
3
- export function WizardBoxConnector({ className }: { className?: string }) {
3
+ export function WizardBoxConnector({
4
+ className,
5
+ direction,
6
+ }: {
7
+ className?: string;
8
+ direction?: "horizontal" | "vertical";
9
+ }) {
4
10
  return (
5
- <div className={cn("mr-[-3px] ml-[-3px]", className)}>
6
- <svg
7
- className={className}
8
- width="31"
9
- height="40"
10
- viewBox="0 0 31 40"
11
- fill="none"
12
- xmlns="http://www.w3.org/2000/svg"
11
+ <>
12
+ <div
13
+ className={cn(
14
+ "mt-[-3px] mb-[-3px] flex items-center justify-center",
15
+ className,
16
+ (!direction || direction === "horizontal") && "md:hidden",
17
+ )}
13
18
  >
14
- <path
15
- d="M3.04199 0C3.55018 6.15949 8.70936 11 15 11C21.2906 11 26.4498 6.1595 26.958 0H31V40H27C27 33.3726 21.6274 28 15 28C8.37258 28 3 33.3726 3 40H0V0H3.04199Z"
16
- fill="white"
17
- />
18
- </svg>
19
- </div>
19
+ <svg
20
+ width="40"
21
+ height="31"
22
+ viewBox="0 0 40 31"
23
+ fill="none"
24
+ xmlns="http://www.w3.org/2000/svg"
25
+ >
26
+ <path
27
+ d="M40 3.04199C33.8405 3.55018 29 8.70936 29 15C29 21.2906 33.8405 26.4498 40 26.958L40 31L-1.35505e-06 31L-1.18021e-06 27C6.62741 27 12 21.6274 12 15C12 8.37258 6.62741 3 -1.31134e-07 3L0 -1.74846e-06L40 0L40 3.04199Z"
28
+ fill="white"
29
+ />
30
+ </svg>
31
+ </div>
32
+
33
+ <div
34
+ className={cn(
35
+ "mt-6 mr-[-3px] ml-[-3px] hidden",
36
+ className,
37
+ (!direction || direction === "horizontal") && "md:block",
38
+ )}
39
+ >
40
+ <svg
41
+ className={className}
42
+ width="31"
43
+ height="40"
44
+ viewBox="0 0 31 40"
45
+ fill="none"
46
+ xmlns="http://www.w3.org/2000/svg"
47
+ >
48
+ <path
49
+ d="M3.04199 0C3.55018 6.15949 8.70936 11 15 11C21.2906 11 26.4498 6.1595 26.958 0H31V40H27C27 33.3726 21.6274 28 15 28C8.37258 28 3 33.3726 3 40H0V0H3.04199Z"
50
+ fill="white"
51
+ />
52
+ </svg>
53
+ </div>
54
+ </>
20
55
  );
21
56
  }
@@ -1,4 +1,4 @@
1
- import { useState } from "react";
1
+ import React from "react";
2
2
  import { Wizard, WizardData, WizardPageModel } from "./PageWizard";
3
3
 
4
4
  import { ItemDescriptor } from "../editor/pageModel";
@@ -11,6 +11,7 @@ import { ChevronLeft, ChevronRight } from "lucide-react";
11
11
 
12
12
  import { Button } from "../components/ui/button";
13
13
  import { cn } from "../lib/utils";
14
+ import { useRef, useEffect } from "react";
14
15
 
15
16
  interface WizardStepsProps {
16
17
  wizard: Wizard;
@@ -45,6 +46,7 @@ interface WizardHeaderProps {
45
46
  onNext: () => void;
46
47
  onFinish: () => void;
47
48
  stepCompleted: number;
49
+ isMobile: boolean;
48
50
  }
49
51
 
50
52
  interface WizardContentProps {
@@ -52,6 +54,15 @@ interface WizardContentProps {
52
54
  children: React.ReactNode;
53
55
  }
54
56
 
57
+ interface MobileNavigationButtonsProps {
58
+ currentStepIndex: number;
59
+ wizard: Wizard;
60
+ stepCompleted: number;
61
+ onPrevious: () => void;
62
+ onNext: () => void;
63
+ onFinish: () => void;
64
+ }
65
+
55
66
  function PreviousButton({
56
67
  currentStepIndex,
57
68
  wizard,
@@ -97,16 +108,32 @@ function NavigationSteps({
97
108
  currentStepIndex,
98
109
  onStepClick,
99
110
  }: NavigationStepsProps) {
111
+ const stepRefs = useRef<(HTMLDivElement | null)[]>([]);
112
+
113
+ useEffect(() => {
114
+ const activeStepElement = stepRefs.current[currentStepIndex];
115
+ if (activeStepElement) {
116
+ activeStepElement.scrollIntoView({
117
+ behavior: "smooth",
118
+ block: "nearest",
119
+ inline: "center",
120
+ });
121
+ }
122
+ }, [currentStepIndex]);
123
+
100
124
  return (
101
125
  <div className="min-w-0 flex-1">
102
- <div className="scrollbar-hide overflow-x-auto scroll-smooth p-2.5 text-xs">
103
- <div className="flex min-w-max items-center gap-3 md:justify-center">
126
+ <div className="p-2.5 text-xs">
127
+ <div className="flex items-center gap-3 md:justify-center">
104
128
  {wizard.steps.map((step, index) => (
105
129
  <>
106
130
  <div
107
131
  key={step.id}
132
+ ref={(el) => {
133
+ stepRefs.current[index] = el;
134
+ }}
108
135
  className={classNames(
109
- "flex min-w-max flex-col items-center gap-1 px-1",
136
+ "flex shrink-0 flex-col items-center gap-1 px-1",
110
137
  currentStepIndex > index && "cursor-pointer",
111
138
  )}
112
139
  onClick={() =>
@@ -131,7 +158,7 @@ function NavigationSteps({
131
158
  currentStepIndex === index
132
159
  ? "text-theme-secondary font-semibold"
133
160
  : currentStepIndex >= index
134
- ? "text-gray-600"
161
+ ? "text-theme-secondary"
135
162
  : "text-gray-400",
136
163
  )}
137
164
  >
@@ -140,7 +167,14 @@ function NavigationSteps({
140
167
  </div>
141
168
 
142
169
  {index < wizard.steps.length - 1 && (
143
- <div className="border-theme-secondary mt-[-20px] h-0 w-4 shrink-0 border-t-2 bg-gray-300 md:w-8" />
170
+ <div
171
+ className={cn(
172
+ index < currentStepIndex
173
+ ? "border-theme-secondary"
174
+ : "border-gray-400",
175
+ "mt-[-20px] h-0 w-4 shrink-0 border-t-2 bg-gray-300 md:w-8",
176
+ )}
177
+ />
144
178
  )}
145
179
  </>
146
180
  ))}
@@ -158,14 +192,19 @@ function WizardHeader({
158
192
  onNext,
159
193
  onFinish,
160
194
  stepCompleted,
195
+ isMobile,
161
196
  }: WizardHeaderProps) {
162
197
  return (
163
- <div className="flex items-center gap-3 border-b border-gray-300 bg-white md:pr-8">
164
- <PreviousButton
165
- currentStepIndex={currentStepIndex}
166
- wizard={wizard}
167
- onPrevious={onPrevious}
168
- />
198
+ <div className="scrollbar-hide flex w-[100vw] items-center gap-3 overflow-x-auto scroll-smooth border-b border-gray-300 bg-white md:w-auto md:px-4">
199
+ {!isMobile && (
200
+ <div className="shrink-0">
201
+ <PreviousButton
202
+ currentStepIndex={currentStepIndex}
203
+ wizard={wizard}
204
+ onPrevious={onPrevious}
205
+ />
206
+ </div>
207
+ )}
169
208
 
170
209
  <NavigationSteps
171
210
  wizard={wizard}
@@ -173,26 +212,28 @@ function WizardHeader({
173
212
  onStepClick={onStepClick}
174
213
  />
175
214
 
176
- <div>
177
- <NextButton
178
- currentStepIndex={currentStepIndex}
179
- wizard={wizard}
180
- stepCompleted={stepCompleted}
181
- onNext={onNext}
182
- onFinish={onFinish}
183
- />
184
- </div>
215
+ {!isMobile && (
216
+ <div className="shrink-0">
217
+ <NextButton
218
+ currentStepIndex={currentStepIndex}
219
+ wizard={wizard}
220
+ stepCompleted={stepCompleted}
221
+ onNext={onNext}
222
+ onFinish={onFinish}
223
+ />
224
+ </div>
225
+ )}
185
226
  </div>
186
227
  );
187
228
  }
188
229
 
189
230
  function WizardContent({ currentStep, children }: WizardContentProps) {
190
231
  return (
191
- <div className="relative flex-1 bg-neutral-100">
192
- <div className="h-full p-8">
232
+ <div className="relative h-full flex-1 bg-neutral-100">
233
+ <div className="h-full p-4 md:p-8">
193
234
  <div className="relative z-10 h-full">
194
- <div className="flex h-full flex-col">
195
- <div className="mb-5 flex gap-4 md:mb-10">
235
+ <div className="flex h-full flex-col gap-6 md:gap-10">
236
+ <div className="flex gap-4">
196
237
  <Logo className="h-8 w-8" />
197
238
  <div className="flex-1 text-neutral-800">
198
239
  <div className="text-lg font-semibold md:text-xl">
@@ -205,7 +246,9 @@ function WizardContent({ currentStep, children }: WizardContentProps) {
205
246
  )}
206
247
  </div>
207
248
  </div>
208
- <div className="relative flex-1">{children}</div>
249
+ <div className="relative flex-1">
250
+ <div className="absolute inset-0 overflow-auto">{children}</div>
251
+ </div>
209
252
  </div>
210
253
  </div>
211
254
  <div className="bg-wizard absolute inset-0" />
@@ -214,19 +257,84 @@ function WizardContent({ currentStep, children }: WizardContentProps) {
214
257
  );
215
258
  }
216
259
 
260
+ function MobileNavigationButtons({
261
+ currentStepIndex,
262
+ wizard,
263
+ stepCompleted,
264
+ onPrevious,
265
+ onNext,
266
+ onFinish,
267
+ }: MobileNavigationButtonsProps) {
268
+ const isLastStep = currentStepIndex === wizard.steps.length - 1;
269
+ const isNextDisabled = stepCompleted < currentStepIndex;
270
+ const showPrevious = currentStepIndex > 0;
271
+
272
+ return (
273
+ <div className="srcollbar-hide w-[100vw] overflow-x-auto border-t border-gray-300 bg-white px-4 py-3">
274
+ <div className="flex gap-3">
275
+ {showPrevious && (
276
+ <Button onClick={onPrevious} variant="outline" className="flex-1">
277
+ <ChevronLeft className="h-4 w-4" />
278
+ {wizard.steps[currentStepIndex - 1]?.name}
279
+ </Button>
280
+ )}
281
+
282
+ {isLastStep ? (
283
+ <Button
284
+ disabled={isNextDisabled}
285
+ onClick={onFinish}
286
+ className={cn("flex-1", !showPrevious && "w-full")}
287
+ >
288
+ Finish
289
+ <ChevronRight className="h-4 w-4" />
290
+ </Button>
291
+ ) : (
292
+ <Button
293
+ disabled={isNextDisabled}
294
+ onClick={onNext}
295
+ className={cn("flex-1", !showPrevious && "w-full")}
296
+ >
297
+ {wizard.steps[currentStepIndex + 1]?.name}
298
+ <ChevronRight className="h-4 w-4" />
299
+ </Button>
300
+ )}
301
+ </div>
302
+ </div>
303
+ );
304
+ }
305
+
217
306
  export function WizardSteps({ wizard, parentItem }: WizardStepsProps) {
218
- const [currentStepIndex, setCurrentStepIndex] = useState(0);
219
- const [data, setData] = useState<WizardData>({});
220
- const [pageModel, setPageModel] = useState<WizardPageModel>({
307
+ const editContext = useEditContext();
308
+ const pageWizard = editContext?.pageWizard;
309
+
310
+ // Use state from pageWizard context instead of local state
311
+ const currentStepIndex = pageWizard?.currentStepIndex ?? 0;
312
+ const setCurrentStepIndex = pageWizard?.setCurrentStepIndex ?? (() => {});
313
+ const data = pageWizard?.data ?? {};
314
+ const setData = pageWizard?.setData ?? (() => {});
315
+ const pageModel = pageWizard?.pageModel ?? {
221
316
  components: [],
222
317
  name: "",
223
318
  metaDescription: "",
224
319
  metaKeywords: "",
225
- });
320
+ };
321
+ const setPageModel = pageWizard?.setPageModel ?? (() => {});
322
+ const internalState = pageWizard?.internalState ?? {};
323
+ const setInternalState = pageWizard?.setInternalState ?? (() => {});
324
+ const stepCompleted = pageWizard?.stepCompleted ?? -1;
325
+ const setStepCompleted = pageWizard?.setStepCompleted ?? (() => {});
326
+
327
+ const beforeNextCallbackRef = pageWizard?.beforeNextCallbackRef ?? {
328
+ current: null,
329
+ };
226
330
 
227
- const editContext = useEditContext();
228
- const [internalState, setInternalState] = useState<any>({});
229
- const [stepCompleted, setStepCompleted] = useState(-1);
331
+ const isMobile = editContext?.isMobile ?? false;
332
+
333
+ const setBeforeNextCallback = (callback: (() => Promise<boolean>) | null) => {
334
+ if (beforeNextCallbackRef) {
335
+ beforeNextCallbackRef.current = callback;
336
+ }
337
+ };
230
338
 
231
339
  const getCurrentStep = () => {
232
340
  const step = wizard.steps[currentStepIndex];
@@ -262,6 +370,7 @@ export function WizardSteps({ wizard, parentItem }: WizardStepsProps) {
262
370
  setStepCompleted(currentStepIndex - 1);
263
371
  }
264
372
  }}
373
+ setBeforeNextCallback={setBeforeNextCallback}
265
374
  internalState={internalState}
266
375
  setInternalState={setInternalState}
267
376
  parentItem={parentItem}
@@ -276,6 +385,7 @@ export function WizardSteps({ wizard, parentItem }: WizardStepsProps) {
276
385
  document.startViewTransition(() => {
277
386
  flushSync(() => {
278
387
  setCurrentStepIndex(index);
388
+ beforeNextCallbackRef.current = null; // Clear callback when switching steps
279
389
  });
280
390
  });
281
391
  };
@@ -284,7 +394,15 @@ export function WizardSteps({ wizard, parentItem }: WizardStepsProps) {
284
394
  switchStep(currentStepIndex - 1);
285
395
  };
286
396
 
287
- const handleNext = () => {
397
+ const handleNext = async () => {
398
+ // If there's a beforeNext callback, execute it first
399
+ if (beforeNextCallbackRef.current) {
400
+ console.log("Calling beforeNext callback");
401
+ const canProceed = await beforeNextCallbackRef.current();
402
+ if (!canProceed) {
403
+ return; // Don't proceed if callback returns false
404
+ }
405
+ }
288
406
  switchStep(currentStepIndex + 1);
289
407
  };
290
408
 
@@ -306,11 +424,22 @@ export function WizardSteps({ wizard, parentItem }: WizardStepsProps) {
306
424
  onNext={handleNext}
307
425
  onFinish={handleFinish}
308
426
  stepCompleted={stepCompleted}
427
+ isMobile={isMobile}
309
428
  />
310
429
 
311
430
  <WizardContent currentStep={currentStep}>
312
431
  {getCurrentStep()}
313
432
  </WizardContent>
433
+ {isMobile && (
434
+ <MobileNavigationButtons
435
+ currentStepIndex={currentStepIndex}
436
+ wizard={wizard}
437
+ stepCompleted={stepCompleted}
438
+ onPrevious={handlePrevious}
439
+ onNext={handleNext}
440
+ onFinish={handleFinish}
441
+ />
442
+ )}
314
443
  </div>
315
444
  );
316
445
  }
@@ -5,7 +5,7 @@ import { post } from "../editor/services/serviceHelper";
5
5
  import { Wizard } from "./PageWizard";
6
6
 
7
7
  export async function getWizards(
8
- parentItem: ItemDescriptor
8
+ parentItem: ItemDescriptor,
9
9
  ): Promise<Wizard[]> {
10
10
  const result = await post("/alpaca/editor/page-wizard/wizards", parentItem);
11
11
  return result.data as Wizard[] | [];
@@ -31,5 +31,5 @@ export function createWizardAiContext({
31
31
 
32
32
  export async function wipeComponents(pageItem: ItemDescriptor) {
33
33
  const result = await post("/alpaca/editor/page-wizard/wipePage", pageItem);
34
- return result.data;
34
+ return result;
35
35
  }
@@ -122,23 +122,86 @@ export function CollectStep({
122
122
  }
123
123
  };
124
124
 
125
- const uploadPanel: SplitterPanel = {
126
- name: "upload",
127
- defaultSize: 300,
128
- collapsible: false,
129
- content: (
130
- <div className="6 flex flex-col items-stretch gap-6 p-2">
131
- <div className="flex flex-col gap-2">
132
- <div className="text-sm font-semibold text-gray-700">
133
- Upload a file
125
+ return (
126
+ <div className="grid grid-cols-1 gap-4 md:grid-cols-2">
127
+ <Card
128
+ icon={<UploadIcon className="text-theme-secondary" />}
129
+ title="Upload a file (optional)"
130
+ collapsible="mobileOnly"
131
+ defaultCollapsed="mobileOnly"
132
+ description="Upload a file to the page"
133
+ >
134
+ {error && <div className="mt-2 text-sm text-red-500">{error}</div>}
135
+ <div
136
+ className={`flex flex-col items-center justify-center border border-dashed border-gray-300 p-8 ${
137
+ isUploading ? "bg-gray-200" : "bg-white"
138
+ }`}
139
+ onDrop={handleDrop}
140
+ onDragOver={(e) => e.preventDefault()}
141
+ >
142
+ <div className="flex flex-col items-center justify-center gap-1 text-center text-sm">
143
+ {!isUploading && (
144
+ <svg
145
+ width="49"
146
+ height="48"
147
+ viewBox="0 0 49 48"
148
+ fill="none"
149
+ xmlns="http://www.w3.org/2000/svg"
150
+ >
151
+ <rect
152
+ x="0.666992"
153
+ width="48"
154
+ height="48"
155
+ rx="24"
156
+ fill="#F6EEFF"
157
+ />
158
+ <path
159
+ d="M32.604 20.68C32.594 20.648 32.583 20.6167 32.571 20.586C32.5235 20.4775 32.4572 20.3783 32.375 20.293L26.375 14.293C26.2897 14.2108 26.1905 14.1445 26.082 14.097C26.052 14.083 26.02 14.075 25.988 14.064C25.9043 14.0356 25.8172 14.0185 25.729 14.013C25.707 14.011 25.688 14 25.667 14H18.667C17.564 14 16.667 14.897 16.667 16V32C16.667 33.103 17.564 34 18.667 34H30.667C31.77 34 32.667 33.103 32.667 32V21C32.667 20.979 32.656 20.96 32.654 20.938C32.6487 20.8502 32.6319 20.7634 32.604 20.68ZM29.253 20H26.667V17.414L29.253 20ZM18.667 32V16H24.667V21C24.667 21.2652 24.7723 21.5196 24.9599 21.7071C25.1474 21.8946 25.4018 22 25.667 22H30.667L30.669 32H18.667Z"
160
+ fill="#9650FB"
161
+ />
162
+ </svg>
163
+ )}
164
+ {isUploading && <Spinner />}
165
+ <input
166
+ ref={fileInputRef}
167
+ type="file"
168
+ multiple
169
+ accept=".pdf,.doc,.docx"
170
+ style={{ display: "none" }}
171
+ onChange={(e) => {
172
+ const file = e.target.files?.[0];
173
+ if (file) {
174
+ uploadFile(file);
175
+ }
176
+ }}
177
+ onDrop={handleDrop}
178
+ disabled={isUploading}
179
+ />
180
+ <div className="flex items-center gap-1">
181
+ <span
182
+ className={`text-sm font-medium ${
183
+ isUploading
184
+ ? "text-gray-500"
185
+ : "text-theme-secondary cursor-pointer underline"
186
+ } `}
187
+ onClick={triggerFileInput}
188
+ >
189
+ Click
190
+ </span>
191
+ or drag & drop to upload
192
+ </div>
134
193
  </div>
135
194
  </div>
136
-
137
- {error && <div className="mt-2 text-sm text-red-500">{error}</div>}
138
-
195
+ </Card>
196
+ <Card
197
+ icon={<LinkIcon className="text-theme-secondary" />}
198
+ title="Scrape page from URL (optional)"
199
+ description="Upload a file to the page"
200
+ collapsible="mobileOnly"
201
+ defaultCollapsed="mobileOnly"
202
+ >
139
203
  <div className="flex flex-col gap-2">
140
204
  <div className="text-sm font-semibold text-gray-700">
141
- Scrape page from URL
142
205
  <div className="text-xs font-normal text-gray-500">
143
206
  Only scrape websites you have permission to access. You are
144
207
  responsible for complying with the website's terms of service and
@@ -164,134 +227,25 @@ export function CollectStep({
164
227
  </ActionButton>
165
228
  </div>
166
229
  </div>
167
- </div>
168
- ),
169
- };
170
-
171
- return (
172
- <div className="absolute inset-0 overflow-auto">
173
- <div className="grid grid-cols-2 gap-4">
174
- <Card
175
- icon={<UploadIcon className="text-theme-secondary" />}
176
- title="Upload a file (optional)"
177
- description="Upload a file to the page"
178
- className="flex-1"
179
- >
180
- {error && <div className="mt-2 text-sm text-red-500">{error}</div>}
181
- <div
182
- className={`flex flex-col items-center justify-center border border-dashed border-gray-300 p-8 ${
183
- isUploading ? "bg-gray-200" : "bg-white"
184
- }`}
185
- onDrop={handleDrop}
186
- onDragOver={(e) => e.preventDefault()}
187
- >
188
- <div className="flex flex-col items-center justify-center gap-1 text-center text-sm">
189
- {!isUploading && (
190
- <svg
191
- width="49"
192
- height="48"
193
- viewBox="0 0 49 48"
194
- fill="none"
195
- xmlns="http://www.w3.org/2000/svg"
196
- >
197
- <rect
198
- x="0.666992"
199
- width="48"
200
- height="48"
201
- rx="24"
202
- fill="#F6EEFF"
203
- />
204
- <path
205
- d="M32.604 20.68C32.594 20.648 32.583 20.6167 32.571 20.586C32.5235 20.4775 32.4572 20.3783 32.375 20.293L26.375 14.293C26.2897 14.2108 26.1905 14.1445 26.082 14.097C26.052 14.083 26.02 14.075 25.988 14.064C25.9043 14.0356 25.8172 14.0185 25.729 14.013C25.707 14.011 25.688 14 25.667 14H18.667C17.564 14 16.667 14.897 16.667 16V32C16.667 33.103 17.564 34 18.667 34H30.667C31.77 34 32.667 33.103 32.667 32V21C32.667 20.979 32.656 20.96 32.654 20.938C32.6487 20.8502 32.6319 20.7634 32.604 20.68ZM29.253 20H26.667V17.414L29.253 20ZM18.667 32V16H24.667V21C24.667 21.2652 24.7723 21.5196 24.9599 21.7071C25.1474 21.8946 25.4018 22 25.667 22H30.667L30.669 32H18.667Z"
206
- fill="#9650FB"
207
- />
208
- </svg>
209
- )}
210
- {isUploading && <Spinner />}
211
- <input
212
- ref={fileInputRef}
213
- type="file"
214
- multiple
215
- accept=".pdf,.doc,.docx"
216
- style={{ display: "none" }}
217
- onChange={(e) => {
218
- const file = e.target.files?.[0];
219
- if (file) {
220
- uploadFile(file);
221
- }
222
- }}
223
- onDrop={handleDrop}
224
- disabled={isUploading}
225
- />
226
- <div className="flex items-center gap-1">
227
- <span
228
- className={`text-sm font-medium ${
229
- isUploading
230
- ? "text-gray-500"
231
- : "text-theme-secondary cursor-pointer underline"
232
- } `}
233
- onClick={triggerFileInput}
234
- >
235
- Click
236
- </span>
237
- or drag & drop to upload
238
- </div>
239
- </div>
240
- </div>
241
- </Card>
242
- <Card
243
- icon={<LinkIcon className="text-theme-secondary" />}
244
- title="Scrape page from URL (optional)"
245
- description="Upload a file to the page"
246
- className="flex-1"
247
- >
248
- <div className="flex flex-col gap-2">
249
- <div className="text-sm font-semibold text-gray-700">
250
- <div className="text-xs font-normal text-gray-500">
251
- Only scrape websites you have permission to access. You are
252
- responsible for complying with the website's terms of service
253
- and all applicable laws.
254
- </div>
255
- </div>
256
- <InputText
257
- type="text"
258
- className="rounded-md border border-gray-300 px-3 py-2"
259
- onChange={(e) => setScrapeUrl(e.target.value)}
260
- />
261
- {scrapeError && (
262
- <div className="mt-2 text-sm text-red-500">{scrapeError}</div>
263
- )}
264
- <div className="flex gap-2">
265
- <ActionButton
266
- type="submit"
267
- isLoading={isScraping}
268
- onClick={handleScrape}
269
- loadingText="Scraping..."
270
- >
271
- Scrape
272
- </ActionButton>
273
- </div>
274
- </div>
275
- </Card>
276
- <Card
277
- icon={<DocumentIcon className="text-theme-secondary" />}
278
- title="Text"
279
- description="Provide the text you want to use for the page"
280
- className="col-span-2"
281
- >
282
- <InputTextarea
283
- className="max-h-full w-full"
284
- value={data.htmlContent}
285
- rows={20}
286
- onChange={(e) =>
287
- setData((prev: WizardData) => ({
288
- ...prev,
289
- htmlContent: e.target.value || "",
290
- }))
291
- }
292
- />
293
- </Card>
294
- </div>
230
+ </Card>
231
+ <Card
232
+ icon={<DocumentIcon className="text-theme-secondary" />}
233
+ title="Text"
234
+ description="Provide the text you want to use for the page"
235
+ className="md:col-span-2"
236
+ >
237
+ <InputTextarea
238
+ className="max-h-full w-full"
239
+ value={data.htmlContent}
240
+ rows={20}
241
+ onChange={(e) =>
242
+ setData((prev: WizardData) => ({
243
+ ...prev,
244
+ htmlContent: e.target.value || "",
245
+ }))
246
+ }
247
+ />
248
+ </Card>
295
249
  </div>
296
250
  );
297
251
  }