@vertesia/fusion-ux 1.2.0 → 1.4.0-dev.20260614.160504Z

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.
Files changed (126) hide show
  1. package/LICENSE +198 -10
  2. package/lib/fusion-fragment/ChartRenderer.d.ts.map +1 -0
  3. package/lib/{esm/fusion-fragment → fusion-fragment}/ChartRenderer.js +8 -6
  4. package/lib/fusion-fragment/ChartRenderer.js.map +1 -0
  5. package/lib/{types/fusion-fragment → fusion-fragment}/FieldRenderer.d.ts +1 -1
  6. package/lib/fusion-fragment/FieldRenderer.d.ts.map +1 -0
  7. package/lib/{esm/fusion-fragment → fusion-fragment}/FieldRenderer.js +14 -8
  8. package/lib/fusion-fragment/FieldRenderer.js.map +1 -0
  9. package/lib/{types/fusion-fragment → fusion-fragment}/FusionFragmentContext.d.ts +3 -3
  10. package/lib/fusion-fragment/FusionFragmentContext.d.ts.map +1 -0
  11. package/lib/{esm/fusion-fragment → fusion-fragment}/FusionFragmentContext.js +2 -2
  12. package/lib/fusion-fragment/FusionFragmentContext.js.map +1 -0
  13. package/lib/fusion-fragment/FusionFragmentHandler.d.ts.map +1 -0
  14. package/lib/{esm/fusion-fragment → fusion-fragment}/FusionFragmentHandler.js +7 -14
  15. package/lib/fusion-fragment/FusionFragmentHandler.js.map +1 -0
  16. package/lib/fusion-fragment/FusionFragmentRenderer.d.ts.map +1 -0
  17. package/lib/{esm/fusion-fragment → fusion-fragment}/FusionFragmentRenderer.js +2 -2
  18. package/lib/fusion-fragment/FusionFragmentRenderer.js.map +1 -0
  19. package/lib/{types/fusion-fragment → fusion-fragment}/SectionRenderer.d.ts +1 -1
  20. package/lib/fusion-fragment/SectionRenderer.d.ts.map +1 -0
  21. package/lib/{esm/fusion-fragment → fusion-fragment}/SectionRenderer.js +12 -5
  22. package/lib/fusion-fragment/SectionRenderer.js.map +1 -0
  23. package/lib/fusion-fragment/TableRenderer.d.ts.map +1 -0
  24. package/lib/{esm/fusion-fragment → fusion-fragment}/TableRenderer.js +9 -7
  25. package/lib/fusion-fragment/TableRenderer.js.map +1 -0
  26. package/lib/{types/fusion-fragment → fusion-fragment}/index.d.ts +4 -4
  27. package/lib/fusion-fragment/index.d.ts.map +1 -0
  28. package/lib/{esm/fusion-fragment → fusion-fragment}/index.js +4 -4
  29. package/lib/fusion-fragment/index.js.map +1 -0
  30. package/lib/{types/index.d.ts → index.d.ts} +4 -4
  31. package/lib/index.d.ts.map +1 -0
  32. package/lib/{esm/index.js → index.js} +4 -4
  33. package/lib/index.js.map +1 -0
  34. package/lib/{types/render → render}/index.d.ts +1 -1
  35. package/lib/render/index.d.ts.map +1 -0
  36. package/lib/{esm/render → render}/index.js +1 -1
  37. package/lib/render/index.js.map +1 -0
  38. package/lib/render/textPreview.d.ts.map +1 -0
  39. package/lib/{esm/render → render}/textPreview.js +12 -9
  40. package/lib/render/textPreview.js.map +1 -0
  41. package/lib/types.d.ts.map +1 -0
  42. package/lib/types.js.map +1 -0
  43. package/lib/validation/formatErrors.d.ts.map +1 -0
  44. package/lib/{esm/validation → validation}/formatErrors.js +1 -1
  45. package/lib/validation/formatErrors.js.map +1 -0
  46. package/lib/validation/fuzzyMatch.d.ts.map +1 -0
  47. package/lib/{esm/validation → validation}/fuzzyMatch.js +3 -4
  48. package/lib/validation/fuzzyMatch.js.map +1 -0
  49. package/lib/validation/index.d.ts +8 -0
  50. package/lib/validation/index.d.ts.map +1 -0
  51. package/lib/validation/index.js +8 -0
  52. package/lib/validation/index.js.map +1 -0
  53. package/lib/{types/validation → validation}/schemas.d.ts +1 -1
  54. package/lib/validation/schemas.d.ts.map +1 -0
  55. package/lib/{esm/validation → validation}/schemas.js +25 -25
  56. package/lib/validation/schemas.js.map +1 -0
  57. package/lib/validation/validateTemplate.d.ts.map +1 -0
  58. package/lib/{esm/validation → validation}/validateTemplate.js +23 -21
  59. package/lib/validation/validateTemplate.js.map +1 -0
  60. package/lib/vertesia-fusion-ux.js +1 -1
  61. package/lib/vertesia-fusion-ux.js.map +1 -1
  62. package/package.json +23 -35
  63. package/src/fusion-fragment/ChartRenderer.tsx +95 -96
  64. package/src/fusion-fragment/FieldRenderer.tsx +173 -174
  65. package/src/fusion-fragment/FusionFragmentContext.tsx +31 -37
  66. package/src/fusion-fragment/FusionFragmentHandler.tsx +214 -223
  67. package/src/fusion-fragment/FusionFragmentRenderer.tsx +102 -107
  68. package/src/fusion-fragment/SectionRenderer.tsx +174 -169
  69. package/src/fusion-fragment/TableRenderer.tsx +175 -171
  70. package/src/fusion-fragment/index.ts +11 -11
  71. package/src/index.ts +42 -45
  72. package/src/render/index.ts +3 -3
  73. package/src/render/textPreview.ts +183 -186
  74. package/src/types.ts +174 -174
  75. package/src/validation/formatErrors.ts +86 -86
  76. package/src/validation/fuzzyMatch.ts +69 -77
  77. package/src/validation/index.ts +3 -3
  78. package/src/validation/schemas.ts +120 -120
  79. package/src/validation/validateTemplate.ts +225 -226
  80. package/lib/esm/fusion-fragment/ChartRenderer.js.map +0 -1
  81. package/lib/esm/fusion-fragment/FieldRenderer.js.map +0 -1
  82. package/lib/esm/fusion-fragment/FusionFragmentContext.js.map +0 -1
  83. package/lib/esm/fusion-fragment/FusionFragmentHandler.js.map +0 -1
  84. package/lib/esm/fusion-fragment/FusionFragmentRenderer.js.map +0 -1
  85. package/lib/esm/fusion-fragment/SectionRenderer.js.map +0 -1
  86. package/lib/esm/fusion-fragment/TableRenderer.js.map +0 -1
  87. package/lib/esm/fusion-fragment/index.js.map +0 -1
  88. package/lib/esm/index.js.map +0 -1
  89. package/lib/esm/render/index.js.map +0 -1
  90. package/lib/esm/render/textPreview.js.map +0 -1
  91. package/lib/esm/types.js.map +0 -1
  92. package/lib/esm/validation/formatErrors.js.map +0 -1
  93. package/lib/esm/validation/fuzzyMatch.js.map +0 -1
  94. package/lib/esm/validation/index.js +0 -8
  95. package/lib/esm/validation/index.js.map +0 -1
  96. package/lib/esm/validation/schemas.js.map +0 -1
  97. package/lib/esm/validation/validateTemplate.js.map +0 -1
  98. package/lib/tsconfig.tsbuildinfo +0 -1
  99. package/lib/types/fusion-fragment/ChartRenderer.d.ts.map +0 -1
  100. package/lib/types/fusion-fragment/FieldRenderer.d.ts.map +0 -1
  101. package/lib/types/fusion-fragment/FusionFragmentContext.d.ts.map +0 -1
  102. package/lib/types/fusion-fragment/FusionFragmentHandler.d.ts.map +0 -1
  103. package/lib/types/fusion-fragment/FusionFragmentRenderer.d.ts.map +0 -1
  104. package/lib/types/fusion-fragment/SectionRenderer.d.ts.map +0 -1
  105. package/lib/types/fusion-fragment/TableRenderer.d.ts.map +0 -1
  106. package/lib/types/fusion-fragment/index.d.ts.map +0 -1
  107. package/lib/types/index.d.ts.map +0 -1
  108. package/lib/types/render/index.d.ts.map +0 -1
  109. package/lib/types/render/textPreview.d.ts.map +0 -1
  110. package/lib/types/types.d.ts.map +0 -1
  111. package/lib/types/validation/formatErrors.d.ts.map +0 -1
  112. package/lib/types/validation/fuzzyMatch.d.ts.map +0 -1
  113. package/lib/types/validation/index.d.ts +0 -8
  114. package/lib/types/validation/index.d.ts.map +0 -1
  115. package/lib/types/validation/schemas.d.ts.map +0 -1
  116. package/lib/types/validation/validateTemplate.d.ts.map +0 -1
  117. /package/lib/{types/fusion-fragment → fusion-fragment}/ChartRenderer.d.ts +0 -0
  118. /package/lib/{types/fusion-fragment → fusion-fragment}/FusionFragmentHandler.d.ts +0 -0
  119. /package/lib/{types/fusion-fragment → fusion-fragment}/FusionFragmentRenderer.d.ts +0 -0
  120. /package/lib/{types/fusion-fragment → fusion-fragment}/TableRenderer.d.ts +0 -0
  121. /package/lib/{types/render → render}/textPreview.d.ts +0 -0
  122. /package/lib/{types/types.d.ts → types.d.ts} +0 -0
  123. /package/lib/{esm/types.js → types.js} +0 -0
  124. /package/lib/{types/validation → validation}/formatErrors.d.ts +0 -0
  125. /package/lib/{types/validation → validation}/fuzzyMatch.d.ts +0 -0
  126. /package/lib/{types/validation → validation}/validateTemplate.d.ts +0 -0
@@ -3,229 +3,226 @@
3
3
  * Generates a text description of what the fragment will look like
4
4
  */
5
5
 
6
- import type { FragmentTemplate, FieldTemplate } from '../types.js';
6
+ import type { FieldTemplate, FragmentTemplate } from '../types.js';
7
7
 
8
8
  /**
9
9
  * Generate sample data for preview rendering
10
10
  * Creates placeholder values based on field definitions
11
11
  */
12
- export function generateSampleData(
13
- template: FragmentTemplate,
14
- dataKeys: string[]
15
- ): Record<string, unknown> {
16
- const data: Record<string, unknown> = {};
17
-
18
- // Add provided data keys with placeholder values
19
- for (const key of dataKeys) {
20
- data[key] = `<${key}>`;
21
- }
22
-
23
- // Override with more specific placeholders based on field format
24
- for (const section of template.sections) {
25
- if (section.fields) {
26
- for (const field of section.fields) {
27
- if (field.key in data) {
28
- data[field.key] = getSampleValue(field);
12
+ export function generateSampleData(template: FragmentTemplate, dataKeys: string[]): Record<string, unknown> {
13
+ const data: Record<string, unknown> = {};
14
+
15
+ // Add provided data keys with placeholder values
16
+ for (const key of dataKeys) {
17
+ data[key] = `<${key}>`;
18
+ }
19
+
20
+ // Override with more specific placeholders based on field format
21
+ for (const section of template.sections) {
22
+ if (section.fields) {
23
+ for (const field of section.fields) {
24
+ if (field.key in data) {
25
+ data[field.key] = getSampleValue(field);
26
+ }
27
+ }
29
28
  }
30
- }
31
29
  }
32
- }
33
30
 
34
- return data;
31
+ return data;
35
32
  }
36
33
 
37
34
  /**
38
35
  * Get a sample value for a field based on its format
39
36
  */
40
37
  function getSampleValue(field: FieldTemplate): unknown {
41
- switch (field.format) {
42
- case 'number':
43
- return 1234;
44
- case 'currency':
45
- return 1000000;
46
- case 'percent':
47
- return 25;
48
- case 'date':
49
- return new Date().toISOString().split('T')[0];
50
- case 'boolean':
51
- return true;
52
- case 'text':
53
- default:
54
- return `Sample ${field.label}`;
55
- }
38
+ switch (field.format) {
39
+ case 'number':
40
+ return 1234;
41
+ case 'currency':
42
+ return 1000000;
43
+ case 'percent':
44
+ return 25;
45
+ case 'date':
46
+ return new Date().toISOString().split('T')[0];
47
+ case 'boolean':
48
+ return true;
49
+ default:
50
+ return `Sample ${field.label}`;
51
+ }
56
52
  }
57
53
 
58
54
  /**
59
55
  * Generate a text description of the template for preview
60
56
  * Used for non-vision models
61
57
  */
62
- export function generateTextPreview(
63
- template: FragmentTemplate,
64
- dataKeys: string[]
65
- ): string {
66
- const lines: string[] = [];
58
+ export function generateTextPreview(template: FragmentTemplate, dataKeys: string[]): string {
59
+ const lines: string[] = [];
67
60
 
68
- lines.push('Template structure preview:');
69
- lines.push('');
70
-
71
- if (template.title) {
72
- lines.push(`## ${template.title}`);
61
+ lines.push('Template structure preview:');
73
62
  lines.push('');
74
- }
75
-
76
- for (const section of template.sections) {
77
- const layout = section.layout || 'grid-3';
78
-
79
- lines.push(`### ${section.title}`);
80
-
81
- if (layout === 'table') {
82
- lines.push(`Layout: table`);
83
- if (section.dataKey) {
84
- lines.push(`Data key: \`${section.dataKey}\``);
85
- }
86
- lines.push('');
87
-
88
- if (section.columns) {
89
- lines.push('Columns:');
90
- for (const col of section.columns) {
91
- let colLine = `- **${col.header}** \u2192 \`${col.key}\``;
92
- if (col.format && col.format !== 'text') {
93
- colLine += ` (${col.format})`;
94
- }
95
- lines.push(colLine);
96
- }
97
- }
98
- } else if (layout === 'chart') {
99
- lines.push(`Layout: chart`);
100
- if (section.chart) {
101
- const chart = section.chart;
102
- if (chart.title) {
103
- lines.push(`Chart title: ${chart.title}`);
104
- }
105
- if (chart.description) {
106
- lines.push(`Description: ${chart.description}`);
107
- }
108
63
 
109
- const markType = chart.spec.mark
110
- ? (typeof chart.spec.mark === 'string' ? chart.spec.mark : (chart.spec.mark as { type?: string }).type || 'unknown')
111
- : 'composite';
112
- lines.push(`Chart type: ${markType}`);
113
-
114
- if (chart.dataKey) {
115
- lines.push(`Data key: \`${chart.dataKey}\``);
116
- if (!dataKeys.includes(chart.dataKey)) {
117
- lines.push('\u26a0\ufe0f **dataKey not found in data**');
118
- }
119
- } else if (chart.spec.data?.values) {
120
- lines.push(`Inline data: ${(chart.spec.data.values as unknown[]).length} points`);
121
- }
64
+ if (template.title) {
65
+ lines.push(`## ${template.title}`);
66
+ lines.push('');
67
+ }
122
68
 
123
- if (chart.height) {
124
- lines.push(`Height: ${chart.height}px`);
69
+ for (const section of template.sections) {
70
+ const layout = section.layout || 'grid-3';
71
+
72
+ lines.push(`### ${section.title}`);
73
+
74
+ if (layout === 'table') {
75
+ lines.push(`Layout: table`);
76
+ if (section.dataKey) {
77
+ lines.push(`Data key: \`${section.dataKey}\``);
78
+ }
79
+ lines.push('');
80
+
81
+ if (section.columns) {
82
+ lines.push('Columns:');
83
+ for (const col of section.columns) {
84
+ let colLine = `- **${col.header}** \u2192 \`${col.key}\``;
85
+ if (col.format && col.format !== 'text') {
86
+ colLine += ` (${col.format})`;
87
+ }
88
+ lines.push(colLine);
89
+ }
90
+ }
91
+ } else if (layout === 'chart') {
92
+ lines.push(`Layout: chart`);
93
+ if (section.chart) {
94
+ const chart = section.chart;
95
+ if (chart.title) {
96
+ lines.push(`Chart title: ${chart.title}`);
97
+ }
98
+ if (chart.description) {
99
+ lines.push(`Description: ${chart.description}`);
100
+ }
101
+
102
+ const markType = chart.spec.mark
103
+ ? typeof chart.spec.mark === 'string'
104
+ ? chart.spec.mark
105
+ : (chart.spec.mark as { type?: string }).type || 'unknown'
106
+ : 'composite';
107
+ lines.push(`Chart type: ${markType}`);
108
+
109
+ if (chart.dataKey) {
110
+ lines.push(`Data key: \`${chart.dataKey}\``);
111
+ if (!dataKeys.includes(chart.dataKey)) {
112
+ lines.push('\u26a0\ufe0f **dataKey not found in data**');
113
+ }
114
+ } else if (chart.spec.data?.values) {
115
+ lines.push(`Inline data: ${(chart.spec.data.values as unknown[]).length} points`);
116
+ }
117
+
118
+ if (chart.height) {
119
+ lines.push(`Height: ${chart.height}px`);
120
+ }
121
+ }
122
+ lines.push('');
123
+ } else {
124
+ const layoutDesc = layout === 'list' ? 'vertical list' : `${layout.split('-')[1]}-column grid`;
125
+ lines.push(`Layout: ${layoutDesc}${section.collapsed ? ' (collapsed by default)' : ''}`);
126
+ lines.push('');
127
+
128
+ if (section.fields) {
129
+ for (const field of section.fields) {
130
+ let fieldLine = `- **${field.label}** \u2192 \`${field.key}\``;
131
+
132
+ const attributes: string[] = [];
133
+ if (field.format && field.format !== 'text') {
134
+ attributes.push(field.format);
135
+ }
136
+ if (field.unit) {
137
+ attributes.push(`unit: "${field.unit}"`);
138
+ }
139
+ if (field.editable) {
140
+ attributes.push('editable');
141
+ }
142
+ if (field.highlight) {
143
+ attributes.push(`highlight: ${field.highlight}`);
144
+ }
145
+
146
+ if (attributes.length > 0) {
147
+ fieldLine += ` (${attributes.join(', ')})`;
148
+ }
149
+
150
+ // Check if key exists in data
151
+ if (!dataKeys.includes(field.key)) {
152
+ fieldLine += ' \u26a0\ufe0f **key not found in data**';
153
+ }
154
+
155
+ lines.push(fieldLine);
156
+ }
157
+ }
125
158
  }
126
- }
127
- lines.push('');
128
- } else {
129
- const layoutDesc = layout === 'list' ? 'vertical list' : `${layout.split('-')[1]}-column grid`;
130
- lines.push(`Layout: ${layoutDesc}${section.collapsed ? ' (collapsed by default)' : ''}`);
131
- lines.push('');
132
-
133
- if (section.fields) {
134
- for (const field of section.fields) {
135
- let fieldLine = `- **${field.label}** \u2192 \`${field.key}\``;
136
-
137
- const attributes: string[] = [];
138
- if (field.format && field.format !== 'text') {
139
- attributes.push(field.format);
140
- }
141
- if (field.unit) {
142
- attributes.push(`unit: "${field.unit}"`);
143
- }
144
- if (field.editable) {
145
- attributes.push('editable');
146
- }
147
- if (field.highlight) {
148
- attributes.push(`highlight: ${field.highlight}`);
149
- }
150
-
151
- if (attributes.length > 0) {
152
- fieldLine += ` (${attributes.join(', ')})`;
153
- }
154
-
155
- // Check if key exists in data
156
- if (!dataKeys.includes(field.key)) {
157
- fieldLine += ' \u26a0\ufe0f **key not found in data**';
158
- }
159
-
160
- lines.push(fieldLine);
161
- }
162
- }
159
+
160
+ lines.push('');
163
161
  }
164
162
 
165
- lines.push('');
166
- }
163
+ if (template.footer) {
164
+ lines.push('---');
165
+ lines.push(`Footer: ${template.footer}`);
166
+ lines.push('');
167
+ }
168
+
169
+ // Summary
170
+ const totalFields = template.sections.reduce(
171
+ (sum, s) => sum + (s.fields?.length || 0) + (s.columns?.length || 0),
172
+ 0,
173
+ );
174
+ const missingKeys = template.sections
175
+ .flatMap((s) => s.fields || [])
176
+ .filter((f) => !dataKeys.includes(f.key))
177
+ .map((f) => f.key);
167
178
 
168
- if (template.footer) {
169
179
  lines.push('---');
170
- lines.push(`Footer: ${template.footer}`);
171
- lines.push('');
172
- }
173
-
174
- // Summary
175
- const totalFields = template.sections.reduce(
176
- (sum, s) => sum + (s.fields?.length || 0) + (s.columns?.length || 0),
177
- 0
178
- );
179
- const missingKeys = template.sections
180
- .flatMap(s => s.fields || [])
181
- .filter(f => !dataKeys.includes(f.key))
182
- .map(f => f.key);
183
-
184
- lines.push('---');
185
- lines.push(`Summary: ${template.sections.length} section(s), ${totalFields} field(s)/column(s)`);
186
-
187
- if (missingKeys.length > 0) {
188
- lines.push(`\u26a0\ufe0f Missing keys: ${missingKeys.join(', ')}`);
189
- } else {
190
- lines.push('\u2705 All field keys found in data');
191
- }
192
-
193
- return lines.join('\n');
180
+ lines.push(`Summary: ${template.sections.length} section(s), ${totalFields} field(s)/column(s)`);
181
+
182
+ if (missingKeys.length > 0) {
183
+ lines.push(`\u26a0\ufe0f Missing keys: ${missingKeys.join(', ')}`);
184
+ } else {
185
+ lines.push('\u2705 All field keys found in data');
186
+ }
187
+
188
+ return lines.join('\n');
194
189
  }
195
190
 
196
191
  /**
197
192
  * Generate a compact description for tool responses
198
193
  */
199
194
  export function generateCompactPreview(template: FragmentTemplate): string {
200
- const sections = template.sections.map(s => {
201
- if (s.layout === 'table' && s.columns) {
202
- const colList = s.columns
203
- .slice(0, 3)
204
- .map(c => c.header)
205
- .join(', ');
206
- const more = s.columns.length > 3 ? `, +${s.columns.length - 3} more` : '';
207
- return `${s.title} (table): ${colList}${more}`;
208
- }
195
+ const sections = template.sections.map((s) => {
196
+ if (s.layout === 'table' && s.columns) {
197
+ const colList = s.columns
198
+ .slice(0, 3)
199
+ .map((c) => c.header)
200
+ .join(', ');
201
+ const more = s.columns.length > 3 ? `, +${s.columns.length - 3} more` : '';
202
+ return `${s.title} (table): ${colList}${more}`;
203
+ }
209
204
 
210
- if (s.layout === 'chart' && s.chart) {
211
- const markType = s.chart.spec.mark
212
- ? (typeof s.chart.spec.mark === 'string' ? s.chart.spec.mark : (s.chart.spec.mark as { type?: string }).type || 'chart')
213
- : 'chart';
214
- return `${s.title} (${markType} chart)`;
215
- }
205
+ if (s.layout === 'chart' && s.chart) {
206
+ const markType = s.chart.spec.mark
207
+ ? typeof s.chart.spec.mark === 'string'
208
+ ? s.chart.spec.mark
209
+ : (s.chart.spec.mark as { type?: string }).type || 'chart'
210
+ : 'chart';
211
+ return `${s.title} (${markType} chart)`;
212
+ }
216
213
 
217
- if (s.fields) {
218
- const fieldList = s.fields
219
- .slice(0, 3)
220
- .map(f => f.label)
221
- .join(', ');
222
- const more = s.fields.length > 3 ? `, +${s.fields.length - 3} more` : '';
223
- return `${s.title}: ${fieldList}${more}`;
224
- }
214
+ if (s.fields) {
215
+ const fieldList = s.fields
216
+ .slice(0, 3)
217
+ .map((f) => f.label)
218
+ .join(', ');
219
+ const more = s.fields.length > 3 ? `, +${s.fields.length - 3} more` : '';
220
+ return `${s.title}: ${fieldList}${more}`;
221
+ }
225
222
 
226
- return s.title;
227
- });
223
+ return s.title;
224
+ });
228
225
 
229
- const title = template.title ? `"${template.title}" - ` : '';
230
- return `${title}${sections.join(' | ')}`;
226
+ const title = template.title ? `"${template.title}" - ` : '';
227
+ return `${title}${sections.join(' | ')}`;
231
228
  }