@pixerate/editor-svelte 0.105.0 → 0.107.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,7 +1,8 @@
1
1
  <script lang="ts">
2
2
  import { normalizeHexColor, parameterLabel, type ColorParameterField } from '@pixerate/editor/parameters';
3
+ import ColorPicker from '../color/ColorPicker.svelte';
3
4
  import ParameterCommitInput from './ParameterCommitInput.svelte';
4
- import { parameterInputClass, parameterRangeClass } from './styles.js';
5
+ import { parameterInputClass } from './styles.js';
5
6
 
6
7
  interface Props {
7
8
  field: ColorParameterField;
@@ -19,44 +20,53 @@
19
20
  const alpha = $derived(!!field.alpha);
20
21
  const hex = $derived(normalizeHexColor(value, true) ?? '#000000ff');
21
22
  const rgb = $derived(hex.slice(0, 7));
22
- const a = $derived(hex.slice(7));
23
23
  const shown = $derived(alpha ? hex : rgb);
24
24
  const off = $derived(disabled || !!field.readOnly);
25
25
  const name = $derived(parameterLabel(field));
26
26
 
27
- let picking = false;
28
- function start() {
29
- if (picking) return;
30
- picking = true;
31
- ongesturestart?.();
32
- }
33
- function end() {
34
- if (!picking) return;
35
- picking = false;
36
- ongestureend?.();
37
- }
27
+ let open = $state(false);
28
+ let containerEl = $state<HTMLDivElement | null>(null);
29
+ let buttonEl = $state<HTMLButtonElement | null>(null);
30
+ let popoverEl = $state<HTMLDivElement | null>(null);
31
+
32
+ $effect(() => {
33
+ if (!open) return;
34
+ function onPointerDown(e: PointerEvent) {
35
+ if (containerEl && !containerEl.contains(e.target as Node)) {
36
+ open = false;
37
+ }
38
+ }
39
+ function onKeyDown(e: KeyboardEvent) {
40
+ if (e.key === 'Escape') {
41
+ e.stopPropagation();
42
+ open = false;
43
+ buttonEl?.focus();
44
+ }
45
+ }
46
+ window.addEventListener('pointerdown', onPointerDown, true);
47
+ window.addEventListener('keydown', onKeyDown, true);
48
+ return () => {
49
+ window.removeEventListener('pointerdown', onPointerDown, true);
50
+ window.removeEventListener('keydown', onKeyDown, true);
51
+ };
52
+ });
38
53
  </script>
39
54
 
40
- <!-- A colour picker with a hex box, an alpha slider (with `alpha`) and swatches. -->
41
- <div class="space-y-1.5">
55
+ <!-- A colour picker with a hex box and a popup ColorPicker. -->
56
+ <div bind:this={containerEl} class="relative space-y-1.5">
42
57
  <div class="flex items-center gap-2">
43
- <span
44
- class="relative h-7 w-9 shrink-0 overflow-hidden rounded-md border border-input bg-[repeating-conic-gradient(#d4d4d8_0_25%,#fff_0_50%)] bg-[length:8px_8px]"
58
+ <button
59
+ bind:this={buttonEl}
60
+ type="button"
61
+ aria-label={name}
62
+ aria-expanded={open}
63
+ aria-haspopup="dialog"
64
+ disabled={off}
65
+ onclick={() => (open = !open)}
66
+ class="relative h-7 w-9 shrink-0 overflow-hidden rounded-md border border-input bg-[repeating-conic-gradient(#d4d4d8_0_25%,#fff_0_50%)] bg-[length:8px_8px] focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary disabled:cursor-not-allowed disabled:opacity-50"
45
67
  >
46
68
  <span class="absolute inset-0" style:background={shown}></span>
47
- <input
48
- type="color"
49
- aria-label={name}
50
- value={rgb}
51
- disabled={off}
52
- class="absolute inset-0 h-full w-full cursor-pointer opacity-0 disabled:cursor-not-allowed"
53
- oninput={(e) => {
54
- start();
55
- onchange(alpha ? `${e.currentTarget.value}${a}` : e.currentTarget.value);
56
- }}
57
- onblur={end}
58
- />
59
- </span>
69
+ </button>
60
70
  <ParameterCommitInput
61
71
  {id}
62
72
  aria-label="{name} hex"
@@ -70,40 +80,29 @@
70
80
  }}
71
81
  />
72
82
  </div>
73
- {#if alpha}
74
- <input
75
- type="range"
76
- aria-label="{name} opacity"
77
- min="0"
78
- max="255"
79
- step="1"
80
- value={parseInt(a, 16)}
81
- disabled={off}
82
- class={parameterRangeClass}
83
- onpointerdown={start}
84
- onpointerup={end}
85
- onpointercancel={end}
86
- onblur={end}
87
- oninput={(e) => onchange(`${rgb}${Number(e.currentTarget.value).toString(16).padStart(2, '0')}`)}
88
- />
89
- {/if}
90
- {#if field.swatches && field.swatches.length > 0}
91
- <div class="flex flex-wrap gap-1">
92
- {#each field.swatches as s (s)}
93
- {@const swatch = normalizeHexColor(s, alpha)}
94
- {#if swatch}
95
- <button
96
- type="button"
97
- title={swatch}
98
- aria-label="{name} {swatch}"
99
- aria-pressed={swatch === shown}
100
- disabled={off}
101
- onclick={() => onchange(swatch)}
102
- class="h-5 w-5 rounded border border-input aria-pressed:ring-1 aria-pressed:ring-primary"
103
- style:background={swatch}
104
- ></button>
105
- {/if}
106
- {/each}
83
+ {#if open}
84
+ <div
85
+ bind:this={popoverEl}
86
+ role="dialog"
87
+ aria-label={name}
88
+ tabindex="-1"
89
+ onfocusout={(e) => {
90
+ if (popoverEl && !popoverEl.contains(e.relatedTarget as Node)) {
91
+ open = false;
92
+ }
93
+ }}
94
+ class="absolute left-0 top-full z-50 mt-1 w-64 rounded-lg border border-border bg-popover p-2 text-popover-foreground shadow-xl"
95
+ style="background: var(--popover, var(--background, #fff));"
96
+ >
97
+ <ColorPicker
98
+ value={shown}
99
+ {alpha}
100
+ swatches={field.swatches}
101
+ disabled={off}
102
+ {onchange}
103
+ {ongesturestart}
104
+ {ongestureend}
105
+ />
107
106
  </div>
108
107
  {/if}
109
108
  </div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixerate/editor-svelte",
3
- "version": "0.105.0",
3
+ "version": "0.107.0",
4
4
  "description": "Svelte bindings and prompt/rich-text components for @pixerate/editor",
5
5
  "author": "Pixerate",
6
6
  "license": "MIT",
@@ -88,6 +88,16 @@
88
88
  "svelte": "./dist/video-editor/index.js",
89
89
  "default": "./dist/video-editor/index.js"
90
90
  },
91
+ "./color": {
92
+ "types": "./dist/color/index.d.ts",
93
+ "svelte": "./dist/color/index.js",
94
+ "default": "./dist/color/index.js"
95
+ },
96
+ "./gradient": {
97
+ "types": "./dist/gradient/index.d.ts",
98
+ "svelte": "./dist/gradient/index.js",
99
+ "default": "./dist/gradient/index.js"
100
+ },
91
101
  "./package.json": "./package.json"
92
102
  },
93
103
  "typesVersions": {
@@ -130,6 +140,12 @@
130
140
  ],
131
141
  "video-editor": [
132
142
  "./dist/video-editor/index.d.ts"
143
+ ],
144
+ "color": [
145
+ "./dist/color/index.d.ts"
146
+ ],
147
+ "gradient": [
148
+ "./dist/gradient/index.d.ts"
133
149
  ]
134
150
  }
135
151
  },
@@ -144,7 +160,7 @@
144
160
  "@tiptap/extension-bubble-menu": "^2.27.3",
145
161
  "@tiptap/extension-placeholder": "^2.27.3",
146
162
  "@tiptap/starter-kit": "^2.27.3",
147
- "@pixerate/editor": "0.146.0"
163
+ "@pixerate/editor": "0.148.0"
148
164
  },
149
165
  "peerDependencies": {
150
166
  "@dagrejs/dagre": "^1.1.4",