@pixerate/editor-svelte 0.123.0 → 0.124.1

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.
@@ -39,6 +39,7 @@
39
39
  defaultChartErrorBarValue,
40
40
  formatChartAmountList,
41
41
  isCartesianChart,
42
+ listChartMaps,
42
43
  suggestChartReferences,
43
44
  parseChartAmountList,
44
45
  type ChartAxis,
@@ -427,6 +428,29 @@
427
428
  </div>
428
429
  </div>
429
430
  {/if}
431
+ {#if spec.type === 'choropleth'}
432
+ {@const maps = listChartMaps()}
433
+ <div class="flex items-center gap-2">
434
+ <label for="{idPrefix}-map" class="{chartLabelClass} w-20 shrink-0">Map</label>
435
+ <select id="{idPrefix}-map" class={chartInputClass} value={spec.map} data-option="map" onchange={(e) => controller.update({ map: e.currentTarget.value })}>
436
+ {#each [...new Set([spec.map, ...maps.map((m) => m.id)])] as id (id)}
437
+ <option value={id}>{maps.find((m) => m.id === id)?.name ?? `${id} (not loaded)`}</option>
438
+ {/each}
439
+ </select>
440
+ </div>
441
+ <div class="flex items-center gap-2">
442
+ <label for="{idPrefix}-map-steps" class="{chartLabelClass} w-20 shrink-0">Classes</label>
443
+ <div class="min-w-0 flex-1">
444
+ <ChartCommitInput id="{idPrefix}-map-steps" value={String(spec.mapSteps)} inputmode="numeric" data-option="mapSteps" disabled={spec.mapThresholds.length > 0} oncommit={(text) => controller.update({ mapSteps: Number(text) }).ok} />
445
+ </div>
446
+ </div>
447
+ <div class="flex items-center gap-2">
448
+ <label for="{idPrefix}-map-breaks" class="{chartLabelClass} w-20 shrink-0">Breaks</label>
449
+ <div class="min-w-0 flex-1">
450
+ <ChartCommitInput id="{idPrefix}-map-breaks" value={spec.mapThresholds.join(', ')} placeholder="Equal classes" data-option="mapThresholds" oncommit={(text) => controller.update({ mapThresholds: text.trim() ? text.split(',').map((t) => Number(t.trim())) : [] }).ok} />
451
+ </div>
452
+ </div>
453
+ {/if}
430
454
  {#if spec.type === 'barrace'}
431
455
  <div class="flex items-center gap-2">
432
456
  <label for="{idPrefix}-race-top" class="{chartLabelClass} w-20 shrink-0">Bars</label>
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import { onDestroy } from 'svelte';
2
+ import { onDestroy, untrack } from 'svelte';
3
3
  import { effectSampleInputs, type EffectAuthoringSession, type EffectRenderer } from '@pixerate/editor/effects';
4
4
  import { effectAuthoringOf } from './effects.svelte.js';
5
5
  import EffectParameters from './EffectParameters.svelte';
@@ -32,6 +32,12 @@
32
32
  let renderer: EffectRenderer | null = $state.raw(null);
33
33
  let rendering = false;
34
34
  let pending = false;
35
+ /** Why the preview shows nothing: the preview could not be made, or its last frame failed. */
36
+ let previewError: string | null = $state(null);
37
+
38
+ function clearCanvas() {
39
+ canvas?.getContext('2d')?.clearRect(0, 0, canvas.width, canvas.height);
40
+ }
35
41
 
36
42
  // Preset saving state
37
43
  let savingPreset = $state(false);
@@ -49,6 +55,12 @@
49
55
  const w = previewSize.width;
50
56
  const h = previewSize.height;
51
57
 
58
+ // A new session must not show the last session's frame, whatever happens next.
59
+ untrack(() => {
60
+ clearCanvas();
61
+ previewError = null;
62
+ });
63
+
52
64
  if (!s) {
53
65
  if (renderer) {
54
66
  renderer.dispose();
@@ -67,6 +79,9 @@
67
79
  }
68
80
  createdRenderer = r;
69
81
  renderer = r;
82
+ }).catch((e: unknown) => {
83
+ // The session's own reason (state.previewError) when it has one, else the error's.
84
+ if (live) previewError = s.getState().previewError || (e instanceof Error ? e.message : String(e));
70
85
  });
71
86
 
72
87
  return () => {
@@ -103,8 +118,14 @@
103
118
  if (ctx && typeof ImageData !== 'undefined') {
104
119
  ctx.putImageData(new ImageData(new Uint8ClampedArray(pixels.data), pixels.width, pixels.height), 0, 0);
105
120
  }
106
- } catch {
107
- // A failed frame (for example a disposed renderer) is skipped; the next change draws again.
121
+ if (renderer === r) previewError = null;
122
+ } catch (e) {
123
+ // A frame from a renderer that has since been replaced (or disposed) is skipped; a failure
124
+ // of the current one clears the canvas and says why. The next change draws again.
125
+ if (renderer === r) {
126
+ clearCanvas();
127
+ previewError = e instanceof Error ? e.message : String(e);
128
+ }
108
129
  }
109
130
  } while (pending);
110
131
  } finally {
@@ -261,6 +282,11 @@
261
282
  class="h-full w-full object-contain"
262
283
  aria-label="Effect preview canvas"
263
284
  ></canvas>
285
+ {#if previewError}
286
+ <div class="absolute inset-0 flex items-center justify-center p-4 text-center text-xs text-white/80" role="status" data-effect-preview-error>
287
+ {previewError}
288
+ </div>
289
+ {/if}
264
290
  </div>
265
291
  {#if current.issues.length > 0}
266
292
  <div class="space-y-1 rounded border border-destructive/20 bg-destructive/10 p-2 text-xs" data-effect-issues>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixerate/editor-svelte",
3
- "version": "0.123.0",
3
+ "version": "0.124.1",
4
4
  "description": "Svelte bindings and prompt/rich-text components for @pixerate/editor",
5
5
  "author": "Pixerate",
6
6
  "license": "MIT",
@@ -168,7 +168,7 @@
168
168
  "@tiptap/extension-bubble-menu": "^2.27.3",
169
169
  "@tiptap/extension-placeholder": "^2.27.3",
170
170
  "@tiptap/starter-kit": "^2.27.3",
171
- "@pixerate/editor": "0.166.0"
171
+ "@pixerate/editor": "0.168.0"
172
172
  },
173
173
  "peerDependencies": {
174
174
  "@dagrejs/dagre": "^1.1.4",