@alpaca-editor/core 1.0.3956 → 1.0.3960

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 (247) hide show
  1. package/build.css +1 -1
  2. package/dist/components/ui/badge.d.ts +9 -0
  3. package/dist/components/ui/badge.js +23 -0
  4. package/dist/components/ui/badge.js.map +1 -0
  5. package/dist/components/ui/button.js +3 -3
  6. package/dist/components/ui/button.js.map +1 -1
  7. package/dist/components/ui/command.d.ts +18 -0
  8. package/dist/components/ui/command.js +35 -0
  9. package/dist/components/ui/command.js.map +1 -0
  10. package/dist/components/ui/dialog.d.ts +15 -0
  11. package/dist/components/ui/dialog.js +37 -0
  12. package/dist/components/ui/dialog.js.map +1 -0
  13. package/dist/components/ui/dropdown-menu.d.ts +25 -0
  14. package/dist/components/ui/dropdown-menu.js +52 -0
  15. package/dist/components/ui/dropdown-menu.js.map +1 -0
  16. package/dist/components/ui/input.d.ts +3 -0
  17. package/dist/components/ui/input.js +7 -0
  18. package/dist/components/ui/input.js.map +1 -0
  19. package/dist/components/ui/menubar.d.ts +26 -0
  20. package/dist/components/ui/menubar.js +55 -0
  21. package/dist/components/ui/menubar.js.map +1 -0
  22. package/dist/components/ui/popover.d.ts +9 -0
  23. package/dist/components/ui/popover.js +63 -0
  24. package/dist/components/ui/popover.js.map +1 -0
  25. package/dist/components/ui/switch.d.ts +4 -0
  26. package/dist/components/ui/switch.js +9 -0
  27. package/dist/components/ui/switch.js.map +1 -0
  28. package/dist/components/ui/tooltip.d.ts +7 -0
  29. package/dist/components/ui/tooltip.js +18 -0
  30. package/dist/components/ui/tooltip.js.map +1 -0
  31. package/dist/config/config.js +79 -63
  32. package/dist/config/config.js.map +1 -1
  33. package/dist/config/types.d.ts +3 -3
  34. package/dist/editor/ContentTree.js +1 -1
  35. package/dist/editor/ContentTree.js.map +1 -1
  36. package/dist/editor/Editor.js +6 -2
  37. package/dist/editor/Editor.js.map +1 -1
  38. package/dist/editor/FieldList.js +1 -1
  39. package/dist/editor/FieldList.js.map +1 -1
  40. package/dist/editor/FieldListField.js +1 -1
  41. package/dist/editor/FieldListField.js.map +1 -1
  42. package/dist/editor/ImageEditor.js +16 -6
  43. package/dist/editor/ImageEditor.js.map +1 -1
  44. package/dist/editor/MainLayout.js +4 -4
  45. package/dist/editor/MainLayout.js.map +1 -1
  46. package/dist/editor/MobileLayout.js +3 -3
  47. package/dist/editor/MobileLayout.js.map +1 -1
  48. package/dist/editor/PictureEditor.js +29 -15
  49. package/dist/editor/PictureEditor.js.map +1 -1
  50. package/dist/editor/Titlebar.js +6 -11
  51. package/dist/editor/Titlebar.js.map +1 -1
  52. package/dist/editor/ai/GhostWriter.js +1 -1
  53. package/dist/editor/ai/GhostWriter.js.map +1 -1
  54. package/dist/editor/client/EditorClient.d.ts +4 -2
  55. package/dist/editor/client/EditorClient.js +32 -11
  56. package/dist/editor/client/EditorClient.js.map +1 -1
  57. package/dist/editor/client/editContext.d.ts +4 -1
  58. package/dist/editor/client/editContext.js.map +1 -1
  59. package/dist/editor/client/operations.js +2 -2
  60. package/dist/editor/client/pageModelBuilder.js +3 -6
  61. package/dist/editor/client/pageModelBuilder.js.map +1 -1
  62. package/dist/editor/commands/itemCommands.d.ts +2 -0
  63. package/dist/editor/commands/itemCommands.js +180 -0
  64. package/dist/editor/commands/itemCommands.js.map +1 -1
  65. package/dist/editor/field-types/MultiLineText.js +1 -1
  66. package/dist/editor/field-types/MultiLineText.js.map +1 -1
  67. package/dist/editor/field-types/SingleLineText.js +1 -1
  68. package/dist/editor/field-types/SingleLineText.js.map +1 -1
  69. package/dist/editor/menubar/ActiveUsers.js +98 -4
  70. package/dist/editor/menubar/ActiveUsers.js.map +1 -1
  71. package/dist/editor/menubar/{ActionsMenu.d.ts → ItemActionsMenu.d.ts} +1 -1
  72. package/dist/editor/menubar/ItemActionsMenu.js +23 -0
  73. package/dist/editor/menubar/ItemActionsMenu.js.map +1 -0
  74. package/dist/editor/menubar/ItemLanguageVersion.js +2 -2
  75. package/dist/editor/menubar/ItemLanguageVersion.js.map +1 -1
  76. package/dist/editor/menubar/LanguageSelector.d.ts +1 -2
  77. package/dist/editor/menubar/LanguageSelector.js +23 -23
  78. package/dist/editor/menubar/LanguageSelector.js.map +1 -1
  79. package/dist/editor/menubar/PageSelector.js +7 -8
  80. package/dist/editor/menubar/PageSelector.js.map +1 -1
  81. package/dist/editor/menubar/PageViewerControls.js +22 -19
  82. package/dist/editor/menubar/PageViewerControls.js.map +1 -1
  83. package/dist/editor/menubar/PreviewSecondaryControls.js +2 -3
  84. package/dist/editor/menubar/PreviewSecondaryControls.js.map +1 -1
  85. package/dist/editor/menubar/User.js +1 -1
  86. package/dist/editor/menubar/User.js.map +1 -1
  87. package/dist/editor/menubar/VersionSelector.js +36 -31
  88. package/dist/editor/menubar/VersionSelector.js.map +1 -1
  89. package/dist/editor/menubar/WorkflowButton.d.ts +1 -0
  90. package/dist/editor/menubar/WorkflowButton.js +41 -0
  91. package/dist/editor/menubar/WorkflowButton.js.map +1 -0
  92. package/dist/editor/page-editor-chrome/FrameMenu.js +5 -5
  93. package/dist/editor/page-editor-chrome/FrameMenu.js.map +1 -1
  94. package/dist/editor/page-editor-chrome/SuggestionHighlightings.js +2 -2
  95. package/dist/editor/page-editor-chrome/SuggestionHighlightings.js.map +1 -1
  96. package/dist/editor/page-viewer/EditorForm.d.ts +2 -1
  97. package/dist/editor/page-viewer/EditorForm.js +61 -49
  98. package/dist/editor/page-viewer/EditorForm.js.map +1 -1
  99. package/dist/editor/page-viewer/PageViewer.d.ts +2 -1
  100. package/dist/editor/page-viewer/PageViewer.js +28 -44
  101. package/dist/editor/page-viewer/PageViewer.js.map +1 -1
  102. package/dist/editor/page-viewer/PageViewerFrame.js +1 -1
  103. package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
  104. package/dist/editor/reviews/Comments.js +9 -9
  105. package/dist/editor/reviews/Comments.js.map +1 -1
  106. package/dist/editor/reviews/SuggestedEdit.js +3 -3
  107. package/dist/editor/services/contentService.d.ts +18 -0
  108. package/dist/editor/services/contentService.js +6 -0
  109. package/dist/editor/services/contentService.js.map +1 -1
  110. package/dist/editor/services/editService.d.ts +5 -0
  111. package/dist/editor/services/editService.js +4 -0
  112. package/dist/editor/services/editService.js.map +1 -1
  113. package/dist/editor/services/systemService.d.ts +2 -1
  114. package/dist/editor/services/systemService.js +4 -1
  115. package/dist/editor/services/systemService.js.map +1 -1
  116. package/dist/editor/sidebar/ComponentTree.js +26 -10
  117. package/dist/editor/sidebar/ComponentTree.js.map +1 -1
  118. package/dist/editor/sidebar/Divider.d.ts +6 -0
  119. package/dist/editor/sidebar/Divider.js +6 -0
  120. package/dist/editor/sidebar/Divider.js.map +1 -0
  121. package/dist/editor/sidebar/LeftToolbar.d.ts +1 -0
  122. package/dist/editor/sidebar/LeftToolbar.js +16 -0
  123. package/dist/editor/sidebar/LeftToolbar.js.map +1 -0
  124. package/dist/editor/sidebar/SEOInfo.d.ts +1 -0
  125. package/dist/editor/sidebar/SEOInfo.js +169 -0
  126. package/dist/editor/sidebar/SEOInfo.js.map +1 -0
  127. package/dist/editor/sidebar/Sidebar.js +1 -1
  128. package/dist/editor/sidebar/Sidebar.js.map +1 -1
  129. package/dist/editor/sidebar/SidebarView.d.ts +3 -2
  130. package/dist/editor/sidebar/SidebarView.js +22 -60
  131. package/dist/editor/sidebar/SidebarView.js.map +1 -1
  132. package/dist/editor/sidebar/ViewSelector.js +66 -20
  133. package/dist/editor/sidebar/ViewSelector.js.map +1 -1
  134. package/dist/editor/ui/Icons.d.ts +4 -0
  135. package/dist/editor/ui/Icons.js +15 -3
  136. package/dist/editor/ui/Icons.js.map +1 -1
  137. package/dist/editor/ui/Section.js +1 -1
  138. package/dist/editor/ui/Section.js.map +1 -1
  139. package/dist/editor/ui/SimpleIconButton.d.ts +1 -2
  140. package/dist/editor/ui/SimpleIconButton.js +8 -13
  141. package/dist/editor/ui/SimpleIconButton.js.map +1 -1
  142. package/dist/editor/ui/SimpleTabs.js +2 -2
  143. package/dist/editor/ui/SimpleTabs.js.map +1 -1
  144. package/dist/editor/ui/SimpleToolbar.js +1 -1
  145. package/dist/editor/ui/SimpleToolbar.js.map +1 -1
  146. package/dist/editor/ui/Splitter.d.ts +4 -0
  147. package/dist/editor/ui/Splitter.js +6 -7
  148. package/dist/editor/ui/Splitter.js.map +1 -1
  149. package/dist/editor/views/CompareView.js +16 -4
  150. package/dist/editor/views/CompareView.js.map +1 -1
  151. package/dist/editor/views/SingleEditView.d.ts +2 -1
  152. package/dist/editor/views/SingleEditView.js +2 -2
  153. package/dist/editor/views/SingleEditView.js.map +1 -1
  154. package/dist/page-wizard/steps/ContentStep.js +1 -1
  155. package/dist/page-wizard/steps/ContentStep.js.map +1 -1
  156. package/dist/revision.d.ts +2 -2
  157. package/dist/revision.js +2 -2
  158. package/dist/splash-screen/NewPage.js +8 -6
  159. package/dist/splash-screen/NewPage.js.map +1 -1
  160. package/dist/splash-screen/RecentPages.js +3 -8
  161. package/dist/splash-screen/RecentPages.js.map +1 -1
  162. package/dist/styles.css +1519 -543
  163. package/dist/tour/Tour.js +79 -10
  164. package/dist/tour/Tour.js.map +1 -1
  165. package/dist/tour/default-tour.js +55 -45
  166. package/dist/tour/default-tour.js.map +1 -1
  167. package/dist/types.d.ts +19 -1
  168. package/package.json +13 -5
  169. package/src/components/ui/badge.tsx +46 -0
  170. package/src/components/ui/button.tsx +3 -3
  171. package/src/components/ui/command.tsx +184 -0
  172. package/src/components/ui/dialog.tsx +143 -0
  173. package/src/components/ui/dropdown-menu.tsx +257 -0
  174. package/src/components/ui/input.tsx +21 -0
  175. package/src/components/ui/menubar.tsx +276 -0
  176. package/src/components/ui/popover.tsx +113 -0
  177. package/src/components/ui/switch.tsx +31 -0
  178. package/src/components/ui/tooltip.tsx +61 -0
  179. package/src/config/config.tsx +102 -65
  180. package/src/config/types.ts +3 -3
  181. package/src/editor/ContentTree.tsx +1 -1
  182. package/src/editor/Editor.tsx +8 -2
  183. package/src/editor/FieldList.tsx +2 -2
  184. package/src/editor/FieldListField.tsx +1 -1
  185. package/src/editor/ImageEditor.tsx +44 -21
  186. package/src/editor/MainLayout.tsx +21 -16
  187. package/src/editor/MobileLayout.tsx +3 -2
  188. package/src/editor/PictureEditor.tsx +74 -45
  189. package/src/editor/Titlebar.tsx +12 -24
  190. package/src/editor/ai/GhostWriter.tsx +1 -1
  191. package/src/editor/client/EditorClient.tsx +55 -13
  192. package/src/editor/client/editContext.ts +5 -0
  193. package/src/editor/client/operations.ts +2 -2
  194. package/src/editor/client/pageModelBuilder.ts +3 -7
  195. package/src/editor/commands/itemCommands.tsx +272 -0
  196. package/src/editor/field-types/MultiLineText.tsx +1 -1
  197. package/src/editor/field-types/SingleLineText.tsx +1 -1
  198. package/src/editor/menubar/ActiveUsers.tsx +271 -5
  199. package/src/editor/menubar/ItemActionsMenu.tsx +89 -0
  200. package/src/editor/menubar/ItemLanguageVersion.tsx +7 -5
  201. package/src/editor/menubar/LanguageSelector.tsx +105 -134
  202. package/src/editor/menubar/PageSelector.tsx +25 -27
  203. package/src/editor/menubar/PageViewerControls.tsx +126 -78
  204. package/src/editor/menubar/PreviewSecondaryControls.tsx +0 -2
  205. package/src/editor/menubar/User.tsx +2 -2
  206. package/src/editor/menubar/VersionSelector.tsx +124 -99
  207. package/src/editor/menubar/WorkflowButton.tsx +115 -0
  208. package/src/editor/page-editor-chrome/FrameMenu.tsx +5 -5
  209. package/src/editor/page-editor-chrome/SuggestionHighlightings.tsx +2 -2
  210. package/src/editor/page-viewer/EditorForm.tsx +112 -87
  211. package/src/editor/page-viewer/PageViewer.tsx +75 -92
  212. package/src/editor/page-viewer/PageViewerFrame.tsx +1 -1
  213. package/src/editor/reviews/Comments.tsx +19 -20
  214. package/src/editor/reviews/SuggestedEdit.tsx +3 -3
  215. package/src/editor/services/contentService.ts +28 -0
  216. package/src/editor/services/editService.ts +12 -0
  217. package/src/editor/services/systemService.ts +5 -2
  218. package/src/editor/sidebar/ComponentTree.tsx +34 -12
  219. package/src/editor/sidebar/Divider.tsx +22 -0
  220. package/src/editor/sidebar/LeftToolbar.tsx +36 -0
  221. package/src/editor/sidebar/SEOInfo.tsx +265 -0
  222. package/src/editor/sidebar/Sidebar.tsx +1 -0
  223. package/src/editor/sidebar/SidebarView.tsx +77 -111
  224. package/src/editor/sidebar/ViewSelector.tsx +211 -43
  225. package/src/editor/ui/Icons.tsx +155 -10
  226. package/src/editor/ui/Section.tsx +1 -1
  227. package/src/editor/ui/SimpleIconButton.tsx +30 -28
  228. package/src/editor/ui/SimpleTabs.tsx +3 -3
  229. package/src/editor/ui/SimpleToolbar.tsx +1 -1
  230. package/src/editor/ui/Splitter.tsx +14 -7
  231. package/src/editor/views/CompareView.tsx +23 -11
  232. package/src/editor/views/SingleEditView.tsx +3 -0
  233. package/src/page-wizard/steps/ContentStep.tsx +0 -1
  234. package/src/revision.ts +2 -2
  235. package/src/splash-screen/NewPage.tsx +18 -13
  236. package/src/splash-screen/RecentPages.tsx +4 -10
  237. package/src/tour/Tour.tsx +125 -34
  238. package/src/tour/default-tour.tsx +55 -45
  239. package/src/types.ts +21 -1
  240. package/styles.css +301 -1
  241. package/dist/editor/menubar/ActionsMenu.js +0 -49
  242. package/dist/editor/menubar/ActionsMenu.js.map +0 -1
  243. package/dist/editor/menubar/SecondaryControls.d.ts +0 -1
  244. package/dist/editor/menubar/SecondaryControls.js +0 -17
  245. package/dist/editor/menubar/SecondaryControls.js.map +0 -1
  246. package/src/editor/menubar/ActionsMenu.tsx +0 -94
  247. package/src/editor/menubar/SecondaryControls.tsx +0 -45
package/src/tour/Tour.tsx CHANGED
@@ -9,6 +9,7 @@ import { ActionButton } from "../components/ActionButton";
9
9
  export function Tour({ tourStopCallback }: { tourStopCallback: () => void }) {
10
10
  const [currentStep, setCurrentStep] = useState<string>("start-tour");
11
11
  const [show, setShow] = useState(true);
12
+ const [bubbleVisible, setBubbleVisible] = useState(true);
12
13
  const editContext = useEditContext();
13
14
  const [focusRect, setFocusRect] = useState<DOMRect | null>(null);
14
15
  const [pointToRect, setPointToRect] = useState<DOMRect | null>(null);
@@ -36,7 +37,6 @@ export function Tour({ tourStopCallback }: { tourStopCallback: () => void }) {
36
37
  rect.width + extendFocus,
37
38
  rect.height + extendFocus,
38
39
  );
39
-
40
40
  resolve(rect);
41
41
  } else if (timeout > 0 && Date.now() - startTime >= timeout) {
42
42
  resolve(undefined);
@@ -178,6 +178,16 @@ export function Tour({ tourStopCallback }: { tourStopCallback: () => void }) {
178
178
  await delay(randomDelay);
179
179
  }
180
180
  }
181
+ /**
182
+ * Animated step change with fade out/in transition
183
+ */
184
+ const animatedStepChange = async (newStepId: string) => {
185
+ setBubbleVisible(false); // Fade out
186
+ await delay(200); // Wait for fade out
187
+ setCurrentStep(newStepId); // Change content
188
+ await delay(50); // Small delay
189
+ setBubbleVisible(true); // Fade in
190
+ };
181
191
 
182
192
  /**
183
193
  * Stops the tour and resets the state.
@@ -191,10 +201,9 @@ export function Tour({ tourStopCallback }: { tourStopCallback: () => void }) {
191
201
  const tours = editContext!.configuration.tours;
192
202
  const tour =
193
203
  tours[editContext!.configuration.activeTour as keyof typeof tours];
194
-
195
204
  const tourSteps = tour.getSteps({
196
205
  editContext: editContext as EditContextType,
197
- nextStep: (stepId) => setCurrentStep(stepId),
206
+ nextStep: (stepId) => animatedStepChange(stepId),
198
207
  stopTour: () => tourStopCallback(),
199
208
  waitForElement,
200
209
  waitForElementToDisappear,
@@ -224,22 +233,20 @@ export function Tour({ tourStopCallback }: { tourStopCallback: () => void }) {
224
233
 
225
234
  if (step.focusElement) {
226
235
  const rect = await waitForElement(step.focusElement, 5000);
227
- if (!rect) setCurrentStep("error");
236
+ if (!rect) animatedStepChange("error");
228
237
  else setFocusRect(rect);
229
238
  }
230
239
 
231
- setShow(true);
232
-
233
- if (step.waitForUserInput) {
240
+ setShow(true); if (step.waitForUserInput) {
234
241
  const nextStep = (await step.waitForUserInput()) || step.nextStep;
235
242
  if (nextStep) {
236
- setCurrentStep(nextStep);
243
+ animatedStepChange(nextStep);
237
244
  } else console.log("no next step defined for step", currentStep);
238
245
  } else {
239
246
  if (step.waitForElement) {
240
247
  await waitForElement(step.waitForElement);
241
248
  if (step.nextStep) {
242
- setCurrentStep(step.nextStep);
249
+ animatedStepChange(step.nextStep);
243
250
  }
244
251
  }
245
252
  }
@@ -274,8 +281,23 @@ export function Tour({ tourStopCallback }: { tourStopCallback: () => void }) {
274
281
  if (!step) {
275
282
  throw new Error(`Tour step ${currentStep} not found`);
276
283
  }
277
-
278
- const bubblePosition = step.bubblePosition || "right";
284
+ // On mobile, always use bottom or top positioning for better UX
285
+ const isMobile = window.innerWidth < 768;
286
+ let bubblePosition: "left" | "right" | "bottom" | "top-right" = step.bubblePosition as
287
+ | "left"
288
+ | "right"
289
+ | "bottom"
290
+ | "top-right"
291
+ || "right";
292
+
293
+ if (isMobile) {
294
+ // On mobile, prefer bottom positioning, but use top if element is in bottom half of screen
295
+ if (pointToRect && pointToRect.top > window.innerHeight / 2) {
296
+ bubblePosition = "top-right"; // We'll use top-right but modify it for mobile
297
+ } else {
298
+ bubblePosition = "bottom";
299
+ }
300
+ }
279
301
  const bubbleStyle: React.CSSProperties = {};
280
302
 
281
303
  let boxStyle: React.CSSProperties = {
@@ -312,12 +334,12 @@ export function Tour({ tourStopCallback }: { tourStopCallback: () => void }) {
312
334
  arrowStyle = {
313
335
  marginRight: "-20px",
314
336
  };
315
- }
316
-
337
+ }
338
+
317
339
  if (bubblePosition === "bottom") {
318
340
  boxStyle = {
319
341
  position: "absolute",
320
- left: pointToRect.left + pointToRect.width / 2,
342
+ left: isMobile ? "50%" : pointToRect.left + pointToRect.width / 2,
321
343
  top: pointToRect.top + pointToRect.height,
322
344
  transform: "translate(-50%, 0)",
323
345
  };
@@ -331,7 +353,7 @@ export function Tour({ tourStopCallback }: { tourStopCallback: () => void }) {
331
353
  if (bubblePosition === "top-right") {
332
354
  boxStyle = {
333
355
  position: "absolute",
334
- left: pointToRect.left + pointToRect.width,
356
+ left: isMobile ? "50%" : pointToRect.left + pointToRect.width,
335
357
  bottom: window.innerHeight - pointToRect.top,
336
358
  transform: "translate(-50%, 0)",
337
359
  flexDirection: "column-reverse",
@@ -344,11 +366,60 @@ export function Tour({ tourStopCallback }: { tourStopCallback: () => void }) {
344
366
  arrowStyle = {
345
367
  transform: "scaleX(-1)",
346
368
  };
369
+ } }
370
+ }
371
+
372
+ // Viewport correction: ensure bubble stays within screen bounds
373
+ const getCorrectedBoxStyle = (style: React.CSSProperties): React.CSSProperties => {
374
+ if (!pointToRect) return style;
375
+
376
+ const correctedStyle = { ...style };
377
+ const margin = 10; // Small margin from screen edges
378
+
379
+ // For absolute positioning, check if bubble would be outside viewport
380
+ if (correctedStyle.position === 'absolute') {
381
+ // If bubble would be too far down, move it up (can overlap with target element)
382
+ if (typeof correctedStyle.top === 'number') {
383
+ const maxTop = window.innerHeight - 250; // Reserve 250px for bubble height
384
+ if (correctedStyle.top > maxTop) {
385
+ correctedStyle.top = Math.max(margin, maxTop);
386
+ }
387
+ }
388
+
389
+ // If bubble would be too far right, move it left
390
+ if (typeof correctedStyle.left === 'number') {
391
+ const bubbleWidth = isMobile ? window.innerWidth * 0.95 : 500;
392
+ const maxLeft = window.innerWidth - bubbleWidth - margin;
393
+ if (correctedStyle.left > maxLeft) {
394
+ correctedStyle.left = Math.max(margin, maxLeft);
395
+ }
396
+ }
397
+
398
+ // Handle right positioning
399
+ if (typeof correctedStyle.right === 'number') {
400
+ const bubbleWidth = isMobile ? window.innerWidth * 0.95 : 500;
401
+ if (correctedStyle.right > window.innerWidth - bubbleWidth - margin) {
402
+ correctedStyle.right = margin;
403
+ }
404
+ }
405
+
406
+ // Handle bottom positioning - if too high, place at bottom of screen
407
+ if (typeof correctedStyle.bottom === 'number') {
408
+ const maxBottom = window.innerHeight - 250;
409
+ if (correctedStyle.bottom > maxBottom) {
410
+ delete correctedStyle.bottom;
411
+ correctedStyle.top = window.innerHeight - 200 - margin; // Place near bottom
412
+ }
347
413
  }
348
414
  }
349
- }
415
+
416
+ return correctedStyle;
417
+ };
350
418
 
351
- const arrowRotation = bubblePosition === "right" ? "-a-rotate-90" : "";
419
+ // Apply viewport correction
420
+ boxStyle = getCorrectedBoxStyle(boxStyle);
421
+
422
+ const arrowRotation = bubblePosition === "right" ? "-rotate-90" : "";
352
423
 
353
424
  const overlayStyle: React.CSSProperties = {
354
425
  position: "fixed",
@@ -358,6 +429,7 @@ export function Tour({ tourStopCallback }: { tourStopCallback: () => void }) {
358
429
  height: "100%",
359
430
  backgroundColor: "rgba(0, 0, 0, 0.3)",
360
431
  pointerEvents: "auto",
432
+ transition: "all 0.2s ease-in-out",
361
433
  clipPath: focusRect
362
434
  ? `polygon(0% 0%, 0% 100%, ${focusRect.left}px 100%, ${
363
435
  focusRect.left
@@ -380,26 +452,30 @@ export function Tour({ tourStopCallback }: { tourStopCallback: () => void }) {
380
452
  return (
381
453
  <>
382
454
  <div className="overlay" style={overlayStyle}></div>
383
-
455
+
384
456
  <div
385
457
  style={boxStyle}
386
- className="fade-in flex flex-col items-center text-gray-800"
458
+ className={`fade-in flex flex-col items-center text-gray-800 transition-opacity duration-200 ${
459
+ bubbleVisible ? 'opacity-100' : 'opacity-0'
460
+ }`}
387
461
  >
388
462
  {focusRect && (
389
- <svg
390
- width="100px"
391
- height="100px"
392
- viewBox="0 -7.89 113.08 113.08"
393
- xmlns="http://www.w3.org/2000/svg"
394
- className={classNames("pointer-events-none", arrowRotation)}
395
- style={arrowStyle}
396
- >
463
+ <div className="pointer-events-none">
464
+ <svg
465
+ width="100px"
466
+ height="100px"
467
+ viewBox="0 -7.89 113.08 113.08"
468
+ xmlns="http://www.w3.org/2000/svg"
469
+ className={classNames("pointer-events-none", arrowRotation)}
470
+ style={arrowStyle}
471
+ >
397
472
  <path
398
473
  style={{ stroke: "#0000ff", fill: "#0000ff" }}
399
474
  d="M20.1871 175C15.7485 172.891 13.0008 172.469 12.1553 170.992C8.98489 165.508 5.39173 160.024 3.70083 153.908C-1.37187 137.666 -0.737781 121.214 2.64402 104.762C8.35081 76.7092 21.0325 51.8201 36.8847 28.1966C38.5756 25.6655 40.0552 23.1344 41.7461 20.3924C41.7461 20.1814 41.5347 19.7596 41.112 19.1268C36.462 20.3923 31.6007 21.6579 26.9507 22.7125C24.4144 23.1344 21.4552 23.1344 18.9189 22.2907C17.4394 21.8688 15.3258 19.5486 15.3258 18.0722C15.3258 16.1739 16.8053 13.8537 18.0735 12.1663C19.1303 11.1117 21.0326 10.9008 22.7235 10.4789C35.4052 7.31508 48.087 3.72935 60.9801 0.776411C71.9709 -1.75468 75.564 1.83105 74.9299 12.5882C74.2959 23.7672 74.0845 34.9462 73.6618 45.9142C73.4505 49.289 72.8164 52.8747 72.3936 56.6714C63.5164 52.6638 63.5164 52.6638 60.346 18.494C47.0301 33.2588 38.1529 49.289 29.9098 65.7411C21.6666 82.1932 16.1712 99.489 13.2121 117.839C10.2531 136.823 13.8462 154.751 20.1871 175Z"
400
475
  fill="#0D1927"
401
- />
476
+ />
402
477
  </svg>
478
+ </div>
403
479
  )}
404
480
 
405
481
  <style>
@@ -421,16 +497,28 @@ export function Tour({ tourStopCallback }: { tourStopCallback: () => void }) {
421
497
  `}
422
498
  </style>
423
499
  <div
424
- className={`border-theme-secondary relative flex items-stretch justify-center gap-6 rounded-lg border bg-gray-50 shadow-2xl`}
500
+ className={`border-theme-secondary relative flex rounded-lg border bg-gray-50 shadow-2xl ${
501
+ isMobile
502
+ ? 'w-[95vw] flex-col items-center gap-3 p-4'
503
+ : 'items-stretch justify-center gap-6'
504
+ }`}
425
505
  style={bubbleStyle}
426
- >
427
- <div className="flex flex-col items-end justify-end gap-2 pt-5">
428
- <div className="bg-wizard-tour aspect-square w-40"></div>
506
+ >
507
+ <div className={`flex flex-col gap-2 ${
508
+ isMobile ? 'items-center justify-center' : 'items-end justify-end pt-5'
509
+ }`}>
510
+ <div className={`bg-wizard-tour aspect-square ${
511
+ isMobile ? 'w-20' : 'w-40'
512
+ }`}></div>
429
513
  </div>
430
- <div className="flex flex-col items-end justify-between gap-3 p-6">
514
+ <div className={`flex flex-col gap-3 ${
515
+ isMobile ? 'items-center justify-center p-3' : 'items-end justify-between p-6'
516
+ }`}>
431
517
  {/* Step Content */}
432
518
  <div className="flex items-start">
433
- <div className="flex max-w-[450px] flex-col gap-2 text-center text-2xl text-gray-800">
519
+ <div className={`flex flex-col gap-2 text-center text-gray-800 ${
520
+ isMobile ? 'max-w-[80vw] text-lg' : 'max-w-[450px] text-2xl'
521
+ }`}>
434
522
  <div className="flex items-center gap-3">
435
523
  <Logo className="w-8" />
436
524
  <div className="text-xl font-bold">{step.title}</div>
@@ -440,6 +528,9 @@ export function Tour({ tourStopCallback }: { tourStopCallback: () => void }) {
440
528
  <button
441
529
  className="text-2xs flex cursor-pointer items-center gap-2 font-bold"
442
530
  onClick={stopTour}
531
+ type="button"
532
+ title="Close tour"
533
+ aria-label="Close tour"
443
534
  >
444
535
  <X className="h-4 w-4" />
445
536
  </button>
@@ -52,8 +52,8 @@ export function getDefaultTourSteps(
52
52
  className: "button button-secondary mt-2",
53
53
  },
54
54
  ],
55
- },
56
- "new-page": {
55
+ }, "new-page": {
56
+ title: "Create a New Page",
57
57
  description: (
58
58
  <>
59
59
  Click on the <b>New Page</b> tab to create a new page
@@ -65,30 +65,39 @@ export function getDefaultTourSteps(
65
65
  await waitForElement(".tour-pick-location");
66
66
  },
67
67
  nextStep: "pick-location",
68
- },
69
- "pick-location": {
68
+ }, "pick-location": {
69
+ title: "Choose Location",
70
70
  description: (
71
71
  <>
72
72
  Open up a folder for your page
73
73
  </>
74
74
  ),
75
- focusElement: ".tree-container",
76
- bubblePosition: "bottom",
75
+ focusElement: ".tour-pick-location",
76
+ bubblePosition: "right",
77
77
  waitForUserInput: async () => {
78
78
  await waitForElement(".bg-theme-secondary-light");
79
79
  },
80
80
  nextStep: "choose-template",
81
- },
82
- "choose-template": {
81
+ }, "choose-template": {
82
+ title: "Select Template",
83
83
  description: "Select a template for your page",
84
84
  focusElement: ".tour-choose-template",
85
85
  waitForUserInput: async () => {
86
- await waitForElement(".bg-theme-secondary-light");
86
+ return new Promise<void>((resolve) => {
87
+ const templateArea = document.querySelector(".tour-choose-template");
88
+ if (templateArea) {
89
+ const handleClick = () => {
90
+ templateArea.removeEventListener("click", handleClick);
91
+ resolve();
92
+ };
93
+ templateArea.addEventListener("click", handleClick);
94
+ }
95
+ });
87
96
  },
88
97
  bubblePosition: "left",
89
98
  nextStep: "enter-name",
90
- },
91
- "enter-name": {
99
+ }, "enter-name": {
100
+ title: "Name Your Page",
92
101
  description: "Enter a name for your page",
93
102
  focusElement: "#new-page-name",
94
103
  bubblePosition: "left",
@@ -96,25 +105,25 @@ export function getDefaultTourSteps(
96
105
  await waitForElement("#create-new-page-button:not([disabled])");
97
106
  },
98
107
  nextStep: "create-page",
99
- },
100
- "create-page": {
108
+ }, "create-page": {
109
+ title: "Create Page",
101
110
  description: "Click the Create button",
102
111
  focusElement: "#create-new-page-button",
103
- bubblePosition: "bottom",
112
+ bubblePosition: "left",
104
113
  waitForUserInput: async () => {
105
114
  // wait for loading spinner
106
115
  await waitForElement(".pi-cog");
107
116
  },
108
117
  nextStep: "loading",
109
- },
110
- "loading": {
118
+ }, "loading": {
119
+ title: "Loading...",
111
120
  description: "Waiting for your new page...",
112
121
  waitForUserInput: async () => {
113
122
  await waitForElementToDisappear(".pi-cog");
114
123
  },
115
124
  nextStep: "ready-to-add-component",
116
- },
117
- "ready-to-add-component": {
125
+ }, "ready-to-add-component": {
126
+ title: "Ready to Add Components",
118
127
  description: "Wanna add a component to your beautiful empty page?",
119
128
  buttons: [
120
129
  {
@@ -132,8 +141,8 @@ export function getDefaultTourSteps(
132
141
  },
133
142
  },
134
143
  ],
135
- },
136
- "insert-component": {
144
+ }, "insert-component": {
145
+ title: "Insert Component",
137
146
  description: "Excellent, click on the plus button to insert a component.",
138
147
  focusElement: "#insert-component-button",
139
148
  bubblePosition: "bottom",
@@ -141,17 +150,17 @@ export function getDefaultTourSteps(
141
150
  await waitForElement(".tour-component-palette");
142
151
  },
143
152
  nextStep: "drag-component",
144
- },
145
- "drag-component": {
153
+ }, "drag-component": {
154
+ title: "Drag & Drop Component",
146
155
  description: `Drag and drop a ${config.firstComponentTemplateName} component to your page.`,
147
156
  focusElement: `#insert-component-${config.firstComponentTemplateId}`,
148
- bubblePosition: "bottom",
157
+ bubblePosition: "right",
149
158
  waitForUserInput: async () => {
150
159
  await waitForElement(".tour-placeholder-dropzone");
151
160
  },
152
161
  nextStep: "drop-component-on-placeholder",
153
- },
154
- "drop-component-on-placeholder": {
162
+ }, "drop-component-on-placeholder": {
163
+ title: "Drop Here!",
155
164
  description: "Drop the component onto this placeholder!",
156
165
  focusElement: ".tour-placeholder-dropzone",
157
166
  bubblePosition: "left",
@@ -165,8 +174,8 @@ export function getDefaultTourSteps(
165
174
  return "drag-component";
166
175
  },
167
176
  nextStep: "enter-title",
168
- },
169
- "enter-title": {
177
+ }, "enter-title": {
178
+ title: "Fill in Content",
170
179
  description: `Excellent! Now lets fill in the fields. First enter a ${config.firstComponentTextFieldName}`,
171
180
  focusElement: `[data-field-id='${config.firstComponentTextFieldId}']`,
172
181
  waitForUserInput: async () => {
@@ -177,8 +186,8 @@ export function getDefaultTourSteps(
177
186
  );
178
187
  },
179
188
  nextStep: "see-content-update",
180
- },
181
- "see-content-update": {
189
+ }, "see-content-update": {
190
+ title: "Live Updates",
182
191
  description:
183
192
  "See how the content is automatically updating on your page?",
184
193
  focusElement: `[data-field-id='${config.firstComponentTextFieldId}']`,
@@ -193,8 +202,8 @@ export function getDefaultTourSteps(
193
202
  );
194
203
  },
195
204
  nextStep: "edit-content-inline",
196
- },
197
- "edit-content-inline": {
205
+ }, "edit-content-inline": {
206
+ title: "Inline Editing",
198
207
  description:
199
208
  "You can also directly edit the content on the page. Click on the [Introduction] placeholder here and start typing!",
200
209
  focusElement: `iframe:[data-fieldid='${config.firstComponentRichTextFieldId}']`,
@@ -208,8 +217,8 @@ export function getDefaultTourSteps(
208
217
  );
209
218
  },
210
219
  nextStep: "ai-intro",
211
- },
212
- "ai-intro": {
220
+ }, "ai-intro": {
221
+ title: "AI-Powered Editing",
213
222
  description:
214
223
  "But hey, this is an AI editor, so why not let the AI do some of the work for you?",
215
224
  buttons: [
@@ -222,16 +231,17 @@ export function getDefaultTourSteps(
222
231
  onClick: () => nextStep("ai-sidebar"),
223
232
  },
224
233
  ],
225
- },
226
- "ai-sidebar": {
234
+ }, "ai-sidebar": {
235
+ title: "Open AI Chat",
227
236
  description: "Click on the AI sidebar to open the AI chat.",
228
237
  focusElement: `[data-sidebarview-name='ai']`,
238
+ bubblePosition: "right",
229
239
  nextStep: "ai-terminal",
230
240
  waitForElement: "[data-sidebarview-name='ai'].active",
231
- },
232
- "ai-terminal": {
241
+ }, "ai-terminal": {
242
+ title: "AI Assistant",
233
243
  description:
234
- "Let me take control and add tell the AI to add some more components.",
244
+ "Let me take control and tell the AI to add some more components.",
235
245
  focusElement: `.tour-ai-terminal textarea`,
236
246
  waitForUserInput: async () => {
237
247
  await delay(1000);
@@ -240,25 +250,25 @@ export function getDefaultTourSteps(
240
250
  (aiTerminal as HTMLTextAreaElement).focus();
241
251
  await simulateTyping(
242
252
  aiTerminal as HTMLTextAreaElement,
243
- `Plase add three components of type ${config.firstComponentTemplateName} with some funny dummy content to the page.`,
253
+ `Please add three components of type ${config.firstComponentTemplateName} with some funny dummy content to the page.`,
244
254
  );
245
255
  }
246
256
  },
247
257
  bubblePosition: "top-right",
248
258
  nextStep: "ai-submit",
249
- },
250
- "ai-submit": {
259
+ }, "ai-submit": {
260
+ title: "Send AI Request",
251
261
  description: "Click on the Send button to submit the prompt to the AI.",
252
262
  focusElement: ".tour-ai-terminal .tour-send-button",
253
263
  bubblePosition: "top-right",
254
264
  nextStep: "ai-watch-components-added",
255
- waitForElement: ".tour-ai-terminal .a-prompt",
256
- },
257
- "ai-watch-components-added": {
265
+ waitForElement: ".tour-ai-terminal .prompt",
266
+ }, "ai-watch-components-added": {
267
+ title: "AI Magic in Action",
258
268
  description:
259
269
  "Watch how the AI adds the components to the page. This can take a few seconds.",
260
270
  focusElement: ".tour-ai-terminal",
261
- pointToElement: ".tour-ai-terminal .a-prompt",
271
+ pointToElement: ".tour-ai-terminal .prompt",
262
272
  waitForElement: ".tour-ai-response-message-changes",
263
273
  nextStep: "congratulations",
264
274
  },
package/src/types.ts CHANGED
@@ -152,6 +152,8 @@ export type View = {
152
152
  export type UserInfo = {
153
153
  user: User;
154
154
  views: View[];
155
+ browseHistory?: UserBrowseHistoryEntry[];
156
+ preferences: UserPreferences;
155
157
  };
156
158
 
157
159
  export type User = {
@@ -162,6 +164,12 @@ export type User = {
162
164
  isLimitedPreviewUser?: boolean;
163
165
  };
164
166
 
167
+ export type UserPreferences = {
168
+ pinnedViews?: string[];
169
+ showViewNames?: boolean;
170
+ showRightSidebar?: boolean;
171
+ };
172
+
165
173
  export type HistoryEntry = {
166
174
  name: string;
167
175
  path: string;
@@ -173,6 +181,18 @@ export type HistoryEntry = {
173
181
  language: string;
174
182
  };
175
183
 
184
+ export type UserBrowseHistoryEntry = {
185
+ id: number;
186
+ userName: string;
187
+ itemId: string;
188
+ itemLanguage: string;
189
+ itemVersion: number;
190
+ visitedAt: string;
191
+ sessionId?: string;
192
+ itemPath: string;
193
+ itemName: string;
194
+ };
195
+
176
196
  export type FieldHistoryItem = {
177
197
  user: string;
178
198
  date: string;
@@ -320,7 +340,7 @@ export interface SuggestedEdit {
320
340
  author?: string;
321
341
  authorDisplayName?: string;
322
342
  created?: string;
323
- status: string;
343
+ status: "rejected" | "applied" | "pending";
324
344
  updatedBy?: string;
325
345
  updated?: string;
326
346
  comments?: string;