@taylorwong/ichartjs 2.0.1
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 +69 -0
- package/LICENSE +201 -0
- package/README.md +194 -0
- package/agent-recipes/diagrams/agent-orchestration.json +18 -0
- package/agent-recipes/diagrams/approval-process.json +16 -0
- package/agent-recipes/diagrams/responsibility-mapping.json +13 -0
- package/agent-recipes/diagrams/workflow.json +19 -0
- package/agent-recipes/foundational-analysis.json +18 -0
- package/agent-recipes/project-management.json +47 -0
- package/agent-recipes/trend-line.json +21 -0
- package/docs/agent/README.md +62 -0
- package/docs/agent/charting-scenario.md +82 -0
- package/docs/agent/coding-agent-integration.md +88 -0
- package/docs/agent/development/2.0-release-readiness.md +65 -0
- package/docs/agent/development/iteration-2.md +9 -0
- package/docs/agent/development/iteration-3.md +142 -0
- package/docs/agent/development/iteration-4.md +261 -0
- package/docs/agent/development/iteration-5.md +43 -0
- package/docs/agent/development/iteration-6.md +130 -0
- package/docs/agent/development/iteration-7.md +117 -0
- package/docs/agent/development/iteration-8-acceptance.md +68 -0
- package/docs/agent/development/iteration-8.md +116 -0
- package/docs/agent/development/iteration-9.md +44 -0
- package/docs/agent/development/playground-plan.md +143 -0
- package/docs/agent/development/prompt-contract.md +22 -0
- package/docs/agent/development/rc-1-acceptance.md +43 -0
- package/docs/agent/development/roadmap.md +259 -0
- package/docs/agent/development-guide.md +60 -0
- package/docs/agent/diagram-scenario.md +82 -0
- package/docs/agent/editing-contract.md +71 -0
- package/docs/agent/frontend-integration.md +66 -0
- package/docs/agent/project-scenario.md +89 -0
- package/docs/agent/quickstart.md +205 -0
- package/docs/agent/runtime-contract.md +132 -0
- package/docs/agent/theme-guide.md +59 -0
- package/docs/agent/zh-CN/README.md +26 -0
- package/docs/agent/zh-CN/charting-scenario.md +62 -0
- package/docs/agent/zh-CN/coding-agent-integration.md +36 -0
- package/docs/agent/zh-CN/development-guide.md +31 -0
- package/docs/agent/zh-CN/diagram-scenario.md +37 -0
- package/docs/agent/zh-CN/editing-contract.md +27 -0
- package/docs/agent/zh-CN/frontend-integration.md +31 -0
- package/docs/agent/zh-CN/project-scenario.md +40 -0
- package/docs/agent/zh-CN/quickstart.md +84 -0
- package/docs/agent/zh-CN/runtime-contract.md +85 -0
- package/docs/agent/zh-CN/theme-guide.md +50 -0
- package/docs/manifests/capabilities.json +79 -0
- package/docs/manifests/commands.json +30 -0
- package/docs/manifests/schemas.json +13 -0
- package/examples/agent-workflow.mjs +94 -0
- package/package.json +55 -0
- package/skills/ichartjs/SKILL.md +72 -0
- package/skills/ichartjs/agents/openai.yaml +4 -0
- package/skills/ichartjs/references/agent-contract.md +39 -0
- package/skills/ichartjs/references/chart-selection.md +22 -0
- package/src/capabilities.mjs +190 -0
- package/src/charts.mjs +234 -0
- package/src/command.mjs +93 -0
- package/src/data.mjs +75 -0
- package/src/diagram-interaction.mjs +195 -0
- package/src/diagram.mjs +135 -0
- package/src/edit-controller.mjs +192 -0
- package/src/edit.mjs +369 -0
- package/src/format.mjs +19 -0
- package/src/history.mjs +14 -0
- package/src/index.mjs +562 -0
- package/src/plugin.mjs +18 -0
- package/src/project-analytics.mjs +357 -0
- package/src/project-linking.mjs +72 -0
- package/src/project.mjs +370 -0
- package/src/recipes.mjs +18 -0
- package/src/renderer.mjs +77 -0
- package/src/scale.mjs +9 -0
- package/src/scene.mjs +18 -0
- package/src/schema.mjs +142 -0
- package/src/spec.mjs +127 -0
- package/src/theme.mjs +232 -0
- package/src/transforms.mjs +34 -0
- package/src/validation.mjs +106 -0
- package/types/index.d.ts +134 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Business data validation against declared schemas and cross-field rules.
|
|
3
|
+
* Returns normalized rows plus structured errors and warnings.
|
|
4
|
+
*/
|
|
5
|
+
import { copyJSON, isRecord, issue, validateDataSchema } from './schema.mjs';
|
|
6
|
+
|
|
7
|
+
export function isDateOnly(value) {
|
|
8
|
+
if (typeof value !== 'string' || !/^\d{4}-\d{2}-\d{2}$/.test(value)) return false;
|
|
9
|
+
const time = Date.parse(`${value}T00:00:00.000Z`);
|
|
10
|
+
return Number.isFinite(time) && new Date(time).toISOString().slice(0, 10) === value;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function cyclicIds(rows, key, field) {
|
|
14
|
+
const degree = new Map(rows.map(row => [row[key], 0])), next = new Map(rows.map(row => [row[key], []]));
|
|
15
|
+
rows.forEach(row => (row[field] || []).forEach(value => { const id = typeof value === 'string' ? value : value?.id; if (degree.has(id)) { degree.set(row[key], degree.get(row[key]) + 1); next.get(id).push(row[key]); } }));
|
|
16
|
+
const queue = [...degree.keys()].filter(id => degree.get(id) === 0);
|
|
17
|
+
for (let index = 0; index < queue.length; index += 1) next.get(queue[index]).forEach(id => { degree.set(id, degree.get(id) - 1); if (degree.get(id) === 0) queue.push(id); });
|
|
18
|
+
return [...degree.keys()].filter(id => degree.get(id) > 0);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function validateData(input, schema, options = {}) {
|
|
22
|
+
const contract = validateDataSchema(schema), errors = [...contract.errors], warnings = [], normalizations = [];
|
|
23
|
+
let original = [], rows = [], references = {};
|
|
24
|
+
if (!contract.valid) return { valid: false, errors, warnings, normalizations, original, rows };
|
|
25
|
+
try {
|
|
26
|
+
original = copyJSON(input);
|
|
27
|
+
references = copyJSON(options.references ?? {});
|
|
28
|
+
if (!Array.isArray(original) || !isRecord(references)) throw new Error('Data must be a row array; references must be a table object.');
|
|
29
|
+
rows = copyJSON(original);
|
|
30
|
+
} catch (error) { return { valid: false, errors: [issue('INVALID_DATA', 'values', error.message)], warnings, normalizations, original: [], rows: [] }; }
|
|
31
|
+
if (options.progressUnit !== undefined && !['ratio', 'percent'].includes(options.progressUnit)) errors.push(issue('PROGRESS_UNIT', 'options.progressUnit', 'Use ratio or percent explicitly.'));
|
|
32
|
+
const normalizeField = (object, name, field, path) => {
|
|
33
|
+
if (!Object.hasOwn(object, name)) {
|
|
34
|
+
if (Object.hasOwn(field, 'default')) {
|
|
35
|
+
object[name] = copyJSON(field.default);
|
|
36
|
+
normalizations.push({ path, beforePresent: false, after: copyJSON(object[name]), reason: 'default' });
|
|
37
|
+
} else { if (field.required) errors.push(issue('REQUIRED', path, 'Required field is missing.')); return; }
|
|
38
|
+
}
|
|
39
|
+
const value = object[name];
|
|
40
|
+
if (value === null && field.nullable) return;
|
|
41
|
+
if (field.anyOf) {
|
|
42
|
+
const option = field.anyOf.find(candidate => candidate.type === 'string' ? typeof value === 'string' : candidate.type === 'object' ? isRecord(value) : candidate.type === 'array' ? Array.isArray(value) : candidate.type === 'number' ? typeof value === 'number' && Number.isFinite(value) : candidate.type === 'boolean' ? typeof value === 'boolean' : candidate.type === 'date' ? isDateOnly(value) : candidate.type === 'enum' ? candidate.values.includes(value) : false);
|
|
43
|
+
if (!option) errors.push(issue('FIELD_VALUE', path, 'Value does not match any supported field shape.'));
|
|
44
|
+
else normalizeField(object, name, { ...option, required: field.required }, path);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const correctType = field.type === 'string' ? typeof value === 'string' && (!field.required || value.length > 0)
|
|
48
|
+
: field.type === 'number' ? typeof value === 'number' && Number.isFinite(value)
|
|
49
|
+
: field.type === 'boolean' ? typeof value === 'boolean'
|
|
50
|
+
: field.type === 'date' ? isDateOnly(value)
|
|
51
|
+
: field.type === 'enum' ? field.values.includes(value)
|
|
52
|
+
: field.type === 'array' ? Array.isArray(value) : isRecord(value);
|
|
53
|
+
if (!correctType) { errors.push(issue('FIELD_VALUE', path, `Expected ${field.type}.`, field.type === 'date' ? 'Use a real calendar date YYYY-MM-DD; timestamps are not date-only values.' : 'Use the declared type; automatic string/number coercion is disabled.')); return; }
|
|
54
|
+
if (field.type === 'number' && ((field.min !== undefined && value < field.min) || (field.max !== undefined && value > field.max))) errors.push(issue('OUT_OF_RANGE', path, 'Value is outside the declared limits.'));
|
|
55
|
+
if (field.type === 'array') {
|
|
56
|
+
if (field.unique && new Set(value.map(item => JSON.stringify(item))).size !== value.length) errors.push(issue('DUPLICATE_VALUE', path, 'Array values must be unique.'));
|
|
57
|
+
value.forEach((item, index) => normalizeField(value, index, field.items, `${path}.${index}`));
|
|
58
|
+
}
|
|
59
|
+
if (field.type === 'object') {
|
|
60
|
+
Object.keys(value).filter(key => !Object.hasOwn(field.properties, key)).forEach(key => errors.push(issue('UNKNOWN_FIELD', `${path}.${key}`, 'Object property is not declared.')));
|
|
61
|
+
Object.entries(field.properties).forEach(([key, child]) => normalizeField(value, key, child, `${path}.${key}`));
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
const ids = new Set();
|
|
65
|
+
rows.forEach((row, index) => {
|
|
66
|
+
const path = `values.${index}`;
|
|
67
|
+
if (!isRecord(row)) { errors.push(issue('INVALID_RECORD', path, 'Each row must be an object.')); return; }
|
|
68
|
+
if (options.progressUnit === 'ratio' && schema.name === 'project-task' && Object.hasOwn(row, 'progress')) {
|
|
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' }); }
|
|
71
|
+
}
|
|
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
|
+
Object.entries(schema.fields).forEach(([name, field]) => normalizeField(row, name, field, `${path}.${name}`));
|
|
74
|
+
if (ids.has(row[schema.key])) errors.push(issue('DUPLICATE_ID', `${path}.${schema.key}`, 'Primary keys must be unique.'));
|
|
75
|
+
ids.add(row[schema.key]);
|
|
76
|
+
});
|
|
77
|
+
if (!errors.length) {
|
|
78
|
+
rows.forEach((row, index) => {
|
|
79
|
+
for (const [name, field] of Object.entries(schema.fields)) {
|
|
80
|
+
if (!field.references || row[name] == null) continue;
|
|
81
|
+
let targets = ids;
|
|
82
|
+
if (field.references !== 'self') {
|
|
83
|
+
const table = references[field.references];
|
|
84
|
+
if (!Array.isArray(table) || table.some(id => typeof id !== 'string')) { errors.push(issue('REFERENCE_CONTEXT', `references.${field.references}`, 'Supply the trusted related record IDs before validating references.')); continue; }
|
|
85
|
+
targets = new Set(table);
|
|
86
|
+
}
|
|
87
|
+
const values = (Array.isArray(row[name]) ? row[name] : [row[name]]).map(value => typeof value === 'string' ? value : value?.id);
|
|
88
|
+
values.forEach(id => { if (!targets.has(id)) errors.push(issue('MISSING_REFERENCE', `values.${index}.${name}`, `Unknown referenced ID: ${id}`)); });
|
|
89
|
+
}
|
|
90
|
+
for (const rule of schema.rules || []) {
|
|
91
|
+
let valid = true;
|
|
92
|
+
if (rule.kind === 'compare' && row[rule.left] != null && row[rule.right] != null) {
|
|
93
|
+
const left = row[rule.left], right = row[rule.right];
|
|
94
|
+
valid = { gte: left >= right, gt: left > right, lte: left <= right, lt: left < right, eq: left === right }[rule.op];
|
|
95
|
+
} else if (rule.kind === 'implies') valid = JSON.stringify(row[rule.if.field]) !== JSON.stringify(rule.if.equals) || JSON.stringify(row[rule.then.field]) === JSON.stringify(rule.then.equals);
|
|
96
|
+
if (!valid) errors.push(issue('BUSINESS_RULE', `values.${index}`, rule.message || `Rule ${rule.id} failed.`, 'Update related fields together.', rule.id));
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
for (const [name, field] of Object.entries(schema.fields)) if (field.acyclic) {
|
|
100
|
+
const blocked = cyclicIds(rows, schema.key, name);
|
|
101
|
+
if (blocked.length) errors.push(issue('CYCLIC_DEPENDENCY', `values.*.${name}`, `Cycle blocks records: ${blocked.join(', ')}`));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (normalizations.length) warnings.push(issue('NORMALIZED_DATA', 'values', 'Explicit conversions/defaults were applied to the returned copy; input is unchanged.', 'Use the normalized rows as the preview baseline.'));
|
|
105
|
+
return { valid: errors.length === 0, errors, warnings, normalizations, original, rows };
|
|
106
|
+
}
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
export type Renderer = 'canvas' | 'svg' | 'auto';
|
|
2
|
+
export type ChartType = 'line' | 'area' | 'bar' | 'column' | 'pie' | 'scatter' | 'funnel' | 'gauge' | 'heatmap' | 'radar' | 'gantt' | 'timeline' | 'milestone' | 'burndown' | 'flow' | 'swimlane';
|
|
3
|
+
export type ThemeMode = 'auto' | 'light' | 'dark' | 'contrast';
|
|
4
|
+
export type ThemePreset = 'auto' | 'analysis' | 'dashboard' | 'report' | 'presentation' | 'project' | 'diagram';
|
|
5
|
+
export type ThemePalette = 'auto' | 'categorical' | 'sequential' | 'diverging' | 'status';
|
|
6
|
+
export type ExportKind = 'json' | 'svg' | 'png' | 'jpeg' | 'jpg' | 'image/png' | 'image/jpeg' | 'image/svg+xml' | 'application/json';
|
|
7
|
+
export type ExportAs = 'string' | 'dataurl' | 'blob' | 'object';
|
|
8
|
+
export interface ExportError { valid: false; code: string; rasterCode?: string; message?: string; suggestion?: string; [key: string]: unknown }
|
|
9
|
+
export interface ThemeConfig { mode?: ThemeMode; preset?: ThemePreset; palette?: ThemePalette; tokens?: Record<string, unknown>; branding?: boolean | { enabled?: boolean; [key: string]: unknown }; [key: string]: unknown; }
|
|
10
|
+
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; }
|
|
11
|
+
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[]; }
|
|
12
|
+
export interface Diagnostic { code: string; path?: string; message: string; expected?: unknown; suggestion?: string; [key: string]: unknown; }
|
|
13
|
+
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; }
|
|
14
|
+
export interface DataInspection { version: '1.0'; rows: number; fields: DataFieldInfo[]; dimensions: string[]; measures: string[]; temporalFields: string[]; missingValueCount: number; warnings: Diagnostic[]; }
|
|
15
|
+
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>; }
|
|
16
|
+
export interface RuntimeCapabilities { version: '2.0'; contractVersion: '1.0'; chartTypes: ChartType[]; charts: Record<ChartType, ChartCapability>; intents: string[]; renderers: Array<'canvas' | 'svg'>; interactions: string[]; exports: Array<'png' | 'svg' | 'json' | 'jpeg'>; styleSystem: { modes: ThemeMode[]; presets: ThemePreset[]; palettes: ThemePalette[]; switchable: boolean; automatic: boolean; [key: string]: unknown }; 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; }
|
|
17
|
+
export interface ChartPlan { version: '1.0'; intent: string; 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; }
|
|
18
|
+
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[]; style: Partial<StyleRecommendation> & { name?: string }; lineage: { recordIds: string[]; sourcePreserved: boolean }; accessibility: { enabled: boolean; summary: string }; }
|
|
19
|
+
export interface ChartSpec { type: ChartType; renderer?: Renderer; container?: string | Element; width?: number; height?: number; data?: Array<Record<string, unknown>> | { values?: Array<Record<string, unknown>>; [key: string]: unknown }; encoding?: Record<string, unknown>; title?: { text?: string; subtitle?: string }; legend?: { visible?: boolean; position?: string }; grid?: { visible?: boolean; color?: string }; labels?: { enabled?: boolean; format?: string | Record<string, unknown>; color?: string; font?: string }; interaction?: Record<string, boolean>; accessibility?: { enabled?: boolean; description?: string }; theme?: ThemeMode | ThemePreset | ThemeConfig | ResolvedTheme; [key: string]: unknown; }
|
|
20
|
+
export interface BinTransform { type: 'bin'; field: string; output?: string; thresholds?: number; step?: number; extent?: [number, number]; }
|
|
21
|
+
export interface RadarIndicator { name: string; field: string; min?: number; max?: number; }
|
|
22
|
+
export type BusinessFieldType = 'string' | 'number' | 'boolean' | 'date' | 'enum' | 'array' | 'object';
|
|
23
|
+
export interface BusinessField { type?: BusinessFieldType; anyOf?: BusinessField[]; required?: boolean; editable?: boolean; agentEditable?: boolean; nullable?: boolean; default?: unknown; min?: number; max?: number; values?: string[]; items?: BusinessField; properties?: Record<string, BusinessField>; references?: string; acyclic?: boolean; unique?: boolean; }
|
|
24
|
+
export interface BusinessDataSchema { name: string; version: '1.0'; key: string; fields: Record<string, BusinessField>; rules?: Array<Record<string, unknown>>; }
|
|
25
|
+
|
|
26
|
+
export interface LinkedFilters { owner?: string[]; status?: string[]; priority?: string[]; sprint?: string[]; label?: string[]; }
|
|
27
|
+
export interface LinkedState { filters: Required<LinkedFilters>; selection: string[]; selectedCount: number; sourceCount: number; visibleCount: number; sourceRecordIds: string[]; visibleRecordIds: string[]; }
|
|
28
|
+
|
|
29
|
+
export interface ProjectCalendarConfig { timezone?: 'UTC' | string; workingWeekdays?: number[]; holidays?: string[]; nonWorkingDayPolicy?: 'next-working-day' | 'previous-working-day' | 'allow' | string; }
|
|
30
|
+
export interface DependencyRule { id: string; type?: 'finish-to-start' | 'start-to-start' | 'finish-to-finish' | 'start-to-finish'; lag?: number; lead?: number; }
|
|
31
|
+
export interface ScheduleTaskResult { id: string; earliestStart: string | null; earliestFinish: string | null; latestStart: string | null; latestFinish: string | null; float: number; slack: number; critical: boolean; baselineVarianceDays: number | null; startVarianceDays: number | null; endVarianceDays: number | null; dependencies: DependencyRule[]; adjustedStart: string | null; adjustedEnd: string | null; }
|
|
32
|
+
export interface ScheduleAnalysisResult { calendar: Required<ProjectCalendarConfig>; tasks: ScheduleTaskResult[]; criticalIds: string[]; criticalEdges: Array<{ from: string; to: string }>; duration: number; assumptions: string[]; warnings: Array<Record<string, unknown>>; rows: Array<Record<string, unknown>>; }
|
|
33
|
+
export interface BurndownAnalysisResult { samples: Array<Record<string, unknown>>; initialScope?: number; start?: number; end?: number; forecast: { date: string | null; velocity?: number; reason: string; time?: number }; assumptions: string[]; warnings: Array<Record<string, unknown>>; }
|
|
34
|
+
export interface CapacityAnalysisResult { rows: Array<Record<string, unknown>>; warnings: Array<Record<string, unknown>>; assumptions: string[]; chartType?: string; values?: Array<Record<string, unknown>>; }
|
|
35
|
+
export interface ProjectAnalyticsState { linked?: LinkedState; schedule?: ScheduleAnalysisResult; burndown?: BurndownAnalysisResult; assumptions?: string[]; warnings?: Array<Record<string, unknown>>; [key: string]: unknown; }
|
|
36
|
+
|
|
37
|
+
export interface EditOperation { op: string; recordId?: string; taskId?: string; nodeId?: string; nodeIds?: string[]; edgeId?: string; groupId?: string | null; policy?: 'ungroup' | 'delete-members'; field?: string; value?: unknown; changes?: Record<string, unknown>; days?: number; dependencyId?: string; position?: { x: number; y: number }; size?: { width: number; height: number }; offset?: { x: number; y: number }; delta?: { x: number; y: number }; alignment?: 'left' | 'center' | 'right' | 'top' | 'middle' | 'bottom'; laneId?: string; }
|
|
38
|
+
export interface EditCommand { version?: '1.0'; type: 'edit' | 'layout-edit'; reason?: string; operations: EditOperation[]; }
|
|
39
|
+
export interface EditPreview { valid: boolean; id: string; command: EditCommand; changes: Array<{ path: string; before: unknown; after: unknown; operation: string }>; patches: Array<{ op: string; path: string; value: unknown }>; affectedRecords: string[]; warnings: Array<Record<string, unknown>>; requiresConfirmation: boolean; before: unknown[]; after: unknown[]; }
|
|
40
|
+
|
|
41
|
+
export interface Chart {
|
|
42
|
+
getSpec(): ChartSpec;
|
|
43
|
+
describe(): Record<string, unknown>;
|
|
44
|
+
explain(): ChartExplanation;
|
|
45
|
+
update(spec: Partial<ChartSpec>): this;
|
|
46
|
+
setData(data: Array<Record<string, unknown>>): this;
|
|
47
|
+
setTheme(theme?: ChartSpec['theme']): this;
|
|
48
|
+
getTheme(): ResolvedTheme;
|
|
49
|
+
resize(width?: number, height?: number): this;
|
|
50
|
+
resetZoom(): this;
|
|
51
|
+
zoomTo(view: Record<string, number>): this;
|
|
52
|
+
panBy(delta: { x?: number; y?: number }): this;
|
|
53
|
+
clearSelection(): this;
|
|
54
|
+
toDataURL(type?: 'image/png' | 'image/jpeg' | 'image/svg+xml'): string | ExportError;
|
|
55
|
+
toBlob(type?: 'image/png' | 'image/jpeg' | 'image/svg+xml'): Blob | ExportError;
|
|
56
|
+
export(options?: { type?: ExportKind; as?: ExportAs }): string | { version: string; spec: unknown; state: unknown } | Blob | ExportError;
|
|
57
|
+
exportAsync(options?: { type?: ExportKind; as?: ExportAs }): Promise<string | { version: string; spec: unknown; state: unknown } | Blob>;
|
|
58
|
+
download(options?: { type?: ExportKind | 'json' }): { valid: boolean; filename?: string; size?: number; type?: string; code?: string; message?: string } | ExportError | string;
|
|
59
|
+
downloadPNG(): ReturnType<Chart['download']>;
|
|
60
|
+
downloadSVG(): ReturnType<Chart['download']>;
|
|
61
|
+
downloadJSON(): ReturnType<Chart['download']>;
|
|
62
|
+
destroy(): void;
|
|
63
|
+
inspectDataSchema(): ReturnType<typeof inspectDataSchema>;
|
|
64
|
+
validateData(): Record<string, unknown>;
|
|
65
|
+
validateEdit(command: EditCommand): Record<string, unknown>;
|
|
66
|
+
previewEdit(command: EditCommand): EditPreview;
|
|
67
|
+
applyEdit(command: EditCommand, options?: { preview?: EditPreview; confirmed?: boolean; approval?: unknown; previewId?: string; expectedRevision?: number; actor?: string; source?: string; reason?: string }): Record<string, unknown>;
|
|
68
|
+
getChangeSet(): Record<string, unknown> | null;
|
|
69
|
+
getState(): Record<string, unknown>;
|
|
70
|
+
getProjectAnalytics(): ProjectAnalyticsState | null;
|
|
71
|
+
getLinkedState(): LinkedState | null;
|
|
72
|
+
setLinkedFilters(filters: LinkedFilters): this;
|
|
73
|
+
setLinkedSelection(selection: string[]): this;
|
|
74
|
+
selectNodes(nodeIds: string[], options?: { additive?: boolean }): this;
|
|
75
|
+
selectGroup(groupId: string, options?: { additive?: boolean }): this;
|
|
76
|
+
getSelectedNodeIds(): string[];
|
|
77
|
+
moveSelectedBy(delta: { x: number; y: number }, options?: Record<string, unknown>): Record<string, unknown>;
|
|
78
|
+
alignSelected(alignment: EditOperation['alignment'], options?: Record<string, unknown>): Record<string, unknown>;
|
|
79
|
+
snapSelected(options?: Record<string, unknown>): Record<string, unknown>;
|
|
80
|
+
moveGroupBy(groupId: string, delta: { x: number; y: number }, options?: Record<string, unknown>): Record<string, unknown>;
|
|
81
|
+
resizeGroup(groupId: string, size: { width: number; height: number }, options?: Record<string, unknown>): Record<string, unknown>;
|
|
82
|
+
assignSelectedToGroup(groupId: string | null, options?: Record<string, unknown>): Record<string, unknown>;
|
|
83
|
+
duplicateGroup(groupId: string, options?: Record<string, unknown>): Record<string, unknown>;
|
|
84
|
+
deleteGroup(groupId: string, options?: Record<string, unknown>): Record<string, unknown>;
|
|
85
|
+
undo(): Record<string, unknown>;
|
|
86
|
+
redo(): Record<string, unknown>;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function createChart(spec: ChartSpec): Chart;
|
|
90
|
+
export function normalizeSpec(spec: Partial<ChartSpec>): ChartSpec;
|
|
91
|
+
export function validateSpec(spec: Partial<ChartSpec>): { valid: boolean; errors: Diagnostic[]; warnings: Diagnostic[]; normalizations: Diagnostic[]; spec: ChartSpec };
|
|
92
|
+
export function normalizeData(input: unknown): { rows: Array<Record<string, unknown>>; fields: DataFieldInfo[]; warnings: Diagnostic[] };
|
|
93
|
+
export function inspectData(input: unknown): DataInspection;
|
|
94
|
+
export function getCapabilities(): RuntimeCapabilities;
|
|
95
|
+
export function getChartCapability(type: ChartType | string): ChartCapability | null;
|
|
96
|
+
export function planChart(input: unknown, options?: { intent?: string; renderer?: Renderer; context?: string; theme?: ChartSpec['theme']; preferredColorScheme?: 'light' | 'dark' }): ChartPlan;
|
|
97
|
+
export function recommend(input: unknown, options?: { intent?: string; renderer?: Renderer }): { primary: ChartType; alternatives: ChartType[]; reason: string; reasons: string[]; confidence: number; requiredFields: string[]; assumptions: string[]; warnings: Diagnostic[]; nextActions: string[] };
|
|
98
|
+
export function explainChart(spec: ChartSpec, model?: Record<string, unknown>): ChartExplanation;
|
|
99
|
+
export function planStyle(spec?: Partial<ChartSpec>, options?: { context?: string; theme?: ChartSpec['theme']; preferredColorScheme?: 'light' | 'dark' }): StyleRecommendation;
|
|
100
|
+
export function resolveTheme(theme?: ChartSpec['theme'], options?: Partial<ChartSpec> & { context?: string; preferredColorScheme?: 'light' | 'dark' }): ResolvedTheme;
|
|
101
|
+
export function contrastRatio(foreground: string, background: string): number | null;
|
|
102
|
+
export function validateThemeContrast(theme: ResolvedTheme): Diagnostic[];
|
|
103
|
+
export const themeModes: ThemeMode[];
|
|
104
|
+
export const themePresets: ThemePreset[];
|
|
105
|
+
export const themePalettes: ThemePalette[];
|
|
106
|
+
export const styleCapabilities: RuntimeCapabilities['styleSystem'];
|
|
107
|
+
export function binData(rows: Array<Record<string, unknown>>, options: Omit<BinTransform, 'type'>): { rows: Array<Record<string, unknown>>; warnings: Array<Record<string, unknown>>; assumptions: string[] };
|
|
108
|
+
export function applyTransforms(rows: Array<Record<string, unknown>>, transforms: BinTransform | BinTransform[]): { rows: Array<Record<string, unknown>>; warnings: Array<Record<string, unknown>>; assumptions: string[] };
|
|
109
|
+
export function getBusinessSchema(name: string): BusinessDataSchema;
|
|
110
|
+
export function inspectDataSchema(schema: BusinessDataSchema): Record<string, unknown>;
|
|
111
|
+
export function validateData(values: unknown[], schema: BusinessDataSchema, options?: Record<string, unknown>): Record<string, unknown>;
|
|
112
|
+
export function previewEdit(command: EditCommand, options: Record<string, unknown>): EditPreview;
|
|
113
|
+
export function validateEdit(command: EditCommand, options: Record<string, unknown>): Record<string, unknown>;
|
|
114
|
+
export function getEditCapabilities(schema: BusinessDataSchema): Record<string, unknown>;
|
|
115
|
+
export function validateRecipe(recipe: Record<string, unknown>, capabilities?: Record<string, unknown>): Record<string, unknown>;
|
|
116
|
+
|
|
117
|
+
export function normalizeProjectCalendar(input?: ProjectCalendarConfig): { calendar: Required<ProjectCalendarConfig>; warnings: Array<Record<string, unknown>> };
|
|
118
|
+
export function applyWorkingCalendar(value: string | Date, options?: ProjectCalendarConfig | { calendar?: ProjectCalendarConfig }): { date: string | null; adjusted: boolean; warnings: Array<Record<string, unknown>> };
|
|
119
|
+
export function normalizeDependencies(rows: Array<Record<string, unknown>>, options?: Record<string, unknown>): { rows: Array<Record<string, unknown>>; warnings: Array<Record<string, unknown>> };
|
|
120
|
+
export function analyzeSchedule(rows: Array<Record<string, unknown>>, options?: { calendar?: ProjectCalendarConfig }): ScheduleAnalysisResult;
|
|
121
|
+
export function analyzeBurndownSeries(rows: Array<Record<string, unknown>>, options?: Record<string, unknown>): BurndownAnalysisResult;
|
|
122
|
+
export function analyzeCapacity(rows: Array<Record<string, unknown>>, options?: Record<string, unknown>): CapacityAnalysisResult;
|
|
123
|
+
export function buildCapacityView(rows: Array<Record<string, unknown>>, options?: Record<string, unknown>): CapacityAnalysisResult;
|
|
124
|
+
export function buildCumulativeFlowSeries(rows: Array<Record<string, unknown>>, options?: Record<string, unknown>): CapacityAnalysisResult;
|
|
125
|
+
export function buildVelocitySeries(rows: Array<Record<string, unknown>>, options?: Record<string, unknown>): CapacityAnalysisResult;
|
|
126
|
+
export function buildReleaseForecast(rows: Array<Record<string, unknown>>, options?: Record<string, unknown>): CapacityAnalysisResult;
|
|
127
|
+
export function buildRiskMatrixSeries(rows: Array<Record<string, unknown>>, options?: Record<string, unknown>): CapacityAnalysisResult;
|
|
128
|
+
export function buildIssueAgingSeries(rows: Array<Record<string, unknown>>, options?: Record<string, unknown>): CapacityAnalysisResult;
|
|
129
|
+
|
|
130
|
+
export function normalizeLinkedFilters(input?: LinkedFilters): Required<LinkedFilters>;
|
|
131
|
+
export function normalizeLinkedSelection(input?: string[]): string[];
|
|
132
|
+
export function filterProjectRows(rows: Array<Record<string, unknown>>, linked?: { filters?: LinkedFilters } | LinkedFilters): Array<Record<string, unknown>>;
|
|
133
|
+
export function createLinkedProjectState(rows: Array<Record<string, unknown>>, linked?: { filters?: LinkedFilters; selection?: string[] }): LinkedState;
|
|
134
|
+
export function linkedRecordId(row: Record<string, unknown>, index?: number): string;
|