@pixerate/editor-svelte 0.127.1 → 0.128.2

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/README.md CHANGED
@@ -4,6 +4,9 @@ Svelte 5 bindings for [`@pixerate/editor`](https://www.npmjs.com/package/@pixera
4
4
 
5
5
  ```bash
6
6
  npm install @pixerate/editor-svelte @pixerate/editor svelte
7
+ # only if you use the rich-text or prompt editors (the root entry): TipTap, and the rich-text peers
8
+ # listed in the @pixerate/editor README
9
+ npm install @tiptap/extension-bubble-menu @tiptap/core @tiptap/pm @tiptap/starter-kit @tiptap/extension-placeholder
7
10
  # only if you use @pixerate/editor-svelte/canvas:
8
11
  npm install @xyflow/svelte @dagrejs/dagre
9
12
  ```
@@ -1,8 +1,10 @@
1
1
  <script lang="ts">
2
- import { onDestroy } from 'svelte';
2
+ import { onDestroy, type Snippet } from 'svelte';
3
3
  import {
4
4
  CSS_VARIABLE_CHART_THEME,
5
5
  chartClientToScene,
6
+ chartTooltipAt,
7
+ sameChartTooltip,
6
8
  describeChartSelection,
7
9
  handleChartKey,
8
10
  layoutChart,
@@ -12,7 +14,9 @@
12
14
  type ChartPresence,
13
15
  type ChartScene,
14
16
  type ChartTextMeasure,
15
- type ChartTheme
17
+ type ChartTheme,
18
+ type ChartTooltip,
19
+ type ChartTooltipMode
16
20
  } from '@pixerate/editor/chart';
17
21
  import { chartStateOf } from './createChartEditor.svelte.js';
18
22
  import ChartMarks from './ChartMarks.svelte';
@@ -38,6 +42,10 @@
38
42
  presence?: ChartPresence;
39
43
  /** Receives the scene as drawn (e.g. for `ChartDirector`'s `scene`). */
40
44
  sceneRef?: { current: ChartScene | null };
45
+ /** Show a tooltip on hover: `point` (or `true`) for the bar, point or slice under the pointer, `category` for every series in the category under it (default off). */
46
+ tooltip?: boolean | ChartTooltipMode;
47
+ /** Draws the tooltip's content instead of the category label and one row per series. */
48
+ tooltipContent?: Snippet<[ChartTooltip]>;
41
49
  }
42
50
 
43
51
  let {
@@ -51,7 +59,9 @@
51
59
  emptyMessage,
52
60
  class: className = '',
53
61
  presence,
54
- sceneRef
62
+ sceneRef,
63
+ tooltip = false,
64
+ tooltipContent
55
65
  }: Props = $props();
56
66
 
57
67
  const view = chartStateOf(() => controller);
@@ -94,6 +104,10 @@
94
104
  $effect(() => {
95
105
  if (sceneRef) sceneRef.current = scene;
96
106
  });
107
+ const tooltipMode = $derived<ChartTooltipMode | null>(tooltip === true ? 'point' : tooltip || null);
108
+ let tip = $state.raw<ChartTooltip | null>(null);
109
+ // In wrapper pixels; `flip` puts the tooltip left of the pointer near the right edge.
110
+ let tipAt = $state({ left: 0, top: 0, flip: false });
97
111
  const byKey = $derived(new Map(scene.marks.map((m) => [m.key, m])));
98
112
  const label = $derived(view.current.spec.title || 'Chart');
99
113
 
@@ -108,12 +122,26 @@
108
122
  controller.select(target ?? null);
109
123
  drag = startChartPointDrag(controller, scene, target, scenePoint(e));
110
124
  if (drag) {
125
+ tip = null;
111
126
  frozen = { valueDomain: drag.valueDomain, valueDomain2: drag.valueDomain2 ?? null, xDomain: drag.xDomain ?? null, readout: drag.target };
112
127
  svg?.setPointerCapture?.(e.pointerId);
113
128
  }
114
129
  }
115
130
  function pointermove(e: PointerEvent) {
116
131
  drag?.move(scenePoint(e), { fine: e.altKey, lockAxis: e.shiftKey, noSnap: e.ctrlKey || e.metaKey });
132
+ hover(e);
133
+ }
134
+ function hover(e: PointerEvent) {
135
+ if (!tooltipMode || drag || !wrapper) {
136
+ tip = null;
137
+ return;
138
+ }
139
+ const next = chartTooltipAt(view.current.spec, scene, scenePoint(e), { mode: tooltipMode, measureText });
140
+ if (!sameChartTooltip(tip, next)) tip = next;
141
+ if (!next) return;
142
+ const box = wrapper.getBoundingClientRect();
143
+ const left = e.clientX - box.left;
144
+ tipAt = { left, top: e.clientY - box.top, flip: left > box.width * 0.6 };
117
145
  }
118
146
  function endDrag() {
119
147
  drag?.end();
@@ -132,7 +160,7 @@
132
160
  }
133
161
  </script>
134
162
 
135
- <div bind:this={wrapper} class="w-full {className}" data-chart-canvas="">
163
+ <div bind:this={wrapper} class="relative w-full {className}" data-chart-canvas="">
136
164
  <!-- svelte-ignore a11y_no_noninteractive_tabindex, a11y_no_noninteractive_element_interactions -->
137
165
  <svg
138
166
  bind:this={svg}
@@ -147,9 +175,31 @@
147
175
  onpointermove={pointermove}
148
176
  onpointerup={endDrag}
149
177
  onpointercancel={endDrag}
178
+ onpointerleave={() => (tip = null)}
150
179
  onkeydown={keydown}
151
180
  >
152
181
  <ChartMarks marks={scene.marks} fontFamily={scene.theme.fontFamily} interactive={editable} />
153
182
  {#if presence}<ChartPresenceLayer {presence} />{/if}
154
183
  </svg>
184
+ {#if tip}
185
+ <div
186
+ role="tooltip"
187
+ data-chart-tooltip=""
188
+ class="pointer-events-none absolute z-10 min-w-32 rounded-md border px-2.5 py-1.5 text-xs shadow-md"
189
+ style="left: {tipAt.left}px; top: {tipAt.top}px; transform: translate({tipAt.flip ? 'calc(-100% - 12px)' : '12px'}, calc(-100% - 8px)); background: var(--popover, #ffffff); color: var(--popover-foreground, #0f172a); border-color: var(--border, #e2e8f0); font-family: {scene.theme.fontFamily};"
190
+ >
191
+ {#if tooltipContent}
192
+ {@render tooltipContent(tip)}
193
+ {:else}
194
+ {#if tip.title}<div class="mb-1 font-medium">{tip.title}</div>{/if}
195
+ {#each tip.items as item (item.seriesId)}
196
+ <div class="flex items-center gap-2">
197
+ <span class="h-2 w-2 shrink-0 rounded-full" style="background: {item.color}"></span>
198
+ <span style="color: var(--muted-foreground, #64748b)">{item.name}</span>
199
+ <span class="ml-auto pl-3 font-medium tabular-nums">{item.text}</span>
200
+ </div>
201
+ {/each}
202
+ {/if}
203
+ </div>
204
+ {/if}
155
205
  </div>
@@ -1,4 +1,5 @@
1
- import { type ChartController, type ChartPresence, type ChartScene, type ChartTextMeasure, type ChartTheme } from '@pixerate/editor/chart';
1
+ import { type Snippet } from 'svelte';
2
+ import { type ChartController, type ChartPresence, type ChartScene, type ChartTextMeasure, type ChartTheme, type ChartTooltip, type ChartTooltipMode } from '@pixerate/editor/chart';
2
3
  interface Props {
3
4
  controller: ChartController;
4
5
  /** Scene width; with `responsive` this is only the fallback before the container is measured (default 640). */
@@ -21,6 +22,10 @@ interface Props {
21
22
  sceneRef?: {
22
23
  current: ChartScene | null;
23
24
  };
25
+ /** Show a tooltip on hover: `point` (or `true`) for the bar, point or slice under the pointer, `category` for every series in the category under it (default off). */
26
+ tooltip?: boolean | ChartTooltipMode;
27
+ /** Draws the tooltip's content instead of the category label and one row per series. */
28
+ tooltipContent?: Snippet<[ChartTooltip]>;
24
29
  }
25
30
  declare const ChartCanvas: import("svelte").Component<Props, {}, "">;
26
31
  type ChartCanvas = ReturnType<typeof ChartCanvas>;
package/dist/index.d.ts CHANGED
@@ -13,6 +13,7 @@ export * from "./createNavigationGuard.svelte.js";
13
13
  export * from "./history/index.js";
14
14
  export * from "./fileImport.svelte.js";
15
15
  export * from "./docxExport.svelte.js";
16
+ export { formatCommandsFor, type FormatManifest, type FormatManifestCommand, type CodeLanguageOption, type FormatCommandOptions } from "@pixerate/editor";
16
17
  export * from "./agentTools.svelte.js";
17
18
  export * from "./playback/index.js";
18
19
  export * from "./toolBridge.svelte.js";
package/dist/index.js CHANGED
@@ -4,6 +4,7 @@ export * from "./createNavigationGuard.svelte.js";
4
4
  export * from "./history/index.js";
5
5
  export * from "./fileImport.svelte.js";
6
6
  export * from "./docxExport.svelte.js";
7
+ export { formatCommandsFor } from "@pixerate/editor";
7
8
  export * from "./agentTools.svelte.js";
8
9
  export * from "./playback/index.js";
9
10
  export * from "./toolBridge.svelte.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixerate/editor-svelte",
3
- "version": "0.127.1",
3
+ "version": "0.128.2",
4
4
  "description": "Svelte bindings and prompt/rich-text components for @pixerate/editor",
5
5
  "author": "Pixerate",
6
6
  "license": "MIT",
@@ -165,15 +165,15 @@
165
165
  "**/*.css"
166
166
  ],
167
167
  "dependencies": {
168
- "@tiptap/extension-bubble-menu": "^2.27.3",
169
- "@tiptap/extension-placeholder": "^2.27.3",
170
- "@tiptap/starter-kit": "^2.27.3",
171
- "@pixerate/editor": "0.171.0"
168
+ "@pixerate/editor": "0.174.0"
172
169
  },
173
170
  "peerDependencies": {
174
171
  "@dagrejs/dagre": "^1.1.4",
175
172
  "@tiptap/core": "^2.27.3",
173
+ "@tiptap/extension-bubble-menu": "^2.27.3",
174
+ "@tiptap/extension-placeholder": "^2.27.3",
176
175
  "@tiptap/pm": "^2.27.3",
176
+ "@tiptap/starter-kit": "^2.27.3",
177
177
  "@xyflow/svelte": "^1.6.0",
178
178
  "svelte": "^5.57.2"
179
179
  },
@@ -181,6 +181,21 @@
181
181
  "@dagrejs/dagre": {
182
182
  "optional": true
183
183
  },
184
+ "@tiptap/core": {
185
+ "optional": true
186
+ },
187
+ "@tiptap/extension-bubble-menu": {
188
+ "optional": true
189
+ },
190
+ "@tiptap/extension-placeholder": {
191
+ "optional": true
192
+ },
193
+ "@tiptap/pm": {
194
+ "optional": true
195
+ },
196
+ "@tiptap/starter-kit": {
197
+ "optional": true
198
+ },
184
199
  "@xyflow/svelte": {
185
200
  "optional": true
186
201
  }
@@ -190,7 +205,10 @@
190
205
  "@sveltejs/package": "^3.0.1",
191
206
  "@sveltejs/vite-plugin-svelte": "^5.0.3",
192
207
  "@tiptap/core": "^2.27.3",
208
+ "@tiptap/extension-bubble-menu": "^2.27.3",
209
+ "@tiptap/extension-placeholder": "^2.27.3",
193
210
  "@tiptap/pm": "^2.27.3",
211
+ "@tiptap/starter-kit": "^2.27.3",
194
212
  "@types/dagre": "^0.7.52",
195
213
  "@xyflow/svelte": "^1.7.0",
196
214
  "svelte": "^5.57.2",