layerchart 0.36.5 → 0.37.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.
Files changed (55) hide show
  1. package/dist/components/Arc.svelte +4 -2
  2. package/dist/components/Arc.svelte.d.ts +4 -2
  3. package/dist/components/Area.svelte +2 -2
  4. package/dist/components/Area.svelte.d.ts +2 -2
  5. package/dist/components/Axis.svelte +59 -10
  6. package/dist/components/Axis.svelte.d.ts +6 -3
  7. package/dist/components/Calendar.svelte +2 -2
  8. package/dist/components/Chart.svelte +74 -31
  9. package/dist/components/Chart.svelte.d.ts +33 -6
  10. package/dist/components/Circle.svelte +2 -2
  11. package/dist/components/Circle.svelte.d.ts +2 -2
  12. package/dist/components/ClipPath.svelte +1 -1
  13. package/dist/components/ClipPath.svelte.d.ts +2 -2
  14. package/dist/components/GeoCircle.svelte +1 -1
  15. package/dist/components/GeoCircle.svelte.d.ts +2 -2
  16. package/dist/components/GeoContext.svelte +31 -7
  17. package/dist/components/GeoContext.svelte.d.ts +2 -0
  18. package/dist/components/GeoPath.svelte +12 -10
  19. package/dist/components/GeoPath.svelte.d.ts +5 -4
  20. package/dist/components/GeoPoint.svelte +1 -3
  21. package/dist/components/GeoTile.svelte +1 -3
  22. package/dist/components/Group.svelte +18 -1
  23. package/dist/components/Group.svelte.d.ts +4 -2
  24. package/dist/components/HitCanvas.svelte +86 -0
  25. package/dist/components/HitCanvas.svelte.d.ts +32 -0
  26. package/dist/components/Hull.svelte +4 -4
  27. package/dist/components/Hull.svelte.d.ts +3 -3
  28. package/dist/components/Line.svelte +2 -2
  29. package/dist/components/Line.svelte.d.ts +2 -2
  30. package/dist/components/Link.svelte +4 -4
  31. package/dist/components/Link.svelte.d.ts +4 -4
  32. package/dist/components/Pie.svelte +9 -2
  33. package/dist/components/Rect.svelte +4 -4
  34. package/dist/components/Rect.svelte.d.ts +4 -4
  35. package/dist/components/Spline.svelte +2 -2
  36. package/dist/components/Spline.svelte.d.ts +2 -2
  37. package/dist/components/TooltipContext.svelte +21 -18
  38. package/dist/components/TooltipContext.svelte.d.ts +4 -4
  39. package/dist/components/{Transform.svelte → TransformContext.svelte} +87 -76
  40. package/dist/components/TransformContext.svelte.d.ts +111 -0
  41. package/dist/components/Voronoi.svelte +13 -5
  42. package/dist/components/Voronoi.svelte.d.ts +3 -3
  43. package/dist/components/index.d.ts +1 -1
  44. package/dist/components/index.js +1 -1
  45. package/dist/components/layout/Canvas.svelte +78 -0
  46. package/dist/components/layout/Canvas.svelte.d.ts +37 -0
  47. package/dist/components/layout/Svg.svelte +68 -0
  48. package/dist/components/layout/Svg.svelte.d.ts +32 -0
  49. package/dist/docs/TransformControls.svelte +4 -2
  50. package/dist/docs/TransformControls.svelte.d.ts +1 -2
  51. package/dist/docs/TransformDebug.svelte +21 -0
  52. package/dist/docs/TransformDebug.svelte.d.ts +16 -0
  53. package/dist/utils/event.d.ts +1 -1
  54. package/package.json +1 -1
  55. package/dist/components/Transform.svelte.d.ts +0 -76
@@ -1,23 +1,53 @@
1
- <script>import { getContext, createEventDispatcher } from 'svelte';
1
+ <script context="module">import { getContext, setContext } from 'svelte';
2
+ import { writable } from 'svelte/store';
3
+ export const transformContextKey = Symbol();
4
+ const defaultContext = {
5
+ mode: 'none',
6
+ scale: writable(1),
7
+ translate: writable({ x: 0, y: 0 }),
8
+ dragging: writable(false),
9
+ reset: () => { },
10
+ zoomIn: () => { },
11
+ zoomOut: () => { },
12
+ translateCenter: () => { },
13
+ zoomTo: () => { },
14
+ };
15
+ export function transformContext() {
16
+ return getContext(transformContextKey) ?? defaultContext;
17
+ }
18
+ function setTransformContext(transform) {
19
+ setContext(transformContextKey, transform);
20
+ }
21
+ </script>
22
+
23
+ <script>import { createEventDispatcher } from 'svelte';
2
24
  import { motionStore } from '../stores/motionStore.js';
3
- const { width, height, padding } = getContext('LayerCake');
4
- export let mode = 'svg';
25
+ const { width, height } = getContext('LayerCake');
26
+ export let mode = 'none';
5
27
  export let translateOnScale = false;
6
28
  export let spring = undefined;
7
29
  export let tweened = undefined;
30
+ export let processTranslate = (x, y, deltaX, deltaY, scale) => {
31
+ return {
32
+ x: x + deltaX / scale,
33
+ y: y + deltaY / scale,
34
+ };
35
+ };
36
+ /** Disable pointer events including move/dragging */
8
37
  export let disablePointer = false;
38
+ /** Action to take during wheel scroll */
9
39
  export let scroll = 'none';
40
+ /** Distance/threshold to consider drag vs click (disable click propagation) */
10
41
  export let clickDistance = 10;
11
42
  const dispatch = createEventDispatcher();
12
- let dragging = false;
13
- let moved = false;
43
+ let pointerDown = false;
44
+ const dragging = writable(false);
14
45
  export let initialTranslate = { x: 0, y: 0 };
15
- const translate = motionStore(initialTranslate, { spring, tweened });
46
+ export const translate = motionStore(initialTranslate, { spring, tweened });
16
47
  export let initialScale = 1;
17
- const scale = motionStore(initialScale, { spring, tweened });
48
+ export const scale = motionStore(initialScale, { spring, tweened });
18
49
  let startPoint = { x: 0, y: 0 };
19
50
  let startTranslate = { x: 0, y: 0 };
20
- let svgEl = null;
21
51
  export function reset() {
22
52
  $translate = initialTranslate;
23
53
  $scale = initialScale;
@@ -44,44 +74,50 @@ export function zoomTo(center, rect) {
44
74
  $scale = $width < $height ? $width / rect.width : $height / rect.height;
45
75
  }
46
76
  }
47
- function onMouseDown(e) {
77
+ setTransformContext({
78
+ mode,
79
+ scale,
80
+ translate,
81
+ dragging,
82
+ reset,
83
+ zoomIn,
84
+ zoomOut,
85
+ translateCenter,
86
+ zoomTo,
87
+ });
88
+ function onPointerDown(e) {
48
89
  if (disablePointer)
49
90
  return;
50
91
  e.preventDefault();
51
- dragging = true;
52
- moved = false;
53
- svgEl = e.currentTarget.ownerSVGElement; // capture for reference in mousemove event
54
- startPoint = localPoint(svgEl, e);
92
+ pointerDown = true;
93
+ $dragging = false;
94
+ startPoint = localPoint(e);
55
95
  startTranslate = $translate;
56
- window.addEventListener('mousemove', onMouseMove, { capture: true });
57
- window.addEventListener('mouseup', onMouseUp);
58
96
  dispatch('dragstart');
59
97
  }
60
- function onMouseMove(e) {
61
- if (!dragging)
98
+ function onPointerMove(e) {
99
+ if (!pointerDown)
62
100
  return;
63
101
  e.preventDefault(); // Stop text selection
64
- e.stopPropagation(); // Stop tooltip from trigging (along with `capture: true`)
65
- const endPoint = localPoint(svgEl, e);
102
+ const endPoint = localPoint(e);
66
103
  const deltaX = endPoint.x - startPoint.x;
67
104
  const deltaY = endPoint.y - startPoint.y;
68
- translate.set({
69
- x: startTranslate.x + deltaX / (mode === 'manual' ? 1 : $scale),
70
- y: startTranslate.y + deltaY / (mode === 'manual' ? 1 : $scale),
71
- }, spring ? { hard: true } : tweened ? { duration: 0 } : undefined);
72
- if (!moved) {
105
+ if (!$dragging) {
73
106
  // If dragged beyond threshold, disable click propagation
74
- moved = deltaX * deltaX + deltaY * deltaY > clickDistance;
107
+ $dragging = deltaX * deltaX + deltaY * deltaY > clickDistance;
108
+ }
109
+ if ($dragging) {
110
+ e.stopPropagation(); // Stop tooltip from trigging (along with `capture: true`)
111
+ e.currentTarget.setPointerCapture(e.pointerId);
112
+ translate.set(processTranslate(startTranslate.x, startTranslate.y, deltaX, deltaY, $scale), spring ? { hard: true } : tweened ? { duration: 0 } : undefined);
75
113
  }
76
114
  }
77
- function onMouseUp(e) {
78
- dragging = false;
79
- window.removeEventListener('mousemove', onMouseMove);
80
- window.removeEventListener('mouseup', onMouseUp);
115
+ function onPointerUp(e) {
116
+ pointerDown = false;
81
117
  dispatch('dragend');
82
118
  }
83
119
  function onClick(e) {
84
- if (moved) {
120
+ if ($dragging) {
85
121
  // Do not propagate click event to children if drag/moved. Registered in capture phase (top-down)
86
122
  e.stopPropagation();
87
123
  }
@@ -89,15 +125,14 @@ function onClick(e) {
89
125
  function onDoubleClick(e) {
90
126
  if (disablePointer)
91
127
  return;
92
- const point = localPoint(svgEl, e);
128
+ const point = localPoint(e);
93
129
  scaleTo(e.shiftKey ? 0.5 : 2, point);
94
130
  }
95
131
  function onWheel(e) {
96
132
  if (scroll === 'none' || disablePointer)
97
133
  return;
98
134
  e.preventDefault();
99
- svgEl = e.currentTarget.ownerSVGElement;
100
- const point = (startPoint = localPoint(svgEl, e));
135
+ const point = (startPoint = localPoint(e));
101
136
  // Pinch to zoom is registered as a wheel event with control key
102
137
  const pinchToZoom = e.ctrlKey;
103
138
  if (scroll === 'scale' || pinchToZoom) {
@@ -106,10 +141,7 @@ function onWheel(e) {
106
141
  scaleTo(Math.pow(2, scaleBy), point, spring ? { hard: true } : tweened ? { duration: 0 } : undefined);
107
142
  }
108
143
  else if (scroll === 'translate') {
109
- translate.update((startTranslate) => ({
110
- x: startTranslate.x + -e.deltaX / (mode === 'manual' ? 1 : $scale),
111
- y: startTranslate.y + -e.deltaY / (mode === 'manual' ? 1 : $scale),
112
- }), spring ? { hard: true } : tweened ? { duration: 0 } : undefined);
144
+ translate.update((startTranslate) => processTranslate(startTranslate.x, startTranslate.y, -e.deltaX, -e.deltaY, $scale), spring ? { hard: true } : tweened ? { duration: 0 } : undefined);
113
145
  }
114
146
  }
115
147
  /**
@@ -132,59 +164,38 @@ function scaleTo(value, point, options = undefined) {
132
164
  translate.set(newTranslate, options);
133
165
  }
134
166
  }
135
- function localPoint(svgEl, e) {
136
- if (svgEl) {
137
- const screenCTM = svgEl.getScreenCTM();
138
- let point = svgEl.createSVGPoint();
139
- point.x = e.clientX;
140
- point.y = e.clientY;
141
- point = point.matrixTransform(screenCTM?.inverse());
142
- return {
143
- x: point.x,
144
- y: point.y,
145
- };
146
- }
147
- else {
148
- return {
149
- x: e.clientX,
150
- y: e.clientY,
151
- };
152
- }
167
+ function localPoint(e) {
168
+ return {
169
+ x: e.offsetX,
170
+ y: e.offsetY,
171
+ };
153
172
  }
154
173
  $: center = { x: $width / 2, y: $height / 2 };
155
174
  $: viewportCenter = {
156
175
  x: center.x - $translate.x,
157
176
  y: center.y - $translate.y,
158
177
  };
159
- let transform = '';
160
- $: if (mode === 'svg') {
161
- const newTranslate = {
162
- x: $translate.x * $scale + center.x - center.x * $scale,
163
- y: $translate.y * $scale + center.y - center.y * $scale,
164
- };
165
- transform = `translate(${newTranslate.x},${newTranslate.y}) scale(${$scale})`;
166
- }
167
178
  $: dispatch('transform', { scale: $scale, translate: $translate });
168
179
  </script>
169
180
 
170
- <g
181
+ <div
171
182
  on:mousewheel={onWheel}
172
- on:mousedown={onMouseDown}
183
+ on:pointerdown={onPointerDown}
184
+ on:pointermove={onPointerMove}
185
+ on:touchmove={(e) => {
186
+ // Touch events cause pointer events to be interrupted.
187
+ // Typically `touch-action: none` works, but doesn't appear to with SVG, but `preventDefault()` works here
188
+ // https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events#touch-action_css_property
189
+ e.preventDefault();
190
+ }}
191
+ on:pointerup={onPointerUp}
173
192
  on:dblclick={onDoubleClick}
174
193
  on:click|capture={onClick}
175
194
  on:click
176
195
  on:keydown
177
196
  on:keyup
178
197
  on:keypress
198
+ class="h-full"
179
199
  >
180
- <rect
181
- x={-$padding.left}
182
- y={-$padding.top}
183
- width={$width + $padding.left + $padding.right}
184
- height={$height + $padding.top + $padding.bottom}
185
- fill="transparent"
186
- />
187
- <g {transform}>
188
- <slot scale={$scale} {zoomTo} {reset} />
189
- </g>
190
- </g>
200
+ <slot transform={{ scale: $scale, translate: $translate, zoomTo, reset }} />
201
+ </div>
@@ -0,0 +1,111 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ import { type Readable, type Writable } from 'svelte/store';
3
+ export declare const transformContextKey: unique symbol;
4
+ export type TransformContextValue = {
5
+ mode: 'canvas' | 'none';
6
+ scale: Writable<number>;
7
+ translate: Writable<{
8
+ x: number;
9
+ y: number;
10
+ }>;
11
+ dragging: Readable<boolean>;
12
+ reset(): void;
13
+ zoomIn(): void;
14
+ zoomOut(): void;
15
+ translateCenter(): void;
16
+ zoomTo(center: {
17
+ x: number;
18
+ y: number;
19
+ }, rect?: {
20
+ width: number;
21
+ height: number;
22
+ }): void;
23
+ };
24
+ export type TransformContext = TransformContextValue;
25
+ export declare function transformContext(): TransformContext;
26
+ import { motionStore } from '../stores/motionStore.js';
27
+ declare const __propDef: {
28
+ props: {
29
+ mode?: "none" | "canvas" | undefined;
30
+ translateOnScale?: boolean | undefined;
31
+ spring?: boolean | Parameters<typeof motionStore>[1]['spring'];
32
+ tweened?: boolean | Parameters<typeof motionStore>[1]['tweened'];
33
+ processTranslate?: ((x: number, y: number, deltaX: number, deltaY: number, scale: number) => {
34
+ x: number;
35
+ y: number;
36
+ }) | undefined;
37
+ /** Disable pointer events including move/dragging */ disablePointer?: boolean | undefined;
38
+ /** Action to take during wheel scroll */ scroll?: "none" | "scale" | "translate" | undefined;
39
+ /** Distance/threshold to consider drag vs click (disable click propagation) */ clickDistance?: number | undefined;
40
+ initialTranslate?: {
41
+ x: number;
42
+ y: number;
43
+ } | undefined;
44
+ translate?: import("svelte/motion").Spring<any> | import("svelte/motion").Tweened<any> | Writable<any> | undefined;
45
+ initialScale?: number | undefined;
46
+ scale?: import("svelte/motion").Spring<any> | import("svelte/motion").Tweened<any> | Writable<any> | undefined;
47
+ reset?: (() => void) | undefined;
48
+ zoomIn?: (() => void) | undefined;
49
+ zoomOut?: (() => void) | undefined;
50
+ translateCenter?: (() => void) | undefined;
51
+ zoomTo?: ((center: {
52
+ x: number;
53
+ y: number;
54
+ }, rect?: {
55
+ width: number;
56
+ height: number;
57
+ }) => void) | undefined;
58
+ };
59
+ events: {
60
+ click: MouseEvent;
61
+ keydown: KeyboardEvent;
62
+ keyup: KeyboardEvent;
63
+ keypress: KeyboardEvent;
64
+ dragstart: CustomEvent<null>;
65
+ dragend: CustomEvent<null>;
66
+ transform: CustomEvent<{
67
+ scale: number;
68
+ translate: {
69
+ x: number;
70
+ y: number;
71
+ };
72
+ }>;
73
+ } & {
74
+ [evt: string]: CustomEvent<any>;
75
+ };
76
+ slots: {
77
+ default: {
78
+ transform: {
79
+ scale: any;
80
+ translate: any;
81
+ zoomTo: (center: {
82
+ x: number;
83
+ y: number;
84
+ }, rect?: {
85
+ width: number;
86
+ height: number;
87
+ }) => void;
88
+ reset: () => void;
89
+ };
90
+ };
91
+ };
92
+ };
93
+ export type TransformContextProps = typeof __propDef.props;
94
+ export type TransformContextEvents = typeof __propDef.events;
95
+ export type TransformContextSlots = typeof __propDef.slots;
96
+ export default class TransformContext extends SvelteComponentTyped<TransformContextProps, TransformContextEvents, TransformContextSlots> {
97
+ get translate(): NonNullable<import("svelte/motion").Spring<any> | import("svelte/motion").Tweened<any> | Writable<any> | undefined>;
98
+ get scale(): NonNullable<import("svelte/motion").Spring<any> | import("svelte/motion").Tweened<any> | Writable<any> | undefined>;
99
+ get reset(): () => void;
100
+ get zoomIn(): () => void;
101
+ get zoomOut(): () => void;
102
+ get translateCenter(): () => void;
103
+ get zoomTo(): (center: {
104
+ x: number;
105
+ y: number;
106
+ }, rect?: {
107
+ width: number;
108
+ height: number;
109
+ } | undefined) => void;
110
+ }
111
+ export {};
@@ -33,9 +33,13 @@ $: boundHeight = Math.max($height, 0);
33
33
  <GeoPath
34
34
  geojson={feature}
35
35
  class={cls('fill-transparent', classes.path)}
36
- on:mousemove={(e) =>
37
- dispatch('mousemove', { event: e, data: feature.properties.site.data, feature })}
38
- on:mouseleave
36
+ on:pointermove={(e) =>
37
+ dispatch('pointermove', { event: e, data: feature.properties.site.data, feature })}
38
+ on:pointerleave
39
+ on:touchmove={(e) => {
40
+ // Prevent touch to not interfer with pointer
41
+ e.preventDefault();
42
+ }}
39
43
  on:click={(e) => dispatch('click', { data: feature.properties.site.data, feature })}
40
44
  />
41
45
  {/each}
@@ -45,8 +49,12 @@ $: boundHeight = Math.max($height, 0);
45
49
  <path
46
50
  d={voronoi.renderCell(i)}
47
51
  class={cls('fill-transparent', classes.path)}
48
- on:mousemove={(e) => dispatch('mousemove', { event: e, data: point.data, point })}
49
- on:mouseleave
52
+ on:pointermove={(e) => dispatch('pointermove', { event: e, data: point.data, point })}
53
+ on:pointerleave
54
+ on:touchmove={(e) => {
55
+ // Prevent touch to not interfer with pointer
56
+ e.preventDefault();
57
+ }}
50
58
  on:click={(e) => dispatch('click', { data: point.data, point })}
51
59
  />
52
60
  {/each}
@@ -10,14 +10,14 @@ declare const __propDef: {
10
10
  } | undefined;
11
11
  };
12
12
  events: {
13
- mouseleave: MouseEvent;
13
+ pointerleave: PointerEvent;
14
14
  click: CustomEvent<{
15
15
  data: any;
16
16
  point?: [number, number] | undefined;
17
17
  feature?: GeoPermissibleObjects | undefined;
18
18
  }>;
19
- mousemove: CustomEvent<{
20
- event: MouseEvent;
19
+ pointermove: CustomEvent<{
20
+ event: PointerEvent;
21
21
  data: any;
22
22
  point?: [number, number] | undefined;
23
23
  feature?: GeoPermissibleObjects | undefined;
@@ -51,7 +51,7 @@ export { default as Tooltip } from './Tooltip.svelte';
51
51
  export { default as TooltipContext } from './TooltipContext.svelte';
52
52
  export { default as TooltipItem } from './TooltipItem.svelte';
53
53
  export { default as TooltipSeparator } from './TooltipSeparator.svelte';
54
+ export { default as TransformContext, transformContext } from './TransformContext.svelte';
54
55
  export { default as Tree } from './Tree.svelte';
55
56
  export { default as Treemap } from './Treemap.svelte';
56
57
  export { default as Voronoi } from './Voronoi.svelte';
57
- export { default as Transform } from './Transform.svelte';
@@ -51,7 +51,7 @@ export { default as Tooltip } from './Tooltip.svelte';
51
51
  export { default as TooltipContext } from './TooltipContext.svelte';
52
52
  export { default as TooltipItem } from './TooltipItem.svelte';
53
53
  export { default as TooltipSeparator } from './TooltipSeparator.svelte';
54
+ export { default as TransformContext, transformContext } from './TransformContext.svelte';
54
55
  export { default as Tree } from './Tree.svelte';
55
56
  export { default as Treemap } from './Treemap.svelte';
56
57
  export { default as Voronoi } from './Voronoi.svelte';
57
- export { default as Transform } from './Transform.svelte';
@@ -0,0 +1,78 @@
1
+ <script>import { getContext, onMount, setContext } from 'svelte';
2
+ import { writable } from 'svelte/store';
3
+ import { scaleCanvas } from 'layercake';
4
+ import { cls } from 'svelte-ux';
5
+ import { transformContext } from '../TransformContext.svelte';
6
+ const { width, height, padding } = getContext('LayerCake');
7
+ /** The `<canvas>` tag. Useful for bindings. */
8
+ export let element = undefined;
9
+ /** The `<canvas>`'s 2d context. Useful for bindings. */
10
+ export let context = undefined;
11
+ /** Force the use of a software (instead of hardware accelerated) 2D canvas and can save memory when calling getImageData() frequently.
12
+ * see: https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/getContext#willreadfrequently */
13
+ export let willReadFrequently = false;
14
+ /** The layer's z-index. */
15
+ export let zIndex = undefined;
16
+ /** Set this to `false` to set `pointer-events: none;` on the entire layer. */
17
+ export let pointerEvents = undefined;
18
+ /** Text to display if the browser won't render a canvas tag. You can also set arbitrary HTML via the "fallback" slot but this is fine if you just need text. If you use the "fallback" slot, this prop is ignored. */
19
+ export let fallback = '';
20
+ /** A string passed to the `aria-label` on the `<canvas>` tag. */
21
+ export let label = undefined;
22
+ /** A string passed to the `aria-labelledby` on the `<canvas>` tag. */
23
+ export let labelledBy = undefined;
24
+ /** A string passed to `aria-describedby` property on the `<canvas>` tag. */
25
+ export let describedBy = undefined;
26
+ const ctx = writable({});
27
+ onMount(() => {
28
+ context = element?.getContext('2d', { willReadFrequently });
29
+ });
30
+ const { mode, scale, translate } = transformContext();
31
+ $: if (context) {
32
+ scaleCanvas(context, $width, $height);
33
+ context.clearRect(0, 0, $width, $height);
34
+ if (mode === 'canvas') {
35
+ const center = { x: $width / 2, y: $height / 2 };
36
+ const newTranslate = {
37
+ x: $translate.x * $scale + center.x - center.x * $scale,
38
+ y: $translate.y * $scale + center.y - center.y * $scale,
39
+ };
40
+ context.translate(newTranslate.x, newTranslate.y);
41
+ context.scale($scale, $scale);
42
+ }
43
+ // Force children to re-draw
44
+ $ctx = context;
45
+ }
46
+ $: ctx.set(context);
47
+ setContext('canvas', { ctx });
48
+ </script>
49
+
50
+ <canvas
51
+ bind:this={element}
52
+ style:top="{$padding.top}px"
53
+ style:right="{$padding.right}px"
54
+ style:bottom="{$padding.bottom}px"
55
+ style:left="{$padding.left}px"
56
+ style:z-index={zIndex}
57
+ class={cls(
58
+ 'layercake-layout-canvas',
59
+ 'absolute w-full h-full',
60
+ pointerEvents === false && 'pointer-events-none',
61
+ $$restProps.class
62
+ )}
63
+ aria-label={label}
64
+ aria-labelledby={labelledBy}
65
+ aria-describedby={describedBy}
66
+ on:pointerenter
67
+ on:pointermove
68
+ on:pointerleave
69
+ on:pointerleave
70
+ on:touchmove
71
+ on:click
72
+ >
73
+ <slot name="fallback">
74
+ {fallback || ''}
75
+ </slot>
76
+ </canvas>
77
+
78
+ <slot {element} {context}></slot>
@@ -0,0 +1,37 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ [x: string]: any;
5
+ element?: HTMLCanvasElement | undefined;
6
+ context?: CanvasRenderingContext2D | undefined;
7
+ willReadFrequently?: boolean | undefined;
8
+ zIndex?: undefined;
9
+ pointerEvents?: boolean | undefined;
10
+ fallback?: string | undefined;
11
+ label?: string | undefined;
12
+ labelledBy?: string | undefined;
13
+ describedBy?: string | undefined;
14
+ };
15
+ events: {
16
+ pointerenter: PointerEvent;
17
+ pointermove: PointerEvent;
18
+ pointerleave: PointerEvent;
19
+ touchmove: TouchEvent;
20
+ click: MouseEvent;
21
+ } & {
22
+ [evt: string]: CustomEvent<any>;
23
+ };
24
+ slots: {
25
+ fallback: {};
26
+ default: {
27
+ element: HTMLCanvasElement | undefined;
28
+ context: CanvasRenderingContext2D;
29
+ };
30
+ };
31
+ };
32
+ export type CanvasProps = typeof __propDef.props;
33
+ export type CanvasEvents = typeof __propDef.events;
34
+ export type CanvasSlots = typeof __propDef.slots;
35
+ export default class Canvas extends SvelteComponentTyped<CanvasProps, CanvasEvents, CanvasSlots> {
36
+ }
37
+ export {};
@@ -0,0 +1,68 @@
1
+ <script>import { getContext } from 'svelte';
2
+ import { cls } from 'svelte-ux';
3
+ import { transformContext } from '../TransformContext.svelte';
4
+ /** The layer's `<svg>` tag. Useful for bindings. */
5
+ export let element = undefined;
6
+ /** The layer's `<g>` tag. Useful for bindings. */
7
+ export let innerElement = undefined;
8
+ /** The layer's z-index. */
9
+ export let zIndex = undefined;
10
+ /** Set this to `false` to set `pointer-events: none;` on the entire layer. */
11
+ export let pointerEvents = undefined;
12
+ /** A string passed to the `viewBox` property on the `<svg>` tag. */
13
+ export let viewBox = undefined;
14
+ /** A string passed to the `aria-label` property on the `<svg>` tag. */
15
+ export let label = undefined;
16
+ /** A string passed to the `aria-labelledby property` on the `<svg>` tag. */
17
+ export let labelledBy = undefined;
18
+ /** A string passed to the `aria-describedby` property on the `<svg>` tag. */
19
+ export let describedBy = undefined;
20
+ /** Shorthand to set the contents of `<title></title>` for accessibility. You can also set arbitrary HTML via the "title" slot but this is a convenient shorthand. If you use the "title" slot, this prop is ignored. */
21
+ export let title = undefined;
22
+ const { containerWidth, containerHeight, width, height, padding } = getContext('LayerCake');
23
+ const { mode, scale, translate } = transformContext();
24
+ let transform = '';
25
+ $: if (mode === 'canvas') {
26
+ const center = { x: $width / 2, y: $height / 2 };
27
+ const newTranslate = {
28
+ x: $translate.x * $scale + center.x - center.x * $scale,
29
+ y: $translate.y * $scale + center.y - center.y * $scale,
30
+ };
31
+ transform = `translate(${newTranslate.x},${newTranslate.y}) scale(${$scale})`;
32
+ }
33
+ </script>
34
+
35
+ <svg
36
+ bind:this={element}
37
+ {viewBox}
38
+ width={$containerWidth}
39
+ height={$containerHeight}
40
+ style:z-index={zIndex}
41
+ class={cls(
42
+ 'layercake-layout-svg',
43
+ 'absolute top-0 left-0 overflow-visible',
44
+ pointerEvents === false && 'pointer-events-none'
45
+ )}
46
+ aria-label={label}
47
+ aria-labelledby={labelledBy}
48
+ aria-describedby={describedBy}
49
+ on:click
50
+ >
51
+ <slot name="title">
52
+ {#if title}<title>{title}</title>{/if}
53
+ </slot>
54
+
55
+ <defs>
56
+ <slot name="defs"></slot>
57
+ </defs>
58
+
59
+ <g
60
+ bind:this={innerElement}
61
+ class="layercake-layout-svg_g"
62
+ transform="translate({$padding.left}, {$padding.top})"
63
+ >
64
+ <g {transform}>
65
+ <slot {element}></slot>
66
+ </g>
67
+ </g>
68
+ </svg>
@@ -0,0 +1,32 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ /** The layer's `<svg>` tag. Useful for bindings. */ element?: SVGElement | undefined;
5
+ /** The layer's `<g>` tag. Useful for bindings. */ innerElement?: SVGGElement | undefined;
6
+ /** The layer's z-index. */ zIndex?: undefined;
7
+ /** Set this to `false` to set `pointer-events: none;` on the entire layer. */ pointerEvents?: boolean | undefined;
8
+ /** A string passed to the `viewBox` property on the `<svg>` tag. */ viewBox?: string | undefined;
9
+ /** A string passed to the `aria-label` property on the `<svg>` tag. */ label?: string | undefined;
10
+ /** A string passed to the `aria-labelledby property` on the `<svg>` tag. */ labelledBy?: string | undefined;
11
+ /** A string passed to the `aria-describedby` property on the `<svg>` tag. */ describedBy?: string | undefined;
12
+ /** Shorthand to set the contents of `<title></title>` for accessibility. You can also set arbitrary HTML via the "title" slot but this is a convenient shorthand. If you use the "title" slot, this prop is ignored. */ title?: string | undefined;
13
+ };
14
+ events: {
15
+ click: MouseEvent;
16
+ } & {
17
+ [evt: string]: CustomEvent<any>;
18
+ };
19
+ slots: {
20
+ title: {};
21
+ defs: {};
22
+ default: {
23
+ element: SVGElement | undefined;
24
+ };
25
+ };
26
+ };
27
+ export type SvgProps = typeof __propDef.props;
28
+ export type SvgEvents = typeof __propDef.events;
29
+ export type SvgSlots = typeof __propDef.slots;
30
+ export default class Svg extends SvelteComponentTyped<SvgProps, SvgEvents, SvgSlots> {
31
+ }
32
+ export {};
@@ -1,8 +1,9 @@
1
1
  <script>import { Button, Tooltip, cls } from 'svelte-ux';
2
2
  import { mdiArrowULeftTop, mdiMagnifyPlusOutline, mdiMagnifyMinusOutline, mdiImageFilterCenterFocus, } from '@mdi/js';
3
- export let transform;
3
+ import { transformContext } from '../components/TransformContext.svelte';
4
4
  export let placement = 'top-right';
5
5
  export let orientation = 'vertical';
6
+ const transform = transformContext();
6
7
  </script>
7
8
 
8
9
  <div
@@ -19,7 +20,8 @@ export let orientation = 'vertical';
19
20
  'bottom-left': 'absolute bottom-0 left-0',
20
21
  bottom: 'absolute bottom-0 left-1/2 -translate-x-1/2',
21
22
  'bottom-right': 'absolute bottom-0 right-0',
22
- }[placement]
23
+ }[placement],
24
+ $$props.class
23
25
  )}
24
26
  >
25
27
  <Tooltip title="Zoom in">
@@ -1,8 +1,7 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
- import type Transform from '../components/Transform.svelte';
3
2
  declare const __propDef: {
4
3
  props: {
5
- transform: Transform;
4
+ [x: string]: any;
6
5
  placement?: ("center" | "top" | "bottom" | "left" | "right" | "top-left" | "top-right" | "bottom-left" | "bottom-right") | undefined;
7
6
  orientation?: "horizontal" | "vertical" | undefined;
8
7
  };