@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.
- package/dist/components/editor/design.svelte +92 -0
- package/dist/components/editor/design.svelte.d.ts +8 -0
- package/dist/components/editor/editor.svelte +1 -1
- package/dist/components/editor/editor.svelte.js +14 -2
- package/dist/components/editor/header.svelte +1 -1
- package/dist/components/editor/index.d.ts +2 -1
- package/dist/components/editor/index.js +2 -1
- package/dist/components/editor/page-editor.svelte +7 -0
- package/dist/components/editor/{pages-navigation/page-preview.svelte → page-preview.svelte} +4 -4
- package/dist/components/editor/{pages-navigation/page-preview.svelte.d.ts → page-preview.svelte.d.ts} +2 -2
- package/dist/components/editor/page-transition-preview.svelte +34 -0
- package/dist/components/editor/page-transition-preview.svelte.d.ts +9 -0
- package/dist/components/editor/page-with-transition.svelte +48 -0
- package/dist/components/editor/page-with-transition.svelte.d.ts +10 -0
- package/dist/components/editor/page.svelte +12 -19
- package/dist/components/editor/pages-navigation/pages-navigation-item.svelte +80 -20
- package/dist/components/editor/pages-navigation/pages-navigation.svelte +7 -4
- package/dist/components/editor/sidebar/color-sidebar/color-sidebar.svelte +91 -81
- package/dist/components/editor/sidebar/color-sidebar/color-sidebar.svelte.d.ts +5 -1
- package/dist/components/editor/sidebar/font-sidebar/font-sidebar.svelte +9 -5
- package/dist/components/editor/sidebar/font-sidebar/font-sidebar.svelte.d.ts +5 -1
- package/dist/components/editor/sidebar/image-crop-sidebar.svelte +28 -37
- package/dist/components/editor/sidebar/image-crop-sidebar.svelte.d.ts +2 -0
- package/dist/components/editor/sidebar/position-sidebar/index.d.ts +2 -0
- package/dist/components/editor/sidebar/position-sidebar/index.js +2 -0
- package/dist/components/editor/sidebar/position-sidebar/position-sidebar.svelte +130 -0
- package/dist/components/editor/sidebar/position-sidebar/position-sidebar.svelte.d.ts +7 -0
- package/dist/components/editor/sidebar/sidebar-text-tab.svelte +7 -3
- package/dist/components/editor/sidebar/sidebar-text-tab.svelte.d.ts +5 -16
- package/dist/components/editor/sidebar/sidebar-uploads-tab.svelte +8 -6
- package/dist/components/editor/sidebar/sidebar-uploads-tab.svelte.d.ts +5 -1
- package/dist/components/editor/sidebar/sidebar-wrapper.svelte +4 -3
- package/dist/components/editor/sidebar/sidebar-wrapper.svelte.d.ts +1 -0
- package/dist/components/editor/sidebar/sidebar.svelte +20 -13
- package/dist/components/editor/sidebar/transition-sidebar/index.d.ts +2 -0
- package/dist/components/editor/sidebar/transition-sidebar/index.js +2 -0
- package/dist/components/editor/sidebar/transition-sidebar/transition-sidebar.svelte +257 -0
- package/dist/components/editor/sidebar/transition-sidebar/transition-sidebar.svelte.d.ts +7 -0
- package/dist/components/editor/types.d.ts +40 -6
- package/dist/components/editor/utils.d.ts +2 -2
- package/dist/components/editor/utils.js +21 -0
- package/dist/components/ui/button/button.svelte +2 -1
- package/dist/components/ui/button/button.svelte.d.ts +3 -0
- package/dist/transitions/circleWipe.d.ts +10 -0
- package/dist/transitions/circleWipe.js +16 -0
- package/dist/transitions/lineWipe.d.ts +9 -0
- package/dist/transitions/lineWipe.js +17 -0
- package/dist/transitions/stack.d.ts +8 -0
- package/dist/transitions/stack.js +13 -0
- package/package.json +1 -1
- package/dist/components/editor/layers/types/image/image-layer-active.svelte +0 -36
- package/dist/components/editor/layers/types/image/image-layer-active.svelte.d.ts +0 -7
- package/dist/components/editor/sidebar/position-sidebar.svelte +0 -136
- 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.
|
|
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
|
|
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
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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,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
|
-
|
|
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?:
|
|
298
|
+
pages?: PageInput[];
|
|
271
299
|
}
|
|
272
300
|
interface SingleModeOption extends BaseOptions {
|
|
273
301
|
mode: 'single';
|
|
274
|
-
page?:
|
|
302
|
+
page?: PageInput;
|
|
275
303
|
}
|
|
276
304
|
export type EditorOptions = MultipleModeOption | SingleModeOption;
|
|
277
|
-
export interface
|
|
278
|
-
|
|
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: () =>
|
|
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-
|
|
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,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;
|