@pixerate/editor-svelte 0.74.0 → 0.75.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.
@@ -1,12 +1,14 @@
1
1
  <script lang="ts">
2
- import type { FreeTransformField, FreeTransformTool, Interpolation } from '@pixerate/editor/image-editor';
3
- import { FREE_TRANSFORM_FIELDS, FREE_TRANSFORM_MODE_OPTIONS, INTERPOLATIONS, TRANSFORM_ANCHORS } from '@pixerate/editor/image-editor';
2
+ import type { FreeTransformField, FreeTransformTool, Interpolation, WarpBar } from '@pixerate/editor/image-editor';
3
+ import { FREE_TRANSFORM_FIELDS, FREE_TRANSFORM_MODE_OPTIONS, INTERPOLATIONS, TRANSFORM_ANCHORS, WARP_GRID_OPTIONS, WARP_STYLE_OPTIONS } from '@pixerate/editor/image-editor';
4
4
 
5
5
  /**
6
6
  * Free Transform's options bar (Photoshop's): the mode switch (Free, Rotate, Skew, Distort,
7
- * Perspective), the reference-point locator, X / Y of the reference point, W / H in percent
8
- * with the proportional chain, the angle and skews, the interpolation, and Commit (Enter) /
9
- * Cancel (Esc). Typed values apply on Enter or when the field loses focus.
7
+ * Perspective, Warp), the reference-point locator, X / Y of the reference point, W / H in
8
+ * percent with the proportional chain, the angle and skews, the interpolation, and Commit
9
+ * (Enter) / Cancel (Esc). In Warp mode the numbers give way to the warp style, bend, horizontal
10
+ * and vertical distortion, orientation and grid. Typed values apply on Enter or when the field
11
+ * loses focus.
10
12
  */
11
13
  let { tool, class: className = '' }: { tool: FreeTransformTool; class?: string } = $props();
12
14
 
@@ -16,12 +18,23 @@
16
18
  /** What the bar shows, re-read whenever the tool changes. */
17
19
  const view = $derived.by(() => {
18
20
  void tick;
19
- return { bar: tool.active ? tool.bar() : null, mode: tool.mode, proportional: tool.proportional, interpolation: tool.interpolation, error: tool.error };
21
+ return { bar: tool.active ? tool.bar() : null, mode: tool.mode, proportional: tool.proportional, interpolation: tool.interpolation, error: tool.error, warp: tool.warpBar() };
20
22
  });
21
23
  const bar = $derived(view.bar);
22
24
  const chip = (on: boolean) => `px-2 py-1 rounded text-[11px] ${on ? 'bg-indigo-600 text-white' : 'bg-slate-800 text-slate-300 hover:text-white'}`;
23
25
  const round = (v: number, unit: string) => (unit === 'px' ? Math.round(v * 10) / 10 : Math.round(v * 100) / 100);
24
26
 
27
+ const WARP_NUMBERS = [
28
+ { key: 'bend', label: 'Bend', aria: 'Warp bend in percent' },
29
+ { key: 'horizontal', label: 'H', aria: 'Warp horizontal distortion in percent' },
30
+ { key: 'vertical', label: 'V', aria: 'Warp vertical distortion in percent' },
31
+ ] as const;
32
+ function warpNumber(key: 'bend' | 'horizontal' | 'vertical', raw: string) {
33
+ const v = Number(raw);
34
+ if (raw.trim() !== '' && Number.isFinite(v) && v !== tool.warpBar()[key]) tool.setWarp({ [key]: Math.max(-100, Math.min(100, v)) } as Partial<WarpBar>);
35
+ }
36
+ const gridId = (w: WarpBar) => WARP_GRID_OPTIONS.find((g) => g.columns === w.columns && g.rows === w.rows)?.id ?? '1x1';
37
+
25
38
  function apply(field: FreeTransformField, raw: string) {
26
39
  const b = tool.bar();
27
40
  const v = Number(raw);
@@ -41,7 +54,67 @@
41
54
  <button type="button" aria-label={`Reference point ${a}`} title={`Reference point: ${a}`} class="h-2.5 w-2.5 rounded-sm bg-slate-700 hover:bg-indigo-500" onclick={() => tool.setReference(a)}></button>
42
55
  {/each}
43
56
  </div>
44
- {#each FREE_TRANSFORM_FIELDS as f (f.id)}
57
+ {#if view.mode === 'warp'}
58
+ <div class="flex flex-wrap items-center gap-2" role="group" aria-label="Warp options">
59
+ <label class="flex items-center gap-1">
60
+ <span class="text-slate-400">Warp</span>
61
+ <select aria-label="Warp style" value={view.warp.style} onchange={(e) => tool.setWarp({ style: e.currentTarget.value as WarpBar['style'] })} class="rounded border border-slate-700 bg-slate-900 px-1 py-0.5">
62
+ {#each WARP_STYLE_OPTIONS as o (o.id)}
63
+ <option value={o.id}>{o.label}</option>
64
+ {/each}
65
+ </select>
66
+ </label>
67
+ {#each WARP_NUMBERS as n (n.key)}
68
+ <label class="flex items-center gap-1">
69
+ <span class="text-slate-400">{n.label}</span>
70
+ {#key view.warp[n.key]}
71
+ <input
72
+ type="number"
73
+ aria-label={n.aria}
74
+ value={view.warp[n.key]}
75
+ min={-100}
76
+ max={100}
77
+ disabled={view.warp.style === 'custom'}
78
+ class="w-14 rounded border border-slate-700 bg-slate-900 px-1 py-0.5 text-right disabled:opacity-40"
79
+ onblur={(e) => warpNumber(n.key, e.currentTarget.value)}
80
+ onkeydown={(e) => {
81
+ if (e.key === 'Enter') {
82
+ e.preventDefault();
83
+ e.stopPropagation();
84
+ warpNumber(n.key, e.currentTarget.value);
85
+ }
86
+ }}
87
+ />
88
+ {/key}
89
+ <span class="text-slate-500">%</span>
90
+ </label>
91
+ {/each}
92
+ <button
93
+ type="button"
94
+ title="Bend along the vertical axis"
95
+ aria-pressed={view.warp.orientation === 'vertical'}
96
+ disabled={view.warp.style === 'custom'}
97
+ class={chip(view.warp.orientation === 'vertical')}
98
+ onclick={() => tool.setWarp({ orientation: view.warp.orientation === 'vertical' ? 'horizontal' : 'vertical' })}>Vertical</button>
99
+ <label class="flex items-center gap-1">
100
+ <span class="text-slate-400">Grid</span>
101
+ <select
102
+ aria-label="Warp grid"
103
+ value={gridId(view.warp)}
104
+ onchange={(e) => {
105
+ const g = WARP_GRID_OPTIONS.find((o) => o.id === e.currentTarget.value)!;
106
+ tool.setWarp({ columns: g.columns, rows: g.rows });
107
+ }}
108
+ class="rounded border border-slate-700 bg-slate-900 px-1 py-0.5"
109
+ >
110
+ {#each WARP_GRID_OPTIONS as g (g.id)}
111
+ <option value={g.id}>{g.label}</option>
112
+ {/each}
113
+ </select>
114
+ </label>
115
+ </div>
116
+ {/if}
117
+ {#each view.mode === 'warp' ? [] : FREE_TRANSFORM_FIELDS as f (f.id)}
45
118
  <label class="flex items-center gap-1" title={f.title}>
46
119
  <span class="text-slate-400">{f.label}</span>
47
120
  {#key round(bar[f.id], f.unit)}
@@ -1 +1 @@
1
- {"version":3,"file":"FreeTransformOptionsBar.svelte.d.ts","sourceRoot":"","sources":["../../src/image-editor/FreeTransformOptionsBar.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAsB,iBAAiB,EAAiB,MAAM,+BAA+B,CAAC;AAGzG,KAAK,gBAAgB,GAAI;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAmFtE,QAAA,MAAM,uBAAuB,sDAAwC,CAAC;AACtE,KAAK,uBAAuB,GAAG,UAAU,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAC1E,eAAe,uBAAuB,CAAC"}
1
+ {"version":3,"file":"FreeTransformOptionsBar.svelte.d.ts","sourceRoot":"","sources":["../../src/image-editor/FreeTransformOptionsBar.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAsB,iBAAiB,EAA0B,MAAM,+BAA+B,CAAC;AAGlH,KAAK,gBAAgB,GAAI;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAuItE,QAAA,MAAM,uBAAuB,sDAAwC,CAAC;AACtE,KAAK,uBAAuB,GAAG,UAAU,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAC1E,eAAe,uBAAuB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixerate/editor-svelte",
3
- "version": "0.74.0",
3
+ "version": "0.75.0",
4
4
  "description": "Svelte bindings and prompt/rich-text components for @pixerate/editor",
5
5
  "author": "Pixerate",
6
6
  "license": "MIT",
@@ -131,7 +131,7 @@
131
131
  "@tiptap/extension-bubble-menu": "^2.11.5",
132
132
  "@tiptap/extension-placeholder": "^2.11.5",
133
133
  "@tiptap/starter-kit": "^2.11.5",
134
- "@pixerate/editor": "0.99.0"
134
+ "@pixerate/editor": "0.100.0"
135
135
  },
136
136
  "peerDependencies": {
137
137
  "@dagrejs/dagre": "^1.1.4",