@taylorwong/ichartjs 2.0.19 → 2.0.21
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 +11 -0
- package/README.md +3 -2
- package/docs/agent/coding-agent-integration.md +1 -1
- package/docs/agent/conversational-workflow.md +134 -0
- package/docs/agent/development/2.0-release-readiness.md +1 -1
- package/docs/agent/development/iteration-16.md +70 -0
- package/docs/agent/development/iteration-17.md +55 -0
- package/docs/agent/development/roadmap.md +20 -2
- package/docs/agent/diagram-scenario.md +2 -0
- package/docs/agent/frontend-integration.md +1 -1
- package/docs/agent/runtime-contract.md +3 -1
- package/docs/agent/usage-scenarios.md +5 -1
- package/docs/agent/zh-CN/coding-agent-integration.md +1 -1
- package/docs/agent/zh-CN/conversational-workflow.md +128 -0
- package/docs/agent/zh-CN/diagram-scenario.md +2 -0
- package/docs/agent/zh-CN/frontend-integration.md +1 -1
- package/docs/agent/zh-CN/iteration-17.md +50 -0
- package/docs/agent/zh-CN/runtime-contract.md +3 -1
- package/docs/agent/zh-CN/usage-scenarios.md +5 -1
- package/docs/manifests/capabilities.json +62 -5
- package/package.json +3 -2
- package/skills/ichartjs/SKILL.md +3 -1
- package/src/capabilities.mjs +37 -3
- package/src/index.mjs +11 -7
- package/src/preferences.mjs +24 -1
- package/src/project.mjs +2 -2
- package/src/renderer.mjs +2 -2
- package/src/scene.mjs +5 -0
- package/src/spec.mjs +4 -2
- package/src/validation.mjs +2 -2
- package/types/index.d.ts +6 -4
package/src/validation.mjs
CHANGED
|
@@ -33,7 +33,7 @@ export function validateData(input, schema, options = {}) {
|
|
|
33
33
|
if (!Object.hasOwn(object, name)) {
|
|
34
34
|
if (Object.hasOwn(field, 'default')) {
|
|
35
35
|
object[name] = copyJSON(field.default);
|
|
36
|
-
normalizations.push({ path, beforePresent: false, after: copyJSON(object[name]), reason: 'default' });
|
|
36
|
+
normalizations.push({ code: 'DEFAULT_VALUE', path, beforePresent: false, after: copyJSON(object[name]), reason: 'default' });
|
|
37
37
|
} else { if (field.required) errors.push(issue('REQUIRED', path, 'Required field is missing.')); return; }
|
|
38
38
|
}
|
|
39
39
|
const value = object[name];
|
|
@@ -67,7 +67,7 @@ export function validateData(input, schema, options = {}) {
|
|
|
67
67
|
if (!isRecord(row)) { errors.push(issue('INVALID_RECORD', path, 'Each row must be an object.')); return; }
|
|
68
68
|
if (options.progressUnit === 'ratio' && schema.name === 'project-task' && Object.hasOwn(row, 'progress')) {
|
|
69
69
|
if (typeof row.progress !== 'number' || row.progress < 0 || row.progress > 1) errors.push(issue('PROGRESS_UNIT', `${path}.progress`, 'Ratio progress must be between 0 and 1.'));
|
|
70
|
-
else { const before = row.progress; row.progress *= 100; normalizations.push({ path: `${path}.progress`, beforePresent: true, before, after: row.progress, reason: 'ratio-to-percent' }); }
|
|
70
|
+
else { const before = row.progress; row.progress *= 100; normalizations.push({ code: 'PROGRESS_UNIT_CONVERSION', path: `${path}.progress`, beforePresent: true, before, after: row.progress, reason: 'ratio-to-percent' }); }
|
|
71
71
|
}
|
|
72
72
|
Object.keys(row).filter(key => !Object.hasOwn(schema.fields, key)).forEach(key => errors.push(issue('UNKNOWN_FIELD', `${path}.${key}`, 'Field is not declared in the business schema.')));
|
|
73
73
|
Object.entries(schema.fields).forEach(([name, field]) => normalizeField(row, name, field, `${path}.${name}`));
|
package/types/index.d.ts
CHANGED
|
@@ -16,8 +16,9 @@ export type ChartPreferencesPatch = Partial<Omit<ChartPreferences, 'version'>> &
|
|
|
16
16
|
export interface PreferenceCapabilityOption { value: string | number | boolean | null; label: string; }
|
|
17
17
|
export interface PreferenceFieldCapability { path: string; group: 'theme' | 'typography' | 'components' | 'behavior'; groupLabel: string; type: 'enum' | 'number' | 'tri-state'; label: string; description: string; default: string | number | boolean | null; options: PreferenceCapabilityOption[]; scopes: Array<'global' | 'chart'>; supported: boolean; applicability: string; menu: { visible: boolean; control: 'select' | 'toggle' }; minimum?: number; maximum?: number; }
|
|
18
18
|
export interface PreferenceCapabilities { version: '1.0'; locale: 'en' | 'zh-CN'; chartType: ChartType | null; scopes: Array<'global' | 'chart'>; persistence: Array<'memory' | 'localStorage' | 'adapter'>; precedence: string[]; fields: PreferenceFieldCapability[]; }
|
|
19
|
+
export interface PreferenceResolution { version: '1.0'; precedence: string[]; storage: 'localStorage' | 'adapter' | 'memory'; scopes: { defaults: string; spec: string; global: string | null; chart: string | null; }; }
|
|
19
20
|
export interface PreferencesStoreState { version: '1.0'; global: ChartPreferences; charts: Record<string, ChartPreferencesPatch>; }
|
|
20
|
-
export interface PreferencesStore { version: '1.0'; storageKey: string; storage: 'localStorage' | 'memory'; getState(): PreferencesStoreState; getGlobal(): ChartPreferences; getChart(chartId: string): ChartPreferencesPatch; getEffective(chartId?: string | null): ChartPreferences; setGlobal(patch: ChartPreferencesPatch, options?: { source?: string; persist?: boolean }): ChartPreferences; setChart(chartId: string, patch: ChartPreferencesPatch, options?: { source?: string; persist?: boolean }): ChartPreferences; reset(options?: { scope?: 'all' | 'global' | 'chart'; chartId?: string; source?: string; persist?: boolean }): ChartPreferences; subscribe(listener: (event: { type: 'change'; scope: string; chartId: string | null; source: string; persisted: boolean; preferences: ChartPreferences; state: PreferencesStoreState }) => void): () => void; persist(): boolean; }
|
|
21
|
+
export interface PreferencesStore { version: '1.0'; storageKey: string; storage: 'localStorage' | 'adapter' | 'memory'; getState(): PreferencesStoreState; getGlobal(): ChartPreferences; getChart(chartId: string): ChartPreferencesPatch; getEffective(chartId?: string | null): ChartPreferences; getResolution(chartId?: string | null): PreferenceResolution; setGlobal(patch: ChartPreferencesPatch, options?: { source?: string; persist?: boolean }): ChartPreferences; setChart(chartId: string, patch: ChartPreferencesPatch, options?: { source?: string; persist?: boolean }): ChartPreferences; reset(options?: { scope?: 'all' | 'global' | 'chart'; chartId?: string; source?: string; persist?: boolean }): ChartPreferences; subscribe(listener: (event: { type: 'change'; scope: string; chartId: string | null; source: string; persisted: boolean; preferences: ChartPreferences; state: PreferencesStoreState }) => void): () => void; persist(): boolean; }
|
|
21
22
|
export interface PreferencesStorage { getItem(key: string): string | null; setItem(key: string, value: string): void; removeItem?(key: string): void; }
|
|
22
23
|
export interface StyleRecommendation { version: '1.0'; preset: Exclude<ThemePreset, 'auto'>; mode: ThemeMode; resolvedMode: Exclude<ThemeMode, 'auto'>; palette: Exclude<ThemePalette, 'auto'>; reasons: string[]; warnings: Diagnostic[]; userOverride: boolean; }
|
|
23
24
|
export interface ResolvedTheme extends ThemeConfig { name: string; resolvedMode: Exclude<ThemeMode, 'auto'>; background: string; surface: string; text: string; muted: string; axis: string; grid: string; border: string; focus: string; selection: string; colors: string[]; palettes: Record<string, unknown>; status: Record<string, string>; typography: Record<string, { size: number; weight: number; lineHeight: number; font: string }>; layout: Record<string, unknown>; marks: Record<string, unknown>; reasons: string[]; warnings: Diagnostic[]; }
|
|
@@ -26,12 +27,12 @@ export class ChartValidationError extends Error { name: 'ChartValidationError';
|
|
|
26
27
|
export interface DataFieldInfo { name: string; type: 'quantitative' | 'temporal' | 'category' | 'unknown'; role: 'identifier' | 'measure' | 'temporal-dimension' | 'dimension'; unit: string | null; cardinality: number; validCount: number; nullCount: number; min?: number; max?: number; temporalMin?: string; temporalMax?: string; }
|
|
27
28
|
export interface DataInspection { version: '1.0'; rows: number; fields: DataFieldInfo[]; dimensions: string[]; measures: string[]; temporalFields: string[]; missingValueCount: number; warnings: Diagnostic[]; }
|
|
28
29
|
export interface ChartCapability { type: ChartType; family: string; intents: string[]; required: string[]; optional: string[]; dataShapes: string[]; interactions: string[]; features: Record<string, 'supported' | 'not-applicable' | 'degraded'>; renderers: Array<'canvas' | 'svg'>; exports: string[]; limits: Record<string, number>; }
|
|
29
|
-
export interface RuntimeCapabilities { version: '2.0'; contractVersion: '1.1'; chartTypes: ChartType[]; charts: Record<ChartType, ChartCapability>; intents: string[]; locale?: { default: string; recommended: string[]; appliesTo: string[]; inputDates: string }; renderers: Array<'canvas' | 'svg'>; interactions: string[]; exports: Array<'png' | 'svg' | 'json' | 'jpeg'>; chartModes?: Record<string, unknown>; diagram?: { flowNodeKinds?: FlowNodeKind[]; flowBranchEdges?: { label: string; minimumOutgoing: number }; flowLoops?: string; flowConnectors?: { kind: FlowNodeKind; linking: string }; [key: string]: unknown }; styleSystem: { modes: ThemeMode[]; presets: ThemePreset[]; palettes: ThemePalette[]; switchable: boolean; automatic: boolean; [key: string]: unknown }; preferences?: { version: '1.0'; scopes: string[]; persistence: string[]; fields: string[]; agentAdjustable: boolean; interactiveSettingsUI: boolean; precedence: string[]; schema: PreferenceCapabilities }; headless: { preview?: boolean; json: boolean; svg: boolean; png: boolean | string }; export: { types: string[]; mime: Record<string, string>; browser: Record<string, boolean>; headless: Record<string, string | boolean>; methods: string[]; options: Record<string, unknown>; branding: Record<string, unknown> }; branding: { defaultEnabled: boolean; signature: string; options: Record<string, unknown> }; [key: string]: unknown; }
|
|
30
|
+
export interface RuntimeCapabilities { version: '2.0'; contractVersion: '1.1'; chartTypes: ChartType[]; charts: Record<ChartType, ChartCapability>; intents: string[]; locale?: { default: string; recommended: string[]; appliesTo: string[]; inputDates: string }; renderers: Array<'canvas' | 'svg'>; interactions: string[]; exports: Array<'png' | 'svg' | 'json' | 'jpeg'>; chartModes?: Record<string, unknown>; conversationalWorkflow?: { version: '1.0'; steps: string[]; routing: Record<string, string>; confirmation: string[]; selfCheck: string[] }; agentReliability?: Record<string, unknown>; diagram?: { flowNodeKinds?: FlowNodeKind[]; flowBranchEdges?: { label: string; minimumOutgoing: number }; flowLoops?: string; flowConnectors?: { kind: FlowNodeKind; linking: string }; [key: string]: unknown }; styleSystem: { modes: ThemeMode[]; presets: ThemePreset[]; palettes: ThemePalette[]; switchable: boolean; automatic: boolean; [key: string]: unknown }; preferences?: { version: '1.0'; scopes: string[]; persistence: string[]; fields: string[]; agentAdjustable: boolean; interactiveSettingsUI: boolean; precedence: string[]; schema: PreferenceCapabilities }; headless: { preview?: boolean; json: boolean; svg: boolean; png: boolean | string }; export: { types: string[]; mime: Record<string, string>; browser: Record<string, boolean>; headless: Record<string, string | boolean>; methods: string[]; options: Record<string, unknown>; branding: Record<string, unknown> }; branding: { defaultEnabled: boolean; signature: string; options: Record<string, unknown> }; [key: string]: unknown; }
|
|
30
31
|
export interface ChartPlan { version: '1.0'; intent: string; intentKnown?: boolean; intentSuggestions?: string[]; fallbackUsed?: boolean; primary: ChartType; alternatives: ChartType[]; confidence: number; reasons: string[]; requiredFields: string[]; suggestedEncodings: { dimension: string | null; measure: string | null; secondaryMeasure: string | null }; assumptions: string[]; warnings: Diagnostic[]; unsupportedRequests: string[]; nextActions: string[]; capability: ChartCapability; styleRecommendation: StyleRecommendation; data: DataInspection; }
|
|
31
32
|
export interface AxisState { rawDomain: [number, number]; domain: [number, number]; ticks: number[]; step: number | null; policy: 'nice' | 'raw' | 'explicit'; }
|
|
32
33
|
export interface TimeAxisState { orientation: 'horizontal'; field: 'date'; coordinate: 'x'; rowCoordinate: 'y'; domain: [number, number]; domainISO: [string, string]; }
|
|
33
34
|
export interface ChartHealth { version: '1.0'; status: 'ready' | 'degraded' | 'empty'; renderable: boolean; issues: string[]; metrics: { warnings: number; suppressedLabels: number; clampedValues: number; renderedMarks: number }; }
|
|
34
|
-
export interface ChartExplanation { version: '1.0'; type: ChartType; family: string; purpose: string; renderer: Renderer; dataCount: number; encodings: Record<string, string | string[]>; transforms: string[]; interactions: string[]; assumptions: string[]; warnings: Diagnostic[]; axes?: { y?: AxisState; right?: AxisState } | null; timeAxis?: TimeAxisState | null; health?: ChartHealth; style: Partial<StyleRecommendation> & { name?: string }; lineage: { recordIds: string[]; sourcePreserved: boolean }; accessibility: { enabled: boolean; summary: string }; }
|
|
35
|
+
export interface ChartExplanation { version: '1.0'; type: ChartType; family: string; purpose: string; renderer: Renderer; dataCount: number; encodings: Record<string, string | string[]>; transforms: string[]; interactions: string[]; effective?: { renderer?: Renderer; title?: ChartTitle; legend?: ChartLegend; grid?: Record<string, unknown>; labels?: ChartLabels; interaction?: ChartInteraction; branding?: ChartSpec['branding'] }; assumptions: string[]; normalizations?: Diagnostic[]; warnings: Diagnostic[]; axes?: { y?: AxisState; right?: AxisState } | null; timeAxis?: TimeAxisState | null; health?: ChartHealth; style: Partial<StyleRecommendation> & { name?: string }; lineage: { recordIds: string[]; sourcePreserved: boolean }; accessibility: { enabled: boolean; summary: string }; }
|
|
35
36
|
export interface ChartInteraction { tooltip?: boolean; hover?: boolean; click?: boolean; crosshair?: boolean; zoom?: boolean; pan?: boolean; brush?: boolean; drag?: boolean; edgeDrag?: boolean; portConnect?: boolean; keyboard?: boolean; [key: string]: boolean | undefined; }
|
|
36
37
|
export interface ChartEditing { enabled?: boolean; mode?: 'command' | string; requireConfirmation?: boolean; allowDelete?: boolean; allowStructuralChanges?: boolean; }
|
|
37
38
|
export interface ChartTitle { text?: string; subtitle?: string; label?: string; }
|
|
@@ -105,7 +106,7 @@ export interface ClipboardState { nodes: DiagramNode[]; edges: DiagramEdge[]; }
|
|
|
105
106
|
export interface ChartLayoutState { family: string | null; plot: Record<string, unknown>; chrome: Record<string, unknown> | null; labels: Record<string, unknown> | null; }
|
|
106
107
|
export interface ChartAxesState { y?: AxisState; right?: AxisState; [key: string]: unknown; }
|
|
107
108
|
export interface ChartBrandingState { enabled: boolean; signature: string; text: string | null; }
|
|
108
|
-
export interface ChartState { renderer: string; width: number; height: number; dataCount: number; selected: unknown[]; revision: number; history: { undo: number; redo: number }; view: Record<string, unknown> | null; style?: Partial<StyleRecommendation> & { name?: string; mode?: ThemeMode; resolvedMode?: string; palette?: ThemePalette }; layout?: ChartLayoutState | null; timeAxis?: TimeAxisState | null; axes?: ChartAxesState | null; health: ChartHealth; preferences: ChartPreferences; branding?: ChartBrandingState; warnings: Diagnostic[]; assumptions?: string[]; normalizations?: Diagnostic[]; collapsedGroups?: string[]; projectAnalytics?: ProjectAnalyticsState | null; linked?: LinkedState | null; clipboard: { nodes: number; edges: number }; [key: string]: unknown; }
|
|
109
|
+
export interface ChartState { renderer: string; width: number; height: number; dataCount: number; selected: unknown[]; revision: number; history: { undo: number; redo: number }; view: Record<string, unknown> | null; style?: Partial<StyleRecommendation> & { name?: string; mode?: ThemeMode; resolvedMode?: string; palette?: ThemePalette }; layout?: ChartLayoutState | null; timeAxis?: TimeAxisState | null; axes?: ChartAxesState | null; health: ChartHealth; preferences: ChartPreferences; preferenceResolution: PreferenceResolution; branding?: ChartBrandingState; warnings: Diagnostic[]; assumptions?: string[]; normalizations?: Diagnostic[]; collapsedGroups?: string[]; projectAnalytics?: ProjectAnalyticsState | null; linked?: LinkedState | null; clipboard: { nodes: number; edges: number }; [key: string]: unknown; }
|
|
109
110
|
export interface DiagramConfig { mode?: 'process' | 'architecture' | 'mindmap'; layout?: 'manual' | 'layered' | 'tree' | 'radial'; routing?: 'straight' | 'orthogonal' | 'curved'; curveTension?: number; grid?: number; snap?: boolean; }
|
|
110
111
|
export interface ArchitectureLayer { id: string; label?: string; }
|
|
111
112
|
export interface ArchitectureBoundary { id: string; label?: string; nodeIds?: string[]; padding?: number; color?: string; }
|
|
@@ -137,6 +138,7 @@ export interface Chart {
|
|
|
137
138
|
setTheme(theme?: ChartSpec['theme']): this;
|
|
138
139
|
getTheme(): ResolvedTheme;
|
|
139
140
|
getPreferences(): ChartPreferences;
|
|
141
|
+
getPreferenceResolution(): PreferenceResolution;
|
|
140
142
|
setPreferences(patch?: ChartPreferencesPatch, options?: { scope?: 'chart' | 'global'; source?: string; persist?: boolean }): this;
|
|
141
143
|
resetPreferences(options?: { scope?: 'all' | 'global' | 'chart'; source?: string; persist?: boolean }): this;
|
|
142
144
|
resize(width?: number, height?: number): this;
|