@alpaca-editor/core 1.0.3903 → 1.0.3905

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 (92) 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/editContext.d.ts +14 -1
  17. package/dist/editor/client/editContext.js.map +1 -1
  18. package/dist/editor/page-editor-chrome/CommentHighlighting.js +4 -1
  19. package/dist/editor/page-editor-chrome/CommentHighlighting.js.map +1 -1
  20. package/dist/editor/ui/Splitter.js +3 -1
  21. package/dist/editor/ui/Splitter.js.map +1 -1
  22. package/dist/page-wizard/WizardBoxConnector.d.ts +2 -1
  23. package/dist/page-wizard/WizardBoxConnector.js +3 -3
  24. package/dist/page-wizard/WizardBoxConnector.js.map +1 -1
  25. package/dist/page-wizard/WizardSteps.js +62 -16
  26. package/dist/page-wizard/WizardSteps.js.map +1 -1
  27. package/dist/page-wizard/service.d.ts +1 -1
  28. package/dist/page-wizard/service.js +1 -1
  29. package/dist/page-wizard/service.js.map +1 -1
  30. package/dist/page-wizard/steps/CollectStep.js +11 -17
  31. package/dist/page-wizard/steps/CollectStep.js.map +1 -1
  32. package/dist/page-wizard/steps/ComponentTypesSelector.d.ts +1 -0
  33. package/dist/page-wizard/steps/ComponentTypesSelector.js +53 -78
  34. package/dist/page-wizard/steps/ComponentTypesSelector.js.map +1 -1
  35. package/dist/page-wizard/steps/ContentStep.d.ts +2 -0
  36. package/dist/page-wizard/steps/ContentStep.js +403 -0
  37. package/dist/page-wizard/steps/ContentStep.js.map +1 -0
  38. package/dist/page-wizard/steps/Generate.js +1 -1
  39. package/dist/page-wizard/steps/Generate.js.map +1 -1
  40. package/dist/page-wizard/steps/ImagesStep.js +16 -13
  41. package/dist/page-wizard/steps/ImagesStep.js.map +1 -1
  42. package/dist/page-wizard/steps/SelectStep.js +1 -1
  43. package/dist/page-wizard/steps/SelectStep.js.map +1 -1
  44. package/dist/page-wizard/steps/SetupPageStep.d.ts +2 -0
  45. package/dist/page-wizard/steps/SetupPageStep.js +152 -0
  46. package/dist/page-wizard/steps/SetupPageStep.js.map +1 -0
  47. package/dist/page-wizard/steps/usePageCreator.js +4 -4
  48. package/dist/page-wizard/steps/usePageCreator.js.map +1 -1
  49. package/dist/page-wizard/usePageWizard.d.ts +17 -3
  50. package/dist/page-wizard/usePageWizard.js +62 -2
  51. package/dist/page-wizard/usePageWizard.js.map +1 -1
  52. package/dist/revision.d.ts +2 -2
  53. package/dist/revision.js +2 -2
  54. package/dist/splash-screen/NewPage.js +10 -10
  55. package/dist/splash-screen/NewPage.js.map +1 -1
  56. package/dist/splash-screen/SplashScreen.js +3 -3
  57. package/dist/splash-screen/SplashScreen.js.map +1 -1
  58. package/dist/styles.css +182 -63
  59. package/package.json +1 -1
  60. package/src/components/ui/CardConnector.tsx +50 -15
  61. package/src/components/ui/button.tsx +1 -1
  62. package/src/components/ui/card.tsx +331 -15
  63. package/src/config/config.tsx +4 -2
  64. package/src/config/types.ts +3 -0
  65. package/src/editor/MobileLayout.tsx +7 -9
  66. package/src/editor/PictureEditor.tsx +16 -10
  67. package/src/editor/client/editContext.ts +23 -1
  68. package/src/editor/page-editor-chrome/CommentHighlighting.tsx +6 -1
  69. package/src/editor/ui/Splitter.tsx +10 -1
  70. package/src/page-wizard/WizardBoxConnector.tsx +50 -15
  71. package/src/page-wizard/WizardSteps.tsx +161 -32
  72. package/src/page-wizard/service.ts +2 -2
  73. package/src/page-wizard/steps/CollectStep.tsx +95 -141
  74. package/src/page-wizard/steps/ComponentTypesSelector.tsx +225 -245
  75. package/src/page-wizard/steps/ContentStep.tsx +648 -0
  76. package/src/page-wizard/steps/Generate.tsx +3 -3
  77. package/src/page-wizard/steps/ImagesStep.tsx +20 -15
  78. package/src/page-wizard/steps/SelectStep.tsx +4 -4
  79. package/src/page-wizard/steps/SetupPageStep.tsx +329 -0
  80. package/src/page-wizard/steps/usePageCreator.ts +4 -4
  81. package/src/page-wizard/usePageWizard.ts +69 -4
  82. package/src/revision.ts +2 -2
  83. package/src/splash-screen/NewPage.tsx +22 -16
  84. package/src/splash-screen/SplashScreen.tsx +3 -1
  85. package/dist/page-wizard/steps/CreatePage.d.ts +0 -12
  86. package/dist/page-wizard/steps/CreatePage.js +0 -149
  87. package/dist/page-wizard/steps/CreatePage.js.map +0 -1
  88. package/dist/page-wizard/steps/CreatePageAndLayoutStep.d.ts +0 -2
  89. package/dist/page-wizard/steps/CreatePageAndLayoutStep.js +0 -236
  90. package/dist/page-wizard/steps/CreatePageAndLayoutStep.js.map +0 -1
  91. package/src/page-wizard/steps/CreatePage.tsx +0 -329
  92. package/src/page-wizard/steps/CreatePageAndLayoutStep.tsx +0 -430
@@ -1,4 +1,6 @@
1
1
  import { cn } from "../../lib/utils";
2
+ import { useState, useEffect } from "react";
3
+ import { Expand, Shrink } from "lucide-react";
2
4
 
3
5
  /**
4
6
  * A reusable card component with header (icon, title, description) and content area.
@@ -11,6 +13,12 @@ export function Card({
11
13
  description,
12
14
  className,
13
15
  noPadding,
16
+ collapsible = "no",
17
+ defaultCollapsed = "no",
18
+ summary,
19
+ footer,
20
+ showFullscreenButton = false,
21
+ onFullscreen,
14
22
  }: {
15
23
  children: React.ReactNode;
16
24
  icon: React.ReactNode;
@@ -18,27 +26,335 @@ export function Card({
18
26
  description: string;
19
27
  className?: string;
20
28
  noPadding?: boolean;
29
+ collapsible?: "yes" | "no" | "mobileOnly";
30
+ defaultCollapsed?: "yes" | "no" | "mobileOnly";
31
+ summary?: React.ReactNode;
32
+ footer?: React.ReactNode;
33
+ showFullscreenButton?: boolean;
34
+ onFullscreen?: () => void;
21
35
  }) {
36
+ const [isExpanded, setIsExpanded] = useState(() => {
37
+ if (defaultCollapsed === "yes") return false; // Starts collapsed
38
+ if (defaultCollapsed === "no") return true; // Starts expanded
39
+ if (defaultCollapsed === "mobileOnly") return false; // Starts collapsed on mobile, but we'll handle desktop separately
40
+ return true; // Default
41
+ });
42
+
43
+ const [isFullscreen, setIsFullscreen] = useState(false);
44
+
45
+ const isCollapsibleEnabled = collapsible !== "no";
46
+
47
+ // Prevent body scroll when fullscreen is active
48
+ useEffect(() => {
49
+ if (isFullscreen) {
50
+ document.body.style.overflow = "hidden";
51
+ return () => {
52
+ document.body.style.overflow = "";
53
+ };
54
+ }
55
+ }, [isFullscreen]);
56
+
57
+ // Check if collapsible behavior should be active (considering mobile-only options)
58
+ const isCollapsibleActive = () => {
59
+ if (collapsible === "no") return false;
60
+ if (collapsible === "mobileOnly") {
61
+ // Only collapsible on mobile - we'll handle this with CSS classes
62
+ return true;
63
+ }
64
+ return true; // For "yes"
65
+ };
66
+
67
+ // Determine what content to show based on collapsible state
68
+ const getContentToShow = () => {
69
+ if (!isCollapsibleEnabled) return children;
70
+
71
+ return isExpanded ? children : summary;
72
+ };
73
+
74
+ const shouldShowContent = () => {
75
+ if (!isCollapsibleEnabled) return true;
76
+
77
+ // Always show content area if we have either main content or summary
78
+ if (!isExpanded && summary) return true;
79
+ if (isExpanded) return true;
80
+
81
+ return false;
82
+ };
83
+
84
+ const toggleExpanded = () => {
85
+ if (isCollapsibleActive()) {
86
+ setIsExpanded(!isExpanded);
87
+ }
88
+ };
89
+
90
+ const handleFullscreen = () => {
91
+ setIsFullscreen(true);
92
+ onFullscreen?.();
93
+ };
94
+
95
+ const handleExitFullscreen = () => {
96
+ setIsFullscreen(false);
97
+ };
98
+
22
99
  return (
23
- <div
24
- className={cn(
25
- "flex h-full flex-col gap-2 rounded-md bg-white",
26
- className,
100
+ <>
101
+ {/* Blurred background overlay - only visible in fullscreen */}
102
+ {isFullscreen && (
103
+ <div
104
+ className="fixed inset-0 z-40 bg-black/20 backdrop-blur-sm md:hidden"
105
+ onClick={handleExitFullscreen}
106
+ />
27
107
  )}
28
- >
29
- <div className="flex flex-col justify-between gap-1 p-6 pb-2">
30
- <div className="flex items-center gap-2">
31
- <div className="text-theme-secondary flex h-4 w-4 items-center justify-center rounded-full">
32
- {icon}
108
+
109
+ <div
110
+ className={cn(
111
+ "flex flex-col rounded-md bg-white transition-all duration-300 ease-in-out",
112
+ className,
113
+ isFullscreen && [
114
+ // Fullscreen styles - only on mobile
115
+ "fixed inset-0 z-50 mx-0 mt-[30px] h-[calc(100vh-60px)] shadow-xl md:relative md:inset-auto md:mx-auto md:mt-0 md:h-auto md:shadow-none",
116
+ ],
117
+ )}
118
+ >
119
+ <div
120
+ className={cn(
121
+ "flex flex-col justify-between gap-1 p-4 pb-2 md:p-6",
122
+ isCollapsibleEnabled && "cursor-pointer",
123
+ )}
124
+ onClick={isCollapsibleEnabled ? toggleExpanded : undefined}
125
+ >
126
+ <div className="flex items-center justify-between gap-2">
127
+ <div className="flex items-center gap-2">
128
+ <div className="text-theme-secondary flex h-4 w-4 items-center justify-center rounded-full">
129
+ {icon}
130
+ </div>
131
+ <div className="text-base font-bold text-neutral-800">
132
+ {title}
133
+ </div>
134
+ </div>
135
+ <div className="flex items-center gap-2">
136
+ {/* Fullscreen button - only on mobile */}
137
+ {showFullscreenButton && (
138
+ <button
139
+ onClick={handleFullscreen}
140
+ className={cn(
141
+ "flex-shrink-0 text-neutral-500 transition-colors duration-200 hover:text-neutral-700 md:hidden",
142
+ isFullscreen && "hidden",
143
+ )}
144
+ aria-label="Open fullscreen"
145
+ >
146
+ <Expand className="h-4 w-4" />
147
+ </button>
148
+ )}
149
+
150
+ {/* Exit fullscreen button - only visible in fullscreen */}
151
+ {showFullscreenButton && isFullscreen && (
152
+ <button
153
+ onClick={handleExitFullscreen}
154
+ className="flex-shrink-0 text-neutral-500 transition-colors duration-200 hover:text-neutral-700 md:hidden"
155
+ aria-label="Exit fullscreen"
156
+ >
157
+ <Shrink className="h-4 w-4" />
158
+ </button>
159
+ )}
160
+
161
+ {/* Show toggle in header when no summary is provided */}
162
+ {isCollapsibleEnabled && !summary && (
163
+ <>
164
+ {collapsible === "yes" && (
165
+ <button
166
+ onClick={toggleExpanded}
167
+ className="flex-shrink-0 text-neutral-500 transition-colors duration-200 hover:text-neutral-700"
168
+ aria-label={isExpanded ? "Collapse" : "Expand"}
169
+ >
170
+ <svg
171
+ className={cn(
172
+ "h-4 w-4 transition-transform duration-200",
173
+ isExpanded ? "rotate-180" : "rotate-0",
174
+ )}
175
+ fill="none"
176
+ stroke="currentColor"
177
+ viewBox="0 0 24 24"
178
+ >
179
+ <path
180
+ strokeLinecap="round"
181
+ strokeLinejoin="round"
182
+ strokeWidth={2}
183
+ d="M19 9l-7 7-7-7"
184
+ />
185
+ </svg>
186
+ </button>
187
+ )}
188
+ {collapsible === "mobileOnly" && (
189
+ <button
190
+ onClick={toggleExpanded}
191
+ className="flex-shrink-0 text-neutral-500 transition-colors duration-200 hover:text-neutral-700 md:hidden"
192
+ aria-label={isExpanded ? "Collapse" : "Expand"}
193
+ >
194
+ <svg
195
+ className={cn(
196
+ "h-4 w-4 transition-transform duration-200",
197
+ isExpanded ? "rotate-180" : "rotate-0",
198
+ )}
199
+ fill="none"
200
+ stroke="currentColor"
201
+ viewBox="0 0 24 24"
202
+ >
203
+ <path
204
+ strokeLinecap="round"
205
+ strokeLinejoin="round"
206
+ strokeWidth={2}
207
+ d="M19 9l-7 7-7-7"
208
+ />
209
+ </svg>
210
+ </button>
211
+ )}
212
+ </>
213
+ )}
214
+ </div>
33
215
  </div>
34
- <div className="text-base font-bold text-neutral-800">{title}</div>
216
+ <div className="mb-1 text-xs text-neutral-500">{description}</div>
35
217
  </div>
36
- <div className="mb-1 text-xs text-neutral-500">{description}</div>
37
- </div>
38
218
 
39
- <div className={cn("flex-1", noPadding ? "" : "p-6 pt-0", className)}>
40
- {children}
219
+ {shouldShowContent() && (
220
+ <div
221
+ className={cn(
222
+ "flex-1 transition-all duration-300 ease-in-out",
223
+ noPadding ? "" : "p-6 pt-0",
224
+ isFullscreen && "overflow-hidden",
225
+ // Handle responsive behavior for mobile-only collapsible options
226
+ collapsible === "mobileOnly" &&
227
+ !isExpanded &&
228
+ summary &&
229
+ "block md:hidden",
230
+ collapsible === "mobileOnly" && isExpanded && "block",
231
+ className,
232
+ )}
233
+ >
234
+ {!isExpanded && summary && isCollapsibleEnabled ? (
235
+ <div className="flex items-start justify-between gap-2">
236
+ <div className="flex-1">{summary}</div>
237
+ {/* Show toggle button next to summary when summary exists */}
238
+ {collapsible === "yes" && (
239
+ <button
240
+ onClick={toggleExpanded}
241
+ className="flex-shrink-0 text-neutral-500 transition-colors duration-200 hover:text-neutral-700"
242
+ aria-label="Expand"
243
+ >
244
+ <svg
245
+ className="h-4 w-4 rotate-0 transition-transform duration-200"
246
+ fill="none"
247
+ stroke="currentColor"
248
+ viewBox="0 0 24 24"
249
+ >
250
+ <path
251
+ strokeLinecap="round"
252
+ strokeLinejoin="round"
253
+ strokeWidth={2}
254
+ d="M19 9l-7 7-7-7"
255
+ />
256
+ </svg>
257
+ </button>
258
+ )}
259
+ {collapsible === "mobileOnly" && (
260
+ <button
261
+ onClick={toggleExpanded}
262
+ className="flex-shrink-0 text-neutral-500 transition-colors duration-200 hover:text-neutral-700 md:hidden"
263
+ aria-label="Expand"
264
+ >
265
+ <svg
266
+ className="h-4 w-4 rotate-0 transition-transform duration-200"
267
+ fill="none"
268
+ stroke="currentColor"
269
+ viewBox="0 0 24 24"
270
+ >
271
+ <path
272
+ strokeLinecap="round"
273
+ strokeLinejoin="round"
274
+ strokeWidth={2}
275
+ d="M19 9l-7 7-7-7"
276
+ />
277
+ </svg>
278
+ </button>
279
+ )}
280
+ </div>
281
+ ) : (
282
+ <>
283
+ {isExpanded && isCollapsibleEnabled && summary ? (
284
+ <div className="flex items-start justify-between gap-2">
285
+ <div className="flex-1">{children}</div>
286
+ {/* Show toggle button next to content when summary exists */}
287
+ {collapsible === "yes" && (
288
+ <button
289
+ onClick={toggleExpanded}
290
+ className="flex-shrink-0 text-neutral-500 transition-colors duration-200 hover:text-neutral-700"
291
+ aria-label="Collapse"
292
+ >
293
+ <svg
294
+ className="h-4 w-4 rotate-180 transition-transform duration-200"
295
+ fill="none"
296
+ stroke="currentColor"
297
+ viewBox="0 0 24 24"
298
+ >
299
+ <path
300
+ strokeLinecap="round"
301
+ strokeLinejoin="round"
302
+ strokeWidth={2}
303
+ d="M19 9l-7 7-7-7"
304
+ />
305
+ </svg>
306
+ </button>
307
+ )}
308
+ {collapsible === "mobileOnly" && (
309
+ <button
310
+ onClick={toggleExpanded}
311
+ className="flex-shrink-0 text-neutral-500 transition-colors duration-200 hover:text-neutral-700 md:hidden"
312
+ aria-label="Collapse"
313
+ >
314
+ <svg
315
+ className="h-4 w-4 rotate-180 transition-transform duration-200"
316
+ fill="none"
317
+ stroke="currentColor"
318
+ viewBox="0 0 24 24"
319
+ >
320
+ <path
321
+ strokeLinecap="round"
322
+ strokeLinejoin="round"
323
+ strokeWidth={2}
324
+ d="M19 9l-7 7-7-7"
325
+ />
326
+ </svg>
327
+ </button>
328
+ )}
329
+ </div>
330
+ ) : (
331
+ getContentToShow()
332
+ )}
333
+ </>
334
+ )}
335
+ </div>
336
+ )}
337
+
338
+ {/* Show full content on desktop when using mobile-only collapsible options */}
339
+ {collapsible === "mobileOnly" && (
340
+ <div
341
+ className={cn(
342
+ "hidden flex-1 transition-all duration-300 ease-in-out md:block",
343
+ noPadding ? "" : "p-6 pt-0",
344
+ className,
345
+ )}
346
+ >
347
+ {children}
348
+ </div>
349
+ )}
350
+
351
+ {/* Footer - always displayed regardless of collapsed state */}
352
+ {footer && (
353
+ <div className="border-t border-gray-100 p-4 pt-0 md:p-6 md:pt-0">
354
+ {footer}
355
+ </div>
356
+ )}
41
357
  </div>
42
- </div>
358
+ </>
43
359
  );
44
360
  }
@@ -94,7 +94,8 @@ import { LayoutStep } from "../page-wizard/steps/LayoutStep";
94
94
  import { BuildPageStep } from "../page-wizard/steps/BuildPageStep";
95
95
  import { SelectStep } from "../page-wizard/steps/SelectStep";
96
96
  import { ImagesStep } from "../page-wizard/steps/ImagesStep";
97
- import { CreatePageAndLayoutStep } from "../page-wizard/steps/CreatePageAndLayoutStep";
97
+ import { ContentStep } from "../page-wizard/steps/ContentStep";
98
+ import { SetupPageStep } from "../page-wizard/steps/SetupPageStep";
98
99
  import { getWizards } from "../page-wizard/service";
99
100
 
100
101
  import { startPageWizardCommand } from "../page-wizard/startPageWizardCommand";
@@ -323,7 +324,8 @@ export const getConfiguration = (): EditorConfiguration => {
323
324
  BuildPageStep,
324
325
  SelectStep,
325
326
  ImagesStep,
326
- CreatePageAndLayoutStep,
327
+ ContentStep,
328
+ SetupPageStep,
327
329
  },
328
330
  },
329
331
 
@@ -267,11 +267,14 @@ export type TranslationStatus = {
267
267
 
268
268
  export interface StepComponentProps {
269
269
  step: any;
270
+
270
271
  data: WizardData;
271
272
  setData: React.Dispatch<React.SetStateAction<WizardData>>;
272
273
  wizard: Wizard;
273
274
  parentItem?: ItemDescriptor;
274
275
  setStepCompleted: (completed: boolean) => void;
276
+ setBeforeNextCallback?: (callback: (() => Promise<boolean>) | null) => void;
277
+
275
278
  internalState: any;
276
279
  setInternalState: Dispatch<SetStateAction<any>>;
277
280
  pageModel: WizardPageModel;
@@ -51,15 +51,13 @@ export function MobileLayout(props: MainLayoutProps) {
51
51
  return (
52
52
  <div className={cn("flex flex-col select-none", className)}>
53
53
  {editContext?.configuration.editor.titlebar}
54
- <div className="flex flex-1">
55
- <div className="flex-1">
56
- <Splitter
57
- panels={panels}
58
- direction="vertical"
59
- localStorageKey="mobile-layout-splitter"
60
- />
61
- </div>
62
- </div>
54
+
55
+ <Splitter
56
+ panels={panels}
57
+ direction="vertical"
58
+ localStorageKey="mobile-layout-splitter"
59
+ />
60
+
63
61
  {!props.view.hideViewSelector && <ViewSelector />}
64
62
  {/* <div className="text-2xs fixed right-0 bottom-0 z-50 flex flex-col rounded-tl-2xl bg-gray-50/70 px-1 pt-1 text-center font-mono text-gray-400">
65
63
  <div title={buildDate}>{version}</div>
@@ -22,10 +22,16 @@ export function PictureEditor({
22
22
  const editContext = useEditContext();
23
23
 
24
24
  const variant = field.value?.variants?.find((v) => v.name === variantName);
25
- const raw =
26
- field?.rawValue && field?.rawValue[0] === "{"
27
- ? (JSON.parse(field?.rawValue) as PictureRawValue)
28
- : ({ Variants: [] } as PictureRawValue);
25
+ const raw = (() => {
26
+ try {
27
+ return field?.rawValue && field?.rawValue[0] === "{"
28
+ ? (JSON.parse(field?.rawValue) as PictureRawValue)
29
+ : ({ Variants: [] } as PictureRawValue);
30
+ } catch (error) {
31
+ console.warn("Failed to parse picture field raw value:", error);
32
+ return { Variants: [] } as PictureRawValue;
33
+ }
34
+ })();
29
35
 
30
36
  const rawVariant = raw.Variants?.find((x) => x.Name == variantName);
31
37
 
@@ -57,7 +63,7 @@ export function PictureEditor({
57
63
  refresh: "immediate",
58
64
  });
59
65
  },
60
- [field, variant]
66
+ [field, variant],
61
67
  );
62
68
 
63
69
  const videoSelected = useCallback(
@@ -79,7 +85,7 @@ export function PictureEditor({
79
85
  refresh: "immediate",
80
86
  });
81
87
  },
82
- [field, variant]
88
+ [field, variant],
83
89
  );
84
90
 
85
91
  async function selectMedia(mode: MediaSelectorMode) {
@@ -117,21 +123,21 @@ export function PictureEditor({
117
123
  behavior: "instant",
118
124
  left: 0,
119
125
  top: e.deltaY,
120
- }
126
+ },
121
127
  );
122
128
  editContext?.pageView.editorIframeRef!.current?.contentWindow?.document.body?.scrollBy(
123
129
  {
124
130
  behavior: "instant",
125
131
  left: 0,
126
132
  top: e.deltaY,
127
- }
133
+ },
128
134
  );
129
135
  }}
130
136
  style={style}
131
137
  data-testid="select-media"
132
138
  >
133
139
  {showMenu && (
134
- <div className="p-3 grid grid-cols-2 gap-1.5 items-stretch justify-center text-sm min-w-48">
140
+ <div className="grid min-w-48 grid-cols-2 items-stretch justify-center gap-1.5 p-3 text-sm">
135
141
  <Btn
136
142
  label="Select"
137
143
  icon="pi pi-image"
@@ -196,7 +202,7 @@ function Btn({
196
202
  }) {
197
203
  return (
198
204
  <button
199
- className={`btn bg-gray-500 text-white p-1.5 rounded-lg opacity-70 border hover:opacity-85 gap-1.5 flex items-center cursor-pointer ${className}`}
205
+ className={`btn flex cursor-pointer items-center gap-1.5 rounded-lg border bg-gray-500 p-1.5 text-white opacity-70 hover:opacity-85 ${className}`}
200
206
  onClick={onClick}
201
207
  data-testid={testId}
202
208
  >
@@ -51,7 +51,11 @@ import { ItemsRepository } from "./itemsRepository";
51
51
  import { MediaSelectorMode } from "../media-selector/MediaSelector";
52
52
  import { ComponentCommand } from "../commands/componentCommands";
53
53
  import { AiTerminalOptions } from "../ai/AiTerminal";
54
- import { Wizard } from "../../page-wizard/PageWizard";
54
+ import {
55
+ Wizard,
56
+ WizardData,
57
+ WizardPageModel,
58
+ } from "../../page-wizard/PageWizard";
55
59
  export type DragObject = {
56
60
  type: "template" | "component" | "link-component" | "items";
57
61
  typeId: string;
@@ -322,6 +326,24 @@ export type EditContextType = {
322
326
  setParentItem: React.Dispatch<
323
327
  React.SetStateAction<ItemDescriptor | undefined>
324
328
  >;
329
+ // Wizard step state
330
+ currentStepIndex: number;
331
+ setCurrentStepIndex: React.Dispatch<React.SetStateAction<number>>;
332
+ data: WizardData;
333
+ setData: React.Dispatch<React.SetStateAction<WizardData>>;
334
+ pageModel: WizardPageModel;
335
+ setPageModel: React.Dispatch<React.SetStateAction<WizardPageModel>>;
336
+ internalState: any;
337
+ setInternalState: React.Dispatch<React.SetStateAction<any>>;
338
+ stepCompleted: number;
339
+ setStepCompleted: React.Dispatch<React.SetStateAction<number>>;
340
+ pageItem: ItemDescriptor | undefined;
341
+ setPageItem: React.Dispatch<
342
+ React.SetStateAction<ItemDescriptor | undefined>
343
+ >;
344
+ beforeNextCallbackRef: React.MutableRefObject<
345
+ (() => Promise<boolean>) | null
346
+ >;
325
347
  };
326
348
 
327
349
  webSocketMessages: WebSocketMessage[];
@@ -103,7 +103,12 @@ export function CommentHighlighting({
103
103
 
104
104
  if (!rects || rects.length === 0) {
105
105
  let fallbackElement = fieldElement;
106
- if (!fallbackElement && comment.itemId && editContext.page) {
106
+ if (
107
+ !fallbackElement &&
108
+ comment.itemId &&
109
+ editContext.page &&
110
+ iframe.contentWindow?.document.body
111
+ ) {
107
112
  const componentStart = iframe.contentWindow?.document.body.querySelector(
108
113
  "[data-component-start='" + comment.itemId + "']",
109
114
  );
@@ -260,7 +260,16 @@ export const Splitter: React.FC<SplitterProps> = ({
260
260
  }
261
261
  }
262
262
  }}
263
- ></div>
263
+ >
264
+ {/* Visual indicator line for mobile splitters */}
265
+ <div
266
+ className={`${
267
+ isHorizontal
268
+ ? "h-8 w-[2px] bg-gray-500 md:hidden"
269
+ : "h-[2px] w-8 bg-gray-500 md:hidden"
270
+ }`}
271
+ />
272
+ </div>
264
273
  );
265
274
  };
266
275
 
@@ -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
  }