@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
@@ -7,9 +7,10 @@
7
7
  import SidebarUploadsTab from './sidebar-uploads-tab.svelte';
8
8
  import type { Editor } from '../editor.svelte.js';
9
9
  import type { ActiveSidebarTab } from '../types.js';
10
- import PositionSidebar from './position-sidebar.svelte';
10
+ import { PositionSidebar } from './position-sidebar/index.js';
11
11
  import { ColorSidebar } from './color-sidebar/index.js';
12
12
  import { FontSidebar } from './font-sidebar/index.js';
13
+ import { TransitionSidebar } from './transition-sidebar/index.js';
13
14
  import ImageCropSidebar from './image-crop-sidebar.svelte';
14
15
 
15
16
  interface Props {
@@ -64,19 +65,25 @@
64
65
  </div>
65
66
 
66
67
  {#if editor.activeSidebarPopup || editor.activeSidebarTab || editor.imageCropLayer}
67
- <div class="h-full w-80 shrink-0 overflow-y-auto border-r border-gray-200 bg-background p-2">
68
+ <div class="h-full w-80 shrink-0 overflow-y-auto border-r border-gray-200">
68
69
  {#if editor.imageCropLayer}
69
- <ImageCropSidebar layer={editor.imageCropLayer} />
70
- {:else if editor.activeSidebarPopup === 'position'}
71
- <PositionSidebar />
72
- {:else if editor.activeSidebarPopup === 'font'}
73
- <FontSidebar />
74
- {:else if editor.activeSidebarPopup?.indexOf('Color')}
75
- <ColorSidebar />
76
- {:else if editor.activeSidebarTab === 'text'}
77
- <SidebarTextTab />
78
- {:else if editor.activeSidebarTab === 'uploads'}
79
- <SidebarUploadsTab />
70
+ <ImageCropSidebar {editor} layer={editor.imageCropLayer} />
71
+ {:else if editor.activeSidebarPopup}
72
+ {#if editor.activeSidebarPopup === 'position'}
73
+ <PositionSidebar {editor} />
74
+ {:else if editor.activeSidebarPopup === 'font'}
75
+ <FontSidebar {editor} />
76
+ {:else if editor.activeSidebarPopup.indexOf('Color') > 0}
77
+ <ColorSidebar {editor} />
78
+ {:else if editor.activeSidebarPopup === 'transition'}
79
+ <TransitionSidebar {editor} />
80
+ {/if}
81
+ {:else if editor.activeSidebarTab}
82
+ {#if editor.activeSidebarTab === 'text'}
83
+ <SidebarTextTab {editor} />
84
+ {:else if editor.activeSidebarTab === 'uploads'}
85
+ <SidebarUploadsTab {editor} />
86
+ {/if}
80
87
  {/if}
81
88
  </div>
82
89
  {/if}
@@ -0,0 +1,2 @@
1
+ import TransitionSidebar from './transition-sidebar.svelte';
2
+ export { TransitionSidebar };
@@ -0,0 +1,2 @@
1
+ import TransitionSidebar from './transition-sidebar.svelte';
2
+ export { TransitionSidebar };
@@ -0,0 +1,257 @@
1
+ <script lang="ts">
2
+ import XIcon from '@lucide/svelte/icons/x';
3
+ import Button from '../../../ui/button/button.svelte';
4
+ import type { Editor } from '../../editor.svelte.js';
5
+ import type {
6
+ HistoryAction,
7
+ PageTransition,
8
+ PageTransitionDirection,
9
+ PageTransitionFlow,
10
+ } from '../../types.js';
11
+ import SidebarWrapper from '../sidebar-wrapper.svelte';
12
+ import { Slider } from '../../../ui/slider/index.js';
13
+ import { Input } from '../../../ui/input/index.js';
14
+ import { createDebouncedCallback } from '../../../../utils.js';
15
+
16
+ interface Props {
17
+ editor: Editor;
18
+ }
19
+
20
+ const { editor }: Props = $props();
21
+
22
+ let duration = $derived(editor.activePage.transition?.duration || 500);
23
+
24
+ const setDuration = (value: string | number, debounce = false) => {
25
+ if (!editor.activePage.transition) return;
26
+
27
+ value = Number(value);
28
+ duration = value * 1000;
29
+
30
+ if (editor.activePage.transition) {
31
+ setTransition({ ...editor.activePage.transition, duration }, debounce);
32
+ }
33
+ };
34
+
35
+ const directions: PageTransitionDirection[] = ['left', 'right', 'up', 'down'];
36
+ const flows: PageTransitionFlow[] = ['in', 'out'];
37
+
38
+ const transitionButtons: { type: string; label: string; getState: () => PageTransition }[] = [
39
+ {
40
+ type: 'fade',
41
+ label: 'Fade',
42
+ getState: () => ({ type: 'fade', duration }),
43
+ },
44
+ {
45
+ type: 'slide',
46
+ label: 'Slide',
47
+ getState: () => ({ type: 'slide', duration, direction: 'left' }),
48
+ },
49
+ {
50
+ type: 'circleWipe',
51
+ label: 'Circle Wipe',
52
+ getState: () => ({ type: 'circleWipe', duration, flow: 'in' }),
53
+ },
54
+ {
55
+ type: 'lineWipe',
56
+ label: 'Line Wipe',
57
+ getState: () => ({ type: 'lineWipe', duration, direction: 'left' }),
58
+ },
59
+ {
60
+ type: 'stack',
61
+ label: 'Stack',
62
+ getState: () => ({ type: 'stack', duration, direction: 'down' }),
63
+ },
64
+ ];
65
+
66
+ let undo: object | null = null;
67
+
68
+ const debouncedUpdates = createDebouncedCallback((actions) => {
69
+ editor.historyPush(actions);
70
+ undo = null;
71
+ }, 500);
72
+
73
+ const setTransition = (value: PageTransition | null, debounce = false) => {
74
+ if (!undo) {
75
+ undo = { transition: $state.snapshot(editor.activePage.transition) };
76
+ }
77
+ const action: HistoryAction = {
78
+ type: 'pageUpdate',
79
+ pageId: editor.activePage.id,
80
+ undo,
81
+ redo: { transition: value },
82
+ };
83
+ if (debounce) {
84
+ debouncedUpdates(action);
85
+ } else {
86
+ editor.pageTransitionPreview = value;
87
+ editor.historyPush(action);
88
+ undo = null;
89
+ }
90
+ };
91
+
92
+ const allPagesHaveSameTransition = $derived.by(() => {
93
+ if (!editor.pages.length) return true;
94
+
95
+ const firstPageTransition = editor.pages[0].transition || {};
96
+ const firstPageTransitionKeys = Object.keys(firstPageTransition);
97
+ return editor.pages.every((page) => {
98
+ const transition = page.transition || {};
99
+
100
+ const keys = Object.keys(transition);
101
+ if (keys.length !== firstPageTransitionKeys.length) return false;
102
+
103
+ return keys.every(
104
+ (key) =>
105
+ key in firstPageTransition &&
106
+ (transition as Record<string, unknown>)[key] ===
107
+ (firstPageTransition as Record<string, unknown>)[key],
108
+ );
109
+ });
110
+ });
111
+
112
+ const setTransitionToAllPages = () => {
113
+ const redo = { transition: $state.snapshot(editor.activePage.transition) };
114
+ editor.historyPush(
115
+ editor.pages.map((page) => ({
116
+ type: 'pageUpdate',
117
+ pageId: page.id,
118
+ undo: { transition: $state.snapshot(page.transition) },
119
+ redo,
120
+ })),
121
+ );
122
+ };
123
+
124
+ // close sidebar if there is no next page
125
+ $effect(() => {
126
+ const nextPage = editor.sortedPages.find((p) => p.sortOrder > editor.activePage.sortOrder);
127
+ if (!nextPage) {
128
+ editor.activeSidebarPopup = null;
129
+ }
130
+ });
131
+ </script>
132
+
133
+ <SidebarWrapper name="Transition">
134
+ <div class="grid grid-cols-3 gap-2 p-2">
135
+ <Button
136
+ variant="outline"
137
+ size="vague"
138
+ class="aspect-square"
139
+ active={!editor.activePage.transition}
140
+ onclick={() => setTransition(null)}
141
+ >
142
+ <XIcon />
143
+ </Button>
144
+
145
+ {#each transitionButtons as button}
146
+ <Button
147
+ variant="outline"
148
+ size="vague"
149
+ class="aspect-square"
150
+ active={editor.activePage.transition?.type === button.type}
151
+ onclick={() => setTransition(button.getState())}
152
+ onmouseenter={() =>
153
+ (editor.pageTransitionPreview =
154
+ editor.activePage.transition?.type === button.type
155
+ ? editor.activePage.transition
156
+ : button.getState())}
157
+ onmouseleave={() => (editor.pageTransitionPreview = null)}
158
+ >
159
+ {button.label}
160
+ </Button>
161
+ {/each}
162
+
163
+ {#if editor.activePage.transition}
164
+ {@const transition = editor.activePage.transition}
165
+ {@const buttonIndex =
166
+ transitionButtons.findIndex((button) => button.type === transition.type) + 1}
167
+ {@const rowIndex = Math.floor(buttonIndex / 3) + 1}
168
+ {@const colIndex = Math.floor(buttonIndex % 3) + 1}
169
+ <div class="col-span-full" style:grid-row={rowIndex + 1}>
170
+ <div class="grid grid-cols-3 gap-2">
171
+ <div
172
+ class="h-0 w-0 justify-self-center border-b-border"
173
+ style:border-bottom-width="10px"
174
+ style:border-left="10px solid transparent"
175
+ style:border-right="10px solid transparent"
176
+ style:grid-column="{colIndex} / {colIndex + 1}"
177
+ ></div>
178
+ </div>
179
+ <div class="mb-4 rounded-md border border-border p-2">
180
+ <div class="py-2">
181
+ <div class="text-sm font-medium">Duration (seconds)</div>
182
+ <div class="flex items-center gap-2">
183
+ <div class="grow">
184
+ <Slider
185
+ type="single"
186
+ value={duration / 1000}
187
+ min={0.1}
188
+ max={2.5}
189
+ step={0.01}
190
+ onValueChange={(value) => setDuration(value, true)}
191
+ />
192
+ </div>
193
+ <Input
194
+ class="w-12 bg-transparent p-0 text-center font-semibold leading-none [&::-webkit-inner-spin-button]:appearance-none"
195
+ inputmode="decimal"
196
+ placeholder="--"
197
+ value={duration / 1000}
198
+ onchange={(e) => setDuration(e.currentTarget.value)}
199
+ />
200
+ </div>
201
+ </div>
202
+ {#if ['slide', 'lineWipe', 'circleWipe', 'stack'].includes(transition.type)}
203
+ <div class="flex flex-col gap-2 py-2">
204
+ <div class="text-sm font-medium">Direction</div>
205
+ <div class="grid grid-flow-col gap-2">
206
+ {#if transition.type === 'slide' || transition.type === 'lineWipe' || transition.type === 'stack'}
207
+ {#each directions as direction}
208
+ <Button
209
+ variant="outline"
210
+ active={transition.direction === direction}
211
+ onclick={() => {
212
+ setTransition({ ...transition, direction });
213
+ }}
214
+ onmouseenter={() => {
215
+ editor.pageTransitionPreview = { ...transition, direction };
216
+ }}
217
+ onmouseleave={() => {
218
+ editor.pageTransitionPreview = null;
219
+ }}
220
+ >
221
+ {direction}
222
+ </Button>
223
+ {/each}
224
+ {:else if transition.type === 'circleWipe'}
225
+ {#each flows as flow}
226
+ <Button
227
+ variant="outline"
228
+ active={transition.flow === flow}
229
+ onclick={() => {
230
+ setTransition({ ...transition, flow });
231
+ }}
232
+ onmouseenter={() => {
233
+ editor.pageTransitionPreview = { ...transition, flow };
234
+ }}
235
+ onmouseleave={() => {
236
+ editor.pageTransitionPreview = null;
237
+ }}
238
+ >
239
+ {flow}
240
+ </Button>
241
+ {/each}
242
+ {/if}
243
+ </div>
244
+ </div>
245
+ {/if}
246
+ </div>
247
+ </div>
248
+ {/if}
249
+ </div>
250
+ {#if !allPagesHaveSameTransition}
251
+ <div class="p-2">
252
+ <Button class="w-full" variant="outline" onclick={() => setTransitionToAllPages()}>
253
+ Apply between all pages
254
+ </Button>
255
+ </div>
256
+ {/if}
257
+ </SidebarWrapper>
@@ -0,0 +1,7 @@
1
+ import type { Editor } from '../../editor.svelte.js';
2
+ interface Props {
3
+ editor: Editor;
4
+ }
5
+ declare const TransitionSidebar: import("svelte").Component<Props, {}, "">;
6
+ type TransitionSidebar = ReturnType<typeof TransitionSidebar>;
7
+ export default TransitionSidebar;
@@ -1,8 +1,8 @@
1
1
  import { type JSONContent } from '@tiptap/core';
2
- import type { HTMLAttributes } from 'svelte/elements';
2
+ type OptionalKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
3
3
  export type ActiveSidebarTab = 'text' | 'uploads';
4
4
  type Colored = 'background' | 'text' | 'border';
5
- export type ActiveSidebarPopup = 'position' | 'font' | `${Colored}Color`;
5
+ export type ActiveSidebarPopup = 'position' | 'font' | `${Colored}Color` | 'transition';
6
6
  export type Fonts = {
7
7
  [key: string]: {
8
8
  type: string;
@@ -63,6 +63,32 @@ export type Gradient = {
63
63
  colors: string[];
64
64
  };
65
65
  export type BackgroundImage = Pick<ImageLayer, 'opacity' | 'scale' | 'image' | 'imageRotate' | 'offsetX' | 'offsetY' | 'flipX' | 'flipY'>;
66
+ interface BasePageTransition {
67
+ type: string;
68
+ duration: number;
69
+ }
70
+ export type PageTransitionDirection = 'left' | 'right' | 'up' | 'down';
71
+ export type PageTransitionFlow = 'in' | 'out';
72
+ export interface DirectionPageTransition extends BasePageTransition {
73
+ direction: PageTransitionDirection;
74
+ }
75
+ interface FadePageTransition extends BasePageTransition {
76
+ type: 'fade';
77
+ }
78
+ interface SlidePageTransition extends DirectionPageTransition {
79
+ type: 'slide';
80
+ }
81
+ export interface CircleWipePageTransition extends BasePageTransition {
82
+ type: 'circleWipe';
83
+ flow: PageTransitionFlow;
84
+ }
85
+ interface LineWipePageTransition extends DirectionPageTransition {
86
+ type: 'lineWipe';
87
+ }
88
+ interface StackPageTransition extends DirectionPageTransition {
89
+ type: 'stack';
90
+ }
91
+ export type PageTransition = FadePageTransition | SlidePageTransition | CircleWipePageTransition | LineWipePageTransition | StackPageTransition;
66
92
  export type Page = {
67
93
  id: string;
68
94
  backgroundColor: string | null;
@@ -71,7 +97,9 @@ export type Page = {
71
97
  layers: Layer[];
72
98
  sortOrder: number;
73
99
  locked: boolean;
100
+ transition: PageTransition | null;
74
101
  };
102
+ export type PageInput = OptionalKeys<Page, "transition">;
75
103
  export type ActiveAction = {
76
104
  id: string;
77
105
  type: string;
@@ -267,15 +295,21 @@ interface BaseOptions {
267
295
  }
268
296
  interface MultipleModeOption extends BaseOptions {
269
297
  mode?: 'multiple';
270
- pages?: Page[];
298
+ pages?: PageInput[];
271
299
  }
272
300
  interface SingleModeOption extends BaseOptions {
273
301
  mode: 'single';
274
- page?: Page;
302
+ page?: PageInput;
275
303
  }
276
304
  export type EditorOptions = MultipleModeOption | SingleModeOption;
277
- export interface PageOptions extends HTMLAttributes<HTMLDivElement> {
278
- page: Page;
305
+ export interface DesignOptions {
306
+ pages: PageInput[];
307
+ thumbScale?: number;
308
+ fonts?: Fonts;
309
+ loadFont?: (family: string) => Promise<void>;
310
+ }
311
+ export interface PageOptions {
312
+ page: PageInput;
279
313
  thumbScale?: number;
280
314
  fonts?: Fonts;
281
315
  loadFont?: (family: string) => Promise<void>;
@@ -1,9 +1,9 @@
1
- import type { Gradient, Page } from './types.js';
1
+ import type { Gradient, PageInput, Page } from './types.js';
2
2
  export declare const arraysEqual: (a: unknown[], b: unknown[]) => boolean;
3
3
  export declare const checkImage: (url: string) => Promise<HTMLImageElement>;
4
4
  export declare function gradientToString(gradient: Gradient): string;
5
5
  export declare function stringToGradient(value: string): Gradient;
6
- export declare const getPages: () => Page[];
6
+ export declare const getPages: () => PageInput[];
7
7
  export declare const buildParagraphHtml: ({ text, fontSize, lineHeight, textAlign, uppercase, bold, italic, }: {
8
8
  text: string;
9
9
  fontSize?: number;
@@ -426,6 +426,26 @@ const generateBackgroundColor = () => {
426
426
  return randomHexColor();
427
427
  }
428
428
  };
429
+ const generateTransition = () => {
430
+ const duration = Math.floor(Math.random() * 1000) + 1000;
431
+ const transitions = [
432
+ { type: 'fade', duration },
433
+ { type: 'slide', duration, direction: 'left' },
434
+ { type: 'circleWipe', duration, flow: 'in' },
435
+ { type: 'lineWipe', duration, direction: 'left' },
436
+ { type: 'stack', duration, direction: 'down' },
437
+ ];
438
+ const transition = transitions[Math.floor(Math.random() * transitions.length)];
439
+ if ('direction' in transition) {
440
+ const directions = ['left', 'right', 'up', 'down'];
441
+ transition.direction = directions[Math.floor(Math.random() * directions.length)];
442
+ }
443
+ if ('flow' in transition) {
444
+ const flows = ['in', 'out'];
445
+ transition.flow = flows[Math.floor(Math.random() * flows.length)];
446
+ }
447
+ return transition;
448
+ };
429
449
  export const cognitionPageToJson = (page) => {
430
450
  let sortOrder = 1;
431
451
  const layers = [];
@@ -474,5 +494,6 @@ export const cognitionPageToJson = (page) => {
474
494
  backgroundLocked: false,
475
495
  locked: false,
476
496
  layers,
497
+ transition: generateTransition(),
477
498
  };
478
499
  };
@@ -23,6 +23,7 @@
23
23
  lg: 'h-11 rounded-md px-8',
24
24
  icon: 'h-10 w-10',
25
25
  'icon-xs': 'h-8 w-8',
26
+ vague: '',
26
27
  },
27
28
  active: {
28
29
  true: '',
@@ -32,7 +33,7 @@
32
33
  {
33
34
  active: true,
34
35
  variant: 'outline',
35
- class: 'border-2 border-primary',
36
+ class: 'border-primary',
36
37
  },
37
38
  {
38
39
  active: true,
@@ -18,6 +18,7 @@ export declare const buttonVariants: import("tailwind-variants").TVReturnType<{
18
18
  lg: string;
19
19
  icon: string;
20
20
  'icon-xs': string;
21
+ vague: string;
21
22
  };
22
23
  active: {
23
24
  true: string;
@@ -39,6 +40,7 @@ export declare const buttonVariants: import("tailwind-variants").TVReturnType<{
39
40
  lg: string;
40
41
  icon: string;
41
42
  'icon-xs': string;
43
+ vague: string;
42
44
  };
43
45
  active: {
44
46
  true: string;
@@ -60,6 +62,7 @@ export declare const buttonVariants: import("tailwind-variants").TVReturnType<{
60
62
  lg: string;
61
63
  icon: string;
62
64
  'icon-xs': string;
65
+ vague: string;
63
66
  };
64
67
  active: {
65
68
  true: string;
@@ -0,0 +1,10 @@
1
+ import type { TransitionConfig } from 'svelte/transition';
2
+ export interface CircleWipeParams {
3
+ duration?: number;
4
+ easing?: (t: number) => number;
5
+ x?: string;
6
+ y?: string;
7
+ maxRadius?: number;
8
+ direction?: 'in' | 'out';
9
+ }
10
+ export declare function circleWipe(_node: HTMLElement, { duration, easing, x, y, maxRadius, direction, }?: CircleWipeParams): TransitionConfig;
@@ -0,0 +1,16 @@
1
+ export function circleWipe(_node, { duration = 600, easing = (t) => t, x = '50%', y = '50%', maxRadius = 100, direction = 'in', } = {}) {
2
+ return {
3
+ duration,
4
+ easing,
5
+ css: (t, u) => {
6
+ const r = (direction === 'in' ? u : t) * maxRadius;
7
+ const innerColor = direction === 'in' ? 'rgba(0,0,0,1)' : 'rgba(0,0,0,0)';
8
+ const outerColor = direction === 'in' ? 'rgba(0,0,0,0)' : 'rgba(0,0,0,1)';
9
+ const mask = `radial-gradient(circle at ${x} ${y}, ${outerColor} ${r}%, ${innerColor} ${r}%)`;
10
+ return `
11
+ mask: ${mask};
12
+ -webkit-mask: ${mask};
13
+ `;
14
+ },
15
+ };
16
+ }
@@ -0,0 +1,9 @@
1
+ import type { TransitionConfig } from 'svelte/transition';
2
+ export interface LineWipeParams {
3
+ duration?: number;
4
+ easing?: (t: number) => number;
5
+ x?: string;
6
+ y?: string;
7
+ direction?: 'left' | 'right' | 'up' | 'down';
8
+ }
9
+ export declare function lineWipe(_node: HTMLElement, { duration, easing, direction }?: LineWipeParams): TransitionConfig;
@@ -0,0 +1,17 @@
1
+ export function lineWipe(_node, { duration = 600, easing = (t) => t, direction = 'left' } = {}) {
2
+ return {
3
+ duration,
4
+ easing,
5
+ css: (t) => {
6
+ const offset = t * 100;
7
+ const angle = { left: 270, up: 0, right: 90, down: 180 }[direction];
8
+ const startColor = 'rgba(0,0,0,1)';
9
+ const endColor = 'rgba(0,0,0,0)';
10
+ const mask = `linear-gradient(${angle}deg, ${startColor} ${offset}%, ${endColor} ${offset}%)`;
11
+ return `
12
+ mask: ${mask};
13
+ -webkit-mask: ${mask};
14
+ `;
15
+ },
16
+ };
17
+ }
@@ -0,0 +1,8 @@
1
+ import type { TransitionConfig } from 'svelte/transition';
2
+ export interface StackParams {
3
+ duration?: number;
4
+ easing?: (t: number) => number;
5
+ direction?: 'left' | 'right' | 'up' | 'down';
6
+ reverse?: boolean;
7
+ }
8
+ export declare function stack(_node: HTMLElement, { duration, easing, direction, reverse }?: StackParams): TransitionConfig;
@@ -0,0 +1,13 @@
1
+ export function stack(_node, { duration = 600, easing = (t) => t, direction = 'left', reverse = false } = {}) {
2
+ return {
3
+ duration,
4
+ easing,
5
+ css: (t, u) => {
6
+ const offset = (direction === 'left' || direction === 'up' ? 1 : -1) * (reverse ? -t : u);
7
+ const axis = direction === 'left' || direction === 'right' ? 'X' : 'Y';
8
+ return `
9
+ transform: translate${axis}(${offset * 100}%);
10
+ `;
11
+ },
12
+ };
13
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peteai/presentation-editor",
3
- "version": "0.0.9",
3
+ "version": "0.0.10",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build && npm run package",
@@ -1,36 +0,0 @@
1
- <script lang="ts">
2
- import type { ImageLayer } from '../../../types.js';
3
- import { SideResizeControl } from '../../controls/side-resize-control/index.js';
4
- import { CornerScaleControl } from '../../controls/corner-scale-control/index.js';
5
- import { RotateControl } from '../../controls/rotate-control/index.js';
6
- import { getEditorContext } from '../../../editor.svelte.js';
7
-
8
- interface Props {
9
- layer: ImageLayer;
10
- }
11
-
12
- let { layer = $bindable() }: Props = $props();
13
-
14
- const editor = getEditorContext();
15
- </script>
16
-
17
- <div
18
- class="pointer-events-none absolute left-0 top-0 h-full w-full"
19
- style:width={`${layer.width * layer.scale * editor.zoom}px`}
20
- style:height={`${layer.height * layer.scale * editor.zoom}px`}
21
- style:transform={`translate(${layer.x * editor.zoom}px, ${layer.y * editor.zoom}px) rotate(${layer.rotate}deg)`}
22
- >
23
- <div class="h-full w-full outline-none transition-opacity duration-300">
24
- <div class="flex h-full w-full items-center justify-center">
25
- <SideResizeControl origin="left" bind:layer />
26
- <SideResizeControl origin="right" bind:layer />
27
- <SideResizeControl origin="top" bind:layer />
28
- <SideResizeControl origin="bottom" bind:layer />
29
- <CornerScaleControl origin="bottom-right" />
30
- <CornerScaleControl origin="bottom-left" />
31
- <CornerScaleControl origin="top-right" />
32
- <CornerScaleControl origin="top-left" />
33
- <RotateControl />
34
- </div>
35
- </div>
36
- </div>
@@ -1,7 +0,0 @@
1
- import type { ImageLayer } from '../../../types.js';
2
- interface Props {
3
- layer: ImageLayer;
4
- }
5
- declare const ImageLayerActive: import("svelte").Component<Props, {}, "layer">;
6
- type ImageLayerActive = ReturnType<typeof ImageLayerActive>;
7
- export default ImageLayerActive;