@astryxdesign/vega 0.5.2-canary.c9c8564 → 0.5.2-canary.cb13c1e

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
@@ -17,6 +17,7 @@ Renders [Vega](https://vega.github.io/vega/) and [Vega-Lite](https://vega.github
17
17
  | `tsup.config.ts` | Config | Build config: CJS + ESM + `.d.ts` outputs |
18
18
  | `src/index.ts` | Barrel | Public API surface |
19
19
  | `src/VegaChart.tsx` | Component | Inspects `$schema`, compiles or renders, owns View lifecycle |
20
+ | `src/viewInputs.ts` | Utility | Detects value changes in the props that own the View |
20
21
  | `src/schema.ts` | Utility | Parses and validates Vega/Vega-Lite `$schema` URLs |
21
22
  | `src/types.ts` | Types | Shared TypeScript types for this package |
22
23
 
@@ -133,9 +134,51 @@ import {VegaChart} from '@astryxdesign/vega';
133
134
  | -------------------- | --------- | --------------------------------------------------------- |
134
135
  | `ast` | `boolean` | Retain expression AST in the runtime (useful for tooling) |
135
136
 
137
+ ### View lifecycle
138
+
139
+ `<VegaChart>` builds a Vega `View` on mount and finalizes it on unmount. In
140
+ between, it rebuilds the View only when `spec`, `compileOptions`,
141
+ `parseConfig`, `parseOptions`, or `viewOptions` **changes value** — these props
142
+ are compared by value against the values the live View was built from, not by
143
+ reference. Two consequences, and you need neither `useMemo` nor a discipline
144
+ about object identity for either:
145
+
146
+ - an object literal rebuilt inline on every render does **not** tear the chart
147
+ down;
148
+ - a spec you edit **in place** — held in a ref, a module constant, or shared
149
+ between renders — **is** picked up, because the comparison is against a copy
150
+ taken when the View was built, not against the previous props.
151
+
152
+ Functions inside those props (a `tooltip` handler, `logger`, `loader`, `expr`,
153
+ or `fieldTitle`) and class instances are compared by reference, since their
154
+ behavior lives in methods a copy cannot capture: replace the value rather than
155
+ mutating it.
156
+
157
+ Two shapes cannot be copied for comparison: a subtree that re-enters an object
158
+ already on its own path (a reference cycle), and one nested deeper than 100
159
+ levels. Those parts are compared **by reference**, so passing the **same**
160
+ object again is stable — a chart built from a cyclic spec is not rebuilt on
161
+ every render — while passing a **new** object rebuilds the View even when it
162
+ holds equal values.
163
+
164
+ What that costs differs between the two:
165
+
166
+ - **A cycle hides nothing.** Its re-entry edge points back at an object the
167
+ copy already walked, so an in-place edit anywhere in a cyclic spec is still
168
+ detected normally.
169
+ - **Past 100 levels, an in-place edit is invisible** — the reference did not
170
+ change and the values below were never copied. Replace the object, or drive
171
+ the View through `onReady`, to update from down there.
172
+
173
+ Everything the copy did reach is compared by value either way, so a mutation
174
+ elsewhere in the spec is picked up even when part of it is opaque.
175
+
176
+ Everything else is inert to the lifecycle: `data`, `className`, `style`,
177
+ `onReady`, and `onError` never rebuild the View.
178
+
136
179
  ### Data loading
137
180
 
138
- `data` maps dataset names to tuple arrays and is applied via `view.data(name, tuples)` during View initialization, before the first render. It is _not reactive_; changes after mount are ignored.
181
+ `data` maps dataset names to tuple arrays and is applied via `view.data(name, tuples)` during View initialization, before the first render. It is _not reactive_; changes after mount are ignored, and a new `data` object never rebuilds the View by itself. (When something else rebuilds the View, the new View loads whatever `data` holds at that moment.)
139
182
 
140
183
  To update data dynamically after render, use `onReady` to get the live View and drive it yourself:
141
184
 
@@ -23,17 +23,24 @@ import type { VegaChartProps } from './types';
23
23
  * new vega.View(runtime, { ...viewOptions, container })
24
24
  *
25
25
  * Initial dataset values can be provided via `data`. They are loaded once
26
- * during View initialization, before the first render, and are not reactive.
26
+ * during View initialization, before the first render, and are not reactive:
27
+ * a change to `data` alone never rebuilds the View, and is not applied to the
28
+ * live one. Use `onReady` to drive data after mount.
27
29
  *
28
30
  * It owns the full `View` lifecycle: creates the view on mount, re-creates
29
- * it when `spec`, `parseConfig`, `parseOptions`, or `viewOptions` changes,
30
- * and calls `view.finalize()` on cleanup to release all runtime resources.
31
+ * it when `spec`, `compileOptions`, `parseConfig`, `parseOptions`, or
32
+ * `viewOptions` changes, and calls `view.finalize()` on cleanup to release
33
+ * all runtime resources.
34
+ *
35
+ * "Changes" means the value changed, not the reference: those props are
36
+ * compared by value against a copy taken when the live View was built, so an
37
+ * inline spec or options object rebuilt on every render keeps the live View
38
+ * (and its zoom, hover, and signal state), while a spec mutated in place is
39
+ * still picked up. Nothing needs to be memoized for either to hold.
31
40
  *
32
41
  * Callbacks (`onReady`, `onError`) are non-reactive Effect Events -- they
33
42
  * always see the latest props and never re-run the View lifecycle, so you
34
- * don't need to memoize them. Pass stable references (or `useMemo`)
35
- * for `parseConfig`, `parseOptions`, `viewOptions`, and `data` to avoid
36
- * unnecessary re-renders.
43
+ * don't need to memoize them.
37
44
  *
38
45
  * Note: this component does not accept `xstyle` because `@astryxdesign/vega` does not
39
46
  * depend on StyleX. Use `className` or `style` for layout overrides.
@@ -1 +1 @@
1
- {"version":3,"file":"VegaChart.d.ts","sourceRoot":"","sources":["../src/VegaChart.tsx"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,OAAO,KAA0C,MAAM,OAAO,CAAC;AAI/D,OAAO,KAAK,EAAC,cAAc,EAAyB,MAAM,SAAS,CAAC;AAEpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,wBAAgB,SAAS,CAAC,EACxB,IAAI,EACJ,IAAI,EACJ,cAAc,EACd,WAAW,EACX,YAAY,EACZ,WAAW,EACX,SAAS,EACT,KAAK,EACL,GAAG,EACH,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,WAAW,EACpB,GAAG,KAAK,EACT,EAAE,cAAc,qBAiGhB;yBA9Ge,SAAS"}
1
+ {"version":3,"file":"VegaChart.d.ts","sourceRoot":"","sources":["../src/VegaChart.tsx"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,OAAO,KAAoD,MAAM,OAAO,CAAC;AAMzE,OAAO,KAAK,EAAC,cAAc,EAAyB,MAAM,SAAS,CAAC;AAEpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8DG;AACH,wBAAgB,SAAS,CAAC,EACxB,IAAI,EACJ,IAAI,EACJ,cAAc,EACd,WAAW,EACX,YAAY,EACZ,WAAW,EACX,SAAS,EACT,KAAK,EACL,GAAG,EACH,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,WAAW,EACpB,GAAG,KAAK,EACT,EAAE,cAAc,qBAsIhB;yBAnJe,SAAS"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=VegaChart.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VegaChart.test.d.ts","sourceRoot":"","sources":["../src/VegaChart.test.tsx"],"names":[],"mappings":""}
package/dist/index.js CHANGED
@@ -29,6 +29,67 @@ function parseSchema(schema) {
29
29
  return { ok: true, library, version };
30
30
  }
31
31
 
32
+ // src/viewInputs.ts
33
+ var MAX_DEPTH = 100;
34
+ var OPAQUE = /* @__PURE__ */ Symbol("astryx.vega.opaque");
35
+ function opaque(value) {
36
+ return { [OPAQUE]: value };
37
+ }
38
+ function isOpaque(value) {
39
+ return typeof value === "object" && value !== null && OPAQUE in value;
40
+ }
41
+ function latchViewInputs(inputs) {
42
+ return { inputs, snapshot: snapshotValue(inputs, 0, /* @__PURE__ */ new Set()) };
43
+ }
44
+ function latchIsCurrent(latch, inputs) {
45
+ return matchesSnapshot(latch.snapshot, inputs);
46
+ }
47
+ function snapshotValue(value, depth, path) {
48
+ if (!isWalkable(value)) {
49
+ return value;
50
+ }
51
+ if (depth >= MAX_DEPTH || path.has(value)) {
52
+ return opaque(value);
53
+ }
54
+ path.add(value);
55
+ const copy = Array.isArray(value) ? value.map((item) => snapshotValue(item, depth + 1, path)) : Object.fromEntries(
56
+ Object.entries(value).map(([key, entry]) => [
57
+ key,
58
+ snapshotValue(entry, depth + 1, path)
59
+ ])
60
+ );
61
+ path.delete(value);
62
+ return copy;
63
+ }
64
+ function matchesSnapshot(snapshot, value) {
65
+ if (isOpaque(snapshot)) {
66
+ return Object.is(snapshot[OPAQUE], value);
67
+ }
68
+ if (Array.isArray(snapshot)) {
69
+ return Array.isArray(value) && snapshot.length === value.length && snapshot.every((item, index) => matchesSnapshot(item, value[index]));
70
+ }
71
+ if (isPlainObject(snapshot)) {
72
+ if (!isPlainObject(value)) {
73
+ return false;
74
+ }
75
+ const keys = Object.keys(snapshot);
76
+ return keys.length === Object.keys(value).length && keys.every(
77
+ (key) => Object.prototype.hasOwnProperty.call(value, key) && matchesSnapshot(snapshot[key], value[key])
78
+ );
79
+ }
80
+ return Object.is(snapshot, value);
81
+ }
82
+ function isWalkable(value) {
83
+ return Array.isArray(value) || isPlainObject(value);
84
+ }
85
+ function isPlainObject(value) {
86
+ if (typeof value !== "object" || value === null) {
87
+ return false;
88
+ }
89
+ const proto = Object.getPrototypeOf(value);
90
+ return proto === Object.prototype || proto === null;
91
+ }
92
+
32
93
  // src/VegaChart.tsx
33
94
  var _jsxruntime = require('react/jsx-runtime');
34
95
  function VegaChart({
@@ -46,17 +107,37 @@ function VegaChart({
46
107
  ...props
47
108
  }) {
48
109
  const containerRef = _react.useRef.call(void 0, null);
110
+ const inputs = {
111
+ spec,
112
+ compileOptions,
113
+ parseConfig,
114
+ parseOptions,
115
+ viewOptions
116
+ };
117
+ const [latch, setLatch] = _react.useState.call(void 0, () => latchViewInputs(inputs));
118
+ if (!latchIsCurrent(latch, inputs)) {
119
+ setLatch(latchViewInputs(inputs));
120
+ }
49
121
  const onReady = _react.useEffectEvent.call(void 0, (view) => {
50
122
  _optionalChain([onReadyProp, 'optionalCall', _ => _(view)]);
51
123
  });
52
124
  const onError = _react.useEffectEvent.call(void 0, (error) => {
53
125
  _optionalChain([onErrorProp, 'optionalCall', _2 => _2(error)]);
54
126
  });
127
+ const loadInitialData = _react.useEffectEvent.call(void 0, (view) => {
128
+ if (!data) {
129
+ return;
130
+ }
131
+ for (const [name, tuples] of Object.entries(data)) {
132
+ view.data(name, tuples);
133
+ }
134
+ });
55
135
  _react.useEffect.call(void 0, () => {
56
136
  const container = containerRef.current;
57
137
  if (!container) {
58
138
  return;
59
139
  }
140
+ const { spec: spec2 } = latch.inputs;
60
141
  let cancelled = false;
61
142
  let view = null;
62
143
  const fail = (err) => {
@@ -65,23 +146,23 @@ function VegaChart({
65
146
  }
66
147
  };
67
148
  try {
68
- const schemaResult = parseSchema(spec.$schema);
149
+ const schemaResult = parseSchema(spec2.$schema);
69
150
  if (!schemaResult.ok) {
70
151
  fail(new Error(schemaResult.error));
71
152
  return;
72
153
  }
73
- const vegaSpec = schemaResult.library === "vega-lite" ? _vegalite.compile.call(void 0, spec, compileOptions).spec : spec;
74
- const runtime = _vega.parse.call(void 0, vegaSpec, parseConfig, parseOptions);
154
+ const vegaSpec = schemaResult.library === "vega-lite" ? _vegalite.compile.call(void 0, spec2, latch.inputs.compileOptions).spec : spec2;
155
+ const runtime = _vega.parse.call(void 0,
156
+ vegaSpec,
157
+ latch.inputs.parseConfig,
158
+ latch.inputs.parseOptions
159
+ );
75
160
  view = new (0, _vega.View)(runtime, {
76
161
  hover: true,
77
- ...viewOptions,
162
+ ...latch.inputs.viewOptions,
78
163
  container
79
164
  });
80
- if (data) {
81
- for (const [name, tuples] of Object.entries(data)) {
82
- view.data(name, tuples);
83
- }
84
- }
165
+ loadInitialData(view);
85
166
  view.runAsync().then(() => {
86
167
  if (cancelled) {
87
168
  _optionalChain([view, 'optionalAccess', _3 => _3.finalize, 'call', _4 => _4()]);
@@ -98,7 +179,7 @@ function VegaChart({
98
179
  cancelled = true;
99
180
  _optionalChain([view, 'optionalAccess', _5 => _5.finalize, 'call', _6 => _6()]);
100
181
  };
101
- }, [spec, data, compileOptions, parseConfig, parseOptions, viewOptions]);
182
+ }, [latch]);
102
183
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
103
184
  "div",
104
185
  {
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/VegaChart.tsx
2
- import { useEffect, useEffectEvent, useRef } from "react";
2
+ import { useEffect, useEffectEvent, useRef, useState } from "react";
3
3
  import { parse, View } from "vega";
4
4
  import { compile } from "vega-lite";
5
5
 
@@ -29,6 +29,67 @@ function parseSchema(schema) {
29
29
  return { ok: true, library, version };
30
30
  }
31
31
 
32
+ // src/viewInputs.ts
33
+ var MAX_DEPTH = 100;
34
+ var OPAQUE = /* @__PURE__ */ Symbol("astryx.vega.opaque");
35
+ function opaque(value) {
36
+ return { [OPAQUE]: value };
37
+ }
38
+ function isOpaque(value) {
39
+ return typeof value === "object" && value !== null && OPAQUE in value;
40
+ }
41
+ function latchViewInputs(inputs) {
42
+ return { inputs, snapshot: snapshotValue(inputs, 0, /* @__PURE__ */ new Set()) };
43
+ }
44
+ function latchIsCurrent(latch, inputs) {
45
+ return matchesSnapshot(latch.snapshot, inputs);
46
+ }
47
+ function snapshotValue(value, depth, path) {
48
+ if (!isWalkable(value)) {
49
+ return value;
50
+ }
51
+ if (depth >= MAX_DEPTH || path.has(value)) {
52
+ return opaque(value);
53
+ }
54
+ path.add(value);
55
+ const copy = Array.isArray(value) ? value.map((item) => snapshotValue(item, depth + 1, path)) : Object.fromEntries(
56
+ Object.entries(value).map(([key, entry]) => [
57
+ key,
58
+ snapshotValue(entry, depth + 1, path)
59
+ ])
60
+ );
61
+ path.delete(value);
62
+ return copy;
63
+ }
64
+ function matchesSnapshot(snapshot, value) {
65
+ if (isOpaque(snapshot)) {
66
+ return Object.is(snapshot[OPAQUE], value);
67
+ }
68
+ if (Array.isArray(snapshot)) {
69
+ return Array.isArray(value) && snapshot.length === value.length && snapshot.every((item, index) => matchesSnapshot(item, value[index]));
70
+ }
71
+ if (isPlainObject(snapshot)) {
72
+ if (!isPlainObject(value)) {
73
+ return false;
74
+ }
75
+ const keys = Object.keys(snapshot);
76
+ return keys.length === Object.keys(value).length && keys.every(
77
+ (key) => Object.prototype.hasOwnProperty.call(value, key) && matchesSnapshot(snapshot[key], value[key])
78
+ );
79
+ }
80
+ return Object.is(snapshot, value);
81
+ }
82
+ function isWalkable(value) {
83
+ return Array.isArray(value) || isPlainObject(value);
84
+ }
85
+ function isPlainObject(value) {
86
+ if (typeof value !== "object" || value === null) {
87
+ return false;
88
+ }
89
+ const proto = Object.getPrototypeOf(value);
90
+ return proto === Object.prototype || proto === null;
91
+ }
92
+
32
93
  // src/VegaChart.tsx
33
94
  import { jsx } from "react/jsx-runtime";
34
95
  function VegaChart({
@@ -46,17 +107,37 @@ function VegaChart({
46
107
  ...props
47
108
  }) {
48
109
  const containerRef = useRef(null);
110
+ const inputs = {
111
+ spec,
112
+ compileOptions,
113
+ parseConfig,
114
+ parseOptions,
115
+ viewOptions
116
+ };
117
+ const [latch, setLatch] = useState(() => latchViewInputs(inputs));
118
+ if (!latchIsCurrent(latch, inputs)) {
119
+ setLatch(latchViewInputs(inputs));
120
+ }
49
121
  const onReady = useEffectEvent((view) => {
50
122
  onReadyProp?.(view);
51
123
  });
52
124
  const onError = useEffectEvent((error) => {
53
125
  onErrorProp?.(error);
54
126
  });
127
+ const loadInitialData = useEffectEvent((view) => {
128
+ if (!data) {
129
+ return;
130
+ }
131
+ for (const [name, tuples] of Object.entries(data)) {
132
+ view.data(name, tuples);
133
+ }
134
+ });
55
135
  useEffect(() => {
56
136
  const container = containerRef.current;
57
137
  if (!container) {
58
138
  return;
59
139
  }
140
+ const { spec: spec2 } = latch.inputs;
60
141
  let cancelled = false;
61
142
  let view = null;
62
143
  const fail = (err) => {
@@ -65,23 +146,23 @@ function VegaChart({
65
146
  }
66
147
  };
67
148
  try {
68
- const schemaResult = parseSchema(spec.$schema);
149
+ const schemaResult = parseSchema(spec2.$schema);
69
150
  if (!schemaResult.ok) {
70
151
  fail(new Error(schemaResult.error));
71
152
  return;
72
153
  }
73
- const vegaSpec = schemaResult.library === "vega-lite" ? compile(spec, compileOptions).spec : spec;
74
- const runtime = parse(vegaSpec, parseConfig, parseOptions);
154
+ const vegaSpec = schemaResult.library === "vega-lite" ? compile(spec2, latch.inputs.compileOptions).spec : spec2;
155
+ const runtime = parse(
156
+ vegaSpec,
157
+ latch.inputs.parseConfig,
158
+ latch.inputs.parseOptions
159
+ );
75
160
  view = new View(runtime, {
76
161
  hover: true,
77
- ...viewOptions,
162
+ ...latch.inputs.viewOptions,
78
163
  container
79
164
  });
80
- if (data) {
81
- for (const [name, tuples] of Object.entries(data)) {
82
- view.data(name, tuples);
83
- }
84
- }
165
+ loadInitialData(view);
85
166
  view.runAsync().then(() => {
86
167
  if (cancelled) {
87
168
  view?.finalize();
@@ -98,7 +179,7 @@ function VegaChart({
98
179
  cancelled = true;
99
180
  view?.finalize();
100
181
  };
101
- }, [spec, data, compileOptions, parseConfig, parseOptions, viewOptions]);
182
+ }, [latch]);
102
183
  return /* @__PURE__ */ jsx(
103
184
  "div",
104
185
  {
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=schema.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.test.d.ts","sourceRoot":"","sources":["../src/schema.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=vegaLiteConfig.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vegaLiteConfig.test.d.ts","sourceRoot":"","sources":["../src/vegaLiteConfig.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * @file viewInputs.ts
3
+ * @input The VegaChart props that own the Vega View lifecycle
4
+ * @output The ViewInputs type plus latch/compare helpers VegaChart rebuilds on
5
+ * @position Internal utility; used by VegaChart to decide when to rebuild
6
+ *
7
+ * SYNC: When modified, update /packages/vega/README.md
8
+ */
9
+ import type { VegaChartProps } from './types';
10
+ /**
11
+ * The props the Vega runtime is built from. A change to any of them produces
12
+ * a different runtime, so the View is torn down and rebuilt. `data`,
13
+ * `className`, `style`, and the callbacks are absent because none of them
14
+ * change the runtime.
15
+ */
16
+ export type ViewInputs = Pick<VegaChartProps, 'spec' | 'compileOptions' | 'parseConfig' | 'parseOptions' | 'viewOptions'>;
17
+ /**
18
+ * The inputs the live View was built from, beside a structural copy of their
19
+ * values at that moment.
20
+ *
21
+ * The copy is the whole point. Comparing the incoming props against the
22
+ * *previous props* cannot see a spec mutated in place — both sides are the
23
+ * same object, so the old value is already gone and the chart silently goes
24
+ * stale. Comparing against a copy taken when the View was built can.
25
+ *
26
+ * The copy is also compared during render, so its verdict must be stable for
27
+ * an unchanged input: a part that always reported "changed" would loop React
28
+ * forever. See {@link Opaque} for the parts that cannot be copied.
29
+ */
30
+ export type ViewInputsLatch = {
31
+ /** The caller's own objects, handed to Vega untouched. */
32
+ readonly inputs: ViewInputs;
33
+ readonly snapshot: unknown;
34
+ };
35
+ export declare function latchViewInputs(inputs: ViewInputs): ViewInputsLatch;
36
+ /**
37
+ * Whether `inputs` still carries the values the latched View was built from.
38
+ *
39
+ * Plain objects and arrays are compared entry by entry, so a spec or options
40
+ * bag rebuilt inline on every render counts as unchanged. Everything else --
41
+ * functions (tooltip handlers, loggers, loaders, field-title formatters),
42
+ * class instances, dates -- compares by reference, because two instances can
43
+ * behave differently even when they look alike, and the View built from them
44
+ * would too.
45
+ */
46
+ export declare function latchIsCurrent(latch: ViewInputsLatch, inputs: ViewInputs): boolean;
47
+ //# sourceMappingURL=viewInputs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viewInputs.d.ts","sourceRoot":"","sources":["../src/viewInputs.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,SAAS,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,IAAI,CAC3B,cAAc,EACd,MAAM,GAAG,gBAAgB,GAAG,aAAa,GAAG,cAAc,GAAG,aAAa,CAC3E,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B,CAAC;AAuCF,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,eAAe,CAEnE;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,eAAe,EACtB,MAAM,EAAE,UAAU,GACjB,OAAO,CAET"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=viewInputs.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viewInputs.test.d.ts","sourceRoot":"","sources":["../src/viewInputs.test.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astryxdesign/vega",
3
- "version": "0.5.2-canary.c9c8564",
3
+ "version": "0.5.2-canary.cb13c1e",
4
4
  "description": "Astryx Vega wrapper — chart and data visualization components. Published to npm only under the @canary dist-tag for early testing; never released as a stable (latest) version.",
5
5
  "author": "Meta Open Source",
6
6
  "license": "MIT",
@@ -57,6 +57,8 @@
57
57
  "scripts": {
58
58
  "build": "tsup && tsc --project tsconfig.json --emitDeclarationOnly --declaration --noEmit false --outDir dist",
59
59
  "dev": "tsup --watch",
60
+ "test": "vitest run --root ../..",
61
+ "test:watch": "vitest --root ../..",
60
62
  "typecheck": "tsc --noEmit"
61
63
  }
62
64
  }