@eifi1/ui-kit 0.49.0 → 0.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/README.md +11 -7
  2. package/dist/admin/user-roster.d.ts +16 -10
  3. package/dist/admin/user-roster.js +7 -3
  4. package/dist/admin/user-roster.js.map +1 -1
  5. package/dist/auth/verify-email.d.ts +9 -1
  6. package/dist/auth/verify-email.js +3 -1
  7. package/dist/auth/verify-email.js.map +1 -1
  8. package/dist/components/amount-input.d.ts +2 -1
  9. package/dist/components/amount-input.js +3 -2
  10. package/dist/components/amount-input.js.map +1 -1
  11. package/dist/components/autocomplete.js +1 -0
  12. package/dist/components/autocomplete.js.map +1 -1
  13. package/dist/components/combobox-core.js +1 -0
  14. package/dist/components/combobox-core.js.map +1 -1
  15. package/dist/components/combobox-suggestions.js +1 -0
  16. package/dist/components/combobox-suggestions.js.map +1 -1
  17. package/dist/components/currency-select.d.ts +28 -2
  18. package/dist/components/currency-select.js +56 -10
  19. package/dist/components/currency-select.js.map +1 -1
  20. package/dist/components/data-table-mobile.d.ts +11 -2
  21. package/dist/components/data-table-mobile.js +62 -8
  22. package/dist/components/data-table-mobile.js.map +1 -1
  23. package/dist/components/data-table-row.d.ts +1 -1
  24. package/dist/components/data-table-row.js.map +1 -1
  25. package/dist/components/data-table.js +3 -1
  26. package/dist/components/data-table.js.map +1 -1
  27. package/dist/components/dropdown.js +1 -0
  28. package/dist/components/dropdown.js.map +1 -1
  29. package/dist/components/full-bleed-dialog.js +1 -0
  30. package/dist/components/full-bleed-dialog.js.map +1 -1
  31. package/dist/components/modal.js +1 -0
  32. package/dist/components/modal.js.map +1 -1
  33. package/dist/components/number-input.d.ts +2 -1
  34. package/dist/components/number-input.js +6 -2
  35. package/dist/components/number-input.js.map +1 -1
  36. package/dist/components/numpad-sheet.js +2 -0
  37. package/dist/components/numpad-sheet.js.map +1 -1
  38. package/dist/components/picker-sheet.js +2 -0
  39. package/dist/components/picker-sheet.js.map +1 -1
  40. package/dist/components/popover.js +1 -0
  41. package/dist/components/popover.js.map +1 -1
  42. package/dist/eslint/index.js +1 -1
  43. package/dist/i18n/defaults.js +2 -0
  44. package/dist/i18n/defaults.js.map +1 -1
  45. package/dist/i18n/german.js +14 -1
  46. package/dist/i18n/german.js.map +1 -1
  47. package/dist/i18n/kit-labels.d.ts +3 -0
  48. package/dist/i18n/kit-labels.js.map +1 -1
  49. package/dist/i18n/locales/en.js +16 -1
  50. package/dist/i18n/locales/en.js.map +3 -3
  51. package/dist/i18n/locales/es.js +14 -1
  52. package/dist/i18n/locales/es.js.map +1 -1
  53. package/dist/i18n/locales/fr.js +14 -1
  54. package/dist/i18n/locales/fr.js.map +1 -1
  55. package/dist/i18n/locales/hu.js +14 -1
  56. package/dist/i18n/locales/hu.js.map +1 -1
  57. package/dist/i18n/locales/it.js +14 -1
  58. package/dist/i18n/locales/it.js.map +1 -1
  59. package/dist/i18n/locales/zh.js +14 -1
  60. package/dist/i18n/locales/zh.js.map +1 -1
  61. package/dist/i18n/review.js +1 -0
  62. package/dist/i18n/review.js.map +1 -1
  63. package/dist/lib/data-attributes.d.ts +11 -0
  64. package/dist/lib/data-attributes.js +10 -0
  65. package/dist/lib/data-attributes.js.map +1 -0
  66. package/dist/lib/format.d.ts +1 -0
  67. package/dist/lib/format.js +2 -0
  68. package/dist/lib/format.js.map +1 -1
  69. package/dist/lib/minus.d.ts +10 -0
  70. package/dist/lib/minus.js.map +1 -1
  71. package/dist/testing/react.d.ts +25 -0
  72. package/dist/testing/react.js +19 -0
  73. package/dist/testing/react.js.map +1 -0
  74. package/dist/tour/tour-dock.d.ts +42 -0
  75. package/dist/tour/tour-dock.js +80 -0
  76. package/dist/tour/tour-dock.js.map +1 -0
  77. package/dist/tour/tour-gates.d.ts +71 -0
  78. package/dist/tour/tour-gates.js +114 -0
  79. package/dist/tour/tour-gates.js.map +1 -0
  80. package/dist/tour/tour-guide-button.d.ts +27 -0
  81. package/dist/tour/tour-guide-button.js +45 -0
  82. package/dist/tour/tour-guide-button.js.map +1 -0
  83. package/dist/tour/tour-guide-labels.d.ts +8 -0
  84. package/dist/tour/tour-guide-labels.js +9 -0
  85. package/dist/tour/tour-guide-labels.js.map +1 -0
  86. package/dist/tour/tour-labels.js +9 -1
  87. package/dist/tour/tour-labels.js.map +1 -1
  88. package/dist/tour/tour.d.ts +133 -9
  89. package/dist/tour/tour.js +594 -70
  90. package/dist/tour/tour.js.map +1 -1
  91. package/dist/tour/use-tour-url-sync.d.ts +5 -2
  92. package/dist/tour/use-tour-url-sync.js +7 -1
  93. package/dist/tour/use-tour-url-sync.js.map +1 -1
  94. package/dist/tour.d.ts +2 -0
  95. package/dist/tour.js +3 -0
  96. package/dist/tour.js.map +1 -1
  97. package/dist/wizard/stepper-nav.js +15 -2
  98. package/dist/wizard/stepper-nav.js.map +1 -1
  99. package/dist/wizard/types.d.ts +11 -0
  100. package/dist/wizard/types.js.map +1 -1
  101. package/dist/wizard/use-wizard.js +11 -5
  102. package/dist/wizard/use-wizard.js.map +1 -1
  103. package/package.json +9 -1
  104. package/src/admin/user-roster.tsx +22 -12
  105. package/src/auth/verify-email.tsx +10 -0
  106. package/src/components/amount-input.tsx +5 -4
  107. package/src/components/autocomplete.tsx +2 -0
  108. package/src/components/combobox-core.tsx +2 -0
  109. package/src/components/combobox-suggestions.tsx +2 -0
  110. package/src/components/currency-select.tsx +95 -6
  111. package/src/components/data-table-mobile.tsx +99 -8
  112. package/src/components/data-table-row.tsx +1 -0
  113. package/src/components/data-table.tsx +9 -1
  114. package/src/components/dropdown.tsx +2 -0
  115. package/src/components/full-bleed-dialog.tsx +3 -0
  116. package/src/components/modal.tsx +3 -0
  117. package/src/components/number-input.tsx +8 -3
  118. package/src/components/numpad-sheet.tsx +4 -0
  119. package/src/components/picker-sheet.tsx +4 -0
  120. package/src/components/popover.tsx +2 -0
  121. package/src/i18n/defaults.ts +2 -0
  122. package/src/i18n/german.ts +13 -0
  123. package/src/i18n/kit-labels.tsx +3 -0
  124. package/src/i18n/locales/es.ts +13 -0
  125. package/src/i18n/locales/fr.ts +13 -0
  126. package/src/i18n/locales/hu.ts +13 -0
  127. package/src/i18n/locales/it.ts +13 -0
  128. package/src/i18n/locales/zh.ts +13 -0
  129. package/src/i18n/review.ts +1 -0
  130. package/src/lib/data-attributes.ts +14 -0
  131. package/src/lib/format.ts +2 -0
  132. package/src/lib/minus.ts +10 -0
  133. package/src/testing/react.ts +59 -0
  134. package/src/tour/tour-dock.ts +132 -0
  135. package/src/tour/tour-gates.ts +195 -0
  136. package/src/tour/tour-guide-button.tsx +64 -0
  137. package/src/tour/tour-guide-labels.ts +15 -0
  138. package/src/tour/tour-labels.ts +8 -0
  139. package/src/tour/tour.tsx +949 -86
  140. package/src/tour/use-tour-url-sync.ts +14 -4
  141. package/src/tour.ts +3 -0
  142. package/src/wizard/stepper-nav.tsx +23 -3
  143. package/src/wizard/types.ts +12 -0
  144. package/src/wizard/use-wizard.ts +16 -9
@@ -3,12 +3,14 @@ import { type LabelOverride } from "../i18n/kit-labels.js";
3
3
  import { DEFAULT_TOUR_LABELS } from "./tour-labels.js";
4
4
  import type { TourInfo } from "./tour-info.js";
5
5
  import { type UseTourProgressOptions } from "./use-tour-progress.js";
6
+ export { useTourGate, useTourGateRelease } from "./tour-gates.js";
7
+ export type { TourGateRelease } from "./tour-gates.js";
6
8
  /**
7
9
  * `start`/`end` follow the reading direction (`end` is the right side in LTR and the
8
10
  * left side in RTL) and are what a translated app wants. `left`/`right` stay physical
9
11
  * for the steps that genuinely mean a screen side.
10
12
  */
11
- export type TourPlacement = "top" | "right" | "bottom" | "left" | "start" | "end" | "center";
13
+ export type TourPlacement = "top" | "right" | "bottom" | "left" | "start" | "end" | "center" | "dock";
12
14
  export interface TourStep {
13
15
  /** CSS selector for the element to spotlight. Omit for a centered step
14
16
  * (welcome/finish). If the target isn't found/visible, the step centers. */
@@ -17,13 +19,22 @@ export interface TourStep {
17
19
  body: ReactNode;
18
20
  /** Extra footer content, e.g. a "load sample data" shortcut. */
19
21
  action?: ReactNode;
20
- /** Spotlight padding around the target, px (default 8). */
22
+ /** Spotlight padding around the target, px (default 8). On a field step the spot also
23
+ * takes in the lines the field's `aria-describedby` names when they sit within the
24
+ * ring's reach of it (a hint or warning line under the field, keksdose S1, §11.6). */
21
25
  padding?: number;
22
26
  /** Where the card sits relative to the target. Omit for auto placement
23
27
  * (below → above → centered). "center" ignores the target and centers on
24
28
  * screen. "start"/"end" are the logical sides and flip in RTL; "left"/"right"
25
29
  * are physical. An explicit side flips to the opposite side if it would
26
- * overflow, then clamps into the viewport. */
30
+ * overflow, then clamps into the viewport.
31
+ *
32
+ * `"dock"` (0.50, §11.7): below `sm` (640 px) the card is pinned full-width to the top
33
+ * or bottom edge of the usable band — the visual viewport less the keyboard and any
34
+ * `[data-tour-obstruction]` (the number pad) — on the edge away from the field, and the
35
+ * field's scroll container brings it into the other half. From `sm` up it is auto
36
+ * placement. On a phone a field step (`interactive`, `awaitInput`, `gate`, `awaitGate`)
37
+ * with a target and no `placement` docks by default (`TourProvider dockOnPhones`). */
27
38
  placement?: TourPlacement;
28
39
  /** Advance only when the user clicks the spotlighted target itself (not the
29
40
  * card's Next button). Requires `target`: the real control's own handler runs
@@ -58,9 +69,58 @@ export interface TourStep {
58
69
  * button) has nothing to compare: call `useTour().next()` from its `onChange`.
59
70
  */
60
71
  awaitInput?: boolean;
72
+ /**
73
+ * 0.50 (docs/tours-harmonization.md §11.1): Next stays locked until the gate `key` is
74
+ * satisfied — the form publishes it with `useTourGate(key, satisfied)` beside the field.
75
+ * Implies `interactive`. The locked Next is `aria-disabled` with {@link gateHint} under
76
+ * it; pressing it focuses the field. Once satisfied the tour does NOT advance by itself:
77
+ * Next, Enter in the field, or focus leaving the field to nowhere or to the card (the
78
+ * number pad's Done) moves on. A key nobody publishes is not enforced (the form closed
79
+ * under the tour): Next opens. A step may have a `gate` and no `target`.
80
+ */
81
+ gate?: string;
82
+ /** Overrides `labels.gateHint` for this step. */
83
+ gateHint?: string;
84
+ /**
85
+ * 0.50 (§11.4): wait for the app to RELEASE this key — `useTourGateRelease().release(key)`
86
+ * from the save's `onSuccess`. Implies `interactive`; usually it targets the Save button,
87
+ * whose hole stays click-through. Next is replaced by {@link awaitGateHint}, and a click
88
+ * does not advance: only `release` does. A release that arrives on an earlier step (Enter
89
+ * in the last field submitted the form) jumps past the first later step awaiting the key.
90
+ * `refuse(key, reason)` keeps the step and shows the reason, with a "Back to …" link to the
91
+ * first earlier field whose gate is now unsatisfied; the kit never jumps there itself.
92
+ * A viewer who cannot save gets `awaitGate: undefined`, so a plain Next.
93
+ */
94
+ awaitGate?: string;
95
+ /** Overrides `labels.awaitGateHint` for this step. */
96
+ awaitGateHint?: string;
97
+ /**
98
+ * 0.50 (§11.2): the field may stay empty. While the `gate` is unsatisfied the card
99
+ * offers "Leave empty" beside the locked Next, which moves on without touching the field
100
+ * (the kit never writes app values); the title carries an "Optional" chip. Not a skip:
101
+ * the run continues and can complete. Without a `gate`, only the chip.
102
+ */
103
+ optional?: boolean;
104
+ /**
105
+ * 0.50 (§11.3): shown only if this returns true on ARRIVAL (evaluated before
106
+ * `beforeStep`, so a skipped step never navigates). Next walks forward to the first step
107
+ * shown, Back to the nearest earlier one shown now. Branch facts are gates:
108
+ * `when: (c) => c.gate("txn.transfer") === true`. Keep it pure and cheap: the counter
109
+ * evaluates every step's `when` on each arrival. A throw counts as skipped.
110
+ */
111
+ when?: (ctx: TourStepContext) => boolean;
61
112
  /** Runs before the step is shown — e.g. navigate to a route, open a panel.
62
- * May be async; the step waits for it, then locates the target. */
63
- beforeStep?: () => void | Promise<void>;
113
+ * May be async; the step waits for it, then locates the target. Receives the
114
+ * {@link TourStepContext} (0.50); a step entered by "Guide me" sees `via: "at"` and
115
+ * should leave an open form alone. */
116
+ beforeStep?: (ctx: TourStepContext) => void | Promise<void>;
117
+ }
118
+ /** What a step's `when` and `beforeStep` may ask on arrival (0.50, §11.3). */
119
+ export interface TourStepContext {
120
+ /** The gate's current value: true/false, or undefined while nobody publishes it. */
121
+ gate(key: string): boolean | undefined;
122
+ /** How this step is being entered. */
123
+ via: "start" | "at" | "next" | "back" | "goto";
64
124
  }
65
125
  export interface TourLabels {
66
126
  next: string;
@@ -71,10 +131,42 @@ export interface TourLabels {
71
131
  awaitClickHint: string;
72
132
  /** Shown in place of the Next button on an `awaitInput` step (0.46). */
73
133
  awaitInputHint: string;
74
- /** Step counter, e.g. (2, 7) => "2 / 7". */
134
+ /** Step counter, e.g. (2, 7) => "2 / 7". Counts the steps the run shows (0.50). */
75
135
  step: (current: number, total: number) => string;
136
+ /** 0.50: an `optional` gate step's button while the field is empty. */
137
+ leaveEmpty: string;
138
+ /** 0.50: the chip beside an `optional` step's title. */
139
+ optional: string;
140
+ /** 0.50: under a `gate` step's locked Next (`TourStep.gateHint` overrides it). */
141
+ gateHint: string;
142
+ /** 0.50: announced (screen readers only) when a gate step's field is filled. */
143
+ gateReady: string;
144
+ /** 0.50: in place of Next on an `awaitGate` step (`TourStep.awaitGateHint` overrides it). */
145
+ awaitGateHint: string;
146
+ /** 0.50: the warning when the app `refuse`s an `awaitGate` step without a reason. */
147
+ awaitGateRefused: string;
148
+ /** 0.50: the link to an earlier step whose field was emptied, after a refused save. */
149
+ backToStep: (title: string) => string;
76
150
  }
77
151
  export { DEFAULT_TOUR_LABELS };
152
+ /** 0.50 (§11.5): a step index, or the `data-tour` value of the step's anchor. */
153
+ export type TourAt = number | string;
154
+ /** `useTour().start`, both forms: what `TourProvider` hands its `launch` as the third argument. */
155
+ export type TourStart = TourContextValue["start"];
156
+ /**
157
+ * 0.50 (§11.5): the app's launcher — the shape `useTourUrlSync` already takes, plus `at`.
158
+ * It builds the steps (`prepare()`, `build()`, `tour: tourInfo(def)`) and passes `at` on to
159
+ * `start(steps, { …, at })`. Give the same function to `TourProvider launch` and to
160
+ * `useTourUrlSync`.
161
+ *
162
+ * `start` is the provider's own `start` (keksdose N4), so the launcher needs no ref to a
163
+ * component below the provider and may be defined above it. `useTourUrlSync` passes it too
164
+ * (under a provider). A two-argument launcher that reaches `start` its own way still works.
165
+ */
166
+ export type TourLauncher = (id: string, opts: {
167
+ startIndex?: number;
168
+ at?: TourAt;
169
+ }, start: TourStart) => void | Promise<unknown>;
78
170
  interface StartOptions {
79
171
  /** Stable id of the tour, surfaced as `activeId` so the app can mirror it to
80
172
  * the URL (deep-link / evaluation tracking) and record completion. Defaults to
@@ -86,6 +178,15 @@ interface StartOptions {
86
178
  tour?: TourInfo;
87
179
  /** Start at this step index instead of 0 (clamped) — for URL/deep-link resume. */
88
180
  startIndex?: number;
181
+ /**
182
+ * 0.50 (§11.5): start here AND make it the floor — earlier steps never run (nor their
183
+ * `beforeStep`), Back stops here, `position`/`count` count from here, and the finish
184
+ * records the completion as a full run does (Marcel, Q2). A number is a step index
185
+ * (clamped); a string is the first step whose `target` contains `data-tour="<at>"`
186
+ * verbatim (unknown: 0, with a development warning). The `at` step is entered with
187
+ * `via: "at"`. With `startIndex` too, `startIndex` picks the step and `at` the floor.
188
+ */
189
+ at?: TourAt;
89
190
  /** Fires synchronously when the tour starts (e.g. enable a mock interceptor). */
90
191
  onStart?: () => void;
91
192
  /** After the last step: runs after the provider's progress write and `onComplete`. */
@@ -107,8 +208,17 @@ interface TourContextValue {
107
208
  active: boolean;
108
209
  /** Id of the running tour (from {@link StartOptions.id}), else null. */
109
210
  activeId: string | null;
110
- /** Start a tour with the given steps. */
111
- start: (steps: TourStep[], opts?: StartOptions) => void;
211
+ /**
212
+ * Start a tour with the given steps — or, by id (0.50), through the provider's `launch`:
213
+ * `start("create-transaction", { at: "txn-entry-mode" })`. Without a `launch` the id form
214
+ * does nothing (a development build warns).
215
+ */
216
+ start: {
217
+ (id: string, opts?: {
218
+ at?: TourAt;
219
+ }): void;
220
+ (steps: TourStep[], opts?: StartOptions): void;
221
+ };
112
222
  /** End the current tour (no callbacks fire). */
113
223
  stop: () => void;
114
224
  /** Advance one step; past the last step it finishes the tour (fires onFinish). */
@@ -121,6 +231,10 @@ interface TourContextValue {
121
231
  index: number;
122
232
  /** Total steps (0 while inactive). */
123
233
  total: number;
234
+ /** 0.50: 1-based position among the steps this run shows, for "3 of 9"; 0 while inactive. */
235
+ position: number;
236
+ /** 0.50: how many steps this run shows, from its first (the `at` floor) to the end; 0 while inactive. */
237
+ count: number;
124
238
  }
125
239
  export declare function useTour(): TourContextValue;
126
240
  /**
@@ -165,11 +279,21 @@ export declare function useTourOptional(): TourContextValue | null;
165
279
  * new `storageKey` (an account switch on a shared PC) is followed on the next
166
280
  * completion, without a remount.
167
281
  */
168
- export declare function TourProvider({ children, labels, progress, onComplete, }: {
282
+ export declare function TourProvider({ children, labels, progress, onComplete, launch, dockOnPhones, }: {
169
283
  children: ReactNode;
170
284
  labels?: LabelOverride<TourLabels>;
285
+ /**
286
+ * 0.50 (§11.5): lets `start(id)` and `<TourGuideButton>` start a tour by id. Usually the
287
+ * same function the app gives `useTourUrlSync`.
288
+ */
289
+ launch?: TourLauncher;
171
290
  /** The app's tour progress: the same options its `useTourProgress` readers use. */
172
291
  progress?: UseTourProgressOptions;
173
292
  /** A tour's last step was finished; see {@link TourCompletion}. */
174
293
  onComplete?: (tour: TourInfo | undefined, completion: TourCompletion) => void;
294
+ /**
295
+ * 0.50 (§11.7, Marcel's Q1): below `sm`, a field step with a target and no `placement`
296
+ * docks. Default `true`; `false` makes docking strictly opt-in (`placement: "dock"`).
297
+ */
298
+ dockOnPhones?: boolean;
175
299
  }): import("react").JSX.Element;