@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
|
@@ -39,11 +39,15 @@ function flagOf(lang: AccountMenuLanguageOption): ReactNode {
|
|
|
39
39
|
);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
interface AccountMenuLanguageBaseProps {
|
|
42
|
+
export interface AccountMenuLanguageProps {
|
|
44
43
|
languages: readonly AccountMenuLanguageOption[];
|
|
45
44
|
/** The active language's code. */
|
|
46
45
|
value: string | undefined;
|
|
46
|
+
/** A pick: the app sets the device's language and, signed in, the account's
|
|
47
|
+
* (settings §6.2). `value` + `onChange`, as every kit control pairs them
|
|
48
|
+
* (CONTRIBUTING §4; refactor audit 2026-10-30, API-5). Required: 0.53 removed the
|
|
49
|
+
* deprecated `onPick`. */
|
|
50
|
+
onChange: (code: string) => void;
|
|
47
51
|
/** The account menu's `close` (from `TopBarActionMenu`'s `children`): a pick shuts it. */
|
|
48
52
|
close?: () => void;
|
|
49
53
|
/** The row's name. Default: `topBar.language` ("Language"). */
|
|
@@ -52,28 +56,6 @@ interface AccountMenuLanguageBaseProps {
|
|
|
52
56
|
defaultOpen?: boolean;
|
|
53
57
|
}
|
|
54
58
|
|
|
55
|
-
/**
|
|
56
|
-
* `onChange`, or the deprecated `onPick`, is required: with both optional, a row an app
|
|
57
|
-
* moved off `onPick` without adding `onChange` — or with it misspelt — compiled, and a
|
|
58
|
-
* pick only closed the menu (0.52 code review, account-menu-language.tsx).
|
|
59
|
-
*/
|
|
60
|
-
export type AccountMenuLanguageProps = AccountMenuLanguageBaseProps &
|
|
61
|
-
(
|
|
62
|
-
| {
|
|
63
|
-
/** A pick: the app sets the device's language and, signed in, the account's
|
|
64
|
-
* (settings §6.2). `value` + `onChange`, as every kit control pairs them
|
|
65
|
-
* (CONTRIBUTING §4; refactor audit 2026-10-30, API-5). */
|
|
66
|
-
onChange: (code: string) => void;
|
|
67
|
-
/** @deprecated 0.52 — `onChange` (the same call); removed in 0.53. */
|
|
68
|
-
onPick?: (code: string) => void;
|
|
69
|
-
}
|
|
70
|
-
| {
|
|
71
|
-
onChange?: undefined;
|
|
72
|
-
/** @deprecated 0.52 — `onChange` (the same call); removed in 0.53. */
|
|
73
|
-
onPick: (code: string) => void;
|
|
74
|
-
}
|
|
75
|
-
);
|
|
76
|
-
|
|
77
59
|
/**
|
|
78
60
|
* The language choice INSIDE the account menu (docs/top-bar-harmonization.md §2.3),
|
|
79
61
|
* keksdose's sub-list: a `Disclosure variant="menu"` row — the globe, "Language", the
|
|
@@ -89,12 +71,10 @@ export function AccountMenuLanguage({
|
|
|
89
71
|
languages,
|
|
90
72
|
value,
|
|
91
73
|
onChange,
|
|
92
|
-
onPick,
|
|
93
74
|
close,
|
|
94
75
|
label,
|
|
95
76
|
defaultOpen = false,
|
|
96
77
|
}: AccountMenuLanguageProps) {
|
|
97
|
-
const change = onChange ?? onPick;
|
|
98
78
|
const words = useKitLabels("topBar", DEFAULT_TOP_BAR_LABELS);
|
|
99
79
|
const [open, setOpen] = useState(defaultOpen);
|
|
100
80
|
const active = languages.find((l) => l.code === value);
|
|
@@ -131,7 +111,7 @@ export function AccountMenuLanguage({
|
|
|
131
111
|
<MenuItem
|
|
132
112
|
checked={lang.code === value}
|
|
133
113
|
onClick={() => {
|
|
134
|
-
|
|
114
|
+
onChange(lang.code);
|
|
135
115
|
setOpen(false);
|
|
136
116
|
close?.();
|
|
137
117
|
}}
|
|
@@ -4,44 +4,26 @@ import { useAppearanceLabels, type AppearanceLabels } from "../components/appear
|
|
|
4
4
|
import type { LabelOverride } from "../i18n/kit-labels";
|
|
5
5
|
import { TEXT_SIZES, useTextSize, type TextSize } from "../theme/text-size";
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
interface AccountMenuTextSizeBaseProps {
|
|
7
|
+
export interface AccountMenuTextSizeProps {
|
|
9
8
|
/** The size in force. Default: the one on `<html>` ({@link useTextSize}), which is the
|
|
10
9
|
* size whoever applied it put there. */
|
|
11
10
|
value?: TextSize;
|
|
11
|
+
/**
|
|
12
|
+
* A step: the next size down or up. The app applies it and keeps it as its
|
|
13
|
+
* Settings ▸ Appearance does — `useAccountAppearance`'s `pickTextSize` (this
|
|
14
|
+
* device, and the account when signed in), with `appearance.saveFailed` as the
|
|
15
|
+
* toast when the account refused. The kit does not apply it itself, so the two
|
|
16
|
+
* places can never disagree. `value` + `onChange`, as every kit control pairs them
|
|
17
|
+
* (CONTRIBUTING §4; refactor audit 2026-10-30, API-5). Required: 0.53 removed the
|
|
18
|
+
* deprecated `onPick`.
|
|
19
|
+
*/
|
|
20
|
+
onChange: (size: TextSize) => void;
|
|
12
21
|
/** The row's name. Default: `appearance.textSize` ("Text size"). */
|
|
13
22
|
label?: string;
|
|
14
23
|
/** The `appearance` words (`textSize`, `textSizes`, `textSmaller`, `textLarger`). */
|
|
15
24
|
labels?: LabelOverride<AppearanceLabels>;
|
|
16
25
|
}
|
|
17
26
|
|
|
18
|
-
/**
|
|
19
|
-
* `onChange`, or the deprecated `onPick`, is required: with both optional, a row an app
|
|
20
|
-
* moved off `onPick` without adding `onChange` — or with it misspelt — compiled, and A− /
|
|
21
|
-
* A+ stayed enabled and changed nothing (0.52 code review, account-menu-language.tsx).
|
|
22
|
-
*/
|
|
23
|
-
export type AccountMenuTextSizeProps = AccountMenuTextSizeBaseProps &
|
|
24
|
-
(
|
|
25
|
-
| {
|
|
26
|
-
/**
|
|
27
|
-
* A step: the next size down or up. The app applies it and keeps it as its
|
|
28
|
-
* Settings ▸ Appearance does — `useAccountAppearance`'s `pickTextSize` (this
|
|
29
|
-
* device, and the account when signed in), with `appearance.saveFailed` as the
|
|
30
|
-
* toast when the account refused. The kit does not apply it itself, so the two
|
|
31
|
-
* places can never disagree. `value` + `onChange`, as every kit control pairs them
|
|
32
|
-
* (CONTRIBUTING §4; refactor audit 2026-10-30, API-5).
|
|
33
|
-
*/
|
|
34
|
-
onChange: (size: TextSize) => void;
|
|
35
|
-
/** @deprecated 0.52 — `onChange` (the same call); removed in 0.53. */
|
|
36
|
-
onPick?: (size: TextSize) => void;
|
|
37
|
-
}
|
|
38
|
-
| {
|
|
39
|
-
onChange?: undefined;
|
|
40
|
-
/** @deprecated 0.52 — `onChange` (the same call); removed in 0.53. */
|
|
41
|
-
onPick: (size: TextSize) => void;
|
|
42
|
-
}
|
|
43
|
-
);
|
|
44
|
-
|
|
45
27
|
/**
|
|
46
28
|
* The text size one tap away, INSIDE the account menu (0.46, keksdose live #426, its
|
|
47
29
|
* `TextSizeRow`): the row's icon and name, the size in force, and A− / A+, which step
|
|
@@ -55,15 +37,14 @@ export type AccountMenuTextSizeProps = AccountMenuTextSizeBaseProps &
|
|
|
55
37
|
* behind it and can step again. The size's name is a polite live region, so a step is
|
|
56
38
|
* announced.
|
|
57
39
|
*/
|
|
58
|
-
export function AccountMenuTextSize({ value, onChange,
|
|
59
|
-
const change = onChange ?? onPick;
|
|
40
|
+
export function AccountMenuTextSize({ value, onChange, label, labels: labelsProp }: AccountMenuTextSizeProps) {
|
|
60
41
|
const labels = useAppearanceLabels(labelsProp);
|
|
61
42
|
const onHtml = useTextSize().size;
|
|
62
43
|
const size = value ?? onHtml;
|
|
63
44
|
const index = TEXT_SIZES.indexOf(size);
|
|
64
45
|
const step = (by: -1 | 1) => {
|
|
65
46
|
const next = TEXT_SIZES[index + by];
|
|
66
|
-
if (next)
|
|
47
|
+
if (next) onChange(next);
|
|
67
48
|
};
|
|
68
49
|
return (
|
|
69
50
|
<li data-account-menu-text-size="" className="flex items-center gap-2 px-3 py-1.5 text-sm">
|
package/src/shell/app-shell.tsx
CHANGED
|
@@ -201,19 +201,6 @@ export function pickMobileBar<T>(
|
|
|
201
201
|
};
|
|
202
202
|
}
|
|
203
203
|
|
|
204
|
-
/**
|
|
205
|
-
* Split the bar's entries into the cells shown and the ones under "More", in the app's
|
|
206
|
-
* order (§10.7: the app puts its four most used first, or orders by role). One hidden
|
|
207
|
-
* entry is no saving — the More cell would take its place — so the bar then shows them
|
|
208
|
-
* all: the cell count is the same either way, and a real entry beats a detour.
|
|
209
|
-
*/
|
|
210
|
-
export function splitMobileBar<T>(entries: readonly T[], max: number): { shown: T[]; hidden: T[] } {
|
|
211
|
-
// Entries before More, as 0.32 counted them; {@link pickMobileBar} counts cells.
|
|
212
|
-
const limit = Math.max(1, Math.floor(max));
|
|
213
|
-
if (entries.length <= limit + 1) return { shown: [...entries], hidden: [] };
|
|
214
|
-
return { shown: entries.slice(0, limit), hidden: entries.slice(limit) };
|
|
215
|
-
}
|
|
216
|
-
|
|
217
204
|
/** The bar's cell count at `size`: `mobileMaxItems`, else the default. */
|
|
218
205
|
function mobileCells(maxItems: AppShellProps["mobileMaxItems"], size: TextSize): number {
|
|
219
206
|
if (maxItems === undefined) return DEFAULT_MOBILE_MAX_ITEMS[size];
|
|
@@ -56,7 +56,7 @@ export interface CompanySwitcherProps<Id extends string | number> {
|
|
|
56
56
|
* The company switcher in the top bar (docs/auth-harmonization.md §5.3, §8): a kastlan
|
|
57
57
|
* user may belong to several companies, and the access token carries the current one,
|
|
58
58
|
* so switching is a request for new tokens — `onSwitch`, the app's. Built on
|
|
59
|
-
* {@link OptionSwitcherMenu}
|
|
59
|
+
* {@link OptionSwitcherMenu}: the icon trigger, the current company
|
|
60
60
|
* in its tooltip, the list with a check on the current one.
|
|
61
61
|
*
|
|
62
62
|
* **Only for more than one company** — a user in one company has nothing to switch, and
|
package/src/shell/dev-menu.tsx
CHANGED
|
@@ -95,7 +95,7 @@ const isRow = (entry: TopBarMenuEntry) => entry.kind !== "heading" && entry.kind
|
|
|
95
95
|
|
|
96
96
|
/**
|
|
97
97
|
* The top bar's local-dev menu (docs/top-bar-harmonization.md §2.7, §2.7.1, §6.2, §6.3):
|
|
98
|
-
* ONE amber flask
|
|
98
|
+
* ONE amber flask over the kit's Account section and the app's own.
|
|
99
99
|
*
|
|
100
100
|
* 0.42's `DevSwitchers` drew a flask per switcher and had no place for anything else,
|
|
101
101
|
* and an app has more dev controls than a role and a plan — keksdose's budget role, a
|
|
@@ -6,7 +6,7 @@ import { useKitLabels, type LabelOverride } from "../i18n/kit-labels";
|
|
|
6
6
|
* `DevSwitchers`, whose words these still are, §2.7.1). A module
|
|
7
7
|
* of words with no component code, like every `*-labels.ts` (0.34, KS U8). The language
|
|
8
8
|
* sub-list (`AccountMenuLanguage`) names itself with `topBar.language`, and the role in the
|
|
9
|
-
* dev flask's name is `topBar.role
|
|
9
|
+
* dev flask's name is `topBar.role`.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
/** `TourMenu`'s words (§2.4). */
|
package/src/shell.ts
CHANGED
|
@@ -4,17 +4,20 @@
|
|
|
4
4
|
// `react-router`: AppShell renders NavLink and TopBarActionMenu renders Link.
|
|
5
5
|
export * from "./shell/topbar-controls";
|
|
6
6
|
export * from "./shell/top-bar";
|
|
7
|
-
|
|
8
|
-
//
|
|
9
|
-
//
|
|
7
|
+
// Named, not `*`: 0.53 took `pickMobileBar` off the surface (deprecated in 0.52, refactor
|
|
8
|
+
// audit 2026-10-30, API-4) — AppShell's own — and removed `splitMobileBar`, which nothing
|
|
9
|
+
// called any more.
|
|
10
10
|
export {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
DEFAULT_APP_SHELL_MORE_LABELS,
|
|
12
|
+
DEFAULT_MOBILE_MAX_ITEMS,
|
|
13
|
+
AppShell,
|
|
14
|
+
type AppShellSubItem,
|
|
15
|
+
type AppShellNavItem,
|
|
16
|
+
type AppShellSidebarFooterItem,
|
|
17
|
+
type AppShellMoreLabels,
|
|
18
|
+
type AppShellProps,
|
|
15
19
|
} from "./shell/app-shell";
|
|
16
20
|
export * from "./shell/option-switcher-menu";
|
|
17
|
-
export * from "./shell/role-switcher";
|
|
18
21
|
export * from "./shell/topbar-action-menu";
|
|
19
22
|
export * from "./shell/top-bar-brand";
|
|
20
23
|
export * from "./shell/auth-layout";
|
|
@@ -33,20 +36,9 @@ export type { UseAdminMenuEntryOptions } from "./shell/admin-menu";
|
|
|
33
36
|
export { AdminWaitingBadge } from "./shell/admin-menu";
|
|
34
37
|
export type { AdminWaitingBadgeProps } from "./shell/admin-menu";
|
|
35
38
|
// 0.31.0: the settings and admin pages' shell (docs/settings-harmonization.md §3, §5).
|
|
36
|
-
export {
|
|
37
|
-
SettingsLayout,
|
|
38
|
-
/** @deprecated 0.52 — `SettingsLayout`, which shows its search past that many entries (API-4); removed in 0.53 */
|
|
39
|
-
SETTINGS_SEARCH_THRESHOLD,
|
|
40
|
-
} from "./settings/settings-layout";
|
|
39
|
+
export { SettingsLayout } from "./settings/settings-layout";
|
|
41
40
|
export type { SettingsLayoutProps, SettingsLayoutWidth, SettingsDocumentTitleParts } from "./settings/settings-layout";
|
|
42
|
-
export {
|
|
43
|
-
useSettingsRoute,
|
|
44
|
-
/** @deprecated 0.52 — `useSettingsRoute`, which resolves the location with it (API-4); removed in 0.53 */
|
|
45
|
-
resolveSettingsLocation,
|
|
46
|
-
settingsFromListState,
|
|
47
|
-
/** @deprecated 0.52 — `settingsFromListState` and `useSettingsRoute`, which write and read it (API-4); removed in 0.53 */
|
|
48
|
-
SETTINGS_FROM_LIST_STATE,
|
|
49
|
-
} from "./settings/use-settings-route";
|
|
41
|
+
export { useSettingsRoute, settingsFromListState } from "./settings/use-settings-route";
|
|
50
42
|
export type {
|
|
51
43
|
UseSettingsRouteOptions,
|
|
52
44
|
SettingsRoute,
|
|
@@ -55,14 +47,7 @@ export type {
|
|
|
55
47
|
SettingsLocationRules,
|
|
56
48
|
SettingsLocationResult,
|
|
57
49
|
} from "./settings/use-settings-route";
|
|
58
|
-
export {
|
|
59
|
-
useSettingsFocus,
|
|
60
|
-
useFocusParam,
|
|
61
|
-
/** @deprecated 0.52 — `useSettingsFocus` / `useFocusParam`, which ring the card with it (API-4); removed in 0.53 */
|
|
62
|
-
SETTINGS_FOCUS_RING,
|
|
63
|
-
/** @deprecated 0.52 — `useSettingsFocus` / `useFocusParam`, which hold the ring that long (API-4); removed in 0.53 */
|
|
64
|
-
SETTINGS_FOCUS_MS,
|
|
65
|
-
} from "./settings/use-settings-focus";
|
|
50
|
+
export { useSettingsFocus, useFocusParam } from "./settings/use-settings-focus";
|
|
66
51
|
export { SettingsSection } from "./settings/settings-section";
|
|
67
52
|
export type { SettingsSectionProps } from "./settings/settings-section";
|
|
68
53
|
export { useSettingsLayout } from "./settings/settings-context";
|
|
@@ -99,11 +84,7 @@ export type { PublicHeaderProps, PublicHeaderBrand } from "./landing/public-head
|
|
|
99
84
|
// 0.42.0: the top bar's shared parts (docs/top-bar-harmonization.md §3.1) — the slots in
|
|
100
85
|
// §2.1's order, the account menu's language sub-list, the tours menu, the sync status, the
|
|
101
86
|
// local-dev menu, and their words.
|
|
102
|
-
export {
|
|
103
|
-
TopBarActions,
|
|
104
|
-
/** @deprecated 0.52 — `TopBarActions`, which puts its slots in that order (API-4); removed in 0.53 */
|
|
105
|
-
TOP_BAR_ACTION_ORDER,
|
|
106
|
-
} from "./shell/top-bar-actions";
|
|
87
|
+
export { TopBarActions } from "./shell/top-bar-actions";
|
|
107
88
|
export type { TopBarActionsProps } from "./shell/top-bar-actions";
|
|
108
89
|
export { AccountMenuLanguage } from "./shell/account-menu-language";
|
|
109
90
|
export type { AccountMenuLanguageProps, AccountMenuLanguageOption } from "./shell/account-menu-language";
|
|
@@ -112,19 +93,11 @@ export { AccountMenuTextSize } from "./shell/account-menu-text-size";
|
|
|
112
93
|
export type { AccountMenuTextSizeProps } from "./shell/account-menu-text-size";
|
|
113
94
|
export { TourMenu } from "./shell/tour-menu";
|
|
114
95
|
export type { TourMenuProps, TourMenuTour } from "./shell/tour-menu";
|
|
115
|
-
export {
|
|
116
|
-
SyncStatusIndicator,
|
|
117
|
-
/** @deprecated 0.52 — `SyncStatusIndicator`, which derives its state with it (API-4); removed in 0.53 */
|
|
118
|
-
syncState,
|
|
119
|
-
} from "./shell/sync-status-indicator";
|
|
96
|
+
export { SyncStatusIndicator } from "./shell/sync-status-indicator";
|
|
120
97
|
export type { SyncStatus, SyncState, SyncStatusScope, SyncStatusIndicatorProps } from "./shell/sync-status-indicator";
|
|
121
98
|
// 0.51 (§2.7.1, keksdose): one flask, the kit's Account section and the app's own dev
|
|
122
99
|
// sections. 0.42's `DevSwitchers`, a DevMenu with no sections since 0.51, went in 0.52.
|
|
123
|
-
export {
|
|
124
|
-
DevMenu,
|
|
125
|
-
/** @deprecated 0.52 — `DevMenu`, which keeps the role there unless `storageKey` names another key (API-4); removed in 0.53 */
|
|
126
|
-
DEV_ORIGINAL_ROLE_KEY,
|
|
127
|
-
} from "./shell/dev-menu";
|
|
100
|
+
export { DevMenu } from "./shell/dev-menu";
|
|
128
101
|
export type { DevMenuProps, DevMenuSection } from "./shell/dev-menu";
|
|
129
102
|
export { DEFAULT_TOP_BAR_PARTS_LABELS, useTopBarPartsLabels } from "./shell/top-bar-parts-labels";
|
|
130
103
|
export type {
|
package/src/sync.ts
CHANGED
|
@@ -4,13 +4,7 @@
|
|
|
4
4
|
// The only entry point that imports `dexie` — an optional peer for that reason. It never loads
|
|
5
5
|
// `/offline`'s TanStack and idb-keyval peers: the leaf utilities both entries export live in
|
|
6
6
|
// one module of their own (src/offline/local-first.ts). NOT re-exported from the main barrel.
|
|
7
|
-
export {
|
|
8
|
-
createSyncDb,
|
|
9
|
-
rowByPk,
|
|
10
|
-
SYNC_DB_PK_INDEX,
|
|
11
|
-
/** @deprecated 0.52 — `createSyncDb`, which declares them (`extraStores` for an app's own) (API-4); removed in 0.53 */
|
|
12
|
-
SYNC_DB_STORES,
|
|
13
|
-
} from "./sync/db";
|
|
7
|
+
export { createSyncDb, rowByPk, SYNC_DB_PK_INDEX } from "./sync/db";
|
|
14
8
|
export type {
|
|
15
9
|
CreateSyncDbOptions,
|
|
16
10
|
OutboxChange,
|
|
@@ -20,14 +14,7 @@ export type {
|
|
|
20
14
|
SyncedRow,
|
|
21
15
|
SyncMetaEntry,
|
|
22
16
|
} from "./sync/db";
|
|
23
|
-
export {
|
|
24
|
-
createSyncEngine,
|
|
25
|
-
DEFAULT_HOLD_CODES,
|
|
26
|
-
/** @deprecated 0.52 — `createSyncEngine`, whose `backoffMs` defaults to it (API-4); removed in 0.53 */
|
|
27
|
-
DEFAULT_SYNC_BACKOFF_MS,
|
|
28
|
-
releaseSyncEngine,
|
|
29
|
-
syncEngineFor,
|
|
30
|
-
} from "./sync/engine";
|
|
17
|
+
export { createSyncEngine, DEFAULT_HOLD_CODES, releaseSyncEngine, syncEngineFor } from "./sync/engine";
|
|
31
18
|
export type {
|
|
32
19
|
SyncCounts,
|
|
33
20
|
SyncEngine,
|
|
@@ -74,8 +74,6 @@ export const CHART_ROLES = {
|
|
|
74
74
|
outline: "var(--chart-ink)",
|
|
75
75
|
} as const;
|
|
76
76
|
|
|
77
|
-
/** `--chart-ink` per theme, as hex (tokens.css holds the same two). */
|
|
78
|
-
export const CHART_INK_HEX = { light: "#1a1a17", dark: "#f0efe8" } as const;
|
|
79
77
|
/** `--chart-muted` per theme, as hex (tokens.css holds the same two). */
|
|
80
78
|
export const CHART_MUTED_HEX = { light: "#6b6a63", dark: "#a8a79f" } as const;
|
|
81
79
|
|
package/tokens.css
CHANGED
|
@@ -397,13 +397,13 @@ html[data-text-size="xlarge"] {
|
|
|
397
397
|
was: beside red-700 that orange read as a second error colour, and "unsaved" has
|
|
398
398
|
to look like a caution, not an alarm. Light, it is amber-600's hue and chroma at a
|
|
399
399
|
SOLVED lightness (3.1:1 on the worst surface). Below 4.5:1, so it is not a TEXT
|
|
400
|
-
colour:
|
|
400
|
+
colour: a state's words go in `--text-secondary` beside it.
|
|
401
401
|
|
|
402
402
|
GREEN AND RED ARE THE CLASSIC CVD-UNSAFE PAIR, and the rest of this file goes out
|
|
403
403
|
of its way to avoid it — the money trio is teal/amber/violet for exactly this
|
|
404
404
|
reason. They are used here because the states were specified in these colours, so
|
|
405
|
-
|
|
406
|
-
|
|
405
|
+
every state needs its own ICON as well and colour is never the only signal (as
|
|
406
|
+
FieldSyncIndicator, which drew them until 0.53, gave it). Do not drop the icons. */
|
|
407
407
|
--status-synced: #166534; /* green-800 — persisted */
|
|
408
408
|
--status-pending: #1d4ed8; /* blue-700 — in flight */
|
|
409
409
|
--status-edited: #bf6800; /* solved — dirty, not yet saved */
|
|
@@ -871,7 +871,7 @@ html[data-text-size="xlarge"] {
|
|
|
871
871
|
* counts a `[var(--role)]` class, and a `ring-[length:var(--…)]` width, for any token that
|
|
872
872
|
* has a utility here and allows none (`ROLE_BUDGET` 0). What stays `[var()]` has no
|
|
873
873
|
* utility on purpose: the chart colours (lookup tables of `--chart-N`), `--status-*`
|
|
874
|
-
* (
|
|
874
|
+
* (the field-sync four), and the cross-property one-offs (`bg-[var(--border)]` as a
|
|
875
875
|
* divider, `ring-[var(--text-primary)]`) — a utility there would undo the property
|
|
876
876
|
* scoping above. `check:tailwind` asserts one per namespace survives a build, and the
|
|
877
877
|
* README's "Styling" table is generated from this block (`scripts/gen-styling-inventory.mjs`).
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* How the three billing confirms — `CancelSubscriptionConfirm`, `PlanSwitchConfirm`,
|
|
3
|
-
* `GrantWarningConfirm` — are closed in 0.52: `onClose`, as every other kit dialog
|
|
4
|
-
* (CONTRIBUTING §4; refactor audit 2026-10-30, API-5), and for one minor the deprecated
|
|
5
|
-
* `onOpenChange`, called with `false` when there is no `onClose`.
|
|
6
|
-
*
|
|
7
|
-
* 0.52 made `onOpenChange` optional for its deprecation and gave `onClose` beside it as
|
|
8
|
-
* optional too, so a confirm given NEITHER compiled — `<CancelSubscriptionConfirm open
|
|
9
|
-
* periodEnd={…} onConfirm={…} />` — and Back, Escape and the backdrop then called nothing:
|
|
10
|
-
* a dialog nobody could dismiss, where 0.51's compiler had required `onOpenChange` (0.52
|
|
11
|
-
* code review, cancel-subscription.tsx). And the fallback between the two was written
|
|
12
|
-
* three times, once per dialog.
|
|
13
|
-
*
|
|
14
|
-
* @internal Not part of the barrel; each dialog's props type is.
|
|
15
|
-
*/
|
|
16
|
-
/** The two close props as a dialog's own props interface declares them. */
|
|
17
|
-
interface CloseProps {
|
|
18
|
-
onClose?: () => void;
|
|
19
|
-
onOpenChange?: (open: boolean) => void;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* `P` with ONE of its two close props required — `onClose`, or alone the deprecated
|
|
23
|
-
* `onOpenChange`; both may be given, and `onClose` is then the one called. Built from
|
|
24
|
-
* `P`'s own members (`Pick`), so their docs and the deprecation stay the ones `P` writes.
|
|
25
|
-
*/
|
|
26
|
-
export type WithDialogClose<P extends CloseProps> = P & (Required<Pick<P, "onClose">> | Required<Pick<P, "onOpenChange">>);
|
|
27
|
-
/** The dialog's close: `onClose`, else `onOpenChange(false)`. */
|
|
28
|
-
export declare function dialogClose({ onClose, onOpenChange }: CloseProps): () => void;
|
|
29
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/billing/dialog-close.ts"],"sourcesContent":["/**\n * How the three billing confirms — `CancelSubscriptionConfirm`, `PlanSwitchConfirm`,\n * `GrantWarningConfirm` — are closed in 0.52: `onClose`, as every other kit dialog\n * (CONTRIBUTING §4; refactor audit 2026-10-30, API-5), and for one minor the deprecated\n * `onOpenChange`, called with `false` when there is no `onClose`.\n *\n * 0.52 made `onOpenChange` optional for its deprecation and gave `onClose` beside it as\n * optional too, so a confirm given NEITHER compiled — `<CancelSubscriptionConfirm open\n * periodEnd={…} onConfirm={…} />` — and Back, Escape and the backdrop then called nothing:\n * a dialog nobody could dismiss, where 0.51's compiler had required `onOpenChange` (0.52\n * code review, cancel-subscription.tsx). And the fallback between the two was written\n * three times, once per dialog.\n *\n * @internal Not part of the barrel; each dialog's props type is.\n */\n\n/** The two close props as a dialog's own props interface declares them. */\ninterface CloseProps {\n onClose?: () => void;\n onOpenChange?: (open: boolean) => void;\n}\n\n/**\n * `P` with ONE of its two close props required — `onClose`, or alone the deprecated\n * `onOpenChange`; both may be given, and `onClose` is then the one called. Built from\n * `P`'s own members (`Pick`), so their docs and the deprecation stay the ones `P` writes.\n */\nexport type WithDialogClose<P extends CloseProps> = P &\n (Required<Pick<P, \"onClose\">> | Required<Pick<P, \"onOpenChange\">>);\n\n/** The dialog's close: `onClose`, else `onOpenChange(false)`. */\nexport function dialogClose({ onClose, onOpenChange }: CloseProps): () => void {\n return () => (onClose ? onClose() : onOpenChange?.(false));\n}\n"],"mappings":";AA+BO,SAAS,YAAY,EAAE,SAAS,aAAa,GAA2B;AAC7E,SAAO,MAAO,UAAU,QAAQ,IAAI,eAAe,KAAK;AAC1D;","names":[]}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
const DEFAULT_FIELD_SYNC_LABELS = {
|
|
3
|
-
synced: "Saved",
|
|
4
|
-
edited: "Unsaved changes",
|
|
5
|
-
pending: "Saving\u2026",
|
|
6
|
-
error: "Could not save",
|
|
7
|
-
retry: "Retry"
|
|
8
|
-
};
|
|
9
|
-
export {
|
|
10
|
-
DEFAULT_FIELD_SYNC_LABELS
|
|
11
|
-
};
|
|
12
|
-
//# sourceMappingURL=field-sync-labels.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/field-sync-labels.ts"],"sourcesContent":["// The English words of ./field-sync, in a module with no component code: the English\n// catalogue (src/i18n/defaults.ts) imports them without the component, so `en` loads as one\n// chunk like the other languages (0.34, KS U8). ./field-sync re-exports them.\n\nimport type { FieldSyncLabels } from \"./field-sync\";\n\n/** @deprecated 0.52 — none: no app uses the FieldSync family (MOD-5); removed in 0.53. */\nexport const DEFAULT_FIELD_SYNC_LABELS: FieldSyncLabels = {\n synced: \"Saved\",\n edited: \"Unsaved changes\",\n pending: \"Saving…\",\n error: \"Could not save\",\n retry: \"Retry\",\n};\n"],"mappings":";AAOO,MAAM,4BAA6C;AAAA,EACxD,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,OAAO;AAAA,EACP,OAAO;AACT;","names":[]}
|
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from "react";
|
|
2
|
-
import { type LabelOverride } from "../i18n/kit-labels.js";
|
|
3
|
-
import { DEFAULT_FIELD_SYNC_LABELS } from "./field-sync-labels.js";
|
|
4
|
-
/**
|
|
5
|
-
* Sync state for a field backed by a database row.
|
|
6
|
-
*
|
|
7
|
-
* The four states a value can be in between the keyboard and the server:
|
|
8
|
-
*
|
|
9
|
-
* synced the draft equals what was last persisted
|
|
10
|
-
* edited the draft differs and nothing has been sent yet
|
|
11
|
-
* pending a save is in flight
|
|
12
|
-
* error the last save was rejected; `error` carries why
|
|
13
|
-
*
|
|
14
|
-
* `useFieldSync` is the engine and holds no opinion about markup;
|
|
15
|
-
* `FieldSyncIndicator` is the affordance and holds no state. They are separate
|
|
16
|
-
* because the state is useful without the dot — a form can disable its submit
|
|
17
|
-
* button while any field is `pending`, and a router can block navigation while
|
|
18
|
-
* any field is `edited`.
|
|
19
|
-
*
|
|
20
|
-
* Deprecated in 0.52 as a whole, removed in 0.53 (decision 4 of the refactor audit
|
|
21
|
-
* 2026-10-30, MOD-5): no app renders it or calls the hook — 483 lines and a namespace in
|
|
22
|
-
* seven catalogues that only this package's tests and showcase read. An app that wants
|
|
23
|
-
* it keeps a copy of this file.
|
|
24
|
-
*
|
|
25
|
-
* @deprecated 0.52 — none: no app uses the FieldSync family (MOD-5); removed in 0.53.
|
|
26
|
-
*/
|
|
27
|
-
export type FieldSyncState = "synced" | "edited" | "pending" | "error";
|
|
28
|
-
/** @deprecated 0.52 — none: no app uses the FieldSync family (MOD-5); removed in 0.53. */
|
|
29
|
-
export interface FieldSyncLabels {
|
|
30
|
-
synced: string;
|
|
31
|
-
edited: string;
|
|
32
|
-
pending: string;
|
|
33
|
-
/** Shown when the failure carries no message of its own. */
|
|
34
|
-
error: string;
|
|
35
|
-
retry: string;
|
|
36
|
-
}
|
|
37
|
-
export { DEFAULT_FIELD_SYNC_LABELS };
|
|
38
|
-
/** @deprecated 0.52 — none: no app uses the FieldSync family (MOD-5); removed in 0.53. */
|
|
39
|
-
export interface UseFieldSyncOptions<T> {
|
|
40
|
-
/** What the database currently holds. Changing it re-seeds a CLEAN field. */
|
|
41
|
-
value: T;
|
|
42
|
-
/** Persist `next`. Reject — or throw — to put the field in `error`. */
|
|
43
|
-
onSave: (next: T) => Promise<void> | void;
|
|
44
|
-
/**
|
|
45
|
-
* Quiet period before an edit saves itself, in ms. Default `0`: no auto-save at
|
|
46
|
-
* all, so `save()` is the only way to persist — called on blur by `FieldSyncRow`,
|
|
47
|
-
* and on Enter by the caller. Saving after a pause in typing wrote half-finished
|
|
48
|
-
* values to the database whenever somebody stopped to think; pass a positive
|
|
49
|
-
* number only for a field where that is genuinely wanted.
|
|
50
|
-
*/
|
|
51
|
-
debounceMs?: number;
|
|
52
|
-
/** How to tell two values apart. Defaults to `Object.is`. */
|
|
53
|
-
equals?: (a: T, b: T) => boolean;
|
|
54
|
-
/** Called once per rejected save, with whatever `onSave` threw. */
|
|
55
|
-
onError?: (error: Error) => void;
|
|
56
|
-
}
|
|
57
|
-
/** @deprecated 0.52 — none: no app uses the FieldSync family (MOD-5); removed in 0.53. */
|
|
58
|
-
export interface UseFieldSyncReturn<T> {
|
|
59
|
-
/** The draft — bind this to the input, not the `value` option. */
|
|
60
|
-
value: T;
|
|
61
|
-
setValue: (next: T) => void;
|
|
62
|
-
state: FieldSyncState;
|
|
63
|
-
/** Non-null exactly when `state === "error"`. */
|
|
64
|
-
error: Error | null;
|
|
65
|
-
/** True whenever the draft differs from the last persisted value. */
|
|
66
|
-
dirty: boolean;
|
|
67
|
-
/** Persist now, cancelling any pending debounce. A no-op on a clean field. */
|
|
68
|
-
save: () => void;
|
|
69
|
-
/** Send the current draft again after a failure. */
|
|
70
|
-
retry: () => void;
|
|
71
|
-
/** Throw the draft away and go back to the last persisted value. */
|
|
72
|
-
reset: () => void;
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Track one database-backed field: a local draft, a debounced save, and the state
|
|
76
|
-
* of the round trip.
|
|
77
|
-
*
|
|
78
|
-
* Four things this handles that a `useState` + `useEffect` in a page does not:
|
|
79
|
-
*
|
|
80
|
-
* 1. **An edit during a save is never lost.** A save in flight is not cancelled
|
|
81
|
-
* and not raced — when it settles, the draft is compared again and sent once
|
|
82
|
-
* more if it moved. Cancelling instead would drop a keystroke that arrived
|
|
83
|
-
* mid-flight; firing immediately would let two writes land out of order.
|
|
84
|
-
* 2. **The server value is only adopted when the field is clean.** An external
|
|
85
|
-
* refresh that overwrote what somebody was typing would be a data-loss bug, so
|
|
86
|
-
* a dirty draft wins and keeps winning until it is saved or reset.
|
|
87
|
-
* 3. **Nothing is set after unmount.** The save resolves into a component that
|
|
88
|
-
* may be gone — a row scrolled out of a virtualised table, a closed dialog.
|
|
89
|
-
* 4. **`onSave` is read through a ref**, so an inline arrow — which every call
|
|
90
|
-
* site will pass — does not restart the debounce on every render.
|
|
91
|
-
*
|
|
92
|
-
* @deprecated 0.52 — none: no app uses the FieldSync family (MOD-5); removed in 0.53.
|
|
93
|
-
*/
|
|
94
|
-
export declare function useFieldSync<T>({ value, onSave, debounceMs, equals, onError, }: UseFieldSyncOptions<T>): UseFieldSyncReturn<T>;
|
|
95
|
-
/** @deprecated 0.52 — none: no app uses the FieldSync family (MOD-5); removed in 0.53. */
|
|
96
|
-
export interface FieldSyncIndicatorProps {
|
|
97
|
-
state: FieldSyncState;
|
|
98
|
-
/** The failure. Its message becomes the tooltip when `state === "error"`. */
|
|
99
|
-
error?: Error | null;
|
|
100
|
-
/** Override any of the five English defaults. */
|
|
101
|
-
labels?: LabelOverride<FieldSyncLabels>;
|
|
102
|
-
/** Render the label beside the icon instead of only in the tooltip. Always on at
|
|
103
|
-
* Large and Extra large (0.32, docs/text-size-harmonization.md §4 "No fact only in a
|
|
104
|
-
* tooltip"): the reader who asked for bigger type gets the words, not a 14 px glyph
|
|
105
|
-
* and a bubble. */
|
|
106
|
-
showLabel?: boolean;
|
|
107
|
-
/** When given, the error state renders a retry button after the icon. */
|
|
108
|
-
onRetry?: () => void;
|
|
109
|
-
className?: string;
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* The affordance for {@link useFieldSync}: a coloured icon, and the reason on hover.
|
|
113
|
-
*
|
|
114
|
-
* **Every state has its own icon, and that is not decoration.** The four colours
|
|
115
|
-
* include the green/red pair, which is the one combination this package's palette
|
|
116
|
-
* otherwise refuses (see the note in `tokens.css`) because red-green colour blindness
|
|
117
|
-
* affects roughly one man in twelve. The icon is what carries the meaning for them,
|
|
118
|
-
* and what carries it into a greyscale print or a screenshot. WCAG 1.4.1 is the same
|
|
119
|
-
* requirement stated formally.
|
|
120
|
-
*
|
|
121
|
-
* The state is also announced: the wrapper is a polite live region, so a screen
|
|
122
|
-
* reader hears "Saving…" then "Saved" without the user going looking. `error` is
|
|
123
|
-
* assertive instead — a failed write is worth interrupting for.
|
|
124
|
-
*
|
|
125
|
-
* @deprecated 0.52 — none: no app uses the FieldSync family (MOD-5); removed in 0.53.
|
|
126
|
-
*/
|
|
127
|
-
export declare function FieldSyncIndicator({ state, error, labels, showLabel, onRetry, className, }: FieldSyncIndicatorProps): import("react").JSX.Element;
|
|
128
|
-
/**
|
|
129
|
-
* The field's own frame, coloured by state — applied from the WRAPPER to whatever
|
|
130
|
-
* native control sits inside it, so {@link FieldSyncRow} works with any of the kit's
|
|
131
|
-
* inputs (and a caller's own) without each one growing a `syncState` prop.
|
|
132
|
-
*
|
|
133
|
-
* Border AND a 1px ring, for the reason {@link FIELD_INVALID} gives: a lone 1px
|
|
134
|
-
* border loses a vertical edge to sub-pixel spread at 125% display scaling. The
|
|
135
|
-
* `:focus` twins are what keep the state visible while the reader is typing —
|
|
136
|
-
* the base field class's `focus:` brand colour is `(0,2,0)` and would otherwise win
|
|
137
|
-
* over a descendant selector exactly when the field is in use.
|
|
138
|
-
*
|
|
139
|
-
* `synced` is green, but {@link FieldSyncRow} paints it only for a moment after a
|
|
140
|
-
* save lands — a form of eight permanently green boxes says nothing the absence of
|
|
141
|
-
* colour does not.
|
|
142
|
-
*
|
|
143
|
-
* Every class is a literal so Tailwind's scanner can see it.
|
|
144
|
-
*
|
|
145
|
-
* @deprecated 0.52 — none: no app uses the FieldSync family (MOD-5); removed in 0.53.
|
|
146
|
-
*/
|
|
147
|
-
export declare const FIELD_SYNC_FRAME: Record<FieldSyncState, string>;
|
|
148
|
-
/** How long the green "saved" frame and check stay after a save lands, in ms.
|
|
149
|
-
*
|
|
150
|
-
* @deprecated 0.52 — none: no app uses the FieldSync family (MOD-5); removed in 0.53. */
|
|
151
|
-
export declare const FIELD_SYNC_SAVED_MS = 1500;
|
|
152
|
-
/** @deprecated 0.52 — none: no app uses the FieldSync family (MOD-5); removed in 0.53. */
|
|
153
|
-
export interface FieldSyncRowProps<T> extends Omit<FieldSyncIndicatorProps, "state" | "error" | "showLabel"> {
|
|
154
|
-
sync: UseFieldSyncReturn<T>;
|
|
155
|
-
children: ReactNode;
|
|
156
|
-
/** Call `sync.save()` when focus leaves the field. Default true — together with the
|
|
157
|
-
* hook's default `debounceMs: 0` this is "save on blur": nothing is written while
|
|
158
|
-
* the reader is still typing, however long they pause. */
|
|
159
|
-
saveOnBlur?: boolean;
|
|
160
|
-
/** How long the saved confirmation shows. Default {@link FIELD_SYNC_SAVED_MS}. */
|
|
161
|
-
savedMs?: number;
|
|
162
|
-
}
|
|
163
|
-
/**
|
|
164
|
-
* A field wearing its sync state — as its FRAME COLOUR and an ICON AT THE END OF THE
|
|
165
|
-
* FIELD, so the field never changes size (a helper line appearing under it moved
|
|
166
|
-
* everything below it on every save):
|
|
167
|
-
*
|
|
168
|
-
* edited amber frame, pencil — changed, not yet saved
|
|
169
|
-
* pending blue frame, spinning circle — for as long as the save is in flight
|
|
170
|
-
* synced green frame, check — for {@link FIELD_SYNC_SAVED_MS} after a
|
|
171
|
-
* save lands, then an ordinary field again
|
|
172
|
-
* error red frame, alert mark — hover or focus the mark for the reason;
|
|
173
|
-
* click it to retry
|
|
174
|
-
*
|
|
175
|
-
* It saves when focus LEAVES the field (`saveOnBlur`), not after a pause in typing: a
|
|
176
|
-
* database write in the middle of a word is a write nobody asked for. Enter in a
|
|
177
|
-
* single-line field is the caller's to wire to `sync.save`.
|
|
178
|
-
*
|
|
179
|
-
* Colour is never the only signal: every state has its own icon, and the state text is
|
|
180
|
-
* always in the DOM as a live region — polite for the ordinary states, assertive for
|
|
181
|
-
* a failure. The input gets end padding for the icon whether or not one is showing,
|
|
182
|
-
* so the text never reflows when the state changes.
|
|
183
|
-
*
|
|
184
|
-
* @deprecated 0.52 — none: no app uses the FieldSync family (MOD-5); removed in 0.53.
|
|
185
|
-
*/
|
|
186
|
-
export declare function FieldSyncRow<T>({ sync, children, className, labels, onRetry, saveOnBlur, savedMs, }: FieldSyncRowProps<T>): import("react").JSX.Element;
|