gridsmith-ui 0.25.0 → 0.27.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.
Files changed (105) hide show
  1. package/CHANGELOG.md +969 -0
  2. package/README.md +21 -5
  3. package/dist/charts.d.ts +2 -2
  4. package/dist/charts.js +58 -43
  5. package/dist/charts.js.map +1 -1
  6. package/dist/chat.js +4 -3
  7. package/dist/chat.js.map +1 -1
  8. package/dist/{chunk-W7GCEJEH.js → chunk-2CKSSWYG.js} +10 -6
  9. package/dist/chunk-2CKSSWYG.js.map +1 -0
  10. package/dist/chunk-3BRQRKDO.js +1 -0
  11. package/dist/chunk-3BRQRKDO.js.map +1 -1
  12. package/dist/{chunk-RWKCAKN3.js → chunk-5TUVX4B2.js} +6 -5
  13. package/dist/chunk-5TUVX4B2.js.map +1 -0
  14. package/dist/{chunk-X2HEV7FB.js → chunk-64TXZ4L7.js} +23 -33
  15. package/dist/chunk-64TXZ4L7.js.map +1 -0
  16. package/dist/chunk-7Q46JXSK.js +1 -0
  17. package/dist/chunk-7Q46JXSK.js.map +1 -1
  18. package/dist/chunk-CRQ6KCRD.js +1 -0
  19. package/dist/chunk-CRQ6KCRD.js.map +1 -1
  20. package/dist/{chunk-HZIP4EJI.js → chunk-EKBWWA6P.js} +53 -6
  21. package/dist/chunk-EKBWWA6P.js.map +1 -0
  22. package/dist/chunk-HP7WUZPK.js +1 -0
  23. package/dist/chunk-HP7WUZPK.js.map +1 -1
  24. package/dist/{chunk-QGSCF7PN.js → chunk-IXR4UEF4.js} +5 -4
  25. package/dist/chunk-IXR4UEF4.js.map +1 -0
  26. package/dist/chunk-M2QRNBDQ.js +1 -0
  27. package/dist/chunk-M2QRNBDQ.js.map +1 -1
  28. package/dist/chunk-MD2EFMES.js +1 -0
  29. package/dist/chunk-MD2EFMES.js.map +1 -1
  30. package/dist/chunk-NRHIYS5W.js +1 -0
  31. package/dist/chunk-NRHIYS5W.js.map +1 -1
  32. package/dist/chunk-OTCEJN64.js +1 -0
  33. package/dist/chunk-OTCEJN64.js.map +1 -1
  34. package/dist/chunk-OYNUU346.js +78 -0
  35. package/dist/chunk-OYNUU346.js.map +1 -0
  36. package/dist/{chunk-FHMCAOAH.js → chunk-PO65I3MQ.js} +4 -3
  37. package/dist/chunk-PO65I3MQ.js.map +1 -0
  38. package/dist/chunk-QM4SJKWV.js +1 -0
  39. package/dist/chunk-QM4SJKWV.js.map +1 -1
  40. package/dist/{chunk-3CUKJ4VP.js → chunk-R5NFCEZ3.js} +11 -8
  41. package/dist/chunk-R5NFCEZ3.js.map +1 -0
  42. package/dist/{chunk-2YSEME33.js → chunk-SFY2KMHG.js} +64 -6
  43. package/dist/chunk-SFY2KMHG.js.map +1 -0
  44. package/dist/{chunk-HYMXAIXN.js → chunk-TJEV7YAY.js} +38 -10
  45. package/dist/chunk-TJEV7YAY.js.map +1 -0
  46. package/dist/chunk-WH2FUFAC.js +1 -0
  47. package/dist/chunk-WH2FUFAC.js.map +1 -1
  48. package/dist/chunk-XVB55M3N.js +1 -0
  49. package/dist/chunk-XVB55M3N.js.map +1 -1
  50. package/dist/{chunk-JXANCXK6.js → chunk-ZI3OQDET.js} +19 -4
  51. package/dist/chunk-ZI3OQDET.js.map +1 -0
  52. package/dist/data-grid.d.ts +1 -1
  53. package/dist/data-grid.js +6 -4
  54. package/dist/data-grid.js.map +1 -1
  55. package/dist/editor-mentions.js +3 -2
  56. package/dist/editor-mentions.js.map +1 -1
  57. package/dist/editor.js +4 -3
  58. package/dist/editor.js.map +1 -1
  59. package/dist/{feather-W26ERBQV.js → feather-FNBQ74RR.js} +12 -18
  60. package/dist/feather-FNBQ74RR.js.map +1 -0
  61. package/dist/{heroicons-MY43466C.js → heroicons-DODCSYWD.js} +11 -9
  62. package/dist/heroicons-DODCSYWD.js.map +1 -0
  63. package/dist/icons.d.ts +32 -5
  64. package/dist/icons.js +2 -1
  65. package/dist/icons.js.map +1 -1
  66. package/dist/index.d.ts +469 -67
  67. package/dist/index.js +3017 -1751
  68. package/dist/index.js.map +1 -1
  69. package/dist/kanban.js +5 -5
  70. package/dist/{lucide-CMPVM3PS.js → lucide-ZWE3EPGP.js} +11 -9
  71. package/dist/lucide-ZWE3EPGP.js.map +1 -0
  72. package/dist/{phosphor-RMHZOW2O.js → phosphor-DIHPA4AJ.js} +11 -9
  73. package/dist/phosphor-DIHPA4AJ.js.map +1 -0
  74. package/dist/resizable.js +8 -7
  75. package/dist/resizable.js.map +1 -1
  76. package/dist/roots.css +43 -7
  77. package/dist/{tabler-MJVEYHA5.js → tabler-D3VYTSGI.js} +11 -9
  78. package/dist/tabler-D3VYTSGI.js.map +1 -0
  79. package/dist/tokens.css +17 -8
  80. package/dist/{use-pagination-BnKOnBdz.d.ts → use-pagination-BxcRlNQG.d.ts} +6 -0
  81. package/dist/utils.d.ts +275 -1
  82. package/dist/utils.js +875 -1
  83. package/dist/utils.js.map +1 -1
  84. package/dist/virtualized.d.ts +1 -1
  85. package/dist/virtualized.js +6 -4
  86. package/dist/virtualized.js.map +1 -1
  87. package/dist-static/tokens.css +17 -8
  88. package/package.json +5 -3
  89. package/dist/chunk-2YSEME33.js.map +0 -1
  90. package/dist/chunk-3CUKJ4VP.js.map +0 -1
  91. package/dist/chunk-FHMCAOAH.js.map +0 -1
  92. package/dist/chunk-HYMXAIXN.js.map +0 -1
  93. package/dist/chunk-HZIP4EJI.js.map +0 -1
  94. package/dist/chunk-JXANCXK6.js.map +0 -1
  95. package/dist/chunk-QGSCF7PN.js.map +0 -1
  96. package/dist/chunk-RWKCAKN3.js.map +0 -1
  97. package/dist/chunk-W7GCEJEH.js.map +0 -1
  98. package/dist/chunk-WOVYHFUD.js +0 -50
  99. package/dist/chunk-WOVYHFUD.js.map +0 -1
  100. package/dist/chunk-X2HEV7FB.js.map +0 -1
  101. package/dist/feather-W26ERBQV.js.map +0 -1
  102. package/dist/heroicons-MY43466C.js.map +0 -1
  103. package/dist/lucide-CMPVM3PS.js.map +0 -1
  104. package/dist/phosphor-RMHZOW2O.js.map +0 -1
  105. package/dist/tabler-MJVEYHA5.js.map +0 -1
package/dist/index.d.ts CHANGED
@@ -5,8 +5,8 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
5
5
  import { M as MentionSuggestion } from './MentionList-CoNBRFGR.js';
6
6
  import { C as ColumnKind, B as BreakpointKey } from './table-utils-BkjNEWts.js';
7
7
  export { a as BreakpointWidthProvider, u as useBreakpoint } from './table-utils-BkjNEWts.js';
8
- import { P as Pager, A as AppShellPreferences } from './use-pagination-BnKOnBdz.js';
9
- export { a as PaginationOptions, b as PreferencesContext, R as ResolvedPreferences, p as preferenceActionKey, u as usePagination, c as usePreferences } from './use-pagination-BnKOnBdz.js';
8
+ import { P as Pager, A as AppShellPreferences } from './use-pagination-BxcRlNQG.js';
9
+ export { a as PaginationOptions, b as PreferencesContext, R as ResolvedPreferences, p as preferenceActionKey, u as usePagination, c as usePreferences } from './use-pagination-BxcRlNQG.js';
10
10
  export { B as BreadcrumbItem, a as Breadcrumbs, b as BreadcrumbsSeparator, c as BreadcrumbsSize, d as BreadcrumbsVariant } from './Breadcrumbs-CGS8GKl-.js';
11
11
 
12
12
  type ButtonVariant = "default" | "secondary" | "tertiary" | "outline" | "ghost" | "destructive" | "success" | "warning" | "link";
@@ -196,6 +196,8 @@ interface ComboboxOption {
196
196
  value: string;
197
197
  label: string;
198
198
  disabled?: boolean;
199
+ /** Words a search finds it by as well as its label, never shown (gridsmith-ui 0.26.0 or later): TimezoneSelect's renamed cities. */
200
+ keywords?: string;
199
201
  }
200
202
  interface ComboboxProps extends FieldControlWiring {
201
203
  value: string;
@@ -214,24 +216,38 @@ interface ComboboxProps extends FieldControlWiring {
214
216
  }
215
217
  declare function Combobox({ value, onChange: onChangeProp, options, placeholder, disabled, loading, className, ref, container, error, size: sizeProp, "aria-label": ariaLabel, ...wiring }: ComboboxProps): react_jsx_runtime.JSX.Element;
216
218
 
219
+ /**
220
+ * Time zones by the browser's own names, and their offsets (Sprint 25.17 A28), apart from the TimezoneSelect component since
221
+ * Sprint 25.22 so a server can call them: nothing here needs React. `gridsmith-ui/utils` exports canonicalTimeZone and
222
+ * timeZoneOffset for server code; browserTimeZone reads the zone of whatever runs it, a server's own there.
223
+ */
217
224
  /**
218
225
  * The browser's own name for a zone (Sprint 25.17 A28, R28-51): one browser always names a zone one way, so a stored
219
226
  * "Asia/Calcutta" and a listed "Asia/Kolkata" are one zone, with no alias table shipped. An id the browser doesn't know
220
227
  * stays as given.
221
228
  */
222
229
  declare function canonicalTimeZone(zone: string): string;
223
- /** The browser's time zone, by its own name; "UTC" where the browser names none. */
230
+ /** The browser's time zone, by its own name; "UTC" where the browser names none. On a server, the server's zone. */
224
231
  declare function browserTimeZone(): string;
225
232
  /**
226
- * A zone's offset from UTC at an instant, as the page's language names it ("GMT+1", "GMT-5", "GMT+5:30"): read at that
227
- * instant, so it follows daylight saving.
233
+ * A zone's offset from UTC at an instant, as the locale given names it ("GMT+1", "GMT-5", "GMT+5:30"; a component's
234
+ * useFormatLocale(), else the browser's reading): read at that instant, so it follows daylight saving.
228
235
  */
229
- declare function timeZoneOffset(zone: string, at?: Date): string;
236
+ declare function timeZoneOffset(zone: string, at?: Date, locale?: string | undefined): string;
237
+
238
+ /**
239
+ * The visitor's time zone, once the browser has the page (Sprint 25.20 D3): undefined on a server and while hydrating,
240
+ * where browserTimeZone() would read the server's own. A settings page calls it at its top, starts its state from the
241
+ * stored zone and shows this one where none is stored, `value={zone ?? browserZone}`, saving `zone ?? browserZone`.
242
+ */
243
+ declare function useBrowserTimeZone(): string | undefined;
230
244
  interface TimezoneSelectProps extends FieldControlWiring {
231
245
  /**
232
246
  * The stored zone, an IANA id ("Europe/London"). Empty: the field is empty, and the browser's zone is the list's first
233
- * option, marked as the user's, to pick with one key. Start the page's state from the stored zone, else
234
- * browserTimeZone(), to show the browser's as chosen.
247
+ * option, marked as the user's, to pick with one key. To show the browser's as chosen: `const browserZone =
248
+ * useBrowserTimeZone()` at the component's top (a hook, never behind `??`), the state from the stored zone, then
249
+ * `value={zone ?? browserZone}`, and save and check `zone ?? browserZone`, the zone the field shows (it is undefined
250
+ * until the browser has the page).
235
251
  */
236
252
  value?: string;
237
253
  /** Called with the chosen zone's id, by the browser's own name. */
@@ -251,6 +267,11 @@ interface TimezoneSelectProps extends FieldControlWiring {
251
267
  */
252
268
  declare function TimezoneSelect({ value, onChange, placeholder, ...rest }: TimezoneSelectProps): react_jsx_runtime.JSX.Element;
253
269
 
270
+ /**
271
+ * Times as people read them, relative or in full (Sprint 25.17 A29), apart from the RelativeTime component since Sprint
272
+ * 25.22 (nothing here needs React). Not on `gridsmith-ui/utils` (that sprint's review): a relative time and a full one
273
+ * depend on the visitor's clock and time zone, which a server doesn't know, so a server page hands RelativeTime the time.
274
+ */
254
275
  /** A time: an ISO string, a Date, or milliseconds since the epoch. */
255
276
  type TimeValue = string | Date | number;
256
277
  /**
@@ -262,15 +283,22 @@ type TimeValue = string | Date | number;
262
283
  declare function formatRelativeTime(time: TimeValue, options: {
263
284
  thresholdHours: number;
264
285
  now?: number;
286
+ locale?: string;
265
287
  }): string;
288
+ /**
289
+ * The full timestamp, as the tooltip and a screen reader give it: the date, the time and its zone, in the locale given
290
+ * (a component's useFormatLocale()), else the browser's reading.
291
+ */
292
+ declare function formatFullTime(time: TimeValue, locale?: string): string;
293
+
266
294
  /**
267
295
  * formatRelativeTime with the project's threshold, the shell's (dateTime.relativeThresholdHours), for a time drawn as
268
296
  * text in a slot that takes a string: a Timeline item's `timestamp`, with the time itself as its `dateTime` so the exact
269
- * time shows on hover. The text is read when the page renders; RelativeTime draws a time that refreshes as it ages.
297
+ * time shows on hover. The text is read when the page renders; RelativeTime draws a time that refreshes as it ages. It
298
+ * depends on the visitor's clock and time zone, which a server doesn't know, so it is empty until the browser has the
299
+ * page (Sprint 25.20 D3).
270
300
  */
271
301
  declare function useRelativeTimeFormat(): (time: TimeValue) => string;
272
- /** The full timestamp, as the tooltip and a screen reader give it: the date, the time and its zone, in the page's language. */
273
- declare function formatFullTime(time: TimeValue): string;
274
302
  interface RelativeTimeProps {
275
303
  /** The time: an ISO string, a Date, or milliseconds since the epoch. */
276
304
  time: TimeValue;
@@ -326,6 +354,12 @@ interface RadioOption {
326
354
  value: string;
327
355
  label: string;
328
356
  disabled?: boolean;
357
+ /**
358
+ * What the option asks for next, shown under it while it is chosen (GOV.UK's conditional reveal; Sprint 25.19 R2):
359
+ * "On a date" shows its date, "After a number of times" its number. It sits under the option, never inside the
360
+ * radio, and Tab reaches it from the option. Give its field a label of its own.
361
+ */
362
+ reveal?: ReactNode;
329
363
  }
330
364
  /** A Field passes its wiring (0.21.0): its label names the group, and its hint and error describe it. */
331
365
  interface RadioGroupProps extends FieldControlWiring {
@@ -338,6 +372,9 @@ interface RadioGroupProps extends FieldControlWiring {
338
372
  }
339
373
  declare function RadioGroup({ value, onChange: onChangeProp, options, orientation, className, label, ...wiring }: RadioGroupProps): react_jsx_runtime.JSX.Element;
340
374
 
375
+ /** A day of the week as `Date.getDay()` counts them: Sunday 0, Monday 1 … Saturday 6. */
376
+ type Weekday = 0 | 1 | 2 | 3 | 4 | 5 | 6;
377
+
341
378
  interface DatePickerProps extends Omit<FieldControlWiring, "id"> {
342
379
  value: Date | null;
343
380
  onChange: (date: Date | null) => void;
@@ -364,8 +401,10 @@ interface DatePickerProps extends Omit<FieldControlWiring, "id"> {
364
401
  start?: Date | null;
365
402
  end?: Date | null;
366
403
  };
404
+ /** The week's first day, Sunday 0 to Saturday 6. Default: the first day of the visitor's week, from their browser's languages, then the page's language, then Monday (gridsmith-ui 0.27.0); Sunday before. */
405
+ weekStartsOn?: Weekday;
367
406
  }
368
- declare function DatePicker({ value, onChange: onChangeProp, placeholder, disabled, className, ref, container, error, label, id, size: sizeProp, min, max, range, ...wiring }: DatePickerProps): react_jsx_runtime.JSX.Element;
407
+ declare function DatePicker({ value, onChange: onChangeProp, placeholder, disabled, className, ref, container, error, label, id, size: sizeProp, min, max, range, weekStartsOn: weekStartsOnProp, ...wiring }: DatePickerProps): react_jsx_runtime.JSX.Element;
369
408
 
370
409
  interface DateRange {
371
410
  start: Date | null;
@@ -393,8 +432,8 @@ interface DateRangePickerProps extends Omit<FieldControlWiring, "id"> {
393
432
  max?: Date;
394
433
  /** Quick ranges listed beside the calendars. Pass [] to hide; omit for the defaults. */
395
434
  presets?: DateRangePreset[];
396
- /** First day of the week. Default 0 (Sunday). */
397
- weekStartsOn?: 0 | 1;
435
+ /** The week's first day, Sunday 0 to Saturday 6. Default: the first day of the visitor's week, from their browser's languages, then the page's language, then Monday (gridsmith-ui 0.27.0); Sunday before. */
436
+ weekStartsOn?: Weekday;
398
437
  size?: ControlSize;
399
438
  }
400
439
  declare const DEFAULT_DATE_RANGE_PRESETS: DateRangePreset[];
@@ -404,7 +443,231 @@ declare const DEFAULT_DATE_RANGE_PRESETS: DateRangePreset[];
404
443
  * the end (clicking before the start restarts the selection). Closes on
405
444
  * Escape or outside click. Pair with <Field> for label/hint/error wiring.
406
445
  */
407
- declare function DateRangePicker({ value, onChange: onChangeProp, placeholder, disabled, error, label, id, className, ref, container, min, max, presets, weekStartsOn, size: sizeProp, ...wiring }: DateRangePickerProps): react_jsx_runtime.JSX.Element;
446
+ declare function DateRangePicker({ value, onChange: onChangeProp, placeholder, disabled, error, label, id, className, ref, container, min, max, presets, weekStartsOn: weekStartsOnProp, size: sizeProp, ...wiring }: DateRangePickerProps): react_jsx_runtime.JSX.Element;
447
+
448
+ /**
449
+ * How something repeats (Sprint 25.19 R1): the iCalendar standard's rule (RFC 5545 `RRULE`), in the subset Outlook's and
450
+ * Google's menus write (P5), read in the event's local time. The quick choices are stored in the standard's implied form
451
+ * (P6): a weekly rule with no `weekdays`, a monthly rule with no `day` or `nth` and a bare yearly rule repeat on the
452
+ * start's own weekday, date or anniversary, so moving the event moves them. The event's own start is always its first
453
+ * occurrence.
454
+ */
455
+ type RecurrenceFrequency = "daily" | "weekly" | "monthly" | "yearly";
456
+ /** An nth weekday of a month: the first to the fourth, or the last (−1). A fifth weekday is the last. */
457
+ type WeekOfMonth = 1 | 2 | 3 | 4 | -1;
458
+ interface Recurrence {
459
+ freq: RecurrenceFrequency;
460
+ /** Every n days, weeks, months or years. Default 1. */
461
+ interval?: number;
462
+ /** Weekly: the days it repeats on, Sunday 0 to Saturday 6. Left out, the start's own weekday. */
463
+ weekdays?: Weekday[];
464
+ /** Monthly, or yearly with `month`: a day of the month, 1 to 31, or −1 for the last day. A month without the day is skipped. */
465
+ day?: number;
466
+ /** Monthly, or yearly with `month`: an nth weekday, `{ week: 1, weekday: 2 }` the first Tuesday. */
467
+ nth?: {
468
+ week: WeekOfMonth;
469
+ weekday: Weekday;
470
+ };
471
+ /** Yearly: the month, 1 to 12, with `day` or `nth`. A bare yearly rule repeats on the start's anniversary. */
472
+ month?: number;
473
+ /** The week's first day (WKST), which places a weekly rule's weeks. Default Monday, as RFC 5545 says. */
474
+ weekStart?: Weekday;
475
+ /**
476
+ * The last moment it occurs. A date at midnight includes its whole day ("until 30 November"); an all-day event's is a
477
+ * date. RecurrencePicker stores the end of the chosen day, which other apps read exactly. Left out with `count`, it
478
+ * never ends. A rule read back from JSON may carry it as a string: the library reads it as the date it was.
479
+ */
480
+ until?: Date;
481
+ /** How many times it occurs, the first included, and the excluded dates among them (RFC 5545). */
482
+ count?: number;
483
+ }
484
+ /** The fields a repeating event carries; a Calendar event has them as `repeat` and `exceptions` (P12: never `recurrence`). */
485
+ interface RepeatingEvent {
486
+ id: string;
487
+ start: Date;
488
+ end?: Date;
489
+ allDay?: boolean;
490
+ /** The rule, or a rule string `parseRRule` reads ("RRULE:FREQ=WEEKLY;BYDAY=TU,TH"). */
491
+ repeat?: Recurrence | string;
492
+ /** The dates left out, as day keys in local time ("2026-10-20"): the original date of each occurrence removed or moved. */
493
+ exceptions?: string[];
494
+ /**
495
+ * On an occurrence, its series' id and its original date (a day key), as RFC 5545's RECURRENCE-ID links an edited
496
+ * instance to its series. Each occurrence `occurrences` gives carries it, and so does an occurrence changed on its own
497
+ * ("This event"), which the page stores under an id of its own: the series leaves the date out, and the edit helpers
498
+ * find it by its link.
499
+ */
500
+ series?: {
501
+ id: string;
502
+ date: string;
503
+ };
504
+ }
505
+ /** Which occurrences a change or a deletion applies to: this one, it and the ones after it, or the whole series. */
506
+ type RecurrenceScope = "this" | "following" | "all";
507
+ /**
508
+ * What a choice in RecurrenceScopeDialog does to the page's events: `events`, the list as it now is, for a page that
509
+ * keeps its events in state; or `save`, the events to write (new or changed, each by its id), and `remove`, the ids to
510
+ * delete, for a page that stores them elsewhere.
511
+ */
512
+ interface RepeatChange<T> {
513
+ events: T[];
514
+ save: T[];
515
+ remove: string[];
516
+ }
517
+ /** One occurrence of a series: the event without its repeat fields, its own id, start and end, and where it came from. */
518
+ type Occurrence<T extends RepeatingEvent> = Omit<T, "repeat" | "exceptions"> & {
519
+ id: string;
520
+ start: Date;
521
+ end?: Date;
522
+ /** The series' id and this occurrence's original date (a day key), which the edit helpers take. */
523
+ series: {
524
+ id: string;
525
+ date: string;
526
+ };
527
+ };
528
+ /**
529
+ * The rule a string holds, or null when it is outside P5's subset (the event is then drawn once, its rule kept as written):
530
+ * FREQ, INTERVAL and WKST; weekly BYDAY days; a monthly or yearly BYMONTHDAY, or one nth BYDAY ("1TU", or "TU" with
531
+ * BYSETPOS=1); a yearly BYMONTH with either; UNTIL (a date, a floating or a UTC date-time) or COUNT. The "RRULE:" prefix
532
+ * is optional. A daily rule with days (every weekday, as some apps write it) reads as weekly on them.
533
+ */
534
+ declare function parseRRule(text: string): Recurrence | null;
535
+ /**
536
+ * The rule as an RRULE string, "RRULE:FREQ=…", for an iCalendar file or another app. UNTIL is written as a date for an
537
+ * all-day event and in UTC for a timed one, as RFC 5545 asks.
538
+ */
539
+ declare function toRRule(rule: Recurrence, { allDay }?: {
540
+ allDay?: boolean;
541
+ }): string;
542
+ /**
543
+ * A rule from a value: the object itself, the rule a string holds, or null for an unreadable string or none. A rule read
544
+ * back from JSON (storage, an API) has its end as a string, which is read as the date it was; an end that isn't a date
545
+ * makes the rule unreadable, so the event is drawn once rather than guessed at.
546
+ */
547
+ declare function readRecurrence(value: Recurrence | string | undefined | null): Recurrence | null;
548
+ /** The nth weekday a date is: the last when it is in its month's last seven days (a fifth Tuesday is the last). */
549
+ declare function nthOf(date: Date): {
550
+ week: WeekOfMonth;
551
+ weekday: Weekday;
552
+ };
553
+ /**
554
+ * Every occurrence of a repeating event that overlaps [from, to), in order: the event without its repeat fields, each
555
+ * with the id "<id>::<date>", its own start and end (the same wall-clock times and number of days) and `series`, its
556
+ * original date. Its excluded dates are left out. An event that doesn't repeat, or whose rule can't be read, is itself,
557
+ * when it overlaps.
558
+ */
559
+ declare function occurrences<T extends RepeatingEvent>(event: T, from: Date, to: Date): Array<T | Occurrence<T>>;
560
+ /**
561
+ * The occurrence of a series on a day (a day key), or undefined when it has none that day (the rule skips it, or it is
562
+ * excluded): for a page whose Edit has an address of its own, which carries the series' id and the date. Given the
563
+ * page's events, an occurrence changed on its own on that date ("This event") is found too.
564
+ */
565
+ declare function occurrenceOn<T extends RepeatingEvent>(series: T, date: string, events?: readonly T[]): Occurrence<T> | undefined;
566
+ /**
567
+ * Saves the user's edit to an occurrence, for the scope they chose in RecurrenceScopeDialog: the page stores what it
568
+ * returns. `occurrence` is the event they opened, one the Calendar handed over or one changed on its own before (the
569
+ * page's own); `changes` the form's fields, every one or only those changed (only what differs from the opened event
570
+ * applies); `newId` an id of the page's, for the event or the series a choice makes.
571
+ * - "This event": the occurrence becomes an event of its own, linked to its series by `series`, its date left out of the
572
+ * series; one changed on its own before just takes the edit.
573
+ * - "This and following events": the series ends the day before and a new one starts on the date, under `newId`, with
574
+ * the edit; the events changed on their own from the date on go with it.
575
+ * - "All events": the series takes the edit, and a moved time or day moves it and its rule, so every earlier date stays.
576
+ * The events changed on their own keep what they changed themselves (a field, another day, other times) and follow the
577
+ * rest. A changed repeat removes them, as Outlook does, and their dates go back to the new rule (RecurrenceScopeDialog's
578
+ * `edited` says so first); a deleted date stays deleted.
579
+ */
580
+ declare function saveOccurrence<T extends RepeatingEvent>(events: readonly T[], occurrence: Occurrence<T> | T, scope: RecurrenceScope, changes: Partial<T>, newId: string): RepeatChange<T>;
581
+ /**
582
+ * Deletes an occurrence, for the scope the user chose in RecurrenceScopeDialog: the page stores what it returns. "This
583
+ * event" leaves its date out of the series (an event changed on its own is removed, and its date stays empty); "This
584
+ * and following events" ends the series the day before and removes the events changed on their own from the date on;
585
+ * "All events" removes the series and every event changed on its own.
586
+ */
587
+ declare function deleteOccurrence<T extends RepeatingEvent>(events: readonly T[], occurrence: Occurrence<T> | T, scope: RecurrenceScope): RepeatChange<T>;
588
+ /**
589
+ * How many of a series' events changed on their own each scope covers, for RecurrenceScopeDialog's `edited`: "This and
590
+ * following events" those from the occurrence's date on, "All events" every one.
591
+ */
592
+ declare function countEdited<T extends RepeatingEvent>(events: readonly T[], occurrence: Occurrence<T> | T): {
593
+ following: number;
594
+ all: number;
595
+ };
596
+ /**
597
+ * The rule in words, for its date: "Every week on Tuesday and Thursday, until 30 November 2026", "Every month on the
598
+ * first Tuesday", "Every year on 6 October". The days and dates are written in the locale given (a component's
599
+ * useFormatLocale(), Sprint 25.20), else the browser's reading of the page's language.
600
+ */
601
+ declare function describeRecurrence(rule: Recurrence, start: Date, locale?: string | undefined): string;
602
+ interface RecurrencePreset {
603
+ /** The choice in words, as describeRecurrence writes it for the date. */
604
+ label: string;
605
+ rule: Recurrence;
606
+ }
607
+ /**
608
+ * The quick choices for a date, each one including it (P6): every day; every weekday, for a weekday; every week on its
609
+ * weekday; every month on its nth weekday (the fourth and "the last" both for a fourth one in a month's last seven days,
610
+ * only "the last" for a fifth); every month on its date, and on the last day when it is one; every year on its
611
+ * anniversary. The weekly, monthly-by-date and yearly choices are the
612
+ * implied form, so they follow the date when the event moves.
613
+ */
614
+ declare function recurrencePresets(start: Date, locale?: string | undefined): RecurrencePreset[];
615
+ /** Whether two rules repeat the same way (an `until` compared by its moment). */
616
+ declare function sameRecurrence(a: Recurrence | null | undefined, b: Recurrence | null | undefined): boolean;
617
+
618
+ interface RecurrencePickerProps extends FieldControlWiring {
619
+ /**
620
+ * The rule; a rule string from another app (RFC 5545's RRULE), read as a rule when the library can show it, and kept
621
+ * as written, shown as "Custom repeat", when it can't; or null for "Does not repeat".
622
+ */
623
+ value: Recurrence | string | null;
624
+ /** The new rule, or null. A rule string the field can't show is never changed unless the user chooses another. */
625
+ onChange: (value: Recurrence | null) => void;
626
+ /** The event's start: the quick choices are its own, and an end date comes after it. */
627
+ start: Date;
628
+ /** Standalone, the field's label: default "Repeat". In a Field, the Field's label names it. */
629
+ label?: string;
630
+ /** The week's first day for the days of a weekly repeat. Default: the visitor's, as the Calendar's. */
631
+ weekStartsOn?: Weekday;
632
+ className?: string;
633
+ }
634
+ declare function RecurrencePicker({ value, onChange: onChangeProp, start, label, weekStartsOn, className, ...wiring }: RecurrencePickerProps): react_jsx_runtime.JSX.Element;
635
+
636
+ interface RecurrenceScopeDialogProps {
637
+ open: boolean;
638
+ /** The question, in the action's words: "Delete Stand-up?", "Save changes to Stand-up?". */
639
+ title: string;
640
+ /** The action's own word, the button that goes ahead: "Delete", "Save". */
641
+ verb: string;
642
+ /** A deletion: the button is red, and Enter in the dialog never goes ahead (Cancel is the default). */
643
+ destructive?: boolean;
644
+ /**
645
+ * The edit changes how it repeats: one occurrence can't take a rule of its own, so "This event" isn't offered, and
646
+ * "This and following events" is the default (as Google asks). Pass `!sameRecurrence(readRecurrence(edited.repeat),
647
+ * readRecurrence(series.repeat))`; never for a deletion.
648
+ */
649
+ repeatChanged?: boolean;
650
+ /**
651
+ * How many of the series' events were changed on their own ("This event") that each choice covers: pass
652
+ * `countEdited(events, occurrence)`. With repeatChanged, the dialog says that the chosen one undoes their changes, as
653
+ * Outlook warns before it does.
654
+ */
655
+ edited?: {
656
+ following: number;
657
+ all: number;
658
+ };
659
+ /** The scope chosen, when the user goes ahead. The page then changes its events with saveOccurrence or deleteOccurrence. */
660
+ onChoose: (scope: RecurrenceScope) => void;
661
+ /** Nothing changes; focus goes back to what opened the dialog. */
662
+ onCancel: () => void;
663
+ }
664
+ /**
665
+ * One repeat or the series (Sprint 25.19 R4, P7): what Outlook and Google ask when an occurrence of a repeating event is
666
+ * changed or deleted. "This event", the default, "This and following events" or "All events", and the action's own
667
+ * button beside Cancel, in the Dialog's footer. The data side is the library's: saveOccurrence and deleteOccurrence. An
668
+ * edit that changes how it repeats offers only the last two, and says when one undoes events changed on their own.
669
+ */
670
+ declare function RecurrenceScopeDialog({ open, title, verb, destructive, repeatChanged, edited, onChoose, onCancel }: RecurrenceScopeDialogProps): react_jsx_runtime.JSX.Element;
408
671
 
409
672
  type FileUploadStatus = "added" | "queued" | "uploading" | "done" | "error";
410
673
  /** One file in the list: the page's own (`files`), or FileUpload's (the file was picked here). */
@@ -1049,20 +1312,72 @@ interface TableProps {
1049
1312
  }
1050
1313
  declare function Table({ columns: columnsProp, data, className, sortable, sortKey: controlledSortKey, sortDir: controlledSortDir, onSortChange, selectable, selectedRows, onSelectionChange, expandable, renderExpanded, rowKey, expandedRows: expandedRowsProp, defaultExpandedRows, onExpandedChange, density, stickyHeader, striped, loading, emptyState, onRowClick, mobileBreakpoint: mobileBreakpointProp, cardsBelow, pager, title, description, actions, "aria-label": ariaLabel, ref, }: TableProps): string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | react.ReactPortal | react.ReactElement<unknown, string | react.JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | react_jsx_runtime.JSX.Element | null | undefined;
1051
1314
 
1315
+ /** Someone attending an event: their name shows in the event's card (gridsmith-ui 0.26.0 or later). */
1316
+ interface CalendarEventAttendee {
1317
+ name: string;
1318
+ /** Shown in their avatar; their name's initials when left out. */
1319
+ initials?: string;
1320
+ }
1052
1321
  interface CalendarEvent {
1053
1322
  id: string;
1054
1323
  title: string;
1055
1324
  start: Date;
1325
+ /**
1326
+ * An all-day event's last day ("7 to 9 September" ends on the 9th); a timed event's end, which it doesn't include:
1327
+ * one ending at midnight ends the day before.
1328
+ */
1056
1329
  end?: Date;
1057
1330
  allDay?: boolean;
1331
+ /** A key of the Calendar's `categories`. */
1058
1332
  category?: string;
1059
1333
  description?: string;
1060
1334
  location?: string;
1335
+ /** The people attending, named in the event's card (gridsmith-ui 0.26.0 or later). */
1336
+ attendees?: CalendarEventAttendee[];
1337
+ /**
1338
+ * How it repeats (gridsmith-ui 0.27.0 or later): the rule RecurrencePicker gives, or an iCalendar RRULE string from
1339
+ * another app ("RRULE:FREQ=WEEKLY;BYDAY=TU,TH"). The Calendar draws every occurrence in every view; a rule it can't read
1340
+ * draws the event once, its card saying it repeats. A field of the app's own named `recurrence` is not read.
1341
+ */
1342
+ repeat?: Recurrence | string;
1343
+ /** The dates a repeating event leaves out, as day keys in local time ("2026-10-20"): an occurrence deleted or moved. */
1344
+ exceptions?: string[];
1345
+ /**
1346
+ * On an occurrence of a repeating event: its series' id and its original date. The Calendar hands each occurrence to
1347
+ * eventActions and onEventClick with it, under its own id, "<series id>::<date>". An occurrence changed on its own
1348
+ * ("This event") keeps it too, stored by the page under an id of its own: the Calendar draws it in its date's place and
1349
+ * its card names the series' schedule. saveOccurrence and deleteOccurrence take either.
1350
+ */
1351
+ series?: {
1352
+ id: string;
1353
+ date: string;
1354
+ };
1061
1355
  }
1356
+ /**
1357
+ * An event type's colour (gridsmith-ui 0.26.0 or later): one of the theme's supporting colours by number (1 to 5, as
1358
+ * Badge's palette colours), "accent" or "neutral". Its events draw in that colour's readable pair, as a rota's shifts do:
1359
+ * the pale fill, the deep text, the colour on the edge. A supporting colour's token written as a CSS colour
1360
+ * ("var(--ds-palette-2-bold)") is read as that colour, and so is a chart colour ("var(--ds-chart-1)" the accent,
1361
+ * "var(--ds-chart-3)" supporting colour 2), so a legend can draw the same string; any other CSS colour draws on the
1362
+ * neutral pair, the colour on its edge only, so its text always reads.
1363
+ */
1364
+ type CalendarColour = number | "accent" | "neutral" | (string & {});
1062
1365
  interface EventCategory {
1063
- color: string;
1366
+ color: CalendarColour;
1064
1367
  label: string;
1065
1368
  }
1369
+ /** A button in an event's card (gridsmith-ui 0.26.0 or later): the card closes, gives focus back to the event, then runs it. */
1370
+ interface CalendarEventAction {
1371
+ label: string;
1372
+ onClick: (event: CalendarEvent) => void;
1373
+ variant?: "default" | "secondary" | "outline" | "ghost" | "destructive";
1374
+ /** An icon name ("edit"), drawn as the theme's icon, or an element. */
1375
+ iconLeft?: IconSlot;
1376
+ }
1377
+ /** Where a day or a time was chosen: `time` is "HH:mm", from the week view's hours (an hour's lower half gives :30). */
1378
+ interface CalendarDayClickDetail {
1379
+ time?: string;
1380
+ }
1066
1381
  type CalendarView = "month" | "week" | "year";
1067
1382
  type CalendarSize = "default" | "compact";
1068
1383
  interface CalendarProps {
@@ -1070,6 +1385,11 @@ interface CalendarProps {
1070
1385
  view?: CalendarView;
1071
1386
  defaultView?: CalendarView;
1072
1387
  onViewChange?: (view: CalendarView) => void;
1388
+ /**
1389
+ * The date shown (its month, week or year). A Date is an instant, whose day is the visitor's (midnight on a server in
1390
+ * UTC is the evening before in New York), so on a server-rendered page the Calendar holds its place, at its size, until
1391
+ * the browser has the page, and draws then (gridsmith-ui 0.27.0).
1392
+ */
1073
1393
  date?: Date;
1074
1394
  defaultDate?: Date;
1075
1395
  onDateChange?: (date: Date) => void;
@@ -1077,15 +1397,33 @@ interface CalendarProps {
1077
1397
  start: Date;
1078
1398
  end: Date;
1079
1399
  }) => void;
1400
+ /**
1401
+ * A page that opens its own surface for an event (a page of its own, a drawer): the Calendar's card is then not shown.
1402
+ * Leave it out for the card, and put the page's buttons in `eventActions`.
1403
+ */
1080
1404
  onEventClick?: (event: CalendarEvent) => void;
1081
- onDayClick?: (date: Date) => void;
1405
+ /**
1406
+ * A day or a time chosen to start an event: a month's day, a week's day, or (gridsmith-ui 0.26.0 or later) a week's
1407
+ * hour, with its time. `date` is the day at midnight. By keyboard: Enter or Space on a day or an hour.
1408
+ */
1409
+ onDayClick?: (date: Date, detail?: CalendarDayClickDetail) => void;
1410
+ /**
1411
+ * The buttons in an event's card (gridsmith-ui 0.26.0 or later), where Edit goes: the same for every event, or worked
1412
+ * out for each (none for one the user can't change).
1413
+ */
1414
+ eventActions?: CalendarEventAction[] | ((event: CalendarEvent) => CalendarEventAction[]);
1082
1415
  categories?: Record<string, EventCategory>;
1083
- weekStartsOn?: 0 | 1;
1416
+ /**
1417
+ * The week's first day, Sunday 0 to Saturday 6. Default: the first day of the visitor's week, from their browser's
1418
+ * languages, then the page's language, then Monday (gridsmith-ui 0.27.0; Monday before). On a server-rendered page the
1419
+ * Calendar is drawn once the browser has the page (its days are the visitor's), so its week is the browser's.
1420
+ */
1421
+ weekStartsOn?: Weekday;
1084
1422
  size?: CalendarSize;
1085
1423
  className?: string;
1086
1424
  }
1087
1425
 
1088
- declare function Calendar({ events, view: controlledView, defaultView, onViewChange, date: controlledDate, defaultDate, onDateChange, onDateRangeChange, onEventClick, onDayClick, categories, weekStartsOn, size, className, }: CalendarProps): react_jsx_runtime.JSX.Element;
1426
+ declare function Calendar({ events, view: controlledView, defaultView, onViewChange, date: controlledDate, defaultDate, onDateChange, onDateRangeChange, onEventClick, onDayClick, eventActions, categories, weekStartsOn: weekStartsOnProp, size, className, }: CalendarProps): react_jsx_runtime.JSX.Element;
1089
1427
 
1090
1428
  type BadgeVariant = "default" | "neutral" | "subtle" | "success" | "success-soft" | "warning" | "warning-soft" | "error" | "error-soft" | "outline";
1091
1429
  type BadgeSize = "xs" | "sm" | "md";
@@ -1669,10 +2007,12 @@ interface StackedListProps {
1669
2007
  declare const StackedList: react.ForwardRefExoticComponent<StackedListProps & react.RefAttributes<HTMLUListElement>>;
1670
2008
 
1671
2009
  /**
1672
- * Dates on a time axis (Sprint 25.7, Part D). A calendar day is a whole-number day index: days since 1970-01-01,
1673
- * counted on UTC day boundaries, so every day is the same width and a clock change never stretches or shrinks one.
1674
- * A "YYYY-MM-DD" string is a calendar day in the user's zone and is never parsed as UTC (new Date("2026-03-03") is
1675
- * 2 March, 19:00 in New York). Tick labels come from Intl in the locale, longest form first.
2010
+ * Calendar days, and ranges of them in words (Sprint 25.7, Part D). A calendar day is a whole-number day index: days since
2011
+ * 1970-01-01, counted on UTC day boundaries, so every day is the same width and a clock change never stretches or shrinks
2012
+ * one. A "YYYY-MM-DD" string is a calendar day in the user's zone and is never parsed as UTC (new Date("2026-03-03") is
2013
+ * 2 March, 19:00 in New York). Apart from the time scale (lib/time-scale.ts) since Sprint 25.22, so a server can call
2014
+ * them: nothing here needs React or a browser, and `gridsmith-ui/utils` exports them for server code. On a server a Date
2015
+ * or a date-time string is read in the server's time zone; a calendar day or a day index is the same everywhere.
1676
2016
  */
1677
2017
  /** A Date, or a string: "YYYY-MM-DD" is a calendar day; any other string is a date-time. */
1678
2018
  type DateInput = Date | string;
@@ -1693,6 +2033,37 @@ declare function dateOfDay(day: number): Date;
1693
2033
  * index does. A range's start can make a midnight Date half-open too (scale.span, formatDateRange, timeExtent).
1694
2034
  */
1695
2035
  declare function endDayOf(value: DateInput | number): number;
2036
+ /**
2037
+ * The earliest start and the latest end of some ranges, as day indices for useTimeScale: the end is where the last
2038
+ * range stops (inclusive for a whole day, as endDayOf), and a range with no end ends where it starts (a milestone).
2039
+ * NaN for no dated range, which the scale shows as today. A range, a start or an end that is null is skipped.
2040
+ */
2041
+ declare function timeExtent(ranges: Iterable<{
2042
+ start: DateInput;
2043
+ end?: DateInput;
2044
+ }>): {
2045
+ start: number;
2046
+ end: number;
2047
+ };
2048
+ interface DateRangeWords {
2049
+ locale?: string;
2050
+ /** Joins the two ends in place of Intl's separator. Default " to " in English, and Intl's own separator elsewhere. */
2051
+ to?: string;
2052
+ /** Intl options for the days. Default { day: "numeric", month: "long" }; the year is added when the ends' years differ. */
2053
+ day?: Intl.DateTimeFormatOptions;
2054
+ /** Intl options for the times of a date-time range. Default { hour: "2-digit", minute: "2-digit" }. */
2055
+ time?: Intl.DateTimeFormatOptions;
2056
+ }
2057
+ /**
2058
+ * A range in words, in the locale, for accessible names: "3 to 14 March", "28 September to 3 October", "16 September"
2059
+ * for one day. The end is inclusive for a whole day, as scale.span (a day index is where the range stops). A date-time
2060
+ * range is named by its times, and the end's day only when it differs: "Friday 23 October, 06:00 to 14:00". Intl
2061
+ * joins each day and time in the locale's own way, and outside English the two ends too ("10/31(土曜日)~11/01(日曜日)");
2062
+ * the year shows when the two ends are in different years. A null end is the start's own day; a start that is no date
2063
+ * gives "".
2064
+ */
2065
+ declare function formatDateRange(start: DateInput | number, end?: DateInput | number, words?: DateRangeWords): string;
2066
+
1696
2067
  interface TimeTick {
1697
2068
  /** Stable: "2026-09" for September 2026, "2026-09-07" for a day or the week starting on it, "2026-Q3", "2026". */
1698
2069
  key: string;
@@ -1745,7 +2116,7 @@ interface TimeScale {
1745
2116
  today: number | null;
1746
2117
  /** The moment `today` names, as a fractional day index (its time of day), when the scale shows it: an hourly view's "now". */
1747
2118
  now: number | null;
1748
- weekStartsOn: 0 | 1;
2119
+ weekStartsOn: Weekday;
1749
2120
  locale?: string;
1750
2121
  }
1751
2122
  interface TimeScaleOptions {
@@ -1759,9 +2130,18 @@ interface TimeScaleOptions {
1759
2130
  * hydrates its HTML, draw no today. Demos and tests pass a fixed date; a date-time gives an hourly view its "now".
1760
2131
  */
1761
2132
  today?: DateInput;
1762
- /** Default 1 (Monday), as Calendar's. */
1763
- weekStartsOn?: 0 | 1;
1764
- /** Default the page's language (its `lang`, in the visitor's formats where they speak it: formatLocale). */
2133
+ /**
2134
+ * The week's first day, Sunday 0 to Saturday 6. Default: the first day where `locale` is spoken, else the visitor's
2135
+ * (their browser's languages, then the page's language, then Monday), as the Calendar's (gridsmith-ui 0.27.0; Monday
2136
+ * before). On a server, useTimeScale starts the week on the day of the visitor's language from the request (a
2137
+ * LocaleProvider given the Accept-Language header), else Monday, and the browser's own day applies once it has the page;
2138
+ * createTimeScale, with no render to wait for, reads it when called (Monday on a server).
2139
+ */
2140
+ weekStartsOn?: Weekday;
2141
+ /**
2142
+ * Default the page's language in the visitor's formats where they speak it: on a server and while the browser hydrates
2143
+ * the server's HTML, the LocaleProvider's choice (else "en"); then the browser's own reading (useFormatLocale).
2144
+ */
1765
2145
  locale?: string;
1766
2146
  /** Px per day at each level, where a view needs another density (the defaults fit each level's labels). */
1767
2147
  pxPerDay?: Partial<Record<TimeZoom, number>>;
@@ -1772,37 +2152,7 @@ interface TimeScaleOptions {
1772
2152
  * Maps dates to pixels and back in calendar days, and makes the major and minor ticks for the zoom level. The scale
1773
2153
  * is the same object while its inputs mean the same days, so a Date made on every render does not rebuild it.
1774
2154
  */
1775
- declare function useTimeScale({ start, end, zoom, today, weekStartsOn, locale, pxPerDay, pad }: TimeScaleOptions): TimeScale;
1776
- /**
1777
- * The earliest start and the latest end of some ranges, as day indices for useTimeScale: the end is where the last
1778
- * range stops (inclusive for a whole day, as endDayOf), and a range with no end ends where it starts (a milestone).
1779
- * NaN for no dated range, which the scale shows as today. A range, a start or an end that is null is skipped.
1780
- */
1781
- declare function timeExtent(ranges: Iterable<{
1782
- start: DateInput;
1783
- end?: DateInput;
1784
- }>): {
1785
- start: number;
1786
- end: number;
1787
- };
1788
- interface DateRangeWords {
1789
- locale?: string;
1790
- /** Joins the two ends in place of Intl's separator. Default " to " in English, and Intl's own separator elsewhere. */
1791
- to?: string;
1792
- /** Intl options for the days. Default { day: "numeric", month: "long" }; the year is added when the ends' years differ. */
1793
- day?: Intl.DateTimeFormatOptions;
1794
- /** Intl options for the times of a date-time range. Default { hour: "2-digit", minute: "2-digit" }. */
1795
- time?: Intl.DateTimeFormatOptions;
1796
- }
1797
- /**
1798
- * A range in words, in the locale, for accessible names: "3 to 14 March", "28 September to 3 October", "16 September"
1799
- * for one day. The end is inclusive for a whole day, as scale.span (a day index is where the range stops). A date-time
1800
- * range is named by its times, and the end's day only when it differs: "Friday 23 October, 06:00 to 14:00". Intl
1801
- * joins each day and time in the locale's own way, and outside English the two ends too ("10/31(土曜日)~11/01(日曜日)");
1802
- * the year shows when the two ends are in different years. A null end is the start's own day; a start that is no date
1803
- * gives "".
1804
- */
1805
- declare function formatDateRange(start: DateInput | number, end?: DateInput | number, words?: DateRangeWords): string;
2155
+ declare function useTimeScale({ start, end, zoom, today, weekStartsOn: own, locale: ownLocale, pxPerDay, pad }: TimeScaleOptions): TimeScale;
1806
2156
 
1807
2157
  /**
1808
2158
  * What a TimeViewport gives the things drawn inside it (Sprint 25.7, Part D). The scroll position lives in a store of
@@ -1965,6 +2315,45 @@ interface TimeScaleHeaderProps {
1965
2315
  */
1966
2316
  declare function TimeScaleHeader({ todayLabel, className }: TimeScaleHeaderProps): react_jsx_runtime.JSX.Element;
1967
2317
 
2318
+ interface LocaleProviderProps {
2319
+ /**
2320
+ * The page's language: the same value as the app's `<html lang>` ("en"), from one constant, so the two never drift
2321
+ * apart. Required (the review): a provider without it wrote the page in English even where `<html lang>` said otherwise.
2322
+ */
2323
+ lang: string;
2324
+ /**
2325
+ * The request's `Accept-Language` header, as sent (`(await headers()).get("accept-language")` in a Next.js root layout,
2326
+ * `request.headers.get("accept-language")` in a Remix root loader). Left out (a static export, Remix in SPA mode), the
2327
+ * server writes the page's language, and the browser the visitor's form of it once the page has loaded.
2328
+ */
2329
+ acceptLanguage?: string | null;
2330
+ children?: ReactNode;
2331
+ }
2332
+ /**
2333
+ * The page's language and the visitor's, for a server-rendered app (Sprint 25.20 D1): put at the top of the app, it lets
2334
+ * the server write every date and number in the visitor's form of the page's language ("6 Oct 2026" for a British visitor
2335
+ * to an English page), and the browser hydrate with the same, so nothing changes once the page has loaded. A Vite app,
2336
+ * drawn in the browser alone, doesn't need it.
2337
+ */
2338
+ declare function LocaleProvider({ lang, acceptLanguage, children }: LocaleProviderProps): react_jsx_runtime.JSX.Element;
2339
+
2340
+ /**
2341
+ * The locale a component writes its dates and numbers in (Sprint 25.20 L1). On a server, and while the browser hydrates
2342
+ * the server's HTML, the one the server chose: LocaleProvider's (the visitor's form of the page's language, from the
2343
+ * request), else "en", never a machine's own default, so both sides write the same. Once the page has loaded, the
2344
+ * browser's own reading (the visitor's form of the page's `lang`, as formatLocale() reads it), usually the same. A render
2345
+ * with no server HTML reads the browser's from its first render. Undefined is the browser's own language.
2346
+ */
2347
+ declare function useFormatLocale(): string | undefined;
2348
+
2349
+ /**
2350
+ * Whether the browser has taken the page over (Sprint 25.20 D3): false on a server, and in the render that hydrates the
2351
+ * server's HTML (it must draw what the server drew), true straight after. A render with no server HTML (a Vite app, a
2352
+ * component mounted later) is true from its first render. What depends on the visitor's clock or time zone, which no
2353
+ * server knows, waits for it.
2354
+ */
2355
+ declare function useHydrated(): boolean;
2356
+
1968
2357
  /**
1969
2358
  * Labels along a scale that never overlap (Sprint 25.7, Part D; data-visualisation#7). Each label gets the longest form
1970
2359
  * that fits its box ("September" → "Sept" → "S"), one form along the row; when even the shortest does not fit, the row
@@ -2017,7 +2406,7 @@ declare function fitLabel(labels: readonly string[], width: number, measure: (te
2017
2406
  * web fonts finish loading. Give it an element whose size follows its text (a span holding a character, out of sight),
2018
2407
  * not a box of fixed size: its resize is how a change of text size (the theme's base size, a class up the tree) is seen.
2019
2408
  */
2020
- declare function useTextMeasure(ref: RefObject<HTMLElement | null>): (text: string) => number;
2409
+ declare function useTextMeasure(ref: RefObject<HTMLElement | null>, active?: boolean): (text: string) => number;
2021
2410
  /** fitLabels in the computed font of `ref`, the row the labels are drawn in. */
2022
2411
  declare function useFittedLabels(boxes: readonly LabelBox[], ref: RefObject<HTMLElement | null>, options?: FitLabelsOptions): FittedLabel[];
2023
2412
 
@@ -2118,8 +2507,8 @@ interface GanttProps<T extends GanttItem = GanttItem> {
2118
2507
  onZoomChange?: (zoom: TimeZoom) => void;
2119
2508
  /** Default now; demos and tests pass a fixed date. */
2120
2509
  today?: DateInput;
2121
- /** Default 1 (Monday), as Calendar's. */
2122
- weekStartsOn?: 0 | 1;
2510
+ /** The week's first day, Sunday 0 to Saturday 6. Default: the first day of the visitor's week, from their browser's languages, then the page's language, then Monday (gridsmith-ui 0.27.0); with `locale`, that language's. As the Calendar's. */
2511
+ weekStartsOn?: Weekday;
2123
2512
  /** Default the page's language (its `lang`, in the visitor's formats where they speak it): the scale's labels and the items' dates. */
2124
2513
  locale?: string;
2125
2514
  /**
@@ -2209,7 +2598,7 @@ interface LauncherProps {
2209
2598
  align?: "center" | "end";
2210
2599
  /** Accessible name for every variant; visible text for pill and ribbon. */
2211
2600
  label: string;
2212
- /** bubble and pill default to "sparkles" (curated; the Feather pack substitutes a star). A ribbon shows only its label unless an icon is given. */
2601
+ /** bubble and pill default to "sparkles" (curated; a Feather theme draws Lucide's, as Feather has none). A ribbon shows only its label unless an icon is given. */
2213
2602
  icon?: IconName | ReactNode;
2214
2603
  /** Unread count (number) or a dot (true). */
2215
2604
  badge?: number | boolean;
@@ -2414,12 +2803,20 @@ interface Step {
2414
2803
  label: string;
2415
2804
  description?: string;
2416
2805
  status?: "complete" | "error" | "loading";
2417
- /** Not reached yet, so it can't be gone to: its circle can't be pressed (Sprint 25.16 A30, useFlowSteps' stepper). */
2806
+ /**
2807
+ * Not reached yet, so it can't be gone to (Sprint 25.16 A30, useFlowSteps' stepper): its circle is greyed, can't be
2808
+ * pressed, and is named "cannot start yet" (Sprint 25.19 S3, the owner's D10).
2809
+ */
2418
2810
  disabled?: boolean;
2419
2811
  }
2420
2812
  interface StepperProps {
2421
2813
  steps: Step[];
2422
2814
  currentStep: number;
2815
+ /**
2816
+ * Goes to a step. Pass it and every step not `disabled` is a button, backwards or forwards (the owner's D10: a step
2817
+ * already reached opens from its number). Mark the steps not reached yet `disabled` rather than ignoring their click;
2818
+ * useFlowSteps does both. Leave it out and the Stepper only shows progress: none of its steps is a button.
2819
+ */
2423
2820
  onStepChange?: (step: number) => void;
2424
2821
  orientation?: "horizontal" | "vertical";
2425
2822
  className?: string;
@@ -2568,6 +2965,7 @@ type PageHeaderBehavior = "static" | "snapping";
2568
2965
  type PageHeaderIntensity = "subtle" | "bold";
2569
2966
  interface PageHeaderProps {
2570
2967
  title: string;
2968
+ /** A line under the title. The minimal header doesn't show it (Sprint 25.21 H2: it's minimal for a reason). */
2571
2969
  description?: string;
2572
2970
  /**
2573
2971
  * A short line above the title: the section the page belongs to, or its place in a flow ("Step 2 of 6") — GOV.UK's
@@ -3392,9 +3790,12 @@ interface FlowSteps<A, S extends FlowStep<A>> {
3392
3790
  next: (patch?: Partial<A>) => void;
3393
3791
  /** PageHeader's onBack: the step before, or undefined on the first step (no Back link there). */
3394
3792
  back: (() => void) | undefined;
3395
- /** Goes to a step reached; any other is ignored. */
3793
+ /** Goes to a step reached, backwards only when the project lets a flow go back (forms.canNavigateBack); any other is ignored. */
3396
3794
  goTo: (step: number) => void;
3397
- /** The Stepper's props: the steps shown (done before the furthest, and a step past it can't be pressed), this one, and going to one. */
3795
+ /**
3796
+ * The Stepper's props: the steps shown (done before the furthest; a step past it disabled, so the Stepper greys it and
3797
+ * names it "cannot start yet"), this one, and going to one: any step reached opens, backwards or forwards.
3798
+ */
3398
3799
  stepper: {
3399
3800
  steps: {
3400
3801
  label: string;
@@ -3402,7 +3803,8 @@ interface FlowSteps<A, S extends FlowStep<A>> {
3402
3803
  disabled?: boolean;
3403
3804
  }[];
3404
3805
  currentStep: number;
3405
- onStepChange: (index: number) => void;
3806
+ /** Goes to a step already reached; undefined when the project doesn't let a flow go back (the list then shows progress). */
3807
+ onStepChange?: (index: number) => void;
3406
3808
  };
3407
3809
  /** Keeps the progress and leaves the flow, for exitTo. */
3408
3810
  saveAndExit: () => void;
@@ -3693,4 +4095,4 @@ interface UseTextOverflowResult {
3693
4095
  */
3694
4096
  declare function useTextOverflow(options?: UseTextOverflowOptions): UseTextOverflowResult;
3695
4097
 
3696
- export { Accordion, ActionPanel, ActionPanelGroup, AddAnother, type AddAnotherProps, Alert, type AlertPlacement, AppShell, type AppShellContextValue, type AppShellFocus, AppShellPreferences, type AppShellTheme, AsidePanel, type AsidePanelProps, type AsidePanelSide, Avatar, AvatarGroup, type AvatarGroupItem, type AvatarGroupProps, type AvatarStatus, Badge, type BadgePaletteColor, type BadgeSeverity, type BadgeSize, type BadgeVariant, BottomNav, type BottomNavItem, BreakpointKey, BulkActionBar, Button, ButtonSizeContext, Calendar, type CalendarDay, Card, CardContent, CardDescription, CardFooter, CardGrid, type CardGridProps, CardHeader, type CardSelectType, CardTitle, type CardVariant, Carousel, type ChatMessage, type ChatMessageAction, type ChatMessageLayout, ChatMessageList, type ChatMessageSender, type ChatMessageSource, type ChatMessageStatus, ChatPanel, type ChatPanelProps, type ChatPanelStatusTone, Checkbox, CheckboxGroup, CheckboxGroupItem, CodeBlock, Collapsible, ColorPicker, type Column, Combobox, CommandPalette, ContextMenu, type ControlSize, ControlSizeContext, CornerPanel, type CornerPanelEdge, type CornerPanelProps, DEFAULT_DATE_RANGE_PRESETS, DangerZone, type DangerZoneProps, DataList, type DateInput, DatePicker, type DateRange, DateRangePicker, type DateRangePickerProps, type DateRangePreset, type DateRangeWords, type DescriptionItem, DescriptionList, type DescriptionListOrientation, type DescriptionListSize, type DestructiveActionHandle, type DestructiveActionOptions, Dialog, Divider, Dock, Drawer, Dropdown, DropdownMenu, type DropdownMenuDivider, type DropdownMenuEntry, type DropdownMenuItem, EmptyState, EntityCell, Field, type FieldControlProps, type FieldLabel, type FieldProps, FileUpload, type FileUploadItem, type FileUploadRequestOptions, type FileUploadStatus, type FitLabelsOptions, type FittedLabel, type FlowNavigate, type FlowProgress, FlowSaved, type FlowSavedProps, type FlowStep, type FlowSteps, FormWrapper, Gantt, type GanttGroup, type GanttItem, type GanttProps, type GanttStatus, type GanttTone, type GridKeyboard, type GridKeyboardOptions, HoverCard, InlineFieldError, Input, Kbd, Label, type LabelBox, Launcher, type LauncherEdge, type LauncherProps, type LauncherVariant, type LauncherWhenOpen, Link, type LinkProps, MentionInput, type MentionInputProps, MentionSuggestion, MobileHeaderMenu, type MobileHeaderMenuItemData, type MobileHeaderMenuType, NavItem, type NavItemProps, type NavItemType, NavMenu, type NavMenuItem, Navbar, type NavbarSize, type NavbarType, type NavbarVariant, NotificationCenter, NumberInput, PageActions, PageContainer, type PageContainerWidth, PageHeader, type PageHeaderBehavior, type PageHeaderIntensity, type PageHeaderProps, type PageHeaderVariant, Pager, Pagination, PinInput, Popover, Progress, type PromiseToastMessages, RadioGroup, Rating, RelativeTime, type RelativeTimeProps, ScrollArea, SectionHeading, type SectionHeadingProps, SegmentedControl, SettingsLayout, type SettingsLayoutProps, type SettingsSection, Sheet, Sidebar, type SidebarContextValue, type SidebarItem, SidebarNav, type SidebarNavSize, type SidebarPosition, type SidebarSection, type SidebarType, Skeleton, SkipLink, SliderRange, type SortDir, Spinner, StackedList, type StackedListVariant, StatsCard, StatusDot, type StatusDotVariant, Stepper, TIME_ZOOMS, type Tab, Table, type TableDensity, type TableProps, type TableRow, TableToolbar, type TableToolbarActiveFilter, type TableToolbarFilterOption, Tabs, Tag, TagInput, type TagPaletteColor, type TagVariant, TextOverflow, type TextOverflowProps, Textarea, TimeBar, type TimeBarProps, TimePicker, TimeRow, type TimeRowProps, type TimeScale, TimeScaleHeader, type TimeScaleHeaderProps, type TimeScaleOptions, type TimeTick, type TimeValue, TimeViewport, type TimeViewportHandle, type TimeViewportLayout, type TimeViewportProps, type TimeViewportState, type TimeZoom, Timeline, TimezoneSelect, type TimezoneSelectProps, Toast, type ToastAction, type ToastApi, type ToastOptions, type ToastPosition, ToastProvider, type ToastVariant, Toggle, Tooltip, Tour, TransferList, TreeView, type Trend, type UseFlowStepsOptions, type UseTextOverflowOptions, type UseTextOverflowResult, browserTimeZone, canonicalTimeZone, dateOfDay, dayOf, endDayOf, fitLabel, fitLabels, formatDateRange, formatFullTime, formatRelativeTime, readFlowProgress, timeExtent, timeZoneOffset, useAppShell, useContentWidth, useDestructiveAction, useFittedLabels, useFlowSteps, useFormContext, useGridKeyboard, useRelativeTimeFormat, useSidebar, useTextMeasure, useTextOverflow, useTimeScale, useTimeViewport, useTimeViewportLayout, useToast, useToastOptional, useUnsavedChanges };
4098
+ export { Accordion, ActionPanel, ActionPanelGroup, AddAnother, type AddAnotherProps, Alert, type AlertPlacement, AppShell, type AppShellContextValue, type AppShellFocus, AppShellPreferences, type AppShellTheme, AsidePanel, type AsidePanelProps, type AsidePanelSide, Avatar, AvatarGroup, type AvatarGroupItem, type AvatarGroupProps, type AvatarStatus, Badge, type BadgePaletteColor, type BadgeSeverity, type BadgeSize, type BadgeVariant, BottomNav, type BottomNavItem, BreakpointKey, BulkActionBar, Button, ButtonSizeContext, Calendar, type CalendarColour, type CalendarDay, type CalendarDayClickDetail, type CalendarEvent, type CalendarEventAction, type CalendarEventAttendee, type CalendarProps, type CalendarSize, type CalendarView, Card, CardContent, CardDescription, CardFooter, CardGrid, type CardGridProps, CardHeader, type CardSelectType, CardTitle, type CardVariant, Carousel, type ChatMessage, type ChatMessageAction, type ChatMessageLayout, ChatMessageList, type ChatMessageSender, type ChatMessageSource, type ChatMessageStatus, ChatPanel, type ChatPanelProps, type ChatPanelStatusTone, Checkbox, CheckboxGroup, CheckboxGroupItem, CodeBlock, Collapsible, CollapsibleContent, CollapsibleTrigger, ColorPicker, type Column, Combobox, CommandPalette, ContextMenu, type ControlSize, ControlSizeContext, CornerPanel, type CornerPanelEdge, type CornerPanelProps, DEFAULT_DATE_RANGE_PRESETS, DangerZone, type DangerZoneProps, DataList, type DateInput, DatePicker, type DateRange, DateRangePicker, type DateRangePickerProps, type DateRangePreset, type DateRangeWords, type DescriptionItem, DescriptionList, type DescriptionListOrientation, type DescriptionListSize, type DestructiveActionHandle, type DestructiveActionOptions, Dialog, Divider, Dock, Drawer, Dropdown, DropdownMenu, type DropdownMenuDivider, type DropdownMenuEntry, type DropdownMenuItem, EmptyState, EntityCell, type EventCategory, Field, type FieldControlProps, type FieldLabel, type FieldProps, FileUpload, type FileUploadItem, type FileUploadRequestOptions, type FileUploadStatus, type FitLabelsOptions, type FittedLabel, type FlowNavigate, type FlowProgress, FlowSaved, type FlowSavedProps, type FlowStep, type FlowSteps, FormWrapper, Gantt, type GanttGroup, type GanttItem, type GanttProps, type GanttStatus, type GanttTone, type GridKeyboard, type GridKeyboardOptions, HoverCard, InlineFieldError, Input, Kbd, Label, type LabelBox, Launcher, type LauncherEdge, type LauncherProps, type LauncherVariant, type LauncherWhenOpen, Link, type LinkProps, LocaleProvider, type LocaleProviderProps, MentionInput, type MentionInputProps, MentionSuggestion, MobileHeaderMenu, type MobileHeaderMenuItemData, type MobileHeaderMenuType, NavItem, type NavItemProps, type NavItemType, NavMenu, type NavMenuItem, Navbar, type NavbarSize, type NavbarType, type NavbarVariant, NotificationCenter, NumberInput, type Occurrence, PageActions, PageContainer, type PageContainerWidth, PageHeader, type PageHeaderBehavior, type PageHeaderIntensity, type PageHeaderProps, type PageHeaderVariant, Pager, Pagination, PinInput, Popover, Progress, type PromiseToastMessages, RadioGroup, Rating, type Recurrence, type RecurrenceFrequency, RecurrencePicker, type RecurrencePickerProps, type RecurrencePreset, type RecurrenceScope, RecurrenceScopeDialog, type RecurrenceScopeDialogProps, RelativeTime, type RelativeTimeProps, type RepeatChange, type RepeatingEvent, ScrollArea, SectionHeading, type SectionHeadingProps, SegmentedControl, SettingsLayout, type SettingsLayoutProps, type SettingsSection, Sheet, Sidebar, type SidebarContextValue, type SidebarItem, SidebarNav, type SidebarNavSize, type SidebarPosition, type SidebarSection, type SidebarType, Skeleton, SkipLink, SliderRange, type SortDir, Spinner, StackedList, type StackedListVariant, StatsCard, StatusDot, type StatusDotVariant, Stepper, TIME_ZOOMS, type Tab, Table, type TableDensity, type TableProps, type TableRow, TableToolbar, type TableToolbarActiveFilter, type TableToolbarFilterOption, Tabs, TabsContent, TabsList, TabsTrigger, Tag, TagInput, type TagPaletteColor, type TagVariant, TextOverflow, type TextOverflowProps, Textarea, TimeBar, type TimeBarProps, TimePicker, TimeRow, type TimeRowProps, type TimeScale, TimeScaleHeader, type TimeScaleHeaderProps, type TimeScaleOptions, type TimeTick, type TimeValue, TimeViewport, type TimeViewportHandle, type TimeViewportLayout, type TimeViewportProps, type TimeViewportState, type TimeZoom, Timeline, TimezoneSelect, type TimezoneSelectProps, Toast, type ToastAction, type ToastApi, type ToastOptions, type ToastPosition, ToastProvider, type ToastVariant, Toggle, Tooltip, Tour, TransferList, TreeView, type Trend, type UseFlowStepsOptions, type UseTextOverflowOptions, type UseTextOverflowResult, type WeekOfMonth, type Weekday, browserTimeZone, canonicalTimeZone, countEdited, dateOfDay, dayOf, deleteOccurrence, describeRecurrence, endDayOf, fitLabel, fitLabels, formatDateRange, formatFullTime, formatRelativeTime, nthOf, occurrenceOn, occurrences, parseRRule, readFlowProgress, readRecurrence, recurrencePresets, sameRecurrence, saveOccurrence, timeExtent, timeZoneOffset, toRRule, useAppShell, useBrowserTimeZone, useContentWidth, useDestructiveAction, useFittedLabels, useFlowSteps, useFormContext, useFormatLocale, useGridKeyboard, useHydrated, useRelativeTimeFormat, useSidebar, useTextMeasure, useTextOverflow, useTimeScale, useTimeViewport, useTimeViewportLayout, useToast, useToastOptional, useUnsavedChanges };