@peteai/presentation-editor 0.0.9 → 0.0.10

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 (54) hide show
  1. package/dist/components/editor/design.svelte +92 -0
  2. package/dist/components/editor/design.svelte.d.ts +8 -0
  3. package/dist/components/editor/editor.svelte +1 -1
  4. package/dist/components/editor/editor.svelte.js +14 -2
  5. package/dist/components/editor/header.svelte +1 -1
  6. package/dist/components/editor/index.d.ts +2 -1
  7. package/dist/components/editor/index.js +2 -1
  8. package/dist/components/editor/page-editor.svelte +7 -0
  9. package/dist/components/editor/{pages-navigation/page-preview.svelte → page-preview.svelte} +4 -4
  10. package/dist/components/editor/{pages-navigation/page-preview.svelte.d.ts → page-preview.svelte.d.ts} +2 -2
  11. package/dist/components/editor/page-transition-preview.svelte +34 -0
  12. package/dist/components/editor/page-transition-preview.svelte.d.ts +9 -0
  13. package/dist/components/editor/page-with-transition.svelte +48 -0
  14. package/dist/components/editor/page-with-transition.svelte.d.ts +10 -0
  15. package/dist/components/editor/page.svelte +12 -19
  16. package/dist/components/editor/pages-navigation/pages-navigation-item.svelte +80 -20
  17. package/dist/components/editor/pages-navigation/pages-navigation.svelte +7 -4
  18. package/dist/components/editor/sidebar/color-sidebar/color-sidebar.svelte +91 -81
  19. package/dist/components/editor/sidebar/color-sidebar/color-sidebar.svelte.d.ts +5 -1
  20. package/dist/components/editor/sidebar/font-sidebar/font-sidebar.svelte +9 -5
  21. package/dist/components/editor/sidebar/font-sidebar/font-sidebar.svelte.d.ts +5 -1
  22. package/dist/components/editor/sidebar/image-crop-sidebar.svelte +28 -37
  23. package/dist/components/editor/sidebar/image-crop-sidebar.svelte.d.ts +2 -0
  24. package/dist/components/editor/sidebar/position-sidebar/index.d.ts +2 -0
  25. package/dist/components/editor/sidebar/position-sidebar/index.js +2 -0
  26. package/dist/components/editor/sidebar/position-sidebar/position-sidebar.svelte +130 -0
  27. package/dist/components/editor/sidebar/position-sidebar/position-sidebar.svelte.d.ts +7 -0
  28. package/dist/components/editor/sidebar/sidebar-text-tab.svelte +7 -3
  29. package/dist/components/editor/sidebar/sidebar-text-tab.svelte.d.ts +5 -16
  30. package/dist/components/editor/sidebar/sidebar-uploads-tab.svelte +8 -6
  31. package/dist/components/editor/sidebar/sidebar-uploads-tab.svelte.d.ts +5 -1
  32. package/dist/components/editor/sidebar/sidebar-wrapper.svelte +4 -3
  33. package/dist/components/editor/sidebar/sidebar-wrapper.svelte.d.ts +1 -0
  34. package/dist/components/editor/sidebar/sidebar.svelte +20 -13
  35. package/dist/components/editor/sidebar/transition-sidebar/index.d.ts +2 -0
  36. package/dist/components/editor/sidebar/transition-sidebar/index.js +2 -0
  37. package/dist/components/editor/sidebar/transition-sidebar/transition-sidebar.svelte +257 -0
  38. package/dist/components/editor/sidebar/transition-sidebar/transition-sidebar.svelte.d.ts +7 -0
  39. package/dist/components/editor/types.d.ts +40 -6
  40. package/dist/components/editor/utils.d.ts +2 -2
  41. package/dist/components/editor/utils.js +21 -0
  42. package/dist/components/ui/button/button.svelte +2 -1
  43. package/dist/components/ui/button/button.svelte.d.ts +3 -0
  44. package/dist/transitions/circleWipe.d.ts +10 -0
  45. package/dist/transitions/circleWipe.js +16 -0
  46. package/dist/transitions/lineWipe.d.ts +9 -0
  47. package/dist/transitions/lineWipe.js +17 -0
  48. package/dist/transitions/stack.d.ts +8 -0
  49. package/dist/transitions/stack.js +13 -0
  50. package/package.json +1 -1
  51. package/dist/components/editor/layers/types/image/image-layer-active.svelte +0 -36
  52. package/dist/components/editor/layers/types/image/image-layer-active.svelte.d.ts +0 -7
  53. package/dist/components/editor/sidebar/position-sidebar.svelte +0 -136
  54. package/dist/components/editor/sidebar/position-sidebar.svelte.d.ts +0 -3
@@ -0,0 +1,92 @@
1
+ <script lang="ts">
2
+ import { BROWSER } from 'esm-env';
3
+ import { onMount } from 'svelte';
4
+ import type { DesignOptions, Page } from './types.js';
5
+ import { normalizePage } from './editor.svelte.js';
6
+ import { extractNodeFonts } from './layers/types/text/editor/utils.js';
7
+ import { defaultFonts } from './fonts.js';
8
+ import PageWithTransition from './page-with-transition.svelte';
9
+
10
+ const {
11
+ pages: pagesInput,
12
+ fonts = defaultFonts,
13
+ loadFont = async (family: string) => {
14
+ const font = fonts[family];
15
+ if (!font) return;
16
+ const WebFont = await import('webfontloader');
17
+ return new Promise((resolve, reject) => {
18
+ WebFont.load({
19
+ [font.type]: { families: [family] },
20
+ active: () => resolve(),
21
+ inactive: reject,
22
+ });
23
+ });
24
+ },
25
+ }: DesignOptions = $props();
26
+
27
+ const pages = pagesInput.map(normalizePage);
28
+
29
+ if (BROWSER) {
30
+ const fontFamilies = pages
31
+ .flatMap((page) => page.layers)
32
+ .filter((layer) => layer.type === 'text')
33
+ .flatMap((layer) => extractNodeFonts(layer.html));
34
+ Promise.all(fontFamilies.map(loadFont));
35
+ }
36
+
37
+ let element: HTMLDivElement | null = $state(null);
38
+
39
+ const width = 1920;
40
+ const height = 1080;
41
+
42
+ let thumbScale = $state(1);
43
+
44
+ onMount(() => {
45
+ const observer = new ResizeObserver((entries) => {
46
+ for (const entry of entries) {
47
+ const scaleX = entry.contentRect.width / width;
48
+ const scaleY = entry.contentRect.height / height;
49
+ thumbScale = Math.min(scaleX, scaleY); // preserve aspect ratio
50
+ }
51
+ });
52
+
53
+ if (element) observer.observe(element);
54
+
55
+ return () => observer.disconnect();
56
+ });
57
+
58
+ let sortedPages = $derived(pages.sort((a, b) => a.sortOrder - b.sortOrder));
59
+ let currentPageIndex = $state(0);
60
+ let page = $derived(sortedPages[currentPageIndex]);
61
+ let previousPage: Page | undefined = $state();
62
+
63
+ const setIndex = (index: number) => {
64
+ previousPage = page;
65
+ transition = page.transition;
66
+ currentPageIndex = index;
67
+ };
68
+ let transition = $derived(previousPage?.transition);
69
+
70
+ export const prevPage = () => {
71
+ if (currentPageIndex <= 0) return;
72
+ setIndex(currentPageIndex - 1);
73
+ };
74
+
75
+ export const nextPage = () => {
76
+ if (currentPageIndex >= sortedPages.length - 1) return;
77
+ setIndex(currentPageIndex + 1);
78
+ };
79
+
80
+ export const setPageIndex = (index: number) => {
81
+ if (index < 0 || index >= sortedPages.length) return;
82
+ setIndex(index);
83
+ };
84
+ </script>
85
+
86
+ <div bind:this={element} class="grid h-full w-full place-items-center">
87
+ <div style:width="{width * thumbScale}px" style:height="{height * thumbScale}px">
88
+ {#key page.id}
89
+ <PageWithTransition {page} {previousPage} {transition} {thumbScale} />
90
+ {/key}
91
+ </div>
92
+ </div>
@@ -0,0 +1,8 @@
1
+ import type { DesignOptions } from './types.js';
2
+ declare const Design: import("svelte").Component<DesignOptions, {
3
+ prevPage: () => void;
4
+ nextPage: () => void;
5
+ setPageIndex: (index: number) => void;
6
+ }, "">;
7
+ type Design = ReturnType<typeof Design>;
8
+ export default Design;
@@ -216,7 +216,7 @@
216
216
  <Hotkeys />
217
217
 
218
218
  <!-- svelte-ignore a11y_no_static_element_interactions -->
219
- <div class="flex h-full w-full select-none" ondragover={onDragOver} ondrop={onDrop}>
219
+ <div class="flex h-full w-full select-none bg-background" ondragover={onDragOver} ondrop={onDrop}>
220
220
  <Sidebar {editor} />
221
221
  <div class="flex h-full flex-1 select-none flex-col overflow-auto">
222
222
  <Dragged {editor} />
@@ -7,6 +7,12 @@ import { calculateBoundingBox, calculateImageCover, checkPolygonsIntersect, getR
7
7
  import createEditor from './layers/types/text/editor/createEditor.js';
8
8
  import { extensions } from './layers/types/text/extensions.js';
9
9
  import { SvelteSet } from 'svelte/reactivity';
10
+ export const normalizePage = (page) => {
11
+ return {
12
+ ...page,
13
+ transition: page.transition || null,
14
+ };
15
+ };
10
16
  export class Editor {
11
17
  mode = 'multiple';
12
18
  fonts = defaultFonts;
@@ -125,6 +131,7 @@ export class Editor {
125
131
  selectedLayersNotLocked = $derived(this.selectedLayers.filter((layer) => !layer.locked));
126
132
  selectedSimpleLayersNotLocked = $derived(this.selectedLayersNotLocked.flatMap((l) => l.type === 'group' ? this.findGroupChildren(this.activePage, l.id) : l));
127
133
  activeGroupRotate = $state(0);
134
+ pageTransitionPreview = $state(null);
128
135
  pageSelected = $state(false);
129
136
  clipboard = null;
130
137
  htmlEditor = createEditor({
@@ -142,11 +149,15 @@ export class Editor {
142
149
  const { page, ...rest } = options;
143
150
  Object.assign(this, { ...rest });
144
151
  if (page) {
145
- Object.assign(this, { pages: [page] });
152
+ Object.assign(this, { pages: [normalizePage(page)] });
146
153
  }
147
154
  }
148
155
  else {
149
- Object.assign(this, options);
156
+ const { pages, ...rest } = options;
157
+ Object.assign(this, rest);
158
+ if (pages) {
159
+ Object.assign(this, { pages: pages.map(normalizePage) });
160
+ }
150
161
  }
151
162
  if (!this.pages.length) {
152
163
  this.addPage();
@@ -163,6 +174,7 @@ export class Editor {
163
174
  backgroundImage: null,
164
175
  backgroundLocked: false,
165
176
  layers: [],
177
+ transition: null,
166
178
  };
167
179
  }
168
180
  addPage({ page, index } = {}) {
@@ -16,7 +16,7 @@
16
16
  let disabled = $derived(!!editor.imageCropLayer);
17
17
  </script>
18
18
 
19
- <div class="h-12 w-full border-b border-gray-200 bg-background px-2">
19
+ <div class="h-12 w-full border-b border-gray-200 px-2">
20
20
  <div class="flex h-full items-center justify-between">
21
21
  <div class="grid grid-flow-col items-center gap-2">
22
22
  <Button
@@ -1,3 +1,4 @@
1
1
  import Editor from './editor.svelte';
2
+ import Design from './design.svelte';
2
3
  import Page from './page.svelte';
3
- export { Editor, Page };
4
+ export { Editor, Design, Page };
@@ -1,3 +1,4 @@
1
1
  import Editor from './editor.svelte';
2
+ import Design from './design.svelte';
2
3
  import Page from './page.svelte';
3
- export { Editor, Page };
4
+ export { Editor, Design, Page };
@@ -15,6 +15,7 @@
15
15
  import PageInner from './page-inner.svelte';
16
16
  import ActiveLayers from './active-layers.svelte';
17
17
  import SnappingGuides from './snapping-guides.svelte';
18
+ import PageTransitionPreview from './page-transition-preview.svelte';
18
19
 
19
20
  interface Props {
20
21
  viewportRef: HTMLDivElement | null;
@@ -96,6 +97,12 @@
96
97
  {/if}
97
98
 
98
99
  <SnappingGuides zoom={editor.zoom} guides={activeLayerGuides} />
100
+
101
+ {#if editor.pageTransitionPreview}
102
+ {#key editor.pageTransitionPreview}
103
+ <PageTransitionPreview {editor} transition={editor.pageTransitionPreview} />
104
+ {/key}
105
+ {/if}
99
106
  </div>
100
107
  </div>
101
108
  </div>
@@ -5,15 +5,15 @@
5
5
  TextLayerContent,
6
6
  ImageLayerContent,
7
7
  GroupLayerContent,
8
- } from '../layers/index.js';
9
- import type { Page } from '../types.js';
8
+ } from './layers/index.js';
9
+ import type { Page } from './types.js';
10
10
 
11
11
  interface Props {
12
12
  page: Page;
13
- thumbScale: number;
13
+ thumbScale?: number;
14
14
  }
15
15
 
16
- let { page, thumbScale }: Props = $props();
16
+ let { page, thumbScale = 1 }: Props = $props();
17
17
 
18
18
  let rootLayers = $derived(page.layers.filter((l) => l.type === 'group' || !l.groupId));
19
19
  </script>
@@ -1,7 +1,7 @@
1
- import type { Page } from '../types.js';
1
+ import type { Page } from './types.js';
2
2
  interface Props {
3
3
  page: Page;
4
- thumbScale: number;
4
+ thumbScale?: number;
5
5
  }
6
6
  declare const PagePreview: import("svelte").Component<Props, {}, "">;
7
7
  type PagePreview = ReturnType<typeof PagePreview>;
@@ -0,0 +1,34 @@
1
+ <script lang="ts">
2
+ import { onMount } from 'svelte';
3
+ import type { PageTransition } from './types.js';
4
+ import type { Editor } from './editor.svelte.js';
5
+ import PageWithTransition from './page-with-transition.svelte';
6
+
7
+ interface Props {
8
+ editor: Editor;
9
+ transition: PageTransition;
10
+ }
11
+
12
+ const { editor, transition }: Props = $props();
13
+
14
+ let nextPage = $derived(
15
+ editor.sortedPages.find((p) => p.sortOrder > editor.activePage.sortOrder),
16
+ );
17
+
18
+ onMount(() => {
19
+ const timeout = setTimeout(() => {
20
+ editor.pageTransitionPreview = null;
21
+ }, transition.duration + 500);
22
+
23
+ return () => clearTimeout(timeout);
24
+ });
25
+ </script>
26
+
27
+ {#if nextPage}
28
+ <PageWithTransition
29
+ page={nextPage}
30
+ previousPage={editor.activePage}
31
+ {transition}
32
+ thumbScale={editor.zoom}
33
+ />
34
+ {/if}
@@ -0,0 +1,9 @@
1
+ import type { PageTransition } from './types.js';
2
+ import type { Editor } from './editor.svelte.js';
3
+ interface Props {
4
+ editor: Editor;
5
+ transition: PageTransition;
6
+ }
7
+ declare const PageTransitionPreview: import("svelte").Component<Props, {}, "">;
8
+ type PageTransitionPreview = ReturnType<typeof PageTransitionPreview>;
9
+ export default PageTransitionPreview;
@@ -0,0 +1,48 @@
1
+ <script lang="ts">
2
+ import { fade } from 'svelte/transition';
3
+ import { circleWipe } from '../../transitions/circleWipe.js';
4
+ import { lineWipe } from '../../transitions/lineWipe.js';
5
+ import { stack } from '../../transitions/stack.js';
6
+ import type { Page, PageTransition } from './types.js';
7
+ import PagePreview from './page-preview.svelte';
8
+
9
+ interface Props {
10
+ page: Page;
11
+ previousPage?: Page;
12
+ transition: PageTransition | null | undefined;
13
+ thumbScale: number;
14
+ }
15
+
16
+ const { page, previousPage, transition, thumbScale }: Props = $props();
17
+
18
+ const previousPageTransition = (node: HTMLElement) => {
19
+ if (!transition) return { duration: 0 };
20
+ if (transition.type === 'slide') return stack(node, { ...transition, reverse: true });
21
+ return { duration: 0 };
22
+ };
23
+
24
+ const pageTransition = (node: HTMLElement) => {
25
+ if (!transition) return { duration: 0 };
26
+ if (transition.type === 'fade') return fade(node, transition);
27
+ if (transition.type === 'slide') return stack(node, transition);
28
+ if (transition.type === 'circleWipe') return circleWipe(node, transition);
29
+ if (transition.type === 'lineWipe') return lineWipe(node, transition);
30
+ if (transition.type === 'stack') return stack(node, transition);
31
+ return { duration: 0 };
32
+ };
33
+ </script>
34
+
35
+ <div class="relative h-full w-full overflow-hidden">
36
+ {#if previousPage}
37
+ <div class="absolute inset-0">
38
+ <div in:previousPageTransition|global class="h-full w-full">
39
+ <PagePreview page={previousPage} {thumbScale} />
40
+ </div>
41
+ </div>
42
+ {/if}
43
+ <div class="absolute inset-0">
44
+ <div in:pageTransition|global class="h-full w-full">
45
+ <PagePreview {page} {thumbScale} />
46
+ </div>
47
+ </div>
48
+ </div>
@@ -0,0 +1,10 @@
1
+ import type { Page, PageTransition } from './types.js';
2
+ interface Props {
3
+ page: Page;
4
+ previousPage?: Page;
5
+ transition: PageTransition | null | undefined;
6
+ thumbScale: number;
7
+ }
8
+ declare const PageWithTransition: import("svelte").Component<Props, {}, "">;
9
+ type PageWithTransition = ReturnType<typeof PageWithTransition>;
10
+ export default PageWithTransition;
@@ -2,13 +2,13 @@
2
2
  import { BROWSER } from 'esm-env';
3
3
  import { onMount } from 'svelte';
4
4
  import type { PageOptions } from './types.js';
5
+ import { normalizePage } from './editor.svelte.js';
5
6
  import { extractNodeFonts } from './layers/types/text/editor/utils.js';
6
7
  import { defaultFonts } from './fonts.js';
7
- import PagePreview from './pages-navigation/page-preview.svelte';
8
+ import PagePreview from './page-preview.svelte';
8
9
 
9
10
  const {
10
- page,
11
- thumbScale = 1,
11
+ page: pageInput,
12
12
  fonts = defaultFonts,
13
13
  loadFont = async (family: string) => {
14
14
  const font = fonts[family];
@@ -22,10 +22,10 @@
22
22
  });
23
23
  });
24
24
  },
25
- class: className,
26
- ...restProps
27
25
  }: PageOptions = $props();
28
26
 
27
+ const page = normalizePage(pageInput);
28
+
29
29
  if (BROWSER) {
30
30
  const fontFamilies = page.layers
31
31
  .filter((layer) => layer.type === 'text')
@@ -35,17 +35,17 @@
35
35
 
36
36
  let element: HTMLDivElement | null = $state(null);
37
37
 
38
- let width = 1920 * thumbScale;
39
- let height = 1080 * thumbScale;
38
+ const width = 1920;
39
+ const height = 1080;
40
40
 
41
- let scale = $state(1);
41
+ let thumbScale = $state(1);
42
42
 
43
43
  onMount(() => {
44
44
  const observer = new ResizeObserver((entries) => {
45
45
  for (const entry of entries) {
46
46
  const scaleX = entry.contentRect.width / width;
47
47
  const scaleY = entry.contentRect.height / height;
48
- scale = Math.min(scaleX, scaleY); // preserve aspect ratio
48
+ thumbScale = Math.min(scaleX, scaleY); // preserve aspect ratio
49
49
  }
50
50
  });
51
51
 
@@ -55,15 +55,8 @@
55
55
  });
56
56
  </script>
57
57
 
58
- <div class={className} {...restProps}>
59
- <div bind:this={element} class="h-full w-full">
60
- <div
61
- class="relative origin-top-left"
62
- style:width="{width}px"
63
- style:height="{height}px"
64
- style:transform="scale({scale})"
65
- >
66
- <PagePreview {page} {thumbScale} />
67
- </div>
58
+ <div bind:this={element} class="grid h-full w-full place-items-center">
59
+ <div class="relative" style:width="{width * thumbScale}px" style:height="{height * thumbScale}px">
60
+ <PagePreview {page} {thumbScale} />
68
61
  </div>
69
62
  </div>
@@ -1,6 +1,7 @@
1
1
  <script lang="ts">
2
2
  import { dragHandle } from 'svelte-dnd-action';
3
3
  import PlusIcon from '@lucide/svelte/icons/plus';
4
+ import ArrowBigRightDashIcon from '@lucide/svelte/icons/arrow-big-right-dash';
4
5
  import EllipsisIcon from '@lucide/svelte/icons/ellipsis';
5
6
  import IconLocked from '@lucide/svelte/icons/lock-keyhole';
6
7
  import { Button, buttonVariants } from '../../ui/button/index.js';
@@ -9,8 +10,8 @@
9
10
  import { cn } from '../../../utils.js';
10
11
  import type { Editor } from '../editor.svelte.js';
11
12
  import type { Page } from '../types.js';
12
- import PagePreviewMenuContent from '../menu/page-menu-content.svelte';
13
- import PagePreview from './page-preview.svelte';
13
+ import PageMenuContent from '../menu/page-menu-content.svelte';
14
+ import PagePreview from '../page-preview.svelte';
14
15
 
15
16
  interface Props {
16
17
  editor: Editor;
@@ -24,27 +25,29 @@
24
25
  let menuOpen = $state(false);
25
26
  </script>
26
27
 
27
- <div class="relative flex items-center">
28
- <div class="group h-full">
29
- <div class="absolute -left-2 top-0 z-20 h-full w-4 group-hover:w-16"></div>
30
- <div
31
- class="relative z-30 flex h-full w-0 items-center justify-center transition-all duration-300 group-hover:w-6"
32
- >
28
+ <div class="relative flex items-stretch">
29
+ {#if index === 0}
30
+ <div class="group ml-2 py-2">
31
+ <div class="absolute -left-2 top-0 z-20 h-full w-4 group-hover:w-16"></div>
33
32
  <div
34
- class="absolute inline-flex flex-col opacity-0 transition-opacity duration-500 group-hover:opacity-100"
35
- role="menu"
33
+ class="relative z-30 flex h-full w-0 items-center justify-center transition-all duration-300 group-hover:w-6"
36
34
  >
37
- <Button
38
- variant="outline"
39
- size="icon-xs"
40
- class="my-1 h-6 w-6 rounded-full"
41
- onclick={() => editor.addPage({ index })}
35
+ <div
36
+ class="absolute inline-flex flex-col opacity-0 transition-opacity duration-500 group-hover:opacity-100"
37
+ role="menu"
42
38
  >
43
- <PlusIcon class="h-4 w-4" />
44
- </Button>
39
+ <Button
40
+ variant="outline"
41
+ size="icon-xs"
42
+ class="my-1 h-6 w-6 rounded-full"
43
+ onclick={() => editor.addPage({ index })}
44
+ >
45
+ <PlusIcon class="h-4 w-4" />
46
+ </Button>
47
+ </div>
45
48
  </div>
46
49
  </div>
47
- </div>
50
+ {/if}
48
51
  <div class="group relative mx-2 my-1 transition-transform">
49
52
  <div use:dragHandle role="none">
50
53
  <button class="block" onclick={() => editor.setActivePage(page.id)}>
@@ -73,7 +76,7 @@
73
76
  </div>
74
77
  </ContextMenu.Trigger>
75
78
  <ContextMenu.Content class="w-72">
76
- <PagePreviewMenuContent {editor} {page} />
79
+ <PageMenuContent {editor} {page} />
77
80
  </ContextMenu.Content>
78
81
  </ContextMenu.Root>
79
82
  </button>
@@ -115,9 +118,66 @@
115
118
  </DropdownMenu.Trigger>
116
119
 
117
120
  <DropdownMenu.Content class="w-72" side="top" align="start" trapFocus={false}>
118
- <PagePreviewMenuContent {editor} {page} />
121
+ <PageMenuContent {editor} {page} />
119
122
  </DropdownMenu.Content>
120
123
  </DropdownMenu.Root>
121
124
  </div>
122
125
  </div>
126
+ {#if index < editor.pages.length - 1}
127
+ <div class="group py-2">
128
+ <div class="absolute -right-2 top-0 z-20 h-full w-4 group-hover:w-16"></div>
129
+ <div
130
+ class="relative z-30 flex h-full w-0 items-center justify-center transition-all duration-300 group-hover:w-6"
131
+ >
132
+ <!-- {#if page.transition}
133
+ <div
134
+ class="absolute inline-flex flex-col opacity-100 transition-opacity duration-500 group-hover:opacity-0"
135
+ >
136
+ <Button
137
+ variant="outline"
138
+ size="icon-xs"
139
+ active={page.id === editor.activePage.id}
140
+ class="my-1 h-6 w-6 rounded-full"
141
+ onclick={() => editor.setActivePage(page.id)}
142
+ >
143
+ <ArrowBigRightDashIcon class="h-4 w-4" />
144
+ </Button>
145
+ </div>
146
+ {/if} -->
147
+ <div class="flex h-full flex-col items-center" role="menu">
148
+ <div
149
+ class="flex flex-1 items-center opacity-0 transition-all duration-500 group-hover:opacity-100"
150
+ >
151
+ <Button
152
+ variant="outline"
153
+ size="icon-xs"
154
+ class="h-6 w-6 rounded-full"
155
+ onclick={() => editor.addPage({ index: index + 1 })}
156
+ >
157
+ <PlusIcon class="h-4 w-4" />
158
+ </Button>
159
+ </div>
160
+ <div
161
+ class={cn(
162
+ 'flex flex-1 items-center transition-all group-hover:translate-y-0 group-hover:opacity-100',
163
+ page.transition ? '-translate-y-1/2 duration-300' : 'opacity-0 duration-500',
164
+ )}
165
+ >
166
+ <Button
167
+ variant="outline"
168
+ size="icon-xs"
169
+ class="h-6 w-6 rounded-full"
170
+ active={!!page.transition && page.id === editor.activePage.id}
171
+ onclick={() => {
172
+ editor.setActivePage(page.id);
173
+ editor.activeSidebarPopup = 'transition';
174
+ }}
175
+ >
176
+ <ArrowBigRightDashIcon class="h-4 w-4" />
177
+ </Button>
178
+ </div>
179
+ </div>
180
+ </div>
181
+ </div>
182
+ {/if}
123
183
  </div>
@@ -5,6 +5,7 @@
5
5
  import type { Editor } from '../editor.svelte.js';
6
6
  import type { Page } from '../types.js';
7
7
  import PagesNavigationItem from './pages-navigation-item.svelte';
8
+ import { Button } from '../../ui/button/index.js';
8
9
 
9
10
  interface Props {
10
11
  editor: Editor;
@@ -85,19 +86,21 @@
85
86
  {/each}
86
87
  </section>
87
88
  <div class="relative py-2" role="none">
88
- <button
89
- class="mx-2 my-1 rounded-xl"
89
+ <Button
90
+ variant="outline"
91
+ size="vague"
92
+ class="mx-2 my-1 rounded-lg"
90
93
  aria-label="New Page"
91
94
  onclick={() => editor.addPage({ index: editor.pages.length })}
92
95
  >
93
96
  <div
94
- class="relative flex items-center justify-center overflow-hidden rounded-lg bg-gray-400"
97
+ class="relative flex items-center justify-center"
95
98
  style:width="{editor.width * thumbScale}px"
96
99
  style:height="{editor.height * thumbScale}px"
97
100
  >
98
101
  <PlusIcon class="h-6 w-6" />
99
102
  </div>
100
- </button>
103
+ </Button>
101
104
  </div>
102
105
  </div>
103
106
  </nav>