@stina/extension-api 1.16.0 → 1.18.0

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.
@@ -5,6 +5,7 @@
5
5
  */
6
6
 
7
7
  import { z } from 'zod'
8
+ import { LocalizedStringSchema } from './localization.schema.js'
8
9
 
9
10
  // =============================================================================
10
11
  // CSS Properties
@@ -180,8 +181,8 @@ export const HeaderPropsSchema = z
180
181
  .object({
181
182
  component: z.literal('Header'),
182
183
  level: z.number().min(1).max(6).describe('Heading level (1-6)'),
183
- title: z.string().describe('Header title'),
184
- description: z.union([z.string(), z.array(z.string())]).optional().describe('Description text'),
184
+ title: LocalizedStringSchema.describe('Header title'),
185
+ description: z.union([LocalizedStringSchema, z.array(LocalizedStringSchema)]).optional().describe('Description text'),
185
186
  icon: z.string().optional().describe('Icon name'),
186
187
  style: ExtensionComponentStyleSchema.optional(),
187
188
  })
@@ -191,7 +192,7 @@ export const HeaderPropsSchema = z
191
192
  export const LabelPropsSchema = z
192
193
  .object({
193
194
  component: z.literal('Label'),
194
- text: z.string().describe('Label text'),
195
+ text: LocalizedStringSchema.describe('Label text'),
195
196
  style: ExtensionComponentStyleSchema.optional(),
196
197
  })
197
198
  .passthrough()
@@ -208,7 +209,7 @@ export const ClockPropsSchema = z
208
209
  export const ParagraphPropsSchema = z
209
210
  .object({
210
211
  component: z.literal('Paragraph'),
211
- text: z.string().describe('Paragraph text'),
212
+ text: LocalizedStringSchema.describe('Paragraph text'),
212
213
  style: ExtensionComponentStyleSchema.optional(),
213
214
  })
214
215
  .passthrough()
@@ -217,9 +218,9 @@ export const ParagraphPropsSchema = z
217
218
  export const ButtonPropsSchema = z
218
219
  .object({
219
220
  component: z.literal('Button'),
220
- text: z.string().describe('Button text'),
221
+ text: LocalizedStringSchema.describe('Button text'),
221
222
  type: z.enum(['normal', 'primary', 'danger', 'accent']).optional().describe('Visual style'),
222
- title: z.string().optional().describe('Tooltip shown on hover'),
223
+ title: LocalizedStringSchema.optional().describe('Tooltip shown on hover'),
223
224
  disabled: z.boolean().optional().describe('Disable the button'),
224
225
  onClickAction: ExtensionActionRefSchema.describe('Action to call on click'),
225
226
  style: ExtensionComponentStyleSchema.optional(),
@@ -230,8 +231,8 @@ export const ButtonPropsSchema = z
230
231
  export const TextInputPropsSchema = z
231
232
  .object({
232
233
  component: z.literal('TextInput'),
233
- label: z.string().describe('Input label'),
234
- placeholder: z.string().optional().describe('Placeholder text'),
234
+ label: LocalizedStringSchema.describe('Input label'),
235
+ placeholder: LocalizedStringSchema.optional().describe('Placeholder text'),
235
236
  value: z.string().optional().describe('Current value'),
236
237
  onChangeAction: ExtensionActionRefSchema.optional().describe('Action to call on change'),
237
238
  style: ExtensionComponentStyleSchema.optional(),
@@ -242,8 +243,8 @@ export const TextInputPropsSchema = z
242
243
  export const PasswordInputPropsSchema = z
243
244
  .object({
244
245
  component: z.literal('PasswordInput'),
245
- label: z.string().describe('Input label'),
246
- placeholder: z.string().optional().describe('Placeholder text'),
246
+ label: LocalizedStringSchema.describe('Input label'),
247
+ placeholder: LocalizedStringSchema.optional().describe('Placeholder text'),
247
248
  value: z.string().optional().describe('Current value'),
248
249
  onChangeAction: ExtensionActionRefSchema.optional().describe('Action to call on change'),
249
250
  style: ExtensionComponentStyleSchema.optional(),
@@ -254,8 +255,8 @@ export const PasswordInputPropsSchema = z
254
255
  export const NumberInputPropsSchema = z
255
256
  .object({
256
257
  component: z.literal('NumberInput'),
257
- label: z.string().describe('Input label'),
258
- placeholder: z.string().optional().describe('Placeholder text'),
258
+ label: LocalizedStringSchema.describe('Input label'),
259
+ placeholder: LocalizedStringSchema.optional().describe('Placeholder text'),
259
260
  value: z.union([z.string(), z.number()]).optional().describe('Current value'),
260
261
  min: z.number().optional().describe('Minimum value'),
261
262
  max: z.number().optional().describe('Maximum value'),
@@ -269,8 +270,8 @@ export const NumberInputPropsSchema = z
269
270
  export const TextAreaPropsSchema = z
270
271
  .object({
271
272
  component: z.literal('TextArea'),
272
- label: z.string().describe('Input label'),
273
- placeholder: z.string().optional().describe('Placeholder text'),
273
+ label: LocalizedStringSchema.describe('Input label'),
274
+ placeholder: LocalizedStringSchema.optional().describe('Placeholder text'),
274
275
  value: z.string().optional().describe('Current value'),
275
276
  rows: z.number().int().positive().optional().describe('Number of visible text rows'),
276
277
  onChangeAction: ExtensionActionRefSchema.optional().describe('Action to call on change'),
@@ -282,7 +283,7 @@ export const TextAreaPropsSchema = z
282
283
  export const DateTimeInputPropsSchema = z
283
284
  .object({
284
285
  component: z.literal('DateTimeInput'),
285
- label: z.string().describe('Input label'),
286
+ label: LocalizedStringSchema.describe('Input label'),
286
287
  value: z.string().optional().describe('Current value'),
287
288
  onChangeAction: ExtensionActionRefSchema.optional().describe('Action to call on change'),
288
289
  style: ExtensionComponentStyleSchema.optional(),
@@ -293,8 +294,8 @@ export const DateTimeInputPropsSchema = z
293
294
  export const SelectPropsSchema = z
294
295
  .object({
295
296
  component: z.literal('Select'),
296
- label: z.string().describe('Select label'),
297
- options: z.array(z.object({ label: z.string(), value: z.string() })).describe('Available options'),
297
+ label: LocalizedStringSchema.describe('Select label'),
298
+ options: z.array(z.object({ label: LocalizedStringSchema, value: z.string() })).describe('Available options'),
298
299
  selectedValue: z.string().optional().describe('Currently selected value'),
299
300
  onChangeAction: ExtensionActionRefSchema.optional().describe('Action to call on change'),
300
301
  style: ExtensionComponentStyleSchema.optional(),
@@ -305,7 +306,7 @@ export const SelectPropsSchema = z
305
306
  export const IconPickerPropsSchema = z
306
307
  .object({
307
308
  component: z.literal('IconPicker'),
308
- label: z.string().optional().describe('Picker label'),
309
+ label: LocalizedStringSchema.optional().describe('Picker label'),
309
310
  value: z.string().optional().describe('Currently selected icon name'),
310
311
  onChangeAction: ExtensionActionRefSchema.optional().describe('Action to call on change'),
311
312
  style: ExtensionComponentStyleSchema.optional(),
@@ -356,7 +357,7 @@ export const IconPropsSchema = z
356
357
  .object({
357
358
  component: z.literal('Icon'),
358
359
  name: z.string().describe('Icon name'),
359
- title: z.string().optional().describe('Icon title'),
360
+ title: LocalizedStringSchema.optional().describe('Icon title'),
360
361
  style: ExtensionComponentStyleSchema.optional(),
361
362
  })
362
363
  .passthrough()
@@ -370,7 +371,7 @@ export const IconButtonPropsSchema = z
370
371
  .object({
371
372
  component: z.literal('IconButton'),
372
373
  icon: z.string().describe('Icon name'),
373
- tooltip: z.string().describe('Tooltip text'),
374
+ tooltip: LocalizedStringSchema.describe('Tooltip text'),
374
375
  active: z.boolean().optional().describe('Whether the button is active'),
375
376
  disabled: z.boolean().optional().describe('Whether the button is disabled'),
376
377
  type: IconButtonTypeSchema.optional().describe('Button style type'),
@@ -383,7 +384,7 @@ export const IconButtonPropsSchema = z
383
384
  export const PanelActionSchema = z
384
385
  .object({
385
386
  icon: z.string().describe('Icon name'),
386
- tooltip: z.string().describe('Tooltip text'),
387
+ tooltip: LocalizedStringSchema.describe('Tooltip text'),
387
388
  action: ExtensionActionRefSchema.describe('Action to call'),
388
389
  type: IconButtonTypeSchema.optional().describe('Button style type'),
389
390
  })
@@ -392,8 +393,8 @@ export const PanelActionSchema = z
392
393
  export const PanelPropsSchema = z
393
394
  .object({
394
395
  component: z.literal('Panel'),
395
- title: z.string().describe('Panel title'),
396
- description: z.union([z.string(), z.array(z.string())]).optional().describe('Description text'),
396
+ title: LocalizedStringSchema.describe('Panel title'),
397
+ description: z.union([LocalizedStringSchema, z.array(LocalizedStringSchema)]).optional().describe('Description text'),
397
398
  icon: z.string().optional().describe('Icon name'),
398
399
  actions: z.array(PanelActionSchema).optional().describe('Action buttons'),
399
400
  content: ExtensionComponentDataSchema.optional().describe('Panel content'),
@@ -405,8 +406,8 @@ export const PanelPropsSchema = z
405
406
  export const TogglePropsSchema = z
406
407
  .object({
407
408
  component: z.literal('Toggle'),
408
- label: z.string().optional().describe('Toggle label'),
409
- description: z.string().optional().describe('Description text'),
409
+ label: LocalizedStringSchema.optional().describe('Toggle label'),
410
+ description: LocalizedStringSchema.optional().describe('Description text'),
410
411
  checked: z.boolean().optional().describe('Whether the toggle is checked'),
411
412
  disabled: z.boolean().optional().describe('Whether the toggle is disabled'),
412
413
  onChangeAction: ExtensionActionRefSchema.optional().describe('Action to call on change'),
@@ -418,8 +419,8 @@ export const TogglePropsSchema = z
418
419
  export const CollapsiblePropsSchema = z
419
420
  .object({
420
421
  component: z.literal('Collapsible'),
421
- title: z.string().describe('Title displayed in the header'),
422
- description: z.union([z.string(), z.array(z.string())]).optional().describe('Description text'),
422
+ title: LocalizedStringSchema.describe('Title displayed in the header'),
423
+ description: z.union([LocalizedStringSchema, z.array(LocalizedStringSchema)]).optional().describe('Description text'),
423
424
  icon: z.string().optional().describe('Icon name'),
424
425
  defaultExpanded: z.boolean().optional().describe('Whether expanded by default'),
425
426
  content: ExtensionComponentDataSchema.optional().describe('Content when expanded'),
@@ -435,7 +436,7 @@ export const PillVariantSchema = z
435
436
  export const PillPropsSchema = z
436
437
  .object({
437
438
  component: z.literal('Pill'),
438
- text: z.string().describe('Pill text'),
439
+ text: LocalizedStringSchema.describe('Pill text'),
439
440
  icon: z.string().optional().describe('Icon name'),
440
441
  variant: PillVariantSchema.optional().describe('Color variant'),
441
442
  style: ExtensionComponentStyleSchema.optional(),
@@ -446,7 +447,7 @@ export const PillPropsSchema = z
446
447
  export const CheckboxPropsSchema = z
447
448
  .object({
448
449
  component: z.literal('Checkbox'),
449
- label: z.string().describe('Checkbox label'),
450
+ label: LocalizedStringSchema.describe('Checkbox label'),
450
451
  checked: z.boolean().optional().describe('Whether the checkbox is checked'),
451
452
  disabled: z.boolean().optional().describe('Whether the checkbox is disabled'),
452
453
  strikethrough: z.boolean().optional().describe('Strike through label when checked'),
@@ -459,7 +460,7 @@ export const CheckboxPropsSchema = z
459
460
  export const MarkdownPropsSchema = z
460
461
  .object({
461
462
  component: z.literal('Markdown'),
462
- content: z.string().describe('Markdown content'),
463
+ content: LocalizedStringSchema.describe('Markdown content'),
463
464
  style: ExtensionComponentStyleSchema.optional(),
464
465
  })
465
466
  .passthrough()
@@ -478,7 +479,7 @@ export const TextPreviewPropsSchema = z
478
479
  export const ModalPropsSchema = z
479
480
  .object({
480
481
  component: z.literal('Modal'),
481
- title: z.string().describe('Modal title'),
482
+ title: LocalizedStringSchema.describe('Modal title'),
482
483
  open: z.boolean().optional().describe('Whether the modal is open'),
483
484
  maxWidth: z.string().optional().describe('Max width of the modal'),
484
485
  body: ExtensionComponentDataSchema.optional().describe('Modal body content'),
@@ -506,7 +507,7 @@ export const FrameVariantSchema = z
506
507
  export const FramePropsSchema = z
507
508
  .object({
508
509
  component: z.literal('Frame'),
509
- title: z.union([z.string(), ExtensionComponentChildrenSchema]).optional().describe('Optional title (string or components)'),
510
+ title: z.union([LocalizedStringSchema, ExtensionComponentChildrenSchema]).optional().describe('Optional title (string or components)'),
510
511
  icon: z.string().optional().describe('Icon name'),
511
512
  collapsible: z.boolean().optional().describe('Whether content can be toggled'),
512
513
  defaultExpanded: z.boolean().optional().describe('Whether expanded by default'),
@@ -598,7 +599,7 @@ export const WeatherForecastStepSchema = z
598
599
  export const WeatherForecastPropsSchema = z
599
600
  .object({
600
601
  component: z.literal('WeatherForecast'),
601
- title: z.string().optional().describe('Heading above the row'),
602
+ title: LocalizedStringSchema.optional().describe('Heading above the row'),
602
603
  icon: z.string().optional().describe('Icon shown to the left of the title'),
603
604
  unit: z.string().optional().describe('Written after every temperature. Defaults to °'),
604
605
  steps: z.array(WeatherForecastStepSchema).min(1).describe('Steps, hourly or daily'),
@@ -631,7 +632,7 @@ export const ChartPropsSchema = z
631
632
  chart: ChartKindSchema.optional().describe('Defaults to line'),
632
633
  series: z.array(ChartSeriesSchema).min(1).max(8).describe('At most eight series'),
633
634
  labels: z.array(z.string()).optional().describe('One per point, along the horizontal axis'),
634
- title: z.string().optional().describe('Heading above the plot'),
635
+ title: LocalizedStringSchema.optional().describe('Heading above the plot'),
635
636
  icon: z.string().optional().describe('Icon shown to the left of the title'),
636
637
  unit: z.string().optional().describe('Written after every value'),
637
638
  zeroBaseline: z.boolean().optional().describe('Force the value axis to include zero'),
@@ -646,10 +647,10 @@ export const StatTrendSchema = z.enum(['up', 'down', 'flat']).describe('Directio
646
647
  export const StatTilePropsSchema = z
647
648
  .object({
648
649
  component: z.literal('StatTile'),
649
- label: z.string().describe('What the number is'),
650
+ label: LocalizedStringSchema.describe('What the number is'),
650
651
  value: z.union([z.string(), z.number()]).describe('The number itself'),
651
652
  unit: z.string().optional().describe('Written after the value in smaller type'),
652
- caption: z.string().optional().describe('One quiet line under the number'),
653
+ caption: LocalizedStringSchema.optional().describe('One quiet line under the number'),
653
654
  icon: z.string().optional().describe('Icon name'),
654
655
  trend: StatTrendSchema.optional(),
655
656
  trendLabel: z.string().optional().describe('The change in words'),
@@ -670,7 +671,7 @@ export const ProgressColorSchema = z
670
671
  export const ProgressBarPropsSchema = z
671
672
  .object({
672
673
  component: z.literal('ProgressBar'),
673
- label: z.string().describe('What is being measured'),
674
+ label: LocalizedStringSchema.describe('What is being measured'),
674
675
  value: z.number().describe('Where the reading sits. Clamped to the range'),
675
676
  min: z.number().optional().describe('Bottom of the range. Defaults to 0'),
676
677
  max: z.number().optional().describe('Top of the range. Defaults to 100'),
@@ -678,7 +679,7 @@ export const ProgressBarPropsSchema = z
678
679
  color: ProgressColorSchema.optional().describe('Defaults to accent'),
679
680
  unit: z.string().optional().describe('Written after the value'),
680
681
  valueLabel: z.string().optional().describe('The readout in words, replacing value and unit'),
681
- caption: z.string().optional().describe('One quiet line under the reading'),
682
+ caption: LocalizedStringSchema.optional().describe('One quiet line under the reading'),
682
683
  icon: z.string().optional().describe('Icon name'),
683
684
  style: ExtensionComponentStyleSchema.optional(),
684
685
  })
@@ -725,7 +726,7 @@ export const TimelineEntrySchema = z
725
726
  export const TimelinePropsSchema = z
726
727
  .object({
727
728
  component: z.literal('Timeline'),
728
- title: z.string().optional().describe('Heading above the rail'),
729
+ title: LocalizedStringSchema.optional().describe('Heading above the rail'),
729
730
  icon: z.string().optional().describe('Icon shown to the left of the title'),
730
731
  entries: z.array(TimelineEntrySchema).min(1).describe('Entries, in the order they happen'),
731
732
  style: ExtensionComponentStyleSchema.optional(),
@@ -740,7 +741,7 @@ export const NoteVariantSchema = z
740
741
  export const NotePropsSchema = z
741
742
  .object({
742
743
  component: z.literal('Note'),
743
- title: z.string().optional(),
744
+ title: LocalizedStringSchema.optional(),
744
745
  icon: z.string().optional().describe('Icon shown to the left of the title'),
745
746
  badge: z.string().optional().describe('Trailing badge next to the title'),
746
747
  content: z.string().describe('The body, as markdown'),
@@ -798,7 +799,7 @@ export const AgendaDaySchema = z
798
799
  export const AgendaPropsSchema = z
799
800
  .object({
800
801
  component: z.literal('Agenda'),
801
- title: z.string().optional(),
802
+ title: LocalizedStringSchema.optional(),
802
803
  icon: z.string().optional().describe('Icon shown to the left of the title'),
803
804
  days: z.array(AgendaDaySchema),
804
805
  warnOverlaps: z.boolean().optional().describe('Word clashes between events'),
@@ -6,17 +6,10 @@
6
6
 
7
7
  import { z } from 'zod'
8
8
  import { ExtensionComponentDataSchema } from './components.schema.js'
9
+ import { LocalizedStringSchema } from './localization.schema.js'
9
10
 
10
- // =============================================================================
11
- // Localization
12
- // =============================================================================
11
+ export { LocalizedStringSchema }
13
12
 
14
- /**
15
- * Localized string - either a simple string or a map of language codes to strings
16
- */
17
- export const LocalizedStringSchema = z
18
- .union([z.string(), z.record(z.string())])
19
- .describe('String or localized string map')
20
13
 
21
14
  // =============================================================================
22
15
  // Tool Settings Views
@@ -58,7 +51,7 @@ export const ToolSettingsListGroupBySchema = z
58
51
  .optional()
59
52
  .describe('Explicit ordering of group values; unlisted groups appear afterwards alphabetically'),
60
53
  labels: z
61
- .record(z.string())
54
+ .record(LocalizedStringSchema)
62
55
  .optional()
63
56
  .describe('Human-friendly labels per group value (rendered as section headers)'),
64
57
  })
@@ -115,8 +108,16 @@ export const ToolSettingsViewSchema = z
115
108
  export const ToolSettingsViewDefinitionSchema = z
116
109
  .object({
117
110
  id: z.string().describe('Unique view ID within the extension'),
118
- title: z.string().describe('Display title'),
119
- description: z.string().optional().describe('Help text'),
111
+ title: LocalizedStringSchema.describe('Display title'),
112
+ description: LocalizedStringSchema.optional().describe('Help text'),
113
+ // A string rather than the known topics: one this host does not know yet must not stop
114
+ // the extension installing, it only lands on the extension's own page.
115
+ topic: z
116
+ .string()
117
+ .optional()
118
+ .describe(
119
+ 'What the view is about, which decides where Stina shows it: accounts, notifications, personal or tracking. Without one, or with one Stina does not know, the view is shown on the extension\'s own page.'
120
+ ),
120
121
  view: ToolSettingsViewSchema.describe('View configuration'),
121
122
  })
122
123
  .describe('Tool settings view definition')
@@ -170,7 +171,7 @@ export const PanelViewSchema = z
170
171
  export const PanelDefinitionSchema = z
171
172
  .object({
172
173
  id: z.string().describe('Unique panel ID within the extension'),
173
- title: z.string().describe('Display title'),
174
+ title: LocalizedStringSchema.describe('Display title'),
174
175
  icon: z.string().optional().describe('Icon name (from huge-icons)'),
175
176
  view: PanelViewSchema.describe('Panel view schema'),
176
177
  })
@@ -188,7 +189,7 @@ export const PanelDefinitionSchema = z
188
189
  export const StatusCardDefinitionSchema = z
189
190
  .object({
190
191
  id: z.string().describe('Unique card ID within the extension'),
191
- title: z.string().describe('What it is called where the user picks it'),
192
+ title: LocalizedStringSchema.describe('What it is called where the user picks it'),
192
193
  icon: z.string().optional().describe('Icon name (from huge-icons)'),
193
194
  size: z
194
195
  .enum(['line', 'block'])
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Localization Schema
3
+ *
4
+ * Kept apart so both the component and the contribution schemas can use it without importing
5
+ * each other.
6
+ */
7
+
8
+ import { z } from 'zod'
9
+
10
+ /**
11
+ * Localized string - either a simple string or a map of language codes to strings
12
+ */
13
+ export const LocalizedStringSchema = z
14
+ .union([z.string(), z.record(z.string())])
15
+ .describe('String or localized string map')