@jini-ai/ui 0.6.16 → 0.6.19
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/CHANGELOG.md +18 -0
- package/dist/features/charts/catalog-manifests.d.ts +25 -0
- package/dist/features/charts/catalog-manifests.js +73 -0
- package/dist/features/charts/index.d.ts +2 -1
- package/dist/features/charts/index.js +2 -1
- package/dist/features/charts/react.d.ts +10 -6
- package/dist/features/charts/react.js +40 -33
- package/dist/features/charts/wire.d.ts +733 -0
- package/dist/features/charts/wire.js +37 -0
- package/dist/features/i18n/dictionaries/settings-dialog.ar.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.bn.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.de.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.en.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.es.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.fa.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.fr.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.hi.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.hu.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.id.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.it.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.ja.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.ko.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.pl.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.pt-BR.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.ru.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.th.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.tr.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.uk.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.ur.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.zh-CN.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.zh-TW.js +3 -0
- package/dist/features/interactive-ui/index.js +4 -1
- package/dist/features/lexical-rich-text-editor/react/components/RichTextInput.js +2 -1
- package/dist/features/mcp-ui/surfaces/outcome.d.ts +7 -1
- package/dist/features/mcp-ui/surfaces/outcome.js +47 -8
- package/dist/features/sketch-editor/react/hooks/useSketchSaveWorkflow.js +2 -1
- package/dist/react/components/TooltipLayer.js +27 -2
- package/package.json +10 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @jini-ai/ui
|
|
2
2
|
|
|
3
|
+
## 0.6.19
|
|
4
|
+
|
|
5
|
+
- A `<provider>.<kind>-chart` entry from `createChartInteractiveRegistry` now draws with the provider it advertises. Components were cached by chart kind only, so with another enabled provider as the site default, `plugin.echarts.bar-chart` could render through that default. The legacy `recharts.*` aliases and `chart.spec` keep generic selection.
|
|
6
|
+
- `@jini-ai/ui/charts` adds `chartCatalogManifests({ providers }, { siteProvider })`, the one headless owner of chart catalog entries: per-provider `<provider>.<kind>-chart` entries (now described), the legacy `recharts.*` entries with unchanged ids, schemas and descriptions, and a stable `chart.spec` entry (`{ spec }`, any kind, one or more series; `chartSpecPropsSchema` rejects empty series or data, rows missing a series or category, and non-numeric series values). `chart.spec` is listed with zero providers and then renders the data table.
|
|
7
|
+
- `createChartInteractiveRegistry` now attaches components to exactly those manifests. The unadvertised `core.table.<kind>-chart` fallback ids are gone; the legacy `recharts.*` ids report `core.table` when no provider draws their kind.
|
|
8
|
+
- `DEFAULT_INTERACTIVE_UI_REGISTRY` now also holds `chart.spec` (after the legacy chart ids), so a host with no chart provider snapshot still renders a saved `chart.spec` surface as the data table. `ALL_MANIFESTS` is unchanged.
|
|
9
|
+
|
|
10
|
+
## Unreleased (0.6.18)
|
|
11
|
+
|
|
12
|
+
- Redact sketch export and rich-text editor callback exception diagnostics without Node-only imports.
|
|
13
|
+
|
|
14
|
+
## 0.6.17
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- Add localized folder-chip strings.
|
|
19
|
+
- Handle npm 12 pack JSON through the shared parser in publication-hygiene tests.
|
|
20
|
+
|
|
3
21
|
## 0.6.16
|
|
4
22
|
|
|
5
23
|
### Minor Changes
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { InteractiveComponentManifest } from '../interactive-ui/types.js';
|
|
2
|
+
import { type ChartKind } from './contract.js';
|
|
3
|
+
/** What a catalog needs to know about an admitted provider: no code, no URLs. */
|
|
4
|
+
export interface ChartCatalogProvider {
|
|
5
|
+
readonly id: string;
|
|
6
|
+
readonly kinds: readonly ChartKind[];
|
|
7
|
+
}
|
|
8
|
+
/** Stable id for the generic multi-series entry. It exists with zero providers (it renders as a table). */
|
|
9
|
+
export declare const CHART_SPEC_COMPONENT_ID = "chart.spec";
|
|
10
|
+
/** Provider id the catalog reports when no admitted provider draws a kind. */
|
|
11
|
+
export declare const CHART_TABLE_PROVIDER = "core.table";
|
|
12
|
+
/**
|
|
13
|
+
* Build every chart entry for the current admitted providers:
|
|
14
|
+
* - one `<provider>.<kind>-chart` entry per provider and kind it draws, in selection order;
|
|
15
|
+
* - the legacy wire entries (unchanged ids, schemas and descriptions), reporting the selected provider;
|
|
16
|
+
* - `chart.spec`, present even with no provider.
|
|
17
|
+
* @complexity O(k * p) for k kinds and p providers.
|
|
18
|
+
* @example chartCatalogManifests({ providers: [{ id: 'plugin.charts', kinds: ['bar'] }] }, { siteProvider: 'plugin.charts' })
|
|
19
|
+
*/
|
|
20
|
+
export declare function chartCatalogManifests({ providers }: {
|
|
21
|
+
providers: readonly ChartCatalogProvider[];
|
|
22
|
+
}, { siteProvider }?: {
|
|
23
|
+
siteProvider?: string | undefined;
|
|
24
|
+
}): readonly InteractiveComponentManifest[];
|
|
25
|
+
//# sourceMappingURL=catalog-manifests.d.ts.map
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/** The one headless owner of chart catalog entries. The browser registry attaches components to
|
|
2
|
+
* these exact entries; a server catalog serves them as they are. React-free and DOM-free.
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { chartSpecSchema } from './contract.js';
|
|
6
|
+
import { chartCapability, chartProvidersByKind, createChartProviderRegistry } from './registry.js';
|
|
7
|
+
import { chartSpecPropsSchema, chartWireManifests } from './wire.js';
|
|
8
|
+
/** Stable id for the generic multi-series entry. It exists with zero providers (it renders as a table). */
|
|
9
|
+
export const CHART_SPEC_COMPONENT_ID = 'chart.spec';
|
|
10
|
+
/** Provider id the catalog reports when no admitted provider draws a kind. */
|
|
11
|
+
export const CHART_TABLE_PROVIDER = 'core.table';
|
|
12
|
+
const LEGACY_KINDS = ['bar', 'line', 'pie'];
|
|
13
|
+
/** Catalog selection only needs ids and kinds; provider code always loads in the browser. */
|
|
14
|
+
function catalogProviderRegistry({ providers }, _options = {}) {
|
|
15
|
+
return createChartProviderRegistry({ providers: providers.map(({ id, kinds }) => ({
|
|
16
|
+
id, kinds, enabled: true, load: () => Promise.reject(new Error('Chart catalogs list providers; they never load them.')),
|
|
17
|
+
})) });
|
|
18
|
+
}
|
|
19
|
+
/** Legacy kinds keep their wire schema (shared by reference); other kinds take `{ spec }` of that kind. */
|
|
20
|
+
function kindPropsSchema({ kind }, { wire } = {}) {
|
|
21
|
+
return wire?.propsSchema ?? z.object({ spec: chartSpecSchema.extend({ kind: z.literal(kind) }) }).passthrough();
|
|
22
|
+
}
|
|
23
|
+
function providerDescription({ kind, provider }, { wire } = {}) {
|
|
24
|
+
const props = wire ? `Same props as ${wire.id} (one series)` : `Props: { spec } with spec.kind "${kind}"`;
|
|
25
|
+
return `${kind} chart drawn by ${provider}. ${props}. For several series use ${CHART_SPEC_COMPONENT_ID}.`;
|
|
26
|
+
}
|
|
27
|
+
function specDescription({ kinds }, _options = {}) {
|
|
28
|
+
const drawn = kinds.length > 0
|
|
29
|
+
? `Kinds the enabled chart providers draw: ${kinds.join(', ')}. Other kinds show the data as a table.`
|
|
30
|
+
: 'No chart provider is enabled, so the data shows as a table.';
|
|
31
|
+
return 'Any chart from one neutral spec, with one or more series: { spec: { kind, data: rows, categoryKey, '
|
|
32
|
+
+ 'series: [{ key, label? }] } }. Every row carries the category and a number (or null) for every series key. '
|
|
33
|
+
+ `Set spec.provider to prefer one provider. ${drawn}`;
|
|
34
|
+
}
|
|
35
|
+
/** The provider the generic entry reports: the site default when admitted, else the first admitted one. */
|
|
36
|
+
function specProvider({ providers }, { siteProvider } = {}) {
|
|
37
|
+
return (providers.find(({ id }) => id === siteProvider) ?? providers[0])?.id ?? CHART_TABLE_PROVIDER;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Build every chart entry for the current admitted providers:
|
|
41
|
+
* - one `<provider>.<kind>-chart` entry per provider and kind it draws, in selection order;
|
|
42
|
+
* - the legacy wire entries (unchanged ids, schemas and descriptions), reporting the selected provider;
|
|
43
|
+
* - `chart.spec`, present even with no provider.
|
|
44
|
+
* @complexity O(k * p) for k kinds and p providers.
|
|
45
|
+
* @example chartCatalogManifests({ providers: [{ id: 'plugin.charts', kinds: ['bar'] }] }, { siteProvider: 'plugin.charts' })
|
|
46
|
+
*/
|
|
47
|
+
export function chartCatalogManifests({ providers }, { siteProvider } = {}) {
|
|
48
|
+
const registry = catalogProviderRegistry({ providers });
|
|
49
|
+
const admitted = registry.list();
|
|
50
|
+
const kinds = [...new Set([...LEGACY_KINDS, ...admitted.flatMap(({ kinds }) => kinds)])];
|
|
51
|
+
const manifests = [];
|
|
52
|
+
for (const kind of kinds) {
|
|
53
|
+
const capability = chartCapability({ kind });
|
|
54
|
+
const wire = chartWireManifests.find((manifest) => manifest.capabilities.includes(capability));
|
|
55
|
+
const propsSchema = kindPropsSchema({ kind }, { wire });
|
|
56
|
+
const selected = chartProvidersByKind({ registry, kind }, { siteProvider });
|
|
57
|
+
// A provider literally named like a legacy prefix would mint the wire id twice; the wire entry wins.
|
|
58
|
+
for (const { id } of selected.filter((provider) => `${provider.id}.${capability}` !== wire?.id))
|
|
59
|
+
manifests.push({
|
|
60
|
+
id: `${id}.${capability}`, provider: id, capabilities: ['chart', capability, 'graph'], propsSchema,
|
|
61
|
+
description: providerDescription({ kind, provider: id }, { wire }),
|
|
62
|
+
});
|
|
63
|
+
if (wire)
|
|
64
|
+
manifests.push({ ...wire, provider: selected[0]?.id ?? CHART_TABLE_PROVIDER });
|
|
65
|
+
}
|
|
66
|
+
manifests.push({
|
|
67
|
+
id: CHART_SPEC_COMPONENT_ID, provider: specProvider({ providers: admitted }, { siteProvider }),
|
|
68
|
+
capabilities: ['chart', 'chart-spec'], propsSchema: chartSpecPropsSchema,
|
|
69
|
+
description: specDescription({ kinds: [...new Set(admitted.flatMap(({ kinds }) => kinds))] }),
|
|
70
|
+
});
|
|
71
|
+
return manifests;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=catalog-manifests.js.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
/** Headless chart contracts, schemas, theme tokens
|
|
1
|
+
/** Headless chart contracts, schemas, theme tokens, registry selection and catalog manifests (no React or DOM effects). */
|
|
2
|
+
export * from './catalog-manifests.js';
|
|
2
3
|
export * from './contract.js';
|
|
3
4
|
export * from './registry.js';
|
|
4
5
|
export * from './wire.js';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
/** Headless chart contracts, schemas, theme tokens
|
|
1
|
+
/** Headless chart contracts, schemas, theme tokens, registry selection and catalog manifests (no React or DOM effects). */
|
|
2
|
+
export * from './catalog-manifests.js';
|
|
2
3
|
export * from './contract.js';
|
|
3
4
|
export * from './registry.js';
|
|
4
5
|
export * from './wire.js';
|
|
@@ -13,15 +13,19 @@ export interface ChartHostProps {
|
|
|
13
13
|
}
|
|
14
14
|
/** React owns only the container; mountChart owns its descendants and lifecycle. */
|
|
15
15
|
export declare function ChartHost({ spec, registry, theme, siteProvider, onProviderError }: ChartHostProps): ReactElement;
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
type ChartHostOptions = {
|
|
17
|
+
siteProvider?: string | undefined;
|
|
18
|
+
theme?: ChartTheme;
|
|
19
|
+
};
|
|
20
|
+
/** Create a snapshot for validation AND rendering. The entries are exactly the headless catalog
|
|
21
|
+
* manifests (same ids, schemas and providers), each with a component; components are shared per
|
|
22
|
+
* (legacy kind, explicit provider), so a provider entry never draws with another provider.
|
|
23
|
+
* This closure is built once per host snapshot.
|
|
18
24
|
* @example createChartInteractiveRegistry({ registry: base, providers }, { siteProvider: 'plugin.recharts' })
|
|
19
25
|
*/
|
|
20
26
|
export declare function createChartInteractiveRegistry({ registry, providers }: {
|
|
21
27
|
registry: InteractiveUiRegistry;
|
|
22
28
|
providers: ChartProviderRegistry;
|
|
23
|
-
}, options?:
|
|
24
|
-
|
|
25
|
-
theme?: ChartTheme;
|
|
26
|
-
}): InteractiveUiRegistry;
|
|
29
|
+
}, options?: ChartHostOptions): InteractiveUiRegistry;
|
|
30
|
+
export {};
|
|
27
31
|
//# sourceMappingURL=react.d.ts.map
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
/** The only React adapter for the vanilla chart lifecycle; providers own any internal roots. */
|
|
3
3
|
import { useEffect, useRef } from 'react';
|
|
4
|
-
import { z } from 'zod';
|
|
5
4
|
import { InteractiveUiRegistry } from '../interactive-ui/registry.js';
|
|
6
5
|
import { chartSpecSchema, DEFAULT_CHART_THEME } from './contract.js';
|
|
7
6
|
import { mountChart } from './browser.js';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
7
|
+
import { CHART_SPEC_COMPONENT_ID, chartCatalogManifests } from './catalog-manifests.js';
|
|
8
|
+
import { chartCapability } from './registry.js';
|
|
9
|
+
import { chartSpecPropsSchema, chartWireManifests, legacyChartSpec, withSeriesLabels } from './wire.js';
|
|
10
10
|
/** React owns only the container; mountChart owns its descendants and lifecycle. */
|
|
11
11
|
export function ChartHost({ spec, registry, theme = DEFAULT_CHART_THEME, siteProvider, onProviderError }) {
|
|
12
12
|
const element = useRef(null);
|
|
@@ -31,45 +31,52 @@ export function ChartHost({ spec, registry, theme = DEFAULT_CHART_THEME, sitePro
|
|
|
31
31
|
}, [spec, theme]);
|
|
32
32
|
return _jsx("div", { ref: element, className: "jini-chart-host" });
|
|
33
33
|
}
|
|
34
|
-
/** Known wire kinds use the established shapes. Other providers register spec-based entries without
|
|
35
|
-
* adding fields or kinds to the core grammar. This closure is built once per host snapshot.
|
|
36
|
-
*/
|
|
37
34
|
/** Wire kinds that predate spec-based entries and keep their established prop shapes. */
|
|
38
35
|
const LEGACY_CHART_KINDS = ['bar', 'line', 'pie'];
|
|
39
|
-
|
|
36
|
+
/** Known wire kinds use the established shapes. Every other entry, `chart.spec` included, takes
|
|
37
|
+
* `{ spec }`, so providers add kinds without adding fields or kinds to the core grammar.
|
|
38
|
+
* A `<provider>.<kind>-chart` entry passes its `provider`, so it draws with the provider it
|
|
39
|
+
* advertises rather than the site default; wire aliases and `chart.spec` keep generic selection.
|
|
40
|
+
*/
|
|
41
|
+
function chartComponent({ legacyKind, providers, provider }, options) {
|
|
40
42
|
return function RegisteredChart(props) {
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
+
// chart.spec has stricter row/series rules; provider-only kinds retain their own contract.
|
|
44
|
+
const parsed = legacyKind ? legacyChartSpec({ kind: legacyKind, props })
|
|
45
|
+
: provider ? chartSpecSchema.parse(props.spec) : chartSpecPropsSchema.parse(props).spec;
|
|
46
|
+
const spec = withSeriesLabels({ spec: provider ? { ...parsed, provider } : parsed });
|
|
43
47
|
return _jsx(ChartHost, { spec: spec, registry: providers, ...options });
|
|
44
48
|
};
|
|
45
49
|
}
|
|
46
|
-
/**
|
|
47
|
-
|
|
50
|
+
/** The provider a provider-specific entry draws with; undefined for wire aliases and `chart.spec`. */
|
|
51
|
+
function explicitProviderOf({ manifest }, _options = {}) {
|
|
52
|
+
const generic = manifest.id === CHART_SPEC_COMPONENT_ID || chartWireManifests.some(({ id }) => id === manifest.id);
|
|
53
|
+
return generic ? undefined : manifest.provider;
|
|
54
|
+
}
|
|
55
|
+
/** The legacy kind an entry draws, read from its specific `<kind>-chart` capability. */
|
|
56
|
+
function legacyKindOf({ manifest }, _options = {}) {
|
|
57
|
+
const capability = manifest.capabilities.find((candidate) => candidate.endsWith('-chart'));
|
|
58
|
+
return LEGACY_CHART_KINDS.find((kind) => chartCapability({ kind }) === capability);
|
|
59
|
+
}
|
|
60
|
+
/** Create a snapshot for validation AND rendering. The entries are exactly the headless catalog
|
|
61
|
+
* manifests (same ids, schemas and providers), each with a component; components are shared per
|
|
62
|
+
* (legacy kind, explicit provider), so a provider entry never draws with another provider.
|
|
63
|
+
* This closure is built once per host snapshot.
|
|
48
64
|
* @example createChartInteractiveRegistry({ registry: base, providers }, { siteProvider: 'plugin.recharts' })
|
|
49
65
|
*/
|
|
50
66
|
export function createChartInteractiveRegistry({ registry, providers }, options = {}) {
|
|
51
|
-
const
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const
|
|
56
|
-
const
|
|
57
|
-
const
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
if (wire)
|
|
64
|
-
entries.push({ ...wire, id: `core.table.${capability}`, Component });
|
|
65
|
-
}
|
|
67
|
+
const admitted = providers.list().filter(({ enabled }) => enabled).map(({ id, kinds }) => ({ id, kinds }));
|
|
68
|
+
const manifests = chartCatalogManifests({ providers: admitted }, { siteProvider: options.siteProvider });
|
|
69
|
+
const components = new Map();
|
|
70
|
+
const componentFor = (manifest) => {
|
|
71
|
+
const legacyKind = legacyKindOf({ manifest });
|
|
72
|
+
const provider = explicitProviderOf({ manifest });
|
|
73
|
+
const key = JSON.stringify([legacyKind ?? null, provider ?? null]);
|
|
74
|
+
const component = components.get(key) ?? chartComponent({ legacyKind, providers, provider }, options);
|
|
75
|
+
components.set(key, component);
|
|
76
|
+
return component;
|
|
77
|
+
};
|
|
78
|
+
const entries = manifests.map((manifest) => ({ ...manifest, Component: componentFor(manifest) }));
|
|
66
79
|
const existing = registry.list().filter(({ capabilities }) => !capabilities.includes('chart'));
|
|
67
|
-
|
|
68
|
-
for (const wire of chartWireManifests) {
|
|
69
|
-
const capability = wire.capabilities.find((capability) => capability.endsWith('-chart'));
|
|
70
|
-
const selected = snapshot.resolveByCapability({ capability })[0];
|
|
71
|
-
snapshot = snapshot.register({ entry: { ...selected, id: wire.id } });
|
|
72
|
-
}
|
|
73
|
-
return snapshot;
|
|
80
|
+
return new InteractiveUiRegistry({ entries: [...entries, ...existing] });
|
|
74
81
|
}
|
|
75
82
|
//# sourceMappingURL=react.js.map
|