@astryxdesign/vega 0.0.0-bootstrap.0 → 0.1.3-canary.e3beb97
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/LICENSE +21 -0
- package/README.md +231 -1
- package/dist/VegaChart.d.ts +70 -0
- package/dist/VegaChart.d.ts.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +255 -0
- package/dist/index.mjs +255 -0
- package/dist/schema.d.ts +28 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/types.d.ts +164 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/vegaLiteConfig.d.ts +45 -0
- package/dist/vegaLiteConfig.d.ts.map +1 -0
- package/package.json +56 -5
- package/src/VegaChart.tsx +183 -0
- package/src/index.ts +43 -0
- package/src/schema.ts +63 -0
- package/src/types.ts +178 -0
- package/src/vegaLiteConfig.ts +197 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Meta Platforms, Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,233 @@
|
|
|
1
1
|
# @astryxdesign/vega
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Astryx Vega wrapper: chart and data visualization components.
|
|
4
|
+
|
|
5
|
+
Renders [Vega](https://vega.github.io/vega/) and [Vega-Lite](https://vega.github.io/vega-lite/) specifications via the Vega runtime. The component inspects `$schema` to decide whether to compile (Vega-Lite) or render directly (Vega), validates the schema URL before doing either, and exposes the full Vega `parse()` and `View` construction APIs as props.
|
|
6
|
+
|
|
7
|
+
> **Publishing status: canary only.** This package ships to npm **only under the `@canary` dist-tag** — there is no stable (`latest`) release yet. See [Publishing](#publishing) below for the canary model and the steps to graduate it to a public stable release.
|
|
8
|
+
|
|
9
|
+
<!-- SYNC: When files in this directory change, update this document. -->
|
|
10
|
+
|
|
11
|
+
## File Manifest
|
|
12
|
+
|
|
13
|
+
| File | Role | Purpose |
|
|
14
|
+
| ------------------- | --------- | ------------------------------------------------------------ |
|
|
15
|
+
| `package.json` | Config | Package metadata, deps, build scripts |
|
|
16
|
+
| `tsconfig.json` | Config | TypeScript compiler config (extends root) |
|
|
17
|
+
| `tsup.config.ts` | Config | Build config: CJS + ESM + `.d.ts` outputs |
|
|
18
|
+
| `src/index.ts` | Barrel | Public API surface |
|
|
19
|
+
| `src/VegaChart.tsx` | Component | Inspects `$schema`, compiles or renders, owns View lifecycle |
|
|
20
|
+
| `src/schema.ts` | Utility | Parses and validates Vega/Vega-Lite `$schema` URLs |
|
|
21
|
+
| `src/types.ts` | Types | Shared TypeScript types for this package |
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
Vega is published **only** under the `@canary` dist-tag, so you must request that tag explicitly. There is no `latest` version to install yet.
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install @astryxdesign/vega@canary vega vega-lite
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
> Canary builds track the latest commit on `main` (`0.x.y-canary.<sha>`). They can break between any two versions — pin an exact version if you need stability.
|
|
32
|
+
|
|
33
|
+
## Usage
|
|
34
|
+
|
|
35
|
+
### Vega-Lite spec (compiled automatically)
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
import {VegaChart} from '@astryxdesign/vega';
|
|
39
|
+
|
|
40
|
+
<VegaChart
|
|
41
|
+
spec={{
|
|
42
|
+
$schema: 'https://vega.github.io/schema/vega-lite/v5.json',
|
|
43
|
+
mark: 'bar',
|
|
44
|
+
data: {
|
|
45
|
+
values: [
|
|
46
|
+
{a: 'A', b: 28},
|
|
47
|
+
{a: 'B', b: 55},
|
|
48
|
+
],
|
|
49
|
+
},
|
|
50
|
+
encoding: {
|
|
51
|
+
x: {field: 'a', type: 'ordinal'},
|
|
52
|
+
y: {field: 'b', type: 'quantitative'},
|
|
53
|
+
},
|
|
54
|
+
}}
|
|
55
|
+
/>;
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Vega spec (rendered directly, no compilation)
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
<VegaChart
|
|
62
|
+
spec={{
|
|
63
|
+
$schema: 'https://vega.github.io/schema/vega/v5.json',
|
|
64
|
+
marks: [...],
|
|
65
|
+
}}
|
|
66
|
+
/>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Full configuration
|
|
70
|
+
|
|
71
|
+
```tsx
|
|
72
|
+
<VegaChart
|
|
73
|
+
spec={spec}
|
|
74
|
+
parseConfig={{background: '#1a1a1a'}}
|
|
75
|
+
parseOptions={{ast: true}}
|
|
76
|
+
viewOptions={{
|
|
77
|
+
renderer: 'canvas',
|
|
78
|
+
logLevel: 1,
|
|
79
|
+
tooltip: myTooltipHandler,
|
|
80
|
+
locale: myLocale,
|
|
81
|
+
loader: myLoader,
|
|
82
|
+
}}
|
|
83
|
+
onReady={view => {
|
|
84
|
+
view.addSignalListener('highlight', (name, value) => {
|
|
85
|
+
console.log('signal:', name, value);
|
|
86
|
+
});
|
|
87
|
+
}}
|
|
88
|
+
onError={err => console.error('Chart error:', err.message)}
|
|
89
|
+
/>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## API
|
|
93
|
+
|
|
94
|
+
### `<VegaChart>`
|
|
95
|
+
|
|
96
|
+
| Prop | Type | Default | Description |
|
|
97
|
+
| ---------------- | -------------------------------- | ------- | ---------------------------------------------------------- |
|
|
98
|
+
| `spec` | `AnySpec` | -- | Vega or Vega-Lite spec with `$schema` (required) |
|
|
99
|
+
| `data` | `ViewData` | -- | Initial dataset values: `{datasetName: tuples[]}` |
|
|
100
|
+
| `compileOptions` | `CompileOptions` | -- | Options passed to `compile(spec, options)`, Vega-Lite only |
|
|
101
|
+
| `parseConfig` | `Config` | -- | Vega config passed to `parse(spec, config)` |
|
|
102
|
+
| `parseOptions` | `ParseOptions` | -- | Options passed to `parse(spec, config, options)` |
|
|
103
|
+
| `viewOptions` | `Omit<ViewOptions, 'container'>` | -- | Options passed to `new View(runtime, options)` |
|
|
104
|
+
| `className` | `string` | -- | CSS class on the container div |
|
|
105
|
+
| `style` | `CSSProperties` | -- | Inline styles on the container div |
|
|
106
|
+
| `onReady` | `(view: View) => void` | -- | Called with the live Vega View when ready |
|
|
107
|
+
| `onError` | `(err: Error) => void` | -- | Called on schema error, compile failure, or render failure |
|
|
108
|
+
|
|
109
|
+
`viewOptions` maps directly to [`ViewOptions`](https://vega.github.io/vega/docs/api/view/) with `container` omitted (always set by the component). Notable fields:
|
|
110
|
+
|
|
111
|
+
| `viewOptions` field | Type | Description |
|
|
112
|
+
| ------------------- | ------------------- | --------------------------------------- |
|
|
113
|
+
| `renderer` | `'svg' \| 'canvas'` | Rendering backend (default: `'svg'`) |
|
|
114
|
+
| `hover` | `boolean` | Enable hover encoding (default: `true`) |
|
|
115
|
+
| `logLevel` | `number` | Vega log verbosity |
|
|
116
|
+
| `logger` | `LoggerInterface` | Custom logger |
|
|
117
|
+
| `tooltip` | `TooltipHandler` | Custom tooltip handler |
|
|
118
|
+
| `locale` | `LocaleFormatters` | Number and time format locale |
|
|
119
|
+
| `loader` | `Loader` | Custom data loader |
|
|
120
|
+
| `background` | `Color` | Chart background color |
|
|
121
|
+
|
|
122
|
+
`compileOptions` fields (Vega-Lite specs only, ignored otherwise):
|
|
123
|
+
|
|
124
|
+
| `compileOptions` field | Type | Description |
|
|
125
|
+
| ---------------------- | ------------------------------ | --------------------------------------------------- |
|
|
126
|
+
| `config` | `VegaLiteConfig` | Vega-Lite config merged on top of the spec's config |
|
|
127
|
+
| `logger` | `LoggerInterface` | Custom logger used during compilation |
|
|
128
|
+
| `fieldTitle` | `(fieldDef, config) => string` | Custom field title formatter |
|
|
129
|
+
|
|
130
|
+
`parseOptions` fields:
|
|
131
|
+
|
|
132
|
+
| `parseOptions` field | Type | Description |
|
|
133
|
+
| -------------------- | --------- | --------------------------------------------------------- |
|
|
134
|
+
| `ast` | `boolean` | Retain expression AST in the runtime (useful for tooling) |
|
|
135
|
+
|
|
136
|
+
### Data loading
|
|
137
|
+
|
|
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.
|
|
139
|
+
|
|
140
|
+
To update data dynamically after render, use `onReady` to get the live View and drive it yourself:
|
|
141
|
+
|
|
142
|
+
```tsx
|
|
143
|
+
<VegaChart
|
|
144
|
+
spec={spec}
|
|
145
|
+
data={{
|
|
146
|
+
table: [
|
|
147
|
+
{category: 'A', value: 28},
|
|
148
|
+
{category: 'B', value: 55},
|
|
149
|
+
],
|
|
150
|
+
}}
|
|
151
|
+
onReady={view => {
|
|
152
|
+
// Later, update data dynamically:
|
|
153
|
+
view.data('table', newRows);
|
|
154
|
+
view.runAsync();
|
|
155
|
+
}}
|
|
156
|
+
/>
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### `parseSchema(schema)` (exported utility)
|
|
160
|
+
|
|
161
|
+
Parses and validates a Vega `$schema` URL. Returns:
|
|
162
|
+
|
|
163
|
+
- `{ok: true, library: 'vega' | 'vega-lite', version: string}` on success
|
|
164
|
+
- `{ok: false, error: string}` if the URL is missing, malformed, or names an unknown library
|
|
165
|
+
|
|
166
|
+
## Schema validation
|
|
167
|
+
|
|
168
|
+
`VegaChart` validates `spec.$schema` before doing any work. It will call `onError` (and render nothing) if:
|
|
169
|
+
|
|
170
|
+
- `$schema` is missing or not a string
|
|
171
|
+
- The URL doesn't match the expected format (`schema/{library}/{version}.json`)
|
|
172
|
+
- The library name is not `vega` or `vega-lite`
|
|
173
|
+
|
|
174
|
+
## Build
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
pnpm -F @astryxdesign/vega build
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Publishing
|
|
181
|
+
|
|
182
|
+
### Canary (automatic, today)
|
|
183
|
+
|
|
184
|
+
`package.json` keeps `"private": true` plus an `"astryx": { "canaryOnly": true }` marker. The release workflow (`.github/workflows/release.yml`) handles both dist-tags:
|
|
185
|
+
|
|
186
|
+
- The **stable (`latest`) job** skips every package that is `private` **or** `canaryOnly`, so Vega can never be published as a stable release by accident.
|
|
187
|
+
- The **canary job** runs on every push to `main`. In its ephemeral CI checkout only (never in git) it strips the `private` flag from `canaryOnly` packages and publishes them to the `@canary` dist-tag as `0.x.y-canary.<short-sha>`, with npm OIDC trusted publishing + provenance.
|
|
188
|
+
|
|
189
|
+
The committed `private: true` is npm's hard guarantee that no stable publish can ever happen — **do not remove it until the graduation steps below are intentionally taken.**
|
|
190
|
+
|
|
191
|
+
> **First canary won't publish until the package name is claimed on npm.** npm cannot register OIDC trust for a name that does not yet exist on the registry. An `@astryxdesign` npm org owner must bootstrap it once (this also applies before the first stable publish):
|
|
192
|
+
>
|
|
193
|
+
> ```bash
|
|
194
|
+
> npm i -g npm@latest
|
|
195
|
+
> npm login --registry https://registry.npmjs.org # must be an @astryxdesign org owner
|
|
196
|
+
> pnpm run setup-trusted-publishing # audit — shows what needs bootstrap/trust
|
|
197
|
+
> pnpm run setup-trusted-publishing --bootstrap --setup-trust --workflow release.yml
|
|
198
|
+
> ```
|
|
199
|
+
>
|
|
200
|
+
> This publishes a deprecated `0.0.0-bootstrap.0` stub to claim the name and registers `release.yml` as the trusted publisher. Until this is done, CI's canary publish for this package will fail.
|
|
201
|
+
|
|
202
|
+
### Graduating to a public stable (`latest`) release
|
|
203
|
+
|
|
204
|
+
When Vega is ready to be published publicly as a stable release, take these steps (in order). This mirrors how the other public `@astryxdesign/*` packages are released — see the wiki's **Release-Process** page for the authoritative flow.
|
|
205
|
+
|
|
206
|
+
1. **Remove the canary-only gating** from `packages/vega/package.json`:
|
|
207
|
+
- Delete `"private": true`.
|
|
208
|
+
- Delete the `"astryx": { "canaryOnly": true }` block.
|
|
209
|
+
|
|
210
|
+
2. **Join the versioning group.** Add `@astryxdesign/vega` to the `fixed` array in `.changeset/config.json` so it co-versions with the rest of the publishable packages (they all bump to the same version). Set `version` to match the current published version of the other packages.
|
|
211
|
+
|
|
212
|
+
3. **Confirm the name is claimed + trusted on npm** (the bootstrap box above). An `@astryxdesign` org owner runs it once if it hasn't been done already — a stable publish fails for an unclaimed/untrusted name exactly like a canary does.
|
|
213
|
+
|
|
214
|
+
4. **Add a changeset** so the release notes and version bump include Vega:
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
pnpm changeset:new
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
5. **Land the change, then version + publish** through the normal release flow:
|
|
221
|
+
- Merge the PR that removes the gating (a canary publishes automatically on that push to `main`).
|
|
222
|
+
- Run the version-bump PR (`pnpm version-packages`, refresh the lockfile, merge) — this bumps versions on `main` but publishes nothing.
|
|
223
|
+
- Dispatch the stable Release workflow to publish the `latest` dist-tag:
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
gh workflow run release.yml --ref main -f dry-run=true # optional preview
|
|
227
|
+
gh workflow run release.yml --ref main # publish latest
|
|
228
|
+
gh run list --workflow=release.yml -L 3 # watch
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Publishing is tokenless (npm OIDC trusted publishing) and version-gated/idempotent — re-running is safe. No manual `npm publish`, no npm tokens.
|
|
232
|
+
|
|
233
|
+
After the stable publish, `npm install @astryxdesign/vega` (no tag) resolves to the stable release; the `@canary` tag continues to track `main`.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file VegaChart.tsx
|
|
3
|
+
* @input A Vega or Vega-Lite spec (distinguished by $schema), parse config/options, view options, and data
|
|
4
|
+
* @output A React component that renders the spec via the Vega runtime
|
|
5
|
+
* @position Primary component in @astryxdesign/vega; owns the Vega View lifecycle
|
|
6
|
+
*
|
|
7
|
+
* SYNC: When modified, update /packages/vega/README.md
|
|
8
|
+
*/
|
|
9
|
+
import React from 'react';
|
|
10
|
+
import type { VegaChartProps } from './types';
|
|
11
|
+
/**
|
|
12
|
+
* `VegaChart` renders a Vega or Vega-Lite specification using the Vega runtime.
|
|
13
|
+
*
|
|
14
|
+
* The component inspects `spec.$schema` to determine how to handle the spec:
|
|
15
|
+
* - `vega-lite` schema -> compiled to Vega via `vega-lite`'s `compile()`, then rendered
|
|
16
|
+
* - `vega` schema -> rendered directly without compilation
|
|
17
|
+
* - Invalid / missing `$schema` -> calls `onError` and renders nothing
|
|
18
|
+
*
|
|
19
|
+
* Parse and view construction are fully configurable via `parseConfig`,
|
|
20
|
+
* `parseOptions`, and `viewOptions`, which map directly to the Vega API:
|
|
21
|
+
*
|
|
22
|
+
* vega.parse(spec, parseConfig, parseOptions)
|
|
23
|
+
* new vega.View(runtime, { ...viewOptions, container })
|
|
24
|
+
*
|
|
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.
|
|
27
|
+
*
|
|
28
|
+
* 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
|
+
*
|
|
32
|
+
* Callbacks (`onReady`, `onError`) are stable across renders via refs --
|
|
33
|
+
* you don't need to memoize them. Pass stable references (or `useMemo`)
|
|
34
|
+
* for `parseConfig`, `parseOptions`, `viewOptions`, and `data` to avoid
|
|
35
|
+
* unnecessary re-renders.
|
|
36
|
+
*
|
|
37
|
+
* Note: this component does not accept `xstyle` because `@astryxdesign/vega` does not
|
|
38
|
+
* depend on StyleX. Use `className` or `style` for layout overrides.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```
|
|
42
|
+
* import {VegaChart} from '@astryxdesign/vega';
|
|
43
|
+
*
|
|
44
|
+
* // Vega-Lite spec -- compiled automatically
|
|
45
|
+
* <VegaChart
|
|
46
|
+
* spec={{
|
|
47
|
+
* $schema: 'https://vega.github.io/schema/vega-lite/v5.json',
|
|
48
|
+
* mark: 'bar',
|
|
49
|
+
* data: {name: 'table'},
|
|
50
|
+
* encoding: {
|
|
51
|
+
* x: {field: 'a', type: 'ordinal'},
|
|
52
|
+
* y: {field: 'b', type: 'quantitative'},
|
|
53
|
+
* },
|
|
54
|
+
* }}
|
|
55
|
+
* data={{table: [{a: 'A', b: 28}, {a: 'B', b: 55}]}}
|
|
56
|
+
* />
|
|
57
|
+
*
|
|
58
|
+
* // Vega spec -- rendered directly
|
|
59
|
+
* <VegaChart
|
|
60
|
+
* spec={{$schema: 'https://vega.github.io/schema/vega/v5.json', marks: []}}
|
|
61
|
+
* parseConfig={{background: '#1a1a1a'}}
|
|
62
|
+
* viewOptions={{logLevel: 1, tooltip: myTooltipHandler}}
|
|
63
|
+
* />
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export declare function VegaChart({ spec, data, compileOptions, parseConfig, parseOptions, viewOptions, className, style, ref, onReady, onError, ...props }: VegaChartProps): React.JSX.Element;
|
|
67
|
+
export declare namespace VegaChart {
|
|
68
|
+
var displayName: string;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=VegaChart.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VegaChart.d.ts","sourceRoot":"","sources":["../src/VegaChart.tsx"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,OAAO,KAA0B,MAAM,OAAO,CAAC;AAI/C,OAAO,KAAK,EAAC,cAAc,EAAyB,MAAM,SAAS,CAAC;AAEpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AACH,wBAAgB,SAAS,CAAC,EACxB,IAAI,EACJ,IAAI,EACJ,cAAc,EACd,WAAW,EACX,YAAY,EACZ,WAAW,EACX,SAAS,EACT,KAAK,EACL,GAAG,EACH,OAAO,EACP,OAAO,EACP,GAAG,KAAK,EACT,EAAE,cAAc,qBA+FhB;yBA5Ge,SAAS"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file index.ts
|
|
3
|
+
* @input All public exports for @astryxdesign/vega
|
|
4
|
+
* @output Public API surface for the Astryx Vega wrapper package
|
|
5
|
+
* @position Barrel export; entry point for consumers of @astryxdesign/vega
|
|
6
|
+
*
|
|
7
|
+
* SYNC: When modified, update /packages/vega/README.md
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* @file index.ts
|
|
11
|
+
* @input All public exports for @astryxdesign/vega
|
|
12
|
+
* @output Public API surface for the Astryx Vega wrapper package
|
|
13
|
+
* @position Barrel export; entry point for consumers of @astryxdesign/vega
|
|
14
|
+
*
|
|
15
|
+
* SYNC: When modified, update /packages/vega/README.md
|
|
16
|
+
*/
|
|
17
|
+
export { VegaChart } from './VegaChart';
|
|
18
|
+
export { parseSchema } from './schema';
|
|
19
|
+
export { buildVegaLiteConfig, DEFAULT_STROKE_WIDTH, DEFAULT_POINT_SIZE, DEFAULT_LEGEND_ORIENT, LEGEND_OFFSET, TITLE_OFFSET, } from './vegaLiteConfig';
|
|
20
|
+
export type { VegaChartProps, AnySpec, ViewData, VegaSpec, VegaLiteSpec, CompileOptions, ParseOptions, Config, ViewOptions, LoggerInterface, } from './types';
|
|
21
|
+
export type { SchemaLibrary, SchemaResult } from './schema';
|
|
22
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH;;;;;;;GAOG;AAEH,OAAO,EAAC,SAAS,EAAC,MAAM,aAAa,CAAC;AACtC,OAAO,EAAC,WAAW,EAAC,MAAM,UAAU,CAAC;AACrC,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,qBAAqB,EACrB,aAAa,EACb,YAAY,GACb,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,cAAc,EACd,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,MAAM,EACN,WAAW,EACX,eAAe,GAChB,MAAM,SAAS,CAAC;AACjB,YAAY,EAAC,aAAa,EAAE,YAAY,EAAC,MAAM,UAAU,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/VegaChart.tsx
|
|
2
|
+
var _react = require('react');
|
|
3
|
+
var _vega = require('vega');
|
|
4
|
+
var _vegalite = require('vega-lite');
|
|
5
|
+
|
|
6
|
+
// src/schema.ts
|
|
7
|
+
var SCHEMA_RE = /schema\/([\w-]+)\/([\w.-]+)\.json$/;
|
|
8
|
+
function parseSchema(schema) {
|
|
9
|
+
if (schema === void 0 || schema === null) {
|
|
10
|
+
return { ok: false, error: 'Spec is missing a $schema field. Add "$schema": "https://vega.github.io/schema/vega/v5.json" or the vega-lite equivalent.' };
|
|
11
|
+
}
|
|
12
|
+
if (typeof schema !== "string") {
|
|
13
|
+
return { ok: false, error: `$schema must be a string, got ${typeof schema}.` };
|
|
14
|
+
}
|
|
15
|
+
const match = SCHEMA_RE.exec(schema);
|
|
16
|
+
if (!match) {
|
|
17
|
+
return {
|
|
18
|
+
ok: false,
|
|
19
|
+
error: `Unrecognized $schema URL: "${schema}". Expected format: https://vega.github.io/schema/{vega|vega-lite}/{version}.json`
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
const [, library, version] = match;
|
|
23
|
+
if (library !== "vega" && library !== "vega-lite") {
|
|
24
|
+
return {
|
|
25
|
+
ok: false,
|
|
26
|
+
error: `Unknown schema library "${library}". Must be "vega" or "vega-lite".`
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
return { ok: true, library, version };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// src/VegaChart.tsx
|
|
33
|
+
var _jsxruntime = require('react/jsx-runtime');
|
|
34
|
+
function VegaChart({
|
|
35
|
+
spec,
|
|
36
|
+
data,
|
|
37
|
+
compileOptions,
|
|
38
|
+
parseConfig,
|
|
39
|
+
parseOptions,
|
|
40
|
+
viewOptions,
|
|
41
|
+
className,
|
|
42
|
+
style,
|
|
43
|
+
ref,
|
|
44
|
+
onReady,
|
|
45
|
+
onError,
|
|
46
|
+
...props
|
|
47
|
+
}) {
|
|
48
|
+
const containerRef = _react.useRef.call(void 0, null);
|
|
49
|
+
const onReadyRef = _react.useRef.call(void 0, onReady);
|
|
50
|
+
const onErrorRef = _react.useRef.call(void 0, onError);
|
|
51
|
+
onReadyRef.current = onReady;
|
|
52
|
+
onErrorRef.current = onError;
|
|
53
|
+
_react.useEffect.call(void 0, () => {
|
|
54
|
+
const container = containerRef.current;
|
|
55
|
+
if (!container) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
let cancelled = false;
|
|
59
|
+
let view = null;
|
|
60
|
+
const fail = (err) => {
|
|
61
|
+
if (!cancelled) {
|
|
62
|
+
_optionalChain([onErrorRef, 'access', _ => _.current, 'optionalCall', _2 => _2(
|
|
63
|
+
err instanceof Error ? err : new Error(String(err))
|
|
64
|
+
)]);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
try {
|
|
68
|
+
const schemaResult = parseSchema(spec.$schema);
|
|
69
|
+
if (!schemaResult.ok) {
|
|
70
|
+
fail(new Error(schemaResult.error));
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
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);
|
|
75
|
+
view = new (0, _vega.View)(runtime, {
|
|
76
|
+
hover: true,
|
|
77
|
+
...viewOptions,
|
|
78
|
+
container
|
|
79
|
+
});
|
|
80
|
+
if (data) {
|
|
81
|
+
for (const [name, tuples] of Object.entries(data)) {
|
|
82
|
+
view.data(name, tuples);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
view.runAsync().then(() => {
|
|
86
|
+
if (cancelled) {
|
|
87
|
+
_optionalChain([view, 'optionalAccess', _3 => _3.finalize, 'call', _4 => _4()]);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
if (view) {
|
|
91
|
+
_optionalChain([onReadyRef, 'access', _5 => _5.current, 'optionalCall', _6 => _6(view)]);
|
|
92
|
+
}
|
|
93
|
+
}).catch(fail);
|
|
94
|
+
} catch (err) {
|
|
95
|
+
fail(err);
|
|
96
|
+
}
|
|
97
|
+
return () => {
|
|
98
|
+
cancelled = true;
|
|
99
|
+
_optionalChain([view, 'optionalAccess', _7 => _7.finalize, 'call', _8 => _8()]);
|
|
100
|
+
};
|
|
101
|
+
}, [spec, data, compileOptions, parseConfig, parseOptions, viewOptions]);
|
|
102
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
103
|
+
"div",
|
|
104
|
+
{
|
|
105
|
+
ref: (node) => {
|
|
106
|
+
containerRef.current = node;
|
|
107
|
+
if (typeof ref === "function") {
|
|
108
|
+
ref(node);
|
|
109
|
+
} else if (ref) {
|
|
110
|
+
ref.current = node;
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
className,
|
|
114
|
+
style,
|
|
115
|
+
...props
|
|
116
|
+
}
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
VegaChart.displayName = "VegaChart";
|
|
120
|
+
|
|
121
|
+
// src/vegaLiteConfig.ts
|
|
122
|
+
var DEFAULT_STROKE_WIDTH = 2;
|
|
123
|
+
var DEFAULT_POINT_SIZE = 64;
|
|
124
|
+
var DEFAULT_LEGEND_ORIENT = "right";
|
|
125
|
+
var LEGEND_OFFSET = 16;
|
|
126
|
+
var TITLE_OFFSET = 16;
|
|
127
|
+
function buildVegaLiteConfig(token) {
|
|
128
|
+
return {
|
|
129
|
+
axis: {
|
|
130
|
+
domainColor: token("--color-icon-primary"),
|
|
131
|
+
domainWidth: 0.5,
|
|
132
|
+
gridColor: token("--color-background-muted"),
|
|
133
|
+
labelColor: token("--color-text-secondary"),
|
|
134
|
+
labelFont: token("--font-family-body"),
|
|
135
|
+
labelFontSize: 12,
|
|
136
|
+
labelLineHeight: 16,
|
|
137
|
+
labelPadding: 8,
|
|
138
|
+
tickCount: 5,
|
|
139
|
+
ticks: false,
|
|
140
|
+
title: null
|
|
141
|
+
},
|
|
142
|
+
axisX: {
|
|
143
|
+
grid: false
|
|
144
|
+
},
|
|
145
|
+
axisXQuantitative: {
|
|
146
|
+
domain: true
|
|
147
|
+
},
|
|
148
|
+
axisY: {
|
|
149
|
+
domain: false
|
|
150
|
+
},
|
|
151
|
+
axisYQuantitative: {
|
|
152
|
+
grid: true,
|
|
153
|
+
gridWidth: 0.5
|
|
154
|
+
},
|
|
155
|
+
background: token("--color-background-card"),
|
|
156
|
+
legend: {
|
|
157
|
+
labelColor: token("--color-text-secondary"),
|
|
158
|
+
labelFont: token("--font-family-body"),
|
|
159
|
+
labelFontSize: 12,
|
|
160
|
+
labelPadding: 8,
|
|
161
|
+
offset: LEGEND_OFFSET,
|
|
162
|
+
orient: DEFAULT_LEGEND_ORIENT,
|
|
163
|
+
rowPadding: 12,
|
|
164
|
+
title: null,
|
|
165
|
+
titleColor: token("--color-text-secondary"),
|
|
166
|
+
titleFont: token("--font-family-heading"),
|
|
167
|
+
titleFontSize: 16
|
|
168
|
+
},
|
|
169
|
+
line: {
|
|
170
|
+
strokeCap: "round",
|
|
171
|
+
strokeJoin: "round",
|
|
172
|
+
strokeWidth: DEFAULT_STROKE_WIDTH
|
|
173
|
+
},
|
|
174
|
+
padding: 16,
|
|
175
|
+
point: {
|
|
176
|
+
shape: "circle",
|
|
177
|
+
size: DEFAULT_POINT_SIZE,
|
|
178
|
+
fill: token("--color-background-card")
|
|
179
|
+
},
|
|
180
|
+
range: {
|
|
181
|
+
category: [
|
|
182
|
+
token("--color-data-categorical-blue"),
|
|
183
|
+
token("--color-data-categorical-orange"),
|
|
184
|
+
token("--color-data-categorical-purple"),
|
|
185
|
+
token("--color-data-categorical-green"),
|
|
186
|
+
token("--color-data-categorical-pink"),
|
|
187
|
+
token("--color-data-categorical-cyan"),
|
|
188
|
+
token("--color-data-categorical-red"),
|
|
189
|
+
token("--color-data-categorical-teal"),
|
|
190
|
+
token("--color-data-categorical-brown"),
|
|
191
|
+
token("--color-data-categorical-indigo")
|
|
192
|
+
],
|
|
193
|
+
diverging: [
|
|
194
|
+
token("--color-data-blue-5"),
|
|
195
|
+
token("--color-data-blue-4"),
|
|
196
|
+
token("--color-data-blue-3"),
|
|
197
|
+
token("--color-data-blue-2"),
|
|
198
|
+
token("--color-data-blue-1"),
|
|
199
|
+
token("--color-data-gray-1"),
|
|
200
|
+
token("--color-data-red-1"),
|
|
201
|
+
token("--color-data-red-2"),
|
|
202
|
+
token("--color-data-red-3"),
|
|
203
|
+
token("--color-data-red-4"),
|
|
204
|
+
token("--color-data-red-5")
|
|
205
|
+
],
|
|
206
|
+
heatmap: [
|
|
207
|
+
token("--color-data-blue-1"),
|
|
208
|
+
token("--color-data-blue-2"),
|
|
209
|
+
token("--color-data-blue-3"),
|
|
210
|
+
token("--color-data-blue-4"),
|
|
211
|
+
token("--color-data-blue-5")
|
|
212
|
+
],
|
|
213
|
+
ordinal: [
|
|
214
|
+
token("--color-data-blue-5"),
|
|
215
|
+
token("--color-data-blue-4"),
|
|
216
|
+
token("--color-data-blue-3"),
|
|
217
|
+
token("--color-data-blue-2"),
|
|
218
|
+
token("--color-data-blue-1")
|
|
219
|
+
],
|
|
220
|
+
ramp: [
|
|
221
|
+
token("--color-data-blue-1"),
|
|
222
|
+
token("--color-data-blue-2"),
|
|
223
|
+
token("--color-data-blue-3"),
|
|
224
|
+
token("--color-data-blue-4"),
|
|
225
|
+
token("--color-data-blue-5")
|
|
226
|
+
]
|
|
227
|
+
},
|
|
228
|
+
scale: {
|
|
229
|
+
bandPaddingInner: 0.1
|
|
230
|
+
},
|
|
231
|
+
text: {
|
|
232
|
+
color: token("--color-text-primary")
|
|
233
|
+
},
|
|
234
|
+
title: {
|
|
235
|
+
anchor: "start",
|
|
236
|
+
color: token("--color-text-primary"),
|
|
237
|
+
subtitleFontWeight: "normal",
|
|
238
|
+
subtitleColor: token("--color-text-secondary"),
|
|
239
|
+
offset: TITLE_OFFSET
|
|
240
|
+
},
|
|
241
|
+
view: {
|
|
242
|
+
stroke: null
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
exports.DEFAULT_LEGEND_ORIENT = DEFAULT_LEGEND_ORIENT; exports.DEFAULT_POINT_SIZE = DEFAULT_POINT_SIZE; exports.DEFAULT_STROKE_WIDTH = DEFAULT_STROKE_WIDTH; exports.LEGEND_OFFSET = LEGEND_OFFSET; exports.TITLE_OFFSET = TITLE_OFFSET; exports.VegaChart = VegaChart; exports.buildVegaLiteConfig = buildVegaLiteConfig; exports.parseSchema = parseSchema;
|