@eifi1/ui-kit 0.21.0 → 0.23.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 +42 -25
- package/dist/chart.d.ts +19 -14
- package/dist/components/account-chips.d.ts +10 -3
- package/dist/components/account-chips.js +5 -2
- package/dist/components/account-chips.js.map +1 -1
- package/dist/components/account-settings.d.ts +33 -2
- package/dist/components/account-settings.js +43 -21
- package/dist/components/account-settings.js.map +1 -1
- package/dist/components/amount-input.d.ts +53 -14
- package/dist/components/amount-input.js +17 -28
- package/dist/components/amount-input.js.map +1 -1
- package/dist/components/autocomplete.d.ts +29 -0
- package/dist/components/autocomplete.js +134 -104
- package/dist/components/autocomplete.js.map +1 -1
- package/dist/components/button-group.d.ts +19 -14
- package/dist/components/calculator.d.ts +19 -14
- package/dist/components/checkbox-group.d.ts +104 -0
- package/dist/components/checkbox-group.js +111 -0
- package/dist/components/checkbox-group.js.map +1 -0
- package/dist/components/checkbox.d.ts +19 -0
- package/dist/components/checkbox.js +30 -7
- package/dist/components/checkbox.js.map +1 -1
- package/dist/components/chip.d.ts +18 -0
- package/dist/components/chip.js +47 -10
- package/dist/components/chip.js.map +1 -1
- package/dist/components/column-mapper.d.ts +182 -0
- package/dist/components/column-mapper.js +375 -0
- package/dist/components/column-mapper.js.map +1 -0
- package/dist/components/combobox-core.d.ts +39 -2
- package/dist/components/combobox-core.js +29 -6
- package/dist/components/combobox-core.js.map +1 -1
- package/dist/components/combobox.d.ts +91 -2
- package/dist/components/combobox.js +454 -308
- package/dist/components/combobox.js.map +1 -1
- package/dist/components/confirm-dialog.d.ts +69 -161
- package/dist/components/confirm-dialog.js +7 -8
- package/dist/components/confirm-dialog.js.map +1 -1
- package/dist/components/copy-button.d.ts +16 -11
- package/dist/components/country-select.d.ts +167 -0
- package/dist/components/country-select.js +293 -0
- package/dist/components/country-select.js.map +1 -0
- package/dist/components/currency-select.d.ts +17 -1
- package/dist/components/currency-select.js +56 -23
- package/dist/components/currency-select.js.map +1 -1
- package/dist/components/danger-confirm.d.ts +69 -166
- package/dist/components/danger-confirm.js +144 -50
- package/dist/components/danger-confirm.js.map +1 -1
- package/dist/components/data-table-cells.d.ts +1 -2
- package/dist/components/data-table-filter-popover.d.ts +1 -2
- package/dist/components/data-table-filters.d.ts +1 -2
- package/dist/components/data-table-labels.d.ts +4 -97
- package/dist/components/data-table-labels.js +9 -1
- package/dist/components/data-table-labels.js.map +1 -1
- package/dist/components/data-table-pagination.d.ts +3 -1
- package/dist/components/data-table.d.ts +1 -2
- package/dist/components/data-table.js +98 -3
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/date-picker.d.ts +66 -5
- package/dist/components/date-picker.js +378 -66
- package/dist/components/date-picker.js.map +1 -1
- package/dist/components/entity-combobox.d.ts +42 -1
- package/dist/components/entity-combobox.js +154 -113
- package/dist/components/entity-combobox.js.map +1 -1
- package/dist/components/facing-pair.d.ts +19 -14
- package/dist/components/field-parts.d.ts +224 -0
- package/dist/components/field-parts.js +156 -0
- package/dist/components/field-parts.js.map +1 -0
- package/dist/components/field-strip.d.ts +105 -0
- package/dist/components/field-strip.js +46 -0
- package/dist/components/field-strip.js.map +1 -0
- package/dist/components/file-button.d.ts +19 -14
- package/dist/components/file-button.js +13 -3
- package/dist/components/file-button.js.map +1 -1
- package/dist/components/file-dropzone.d.ts +41 -15
- package/dist/components/file-dropzone.js +57 -34
- package/dist/components/file-dropzone.js.map +1 -1
- package/dist/components/form-actions.d.ts +18 -13
- package/dist/components/form-actions.js +69 -5
- package/dist/components/form-actions.js.map +1 -1
- package/dist/components/iban-input.d.ts +69 -0
- package/dist/components/iban-input.js +125 -0
- package/dist/components/iban-input.js.map +1 -0
- package/dist/components/icon-picker.d.ts +21 -2
- package/dist/components/icon-picker.js +19 -4
- package/dist/components/icon-picker.js.map +1 -1
- package/dist/components/inline-edit-field.d.ts +167 -0
- package/dist/components/inline-edit-field.js +293 -0
- package/dist/components/inline-edit-field.js.map +1 -0
- package/dist/components/language-select.d.ts +130 -0
- package/dist/components/language-select.js +18 -0
- package/dist/components/language-select.js.map +1 -0
- package/dist/components/line-items.d.ts +25 -3
- package/dist/components/line-items.js +55 -46
- package/dist/components/line-items.js.map +1 -1
- package/dist/components/list.d.ts +25 -0
- package/dist/components/list.js +16 -5
- package/dist/components/list.js.map +1 -1
- package/dist/components/money-field.d.ts +32 -14
- package/dist/components/money-field.js.map +1 -1
- package/dist/components/month-picker.d.ts +52 -4
- package/dist/components/month-picker.js +291 -86
- package/dist/components/month-picker.js.map +1 -1
- package/dist/components/multi-entity-combobox.d.ts +26 -1
- package/dist/components/multi-entity-combobox.js +143 -102
- package/dist/components/multi-entity-combobox.js.map +1 -1
- package/dist/components/multi-select.d.ts +8 -1
- package/dist/components/multi-select.js +9 -4
- package/dist/components/multi-select.js.map +1 -1
- package/dist/components/number-field.d.ts +34 -19
- package/dist/components/number-field.js +6 -20
- package/dist/components/number-field.js.map +1 -1
- package/dist/components/number-input.d.ts +79 -19
- package/dist/components/number-input.js +90 -38
- package/dist/components/number-input.js.map +1 -1
- package/dist/components/numpad-sheet.d.ts +19 -14
- package/dist/components/one-time-code-input.d.ts +100 -0
- package/dist/components/one-time-code-input.js +137 -0
- package/dist/components/one-time-code-input.js.map +1 -0
- package/dist/components/phone-input.d.ts +69 -0
- package/dist/components/phone-input.js +171 -0
- package/dist/components/phone-input.js.map +1 -0
- package/dist/components/reauth-dialog.d.ts +2 -2
- package/dist/components/reauth-dialog.js +6 -8
- package/dist/components/reauth-dialog.js.map +1 -1
- package/dist/components/series-chart.d.ts +19 -14
- package/dist/components/settings-fields.d.ts +19 -14
- package/dist/components/share-card.d.ts +16 -11
- package/dist/components/sign-chip.d.ts +66 -0
- package/dist/components/sign-chip.js +39 -0
- package/dist/components/sign-chip.js.map +1 -0
- package/dist/components/swatch-picker.d.ts +43 -2
- package/dist/components/swatch-picker.js +80 -32
- package/dist/components/swatch-picker.js.map +1 -1
- package/dist/components/switch.d.ts +19 -0
- package/dist/components/switch.js +24 -6
- package/dist/components/switch.js.map +1 -1
- package/dist/components/text-link.d.ts +18 -13
- package/dist/components/tile-radio.d.ts +88 -13
- package/dist/components/tile-radio.js +28 -11
- package/dist/components/tile-radio.js.map +1 -1
- package/dist/components/time-input.d.ts +24 -15
- package/dist/components/time-input.js.map +1 -1
- package/dist/components/toggle-group.d.ts +47 -1
- package/dist/components/toggle-group.js +110 -69
- package/dist/components/toggle-group.js.map +1 -1
- package/dist/components/trigger-aria.d.ts +3 -0
- package/dist/components/trigger-aria.js +3 -1
- package/dist/components/trigger-aria.js.map +1 -1
- package/dist/components/ui.d.ts +16 -11
- package/dist/components/ui.js +284 -88
- package/dist/components/ui.js.map +1 -1
- package/dist/components/use-table-state.d.ts +1 -2
- package/dist/{data-table-3mi2R3so.d.ts → data-table-labels-B7OdnM0S.d.ts} +140 -3
- package/dist/data-table.d.ts +1 -2
- package/dist/data-table.js +2 -1
- package/dist/data-table.js.map +1 -1
- package/dist/feedback/feedback-attachment.d.ts +1 -1
- package/dist/feedback/feedback-attachment.js +348 -41
- package/dist/feedback/feedback-attachment.js.map +1 -1
- package/dist/feedback/feedback-dialog.d.ts +1 -1
- package/dist/feedback/feedback-dialog.js.map +1 -1
- package/dist/feedback/feedback-inbox.d.ts +3 -2
- package/dist/feedback/feedback-inbox.js.map +1 -1
- package/dist/feedback/feedback-thread.d.ts +68 -253
- package/dist/feedback/feedback-thread.js +46 -10
- package/dist/feedback/feedback-thread.js.map +1 -1
- package/dist/{kit-labels-D1J2_jyD.d.ts → feedback-BxeQVzwq.d.ts} +1206 -20
- package/dist/{feedback-attachment-WFiXJ8We.d.ts → feedback-attachment-fGAzZPf0.d.ts} +178 -11
- package/dist/feedback.d.ts +66 -2
- package/dist/hooks/use-file-drop.d.ts +19 -14
- package/dist/i18n/defaults.d.ts +19 -14
- package/dist/i18n/defaults.js +19 -2
- package/dist/i18n/defaults.js.map +1 -1
- package/dist/i18n/german.d.ts +19 -14
- package/dist/i18n/german.js +84 -5
- package/dist/i18n/german.js.map +1 -1
- package/dist/i18n/kit-labels.d.ts +15 -10
- package/dist/i18n/kit-labels.js +8 -2
- package/dist/i18n/kit-labels.js.map +1 -1
- package/dist/i18n/languages.d.ts +19 -14
- package/dist/i18n/locales/de-CH.d.ts +19 -14
- package/dist/i18n/locales/en.d.ts +19 -14
- package/dist/i18n/locales/en.js +16 -0
- package/dist/i18n/locales/en.js.map +1 -1
- package/dist/i18n/locales/es.d.ts +19 -14
- package/dist/i18n/locales/es.js +83 -5
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.d.ts +19 -14
- package/dist/i18n/locales/fr.js +82 -5
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.d.ts +19 -14
- package/dist/i18n/locales/hu.js +85 -5
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.d.ts +19 -14
- package/dist/i18n/locales/it.js +84 -5
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.d.ts +19 -14
- package/dist/i18n/locales/zh.js +80 -5
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/i18n/review.d.ts +19 -14
- package/dist/i18n/review.js +27 -1
- package/dist/i18n/review.js.map +1 -1
- package/dist/index.d.ts +21 -10
- package/dist/index.js +73 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/column-mapping.d.ts +81 -0
- package/dist/lib/column-mapping.js +108 -0
- package/dist/lib/column-mapping.js.map +1 -0
- package/dist/lib/countries.d.ts +43 -0
- package/dist/lib/countries.js +39 -0
- package/dist/lib/countries.js.map +1 -0
- package/dist/lib/decimal-marks.d.ts +46 -0
- package/dist/lib/decimal-marks.js +40 -0
- package/dist/lib/decimal-marks.js.map +1 -0
- package/dist/lib/iban.d.ts +98 -0
- package/dist/lib/iban.js +154 -0
- package/dist/lib/iban.js.map +1 -0
- package/dist/lib/isin.d.ts +30 -0
- package/dist/lib/isin.js +36 -0
- package/dist/lib/isin.js.map +1 -0
- package/dist/lib/phone.d.ts +69 -0
- package/dist/lib/phone.js +121 -0
- package/dist/lib/phone.js.map +1 -0
- package/dist/lib/table-text.d.ts +109 -1
- package/dist/lib/table-text.js +122 -1
- package/dist/lib/table-text.js.map +1 -1
- package/dist/rhf/fields.d.ts +233 -18
- package/dist/rhf/fields.js +456 -3
- package/dist/rhf/fields.js.map +1 -1
- package/dist/rhf/form.d.ts +19 -14
- package/dist/rhf.d.ts +22 -15
- package/dist/rhf.js.map +1 -1
- package/dist/shell/app-shell.d.ts +18 -13
- package/dist/shell/top-bar-brand.d.ts +19 -14
- package/dist/shell/topbar-action-menu.d.ts +36 -3
- package/dist/shell/topbar-action-menu.js +74 -33
- package/dist/shell/topbar-action-menu.js.map +1 -1
- package/dist/shell.d.ts +18 -13
- package/dist/table-text.d.ts +1 -1
- package/dist/tour/tour.js +20 -24
- package/dist/tour/tour.js.map +1 -1
- package/dist/wizard/stepper-nav.d.ts +49 -16
- package/dist/wizard/stepper-nav.js +4 -0
- package/dist/wizard/stepper-nav.js.map +1 -1
- package/dist/wizard.d.ts +19 -14
- package/package.json +1 -1
- package/src/components/account-chips.tsx +17 -3
- package/src/components/account-settings.tsx +92 -26
- package/src/components/amount-input.tsx +68 -56
- package/src/components/autocomplete.tsx +198 -114
- package/src/components/checkbox-group.tsx +229 -0
- package/src/components/checkbox.tsx +72 -8
- package/src/components/chip.tsx +80 -10
- package/src/components/column-mapper.tsx +666 -0
- package/src/components/combobox-core.tsx +82 -9
- package/src/components/combobox.tsx +661 -340
- package/src/components/confirm-dialog.tsx +12 -8
- package/src/components/country-select.tsx +556 -0
- package/src/components/currency-select.tsx +109 -33
- package/src/components/danger-confirm.tsx +429 -82
- package/src/components/data-table-labels.ts +16 -1
- package/src/components/data-table.tsx +175 -6
- package/src/components/date-picker.tsx +595 -71
- package/src/components/entity-combobox.tsx +235 -124
- package/src/components/field-parts.tsx +403 -0
- package/src/components/field-strip.tsx +149 -0
- package/src/components/file-button.tsx +36 -3
- package/src/components/file-dropzone.tsx +106 -38
- package/src/components/form-actions.tsx +147 -6
- package/src/components/iban-input.tsx +231 -0
- package/src/components/icon-picker.tsx +47 -6
- package/src/components/inline-edit-field.tsx +533 -0
- package/src/components/language-select.tsx +78 -0
- package/src/components/line-items.tsx +35 -2
- package/src/components/list.tsx +55 -6
- package/src/components/money-field.tsx +13 -0
- package/src/components/month-picker.tsx +400 -63
- package/src/components/multi-entity-combobox.tsx +207 -120
- package/src/components/multi-select.tsx +80 -58
- package/src/components/number-field.tsx +28 -46
- package/src/components/number-input.tsx +210 -43
- package/src/components/one-time-code-input.tsx +288 -0
- package/src/components/phone-input.tsx +299 -0
- package/src/components/reauth-dialog.tsx +17 -18
- package/src/components/sign-chip.tsx +103 -0
- package/src/components/swatch-picker.tsx +143 -31
- package/src/components/switch.tsx +58 -7
- package/src/components/tile-radio.tsx +145 -29
- package/src/components/time-input.tsx +8 -1
- package/src/components/toggle-group.tsx +206 -73
- package/src/components/trigger-aria.ts +5 -0
- package/src/components/ui.tsx +479 -138
- package/src/data-table.ts +2 -1
- package/src/feedback/feedback-attachment.tsx +597 -46
- package/src/feedback/feedback-dialog.tsx +9 -3
- package/src/feedback/feedback-inbox.tsx +3 -2
- package/src/feedback/feedback-thread.tsx +113 -9
- package/src/i18n/defaults.ts +18 -1
- package/src/i18n/german.ts +89 -0
- package/src/i18n/kit-labels.tsx +82 -2
- package/src/i18n/locales/en.ts +36 -4
- package/src/i18n/locales/es.ts +87 -0
- package/src/i18n/locales/fr.ts +87 -0
- package/src/i18n/locales/hu.ts +83 -0
- package/src/i18n/locales/it.ts +88 -0
- package/src/i18n/locales/zh.ts +76 -0
- package/src/i18n/review.ts +26 -0
- package/src/index.ts +71 -3
- package/src/lib/column-mapping.ts +234 -0
- package/src/lib/countries.ts +91 -0
- package/src/lib/decimal-marks.ts +99 -0
- package/src/lib/iban.ts +171 -0
- package/src/lib/isin.ts +62 -0
- package/src/lib/phone.ts +211 -0
- package/src/lib/table-text.ts +271 -0
- package/src/rhf/fields.tsx +860 -9
- package/src/rhf.ts +3 -1
- package/src/shell/topbar-action-menu.tsx +134 -38
- package/src/tour/tour.tsx +66 -28
- package/src/wizard/stepper-nav.tsx +35 -1
|
@@ -1,12 +1,14 @@
|
|
|
1
|
+
import { l as FeedbackAttachmentLabels, k as FeedbackAttachmentFieldSingleProps, g as FeedbackAttachmentFieldLabels, u as FeedbackDialogTextLabels } from './feedback-attachment-fGAzZPf0.js';
|
|
2
|
+
import { FeedbackNoteAttachment } from './feedback/feedback-inbox.js';
|
|
1
3
|
import * as react from 'react';
|
|
2
|
-
import { AnchorHTMLAttributes, Ref, ReactElement, ButtonHTMLAttributes,
|
|
3
|
-
import {
|
|
4
|
+
import { InputHTMLAttributes, ReactNode, AnchorHTMLAttributes, Ref, ReactElement, ButtonHTMLAttributes, SelectHTMLAttributes, ComponentPropsWithoutRef, TextareaHTMLAttributes } from 'react';
|
|
5
|
+
import { TooltipSide } from './components/tooltip.js';
|
|
6
|
+
import { f as DataTableLabels } from './data-table-labels-B7OdnM0S.js';
|
|
4
7
|
import { MiniCalendarLabels, WeekDay } from './components/mini-calendar.js';
|
|
5
8
|
import { CalendarHeatmapLabels } from './components/calendar-heatmap.js';
|
|
6
9
|
import { PopoverLabels } from './components/popover.js';
|
|
7
10
|
import { ChipInputLabels } from './components/chip.js';
|
|
8
11
|
import { FieldSyncLabels } from './components/field-sync.js';
|
|
9
|
-
import { TooltipSide } from './components/tooltip.js';
|
|
10
12
|
import { WizardLabels } from './wizard/types.js';
|
|
11
13
|
import { TourLabels } from './tour/tour.js';
|
|
12
14
|
import { CommandPaletteLabels } from './search/command-palette.js';
|
|
@@ -19,15 +21,11 @@ import { SparklineLabels } from './components/sparkline.js';
|
|
|
19
21
|
import { StatTileLabels } from './components/stat-tile.js';
|
|
20
22
|
import { SignaturePadLabels } from './components/signature-pad.js';
|
|
21
23
|
import { PasswordStrengthLabels } from './components/password-strength.js';
|
|
22
|
-
import { DangerConfirmLabels } from './components/danger-confirm.js';
|
|
23
24
|
import { SwatchPickerLabels } from './components/swatch-picker.js';
|
|
24
25
|
import { IconPickerLabels } from './components/icon-picker.js';
|
|
25
26
|
import { DialogFrameProps, DialogFrameLabels } from './components/dialog-frame.js';
|
|
26
27
|
import { MeasuredGridLabels } from './components/measured-grid.js';
|
|
27
|
-
import { f as FeedbackAttachmentFieldLabels, q as FeedbackDialogTextLabels } from './feedback-attachment-WFiXJ8We.js';
|
|
28
|
-
import { FeedbackThreadLabels, FeedbackComposerLabels } from './feedback/feedback-thread.js';
|
|
29
28
|
import { AccountSettingsLabels } from './components/account-settings-labels.js';
|
|
30
|
-
import { ConfirmDialogLabels } from './components/confirm-dialog.js';
|
|
31
29
|
import { FloatingPanelLabels } from './components/floating-panel.js';
|
|
32
30
|
import { BulkActionBarLabels } from './components/bulk-action-bar.js';
|
|
33
31
|
import { ListLabels } from './components/list.js';
|
|
@@ -48,6 +46,13 @@ import { RoleDefinition, AccountStateLabels } from './components/account-chips.j
|
|
|
48
46
|
import { ReauthDialogLabels } from './components/reauth-dialog.js';
|
|
49
47
|
import { ServerWakeLabels } from './components/server-wake.js';
|
|
50
48
|
import { TranslationReviewLabels } from './components/translation-review-labels.js';
|
|
49
|
+
import { CountrySelectLabels } from './components/country-select.js';
|
|
50
|
+
import { InlineEditLabels } from './components/inline-edit-field.js';
|
|
51
|
+
import { IbanKind } from './lib/iban.js';
|
|
52
|
+
import { PhoneCountry, PhoneCountryCode } from './lib/phone.js';
|
|
53
|
+
import { SignChipLabels } from './components/sign-chip.js';
|
|
54
|
+
import { ColumnMapperLabels } from './components/column-mapper.js';
|
|
55
|
+
import './components/field-parts.js';
|
|
51
56
|
|
|
52
57
|
type ButtonVariant = "primary" | "secondary" | "ghost" | "danger" | "brand" | "link";
|
|
53
58
|
type ButtonSize = "sm" | "md";
|
|
@@ -565,7 +570,6 @@ type FieldChevronProps = Omit<ComponentPropsWithoutRef<"svg">, "children">;
|
|
|
565
570
|
* what was picked. */
|
|
566
571
|
declare function FieldChevron({ className, ...rest }: FieldChevronProps): react.JSX.Element;
|
|
567
572
|
declare const FLOATING_LABEL_CLASS: string;
|
|
568
|
-
declare const FLOATING_LABEL_STATIC: string;
|
|
569
573
|
/**
|
|
570
574
|
* The one place that assembles a labelled field: a `relative` wrapper around the
|
|
571
575
|
* control (`children`) plus a floating label inside the top strip. Pass `staticLabel`
|
|
@@ -622,15 +626,6 @@ interface FieldHintProps extends Omit<ComponentPropsWithoutRef<"button">, "child
|
|
|
622
626
|
side?: TooltipSide;
|
|
623
627
|
}
|
|
624
628
|
declare function FieldHint({ label, side, className, "aria-label": ariaLabel, ...rest }: FieldHintProps): react.JSX.Element;
|
|
625
|
-
/**
|
|
626
|
-
* The floating label for a custom-dropdown trigger (a `<span>`, since the trigger is a
|
|
627
|
-
* button not a labelable input). Same placement as {@link FloatingField}'s static label,
|
|
628
|
-
* so every labelled field lines up. Render inside a `relative` wrapper, before the trigger.
|
|
629
|
-
*/
|
|
630
|
-
interface FieldLabelProps extends ComponentPropsWithoutRef<"span"> {
|
|
631
|
-
children: ReactNode;
|
|
632
|
-
}
|
|
633
|
-
declare function FieldLabel({ children, className, ...rest }: FieldLabelProps): react.JSX.Element;
|
|
634
629
|
interface LabelProps extends ComponentPropsWithoutRef<"label"> {
|
|
635
630
|
/** Draw the required mark after the text. The mark is `aria-hidden`: what a
|
|
636
631
|
* screen reader hears is the control's own `required` / `aria-required`, which
|
|
@@ -669,6 +664,22 @@ declare const DEFAULT_PASSWORD_REVEAL_LABELS: PasswordRevealLabels;
|
|
|
669
664
|
/** Caller's labels over the English defaults — the same shape as
|
|
670
665
|
* `resolveDataTableLabels`, so a consumer translates every kit string one way. */
|
|
671
666
|
declare function resolvePasswordRevealLabels(partial?: Partial<PasswordRevealLabels>): PasswordRevealLabels;
|
|
667
|
+
/**
|
|
668
|
+
* What the character counter of {@link Input} and {@link Textarea} (`showCount`) says.
|
|
669
|
+
* The visible "12/80" is digits and a slash and is not translated; these are the words
|
|
670
|
+
* a screen reader gets instead of it.
|
|
671
|
+
*/
|
|
672
|
+
interface CharacterCountLabels {
|
|
673
|
+
/** The counter as part of the field's description, read when focus reaches the
|
|
674
|
+
* field: "12 of 80 characters". */
|
|
675
|
+
count: (used: number, max: number) => string;
|
|
676
|
+
/** Said once, politely, on entering the last stretch before the limit: "8
|
|
677
|
+
* characters left". */
|
|
678
|
+
remaining: (left: number) => string;
|
|
679
|
+
/** Said once, politely, on reaching the limit. */
|
|
680
|
+
limitReached: string;
|
|
681
|
+
}
|
|
682
|
+
declare const DEFAULT_CHARACTER_COUNT_LABELS: CharacterCountLabels;
|
|
672
683
|
interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
|
|
673
684
|
label?: ReactNode;
|
|
674
685
|
/** Classes for the `<input>` itself, as distinct from `className`, which
|
|
@@ -699,6 +710,30 @@ interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
|
|
|
699
710
|
* `invalid`, so the field paints as well as announces. `invalid` alone still
|
|
700
711
|
* covers the case where the message lives elsewhere. See {@link useFieldError}. */
|
|
701
712
|
error?: ReactNode;
|
|
713
|
+
/**
|
|
714
|
+
* Standing advice for the field (keksdose K4: Input had `error` but no `hint`, so the
|
|
715
|
+
* app built the caption by hand under each field, and half of those never reached a
|
|
716
|
+
* screen reader). The {@link Select} rule, so every field reads alike:
|
|
717
|
+
* - plain TEXT (a string or a number) is a caption UNDER the field, attached with
|
|
718
|
+
* `aria-describedby` — after the caller's own ids, before the error's;
|
|
719
|
+
* - anything else (a {@link FieldHint} "?") rides the label line beside the
|
|
720
|
+
* animated label, as NumberInput's does — or, on a field with no label, sits at the
|
|
721
|
+
* field's end edge outside the box, and `className` then styles that row.
|
|
722
|
+
*/
|
|
723
|
+
hint?: ReactNode;
|
|
724
|
+
/**
|
|
725
|
+
* A live "12/80" under the field, with `maxLength` (keksdose K11 — the broadcast,
|
|
726
|
+
* support and handoff-note fields counted by hand). Read with the field as "12 of 80
|
|
727
|
+
* characters", and announced politely only on entering the last stretch and on
|
|
728
|
+
* reaching the limit — never on every keystroke. See {@link CharacterCount}. Ignored
|
|
729
|
+
* without a `maxLength`: a count with no limit is not what this answers. Counts
|
|
730
|
+
* UTF-16 code units, as `maxLength` itself does. Controlled, it counts `value`;
|
|
731
|
+
* uncontrolled, `defaultValue` and then every change event — a value written from
|
|
732
|
+
* outside without one (a form library's `reset`) shows from the next keystroke.
|
|
733
|
+
*/
|
|
734
|
+
showCount?: boolean;
|
|
735
|
+
/** The counter's words. See {@link CharacterCountLabels}. */
|
|
736
|
+
countLabels?: Partial<CharacterCountLabels>;
|
|
702
737
|
/** Names for the password reveal toggle, English by default — it is the one
|
|
703
738
|
* string this component renders on its own behalf, and a German form was
|
|
704
739
|
* reading it out in English. See {@link PasswordRevealLabels}. */
|
|
@@ -735,6 +770,29 @@ interface SelectProps extends Omit<SelectHTMLAttributes<HTMLSelectElement>, "siz
|
|
|
735
770
|
* the chevron is positioned against — so it could set a width and nothing
|
|
736
771
|
* else; this is the way to the element. See {@link Input}'s `inputClassName`. */
|
|
737
772
|
selectClassName?: string;
|
|
773
|
+
/**
|
|
774
|
+
* Why the choice cannot be changed — {@link Button}'s `disabledReason`, for a select
|
|
775
|
+
* that SAVES on change (a role picker in a members table, a status in a row). keksdose
|
|
776
|
+
* K3: those sat inside a hand-rolled `SaveGuard` that forced a native `disabled`, which
|
|
777
|
+
* took the field out of the tab order so the reason never reached a keyboard.
|
|
778
|
+
*
|
|
779
|
+
* With a reason the select is `aria-disabled` instead — still focusable, still showing
|
|
780
|
+
* its value — its list does not open (pointer and keys are swallowed, Tab and Escape
|
|
781
|
+
* excepted), `onChange` is never called, and the reason is in the kit {@link Tooltip}
|
|
782
|
+
* and on `aria-describedby`. It wears the settled look of a disabled field and drops
|
|
783
|
+
* its chevron, as a disabled Select does (dev#474). It wins over `disabled`.
|
|
784
|
+
*
|
|
785
|
+
* Use it CONTROLLED (`value` + `onChange`): React puts a controlled value back after
|
|
786
|
+
* the swallowed change. A touch platform's own picker may still open; nothing it picks
|
|
787
|
+
* is kept or reported.
|
|
788
|
+
*/
|
|
789
|
+
disabledReason?: ReactNode;
|
|
790
|
+
/**
|
|
791
|
+
* This select COMMITS — choosing saves. Under a locked {@link WriteLockProvider} it is
|
|
792
|
+
* locked the `disabledReason` way with the lock's reason (which wins over its own).
|
|
793
|
+
* No provider, or an unlocked one: no effect. Button's `commit`, for keksdose K3.
|
|
794
|
+
*/
|
|
795
|
+
commit?: boolean;
|
|
738
796
|
}
|
|
739
797
|
declare const Select: react.ForwardRefExoticComponent<SelectProps & react.RefAttributes<HTMLSelectElement>>;
|
|
740
798
|
interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
@@ -743,6 +801,14 @@ interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
|
743
801
|
invalid?: boolean;
|
|
744
802
|
/** See {@link Input}'s `error`. */
|
|
745
803
|
error?: ReactNode;
|
|
804
|
+
/** See {@link Input}'s `hint` (keksdose K4): text is a caption under the field, a
|
|
805
|
+
* {@link FieldHint} rides the label line (or, unlabelled, the end edge). */
|
|
806
|
+
hint?: ReactNode;
|
|
807
|
+
/** See {@link Input}'s `showCount` (keksdose K11): a live "12/80" under the field,
|
|
808
|
+
* with `maxLength`, announced only near and at the limit. */
|
|
809
|
+
showCount?: boolean;
|
|
810
|
+
/** The counter's words. See {@link CharacterCountLabels}. */
|
|
811
|
+
countLabels?: Partial<CharacterCountLabels>;
|
|
746
812
|
}
|
|
747
813
|
declare const Textarea: react.ForwardRefExoticComponent<TextareaProps & react.RefAttributes<HTMLTextAreaElement>>;
|
|
748
814
|
interface CardProps extends ComponentPropsWithoutRef<"div"> {
|
|
@@ -1164,6 +1230,375 @@ interface TabsProps<T extends string> extends Omit<ComponentPropsWithoutRef<"div
|
|
|
1164
1230
|
}
|
|
1165
1231
|
declare function Tabs<T extends string>({ tabs, active, onChange, className, wrap, label, panelId, onRemove, removeOn, onAdd, addLabel, labels, busy, orientation, "aria-label": ariaLabel, ...rest }: TabsProps<T>): react.JSX.Element;
|
|
1166
1232
|
|
|
1233
|
+
/**
|
|
1234
|
+
* How typed text is compared with the text it has to repeat — shared by
|
|
1235
|
+
* `DangerConfirm`'s `phraseMatch` and `useConfirm`'s `typedMatch`.
|
|
1236
|
+
*
|
|
1237
|
+
* - `"trim"` ignores spaces around the typed text — a phone keyboard's autocomplete
|
|
1238
|
+
* likes to add one. Case counts: "delete" is not "DELETE".
|
|
1239
|
+
* - `"exact"` compares character for character, spaces included.
|
|
1240
|
+
* - `"caseless"` trims AND ignores case: for an e-mail address, whose domain is
|
|
1241
|
+
* case-insensitive and whose local part every real mail server treats so. Both apps'
|
|
1242
|
+
* "type the account's address" rules (keksdose's `TYPE_EMAIL`, Kurvenschmiede's
|
|
1243
|
+
* `TypedConfirm`) compared `trim().toLowerCase()`, and a capital the user's keyboard
|
|
1244
|
+
* put at the start must not make the right row look like the wrong one.
|
|
1245
|
+
*/
|
|
1246
|
+
type TypedMatch = "trim" | "exact" | "caseless";
|
|
1247
|
+
/** Whether `typed` repeats `target` under `mode` — see {@link TypedMatch}. Exported for
|
|
1248
|
+
* a caller that draws its own field (a dialog that also picks a recipient) and wants
|
|
1249
|
+
* the same rule as the kit's. */
|
|
1250
|
+
declare function typedMatches(typed: string, target: string, mode?: TypedMatch): boolean;
|
|
1251
|
+
/**
|
|
1252
|
+
* Busy-while-a-promise-runs, for an action that MAY return one: `run(result, onResolved)`
|
|
1253
|
+
* marks the caller pending until `result` settles, calls `onResolved` if it fulfilled,
|
|
1254
|
+
* and only clears the flag if it rejected — the caller shows why and the user retries.
|
|
1255
|
+
* Nothing runs after unmount. Shared by `DangerConfirm` and `ReauthDialog`, whose
|
|
1256
|
+
* contract is the same: resolve = done, reject = stay put.
|
|
1257
|
+
*
|
|
1258
|
+
* @internal
|
|
1259
|
+
*/
|
|
1260
|
+
declare function usePromisePending(): {
|
|
1261
|
+
pending: boolean;
|
|
1262
|
+
run: (result: unknown, onResolved: () => void) => boolean;
|
|
1263
|
+
};
|
|
1264
|
+
/** The one word {@link CurrentPasswordInput} says on its own behalf — the
|
|
1265
|
+
* `dangerConfirm.password` label, shared with DangerConfirm's password field, so an
|
|
1266
|
+
* app translates "Password" once. */
|
|
1267
|
+
type CurrentPasswordInputLabels = Pick<DangerConfirmLabels, "password">;
|
|
1268
|
+
/**
|
|
1269
|
+
* Everything {@link Input} takes except what makes this field what it is: `type` is
|
|
1270
|
+
* always `"password"` and `autoComplete` always `"current-password"`.
|
|
1271
|
+
*/
|
|
1272
|
+
interface CurrentPasswordInputProps extends Omit<InputProps, "type" | "autoComplete" | "label"> {
|
|
1273
|
+
/**
|
|
1274
|
+
* The visible label. Default `dangerConfirm.password` ("Password") — unless the field
|
|
1275
|
+
* is named another way (`aria-label` / `aria-labelledby`), which then stays the only
|
|
1276
|
+
* name. Pass the app's own word on a sign-in form ("Password", "Your password"), or
|
|
1277
|
+
* `null` for a field whose `<label htmlFor>` is drawn elsewhere (a form library's
|
|
1278
|
+
* `FormLabel`), which would otherwise be labelled twice.
|
|
1279
|
+
*/
|
|
1280
|
+
label?: ReactNode;
|
|
1281
|
+
/** The value as a string — the `(next) => …` shape, so a caller holding it in
|
|
1282
|
+
* `useState` need not unwrap `event.target.value`. Fires alongside `onChange`,
|
|
1283
|
+
* never instead of it, so a form library's `onChange` keeps working. */
|
|
1284
|
+
onValueChange?: (value: string) => void;
|
|
1285
|
+
/**
|
|
1286
|
+
* A check is running (the sign-in request, the re-auth). The field turns `readOnly`,
|
|
1287
|
+
* NOT `disabled`: the field being submitted is usually the focused one (Enter was
|
|
1288
|
+
* pressed in it), and disabling a focused field drops focus to `<body>` — the user
|
|
1289
|
+
* lands nowhere when the "wrong password" answer comes back.
|
|
1290
|
+
*/
|
|
1291
|
+
busy?: boolean;
|
|
1292
|
+
/** Per-instance override of `dangerConfirm.password`. */
|
|
1293
|
+
labels?: Partial<CurrentPasswordInputLabels>;
|
|
1294
|
+
}
|
|
1295
|
+
/**
|
|
1296
|
+
* The "prove it is you" field: a password input that a password manager fills with
|
|
1297
|
+
* the CURRENT password and never offers to generate a new one for.
|
|
1298
|
+
*
|
|
1299
|
+
* It is the field of a sign-in form, a re-auth step ({@link ReauthDialog} draws the same
|
|
1300
|
+
* field), and {@link DangerConfirm}'s `requirePassword`. Public since 0.22 for kastlan's
|
|
1301
|
+
* sign-in and re-auth (kastlan 1), which wrote `type="password"` +
|
|
1302
|
+
* `autoComplete="current-password"` by hand — and a sign-in field that forgets the
|
|
1303
|
+
* second half gets the browser's "suggest a strong password" offer on the one form where
|
|
1304
|
+
* a NEW password is never what is wanted. The reverse matters as much: a field that sets
|
|
1305
|
+
* a NEW password (a passphrase, a sign-up) must NOT be this one — keksdose #170 keeps
|
|
1306
|
+
* its passphrase doors on `new-password` / `off` for that reason.
|
|
1307
|
+
*
|
|
1308
|
+
* Everything else is {@link Input}: the reveal toggle, `error` (under the field,
|
|
1309
|
+
* `aria-describedby`, `aria-invalid`), `invalid`, `name`, `id`, `autoFocus`, `required`.
|
|
1310
|
+
* The ref is the `<input>`, so it works with `@eifi1/ui-kit/rhf`'s `FormControl` /
|
|
1311
|
+
* a `register()` spread, and controlled or uncontrolled.
|
|
1312
|
+
*
|
|
1313
|
+
* ```tsx
|
|
1314
|
+
* <CurrentPasswordInput name="password" label={t("password")} error={errors.password?.message}
|
|
1315
|
+
* busy={isSubmitting} {...register("password")} />
|
|
1316
|
+
* ```
|
|
1317
|
+
*/
|
|
1318
|
+
declare const CurrentPasswordInput: react.ForwardRefExoticComponent<CurrentPasswordInputProps & react.RefAttributes<HTMLInputElement>>;
|
|
1319
|
+
/** The words {@link TypedConfirmField} says on its own behalf — the `dangerConfirm`
|
|
1320
|
+
* namespace's `phrase` and `phrasePlaceholder`, shared with DangerConfirm's own field,
|
|
1321
|
+
* so the sentence "Type “X” to confirm" is translated once. */
|
|
1322
|
+
type TypedConfirmFieldLabels = Pick<DangerConfirmLabels, "phrase" | "phrasePlaceholder">;
|
|
1323
|
+
interface TypedConfirmFieldProps extends Omit<InputProps, "type" | "value" | "defaultValue" | "label" | "placeholder"> {
|
|
1324
|
+
/** The text to repeat — a word ("DELETE"), a name, an e-mail address. */
|
|
1325
|
+
target: string;
|
|
1326
|
+
/** How the typed text is compared with `target` — {@link TypedMatch}. Default
|
|
1327
|
+
* `"trim"`, as {@link typedMatches}; `"caseless"` for an address or an
|
|
1328
|
+
* acknowledgement word a user may type in any case. */
|
|
1329
|
+
match?: TypedMatch;
|
|
1330
|
+
/** Controlled value. Left out, the field keeps its own (start: `defaultValue`). */
|
|
1331
|
+
value?: string;
|
|
1332
|
+
defaultValue?: string;
|
|
1333
|
+
/** The typed text as a string, on every keystroke. Fires alongside `onChange`. */
|
|
1334
|
+
onValueChange?: (value: string) => void;
|
|
1335
|
+
/**
|
|
1336
|
+
* The typed text started or stopped matching `target` — fired from the keystroke
|
|
1337
|
+
* that flipped it, so an uncontrolled field can still drive the button it guards. A
|
|
1338
|
+
* controlled caller that resets the value itself (on a close) knows the answer
|
|
1339
|
+
* already, and gets no call for that; it can also compute it with {@link typedMatches}.
|
|
1340
|
+
*/
|
|
1341
|
+
onMatchedChange?: (matched: boolean) => void;
|
|
1342
|
+
/** The label. Default `dangerConfirm.phrase(target)` — "Type “DELETE” to confirm". */
|
|
1343
|
+
label?: ReactNode;
|
|
1344
|
+
/** Text inside the empty field. Default `dangerConfirm.phrasePlaceholder` (unset).
|
|
1345
|
+
* Given, the label moves ABOVE the field: a floating label occupies the empty
|
|
1346
|
+
* field, which is exactly where a placeholder shows. `""` means none. */
|
|
1347
|
+
placeholder?: string;
|
|
1348
|
+
/** The guarded action is running: the field turns `readOnly` (not `disabled`, which
|
|
1349
|
+
* would drop the focus Enter left in it). */
|
|
1350
|
+
busy?: boolean;
|
|
1351
|
+
labels?: Partial<TypedConfirmFieldLabels>;
|
|
1352
|
+
}
|
|
1353
|
+
/**
|
|
1354
|
+
* The "type this to confirm" field — {@link DangerConfirm}'s `phrase` field and
|
|
1355
|
+
* `useConfirm({ requireTyped })`'s, on its own (keksdose K7).
|
|
1356
|
+
*
|
|
1357
|
+
* keksdose writes it by hand four times: the privacy enrol, upgrade and sweep dialogs
|
|
1358
|
+
* (type the acknowledgement word, then the key doors appear) and the admin's "type the
|
|
1359
|
+
* user's address" (`UserActionConfirm`), each an `Input` plus its own
|
|
1360
|
+
* `trim().toUpperCase()` / `toLowerCase()` comparison. None of those places is an
|
|
1361
|
+
* arm → confirm tile or a modal confirm — what is guarded is a whole form, or the
|
|
1362
|
+
* next step of a dialog — so the field had to stand alone. What it brings over a plain
|
|
1363
|
+
* `Input`: one match rule ({@link typedMatches}, which lower-cases locale-independently
|
|
1364
|
+
* on purpose), the label worded from the target in the app's language, and the
|
|
1365
|
+
* attributes a phone keyboard needs to leave the text alone (no autocomplete, no
|
|
1366
|
+
* auto-capital, no autocorrect, no spellcheck — a keyboard that "corrects" an e-mail
|
|
1367
|
+
* address makes the guard unpassable).
|
|
1368
|
+
*
|
|
1369
|
+
* The field reports whether it matches (`onMatchedChange`, and `data-matched` on the
|
|
1370
|
+
* `<input>` for styling); what the match unlocks is the caller's. The ref is the
|
|
1371
|
+
* `<input>`.
|
|
1372
|
+
*
|
|
1373
|
+
* ```tsx
|
|
1374
|
+
* const [ok, setOk] = useState(false);
|
|
1375
|
+
* <TypedConfirmField target={t("privacy.enroll_ack_word")} match="caseless" onMatchedChange={setOk} />
|
|
1376
|
+
* {ok && <KeyDoorsForm … />}
|
|
1377
|
+
* ```
|
|
1378
|
+
*/
|
|
1379
|
+
declare const TypedConfirmField: react.ForwardRefExoticComponent<TypedConfirmFieldProps & react.RefAttributes<HTMLInputElement>>;
|
|
1380
|
+
/**
|
|
1381
|
+
* Every string the tile renders — the `dangerConfirm` namespace of
|
|
1382
|
+
* `<UiKitProvider labels>`, overridable per instance through `labels`. The arm and
|
|
1383
|
+
* confirm buttons are usually worded per action ("Delete budget"), which is what the
|
|
1384
|
+
* `armLabel` / `confirmLabel` props are for; these are the fallbacks.
|
|
1385
|
+
*/
|
|
1386
|
+
interface DangerConfirmLabels {
|
|
1387
|
+
/** The button that arms the tile. */
|
|
1388
|
+
arm: string;
|
|
1389
|
+
/** The button that runs the action once the guards are satisfied. */
|
|
1390
|
+
confirm: string;
|
|
1391
|
+
cancel: string;
|
|
1392
|
+
/** The warning above the fields, when no `prompt` is given. */
|
|
1393
|
+
prompt: string;
|
|
1394
|
+
/** Label of the password field (`requirePassword`). */
|
|
1395
|
+
password: string;
|
|
1396
|
+
/** Label of the type-to-confirm field. A FUNCTION of the phrase by default, like
|
|
1397
|
+
* every message that carries a value: where the phrase sits in the sentence moves
|
|
1398
|
+
* with the language. A plain STRING is taken as the finished label — for an app
|
|
1399
|
+
* whose catalogue already words it ("Type DELETE to confirm") and would otherwise
|
|
1400
|
+
* wrap it as `() => label`. */
|
|
1401
|
+
phrase: string | ((phrase: string) => string);
|
|
1402
|
+
/** Placeholder of the type-to-confirm field — a string, or a function of the
|
|
1403
|
+
* phrase (`(p) => p` echoes it). Optional and unset by default: the field keeps its
|
|
1404
|
+
* floating label, as before. Given, the label moves ABOVE the field (a floating
|
|
1405
|
+
* label occupies the empty field, which is exactly where a placeholder shows) and
|
|
1406
|
+
* the placeholder fills the field. An empty string means none. */
|
|
1407
|
+
phrasePlaceholder?: string | ((phrase: string) => string);
|
|
1408
|
+
/** 0.22: the checkbox `requireAcknowledge={true}` shows — "I have read what this does
|
|
1409
|
+
* and want to continue" (keksdose's `admin.users.confirm_ack`). */
|
|
1410
|
+
acknowledge: string;
|
|
1411
|
+
/**
|
|
1412
|
+
* 0.23: why the armed confirm is held while the typed phrase does not match yet — in
|
|
1413
|
+
* the confirm's tooltip and its description (keksdose G4a). A FUNCTION of the phrase
|
|
1414
|
+
* by default ("Type “DELETE” to confirm"), or a finished STRING, as `phrase`.
|
|
1415
|
+
*/
|
|
1416
|
+
needsPhrase: string | ((phrase: string) => string);
|
|
1417
|
+
/** 0.23: why the armed confirm is held while the `requireAcknowledge` box is unticked
|
|
1418
|
+
* — "Tick the box to confirm". */
|
|
1419
|
+
needsAcknowledge: string;
|
|
1420
|
+
/** 0.23: why the armed confirm is held while the `requirePassword` field is empty —
|
|
1421
|
+
* "Enter your password to confirm". */
|
|
1422
|
+
needsPassword: string;
|
|
1423
|
+
}
|
|
1424
|
+
/** `satisfies` rather than a type annotation, so `DEFAULT_DANGER_CONFIRM_LABELS.phrase`
|
|
1425
|
+
* stays callable for a caller that composes its own label from it. */
|
|
1426
|
+
declare const DEFAULT_DANGER_CONFIRM_LABELS: {
|
|
1427
|
+
arm: string;
|
|
1428
|
+
confirm: string;
|
|
1429
|
+
cancel: string;
|
|
1430
|
+
prompt: string;
|
|
1431
|
+
password: string;
|
|
1432
|
+
phrase: (phrase: string) => string;
|
|
1433
|
+
acknowledge: string;
|
|
1434
|
+
needsPhrase: (phrase: string) => string;
|
|
1435
|
+
needsAcknowledge: string;
|
|
1436
|
+
needsPassword: string;
|
|
1437
|
+
};
|
|
1438
|
+
/**
|
|
1439
|
+
* What the guards were answered with — the second argument of
|
|
1440
|
+
* {@link DangerConfirmProps.onConfirm} (0.23, keksdose G4b). A key is there only when its
|
|
1441
|
+
* guard was asked for, so the object can go into a request body as it is.
|
|
1442
|
+
*/
|
|
1443
|
+
interface DangerConfirmValues {
|
|
1444
|
+
/**
|
|
1445
|
+
* The text typed into the `phrase` field — as the match rule compared it: trimmed
|
|
1446
|
+
* under `phraseMatch` `"trim"` and `"caseless"` (the spaces a phone keyboard adds are
|
|
1447
|
+
* not part of it), exactly as typed under `"exact"`. The case is the user's, even
|
|
1448
|
+
* under `"caseless"`: a server that re-checks applies its own rule to it. Absent
|
|
1449
|
+
* without a `phrase`.
|
|
1450
|
+
*/
|
|
1451
|
+
typed?: string;
|
|
1452
|
+
/** The entered password — the same value as the first argument. Absent without
|
|
1453
|
+
* `requirePassword`. */
|
|
1454
|
+
password?: string;
|
|
1455
|
+
/** `true` when the `requireAcknowledge` box was shown — it was ticked, since the
|
|
1456
|
+
* confirm is held until it is. Absent without one. */
|
|
1457
|
+
acknowledged?: true;
|
|
1458
|
+
}
|
|
1459
|
+
/**
|
|
1460
|
+
* One line of {@link DangerConfirmProps.consequences}: what the action will do. A plain
|
|
1461
|
+
* string, or this, for a key of its own and the `severe` mark.
|
|
1462
|
+
*/
|
|
1463
|
+
interface DangerConsequence {
|
|
1464
|
+
/** React key — keksdose keys its lines by what they say ("api_tokens", "only_door").
|
|
1465
|
+
* Default: the text when it is a string, else the position. */
|
|
1466
|
+
key?: string;
|
|
1467
|
+
text: ReactNode;
|
|
1468
|
+
/** "There is no way back" — painted in the danger colour rather than the list's
|
|
1469
|
+
* muted one. keksdose reserves it for the one line that loses something for good. */
|
|
1470
|
+
severe?: boolean;
|
|
1471
|
+
}
|
|
1472
|
+
interface DangerConfirmProps extends Omit<ComponentPropsWithoutRef<"div">, "onChange"> {
|
|
1473
|
+
/**
|
|
1474
|
+
* Runs the action, with the entered password when `requirePassword` is on.
|
|
1475
|
+
*
|
|
1476
|
+
* Return a promise and the tile manages itself: busy until it settles, disarmed
|
|
1477
|
+
* (fields wiped) when it resolves, still armed when it rejects — so the user can
|
|
1478
|
+
* correct a wrong password and retry. The rejection is not swallowed for you to
|
|
1479
|
+
* miss: handle it (and show why) in the caller, as with any mutation.
|
|
1480
|
+
*
|
|
1481
|
+
* 0.23: the second argument is what every guard was answered with — the typed phrase,
|
|
1482
|
+
* the password, the tick ({@link DangerConfirmValues}). keksdose G4b: its admin
|
|
1483
|
+
* actions send the address the admin TYPED, and the server re-checks it against the
|
|
1484
|
+
* account (`assert_confirmed`), so a client that put the wrong row's id in the request
|
|
1485
|
+
* is refused rather than obeyed; the tile kept the text to itself.
|
|
1486
|
+
*
|
|
1487
|
+
* onConfirm={(_password, { typed }) =>
|
|
1488
|
+
* reset.mutateAsync({ id, confirm: { acknowledged: true, confirm_email: typed ?? null } })}
|
|
1489
|
+
*
|
|
1490
|
+
* A second argument rather than one object in place of the password: every
|
|
1491
|
+
* `(password) => …` and `() => …` handler, and a `mutation.mutate` passed as it is,
|
|
1492
|
+
* keeps working unchanged, and a handler that needs one guard's answer names it.
|
|
1493
|
+
*/
|
|
1494
|
+
onConfirm: (password: string | undefined, values: DangerConfirmValues) => void | Promise<unknown>;
|
|
1495
|
+
/** Show a password field; confirm is held until it is filled. */
|
|
1496
|
+
requirePassword?: boolean;
|
|
1497
|
+
/**
|
|
1498
|
+
* Show an "I understand" checkbox; confirm is held until it is ticked
|
|
1499
|
+
* (keksdose K7). `true` words it with `labels.acknowledge`; any other node IS the
|
|
1500
|
+
* checkbox's label ("I understand Anna will be signed out everywhere").
|
|
1501
|
+
*
|
|
1502
|
+
* The guard for an action whose risk is MIS-TARGETING less than carelessness:
|
|
1503
|
+
* keksdose's admin password reset asks for a typed address when the account has an
|
|
1504
|
+
* encrypted door to lose, and a tick otherwise (`UserActionConfirm`), and its plan
|
|
1505
|
+
* editor asks for the tick alone (`UserPlanEditor`). Both were hand-built beside this
|
|
1506
|
+
* tile because it had no tick. It combines with `phrase` and `requirePassword`: every
|
|
1507
|
+
* guard given must be satisfied.
|
|
1508
|
+
*/
|
|
1509
|
+
requireAcknowledge?: ReactNode;
|
|
1510
|
+
/**
|
|
1511
|
+
* What the action will do, said before it happens — a list under the prompt, shown
|
|
1512
|
+
* once armed (keksdose K7, `UserActionConfirm`'s consequences). Strings, or
|
|
1513
|
+
* {@link DangerConsequence}s for a `severe` line in the danger colour.
|
|
1514
|
+
*
|
|
1515
|
+
* Derive them from the row's own facts rather than reciting the worst case: an admin
|
|
1516
|
+
* who reads the same paragraph on every row stops reading it (keksdose dev#488).
|
|
1517
|
+
*/
|
|
1518
|
+
consequences?: readonly (string | DangerConsequence)[];
|
|
1519
|
+
/** Show a "type <phrase> to confirm" field; confirm is held until the field matches
|
|
1520
|
+
* (case-sensitive; surrounding spaces ignored unless `phraseMatch="exact"`). */
|
|
1521
|
+
phrase?: string;
|
|
1522
|
+
/**
|
|
1523
|
+
* How the typed text is compared with `phrase`. `"trim"` (default) ignores spaces
|
|
1524
|
+
* around it — a phone keyboard's autocomplete likes to add one. `"exact"` compares
|
|
1525
|
+
* character for character, spaces included, for an app whose contract is "type
|
|
1526
|
+
* exactly this". `"caseless"` (0.18) also ignores case — for a phrase that is an
|
|
1527
|
+
* e-mail address (keksdose's "type the user's address" admin rule). See
|
|
1528
|
+
* {@link TypedMatch}.
|
|
1529
|
+
*/
|
|
1530
|
+
phraseMatch?: TypedMatch;
|
|
1531
|
+
/** The warning above the fields. Defaults to `labels.prompt`. */
|
|
1532
|
+
prompt?: ReactNode;
|
|
1533
|
+
/** `"danger"` (default) for what cannot be undone; `"warning"` for what can, at a
|
|
1534
|
+
* cost (loading demo data over your own). Colours the prompt and the confirm. */
|
|
1535
|
+
tone?: "danger" | "warning";
|
|
1536
|
+
/** Visible text of the arm button; defaults to `labels.arm`. */
|
|
1537
|
+
armLabel?: ReactNode;
|
|
1538
|
+
/** Visible text of the confirm button; defaults to `labels.confirm`. */
|
|
1539
|
+
confirmLabel?: ReactNode;
|
|
1540
|
+
/** The action is running: confirm shows a spinner and nothing can be pressed. For a
|
|
1541
|
+
* caller that tracks the mutation itself (a `useMutation`'s `isPending`); a
|
|
1542
|
+
* promise returned from `onConfirm` does the same on its own. */
|
|
1543
|
+
busy?: boolean;
|
|
1544
|
+
/** The arm button is disabled. */
|
|
1545
|
+
disabled?: boolean;
|
|
1546
|
+
/**
|
|
1547
|
+
* Why the action is not available — a read-only demo, a write lock, a missing
|
|
1548
|
+
* permission. Disables the arm button like `disabled`, and SAYS so: the sentence is
|
|
1549
|
+
* shown under the button and attached to it with `aria-describedby`, and the button
|
|
1550
|
+
* stays focusable (`aria-disabled`) so a keyboard user can land on it and hear why.
|
|
1551
|
+
*
|
|
1552
|
+
* On the ARM button rather than the confirm: arming asks for a password, and asking
|
|
1553
|
+
* for a password for a write that can never land is the worse of the two. A tile that
|
|
1554
|
+
* is ALREADY armed when the reason arrives (controlled `armed`, or a lock that landed
|
|
1555
|
+
* while it was open) keeps its fields but its confirm takes the reason the same way
|
|
1556
|
+
* — focusable, `aria-disabled`, the reason in its tooltip — and Enter does nothing.
|
|
1557
|
+
*/
|
|
1558
|
+
lockedReason?: ReactNode;
|
|
1559
|
+
/**
|
|
1560
|
+
* This tile COMMITS — the 0.18 write-lock opt-in that {@link Button} has (keksdose
|
|
1561
|
+
* K3). Under a locked {@link WriteLockProvider} the lock's reason becomes
|
|
1562
|
+
* `lockedReason` (and wins over one of the tile's own), so a page that mounts the
|
|
1563
|
+
* provider no longer threads `lockedReason={lock.locked ? lock.reason : undefined}`
|
|
1564
|
+
* into every tile. No provider, or an unlocked one: no effect.
|
|
1565
|
+
*/
|
|
1566
|
+
commit?: boolean;
|
|
1567
|
+
/** Controlled armed state. The parent can then collapse the tile from a mutation's
|
|
1568
|
+
* own `onSuccess` without returning a promise. */
|
|
1569
|
+
armed?: boolean;
|
|
1570
|
+
/** Called with the next armed state — on arm, cancel, and a resolved `onConfirm`. */
|
|
1571
|
+
onArmedChange?: (armed: boolean) => void;
|
|
1572
|
+
/** User-facing strings; see {@link DangerConfirmLabels}. */
|
|
1573
|
+
labels?: Partial<DangerConfirmLabels>;
|
|
1574
|
+
}
|
|
1575
|
+
/**
|
|
1576
|
+
* An "arm → confirm" tile for destructive actions: one button, which expands into a
|
|
1577
|
+
* warning, an optional list of consequences, an optional "I understand" tick, an
|
|
1578
|
+
* optional type-to-confirm field, an optional password field and a confirm that is held
|
|
1579
|
+
* until every guard is satisfied.
|
|
1580
|
+
*
|
|
1581
|
+
* A held confirm SAYS which guard is still open (0.23, keksdose G4a): it is
|
|
1582
|
+
* `aria-disabled` rather than `disabled` — still focusable, so a keyboard user can land
|
|
1583
|
+
* on it — with the reason in the kit {@link Tooltip} and its description ("Type
|
|
1584
|
+
* “DELETE” to confirm", "Tick the box to confirm", "Enter your password to confirm";
|
|
1585
|
+
* `labels.needs*`), the first open guard in the order they are drawn. FormActions'
|
|
1586
|
+
* `submitDisabledReason` does the same for a form's Save. Pressing it, or Enter in a
|
|
1587
|
+
* field, does nothing. A lock's reason wins over a guard's; while the action runs the
|
|
1588
|
+
* confirm is plainly disabled, its spinner saying why.
|
|
1589
|
+
*
|
|
1590
|
+
* Keksdose hand-rolled it three times (load demo data, wipe everything, reset a
|
|
1591
|
+
* budget) and then as `shared/components/danger-confirm.tsx`; the only app-specific
|
|
1592
|
+
* part was its write-lock hook, which is `lockedReason` here.
|
|
1593
|
+
*
|
|
1594
|
+
* The fields are a `<form>`, so Enter confirms once the guards allow it. They are
|
|
1595
|
+
* wiped every time the tile disarms — a password must not sit in a collapsed tile.
|
|
1596
|
+
* Arming moves focus to the first field (or Cancel, when there is none — never to the
|
|
1597
|
+
* destructive button itself), and disarming moves it back to the arm button, so the
|
|
1598
|
+
* keyboard user is never left on an element that just vanished.
|
|
1599
|
+
*/
|
|
1600
|
+
declare function DangerConfirm({ onConfirm, requirePassword, requireAcknowledge, consequences, phrase, phraseMatch, prompt, tone, armLabel, confirmLabel, busy: busyProp, disabled, lockedReason: ownLockedReason, commit, armed: armedProp, onArmedChange, labels: labelsProp, className, ...rest }: DangerConfirmProps): react.JSX.Element;
|
|
1601
|
+
|
|
1167
1602
|
/**
|
|
1168
1603
|
* A button that opens the file picker — the shape all three apps kept writing by hand
|
|
1169
1604
|
* as a `<Button>` plus a hidden `<input type="file">` plus a ref between them (seven
|
|
@@ -1361,6 +1796,22 @@ interface FileButtonProps extends Omit<UseFilePickerOptions, "disabled">, Omit<B
|
|
|
1361
1796
|
* file leaves it as it was. Off by default, so the button's layout is unchanged.
|
|
1362
1797
|
*/
|
|
1363
1798
|
showFileName?: boolean;
|
|
1799
|
+
/**
|
|
1800
|
+
* Why picking is not available — {@link Button}'s `disabledReason`, with the picker's
|
|
1801
|
+
* half added (keksdose K3): the button is `aria-disabled` but stays focusable, the
|
|
1802
|
+
* reason is in the kit Tooltip and its description, a click opens no picker, and a
|
|
1803
|
+
* `droppable` button takes no drop (the drag is still cancelled, so the browser does
|
|
1804
|
+
* not navigate to the file). Wins over `disabled`, as on Button.
|
|
1805
|
+
*/
|
|
1806
|
+
disabledReason?: ReactNode;
|
|
1807
|
+
/**
|
|
1808
|
+
* This pick COMMITS — an upload that starts on pick, an attachment saved at once.
|
|
1809
|
+
* Under a locked {@link WriteLockProvider} it takes the `disabledReason` path with
|
|
1810
|
+
* the lock's reason (which wins over one of its own). No provider, or an unlocked
|
|
1811
|
+
* one: no effect. A picker that only fills a form the user saves later is not a
|
|
1812
|
+
* commit, and is left live — the form's Save carries the lock.
|
|
1813
|
+
*/
|
|
1814
|
+
commit?: boolean;
|
|
1364
1815
|
}
|
|
1365
1816
|
/**
|
|
1366
1817
|
* {@link useFilePicker} behind a {@link Button}: `variant` and every other button prop
|
|
@@ -1376,6 +1827,471 @@ interface FileButtonProps extends Omit<UseFilePickerOptions, "disabled">, Omit<B
|
|
|
1376
1827
|
*/
|
|
1377
1828
|
declare const FileButton: react.ForwardRefExoticComponent<FileButtonProps & react.RefAttributes<HTMLButtonElement>>;
|
|
1378
1829
|
|
|
1830
|
+
/**
|
|
1831
|
+
* The conversation under a report: who said what, when, with what attached — and the
|
|
1832
|
+
* box to answer in.
|
|
1833
|
+
*
|
|
1834
|
+
* Both apps had written it by hand. kastlan's feedback page grew a comment list of
|
|
1835
|
+
* bordered boxes with `slate-*` literals (feedback-page.tsx, "keksdose left this
|
|
1836
|
+
* unbuilt"), and keksdose built the same thing a second time for support
|
|
1837
|
+
* (support-thread.tsx) with sides, bubbles and a composer that clears only what it
|
|
1838
|
+
* sent. This is that second one, generalised: the kit owns the look and the
|
|
1839
|
+
* behaviour, the app owns the data, the upload and every word it does not share.
|
|
1840
|
+
*
|
|
1841
|
+
* **Own vs other** is the caller's per message (`own`), not a comparison the kit makes
|
|
1842
|
+
* against a user id: whose message sits at the END side depends on who is reading,
|
|
1843
|
+
* and only the app knows that (keksdose's support thread labelled a member's question
|
|
1844
|
+
* "Du" in the admin panel the first time round, by reading the wrong field).
|
|
1845
|
+
*
|
|
1846
|
+
* **Redaction.** A thread is somebody's words about their own data — exactly what a
|
|
1847
|
+
* host's demo / screen-share mode blurs. Bodies, authors and attachments carry
|
|
1848
|
+
* `data-private` (the attribute `Tooltip redact` and `StatTile sensitive` use) unless
|
|
1849
|
+
* `redact={false}`.
|
|
1850
|
+
*
|
|
1851
|
+
* **RTL.** Sides are logical — `justify-end` is the reading end, and the bubble's
|
|
1852
|
+
* tucked corner is `rounded-ee` / `rounded-es` — and each body is `dir="auto"`, so a
|
|
1853
|
+
* Hebrew reply in an English thread (or the reverse) lays out as its own language.
|
|
1854
|
+
*
|
|
1855
|
+
* **A chat, too** (keksdose G4/G5). keksdose's support chat is the same conversation
|
|
1856
|
+
* read the chat way: status lines between the messages ("Closed automatically",
|
|
1857
|
+
* "Reopened"), a day line where the date changes, clock times under it, Enter to send
|
|
1858
|
+
* and several files uploaded ahead of the send. Each of those is an opt-in here
|
|
1859
|
+
* (`kind: "event"`, `daySeparators`, `timeFormat="clock"`, `sendOn="enter"`,
|
|
1860
|
+
* `attachmentSlot` + `canSend`), so the feedback thread's defaults stay as they were.
|
|
1861
|
+
*/
|
|
1862
|
+
/** The `feedbackThread` namespace of `<UiKitProvider labels>`. */
|
|
1863
|
+
interface FeedbackThreadLabels {
|
|
1864
|
+
/** Accessible name of the message list. */
|
|
1865
|
+
thread: string;
|
|
1866
|
+
empty: string;
|
|
1867
|
+
loading: string;
|
|
1868
|
+
/** Author line of an `own` message that has no `author` of its own. */
|
|
1869
|
+
you: string;
|
|
1870
|
+
/** The badge beside a `staff` author. */
|
|
1871
|
+
staff: string;
|
|
1872
|
+
/** Accessible name of a message's attachment list. */
|
|
1873
|
+
attachments: string;
|
|
1874
|
+
}
|
|
1875
|
+
declare const DEFAULT_FEEDBACK_THREAD_LABELS: FeedbackThreadLabels;
|
|
1876
|
+
/** The `feedbackComposer` namespace of `<UiKitProvider labels>`. The attach buttons'
|
|
1877
|
+
* words are `feedbackAttachment`'s, shared with the dialog and the note editor. */
|
|
1878
|
+
interface FeedbackComposerLabels {
|
|
1879
|
+
/** Accessible name of the text box. */
|
|
1880
|
+
field: string;
|
|
1881
|
+
placeholder: string;
|
|
1882
|
+
send: string;
|
|
1883
|
+
/** The shortcut line, given the platform's modifier ("Ctrl" or "⌘"). */
|
|
1884
|
+
sendHint: (modifier: string) => string;
|
|
1885
|
+
/** The shortcut line under `sendOn="enter"` (keksdose G5): Enter sends, so say how a
|
|
1886
|
+
* new line is made. */
|
|
1887
|
+
sendHintEnter: string;
|
|
1888
|
+
}
|
|
1889
|
+
declare const DEFAULT_FEEDBACK_COMPOSER_LABELS: FeedbackComposerLabels;
|
|
1890
|
+
interface FeedbackThreadAttachment {
|
|
1891
|
+
id?: string | number;
|
|
1892
|
+
name: string;
|
|
1893
|
+
/** Where to open it. Left out, the attachment is listed by name only. */
|
|
1894
|
+
url?: string;
|
|
1895
|
+
/** MIME type; an `image/*` with a `url` is shown as a thumbnail. */
|
|
1896
|
+
type?: string;
|
|
1897
|
+
/** Bytes, shown beside a non-image. */
|
|
1898
|
+
size?: number;
|
|
1899
|
+
}
|
|
1900
|
+
interface FeedbackThreadMessage {
|
|
1901
|
+
/** Leave out, or `"message"`. `"event"` is a {@link FeedbackThreadEvent}. */
|
|
1902
|
+
kind?: "message";
|
|
1903
|
+
id: string | number;
|
|
1904
|
+
/** Who wrote it. Left out on an `own` message, it reads "You". */
|
|
1905
|
+
author?: ReactNode;
|
|
1906
|
+
/** A `Date`, an ISO string or epoch ms. */
|
|
1907
|
+
createdAt: Date | string | number;
|
|
1908
|
+
body: string;
|
|
1909
|
+
attachments?: readonly FeedbackThreadAttachment[];
|
|
1910
|
+
/** Written by whoever is reading: sits at the end side, in the brand tint. */
|
|
1911
|
+
own?: boolean;
|
|
1912
|
+
/** Written by the team rather than a user: gets the "Staff" badge. */
|
|
1913
|
+
staff?: boolean;
|
|
1914
|
+
}
|
|
1915
|
+
/**
|
|
1916
|
+
* A line in the thread that nobody wrote — "Closed automatically", "Marked as
|
|
1917
|
+
* resolved", "Reopened" — drawn centred and muted with its time, no author, no side,
|
|
1918
|
+
* no bubble.
|
|
1919
|
+
*
|
|
1920
|
+
* keksdose G4: its support chat interleaves these with the messages, and as a message
|
|
1921
|
+
* they came out as a bubble from nobody at the start side, which reads as the member
|
|
1922
|
+
* having said "resolved". Word it for the READER, as with `own`: the app knows whether
|
|
1923
|
+
* "you reopened it" or "Anna reopened it" is true for the person looking.
|
|
1924
|
+
*
|
|
1925
|
+
* The text is the app's, not somebody's words about their data, so it is NOT tagged
|
|
1926
|
+
* `data-private`; one that names a person can wrap the name in its own
|
|
1927
|
+
* `<span data-private>` (`body` is a node for that reason).
|
|
1928
|
+
*/
|
|
1929
|
+
interface FeedbackThreadEvent {
|
|
1930
|
+
kind: "event";
|
|
1931
|
+
id: string | number;
|
|
1932
|
+
/** A `Date`, an ISO string or epoch ms. */
|
|
1933
|
+
createdAt: Date | string | number;
|
|
1934
|
+
body: ReactNode;
|
|
1935
|
+
}
|
|
1936
|
+
/** One row of a {@link FeedbackThread}: a message, or an event line between them. */
|
|
1937
|
+
type FeedbackThreadItem = FeedbackThreadMessage | FeedbackThreadEvent;
|
|
1938
|
+
interface FeedbackThreadProps {
|
|
1939
|
+
/** Oldest first. Event lines ({@link FeedbackThreadEvent}) sit among the messages. */
|
|
1940
|
+
messages: readonly FeedbackThreadItem[];
|
|
1941
|
+
loading?: boolean;
|
|
1942
|
+
/** Replaces the default "No comments yet". */
|
|
1943
|
+
empty?: ReactNode;
|
|
1944
|
+
/**
|
|
1945
|
+
* Draw one attachment yourself — for files behind auth, which a plain `<img src>`
|
|
1946
|
+
* cannot fetch (kastlan's `AuthedImage`), or a lightbox. The default is a thumbnail
|
|
1947
|
+
* link for an image with a `url`, a file link otherwise.
|
|
1948
|
+
*/
|
|
1949
|
+
renderAttachment?: (attachment: FeedbackThreadAttachment, message: FeedbackThreadMessage) => ReactNode;
|
|
1950
|
+
/** Tag bodies, authors and attachments `data-private`. Default true. */
|
|
1951
|
+
redact?: boolean;
|
|
1952
|
+
/**
|
|
1953
|
+
* How a row's time reads. `"relative"` (default): "5 minutes ago", a date past six
|
|
1954
|
+
* days — right for a report's comments, read days apart. `"clock"`: the time of day
|
|
1955
|
+
* in the locale ("14:05", "2:05 PM") — the chat look, keksdose G4; pair it with
|
|
1956
|
+
* `daySeparators`, which say which day that clock time is on. Either way the full
|
|
1957
|
+
* date and time is in the Tooltip.
|
|
1958
|
+
*/
|
|
1959
|
+
timeFormat?: "relative" | "clock";
|
|
1960
|
+
/**
|
|
1961
|
+
* A centred day line before the first row and wherever the next row is on another
|
|
1962
|
+
* calendar day (the device's zone): "Today", "Yesterday", else the date — keksdose
|
|
1963
|
+
* G4. "Today" / "Yesterday" are `Intl.RelativeTimeFormat`'s own words in the kit
|
|
1964
|
+
* locale, so there is no label to translate. Default false.
|
|
1965
|
+
*/
|
|
1966
|
+
daySeparators?: boolean;
|
|
1967
|
+
/** "Now" for the relative times and the day lines — pin it in tests and stories.
|
|
1968
|
+
* Default: the clock. */
|
|
1969
|
+
now?: Date | number;
|
|
1970
|
+
/** Overrides the provider's locale for the times. */
|
|
1971
|
+
locale?: string;
|
|
1972
|
+
labels?: Partial<FeedbackThreadLabels>;
|
|
1973
|
+
className?: string;
|
|
1974
|
+
}
|
|
1975
|
+
declare function FeedbackThread({ messages, loading, empty, renderAttachment, redact, now, locale: localeProp, timeFormat, daySeparators, labels: labelsProp, className, }: FeedbackThreadProps): react.JSX.Element;
|
|
1976
|
+
/** What the composer's attach control takes — {@link FeedbackNoteAttachment} with the
|
|
1977
|
+
* labels optional, since the field reads `feedbackAttachment` from the provider, and
|
|
1978
|
+
* `onError` the field's own (0.23.0): it is handed the refused file and the limit too
|
|
1979
|
+
* (`FeedbackAttachmentErrorInfo`), and a `(kind) => …` handler still fits. */
|
|
1980
|
+
type FeedbackComposerAttachment = Omit<FeedbackNoteAttachment, "labels" | "onError"> & {
|
|
1981
|
+
labels?: Partial<FeedbackAttachmentLabels>;
|
|
1982
|
+
onError?: FeedbackAttachmentFieldSingleProps["onError"];
|
|
1983
|
+
};
|
|
1984
|
+
interface FeedbackComposerProps {
|
|
1985
|
+
/**
|
|
1986
|
+
* Send the comment. Return the promise: the box clears when it RESOLVES, and only of
|
|
1987
|
+
* what was sent — text typed while it was in flight stays. A rejection keeps
|
|
1988
|
+
* everything for a retry (surface the error yourself; the composer stays quiet).
|
|
1989
|
+
*
|
|
1990
|
+
* `attachment` is the built-in field's one picture. Files the host uploaded ahead
|
|
1991
|
+
* (`attachmentSlot`) are the host's state, read by the host here — and `body` may be
|
|
1992
|
+
* `""` when `canSend` let an attachments-only message go.
|
|
1993
|
+
*/
|
|
1994
|
+
onSend: (body: string, attachment: File | null) => void | Promise<unknown>;
|
|
1995
|
+
/** The send is in flight: a spinner on the button and no second send. */
|
|
1996
|
+
pending?: boolean;
|
|
1997
|
+
/** Offer one picture with the comment (file, paste or `onCaptureScreenshot`).
|
|
1998
|
+
* `true` for the defaults. Left out, the composer is text only. */
|
|
1999
|
+
attachment?: boolean | FeedbackComposerAttachment;
|
|
2000
|
+
/**
|
|
2001
|
+
* The host's own attach control, in the row with Send where the built-in field sits
|
|
2002
|
+
* (after it, if both are on) — keksdose G5: its support chat uploads up to N files
|
|
2003
|
+
* AHEAD of the send and sends their refs, which one `File` in `onSend` cannot carry.
|
|
2004
|
+
* The slot is the host's picker plus the chips of what is uploaded; the upload, the
|
|
2005
|
+
* refs and clearing them once `onSend` resolves stay with the host. Pair it with
|
|
2006
|
+
* `canSend`.
|
|
2007
|
+
*/
|
|
2008
|
+
attachmentSlot?: ReactNode;
|
|
2009
|
+
/**
|
|
2010
|
+
* Whether Send is enabled, over the composer's own rule (some text in the box) —
|
|
2011
|
+
* for state the composer cannot see, i.e. `attachmentSlot`'s (keksdose G5): `true`
|
|
2012
|
+
* with files ready makes an empty draft sendable (`onSend("", null)`), `false` while
|
|
2013
|
+
* an upload is still running holds even a written reply back. Left out, the text
|
|
2014
|
+
* decides. `pending` blocks a send either way, as does a draft past `maxLength`.
|
|
2015
|
+
*/
|
|
2016
|
+
canSend?: boolean;
|
|
2017
|
+
/**
|
|
2018
|
+
* Which key sends. `"mod-enter"` (default): Ctrl/⌘+Enter, the report dialog's and
|
|
2019
|
+
* note editor's shortcut, with plain Enter a new line — feedback is written in
|
|
2020
|
+
* paragraphs. `"enter"`: the chat way (keksdose G5) — Enter sends, Shift+Enter is a
|
|
2021
|
+
* new line, Ctrl/⌘+Enter still sends; an Enter that confirms an IME composition
|
|
2022
|
+
* (Japanese, Chinese input) is the IME's, never a send.
|
|
2023
|
+
*/
|
|
2024
|
+
sendOn?: "mod-enter" | "enter";
|
|
2025
|
+
/** Rendered INSTEAD of the composer — the thread is closed, or read-only for this
|
|
2026
|
+
* reader. */
|
|
2027
|
+
disabledReason?: ReactNode;
|
|
2028
|
+
rows?: number;
|
|
2029
|
+
/**
|
|
2030
|
+
* The longest draft the box takes, in UTF-16 code units as the browser counts — the
|
|
2031
|
+
* server's limit, so a reply too long for it is cut off while it is typed rather than
|
|
2032
|
+
* refused by a 422 after the press (keksdose G6: its support replies are capped at
|
|
2033
|
+
* 4,000 on the server, and its other text fields already count against that with
|
|
2034
|
+
* Textarea's `maxLength` + `showCount` since 0.22; the reply box, a composer, could
|
|
2035
|
+
* not). The box's own `maxLength`, so typing and pasting stop at it.
|
|
2036
|
+
*
|
|
2037
|
+
* {@link FeedbackComposerHandle.insertText} is not stopped by it — the browser limits
|
|
2038
|
+
* typing, not a script — and a canned reply is not cut mid-sentence to fit. A draft
|
|
2039
|
+
* past the limit therefore holds Send back (whatever `canSend` says, as `pending`
|
|
2040
|
+
* does) until it is trimmed; with `showCount` the counter, red at the limit, says by
|
|
2041
|
+
* how much.
|
|
2042
|
+
*/
|
|
2043
|
+
maxLength?: number;
|
|
2044
|
+
/**
|
|
2045
|
+
* A live "12/4000" under the box, with `maxLength` — Textarea's `showCount`, the same
|
|
2046
|
+
* counter (keksdose G6): the count is part of the box's description, read with it on
|
|
2047
|
+
* focus, and a polite live region speaks only on entering the last stretch and at the
|
|
2048
|
+
* limit, never per keystroke. Under `size="sm"` the hidden send hint stays the box's
|
|
2049
|
+
* description too, before the count. Ignored without `maxLength`.
|
|
2050
|
+
*/
|
|
2051
|
+
showCount?: boolean;
|
|
2052
|
+
/** The counter's words — the `characterCount` namespace, as on Textarea. */
|
|
2053
|
+
countLabels?: Partial<CharacterCountLabels>;
|
|
2054
|
+
/**
|
|
2055
|
+
* The box's hint, over the `placeholder` label — keksdose F9: an admin answering a
|
|
2056
|
+
* support ticket is asked something else ("Reply to Anna…") than a member adding to
|
|
2057
|
+
* their own report, and one provider-wide label cannot say both.
|
|
2058
|
+
*/
|
|
2059
|
+
placeholder?: string;
|
|
2060
|
+
/**
|
|
2061
|
+
* The draft, controlled — for a host that keeps it itself (saves it per ticket,
|
|
2062
|
+
* prefills a template). Left out, the composer keeps its own. Either way a send
|
|
2063
|
+
* that resolves clears only what was sent: controlled, that is an
|
|
2064
|
+
* `onValueChange("")` the host receives like any keystroke, and only if the draft
|
|
2065
|
+
* is still the one that went out.
|
|
2066
|
+
*/
|
|
2067
|
+
value?: string;
|
|
2068
|
+
/** Every change to the draft — typing, {@link FeedbackComposerHandle.insertText}, the
|
|
2069
|
+
* clear after a send. Required to change a controlled `value`. */
|
|
2070
|
+
onValueChange?: (value: string) => void;
|
|
2071
|
+
/** {@link FeedbackComposerHandle}: put text into the draft from outside (canned-reply
|
|
2072
|
+
* chips) or focus the box. */
|
|
2073
|
+
ref?: Ref<FeedbackComposerHandle>;
|
|
2074
|
+
labels?: Partial<FeedbackComposerLabels>;
|
|
2075
|
+
className?: string;
|
|
2076
|
+
/**
|
|
2077
|
+
* `"sm"` for a narrow host — keksdose's assistant launcher, a small floating panel
|
|
2078
|
+
* (0.22): a small Send button, and the send hint ("Enter to send, Shift + Enter for a
|
|
2079
|
+
* new line") hidden from view but kept as the box's description, so a keyboard or
|
|
2080
|
+
* screen-reader user still learns the shortcut. Default `"md"`.
|
|
2081
|
+
*/
|
|
2082
|
+
size?: "md" | "sm";
|
|
2083
|
+
/**
|
|
2084
|
+
* On the composer's root — the box, or the `disabledReason` line in its place —
|
|
2085
|
+
* with any `data-*` attribute beside it (keksdose K17). keksdose's assistant tour
|
|
2086
|
+
* points at the chat box with `[data-tour="assistant-ask"]`, and a composer that
|
|
2087
|
+
* dropped every attribute it was not told about left the anchor nowhere: the
|
|
2088
|
+
* assistant kept its hand-built box rather than lose the tour step.
|
|
2089
|
+
*/
|
|
2090
|
+
id?: string;
|
|
2091
|
+
/** `data-*` attributes for the root, as `id` — a tour anchor, a test id. */
|
|
2092
|
+
[dataAttribute: `data-${string}`]: string | number | boolean | undefined;
|
|
2093
|
+
}
|
|
2094
|
+
/**
|
|
2095
|
+
* What a {@link FeedbackComposer} `ref` holds.
|
|
2096
|
+
*
|
|
2097
|
+
* keksdose F9: the support admin answers the same five questions all day and wants
|
|
2098
|
+
* chips above the box ("Thanks, fixed in the next release") that drop their text in
|
|
2099
|
+
* where the caret is. A controlled `value` alone cannot do that well — the host sees
|
|
2100
|
+
* the string, not the caret, so it could only append — so the composer, which owns
|
|
2101
|
+
* the textarea, does the splice.
|
|
2102
|
+
*/
|
|
2103
|
+
interface FeedbackComposerHandle {
|
|
2104
|
+
/**
|
|
2105
|
+
* Insert `text` at the caret, replacing any selection (the caret the box last had:
|
|
2106
|
+
* a click on a chip blurs it, and the selection survives the blur), then focus the
|
|
2107
|
+
* box with the caret after the inserted text so the reply can go on. Nothing is
|
|
2108
|
+
* added around it — put a space or a newline in `text` if the reply needs one. A
|
|
2109
|
+
* no-op while `disabledReason` replaces the box.
|
|
2110
|
+
*/
|
|
2111
|
+
insertText: (text: string) => void;
|
|
2112
|
+
focus: () => void;
|
|
2113
|
+
}
|
|
2114
|
+
/**
|
|
2115
|
+
* The answer box under a {@link FeedbackThread}: a textarea, an optional picture,
|
|
2116
|
+
* and Send — Ctrl/⌘+Enter sends, the shortcut the report dialog and the note editor
|
|
2117
|
+
* use, so the habit carries across the feature. Plain Enter is a new line: feedback is
|
|
2118
|
+
* written in paragraphs, unlike a chat — which `sendOn="enter"` is for (keksdose G5).
|
|
2119
|
+
*/
|
|
2120
|
+
declare function FeedbackComposer({ onSend, pending, attachment, attachmentSlot, canSend: canSendProp, sendOn, disabledReason, rows, maxLength, showCount, countLabels, placeholder, value, onValueChange, ref, labels: labelsProp, className, id, size, ...rest }: FeedbackComposerProps): react.JSX.Element;
|
|
2121
|
+
/**
|
|
2122
|
+
* {@link FeedbackComposer} under a name that is not about feedback (keksdose K17).
|
|
2123
|
+
*
|
|
2124
|
+
* The component was never feedback-specific: a textarea, an optional picture or a
|
|
2125
|
+
* host's upload slot, Send, `sendOn="enter"` for the chat way. keksdose's assistant
|
|
2126
|
+
* and support chat are chats, not reports, and an import of `FeedbackComposer` there
|
|
2127
|
+
* reads as a mistake to the next person. The same function, not a wrapper, so the
|
|
2128
|
+
* two names cannot drift.
|
|
2129
|
+
*/
|
|
2130
|
+
declare const ChatComposer: typeof FeedbackComposer;
|
|
2131
|
+
/** {@link FeedbackComposerProps}, for {@link ChatComposer}. */
|
|
2132
|
+
type ChatComposerProps = FeedbackComposerProps;
|
|
2133
|
+
/** {@link FeedbackComposerHandle}, for {@link ChatComposer}. */
|
|
2134
|
+
type ChatComposerHandle = FeedbackComposerHandle;
|
|
2135
|
+
/** {@link FeedbackComposerLabels}, for {@link ChatComposer} — still the `feedbackComposer`
|
|
2136
|
+
* namespace of the provider. */
|
|
2137
|
+
type ChatComposerLabels = FeedbackComposerLabels;
|
|
2138
|
+
|
|
2139
|
+
/**
|
|
2140
|
+
* The `confirmDialog` namespace of `<UiKitProvider labels>`: the two buttons' fallback
|
|
2141
|
+
* text. A call that knows what it is confirming says so per call (`confirmLabel:
|
|
2142
|
+
* "Delete budget"`), which is what the dialog is for — these are for the rest.
|
|
2143
|
+
*/
|
|
2144
|
+
interface ConfirmDialogLabels {
|
|
2145
|
+
confirm: string;
|
|
2146
|
+
cancel: string;
|
|
2147
|
+
/**
|
|
2148
|
+
* 0.18: label of the field a `requireTyped` confirm shows. A FUNCTION of the text to
|
|
2149
|
+
* type by default — where the address sits in the sentence moves with the language —
|
|
2150
|
+
* or a finished STRING. A call's own `typedLabel` wins over it.
|
|
2151
|
+
*
|
|
2152
|
+
* Required, like every key of a namespace: the shipped catalogues
|
|
2153
|
+
* (`@eifi1/ui-kit/i18n/<code>`) translate it, and an app's own full catalogue should
|
|
2154
|
+
* hear about the new string from the compiler rather than show it in English.
|
|
2155
|
+
*/
|
|
2156
|
+
typed: string | ((text: string) => string);
|
|
2157
|
+
}
|
|
2158
|
+
/** `satisfies` rather than a type annotation, so `.typed` stays known-callable for a
|
|
2159
|
+
* caller composing its own label from it. */
|
|
2160
|
+
declare const DEFAULT_CONFIRM_DIALOG_LABELS: {
|
|
2161
|
+
confirm: string;
|
|
2162
|
+
cancel: string;
|
|
2163
|
+
typed: (text: string) => string;
|
|
2164
|
+
};
|
|
2165
|
+
type ConfirmTone = "danger" | "warning" | "neutral";
|
|
2166
|
+
interface ConfirmOptions {
|
|
2167
|
+
/** The question, and the dialog's accessible name. */
|
|
2168
|
+
title: ReactNode;
|
|
2169
|
+
/** The smaller line under it — the consequence. Wired to `aria-describedby`. */
|
|
2170
|
+
body?: ReactNode;
|
|
2171
|
+
/** Default: `confirmDialog.confirm` from the provider, else "Confirm". */
|
|
2172
|
+
confirmLabel?: ReactNode;
|
|
2173
|
+
/** Default: `confirmDialog.cancel` from the provider, else "Cancel". */
|
|
2174
|
+
cancelLabel?: ReactNode;
|
|
2175
|
+
/**
|
|
2176
|
+
* `"danger"` for what cannot be undone (a delete): the confirm is the destructive
|
|
2177
|
+
* button and focus starts on CANCEL. `"warning"` and `"neutral"` (default) start on
|
|
2178
|
+
* the confirm. See {@link ConfirmProvider} for why the two differ.
|
|
2179
|
+
*/
|
|
2180
|
+
tone?: ConfirmTone;
|
|
2181
|
+
/**
|
|
2182
|
+
* 0.18: make the user TYPE this before confirm is enabled — the target account's
|
|
2183
|
+
* e-mail address, a budget's name. For the action whose risk is not "did you mean
|
|
2184
|
+
* it" but "is this the right row": an admin who deactivates somebody has already
|
|
2185
|
+
* proven who THEY are (they passed the admin gate); typing the address is what
|
|
2186
|
+
* proves they read which account they are on. Both keksdose (`TYPE_EMAIL`) and
|
|
2187
|
+
* Kurvenschmiede (`TypedConfirm`) built this beside `useConfirm` because it had no
|
|
2188
|
+
* field.
|
|
2189
|
+
*
|
|
2190
|
+
* The dialog then shows one text field under the body and focuses it (whatever the
|
|
2191
|
+
* tone: a reflexive Enter cannot confirm a field that does not match yet). Confirm
|
|
2192
|
+
* stays disabled until the text matches; Enter in the field confirms once it does.
|
|
2193
|
+
* The answer is still `true` / `false` — the text matched what you passed, so send
|
|
2194
|
+
* that to the server if it asks for the address too, not the user's spelling.
|
|
2195
|
+
*/
|
|
2196
|
+
requireTyped?: string;
|
|
2197
|
+
/** Label of that field. Default: `confirmDialog.typed` — `Type “a@b.c” to confirm`. */
|
|
2198
|
+
typedLabel?: string;
|
|
2199
|
+
/**
|
|
2200
|
+
* How the typed text is compared. Default `"caseless"`: surrounding spaces and case
|
|
2201
|
+
* ignored, the rule both apps applied to an address. `"trim"` keeps case, `"exact"`
|
|
2202
|
+
* keeps spaces too — for a phrase like "DELETE" whose contract is "exactly this".
|
|
2203
|
+
*/
|
|
2204
|
+
typedMatch?: TypedMatch;
|
|
2205
|
+
}
|
|
2206
|
+
type ConfirmFn = (options: ConfirmOptions) => Promise<boolean>;
|
|
2207
|
+
/**
|
|
2208
|
+
* `const confirm = useConfirm()` → `if (!(await confirm({ title }))) return`.
|
|
2209
|
+
*
|
|
2210
|
+
* The returned function is STABLE for the life of the provider, so it can sit in an
|
|
2211
|
+
* effect's or a `useCallback`'s dependency list without re-running it.
|
|
2212
|
+
*
|
|
2213
|
+
* Throws outside a {@link ConfirmProvider}, rather than falling back to
|
|
2214
|
+
* `window.confirm`: a silent fallback is exactly the native dialog the three apps are
|
|
2215
|
+
* migrating away from, and it would look like the migration had worked.
|
|
2216
|
+
*/
|
|
2217
|
+
declare function useConfirm(): ConfirmFn;
|
|
2218
|
+
interface ConfirmProviderProps {
|
|
2219
|
+
children: ReactNode;
|
|
2220
|
+
}
|
|
2221
|
+
/**
|
|
2222
|
+
* The host for {@link useConfirm}: ONE confirm dialog for the whole app, rendered on
|
|
2223
|
+
* {@link DialogFrame}, answering a promise.
|
|
2224
|
+
*
|
|
2225
|
+
* Asked for by all three apps at once — keksdose has 20+ `window.confirm` calls,
|
|
2226
|
+
* kastlan 7, lenkbank 1. The native dialog cannot be translated past its OK/Cancel
|
|
2227
|
+
* (those are the BROWSER's language, not the app's), cannot say which button is the
|
|
2228
|
+
* destructive one, and on an installed PWA it prints the origin over the question.
|
|
2229
|
+
* A promise is what lets each of those call sites change by one `await`:
|
|
2230
|
+
*
|
|
2231
|
+
* if (!window.confirm(t("budget.delete_confirm"))) return;
|
|
2232
|
+
* // becomes
|
|
2233
|
+
* if (!(await confirm({ title: t("budget.delete_confirm"), tone: "danger" }))) return;
|
|
2234
|
+
*
|
|
2235
|
+
* ## Its own provider, not part of `UiKitProvider`
|
|
2236
|
+
*
|
|
2237
|
+
* `UiKitProvider` renders nothing: it is strings and a locale, it is optional, and it
|
|
2238
|
+
* NESTS (an inner one re-labels one table). A dialog host inside it would mount a host
|
|
2239
|
+
* per nested provider, and a component under the inner one would open a second dialog
|
|
2240
|
+
* layer of its own. So the host is its own component, mounted once — inside the
|
|
2241
|
+
* `UiKitProvider` whose strings it should speak, which is also the order the labels
|
|
2242
|
+
* need.
|
|
2243
|
+
*
|
|
2244
|
+
* ## Focus
|
|
2245
|
+
*
|
|
2246
|
+
* On CANCEL for `tone: "danger"`, on CONFIRM otherwise. A confirm is often answered by
|
|
2247
|
+
* a reflexive Enter — the key that pressed the Delete button in the first place may
|
|
2248
|
+
* still be down — and for an action that cannot be undone that reflex must land on the
|
|
2249
|
+
* harmless answer; `DangerConfirm` makes the same call ("never to the destructive
|
|
2250
|
+
* button itself"). For everything else the confirm is the expected answer and Enter
|
|
2251
|
+
* accepting it is what `window.confirm` taught users, which the migrating call sites'
|
|
2252
|
+
* users already rely on. Focus returns to whatever opened it, through `Modal`'s trap.
|
|
2253
|
+
*
|
|
2254
|
+
* ## Escape, the backdrop, Back and Cancel all answer `false`
|
|
2255
|
+
*
|
|
2256
|
+
* Only the confirm button answers `true`. Anything that merely dismisses is a no.
|
|
2257
|
+
*
|
|
2258
|
+
* ## A second `confirm` while one is open QUEUES
|
|
2259
|
+
*
|
|
2260
|
+
* It is shown when the first is answered, and each call gets its own answer. The
|
|
2261
|
+
* alternative — answering the open one `false` to make room — would answer a question
|
|
2262
|
+
* the user never answered: a background prompt ("your session is about to expire")
|
|
2263
|
+
* would cancel the delete they were reading. `false` has to mean "the user said no".
|
|
2264
|
+
* A double-click cannot queue two of the same: the first click opens the modal
|
|
2265
|
+
* synchronously (a discrete event's update is flushed before the next one), so the
|
|
2266
|
+
* second lands on the open dialog rather than on the button — at worst on its
|
|
2267
|
+
* backdrop, which answers `false`, the safe way to be wrong.
|
|
2268
|
+
*
|
|
2269
|
+
* Unmounting the provider answers everything still pending `false`, so no caller's
|
|
2270
|
+
* `await` hangs forever.
|
|
2271
|
+
*
|
|
2272
|
+
* ## keksdose's synchronous call (transaction-swipe-plan.ts)
|
|
2273
|
+
*
|
|
2274
|
+
* `buildTxSwipeActions` is synchronous, but its `window.confirm` sits inside the
|
|
2275
|
+
* action THUNK (`confirmed(key, run)` returns `() => { if (confirm(…)) run() }`), and a
|
|
2276
|
+
* thunk may be async without its caller knowing. So the plan builder stays
|
|
2277
|
+
* synchronous; it takes the confirm as an argument and the thunk awaits it:
|
|
2278
|
+
*
|
|
2279
|
+
* // mobile-transaction-list.tsx
|
|
2280
|
+
* const confirm = useConfirm();
|
|
2281
|
+
* buildTxSwipeActions({ tx, …, confirm });
|
|
2282
|
+
*
|
|
2283
|
+
* // transaction-swipe-plan.ts
|
|
2284
|
+
* const confirmed = (messageKey: string, run: () => void) => () => {
|
|
2285
|
+
* void confirm({ title: t(messageKey), tone: "danger" }).then((ok) => ok && run());
|
|
2286
|
+
* };
|
|
2287
|
+
*
|
|
2288
|
+
* Its test then passes `confirm: vi.fn(async () => false)` instead of stubbing the
|
|
2289
|
+
* global, and asserts after an `await` (the mutation now runs a microtask later). The
|
|
2290
|
+
* row snaps back when the swipe commits, before the answer — which is right: the
|
|
2291
|
+
* dialog, not the half-swiped row, is where the question now is.
|
|
2292
|
+
*/
|
|
2293
|
+
declare function ConfirmProvider({ children }: ConfirmProviderProps): react.JSX.Element;
|
|
2294
|
+
|
|
1379
2295
|
/** The words a copy button says. The visible three are short on purpose (they
|
|
1380
2296
|
* replace the button's own text in the `label` variant); the two announcements
|
|
1381
2297
|
* are the sentences a screen reader hears, since the button's focus never moves. */
|
|
@@ -1445,8 +2361,17 @@ declare function CopyButton({ text, variant, label, buttonVariant, size, tone, s
|
|
|
1445
2361
|
interface FormActionsLabels {
|
|
1446
2362
|
save: string;
|
|
1447
2363
|
cancel: string;
|
|
2364
|
+
/**
|
|
2365
|
+
* The {@link FormActionsProps.submitShortcut} hint beside Save's text, when
|
|
2366
|
+
* {@link FormActionsProps.submitShortcutHint} shows it. `apple` is true on a Mac,
|
|
2367
|
+
* iPhone or iPad, where the key is Cmd: "⌘ Enter" there, "Ctrl+Enter" elsewhere
|
|
2368
|
+
* (a German keyboard says "Strg").
|
|
2369
|
+
*/
|
|
2370
|
+
submitShortcut: (apple: boolean) => string;
|
|
1448
2371
|
}
|
|
1449
2372
|
declare const DEFAULT_FORM_ACTIONS_LABELS: FormActionsLabels;
|
|
2373
|
+
/** See {@link FormActionsProps.submitShortcut}. */
|
|
2374
|
+
type FormActionsSubmitShortcut = "mod-enter";
|
|
1450
2375
|
type FormActionsAlign = "start" | "center" | "end" | "between";
|
|
1451
2376
|
/**
|
|
1452
2377
|
* Where the row sits:
|
|
@@ -1550,6 +2475,27 @@ interface FormActionsProps extends Omit<ComponentPropsWithoutRef<"div">, "childr
|
|
|
1550
2475
|
/** The save button's variant. Default `brand`; `danger` for a save that destroys
|
|
1551
2476
|
* (kastlan's `destructive` flag on its own FormActions). */
|
|
1552
2477
|
submitVariant?: ButtonVariant;
|
|
2478
|
+
/**
|
|
2479
|
+
* The Cancel button's variant. Default `secondary` (the outlined button, as before).
|
|
2480
|
+
* `ghost` for a row where Cancel should step back further than an outline — keksdose
|
|
2481
|
+
* G3: a quiet inline row (a confirm under a table row, a card's own small editor)
|
|
2482
|
+
* whose Cancel was a ghost button before it moved onto FormActions, which drew every
|
|
2483
|
+
* Cancel outlined.
|
|
2484
|
+
*/
|
|
2485
|
+
cancelVariant?: ButtonVariant;
|
|
2486
|
+
/**
|
|
2487
|
+
* The size of every button the row draws itself — Save, Cancel and the
|
|
2488
|
+
* `{ label, onClick }` form of {@link destructive}: Button's `size`. Default `md`.
|
|
2489
|
+
* `sm` (12px text, `px-2 py-1`) for a dense row: a confirm inside a table's expansion
|
|
2490
|
+
* row, a toolbar card. keksdose G3: two such rows had small hand-built buttons and lost
|
|
2491
|
+
* them on adopting FormActions, which had no size. At `sm` the spinner and
|
|
2492
|
+
* {@link submitIcon} shrink with the text.
|
|
2493
|
+
*
|
|
2494
|
+
* Your own elements (`children`, an element passed as `destructive`, `start`) are
|
|
2495
|
+
* yours to size — pass them `size="sm"` too. A `size` in {@link submitProps} still
|
|
2496
|
+
* wins for Save, as it always has.
|
|
2497
|
+
*/
|
|
2498
|
+
size?: ButtonSize;
|
|
1553
2499
|
/**
|
|
1554
2500
|
* A destructive action at the START of the row, apart from Save and Cancel — the
|
|
1555
2501
|
* "Delete" of an edit dialog. Pass `{ label, onClick }` for the kit's quiet danger
|
|
@@ -1606,6 +2552,39 @@ interface FormActionsProps extends Omit<ComponentPropsWithoutRef<"div">, "childr
|
|
|
1606
2552
|
/** The `id` of the `<form>` the save button submits, when the row is rendered
|
|
1607
2553
|
* outside it (a dialog's footer slot). */
|
|
1608
2554
|
form?: string;
|
|
2555
|
+
/**
|
|
2556
|
+
* A keyboard shortcut that presses Save from anywhere in the form. `"mod-enter"`:
|
|
2557
|
+
* Ctrl+Enter, or Cmd+Enter on a Mac — both are accepted everywhere, as keksdose's
|
|
2558
|
+
* editors always have. keksdose K14 (inputs audit 2026-10-02, S5): its transaction
|
|
2559
|
+
* editor, category editor and create card each wrote this as an `onKeyDown` on a
|
|
2560
|
+
* container, re-stating `!pending && !saveDisabled && !lock.locked` every time, and
|
|
2561
|
+
* the one that forgot the lock let the demo's refused save through from the keyboard.
|
|
2562
|
+
*
|
|
2563
|
+
* What it does is what pressing Save does — the same button is clicked, so a form
|
|
2564
|
+
* submits with its validation and its submitter, and `onSubmit` is called in the
|
|
2565
|
+
* `type="button"` mode — and it does NOTHING while Save could not be pressed:
|
|
2566
|
+
* `pending`, `submitDisabled`, or a `commit` under a locked {@link WriteLockProvider}.
|
|
2567
|
+
*
|
|
2568
|
+
* Scoped to the form Save submits (the `form` prop's, else the enclosing `<form>`):
|
|
2569
|
+
* the chord counts only when the focus is inside it, so two editors on one page each
|
|
2570
|
+
* answer for their own fields. Without a form (an `onSubmit` row in a plain container)
|
|
2571
|
+
* the scope is the nearest `role="dialog"`, else the row's parent element — the
|
|
2572
|
+
* container the row ends.
|
|
2573
|
+
*
|
|
2574
|
+
* Listened for on the document, so it runs AFTER every React handler: a field that
|
|
2575
|
+
* takes Ctrl+Enter for itself calls `preventDefault()` or `stopPropagation()` and
|
|
2576
|
+
* the row stays out of it (keksdose live #202 — the create card's Ctrl+Shift+Enter
|
|
2577
|
+
* must create ONE row; the chord here is exactly Ctrl/Cmd+Enter, never with Shift or
|
|
2578
|
+
* Alt). Not during IME composition, and not on a held key's repeats.
|
|
2579
|
+
*
|
|
2580
|
+
* The save button announces it with `aria-keyshortcuts`; {@link submitShortcutHint}
|
|
2581
|
+
* also shows it.
|
|
2582
|
+
*/
|
|
2583
|
+
submitShortcut?: FormActionsSubmitShortcut;
|
|
2584
|
+
/** Show the {@link submitShortcut} beside Save's text ("Ctrl+Enter", "⌘ Enter"; the
|
|
2585
|
+
* `form.submitShortcut` label), dimmed. Hidden on a touch-only device, which has no
|
|
2586
|
+
* keyboard to press it on. Default `false`. */
|
|
2587
|
+
submitShortcutHint?: boolean;
|
|
1609
2588
|
/** Extra actions, placed before Cancel. */
|
|
1610
2589
|
children?: ReactNode;
|
|
1611
2590
|
}
|
|
@@ -1624,7 +2603,7 @@ interface FormActionsProps extends Omit<ComponentPropsWithoutRef<"div">, "childr
|
|
|
1624
2603
|
* The spinner is the kit's {@link Spinner}, drawn inside the button with `label={null}`
|
|
1625
2604
|
* so the button's name stays its text; `aria-busy` is what says it is working.
|
|
1626
2605
|
*/
|
|
1627
|
-
declare function FormActions({ onCancel, onSubmit, submitLabel, cancelLabel, pendingLabel, submitIcon: SubmitIcon, submitProps, pending, submitDisabled, submitDisabledReason, commit, submitVariant, destructive, start: startSlot, align, placement: placementProp, stickyWithin, bleed, form, children, className, style, ...rest }: FormActionsProps): react.JSX.Element;
|
|
2606
|
+
declare function FormActions({ onCancel, onSubmit, submitLabel, cancelLabel, pendingLabel, submitIcon: SubmitIcon, submitProps, pending, submitDisabled, submitDisabledReason, commit, submitVariant, cancelVariant, size, destructive, start: startSlot, align, placement: placementProp, stickyWithin, bleed, form, submitShortcut, submitShortcutHint, children, className, style, ...rest }: FormActionsProps): react.JSX.Element;
|
|
1628
2607
|
|
|
1629
2608
|
/**
|
|
1630
2609
|
* Who holds one record, and the owner's every way of changing that — Kurvenschmiede's
|
|
@@ -1806,6 +2785,147 @@ interface ShareDialogProps extends SharePanelProps, Pick<DialogFrameProps, "open
|
|
|
1806
2785
|
*/
|
|
1807
2786
|
declare function ShareDialog({ open, onClose, size, className, title, description, ...panel }: ShareDialogProps): react.JSX.Element;
|
|
1808
2787
|
|
|
2788
|
+
/** The messages {@link IbanInput} shows under itself, one per {@link IbanProblem}. */
|
|
2789
|
+
interface IbanInputLabels {
|
|
2790
|
+
/** The value does not start with a two-letter country code and two check digits. */
|
|
2791
|
+
format: string;
|
|
2792
|
+
/** The first two letters are no country in the IBAN registry. `code` is those two
|
|
2793
|
+
* letters, as typed (upper case). */
|
|
2794
|
+
country: (code: string) => string;
|
|
2795
|
+
/** The wrong length for the country: `actual` characters typed, `expected` for that
|
|
2796
|
+
* country (spaces not counted in either). */
|
|
2797
|
+
length: (actual: number, expected: number) => string;
|
|
2798
|
+
/** The mod-97 check digits do not match — a mistyped or swapped character. */
|
|
2799
|
+
checksum: string;
|
|
2800
|
+
/** `kind="qr"`: a valid IBAN, but not a QR-IBAN. */
|
|
2801
|
+
qrRequired: string;
|
|
2802
|
+
/** `kind="plain"`: a QR-IBAN, which cannot receive an ordinary transfer. */
|
|
2803
|
+
qrNotAllowed: string;
|
|
2804
|
+
}
|
|
2805
|
+
declare const DEFAULT_IBAN_INPUT_LABELS: IbanInputLabels;
|
|
2806
|
+
interface IbanInputProps extends Omit<InputProps, "type" | "value" | "defaultValue"> {
|
|
2807
|
+
/** The IBAN, compact or not — it is shown in groups of four either way. `""` is
|
|
2808
|
+
* "no IBAN". */
|
|
2809
|
+
value: string;
|
|
2810
|
+
/** The compact, upper-case IBAN (the electronic format, what to store) on every
|
|
2811
|
+
* change — valid or not: a half-typed IBAN is still the field's value. Plain
|
|
2812
|
+
* `onChange` still fires alongside it with the raw event, whose text is the GROUPED
|
|
2813
|
+
* one, so bind this rather than `onChange` to a form. */
|
|
2814
|
+
onValueChange?: (value: string) => void;
|
|
2815
|
+
/** Which IBANs the field accepts. Default `"any"`. `"qr"` / `"plain"`: see
|
|
2816
|
+
* {@link IbanKind} — and why the difference matters, {@link isQrIban}. */
|
|
2817
|
+
kind?: IbanKind;
|
|
2818
|
+
/** The messages, per field. See {@link IbanInputLabels}. */
|
|
2819
|
+
labels?: Partial<IbanInputLabels>;
|
|
2820
|
+
/** The caller's own message, shown INSTEAD of the built-in one while it is set (a
|
|
2821
|
+
* server's "this account is already on file"). `null`, `false` and `""` are no
|
|
2822
|
+
* message, so `touched && errors.iban` can be passed as it is. */
|
|
2823
|
+
error?: ReactNode;
|
|
2824
|
+
}
|
|
2825
|
+
/**
|
|
2826
|
+
* An IBAN field (kastlan, keksdose): typed in any shape, shown in groups of four,
|
|
2827
|
+
* reported compact.
|
|
2828
|
+
*
|
|
2829
|
+
* Both apps had a text field and a regex. What that left out is everything between
|
|
2830
|
+
* the keyboard and the stored value: a pasted "ch09 0000-0000…" stayed lower case
|
|
2831
|
+
* with its hyphens, the grouping that makes 21 characters checkable by eye was
|
|
2832
|
+
* missing, and a wrong IBAN was found out by the bank. Here:
|
|
2833
|
+
*
|
|
2834
|
+
* - **Grouped as you type.** The field shows the paper format ({@link formatIban});
|
|
2835
|
+
* spaces, hyphens and lower case in what is typed or pasted are folded away, and
|
|
2836
|
+
* the caret stays between the same two characters while the groups move around it.
|
|
2837
|
+
* - **Compact out.** `onValueChange` gets the electronic format — upper case, no
|
|
2838
|
+
* spaces — which is the one to store and to compare.
|
|
2839
|
+
* - **Checked, never blocked.** A wrong country, length or checksum shows a message
|
|
2840
|
+
* under the field, through the kit's `error` (so it is the field's
|
|
2841
|
+
* `aria-describedby` and paints it), but every keystroke still lands: a field that
|
|
2842
|
+
* refuses characters cannot be corrected one character at a time. While the field
|
|
2843
|
+
* has focus only what more typing cannot fix is shown; the rest waits for the full
|
|
2844
|
+
* length or for blur. Whether the field is REQUIRED stays the form's rule — an empty
|
|
2845
|
+
* field says nothing.
|
|
2846
|
+
* - **QR-IBAN or not** (kastlan): `kind="qr"` refuses a regular IBAN and
|
|
2847
|
+
* `kind="plain"` refuses a QR-IBAN — a QR-bill can only be paid to a QR-IBAN, and a
|
|
2848
|
+
* QR-IBAN can receive nothing else. See {@link isQrIban}.
|
|
2849
|
+
*
|
|
2850
|
+
* It is {@link Input} underneath, so `label`, `hint`, `error`, `invalid` and the rest
|
|
2851
|
+
* are Input's own and the field reads like every other. A form that must not submit
|
|
2852
|
+
* an invalid IBAN checks {@link isValidIban} / {@link ibanProblem} itself — the field
|
|
2853
|
+
* shows the problem but does not own the submit.
|
|
2854
|
+
*/
|
|
2855
|
+
declare const IbanInput: react.ForwardRefExoticComponent<IbanInputProps & react.RefAttributes<HTMLInputElement>>;
|
|
2856
|
+
|
|
2857
|
+
/** The words {@link PhoneInput} renders on its own behalf. */
|
|
2858
|
+
interface PhoneInputLabels {
|
|
2859
|
+
/** The country-code select's accessible name. */
|
|
2860
|
+
countryCode: string;
|
|
2861
|
+
/** The select's last option: a number from a country not listed, typed with its
|
|
2862
|
+
* own "+". */
|
|
2863
|
+
other: string;
|
|
2864
|
+
}
|
|
2865
|
+
declare const DEFAULT_PHONE_INPUT_LABELS: PhoneInputLabels;
|
|
2866
|
+
interface PhoneInputProps extends Omit<InputProps, "type" | "value" | "defaultValue"> {
|
|
2867
|
+
/** The number: E.164 ("+41210000001") for one the field could read, or free text —
|
|
2868
|
+
* a value saved before the field existed is shown exactly as it is. `""` is no
|
|
2869
|
+
* number. */
|
|
2870
|
+
value: string;
|
|
2871
|
+
/** On every change: E.164 when the typed text reads as a number of the selected
|
|
2872
|
+
* country (or carries its own "+"), otherwise the typed text UNCHANGED. Nothing is
|
|
2873
|
+
* refused — see {@link PhoneInput}. Plain `onChange` still fires with the raw event;
|
|
2874
|
+
* bind this one to a form. */
|
|
2875
|
+
onValueChange?: (value: string) => void;
|
|
2876
|
+
/** The country a number typed without "+" belongs to, until the value says
|
|
2877
|
+
* otherwise. Default `"CH"`. */
|
|
2878
|
+
defaultCountry?: PhoneCountry;
|
|
2879
|
+
/** The countries the select offers, in order; "Other" always follows. Default
|
|
2880
|
+
* {@link PHONE_COUNTRIES} (CH, LI, DE, AT, FR, IT). A stored number from a country
|
|
2881
|
+
* left out still shows under its own code. */
|
|
2882
|
+
countries?: readonly PhoneCountryCode[];
|
|
2883
|
+
/** See {@link PhoneInputLabels}. */
|
|
2884
|
+
labels?: Partial<PhoneInputLabels>;
|
|
2885
|
+
/** Classes for the whole field — the select, the input and the lines under them.
|
|
2886
|
+
* `inputClassName` reaches the `<input>`. */
|
|
2887
|
+
className?: string;
|
|
2888
|
+
}
|
|
2889
|
+
/**
|
|
2890
|
+
* A phone number field (kastlan): a country-code select and the number, stored as
|
|
2891
|
+
* E.164 and shown grouped.
|
|
2892
|
+
*
|
|
2893
|
+
* kastlan's contacts kept whatever was typed — "079 …", "+41 (0)79 …", "0041 79 …" —
|
|
2894
|
+
* which nobody could dial from the app or match against the next import. This field
|
|
2895
|
+
* turns all of those into one stored form, "+41210000001", without taking anything
|
|
2896
|
+
* away from the person typing:
|
|
2897
|
+
*
|
|
2898
|
+
* - **A country to type against.** The select (default CH, then LI, DE, AT, FR, IT
|
|
2899
|
+
* and "Other") says which country a number without "+" belongs to; the national
|
|
2900
|
+
* trunk 0 may be typed or left out. Typing a "+" or "00" overrides it, and the
|
|
2901
|
+
* select follows the number ("+49 …" switches it to DE). Changing the select moves
|
|
2902
|
+
* the national number to the new country code.
|
|
2903
|
+
* - **E.164 when it reads, the text when it does not.** A number the rules read is
|
|
2904
|
+
* emitted as E.164; anything else ("ask reception", an extension) is emitted exactly
|
|
2905
|
+
* as typed. Never refused, never an error of its own: a contact's number is often
|
|
2906
|
+
* known only roughly, and a field that will not save "079 … (mornings)" makes
|
|
2907
|
+
* people type it into the notes instead. An app that needs a dialable number
|
|
2908
|
+
* checks {@link isE164} on submit.
|
|
2909
|
+
* - **Existing values untouched.** A free-text value from before is shown exactly as
|
|
2910
|
+
* it is, and normalised only when someone edits it — the field never rewrites a
|
|
2911
|
+
* record just by being opened.
|
|
2912
|
+
* - **Grouped when settled.** While typing the field shows what was typed; on blur a
|
|
2913
|
+
* number it read is regrouped by its country ("21 000 00 01").
|
|
2914
|
+
*
|
|
2915
|
+
* **The limitation** — there is no libphonenumber behind this (≈150 kB of metadata in
|
|
2916
|
+
* every bundle): the six countries have light rules (the trunk 0, a plausible length)
|
|
2917
|
+
* and every other country is any "+" with 8–15 digits. A well-formed number that does
|
|
2918
|
+
* not exist passes, and German and Austrian landlines, whose area codes vary in length,
|
|
2919
|
+
* are grouped only where the split is known (mobile prefixes, the largest cities) and
|
|
2920
|
+
* otherwise shown as one block. See `lib/phone.ts`.
|
|
2921
|
+
*
|
|
2922
|
+
* `label`, `hint`, `error` and `invalid` read as on {@link Input}: the label floats in
|
|
2923
|
+
* the number's box, and a text hint and the error go under the whole row, attached to
|
|
2924
|
+
* the number with `aria-describedby`. The select is named by `labels.countryCode`, and
|
|
2925
|
+
* the pair is a group named by a string `label`.
|
|
2926
|
+
*/
|
|
2927
|
+
declare const PhoneInput: react.ForwardRefExoticComponent<PhoneInputProps & react.RefAttributes<HTMLInputElement>>;
|
|
2928
|
+
|
|
1809
2929
|
/**
|
|
1810
2930
|
* EVERY string the kit renders, as one typed tree — and an optional provider that
|
|
1811
2931
|
* hands it to every component at once.
|
|
@@ -2032,6 +3152,21 @@ interface UiKitLabels {
|
|
|
2032
3152
|
translationReview: TranslationReviewLabels;
|
|
2033
3153
|
/** 0.19.0: `LegalLinks`' navigation name — the legal pages' shell, for every app. */
|
|
2034
3154
|
legal: LegalLabels;
|
|
3155
|
+
/** 0.22.0: the screen-reader words of `Input` / `Textarea`'s `showCount` counter. */
|
|
3156
|
+
characterCount: CharacterCountLabels;
|
|
3157
|
+
/** 0.22.0: `CountrySelect`. Its list's "no results" and counts are `combobox`'s. */
|
|
3158
|
+
countrySelect: CountrySelectLabels;
|
|
3159
|
+
/** 0.22.0: `InlineEditField` — keksdose K9. */
|
|
3160
|
+
inlineEdit: InlineEditLabels;
|
|
3161
|
+
/** 0.22.0: `IbanInput`'s messages, one per problem. */
|
|
3162
|
+
ibanInput: IbanInputLabels;
|
|
3163
|
+
/** 0.22.0: `PhoneInput`'s country-code select. */
|
|
3164
|
+
phoneInput: PhoneInputLabels;
|
|
3165
|
+
/** 0.22.0: `SignChip` — the outflow / inflow toggle beside an amount. */
|
|
3166
|
+
signChip: SignChipLabels;
|
|
3167
|
+
/** 0.23.0: `ColumnMapper` / `ColumnRoleTable` — a pasted or dropped table, a role per
|
|
3168
|
+
* column. */
|
|
3169
|
+
columnMapper: ColumnMapperLabels;
|
|
2035
3170
|
}
|
|
2036
3171
|
/**
|
|
2037
3172
|
* A label override, as deep as the labels go: an object of labels (a namespace, or a
|
|
@@ -2065,6 +3200,35 @@ declare const DEFAULT_FILE_LABELS: FileLabels;
|
|
|
2065
3200
|
/** "12 kB", "3.4 MB" — `Intl`'s unit formatting, so the digits, the decimal mark and
|
|
2066
3201
|
* the unit's spelling all follow `locale`. */
|
|
2067
3202
|
declare function formatFileSize(bytes: number, locale?: string): string;
|
|
3203
|
+
/** What a {@link KitDateFormatter} is told about the date it is formatting. */
|
|
3204
|
+
interface KitDateFormatContext {
|
|
3205
|
+
/**
|
|
3206
|
+
* How much of a date the string is: `"day"` — the `iso` is `"YYYY-MM-DD"`; `"month"` —
|
|
3207
|
+
* `"YYYY-MM"` (a `MonthPicker`); `"year"` — `"YYYY"` (`MonthPicker mode="year"`).
|
|
3208
|
+
*/
|
|
3209
|
+
unit: "day" | "month" | "year";
|
|
3210
|
+
/** Which kit surface asks: the trigger of a `DatePicker`, of a `DateRangePicker`
|
|
3211
|
+
* (called once per end), of a `MonthPicker`, or a `DateMark`. */
|
|
3212
|
+
source: "datePicker" | "dateRangePicker" | "monthPicker" | "dateMark";
|
|
3213
|
+
/** The locale the kit would have formatted in — the component's `locale` prop, else
|
|
3214
|
+
* the provider's — or `undefined` for the runtime's. */
|
|
3215
|
+
locale: string | undefined;
|
|
3216
|
+
/**
|
|
3217
|
+
* The kit's suggestion: whether this date stands alone where the day of the week
|
|
3218
|
+
* helps — `true` for a `DatePicker`'s trigger and a `DateMark`, `false` for the two
|
|
3219
|
+
* ends of a range (twice the width, in a sentence-like "from – to") and for a month
|
|
3220
|
+
* or a year. keksdose's rule, which this follows: *"A date in a COLUMN carries the
|
|
3221
|
+
* weekday. A date in a SENTENCE does not."* (date-cell.tsx, dev#546). A formatter
|
|
3222
|
+
* is free to ignore it.
|
|
3223
|
+
*/
|
|
3224
|
+
weekday: boolean;
|
|
3225
|
+
}
|
|
3226
|
+
/**
|
|
3227
|
+
* The app's ONE answer to "what does a date look like here" — keksdose K12. Returns the
|
|
3228
|
+
* text for an ISO date (see {@link KitDateFormatContext.unit} for the three shapes).
|
|
3229
|
+
* Return `""` to fall back to the kit's own formatting for that date.
|
|
3230
|
+
*/
|
|
3231
|
+
type KitDateFormatter = (iso: string, context: KitDateFormatContext) => string;
|
|
2068
3232
|
/** Where a chart shows the values under the pointer — see `SeriesChartTooltip.placement`. */
|
|
2069
3233
|
type ChartTooltipPlacement = "cursor" | "above" | "below" | "auto";
|
|
2070
3234
|
/**
|
|
@@ -2127,6 +3291,25 @@ interface UiKitProviderProps {
|
|
|
2127
3291
|
* pointer, as before.
|
|
2128
3292
|
*/
|
|
2129
3293
|
chartTooltipPlacement?: ChartTooltipPlacement;
|
|
3294
|
+
/**
|
|
3295
|
+
* How every kit date below is written, when the component is not told otherwise —
|
|
3296
|
+
* keksdose K12. keksdose has a date-format preference (Settings ▸ date format, feedback
|
|
3297
|
+
* #180) that is not the UI language, and a weekday in the UI language beside digits
|
|
3298
|
+
* in the preference's order (live #246, dev#546): two locales in one string, which
|
|
3299
|
+
* no `locale` + `Intl` options can say. Its `DateField` wraps every `DatePicker` to
|
|
3300
|
+
* pass `formatValue`, and its report range field formats both ends by hand; with this
|
|
3301
|
+
* set once on the provider, those wrappers thin to nothing.
|
|
3302
|
+
*
|
|
3303
|
+
* Used for the trigger text of `DatePicker`, `DateRangePicker` and `MonthPicker`
|
|
3304
|
+
* (month and year mode), and for `DateMark display="date"`. A component's own
|
|
3305
|
+
* `formatValue` or `formatOptions` (`dateStyle` on a DateMark) wins: prop >
|
|
3306
|
+
* provider > the kit's `Intl` default, the order every kit setting resolves in. Left
|
|
3307
|
+
* out (or returning `""`), everything formats exactly as before.
|
|
3308
|
+
*
|
|
3309
|
+
* Keep it stable (`useCallback`, or a module function): it is in the provider's
|
|
3310
|
+
* context value, so a new function every render re-renders every consumer.
|
|
3311
|
+
*/
|
|
3312
|
+
formatDate?: KitDateFormatter;
|
|
2130
3313
|
children: ReactNode;
|
|
2131
3314
|
}
|
|
2132
3315
|
/**
|
|
@@ -2137,7 +3320,7 @@ interface UiKitProviderProps {
|
|
|
2137
3320
|
* it names, so a page can re-label one table's `dataTable.table` without restating
|
|
2138
3321
|
* the language.
|
|
2139
3322
|
*/
|
|
2140
|
-
declare function UiKitProvider({ labels, locale, weekStartsOn, linkComponent, chartTooltipPlacement, children, }: UiKitProviderProps): react.JSX.Element;
|
|
3323
|
+
declare function UiKitProvider({ labels, locale, weekStartsOn, linkComponent, chartTooltipPlacement, formatDate, children, }: UiKitProviderProps): react.JSX.Element;
|
|
2141
3324
|
/** What the nearest provider says about one namespace — `undefined` outside one.
|
|
2142
3325
|
* For a component whose own resolver does more than a merge (the data table
|
|
2143
3326
|
* derives `columnsCount` from `columns`): feed `{ ...overrides, ...props }` to it. */
|
|
@@ -2159,6 +3342,9 @@ declare function useKitLink(): KitLinkComponent | undefined;
|
|
|
2159
3342
|
declare function useKitWeekStart(): WeekDay | undefined;
|
|
2160
3343
|
/** The provider's `chartTooltipPlacement`, or `undefined` — a chart's own prop wins. */
|
|
2161
3344
|
declare function useKitChartTooltipPlacement(): ChartTooltipPlacement | undefined;
|
|
3345
|
+
/** The nearest provider's `formatDate`, or `undefined` — a component's own
|
|
3346
|
+
* `formatValue` / `formatOptions` wins over it. See {@link KitDateFormatter}. */
|
|
3347
|
+
declare function useKitDateFormatter(): KitDateFormatter | undefined;
|
|
2162
3348
|
/** {@link DEFAULT_FILE_LABELS}, but formatting in the provider's locale. */
|
|
2163
3349
|
declare function useKitFileLabels(prop?: Partial<FileLabels>): FileLabels;
|
|
2164
3350
|
/**
|
|
@@ -2175,4 +3361,4 @@ declare function useKitFileLabels(prop?: Partial<FileLabels>): FileLabels;
|
|
|
2175
3361
|
*/
|
|
2176
3362
|
declare function missingKitLabels(labels: UiKitLabelOverrides | undefined, reference: UiKitLabels): string[];
|
|
2177
3363
|
|
|
2178
|
-
export {
|
|
3364
|
+
export { DEFAULT_COPY_BUTTON_LABELS as $, type AppShellLabels as A, Button as B, type CalculatorLabels as C, type ChatComposerHandle as D, type ChatComposerLabels as E, type ChatComposerProps as F, type ComboboxLabels as G, type CommonLabels as H, type ConfirmDialogLabels as I, type ConfirmFn as J, type ConfirmOptions as K, ConfirmProvider as L, type ConfirmProviderProps as M, type ConfirmTone as N, CopyButton as O, type CopyButtonLabels as P, type CopyButtonProps as Q, type CurrencyLabels as R, CurrentPasswordInput as S, type CurrentPasswordInputLabels as T, type CurrentPasswordInputProps as U, DEFAULT_APP_SHELL_LABELS as V, DEFAULT_CALCULATOR_LABELS as W, DEFAULT_CHARACTER_COUNT_LABELS as X, DEFAULT_COMBOBOX_LABELS as Y, DEFAULT_COMMON_LABELS as Z, DEFAULT_CONFIRM_DIALOG_LABELS as _, type ButtonClassesOptions as a, type FormActionsProps as a$, DEFAULT_CURRENCY_LABELS as a0, DEFAULT_DANGER_CONFIRM_LABELS as a1, DEFAULT_DATE_PICKER_LABELS as a2, DEFAULT_FEEDBACK_COMPOSER_LABELS as a3, DEFAULT_FEEDBACK_THREAD_LABELS as a4, DEFAULT_FILE_LABELS as a5, DEFAULT_FILE_PICKER_LABELS as a6, DEFAULT_FORM_ACTIONS_LABELS as a7, DEFAULT_IBAN_INPUT_LABELS as a8, DEFAULT_MULTI_SELECT_LABELS as a9, type FeedbackComposerLabels as aA, type FeedbackComposerProps as aB, FeedbackThread as aC, type FeedbackThreadAttachment as aD, type FeedbackThreadEvent as aE, type FeedbackThreadItem as aF, type FeedbackThreadLabels as aG, type FeedbackThreadMessage as aH, type FeedbackThreadProps as aI, FieldChevron as aJ, type FieldChevronProps as aK, FieldHint as aL, type FieldHintProps as aM, FileButton as aN, type FileButtonProps as aO, type FileLabels as aP, type FilePickerLabels as aQ, type FileRejection as aR, type FileRejectionReason as aS, type FileScreenOptions as aT, FloatingField as aU, type FloatingFieldProps as aV, FormActions as aW, type FormActionsAlign as aX, type FormActionsDestructive as aY, type FormActionsLabels as aZ, type FormActionsPlacement as a_, DEFAULT_PASSWORD_REVEAL_LABELS as aa, DEFAULT_PHONE_INPUT_LABELS as ab, DEFAULT_PICKER_SHEET_LABELS as ac, DEFAULT_SHARE_CARD_LABELS as ad, DEFAULT_SWIPEABLE_ROW_LABELS as ae, DEFAULT_TABS_LABELS as af, DEFAULT_TOP_BAR_LABELS as ag, DangerConfirm as ah, type DangerConfirmLabels as ai, type DangerConfirmProps as aj, type DangerConfirmValues as ak, type DangerConsequence as al, type DatePickerLabels as am, EmptyState as an, type EmptyStateProps as ao, FIELD_BASE as ap, FIELD_DISPLAY as aq, FIELD_FLOATING_PAD as ar, FIELD_INVALID as as, FIELD_TRIGGER as at, FIELD_WRITABLE_LOOK as au, FLOATING_INPUT_CLASS as av, FLOATING_LABEL_CLASS as aw, FeedbackComposer as ax, type FeedbackComposerAttachment as ay, type FeedbackComposerHandle as az, type ButtonLinkProps as b, type UseFilePickerOptions as b$, type FormActionsStickyWithin as b0, type FormActionsSubmitProps as b1, type FormActionsSubmitShortcut as b2, IbanInput as b3, type IbanInputLabels as b4, type IbanInputProps as b5, IconButton as b6, type IconButtonGlyphSize as b7, type IconButtonLinkProps as b8, type IconButtonProps as b9, type ShareCardLabels as bA, type ShareCardProps as bB, ShareDialog as bC, type ShareDialogProps as bD, type ShareGrantee as bE, SharePanel as bF, type SharePanelProps as bG, type SharePendingGrant as bH, type ShareRole as bI, Spinner as bJ, type SpinnerProps as bK, type SwipeableRowLabels as bL, type TabItem as bM, Tabs as bN, type TabsLabels as bO, type TabsProps as bP, Textarea as bQ, type TextareaProps as bR, type TopBarLabels as bS, TypedConfirmField as bT, type TypedConfirmFieldLabels as bU, type TypedConfirmFieldProps as bV, type TypedMatch as bW, type UiKitLabelOverrides as bX, type UiKitLabels as bY, UiKitProvider as bZ, type UiKitProviderProps as b_, type IconButtonSize as ba, type IconButtonTone as bb, type IconButtonToneColor as bc, type IconButtonVariant as bd, Input as be, type InputProps as bf, type KitDateFormatContext as bg, type KitDateFormatter as bh, type KitLinkComponent as bi, type KitLinkProps as bj, Label as bk, type LabelOverride as bl, type LabelProps as bm, type MultiSelectLabels as bn, PHONE_QUERY as bo, type PasswordRevealLabels as bp, PhoneInput as bq, type PhoneInputLabels as br, type PhoneInputProps as bs, type PickerSheetLabels as bt, type ResponsiveFormActionsPlacement as bu, Select as bv, type SelectProps as bw, type ShareAddRequest as bx, type ShareCandidate as by, ShareCard as bz, type ButtonProps as c, type UseFilePickerReturn as c0, buttonClasses as c1, formatFileSize as c2, matchesAccept as c3, missingKitLabels as c4, resolvePasswordRevealLabels as c5, typedMatches as c6, useConfirm as c7, useFilePicker as c8, useKitChartTooltipPlacement as c9, useKitDateFormatter as ca, useKitFileLabels as cb, useKitLabelOverrides as cc, useKitLabels as cd, useKitLink as ce, useKitLocale as cf, useKitWeekStart as cg, type FilePickHandler as ch, usePromisePending as ci, formatAccept as cj, judgePick as ck, screenFiles as cl, summariseRejections as cm, type ButtonSize as d, type ButtonTone as e, type ButtonVariant as f, Card as g, CardAction as h, type CardActionProps as i, CardContent as j, type CardContentProps as k, type CardDensity as l, CardDescription as m, type CardDescriptionProps as n, CardFooter as o, type CardFooterProps as p, CardHeader as q, type CardHeaderProps as r, type CardProps as s, CardTitle as t, type CardTitleLevel as u, type CardTitleProps as v, type CardTone as w, type CharacterCountLabels as x, type ChartTooltipPlacement as y, ChatComposer as z };
|