@adecore/intelligent-ui 0.25.2 → 0.25.3

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/dist/catalog.d.ts CHANGED
@@ -91,6 +91,7 @@ export declare const UI_CATALOG: {
91
91
  value: z.ZodOptional<z.ZodNumber>;
92
92
  max: z.ZodOptional<z.ZodNumber>;
93
93
  }, z.core.$strict>;
94
+ readonly text: 'label';
94
95
  };
95
96
  readonly Steps: {
96
97
  readonly group: 'status';
@@ -112,6 +113,7 @@ export declare const UI_CATALOG: {
112
113
  detail: z.ZodOptional<z.ZodString>;
113
114
  }, z.core.$strict>;
114
115
  readonly parent: 'Steps';
116
+ readonly text: 'label';
115
117
  };
116
118
  readonly Timeline: {
117
119
  readonly group: 'status';
@@ -137,6 +139,7 @@ export declare const UI_CATALOG: {
137
139
  detail: z.ZodOptional<z.ZodString>;
138
140
  }, z.core.$strict>;
139
141
  readonly parent: 'Timeline';
142
+ readonly text: 'title';
140
143
  };
141
144
  readonly Stats: {
142
145
  readonly group: 'data';
@@ -175,6 +178,7 @@ export declare const UI_CATALOG: {
175
178
  label: z.ZodString;
176
179
  }, z.core.$strict>;
177
180
  readonly parent: 'EntityList';
181
+ readonly text: 'value';
178
182
  };
179
183
  readonly Table: {
180
184
  readonly group: 'data';
@@ -260,6 +264,8 @@ export declare const UI_CATALOG: {
260
264
  generated: z.ZodOptional<z.ZodLiteral<"latest">>;
261
265
  alt: z.ZodOptional<z.ZodString>;
262
266
  }, z.core.$strict>;
267
+ readonly needs: 'attachment|generated';
268
+ readonly text: 'caption';
263
269
  };
264
270
  readonly Gallery: {
265
271
  readonly group: 'content';
@@ -280,6 +286,7 @@ export declare const UI_CATALOG: {
280
286
  beforeLabel: z.ZodOptional<z.ZodString>;
281
287
  afterLabel: z.ZodOptional<z.ZodString>;
282
288
  }, z.core.$strict>;
289
+ readonly text: 'caption';
283
290
  };
284
291
  readonly Map: {
285
292
  readonly group: 'places';
@@ -305,6 +312,8 @@ export declare const UI_CATALOG: {
305
312
  value: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>>;
306
313
  }, z.core.$strict>;
307
314
  readonly parent: 'Map';
315
+ readonly needs: 'lat lon|address';
316
+ readonly text: 'name';
308
317
  };
309
318
  readonly Sources: {
310
319
  readonly group: 'content';
@@ -366,6 +375,7 @@ export declare const UI_CATALOG: {
366
375
  value: z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>;
367
376
  }, z.core.$strict>;
368
377
  readonly parent: 'Checklist';
378
+ readonly text: 'label';
369
379
  };
370
380
  readonly Switch: {
371
381
  readonly group: 'inputs';
@@ -374,6 +384,7 @@ export declare const UI_CATALOG: {
374
384
  value: z.ZodBoolean;
375
385
  }, z.core.$strict>;
376
386
  readonly binding: 'value';
387
+ readonly text: 'label';
377
388
  };
378
389
  readonly Slider: {
379
390
  readonly group: 'inputs';
@@ -386,6 +397,7 @@ export declare const UI_CATALOG: {
386
397
  unit: z.ZodOptional<z.ZodString>;
387
398
  }, z.core.$strict>;
388
399
  readonly binding: 'value';
400
+ readonly text: 'label';
389
401
  };
390
402
  readonly Segmented: {
391
403
  readonly group: 'inputs';
@@ -404,6 +416,7 @@ export declare const UI_CATALOG: {
404
416
  }, z.core.$strict>;
405
417
  readonly children: readonly ['Option'];
406
418
  readonly binding: 'value';
419
+ readonly text: 'label';
407
420
  };
408
421
  readonly Option: {
409
422
  readonly group: 'inputs';
@@ -412,6 +425,7 @@ export declare const UI_CATALOG: {
412
425
  value: z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>;
413
426
  }, z.core.$strict>;
414
427
  readonly parent: readonly ['Segmented', 'Select'];
428
+ readonly text: 'label';
415
429
  };
416
430
  readonly TextField: {
417
431
  readonly group: 'inputs';
@@ -422,6 +436,7 @@ export declare const UI_CATALOG: {
422
436
  placeholder: z.ZodOptional<z.ZodString>;
423
437
  }, z.core.$strict>;
424
438
  readonly binding: 'value';
439
+ readonly text: 'label';
425
440
  };
426
441
  readonly Button: {
427
442
  readonly group: 'inputs';
@@ -430,6 +445,7 @@ export declare const UI_CATALOG: {
430
445
  disabled: z.ZodOptional<z.ZodBoolean>;
431
446
  }, z.core.$strict>;
432
447
  readonly action: 'action';
448
+ readonly text: 'label';
433
449
  };
434
450
  readonly Show: {
435
451
  readonly group: 'inputs';
@@ -461,6 +477,7 @@ export declare const UI_CATALOG: {
461
477
  disabled: z.ZodOptional<z.ZodBoolean>;
462
478
  }, z.core.$strict>;
463
479
  readonly parent: 'Choices';
480
+ readonly text: 'label';
464
481
  };
465
482
  };
466
483
  export type UiGroupName = keyof typeof UI_GROUPS;
package/dist/catalog.js CHANGED
@@ -38,14 +38,16 @@ export const UI_CATALOG = {
38
38
  Progress: {
39
39
  group: 'status',
40
40
  description: 'Progress with a label; omit value for indeterminate progress.',
41
- schema: z.strictObject({ value: number.nonnegative().optional(), max: number.positive().optional() })
41
+ schema: z.strictObject({ value: number.nonnegative().optional(), max: number.positive().optional() }),
42
+ text: 'label'
42
43
  },
43
44
  Steps: { group: 'status', description: 'An ordered sequence of steps.', schema: empty, children: ['Step'] },
44
45
  Step: {
45
46
  group: 'status',
46
47
  description: 'One step in a sequence.',
47
48
  schema: z.strictObject({ state: z.enum(['done', 'running', 'pending', 'failed', 'skipped']), detail: text.optional() }),
48
- parent: 'Steps'
49
+ parent: 'Steps',
50
+ text: 'label'
49
51
  },
50
52
  Timeline: { group: 'status', description: 'Events in time order.', schema: empty, children: ['Event'], count: { min: 1 } },
51
53
  Event: {
@@ -56,7 +58,8 @@ export const UI_CATALOG = {
56
58
  tone,
57
59
  detail: text.optional()
58
60
  }),
59
- parent: 'Timeline'
61
+ parent: 'Timeline',
62
+ text: 'title'
60
63
  },
61
64
  Stats: { group: 'data', description: 'A small set of key numbers.', schema: empty, children: ['Stat'] },
62
65
  Stat: {
@@ -66,7 +69,7 @@ export const UI_CATALOG = {
66
69
  parent: 'Stats'
67
70
  },
68
71
  EntityList: { group: 'data', description: 'Labeled facts about an entity.', schema: empty, children: ['Entry'] },
69
- Entry: { group: 'data', description: 'One labeled fact.', schema: z.strictObject({ label: text }), parent: 'EntityList' },
72
+ Entry: { group: 'data', description: 'One labeled fact.', schema: z.strictObject({ label: text }), parent: 'EntityList', text: 'value' },
70
73
  Table: { group: 'data', description: 'Rows with named columns.', schema: z.strictObject({ rows }), children: ['Column'] },
71
74
  Column: {
72
75
  group: 'data',
@@ -98,13 +101,16 @@ export const UI_CATALOG = {
98
101
  description: 'A chat attachment with an optional caption.',
99
102
  schema: z
100
103
  .strictObject({ attachment: name.optional(), generated: z.literal('latest').optional(), alt: text.optional() })
101
- .refine((props) => Boolean(props.attachment) !== Boolean(props.generated), 'Choose attachment or generated, exclusively.')
104
+ .refine((props) => Boolean(props.attachment) !== Boolean(props.generated), 'Choose attachment or generated, exclusively.'),
105
+ needs: 'attachment|generated',
106
+ text: 'caption'
102
107
  },
103
108
  Gallery: { group: 'content', description: 'A grid of images with captions; at most 24.', schema: empty, children: ['Image'], count: { min: 1, max: 24 } },
104
109
  Compare: {
105
110
  group: 'content',
106
111
  description: 'Two chat attachments in one frame with a handle to wipe between them; children are the caption.',
107
- schema: z.strictObject({ before: name, after: name, beforeLabel: text.optional(), afterLabel: text.optional() })
112
+ schema: z.strictObject({ before: name, after: name, beforeLabel: text.optional(), afterLabel: text.optional() }),
113
+ text: 'caption'
108
114
  },
109
115
  Map: {
110
116
  group: 'places',
@@ -126,7 +132,9 @@ export const UI_CATALOG = {
126
132
  value: scalar.optional()
127
133
  })
128
134
  .refine((props) => (props.lat === undefined) === (props.lon === undefined) && (props.lat !== undefined || props.address !== undefined), 'Give lat with lon, or an address.'),
129
- parent: 'Map'
135
+ parent: 'Map',
136
+ needs: 'lat lon|address',
137
+ text: 'name'
130
138
  },
131
139
  Sources: { group: 'content', description: 'Numbered sources without preloading.', schema: empty, children: ['Source'] },
132
140
  Source: {
@@ -150,15 +158,16 @@ export const UI_CATALOG = {
150
158
  children: ['Item'],
151
159
  binding: 'value'
152
160
  },
153
- Item: { group: 'inputs', description: 'One selectable value.', schema: z.strictObject({ value: scalar }), parent: 'Checklist' },
154
- Switch: { group: 'inputs', description: 'A local boolean.', schema: z.strictObject({ value: z.boolean() }), binding: 'value' },
161
+ Item: { group: 'inputs', description: 'One selectable value.', schema: z.strictObject({ value: scalar }), parent: 'Checklist', text: 'label' },
162
+ Switch: { group: 'inputs', description: 'A local boolean.', schema: z.strictObject({ value: z.boolean() }), binding: 'value', text: 'label' },
155
163
  Slider: {
156
164
  group: 'inputs',
157
165
  description: 'A local number in a range.',
158
166
  schema: z
159
167
  .strictObject({ value: number, min: number, max: number, step: number.positive().optional(), unit: text.optional() })
160
168
  .refine((props) => props.min < props.max && props.value >= props.min && props.value <= props.max, 'Value must lie within an increasing range.'),
161
- binding: 'value'
169
+ binding: 'value',
170
+ text: 'label'
162
171
  },
163
172
  Segmented: { group: 'inputs', description: 'Choose one local value.', schema: z.strictObject({ value: scalar }), children: ['Option'], binding: 'value' },
164
173
  Select: {
@@ -166,22 +175,31 @@ export const UI_CATALOG = {
166
175
  description: 'Choose one local value from a dropdown, for more or longer options than Segmented holds; the text beside its Options is its label.',
167
176
  schema: z.strictObject({ value: scalar }),
168
177
  children: ['Option'],
169
- binding: 'value'
178
+ binding: 'value',
179
+ text: 'label'
180
+ },
181
+ Option: {
182
+ group: 'inputs',
183
+ description: 'One local alternative.',
184
+ schema: z.strictObject({ value: scalar }),
185
+ parent: ['Segmented', 'Select'],
186
+ text: 'label'
170
187
  },
171
- Option: { group: 'inputs', description: 'One local alternative.', schema: z.strictObject({ value: scalar }), parent: ['Segmented', 'Select'] },
172
188
  TextField: {
173
189
  group: 'inputs',
174
190
  description: 'A line of local text up to maxLength characters (256 without one, at most 1024); children are the label.',
175
191
  schema: z
176
192
  .strictObject({ value: text, maxLength: z.number().int().min(1).max(1024).optional(), placeholder: text.max(128).optional() })
177
193
  .refine((props) => props.value.length <= (props.maxLength ?? 256), 'Value must not be longer than maxLength.'),
178
- binding: 'value'
194
+ binding: 'value',
195
+ text: 'label'
179
196
  },
180
197
  Button: {
181
198
  group: 'inputs',
182
199
  description: 'Run one local state action when pressed; children are the label.',
183
200
  schema: z.strictObject({ disabled: z.boolean().optional() }),
184
- action: 'action'
201
+ action: 'action',
202
+ text: 'label'
185
203
  },
186
204
  Show: { group: 'inputs', description: 'Show children when the condition is true.', schema: z.strictObject({ when: z.boolean() }) },
187
205
  Each: {
@@ -194,7 +212,8 @@ export const UI_CATALOG = {
194
212
  group: 'choices',
195
213
  description: 'Send its label and visible context once.',
196
214
  schema: z.strictObject({ context: text.optional(), primary: z.boolean().optional(), disabled: z.boolean().optional() }),
197
- parent: 'Choices'
215
+ parent: 'Choices',
216
+ text: 'label'
198
217
  }
199
218
  };
200
219
  export function isUiComponent(name) {
@@ -5,3 +5,11 @@ export declare function uiPropList(entry: {
5
5
  };
6
6
  readonly action?: string;
7
7
  }): string[];
8
+ export declare function uiRequirement(name: string, entry: {
9
+ readonly schema: {
10
+ readonly shape: Readonly<Record<string, z.ZodType>>;
11
+ };
12
+ readonly action?: string;
13
+ readonly needs?: string;
14
+ readonly text?: string;
15
+ }): string;
package/dist/prop-list.js CHANGED
@@ -3,3 +3,11 @@ export function uiPropList(entry) {
3
3
  const props = Object.entries(entry.schema.shape).map(([key, schema]) => `${key}${schema.isOptional() ? '?' : ''}`);
4
4
  return entry.action ? [entry.action, ...props] : props;
5
5
  }
6
+ /* What a component needs in the compact note: the props it cannot do without and, when its text is not the plain content, what that text is. */
7
+ export function uiRequirement(name, entry) {
8
+ const required = entry.needs ??
9
+ uiPropList(entry)
10
+ .filter((prop) => !prop.endsWith('?'))
11
+ .join(' ');
12
+ return `${name}${required ? ` ${required}` : ''}${entry.text ? ` (text: ${entry.text})` : ''}`;
13
+ }
package/dist/text.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { UI_CATALOG, UI_GROUPS } from './catalog.js';
2
- import { uiPropList } from './prop-list.js';
2
+ import { uiPropList, uiRequirement } from './prop-list.js';
3
3
  import { UI_FENCE_LANGUAGE } from './compiler.js';
4
4
  export function uiCompactCatalog() {
5
5
  return Object.entries(UI_CATALOG)
@@ -25,12 +25,12 @@ function uiExample(language) {
25
25
  function uiGroupComponents(group) {
26
26
  return Object.entries(UI_CATALOG).filter(([, entry]) => entry.group === group);
27
27
  }
28
- /* One line per group with the names of its components, for a host that hands the props out per group. */
28
+ /* One line per group with its components and what each needs, for a host that hands the optional props out per group. */
29
29
  function uiGroupNames(detailHint) {
30
30
  const lines = Object.keys(UI_GROUPS).map((group) => `${group}: ${uiGroupComponents(group)
31
- .map(([name]) => name)
31
+ .map(([name, entry]) => uiRequirement(name, entry))
32
32
  .join(', ')}`);
33
- return `Components by group${detailHint ? ` (${detailHint})` : ''}:\n${lines.join('\n')}`;
33
+ return `Components by group${detailHint ? ` (${detailHint})` : ''}, required props (text: words between the tags):\n${lines.join('\n')}`;
34
34
  }
35
35
  export function uiSessionNote({ fenceLanguage = UI_FENCE_LANGUAGE, catalog = 'props', detailHint } = {}) {
36
36
  const components = catalog === 'names' ? uiGroupNames(detailHint) : `Catalog (? means optional props): ${uiCompactCatalog()}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adecore/intelligent-ui",
3
- "version": "0.25.2",
3
+ "version": "0.25.3",
4
4
  "description": "A streaming UI catalog, compiler and bounded expression interpreter without a framework or DOM.",
5
5
  "license": "FSL-1.1-MIT",
6
6
  "author": "Bas Milius",
package/src/catalog.ts CHANGED
@@ -43,14 +43,16 @@ export const UI_CATALOG = {
43
43
  Progress: {
44
44
  group: 'status',
45
45
  description: 'Progress with a label; omit value for indeterminate progress.',
46
- schema: z.strictObject({ value: number.nonnegative().optional(), max: number.positive().optional() })
46
+ schema: z.strictObject({ value: number.nonnegative().optional(), max: number.positive().optional() }),
47
+ text: 'label'
47
48
  },
48
49
  Steps: { group: 'status', description: 'An ordered sequence of steps.', schema: empty, children: ['Step'] },
49
50
  Step: {
50
51
  group: 'status',
51
52
  description: 'One step in a sequence.',
52
53
  schema: z.strictObject({ state: z.enum(['done', 'running', 'pending', 'failed', 'skipped']), detail: text.optional() }),
53
- parent: 'Steps'
54
+ parent: 'Steps',
55
+ text: 'label'
54
56
  },
55
57
  Timeline: { group: 'status', description: 'Events in time order.', schema: empty, children: ['Event'], count: { min: 1 } },
56
58
  Event: {
@@ -62,7 +64,8 @@ export const UI_CATALOG = {
62
64
  tone,
63
65
  detail: text.optional()
64
66
  }),
65
- parent: 'Timeline'
67
+ parent: 'Timeline',
68
+ text: 'title'
66
69
  },
67
70
  Stats: { group: 'data', description: 'A small set of key numbers.', schema: empty, children: ['Stat'] },
68
71
  Stat: {
@@ -72,7 +75,7 @@ export const UI_CATALOG = {
72
75
  parent: 'Stats'
73
76
  },
74
77
  EntityList: { group: 'data', description: 'Labeled facts about an entity.', schema: empty, children: ['Entry'] },
75
- Entry: { group: 'data', description: 'One labeled fact.', schema: z.strictObject({ label: text }), parent: 'EntityList' },
78
+ Entry: { group: 'data', description: 'One labeled fact.', schema: z.strictObject({ label: text }), parent: 'EntityList', text: 'value' },
76
79
  Table: { group: 'data', description: 'Rows with named columns.', schema: z.strictObject({ rows }), children: ['Column'] },
77
80
  Column: {
78
81
  group: 'data',
@@ -104,13 +107,16 @@ export const UI_CATALOG = {
104
107
  description: 'A chat attachment with an optional caption.',
105
108
  schema: z
106
109
  .strictObject({ attachment: name.optional(), generated: z.literal('latest').optional(), alt: text.optional() })
107
- .refine((props) => Boolean(props.attachment) !== Boolean(props.generated), 'Choose attachment or generated, exclusively.')
110
+ .refine((props) => Boolean(props.attachment) !== Boolean(props.generated), 'Choose attachment or generated, exclusively.'),
111
+ needs: 'attachment|generated',
112
+ text: 'caption'
108
113
  },
109
114
  Gallery: { group: 'content', description: 'A grid of images with captions; at most 24.', schema: empty, children: ['Image'], count: { min: 1, max: 24 } },
110
115
  Compare: {
111
116
  group: 'content',
112
117
  description: 'Two chat attachments in one frame with a handle to wipe between them; children are the caption.',
113
- schema: z.strictObject({ before: name, after: name, beforeLabel: text.optional(), afterLabel: text.optional() })
118
+ schema: z.strictObject({ before: name, after: name, beforeLabel: text.optional(), afterLabel: text.optional() }),
119
+ text: 'caption'
114
120
  },
115
121
  Map: {
116
122
  group: 'places',
@@ -136,7 +142,9 @@ export const UI_CATALOG = {
136
142
  (props) => (props.lat === undefined) === (props.lon === undefined) && (props.lat !== undefined || props.address !== undefined),
137
143
  'Give lat with lon, or an address.'
138
144
  ),
139
- parent: 'Map'
145
+ parent: 'Map',
146
+ needs: 'lat lon|address',
147
+ text: 'name'
140
148
  },
141
149
  Sources: { group: 'content', description: 'Numbered sources without preloading.', schema: empty, children: ['Source'] },
142
150
  Source: {
@@ -160,15 +168,16 @@ export const UI_CATALOG = {
160
168
  children: ['Item'],
161
169
  binding: 'value'
162
170
  },
163
- Item: { group: 'inputs', description: 'One selectable value.', schema: z.strictObject({ value: scalar }), parent: 'Checklist' },
164
- Switch: { group: 'inputs', description: 'A local boolean.', schema: z.strictObject({ value: z.boolean() }), binding: 'value' },
171
+ Item: { group: 'inputs', description: 'One selectable value.', schema: z.strictObject({ value: scalar }), parent: 'Checklist', text: 'label' },
172
+ Switch: { group: 'inputs', description: 'A local boolean.', schema: z.strictObject({ value: z.boolean() }), binding: 'value', text: 'label' },
165
173
  Slider: {
166
174
  group: 'inputs',
167
175
  description: 'A local number in a range.',
168
176
  schema: z
169
177
  .strictObject({ value: number, min: number, max: number, step: number.positive().optional(), unit: text.optional() })
170
178
  .refine((props) => props.min < props.max && props.value >= props.min && props.value <= props.max, 'Value must lie within an increasing range.'),
171
- binding: 'value'
179
+ binding: 'value',
180
+ text: 'label'
172
181
  },
173
182
  Segmented: { group: 'inputs', description: 'Choose one local value.', schema: z.strictObject({ value: scalar }), children: ['Option'], binding: 'value' },
174
183
  Select: {
@@ -176,22 +185,31 @@ export const UI_CATALOG = {
176
185
  description: 'Choose one local value from a dropdown, for more or longer options than Segmented holds; the text beside its Options is its label.',
177
186
  schema: z.strictObject({ value: scalar }),
178
187
  children: ['Option'],
179
- binding: 'value'
188
+ binding: 'value',
189
+ text: 'label'
190
+ },
191
+ Option: {
192
+ group: 'inputs',
193
+ description: 'One local alternative.',
194
+ schema: z.strictObject({ value: scalar }),
195
+ parent: ['Segmented', 'Select'],
196
+ text: 'label'
180
197
  },
181
- Option: { group: 'inputs', description: 'One local alternative.', schema: z.strictObject({ value: scalar }), parent: ['Segmented', 'Select'] },
182
198
  TextField: {
183
199
  group: 'inputs',
184
200
  description: 'A line of local text up to maxLength characters (256 without one, at most 1024); children are the label.',
185
201
  schema: z
186
202
  .strictObject({ value: text, maxLength: z.number().int().min(1).max(1024).optional(), placeholder: text.max(128).optional() })
187
203
  .refine((props) => props.value.length <= (props.maxLength ?? 256), 'Value must not be longer than maxLength.'),
188
- binding: 'value'
204
+ binding: 'value',
205
+ text: 'label'
189
206
  },
190
207
  Button: {
191
208
  group: 'inputs',
192
209
  description: 'Run one local state action when pressed; children are the label.',
193
210
  schema: z.strictObject({ disabled: z.boolean().optional() }),
194
- action: 'action'
211
+ action: 'action',
212
+ text: 'label'
195
213
  },
196
214
  Show: { group: 'inputs', description: 'Show children when the condition is true.', schema: z.strictObject({ when: z.boolean() }) },
197
215
  Each: {
@@ -204,7 +222,8 @@ export const UI_CATALOG = {
204
222
  group: 'choices',
205
223
  description: 'Send its label and visible context once.',
206
224
  schema: z.strictObject({ context: text.optional(), primary: z.boolean().optional(), disabled: z.boolean().optional() }),
207
- parent: 'Choices'
225
+ parent: 'Choices',
226
+ text: 'label'
208
227
  }
209
228
  } as const;
210
229
 
package/src/prop-list.ts CHANGED
@@ -5,3 +5,21 @@ export function uiPropList(entry: { readonly schema: { readonly shape: Readonly<
5
5
  const props = Object.entries(entry.schema.shape).map(([key, schema]) => `${key}${schema.isOptional() ? '?' : ''}`);
6
6
  return entry.action ? [entry.action, ...props] : props;
7
7
  }
8
+
9
+ /* What a component needs in the compact note: the props it cannot do without and, when its text is not the plain content, what that text is. */
10
+ export function uiRequirement(
11
+ name: string,
12
+ entry: {
13
+ readonly schema: { readonly shape: Readonly<Record<string, z.ZodType>> };
14
+ readonly action?: string;
15
+ readonly needs?: string;
16
+ readonly text?: string;
17
+ }
18
+ ): string {
19
+ const required =
20
+ entry.needs ??
21
+ uiPropList(entry)
22
+ .filter((prop) => !prop.endsWith('?'))
23
+ .join(' ');
24
+ return `${name}${required ? ` ${required}` : ''}${entry.text ? ` (text: ${entry.text})` : ''}`;
25
+ }
package/src/text.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { UI_CATALOG, UI_GROUPS, type UiGroupName } from './catalog.ts';
2
- import { uiPropList } from './prop-list.ts';
2
+ import { uiPropList, uiRequirement } from './prop-list.ts';
3
3
  import { UI_FENCE_LANGUAGE, type UiBlock } from './compiler.ts';
4
4
 
5
5
  export function uiCompactCatalog(): string {
@@ -39,15 +39,15 @@ function uiGroupComponents(group: string) {
39
39
  return Object.entries(UI_CATALOG).filter(([, entry]) => entry.group === group);
40
40
  }
41
41
 
42
- /* One line per group with the names of its components, for a host that hands the props out per group. */
42
+ /* One line per group with its components and what each needs, for a host that hands the optional props out per group. */
43
43
  function uiGroupNames(detailHint: string | undefined): string {
44
44
  const lines = Object.keys(UI_GROUPS).map(
45
45
  (group) =>
46
46
  `${group}: ${uiGroupComponents(group)
47
- .map(([name]) => name)
47
+ .map(([name, entry]) => uiRequirement(name, entry))
48
48
  .join(', ')}`
49
49
  );
50
- return `Components by group${detailHint ? ` (${detailHint})` : ''}:\n${lines.join('\n')}`;
50
+ return `Components by group${detailHint ? ` (${detailHint})` : ''}, required props (text: words between the tags):\n${lines.join('\n')}`;
51
51
  }
52
52
 
53
53
  export function uiSessionNote({ fenceLanguage = UI_FENCE_LANGUAGE, catalog = 'props', detailHint }: UiTextOptions = {}): string {