@vielzeug/codex 3.0.2 → 3.1.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.
- package/README.md +6 -0
- package/data/catalog.json +1984 -0
- package/data/llms-full.txt +31429 -0
- package/data/llms.txt +47 -0
- package/data/manifest.json +8 -0
- package/data/packages/arsenal.json +216 -0
- package/data/packages/assay.json +46 -0
- package/data/packages/clockwork.json +66 -0
- package/data/packages/codex.json +29 -0
- package/data/packages/coins.json +101 -0
- package/data/packages/conduit.json +68 -0
- package/data/packages/courier.json +55 -0
- package/data/packages/dnd.json +60 -0
- package/data/packages/familiar.json +17 -0
- package/data/packages/flux.json +94 -0
- package/data/packages/focus.json +38 -0
- package/data/packages/forge.json +60 -0
- package/data/packages/gesture.json +37 -0
- package/data/packages/herald.json +81 -0
- package/data/packages/illusionist.json +132 -0
- package/data/packages/keymap.json +51 -0
- package/data/packages/ledger.json +60 -0
- package/data/packages/lingua.json +70 -0
- package/data/packages/mesh.json +54 -0
- package/data/packages/necromancer.json +50 -0
- package/data/packages/orbit.json +99 -0
- package/data/packages/ore.json +65 -0
- package/data/packages/postmaster.json +49 -0
- package/data/packages/prism.json +66 -0
- package/data/packages/pulse.json +71 -0
- package/data/packages/refine.json +12 -0
- package/data/packages/ripple.json +88 -0
- package/data/packages/rune.json +78 -0
- package/data/packages/sandbox.json +26 -0
- package/data/packages/scout.json +63 -0
- package/data/packages/scroll.json +110 -0
- package/data/packages/sentinel.json +35 -0
- package/data/packages/sigil.json +49 -0
- package/data/packages/sourcerer.json +70 -0
- package/data/packages/spell.json +132 -0
- package/data/packages/tempo.json +81 -0
- package/data/packages/vault.json +93 -0
- package/data/packages/ward.json +80 -0
- package/data/packages/wayfinder.json +114 -0
- package/data/refine.json +12828 -0
- package/data/search.json +1582 -0
- package/dist/cli.js +32 -0
- package/dist/cli.js.map +1 -1
- package/dist/skills.d.ts +26 -0
- package/dist/skills.js +46 -0
- package/dist/skills.js.map +1 -0
- package/package.json +6 -6
- package/skills/vielzeug/SKILL.md +153 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"apiSource": "// Public API — all exports for @vielzeug/prism\n\nexport type { EasingFn } from './animation/easing';\n// Chart factories\nexport { createAreaChart } from './charts/area';\nexport { createBarChart } from './charts/bar';\nexport { createLineChart } from './charts/line';\nexport { createPieChart } from './charts/pie';\nexport { createSparkline } from './charts/sparkline';\n// Error classes\nexport { PrismError, PrismRenderError } from './errors';\n// Scale factories\nexport { bandScale } from './scales/band';\nexport { linearScale } from './scales/linear';\nexport { timeScale } from './scales/time';\nexport type { BandScaleConfig, LinearScaleConfig, TimeScaleConfig } from './scales/types';\n// Theme utilities\nexport { resetTheme, seriesColor, setTheme } from './theme';\nexport type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';\n",
|
|
3
|
+
"docs": {
|
|
4
|
+
"index": "---\ntitle: Prism — Responsive SVG data visualization\ndescription: Responsive SVG charts with explicit updates, accessible interactions, and CSS theming.\npackage: prism\ncategory: ui\nkeywords: [chart, svg, visualization, responsive, line-chart, bar-chart, area-chart, typescript]\nrelated: [refine, orbit]\nexports:\n [\n createLineChart,\n createBarChart,\n createAreaChart,\n createPieChart,\n createSparkline,\n linearScale,\n timeScale,\n bandScale,\n seriesColor,\n setTheme,\n resetTheme,\n PrismError,\n ChartA11y,\n ContinuousDatum,\n EasingFn,\n StackSegment,\n XAxisConfig,\n YAxisConfig,\n ]\nenvironments: [browser]\n---\n\n<!-- markdownlint-disable MD025 MD033 MD060 -->\n\n<PackageHero package=\"prism\" />\n\n## Why Prism?\n\nCharting libraries typically require a framework binding, bundle heavy dependencies, or force canvas rendering that can't be styled with CSS. Prism takes a different approach:\n\n```ts\n// Before — Chart.js, imperative setup with a canvas you can't CSS-theme\nimport Chart from 'chart.js/auto';\nconst ctx = document.getElementById('myChart') as HTMLCanvasElement;\nnew Chart(ctx, {\n type: 'line',\n data: { labels, datasets: [{ data: values }] },\n // re-create or mutate the Chart.js instance when data changes\n});\n\n// After — Prism, responsive SVG with an explicit update boundary\nimport { createLineChart } from '@vielzeug/prism';\n\nconst chart = createLineChart(document.getElementById('chart')!, {\n a11y: { ariaLabel: 'Users by day' },\n series: [\n {\n data: [\n { key: 1, value: 12 },\n { key: 2, value: 40 },\n { key: 3, value: 28 },\n ],\n name: 'Users',\n },\n ],\n tooltip: true,\n});\n\nchart.update([\n {\n data: [\n { key: 1, value: 12 },\n { key: 2, value: 40 },\n { key: 3, value: 28 },\n { key: 4, value: 65 },\n ],\n name: 'Users',\n },\n]);\n```\n\n| Feature | Prism | Chart.js | Lightweight Charts | D3 |\n| ------------------ | -------------------------------------------- | ---------------------------------------- | -------------------------------------------- | -------------------------------------------- |\n| Bundle size | <PackageInfo package=\"prism\" type=\"size\" /> | ~60 kB | ~45 kB | ~30 kB (core) |\n| Zero dependencies | <ore-icon name=\"x\" size=\"16\"></ore-icon> (Orbit) | <ore-icon name=\"x\" size=\"16\"></ore-icon> | <ore-icon name=\"x\" size=\"16\"></ore-icon> | <ore-icon name=\"triangle-alert\" size=\"16\"></ore-icon> (modular) |\n| Renderer | SVG | Canvas | Canvas | SVG/Canvas |\n| Data updates | Explicit `update()` | Instance mutation | Series mutation | Manual |\n| CSS themeable | <ore-icon name=\"check\" size=\"16\"></ore-icon> | <ore-icon name=\"x\" size=\"16\"></ore-icon> | Limited | <ore-icon name=\"check\" size=\"16\"></ore-icon> |\n| Framework-neutral | <ore-icon name=\"check\" size=\"16\"></ore-icon> | <ore-icon name=\"check\" size=\"16\"></ore-icon> | <ore-icon name=\"check\" size=\"16\"></ore-icon> | <ore-icon name=\"check\" size=\"16\"></ore-icon> |\n| Accessible SVG | <ore-icon name=\"check\" size=\"16\"></ore-icon> | <ore-icon name=\"x\" size=\"16\"></ore-icon> | <ore-icon name=\"x\" size=\"16\"></ore-icon> | Manual |\n| TypeScript-first | <ore-icon name=\"check\" size=\"16\"></ore-icon> | Partial | <ore-icon name=\"check\" size=\"16\"></ore-icon> | Types available |\n\n<div class=\"decision-callout\">\n\n**Use Prism when** you need lightweight, framework-neutral charts with explicit updates and SVG output that can be styled with CSS. It fits dashboards, admin panels, and data-heavy applications.\n\n**Consider alternatives when** you need 50+ chart types (ECharts), financial trading charts (Lightweight Charts), or low-level visualization grammar (D3).\n\n</div>\n\n## Installation\n\n::: code-group\n\n```sh [pnpm]\npnpm add @vielzeug/prism\n```\n\n```sh [npm]\nnpm install @vielzeug/prism\n```\n\n```sh [yarn]\nyarn add @vielzeug/prism\n```\n\n:::\n\n## Quick Start\n\n```ts\nimport { createLineChart } from '@vielzeug/prism';\nimport '@vielzeug/prism/theme';\n\nconst chart = createLineChart(document.getElementById('chart')!, {\n a11y: { ariaLabel: 'Revenue by month' },\n series: [\n {\n color: '#3b82f6',\n data: [\n { key: 1, value: 10 },\n { key: 2, value: 25 },\n { key: 3, value: 18 },\n { key: 4, value: 32 },\n ],\n name: 'Revenue',\n },\n ],\n xAxis: { position: 'bottom' },\n yAxis: { position: 'left', grid: true },\n tooltip: true,\n crosshair: true,\n onHover: (event) => console.log(event?.datum),\n});\n\n// Update chart data explicitly\nchart.update([\n {\n color: '#3b82f6',\n data: [{ key: 1, value: 10 }, { key: 2, value: 25 }, { key: 3, value: 18 }, { key: 4, value: 32 }, { key: 5, value: 28 }],\n name: 'Revenue',\n },\n]);\n\n// Cleanup when done\nchart.dispose();\n```\n\n## Features\n\n<div class=\"features-grid\">\n\n- **`createLineChart(container, config)`** — line chart with linear, monotone, or step interpolation\n- **`createBarChart(container, config)`** — bar chart with four layout variants: grouped, stacked, grouped-horizontal, stacked-horizontal\n- **`createAreaChart(container, config)`** — filled area with configurable opacity\n- **`createSparkline(container, config)`** — minimal inline sparkline (line, area, or bar variant)\n- **`createPieChart(container, config)`** — pie, donut, or semi-circle donut chart\n- **`linearScale(config)`** — continuous numeric scale with nice tick generation\n- **`timeScale(config)`** — date/time scale with interval-based ticks\n- **`bandScale(config)`** — categorical scale for bar charts\n- **`ChartHandle.update(data)`** — replace chart data synchronously without coupling to a state library\n- **`seriesColor(index, override?)`** — resolve CSS palette color by series index\n- **`setTheme(theme)` / `resetTheme()`** — apply or clear custom colors, font, and grid tokens at runtime\n- **Event hooks** — `onClick` and `onHover` callbacks on every chart\n- **Devtools** — `debugChart()` from `@vielzeug/prism/devtools` logs mount/resize/dispose to `console.debug`; tree-shaken from production unless imported\n- **CSS custom properties** — full theme control via `--prism-*` tokens\n- **Responsive** — auto-resizes via `ResizeObserver`\n- **Accessible** — ARIA labels and semantic SVG structure\n- **`Symbol.dispose`** — explicit resource management following TC39 proposal\n\n</div>\n\n## Sub-paths\n\n| Import | Purpose |\n| -------------------------- | ------------------------------------------------------------------------------------ |\n| `@vielzeug/prism` | All chart factories, scales, and types |\n| `@vielzeug/prism/theme` | Default CSS (custom properties + dark mode) |\n| `@vielzeug/prism/devtools` | `debugChart()` — opt-in `console.debug` lifecycle logging, tree-shaken in production |\n\n## Documentation\n\n<div class=\"doc-links\">\n\n- [Usage Guide](./usage.md)\n- [API Reference](./api.md)\n- [Examples](./examples.md)\n- [Migration Guide](./migration.md)\n\n</div>\n\n## See Also\n\n<div class=\"see-also\">\n\n- [Refine](/refine/) — accessible web components that pair well with Prism for dashboards\n- [Orbit](/orbit/) — floating element positioning for chart tooltips and popovers\n\n</div>\n\n<!-- markdownlint-enable MD025 MD033 MD060 -->\n",
|
|
5
|
+
"api": "---\ntitle: Prism — API Reference\ndescription: Complete chart, scale, theme, handle, configuration, and error contracts for @vielzeug/prism.\n---\n\n[[toc]]\n\n## API Overview\n\n| Symbol | Purpose | Execution mode | Common gotcha |\n| --- | --- | --- | --- |\n| `createLineChart()` | Render a line chart | Sync | Line keys must be numbers or dates |\n| `createAreaChart()` | Render an area chart | Sync | Line keys must be numbers or dates |\n| `createBarChart()` | Render grouped or stacked bars | Sync | Stacked negative values are clamped to zero |\n| `createPieChart()` | Render pie, donut, or semi-circle slices | Sync | Event callbacks use slice/index arguments |\n| `createSparkline()` | Render an inline line, area, bar, or stack | Sync | Omitted `a11y` makes the chart decorative |\n| `linearScale()` | Create a numeric scale | Sync | `nice` defaults to `true` |\n| `timeScale()` | Create a date scale | Sync | Invalid dates produce an invalid domain |\n| `bandScale()` | Create a categorical scale | Sync | Unknown categories map to `0` and warn in development |\n| `setTheme()` | Set Prism CSS custom properties | Sync | Values apply to `document.documentElement` |\n| `resetTheme()` | Remove Prism theme overrides | Sync | Removes only properties managed by `setTheme()` |\n| `seriesColor()` | Resolve a series palette color | Sync | Palette indexes wrap after eight colors |\n| `debugChart()` | Log chart lifecycle events | Sync | Import from `@vielzeug/prism/devtools` |\n\n## Package Entry Point\n\n| Import | Purpose |\n| --- | --- |\n| `@vielzeug/prism` | Chart factories, scales, theme helpers, errors, and public types |\n| `@vielzeug/prism/theme` | Default CSS custom properties and dark-mode values |\n| `@vielzeug/prism/devtools` | Optional `debugChart()` lifecycle logging |\n\n## Chart Factories\n\n### `createLineChart()`\n\n```ts\nfunction createLineChart(\n container: HTMLElement,\n config: LineChartConfig,\n): ChartHandle<LineSeriesConfig[]>;\n```\n\nRenders a line chart and returns a handle that replaces the complete series array through `update()`.\n\n| Parameter | Type | Description |\n| --- | --- | --- |\n| `container` | `HTMLElement` | Host that receives the SVG and optional overlays |\n| `config` | `LineChartConfig` | Initial series, axes, interaction, accessibility, and transition settings |\n\n**Returns:** `ChartHandle<LineSeriesConfig[]>`.\n\n```ts\nimport { createLineChart } from '@vielzeug/prism';\n\nconst chart = createLineChart(container, {\n a11y: { ariaLabel: 'Revenue by month' },\n series: [{ data: [{ key: 1, value: 10 }], name: 'Revenue' }],\n});\n\nchart.update([{ data: [{ key: 2, value: 20 }], name: 'Revenue' }]);\n```\n\n---\n\n### `createAreaChart()`\n\n```ts\nfunction createAreaChart(\n container: HTMLElement,\n config: AreaChartConfig,\n): ChartHandle<AreaSeriesConfig[]>;\n```\n\nRenders an area chart and returns a handle that replaces the complete series array through `update()`.\n\n| Parameter | Type | Description |\n| --- | --- | --- |\n| `container` | `HTMLElement` | Host that receives the SVG and optional overlays |\n| `config` | `AreaChartConfig` | Initial series, axes, interaction, accessibility, and transition settings |\n\n**Returns:** `ChartHandle<AreaSeriesConfig[]>`.\n\n```ts\nimport { createAreaChart } from '@vielzeug/prism';\n\nconst chart = createAreaChart(container, {\n series: [{ data: [{ key: 1, value: 10 }], name: 'Revenue' }],\n});\n```\n\n---\n\n### `createBarChart()`\n\n```ts\nfunction createBarChart(\n container: HTMLElement,\n config: BarChartConfig,\n): ChartHandle<BarSeriesConfig[]>;\n```\n\nRenders grouped, stacked, grouped-horizontal, or stacked-horizontal bars.\n\n| Parameter | Type | Description |\n| --- | --- | --- |\n| `container` | `HTMLElement` | Host that receives the SVG and optional overlays |\n| `config` | `BarChartConfig` | Initial series, variant, axes, accessibility, and interaction settings |\n\n**Returns:** `ChartHandle<BarSeriesConfig[]>`.\n\n```ts\nimport { createBarChart } from '@vielzeug/prism';\n\nconst chart = createBarChart(container, {\n series: [{ data: [{ key: 'Open', value: 12 }], name: 'Tasks' }],\n variant: 'grouped',\n});\n```\n\n---\n\n### `createPieChart()`\n\n```ts\nfunction createPieChart(\n container: HTMLElement,\n config: PieChartConfig,\n): ChartHandle<PieSliceConfig[]>;\n```\n\nRenders pie, donut, or semi-circle slices.\n\n| Parameter | Type | Description |\n| --- | --- | --- |\n| `container` | `HTMLElement` | Host that receives the SVG and optional overlays |\n| `config` | `PieChartConfig` | Initial slices, variant, geometry, accessibility, and interaction settings |\n\n**Returns:** `ChartHandle<PieSliceConfig[]>`.\n\n```ts\nimport { createPieChart } from '@vielzeug/prism';\n\nconst chart = createPieChart(container, {\n data: [{ label: 'Complete', value: 72 }, { label: 'Remaining', value: 28 }],\n variant: 'donut',\n});\n```\n\n---\n\n### `createSparkline()`\n\n```ts\nfunction createSparkline(\n container: HTMLElement,\n config: SparklineConfig,\n): ChartHandle<number[] | StackSegment[]>;\n```\n\nRenders a compact chart without axes, margin, or legend.\n\n| Parameter | Type | Description |\n| --- | --- | --- |\n| `container` | `HTMLElement` | Host that receives the SVG |\n| `config` | `SparklineConfig` | Initial values, variant, appearance, accessibility, and callbacks |\n\n**Returns:** `ChartHandle<number[] | StackSegment[]>`.\n\n```ts\nimport { createSparkline } from '@vielzeug/prism';\n\nconst chart = createSparkline(container, { data: [2, 5, 3, 8], variant: 'area' });\nchart.update([2, 5, 3, 8, 13]);\n```\n\n## Scale Factories\n\n### `linearScale()`\n\n```ts\nfunction linearScale(config: LinearScaleConfig): Scale<number>;\n```\n\n| Field | Type | Default | Description |\n| --- | --- | --- | --- |\n| `domain` | `[number, number]` | — | Input extent |\n| `range` | `[number, number]` | — | Output extent |\n| `clamp` | `boolean` | `false` | Clamp mapped and inverted values |\n| `nice` | `boolean` | `true` | Expand the domain to rounded boundaries |\n\n**Returns:** `Scale<number>`.\n\n```ts\nimport { linearScale } from '@vielzeug/prism';\n\nconst scale = linearScale({ domain: [0, 100], range: [0, 500] });\nscale.map(50); // 250\n```\n\n---\n\n### `timeScale()`\n\n```ts\nfunction timeScale(config: TimeScaleConfig): Scale<Date>;\n```\n\n| Field | Type | Default | Description |\n| --- | --- | --- | --- |\n| `domain` | `[Date, Date]` | — | Input date extent |\n| `range` | `[number, number]` | — | Output extent |\n| `nice` | `boolean` | `true` | Expand the domain to rounded interval boundaries |\n\n**Returns:** `Scale<Date>`.\n\n```ts\nimport { timeScale } from '@vielzeug/prism';\n\nconst scale = timeScale({\n domain: [new Date('2026-01-01'), new Date('2026-12-31')],\n range: [0, 500],\n});\n```\n\n---\n\n### `bandScale()`\n\n```ts\nfunction bandScale(config: BandScaleConfig): BandScale;\n```\n\n| Field | Type | Default | Description |\n| --- | --- | --- | --- |\n| `domain` | `string[]` | — | Ordered categories |\n| `range` | `[number, number]` | — | Output extent |\n| `padding` | `number` | `0.1` | Inner gap ratio |\n| `paddingOuter` | `number` | `padding` | Outer gap ratio |\n\n**Returns:** `BandScale`.\n\n```ts\nimport { bandScale } from '@vielzeug/prism';\n\nconst scale = bandScale({ domain: ['A', 'B'], range: [0, 200] });\n```\n\n## Theme Utilities\n\n### `setTheme()`\n\n```ts\nfunction setTheme(theme: PrismTheme): void;\n```\n\nSets Prism color, font, and grid custom properties on `document.documentElement`.\n\n### `resetTheme()`\n\n```ts\nfunction resetTheme(): void;\n```\n\nRemoves every custom property managed by `setTheme()`.\n\n### `seriesColor()`\n\n```ts\nfunction seriesColor(index: number, override?: string): string;\n```\n\nReturns `override` when provided; otherwise returns `var(--prism-color-N)` with an eight-color wrap.\n\n## Types\n\n### Core types\n\n```ts\ninterface ChartHandle<TData = unknown> {\n readonly disposalSignal: AbortSignal;\n readonly disposed: boolean;\n readonly el: SVGSVGElement;\n update(data: TData): void;\n dispose(): void;\n [Symbol.dispose](): void;\n}\n\ninterface ChartMargin {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n\ninterface ChartDimensions {\n width: number;\n height: number;\n margin: ChartMargin;\n}\n\ntype ChartA11y =\n | { readonly decorative: true }\n | { readonly ariaLabel: string; readonly decorative?: false };\n```\n\n`update()` renders synchronously and throws `PrismRenderError` after disposal. Omitting `a11y` makes the SVG decorative with `aria-hidden=\"true\"`.\n\n---\n\n### Data types\n\n```ts\ninterface Datum<TKey extends Date | number | string = Date | number | string> {\n key: TKey;\n value: number;\n meta?: Record<string, unknown>;\n}\n\ntype ContinuousDatum = Datum<Date | number>;\n\ninterface Series<TDatum extends Datum = Datum> {\n name: string;\n data: TDatum[];\n color?: string;\n}\n\ninterface ChartEvent {\n datum: Datum;\n series: Series;\n originalEvent: Event;\n}\n```\n\nLine and area series use `ContinuousDatum`; bar series accept the complete `Datum` key range.\n\n---\n\n### Chart configurations\n\n```ts\ninterface BaseChartConfig {\n a11y?: ChartA11y;\n legend?: boolean | LegendConfig;\n margin?: Partial<ChartMargin>;\n onClick?: (event: ChartEvent) => void;\n onHover?: (event: ChartEvent | null) => void;\n tooltip?: boolean | TooltipConfig;\n transition?: TransitionConfig;\n xAxis?: XAxisConfig;\n yAxis?: YAxisConfig;\n}\n\ninterface LineChartConfig extends BaseChartConfig {\n crosshair?: boolean | CrosshairConfig;\n series: LineSeriesConfig[];\n}\n\ninterface AreaChartConfig extends BaseChartConfig {\n crosshair?: boolean | CrosshairConfig;\n series: AreaSeriesConfig[];\n}\n\ninterface BarChartConfig extends BaseChartConfig {\n series: BarSeriesConfig[];\n variant?: BarVariant;\n}\n\ninterface PieChartConfig\n extends Omit<BaseChartConfig, 'margin' | 'onClick' | 'onHover' | 'xAxis' | 'yAxis'> {\n data: PieSliceConfig[];\n variant?: PieVariant;\n innerRadius?: number;\n cornerRadius?: number;\n padPixels?: number;\n onClick?: (slice: PieSliceConfig, index: number) => void;\n onHover?: (slice: PieSliceConfig | null, index: number | null) => void;\n}\n\ninterface SparklineConfig {\n data: number[] | StackSegment[];\n variant?: SparklineVariant;\n a11y?: ChartA11y;\n color?: string;\n cornerRadius?: number;\n curve?: 'linear' | 'monotone' | 'step';\n fillOpacity?: number;\n onClick?: (index: number, value: number) => void;\n onHover?: (index: number | null, value: number | null) => void;\n padPixels?: number;\n strokeWidth?: number;\n transition?: TransitionConfig;\n}\n```\n\n---\n\n### Series and slice configurations\n\n```ts\ninterface LineSeriesConfig extends Series<ContinuousDatum> {\n curve?: 'linear' | 'monotone' | 'step';\n pointRadius?: number;\n showPoints?: boolean;\n strokeWidth?: number;\n}\n\ninterface AreaSeriesConfig extends Series<ContinuousDatum> {\n curve?: 'linear' | 'monotone' | 'step';\n fillOpacity?: number;\n showLine?: boolean;\n}\n\ninterface BarSeriesConfig extends Series {\n borderRadius?: number;\n}\n\ninterface PieSliceConfig {\n value: number;\n color?: string;\n label?: string;\n}\n\ninterface StackSegment {\n value: number;\n color?: string;\n label?: string;\n}\n```\n\n---\n\n### Axis, interaction, and transition configurations\n\n```ts\ntype HorizontalAxisPosition = 'bottom' | 'top';\ntype VerticalAxisPosition = 'left' | 'right';\ntype AxisPosition = HorizontalAxisPosition | VerticalAxisPosition;\n\ninterface AxisConfig<TPosition extends AxisPosition = AxisPosition> {\n grid?: boolean | GridConfig;\n label?: string;\n position?: TPosition;\n tickCount?: number;\n tickFormat?: (value: Date | number | string) => string;\n}\n\ntype XAxisConfig = AxisConfig<HorizontalAxisPosition>;\ntype YAxisConfig = AxisConfig<VerticalAxisPosition>;\n\ninterface GridConfig {\n color?: string;\n dash?: string;\n}\n\ninterface TooltipConfig {\n offset?: number;\n render?: (datum: Datum, series: Series) => Node | string;\n}\n\ninterface CrosshairConfig {\n horizontal?: boolean;\n snap?: boolean;\n vertical?: boolean;\n}\n\ninterface LegendConfig {\n position?: LegendPosition;\n}\n\ntype LegendPosition = 'bottom' | 'left' | 'right' | 'top';\n\ninterface TransitionConfig {\n duration?: number;\n easing?: EasingFn | 'ease-in' | 'ease-in-out' | 'ease-out' | 'linear';\n preference?: 'always' | 'never' | 'system';\n stagger?: number;\n}\n\ntype EasingFn = (t: number) => number;\n```\n\nTooltip strings are assigned through `textContent`. Return a `Node` for structured content.\n\n---\n\n### Scale types\n\n```ts\ninterface Scale<T> {\n readonly domain: readonly [T, T];\n readonly range: readonly [number, number];\n map(value: T): number;\n invert(pixel: number): T;\n ticks(count?: number): T[];\n}\n\ninterface BandScale {\n readonly domain: readonly string[];\n readonly range: readonly [number, number];\n map(value: string): number;\n ticks(count?: number): string[];\n bandwidth(): number;\n gap(): number;\n}\n\ninterface LinearScaleConfig {\n domain: [number, number];\n range: [number, number];\n clamp?: boolean;\n nice?: boolean;\n}\n\ninterface TimeScaleConfig {\n domain: [Date, Date];\n range: [number, number];\n nice?: boolean;\n}\n\ninterface BandScaleConfig {\n domain: string[];\n range: [number, number];\n padding?: number;\n paddingOuter?: number;\n}\n```\n\n---\n\n### Remaining unions and theme type\n\n```ts\ntype BarVariant = 'grouped' | 'grouped-horizontal' | 'stacked' | 'stacked-horizontal';\ntype PieVariant = 'donut' | 'pie' | 'semi';\ntype SparklineVariant = 'area' | 'bar' | 'line' | 'stack';\n\ninterface PrismTheme {\n colors?: string[];\n fontFamily?: string;\n gridColor?: string;\n gridOpacity?: number;\n}\n```\n\n## Devtools\n\n### `debugChart()`\n\n```ts\nfunction debugChart<T extends ChartHandle>(\n handle: T,\n options?: { label?: string },\n): T;\n```\n\nLogs mount, resize, and disposal events to `console.debug` and returns the same handle. Import it from `@vielzeug/prism/devtools`.\n\n## Errors\n\n### `PrismError`\n\nBase class for every Prism-originated error. It supports standard `ErrorOptions` cause chaining.\n\n### `PrismRenderError`\n\nExtends `PrismError`. Thrown for invalid containers, failed initial renders, and attempts to update disposed charts.\n",
|
|
6
|
+
"usage": "---\ntitle: Prism — Usage Guide\ndescription: Concepts, update patterns, and best practices for responsive SVG charts with @vielzeug/prism.\n---\n\n[[toc]]\n\n## Basic Usage\n\nEvery chart needs a container element with defined dimensions and the theme CSS:\n\n```ts\nimport { createLineChart } from '@vielzeug/prism';\nimport '@vielzeug/prism/theme';\n\nconst container = document.querySelector<HTMLElement>('#chart')!;\nconst chart = createLineChart(container, {\n series: [\n {\n name: 'Revenue',\n data: [\n { key: 1, value: 10 },\n { key: 2, value: 16 },\n ],\n },\n ],\n});\n\nchart.dispose();\n```\n\n```html\n<div id=\"chart\" style=\"width: 100%; height: 300px;\"></div>\n```\n\nPrism observes the container size via `ResizeObserver` and re-renders automatically on resize. If the container has zero dimensions at mount time, a `warn` is emitted in development — ensure the container has layout before calling the chart factory.\n\n## Updating Data\n\nChart factories render synchronously and return a typed handle. Call `update()` with the same data shape used by the factory when application state changes.\n\n```ts\nimport { createLineChart } from '@vielzeug/prism';\n\nconst chart = createLineChart(container, {\n series: [{ data: [{ key: 1, value: 10 }], name: 'Live' }],\n});\n\nchart.update([\n {\n data: [\n { key: 1, value: 10 },\n { key: 2, value: 20 },\n ],\n name: 'Live',\n },\n]);\n```\n\n`update()` is state-library neutral. Call it from a framework effect, store subscription, event handler, or request callback. It throws after the chart is disposed instead of silently retaining detached state.\n\n## Line Charts\n\n```ts\nimport { createLineChart } from '@vielzeug/prism';\n\nconst chart = createLineChart(container, {\n series: [\n {\n name: 'Revenue',\n data: [\n { key: 1, value: 100 },\n { key: 2, value: 150 },\n { key: 3, value: 130 },\n ],\n color: '#3b82f6',\n curve: 'monotone', // 'linear' | 'monotone' | 'step'\n strokeWidth: 2,\n showPoints: true,\n pointRadius: 4,\n },\n ],\n xAxis: { position: 'bottom' },\n yAxis: { position: 'left', grid: true },\n tooltip: true,\n crosshair: true,\n});\n```\n\n### Multiple Series\n\n```ts\nconst chart = createLineChart(container, {\n series: [\n { name: 'Revenue', data: revenueData, color: '#3b82f6' },\n { name: 'Expenses', data: expenseData, color: '#ef4444' },\n ],\n xAxis: { position: 'bottom' },\n yAxis: { position: 'left', grid: true },\n});\n```\n\n### Time-based X Axis\n\nWhen data points use `Date` objects for `key`, Prism automatically applies a time scale:\n\n```ts\nconst chart = createLineChart(container, {\n series: [\n {\n name: 'Signups',\n data: [\n { key: new Date('2024-01-01'), value: 50 },\n { key: new Date('2024-02-01'), value: 80 },\n { key: new Date('2024-03-01'), value: 120 },\n ],\n },\n ],\n xAxis: { position: 'bottom', tickFormat: (d) => (d as Date).toLocaleDateString() },\n yAxis: { position: 'left' },\n});\n```\n\n## Bar Charts\n\n```ts\nimport { createBarChart } from '@vielzeug/prism';\n\nconst chart = createBarChart(container, {\n series: [\n {\n name: 'Sales',\n data: [\n { key: 'Q1', value: 200 },\n { key: 'Q2', value: 350 },\n { key: 'Q3', value: 280 },\n { key: 'Q4', value: 400 },\n ],\n borderRadius: 4,\n },\n ],\n xAxis: { position: 'bottom' },\n yAxis: { position: 'left', grid: true },\n tooltip: true,\n});\n```\n\n### Variants\n\nSelect the bar layout with `variant`:\n\n| Value | Layout |\n| ---------------------- | -------------------------- |\n| `'grouped'` | Vertical grouped (default) |\n| `'stacked'` | Vertical stacked |\n| `'grouped-horizontal'` | Horizontal grouped |\n| `'stacked-horizontal'` | Horizontal stacked |\n\n```ts\nconst chart = createBarChart(container, {\n variant: 'stacked',\n series: [\n { name: 'Mobile', data: mobileData, color: '#3b82f6', borderRadius: 0 },\n { name: 'Desktop', data: desktopData, color: '#10b981', borderRadius: 0 },\n ],\n xAxis: { position: 'bottom' },\n yAxis: { position: 'left', grid: true },\n tooltip: true,\n legend: true,\n});\n```\n\nFor horizontal layouts, categories appear on the Y axis and values on the X axis:\n\n```ts\nconst chart = createBarChart(container, {\n variant: 'grouped-horizontal',\n series: [{ name: 'Revenue', data, color: '#3b82f6' }],\n xAxis: { position: 'bottom', grid: true },\n yAxis: { position: 'left' },\n});\n```\n\n### Grouped Bars\n\nMultiple series with `variant: 'grouped'` (default) render side-by-side:\n\n```ts\nconst chart = createBarChart(container, {\n series: [\n { name: '2023', data: lastYearData, color: '#94a3b8' },\n { name: '2024', data: thisYearData, color: '#3b82f6' },\n ],\n});\n```\n\n## Area Charts\n\n```ts\nimport { createAreaChart } from '@vielzeug/prism';\n\nconst chart = createAreaChart(container, {\n series: [\n {\n name: 'Users',\n data: userData,\n curve: 'monotone',\n fillOpacity: 0.2,\n showLine: true,\n },\n ],\n xAxis: { position: 'bottom' },\n yAxis: { position: 'left', grid: true },\n crosshair: true,\n});\n```\n\n## Pie, Donut, and Semi-circle Charts\n\nAll three variants use `createPieChart` with the `variant` field:\n\n```ts\nimport { createPieChart } from '@vielzeug/prism';\n\nconst chart = createPieChart(container, {\n data: [\n { label: 'Direct', value: 42, color: '#3b82f6' },\n { label: 'Organic', value: 28, color: '#10b981' },\n { label: 'Referral', value: 18, color: '#f59e0b' },\n { label: 'Social', value: 12, color: '#8b5cf6' },\n ],\n variant: 'donut', // 'pie' | 'donut' | 'semi'\n tooltip: true,\n transition: { duration: 400, easing: 'ease-out' },\n});\n```\n\n### Variants\n\n| Value | Shape |\n| --------- | ------------------------------------------------------- |\n| `'pie'` | Full circle, no hole |\n| `'donut'` | Full circle with inner hole (~55% of outer by default) |\n| `'semi'` | Top-half semicircle with inner hole — useful for gauges |\n\n### Inner Radius\n\n`innerRadius` overrides the automatic calculation:\n\n```ts\ncreatePieChart(container, {\n data,\n variant: 'donut',\n innerRadius: 60, // explicit pixels\n});\n```\n\n### Slice Labels\n\nSet `label` on each `PieSliceConfig` to render text at the arc centroid:\n\n```ts\n{ value: 42, label: '42%' }\n```\n\nStyle labels via CSS:\n\n```css\n:root {\n --prism-pie-label-color: #fff;\n --prism-pie-label-size: 11px;\n}\n```\n\n### Updating Data\n\n```ts\nconst chart = createPieChart(container, {\n data: [\n { label: 'A', value: 40 },\n { label: 'B', value: 60 },\n ],\n variant: 'donut',\n});\n\nchart.update([\n { label: 'A', value: 55 },\n { label: 'B', value: 45 },\n]);\n```\n\n### Event Hooks\n\n```ts\ncreatePieChart(container, {\n data,\n onHover: (slice, index) => {\n // slice/index are null on mouseleave\n if (slice) console.log(slice.label, slice.value);\n },\n onClick: (slice, index) => {\n console.log('clicked', slice.label);\n },\n});\n```\n\n## Sparklines\n\nSparklines are minimal inline charts with no axes, no legend, and no margin — designed to live inline with text or inside table cells.\n\n```ts\nimport { createSparkline } from '@vielzeug/prism';\n\nconst spark = createSparkline(container, {\n data: [12, 18, 14, 22, 19, 28],\n variant: 'line', // 'line' | 'area' | 'bar' (default: 'line')\n color: '#3b82f6',\n curve: 'monotone',\n strokeWidth: 1.5,\n});\n\nspark.dispose();\n```\n\n### Variants\n\n- **`line`** — simple polyline path (default)\n- **`area`** — filled area + line overlay\n- **`bar`** — vertical bar for each data point\n- **`stack`** — horizontal proportional segments; use `StackSegment[]` for `data` with per-segment colors\n\n### Updating Data\n\n```ts\nconst spark = createSparkline(container, {\n data: [12, 18, 14, 22],\n variant: 'area',\n});\n\nspark.update([12, 18, 14, 22, 30]);\n```\n\n### Event Hooks\n\nSparklines use simplified hooks — index-based rather than full `ChartEvent`:\n\n```ts\nconst spark = createSparkline(container, {\n data: [10, 20, 30],\n onHover: (index, value) => {\n // index/value are null on mouseleave\n if (index !== null) console.log(`Hovering point ${index}: ${value}`);\n },\n onClick: (index, value) => {\n console.log(`Clicked point ${index}: ${value}`);\n },\n});\n```\n\n> **Note:** Sparkline SVGs are marked `aria-hidden=\"true\"` since they are decorative. Provide meaningful surrounding text context for accessibility.\n\n## Axes and Grid\n\n```ts\n{\n xAxis: {\n position: 'bottom', // 'top' | 'bottom'\n tickCount: 5,\n tickFormat: (v) => `$${v}`,\n label: 'Month',\n grid: true, // or { color: '#ddd', dash: '4 2' }\n },\n yAxis: {\n position: 'left', // 'left' | 'right'\n grid: { color: '#f0f0f0' },\n label: 'Revenue ($)',\n },\n}\n```\n\n## Tooltips\n\nEnable with `tooltip: true` for default rendering, or provide a custom `render` function. Strings are rendered as text. Return a DOM node for structured content:\n\n```ts\n{\n tooltip: {\n offset: 12,\n render: (datum, series) => {\n const content = document.createElement('strong');\n content.textContent = `${series.name}: ${datum.value.toLocaleString()}`;\n return content;\n },\n },\n}\n```\n\nPrism never injects tooltip strings as HTML, so custom rendering does not require a sanitizer.\n\nThe tooltip element is scoped inside the chart container (not `document.body`) and is removed automatically on `dispose()`.\n\n## Crosshair\n\nA vertical guide that snaps to the nearest data point:\n\n```ts\n{\n crosshair: true,\n // or configure:\n crosshair: { vertical: true, horizontal: true, snap: true },\n}\n```\n\n## Legend\n\nEnable with `legend: true` (defaults to `bottom`) or configure position:\n\n```ts\n{\n legend: true,\n // or:\n legend: { position: 'top' }, // 'top' | 'bottom' | 'left' | 'right'\n}\n```\n\nThe legend renders as a `div` placed outside the SVG. Each item shows a color swatch and the series `name`. Customize via CSS:\n\n```css\n:root {\n --prism-legend-gap: 1rem;\n --prism-legend-dot-size: 0.5rem;\n --prism-legend-font-size: 0.75rem;\n}\n```\n\n## Event Hooks\n\nAll charts expose `onClick` and `onHover` callbacks on the config:\n\n```ts\nconst chart = createLineChart(container, {\n series: [{ name: 'Revenue', data }],\n onHover: (event) => {\n // event is ChartEvent | null (null on mouseleave)\n if (event) console.log(event.datum, event.series);\n },\n onClick: (event) => {\n console.log('clicked', event.datum);\n },\n});\n```\n\n`ChartEvent` provides:\n\n- `datum` — the nearest `Datum`\n- `series` — the corresponding `Series` config\n- `originalEvent` — the raw `MouseEvent`\n\n> **Pie chart events differ** — `onHover` and `onClick` receive `(slice: PieSliceConfig, index: number)` instead of `ChartEvent`. See [`PieChartConfig`](./api.md#piechartconfig) for details.\n\n## Animations\n\nPass a `transition` config to animate enter and update transitions:\n\n```ts\n{\n transition: {\n duration: 400,\n easing: 'ease-out',\n stagger: 30, // bar charts only: ms delay between each bar's enter animation\n },\n}\n```\n\nAll chart types use requestAnimationFrame-based interpolation. Bar charts additionally support `stagger` — a per-bar delay that creates a cascade effect on first render.\n\n## Theming\n\nImport the default theme:\n\n```ts\nimport '@vielzeug/prism/theme';\n```\n\n### Programmatic Theme with `setTheme`\n\nCall `setTheme` once at app startup to apply custom tokens programmatically:\n\n```ts\nimport { setTheme } from '@vielzeug/prism';\n\nsetTheme({\n colors: ['#6366f1', '#22d3ee', '#f59e0b', '#10b981'], // replaces --prism-color-1 through -4\n fontFamily: 'Inter, system-ui, sans-serif', // sets --prism-font-family\n gridColor: '#e2e8f0', // sets --prism-grid-color\n gridOpacity: 0.6, // sets --prism-grid-opacity\n});\n```\n\n`setTheme` writes to `document.documentElement` style, so it takes precedence over CSS file defaults. Call `resetTheme()` to clear every custom property `setTheme` can set and restore the default theme — useful for a theme-switcher's \"reset\" action or test teardown:\n\n```ts\nimport { resetTheme } from '@vielzeug/prism';\n\nresetTheme();\n```\n\n### Custom Theme (CSS)\n\n```css\n:root {\n --prism-color-1: #6366f1;\n --prism-color-2: #22c55e;\n --prism-axis-color: #71717a;\n --prism-grid-color: #f4f4f5;\n --prism-text-color: #18181b;\n --prism-tooltip-bg: #27272a;\n --prism-font-family: 'Inter', system-ui, sans-serif;\n}\n```\n\n### Scoped Themes\n\nApply tokens to a specific container:\n\n```css\n.dark-dashboard {\n --prism-axis-color: #64748b;\n --prism-grid-color: #334155;\n --prism-text-color: #e2e8f0;\n}\n```\n\n### Available Tokens\n\n| Token | Default | Description |\n| ------------------------- | ---------------- | ---------------------- |\n| `--prism-color-{1-8}` | Tailwind palette | Series color palette |\n| `--prism-bg` | `transparent` | Chart background |\n| `--prism-axis-color` | `#94a3b8` | Axis lines and ticks |\n| `--prism-grid-color` | `#e2e8f0` | Grid lines |\n| `--prism-text-color` | `#334155` | Axis labels and text |\n| `--prism-font-family` | `system-ui` | Chart font |\n| `--prism-font-size` | `12px` | Label font size |\n| `--prism-tooltip-bg` | `#1e293b` | Tooltip background |\n| `--prism-tooltip-color` | `#f8fafc` | Tooltip text |\n| `--prism-tooltip-radius` | `6px` | Tooltip border radius |\n| `--prism-crosshair-color` | `#64748b` | Crosshair line |\n| `--prism-crosshair-dash` | `4 2` | Crosshair dash pattern |\n\n## Scales (Standalone)\n\nScales can be used independently for custom visualizations:\n\n```ts\nimport { linearScale, timeScale, bandScale } from '@vielzeug/prism';\n\nconst y = linearScale({ domain: [0, 100], range: [300, 0] });\ny.map(50); // → 150\ny.invert(150); // → 50\ny.ticks(5); // → [0, 20, 40, 60, 80, 100]\n\nconst x = bandScale({ domain: ['A', 'B', 'C'], range: [0, 300] });\nx.map('B'); // → pixel left edge of band B\nx.bandwidth(); // → width of each band\n```\n\n## Lifecycle and Cleanup\n\nEvery chart returns a `ChartHandle`. Always call `dispose()` when removing a chart:\n\n```ts\nconst chart = createLineChart(container, config);\n\n// When done:\nchart.dispose();\n\n// Or with TC39 explicit resource management:\n{\n using chart = createLineChart(container, config);\n // auto-disposed at block end\n}\n```\n\nCalling `dispose()`:\n\n- Cancels in-flight transitions\n- Disconnects the `ResizeObserver`\n- Removes the SVG element, tooltip, and legend from the DOM\n- Restores container styles changed for tooltip positioning\n- Is idempotent — safe to call multiple times\n\nCall `update()` only while the handle is active. Updating a disposed chart throws `PrismRenderError`.\n\n## Responsive Behavior\n\nCharts resize automatically when the container dimensions change. Prism uses `ResizeObserver` internally — no manual `resize()` call is needed.\n\n## Devtools\n\nImport `debugChart()` from the `/devtools` subpath to log a chart's mount, resize, and dispose events to `console.debug`. It's separate from prism's internal validation warnings (those run automatically in development, no import needed) and is tree-shaken from production bundles when this subpath isn't imported.\n\n```ts\nimport { createLineChart } from '@vielzeug/prism';\nimport { debugChart } from '@vielzeug/prism/devtools';\n\nconst chart = debugChart(createLineChart(container, config), { label: 'revenue' });\n// [prism:revenue] mounted\n// [prism:revenue] resized 600×300\nchart.dispose();\n// [prism:revenue] disposed\n```\n\n> `debugChart()` wraps and returns the same `ChartHandle` unchanged, so it drops into any `create*Chart()` call without restructuring your code.\n\n## Framework Integration\n\nPrism has no framework adapter. Connect the same three operations to your framework's lifecycle: create after mount, update when state changes, and dispose before unmount.\n\n```ts\nimport { createLineChart, type ChartHandle, type ContinuousDatum, type LineSeriesConfig } from '@vielzeug/prism';\n\nlet chart: ChartHandle<LineSeriesConfig[]> | undefined;\n\nexport function mountChart(container: HTMLElement, data: ContinuousDatum[]): void {\n chart = createLineChart(container, { series: [{ data, name: 'Series' }] });\n}\n\nexport function updateChart(data: ContinuousDatum[]): void {\n chart?.update([{ data, name: 'Series' }]);\n}\n\nexport function unmountChart(): void {\n chart?.dispose();\n chart = undefined;\n}\n```\n\n## Working with Other Vielzeug Libraries\n\n### With Ripple\n\nKeep state ownership in Ripple and connect it to Prism through an explicit subscription.\n\n```ts\nimport { createLineChart } from '@vielzeug/prism';\nimport { signal } from '@vielzeug/ripple';\n\nconst data = signal([{ key: 1, value: 10 }]);\nconst toSeries = () => [{ data: data.value, name: 'Series' }];\nconst chart = createLineChart(container, { series: toSeries() });\nconst unsubscribe = data.subscribe(() => chart.update(toSeries()));\n\n// Cleanup both owners together.\nunsubscribe();\nchart.dispose();\n```\n\n### With Sourcerer\n\nBind chart data to a Sourcerer remote source so charts update whenever the list refreshes.\n\n```ts\nimport { createBarChart } from '@vielzeug/prism';\nimport { createPageSource } from '@vielzeug/sourcerer';\n\nconst source = createPageSource({\n load: async ({ page, pageSize, signal }) => {\n const result = await api.stats.list({ page, pageSize }, { signal });\n return { items: result.data, totalItems: result.total };\n },\n});\nconst toSeries = (state) => [\n {\n data: state.items.map((item) => ({ key: item.label, value: item.count })),\n name: 'Series',\n },\n];\nconst chart = createBarChart(container, { series: toSeries(source.state) });\nconst unsubscribe = source.subscribe((state) => chart.update(toSeries(state)));\nvoid source.reload().catch(() => undefined);\n```\n\n## Accessibility\n\nAccessibility is a hard requirement for every chart factory. Label informative charts with `a11y: { ariaLabel }`; charts without `a11y` are decorative and render with `aria-hidden=\"true\"`.\n\nLabel a chart that conveys meaningful data:\n\n```ts\ncreateLineChart(container, {\n a11y: { ariaLabel: 'Revenue by month' },\n series: [...],\n});\n```\n\nMark a decorative chart (e.g. a sparkline next to a text label) to exclude it from the accessibility tree:\n\n```ts\ncreateSparkline(container, {\n a11y: { decorative: true },\n data: [...],\n});\n```\n\nWhen `a11y` is omitted, every chart is hidden from assistive technology. Always set `a11y: { ariaLabel: '…' }` on charts that users need to understand.\n\n## Best Practices\n\n- Ensure the container element has explicit dimensions before calling a chart factory — `ResizeObserver` needs a non-zero layout size to trigger the first render.\n- Call `chart.dispose()` in your framework's unmount/cleanup phase to cancel transitions, disconnect resize observation, and remove DOM nodes.\n- Call `chart.update(data)` from your application state boundary; Prism does not require or own a state library.\n- Set `a11y: { ariaLabel: '…' }` on every chart that conveys meaningful data — accessibility is a hard requirement, not an optional add-on.\n- Wrap a chart with `debugChart()` from the `/devtools` subpath only in development code paths; it is tree-shaken in production.\n- For SSR, skip chart creation server-side — Prism depends on DOM APIs and `ResizeObserver`. Render charts only after hydration in a `onMounted`/`useEffect` callback.\n",
|
|
7
|
+
"examples": "---\ntitle: Prism — Examples\ndescription: Focused recipes for creating, updating, and customizing Prism charts.\n---\n\n- [Create a line chart](./examples/line-chart.md)\n- [Update chart data](./examples/update-data.md)\n- [Render a custom tooltip](./examples/custom-tooltip.md)\n- [Render compact charts](./examples/compact-charts.md)\n"
|
|
8
|
+
},
|
|
9
|
+
"examples": [],
|
|
10
|
+
"typeSignatures": {
|
|
11
|
+
"EasingFn": "export type { EasingFn } from './animation/easing';",
|
|
12
|
+
"createAreaChart": "export { createAreaChart } from './charts/area';",
|
|
13
|
+
"createBarChart": "export { createBarChart } from './charts/bar';",
|
|
14
|
+
"createLineChart": "export { createLineChart } from './charts/line';",
|
|
15
|
+
"createPieChart": "export { createPieChart } from './charts/pie';",
|
|
16
|
+
"createSparkline": "export { createSparkline } from './charts/sparkline';",
|
|
17
|
+
"PrismError": "export { PrismError, PrismRenderError } from './errors';",
|
|
18
|
+
"PrismRenderError": "export { PrismError, PrismRenderError } from './errors';",
|
|
19
|
+
"bandScale": "export { bandScale } from './scales/band';",
|
|
20
|
+
"linearScale": "export { linearScale } from './scales/linear';",
|
|
21
|
+
"timeScale": "export { timeScale } from './scales/time';",
|
|
22
|
+
"BandScaleConfig": "export type { BandScaleConfig, LinearScaleConfig, TimeScaleConfig } from './scales/types';",
|
|
23
|
+
"LinearScaleConfig": "export type { BandScaleConfig, LinearScaleConfig, TimeScaleConfig } from './scales/types';",
|
|
24
|
+
"TimeScaleConfig": "export type { BandScaleConfig, LinearScaleConfig, TimeScaleConfig } from './scales/types';",
|
|
25
|
+
"resetTheme": "export { resetTheme, seriesColor, setTheme } from './theme';",
|
|
26
|
+
"seriesColor": "export { resetTheme, seriesColor, setTheme } from './theme';",
|
|
27
|
+
"setTheme": "export { resetTheme, seriesColor, setTheme } from './theme';",
|
|
28
|
+
"AreaChartConfig": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
29
|
+
"AreaSeriesConfig": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
30
|
+
"AxisConfig": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
31
|
+
"AxisPosition": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
32
|
+
"BandScale": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
33
|
+
"BarChartConfig": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
34
|
+
"BarSeriesConfig": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
35
|
+
"BarVariant": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
36
|
+
"BaseChartConfig": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
37
|
+
"ChartA11y": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
38
|
+
"ChartDimensions": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
39
|
+
"ChartEvent": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
40
|
+
"ChartHandle": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
41
|
+
"ChartMargin": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
42
|
+
"ContinuousDatum": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
43
|
+
"CrosshairConfig": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
44
|
+
"Datum": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
45
|
+
"GridConfig": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
46
|
+
"HorizontalAxisPosition": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
47
|
+
"LegendConfig": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
48
|
+
"LegendPosition": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
49
|
+
"LineChartConfig": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
50
|
+
"LineSeriesConfig": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
51
|
+
"PieChartConfig": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
52
|
+
"PieSliceConfig": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
53
|
+
"PieVariant": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
54
|
+
"PrismTheme": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
55
|
+
"Scale": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
56
|
+
"Series": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
57
|
+
"SparklineConfig": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
58
|
+
"SparklineVariant": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
59
|
+
"StackSegment": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
60
|
+
"TooltipConfig": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
61
|
+
"TransitionConfig": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
62
|
+
"VerticalAxisPosition": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
63
|
+
"XAxisConfig": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';",
|
|
64
|
+
"YAxisConfig": "export type {\n AreaChartConfig,\n AreaSeriesConfig,\n AxisConfig,\n AxisPosition,\n BandScale,\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n BaseChartConfig,\n ChartA11y,\n ChartDimensions,\n ChartEvent,\n ChartHandle,\n ChartMargin,\n ContinuousDatum,\n CrosshairConfig,\n Datum,\n GridConfig,\n HorizontalAxisPosition,\n LegendConfig,\n LegendPosition,\n LineChartConfig,\n LineSeriesConfig,\n PieChartConfig,\n PieSliceConfig,\n PieVariant,\n PrismTheme,\n Scale,\n Series,\n SparklineConfig,\n SparklineVariant,\n StackSegment,\n TooltipConfig,\n TransitionConfig,\n VerticalAxisPosition,\n XAxisConfig,\n YAxisConfig,\n} from './types';"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"apiSource": "export {\n PulseAbortError,\n PulseConnectionError,\n PulseDisposedError,\n PulseError,\n PulseProtocolError,\n PulseRoomTimeoutError,\n PulseTimeoutError,\n} from './errors';\nexport { createPulse } from './pulse';\nexport type {\n ChannelDefinition,\n ChannelDefinitions,\n ClientEvents,\n EventKey,\n ExternalStore,\n HeartbeatOptions,\n MessageMap,\n OutgoingMessage,\n OutgoingTransform,\n PresenceRoomScope,\n Pulse,\n PulseChannel,\n PulseEvent,\n PulseOptions,\n PulseSchema,\n PulseStatus,\n ReconnectOptions,\n RoomDefinition,\n RoomDefinitions,\n RoomMap,\n RoomOptions,\n RoomScope,\n RoomScopeBase,\n ServerEvents,\n Unsubscribe,\n} from './types';\n",
|
|
3
|
+
"docs": {
|
|
4
|
+
"index": "---\ntitle: Pulse — Typed WebSocket sessions\ndescription: Explicitly connected, typed WebSocket sessions with scoped channels, ref-counted rooms with reactive presence, reconnect restoration, and heartbeat.\npackage: pulse\ncategory: websockets\nkeywords: [websocket, realtime, channels, presence, rooms, reconnect, heartbeat, typed-messaging, ripple]\nrelated: [herald, ripple, courier, clockwork]\nexports:\n [\n createPulse,\n Pulse,\n PulseChannel,\n RoomScope,\n RoomScopeBase,\n PresenceRoomScope,\n ExternalStore,\n PulseOptions,\n PulseSchema,\n ChannelDefinition,\n ChannelDefinitions,\n RoomDefinition,\n RoomDefinitions,\n RoomOptions,\n OutgoingMessage,\n OutgoingTransform,\n PulseError,\n PulseConnectionError,\n PulseTimeoutError,\n PulseRoomTimeoutError,\n PulseAbortError,\n PulseDisposedError,\n PulseProtocolError,\n PulseEvent,\n ]\nenvironments: [browser, node]\n---\n\n<!-- markdownlint-disable MD025 MD033 MD060 -->\n\n<PackageHero package=\"pulse\" />\n\n## Why Pulse?\n\nNative WebSocket leaves connection ownership, event routing, reconnect restoration, and cleanup to each application. Pulse provides those boundaries while making readiness explicit: applications connect before sending, and disconnected messages never disappear silently.\n\n```ts\n// Before\nconst socket = new WebSocket('wss://api.example.com/ws');\nsocket.addEventListener('message', (event) => route(JSON.parse(event.data)));\nsocket.addEventListener('close', () => setTimeout(() => reconnect(), 1_000));\n\n// After\nconst pulse = createPulse<{ server: { 'chat:message': { text: string } }; client: { 'chat:send': { text: string } } }>(\n 'wss://api.example.com/ws',\n { reconnect: true },\n);\ntry {\n await pulse.connect();\n pulse.on('chat:message', (message) => console.log(message.text));\n pulse.send('chat:send', { text: 'Hello!' });\n} catch (error) {\n console.error('Pulse connection failed:', error);\n}\n```\n\n| Feature | Pulse | Native WebSocket | socket.io-client |\n| --- | --- | --- | --- |\n| Bundle size | <PackageInfo package=\"pulse\" type=\"size\" /> | 0 B | ~44 kB gzip |\n| Explicit readiness | <ore-icon name=\"check\" size=\"16\"></ore-icon> | Manual | <ore-icon name=\"check\" size=\"16\"></ore-icon> |\n| Session restoration | <ore-icon name=\"check\" size=\"16\"></ore-icon> | <ore-icon name=\"x\" size=\"16\"></ore-icon> | Protocol-specific |\n| Typed scoped channels | <ore-icon name=\"check\" size=\"16\"></ore-icon> | <ore-icon name=\"x\" size=\"16\"></ore-icon> | Basic |\n| Typed rooms with presence | <ore-icon name=\"check\" size=\"16\"></ore-icon> | <ore-icon name=\"x\" size=\"16\"></ore-icon> | <ore-icon name=\"x\" size=\"16\"></ore-icon> |\n| Zero runtime dependencies | <ore-icon name=\"check\" size=\"16\"></ore-icon> | <ore-icon name=\"check\" size=\"16\"></ore-icon> | <ore-icon name=\"x\" size=\"16\"></ore-icon> |\n\n<div class=\"decision-callout\">\n\n**Use Pulse when** you need a typed WebSocket session whose reconnect and cleanup behavior must be deterministic.\n\n**Consider native WebSocket when** a single untyped connection does not need retry, routing, or session restoration.\n\n</div>\n\n## Installation\n\n::: code-group\n\n```sh [pnpm]\npnpm add @vielzeug/pulse\n```\n\n```sh [npm]\nnpm install @vielzeug/pulse\n```\n\n```sh [yarn]\nyarn add @vielzeug/pulse\n```\n\n:::\n\n## Quick Start\n\nDefine the protocol schema at construction time, create scopes, then connect before sending.\n\n```ts\nimport { createPulse } from '@vielzeug/pulse';\n\ntype Schema = {\n server: { 'chat:message': { text: string } };\n client: { 'chat:send': { text: string } };\n channels: {\n chat: {\n client: { send: { text: string } };\n server: { message: { text: string } };\n };\n };\n rooms: {\n lobby: { presence: { name: string } };\n };\n};\n\nconst pulse = createPulse<Schema>('wss://api.example.com/ws', {\n reconnect: true,\n});\npulse.tap((event) => {\n if (event.type === 'error') console.error(event.error);\n if (event.type === 'status-change') console.log('status:', event.status);\n});\nconst chat = pulse.channel('chat');\nconst lobby = pulse.room('lobby');\n\ntry {\n await pulse.connect();\n chat.send('send', { text: 'Hello!' });\n await lobby.joined;\n lobby.updatePresence({ name: 'Ada' });\n} catch (error) {\n console.error('Pulse connection failed:', error);\n}\n\npulse.dispose();\n```\n\n## Features\n\n<div class=\"features-grid\">\n\n- **`connect()`** — explicit readiness; application messages throw while disconnected.\n- **`channel()`** — named, schema-bound scopes with independent disposal and reference-counted server subscriptions.\n- **`room()`** — named, schema-bound ref-counted room scopes with optional reactive presence. The first scope sends `join`; the last disposal sends `leave`.\n- **`reconnect`** — ordered restoration of channel subscriptions, room memberships, and local presence state.\n- **`transform`** — one synchronous transform or filter for application messages.\n- **`tap()`** — subscribe to lifecycle events (status changes, errors, disposal) via a typed `PulseEvent` stream.\n- **`heartbeat`** — ping/pong liveness detection that uses the same reconnect controller.\n- **`status` and `rooms`** — framework-neutral external stores for transport and confirmed membership state.\n\n</div>\n\n## Documentation\n\n<div class=\"doc-links\">\n\n- [Usage Guide](./usage.md)\n- [API Reference](./api.md)\n- [Examples](./examples.md)\n- [Migration Guide](./migration.md)\n\n</div>\n\n## See Also\n\n<div class=\"see-also\">\n\n- [Ripple](/ripple/) — bridges Pulse external stores into computed values and effects.\n- [Herald](/herald/) — receives routed Pulse events in an in-process application bus.\n- [Courier](/courier/) — handles request/response traffic alongside a Pulse session.\n- [Clockwork](/clockwork/) — models application-level authentication or session workflows.\n\n</div>\n\n<!-- markdownlint-enable MD025 MD033 MD060 -->\n",
|
|
5
|
+
"api": "---\ntitle: API — Pulse\ndescription: Complete API reference for Pulse, including schema types, options, scopes, and error classes.\npackage: pulse\ncategory: websockets\n---\n\n<!-- markdownlint-disable MD025 -->\n\n[[toc]]\n\n## API Overview\n\n| Symbol | Purpose | Execution mode | Common gotcha |\n| --- | --- | --- | --- |\n| `createPulse()` | Create a typed WebSocket session instance. | Sync (returns `Pulse`) | Does not open the connection — call `connect()`. |\n| `Pulse` | Main instance: channels, rooms, messaging, lifecycle. | Sync methods, async `connect()`/`wait()` | `send()` throws while disconnected. |\n| `PulseChannel` | Scoped channel namespace with independent disposal. | Sync methods, async `wait()` | Each call returns a new scope; ref-counted subscription. |\n| `RoomScope` | Ref-counted room membership with optional presence. | Sync methods, async `joined` | `joined` rejects on transport close or timeout. |\n| `PulseSchema` | Declares server/client events, channels, and rooms. | Type-only | Infer all named scope types from this schema. |\n| `PulseOptions` | Configuration: heartbeat, reconnect, transform. | Type-only | `reconnect` and `heartbeat` default to `false`. |\n| `ExternalStore` | Framework-neutral snapshot and change subscription. | Sync | `subscribe()` does not emit the initial snapshot. |\n| `PulseError` | Base class for all Pulse errors. | Runtime | Check `instanceof` against subclasses. |\n\n## Package Entry Point\n\n| Import | Purpose |\n| --- | --- |\n| `@vielzeug/pulse` | All public exports: `createPulse`, types, and error classes. |\n\n## `createPulse()`\n\n```ts\nfunction createPulse<S extends PulseSchema = PulseSchema>(url: string, options?: PulseOptions): Pulse<S>\n```\n\nCreates a Pulse instance. The WebSocket is not opened until `connect()` is called.\n\n### Type parameters\n\n| Parameter | Constraint | Description |\n| --- | --- | --- |\n| `S` | `PulseSchema` | Schema declaring server events, client events, channels, and rooms. |\n\n### Parameters\n\n| Parameter | Type | Description |\n| --- | --- | --- |\n| `url` | `string` | WebSocket URL. |\n| `options` | `PulseOptions` | Optional configuration. |\n\n### Returns\n\n`Pulse<S>` — the Pulse instance.\n\n---\n\n## `PulseSchema`\n\n```ts\ntype PulseSchema = {\n server?: MessageMap;\n client?: MessageMap;\n channels?: ChannelDefinitions;\n rooms?: RoomDefinitions;\n};\n```\n\nDeclare all protocol surfaces once at construction. Named scopes infer their types from this schema.\n\n| Field | Type | Description |\n| --- | --- | --- |\n| `server` | `MessageMap` | Root events the server sends. |\n| `client` | `MessageMap` | Root events the client sends. |\n| `channels` | `ChannelDefinitions` | Named channel schemas. |\n| `rooms` | `RoomDefinitions` | Named room schemas with optional presence. |\n\n---\n\n## `PulseOptions`\n\n```ts\ntype PulseOptions = {\n heartbeat?: boolean | HeartbeatOptions;\n protocols?: string | string[];\n reconnect?: boolean | ReconnectOptions;\n transform?: OutgoingTransform;\n};\n```\n\n| Option | Type | Default | Description |\n| --- | --- | --- | --- |\n| `heartbeat` | `boolean \\| HeartbeatOptions` | `false` | Ping/pong keep-alive. |\n| `protocols` | `string \\| string[]` | — | Sub-protocols passed to the WebSocket constructor. |\n| `reconnect` | `boolean \\| ReconnectOptions` | `false` | Auto-reconnect on unexpected close. |\n| `transform` | `OutgoingTransform` | — | Transform or filter outgoing application messages. |\n\n---\n\n## `HeartbeatOptions`\n\n```ts\ntype HeartbeatOptions = {\n interval?: number;\n timeout?: number;\n};\n```\n\n| Option | Type | Default | Description |\n| --- | --- | --- | --- |\n| `interval` | `number` | `30_000` | Interval between pings in ms. |\n| `timeout` | `number` | `5_000` | How long to wait for a pong before treating the connection as dead. |\n\n---\n\n## `ReconnectOptions`\n\n```ts\ntype ReconnectOptions = {\n delay?: number | ((attempt: number) => number);\n maxAttempts?: number;\n};\n```\n\n| Option | Type | Default | Description |\n| --- | --- | --- | --- |\n| `delay` | `number \\| ((attempt: number) => number)` | Full-jitter exponential backoff capped at 30 s | Delay between reconnect attempts in ms. `attempt` is zero-based. |\n| `maxAttempts` | `number` | `5` | Maximum number of reconnect attempts after initial failure. |\n\n---\n\n## `OutgoingMessage`\n\n```ts\ntype OutgoingMessage = { channel?: string; event: string; payload: unknown };\n```\n\nAn outgoing application message before it is serialized.\n\n---\n\n## `OutgoingTransform`\n\n```ts\ntype OutgoingTransform = (message: Readonly<OutgoingMessage>) => OutgoingMessage | null;\n```\n\nTransform or filter outgoing application messages. Internal protocol frames (subscribe, join, leave, presence, ping) bypass this hook. Return `null` to drop the message.\n\n---\n\n## `Pulse`\n\n```ts\ntype Pulse<S extends PulseSchema = PulseSchema> = {\n // Channels\n channel<K extends keyof ChannelMap<S> & string>(\n name: K,\n ): PulseChannel<ChannelMap<S>[K]['server'], ChannelMap<S>[K]['client']>;\n\n // Connection\n connect(): Promise<void>;\n disconnect(code?: number, reason?: string): void;\n\n // Lifecycle\n readonly disposalSignal: AbortSignal;\n dispose(): void;\n readonly disposed: boolean;\n\n // Messaging\n on<K extends EventKey<ServerEvents<S>>>(event: K, handler: (payload: ServerEvents<S>[K]) => void): Unsubscribe;\n once<K extends EventKey<ServerEvents<S>>>(event: K, handler: (payload: ServerEvents<S>[K]) => void): Unsubscribe;\n send<K extends EventKey<ClientEvents<S>>>(event: K, payload: ClientEvents<S>[K]): void;\n wait<K extends EventKey<ServerEvents<S>>>(event: K, opts?: { signal?: AbortSignal; timeout?: number }): Promise<ServerEvents<S>[K]>;\n\n // Rooms\n room<K extends keyof RoomMap<S> & string>(name: K, opts?: RoomOptions): RoomScope<RoomMap<S>[K]>;\n readonly rooms: ExternalStore<ReadonlySet<string>>;\n\n // Status\n readonly status: ExternalStore<PulseStatus>;\n\n // Tap\n tap(handler: (event: PulseEvent) => void, options?: { signal?: AbortSignal }): () => void;\n\n [Symbol.dispose](): void;\n};\n```\n\n### `channel(name)`\n\nCreates an isolated message namespace over the shared connection. Each call returns an independently disposable scope. The server subscription is reference-counted.\n\n### `connect()`\n\nExplicitly opens the connection. Resolves after session restoration completes. Rejects if the connection closes before opening.\n\n### `disconnect(code?, reason?)`\n\nCloses the connection without triggering reconnection. Default code is `1000`.\n\n### `dispose()`\n\nPermanently closes the connection and releases all resources. Idempotent.\n\n### `on(event, handler)`\n\nSubscribes to a typed server event. Returns an unsubscribe function.\n\n### `once(event, handler)`\n\nSubscribes once — auto-removes after first invocation.\n\n### `send(event, payload)`\n\nSends a typed event to the server. Throws `PulseConnectionError` unless the connection is open.\n\n### `wait(event, opts?)`\n\nResolves on the next emission of the given server event. Rejects when `opts.signal` aborts, the timeout elapses, or the instance is disposed.\n\n### `room(name, opts?)`\n\nCreates a ref-counted room scope. The first scope sends `join`; the last disposal sends `leave`. When the room definition includes `presence`, the scope exposes reactive presence state.\n\n### `rooms`\n\nReactive set of rooms the client is currently a confirmed member of.\n\n### `status`\n\nReactive connection status: `'connecting' | 'open' | 'reconnecting' | 'closed'`.\n\n### `tap(handler, options?)`\n\nSubscribes to lifecycle events emitted by the Pulse instance. The handler receives a discriminated-union `PulseEvent`. Returns an unsubscribe function.\n\n| Parameter | Type | Description |\n| --- | --- | --- |\n| `handler` | `(event: PulseEvent) => void` | Called for each lifecycle event. |\n| `options.signal` | `AbortSignal` | Optional signal to stop the subscription. |\n\n```ts\nconst pulse = createPulse(url, { reconnect: true });\npulse.tap((event) => {\n if (event.type === 'error') console.error(event.error);\n if (event.type === 'status-change') console.log('status:', event.status);\n});\n```\n\n---\n\n## `ExternalStore`\n\n```ts\ninterface ExternalStore<T> {\n getSnapshot(): T;\n subscribe(listener: () => void): Unsubscribe;\n}\n```\n\nA framework-neutral state source used by `pulse.status`, `pulse.rooms`, and room `presence`. `getSnapshot()` returns the current immutable snapshot. `subscribe()` notifies once for each distinct snapshot and returns an unsubscribe function; listener errors are reported through `pulse.tap()` without interrupting Pulse state transitions.\n\n---\n\n## `PulseEvent`\n\n```ts\ntype PulseEvent =\n | { type: 'status-change'; status: PulseStatus }\n | { type: 'error'; error: PulseError }\n | { type: 'dispose' };\n```\n\nA discriminated union of lifecycle events emitted by a `Pulse` instance. Inspect `event.type` to narrow the payload.\n\n| `type` | Payload | When |\n| --- | --- | --- |\n| `status-change` | `status: PulseStatus` | The connection status transitions. |\n| `error` | `error: PulseError` | A typed transport or protocol error occurs. |\n| `dispose` | — | The instance is disposed. |\n\n---\n\n## `PulseChannel`\n\n```ts\ntype PulseChannel<TServer extends MessageMap = MessageMap, TClient extends MessageMap = MessageMap> = {\n readonly disposalSignal: AbortSignal;\n readonly disposed: boolean;\n readonly name: string;\n dispose(): void;\n on<K extends EventKey<TServer>>(event: K, handler: (payload: TServer[K]) => void): Unsubscribe;\n once<K extends EventKey<TServer>>(event: K, handler: (payload: TServer[K]) => void): Unsubscribe;\n send<K extends EventKey<TClient>>(event: K, payload: TClient[K]): void;\n wait<K extends EventKey<TServer>>(event: K, opts?: { signal?: AbortSignal; timeout?: number }): Promise<TServer[K]>;\n [Symbol.dispose](): void;\n};\n```\n\n---\n\n## `RoomScope`\n\n```ts\ntype RoomScope<R extends RoomDefinition = RoomDefinition> = R extends { presence: infer P }\n ? P extends undefined\n ? RoomScopeBase\n : PresenceRoomScope<P>\n : RoomScopeBase;\n```\n\nA room scope. When the room definition includes `presence`, the scope is a `PresenceRoomScope`; otherwise it is a `RoomScopeBase`.\n\n### `RoomScopeBase`\n\n```ts\ntype RoomScopeBase = {\n readonly disposalSignal: AbortSignal;\n readonly disposed: boolean;\n readonly name: string;\n readonly joined: Promise<void>;\n dispose(): void;\n [Symbol.dispose](): void;\n};\n```\n\n### `PresenceRoomScope`\n\n```ts\ntype PresenceRoomScope<T = unknown> = RoomScopeBase & {\n readonly presence: ExternalStore<ReadonlyMap<string, T>>;\n updatePresence(state: T): void;\n onJoin(handler: (memberId: string, state: T) => void): Unsubscribe;\n onLeave(handler: (memberId: string) => void): Unsubscribe;\n};\n```\n\n| Member | Type | Description |\n| --- | --- | --- |\n| `presence` | `ExternalStore<ReadonlyMap<string, T>>` | Reactive map of `memberId → state`. |\n| `updatePresence(state)` | `(state: T) => void` | Broadcast this client's presence state. Throws `PulseConnectionError` unless open. |\n| `onJoin(handler)` | `(handler) => Unsubscribe` | Called whenever a new member joins with their initial state. |\n| `onLeave(handler)` | `(handler) => Unsubscribe` | Called whenever a member leaves. |\n\n### `RoomOptions`\n\n```ts\ntype RoomOptions = {\n signal?: AbortSignal;\n timeout?: number;\n};\n```\n\n| Option | Type | Description |\n| --- | --- | --- |\n| `signal` | `AbortSignal` | Aborts the join, rejecting `joined` with `PulseAbortError`. |\n| `timeout` | `number` | Join timeout in ms. Rejects `joined` with `PulseRoomTimeoutError`. |\n\n---\n\n## Errors\n\nAll errors extend `PulseError`.\n\n### `PulseError`\n\nBase class for all Pulse errors.\n\n### `PulseConnectionError`\n\nTransport failure, send while disconnected, or room join rejected on close.\n\n### `PulseProtocolError`\n\nMalformed frame or server error frame.\n\n### `PulseTimeoutError`\n\n`wait()` timed out before the server event arrived.\n\n### `PulseRoomTimeoutError`\n\nRoom scope `joined` timed out before the server confirmed membership.\n\n### `PulseAbortError`\n\n`wait()` or room `joined` aborted via AbortSignal.\n\n### `PulseDisposedError`\n\nOperation attempted after disposal.\n\n---\n\n## Channel and room definitions\n\n### `ChannelDefinition`\n\n```ts\ntype ChannelDefinition = { client: MessageMap; server: MessageMap };\n```\n\n### `ChannelDefinitions`\n\n```ts\ntype ChannelDefinitions = Record<string, ChannelDefinition>;\n```\n\n### `RoomDefinition`\n\n```ts\ntype RoomDefinition = { presence?: unknown };\n```\n\n### `RoomDefinitions`\n\n```ts\ntype RoomDefinitions = Record<string, RoomDefinition>;\n```\n\n---\n\n## Utility types\n\n### `MessageMap`\n\n```ts\ntype MessageMap = Record<string, unknown>;\n```\n\n### `EventKey`\n\n```ts\ntype EventKey<T extends MessageMap> = keyof T & string;\n```\n\n### `ServerEvents`\n\n```ts\ntype ServerEvents<S extends PulseSchema> = S extends { server: infer M extends MessageMap } ? M : MessageMap;\n```\n\nExtract server events from a schema, defaulting to an empty map.\n\n### `ClientEvents`\n\n```ts\ntype ClientEvents<S extends PulseSchema> = S extends { client: infer M extends MessageMap } ? M : MessageMap;\n```\n\nExtract client events from a schema, defaulting to an empty map.\n\n### `RoomMap`\n\n```ts\ntype RoomMap<S extends PulseSchema> = S extends { rooms: infer R extends RoomDefinitions } ? R : RoomDefinitions;\n```\n\nExtract room definitions from a schema, defaulting to an empty map.\n\n### `Unsubscribe`\n\n```ts\ntype Unsubscribe = () => void;\n```\n\n### `PulseStatus`\n\n```ts\ntype PulseStatus = 'connecting' | 'open' | 'reconnecting' | 'closed';\n```\n",
|
|
6
|
+
"usage": "---\ntitle: Usage — Pulse\ndescription: Practical guide for connecting, sending, subscribing, joining rooms, and managing lifecycle with Pulse.\npackage: pulse\ncategory: websockets\n---\n\n<!-- markdownlint-disable MD025 -->\n\n[[toc]]\n\n## Basic Usage\n\nDeclare server events, client events, channel schemas, and room schemas once at construction. Named scopes infer their types from this schema.\n\n```ts\nimport { createPulse } from '@vielzeug/pulse';\n\ntype Schema = {\n // Root events the server sends\n server: { 'chat:message': { text: string }; notice: string };\n // Root events the client sends\n client: { 'chat:send': { text: string } };\n // Named channel scopes\n channels: {\n chat: {\n client: { send: { text: string } };\n server: { message: { text: string } };\n };\n alerts: {\n client: { subscribe: { topic: string } };\n server: { alert: { topic: string; severity: 'info' | 'warn' | 'error' } };\n };\n };\n // Named room scopes with optional presence state\n rooms: {\n lobby: { presence: { name: string; color: string } };\n announcements: {};\n };\n};\n```\n\n## Create and connect\n\n```ts\nconst pulse = createPulse<Schema>('wss://api.example.com/ws', {\n reconnect: { delay: 1_000, maxAttempts: 5 },\n heartbeat: { interval: 30_000, timeout: 5_000 },\n});\n\npulse.tap((event) => {\n if (event.type === 'error') console.error(event.error);\n if (event.type === 'status-change') console.log('status:', event.status);\n});\n\ntry {\n await pulse.connect();\n} catch (error) {\n console.error('Connection failed:', error);\n}\n```\n\n`connect()` opens the WebSocket and resolves after session restoration completes. `send()` throws `PulseConnectionError` while disconnected — Pulse never silently drops or buffers application messages.\n\n## Send and receive root events\n\n```ts\npulse.on('chat:message', (message) => console.log(message.text));\npulse.send('chat:send', { text: 'Hello!' });\n```\n\n## Channels\n\nEach `channel()` call returns an independently disposable scope. The server subscription is reference-counted: the first scope sends `subscribe`, the last disposal sends `unsubscribe`.\n\n```ts\nconst chat = pulse.channel('chat');\n\nchat.on('message', (message) => console.log(message.text));\nchat.send('send', { text: 'Hello!' });\n\n// Later\nchat.dispose();\n```\n\nUse `using` for automatic cleanup:\n\n```ts\n{\n using chat = pulse.channel('chat');\n chat.on('message', (message) => console.log(message.text));\n} // chat.dispose() called automatically\n```\n\n## Rooms and presence\n\nEach `room()` call returns a ref-counted room scope. The first scope sends `join`; the last disposal sends `leave`. When the room definition includes `presence`, the scope exposes reactive presence state.\n\n```ts\nconst lobby = pulse.room('lobby');\n\n// joined resolves when the server confirms membership\nawait lobby.joined;\n\n// Reactive presence map: memberId → state\nlobby.onJoin((memberId, state) => console.log(`${memberId} joined: ${state.name}`));\nlobby.onLeave((memberId) => console.log(`${memberId} left`));\n\n// Broadcast your presence\nlobby.updatePresence({ name: 'Ada', color: 'blue' });\n\n// Read current presence\nfor (const [memberId, state] of lobby.presence.getSnapshot()) {\n console.log(`${memberId}: ${state.name}`);\n}\n\n// Leave\nlobby.dispose();\n```\n\nPlain rooms (without presence) work the same way but don't expose presence members:\n\n```ts\nconst announcements = pulse.room('announcements');\nawait announcements.joined;\nannouncements.dispose();\n```\n\n### Room scope options\n\n```ts\n// Timeout if the server doesn't confirm in time\nconst lobby = pulse.room('lobby', { timeout: 5_000 });\ntry {\n await lobby.joined;\n} catch (error) {\n console.error('Join failed:', error);\n}\n\n// Abort via AbortSignal\nconst ctrl = new AbortController();\nconst lobby = pulse.room('lobby', { signal: ctrl.signal });\nctrl.abort(); // joined rejects with PulseAbortError, scope auto-disposes\n```\n\n### Observe the rooms set\n\n`pulse.rooms` is an external store that tracks confirmed room memberships:\n\n```ts\nconst printRooms = () => console.log('Joined rooms:', [...pulse.rooms.getSnapshot()]);\nconst unsubscribe = pulse.rooms.subscribe(printRooms);\n\nprintRooms();\n// Later\nunsubscribe();\n```\n\n## Reconnect\n\nWhen the connection drops unexpectedly, Pulse reconnects using the configured strategy. On reconnect, it restores:\n\n1. Channel subscriptions (sends `subscribe` for each active channel).\n2. Room memberships (sends `join` for each active room scope).\n3. Local presence state (sends `presence` with the last successfully published state).\n\n```ts\nconst pulse = createPulse<Schema>('wss://api.example.com/ws', {\n reconnect: {\n delay: (attempt) => Math.min(1_000 * 2 ** attempt, 30_000),\n maxAttempts: 5,\n },\n});\n```\n\n`joined` rejects on transport close. For post-reconnect membership, read `pulse.rooms` instead.\n\n## Heartbeat\n\n```ts\nconst pulse = createPulse<Schema>('wss://api.example.com/ws', {\n heartbeat: { interval: 30_000, timeout: 5_000 },\n});\n```\n\nPulse sends periodic pings. If a pong doesn't arrive before the timeout, it forces a reconnect using the same reconnect controller.\n\n## Transform outgoing messages\n\n```ts\nconst pulse = createPulse<Schema>('wss://api.example.com/ws', {\n transform: (message) => {\n // Add a timestamp to all messages\n return { ...message, payload: { ...message.payload, ts: Date.now() } };\n },\n});\n```\n\nReturn `null` to drop a message:\n\n```ts\nconst pulse = createPulse<Schema>('wss://api.example.com/ws', {\n transform: (message) => (message.event === 'debug' ? null : message),\n});\n```\n\n## Wait for a specific event\n\n```ts\nconst notice = await pulse.wait('notice', { timeout: 10_000 });\nconsole.log(notice);\n```\n\n## Dispose\n\n```ts\npulse.dispose();\n```\n\nDisposal is idempotent. It closes the connection, rejects pending room joins, clears all listeners, and aborts all scope disposal signals.\n\n## Error handling\n\n```ts\nconst pulse = createPulse<Schema>('wss://api.example.com/ws', {\n reconnect: true,\n});\n\npulse.tap((event) => {\n if (event.type === 'error') {\n if (event.error instanceof PulseConnectionError) {\n console.error('Connection error:', event.error);\n } else if (event.error instanceof PulseProtocolError) {\n console.error('Protocol error:', event.error);\n }\n }\n});\n```\n\n| Error | When |\n| --- | --- |\n| `PulseConnectionError` | Transport failure, send while disconnected, room join rejected on close. |\n| `PulseProtocolError` | Malformed frame or server error frame. |\n| `PulseTimeoutError` | `wait()` times out. |\n| `PulseRoomTimeoutError` | Room scope `joined` times out. |\n| `PulseAbortError` | `wait()` or room `joined` aborted via AbortSignal. |\n| `PulseDisposedError` | Operation attempted after disposal. |\n\n## Working with Other Vielzeug Libraries\n\nPulse external stores plug directly into Flux and Ripple bridges:\n\n```ts\nimport { fromStore } from '@vielzeug/flux';\nimport { effect, fromSubscribable } from '@vielzeug/ripple';\n\nconst statusStream = fromStore(pulse.status);\nconst presence = fromSubscribable(lobby.presence, { signal: lobby.disposalSignal });\nconst presenceEffect = effect(() => console.log([...presence.value]));\n\nconst statusSubscription = statusStream.subscribe((status) => console.log(status));\n// Later\nstatusSubscription.unsubscribe();\npresenceEffect.dispose();\n```\n\n## Best Practices\n\n- Await `connect()` before sending; never assume construction opens the transport.\n- Define the full schema at `createPulse()` so named scopes are type-safe without per-call generics.\n- Use `using` declarations for channel and room scopes so disposal is automatic at block exit.\n- Always call `dispose()` when done — it closes the connection, rejects pending joins, and clears listeners.\n- Call `tap()` to observe lifecycle events; Pulse reports transport and protocol errors there rather than throwing asynchronously.\n- Read `pulse.rooms` for post-reconnect membership; `joined` rejects on transport close.\n- Set a `timeout` on room scopes when the server may never confirm membership.\n- Keep `transform` synchronous; resolve async policy decisions before calling `send()`.\n",
|
|
7
|
+
"examples": "---\ntitle: Examples — Pulse\ndescription: Practical examples for common Pulse usage patterns.\npackage: pulse\ncategory: websockets\n---\n\n<!-- markdownlint-disable MD025 -->\n\n- [Basic Connection](./examples/basic-connection.md)\n- [Channel Multiplexing](./examples/channels.md)\n- [Outgoing Transform](./examples/middleware.md)\n- [Reconnect and Heartbeat](./examples/reconnect-and-heartbeat.md)\n- [Rooms and Presence](./examples/rooms-and-presence.md)\n"
|
|
8
|
+
},
|
|
9
|
+
"examples": [
|
|
10
|
+
{
|
|
11
|
+
"id": "channels",
|
|
12
|
+
"code": "import { createPulse } from '@vielzeug/pulse'\n\n// Isolated channel namespace — listeners and sends are scoped to 'chat'\nconst pulse = createPulse('wss://api.example.com/ws')\nconst chat = pulse.channel('chat')\n\n// Listeners scoped to the channel\nchat.on('message', ({ from, text }) => {\n console.log('[chat] ' + from + ': ' + text)\n})\n\ntry {\n await pulse.connect()\n // Send scoped to the channel\n chat.send('send', { text: 'hey!' })\n} catch (err) {\n console.log('connect failed:', err.message)\n}\n\n// Wait with a per-event timeout\ntry {\n const msg = await chat.wait('message', { timeout: 3_000 })\n console.log('got:', msg.text)\n} catch (err) {\n console.log('channel wait timed out:', err.message)\n}\n\n// Disposing the channel removes all its listeners\n// but the underlying pulse connection stays open\nchat.dispose()\nconsole.log('channel disposed, pulse still open:', pulse.status.getSnapshot())\n\npulse.dispose()",
|
|
13
|
+
"name": "Typed Channels"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"id": "connect-and-send",
|
|
17
|
+
"code": "import { createPulse } from '@vielzeug/pulse'\n\n// Typed WebSocket client: on(), once(), send(), wait()\nconst pulse = createPulse('wss://api.example.com/ws', {\n reconnect: { maxAttempts: 5 },\n})\n\n// Observe runtime events via tap()\npulse.tap((event) => {\n if (event.type === 'error') console.log('transport error:', event.error.message)\n})\n\n// Subscribe before connecting — listeners are synchronous\nconst unsub = pulse.on('chat:message', ({ from, text }) => {\n console.log('[' + from + '] ' + text)\n})\n\n// One-shot listener: fires once and auto-removes\npulse.once('chat:message', (msg) => {\n console.log('first message:', msg.text)\n})\n\n// Connect; send when open\ntry {\n await pulse.connect()\n pulse.send('chat:send', { text: 'Hello, world!' })\n} catch (err) {\n console.log('connect failed:', err.message)\n}\n\n// Await next server event with a 5 s deadline\ntry {\n const msg = await pulse.wait('chat:message', { timeout: 500 })\n console.log('received:', msg.text)\n} catch (err) {\n console.log('wait ended:', err.message)\n}\n\nunsub()\npulse.dispose()",
|
|
18
|
+
"name": "Connect & Send"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"id": "lifecycle",
|
|
22
|
+
"code": "import { createPulse, PulseDisposedError } from '@vielzeug/pulse'\n\n// Status signal, disposalSignal, and error handling on dispose\nconst pulse = createPulse('wss://api.example.com/ws', {\n reconnect: { delay: 1_000, maxAttempts: 3 },\n heartbeat: { interval: 30_000, timeout: 5_000 },\n})\n\n// Observe runtime events via tap()\npulse.tap((event) => {\n if (event.type === 'error') console.log('Pulse error:', event.error.message)\n})\n\n// Construction is closed. connect() makes the transport available.\nconsole.log('initial status:', pulse.status.getSnapshot())\n\n// disposalSignal aborts when dispose() is called\npulse.disposalSignal.addEventListener('abort', () => {\n console.log('disposal signal fired')\n})\n\ntry {\n await pulse.connect()\n console.log('connected:', pulse.status.getSnapshot())\n} catch (err) {\n console.log('connect failed:', err.message)\n}\n\n// dispose() is idempotent — safe to call multiple times\npulse.dispose()\npulse.dispose()\nconsole.log('disposed:', pulse.disposed)\n\n// Methods reject with PulseDisposedError after dispose\ntry {\n await pulse.connect()\n} catch (err) {\n if (err instanceof PulseDisposedError) {\n console.log('connect() rejected with PulseDisposedError — correct')\n }\n}",
|
|
23
|
+
"name": "Lifecycle & Disposal"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"id": "reconnect",
|
|
27
|
+
"code": "import { createPulse, PulseConnectionError } from '@vielzeug/pulse'\n\n// Channels, rooms, and local presence state are restored on reconnect.\nconst pulse = createPulse('wss://api.example.com/ws', {\n reconnect: { delay: 500, maxAttempts: 3 },\n})\n\npulse.tap((event) => {\n if (event.type === 'error') console.log('transport error:', event.error.message)\n})\n\n// Channel is tracked: re-subscribed automatically after every reconnect\nconst chat = pulse.channel('chat')\nchat.on('message', ({ from, text }) => console.log(from + ': ' + text))\n\n// Connect explicitly to observe the status\ntry {\n await pulse.connect()\n console.log('connected, status:', pulse.status.getSnapshot())\n} catch (err) {\n if (err instanceof PulseConnectionError) {\n console.log('connection failed:', err.message)\n }\n}\n\nconsole.log('channel name:', chat.name)\nconsole.log('channel disposed?', chat.disposed)\n\n// Disposing a channel removes it from re-subscription tracking\nchat.dispose()\nconsole.log('channel disposed, pulse still running:', !pulse.disposed)\n\npulse.dispose()",
|
|
28
|
+
"name": "Reconnect & Restoration"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"id": "rooms-presence",
|
|
32
|
+
"code": "import { createPulse } from '@vielzeug/pulse'\n\n// Room scopes: ref-counted membership with reactive presence\nconst pulse = createPulse('wss://api.example.com/ws')\nconst lobby = pulse.room('lobby')\n\ntry {\n await pulse.connect()\n\n // Wait for server confirmation\n await lobby.joined\n console.log('joined lobby, rooms:', [...pulse.rooms.getSnapshot()])\n\n // Broadcast our own presence\n lobby.updatePresence({ avatar: '/me.png', name: 'Alice', status: 'online' })\n\n // Reactive presence map: memberId → state\n const printMembers = () => {\n for (const [id, state] of lobby.presence.getSnapshot()) {\n console.log(' ' + id + ': ' + state.name + ' (' + state.status + ')')\n }\n }\n\n // React to individual joins and leaves\n lobby.onJoin((id, state) => console.log(state.name + ' joined'))\n lobby.onLeave((id) => console.log(id + ' left'))\n} catch (err) {\n console.log('connection or room operation failed:', err.message)\n}\n\n// Dispose the room scope — sends leave when last scope is released\nlobby.dispose()\nconsole.log('rooms after leave:', [...pulse.rooms.getSnapshot()])\n\npulse.dispose()",
|
|
33
|
+
"name": "Rooms & Presence"
|
|
34
|
+
}
|
|
35
|
+
],
|
|
36
|
+
"typeSignatures": {
|
|
37
|
+
"PulseAbortError": "export {\n PulseAbortError,\n PulseConnectionError,\n PulseDisposedError,\n PulseError,\n PulseProtocolError,\n PulseRoomTimeoutError,\n PulseTimeoutError,\n} from './errors';",
|
|
38
|
+
"PulseConnectionError": "export {\n PulseAbortError,\n PulseConnectionError,\n PulseDisposedError,\n PulseError,\n PulseProtocolError,\n PulseRoomTimeoutError,\n PulseTimeoutError,\n} from './errors';",
|
|
39
|
+
"PulseDisposedError": "export {\n PulseAbortError,\n PulseConnectionError,\n PulseDisposedError,\n PulseError,\n PulseProtocolError,\n PulseRoomTimeoutError,\n PulseTimeoutError,\n} from './errors';",
|
|
40
|
+
"PulseError": "export {\n PulseAbortError,\n PulseConnectionError,\n PulseDisposedError,\n PulseError,\n PulseProtocolError,\n PulseRoomTimeoutError,\n PulseTimeoutError,\n} from './errors';",
|
|
41
|
+
"PulseProtocolError": "export {\n PulseAbortError,\n PulseConnectionError,\n PulseDisposedError,\n PulseError,\n PulseProtocolError,\n PulseRoomTimeoutError,\n PulseTimeoutError,\n} from './errors';",
|
|
42
|
+
"PulseRoomTimeoutError": "export {\n PulseAbortError,\n PulseConnectionError,\n PulseDisposedError,\n PulseError,\n PulseProtocolError,\n PulseRoomTimeoutError,\n PulseTimeoutError,\n} from './errors';",
|
|
43
|
+
"PulseTimeoutError": "export {\n PulseAbortError,\n PulseConnectionError,\n PulseDisposedError,\n PulseError,\n PulseProtocolError,\n PulseRoomTimeoutError,\n PulseTimeoutError,\n} from './errors';",
|
|
44
|
+
"createPulse": "export { createPulse } from './pulse';",
|
|
45
|
+
"ChannelDefinition": "export type {\n ChannelDefinition,\n ChannelDefinitions,\n ClientEvents,\n EventKey,\n ExternalStore,\n HeartbeatOptions,\n MessageMap,\n OutgoingMessage,\n OutgoingTransform,\n PresenceRoomScope,\n Pulse,\n PulseChannel,\n PulseEvent,\n PulseOptions,\n PulseSchema,\n PulseStatus,\n ReconnectOptions,\n RoomDefinition,\n RoomDefinitions,\n RoomMap,\n RoomOptions,\n RoomScope,\n RoomScopeBase,\n ServerEvents,\n Unsubscribe,\n} from './types';",
|
|
46
|
+
"ChannelDefinitions": "export type {\n ChannelDefinition,\n ChannelDefinitions,\n ClientEvents,\n EventKey,\n ExternalStore,\n HeartbeatOptions,\n MessageMap,\n OutgoingMessage,\n OutgoingTransform,\n PresenceRoomScope,\n Pulse,\n PulseChannel,\n PulseEvent,\n PulseOptions,\n PulseSchema,\n PulseStatus,\n ReconnectOptions,\n RoomDefinition,\n RoomDefinitions,\n RoomMap,\n RoomOptions,\n RoomScope,\n RoomScopeBase,\n ServerEvents,\n Unsubscribe,\n} from './types';",
|
|
47
|
+
"ClientEvents": "export type {\n ChannelDefinition,\n ChannelDefinitions,\n ClientEvents,\n EventKey,\n ExternalStore,\n HeartbeatOptions,\n MessageMap,\n OutgoingMessage,\n OutgoingTransform,\n PresenceRoomScope,\n Pulse,\n PulseChannel,\n PulseEvent,\n PulseOptions,\n PulseSchema,\n PulseStatus,\n ReconnectOptions,\n RoomDefinition,\n RoomDefinitions,\n RoomMap,\n RoomOptions,\n RoomScope,\n RoomScopeBase,\n ServerEvents,\n Unsubscribe,\n} from './types';",
|
|
48
|
+
"EventKey": "export type {\n ChannelDefinition,\n ChannelDefinitions,\n ClientEvents,\n EventKey,\n ExternalStore,\n HeartbeatOptions,\n MessageMap,\n OutgoingMessage,\n OutgoingTransform,\n PresenceRoomScope,\n Pulse,\n PulseChannel,\n PulseEvent,\n PulseOptions,\n PulseSchema,\n PulseStatus,\n ReconnectOptions,\n RoomDefinition,\n RoomDefinitions,\n RoomMap,\n RoomOptions,\n RoomScope,\n RoomScopeBase,\n ServerEvents,\n Unsubscribe,\n} from './types';",
|
|
49
|
+
"ExternalStore": "export type {\n ChannelDefinition,\n ChannelDefinitions,\n ClientEvents,\n EventKey,\n ExternalStore,\n HeartbeatOptions,\n MessageMap,\n OutgoingMessage,\n OutgoingTransform,\n PresenceRoomScope,\n Pulse,\n PulseChannel,\n PulseEvent,\n PulseOptions,\n PulseSchema,\n PulseStatus,\n ReconnectOptions,\n RoomDefinition,\n RoomDefinitions,\n RoomMap,\n RoomOptions,\n RoomScope,\n RoomScopeBase,\n ServerEvents,\n Unsubscribe,\n} from './types';",
|
|
50
|
+
"HeartbeatOptions": "export type {\n ChannelDefinition,\n ChannelDefinitions,\n ClientEvents,\n EventKey,\n ExternalStore,\n HeartbeatOptions,\n MessageMap,\n OutgoingMessage,\n OutgoingTransform,\n PresenceRoomScope,\n Pulse,\n PulseChannel,\n PulseEvent,\n PulseOptions,\n PulseSchema,\n PulseStatus,\n ReconnectOptions,\n RoomDefinition,\n RoomDefinitions,\n RoomMap,\n RoomOptions,\n RoomScope,\n RoomScopeBase,\n ServerEvents,\n Unsubscribe,\n} from './types';",
|
|
51
|
+
"MessageMap": "export type {\n ChannelDefinition,\n ChannelDefinitions,\n ClientEvents,\n EventKey,\n ExternalStore,\n HeartbeatOptions,\n MessageMap,\n OutgoingMessage,\n OutgoingTransform,\n PresenceRoomScope,\n Pulse,\n PulseChannel,\n PulseEvent,\n PulseOptions,\n PulseSchema,\n PulseStatus,\n ReconnectOptions,\n RoomDefinition,\n RoomDefinitions,\n RoomMap,\n RoomOptions,\n RoomScope,\n RoomScopeBase,\n ServerEvents,\n Unsubscribe,\n} from './types';",
|
|
52
|
+
"OutgoingMessage": "export type {\n ChannelDefinition,\n ChannelDefinitions,\n ClientEvents,\n EventKey,\n ExternalStore,\n HeartbeatOptions,\n MessageMap,\n OutgoingMessage,\n OutgoingTransform,\n PresenceRoomScope,\n Pulse,\n PulseChannel,\n PulseEvent,\n PulseOptions,\n PulseSchema,\n PulseStatus,\n ReconnectOptions,\n RoomDefinition,\n RoomDefinitions,\n RoomMap,\n RoomOptions,\n RoomScope,\n RoomScopeBase,\n ServerEvents,\n Unsubscribe,\n} from './types';",
|
|
53
|
+
"OutgoingTransform": "export type {\n ChannelDefinition,\n ChannelDefinitions,\n ClientEvents,\n EventKey,\n ExternalStore,\n HeartbeatOptions,\n MessageMap,\n OutgoingMessage,\n OutgoingTransform,\n PresenceRoomScope,\n Pulse,\n PulseChannel,\n PulseEvent,\n PulseOptions,\n PulseSchema,\n PulseStatus,\n ReconnectOptions,\n RoomDefinition,\n RoomDefinitions,\n RoomMap,\n RoomOptions,\n RoomScope,\n RoomScopeBase,\n ServerEvents,\n Unsubscribe,\n} from './types';",
|
|
54
|
+
"PresenceRoomScope": "export type {\n ChannelDefinition,\n ChannelDefinitions,\n ClientEvents,\n EventKey,\n ExternalStore,\n HeartbeatOptions,\n MessageMap,\n OutgoingMessage,\n OutgoingTransform,\n PresenceRoomScope,\n Pulse,\n PulseChannel,\n PulseEvent,\n PulseOptions,\n PulseSchema,\n PulseStatus,\n ReconnectOptions,\n RoomDefinition,\n RoomDefinitions,\n RoomMap,\n RoomOptions,\n RoomScope,\n RoomScopeBase,\n ServerEvents,\n Unsubscribe,\n} from './types';",
|
|
55
|
+
"Pulse": "export type {\n ChannelDefinition,\n ChannelDefinitions,\n ClientEvents,\n EventKey,\n ExternalStore,\n HeartbeatOptions,\n MessageMap,\n OutgoingMessage,\n OutgoingTransform,\n PresenceRoomScope,\n Pulse,\n PulseChannel,\n PulseEvent,\n PulseOptions,\n PulseSchema,\n PulseStatus,\n ReconnectOptions,\n RoomDefinition,\n RoomDefinitions,\n RoomMap,\n RoomOptions,\n RoomScope,\n RoomScopeBase,\n ServerEvents,\n Unsubscribe,\n} from './types';",
|
|
56
|
+
"PulseChannel": "export type {\n ChannelDefinition,\n ChannelDefinitions,\n ClientEvents,\n EventKey,\n ExternalStore,\n HeartbeatOptions,\n MessageMap,\n OutgoingMessage,\n OutgoingTransform,\n PresenceRoomScope,\n Pulse,\n PulseChannel,\n PulseEvent,\n PulseOptions,\n PulseSchema,\n PulseStatus,\n ReconnectOptions,\n RoomDefinition,\n RoomDefinitions,\n RoomMap,\n RoomOptions,\n RoomScope,\n RoomScopeBase,\n ServerEvents,\n Unsubscribe,\n} from './types';",
|
|
57
|
+
"PulseEvent": "export type {\n ChannelDefinition,\n ChannelDefinitions,\n ClientEvents,\n EventKey,\n ExternalStore,\n HeartbeatOptions,\n MessageMap,\n OutgoingMessage,\n OutgoingTransform,\n PresenceRoomScope,\n Pulse,\n PulseChannel,\n PulseEvent,\n PulseOptions,\n PulseSchema,\n PulseStatus,\n ReconnectOptions,\n RoomDefinition,\n RoomDefinitions,\n RoomMap,\n RoomOptions,\n RoomScope,\n RoomScopeBase,\n ServerEvents,\n Unsubscribe,\n} from './types';",
|
|
58
|
+
"PulseOptions": "export type {\n ChannelDefinition,\n ChannelDefinitions,\n ClientEvents,\n EventKey,\n ExternalStore,\n HeartbeatOptions,\n MessageMap,\n OutgoingMessage,\n OutgoingTransform,\n PresenceRoomScope,\n Pulse,\n PulseChannel,\n PulseEvent,\n PulseOptions,\n PulseSchema,\n PulseStatus,\n ReconnectOptions,\n RoomDefinition,\n RoomDefinitions,\n RoomMap,\n RoomOptions,\n RoomScope,\n RoomScopeBase,\n ServerEvents,\n Unsubscribe,\n} from './types';",
|
|
59
|
+
"PulseSchema": "export type {\n ChannelDefinition,\n ChannelDefinitions,\n ClientEvents,\n EventKey,\n ExternalStore,\n HeartbeatOptions,\n MessageMap,\n OutgoingMessage,\n OutgoingTransform,\n PresenceRoomScope,\n Pulse,\n PulseChannel,\n PulseEvent,\n PulseOptions,\n PulseSchema,\n PulseStatus,\n ReconnectOptions,\n RoomDefinition,\n RoomDefinitions,\n RoomMap,\n RoomOptions,\n RoomScope,\n RoomScopeBase,\n ServerEvents,\n Unsubscribe,\n} from './types';",
|
|
60
|
+
"PulseStatus": "export type {\n ChannelDefinition,\n ChannelDefinitions,\n ClientEvents,\n EventKey,\n ExternalStore,\n HeartbeatOptions,\n MessageMap,\n OutgoingMessage,\n OutgoingTransform,\n PresenceRoomScope,\n Pulse,\n PulseChannel,\n PulseEvent,\n PulseOptions,\n PulseSchema,\n PulseStatus,\n ReconnectOptions,\n RoomDefinition,\n RoomDefinitions,\n RoomMap,\n RoomOptions,\n RoomScope,\n RoomScopeBase,\n ServerEvents,\n Unsubscribe,\n} from './types';",
|
|
61
|
+
"ReconnectOptions": "export type {\n ChannelDefinition,\n ChannelDefinitions,\n ClientEvents,\n EventKey,\n ExternalStore,\n HeartbeatOptions,\n MessageMap,\n OutgoingMessage,\n OutgoingTransform,\n PresenceRoomScope,\n Pulse,\n PulseChannel,\n PulseEvent,\n PulseOptions,\n PulseSchema,\n PulseStatus,\n ReconnectOptions,\n RoomDefinition,\n RoomDefinitions,\n RoomMap,\n RoomOptions,\n RoomScope,\n RoomScopeBase,\n ServerEvents,\n Unsubscribe,\n} from './types';",
|
|
62
|
+
"RoomDefinition": "export type {\n ChannelDefinition,\n ChannelDefinitions,\n ClientEvents,\n EventKey,\n ExternalStore,\n HeartbeatOptions,\n MessageMap,\n OutgoingMessage,\n OutgoingTransform,\n PresenceRoomScope,\n Pulse,\n PulseChannel,\n PulseEvent,\n PulseOptions,\n PulseSchema,\n PulseStatus,\n ReconnectOptions,\n RoomDefinition,\n RoomDefinitions,\n RoomMap,\n RoomOptions,\n RoomScope,\n RoomScopeBase,\n ServerEvents,\n Unsubscribe,\n} from './types';",
|
|
63
|
+
"RoomDefinitions": "export type {\n ChannelDefinition,\n ChannelDefinitions,\n ClientEvents,\n EventKey,\n ExternalStore,\n HeartbeatOptions,\n MessageMap,\n OutgoingMessage,\n OutgoingTransform,\n PresenceRoomScope,\n Pulse,\n PulseChannel,\n PulseEvent,\n PulseOptions,\n PulseSchema,\n PulseStatus,\n ReconnectOptions,\n RoomDefinition,\n RoomDefinitions,\n RoomMap,\n RoomOptions,\n RoomScope,\n RoomScopeBase,\n ServerEvents,\n Unsubscribe,\n} from './types';",
|
|
64
|
+
"RoomMap": "export type {\n ChannelDefinition,\n ChannelDefinitions,\n ClientEvents,\n EventKey,\n ExternalStore,\n HeartbeatOptions,\n MessageMap,\n OutgoingMessage,\n OutgoingTransform,\n PresenceRoomScope,\n Pulse,\n PulseChannel,\n PulseEvent,\n PulseOptions,\n PulseSchema,\n PulseStatus,\n ReconnectOptions,\n RoomDefinition,\n RoomDefinitions,\n RoomMap,\n RoomOptions,\n RoomScope,\n RoomScopeBase,\n ServerEvents,\n Unsubscribe,\n} from './types';",
|
|
65
|
+
"RoomOptions": "export type {\n ChannelDefinition,\n ChannelDefinitions,\n ClientEvents,\n EventKey,\n ExternalStore,\n HeartbeatOptions,\n MessageMap,\n OutgoingMessage,\n OutgoingTransform,\n PresenceRoomScope,\n Pulse,\n PulseChannel,\n PulseEvent,\n PulseOptions,\n PulseSchema,\n PulseStatus,\n ReconnectOptions,\n RoomDefinition,\n RoomDefinitions,\n RoomMap,\n RoomOptions,\n RoomScope,\n RoomScopeBase,\n ServerEvents,\n Unsubscribe,\n} from './types';",
|
|
66
|
+
"RoomScope": "export type {\n ChannelDefinition,\n ChannelDefinitions,\n ClientEvents,\n EventKey,\n ExternalStore,\n HeartbeatOptions,\n MessageMap,\n OutgoingMessage,\n OutgoingTransform,\n PresenceRoomScope,\n Pulse,\n PulseChannel,\n PulseEvent,\n PulseOptions,\n PulseSchema,\n PulseStatus,\n ReconnectOptions,\n RoomDefinition,\n RoomDefinitions,\n RoomMap,\n RoomOptions,\n RoomScope,\n RoomScopeBase,\n ServerEvents,\n Unsubscribe,\n} from './types';",
|
|
67
|
+
"RoomScopeBase": "export type {\n ChannelDefinition,\n ChannelDefinitions,\n ClientEvents,\n EventKey,\n ExternalStore,\n HeartbeatOptions,\n MessageMap,\n OutgoingMessage,\n OutgoingTransform,\n PresenceRoomScope,\n Pulse,\n PulseChannel,\n PulseEvent,\n PulseOptions,\n PulseSchema,\n PulseStatus,\n ReconnectOptions,\n RoomDefinition,\n RoomDefinitions,\n RoomMap,\n RoomOptions,\n RoomScope,\n RoomScopeBase,\n ServerEvents,\n Unsubscribe,\n} from './types';",
|
|
68
|
+
"ServerEvents": "export type {\n ChannelDefinition,\n ChannelDefinitions,\n ClientEvents,\n EventKey,\n ExternalStore,\n HeartbeatOptions,\n MessageMap,\n OutgoingMessage,\n OutgoingTransform,\n PresenceRoomScope,\n Pulse,\n PulseChannel,\n PulseEvent,\n PulseOptions,\n PulseSchema,\n PulseStatus,\n ReconnectOptions,\n RoomDefinition,\n RoomDefinitions,\n RoomMap,\n RoomOptions,\n RoomScope,\n RoomScopeBase,\n ServerEvents,\n Unsubscribe,\n} from './types';",
|
|
69
|
+
"Unsubscribe": "export type {\n ChannelDefinition,\n ChannelDefinitions,\n ClientEvents,\n EventKey,\n ExternalStore,\n HeartbeatOptions,\n MessageMap,\n OutgoingMessage,\n OutgoingTransform,\n PresenceRoomScope,\n Pulse,\n PulseChannel,\n PulseEvent,\n PulseOptions,\n PulseSchema,\n PulseStatus,\n ReconnectOptions,\n RoomDefinition,\n RoomDefinitions,\n RoomMap,\n RoomOptions,\n RoomScope,\n RoomScopeBase,\n ServerEvents,\n Unsubscribe,\n} from './types';"
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"apiSource": "/**\n * Refine components register through their explicit component entry points.\n *\n * Keeping the package root free of registration side effects makes dependency\n * ownership and bundle contents obvious to application code.\n */\nexport { RefineError } from './errors';\n",
|
|
3
|
+
"docs": {
|
|
4
|
+
"index": "---\ntitle: Refine — Web component library\ndescription: Accessible, themeable web components built with Ore for framework and vanilla DOM apps.\npackage: refine\ncategory: ui-components\nkeywords: [web-components, accessible, themeable, ui, components, design-system]\nrelated: [ore, orbit, forge, keymap]\nexports:\n [\n ore-accordion,\n ore-accordion-item,\n ore-alert,\n ore-async,\n ore-avatar,\n ore-avatar-group,\n ore-badge,\n ore-box,\n ore-breadcrumb,\n ore-breadcrumb-item,\n ore-button,\n ore-button-group,\n ore-calendar,\n ore-card,\n ore-carousel,\n ore-carousel-slide,\n ore-chat-message,\n ore-checkbox,\n ore-checkbox-group,\n ore-chip,\n ore-code-window,\n ore-column,\n ore-combobox,\n ore-combobox-option,\n ore-command-palette,\n ore-command-palette-item,\n ore-copy-command,\n ore-counter,\n ore-datagrid,\n ore-date-picker,\n ore-dialog,\n ore-drawer,\n ore-file-input,\n ore-grid,\n ore-grid-item,\n ore-icon,\n ore-input,\n ore-keyboard-key,\n ore-keyboard-shortcut,\n ore-list,\n ore-list-item,\n ore-marquee,\n ore-menu,\n ore-menu-item,\n ore-menu-separator,\n ore-message-composer,\n ore-navbar,\n ore-navbar-item,\n ore-navigation-menu,\n ore-navigation-menu-item,\n ore-navigation-menu-panel,\n ore-number-input,\n ore-otp-input,\n ore-pagination,\n ore-password-strength,\n ore-popover,\n ore-progress,\n ore-qr-code,\n ore-qr-scanner,\n ore-radio,\n ore-radio-group,\n ore-rating,\n ore-select,\n ore-separator,\n ore-sidebar,\n ore-sidebar-group,\n ore-sidebar-item,\n ore-skeleton,\n ore-slider,\n ore-stats,\n ore-step,\n ore-stepper,\n ore-switch,\n ore-tab-item,\n ore-tab-panel,\n ore-table,\n ore-tabs,\n ore-td,\n ore-text,\n ore-th,\n ore-tr,\n ore-textarea,\n ore-time-picker,\n ore-toast,\n ore-tooltip,\n ore-typing-indicator,\n ]\nenvironments: [browser]\n---\n\n<!-- markdownlint-disable MD025 MD033 MD060 -->\n\n<PackageHero package=\"refine\" />\n\n## Why Refine?\n\nEvery project needs UI primitives. Refine provides accessible web components that work natively anywhere HTML is rendered—no framework required.\n\n```html\n<!-- Before — roll your own button with ARIA -->\n<button class=\"btn btn-primary\" role=\"button\" aria-pressed=\"false\" tabindex=\"0\">\n <span class=\"btn-spinner\" aria-hidden=\"true\"></span>\n Save\n</button>\n\n<!-- After — Refine -->\n<ore-button variant=\"solid\" color=\"primary\" loading>Save</ore-button>\n```\n\n| Feature | Refine | Shoelace | Material Web |\n| ------------------ | ------------------------------------------- | ------------------------------------------ | ------------------------------------------ |\n| Bundle size | <PackageInfo package=\"refine\" type=\"size\" /> | ~145 kB | ~200 kB |\n| Built with | Ore | Lit | Lit |\n| Runtime dependencies | Vielzeug UI primitives + Lucide | Lit + utilities | Lit + Material foundations |\n| Accessible | WCAG AA | WCAG AA | WCAG AA |\n| Framework agnostic | <ore-icon name=\"check\" size=\"16\"></ore-icon> | <ore-icon name=\"check\" size=\"16\"></ore-icon> | <ore-icon name=\"check\" size=\"16\"></ore-icon> |\n\n<div class=\"decision-callout\">\n\n**Use Refine when** you want accessible web components that match the Vielzeug design system without a heavy framework dependency.\n\n**Consider Shoelace or Material Web** if your team is already standardized on those ecosystems and you need their established component catalogs.\n\n</div>\n\n## Installation\n\n::: code-group\n\n```sh [pnpm]\npnpm add @vielzeug/refine\n```\n\n```sh [npm]\nnpm install @vielzeug/refine\n```\n\n```sh [yarn]\nyarn add @vielzeug/refine\n```\n\n:::\n\n## Quick Start\n\n```ts\n// 1. Import global styles once\nimport '@vielzeug/refine/fouc.css'; // Hide unupgraded custom elements until first paint\nimport '@vielzeug/refine/tokens.css'; // Tokens, animations, cascade layers\n\n// 2. Register only the elements you need\nimport '@vielzeug/refine/button';\nimport '@vielzeug/refine/input';\nimport '@vielzeug/refine/card';\n```\n\n```html\n<ore-button variant=\"solid\" color=\"primary\">Save</ore-button>\n<ore-input label=\"Email\" type=\"email\" required></ore-input>\n<ore-card padding=\"lg\">\n <span slot=\"header\">Account</span>\n <p>Card content goes here.</p>\n</ore-card>\n```\n\n```ts\n```\n\n### CDN / Vanilla HTML\n\nUse the self-contained IIFE bundle to load Refine directly from a CDN in any HTML page — no build step required:\n\n```html\n<!-- 1. Styles -->\n<link rel=\"stylesheet\" href=\"https://unpkg.com/@vielzeug/refine/dist/styles/fouc.css\" />\n<link rel=\"stylesheet\" href=\"https://unpkg.com/@vielzeug/refine/dist/styles/tokens.css\" />\n\n<!-- 2. All components (IIFE — registers global Refine namespace) -->\n<script src=\"https://unpkg.com/@vielzeug/refine/dist/refine.iife.js\"></script>\n```\n\nFor bundler-based projects that still want a CDN URL, use the ESM bundle via an import map:\n\n```html\n<script type=\"importmap\">\n {\n \"imports\": {\n \"@vielzeug/refine\": \"https://esm.sh/@vielzeug/refine\",\n \"@vielzeug/refine/button\": \"https://esm.sh/@vielzeug/refine/button\",\n \"@vielzeug/refine/input\": \"https://esm.sh/@vielzeug/refine/input\"\n }\n }\n</script>\n\n<script type=\"module\">\n import '@vielzeug/refine/button';\n import '@vielzeug/refine/input';\n</script>\n```\n\n### Package Entry Points\n\n| Import | Purpose |\n| ------------------------ | ----------------------------------------- |\n| `@vielzeug/refine/fouc.css` | FOUC suppression for unupgraded custom elements |\n| `@vielzeug/refine/tokens.css` | Global design tokens and cascade layers |\n| `@vielzeug/refine/styles/preflight.css` | Optional browser-default reset (includes FOUC suppression) |\n\nComponent registration happens through side-effect imports such as `@vielzeug/refine/button` and `@vielzeug/refine/dialog`.\n\n### Components\n\n**Content:** `ore-avatar`, `ore-avatar-group`, `ore-breadcrumb`, `ore-card`, `ore-carousel`, `ore-carousel-slide`, `ore-chat-message`, `ore-icon`, `ore-keyboard-key`, `ore-keyboard-shortcut`, `ore-list`, `ore-list-item`, `ore-marquee`, `ore-pagination`, `ore-qr-code`, `ore-separator`, `ore-stats`, `ore-step`, `ore-stepper`, `ore-table`, `ore-text`\n\n**Disclosure:** `ore-accordion`, `ore-accordion-item`, `ore-tabs`, `ore-tab-item`, `ore-tab-panel`\n\n**Feedback:** `ore-alert`, `ore-async`, `ore-badge`, `ore-chip`, `ore-password-strength`, `ore-progress`, `ore-skeleton`, `ore-toast`, `ore-typing-indicator`\n\n**Inputs:** `ore-button`, `ore-button-group`, `ore-calendar`, `ore-checkbox`, `ore-checkbox-group`, `ore-column`, `ore-combobox`, `ore-counter`, `ore-datagrid`, `ore-date-picker`, `ore-file-input`, `ore-input`, `ore-message-composer`, `ore-number-input`, `ore-otp-input`, `ore-qr-scanner`, `ore-radio`, `ore-radio-group`, `ore-rating`, `ore-select`, `ore-slider`, `ore-switch`, `ore-textarea`, `ore-time-picker`\n\n**Layout:** `ore-box`, `ore-grid`, `ore-grid-item`, `ore-navbar`, `ore-sidebar`\n\n**Overlay:** `ore-command-palette`, `ore-command-palette-item`, `ore-dialog`, `ore-drawer`, `ore-menu`, `ore-popover`, `ore-tooltip`\n\n## Component portfolio\n\nRefine keeps one public package and classifies components by composition level rather than stability. All listed components remain supported and tested.\n\n- **Foundations** — buttons, inputs, selection controls, disclosure, dialogs, menus, tooltips, layout primitives, and feedback indicators. Start here when building an application-specific interface.\n- **Composed patterns** — data grids, command palettes, navigation menus, steppers, calendars, date/time pickers, file inputs, and message composers. These package recurring accessibility and interaction behavior that is costly to rebuild correctly.\n- **Presentation patterns** — cards, chat messages, code windows, stats, marquees, avatars, badges, and skeletons. Use these when their product vocabulary matches the application; prefer foundations when it does not.\n\nClassification guides discovery and bundle selection. It is not a reason to remove working components or move them into unstable packages; per-component subpath imports remain the tree-shaking boundary.\n\n## Features\n\n<div class=\"features-grid\">\n\n- **Accessible** — keyboard navigation, ARIA wiring, and focus management across interactive components\n- **Themeable** — global tokens plus component-level CSS custom properties\n- **Framework agnostic** — works anywhere HTML can be rendered\n- **Tree-shakeable** — import only the component entry points you register\n- **Comprehensive surface** — inputs, content, disclosure, feedback, layout, and overlay primitives\n- **Typed framework declarations** — DOM, React, and Vue tags derive from the component property contracts\n\n</div>\n\n### Prerequisites\n\n- Browser runtime with Custom Elements support.\n- Import `@vielzeug/refine/fouc.css` and `@vielzeug/refine/tokens.css` before rendering components.\n- For SSR, render placeholders server-side and hydrate components only on the client.\n\n## Documentation\n\n<div class=\"doc-links\">\n\n- [Usage Guide](./usage.md)\n- [API Reference](./api.md)\n- [Migration Guide](./migration.md)\n\n</div>\n\n## See Also\n\n<div class=\"see-also\">\n\n- [Ore](/ore/) — Web component runtime that powers Refine\n- [Orbit](/orbit/) — Floating UI positioning used in Refine's overlays\n- [Forge](/forge/) — Form state management for use with Refine inputs\n- [Keymap](/keymap/) — Keyboard shortcut manager that powers the command palette's global trigger\n\n</div>\n\n<!-- markdownlint-enable MD025 MD033 MD060 -->\n",
|
|
5
|
+
"api": "---\ntitle: Refine — API Reference\ndescription: Published component, stylesheet, framework type, and error entry points for @vielzeug/refine.\n---\n\n[[toc]]\n\n## API Overview\n\n| Symbol | Purpose | Execution mode | Common gotcha |\n| --- | --- | --- | --- |\n| `@vielzeug/refine/<component>` | Register one custom element and export its public types | Sync | Importing a type alone does not register the element |\n| `@vielzeug/refine/tokens.css` | Load required theme tokens, animations, and cascade layers | CSS | Import once before components render |\n| `@vielzeug/refine/fouc.css` | Hide unregistered `ore-*` elements until upgrade | CSS | Load before first paint |\n| `@vielzeug/refine/styles/preflight.css` | Apply the optional browser reset | CSS | The reset affects global elements |\n| `@vielzeug/refine/frameworks/elements` | Register typed DOM tag mappings | Types only | Import for side effects in TypeScript |\n| `@vielzeug/refine/frameworks/react` | Register typed React JSX elements | Types only | Does not provide runtime wrappers |\n| `@vielzeug/refine/frameworks/vue` | Register typed Vue global components | Types only | Does not install a Vue plugin |\n| `RefineError` | Base class for package-defined public errors | Sync | Component configuration warnings do not throw this error |\n\n## Package Entry Point\n\n| Import | Purpose |\n| --- | --- |\n| `@vielzeug/refine` | Export `RefineError` without registering components |\n| `@vielzeug/refine/<component>` | Register one component and export its tag constant, props, events, and related types |\n| `@vielzeug/refine/tokens.css` | Required global design contract |\n| `@vielzeug/refine/fouc.css` | Optional pre-upgrade visibility rule |\n| `@vielzeug/refine/styles/*` | Focused theme, animation, layer, and preflight stylesheets |\n| `@vielzeug/refine/frameworks/*` | TypeScript augmentations for DOM, React, and Vue |\n\n## Styles\n\n```ts\nimport '@vielzeug/refine/fouc.css';\nimport '@vielzeug/refine/tokens.css';\nimport '@vielzeug/refine/styles/preflight.css';\n```\n\n`tokens.css` is required. It defines tokens, animations, and cascade-layer order without resetting global elements. `preflight.css` is optional and includes FOUC suppression.\n\n| Import path | Purpose |\n| --- | --- |\n| `@vielzeug/refine/fouc.css` | FOUC suppression for unupgraded custom elements |\n| `@vielzeug/refine/tokens.css` | Tokens, animation helpers, and cascade layers |\n| `@vielzeug/refine/styles/theme.css` | Theme token declarations |\n| `@vielzeug/refine/styles/animation.css` | Animation helpers |\n| `@vielzeug/refine/styles/layers.css` | Cascade layer declarations |\n| `@vielzeug/refine/styles/preflight.css` | Optional browser reset and FOUC suppression |\n\n## Components\n\nEach component uses one registration and type entry point:\n\n```ts\nimport '@vielzeug/refine/button';\nimport type { OreButtonProps } from '@vielzeug/refine/button';\n```\n\n| Area | Components |\n| --- | --- |\n| Content | `avatar`, `avatar-group`, `breadcrumb`, `card`, `carousel`, `chat-message`, `code-window`, `copy-command`, `icon`, `keyboard-key`, `list`, `list-item`, `marquee`, `pagination`, `separator`, `stats`, `step`, `stepper`, `table`, `text` |\n| Disclosure | `accordion`, `accordion-item`, `tabs`, `tab-item`, `tab-panel` |\n| Feedback | `alert`, `async`, `badge`, `chip`, `password-strength`, `progress`, `skeleton`, `toast`, `typing-indicator` |\n| Inputs | `button`, `button-group`, `calendar`, `checkbox`, `checkbox-group`, `combobox`, `counter`, `datagrid`, `date-picker`, `file-input`, `input`, `message-composer`, `number-input`, `otp-input`, `radio`, `radio-group`, `rating`, `select`, `slider`, `switch`, `textarea`, `time-picker` |\n| Layout | `box`, `grid`, `grid-item`, `navbar`, `sidebar` |\n| Overlays | `command-palette`, `dialog`, `drawer`, `menu`, `navigation-menu`, `popover`, `tooltip` |\n\nEach component page lists its attributes, JavaScript properties, events, slots, parts, and CSS custom properties.\n\n## Framework Types\n\n```ts\nimport type {} from '@vielzeug/refine/frameworks/elements';\nimport type {} from '@vielzeug/refine/frameworks/react';\nimport type {} from '@vielzeug/refine/frameworks/vue';\n```\n\nThe declarations cover every supported tag and derive component properties from Refine's authoritative `HTMLElementTagNameMap`. They provide types only; component registration still uses component subpaths.\n\n## Events and Form Controls\n\nForm controls expose `.value` or `.checked` and dispatch standard `input` and `change` events. Read the property from `event.currentTarget`.\n\nStateful overlays expose controlled `open`, optional `default-open`, and an `open-change` custom event with `{ open, reason }` detail. Component pages define additional detail fields and reasons.\n\n## Types\n\nComponent props follow the `Ore<Component>Props` naming pattern. Event maps follow `Ore<Component>Events`. Import both from the component subpath that owns them.\n\n`RefineElementMap`, `RefineReactIntrinsicElements`, and `RefineVueGlobalComponents` are exported from their respective `frameworks/*` type entry points.\n\n## Errors\n\n### `RefineError`\n\n```ts\nclass RefineError extends Error {\n constructor(message: string, opts?: ErrorOptions);\n}\n```\n\nBase class for public Refine errors. It preserves `cause` through `ErrorOptions`.\n",
|
|
6
|
+
"usage": "---\ntitle: Refine — Usage Guide\ndescription: Register Refine components, configure properties, handle events, compose slots, and integrate frameworks.\n---\n\n[[toc]]\n\n## Basic Usage\n\nLoad the global design contract once, then register only the components used by the page.\n\n```ts\nimport '@vielzeug/refine/tokens.css';\nimport '@vielzeug/refine/button';\nimport '@vielzeug/refine/input';\nimport '@vielzeug/refine/dialog';\n\nconst input = document.querySelector('ore-input');\nconst save = document.querySelector('ore-button');\n\nif (!(input instanceof HTMLElement) || !(save instanceof HTMLElement)) {\n throw new Error('Expected Refine controls');\n}\n\nsave.addEventListener('click', () => {\n console.log((input as HTMLElement & { value: string }).value);\n});\n```\n\nAdd the browser reset only when the application owns global element styling:\n\n```ts\nimport '@vielzeug/refine/styles/preflight.css';\n```\n\n## Set Attributes and Properties\n\nUse attributes for serializable HTML state.\n\n```html\n<ore-button variant=\"outline\" color=\"secondary\" size=\"lg\" disabled>\n Save changes\n</ore-button>\n```\n\nUse JavaScript properties for arrays, objects, callbacks, and controlled state.\n\n```ts\nimport '@vielzeug/refine/datagrid';\nimport type { OreDataGridProps } from '@vielzeug/refine/datagrid';\n\nconst grid = document.querySelector('ore-datagrid') as HTMLElement & OreDataGridProps;\ngrid.columns = [\n { key: 'name', label: 'Name', sortable: true },\n { key: 'role', label: 'Role' },\n];\ngrid.rows = [\n { id: '1', name: 'Ada', role: 'Admin' },\n { id: '2', name: 'Linus', role: 'Editor' },\n];\n```\n\n## Handle Events\n\nForm controls dispatch standard `input` and `change` events. Read their current property from `event.currentTarget`.\n\n```ts\nconst input = document.querySelector('ore-input');\ninput?.addEventListener('input', (event) => {\n const target = event.currentTarget as HTMLElement & { value: string };\n console.log(target.value);\n});\n```\n\nCustom events use kebab-case names and typed detail objects.\n\n```ts\nimport type { OreDialogEvents } from '@vielzeug/refine/dialog';\n\nconst dialog = document.querySelector('ore-dialog');\ndialog?.addEventListener('open-change', (event: CustomEvent<OreDialogEvents['open-change']>) => {\n console.log(event.detail.open, event.detail.reason);\n});\n```\n\n## Compose Slots\n\nDefault slots hold primary content. Named slots identify component-owned regions.\n\n```html\n<ore-card>\n <span slot=\"header\">Account</span>\n <p>Profile settings</p>\n <div slot=\"footer\">\n <ore-button variant=\"ghost\">Cancel</ore-button>\n <ore-button>Save</ore-button>\n </div>\n</ore-card>\n```\n\nInput components commonly expose `prefix`, `suffix`, `label`, `helper`, and `error` slots. Each component reference lists its supported slots.\n\n## Load TypeScript Framework Declarations\n\nImport the declaration matching the framework once in an application type entry point.\n\n::: code-group\n\n```ts [DOM]\nimport type {} from '@vielzeug/refine/frameworks/elements';\n```\n\n```ts [React]\nimport type {} from '@vielzeug/refine/frameworks/react';\n```\n\n```ts [Vue]\nimport type {} from '@vielzeug/refine/frameworks/vue';\n```\n\n:::\n\nThese entry points provide typed tags and component properties. They do not register components or install runtime adapters.\n\n## Framework Integration\n\nRefine elements use native DOM properties, events, and slots. Frameworks differ only in how they forward custom-element properties and events.\n\n::: code-group\n\n```tsx [React 19]\nimport '@vielzeug/refine/button';\n\nexport function SaveButton() {\n return <ore-button variant=\"solid\">Save</ore-button>;\n}\n```\n\n```vue [Vue 3]\n<script setup lang=\"ts\">\nimport '@vielzeug/refine/button';\n</script>\n\n<template>\n <ore-button variant=\"solid\">Save</ore-button>\n</template>\n```\n\n```svelte [Svelte]\n<script lang=\"ts\">\n import '@vielzeug/refine/button';\n</script>\n\n<ore-button variant=\"solid\">Save</ore-button>\n```\n\n:::\n\nSee [Framework Integration](./frameworks.md) for custom events, controlled properties, SSR guards, and framework-specific configuration.\n\n## Working with Other Vielzeug Libraries\n\n### Ore\n\nUse Ore when authoring a custom element that composes Refine components.\n\n```ts\nimport '@vielzeug/refine/button';\nimport { define, html } from '@vielzeug/ore';\n\ndefine('save-panel', {\n setup() {\n return html`<ore-button @click=${() => console.log('save')}>Save</ore-button>`;\n },\n});\n```\n\n### Ripple\n\nUse Ripple to drive component properties from application state.\n\n```ts\nimport '@vielzeug/refine/button';\nimport { effect, signal } from '@vielzeug/ripple';\n\nconst loading = signal(false);\nconst button = document.querySelector('ore-button') as HTMLElement & { loading?: boolean };\nconst loadingEffect = effect(() => {\n button.loading = loading.value;\n});\n\nloadingEffect.dispose();\n```\n\n## Best Practices\n\n- **Import** `tokens.css` once before rendering components.\n- **Register** components through explicit subpaths.\n- **Set** structured data and callbacks as JavaScript properties.\n- **Read** form state from the event target instead of custom event payloads.\n- **Provide** accessible labels for icon-only controls.\n- **Use** component reference pages for supported slots, parts, and CSS properties.\n- **Dispose** application-owned Ripple effects and service handles.\n- **Guard** DOM-dependent component registration during SSR.\n- **Working with AI agents?** Install the `vielzeug` skill (`npx -y @vielzeug/codex skills install`) so agents reach for Refine components and tokens instead of custom widgets — see the [Codex usage guide](../codex/usage.md#agent-skill).\n"
|
|
7
|
+
},
|
|
8
|
+
"examples": [],
|
|
9
|
+
"typeSignatures": {
|
|
10
|
+
"RefineError": "export { RefineError } from './errors';"
|
|
11
|
+
}
|
|
12
|
+
}
|