@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
|
@@ -8,19 +8,14 @@ import { DialogFrame } from "../components/dialog-frame";
|
|
|
8
8
|
import { COMMIT_EXCEPT_BILLING } from "../components/write-lock";
|
|
9
9
|
import { useBillingLabels } from "./billing-labels";
|
|
10
10
|
import type { BillingLabels } from "./billing-labels";
|
|
11
|
-
import { dialogClose } from "./dialog-close";
|
|
12
|
-
import type { WithDialogClose } from "./dialog-close";
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
interface CancelSubscriptionConfirmFields {
|
|
12
|
+
export interface CancelSubscriptionConfirmProps {
|
|
16
13
|
open: boolean;
|
|
17
14
|
/** The admin dismissed it — Back, Escape, the backdrop. Confirm leaves it open: close it
|
|
18
15
|
* once `POST /billing/cancel` answers. 0.52: every other kit dialog's `onClose`
|
|
19
|
-
* (CONTRIBUTING §4; refactor audit 2026-10-30, API-5).
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
* `false` when there is no `onClose`. */
|
|
23
|
-
onOpenChange?: (open: boolean) => void;
|
|
16
|
+
* (CONTRIBUTING §4; refactor audit 2026-10-30, API-5); required since 0.53 removed
|
|
17
|
+
* `onOpenChange` (deprecated in 0.52). */
|
|
18
|
+
onClose: () => void;
|
|
24
19
|
/** The overview's `current_period_end`: the day the subscription ends, in a sentence —
|
|
25
20
|
* the `<UiKitProvider formatDate>` (the app's date preference) when it set one, else the
|
|
26
21
|
* kit's `formatDate`, `"medium"`, in the provider's locale and `timeZone` (0.52). */
|
|
@@ -36,11 +31,6 @@ interface CancelSubscriptionConfirmFields {
|
|
|
36
31
|
labels?: LabelOverride<BillingLabels>;
|
|
37
32
|
}
|
|
38
33
|
|
|
39
|
-
/** What {@link CancelSubscriptionConfirm} takes: `onClose`, or alone the deprecated
|
|
40
|
-
* `onOpenChange`, is required (0.52 code review: with neither it compiled, and nothing
|
|
41
|
-
* could dismiss it). */
|
|
42
|
-
export type CancelSubscriptionConfirmProps = WithDialogClose<CancelSubscriptionConfirmFields>;
|
|
43
|
-
|
|
44
34
|
/**
|
|
45
35
|
* The in-app cancel's confirm (docs/billing-harmonization.md §16.2 decision 2, §16.4,
|
|
46
36
|
* ui-kit 0.42): "Cancel subscription" for an admin the provider's portal doesn't open for
|
|
@@ -68,7 +58,6 @@ export type CancelSubscriptionConfirmProps = WithDialogClose<CancelSubscriptionC
|
|
|
68
58
|
export function CancelSubscriptionConfirm({
|
|
69
59
|
open,
|
|
70
60
|
onClose,
|
|
71
|
-
onOpenChange,
|
|
72
61
|
periodEnd,
|
|
73
62
|
onConfirm,
|
|
74
63
|
pending = false,
|
|
@@ -84,7 +73,7 @@ export function CancelSubscriptionConfirm({
|
|
|
84
73
|
open={open}
|
|
85
74
|
title={labels.cancelConfirmTitle}
|
|
86
75
|
description={labels.cancelConfirmBody(day(periodEnd))}
|
|
87
|
-
onClose={
|
|
76
|
+
onClose={onClose}
|
|
88
77
|
busy={pending}
|
|
89
78
|
data-cancel-subscription-confirm=""
|
|
90
79
|
actions={(close) => (
|
|
@@ -14,8 +14,6 @@ import { Button } from "../components/button";
|
|
|
14
14
|
import { DialogFrame } from "../components/dialog-frame";
|
|
15
15
|
import { useBillingLabels } from "./billing-labels";
|
|
16
16
|
import type { BillingLabels } from "./billing-labels";
|
|
17
|
-
import { dialogClose } from "./dialog-close";
|
|
18
|
-
import type { WithDialogClose } from "./dialog-close";
|
|
19
17
|
import { BILLING_INTERVALS, billingCurrencyFor, formatPlanPrice, planPrice } from "./plan-price";
|
|
20
18
|
import type { BillingCurrency, BillingInterval, PlanPrices } from "./plan-price";
|
|
21
19
|
|
|
@@ -502,16 +500,13 @@ export function PlanPicker({
|
|
|
502
500
|
);
|
|
503
501
|
}
|
|
504
502
|
|
|
505
|
-
|
|
506
|
-
interface GrantWarningConfirmFields {
|
|
503
|
+
export interface GrantWarningConfirmProps {
|
|
507
504
|
/** Shown, controlled. */
|
|
508
505
|
open: boolean;
|
|
509
506
|
/** "Back", Escape, the backdrop — and after "Buy anyway". 0.52: every other kit
|
|
510
|
-
* dialog's `onClose` (CONTRIBUTING §4; refactor audit 2026-10-30, API-5)
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
* `false` when there is no `onClose`. */
|
|
514
|
-
onOpenChange?: (open: boolean) => void;
|
|
507
|
+
* dialog's `onClose` (CONTRIBUTING §4; refactor audit 2026-10-30, API-5); required
|
|
508
|
+
* since 0.53 removed `onOpenChange` (deprecated in 0.52). */
|
|
509
|
+
onClose: () => void;
|
|
515
510
|
/** "Buy anyway": the app opens its checkout. The dialog closes itself after it. */
|
|
516
511
|
onConfirm: () => void;
|
|
517
512
|
/** Prop > `<UiKitProvider labels={{ billing }}>` > English: `grantWarningTitle`,
|
|
@@ -519,11 +514,6 @@ interface GrantWarningConfirmFields {
|
|
|
519
514
|
labels?: LabelOverride<BillingLabels>;
|
|
520
515
|
}
|
|
521
516
|
|
|
522
|
-
/** What {@link GrantWarningConfirm} takes: `onClose`, or alone the deprecated
|
|
523
|
-
* `onOpenChange`, is required (0.52 code review: with neither it compiled, and nothing
|
|
524
|
-
* could dismiss it). */
|
|
525
|
-
export type GrantWarningConfirmProps = WithDialogClose<GrantWarningConfirmFields>;
|
|
526
|
-
|
|
527
517
|
/**
|
|
528
518
|
* 0.42 (§16.8 B): the permanent-grant warning before a checkout — `grantWarningTitle`,
|
|
529
519
|
* `grantWarningBody`, "Back" and "Buy anyway" (`grantWarningAction`). {@link PlanPicker}
|
|
@@ -533,22 +523,15 @@ export type GrantWarningConfirmProps = WithDialogClose<GrantWarningConfirmFields
|
|
|
533
523
|
* to a checkout — show this before that checkout, so a permanent-grant holder is still
|
|
534
524
|
* warned. Carries `data-grant-warning`.
|
|
535
525
|
*/
|
|
536
|
-
export function GrantWarningConfirm({
|
|
537
|
-
open,
|
|
538
|
-
onClose,
|
|
539
|
-
onOpenChange,
|
|
540
|
-
onConfirm,
|
|
541
|
-
labels: labelsProp,
|
|
542
|
-
}: GrantWarningConfirmProps) {
|
|
526
|
+
export function GrantWarningConfirm({ open, onClose, onConfirm, labels: labelsProp }: GrantWarningConfirmProps) {
|
|
543
527
|
const labels = useBillingLabels(labelsProp);
|
|
544
528
|
const common = useKitLabels("common", DEFAULT_COMMON_LABELS);
|
|
545
|
-
const close = dialogClose({ onClose, onOpenChange });
|
|
546
529
|
return (
|
|
547
530
|
<DialogFrame
|
|
548
531
|
open={open}
|
|
549
532
|
title={labels.grantWarningTitle}
|
|
550
533
|
description={labels.grantWarningBody}
|
|
551
|
-
onClose={
|
|
534
|
+
onClose={onClose}
|
|
552
535
|
data-grant-warning=""
|
|
553
536
|
actions={(lower) => (
|
|
554
537
|
<>
|
|
@@ -567,7 +550,7 @@ export function GrantWarningConfirm({
|
|
|
567
550
|
// and the lowering panel is not inert: a double click on "Buy anyway" opened
|
|
568
551
|
// the checkout twice (0.52 code review, plan-card.tsx). The caller's `open`
|
|
569
552
|
// turning false still plays the exit.
|
|
570
|
-
|
|
553
|
+
onClose();
|
|
571
554
|
}}
|
|
572
555
|
>
|
|
573
556
|
{labels.grantWarningAction}
|
|
@@ -13,8 +13,6 @@ import { COMMIT_EXCEPT_BILLING } from "../components/write-lock";
|
|
|
13
13
|
import { DEFAULT_PLAN_CHANGE_LABELS } from "./plan-change-labels";
|
|
14
14
|
import { useBillingLabels } from "./billing-labels";
|
|
15
15
|
import type { BillingLabels } from "./billing-labels";
|
|
16
|
-
import { dialogClose } from "./dialog-close";
|
|
17
|
-
import type { WithDialogClose } from "./dialog-close";
|
|
18
16
|
import type { PlanSwitchPreview } from "./billing-overview";
|
|
19
17
|
import { minorToMajor } from "./plan-price";
|
|
20
18
|
import type { BillingInterval } from "./plan-price";
|
|
@@ -39,16 +37,13 @@ export interface PlanSwitchSide {
|
|
|
39
37
|
interval: BillingInterval;
|
|
40
38
|
}
|
|
41
39
|
|
|
42
|
-
|
|
43
|
-
interface PlanSwitchConfirmFields {
|
|
40
|
+
export interface PlanSwitchConfirmProps {
|
|
44
41
|
open: boolean;
|
|
45
42
|
/** The payer dismissed it — Cancel, Escape, the backdrop. Confirm leaves it open: close
|
|
46
43
|
* it once the switch answers. 0.52: every other kit dialog's `onClose` (CONTRIBUTING
|
|
47
|
-
* §4; refactor audit 2026-10-30, API-5).
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
* `false` when there is no `onClose`. */
|
|
51
|
-
onOpenChange?: (open: boolean) => void;
|
|
44
|
+
* §4; refactor audit 2026-10-30, API-5); required since 0.53 removed `onOpenChange`
|
|
45
|
+
* (deprecated in 0.52). */
|
|
46
|
+
onClose: () => void;
|
|
52
47
|
/** What the payer pays now: the overview's `paid`. */
|
|
53
48
|
from: PlanSwitchSide;
|
|
54
49
|
/** The pick. */
|
|
@@ -88,11 +83,6 @@ interface PlanSwitchConfirmFields {
|
|
|
88
83
|
labels?: LabelOverride<BillingLabels>;
|
|
89
84
|
}
|
|
90
85
|
|
|
91
|
-
/** What {@link PlanSwitchConfirm} takes: `onClose`, or alone the deprecated
|
|
92
|
-
* `onOpenChange`, is required (0.52 code review: with neither it compiled, and nothing
|
|
93
|
-
* could dismiss it). */
|
|
94
|
-
export type PlanSwitchConfirmProps = WithDialogClose<PlanSwitchConfirmFields>;
|
|
95
|
-
|
|
96
86
|
/**
|
|
97
87
|
* The confirm for a plan switch (§15.2.10): from → to, each with its billing period;
|
|
98
88
|
* Paddle's preview — "Charged now" (an upgrade) or "Credited towards your next charges"
|
|
@@ -118,7 +108,6 @@ export type PlanSwitchConfirmProps = WithDialogClose<PlanSwitchConfirmFields>;
|
|
|
118
108
|
export function PlanSwitchConfirm({
|
|
119
109
|
open,
|
|
120
110
|
onClose,
|
|
121
|
-
onOpenChange,
|
|
122
111
|
from,
|
|
123
112
|
to,
|
|
124
113
|
preview,
|
|
@@ -165,7 +154,7 @@ export function PlanSwitchConfirm({
|
|
|
165
154
|
open={open}
|
|
166
155
|
title={labels.switchTitle}
|
|
167
156
|
description={labels.switchFromTo(side(from), side(to))}
|
|
168
|
-
onClose={
|
|
157
|
+
onClose={onClose}
|
|
169
158
|
busy={pending}
|
|
170
159
|
// A preview that loads is busy too, but holds nothing: Cancel stays a way out.
|
|
171
160
|
aria-busy={preview === undefined || undefined}
|
package/src/chart.ts
CHANGED
|
@@ -10,14 +10,24 @@
|
|
|
10
10
|
// because the main barrel re-exports everything here too, so `import { Button } from
|
|
11
11
|
// "@eifi1/ui-kit"` reaches recharts as well (packaging-contract.test.ts asserts it).
|
|
12
12
|
export * from "./components/chart";
|
|
13
|
-
|
|
14
|
-
//
|
|
15
|
-
//
|
|
13
|
+
// Named, not `*`, for chart-palette, series-chart and toggle-legend: 0.53 took the slice's
|
|
14
|
+
// share of the 55 names no app reads off the surface (deprecated in 0.52, refactor audit
|
|
15
|
+
// 2026-10-30, API-4) — `EDGE_MIN_CONTRAST`, `resolveTooltipPlacement`, `STROKE_PATTERNS`,
|
|
16
|
+
// which their modules keep for the kit's own use.
|
|
16
17
|
export {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
PALETTE_SIZE,
|
|
19
|
+
CVD_ORDER,
|
|
20
|
+
paletteFor,
|
|
21
|
+
CHART_COLORS,
|
|
22
|
+
CHART_ROLES,
|
|
23
|
+
CHART_MUTED_HEX,
|
|
24
|
+
chartEdge,
|
|
25
|
+
PALETTE_HEX,
|
|
26
|
+
HEATMAP_HEX,
|
|
27
|
+
lerpHex,
|
|
28
|
+
textOn,
|
|
29
|
+
type PaletteForOptions,
|
|
30
|
+
type HeatStops,
|
|
21
31
|
} from "./theme/chart-palette";
|
|
22
32
|
|
|
23
33
|
// The tile chart (treemap) the apps share — moved here from keksdose so every consumer
|
|
@@ -27,10 +37,42 @@ export * from "./components/treemap-labels";
|
|
|
27
37
|
|
|
28
38
|
// lenkbank's zoomable series chart, its synced x-zoom, the toggle legend and the
|
|
29
39
|
// mirrored-pair axis geometry — moved here so the apps derive them from the package.
|
|
30
|
-
export * from "./components/series-chart";
|
|
31
40
|
export {
|
|
32
|
-
|
|
33
|
-
|
|
41
|
+
AXIS_TICK_WIDTH,
|
|
42
|
+
AXIS_TITLE_STRIP,
|
|
43
|
+
anchoredBand,
|
|
44
|
+
axisBandWidth,
|
|
45
|
+
mergeSeries,
|
|
46
|
+
oneAxis,
|
|
47
|
+
padBand,
|
|
48
|
+
paddedDomain,
|
|
49
|
+
seriesKey,
|
|
50
|
+
soleSeriesColor,
|
|
51
|
+
visibleSeries,
|
|
52
|
+
seriesLegendEntries,
|
|
53
|
+
StaticSeriesChart,
|
|
54
|
+
SeriesChart,
|
|
55
|
+
type TimeTickUnit,
|
|
56
|
+
type SeriesChartAxisBudget,
|
|
57
|
+
type SeriesSource,
|
|
58
|
+
type SeriesChartSeries,
|
|
59
|
+
type SeriesChartType,
|
|
60
|
+
type SeriesChartPoint,
|
|
61
|
+
type SeriesChartRow,
|
|
62
|
+
type SeriesChartXValue,
|
|
63
|
+
type SeriesChartTickValues,
|
|
64
|
+
type SeriesChartAxis,
|
|
65
|
+
type SeriesChartXTick,
|
|
66
|
+
type SeriesChartX,
|
|
67
|
+
type SeriesChartTooltipPlacement,
|
|
68
|
+
type SeriesChartTooltip,
|
|
69
|
+
type SeriesChartSpan,
|
|
70
|
+
type SeriesChartTone,
|
|
71
|
+
type SeriesChartReference,
|
|
72
|
+
type SeriesChartMarker,
|
|
73
|
+
type SeriesChartHit,
|
|
74
|
+
type SeriesChartProps,
|
|
75
|
+
type SeriesLegendAxes,
|
|
34
76
|
} from "./components/series-chart";
|
|
35
77
|
// 0.32.1 (keksdose's 0.32 report): the height every chart takes, for an app's wrappers.
|
|
36
78
|
export type { ChartHeight } from "./components/chart-height";
|
|
@@ -41,10 +83,17 @@ export * from "./components/chart-zoom";
|
|
|
41
83
|
// packaging contract reads this entry's own imports to know which modules may import
|
|
42
84
|
// recharts, so chart-zoom-core has to be one of them (MOD-6).
|
|
43
85
|
export { SharedXZoom } from "./components/chart-zoom-core";
|
|
44
|
-
export * from "./components/toggle-legend";
|
|
45
86
|
export {
|
|
46
|
-
|
|
47
|
-
|
|
87
|
+
strokeDash,
|
|
88
|
+
STEP_DASH,
|
|
89
|
+
toggleHidden,
|
|
90
|
+
ToggleLegend,
|
|
91
|
+
StaticLegend,
|
|
92
|
+
LegendColumn,
|
|
93
|
+
LegendGroup,
|
|
94
|
+
type LegendEntry,
|
|
95
|
+
type ToggleLegendProps,
|
|
96
|
+
type StaticLegendProps,
|
|
48
97
|
} from "./components/toggle-legend";
|
|
49
98
|
export * from "./components/facing-pair";
|
|
50
99
|
export * from "./components/series-chart-labels";
|
|
@@ -149,7 +149,8 @@ export interface AmountInputProps extends FieldHelpProps, DataAttributes {
|
|
|
149
149
|
currencyNames?: Record<string, string>;
|
|
150
150
|
/** Offer only these ISO codes in the chip's list, in this order — `CurrencySelect`'s
|
|
151
151
|
* `options`, since the chip renders CurrencySelect's list (round 0.34 Wave 2, DUP-4).
|
|
152
|
-
* Default every currency the kit knows
|
|
152
|
+
* Default every currency the kit knows but a `retired` one (the lev), which only the
|
|
153
|
+
* field that holds it lists. */
|
|
153
154
|
currencyOptions?: string[];
|
|
154
155
|
/** Focus the field on mount — on mobile this also opens the numpad sheet, so a
|
|
155
156
|
* new-transaction form can jump straight to amount entry (feedback #70). */
|
|
@@ -3,6 +3,7 @@ import type { ComponentPropsWithRef, CSSProperties, KeyboardEvent, ReactNode } f
|
|
|
3
3
|
import { cn } from "../lib/cn";
|
|
4
4
|
import { dirOf, horizontalStep } from "../lib/direction";
|
|
5
5
|
import { addMonthsClamped, localeWeekStart, parseIsoDate, toLocalIso } from "../lib/dates";
|
|
6
|
+
import { dateFormatter } from "../lib/intl-cache";
|
|
6
7
|
import { useKitLabels, useKitLocale, useKitWeekStart, type LabelOverride } from "../i18n/kit-labels";
|
|
7
8
|
import { lerpHex, textOn } from "../theme/chart-palette";
|
|
8
9
|
import { parseHex } from "../theme/color";
|
|
@@ -154,6 +155,8 @@ const DAY_NAME_FORMAT: Intl.DateTimeFormatOptions = {
|
|
|
154
155
|
month: "long",
|
|
155
156
|
year: "numeric",
|
|
156
157
|
};
|
|
158
|
+
/** A month's name over its first column ("Sep"). */
|
|
159
|
+
const MONTH_LABEL_FORMAT: Intl.DateTimeFormatOptions = { month: "short" };
|
|
157
160
|
|
|
158
161
|
/** The empty day: a wash of the text colour, like `--bg-hover`, so it reads as a cell
|
|
159
162
|
* on both themes without claiming any value. */
|
|
@@ -345,7 +348,10 @@ export function CalendarHeatmap({
|
|
|
345
348
|
};
|
|
346
349
|
}, [layout, firstIso, lastIso]);
|
|
347
350
|
|
|
348
|
-
|
|
351
|
+
// Every day cell names its date, so through the kit's formatter cache, as the month
|
|
352
|
+
// labels are: `toLocaleDateString` built one per cell and render, 365 for a year's grid
|
|
353
|
+
// (keksdose audit follow-up, 2026-11-01).
|
|
354
|
+
const formatDay = (d: Date) => dateFormatter(locale, DAY_NAME_FORMAT).format(d);
|
|
349
355
|
|
|
350
356
|
const weekdayLabels = useMemo(() => {
|
|
351
357
|
const ref = new Date(2024, 0, 7 + weekStart); // 7 January 2024 was a Sunday
|
|
@@ -503,7 +509,7 @@ export function CalendarHeatmap({
|
|
|
503
509
|
for (let r = 0; r < 7; r++) {
|
|
504
510
|
const d = dayAt(w * 7 + r);
|
|
505
511
|
if (d && (d.getDate() === 1 || (w === 0 && r === lead && d.getDate() <= 14))) {
|
|
506
|
-
return
|
|
512
|
+
return dateFormatter(locale, MONTH_LABEL_FORMAT).format(d);
|
|
507
513
|
}
|
|
508
514
|
}
|
|
509
515
|
return "";
|
|
@@ -73,7 +73,8 @@ export interface CurrencyOptionListProps {
|
|
|
73
73
|
/** A currency was picked. The host closes the list. */
|
|
74
74
|
onChoose: (code: string) => void;
|
|
75
75
|
/** Only these ISO codes, in this order; codes the kit has no definition for are
|
|
76
|
-
* dropped. Default every one of {@link CURRENCIES}
|
|
76
|
+
* dropped. Default every one of {@link CURRENCIES} that is not `retired` (the chosen
|
|
77
|
+
* one too, if it is). A retired code named here stays: the list is the caller's. */
|
|
77
78
|
codes?: readonly string[];
|
|
78
79
|
/** Translated names by code — see {@link currencyName}. */
|
|
79
80
|
currencyNames?: Record<string, string>;
|
|
@@ -112,19 +113,27 @@ export function CurrencyOptionList({
|
|
|
112
113
|
searchPlaceholder,
|
|
113
114
|
sheetTitle,
|
|
114
115
|
}: CurrencyOptionListProps) {
|
|
116
|
+
const held = getCurrency(value);
|
|
117
|
+
const chosen = held?.code;
|
|
118
|
+
// A retired currency the field holds — the one the default list keeps for it. Its own
|
|
119
|
+
// key, so a change of an ordinary value does not rebuild the rows and their names.
|
|
120
|
+
const heldRetired = held?.retired ? held.code : undefined;
|
|
115
121
|
// Keyed on the codes' CONTENTS: an inline `options={["EUR", "CHF"]}` is a new array
|
|
116
122
|
// every render.
|
|
117
123
|
const codesKey = codes?.join(",");
|
|
118
124
|
const pool = useMemo(
|
|
119
125
|
() =>
|
|
120
126
|
codesKey === undefined
|
|
121
|
-
?
|
|
127
|
+
? // No currency that was replaced (the lev, since Bulgaria's euro: keksdose audit
|
|
128
|
+
// follow-up, 2026-11-01) — unless the field holds it, which then opens on its
|
|
129
|
+
// own row, checked, rather than on a list where nothing is chosen.
|
|
130
|
+
CURRENCIES.filter((c) => !c.retired || c.code === heldRetired)
|
|
122
131
|
: // The caller's order; codes the kit has no definition for are dropped.
|
|
123
132
|
codesKey
|
|
124
133
|
.split(",")
|
|
125
134
|
.map((code) => getCurrency(code))
|
|
126
135
|
.filter((c): c is CurrencyOption => c !== undefined),
|
|
127
|
-
[codesKey],
|
|
136
|
+
[codesKey, heldRetired],
|
|
128
137
|
);
|
|
129
138
|
const named = useMemo(
|
|
130
139
|
() => pool.map((c) => ({ c, name: currencyName(c, currencyNames, locale) })),
|
|
@@ -147,7 +156,6 @@ export function CurrencyOptionList({
|
|
|
147
156
|
}));
|
|
148
157
|
}, [named, query, locale]);
|
|
149
158
|
|
|
150
|
-
const chosen = getCurrency(value)?.code;
|
|
151
159
|
return (
|
|
152
160
|
<ComboboxPanel
|
|
153
161
|
// The core with the currency filter's rows in place of its own.
|
|
@@ -41,7 +41,9 @@ export interface CurrencySelectProps extends Omit<ComponentPropsWithoutRef<"div"
|
|
|
41
41
|
/**
|
|
42
42
|
* Restrict the pickable currencies to these ISO codes (e.g. only the
|
|
43
43
|
* currencies actually present in a budget). Order is preserved. Defaults to
|
|
44
|
-
* the full {@link CURRENCIES} list
|
|
44
|
+
* the full {@link CURRENCIES} list but a `retired` currency (the lev, since
|
|
45
|
+
* Bulgaria's euro), which only a field that holds it lists. A retired code named
|
|
46
|
+
* here is offered: the list is the caller's.
|
|
45
47
|
*/
|
|
46
48
|
options?: string[];
|
|
47
49
|
/** Required and unanswered — {@link FIELD_INVALID}, the same rose border the
|
|
@@ -6,6 +6,7 @@ import { useKitLabels, type LabelOverride } from "../i18n/kit-labels";
|
|
|
6
6
|
import { Button } from "./button";
|
|
7
7
|
import { Input } from "./input";
|
|
8
8
|
import { Label } from "./field-base";
|
|
9
|
+
import { FIELD_ERROR_CLASS } from "./field-parts";
|
|
9
10
|
import { Spinner } from "./spinner";
|
|
10
11
|
import type { ButtonVariant } from "./button-look";
|
|
11
12
|
import type { InputProps } from "./input";
|
|
@@ -536,6 +537,27 @@ export interface DangerConfirmProps extends Omit<ComponentPropsWithRef<"div">, "
|
|
|
536
537
|
* confirm, so a keyboard user can retry or Shift+Tab to the field to correct (0.24).
|
|
537
538
|
*/
|
|
538
539
|
busy?: boolean;
|
|
540
|
+
/**
|
|
541
|
+
* Why the last confirm failed ("Wrong password"), in the tile beside the field it is
|
|
542
|
+
* about rather than in a toast away from it (keksdose audit follow-up, 2026-11-01:
|
|
543
|
+
* PasswordDangerCard toasted its `password_incorrect` for want of this). The app sets
|
|
544
|
+
* it from the failure and words it — a 400 is a wrong password, a 500 is not.
|
|
545
|
+
*
|
|
546
|
+
* Drawn as the field's own `error`, as {@link ReauthDialog} draws its own: under the
|
|
547
|
+
* password with `requirePassword`, else under the typed phrase — the field painted,
|
|
548
|
+
* `aria-invalid`, the message its `aria-describedby` — and in a tile with neither, as
|
|
549
|
+
* a line above the buttons. Announced as it appears (`role="alert"`): it arrives
|
|
550
|
+
* after the press, with focus on the confirm, where a field's description alone is
|
|
551
|
+
* not heard. Passed at all — even as `undefined` — the field keeps its box, as with
|
|
552
|
+
* Input's `error`, so the message going away does not rebuild the field mid-edit.
|
|
553
|
+
*
|
|
554
|
+
* Hidden while the next attempt runs, once the user edits the tick, the phrase or the
|
|
555
|
+
* password (it is about what was submitted), and when the tile arms or disarms, until
|
|
556
|
+
* the next confirm; shown again when a confirm fails with it still set. So a
|
|
557
|
+
* mutation's error can be handed over as it is:
|
|
558
|
+
* `error={mut.error ? message(mut.error) : undefined}`.
|
|
559
|
+
*/
|
|
560
|
+
error?: ReactNode;
|
|
539
561
|
/** The arm button is disabled. */
|
|
540
562
|
disabled?: boolean;
|
|
541
563
|
/**
|
|
@@ -628,30 +650,32 @@ function firstSlotField(slot: HTMLElement | null): HTMLElement | null {
|
|
|
628
650
|
* destructive button itself), and disarming moves it back to the arm button, so the
|
|
629
651
|
* keyboard user is never left on an element that just vanished.
|
|
630
652
|
*/
|
|
631
|
-
export function DangerConfirm({
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
653
|
+
export function DangerConfirm(props: DangerConfirmProps) {
|
|
654
|
+
const {
|
|
655
|
+
onConfirm,
|
|
656
|
+
requirePassword,
|
|
657
|
+
requireAcknowledge,
|
|
658
|
+
consequences,
|
|
659
|
+
phrase,
|
|
660
|
+
phraseMatch = "trim",
|
|
661
|
+
prompt,
|
|
662
|
+
tone = "danger",
|
|
663
|
+
confirmVariant,
|
|
664
|
+
confirmDisabledReason,
|
|
665
|
+
children,
|
|
666
|
+
armLabel,
|
|
667
|
+
confirmLabel,
|
|
668
|
+
busy: busyProp,
|
|
669
|
+
error,
|
|
670
|
+
disabled,
|
|
671
|
+
lockedReason: ownLockedReason,
|
|
672
|
+
commit,
|
|
673
|
+
armed: armedProp,
|
|
674
|
+
onArmedChange,
|
|
675
|
+
labels: labelsProp,
|
|
676
|
+
className,
|
|
677
|
+
...rest
|
|
678
|
+
} = props;
|
|
655
679
|
const labels = useKitLabels("dangerConfirm", DEFAULT_DANGER_CONFIRM_LABELS, labelsProp);
|
|
656
680
|
const lockedReason = useCommitReason(commit, ownLockedReason);
|
|
657
681
|
const [armedState, setArmedState] = useState(false);
|
|
@@ -659,6 +683,9 @@ export function DangerConfirm({
|
|
|
659
683
|
const [password, setPassword] = useState("");
|
|
660
684
|
const [typed, setTyped] = useState("");
|
|
661
685
|
const [acknowledged, setAcknowledged] = useState(false);
|
|
686
|
+
// The `error` describes what was submitted: an edit, an arm or a disarm leaves it
|
|
687
|
+
// describing nothing on screen. Cleared by the next confirm — ReauthDialog's `edited`.
|
|
688
|
+
const [errorStale, setErrorStale] = useState(false);
|
|
662
689
|
const { pending, run } = usePromisePending();
|
|
663
690
|
const busy = Boolean(busyProp) || pending;
|
|
664
691
|
// `readOnly` rather than `disabled` on the fields while busy: disabling the field
|
|
@@ -686,6 +713,8 @@ export function DangerConfirm({
|
|
|
686
713
|
const [wasArmed, setWasArmed] = useState(armed);
|
|
687
714
|
if (wasArmed !== armed) {
|
|
688
715
|
setWasArmed(armed);
|
|
716
|
+
// An `error` still passed is about the attempt before: not shown until a confirm.
|
|
717
|
+
setErrorStale(true);
|
|
689
718
|
if (!armed) {
|
|
690
719
|
setPassword("");
|
|
691
720
|
setTyped("");
|
|
@@ -785,11 +814,22 @@ export function DangerConfirm({
|
|
|
785
814
|
...(asksAcknowledge && { acknowledged: true as const }),
|
|
786
815
|
};
|
|
787
816
|
confirmed.current = true;
|
|
817
|
+
setErrorStale(false);
|
|
788
818
|
// Disarms when it resolves; a rejection leaves it armed, fields kept: the caller
|
|
789
819
|
// shows why, the user retries.
|
|
790
820
|
run(onConfirm(values.password, values), () => setArmed(false));
|
|
791
821
|
};
|
|
792
822
|
|
|
823
|
+
// The failure's message, under the field it is about: the password, else the phrase,
|
|
824
|
+
// else (a tile with neither) a line of its own. Not while the next attempt runs.
|
|
825
|
+
const shownError = errorStale || busy ? undefined : error;
|
|
826
|
+
const errorAlert = hasContent(shownError) ? <span role="alert">{shownError}</span> : undefined;
|
|
827
|
+
const errorOn = requirePassword ? "password" : phrase !== undefined ? "phrase" : "line";
|
|
828
|
+
// Passed at all, the carrying field keeps its box (Input's `error` rule): only then.
|
|
829
|
+
const fieldError = (field: "password" | "phrase") =>
|
|
830
|
+
"error" in props && errorOn === field ? { error: errorAlert } : {};
|
|
831
|
+
const edited = () => setErrorStale(true);
|
|
832
|
+
|
|
793
833
|
// The first field takes focus on arm: the tick, then the phrase, then the password —
|
|
794
834
|
// the order they are drawn in.
|
|
795
835
|
const firstField = asksAcknowledge ? "acknowledge" : phrase !== undefined ? "phrase" : "password";
|
|
@@ -880,7 +920,9 @@ export function DangerConfirm({
|
|
|
880
920
|
// Not `disabled` while busy, for the same reason the fields are readOnly:
|
|
881
921
|
// the box may hold the focus. A change while busy is simply not taken.
|
|
882
922
|
onCheckedChange={(next) => {
|
|
883
|
-
if (
|
|
923
|
+
if (busy) return;
|
|
924
|
+
setAcknowledged(next);
|
|
925
|
+
edited();
|
|
884
926
|
}}
|
|
885
927
|
/>
|
|
886
928
|
)}
|
|
@@ -890,11 +932,15 @@ export function DangerConfirm({
|
|
|
890
932
|
target={phrase}
|
|
891
933
|
match={phraseMatch}
|
|
892
934
|
value={typed}
|
|
893
|
-
onValueChange={
|
|
935
|
+
onValueChange={(next) => {
|
|
936
|
+
setTyped(next);
|
|
937
|
+
edited();
|
|
938
|
+
}}
|
|
894
939
|
busy={busy}
|
|
895
940
|
// Already resolved through this tile's own `labels` prop; handed on so a
|
|
896
941
|
// per-instance phrase wording reaches the field.
|
|
897
942
|
labels={{ phrase: labels.phrase, phrasePlaceholder: labels.phrasePlaceholder }}
|
|
943
|
+
{...fieldError("phrase")}
|
|
898
944
|
/>
|
|
899
945
|
)}
|
|
900
946
|
{requirePassword && (
|
|
@@ -903,9 +949,16 @@ export function DangerConfirm({
|
|
|
903
949
|
label={labels.password}
|
|
904
950
|
value={password}
|
|
905
951
|
busy={busy}
|
|
906
|
-
onValueChange={
|
|
952
|
+
onValueChange={(next) => {
|
|
953
|
+
setPassword(next);
|
|
954
|
+
edited();
|
|
955
|
+
}}
|
|
956
|
+
{...fieldError("password")}
|
|
907
957
|
/>
|
|
908
958
|
)}
|
|
959
|
+
{errorOn === "line" && errorAlert !== undefined && (
|
|
960
|
+
<p className={cn(FIELD_ERROR_CLASS, "mt-0")}>{errorAlert}</p>
|
|
961
|
+
)}
|
|
909
962
|
<div className="flex flex-wrap gap-2">
|
|
910
963
|
<Button id={cancelId} type="button" variant="ghost" disabled={busy} onClick={() => setArmed(false)}>
|
|
911
964
|
{labels.cancel}
|
|
@@ -40,7 +40,8 @@ interface FilterPopoverProps<T> {
|
|
|
40
40
|
* The contents of a column's filter Popover. Renders the right control set for
|
|
41
41
|
* the column's filter type — text search, select checklist, date range (presets
|
|
42
42
|
* + {@link MiniCalendar} + from/to inputs), or numeric min/max with an abs
|
|
43
|
-
* toggle — driving the shared
|
|
43
|
+
* toggle (none for `numberFilter(getValue, { abs: false })`) — driving the shared
|
|
44
|
+
* {@link FilterValue} state.
|
|
44
45
|
*/
|
|
45
46
|
export function FilterPopover<T>({
|
|
46
47
|
column,
|
|
@@ -219,6 +220,11 @@ export function FilterPopover<T>({
|
|
|
219
220
|
}
|
|
220
221
|
|
|
221
222
|
// number
|
|
223
|
+
// `abs: false` on the filter: no "Absolute value" box, and a state that carries `abs`
|
|
224
|
+
// anyway (a view stored before the column lost the box) is handed on without it at the
|
|
225
|
+
// first bound typed — there is no box to untick it with (kastlan reuse audit
|
|
226
|
+
// 2026-11-02, proposal 7).
|
|
227
|
+
const absBox = filter.abs !== false;
|
|
222
228
|
const v = state.type === "number" ? state : { type: "number" as const, min: "", max: "", abs: false };
|
|
223
229
|
// The bounds were native `type="number"` inputs, the one numeric entry in the kit that
|
|
224
230
|
// bypassed decimal-marks (BUG-10, refactor audit 2026-10): where the browser refuses a
|
|
@@ -237,7 +243,7 @@ export function FilterPopover<T>({
|
|
|
237
243
|
type: "number",
|
|
238
244
|
min: bound === "min" ? read : v.min,
|
|
239
245
|
max: bound === "max" ? read : v.max,
|
|
240
|
-
abs: v.abs,
|
|
246
|
+
abs: absBox && v.abs,
|
|
241
247
|
});
|
|
242
248
|
};
|
|
243
249
|
return (
|
|
@@ -266,15 +272,17 @@ export function FilterPopover<T>({
|
|
|
266
272
|
/>
|
|
267
273
|
</label>
|
|
268
274
|
</div>
|
|
269
|
-
|
|
270
|
-
<
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
275
|
+
{absBox && (
|
|
276
|
+
<label className="flex items-center gap-2 text-sm text-secondary">
|
|
277
|
+
<input
|
|
278
|
+
type="checkbox"
|
|
279
|
+
checked={v.abs}
|
|
280
|
+
onChange={(e) => onChange({ type: "number", min: v.min, max: v.max, abs: e.target.checked })}
|
|
281
|
+
className="size-3.5"
|
|
282
|
+
/>
|
|
283
|
+
{labels.numberAbs}
|
|
284
|
+
</label>
|
|
285
|
+
)}
|
|
278
286
|
{clearRow}
|
|
279
287
|
</div>
|
|
280
288
|
);
|