@vertesia/fusion-ux 1.3.0 → 1.4.0-dev.20260615.042033Z

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
@@ -7,31 +7,31 @@
7
7
  * Calculate Levenshtein distance between two strings
8
8
  */
9
9
  export function levenshteinDistance(a: string, b: string): number {
10
- const matrix: number[][] = [];
11
-
12
- // Initialize first column
13
- for (let i = 0; i <= a.length; i++) {
14
- matrix[i] = [i];
15
- }
16
-
17
- // Initialize first row
18
- for (let j = 0; j <= b.length; j++) {
19
- matrix[0][j] = j;
20
- }
21
-
22
- // Fill in the rest of the matrix
23
- for (let i = 1; i <= a.length; i++) {
24
- for (let j = 1; j <= b.length; j++) {
25
- const cost = a[i - 1] === b[j - 1] ? 0 : 1;
26
- matrix[i][j] = Math.min(
27
- matrix[i - 1][j] + 1, // deletion
28
- matrix[i][j - 1] + 1, // insertion
29
- matrix[i - 1][j - 1] + cost // substitution
30
- );
10
+ const matrix: number[][] = [];
11
+
12
+ // Initialize first column
13
+ for (let i = 0; i <= a.length; i++) {
14
+ matrix[i] = [i];
15
+ }
16
+
17
+ // Initialize first row
18
+ for (let j = 0; j <= b.length; j++) {
19
+ matrix[0][j] = j;
31
20
  }
32
- }
33
21
 
34
- return matrix[a.length][b.length];
22
+ // Fill in the rest of the matrix
23
+ for (let i = 1; i <= a.length; i++) {
24
+ for (let j = 1; j <= b.length; j++) {
25
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
26
+ matrix[i][j] = Math.min(
27
+ matrix[i - 1][j] + 1, // deletion
28
+ matrix[i][j - 1] + 1, // insertion
29
+ matrix[i - 1][j - 1] + cost, // substitution
30
+ );
31
+ }
32
+ }
33
+
34
+ return matrix[a.length][b.length];
35
35
  }
36
36
 
37
37
  /**
@@ -41,44 +41,40 @@ export function levenshteinDistance(a: string, b: string): number {
41
41
  * @param maxDistance - Maximum edit distance to consider (default: 3)
42
42
  * @returns The closest key, or undefined if none are close enough
43
43
  */
44
- export function findClosestKey(
45
- input: string,
46
- validKeys: string[],
47
- maxDistance: number = 3
48
- ): string | undefined {
49
- if (validKeys.length === 0) return undefined;
50
-
51
- const inputLower = input.toLowerCase();
52
- let bestMatch: string | undefined;
53
- let bestDistance = Infinity;
54
-
55
- for (const key of validKeys) {
56
- const keyLower = key.toLowerCase();
57
-
58
- // Exact case-insensitive match
59
- if (inputLower === keyLower) {
60
- return key;
61
- }
62
-
63
- // Check if input is a substring or key is a substring
64
- if (inputLower.includes(keyLower) || keyLower.includes(inputLower)) {
65
- const distance = Math.abs(inputLower.length - keyLower.length);
66
- if (distance < bestDistance) {
67
- bestDistance = distance;
68
- bestMatch = key;
69
- }
70
- continue;
71
- }
72
-
73
- // Levenshtein distance
74
- const distance = levenshteinDistance(inputLower, keyLower);
75
- if (distance < bestDistance && distance <= maxDistance) {
76
- bestDistance = distance;
77
- bestMatch = key;
44
+ export function findClosestKey(input: string, validKeys: string[], maxDistance: number = 3): string | undefined {
45
+ if (validKeys.length === 0) return undefined;
46
+
47
+ const inputLower = input.toLowerCase();
48
+ let bestMatch: string | undefined;
49
+ let bestDistance = Infinity;
50
+
51
+ for (const key of validKeys) {
52
+ const keyLower = key.toLowerCase();
53
+
54
+ // Exact case-insensitive match
55
+ if (inputLower === keyLower) {
56
+ return key;
57
+ }
58
+
59
+ // Check if input is a substring or key is a substring
60
+ if (inputLower.includes(keyLower) || keyLower.includes(inputLower)) {
61
+ const distance = Math.abs(inputLower.length - keyLower.length);
62
+ if (distance < bestDistance) {
63
+ bestDistance = distance;
64
+ bestMatch = key;
65
+ }
66
+ continue;
67
+ }
68
+
69
+ // Levenshtein distance
70
+ const distance = levenshteinDistance(inputLower, keyLower);
71
+ if (distance < bestDistance && distance <= maxDistance) {
72
+ bestDistance = distance;
73
+ bestMatch = key;
74
+ }
78
75
  }
79
- }
80
76
 
81
- return bestMatch;
77
+ return bestMatch;
82
78
  }
83
79
 
84
80
  /**
@@ -88,22 +84,18 @@ export function findClosestKey(
88
84
  * @param maxResults - Maximum number of suggestions (default: 3)
89
85
  * @returns Array of similar keys
90
86
  */
91
- export function findSimilarKeys(
92
- input: string,
93
- validKeys: string[],
94
- maxResults: number = 3
95
- ): string[] {
96
- if (validKeys.length === 0) return [];
97
-
98
- const inputLower = input.toLowerCase();
99
-
100
- const scored = validKeys
101
- .map(key => ({
102
- key,
103
- distance: levenshteinDistance(inputLower, key.toLowerCase())
104
- }))
105
- .filter(({ distance }) => distance <= 4) // Filter out very different keys
106
- .sort((a, b) => a.distance - b.distance);
107
-
108
- return scored.slice(0, maxResults).map(({ key }) => key);
87
+ export function findSimilarKeys(input: string, validKeys: string[], maxResults: number = 3): string[] {
88
+ if (validKeys.length === 0) return [];
89
+
90
+ const inputLower = input.toLowerCase();
91
+
92
+ const scored = validKeys
93
+ .map((key) => ({
94
+ key,
95
+ distance: levenshteinDistance(inputLower, key.toLowerCase()),
96
+ }))
97
+ .filter(({ distance }) => distance <= 4) // Filter out very different keys
98
+ .sort((a, b) => a.distance - b.distance);
99
+
100
+ return scored.slice(0, maxResults).map(({ key }) => key);
109
101
  }
@@ -2,7 +2,7 @@
2
2
  * Validation module exports
3
3
  */
4
4
 
5
- export { validateTemplate, parseAndValidateTemplate } from './validateTemplate.js';
6
- export { FragmentTemplateSchema, SectionTemplateSchema, FieldTemplateSchema } from './schemas.js';
5
+ export { formatAvailableKeys, formatValidationErrors, formatValidationSuccess } from './formatErrors.js';
7
6
  export { findClosestKey, findSimilarKeys, levenshteinDistance } from './fuzzyMatch.js';
8
- export { formatValidationErrors, formatValidationSuccess, formatAvailableKeys } from './formatErrors.js';
7
+ export { FieldTemplateSchema, FragmentTemplateSchema, SectionTemplateSchema } from './schemas.js';
8
+ export { parseAndValidateTemplate, validateTemplate } from './validateTemplate.js';
@@ -3,90 +3,90 @@
3
3
  */
4
4
 
5
5
  import type { JSONSchemaType } from 'ajv';
6
- import type { FieldTemplate, SectionTemplate, FragmentTemplate, ColumnTemplate } from '../types.js';
6
+ import type { ColumnTemplate, FieldTemplate, FragmentTemplate, SectionTemplate } from '../types.js';
7
7
 
8
8
  /**
9
9
  * Schema for field options (select dropdowns)
10
10
  */
11
11
  const FieldOptionSchema = {
12
- type: 'object' as const,
13
- properties: {
14
- label: { type: 'string' as const },
15
- value: { type: 'string' as const }
16
- },
17
- required: ['label', 'value'] as const,
18
- additionalProperties: false
12
+ type: 'object' as const,
13
+ properties: {
14
+ label: { type: 'string' as const },
15
+ value: { type: 'string' as const },
16
+ },
17
+ required: ['label', 'value'] as const,
18
+ additionalProperties: false,
19
19
  };
20
20
 
21
21
  /**
22
22
  * Schema for a single field template
23
23
  */
24
24
  export const FieldTemplateSchema: JSONSchemaType<FieldTemplate> = {
25
- type: 'object',
26
- properties: {
27
- label: { type: 'string' },
28
- key: { type: 'string' },
29
- format: {
30
- type: 'string',
31
- enum: ['text', 'number', 'currency', 'percent', 'date', 'boolean'],
32
- nullable: true
33
- },
34
- unit: { type: 'string', nullable: true },
35
- editable: { type: 'boolean', nullable: true },
36
- inputType: {
37
- type: 'string',
38
- enum: ['text', 'number', 'date', 'select', 'checkbox'],
39
- nullable: true
40
- },
41
- options: {
42
- type: 'array',
43
- items: FieldOptionSchema,
44
- nullable: true
25
+ type: 'object',
26
+ properties: {
27
+ label: { type: 'string' },
28
+ key: { type: 'string' },
29
+ format: {
30
+ type: 'string',
31
+ enum: ['text', 'number', 'currency', 'percent', 'date', 'boolean'],
32
+ nullable: true,
33
+ },
34
+ unit: { type: 'string', nullable: true },
35
+ editable: { type: 'boolean', nullable: true },
36
+ inputType: {
37
+ type: 'string',
38
+ enum: ['text', 'number', 'date', 'select', 'checkbox'],
39
+ nullable: true,
40
+ },
41
+ options: {
42
+ type: 'array',
43
+ items: FieldOptionSchema,
44
+ nullable: true,
45
+ },
46
+ min: { type: 'number', nullable: true },
47
+ max: { type: 'number', nullable: true },
48
+ highlight: {
49
+ type: 'string',
50
+ enum: ['success', 'warning', 'error', 'info'],
51
+ nullable: true,
52
+ },
53
+ tooltip: { type: 'string', nullable: true },
54
+ decimals: { type: 'number', nullable: true },
55
+ currency: { type: 'string', nullable: true },
45
56
  },
46
- min: { type: 'number', nullable: true },
47
- max: { type: 'number', nullable: true },
48
- highlight: {
49
- type: 'string',
50
- enum: ['success', 'warning', 'error', 'info'],
51
- nullable: true
52
- },
53
- tooltip: { type: 'string', nullable: true },
54
- decimals: { type: 'number', nullable: true },
55
- currency: { type: 'string', nullable: true }
56
- },
57
- required: ['label', 'key'],
58
- additionalProperties: false
57
+ required: ['label', 'key'],
58
+ additionalProperties: false,
59
59
  };
60
60
 
61
61
  /**
62
62
  * Schema for a table column template
63
63
  */
64
64
  export const ColumnTemplateSchema: JSONSchemaType<ColumnTemplate> = {
65
- type: 'object',
66
- properties: {
67
- header: { type: 'string' },
68
- key: { type: 'string' },
69
- format: {
70
- type: 'string',
71
- enum: ['text', 'number', 'currency', 'percent', 'date', 'boolean'],
72
- nullable: true
73
- },
74
- width: { type: 'string', nullable: true },
75
- align: {
76
- type: 'string',
77
- enum: ['left', 'center', 'right'],
78
- nullable: true
65
+ type: 'object',
66
+ properties: {
67
+ header: { type: 'string' },
68
+ key: { type: 'string' },
69
+ format: {
70
+ type: 'string',
71
+ enum: ['text', 'number', 'currency', 'percent', 'date', 'boolean'],
72
+ nullable: true,
73
+ },
74
+ width: { type: 'string', nullable: true },
75
+ align: {
76
+ type: 'string',
77
+ enum: ['left', 'center', 'right'],
78
+ nullable: true,
79
+ },
80
+ currency: { type: 'string', nullable: true },
81
+ decimals: { type: 'number', nullable: true },
82
+ highlight: {
83
+ type: 'string',
84
+ enum: ['success', 'warning', 'error', 'info'],
85
+ nullable: true,
86
+ },
79
87
  },
80
- currency: { type: 'string', nullable: true },
81
- decimals: { type: 'number', nullable: true },
82
- highlight: {
83
- type: 'string',
84
- enum: ['success', 'warning', 'error', 'info'],
85
- nullable: true
86
- }
87
- },
88
- required: ['header', 'key'],
89
- additionalProperties: false
88
+ required: ['header', 'key'],
89
+ additionalProperties: false,
90
90
  };
91
91
 
92
92
  /**
@@ -95,9 +95,9 @@ export const ColumnTemplateSchema: JSONSchemaType<ColumnTemplate> = {
95
95
  * Note: Using loose typing since VegaLiteSpec is intentionally flexible
96
96
  */
97
97
  export const VegaLiteSpecSchema = {
98
- type: 'object' as const,
99
- additionalProperties: true, // Allow any Vega-Lite properties
100
- // We don't enforce specific properties since Vega-Lite has many valid forms
98
+ type: 'object' as const,
99
+ additionalProperties: true, // Allow any Vega-Lite properties
100
+ // We don't enforce specific properties since Vega-Lite has many valid forms
101
101
  };
102
102
 
103
103
  /**
@@ -105,17 +105,17 @@ export const VegaLiteSpecSchema = {
105
105
  * Note: Using loose typing for spec since VegaLiteSpec is flexible
106
106
  */
107
107
  export const ChartTemplateSchema = {
108
- type: 'object' as const,
109
- properties: {
110
- title: { type: 'string' as const, nullable: true },
111
- description: { type: 'string' as const, nullable: true },
112
- spec: VegaLiteSpecSchema,
113
- height: { type: 'number' as const, nullable: true },
114
- width: { type: 'number' as const, nullable: true },
115
- dataKey: { type: 'string' as const, nullable: true }
116
- },
117
- required: ['spec'] as const,
118
- additionalProperties: false
108
+ type: 'object' as const,
109
+ properties: {
110
+ title: { type: 'string' as const, nullable: true },
111
+ description: { type: 'string' as const, nullable: true },
112
+ spec: VegaLiteSpecSchema,
113
+ height: { type: 'number' as const, nullable: true },
114
+ width: { type: 'number' as const, nullable: true },
115
+ dataKey: { type: 'string' as const, nullable: true },
116
+ },
117
+ required: ['spec'] as const,
118
+ additionalProperties: false,
119
119
  };
120
120
 
121
121
  /**
@@ -123,53 +123,53 @@ export const ChartTemplateSchema = {
123
123
  * Note: Using type assertion due to ChartTemplate's flexible VegaLiteSpec
124
124
  */
125
125
  export const SectionTemplateSchema = {
126
- type: 'object',
127
- properties: {
128
- title: { type: 'string' },
129
- layout: {
130
- type: 'string',
131
- enum: ['grid-2', 'grid-3', 'grid-4', 'list', 'table', 'chart'],
132
- nullable: true
133
- },
134
- collapsed: { type: 'boolean', nullable: true },
135
- fields: {
136
- type: 'array',
137
- items: FieldTemplateSchema,
138
- nullable: true
126
+ type: 'object',
127
+ properties: {
128
+ title: { type: 'string' },
129
+ layout: {
130
+ type: 'string',
131
+ enum: ['grid-2', 'grid-3', 'grid-4', 'list', 'table', 'chart'],
132
+ nullable: true,
133
+ },
134
+ collapsed: { type: 'boolean', nullable: true },
135
+ fields: {
136
+ type: 'array',
137
+ items: FieldTemplateSchema,
138
+ nullable: true,
139
+ },
140
+ columns: {
141
+ type: 'array',
142
+ items: ColumnTemplateSchema,
143
+ nullable: true,
144
+ },
145
+ dataKey: { type: 'string', nullable: true },
146
+ chart: {
147
+ ...ChartTemplateSchema,
148
+ nullable: true,
149
+ },
139
150
  },
140
- columns: {
141
- type: 'array',
142
- items: ColumnTemplateSchema,
143
- nullable: true
144
- },
145
- dataKey: { type: 'string', nullable: true },
146
- chart: {
147
- ...ChartTemplateSchema,
148
- nullable: true
149
- }
150
- },
151
- required: ['title'],
152
- additionalProperties: false
151
+ required: ['title'],
152
+ additionalProperties: false,
153
153
  } as JSONSchemaType<SectionTemplate>;
154
154
 
155
155
  /**
156
156
  * Schema for the root fragment template
157
157
  */
158
158
  export const FragmentTemplateSchema = {
159
- type: 'object',
160
- properties: {
161
- title: { type: 'string', nullable: true },
162
- entityType: {
163
- type: 'string',
164
- enum: ['fund', 'scenario', 'portfolio', 'transaction', 'custom'],
165
- nullable: true
166
- },
167
- sections: {
168
- type: 'array',
169
- items: SectionTemplateSchema
159
+ type: 'object',
160
+ properties: {
161
+ title: { type: 'string', nullable: true },
162
+ entityType: {
163
+ type: 'string',
164
+ enum: ['fund', 'scenario', 'portfolio', 'transaction', 'custom'],
165
+ nullable: true,
166
+ },
167
+ sections: {
168
+ type: 'array',
169
+ items: SectionTemplateSchema,
170
+ },
171
+ footer: { type: 'string', nullable: true },
170
172
  },
171
- footer: { type: 'string', nullable: true }
172
- },
173
- required: ['sections'],
174
- additionalProperties: false
173
+ required: ['sections'],
174
+ additionalProperties: false,
175
175
  } as JSONSchemaType<FragmentTemplate>;