@eifi1/ui-kit 0.28.0 → 0.29.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 (166) hide show
  1. package/README.md +22 -4
  2. package/dist/auth/accept-invitation.d.ts +90 -0
  3. package/dist/auth/accept-invitation.js +117 -0
  4. package/dist/auth/accept-invitation.js.map +1 -0
  5. package/dist/auth/auth-errors.d.ts +60 -0
  6. package/dist/auth/auth-errors.js +32 -0
  7. package/dist/auth/auth-errors.js.map +1 -0
  8. package/dist/auth/complete-name-dialog.d.ts +71 -0
  9. package/dist/auth/complete-name-dialog.js +168 -0
  10. package/dist/auth/complete-name-dialog.js.map +1 -0
  11. package/dist/auth/email-tag.d.ts +60 -0
  12. package/dist/auth/email-tag.js +23 -0
  13. package/dist/auth/email-tag.js.map +1 -0
  14. package/dist/auth/forgot-password-form.d.ts +79 -0
  15. package/dist/auth/forgot-password-form.js +120 -0
  16. package/dist/auth/forgot-password-form.js.map +1 -0
  17. package/dist/auth/form-rules.d.ts +27 -0
  18. package/dist/auth/form-rules.js +23 -0
  19. package/dist/auth/form-rules.js.map +1 -0
  20. package/dist/auth/new-password-fields.d.ts +38 -0
  21. package/dist/auth/new-password-fields.js +54 -0
  22. package/dist/auth/new-password-fields.js.map +1 -0
  23. package/dist/auth/not-found-page.d.ts +57 -0
  24. package/dist/auth/not-found-page.js +40 -0
  25. package/dist/auth/not-found-page.js.map +1 -0
  26. package/dist/auth/register-form.d.ts +86 -0
  27. package/dist/auth/register-form.js +268 -0
  28. package/dist/auth/register-form.js.map +1 -0
  29. package/dist/auth/reset-password-form.d.ts +124 -0
  30. package/dist/auth/reset-password-form.js +164 -0
  31. package/dist/auth/reset-password-form.js.map +1 -0
  32. package/dist/auth/sign-in-form.d.ts +243 -0
  33. package/dist/auth/sign-in-form.js +345 -0
  34. package/dist/auth/sign-in-form.js.map +1 -0
  35. package/dist/auth/status-parts.d.ts +78 -0
  36. package/dist/auth/status-parts.js +83 -0
  37. package/dist/auth/status-parts.js.map +1 -0
  38. package/dist/auth/verify-email.d.ts +121 -0
  39. package/dist/auth/verify-email.js +207 -0
  40. package/dist/auth/verify-email.js.map +1 -0
  41. package/dist/chart.d.ts +17 -2
  42. package/dist/components/amount-input.d.ts +18 -2
  43. package/dist/components/button-group.d.ts +18 -2
  44. package/dist/components/calculator.d.ts +18 -2
  45. package/dist/components/confirm-dialog.d.ts +18 -2
  46. package/dist/components/copy-button.d.ts +18 -2
  47. package/dist/components/danger-confirm.d.ts +18 -2
  48. package/dist/components/facing-pair.d.ts +18 -2
  49. package/dist/components/file-button.d.ts +18 -2
  50. package/dist/components/file-dropzone.d.ts +18 -2
  51. package/dist/components/form-actions.d.ts +18 -2
  52. package/dist/components/iban-input.d.ts +18 -2
  53. package/dist/components/language-select.d.ts +18 -9
  54. package/dist/components/legal-page.d.ts +26 -4
  55. package/dist/components/legal-page.js +24 -5
  56. package/dist/components/legal-page.js.map +1 -1
  57. package/dist/components/legal.d.ts +18 -2
  58. package/dist/components/legal.js +49 -5
  59. package/dist/components/legal.js.map +1 -1
  60. package/dist/components/money-field.d.ts +18 -2
  61. package/dist/components/number-field.d.ts +18 -2
  62. package/dist/components/number-input.d.ts +18 -2
  63. package/dist/components/numpad-sheet.d.ts +18 -2
  64. package/dist/components/phone-input.d.ts +18 -2
  65. package/dist/components/series-chart.d.ts +18 -2
  66. package/dist/components/settings-fields.d.ts +15 -2
  67. package/dist/components/share-card.d.ts +18 -2
  68. package/dist/components/text-link.d.ts +18 -2
  69. package/dist/components/time-input.d.ts +18 -2
  70. package/dist/components/ui.d.ts +17 -1
  71. package/dist/components/user-avatar.d.ts +16 -2
  72. package/dist/components/user-avatar.js +7 -3
  73. package/dist/components/user-avatar.js.map +1 -1
  74. package/dist/feedback/feedback-attachment.d.ts +18 -2
  75. package/dist/feedback/feedback-context.d.ts +18 -2
  76. package/dist/feedback/feedback-crash.d.ts +18 -2
  77. package/dist/feedback/feedback-dialog.d.ts +18 -2
  78. package/dist/feedback/feedback-inbox.d.ts +18 -2
  79. package/dist/feedback/feedback-labels.d.ts +18 -2
  80. package/dist/feedback/feedback-menu.d.ts +18 -2
  81. package/dist/feedback/feedback-record.d.ts +18 -2
  82. package/dist/feedback/feedback-row-detail.d.ts +18 -2
  83. package/dist/feedback/feedback-status-undo.d.ts +18 -2
  84. package/dist/feedback/feedback-submit.d.ts +18 -2
  85. package/dist/feedback/feedback-swipe.d.ts +18 -2
  86. package/dist/feedback/feedback-table.d.ts +18 -2
  87. package/dist/feedback/feedback-thread.d.ts +18 -2
  88. package/dist/feedback.d.ts +18 -2
  89. package/dist/hooks/use-file-drop.d.ts +18 -2
  90. package/dist/i18n/defaults.d.ts +18 -2
  91. package/dist/i18n/defaults.js +18 -0
  92. package/dist/i18n/defaults.js.map +1 -1
  93. package/dist/i18n/german.d.ts +18 -2
  94. package/dist/i18n/german.js +145 -0
  95. package/dist/i18n/german.js.map +1 -1
  96. package/dist/i18n/kit-labels.d.ts +18 -2
  97. package/dist/i18n/kit-labels.js.map +1 -1
  98. package/dist/i18n/languages.d.ts +13 -201
  99. package/dist/i18n/locales/de-CH.d.ts +18 -2
  100. package/dist/i18n/locales/en.d.ts +18 -2
  101. package/dist/i18n/locales/es.d.ts +18 -2
  102. package/dist/i18n/locales/es.js +147 -3
  103. package/dist/i18n/locales/es.js.map +1 -1
  104. package/dist/i18n/locales/fr.d.ts +18 -2
  105. package/dist/i18n/locales/fr.js +147 -0
  106. package/dist/i18n/locales/fr.js.map +1 -1
  107. package/dist/i18n/locales/hu.d.ts +18 -2
  108. package/dist/i18n/locales/hu.js +149 -3
  109. package/dist/i18n/locales/hu.js.map +1 -1
  110. package/dist/i18n/locales/it.d.ts +18 -2
  111. package/dist/i18n/locales/it.js +146 -1
  112. package/dist/i18n/locales/it.js.map +1 -1
  113. package/dist/i18n/locales/zh.d.ts +18 -2
  114. package/dist/i18n/locales/zh.js +146 -1
  115. package/dist/i18n/locales/zh.js.map +1 -1
  116. package/dist/i18n/review.d.ts +18 -2
  117. package/dist/i18n/review.js +17 -7
  118. package/dist/i18n/review.js.map +1 -1
  119. package/dist/index.d.ts +13 -2
  120. package/dist/index.js +49 -1
  121. package/dist/index.js.map +1 -1
  122. package/dist/lib/person-name.d.ts +69 -0
  123. package/dist/lib/person-name.js +65 -0
  124. package/dist/lib/person-name.js.map +1 -0
  125. package/dist/{kit-labels-SBN0biPl.d.ts → register-form-V1OeNlMr.d.ts} +423 -6
  126. package/dist/rhf/fields.d.ts +18 -2
  127. package/dist/rhf/form.d.ts +18 -2
  128. package/dist/rhf.d.ts +18 -2
  129. package/dist/shell/app-shell.d.ts +18 -2
  130. package/dist/shell/company-switcher.d.ts +59 -0
  131. package/dist/shell/company-switcher.js +85 -0
  132. package/dist/shell/company-switcher.js.map +1 -0
  133. package/dist/shell/top-bar-brand.d.ts +18 -2
  134. package/dist/shell/topbar-action-menu.d.ts +1 -0
  135. package/dist/shell.d.ts +12 -2
  136. package/dist/wizard/stepper-nav.d.ts +18 -2
  137. package/dist/wizard.d.ts +18 -2
  138. package/package.json +1 -1
  139. package/src/auth/accept-invitation.tsx +227 -0
  140. package/src/auth/auth-errors.ts +105 -0
  141. package/src/auth/complete-name-dialog.tsx +253 -0
  142. package/src/auth/email-tag.ts +75 -0
  143. package/src/auth/forgot-password-form.tsx +213 -0
  144. package/src/auth/form-rules.ts +40 -0
  145. package/src/auth/new-password-fields.tsx +85 -0
  146. package/src/auth/not-found-page.tsx +98 -0
  147. package/src/auth/register-form.tsx +459 -0
  148. package/src/auth/reset-password-form.tsx +337 -0
  149. package/src/auth/sign-in-form.tsx +687 -0
  150. package/src/auth/status-parts.tsx +138 -0
  151. package/src/auth/verify-email.tsx +358 -0
  152. package/src/components/legal-page.tsx +35 -0
  153. package/src/components/legal.tsx +93 -7
  154. package/src/components/user-avatar.tsx +22 -4
  155. package/src/i18n/defaults.ts +18 -0
  156. package/src/i18n/german.ts +153 -0
  157. package/src/i18n/kit-labels.tsx +27 -0
  158. package/src/i18n/locales/es.ts +156 -3
  159. package/src/i18n/locales/fr.ts +157 -0
  160. package/src/i18n/locales/hu.ts +159 -3
  161. package/src/i18n/locales/it.ts +154 -1
  162. package/src/i18n/locales/zh.ts +149 -1
  163. package/src/i18n/review.ts +15 -6
  164. package/src/index.ts +63 -1
  165. package/src/lib/person-name.ts +157 -0
  166. package/src/shell/company-switcher.tsx +140 -0
@@ -2,7 +2,7 @@ import * as react from 'react';
2
2
  import { ReactElement, ComponentProps } from 'react';
3
3
  import * as react_hook_form from 'react-hook-form';
4
4
  import { FieldValues, FieldPath, ControllerProps } from 'react-hook-form';
5
- import { dp as LabelProps } from '../kit-labels-SBN0biPl.js';
5
+ import { du as LabelProps } from '../register-form-V1OeNlMr.js';
6
6
  import '../data-table-labels-DUELeXpa.js';
7
7
  import '../components/data-table-sort.js';
8
8
  import '../components/swipeable-row.js';
@@ -15,6 +15,7 @@ import '../components/field-sync.js';
15
15
  import '../components/tooltip.js';
16
16
  import '../hooks/use-anchored-rect.js';
17
17
  import '../lib/clipping.js';
18
+ import '../components/field-parts.js';
18
19
  import '../wizard/types.js';
19
20
  import '../tour/tour.js';
20
21
  import '../search/command-palette.js';
@@ -36,6 +37,7 @@ import '../components/modal.js';
36
37
  import '../hooks/use-search-param-state.js';
37
38
  import '../components/measured-grid.js';
38
39
  import '../components/user-avatar.js';
40
+ import '../lib/person-name.js';
39
41
  import '../components/status-dot.js';
40
42
  import '../components/progress-bar.js';
41
43
  import '../components/signed-amount.js';
@@ -55,6 +57,15 @@ import '../components/authed-image.js';
55
57
  import '../components/image-grid.js';
56
58
  import '../components/lightbox.js';
57
59
  import '../components/write-lock.js';
60
+ import '../auth/sign-in-form.js';
61
+ import '../auth/complete-name-dialog.js';
62
+ import '../auth/forgot-password-form.js';
63
+ import '../auth/status-parts.js';
64
+ import '../auth/reset-password-form.js';
65
+ import '../auth/verify-email.js';
66
+ import '../auth/not-found-page.js';
67
+ import '../auth/accept-invitation.js';
68
+ import '../shell/company-switcher.js';
58
69
  import '../components/account-chips.js';
59
70
  import '../lib/format.js';
60
71
  import '../components/reauth-dialog.js';
@@ -70,7 +81,12 @@ import '../components/sign-chip.js';
70
81
  import '../components/column-mapper.js';
71
82
  import '../lib/column-mapping.js';
72
83
  import '../lib/table-text.js';
73
- import '../components/field-parts.js';
84
+ import '../shell/topbar-controls.js';
85
+ import '../theme/palette-presets.js';
86
+ import '../theme/chart-palette.js';
87
+ import '../theme/theme-store.js';
88
+ import 'zustand/middleware';
89
+ import 'zustand';
74
90
 
75
91
  /** The form's `useForm()` return, spread in: `<Form {...form}>`. react-hook-form's own
76
92
  * `FormProvider`, under the name the shadcn file gave it. */
package/dist/rhf.d.ts CHANGED
@@ -4,7 +4,7 @@ export { RhfCheckbox, RhfCheckboxProps, RhfCombobox, RhfComboboxProps, RhfCountr
4
4
  export { RhfLineItemCellContext, RhfLineItems, RhfLineItemsColumn, RhfLineItemsProps } from './rhf/line-items.js';
5
5
  import 'react';
6
6
  import 'react-hook-form';
7
- import './kit-labels-SBN0biPl.js';
7
+ import './register-form-V1OeNlMr.js';
8
8
  import './data-table-labels-DUELeXpa.js';
9
9
  import './components/data-table-sort.js';
10
10
  import './components/swipeable-row.js';
@@ -17,6 +17,7 @@ import './components/field-sync.js';
17
17
  import './components/tooltip.js';
18
18
  import './hooks/use-anchored-rect.js';
19
19
  import './lib/clipping.js';
20
+ import './components/field-parts.js';
20
21
  import './wizard/types.js';
21
22
  import './tour/tour.js';
22
23
  import './search/command-palette.js';
@@ -38,6 +39,7 @@ import './components/modal.js';
38
39
  import './hooks/use-search-param-state.js';
39
40
  import './components/measured-grid.js';
40
41
  import './components/user-avatar.js';
42
+ import './lib/person-name.js';
41
43
  import './components/status-dot.js';
42
44
  import './components/progress-bar.js';
43
45
  import './components/signed-amount.js';
@@ -57,6 +59,15 @@ import './components/authed-image.js';
57
59
  import './components/image-grid.js';
58
60
  import './components/lightbox.js';
59
61
  import './components/write-lock.js';
62
+ import './auth/sign-in-form.js';
63
+ import './auth/complete-name-dialog.js';
64
+ import './auth/forgot-password-form.js';
65
+ import './auth/status-parts.js';
66
+ import './auth/reset-password-form.js';
67
+ import './auth/verify-email.js';
68
+ import './auth/not-found-page.js';
69
+ import './auth/accept-invitation.js';
70
+ import './shell/company-switcher.js';
60
71
  import './components/account-chips.js';
61
72
  import './lib/format.js';
62
73
  import './components/reauth-dialog.js';
@@ -72,7 +83,12 @@ import './components/sign-chip.js';
72
83
  import './components/column-mapper.js';
73
84
  import './lib/column-mapping.js';
74
85
  import './lib/table-text.js';
75
- import './components/field-parts.js';
86
+ import './shell/topbar-controls.js';
87
+ import './theme/palette-presets.js';
88
+ import './theme/chart-palette.js';
89
+ import './theme/theme-store.js';
90
+ import 'zustand/middleware';
91
+ import 'zustand';
76
92
  import './components/number-field.js';
77
93
  import './components/number-input.js';
78
94
  import './components/calculator.js';
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ComponentPropsWithoutRef, ReactNode } from 'react';
3
3
  import { LucideIcon } from 'lucide-react';
4
- import { dk as KitLinkComponent } from '../kit-labels-SBN0biPl.js';
4
+ import { dp as KitLinkComponent } from '../register-form-V1OeNlMr.js';
5
5
  import '../data-table-labels-DUELeXpa.js';
6
6
  import '../components/data-table-sort.js';
7
7
  import '../components/swipeable-row.js';
@@ -13,6 +13,7 @@ import '../components/field-sync.js';
13
13
  import '../components/tooltip.js';
14
14
  import '../hooks/use-anchored-rect.js';
15
15
  import '../lib/clipping.js';
16
+ import '../components/field-parts.js';
16
17
  import '../wizard/types.js';
17
18
  import '../tour/tour.js';
18
19
  import '../search/command-palette.js';
@@ -34,6 +35,7 @@ import '../components/modal.js';
34
35
  import '../hooks/use-search-param-state.js';
35
36
  import '../components/measured-grid.js';
36
37
  import '../components/user-avatar.js';
38
+ import '../lib/person-name.js';
37
39
  import '../components/status-dot.js';
38
40
  import '../components/progress-bar.js';
39
41
  import '../components/signed-amount.js';
@@ -53,6 +55,15 @@ import '../components/authed-image.js';
53
55
  import '../components/image-grid.js';
54
56
  import '../components/lightbox.js';
55
57
  import '../components/write-lock.js';
58
+ import '../auth/sign-in-form.js';
59
+ import '../auth/complete-name-dialog.js';
60
+ import '../auth/forgot-password-form.js';
61
+ import '../auth/status-parts.js';
62
+ import '../auth/reset-password-form.js';
63
+ import '../auth/verify-email.js';
64
+ import '../auth/not-found-page.js';
65
+ import '../auth/accept-invitation.js';
66
+ import './company-switcher.js';
56
67
  import '../components/account-chips.js';
57
68
  import '../lib/format.js';
58
69
  import '../components/reauth-dialog.js';
@@ -68,7 +79,12 @@ import '../components/sign-chip.js';
68
79
  import '../components/column-mapper.js';
69
80
  import '../lib/column-mapping.js';
70
81
  import '../lib/table-text.js';
71
- import '../components/field-parts.js';
82
+ import './topbar-controls.js';
83
+ import '../theme/palette-presets.js';
84
+ import '../theme/chart-palette.js';
85
+ import '../theme/theme-store.js';
86
+ import 'zustand/middleware';
87
+ import 'zustand';
72
88
 
73
89
  interface AppShellSubItem {
74
90
  to: string;
@@ -0,0 +1,59 @@
1
+ import * as react from 'react';
2
+ import { ReactNode } from 'react';
3
+
4
+ /** Every string the switcher renders or speaks — the `companySwitcher` namespace. A
5
+ * different context (keksdose's budgets) renames them all. */
6
+ interface CompanySwitcherLabels {
7
+ /** The trigger's and the menu's accessible name. */
8
+ switchCompany: string;
9
+ /** The small heading over the list. */
10
+ heading: string;
11
+ /** The trigger's tooltip (and description), given the current company's name. */
12
+ current: (name: string) => string;
13
+ /** Read after the current company's name in the list, where the eye sees a check. */
14
+ currentMark: string;
15
+ /** Said while a switch is running. */
16
+ switching: string;
17
+ }
18
+ declare const DEFAULT_COMPANY_SWITCHER_LABELS: CompanySwitcherLabels;
19
+ /** One company the user belongs to — kastlan's `/auth/me` `companies[]` (§5.3). */
20
+ interface CompanySwitcherCompany<Id extends string | number = string | number> {
21
+ /** kastlan's ids are numbers; a string works the same. */
22
+ id: Id;
23
+ name: string;
24
+ }
25
+ interface CompanySwitcherProps<Id extends string | number> {
26
+ /** Every company the user belongs to. With fewer than two there is nothing to
27
+ * switch, and nothing renders. */
28
+ companies: readonly CompanySwitcherCompany<Id>[];
29
+ /** The company the session is in — `/auth/me`'s `current_company_id`. */
30
+ currentId: Id;
31
+ /**
32
+ * Another company was picked: `POST /auth/switch-company {company_id}`, store the
33
+ * fresh tokens, reload what is company-scoped. While the promise runs the switcher is
34
+ * disabled, so a second pick cannot race the first; a rejection frees it (the app
35
+ * says why). Picking the current company does nothing.
36
+ */
37
+ onSwitch: (id: Id) => Promise<unknown> | void;
38
+ /** The trigger's glyph. Default a building; keksdose's budgets would pass a wallet. */
39
+ icon?: ReactNode;
40
+ labels?: Partial<CompanySwitcherLabels>;
41
+ }
42
+ /**
43
+ * The company switcher in the top bar (docs/auth-harmonization.md §5.3, §8): a kastlan
44
+ * user may belong to several companies, and the access token carries the current one,
45
+ * so switching is a request for new tokens — `onSwitch`, the app's. Built on
46
+ * {@link OptionSwitcherMenu}, like `RoleSwitcher`: the icon trigger, the current company
47
+ * in its tooltip, the list with a check on the current one.
48
+ *
49
+ * **Only for more than one company** — a user in one company has nothing to switch, and
50
+ * the top bar stays as it was. **Disabled while a switch runs**: the trigger is swapped
51
+ * for a disabled one with a spinner (`aria-busy`), and "Switching company…" is said, so
52
+ * a second pick cannot race the first. The kit never sends the request.
53
+ *
54
+ * A generic context switcher: the labels rename it ("Switch budget", "Budgets"), `icon`
55
+ * replaces the building, and `id` may be a number (kastlan's) or a string.
56
+ */
57
+ declare function CompanySwitcher<Id extends string | number>({ companies, currentId, onSwitch, icon, labels: labelsProp, }: CompanySwitcherProps<Id>): react.JSX.Element | null;
58
+
59
+ export { CompanySwitcher, type CompanySwitcherCompany, type CompanySwitcherLabels, type CompanySwitcherProps, DEFAULT_COMPANY_SWITCHER_LABELS };
@@ -0,0 +1,85 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { useState } from "react";
4
+ import { Building2 } from "lucide-react";
5
+ import { cn } from "../lib/cn.js";
6
+ import { useKitLabels } from "../i18n/kit-labels.js";
7
+ import { useAnnounce } from "../hooks/use-announce.js";
8
+ import { Spinner } from "../components/ui.js";
9
+ import { OptionSwitcherMenu } from "./option-switcher-menu.js";
10
+ import { TOPBAR_TRIGGER_CLASS } from "./topbar-controls.js";
11
+ const DEFAULT_COMPANY_SWITCHER_LABELS = {
12
+ switchCompany: "Switch company",
13
+ heading: "Companies",
14
+ current: (name) => `Company: ${name}`,
15
+ currentMark: "(current)",
16
+ switching: "Switching company\u2026"
17
+ };
18
+ function CompanySwitcher({
19
+ companies,
20
+ currentId,
21
+ onSwitch,
22
+ icon,
23
+ labels: labelsProp
24
+ }) {
25
+ const labels = useKitLabels("companySwitcher", DEFAULT_COMPANY_SWITCHER_LABELS, labelsProp);
26
+ const [pending, setPending] = useState(false);
27
+ const { announce, regionProps } = useAnnounce();
28
+ if (companies.length < 2) return null;
29
+ const current = companies.find((c) => c.id === currentId);
30
+ const select = (value) => {
31
+ if (pending) return;
32
+ const picked = companies.find((c) => String(c.id) === value);
33
+ if (!picked || picked.id === currentId) return;
34
+ const result = onSwitch(picked.id);
35
+ if (typeof result?.then !== "function") return;
36
+ setPending(true);
37
+ announce(labels.switching);
38
+ result.then(
39
+ () => setPending(false),
40
+ () => setPending(false)
41
+ );
42
+ };
43
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
44
+ pending ? /* @__PURE__ */ jsx(
45
+ "button",
46
+ {
47
+ type: "button",
48
+ disabled: true,
49
+ "aria-busy": "true",
50
+ "aria-label": labels.switchCompany,
51
+ className: cn(TOPBAR_TRIGGER_CLASS, "cursor-wait opacity-60 hover:bg-transparent"),
52
+ children: /* @__PURE__ */ jsx(Spinner, { label: null })
53
+ }
54
+ ) : /* @__PURE__ */ jsx(
55
+ OptionSwitcherMenu,
56
+ {
57
+ ariaLabel: labels.switchCompany,
58
+ title: current ? labels.current(current.name) : void 0,
59
+ heading: labels.heading,
60
+ icon: icon ?? /* @__PURE__ */ jsx(Building2, { className: "size-5" }),
61
+ options: companies.map((c) => ({
62
+ value: String(c.id),
63
+ label: c.id === currentId ? (
64
+ // `relative`: the sr-only mark needs a local containing block.
65
+ /* @__PURE__ */ jsxs("span", { className: "relative", children: [
66
+ c.name,
67
+ /* @__PURE__ */ jsxs("span", { className: "sr-only", children: [
68
+ " ",
69
+ labels.currentMark
70
+ ] })
71
+ ] })
72
+ ) : c.name
73
+ })),
74
+ value: String(currentId),
75
+ onSelect: select
76
+ }
77
+ ),
78
+ /* @__PURE__ */ jsx("span", { ...regionProps })
79
+ ] });
80
+ }
81
+ export {
82
+ CompanySwitcher,
83
+ DEFAULT_COMPANY_SWITCHER_LABELS
84
+ };
85
+ //# sourceMappingURL=company-switcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/shell/company-switcher.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { Building2 } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { useKitLabels } from \"../i18n/kit-labels\";\nimport { useAnnounce } from \"../hooks/use-announce\";\nimport { Spinner } from \"../components/ui\";\nimport { OptionSwitcherMenu } from \"./option-switcher-menu\";\nimport { TOPBAR_TRIGGER_CLASS } from \"./topbar-controls\";\n\n/** Every string the switcher renders or speaks — the `companySwitcher` namespace. A\n * different context (keksdose's budgets) renames them all. */\nexport interface CompanySwitcherLabels {\n /** The trigger's and the menu's accessible name. */\n switchCompany: string;\n /** The small heading over the list. */\n heading: string;\n /** The trigger's tooltip (and description), given the current company's name. */\n current: (name: string) => string;\n /** Read after the current company's name in the list, where the eye sees a check. */\n currentMark: string;\n /** Said while a switch is running. */\n switching: string;\n}\n\nexport const DEFAULT_COMPANY_SWITCHER_LABELS: CompanySwitcherLabels = {\n switchCompany: \"Switch company\",\n heading: \"Companies\",\n current: (name) => `Company: ${name}`,\n currentMark: \"(current)\",\n switching: \"Switching company…\",\n};\n\n/** One company the user belongs to — kastlan's `/auth/me` `companies[]` (§5.3). */\nexport interface CompanySwitcherCompany<Id extends string | number = string | number> {\n /** kastlan's ids are numbers; a string works the same. */\n id: Id;\n name: string;\n}\n\nexport interface CompanySwitcherProps<Id extends string | number> {\n /** Every company the user belongs to. With fewer than two there is nothing to\n * switch, and nothing renders. */\n companies: readonly CompanySwitcherCompany<Id>[];\n /** The company the session is in — `/auth/me`'s `current_company_id`. */\n currentId: Id;\n /**\n * Another company was picked: `POST /auth/switch-company {company_id}`, store the\n * fresh tokens, reload what is company-scoped. While the promise runs the switcher is\n * disabled, so a second pick cannot race the first; a rejection frees it (the app\n * says why). Picking the current company does nothing.\n */\n onSwitch: (id: Id) => Promise<unknown> | void;\n /** The trigger's glyph. Default a building; keksdose's budgets would pass a wallet. */\n icon?: ReactNode;\n labels?: Partial<CompanySwitcherLabels>;\n}\n\n/**\n * The company switcher in the top bar (docs/auth-harmonization.md §5.3, §8): a kastlan\n * user may belong to several companies, and the access token carries the current one,\n * so switching is a request for new tokens — `onSwitch`, the app's. Built on\n * {@link OptionSwitcherMenu}, like `RoleSwitcher`: the icon trigger, the current company\n * in its tooltip, the list with a check on the current one.\n *\n * **Only for more than one company** — a user in one company has nothing to switch, and\n * the top bar stays as it was. **Disabled while a switch runs**: the trigger is swapped\n * for a disabled one with a spinner (`aria-busy`), and \"Switching company…\" is said, so\n * a second pick cannot race the first. The kit never sends the request.\n *\n * A generic context switcher: the labels rename it (\"Switch budget\", \"Budgets\"), `icon`\n * replaces the building, and `id` may be a number (kastlan's) or a string.\n */\nexport function CompanySwitcher<Id extends string | number>({\n companies,\n currentId,\n onSwitch,\n icon,\n labels: labelsProp,\n}: CompanySwitcherProps<Id>) {\n const labels = useKitLabels(\"companySwitcher\", DEFAULT_COMPANY_SWITCHER_LABELS, labelsProp);\n const [pending, setPending] = useState(false);\n const { announce, regionProps } = useAnnounce();\n if (companies.length < 2) return null;\n\n const current = companies.find((c) => c.id === currentId);\n const select = (value: string) => {\n if (pending) return;\n const picked = companies.find((c) => String(c.id) === value);\n if (!picked || picked.id === currentId) return;\n const result = onSwitch(picked.id);\n if (typeof (result as PromiseLike<unknown> | undefined)?.then !== \"function\") return;\n setPending(true);\n announce(labels.switching);\n (result as PromiseLike<unknown>).then(\n () => setPending(false),\n () => setPending(false),\n );\n };\n\n return (\n <>\n {pending ? (\n <button\n type=\"button\"\n disabled\n aria-busy=\"true\"\n aria-label={labels.switchCompany}\n className={cn(TOPBAR_TRIGGER_CLASS, \"cursor-wait opacity-60 hover:bg-transparent\")}\n >\n <Spinner label={null} />\n </button>\n ) : (\n <OptionSwitcherMenu<string>\n ariaLabel={labels.switchCompany}\n title={current ? labels.current(current.name) : undefined}\n heading={labels.heading}\n icon={icon ?? <Building2 className=\"size-5\" />}\n options={companies.map((c) => ({\n value: String(c.id),\n label:\n c.id === currentId ? (\n // `relative`: the sr-only mark needs a local containing block.\n <span className=\"relative\">\n {c.name}\n <span className=\"sr-only\"> {labels.currentMark}</span>\n </span>\n ) : (\n c.name\n ),\n }))}\n value={String(currentId)}\n onSelect={select}\n />\n )}\n {/* Outside both triggers, so it survives the swap and is read when it changes. */}\n <span {...regionProps} />\n </>\n );\n}\n"],"mappings":";AAqGI,mBASM,KAeQ,YAxBd;AArGJ,SAAS,gBAAgB;AAEzB,SAAS,iBAAiB;AAC1B,SAAS,UAAU;AACnB,SAAS,oBAAoB;AAC7B,SAAS,mBAAmB;AAC5B,SAAS,eAAe;AACxB,SAAS,0BAA0B;AACnC,SAAS,4BAA4B;AAiB9B,MAAM,kCAAyD;AAAA,EACpE,eAAe;AAAA,EACf,SAAS;AAAA,EACT,SAAS,CAAC,SAAS,YAAY,IAAI;AAAA,EACnC,aAAa;AAAA,EACb,WAAW;AACb;AA0CO,SAAS,gBAA4C;AAAA,EAC1D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AACV,GAA6B;AAC3B,QAAM,SAAS,aAAa,mBAAmB,iCAAiC,UAAU;AAC1F,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAC5C,QAAM,EAAE,UAAU,YAAY,IAAI,YAAY;AAC9C,MAAI,UAAU,SAAS,EAAG,QAAO;AAEjC,QAAM,UAAU,UAAU,KAAK,CAAC,MAAM,EAAE,OAAO,SAAS;AACxD,QAAM,SAAS,CAAC,UAAkB;AAChC,QAAI,QAAS;AACb,UAAM,SAAS,UAAU,KAAK,CAAC,MAAM,OAAO,EAAE,EAAE,MAAM,KAAK;AAC3D,QAAI,CAAC,UAAU,OAAO,OAAO,UAAW;AACxC,UAAM,SAAS,SAAS,OAAO,EAAE;AACjC,QAAI,OAAQ,QAA6C,SAAS,WAAY;AAC9E,eAAW,IAAI;AACf,aAAS,OAAO,SAAS;AACzB,IAAC,OAAgC;AAAA,MAC/B,MAAM,WAAW,KAAK;AAAA,MACtB,MAAM,WAAW,KAAK;AAAA,IACxB;AAAA,EACF;AAEA,SACE,iCACG;AAAA,cACC;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,UAAQ;AAAA,QACR,aAAU;AAAA,QACV,cAAY,OAAO;AAAA,QACnB,WAAW,GAAG,sBAAsB,6CAA6C;AAAA,QAEjF,8BAAC,WAAQ,OAAO,MAAM;AAAA;AAAA,IACxB,IAEA;AAAA,MAAC;AAAA;AAAA,QACC,WAAW,OAAO;AAAA,QAClB,OAAO,UAAU,OAAO,QAAQ,QAAQ,IAAI,IAAI;AAAA,QAChD,SAAS,OAAO;AAAA,QAChB,MAAM,QAAQ,oBAAC,aAAU,WAAU,UAAS;AAAA,QAC5C,SAAS,UAAU,IAAI,CAAC,OAAO;AAAA,UAC7B,OAAO,OAAO,EAAE,EAAE;AAAA,UAClB,OACE,EAAE,OAAO;AAAA;AAAA,YAEP,qBAAC,UAAK,WAAU,YACb;AAAA,gBAAE;AAAA,cACH,qBAAC,UAAK,WAAU,WAAU;AAAA;AAAA,gBAAE,OAAO;AAAA,iBAAY;AAAA,eACjD;AAAA,cAEA,EAAE;AAAA,QAER,EAAE;AAAA,QACF,OAAO,OAAO,SAAS;AAAA,QACvB,UAAU;AAAA;AAAA,IACZ;AAAA,IAGF,oBAAC,UAAM,GAAG,aAAa;AAAA,KACzB;AAEJ;","names":[]}
@@ -1,6 +1,6 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
- import { dl as KitLinkProps, dk as KitLinkComponent } from '../kit-labels-SBN0biPl.js';
3
+ import { dq as KitLinkProps, dp as KitLinkComponent } from '../register-form-V1OeNlMr.js';
4
4
  import '../data-table-labels-DUELeXpa.js';
5
5
  import '../components/data-table-sort.js';
6
6
  import '../components/swipeable-row.js';
@@ -13,6 +13,7 @@ import '../components/field-sync.js';
13
13
  import '../components/tooltip.js';
14
14
  import '../hooks/use-anchored-rect.js';
15
15
  import '../lib/clipping.js';
16
+ import '../components/field-parts.js';
16
17
  import '../wizard/types.js';
17
18
  import '../tour/tour.js';
18
19
  import '../search/command-palette.js';
@@ -34,6 +35,7 @@ import '../components/modal.js';
34
35
  import '../hooks/use-search-param-state.js';
35
36
  import '../components/measured-grid.js';
36
37
  import '../components/user-avatar.js';
38
+ import '../lib/person-name.js';
37
39
  import '../components/status-dot.js';
38
40
  import '../components/progress-bar.js';
39
41
  import '../components/signed-amount.js';
@@ -53,6 +55,15 @@ import '../components/authed-image.js';
53
55
  import '../components/image-grid.js';
54
56
  import '../components/lightbox.js';
55
57
  import '../components/write-lock.js';
58
+ import '../auth/sign-in-form.js';
59
+ import '../auth/complete-name-dialog.js';
60
+ import '../auth/forgot-password-form.js';
61
+ import '../auth/status-parts.js';
62
+ import '../auth/reset-password-form.js';
63
+ import '../auth/verify-email.js';
64
+ import '../auth/not-found-page.js';
65
+ import '../auth/accept-invitation.js';
66
+ import './company-switcher.js';
56
67
  import '../components/account-chips.js';
57
68
  import '../lib/format.js';
58
69
  import '../components/reauth-dialog.js';
@@ -68,7 +79,12 @@ import '../components/sign-chip.js';
68
79
  import '../components/column-mapper.js';
69
80
  import '../lib/column-mapping.js';
70
81
  import '../lib/table-text.js';
71
- import '../components/field-parts.js';
82
+ import './topbar-controls.js';
83
+ import '../theme/palette-presets.js';
84
+ import '../theme/chart-palette.js';
85
+ import '../theme/theme-store.js';
86
+ import 'zustand/middleware';
87
+ import 'zustand';
72
88
 
73
89
  interface TopBarBrandProps extends Omit<KitLinkProps, "href" | "children"> {
74
90
  /** The brand mark — an SVG, sized by the caller or `h-6 w-auto` by default. */
@@ -3,6 +3,7 @@ import { ReactNode } from 'react';
3
3
  import { MenuItemTone } from '../components/menu-item.js';
4
4
  import { UserAvatarBadge } from '../components/user-avatar.js';
5
5
  import 'lucide-react';
6
+ import '../lib/person-name.js';
6
7
  import '../components/status-dot.js';
7
8
  import '../components/progress-bar.js';
8
9
  import '../components/signed-amount.js';
package/dist/shell.d.ts CHANGED
@@ -13,7 +13,7 @@ import './theme/theme-store.js';
13
13
  import 'zustand/middleware';
14
14
  import 'zustand';
15
15
  import 'lucide-react';
16
- import './kit-labels-SBN0biPl.js';
16
+ import './register-form-V1OeNlMr.js';
17
17
  import './data-table-labels-DUELeXpa.js';
18
18
  import './components/data-table-sort.js';
19
19
  import './components/swipeable-row.js';
@@ -25,6 +25,7 @@ import './components/field-sync.js';
25
25
  import './components/tooltip.js';
26
26
  import './hooks/use-anchored-rect.js';
27
27
  import './lib/clipping.js';
28
+ import './components/field-parts.js';
28
29
  import './wizard/types.js';
29
30
  import './tour/tour.js';
30
31
  import './search/command-palette.js';
@@ -46,6 +47,7 @@ import './components/modal.js';
46
47
  import './hooks/use-search-param-state.js';
47
48
  import './components/measured-grid.js';
48
49
  import './components/user-avatar.js';
50
+ import './lib/person-name.js';
49
51
  import './components/status-dot.js';
50
52
  import './components/progress-bar.js';
51
53
  import './components/signed-amount.js';
@@ -63,6 +65,15 @@ import './components/authed-image.js';
63
65
  import './components/image-grid.js';
64
66
  import './components/lightbox.js';
65
67
  import './components/write-lock.js';
68
+ import './auth/sign-in-form.js';
69
+ import './auth/complete-name-dialog.js';
70
+ import './auth/forgot-password-form.js';
71
+ import './auth/status-parts.js';
72
+ import './auth/reset-password-form.js';
73
+ import './auth/verify-email.js';
74
+ import './auth/not-found-page.js';
75
+ import './auth/accept-invitation.js';
76
+ import './shell/company-switcher.js';
66
77
  import './components/account-chips.js';
67
78
  import './lib/format.js';
68
79
  import './components/reauth-dialog.js';
@@ -78,5 +89,4 @@ import './components/sign-chip.js';
78
89
  import './components/column-mapper.js';
79
90
  import './lib/column-mapping.js';
80
91
  import './lib/table-text.js';
81
- import './components/field-parts.js';
82
92
  import './components/menu-item.js';
@@ -1,6 +1,6 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode, ReactElement } from 'react';
3
- import { bA as ButtonVariant } from '../kit-labels-SBN0biPl.js';
3
+ import { bA as ButtonVariant } from '../register-form-V1OeNlMr.js';
4
4
  import { UseWizardReturn, WizardLabels } from './types.js';
5
5
  import '../data-table-labels-DUELeXpa.js';
6
6
  import '../components/data-table-sort.js';
@@ -14,6 +14,7 @@ import '../components/field-sync.js';
14
14
  import '../components/tooltip.js';
15
15
  import '../hooks/use-anchored-rect.js';
16
16
  import '../lib/clipping.js';
17
+ import '../components/field-parts.js';
17
18
  import '../tour/tour.js';
18
19
  import '../search/command-palette.js';
19
20
  import '../search/global-search.js';
@@ -34,6 +35,7 @@ import '../components/modal.js';
34
35
  import '../hooks/use-search-param-state.js';
35
36
  import '../components/measured-grid.js';
36
37
  import '../components/user-avatar.js';
38
+ import '../lib/person-name.js';
37
39
  import '../components/status-dot.js';
38
40
  import '../components/progress-bar.js';
39
41
  import '../components/signed-amount.js';
@@ -53,6 +55,15 @@ import '../components/authed-image.js';
53
55
  import '../components/image-grid.js';
54
56
  import '../components/lightbox.js';
55
57
  import '../components/write-lock.js';
58
+ import '../auth/sign-in-form.js';
59
+ import '../auth/complete-name-dialog.js';
60
+ import '../auth/forgot-password-form.js';
61
+ import '../auth/status-parts.js';
62
+ import '../auth/reset-password-form.js';
63
+ import '../auth/verify-email.js';
64
+ import '../auth/not-found-page.js';
65
+ import '../auth/accept-invitation.js';
66
+ import '../shell/company-switcher.js';
56
67
  import '../components/account-chips.js';
57
68
  import '../lib/format.js';
58
69
  import '../components/reauth-dialog.js';
@@ -68,7 +79,12 @@ import '../components/sign-chip.js';
68
79
  import '../components/column-mapper.js';
69
80
  import '../lib/column-mapping.js';
70
81
  import '../lib/table-text.js';
71
- import '../components/field-parts.js';
82
+ import '../shell/topbar-controls.js';
83
+ import '../theme/palette-presets.js';
84
+ import '../theme/chart-palette.js';
85
+ import '../theme/theme-store.js';
86
+ import 'zustand/middleware';
87
+ import 'zustand';
72
88
 
73
89
  /**
74
90
  * The chrome around a wizard: the step indicator, the step content, and the
package/dist/wizard.d.ts CHANGED
@@ -6,7 +6,7 @@ export { WizardStep, WizardStepProps } from './wizard/wizard-step.js';
6
6
  export { WizardSummary } from './wizard/wizard-summary.js';
7
7
  export { StepperNav } from './wizard/stepper-nav.js';
8
8
  import 'react';
9
- import './kit-labels-SBN0biPl.js';
9
+ import './register-form-V1OeNlMr.js';
10
10
  import './data-table-labels-DUELeXpa.js';
11
11
  import './components/data-table-sort.js';
12
12
  import './components/swipeable-row.js';
@@ -19,6 +19,7 @@ import './components/field-sync.js';
19
19
  import './components/tooltip.js';
20
20
  import './hooks/use-anchored-rect.js';
21
21
  import './lib/clipping.js';
22
+ import './components/field-parts.js';
22
23
  import './tour/tour.js';
23
24
  import './search/command-palette.js';
24
25
  import './search/global-search.js';
@@ -39,6 +40,7 @@ import './components/modal.js';
39
40
  import './hooks/use-search-param-state.js';
40
41
  import './components/measured-grid.js';
41
42
  import './components/user-avatar.js';
43
+ import './lib/person-name.js';
42
44
  import './components/status-dot.js';
43
45
  import './components/progress-bar.js';
44
46
  import './components/signed-amount.js';
@@ -58,6 +60,15 @@ import './components/authed-image.js';
58
60
  import './components/image-grid.js';
59
61
  import './components/lightbox.js';
60
62
  import './components/write-lock.js';
63
+ import './auth/sign-in-form.js';
64
+ import './auth/complete-name-dialog.js';
65
+ import './auth/forgot-password-form.js';
66
+ import './auth/status-parts.js';
67
+ import './auth/reset-password-form.js';
68
+ import './auth/verify-email.js';
69
+ import './auth/not-found-page.js';
70
+ import './auth/accept-invitation.js';
71
+ import './shell/company-switcher.js';
61
72
  import './components/account-chips.js';
62
73
  import './lib/format.js';
63
74
  import './components/reauth-dialog.js';
@@ -73,4 +84,9 @@ import './components/sign-chip.js';
73
84
  import './components/column-mapper.js';
74
85
  import './lib/column-mapping.js';
75
86
  import './lib/table-text.js';
76
- import './components/field-parts.js';
87
+ import './shell/topbar-controls.js';
88
+ import './theme/palette-presets.js';
89
+ import './theme/chart-palette.js';
90
+ import './theme/theme-store.js';
91
+ import 'zustand/middleware';
92
+ import 'zustand';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eifi1/ui-kit",
3
- "version": "0.28.0",
3
+ "version": "0.29.0",
4
4
  "type": "module",
5
5
  "description": "App-agnostic shared design system: domain-free React components, theme and tokens.",
6
6
  "_sideEffects": "The barrel (src/index.ts) re-exports EVERY component, including components/chart, which statically imports recharts. Without this field a bundler must assume each of those modules has side effects, so it cannot drop the unused ones: importing a Button from '@eifi1/ui-kit' dragged all 433KB of recharts into the consumer's ENTRY chunk, and Keksdose was preloading it on every page load, login included. Nothing in src/ imports for side effects (no bare imports, no CSS imports from JS, no module-level global writes) — the token stylesheet is its own './tokens.css' export — so this is safe. CSS is still listed so any future stylesheet survives. Re-checked when `flag-icons` left `dependencies` and tsup started emitting a `\"use client\"` banner: neither touches this. The flag stylesheet was never imported from JS in the first place (that was the finding), and a directive prologue is a string literal every bundler lifts out before it decides whether a module is inert.",