@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
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import PlusIcon from '@lucide/svelte/icons/plus';
|
|
3
|
-
|
|
3
|
+
import PaletteIcon from '@lucide/svelte/icons/palette';
|
|
4
4
|
import { ColorPicker } from '../../../ui/color-picker/index.js';
|
|
5
5
|
import * as Popover from '../../../ui/popover/index.js';
|
|
6
6
|
import * as Tabs from '../../../ui/tabs/index.js';
|
|
7
7
|
import { cn, createDebouncedCallback } from '../../../../utils.js';
|
|
8
|
-
import {
|
|
9
|
-
import type { HistoryAction, Gradient, ImageLayer, TextLayer, Layer
|
|
8
|
+
import type { Editor } from '../../editor.svelte.js';
|
|
9
|
+
import type { HistoryAction, Gradient, ImageLayer, TextLayer, Layer } from '../../types.js';
|
|
10
10
|
import SidebarWrapper from '../sidebar-wrapper.svelte';
|
|
11
11
|
import ColorSidebarGradientPicker from './color-sidebar-gradient-picker.svelte';
|
|
12
12
|
import ColorSidebarColor from './color-sidebar-color.svelte';
|
|
@@ -20,7 +20,11 @@
|
|
|
20
20
|
|
|
21
21
|
let open = $state(false);
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
interface Props {
|
|
24
|
+
editor: Editor;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const { editor }: Props = $props();
|
|
24
28
|
|
|
25
29
|
const { htmlEditor } = editor;
|
|
26
30
|
|
|
@@ -311,91 +315,82 @@
|
|
|
311
315
|
</script>
|
|
312
316
|
|
|
313
317
|
<SidebarWrapper name="Color">
|
|
314
|
-
<div
|
|
315
|
-
<
|
|
316
|
-
|
|
317
|
-
<div class="grid grid-cols-6 items-stretch gap-1">
|
|
318
|
-
<div class="relative h-0 w-full" style:padding-top="100%">
|
|
319
|
-
<div class="absolute left-0 top-0 h-full w-full">
|
|
320
|
-
<Popover.Root bind:open>
|
|
321
|
-
<Popover.Trigger
|
|
322
|
-
class={cn(
|
|
323
|
-
'relative h-full w-full overflow-hidden rounded-full after:absolute after:inset-0 after:rounded-full after:transition-shadow',
|
|
324
|
-
open ? 'after:shadow-active' : 'hover:after:shadow-hover',
|
|
325
|
-
)}
|
|
326
|
-
>
|
|
327
|
-
<div
|
|
328
|
-
class="relative h-full w-full after:absolute after:inset-0 after:rounded-full after:shadow-inner-1"
|
|
329
|
-
>
|
|
330
|
-
<div
|
|
331
|
-
class="h-full w-full rounded-full"
|
|
332
|
-
style:background={`conic-gradient(red, orange, yellow, green, blue, indigo, violet, red)`}
|
|
333
|
-
></div>
|
|
334
|
-
<span class="absolute inset-0 flex h-full w-full items-center justify-center">
|
|
335
|
-
<span
|
|
336
|
-
class="flex h-6 w-6 items-center justify-center rounded-full bg-background text-foreground"
|
|
337
|
-
>
|
|
338
|
-
<PlusIcon />
|
|
339
|
-
</span>
|
|
340
|
-
</span>
|
|
341
|
-
</div>
|
|
342
|
-
</Popover.Trigger>
|
|
343
|
-
<Popover.Content align="start" sideOffset={2} class="w-80 p-4">
|
|
344
|
-
{#if gradientsAllowed}
|
|
345
|
-
<Tabs.Root
|
|
346
|
-
value={isGradient(currentColor) ? 'gradient' : 'solid'}
|
|
347
|
-
class="w-full"
|
|
348
|
-
onValueChange={switchType}
|
|
349
|
-
>
|
|
350
|
-
<Tabs.List class="grid w-full grid-cols-2">
|
|
351
|
-
<Tabs.Trigger value="solid">Solid color</Tabs.Trigger>
|
|
352
|
-
<Tabs.Trigger value="gradient">Gradient</Tabs.Trigger>
|
|
353
|
-
</Tabs.List>
|
|
354
|
-
<Tabs.Content value="solid">
|
|
355
|
-
{#if !isGradient(currentColor)}
|
|
356
|
-
<ColorPicker hex={currentColor} onChange={({ hex }) => setColor(hex, true)} />
|
|
357
|
-
{/if}
|
|
358
|
-
</Tabs.Content>
|
|
359
|
-
<Tabs.Content value="gradient">
|
|
360
|
-
{#if isGradient(currentColor)}
|
|
361
|
-
<ColorSidebarGradientPicker color={currentColor} {setColor} />
|
|
362
|
-
{/if}
|
|
363
|
-
</Tabs.Content>
|
|
364
|
-
</Tabs.Root>
|
|
365
|
-
{:else}
|
|
366
|
-
<ColorPicker hex={currentColor} onChange={({ hex }) => setColor(hex, true)} />
|
|
367
|
-
{/if}
|
|
368
|
-
</Popover.Content>
|
|
369
|
-
</Popover.Root>
|
|
370
|
-
</div>
|
|
318
|
+
<div>
|
|
319
|
+
<div class="flex items-center gap-2 p-2">
|
|
320
|
+
<h5 class="text-left text-sm font-bold">Document colors</h5>
|
|
371
321
|
</div>
|
|
372
|
-
|
|
322
|
+
<div class="grid grid-cols-6 items-stretch gap-1 p-2">
|
|
373
323
|
<div class="relative h-0 w-full" style:padding-top="100%">
|
|
374
324
|
<div class="absolute left-0 top-0 h-full w-full">
|
|
375
|
-
<
|
|
325
|
+
<Popover.Root bind:open>
|
|
326
|
+
<Popover.Trigger
|
|
327
|
+
class={cn(
|
|
328
|
+
'relative h-full w-full overflow-hidden rounded-full after:absolute after:inset-0 after:rounded-full after:transition-shadow',
|
|
329
|
+
open ? 'after:shadow-active' : 'hover:after:shadow-hover',
|
|
330
|
+
)}
|
|
331
|
+
>
|
|
332
|
+
<div
|
|
333
|
+
class="relative h-full w-full after:absolute after:inset-0 after:rounded-full after:shadow-inner-1"
|
|
334
|
+
>
|
|
335
|
+
<div
|
|
336
|
+
class="h-full w-full rounded-full"
|
|
337
|
+
style:background={`conic-gradient(red, orange, yellow, green, blue, indigo, violet, red)`}
|
|
338
|
+
></div>
|
|
339
|
+
<span class="absolute inset-0 flex h-full w-full items-center justify-center">
|
|
340
|
+
<span
|
|
341
|
+
class="flex h-6 w-6 items-center justify-center rounded-full bg-background text-foreground"
|
|
342
|
+
>
|
|
343
|
+
<PlusIcon />
|
|
344
|
+
</span>
|
|
345
|
+
</span>
|
|
346
|
+
</div>
|
|
347
|
+
</Popover.Trigger>
|
|
348
|
+
<Popover.Content align="start" sideOffset={2} class="w-80 p-4">
|
|
349
|
+
{#if gradientsAllowed}
|
|
350
|
+
<Tabs.Root
|
|
351
|
+
value={isGradient(currentColor) ? 'gradient' : 'solid'}
|
|
352
|
+
class="w-full"
|
|
353
|
+
onValueChange={switchType}
|
|
354
|
+
>
|
|
355
|
+
<Tabs.List class="grid w-full grid-cols-2">
|
|
356
|
+
<Tabs.Trigger value="solid">Solid color</Tabs.Trigger>
|
|
357
|
+
<Tabs.Trigger value="gradient">Gradient</Tabs.Trigger>
|
|
358
|
+
</Tabs.List>
|
|
359
|
+
<Tabs.Content value="solid">
|
|
360
|
+
{#if !isGradient(currentColor)}
|
|
361
|
+
<ColorPicker hex={currentColor} onChange={({ hex }) => setColor(hex, true)} />
|
|
362
|
+
{/if}
|
|
363
|
+
</Tabs.Content>
|
|
364
|
+
<Tabs.Content value="gradient">
|
|
365
|
+
{#if isGradient(currentColor)}
|
|
366
|
+
<ColorSidebarGradientPicker color={currentColor} {setColor} />
|
|
367
|
+
{/if}
|
|
368
|
+
</Tabs.Content>
|
|
369
|
+
</Tabs.Root>
|
|
370
|
+
{:else}
|
|
371
|
+
<ColorPicker hex={currentColor} onChange={({ hex }) => setColor(hex, true)} />
|
|
372
|
+
{/if}
|
|
373
|
+
</Popover.Content>
|
|
374
|
+
</Popover.Root>
|
|
376
375
|
</div>
|
|
377
376
|
</div>
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
</div>
|
|
384
|
-
<div class="text-xs text-muted-foreground">Solid colors</div>
|
|
385
|
-
<div class="grid grid-cols-6 items-stretch gap-1">
|
|
386
|
-
{#each Object.keys(defaultSolidColors) as color}
|
|
387
|
-
<div class="relative h-0 w-full" style:padding-top="100%">
|
|
388
|
-
<div class="absolute left-0 top-0 h-full w-full">
|
|
389
|
-
<ColorSidebarColor {color} {currentColor} onclick={() => setColor(color)} />
|
|
377
|
+
{#each documentColors as color}
|
|
378
|
+
<div class="relative h-0 w-full" style:padding-top="100%">
|
|
379
|
+
<div class="absolute left-0 top-0 h-full w-full">
|
|
380
|
+
<ColorSidebarColor {color} {currentColor} onclick={() => setColor(color)} />
|
|
381
|
+
</div>
|
|
390
382
|
</div>
|
|
391
|
-
|
|
392
|
-
|
|
383
|
+
{/each}
|
|
384
|
+
</div>
|
|
393
385
|
</div>
|
|
394
386
|
|
|
395
|
-
|
|
396
|
-
<div class="
|
|
397
|
-
|
|
398
|
-
|
|
387
|
+
<div>
|
|
388
|
+
<div class="flex items-center gap-2 p-2">
|
|
389
|
+
<PaletteIcon class="h-5 w-5" />
|
|
390
|
+
<h5 class="text-left text-sm font-bold">Default solid colors</h5>
|
|
391
|
+
</div>
|
|
392
|
+
<div class="grid grid-cols-6 items-stretch gap-1 p-2">
|
|
393
|
+
{#each Object.keys(defaultSolidColors) as color}
|
|
399
394
|
<div class="relative h-0 w-full" style:padding-top="100%">
|
|
400
395
|
<div class="absolute left-0 top-0 h-full w-full">
|
|
401
396
|
<ColorSidebarColor {color} {currentColor} onclick={() => setColor(color)} />
|
|
@@ -403,5 +398,20 @@
|
|
|
403
398
|
</div>
|
|
404
399
|
{/each}
|
|
405
400
|
</div>
|
|
401
|
+
</div>
|
|
402
|
+
|
|
403
|
+
{#if gradientsAllowed}
|
|
404
|
+
<div>
|
|
405
|
+
<div class="text-xs text-muted-foreground">Gradients</div>
|
|
406
|
+
<div class="grid grid-cols-6 items-stretch gap-1">
|
|
407
|
+
{#each defaultGradients as color}
|
|
408
|
+
<div class="relative h-0 w-full" style:padding-top="100%">
|
|
409
|
+
<div class="absolute left-0 top-0 h-full w-full">
|
|
410
|
+
<ColorSidebarColor {color} {currentColor} onclick={() => setColor(color)} />
|
|
411
|
+
</div>
|
|
412
|
+
</div>
|
|
413
|
+
{/each}
|
|
414
|
+
</div>
|
|
415
|
+
</div>
|
|
406
416
|
{/if}
|
|
407
417
|
</SidebarWrapper>
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import type { Editor } from '../../editor.svelte.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
editor: Editor;
|
|
4
|
+
}
|
|
5
|
+
declare const ColorSidebar: import("svelte").Component<Props, {}, "">;
|
|
2
6
|
type ColorSidebar = ReturnType<typeof ColorSidebar>;
|
|
3
7
|
export default ColorSidebar;
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { Button } from '../../../ui/button/index.js';
|
|
9
9
|
import { Separator } from '../../../ui/separator/index.js';
|
|
10
10
|
import { cn } from '../../../../utils.js';
|
|
11
|
-
import {
|
|
11
|
+
import type { Editor } from '../../editor.svelte.js';
|
|
12
12
|
import SidebarWrapper from '../sidebar-wrapper.svelte';
|
|
13
13
|
import {
|
|
14
14
|
createEditorNotReactive,
|
|
@@ -17,7 +17,11 @@
|
|
|
17
17
|
} from '../../layers/types/text/editor/utils.js';
|
|
18
18
|
import FontSidebarButton from './font-sidebar-button.svelte';
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
interface Props {
|
|
21
|
+
editor: Editor;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const { editor }: Props = $props();
|
|
21
25
|
|
|
22
26
|
let { htmlEditor } = editor;
|
|
23
27
|
|
|
@@ -133,7 +137,7 @@
|
|
|
133
137
|
</script>
|
|
134
138
|
|
|
135
139
|
<SidebarWrapper name="Font">
|
|
136
|
-
<div class="relative flex items-center">
|
|
140
|
+
<div class="relative flex items-center p-2">
|
|
137
141
|
<div class="pointer-events-none absolute flex w-10 items-center justify-center">
|
|
138
142
|
{#if search}
|
|
139
143
|
<Button variant="ghost" size="icon-xs" class="pointer-events-auto" onclick={cancelSearch}>
|
|
@@ -150,7 +154,7 @@
|
|
|
150
154
|
oninput={() => (searchedPagesLoaded = 1)}
|
|
151
155
|
/>
|
|
152
156
|
</div>
|
|
153
|
-
<div class={cn('flex-1 overflow-y-auto', search && 'hidden')}>
|
|
157
|
+
<div class={cn('flex-1 overflow-y-auto p-2', search && 'hidden')}>
|
|
154
158
|
<div class="flex items-center gap-2 py-2">
|
|
155
159
|
<DocumentIcon class="h-6 w-6" />
|
|
156
160
|
<h5 class="text-left text-sm font-bold">Document fonts</h5>
|
|
@@ -184,7 +188,7 @@
|
|
|
184
188
|
</div>
|
|
185
189
|
|
|
186
190
|
{#if search}
|
|
187
|
-
<div class="flex-1 overflow-y-auto">
|
|
191
|
+
<div class="flex-1 overflow-y-auto p-2">
|
|
188
192
|
{#if searchedFonts.length}
|
|
189
193
|
<div class="flex items-center gap-2 py-2">
|
|
190
194
|
<h5 class="text-left text-sm font-bold">All results</h5>
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import type { Editor } from '../../editor.svelte.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
editor: Editor;
|
|
4
|
+
}
|
|
5
|
+
declare const FontSidebar: import("svelte").Component<Props, {}, "">;
|
|
2
6
|
type FontSidebar = ReturnType<typeof FontSidebar>;
|
|
3
7
|
export default FontSidebar;
|
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import XIcon from '@lucide/svelte/icons/x';
|
|
3
2
|
import { Button } from '../../ui/button/index.js';
|
|
4
3
|
import { Slider } from '../../ui/slider/index.js';
|
|
5
4
|
import { Input } from '../../ui/input/index.js';
|
|
6
|
-
import {
|
|
5
|
+
import type { Editor } from '../editor.svelte.js';
|
|
7
6
|
import {
|
|
8
7
|
calculateImageLayerPropsForImageRotate,
|
|
9
8
|
calculateRelativeRects,
|
|
10
9
|
} from '../layers/utils.js';
|
|
11
10
|
import type { ImageLayer } from '../types.js';
|
|
11
|
+
import SidebarWrapper from './sidebar-wrapper.svelte';
|
|
12
12
|
|
|
13
13
|
interface Props {
|
|
14
|
+
editor: Editor;
|
|
14
15
|
layer: ImageLayer;
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
let { layer }: Props = $props();
|
|
18
|
-
|
|
19
|
-
const editor = $derived(getEditorContext());
|
|
18
|
+
let { editor, layer }: Props = $props();
|
|
20
19
|
|
|
21
20
|
let value = $derived(Math.round(layer.imageRotate * 10) / 10);
|
|
22
21
|
let originalLayer = $derived(
|
|
@@ -74,39 +73,31 @@
|
|
|
74
73
|
});
|
|
75
74
|
</script>
|
|
76
75
|
|
|
77
|
-
<
|
|
78
|
-
<div class="flex items-center
|
|
79
|
-
<div class="
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
</Button>
|
|
83
|
-
</div>
|
|
84
|
-
<div class="flex-1 resize-none overflow-y-auto">
|
|
85
|
-
<div class="flex items-center gap-2">
|
|
86
|
-
<div class="grow">
|
|
87
|
-
<Slider
|
|
88
|
-
type="single"
|
|
89
|
-
{value}
|
|
90
|
-
{min}
|
|
91
|
-
{max}
|
|
92
|
-
{step}
|
|
93
|
-
onValueChange={(value) => setImageRotate(value)}
|
|
94
|
-
onValueCommit={() => (layerCache = null)}
|
|
95
|
-
/>
|
|
96
|
-
</div>
|
|
97
|
-
<Input
|
|
98
|
-
class="w-12 bg-transparent p-0 text-center font-semibold leading-none [&::-webkit-inner-spin-button]:appearance-none"
|
|
99
|
-
inputmode="decimal"
|
|
100
|
-
placeholder="--"
|
|
76
|
+
<SidebarWrapper name="Crop" onclose={() => (editor.imageCropLayer = null)}>
|
|
77
|
+
<div class="flex items-center gap-2 p-2">
|
|
78
|
+
<div class="grow">
|
|
79
|
+
<Slider
|
|
80
|
+
type="single"
|
|
101
81
|
{value}
|
|
102
|
-
|
|
82
|
+
{min}
|
|
83
|
+
{max}
|
|
84
|
+
{step}
|
|
85
|
+
onValueChange={(value) => setImageRotate(value)}
|
|
86
|
+
onValueCommit={() => (layerCache = null)}
|
|
103
87
|
/>
|
|
104
88
|
</div>
|
|
105
|
-
<
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
89
|
+
<Input
|
|
90
|
+
class="w-12 bg-transparent p-0 text-center font-semibold leading-none [&::-webkit-inner-spin-button]:appearance-none"
|
|
91
|
+
inputmode="decimal"
|
|
92
|
+
placeholder="--"
|
|
93
|
+
{value}
|
|
94
|
+
onchange={(e) => setImageRotate(e.currentTarget.value)}
|
|
95
|
+
/>
|
|
96
|
+
</div>
|
|
97
|
+
<div class="flex justify-end gap-2 p-2">
|
|
98
|
+
<Button class="flex-1" variant="outline" onclick={() => (editor.imageCropLayer = null)}>
|
|
99
|
+
Cancel
|
|
100
|
+
</Button>
|
|
101
|
+
<Button class="flex-1" onclick={applyChanges}>Done</Button>
|
|
111
102
|
</div>
|
|
112
|
-
</
|
|
103
|
+
</SidebarWrapper>
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { flip } from 'svelte/animate';
|
|
3
|
+
import { dndzone, type DndEvent } from 'svelte-dnd-action';
|
|
4
|
+
import * as ContextMenu from '../../../ui/context-menu/index.js';
|
|
5
|
+
import {
|
|
6
|
+
LayerButton,
|
|
7
|
+
LayerThumbWrapper,
|
|
8
|
+
TextLayerContent,
|
|
9
|
+
ImageLayerContent,
|
|
10
|
+
BackgroundLayerContent,
|
|
11
|
+
GroupLayerContent,
|
|
12
|
+
} from '../../layers/index.js';
|
|
13
|
+
import type { Editor } from '../../editor.svelte.js';
|
|
14
|
+
import LayerMenuContent from '../../menu/layer-menu-content.svelte';
|
|
15
|
+
import BackgroundMenuContent from '../../menu/background-menu-content.svelte';
|
|
16
|
+
import type { Layer } from '../../types.js';
|
|
17
|
+
import SidebarWrapper from '../sidebar-wrapper.svelte';
|
|
18
|
+
|
|
19
|
+
interface Props {
|
|
20
|
+
editor: Editor;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const { editor }: Props = $props();
|
|
24
|
+
|
|
25
|
+
const flipDurationMs = 300;
|
|
26
|
+
const otherOptions = { flipDurationMs, type: 'layers', dropTargetStyle: {} };
|
|
27
|
+
|
|
28
|
+
function handleDndConsider(e: CustomEvent<DndEvent<Layer>>) {
|
|
29
|
+
editor.rootLayers = e.detail.items;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async function handleDndFinalize(e: CustomEvent<DndEvent<Layer>>) {
|
|
33
|
+
console.log('handleDndFinalize', e);
|
|
34
|
+
|
|
35
|
+
editor.rootLayers = e.detail.items;
|
|
36
|
+
|
|
37
|
+
const index = e.detail.items.findIndex((item) => item.id === e.detail.info.id);
|
|
38
|
+
const item = e.detail.items[index];
|
|
39
|
+
|
|
40
|
+
let redo;
|
|
41
|
+
const prev = e.detail.items[index - 1];
|
|
42
|
+
const next = e.detail.items[index + 1];
|
|
43
|
+
if (prev && next) {
|
|
44
|
+
if (!(prev.sortOrder < item.sortOrder && next.sortOrder > item.sortOrder)) {
|
|
45
|
+
redo = { sortOrder: (prev.sortOrder + next.sortOrder) / 2 };
|
|
46
|
+
}
|
|
47
|
+
} else if (next) {
|
|
48
|
+
if (next && next.sortOrder <= item.sortOrder) {
|
|
49
|
+
redo = { sortOrder: next.sortOrder - 1 };
|
|
50
|
+
}
|
|
51
|
+
} else if (prev) {
|
|
52
|
+
if (prev && prev.sortOrder >= item.sortOrder) {
|
|
53
|
+
redo = { sortOrder: prev.sortOrder + 1 };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (redo) {
|
|
58
|
+
editor.historyPush({
|
|
59
|
+
type: 'layerUpdate',
|
|
60
|
+
pageId: editor.activePage.id,
|
|
61
|
+
layer: { id: item.id, type: item.type },
|
|
62
|
+
undo: { sortOrder: item.sortOrder },
|
|
63
|
+
redo,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
</script>
|
|
68
|
+
|
|
69
|
+
<SidebarWrapper name="Position">
|
|
70
|
+
<div class="flex flex-col gap-2 p-2">
|
|
71
|
+
<section
|
|
72
|
+
class="flex flex-col-reverse gap-2"
|
|
73
|
+
aria-label="Layers"
|
|
74
|
+
use:dndzone={{
|
|
75
|
+
items: editor.rootLayers,
|
|
76
|
+
dragDisabled: editor.activePage.locked,
|
|
77
|
+
...otherOptions,
|
|
78
|
+
}}
|
|
79
|
+
onconsider={handleDndConsider}
|
|
80
|
+
onfinalize={handleDndFinalize}
|
|
81
|
+
>
|
|
82
|
+
{#each editor.rootLayers as layer (layer.id)}
|
|
83
|
+
<div aria-label={layer.type} animate:flip={{ duration: flipDurationMs }}>
|
|
84
|
+
<ContextMenu.Root
|
|
85
|
+
onOpenChange={(open) =>
|
|
86
|
+
open &&
|
|
87
|
+
!editor.activeLayers.find((l) => l.id === layer.id) &&
|
|
88
|
+
editor.setActiveLayers(layer.id)}
|
|
89
|
+
>
|
|
90
|
+
<ContextMenu.Trigger>
|
|
91
|
+
<LayerButton {layer}>
|
|
92
|
+
<LayerThumbWrapper {layer} thumb={{ width: 192, height: 32 }}>
|
|
93
|
+
{#snippet children({ thumbScale })}
|
|
94
|
+
{#if layer.type === 'text'}
|
|
95
|
+
<TextLayerContent {layer} {thumbScale} />
|
|
96
|
+
{:else if layer.type === 'image'}
|
|
97
|
+
<ImageLayerContent {layer} {thumbScale} />
|
|
98
|
+
{:else if layer.type === 'group'}
|
|
99
|
+
<GroupLayerContent page={editor.activePage} {layer} {thumbScale} />
|
|
100
|
+
{/if}
|
|
101
|
+
{/snippet}
|
|
102
|
+
</LayerThumbWrapper>
|
|
103
|
+
</LayerButton>
|
|
104
|
+
</ContextMenu.Trigger>
|
|
105
|
+
<ContextMenu.Content class="w-72">
|
|
106
|
+
<LayerMenuContent />
|
|
107
|
+
</ContextMenu.Content>
|
|
108
|
+
</ContextMenu.Root>
|
|
109
|
+
</div>
|
|
110
|
+
{/each}
|
|
111
|
+
</section>
|
|
112
|
+
<ContextMenu.Root>
|
|
113
|
+
<ContextMenu.Trigger>
|
|
114
|
+
<LayerButton>
|
|
115
|
+
{@const thumbScale = Math.max(192 / editor.width, 32 / editor.height)}
|
|
116
|
+
<div
|
|
117
|
+
class="absolute top-1/2 -translate-y-1/2"
|
|
118
|
+
style:width="{editor.width * thumbScale}px"
|
|
119
|
+
style:height="{editor.height * thumbScale}px"
|
|
120
|
+
>
|
|
121
|
+
<BackgroundLayerContent page={editor.activePage} {thumbScale} />
|
|
122
|
+
</div>
|
|
123
|
+
</LayerButton>
|
|
124
|
+
</ContextMenu.Trigger>
|
|
125
|
+
<ContextMenu.Content class="w-72">
|
|
126
|
+
<BackgroundMenuContent {editor} page={editor.activePage} />
|
|
127
|
+
</ContextMenu.Content>
|
|
128
|
+
</ContextMenu.Root>
|
|
129
|
+
</div>
|
|
130
|
+
</SidebarWrapper>
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import TextIcon from '@lucide/svelte/icons/type';
|
|
3
3
|
import Button from '../../ui/button/button.svelte';
|
|
4
|
-
import {
|
|
4
|
+
import type { Editor } from '../editor.svelte.js';
|
|
5
5
|
import { buildParagraphHtml } from '../utils.js';
|
|
6
6
|
import SidebarTextTabButton from './sidebar-text-tab-button.svelte';
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
interface Props {
|
|
9
|
+
editor: Editor;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const { editor }: Props = $props();
|
|
9
13
|
|
|
10
14
|
const createTextBox = () => {
|
|
11
15
|
const fontSize = 80 / 0.75;
|
|
@@ -65,7 +69,7 @@
|
|
|
65
69
|
];
|
|
66
70
|
</script>
|
|
67
71
|
|
|
68
|
-
<div class="flex flex-col">
|
|
72
|
+
<div class="flex flex-col p-2">
|
|
69
73
|
<Button variant="default" class="w-full" onclick={createTextBox}>
|
|
70
74
|
<TextIcon />
|
|
71
75
|
Add a text box
|
|
@@ -1,18 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
} & Exports;
|
|
5
|
-
(internal: unknown, props: {
|
|
6
|
-
$$events?: Events;
|
|
7
|
-
$$slots?: Slots;
|
|
8
|
-
}): Exports & {
|
|
9
|
-
$set?: any;
|
|
10
|
-
$on?: any;
|
|
11
|
-
};
|
|
12
|
-
z_$$bindings?: Bindings;
|
|
1
|
+
import type { Editor } from '../editor.svelte.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
editor: Editor;
|
|
13
4
|
}
|
|
14
|
-
declare const SidebarTextTab:
|
|
15
|
-
|
|
16
|
-
}, {}, {}, string>;
|
|
17
|
-
type SidebarTextTab = InstanceType<typeof SidebarTextTab>;
|
|
5
|
+
declare const SidebarTextTab: import("svelte").Component<Props, {}, "">;
|
|
6
|
+
type SidebarTextTab = ReturnType<typeof SidebarTextTab>;
|
|
18
7
|
export default SidebarTextTab;
|
|
@@ -7,9 +7,13 @@
|
|
|
7
7
|
import { Label } from '../../ui/label/index.js';
|
|
8
8
|
import UploadsImage from './uploads-image.svelte';
|
|
9
9
|
import { checkImage } from '../utils.js';
|
|
10
|
-
import {
|
|
10
|
+
import type { Editor } from '../editor.svelte.js';
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
interface Props {
|
|
13
|
+
editor: Editor;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const { editor }: Props = $props();
|
|
13
17
|
|
|
14
18
|
let open = $state(false);
|
|
15
19
|
let url = $state('');
|
|
@@ -44,11 +48,9 @@
|
|
|
44
48
|
};
|
|
45
49
|
</script>
|
|
46
50
|
|
|
47
|
-
<div class="relative flex h-full shrink-0 flex-col gap-2">
|
|
51
|
+
<div class="relative flex h-full shrink-0 flex-col gap-2 p-2">
|
|
48
52
|
{#if editor.fileDragged}
|
|
49
|
-
<div
|
|
50
|
-
class="absolute inset-0 z-10 flex h-full w-full flex-col items-center justify-center bg-background"
|
|
51
|
-
>
|
|
53
|
+
<div class="absolute inset-0 z-10 flex h-full w-full flex-col items-center justify-center">
|
|
52
54
|
<div class="grid gap-6">
|
|
53
55
|
<div class="grid justify-center">
|
|
54
56
|
<CloudUploadIcon class="m-auto h-8 w-8" />
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import type { Editor } from '../editor.svelte.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
editor: Editor;
|
|
4
|
+
}
|
|
5
|
+
declare const SidebarUploadsTab: import("svelte").Component<Props, {}, "">;
|
|
2
6
|
type SidebarUploadsTab = ReturnType<typeof SidebarUploadsTab>;
|
|
3
7
|
export default SidebarUploadsTab;
|
|
@@ -5,18 +5,19 @@
|
|
|
5
5
|
|
|
6
6
|
interface Props {
|
|
7
7
|
name: string;
|
|
8
|
+
onclose?: () => void;
|
|
8
9
|
children?: import('svelte').Snippet;
|
|
9
10
|
}
|
|
10
11
|
|
|
11
|
-
let { name, children }: Props = $props();
|
|
12
|
+
let { name, children, onclose = () => (editor.activeSidebarPopup = null) }: Props = $props();
|
|
12
13
|
|
|
13
14
|
const editor = getEditorContext();
|
|
14
15
|
</script>
|
|
15
16
|
|
|
16
17
|
<div class="flex h-full select-none flex-col gap-2">
|
|
17
|
-
<div class="flex items-center justify-between">
|
|
18
|
+
<div class="flex items-center justify-between p-2">
|
|
18
19
|
<div class="text-sm font-bold">{name}</div>
|
|
19
|
-
<Button variant="ghost" size="icon" onclick={
|
|
20
|
+
<Button variant="ghost" size="icon" onclick={onclose}>
|
|
20
21
|
<XIcon />
|
|
21
22
|
</Button>
|
|
22
23
|
</div>
|