@eifi1/ui-kit 0.52.0 → 0.54.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.
- package/README.md +52 -59
- package/dist/account/delete-account-setting.d.ts +3 -2
- package/dist/account/delete-account-setting.js.map +1 -1
- package/dist/auth/auth-errors.d.ts +36 -0
- package/dist/auth/auth-errors.js +20 -0
- package/dist/auth/auth-errors.js.map +1 -1
- package/dist/billing/cancel-subscription.d.ts +5 -14
- package/dist/billing/cancel-subscription.js +1 -3
- package/dist/billing/cancel-subscription.js.map +1 -1
- package/dist/billing/plan-card.d.ts +5 -13
- package/dist/billing/plan-card.js +3 -11
- package/dist/billing/plan-card.js.map +1 -1
- package/dist/billing/plan-switch.d.ts +5 -14
- package/dist/billing/plan-switch.js +1 -3
- package/dist/billing/plan-switch.js.map +1 -1
- package/dist/chart.d.ts +3 -14
- package/dist/chart.js +64 -11
- package/dist/chart.js.map +1 -1
- package/dist/components/amount-input.d.ts +2 -1
- package/dist/components/amount-input.js.map +1 -1
- package/dist/components/calendar-heatmap.js +4 -2
- package/dist/components/calendar-heatmap.js.map +1 -1
- package/dist/components/currency-option-list.d.ts +2 -1
- package/dist/components/currency-option-list.js +10 -3
- package/dist/components/currency-option-list.js.map +1 -1
- package/dist/components/currency-select.d.ts +3 -1
- package/dist/components/currency-select.js.map +1 -1
- package/dist/components/danger-confirm.d.ts +22 -1
- package/dist/components/danger-confirm.js +50 -28
- package/dist/components/danger-confirm.js.map +1 -1
- package/dist/components/data-table-filter-popover.d.ts +2 -1
- package/dist/components/data-table-filter-popover.js +3 -2
- package/dist/components/data-table-filter-popover.js.map +1 -1
- package/dist/components/data-table-filters.d.ts +33 -3
- package/dist/components/data-table-filters.js +6 -4
- package/dist/components/data-table-filters.js.map +1 -1
- package/dist/components/date-field.d.ts +1 -1
- package/dist/components/date-field.js.map +1 -1
- package/dist/components/date-picker.d.ts +1 -1
- package/dist/components/date-picker.js.map +1 -1
- package/dist/components/date-range-picker.d.ts +4 -17
- package/dist/components/date-range-picker.js +2 -2
- package/dist/components/date-range-picker.js.map +1 -1
- package/dist/components/dialog-frame.d.ts +3 -1
- package/dist/components/dialog-frame.js +6 -2
- package/dist/components/dialog-frame.js.map +1 -1
- package/dist/components/mini-calendar.js +3 -2
- package/dist/components/mini-calendar.js.map +1 -1
- package/dist/components/modal.d.ts +27 -0
- package/dist/components/modal.js +5 -3
- package/dist/components/modal.js.map +1 -1
- package/dist/components/nav-pills.d.ts +1 -1
- package/dist/components/nav-pills.js.map +1 -1
- package/dist/components/number-input.js.map +1 -1
- package/dist/components/series-chart-axes.d.ts +1 -1
- package/dist/components/series-chart-axes.js.map +1 -1
- package/dist/components/series-chart.d.ts +64 -19
- package/dist/components/series-chart.js +2 -1
- package/dist/components/series-chart.js.map +1 -1
- package/dist/components/stat-tile.d.ts +21 -2
- package/dist/components/stat-tile.js +4 -2
- package/dist/components/stat-tile.js.map +1 -1
- package/dist/components/treemap-labels.d.ts +6 -1
- package/dist/components/treemap-labels.js +2 -2
- package/dist/components/treemap-labels.js.map +1 -1
- package/dist/components/treemap.d.ts +29 -4
- package/dist/components/treemap.js +22 -9
- package/dist/components/treemap.js.map +1 -1
- package/dist/currencies.d.ts +16 -2
- package/dist/currencies.js +2 -1
- package/dist/currencies.js.map +1 -1
- package/dist/data-table.d.ts +1 -6
- package/dist/data-table.js +1 -9
- package/dist/data-table.js.map +1 -1
- package/dist/demo/demo-countdown.d.ts +0 -5
- package/dist/demo/demo-countdown.js +0 -4
- package/dist/demo/demo-countdown.js.map +1 -1
- package/dist/eslint/index.js +1 -1
- package/dist/feedback/feedback-context-labels.js +2 -1
- package/dist/feedback/feedback-context-labels.js.map +1 -1
- package/dist/feedback/feedback-context.d.ts +19 -3
- package/dist/feedback/feedback-context.js +12 -1
- package/dist/feedback/feedback-context.js.map +1 -1
- package/dist/feedback/feedback-diagnostics.d.ts +17 -0
- package/dist/feedback/feedback-diagnostics.js +27 -0
- package/dist/feedback/feedback-diagnostics.js.map +1 -0
- package/dist/feedback/feedback-dialog.d.ts +10 -0
- package/dist/feedback/feedback-dialog.js +6 -4
- package/dist/feedback/feedback-dialog.js.map +1 -1
- package/dist/feedback/feedback-mutation.d.ts +11 -23
- package/dist/feedback/feedback-mutation.js +1 -9
- package/dist/feedback/feedback-mutation.js.map +1 -1
- package/dist/feedback/feedback-public-list.d.ts +1 -6
- package/dist/feedback/feedback-public-list.js +1 -2
- package/dist/feedback/feedback-public-list.js.map +1 -1
- package/dist/feedback/feedback-record.d.ts +5 -0
- package/dist/feedback/feedback-record.js.map +1 -1
- package/dist/feedback/feedback-row-detail-labels.js +1 -8
- package/dist/feedback/feedback-row-detail-labels.js.map +1 -1
- package/dist/feedback/feedback-row-detail.d.ts +6 -50
- package/dist/feedback/feedback-row-detail.js +3 -8
- package/dist/feedback/feedback-row-detail.js.map +1 -1
- package/dist/feedback/feedback-status-undo.d.ts +3 -19
- package/dist/feedback/feedback-status-undo.js.map +1 -1
- package/dist/feedback/feedback-submit-dialog.d.ts +5 -1
- package/dist/feedback/feedback-submit-dialog.js +15 -3
- package/dist/feedback/feedback-submit-dialog.js.map +1 -1
- package/dist/feedback/feedback-submit.d.ts +30 -2
- package/dist/feedback/feedback-submit.js +5 -2
- package/dist/feedback/feedback-submit.js.map +1 -1
- package/dist/feedback/feedback-thread.d.ts +0 -9
- package/dist/feedback/feedback-thread.js.map +1 -1
- package/dist/feedback.d.ts +6 -40
- package/dist/feedback.js +88 -46
- package/dist/feedback.js.map +1 -1
- package/dist/hooks/use-hotkey.js +11 -1
- package/dist/hooks/use-hotkey.js.map +1 -1
- package/dist/i18n/defaults.js +0 -4
- package/dist/i18n/defaults.js.map +1 -1
- package/dist/i18n/german.js +5 -20
- package/dist/i18n/german.js.map +1 -1
- package/dist/i18n/kit-labels.d.ts +5 -14
- package/dist/i18n/kit-labels.js.map +1 -1
- package/dist/i18n/locales/en.js +5 -31
- package/dist/i18n/locales/en.js.map +3 -3
- package/dist/i18n/locales/es.js +5 -20
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.js +5 -20
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.js +5 -20
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.js +5 -21
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.js +5 -20
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/i18n/review.js +9 -4
- package/dist/i18n/review.js.map +1 -1
- package/dist/i18n/shared-labels.js +0 -1
- package/dist/i18n/shared-labels.js.map +1 -1
- package/dist/index.d.ts +18 -67
- package/dist/index.js +28 -103
- package/dist/index.js.map +1 -1
- package/dist/lib/dates.d.ts +7 -1
- package/dist/lib/dates.js +8 -1
- package/dist/lib/dates.js.map +1 -1
- package/dist/lib/format.d.ts +37 -2
- package/dist/lib/format.js +25 -1
- package/dist/lib/format.js.map +1 -1
- package/dist/lib/intl-cache.d.ts +4 -2
- package/dist/lib/intl-cache.js.map +1 -1
- package/dist/lib/translation-review.d.ts +26 -0
- package/dist/lib/translation-review.js +14 -0
- package/dist/lib/translation-review.js.map +1 -1
- package/dist/rhf/fields.d.ts +2 -2
- package/dist/rhf/fields.js.map +1 -1
- package/dist/search/search-index.d.ts +0 -6
- package/dist/search/search-index.js +0 -4
- package/dist/search/search-index.js.map +1 -1
- package/dist/search.d.ts +1 -8
- package/dist/search.js +2 -7
- package/dist/search.js.map +1 -1
- package/dist/shell/account-menu-language.d.ts +7 -21
- package/dist/shell/account-menu-language.js +1 -3
- package/dist/shell/account-menu-language.js.map +1 -1
- package/dist/shell/account-menu-text-size.d.ts +9 -23
- package/dist/shell/account-menu-text-size.js +2 -3
- package/dist/shell/account-menu-text-size.js.map +1 -1
- package/dist/shell/app-shell.d.ts +0 -10
- package/dist/shell/app-shell.js +1 -7
- package/dist/shell/app-shell.js.map +1 -1
- package/dist/shell/company-switcher.d.ts +1 -1
- package/dist/shell/company-switcher.js.map +1 -1
- package/dist/shell/dev-menu.d.ts +1 -1
- package/dist/shell/dev-menu.js.map +1 -1
- package/dist/shell/top-bar-parts-labels.d.ts +1 -1
- package/dist/shell/top-bar-parts-labels.js.map +1 -1
- package/dist/shell.d.ts +7 -29
- package/dist/shell.js +12 -42
- package/dist/shell.js.map +1 -1
- package/dist/sync.d.ts +2 -6
- package/dist/sync.js +2 -15
- package/dist/sync.js.map +1 -1
- package/dist/theme/chart-palette.d.ts +0 -5
- package/dist/theme/chart-palette.js +0 -2
- package/dist/theme/chart-palette.js.map +1 -1
- package/package.json +1 -1
- package/src/account/delete-account-setting.tsx +3 -2
- package/src/auth/auth-errors.ts +69 -0
- package/src/billing/cancel-subscription.tsx +5 -16
- package/src/billing/plan-card.tsx +7 -24
- package/src/billing/plan-switch.tsx +5 -16
- package/src/chart.ts +62 -13
- package/src/components/amount-input.tsx +2 -1
- package/src/components/calendar-heatmap.tsx +8 -2
- package/src/components/currency-option-list.tsx +12 -4
- package/src/components/currency-select.tsx +3 -1
- package/src/components/danger-confirm.tsx +80 -27
- package/src/components/data-table-filter-popover.tsx +19 -11
- package/src/components/data-table-filters.ts +36 -8
- package/src/components/date-field.tsx +1 -1
- package/src/components/date-picker.tsx +0 -1
- package/src/components/date-range-picker.tsx +6 -22
- package/src/components/dialog-frame.tsx +12 -4
- package/src/components/mini-calendar.tsx +5 -2
- package/src/components/modal.tsx +36 -7
- package/src/components/nav-pills.tsx +1 -1
- package/src/components/number-input.tsx +4 -3
- package/src/components/series-chart-axes.ts +6 -1
- package/src/components/series-chart.tsx +78 -21
- package/src/components/stat-tile.tsx +32 -3
- package/src/components/treemap-labels.ts +11 -3
- package/src/components/treemap.tsx +65 -12
- package/src/currencies.ts +23 -3
- package/src/data-table.ts +1 -11
- package/src/demo/demo-countdown.ts +3 -8
- package/src/feedback/feedback-context-labels.ts +1 -0
- package/src/feedback/feedback-context.tsx +34 -2
- package/src/feedback/feedback-diagnostics.tsx +41 -0
- package/src/feedback/feedback-dialog.tsx +16 -4
- package/src/feedback/feedback-mutation.ts +12 -33
- package/src/feedback/feedback-public-list.tsx +1 -7
- package/src/feedback/feedback-record.ts +5 -0
- package/src/feedback/feedback-row-detail-labels.ts +1 -8
- package/src/feedback/feedback-row-detail.tsx +21 -58
- package/src/feedback/feedback-status-undo.ts +4 -18
- package/src/feedback/feedback-submit-dialog.tsx +15 -2
- package/src/feedback/feedback-submit.tsx +36 -3
- package/src/feedback/feedback-thread.tsx +0 -10
- package/src/feedback.ts +89 -48
- package/src/hooks/use-hotkey.ts +24 -1
- package/src/i18n/defaults.ts +0 -4
- package/src/i18n/german.ts +4 -19
- package/src/i18n/kit-labels.tsx +5 -14
- package/src/i18n/locales/es.ts +4 -19
- package/src/i18n/locales/fr.ts +4 -19
- package/src/i18n/locales/hu.ts +4 -19
- package/src/i18n/locales/it.ts +4 -20
- package/src/i18n/locales/zh.ts +4 -19
- package/src/i18n/review.ts +9 -4
- package/src/i18n/shared-labels.ts +0 -1
- package/src/index.ts +44 -114
- package/src/lib/dates.ts +24 -2
- package/src/lib/format.ts +66 -3
- package/src/lib/intl-cache.ts +4 -2
- package/src/lib/translation-review.ts +52 -0
- package/src/rhf/fields.tsx +2 -2
- package/src/search/search-index.ts +0 -15
- package/src/search.ts +8 -8
- package/src/shell/account-menu-language.tsx +7 -27
- package/src/shell/account-menu-text-size.tsx +13 -32
- package/src/shell/app-shell.tsx +0 -13
- package/src/shell/company-switcher.tsx +1 -1
- package/src/shell/dev-menu.tsx +1 -1
- package/src/shell/top-bar-parts-labels.ts +1 -1
- package/src/shell.ts +17 -44
- package/src/sync.ts +2 -15
- package/src/theme/chart-palette.ts +0 -2
- package/tokens.css +4 -4
- package/dist/billing/dialog-close.d.ts +0 -29
- package/dist/billing/dialog-close.js +0 -8
- package/dist/billing/dialog-close.js.map +0 -1
- package/dist/components/field-sync-labels.d.ts +0 -3
- package/dist/components/field-sync-labels.js +0 -12
- package/dist/components/field-sync-labels.js.map +0 -1
- package/dist/components/field-sync.d.ts +0 -186
- package/dist/components/field-sync.js +0 -269
- package/dist/components/field-sync.js.map +0 -1
- package/dist/components/section-nav.d.ts +0 -44
- package/dist/components/section-nav.js +0 -33
- package/dist/components/section-nav.js.map +0 -1
- package/dist/components/sign-chip-labels.d.ts +0 -3
- package/dist/components/sign-chip-labels.js +0 -11
- package/dist/components/sign-chip-labels.js.map +0 -1
- package/dist/components/sign-chip.d.ts +0 -77
- package/dist/components/sign-chip.js +0 -47
- package/dist/components/sign-chip.js.map +0 -1
- package/dist/lib/isin.d.ts +0 -38
- package/dist/lib/isin.js +0 -36
- package/dist/lib/isin.js.map +0 -1
- package/dist/shell/role-switcher.d.ts +0 -28
- package/dist/shell/role-switcher.js +0 -31
- package/dist/shell/role-switcher.js.map +0 -1
- package/src/billing/dialog-close.ts +0 -34
- package/src/components/field-sync-labels.ts +0 -14
- package/src/components/field-sync.tsx +0 -504
- package/src/components/section-nav.tsx +0 -72
- package/src/components/sign-chip-labels.ts +0 -13
- package/src/components/sign-chip.tsx +0 -133
- package/src/lib/isin.ts +0 -72
- package/src/shell/role-switcher.tsx +0 -53
package/src/index.ts
CHANGED
|
@@ -93,6 +93,10 @@ export {
|
|
|
93
93
|
reviewWrite,
|
|
94
94
|
mergeReviews,
|
|
95
95
|
dropReviews,
|
|
96
|
+
// 0.54: a save or a reset of any size under server-kit's cap of 2000 (kastlan reuse
|
|
97
|
+
// audit 2026-11-02, proposal 5).
|
|
98
|
+
saveReviewsInChunks,
|
|
99
|
+
clearReviewsInChunks,
|
|
96
100
|
translationCorrections,
|
|
97
101
|
// 0.25: grouping and the approvals' Undo (keksdose live #377).
|
|
98
102
|
groupTranslationRows,
|
|
@@ -122,13 +126,11 @@ export type {
|
|
|
122
126
|
TranslationReviewSwipeAction,
|
|
123
127
|
TranslationReviewSwipeBinding,
|
|
124
128
|
} from "./lib/translation-review";
|
|
125
|
-
// 0.22.0, the inputs round: the country list and the IBAN
|
|
129
|
+
// 0.22.0, the inputs round: the country list and the IBAN and phone helpers that
|
|
126
130
|
// CountrySelect, IbanInput and PhoneInput are built on.
|
|
127
131
|
export { COUNTRY_CODES, countryName } from "./lib/countries";
|
|
128
132
|
export { IBAN_LENGTHS, compactIban, formatIban, ibanCheckDigits, ibanProblem, isValidIban, isQrIban } from "./lib/iban";
|
|
129
133
|
export type { IbanKind, IbanProblem } from "./lib/iban";
|
|
130
|
-
// 0.52: deprecated, removed in 0.53 (MOD-5; tagged in lib/isin).
|
|
131
|
-
export { formatIsin, isinCheckDigit, isValidIsin } from "./lib/isin";
|
|
132
134
|
export { PHONE_DIAL_CODES, PHONE_COUNTRIES, parsePhone, formatNationalPhone, formatPhone, isE164 } from "./lib/phone";
|
|
133
135
|
export type { PhoneCountryCode, PhoneCountry, ParsedPhone } from "./lib/phone";
|
|
134
136
|
// 0.23.0: ColumnMapper's pure half (Kurvenschmiede's columns input, keksdose's import map).
|
|
@@ -177,14 +179,9 @@ export type { LongPressOptions, LongPressResult } from "./hooks/use-long-press";
|
|
|
177
179
|
export { useNoIndex } from "./hooks/use-noindex";
|
|
178
180
|
// 0.49 KIT-9: the window's title from page, section and app, in the provider's format.
|
|
179
181
|
export { useDocumentTitle } from "./hooks/use-document-title";
|
|
180
|
-
// 0.
|
|
181
|
-
//
|
|
182
|
-
//
|
|
183
|
-
// declaration: the module keeps it for the kit's own use, only the barrel lets it go.
|
|
184
|
-
export {
|
|
185
|
-
/** @deprecated 0.52 — a formatter's `minus: "ascii"`, where the figure is made (API-4); removed in 0.53 */
|
|
186
|
-
asciiMinusInNumbers,
|
|
187
|
-
} from "./lib/clipboard-minus";
|
|
182
|
+
// 0.53: the 55 names no app reads left the entry points (deprecated in 0.52, refactor audit
|
|
183
|
+
// 2026-10-30, API-4, decision 4) — here 0.49 KIT-1b's `asciiMinusInNumbers`, the copy
|
|
184
|
+
// handler's rule, among them. Their modules keep the ones the kit itself uses.
|
|
188
185
|
export { DEFAULT_DOCUMENT_TITLE_FORMAT, formatDocumentTitle } from "./lib/document-title";
|
|
189
186
|
export type { DocumentTitleParts } from "./lib/document-title";
|
|
190
187
|
export type { SwipeStage, RowSwipeOptions, RowSwipeReturn } from "./hooks/use-row-swipe";
|
|
@@ -344,11 +341,6 @@ export * from "./components/multi-select";
|
|
|
344
341
|
export * from "./components/tooltip";
|
|
345
342
|
export * from "./components/user-avatar";
|
|
346
343
|
export * from "./components/settings-fields";
|
|
347
|
-
// Sync state for a database-backed field: the engine (`useFieldSync`) and the
|
|
348
|
-
// affordance (`FieldSyncIndicator`), kept separate because the state is useful
|
|
349
|
-
// without the dot — a form can gate its submit on any field being `pending`.
|
|
350
|
-
// 0.52: deprecated as a whole, removed in 0.53 (MOD-5; tagged in the module).
|
|
351
|
-
export * from "./components/field-sync";
|
|
352
344
|
export * from "./components/month-picker";
|
|
353
345
|
export * from "./components/checkbox";
|
|
354
346
|
export * from "./components/switch";
|
|
@@ -422,9 +414,6 @@ export * from "./components/alert-banner";
|
|
|
422
414
|
export * from "./components/toggle-group";
|
|
423
415
|
// A wrapping set of links/buttons marked `aria-current` — Tabs-like looks, not tabs.
|
|
424
416
|
export * from "./components/nav-pills";
|
|
425
|
-
// 0.49.0 (KIT-6): a section's pages on the phone, one scrolling row of pills. 0.52:
|
|
426
|
-
// deprecated, removed in 0.53 (MOD-5; tagged in the module).
|
|
427
|
-
export * from "./components/section-nav";
|
|
428
417
|
// A pill carrying one VALUE — inert, a link, or a toggle, depending on which prop it is
|
|
429
418
|
// given — and the list field built from it. Distinct from Button on purpose: a row of
|
|
430
419
|
// buttons reads as "choose an action", a row of chips as "here are the things".
|
|
@@ -441,10 +430,15 @@ export * from "./components/full-bleed-dialog";
|
|
|
441
430
|
export * from "./components/grouped-picker";
|
|
442
431
|
export * from "./components/file-dropzone";
|
|
443
432
|
export * from "./components/mini-calendar";
|
|
444
|
-
|
|
433
|
+
// Named, not `*`: `heatmapLevel` is CalendarHeatmap's own since 0.53 (API-4).
|
|
445
434
|
export {
|
|
446
|
-
|
|
447
|
-
|
|
435
|
+
CalendarHeatmap,
|
|
436
|
+
DEFAULT_CALENDAR_HEATMAP_LABELS,
|
|
437
|
+
heatmapWindowEnd,
|
|
438
|
+
type CalendarHeatmapLabels,
|
|
439
|
+
type CalendarHeatmapDatum,
|
|
440
|
+
type CalendarHeatmapDay,
|
|
441
|
+
type CalendarHeatmapProps,
|
|
448
442
|
} from "./components/calendar-heatmap";
|
|
449
443
|
export * from "./components/date-picker";
|
|
450
444
|
export * from "./components/tree-view";
|
|
@@ -465,13 +459,9 @@ export {
|
|
|
465
459
|
COMMIT_EXCEPT_BILLING,
|
|
466
460
|
DEFAULT_WRITE_LOCK_LABELS,
|
|
467
461
|
} from "./components/write-lock";
|
|
468
|
-
// 0.46 (kastlan K4): the offline lock
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
OFFLINE_LOCK,
|
|
472
|
-
COMMIT_EXCEPT_OFFLINE,
|
|
473
|
-
useOfflineWriteLock,
|
|
474
|
-
} from "./components/write-lock";
|
|
462
|
+
// 0.46 (kastlan K4): the offline lock's scope and its source (the kind, `OFFLINE_LOCK`, left
|
|
463
|
+
// the surface in 0.53: it is the string "offline").
|
|
464
|
+
export { COMMIT_EXCEPT_OFFLINE, useOfflineWriteLock } from "./components/write-lock";
|
|
475
465
|
export type {
|
|
476
466
|
WriteLock,
|
|
477
467
|
WriteLockLabels,
|
|
@@ -535,10 +525,12 @@ export * from "./components/error-boundary";
|
|
|
535
525
|
export * from "./components/copy-button";
|
|
536
526
|
export { AuthedImage, DEFAULT_AUTHED_IMAGE_LABELS } from "./components/authed-image";
|
|
537
527
|
export type { AuthedImageProps, AuthedImageLabels } from "./components/authed-image";
|
|
538
|
-
|
|
528
|
+
// Named, not `*`: `splitFileName` is ImageGrid's own since 0.53 (API-4).
|
|
539
529
|
export {
|
|
540
|
-
|
|
541
|
-
|
|
530
|
+
ImageGrid,
|
|
531
|
+
DEFAULT_IMAGE_GRID_LABELS,
|
|
532
|
+
type ImageGridLabels,
|
|
533
|
+
type ImageGridProps,
|
|
542
534
|
} from "./components/image-grid";
|
|
543
535
|
export * from "./components/lightbox";
|
|
544
536
|
export * from "./components/button-group";
|
|
@@ -567,17 +559,7 @@ export type {
|
|
|
567
559
|
// The toast layer over sonner (an OPTIONAL peer, loaded lazily): `toast` mirrors sonner's
|
|
568
560
|
// API so apps migrate by swapping the import; `<Toaster>` carries the placement, theme,
|
|
569
561
|
// tones and z-index both apps had wired by hand.
|
|
570
|
-
export {
|
|
571
|
-
toast,
|
|
572
|
-
Toaster,
|
|
573
|
-
DEFAULT_TOAST_LABELS,
|
|
574
|
-
/** @deprecated 0.52 — `toast()`, which times a toast with an action by it (API-4); removed in 0.53 */
|
|
575
|
-
TOAST_ACTION_DURATION,
|
|
576
|
-
/** @deprecated 0.52 — `<Toaster>`, whose default `offset` it is (API-4); removed in 0.53 */
|
|
577
|
-
TOASTER_OFFSET_TOP,
|
|
578
|
-
/** @deprecated 0.52 — `<Toaster>`, whose default `offset` it is (API-4); removed in 0.53 */
|
|
579
|
-
TOASTER_OFFSET_BOTTOM,
|
|
580
|
-
} from "./components/toast";
|
|
562
|
+
export { toast, Toaster, DEFAULT_TOAST_LABELS } from "./components/toast";
|
|
581
563
|
export type {
|
|
582
564
|
ToastId,
|
|
583
565
|
ToastAction,
|
|
@@ -682,8 +664,6 @@ export {
|
|
|
682
664
|
// 0.47.0 (keksdose N17): a hand-built table's actions heading and cell.
|
|
683
665
|
RowActionsHead,
|
|
684
666
|
ROW_ACTIONS_CELL_CLASS,
|
|
685
|
-
/** @deprecated 0.52 — `RowActionsHead`, which draws it (API-4); removed in 0.53 */
|
|
686
|
-
ROW_ACTIONS_HEAD_CLASS,
|
|
687
667
|
} from "./components/row-actions";
|
|
688
668
|
export type {
|
|
689
669
|
RowAction,
|
|
@@ -704,8 +684,6 @@ export * from "./components/one-time-code-input";
|
|
|
704
684
|
export * from "./components/language-select";
|
|
705
685
|
export * from "./components/tile-radio";
|
|
706
686
|
export * from "./components/inline-edit-field";
|
|
707
|
-
// 0.52: deprecated, removed in 0.53 (MOD-5; tagged in the module).
|
|
708
|
-
export * from "./components/sign-chip";
|
|
709
687
|
export * from "./components/country-select";
|
|
710
688
|
export * from "./components/iban-input";
|
|
711
689
|
export * from "./components/phone-input";
|
|
@@ -787,7 +765,9 @@ export type { RegisterFormProps, RegisterLabels, RegisterValues } from "./auth/r
|
|
|
787
765
|
export { CompleteNameDialog, DEFAULT_COMPLETE_NAME_LABELS } from "./auth/complete-name-dialog";
|
|
788
766
|
export type { CompleteNameDialogProps, CompleteNameLabels, CompleteNameValues } from "./auth/complete-name-dialog";
|
|
789
767
|
export { taggedEmail } from "./auth/email-tag";
|
|
790
|
-
|
|
768
|
+
// 0.54 (kastlan reuse audit 2026-11-02, proposal 4): `billingRefusalText`, a billing
|
|
769
|
+
// refusal's words, which every app mapped from the code by hand.
|
|
770
|
+
export { isAuthError, authErrorCode, isBillingError, billingRefusalText } from "./auth/auth-errors";
|
|
791
771
|
export type { AuthErrorCode } from "./auth/auth-errors";
|
|
792
772
|
export { ForgotPasswordForm, DEFAULT_FORGOT_PASSWORD_LABELS } from "./auth/forgot-password-form";
|
|
793
773
|
export type { ForgotPasswordFormProps, ForgotPasswordLabels } from "./auth/forgot-password-form";
|
|
@@ -819,7 +799,13 @@ export type { AuthHeadingLevel } from "./auth/status-parts";
|
|
|
819
799
|
// 0.30.0: a rate limit and its wait, and the codes the account, billing and demo calls
|
|
820
800
|
// answer with.
|
|
821
801
|
export { isRateLimited, retryAfterSeconds } from "./auth/auth-errors";
|
|
822
|
-
export type {
|
|
802
|
+
export type {
|
|
803
|
+
AccountErrorCode,
|
|
804
|
+
BillingErrorCode,
|
|
805
|
+
BillingRefusalTextOptions,
|
|
806
|
+
DemoErrorCode,
|
|
807
|
+
KitErrorCode,
|
|
808
|
+
} from "./auth/auth-errors";
|
|
823
809
|
|
|
824
810
|
// ── account ──────────────────────────────────────────────────────────────────
|
|
825
811
|
// In account/ since 0.34, beside the other account cards (MOD-8, refactor audit 2026-10):
|
|
@@ -859,13 +845,9 @@ export type { DataExportSettingProps, DataExportLabels, DataExportFile } from ".
|
|
|
859
845
|
// 0.30.0 (docs/user-admin-harmonization.md): the admin user list and its actions, and the
|
|
860
846
|
// invitations panel. Callbacks only; the confirmation level is the server's.
|
|
861
847
|
export {
|
|
862
|
-
/** @deprecated 0.52 — `useUserRosterColumns`, the same columns in the provider's words (API-4); removed in 0.53 */
|
|
863
|
-
userRosterColumns,
|
|
864
848
|
useUserRosterColumns,
|
|
865
849
|
UserIdentityCell,
|
|
866
850
|
UserRowActions,
|
|
867
|
-
/** @deprecated 0.52 — `useUserRosterColumns`, whose state cell reads it (API-4); removed in 0.53 */
|
|
868
|
-
adminUserStates,
|
|
869
851
|
userRosterSort,
|
|
870
852
|
USER_ROSTER_SORT_KEYS,
|
|
871
853
|
DEFAULT_USER_ROSTER_LABELS,
|
|
@@ -945,13 +927,7 @@ export { adminSectionOrder } from "./admin/admin-sections";
|
|
|
945
927
|
export type { AdminSectionPlace, AdminSectionOrderOptions, AdminKeptSection } from "./admin/admin-sections";
|
|
946
928
|
export { AdminForbidden } from "./admin/admin-forbidden";
|
|
947
929
|
export type { AdminForbiddenProps } from "./admin/admin-forbidden";
|
|
948
|
-
export {
|
|
949
|
-
AdminOverview,
|
|
950
|
-
AttentionTile,
|
|
951
|
-
adminWaitingCount,
|
|
952
|
-
/** @deprecated 0.52 — `AdminOverview`, which links its tiles there unless told otherwise (API-4); removed in 0.53 */
|
|
953
|
-
DEFAULT_ADMIN_ATTENTION_HREFS,
|
|
954
|
-
} from "./admin/admin-overview";
|
|
930
|
+
export { AdminOverview, AttentionTile, adminWaitingCount } from "./admin/admin-overview";
|
|
955
931
|
export type {
|
|
956
932
|
AdminAttention,
|
|
957
933
|
AdminAttentionTile,
|
|
@@ -966,23 +942,10 @@ export type {
|
|
|
966
942
|
export { AdminToolLinks } from "./admin/admin-tool-links";
|
|
967
943
|
export type { AdminToolLink, AdminToolLinksProps } from "./admin/admin-tool-links";
|
|
968
944
|
// 0.45.0 (docs/admin-harmonization.md §9.2.4): "Send a test mail to me".
|
|
969
|
-
export {
|
|
970
|
-
MailTestCard,
|
|
971
|
-
DEFAULT_MAIL_TEST_CARD_LABELS,
|
|
972
|
-
MAIL_TEST_ANCHOR,
|
|
973
|
-
/** @deprecated 0.52 — `MailTestCard`, which masks the address itself (API-4); removed in 0.53 */
|
|
974
|
-
maskMailAddress,
|
|
975
|
-
} from "./admin/mail-test-card";
|
|
945
|
+
export { MailTestCard, DEFAULT_MAIL_TEST_CARD_LABELS, MAIL_TEST_ANCHOR } from "./admin/mail-test-card";
|
|
976
946
|
export type { MailTestCardProps, MailTestCardLabels, MailTestAnswer } from "./admin/mail-test-card";
|
|
977
947
|
// 0.33.0: the operator's plan parts (docs/billing-harmonization.md §14.12).
|
|
978
|
-
export {
|
|
979
|
-
/** @deprecated 0.52 — `usePlanColumn`, the same column in the provider's words (API-4); removed in 0.53 */
|
|
980
|
-
planColumn,
|
|
981
|
-
usePlanColumn,
|
|
982
|
-
PlanChangeConfirm,
|
|
983
|
-
usePlanChangeResult,
|
|
984
|
-
DEFAULT_PLAN_CHANGE_LABELS,
|
|
985
|
-
} from "./admin/plan-change";
|
|
948
|
+
export { usePlanColumn, PlanChangeConfirm, usePlanChangeResult, DEFAULT_PLAN_CHANGE_LABELS } from "./admin/plan-change";
|
|
986
949
|
export type {
|
|
987
950
|
PlanChangeLabels,
|
|
988
951
|
PlanColumnOptions,
|
|
@@ -1007,13 +970,7 @@ export type {
|
|
|
1007
970
|
PlanPrices,
|
|
1008
971
|
PlanPriceAnswer,
|
|
1009
972
|
} from "./billing/plan-price";
|
|
1010
|
-
export {
|
|
1011
|
-
PlanCard,
|
|
1012
|
-
PlanPicker,
|
|
1013
|
-
GrantWarningConfirm,
|
|
1014
|
-
/** @deprecated 0.52 — `PlanPicker`, which marks each card's relation itself (API-4); removed in 0.53 */
|
|
1015
|
-
planRelation,
|
|
1016
|
-
} from "./billing/plan-card";
|
|
973
|
+
export { PlanCard, PlanPicker, GrantWarningConfirm } from "./billing/plan-card";
|
|
1017
974
|
export type {
|
|
1018
975
|
BillingPlan,
|
|
1019
976
|
PlanRelation,
|
|
@@ -1047,21 +1004,10 @@ export {
|
|
|
1047
1004
|
withoutCheckoutReturn,
|
|
1048
1005
|
checkoutReturnUrl,
|
|
1049
1006
|
} from "./billing/checkout-return";
|
|
1050
|
-
export {
|
|
1051
|
-
checkoutFingerprint,
|
|
1052
|
-
/** @deprecated 0.52 — `useCheckoutProcessing`, which asks it (API-4); removed in 0.53 */
|
|
1053
|
-
checkoutLanded,
|
|
1054
|
-
noteCheckoutStarted,
|
|
1055
|
-
useCheckoutProcessing,
|
|
1056
|
-
} from "./billing/checkout-processing";
|
|
1007
|
+
export { checkoutFingerprint, noteCheckoutStarted, useCheckoutProcessing } from "./billing/checkout-processing";
|
|
1057
1008
|
export type { CheckoutOverview, CheckoutProcessingOptions } from "./billing/checkout-processing";
|
|
1058
1009
|
// The link to the pay page and Paddle's locale (§14.4); the page itself ships as dist/pay/.
|
|
1059
|
-
export {
|
|
1060
|
-
/** @deprecated 0.52 — `payPageUrl`, which writes it (API-4); removed in 0.53 */
|
|
1061
|
-
PAY_PAGE_LANG_PARAM,
|
|
1062
|
-
paddleLocale,
|
|
1063
|
-
payPageUrl,
|
|
1064
|
-
} from "./billing/pay-page";
|
|
1010
|
+
export { paddleLocale, payPageUrl } from "./billing/pay-page";
|
|
1065
1011
|
export type { PaddleEnvironment } from "./billing/pay-page";
|
|
1066
1012
|
// 0.39 (§15.2.6): the apps every pay page serves, by their `billing_app` tag.
|
|
1067
1013
|
export { PAY_PAGE_APPS } from "./billing/pay-page";
|
|
@@ -1111,11 +1057,7 @@ export type {
|
|
|
1111
1057
|
ResolveAccountLanguageInput,
|
|
1112
1058
|
ResolvedAccountLanguage,
|
|
1113
1059
|
} from "./settings/use-account-language";
|
|
1114
|
-
export {
|
|
1115
|
-
useAccountAppearance,
|
|
1116
|
-
/** @deprecated 0.52 — `useAccountAppearance`, which resolves the same three values (API-4); removed in 0.53 */
|
|
1117
|
-
resolveAccountAppearance,
|
|
1118
|
-
} from "./settings/use-account-appearance";
|
|
1060
|
+
export { useAccountAppearance } from "./settings/use-account-appearance";
|
|
1119
1061
|
export type {
|
|
1120
1062
|
AppearanceSource,
|
|
1121
1063
|
AccountAppearanceFields,
|
|
@@ -1192,11 +1134,7 @@ export type {
|
|
|
1192
1134
|
} from "./notifications/push-worker";
|
|
1193
1135
|
export { PushDeviceSetting } from "./notifications/push-device-setting";
|
|
1194
1136
|
export type { PushDeviceSettingProps, PushDeviceAction } from "./notifications/push-device-setting";
|
|
1195
|
-
export {
|
|
1196
|
-
PushDevicesSetting,
|
|
1197
|
-
/** @deprecated 0.52 — `PushDevicesSetting`, which names each device with it (API-4); removed in 0.53 */
|
|
1198
|
-
describeUserAgent,
|
|
1199
|
-
} from "./notifications/push-devices-setting";
|
|
1137
|
+
export { PushDevicesSetting } from "./notifications/push-devices-setting";
|
|
1200
1138
|
export type { PushDevicesSettingProps } from "./notifications/push-devices-setting";
|
|
1201
1139
|
export { UnsubscribePanel, unsubscribeTokenType } from "./notifications/unsubscribe-panel";
|
|
1202
1140
|
export type { UnsubscribePanelProps } from "./notifications/unsubscribe-panel";
|
|
@@ -1243,15 +1181,7 @@ export { DEFAULT_DEMO_LABELS, useDemoLabels } from "./demo/demo-labels";
|
|
|
1243
1181
|
export type { DemoLabels } from "./demo/demo-labels";
|
|
1244
1182
|
export { isDemoSession } from "./demo/demo-session";
|
|
1245
1183
|
export type { DemoModel, DemoSessionUser } from "./demo/demo-session";
|
|
1246
|
-
export {
|
|
1247
|
-
useDemoCountdown,
|
|
1248
|
-
/** @deprecated 0.52 — `useDemoCountdown`, the same countdown; its `now` option for a test (API-4); removed in 0.53 */
|
|
1249
|
-
demoCountdown,
|
|
1250
|
-
/** @deprecated 0.52 — `useDemoCountdown`, whose `warning` turns on then (API-4); removed in 0.53 */
|
|
1251
|
-
DEMO_WARNING_MINUTES,
|
|
1252
|
-
/** @deprecated 0.52 — `useDemoCountdown`, whose `lastHour` turns on then (API-4); removed in 0.53 */
|
|
1253
|
-
DEMO_MINUTES_ONLY,
|
|
1254
|
-
} from "./demo/demo-countdown";
|
|
1184
|
+
export { useDemoCountdown } from "./demo/demo-countdown";
|
|
1255
1185
|
export type { DemoCountdown, DemoCountdownOptions, DemoExpiry } from "./demo/demo-countdown";
|
|
1256
1186
|
export { DemoStart } from "./demo/demo-start";
|
|
1257
1187
|
export type { DemoStartProps } from "./demo/demo-start";
|
package/src/lib/dates.ts
CHANGED
|
@@ -24,6 +24,9 @@
|
|
|
24
24
|
* all, so sending it the user's local day is also what it wants.
|
|
25
25
|
*/
|
|
26
26
|
|
|
27
|
+
// Imports nothing else: `@eifi1/ui-kit/dates` reaches no package (packaging-contract).
|
|
28
|
+
import { dateFormatter } from "./intl-cache";
|
|
29
|
+
|
|
27
30
|
/** Zero-pad a number to two digits ("3" -> "03"). */
|
|
28
31
|
export function pad(n: number): string {
|
|
29
32
|
return String(n).padStart(2, "0");
|
|
@@ -124,14 +127,33 @@ export function parseIsoDate(s: string): Date | null {
|
|
|
124
127
|
return dt;
|
|
125
128
|
}
|
|
126
129
|
|
|
130
|
+
/** The fields that make an option set a DATE for `toLocaleDateString` (ECMA-402's
|
|
131
|
+
* ToDateTimeOptions, required "date"): with none of them it adds year, month and day. */
|
|
132
|
+
const DATE_FIELDS = ["weekday", "year", "month", "day", "dateStyle"] as const;
|
|
133
|
+
const NUMERIC_DATE: Intl.DateTimeFormatOptions = { year: "numeric", month: "numeric", day: "numeric" };
|
|
134
|
+
|
|
135
|
+
/** `options` as `toLocaleDateString` reads them: with a date in them, whatever else they
|
|
136
|
+
* ask for. `{ hour: "numeric" }` alone is a date and an hour there, never the hour alone
|
|
137
|
+
* that `Intl.DateTimeFormat` would print for it. */
|
|
138
|
+
function asDateOptions(options: Intl.DateTimeFormatOptions | undefined): Intl.DateTimeFormatOptions {
|
|
139
|
+
if (!options) return NUMERIC_DATE;
|
|
140
|
+
return DATE_FIELDS.some((field) => options[field] !== undefined) ? options : { ...options, ...NUMERIC_DATE };
|
|
141
|
+
}
|
|
142
|
+
|
|
127
143
|
/** Format a "YYYY-MM-DD" string for display in `locale` (empty string when
|
|
128
144
|
* unparseable). Defaults to the locale's short numeric date; pass `options` to
|
|
129
145
|
* override (e.g. `{ dateStyle: "medium" }`). `locale` may be `undefined` since 0.34 —
|
|
130
146
|
* the runtime's default, as `Intl` reads it and as every other kit formatter takes it
|
|
131
|
-
* (DUP-11: DatePicker re-wrapped this function only to pass none).
|
|
147
|
+
* (DUP-11: DatePicker re-wrapped this function only to pass none).
|
|
148
|
+
*
|
|
149
|
+
* Through the kit's formatter cache since 0.54 (keksdose audit follow-up, 2026-11-01):
|
|
150
|
+
* `toLocaleDateString` builds a formatter per call, and this one runs for the date
|
|
151
|
+
* pickers' trigger on every render and for an app's date column once per row. The output
|
|
152
|
+
* is `toLocaleDateString`'s: the same options, with the date it adds when they name none
|
|
153
|
+
* (`asDateOptions`). */
|
|
132
154
|
export function formatIsoDate(iso: string, locale: string | undefined, options?: Intl.DateTimeFormatOptions): string {
|
|
133
155
|
const d = parseIsoDate(iso);
|
|
134
|
-
return d ?
|
|
156
|
+
return d ? dateFormatter(locale, asDateOptions(options)).format(d) : "";
|
|
135
157
|
}
|
|
136
158
|
|
|
137
159
|
/** A "YYYY-MM-DD" string shifted by `days` (negative shifts back), or the input
|
package/src/lib/format.ts
CHANGED
|
@@ -11,8 +11,8 @@ export type { MinusStyle } from "./minus";
|
|
|
11
11
|
export { formatWithMinus } from "./minus";
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* Number, money, percentage, date and relative-time formatting — `Intl`,
|
|
15
|
-
* for the figures an app prints OUTSIDE a kit component.
|
|
14
|
+
* Number, money, percentage, duration (0.54), date and relative-time formatting — `Intl`,
|
|
15
|
+
* in one place, for the figures an app prints OUTSIDE a kit component.
|
|
16
16
|
*
|
|
17
17
|
* Each app grew its own: kastlan's `utils/formatters.ts` (a Swiss-pinned
|
|
18
18
|
* `formatNumber`/`formatCurrency`, a date-fns `formatDate`, and a `formatRelativeTime`
|
|
@@ -99,6 +99,19 @@ export interface FormatMoneyOptions extends FormatNumberBaseOptions {
|
|
|
99
99
|
currencyDisplay?: Intl.NumberFormatOptions["currencyDisplay"];
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
export interface FormatDurationOptions extends BaseOptions {
|
|
103
|
+
/**
|
|
104
|
+
* How the units are written — `Intl.NumberFormat`'s `unitDisplay`, in `locale`:
|
|
105
|
+
* - `"narrow"` (default): "3m 12s", "3 Min. 12 Sek." (de-CH), "3min 12s" (fr) —
|
|
106
|
+
* keksdose's scan readout;
|
|
107
|
+
* - `"short"`: "3 min 12 sec", "3 Min. 12 Sek.", "3 min 12 s";
|
|
108
|
+
* - `"long"`: "3 minutes 12 seconds", "3 Minuten 12 Sekunden", "3 minutes 12 secondes".
|
|
109
|
+
*/
|
|
110
|
+
unitDisplay?: "narrow" | "short" | "long";
|
|
111
|
+
/** The minus of a negative duration — {@link FormatNumberBaseOptions.minus}. */
|
|
112
|
+
minus?: MinusStyle;
|
|
113
|
+
}
|
|
114
|
+
|
|
102
115
|
export interface FormatPercentOptions extends FormatNumberBaseOptions {
|
|
103
116
|
/**
|
|
104
117
|
* `true` (default): `value` is a RATIO, as `Intl` and `StatTile`'s percent delta read
|
|
@@ -162,7 +175,7 @@ function devWarnings(): boolean {
|
|
|
162
175
|
const warnedSites = new Set<string>();
|
|
163
176
|
/** This module's own frames, skipped to find the caller ("Object.formatMoney" is a
|
|
164
177
|
* `useKitFormat` wrapper). */
|
|
165
|
-
const OWN_FRAME = /\b(?:formatNumber|formatMoney|formatPercent|toFormattable|warnInvalid|callSite)\b/;
|
|
178
|
+
const OWN_FRAME = /\b(?:formatNumber|formatMoney|formatPercent|formatDuration|toFormattable|warnInvalid|callSite)\b/;
|
|
166
179
|
|
|
167
180
|
/** The first stack frame outside the formatters: where the bad value was passed. */
|
|
168
181
|
function callSite(): string {
|
|
@@ -248,6 +261,53 @@ export function formatPercent(value: FormattableNumber, options: FormatPercentOp
|
|
|
248
261
|
return formatWithMinus(formatter, ratio, options.minus);
|
|
249
262
|
}
|
|
250
263
|
|
|
264
|
+
/** The units a duration is written in, largest first, with their length in seconds. */
|
|
265
|
+
const DURATION_UNITS = [
|
|
266
|
+
["hour", 3600],
|
|
267
|
+
["minute", 60],
|
|
268
|
+
["second", 1],
|
|
269
|
+
] as const;
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* A number of SECONDS as an elapsed time in `locale`: "42s", "3m 12s", "1h 0m 5s" — and in
|
|
273
|
+
* German "3 Min. 12 Sek.", in French "3min 12s" (keksdose audit follow-up, 2026-11-01:
|
|
274
|
+
* keksdose's `formatElapsed`, the scan card's readout, moves here). Each unit is
|
|
275
|
+
* `Intl.NumberFormat`'s `style: "unit"`, so the digits and the unit's spelling follow
|
|
276
|
+
* `locale`; `unitDisplay` picks the form, narrow by default.
|
|
277
|
+
*
|
|
278
|
+
* - Seconds alone under a minute ("0s", "59s"); minutes and seconds under an hour ("1m 0s",
|
|
279
|
+
* "59m 59s"); from an hour on, hours, minutes and seconds ("1h 0m 0s"). Hours are the
|
|
280
|
+
* largest unit: a day and a bit is "27h 46m 40s". Every unit below the first is printed,
|
|
281
|
+
* zero too, so a ticking readout keeps its shape from one second to the next.
|
|
282
|
+
* - Whole seconds, cut toward zero: a timer reads "59s" until the minute is full.
|
|
283
|
+
* - The parts are joined by a space, as the readout always was — not `Intl.ListFormat`'s
|
|
284
|
+
* "3 Min. und 12 Sek.", which is a sentence rather than a figure.
|
|
285
|
+
* - Negative: the minus on the first unit, as `Intl.DurationFormat` writes one — "−3m 12s",
|
|
286
|
+
* with the kit's minus (`minus`). An elapsed time from a server's clock can come out a
|
|
287
|
+
* second below zero; clamp it before, as keksdose's card does, when that is not news.
|
|
288
|
+
* - `null` / `undefined` print `empty`; `NaN`, ±`Infinity` and a non-numeric string too,
|
|
289
|
+
* with the formatters' development warning. A numeric string ("185") is a number.
|
|
290
|
+
*/
|
|
291
|
+
export function formatDuration(seconds: FormattableNumber, options: FormatDurationOptions = {}): string {
|
|
292
|
+
const n = toFormattable("formatDuration", seconds);
|
|
293
|
+
if (n === undefined) return options.empty ?? EMPTY_FORMATTED_VALUE;
|
|
294
|
+
const unitDisplay = options.unitDisplay ?? "narrow";
|
|
295
|
+
const negative = n < 0;
|
|
296
|
+
let rest = Math.trunc(Math.abs(n));
|
|
297
|
+
const parts: string[] = [];
|
|
298
|
+
for (const [unit, size] of DURATION_UNITS) {
|
|
299
|
+
const count = Math.floor(rest / size);
|
|
300
|
+
rest -= count * size;
|
|
301
|
+
// Units above the first that has a count are left out; seconds always print.
|
|
302
|
+
if (parts.length === 0 && count === 0 && unit !== "second") continue;
|
|
303
|
+
const formatter = numberFormatter(options.locale, { style: "unit", unit, unitDisplay });
|
|
304
|
+
// `count > 0`: under a second either way is "0s", with no sign on it.
|
|
305
|
+
const signed = negative && parts.length === 0 && count > 0 ? -count : count;
|
|
306
|
+
parts.push(formatWithMinus(formatter, signed, options.minus));
|
|
307
|
+
}
|
|
308
|
+
return parts.join(" ");
|
|
309
|
+
}
|
|
310
|
+
|
|
251
311
|
/* ── Dates ─────────────────────────────────────────────────────────────────── */
|
|
252
312
|
|
|
253
313
|
/**
|
|
@@ -436,6 +496,8 @@ export interface KitFormat {
|
|
|
436
496
|
formatNumber: (value: FormattableNumber, options?: WithoutLocale<FormatNumberOptions>) => string;
|
|
437
497
|
formatMoney: (value: FormattableNumber, currency: string, options?: WithoutLocale<FormatMoneyOptions>) => string;
|
|
438
498
|
formatPercent: (value: FormattableNumber, options?: WithoutLocale<FormatPercentOptions>) => string;
|
|
499
|
+
/** 0.54: {@link formatDuration}, a number of seconds as an elapsed time. */
|
|
500
|
+
formatDuration: (seconds: FormattableNumber, options?: WithoutLocale<FormatDurationOptions>) => string;
|
|
439
501
|
formatDate: (
|
|
440
502
|
value: DateInput,
|
|
441
503
|
style?: FormatDateStyle | Intl.DateTimeFormatOptions,
|
|
@@ -462,6 +524,7 @@ export function useKitFormat(locale?: string): KitFormat {
|
|
|
462
524
|
formatNumber: (value, options) => formatNumber(value, { locale: kitLocale, ...options }),
|
|
463
525
|
formatMoney: (value, currency, options) => formatMoney(value, currency, { locale: kitLocale, ...options }),
|
|
464
526
|
formatPercent: (value, options) => formatPercent(value, { locale: kitLocale, ...options }),
|
|
527
|
+
formatDuration: (seconds, options) => formatDuration(seconds, { locale: kitLocale, ...options }),
|
|
465
528
|
formatDate: (value, style, options) => formatDate(value, style, { locale: kitLocale, timeZone, ...options }),
|
|
466
529
|
formatRelativeTime: (value, options) => formatRelativeTime(value, { locale: kitLocale, timeZone, ...options }),
|
|
467
530
|
}),
|
package/src/lib/intl-cache.ts
CHANGED
|
@@ -4,10 +4,12 @@
|
|
|
4
4
|
* Constructing the formatter is the expensive part: keksdose measured 392 ms per click on
|
|
5
5
|
* a 270-row register when each cell built its own (dev#632), and kept its own renderer of
|
|
6
6
|
* the date-format preference because the kit's built one per call (refactor audit
|
|
7
|
-
* 2026-10-30, DUP-2). `lib/format` and `lib/date-format` both format through this one
|
|
7
|
+
* 2026-10-30, DUP-2). `lib/format` and `lib/date-format` both format through this one, and
|
|
8
|
+
* since 0.54 `lib/dates`' `formatIsoDate` (keksdose audit follow-up, 2026-11-01).
|
|
8
9
|
*
|
|
9
10
|
* @internal Not part of the barrel — `lib/format` is re-exported whole, so the cache
|
|
10
|
-
* lives apart from it.
|
|
11
|
+
* lives apart from it. It imports nothing, which `@eifi1/ui-kit/dates` (no package at
|
|
12
|
+
* all) relies on.
|
|
11
13
|
*/
|
|
12
14
|
|
|
13
15
|
const dateFormatters = new Map<string, Intl.DateTimeFormat>();
|
|
@@ -570,6 +570,58 @@ export function dropReviews<T extends TranslationReviewKey>(
|
|
|
570
570
|
return prev.filter((r) => !gone.has(`${r.locale}|${r.key}`));
|
|
571
571
|
}
|
|
572
572
|
|
|
573
|
+
/**
|
|
574
|
+
* How many verdicts one request carries. server-kit refuses more than 2000 in one
|
|
575
|
+
* `PUT /translations/reviews` or `POST /translations/reviews/clear` (`BATCH_MAX`, its
|
|
576
|
+
* translation_review/schemas.py); half of it, as each of the three apps sent. A whole area
|
|
577
|
+
* is rarely more than a few hundred, so most saves are one request; "Approve the
|
|
578
|
+
* unreviewed" over an app's every string is not.
|
|
579
|
+
*/
|
|
580
|
+
const REVIEW_CHUNK = 1000;
|
|
581
|
+
|
|
582
|
+
/**
|
|
583
|
+
* A save of any size under server-kit's cap: `writes` in chunks of 1000, one request
|
|
584
|
+
* after the other, in their order, and every verdict the server answered with, in that
|
|
585
|
+
* order — to patch the page's cached list with {@link mergeReviews} once. `save` is the
|
|
586
|
+
* app's own request (`PUT /translations/reviews`), answering with the verdicts it wrote,
|
|
587
|
+
* in either spelling. No writes, no request: the server refuses an empty batch.
|
|
588
|
+
*
|
|
589
|
+
* A chunk that fails rejects with its error, and the chunks after it are not sent. What
|
|
590
|
+
* the chunks before it wrote stays written — the server has it — but is not handed back,
|
|
591
|
+
* so the page leaves its cache as it was and the panel shows the error; a second try
|
|
592
|
+
* writes those verdicts again, which changes nothing but the time on them.
|
|
593
|
+
*
|
|
594
|
+
* All three apps wrote this loop, with a `chunks` helper and `SAVE_CHUNK = 1000` of
|
|
595
|
+
* their own (kastlan reuse audit 2026-11-02, proposal 5):
|
|
596
|
+
*
|
|
597
|
+
* const written = await saveReviewsInChunks(writes.map(toApiWrite), (part) => translationsApi.save(part));
|
|
598
|
+
* patchCache((reviews) => mergeReviews(reviews, written));
|
|
599
|
+
*/
|
|
600
|
+
export async function saveReviewsInChunks<W extends TranslationReviewKey, R extends TranslationReviewKey>(
|
|
601
|
+
writes: readonly W[],
|
|
602
|
+
save: (chunk: W[]) => Promise<readonly R[]>,
|
|
603
|
+
): Promise<R[]> {
|
|
604
|
+
const written: R[] = [];
|
|
605
|
+
for (let at = 0; at < writes.length; at += REVIEW_CHUNK) {
|
|
606
|
+
written.push(...(await save(writes.slice(at, at + REVIEW_CHUNK))));
|
|
607
|
+
}
|
|
608
|
+
return written;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
/**
|
|
612
|
+
* {@link saveReviewsInChunks} for a reset (`POST /translations/reviews/clear`): `keys` in
|
|
613
|
+
* chunks of 1000, one request after the other, and the keys themselves once every chunk
|
|
614
|
+
* is through — to drop from the cached list with {@link dropReviews} once. A failing
|
|
615
|
+
* chunk rejects as a save's does, and what the chunks before it cleared stays cleared.
|
|
616
|
+
*/
|
|
617
|
+
export async function clearReviewsInChunks<K extends TranslationReviewKey>(
|
|
618
|
+
keys: readonly K[],
|
|
619
|
+
clear: (chunk: K[]) => Promise<unknown>,
|
|
620
|
+
): Promise<K[]> {
|
|
621
|
+
for (let at = 0; at < keys.length; at += REVIEW_CHUNK) await clear(keys.slice(at, at + REVIEW_CHUNK));
|
|
622
|
+
return [...keys];
|
|
623
|
+
}
|
|
624
|
+
|
|
573
625
|
// ── Swipe bindings ──────────────────────────────────────────────────────────────
|
|
574
626
|
|
|
575
627
|
/**
|
package/src/rhf/fields.tsx
CHANGED
|
@@ -899,8 +899,8 @@ export type RhfDateRangePickerProps<
|
|
|
899
899
|
*
|
|
900
900
|
* Without `apply` (the picker's default) the first calendar click is reported on its
|
|
901
901
|
* own, so the form holds `(from, emptyValue)` until the second; with `apply` nothing
|
|
902
|
-
* reaches the form until Apply. `apply` was `commit="apply"` until 0.52 (
|
|
903
|
-
*
|
|
902
|
+
* reaches the form until Apply. `apply` was `commit="apply"` until 0.52 (gone in 0.53):
|
|
903
|
+
* `commit` is now the write lock's, as on every other binding — with
|
|
904
904
|
* `disabledReason`, the picker's own (refactor audit 2026-10-30, API-3).
|
|
905
905
|
*
|
|
906
906
|
* The common props (`label`, `hint`, `required`, `disabled`, `excludeWhenDisabled`,
|
|
@@ -281,18 +281,3 @@ function capByGroup<E extends SearchEntry>(hits: SearchHit<E>[], groupLimit: num
|
|
|
281
281
|
}
|
|
282
282
|
return out;
|
|
283
283
|
}
|
|
284
|
-
|
|
285
|
-
/**
|
|
286
|
-
* One-shot form of {@link createSearchIndex}: the matching entries, best first. For a
|
|
287
|
-
* list that changes on every call (a server response, a store selector); build an index
|
|
288
|
-
* once when the entries are stable.
|
|
289
|
-
*/
|
|
290
|
-
export function matchEntries<E extends SearchEntry>(
|
|
291
|
-
entries: readonly E[],
|
|
292
|
-
query: string,
|
|
293
|
-
options?: SearchIndexOptions,
|
|
294
|
-
): E[] {
|
|
295
|
-
return createSearchIndex(entries, options)
|
|
296
|
-
.search(query)
|
|
297
|
-
.map((hit) => hit.entry);
|
|
298
|
-
}
|
package/src/search.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
// `@eifi1/ui-kit/search` — the command palette / global search.
|
|
2
2
|
// A re-slicing of the main barrel, not a new API.
|
|
3
3
|
export * from "./search/command-palette";
|
|
4
|
-
|
|
5
|
-
// 0.52
|
|
4
|
+
// Named, not `*`: 0.53 took `SEARCH_TIER_POINTS` and `normalizeSearchText` off the surface
|
|
5
|
+
// (deprecated in 0.52, refactor audit 2026-10-30, API-4); the index keeps them.
|
|
6
6
|
export {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
createSearchIndex,
|
|
8
|
+
type SearchEntry,
|
|
9
|
+
type SearchMatchField,
|
|
10
|
+
type SearchHit,
|
|
11
|
+
type SearchIndexOptions,
|
|
12
|
+
type SearchIndex,
|
|
13
13
|
} from "./search/search-index";
|
|
14
14
|
export * from "./search/global-search";
|