@pixerate/editor-svelte 0.202.1 → 0.204.0

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.
@@ -0,0 +1,210 @@
1
+ <script lang="ts">
2
+ import { untrack } from 'svelte';
3
+ import {
4
+ EVOLUTION_SLIDERS,
5
+ exportProposalContactSheetPng,
6
+ liveStrokeRefusal,
7
+ normalizeMutationRates,
8
+ paintProposalGhost,
9
+ proposalGenomeStrokes,
10
+ type EvolutionMutationRates,
11
+ type PaintEditorController,
12
+ type PaintProposals,
13
+ type PaintProposalsState,
14
+ } from '@pixerate/editor/paint-editor';
15
+ import PaintSlider from './PaintSlider.svelte';
16
+ import { attempt, button, chip, paintEditorState, panel } from './paintEditorRune.svelte.js';
17
+
18
+ interface Props {
19
+ controller: PaintEditorController;
20
+ /** Optional proposals store (defaults to `controller.proposals`). */
21
+ proposals?: PaintProposals;
22
+ class?: string;
23
+ }
24
+ let { controller, proposals, class: className = '' }: Props = $props();
25
+ const editor = paintEditorState(() => controller);
26
+ const store = $derived(proposals ?? controller.proposals);
27
+
28
+ let proposalState = $state.raw<PaintProposalsState>({ proposals: [] });
29
+ $effect(() => {
30
+ const s = store;
31
+ return untrack(() => {
32
+ proposalState = s.getState();
33
+ return s.subscribe((next) => {
34
+ proposalState = next;
35
+ });
36
+ });
37
+ });
38
+
39
+ let selectedStrokes = $state<string[]>([]);
40
+ let selectedProposals = $state<string[]>([]);
41
+ let count = $state(4);
42
+ let seed = $state(1);
43
+ let mutation = $state<Required<EvolutionMutationRates>>(normalizeMutationRates());
44
+ let contactSheetUrl = $state<string | null>(null);
45
+ let error = $state<string | null>(null);
46
+ const run = (fn: () => unknown) => attempt(fn, (m) => (error = m));
47
+
48
+ const eligibleStrokes = $derived(editor.current.document.strokes.filter((s) => !liveStrokeRefusal(s.brush)));
49
+ const activeStrokeIds = $derived(selectedStrokes.filter((id) => eligibleStrokes.some((s) => s.id === id)));
50
+ const effectiveStrokeIds = $derived(
51
+ activeStrokeIds.length > 0
52
+ ? activeStrokeIds
53
+ : editor.current.selectedStroke && eligibleStrokes.some((s) => s.id === editor.current.selectedStroke)
54
+ ? [editor.current.selectedStroke]
55
+ : eligibleStrokes.length > 0
56
+ ? [eligibleStrokes[eligibleStrokes.length - 1]!.id]
57
+ : []
58
+ );
59
+ const variants = $derived(proposalState.proposals.filter((p) => proposalGenomeStrokes(p).length > 0));
60
+ const activeProposalIds = $derived(selectedProposals.filter((id) => variants.some((v) => v.id === id)));
61
+
62
+ function toggleStroke(id: string) {
63
+ selectedStrokes = selectedStrokes.includes(id) ? selectedStrokes.filter((x) => x !== id) : [...selectedStrokes.slice(-15), id];
64
+ }
65
+
66
+ function toggleProposal(id: string) {
67
+ selectedProposals = selectedProposals.includes(id) ? selectedProposals.filter((x) => x !== id) : [...selectedProposals.slice(-1), id];
68
+ }
69
+
70
+ function drawPixels(node: HTMLCanvasElement, data: Uint8ClampedArray) {
71
+ const draw = (d: Uint8ClampedArray) => {
72
+ const ctx = node.getContext('2d');
73
+ if (ctx && typeof ImageData !== 'undefined') ctx.putImageData(new ImageData(new Uint8ClampedArray(d), node.width, node.height), 0, 0);
74
+ };
75
+ draw(data);
76
+ return { update: draw };
77
+ }
78
+ </script>
79
+
80
+ <!-- Evolutionary strokes: pick recorded dry strokes, adjust mutation rates, and breed a grid of mutated stroke proposals. -->
81
+ <div class={`${panel} ${className}`} data-testid="evolution-panel">
82
+ <div class="flex items-center justify-between">
83
+ <span class="font-medium text-slate-300">Evolution ({eligibleStrokes.length})</span>
84
+ <label class="flex items-center gap-1 text-[11px] text-slate-400">
85
+ <span>Count</span>
86
+ <input
87
+ type="number"
88
+ aria-label="Variant count"
89
+ min="2"
90
+ max="12"
91
+ value={count}
92
+ onchange={(e) => {
93
+ count = Math.max(2, Math.min(12, Number(e.currentTarget.value) || 4));
94
+ }}
95
+ class="w-11 rounded bg-slate-800 px-1 py-0.5 text-right font-mono text-slate-200"
96
+ />
97
+ </label>
98
+ </div>
99
+
100
+ {#if eligibleStrokes.length > 0}
101
+ <div class="flex max-h-20 flex-wrap gap-1 overflow-y-auto" role="listbox" aria-label="Parent strokes">
102
+ {#each eligibleStrokes as s, i (s.id)}
103
+ {@const on = effectiveStrokeIds.includes(s.id)}
104
+ <button
105
+ type="button"
106
+ role="option"
107
+ aria-selected={on}
108
+ title={`${i + 1}. ${s.brush.name} (${s.id})`}
109
+ class={`h-5 w-5 rounded ring-1 ${on ? 'ring-indigo-400' : 'ring-slate-700'}`}
110
+ style={`background: ${s.color}`}
111
+ onclick={() => toggleStroke(s.id)}
112
+ ></button>
113
+ {/each}
114
+ </div>
115
+ {/if}
116
+
117
+ {#each EVOLUTION_SLIDERS as c (c.path)}
118
+ {@const key = c.path as keyof EvolutionMutationRates}
119
+ <PaintSlider control={c} value={mutation[key]} onchange={(v) => (mutation = { ...mutation, [key]: v })} />
120
+ {/each}
121
+
122
+ <div class="flex flex-wrap gap-1">
123
+ <button
124
+ type="button"
125
+ class={button}
126
+ disabled={effectiveStrokeIds.length === 0 || editor.current.stroking}
127
+ onclick={() =>
128
+ run(() => {
129
+ controller.breedStrokes({ strokeIds: effectiveStrokeIds, count, mutation, seed });
130
+ seed += 1;
131
+ })}
132
+ >
133
+ Breed strokes
134
+ </button>
135
+ {#if activeProposalIds.length === 2}
136
+ <button
137
+ type="button"
138
+ class={button}
139
+ disabled={editor.current.stroking}
140
+ onclick={() =>
141
+ run(() => {
142
+ controller.breedProposal({ proposalIds: activeProposalIds, count, mutation, seed });
143
+ seed += 1;
144
+ })}
145
+ >
146
+ Cross over (2)
147
+ </button>
148
+ {/if}
149
+ {#if variants.length > 0}
150
+ <button
151
+ type="button"
152
+ class={button}
153
+ onclick={() =>
154
+ run(() => {
155
+ const sheet = exportProposalContactSheetPng(controller, variants);
156
+ contactSheetUrl = `data:image/png;base64,${sheet.base64}`;
157
+ })}
158
+ >
159
+ Contact sheet
160
+ </button>
161
+ {/if}
162
+ </div>
163
+
164
+ {#if variants.length > 0}
165
+ <div class="grid grid-cols-2 gap-1.5" data-testid="evolution-grid">
166
+ {#each variants as p (p.id)}
167
+ {@const g = paintProposalGhost(p)}
168
+ {@const picked = activeProposalIds.includes(p.id)}
169
+ <div
170
+ data-testid={`evolution-variant-${p.id}`}
171
+ class={`flex flex-col gap-1 rounded border p-1.5 ${picked ? 'border-indigo-500 bg-slate-800/90' : 'border-slate-800 bg-slate-950/60'}`}
172
+ >
173
+ <div class="flex items-center justify-between gap-1">
174
+ <button type="button" aria-pressed={picked} class={chip(picked)} onclick={() => toggleProposal(p.id)}>{p.title}</button>
175
+ </div>
176
+ {#if g}
177
+ <div class="flex h-16 items-center justify-center overflow-hidden rounded bg-slate-900/80 p-1">
178
+ <canvas use:drawPixels={g.data} width={g.width} height={g.height} role="img" aria-label={p.title} class="max-h-full max-w-full object-contain"></canvas>
179
+ </div>
180
+ {/if}
181
+ {#if p.rationale}
182
+ <span class="line-clamp-2 text-[10px] text-slate-400" title={p.rationale}>{p.rationale}</span>
183
+ {/if}
184
+ <div class="flex flex-wrap gap-1">
185
+ <button
186
+ type="button"
187
+ class={button}
188
+ disabled={editor.current.stroking}
189
+ onclick={() =>
190
+ run(() => {
191
+ controller.breedProposal({ proposalIds: [p.id], count, mutation, seed });
192
+ seed += 1;
193
+ })}
194
+ >
195
+ Breed from
196
+ </button>
197
+ <button type="button" class={button} onclick={() => run(() => store.accept(p.id))}>Accept</button>
198
+ <button type="button" class={button} onclick={() => run(() => store.reject(p.id))}>Dismiss</button>
199
+ </div>
200
+ </div>
201
+ {/each}
202
+ </div>
203
+ {/if}
204
+
205
+ {#if contactSheetUrl}
206
+ <img src={contactSheetUrl} alt="Variant contact sheet" class="w-full rounded border border-slate-800" data-testid="evolution-contact-sheet" />
207
+ {/if}
208
+
209
+ {#if error}<p role="alert" class="text-[11px] text-rose-400">{error}</p>{/if}
210
+ </div>
@@ -0,0 +1,10 @@
1
+ import { type PaintEditorController, type PaintProposals } from '@pixerate/editor/paint-editor';
2
+ interface Props {
3
+ controller: PaintEditorController;
4
+ /** Optional proposals store (defaults to `controller.proposals`). */
5
+ proposals?: PaintProposals;
6
+ class?: string;
7
+ }
8
+ declare const EvolutionPanel: import("svelte").Component<Props, {}, "">;
9
+ type EvolutionPanel = ReturnType<typeof EvolutionPanel>;
10
+ export default EvolutionPanel;
@@ -9,6 +9,7 @@
9
9
  handlePaintShortcut,
10
10
  viewCssTransform,
11
11
  type PaintEditorController,
12
+ type FillRegionOptions,
12
13
  type PaintPresence,
13
14
  type PaintProposals,
14
15
  type PaintAgentStrokes,
@@ -26,6 +27,8 @@
26
27
  controller: PaintEditorController;
27
28
  /** The active tool (default brush). */
28
29
  tool?: PaintTool;
30
+ /** Options for the Fill tool (`tool === 'fill'`). */
31
+ fillOptions?: Omit<FillRegionOptions, 'x' | 'y' | 'points'>;
29
32
  /** Draw the symmetry axes and perspective lines (default true). */
30
33
  showGuides?: boolean;
31
34
  /** Fit the canvas in the viewport on mount (default true). */
@@ -40,7 +43,7 @@
40
43
  agentStrokes?: PaintAgentStrokes;
41
44
  class?: string;
42
45
  }
43
- let { controller, tool = 'brush', showGuides = true, fitOnMount = true, onerror, presence, proposals, agentStrokes, class: className = '' }: Props = $props();
46
+ let { controller, tool = 'brush', fillOptions, showGuides = true, fitOnMount = true, onerror, presence, proposals, agentStrokes, class: className = '' }: Props = $props();
44
47
  let agentLines = $state.raw<PaintAgentStrokesState>({ strokes: [] });
45
48
  $effect(() => {
46
49
  const store = agentStrokes;
@@ -71,6 +74,7 @@
71
74
  );
72
75
  $effect(() => {
73
76
  gesture.tool = tool;
77
+ if (fillOptions) gesture.fillOptions = fillOptions;
74
78
  });
75
79
  const doc = $derived(snap.document.canvas);
76
80
 
@@ -1,8 +1,10 @@
1
- import { type PaintEditorController, type PaintPresence, type PaintProposals, type PaintAgentStrokes, type PaintTool } from '@pixerate/editor/paint-editor';
1
+ import { type PaintEditorController, type FillRegionOptions, type PaintPresence, type PaintProposals, type PaintAgentStrokes, type PaintTool } from '@pixerate/editor/paint-editor';
2
2
  interface Props {
3
3
  controller: PaintEditorController;
4
4
  /** The active tool (default brush). */
5
5
  tool?: PaintTool;
6
+ /** Options for the Fill tool (`tool === 'fill'`). */
7
+ fillOptions?: Omit<FillRegionOptions, 'x' | 'y' | 'points'>;
6
8
  /** Draw the symmetry axes and perspective lines (default true). */
7
9
  showGuides?: boolean;
8
10
  /** Fit the canvas in the viewport on mount (default true). */
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import { PaintPresence, documentToScreen, screenToDocument, type PaintEditorController, type PaintProposals, type PaintAgentStrokes, type PaintTool } from '@pixerate/editor/paint-editor';
2
+ import { PaintPresence, documentToScreen, screenToDocument, type FillRegionOptions, type PaintEditorController, type PaintProposals, type PaintAgentStrokes, type PaintTool } from '@pixerate/editor/paint-editor';
3
3
  import type { AgentPlayback, PlaybackPoint, PlaybackRect, PlaybackRef } from '@pixerate/editor/tools';
4
4
  import { createPlaybackSurface, getAgentPlayback } from '../playback/playback.svelte.js';
5
5
  import PresenceLayer from '../playback/PresenceLayer.svelte';
@@ -13,6 +13,7 @@
13
13
  import StickerPanel from './StickerPanel.svelte';
14
14
  import StrokePanel from './StrokePanel.svelte';
15
15
  import PathStrokePanel from './PathStrokePanel.svelte';
16
+ import EvolutionPanel from './EvolutionPanel.svelte';
16
17
  import PaintEffectsPanel from './PaintEffectsPanel.svelte';
17
18
  import { chip, paintEffectsProvider } from './paintEditorRune.svelte.js';
18
19
 
@@ -105,6 +106,7 @@
105
106
  return c && box ? { x: c.x - box.left, y: c.y - box.top } : p;
106
107
  };
107
108
  let tool = $state<PaintTool>('brush');
109
+ let fillOptions = $state<Omit<FillRegionOptions, 'x' | 'y' | 'points'>>({ reference: 'all', tolerance: 32, closeGap: 4, expand: 1, antialias: true });
108
110
  let tab = $state<'color' | 'wet' | 'paper' | 'layers' | 'effects'>('color');
109
111
  const effects = paintEffectsProvider(() => controller);
110
112
  const tabs = $derived(effects.current ? (['color', 'wet', 'paper', 'layers', 'effects'] as const) : (['color', 'wet', 'paper', 'layers'] as const));
@@ -116,12 +118,12 @@
116
118
  {#if playing}
117
119
  <PresenceLayer presence={agentPresence} viewport={docToRoot} />
118
120
  {/if}
119
- <PaintToolbar {controller} {tool} ontoolchange={(t) => (tool = t)} {fileName} />
121
+ <PaintToolbar {controller} {tool} ontoolchange={(t) => (tool = t)} {fillOptions} onfilloptionschange={(f) => (fillOptions = f)} {fileName} />
120
122
  <div class="flex min-h-0 flex-1 gap-2">
121
123
  <BrushPanel {controller} class="w-60 shrink-0 overflow-y-auto pr-1" />
122
124
  <div class="flex min-w-0 flex-1 flex-col">
123
125
  <!-- With playback the editor draws the cursor (over the panels too), so the canvas doesn't. -->
124
- <PaintCanvas {controller} {tool} presence={playing ? undefined : presence} {proposals} {agentStrokes} onerror={(e) => (error = e)} class="flex-1 rounded-lg" />
126
+ <PaintCanvas {controller} {tool} {fillOptions} presence={playing ? undefined : presence} {proposals} {agentStrokes} onerror={(e) => (error = e)} class="flex-1 rounded-lg" />
125
127
  {#if error}<p role="alert" class="mt-1 text-[11px] text-rose-400">{error}</p>{/if}
126
128
  </div>
127
129
  <div class="flex w-64 shrink-0 flex-col gap-2 overflow-y-auto pr-1">
@@ -134,7 +136,7 @@
134
136
  {#if tab === 'color'}<ColorPanel {controller} />{/if}
135
137
  {#if tab === 'wet'}<WetPanel {controller} />{/if}
136
138
  {#if tab === 'paper'}<PaperPanel {controller} />{/if}
137
- {#if tab === 'layers'}<PaintLayersPanel {controller} /><StrokePanel {controller} /><PathStrokePanel {controller} /><StickerPanel {controller} />{/if}
139
+ {#if tab === 'layers'}<PaintLayersPanel {controller} /><StrokePanel {controller} /><PathStrokePanel {controller} /><EvolutionPanel {controller} {proposals} /><StickerPanel {controller} />{/if}
138
140
  {#if tab === 'effects' && effects.current}<PaintEffectsPanel {controller} />{/if}
139
141
  </div>
140
142
  </div>
@@ -1,18 +1,33 @@
1
1
  <script lang="ts">
2
- import { PAINT_TOOLS, SYMMETRY_MODES, decodeImageBlob, downloadBytes, quickStencil, timeLapseZip, type PaintEditorController, type PaintTool, type SymmetryMode } from '@pixerate/editor/paint-editor';
2
+ import { PAINT_TOOLS, SYMMETRY_MODES, decodeImageBlob, downloadBytes, quickStencil, timeLapseZip, type FillRegionOptions, type PaintEditorController, type PaintTool, type SymmetryMode } from '@pixerate/editor/paint-editor';
3
3
  import { attempt, button, chip, paintEditorState } from './paintEditorRune.svelte.js';
4
4
 
5
+ type FillToolbarOptions = Omit<FillRegionOptions, 'x' | 'y' | 'points'>;
6
+
5
7
  interface Props {
6
8
  controller: PaintEditorController;
7
9
  tool: PaintTool;
8
10
  ontoolchange: (tool: PaintTool) => void;
11
+ fillOptions?: FillToolbarOptions;
12
+ onfilloptionschange?: (options: FillToolbarOptions) => void;
9
13
  /** Base name of saved and exported files (default `painting`). */
10
14
  fileName?: string;
11
15
  class?: string;
12
16
  }
13
- let { controller, tool, ontoolchange, fileName = 'painting', class: className = '' }: Props = $props();
17
+ let { controller, tool, ontoolchange, fillOptions: controlledFill, onfilloptionschange, fileName = 'painting', class: className = '' }: Props = $props();
14
18
  const editor = paintEditorState(() => controller);
15
19
  const snap = $derived(editor.current);
20
+ let localFill = $state<FillToolbarOptions>({ reference: 'all', tolerance: 32, closeGap: 4, expand: 1, antialias: true });
21
+ const fill = $derived(controlledFill ?? localFill);
22
+ const updateFill = (patch: Partial<FillToolbarOptions>) => {
23
+ const next = { ...fill, ...patch };
24
+ localFill = next;
25
+ onfilloptionschange?.(next);
26
+ };
27
+ const layers = $derived.by(() => {
28
+ void snap;
29
+ return controller.listLayers().filter((l) => l.type === 'pixel');
30
+ });
16
31
  const symmetry = $derived(snap.guides.symmetry);
17
32
  const perspective = $derived(snap.guides.perspective);
18
33
  const tracing = $derived(snap.guides.tracing);
@@ -63,6 +78,33 @@
63
78
  {#each PAINT_TOOLS as t (t.id)}
64
79
  <button type="button" aria-pressed={tool === t.id} title={`${t.label} (${t.key.toUpperCase()})`} class={chip(tool === t.id)} onclick={() => ontoolchange(t.id)}>{t.label}</button>
65
80
  {/each}
81
+ {#if tool === 'fill'}
82
+ <div class="flex items-center gap-1.5 rounded border border-slate-700/80 bg-slate-900/60 px-2 py-0.5 text-[11px] text-slate-300" data-testid="paint-fill-options">
83
+ <label class="flex items-center gap-1">
84
+ <span>Ref</span>
85
+ <select aria-label="Fill reference" class="rounded bg-slate-800 px-1 py-0.5 text-[11px]" value={fill.reference ?? 'all'} onchange={(e) => updateFill({ reference: e.currentTarget.value })}>
86
+ <option value="all">All layers</option>
87
+ <option value="layer">Active layer</option>
88
+ {#each layers as l (l.id)}
89
+ <option value={l.id}>{l.name}</option>
90
+ {/each}
91
+ </select>
92
+ </label>
93
+ <label class="flex items-center gap-1">
94
+ <span>Tol</span>
95
+ <input type="number" aria-label="Fill tolerance" min="0" max="255" value={fill.tolerance ?? 32} oninput={(e) => updateFill({ tolerance: Math.max(0, Math.min(255, Number(e.currentTarget.value) || 0)) })} class="w-11 rounded bg-slate-800 px-1 py-0.5 text-[11px]" />
96
+ </label>
97
+ <label class="flex items-center gap-1">
98
+ <span>Gap</span>
99
+ <input type="number" aria-label="Close gap" min="0" max="32" value={fill.closeGap ?? 4} oninput={(e) => updateFill({ closeGap: Math.max(0, Math.min(32, Number(e.currentTarget.value) || 0)) })} class="w-10 rounded bg-slate-800 px-1 py-0.5 text-[11px]" />
100
+ </label>
101
+ <label class="flex items-center gap-1">
102
+ <span>Expand</span>
103
+ <input type="number" aria-label="Expand fill" min="-16" max="16" value={fill.expand ?? 1} oninput={(e) => updateFill({ expand: Math.max(-16, Math.min(16, Number(e.currentTarget.value) || 0)) })} class="w-10 rounded bg-slate-800 px-1 py-0.5 text-[11px]" />
104
+ </label>
105
+ <button type="button" class={chip(Boolean(fill.wet))} aria-pressed={Boolean(fill.wet)} onclick={() => updateFill({ wet: !fill.wet })}>Wet</button>
106
+ </div>
107
+ {/if}
66
108
  <span class="mx-1 h-4 w-px bg-slate-700"></span>
67
109
  <button type="button" class={button} disabled={!snap.canUndo} title={snap.undoLabel ? `Undo ${snap.undoLabel}` : 'Undo'} onclick={() => controller.undo()}>Undo</button>
68
110
  <button type="button" class={button} disabled={!snap.canRedo} title={snap.redoLabel ? `Redo ${snap.redoLabel}` : 'Redo'} onclick={() => controller.redo()}>Redo</button>
@@ -1,8 +1,11 @@
1
- import { type PaintEditorController, type PaintTool } from '@pixerate/editor/paint-editor';
1
+ import { type FillRegionOptions, type PaintEditorController, type PaintTool } from '@pixerate/editor/paint-editor';
2
+ type FillToolbarOptions = Omit<FillRegionOptions, 'x' | 'y' | 'points'>;
2
3
  interface Props {
3
4
  controller: PaintEditorController;
4
5
  tool: PaintTool;
5
6
  ontoolchange: (tool: PaintTool) => void;
7
+ fillOptions?: FillToolbarOptions;
8
+ onfilloptionschange?: (options: FillToolbarOptions) => void;
6
9
  /** Base name of saved and exported files (default `painting`). */
7
10
  fileName?: string;
8
11
  class?: string;
@@ -13,6 +13,7 @@ import type StickerPanelComponent from './StickerPanel.svelte';
13
13
  import type StickerPickerComponent from './StickerPicker.svelte';
14
14
  import type StrokePanelComponent from './StrokePanel.svelte';
15
15
  import type PathStrokePanelComponent from './PathStrokePanel.svelte';
16
+ import type EvolutionPanelComponent from './EvolutionPanel.svelte';
16
17
  import type PaintEffectsPanelComponent from './PaintEffectsPanel.svelte';
17
18
  import type PaintGradientEditorComponent from './PaintGradientEditor.svelte';
18
19
  export { default as PaintEditor } from './PaintEditor.svelte';
@@ -29,6 +30,7 @@ export { default as StickerPanel } from './StickerPanel.svelte';
29
30
  export { default as StickerPicker } from './StickerPicker.svelte';
30
31
  export { default as StrokePanel } from './StrokePanel.svelte';
31
32
  export { default as PathStrokePanel } from './PathStrokePanel.svelte';
33
+ export { default as EvolutionPanel } from './EvolutionPanel.svelte';
32
34
  export { default as PaintEffectsPanel } from './PaintEffectsPanel.svelte';
33
35
  export { default as PaintGradientEditor } from './PaintGradientEditor.svelte';
34
36
  export { default as PaintSlider } from './PaintSlider.svelte';
@@ -50,5 +52,6 @@ export type StickerPanelProps = ComponentProps<typeof StickerPanelComponent>;
50
52
  export type StickerPickerProps = ComponentProps<typeof StickerPickerComponent>;
51
53
  export type StrokePanelProps = ComponentProps<typeof StrokePanelComponent>;
52
54
  export type PathStrokePanelProps = ComponentProps<typeof PathStrokePanelComponent>;
55
+ export type EvolutionPanelProps = ComponentProps<typeof EvolutionPanelComponent>;
53
56
  export type PaintEffectsPanelProps = ComponentProps<typeof PaintEffectsPanelComponent>;
54
57
  export type PaintGradientEditorProps = ComponentProps<typeof PaintGradientEditorComponent>;
@@ -14,6 +14,7 @@ export { default as StickerPanel } from './StickerPanel.svelte';
14
14
  export { default as StickerPicker } from './StickerPicker.svelte';
15
15
  export { default as StrokePanel } from './StrokePanel.svelte';
16
16
  export { default as PathStrokePanel } from './PathStrokePanel.svelte';
17
+ export { default as EvolutionPanel } from './EvolutionPanel.svelte';
17
18
  export { default as PaintEffectsPanel } from './PaintEffectsPanel.svelte';
18
19
  export { default as PaintGradientEditor } from './PaintGradientEditor.svelte';
19
20
  export { default as PaintSlider } from './PaintSlider.svelte';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixerate/editor-svelte",
3
- "version": "0.202.1",
3
+ "version": "0.204.0",
4
4
  "description": "Svelte bindings and prompt/rich-text components for @pixerate/editor",
5
5
  "author": "Pixerate",
6
6
  "license": "MIT",
@@ -184,7 +184,7 @@
184
184
  "**/*.css"
185
185
  ],
186
186
  "dependencies": {
187
- "@pixerate/editor": "0.272.1"
187
+ "@pixerate/editor": "0.274.0"
188
188
  },
189
189
  "peerDependencies": {
190
190
  "@dagrejs/dagre": "^1.1.4",