@better-forge/ui 0.0.0-stage → 0.1.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 (234) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +13 -3
  3. package/dist/api/client.d.ts +42 -0
  4. package/dist/api/client.d.ts.map +1 -0
  5. package/dist/api/client.js +130 -0
  6. package/dist/api/client.js.map +1 -0
  7. package/dist/components/ConfirmIdentityModal.d.ts +18 -0
  8. package/dist/components/ConfirmIdentityModal.d.ts.map +1 -0
  9. package/dist/components/ConfirmIdentityModal.js +30 -0
  10. package/dist/components/ConfirmIdentityModal.js.map +1 -0
  11. package/dist/components/ConfirmModal.d.ts +18 -0
  12. package/dist/components/ConfirmModal.d.ts.map +1 -0
  13. package/dist/components/ConfirmModal.js +11 -0
  14. package/dist/components/ConfirmModal.js.map +1 -0
  15. package/dist/components/CopyButton.d.ts +11 -0
  16. package/dist/components/CopyButton.d.ts.map +1 -0
  17. package/dist/components/CopyButton.js +44 -0
  18. package/dist/components/CopyButton.js.map +1 -0
  19. package/dist/components/CredentialSection.d.ts +38 -0
  20. package/dist/components/CredentialSection.d.ts.map +1 -0
  21. package/dist/components/CredentialSection.js +69 -0
  22. package/dist/components/CredentialSection.js.map +1 -0
  23. package/dist/components/ErrorBoundary.d.ts +18 -0
  24. package/dist/components/ErrorBoundary.d.ts.map +1 -0
  25. package/dist/components/ErrorBoundary.js +25 -0
  26. package/dist/components/ErrorBoundary.js.map +1 -0
  27. package/dist/components/ModalShell.d.ts +58 -0
  28. package/dist/components/ModalShell.d.ts.map +1 -0
  29. package/dist/components/ModalShell.js +92 -0
  30. package/dist/components/ModalShell.js.map +1 -0
  31. package/dist/components/ResetTwoFactorModal.d.ts +14 -0
  32. package/dist/components/ResetTwoFactorModal.d.ts.map +1 -0
  33. package/dist/components/ResetTwoFactorModal.js +16 -0
  34. package/dist/components/ResetTwoFactorModal.js.map +1 -0
  35. package/dist/components/SidePanel.d.ts +35 -0
  36. package/dist/components/SidePanel.d.ts.map +1 -0
  37. package/dist/components/SidePanel.js +19 -0
  38. package/dist/components/SidePanel.js.map +1 -0
  39. package/dist/components/SingleSignOnModal.d.ts +4 -0
  40. package/dist/components/SingleSignOnModal.d.ts.map +1 -0
  41. package/dist/components/SingleSignOnModal.js +64 -0
  42. package/dist/components/SingleSignOnModal.js.map +1 -0
  43. package/dist/components/SsoConfirmation.d.ts +22 -0
  44. package/dist/components/SsoConfirmation.d.ts.map +1 -0
  45. package/dist/components/SsoConfirmation.js +87 -0
  46. package/dist/components/SsoConfirmation.js.map +1 -0
  47. package/dist/components/VaultTypePicker.d.ts +13 -0
  48. package/dist/components/VaultTypePicker.d.ts.map +1 -0
  49. package/dist/components/VaultTypePicker.js +62 -0
  50. package/dist/components/VaultTypePicker.js.map +1 -0
  51. package/dist/components/WhatsNew.d.ts +18 -0
  52. package/dist/components/WhatsNew.d.ts.map +1 -0
  53. package/dist/components/WhatsNew.js +50 -0
  54. package/dist/components/WhatsNew.js.map +1 -0
  55. package/dist/components/formParts.d.ts +40 -0
  56. package/dist/components/formParts.d.ts.map +1 -0
  57. package/dist/components/formParts.js +31 -0
  58. package/dist/components/formParts.js.map +1 -0
  59. package/dist/components/ui/Alert.d.ts +15 -0
  60. package/dist/components/ui/Alert.d.ts.map +1 -0
  61. package/dist/components/ui/Alert.js +14 -0
  62. package/dist/components/ui/Alert.js.map +1 -0
  63. package/dist/components/ui/DataTable.d.ts +52 -0
  64. package/dist/components/ui/DataTable.d.ts.map +1 -0
  65. package/dist/components/ui/DataTable.js +112 -0
  66. package/dist/components/ui/DataTable.js.map +1 -0
  67. package/dist/components/ui/Field.d.ts +27 -0
  68. package/dist/components/ui/Field.d.ts.map +1 -0
  69. package/dist/components/ui/Field.js +25 -0
  70. package/dist/components/ui/Field.js.map +1 -0
  71. package/dist/components/ui/PageHeader.d.ts +18 -0
  72. package/dist/components/ui/PageHeader.d.ts.map +1 -0
  73. package/dist/components/ui/PageHeader.js +10 -0
  74. package/dist/components/ui/PageHeader.js.map +1 -0
  75. package/dist/components/ui/Pagination.d.ts +21 -0
  76. package/dist/components/ui/Pagination.d.ts.map +1 -0
  77. package/dist/components/ui/Pagination.js +10 -0
  78. package/dist/components/ui/Pagination.js.map +1 -0
  79. package/dist/components/ui/QuickStartPanel.d.ts +21 -0
  80. package/dist/components/ui/QuickStartPanel.d.ts.map +1 -0
  81. package/dist/components/ui/QuickStartPanel.js +11 -0
  82. package/dist/components/ui/QuickStartPanel.js.map +1 -0
  83. package/dist/components/ui/StateViews.d.ts +50 -0
  84. package/dist/components/ui/StateViews.d.ts.map +1 -0
  85. package/dist/components/ui/StateViews.js +33 -0
  86. package/dist/components/ui/StateViews.js.map +1 -0
  87. package/dist/components/ui/Switch.d.ts +16 -0
  88. package/dist/components/ui/Switch.d.ts.map +1 -0
  89. package/dist/components/ui/Switch.js +15 -0
  90. package/dist/components/ui/Switch.js.map +1 -0
  91. package/dist/components/ui/Toast.d.ts +20 -0
  92. package/dist/components/ui/Toast.d.ts.map +1 -0
  93. package/dist/components/ui/Toast.js +46 -0
  94. package/dist/components/ui/Toast.js.map +1 -0
  95. package/dist/components/ui/index.d.ts +10 -0
  96. package/dist/components/ui/index.d.ts.map +1 -0
  97. package/dist/components/ui/index.js +10 -0
  98. package/dist/components/ui/index.js.map +1 -0
  99. package/dist/config.d.ts +46 -0
  100. package/dist/config.d.ts.map +1 -0
  101. package/dist/config.js +12 -0
  102. package/dist/config.js.map +1 -0
  103. package/dist/hooks/useDarkMode.d.ts +2 -0
  104. package/dist/hooks/useDarkMode.d.ts.map +1 -0
  105. package/dist/hooks/useDarkMode.js +37 -0
  106. package/dist/hooks/useDarkMode.js.map +1 -0
  107. package/dist/hooks/useDebouncedValue.d.ts +6 -0
  108. package/dist/hooks/useDebouncedValue.d.ts.map +1 -0
  109. package/dist/hooks/useDebouncedValue.js +19 -0
  110. package/dist/hooks/useDebouncedValue.js.map +1 -0
  111. package/dist/index.d.ts +36 -0
  112. package/dist/index.d.ts.map +1 -0
  113. package/dist/index.js +36 -0
  114. package/dist/index.js.map +1 -0
  115. package/dist/lib/changelog.d.ts +32 -0
  116. package/dist/lib/changelog.d.ts.map +1 -0
  117. package/dist/lib/changelog.js +71 -0
  118. package/dist/lib/changelog.js.map +1 -0
  119. package/dist/lib/dateFormat.d.ts +24 -0
  120. package/dist/lib/dateFormat.d.ts.map +1 -0
  121. package/dist/lib/dateFormat.js +67 -0
  122. package/dist/lib/dateFormat.js.map +1 -0
  123. package/dist/navigation.d.ts +5 -0
  124. package/dist/navigation.d.ts.map +1 -0
  125. package/dist/navigation.js +7 -0
  126. package/dist/navigation.js.map +1 -0
  127. package/dist/pages/ApiTokens.d.ts +9 -0
  128. package/dist/pages/ApiTokens.d.ts.map +1 -0
  129. package/dist/pages/ApiTokens.js +116 -0
  130. package/dist/pages/ApiTokens.js.map +1 -0
  131. package/dist/pages/AuditLog.d.ts +14 -0
  132. package/dist/pages/AuditLog.d.ts.map +1 -0
  133. package/dist/pages/AuditLog.js +104 -0
  134. package/dist/pages/AuditLog.js.map +1 -0
  135. package/dist/pages/Backups.d.ts +2 -0
  136. package/dist/pages/Backups.d.ts.map +1 -0
  137. package/dist/pages/Backups.js +118 -0
  138. package/dist/pages/Backups.js.map +1 -0
  139. package/dist/pages/ChangePassword.d.ts +2 -0
  140. package/dist/pages/ChangePassword.d.ts.map +1 -0
  141. package/dist/pages/ChangePassword.js +40 -0
  142. package/dist/pages/ChangePassword.js.map +1 -0
  143. package/dist/pages/Login.d.ts +12 -0
  144. package/dist/pages/Login.d.ts.map +1 -0
  145. package/dist/pages/Login.js +69 -0
  146. package/dist/pages/Login.js.map +1 -0
  147. package/dist/pages/Settings.d.ts +2 -0
  148. package/dist/pages/Settings.d.ts.map +1 -0
  149. package/dist/pages/Settings.js +149 -0
  150. package/dist/pages/Settings.js.map +1 -0
  151. package/dist/pages/Setup.d.ts +2 -0
  152. package/dist/pages/Setup.d.ts.map +1 -0
  153. package/dist/pages/Setup.js +113 -0
  154. package/dist/pages/Setup.js.map +1 -0
  155. package/dist/pages/SsoConfirm.d.ts +3 -0
  156. package/dist/pages/SsoConfirm.d.ts.map +1 -0
  157. package/dist/pages/SsoConfirm.js +20 -0
  158. package/dist/pages/SsoConfirm.js.map +1 -0
  159. package/dist/pages/SsoTestResult.d.ts +2 -0
  160. package/dist/pages/SsoTestResult.d.ts.map +1 -0
  161. package/dist/pages/SsoTestResult.js +49 -0
  162. package/dist/pages/SsoTestResult.js.map +1 -0
  163. package/dist/pages/Users.d.ts +22 -0
  164. package/dist/pages/Users.d.ts.map +1 -0
  165. package/dist/pages/Users.js +124 -0
  166. package/dist/pages/Users.js.map +1 -0
  167. package/dist/pages/Vault.d.ts +2 -0
  168. package/dist/pages/Vault.d.ts.map +1 -0
  169. package/dist/pages/Vault.js +372 -0
  170. package/dist/pages/Vault.js.map +1 -0
  171. package/dist/shell/AdminShell.d.ts +46 -0
  172. package/dist/shell/AdminShell.d.ts.map +1 -0
  173. package/dist/shell/AdminShell.js +76 -0
  174. package/dist/shell/AdminShell.js.map +1 -0
  175. package/dist/shell/guards.d.ts +28 -0
  176. package/dist/shell/guards.d.ts.map +1 -0
  177. package/dist/shell/guards.js +71 -0
  178. package/dist/shell/guards.js.map +1 -0
  179. package/icons.json +170 -0
  180. package/package.json +71 -6
  181. package/src/api/client.ts +139 -0
  182. package/src/components/ConfirmIdentityModal.tsx +82 -0
  183. package/src/components/ConfirmModal.tsx +83 -0
  184. package/src/components/CopyButton.tsx +71 -0
  185. package/src/components/CredentialSection.tsx +270 -0
  186. package/src/components/ErrorBoundary.tsx +47 -0
  187. package/src/components/ModalShell.tsx +160 -0
  188. package/src/components/ResetTwoFactorModal.tsx +74 -0
  189. package/src/components/SidePanel.tsx +96 -0
  190. package/src/components/SingleSignOnModal.tsx +161 -0
  191. package/src/components/SsoConfirmation.tsx +96 -0
  192. package/src/components/VaultTypePicker.tsx +131 -0
  193. package/src/components/WhatsNew.tsx +84 -0
  194. package/src/components/formParts.tsx +59 -0
  195. package/src/components/ui/Alert.tsx +45 -0
  196. package/src/components/ui/DataTable.tsx +225 -0
  197. package/src/components/ui/Field.tsx +63 -0
  198. package/src/components/ui/PageHeader.tsx +36 -0
  199. package/src/components/ui/Pagination.tsx +37 -0
  200. package/src/components/ui/QuickStartPanel.tsx +57 -0
  201. package/src/components/ui/StateViews.tsx +135 -0
  202. package/src/components/ui/Switch.tsx +65 -0
  203. package/src/components/ui/Toast.tsx +104 -0
  204. package/src/components/ui/index.ts +9 -0
  205. package/src/config.ts +46 -0
  206. package/src/hooks/useDarkMode.ts +38 -0
  207. package/src/hooks/useDebouncedValue.ts +22 -0
  208. package/src/index.ts +42 -0
  209. package/src/lib/changelog.ts +93 -0
  210. package/src/lib/dateFormat.ts +90 -0
  211. package/src/navigation.ts +6 -0
  212. package/src/pages/ApiTokens.tsx +361 -0
  213. package/src/pages/AuditLog.tsx +388 -0
  214. package/src/pages/Backups.tsx +170 -0
  215. package/src/pages/ChangePassword.tsx +84 -0
  216. package/src/pages/Login.tsx +275 -0
  217. package/src/pages/Settings.tsx +264 -0
  218. package/src/pages/Setup.tsx +438 -0
  219. package/src/pages/SsoConfirm.tsx +26 -0
  220. package/src/pages/SsoTestResult.tsx +104 -0
  221. package/src/pages/Users.tsx +426 -0
  222. package/src/pages/Vault.tsx +1036 -0
  223. package/src/shell/AdminShell.tsx +256 -0
  224. package/src/shell/guards.tsx +88 -0
  225. package/styles/base.css +521 -0
  226. package/styles/fonts/inter-latin-1.woff2 +0 -0
  227. package/styles/fonts/inter-latin-ext.woff2 +0 -0
  228. package/styles/fonts/jetbrains-mono-latin-3.woff2 +0 -0
  229. package/styles/fonts/jetbrains-mono-latin-ext-2.woff2 +0 -0
  230. package/styles/fonts/manrope-latin-5.woff2 +0 -0
  231. package/styles/fonts/manrope-latin-ext-4.woff2 +0 -0
  232. package/styles/fonts/material-symbols-outlined-fill.woff2 +0 -0
  233. package/styles/icons.css +4 -0
  234. package/tailwind-preset.js +79 -0
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useId } from 'react';
3
+ /**
4
+ * First-run panel shown in place of an empty list when the first step is a choice, e.g. which kind of
5
+ * channel to create. Each tile starts the create flow with that choice already made.
6
+ */
7
+ export function QuickStartPanel({ title, description, options, onPick }) {
8
+ const titleId = useId();
9
+ return (_jsxs("section", { "aria-labelledby": titleId, className: "rounded-2xl p-5 space-y-4", style: { background: 'var(--m3-surface-container-low)', border: '1px solid var(--m3-outline-variant)' }, children: [_jsxs("div", { className: "space-y-0.5", children: [_jsx("h2", { id: titleId, className: "font-headline font-semibold text-[15px]", style: { color: 'var(--m3-on-surface)' }, children: title }), description && _jsx("p", { className: "text-[13px]", style: { color: 'var(--m3-secondary)' }, children: description })] }), _jsx("ul", { className: "grid gap-2.5 grid-cols-[repeat(auto-fill,minmax(150px,1fr))]", children: options.map((option) => (_jsx("li", { children: _jsxs("button", { type: "button", onClick: () => onPick(option.key), className: "w-full h-full grid gap-2 content-start text-left rounded-[14px] p-3.5 border border-outline-variant bg-surface text-on-surface hover:border-outline hover:bg-surface-container-lowest motion-safe:transition-colors focus-ring", children: [_jsx("span", { className: "grid place-items-center w-[34px] h-[34px] rounded-[10px]", "aria-hidden": "true", style: { background: 'var(--admin-icon-container)', color: 'var(--admin-icon-color)' }, children: option.icon }), _jsx("span", { className: "text-[13px] font-semibold", children: option.label }), _jsx("span", { className: "text-xs", style: { color: 'var(--m3-secondary)' }, children: option.hint })] }) }, option.key))) })] }));
10
+ }
11
+ //# sourceMappingURL=QuickStartPanel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QuickStartPanel.js","sourceRoot":"","sources":["../../../src/components/ui/QuickStartPanel.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,EAAkB,MAAM,OAAO,CAAA;AAiB7C;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAmB,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAA2B;IAChH,MAAM,OAAO,GAAG,KAAK,EAAE,CAAA;IACvB,OAAO,CACL,sCACmB,OAAO,EACxB,SAAS,EAAC,2BAA2B,EACrC,KAAK,EAAE,EAAE,UAAU,EAAE,iCAAiC,EAAE,MAAM,EAAE,qCAAqC,EAAE,aAEvG,eAAK,SAAS,EAAC,aAAa,aAC1B,aAAI,EAAE,EAAE,OAAO,EAAE,SAAS,EAAC,yCAAyC,EAAC,KAAK,EAAE,EAAE,KAAK,EAAE,sBAAsB,EAAE,YAAG,KAAK,GAAM,EAC1H,WAAW,IAAI,YAAG,SAAS,EAAC,aAAa,EAAC,KAAK,EAAE,EAAE,KAAK,EAAE,qBAAqB,EAAE,YAAG,WAAW,GAAK,IACjG,EACN,aAAI,SAAS,EAAC,8DAA8D,YACzE,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CACvB,uBACE,kBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EACjC,SAAS,EAAC,gOAAgO,aAE1O,eACE,SAAS,EAAC,0DAA0D,iBACxD,MAAM,EAClB,KAAK,EAAE,EAAE,UAAU,EAAE,6BAA6B,EAAE,KAAK,EAAE,yBAAyB,EAAE,YAErF,MAAM,CAAC,IAAI,GACP,EACP,eAAM,SAAS,EAAC,2BAA2B,YAAE,MAAM,CAAC,KAAK,GAAQ,EACjE,eAAM,SAAS,EAAC,SAAS,EAAC,KAAK,EAAE,EAAE,KAAK,EAAE,qBAAqB,EAAE,YAAG,MAAM,CAAC,IAAI,GAAQ,IAChF,IAfF,MAAM,CAAC,GAAG,CAgBd,CACN,CAAC,GACC,IACG,CACX,CAAA;AACH,CAAC"}
@@ -0,0 +1,50 @@
1
+ import type { ReactNode } from 'react';
2
+ interface LoadingStateProps {
3
+ label?: string | undefined;
4
+ className?: string | undefined;
5
+ }
6
+ /** Centered spinner with a caption for data that is still loading. */
7
+ export declare function LoadingState({ label, className }: LoadingStateProps): import("react").JSX.Element;
8
+ interface ErrorStateProps {
9
+ message?: ReactNode | undefined;
10
+ /** Renders a "Try again" button. Pass e.g. `() => void query.refetch()`. */
11
+ onRetry?: (() => void) | undefined;
12
+ className?: string | undefined;
13
+ }
14
+ /** Failed-to-load panel with an optional retry action. */
15
+ export declare function ErrorState({ message, onRetry, className }: ErrorStateProps): import("react").JSX.Element;
16
+ type EmptyStateVariant = 'card' | 'inset' | 'row';
17
+ interface EmptyStateProps {
18
+ title: ReactNode;
19
+ description?: ReactNode | undefined;
20
+ /** Material Symbols icon name, e.g. "radio_button_checked". */
21
+ icon?: string | undefined;
22
+ /**
23
+ * Optional follow-up action. Leave it out when the page header already offers the same action and
24
+ * put an `EmptyStateLink` in the description instead.
25
+ */
26
+ action?: ReactNode | undefined;
27
+ /**
28
+ * - `card` (default): a standalone compact strip, for pages without a table or list container.
29
+ * - `inset`: a row inside a card or list, separated from what is above it by a divider.
30
+ * - `row`: bare content for a table cell; use `EmptyTableRow` rather than this directly.
31
+ */
32
+ variant?: EmptyStateVariant | undefined;
33
+ className?: string | undefined;
34
+ }
35
+ /** Compact placeholder for an empty list: an icon, a short explanation and an optional action in one row. */
36
+ export declare function EmptyState({ title, description, icon, action, variant, className }: EmptyStateProps): import("react").JSX.Element;
37
+ interface EmptyTableRowProps extends Omit<EmptyStateProps, 'variant' | 'className'> {
38
+ /** Number of columns in the table, so the message spans the whole row. */
39
+ colSpan: number;
40
+ }
41
+ /** The only `<tbody>` row while a table has no data, so the table and its headers keep their place. */
42
+ export declare function EmptyTableRow({ colSpan, ...props }: EmptyTableRowProps): import("react").JSX.Element;
43
+ interface EmptyStateLinkProps {
44
+ onClick: () => void;
45
+ children: ReactNode;
46
+ }
47
+ /** Inline text action inside an empty-state description, e.g. "Alerts stay silent until you [add a channel]." */
48
+ export declare function EmptyStateLink({ onClick, children }: EmptyStateLinkProps): import("react").JSX.Element;
49
+ export {};
50
+ //# sourceMappingURL=StateViews.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StateViews.d.ts","sourceRoot":"","sources":["../../../src/components/ui/StateViews.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAA;AAErD,UAAU,iBAAiB;IACzB,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC/B;AAED,sEAAsE;AACtE,wBAAgB,YAAY,CAAC,EAAE,KAAkB,EAAE,SAAS,EAAE,EAAE,iBAAiB,+BAOhF;AAED,UAAU,eAAe;IACvB,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;IAC/B,4EAA4E;IAC5E,OAAO,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAA;IAClC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC/B;AAED,0DAA0D;AAC1D,wBAAgB,UAAU,CAAC,EAAE,OAAyD,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,eAAe,+BAiB5H;AAED,KAAK,iBAAiB,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAA;AAEjD,UAAU,eAAe;IACvB,KAAK,EAAE,SAAS,CAAA;IAChB,WAAW,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;IACnC,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACzB;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;IAC9B;;;;OAIG;IACH,OAAO,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAA;IACvC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC/B;AAcD,6GAA6G;AAC7G,wBAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,IAAc,EAAE,MAAM,EAAE,OAAgB,EAAE,SAAS,EAAE,EAAE,eAAe,+BAoBtH;AAED,UAAU,kBAAmB,SAAQ,IAAI,CAAC,eAAe,EAAE,SAAS,GAAG,WAAW,CAAC;IACjF,0EAA0E;IAC1E,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,uGAAuG;AACvG,wBAAgB,aAAa,CAAC,EAAE,OAAO,EAAE,GAAG,KAAK,EAAE,EAAE,kBAAkB,+BAQtE;AAED,UAAU,mBAAmB;IAC3B,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED,iHAAiH;AACjH,wBAAgB,cAAc,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,mBAAmB,+BAWxE"}
@@ -0,0 +1,33 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import clsx from 'clsx';
3
+ /** Centered spinner with a caption for data that is still loading. */
4
+ export function LoadingState({ label = 'Loading…', className }) {
5
+ return (_jsxs("div", { role: "status", "aria-live": "polite", className: clsx('flex items-center justify-center gap-3 py-12 text-sm', className), style: { color: 'var(--m3-secondary)' }, children: [_jsx("span", { className: "material-symbols-outlined animate-spin", "aria-hidden": "true", style: { fontSize: '20px' }, children: "progress_activity" }), _jsx("span", { children: label })] }));
6
+ }
7
+ /** Failed-to-load panel with an optional retry action. */
8
+ export function ErrorState({ message = 'Something went wrong while loading this data.', onRetry, className }) {
9
+ return (_jsxs("div", { role: "alert", className: clsx('flex flex-col items-center justify-center gap-3 rounded-2xl px-6 py-10 text-center', className), style: { background: 'var(--m3-down-bg)', color: 'var(--m3-down)' }, children: [_jsx("span", { className: "material-symbols-outlined", "aria-hidden": "true", style: { fontSize: '28px' }, children: "error" }), _jsx("p", { className: "text-sm max-w-md", children: message }), onRetry && (_jsxs("button", { type: "button", onClick: onRetry, className: "btn btn-secondary btn-sm", children: [_jsx("span", { className: "material-symbols-outlined", "aria-hidden": "true", children: "refresh" }), "Try again"] }))] }));
10
+ }
11
+ const EMPTY_VARIANT_CLASS = {
12
+ card: 'rounded-2xl px-5 py-4',
13
+ inset: 'px-6 py-5',
14
+ row: '',
15
+ };
16
+ const EMPTY_VARIANT_STYLE = {
17
+ card: { background: 'var(--m3-surface-container-low)', border: '1px solid var(--m3-outline-variant)' },
18
+ inset: { borderTop: '1px solid var(--m3-outline-variant)' },
19
+ row: undefined,
20
+ };
21
+ /** Compact placeholder for an empty list: an icon, a short explanation and an optional action in one row. */
22
+ export function EmptyState({ title, description, icon = 'inbox', action, variant = 'card', className }) {
23
+ return (_jsxs("div", { className: clsx('flex flex-wrap items-center gap-x-3.5 gap-y-3 text-left', EMPTY_VARIANT_CLASS[variant], className), style: EMPTY_VARIANT_STYLE[variant], children: [_jsx("span", { className: "grid place-items-center w-10 h-10 rounded-xl flex-none", "aria-hidden": "true", style: { background: 'var(--admin-icon-container)', color: 'var(--admin-icon-color)' }, children: _jsx("span", { className: "material-symbols-outlined", style: { fontSize: '20px' }, children: icon }) }), _jsxs("div", { className: "min-w-0 flex-[1_1_15rem] space-y-0.5", children: [_jsx("p", { className: "font-headline font-semibold text-sm", style: { color: 'var(--m3-on-surface)' }, children: title }), description && _jsx("p", { className: "text-[13px]", style: { color: 'var(--m3-secondary)' }, children: description })] }), action && _jsx("div", { className: "flex-none sm:ml-auto", children: action })] }));
24
+ }
25
+ /** The only `<tbody>` row while a table has no data, so the table and its headers keep their place. */
26
+ export function EmptyTableRow({ colSpan, ...props }) {
27
+ return (_jsx("tr", { children: _jsx("td", { colSpan: colSpan, className: "px-4 py-7", children: _jsx(EmptyState, { variant: "row", ...props }) }) }));
28
+ }
29
+ /** Inline text action inside an empty-state description, e.g. "Alerts stay silent until you [add a channel]." */
30
+ export function EmptyStateLink({ onClick, children }) {
31
+ return (_jsx("button", { type: "button", onClick: onClick, className: "font-semibold underline underline-offset-[3px] rounded focus-ring", style: { color: 'var(--m3-on-surface)' }, children: children }));
32
+ }
33
+ //# sourceMappingURL=StateViews.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StateViews.js","sourceRoot":"","sources":["../../../src/components/ui/StateViews.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { type ReactNode } from 'react';
2
+ interface SwitchProps {
3
+ checked: boolean;
4
+ onChange: (checked: boolean) => void;
5
+ /** Visible label; clicking it toggles the switch. Without it pass `aria-label`. */
6
+ label?: ReactNode | undefined;
7
+ description?: ReactNode | undefined;
8
+ disabled?: boolean | undefined;
9
+ id?: string | undefined;
10
+ 'aria-label'?: string | undefined;
11
+ className?: string | undefined;
12
+ }
13
+ /** On/off toggle rendered as <button role="switch">, optionally with a clickable label and a description. */
14
+ export declare function Switch({ checked, onChange, label, description, disabled, id, 'aria-label': ariaLabel, className }: SwitchProps): import("react").JSX.Element;
15
+ export {};
16
+ //# sourceMappingURL=Switch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Switch.d.ts","sourceRoot":"","sources":["../../../src/components/ui/Switch.tsx"],"names":[],"mappings":"AACA,OAAO,EAAS,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAE7C,UAAU,WAAW;IACnB,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;IACpC,mFAAmF;IACnF,KAAK,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;IAC7B,WAAW,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;IACnC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAC9B,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACvB,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACjC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC/B;AAED,6GAA6G;AAC7G,wBAAgB,MAAM,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,QAAgB,EAAE,EAAE,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,WAAW,+BAgDtI"}
@@ -0,0 +1,15 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import clsx from 'clsx';
3
+ import { useId } from 'react';
4
+ /** On/off toggle rendered as <button role="switch">, optionally with a clickable label and a description. */
5
+ export function Switch({ checked, onChange, label, description, disabled = false, id, 'aria-label': ariaLabel, className }) {
6
+ const generatedId = useId();
7
+ const switchId = id ?? generatedId;
8
+ const labelId = `${switchId}-label`;
9
+ const descriptionId = `${switchId}-description`;
10
+ const control = (_jsx("button", { id: switchId, type: "button", role: "switch", "aria-checked": checked, "aria-label": label ? undefined : ariaLabel, "aria-labelledby": label ? labelId : undefined, "aria-describedby": description ? descriptionId : undefined, disabled: disabled, onClick: () => onChange(!checked), className: "relative flex-shrink-0 w-12 h-7 rounded-full transition-colors focus-ring disabled:opacity-50 disabled:cursor-not-allowed", style: { background: checked ? 'var(--admin-control-accent)' : 'var(--m3-outline-variant)' }, children: _jsx("span", { "aria-hidden": "true", className: "absolute top-1 w-5 h-5 rounded-full transition-all", style: { left: checked ? '24px' : '4px', background: checked ? 'var(--admin-control-on)' : 'var(--m3-outline)' } }) }));
11
+ if (!label && !description)
12
+ return _jsx("span", { className: clsx('inline-flex', className), children: control });
13
+ return (_jsxs("div", { className: clsx('flex items-start justify-between gap-4', className), children: [_jsxs("div", { className: "min-w-0", children: [label && (_jsx("label", { id: labelId, htmlFor: switchId, className: clsx('block text-sm font-medium', disabled ? 'cursor-not-allowed' : 'cursor-pointer'), style: { color: 'var(--m3-on-surface)' }, children: label })), description && _jsx("p", { id: descriptionId, className: "text-xs mt-0.5", style: { color: 'var(--m3-secondary)' }, children: description })] }), control] }));
14
+ }
15
+ //# sourceMappingURL=Switch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Switch.js","sourceRoot":"","sources":["../../../src/components/ui/Switch.tsx"],"names":[],"mappings":";AAAA,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,KAAK,EAAkB,MAAM,OAAO,CAAA;AAc7C,6GAA6G;AAC7G,MAAM,UAAU,MAAM,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,GAAG,KAAK,EAAE,EAAE,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAe;IACrI,MAAM,WAAW,GAAG,KAAK,EAAE,CAAA;IAC3B,MAAM,QAAQ,GAAG,EAAE,IAAI,WAAW,CAAA;IAClC,MAAM,OAAO,GAAG,GAAG,QAAQ,QAAQ,CAAA;IACnC,MAAM,aAAa,GAAG,GAAG,QAAQ,cAAc,CAAA;IAE/C,MAAM,OAAO,GAAG,CACd,iBACE,EAAE,EAAE,QAAQ,EACZ,IAAI,EAAC,QAAQ,EACb,IAAI,EAAC,QAAQ,kBACC,OAAO,gBACT,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,qBACxB,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,sBAC1B,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,EACzD,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EACjC,SAAS,EAAC,2HAA2H,EACrI,KAAK,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,6BAA6B,CAAC,CAAC,CAAC,2BAA2B,EAAE,YAE5F,8BACc,MAAM,EAClB,SAAS,EAAC,oDAAoD,EAC9D,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,mBAAmB,EAAE,GAChH,GACK,CACV,CAAA;IAED,IAAI,CAAC,KAAK,IAAI,CAAC,WAAW;QAAE,OAAO,eAAM,SAAS,EAAE,IAAI,CAAC,aAAa,EAAE,SAAS,CAAC,YAAG,OAAO,GAAQ,CAAA;IAEpG,OAAO,CACL,eAAK,SAAS,EAAE,IAAI,CAAC,wCAAwC,EAAE,SAAS,CAAC,aACvE,eAAK,SAAS,EAAC,SAAS,aACrB,KAAK,IAAI,CACR,gBACE,EAAE,EAAE,OAAO,EACX,OAAO,EAAE,QAAQ,EACjB,SAAS,EAAE,IAAI,CAAC,2BAA2B,EAAE,QAAQ,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,gBAAgB,CAAC,EAChG,KAAK,EAAE,EAAE,KAAK,EAAE,sBAAsB,EAAE,YAEvC,KAAK,GACA,CACT,EACA,WAAW,IAAI,YAAG,EAAE,EAAE,aAAa,EAAE,SAAS,EAAC,gBAAgB,EAAC,KAAK,EAAE,EAAE,KAAK,EAAE,qBAAqB,EAAE,YAAG,WAAW,GAAK,IACvH,EACL,OAAO,IACJ,CACP,CAAA;AACH,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { type ReactNode } from 'react';
2
+ export type ToastTone = 'success' | 'error' | 'info';
3
+ export interface ToastOptions {
4
+ /** Milliseconds before it disappears on its own; 0 keeps it until dismissed. Default 4000. */
5
+ duration?: number | undefined;
6
+ }
7
+ export interface ToastApi {
8
+ success: (message: ReactNode, options?: ToastOptions) => number;
9
+ error: (message: ReactNode, options?: ToastOptions) => number;
10
+ info: (message: ReactNode, options?: ToastOptions) => number;
11
+ dismiss: (id: number) => void;
12
+ }
13
+ export declare const TOAST_DURATION = 4000;
14
+ /** `const toast = useToast(); toast.success('Saved')`. The returned object is stable across renders. */
15
+ export declare function useToast(): ToastApi;
16
+ /** Mount once near the root; renders the bottom-right toast stack above every modal. */
17
+ export declare function ToastProvider({ children }: {
18
+ children: ReactNode;
19
+ }): import("react").JSX.Element;
20
+ //# sourceMappingURL=Toast.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Toast.d.ts","sourceRoot":"","sources":["../../../src/components/ui/Toast.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAgF,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAIpH,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAA;AAEpD,MAAM,WAAW,YAAY;IAC3B,8FAA8F;IAC9F,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC9B;AAED,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,YAAY,KAAK,MAAM,CAAA;IAC/D,KAAK,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,YAAY,KAAK,MAAM,CAAA;IAC7D,IAAI,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,YAAY,KAAK,MAAM,CAAA;IAC5D,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;CAC9B;AAID,eAAO,MAAM,cAAc,OAAO,CAAA;AAOlC,wGAAwG;AACxG,wBAAgB,QAAQ,IAAI,QAAQ,CAEnC;AAsCD,wFAAwF;AACxF,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,+BAkClE"}
@@ -0,0 +1,46 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
3
+ import { createPortal } from 'react-dom';
4
+ import { MODAL_Z_INDEX } from '../ModalShell';
5
+ export const TOAST_DURATION = 4000;
6
+ const noop = { success: () => 0, error: () => 0, info: () => 0, dismiss: () => { } };
7
+ // Outside a provider (isolated component tests) toasts are silently dropped instead of throwing.
8
+ const ToastContext = createContext(noop);
9
+ /** `const toast = useToast(); toast.success('Saved')`. The returned object is stable across renders. */
10
+ export function useToast() {
11
+ return useContext(ToastContext);
12
+ }
13
+ const TONE_STYLE = {
14
+ success: { icon: 'check_circle', color: 'var(--m3-up)' },
15
+ error: { icon: 'error', color: 'var(--m3-down)' },
16
+ info: { icon: 'info', color: 'var(--m3-on-surface-variant)' },
17
+ };
18
+ function ToastItem({ toast, onDismiss }) {
19
+ const [paused, setPaused] = useState(false);
20
+ const { icon, color } = TONE_STYLE[toast.tone];
21
+ useEffect(() => {
22
+ if (paused || toast.duration <= 0)
23
+ return;
24
+ const timer = setTimeout(() => onDismiss(toast.id), toast.duration);
25
+ return () => clearTimeout(timer);
26
+ }, [paused, toast.duration, toast.id, onDismiss]);
27
+ return (_jsxs("div", { role: toast.tone === 'error' ? 'alert' : 'status', "data-tone": toast.tone, className: "admin-toast pointer-events-auto flex items-start gap-3 rounded-xl px-4 py-3 text-sm w-full", style: { background: 'var(--m3-surface-container-lowest)', color: 'var(--m3-on-surface)', border: '1px solid var(--m3-outline-variant)', borderLeft: `4px solid ${color}`, boxShadow: '0 8px 24px rgba(0,0,0,0.14)' }, onMouseEnter: () => setPaused(true), onMouseLeave: () => setPaused(false), onFocus: () => setPaused(true), onBlur: () => setPaused(false), children: [_jsx("span", { className: "material-symbols-outlined flex-shrink-0 mt-px", "aria-hidden": "true", style: { fontSize: '18px', color }, children: icon }), _jsx("div", { className: "flex-1 min-w-0 break-words", children: toast.message }), _jsx("button", { type: "button", onClick: () => onDismiss(toast.id), "aria-label": "Dismiss", className: "btn-icon -my-1 -mr-2 w-7 h-7", children: _jsx("span", { className: "material-symbols-outlined", "aria-hidden": "true", style: { fontSize: '16px' }, children: "close" }) })] }));
28
+ }
29
+ /** Mount once near the root; renders the bottom-right toast stack above every modal. */
30
+ export function ToastProvider({ children }) {
31
+ const [toasts, setToasts] = useState([]);
32
+ const nextId = useRef(1);
33
+ const dismiss = useCallback((id) => {
34
+ setToasts((current) => current.filter((toast) => toast.id !== id));
35
+ }, []);
36
+ const api = useMemo(() => {
37
+ const push = (tone) => (message, options) => {
38
+ const id = nextId.current++;
39
+ setToasts((current) => [...current.slice(-4), { id, tone, message, duration: options?.duration ?? TOAST_DURATION }]);
40
+ return id;
41
+ };
42
+ return { success: push('success'), error: push('error'), info: push('info'), dismiss };
43
+ }, [dismiss]);
44
+ return (_jsxs(ToastContext.Provider, { value: api, children: [children, createPortal(_jsx("div", { role: "region", "aria-live": "polite", "aria-label": "Notifications", className: "fixed bottom-4 right-4 left-4 sm:left-auto sm:w-96 flex flex-col items-end gap-2 pointer-events-none", style: { zIndex: MODAL_Z_INDEX + 1 }, children: toasts.map((toast) => _jsx(ToastItem, { toast: toast, onDismiss: dismiss }, toast.id)) }), document.body)] }));
45
+ }
46
+ //# sourceMappingURL=Toast.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Toast.js","sourceRoot":"","sources":["../../../src/components/ui/Toast.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAA;AACpH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAkB7C,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAA;AAElC,MAAM,IAAI,GAAa,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAA;AAE7F,iGAAiG;AACjG,MAAM,YAAY,GAAG,aAAa,CAAW,IAAI,CAAC,CAAA;AAElD,wGAAwG;AACxG,MAAM,UAAU,QAAQ;IACtB,OAAO,UAAU,CAAC,YAAY,CAAC,CAAA;AACjC,CAAC;AAED,MAAM,UAAU,GAAuD;IACrE,OAAO,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,cAAc,EAAE;IACxD,KAAK,EAAI,EAAE,IAAI,EAAE,OAAO,EAAS,KAAK,EAAE,gBAAgB,EAAE;IAC1D,IAAI,EAAK,EAAE,IAAI,EAAE,MAAM,EAAU,KAAK,EAAE,8BAA8B,EAAE;CACzE,CAAA;AAED,SAAS,SAAS,CAAC,EAAE,KAAK,EAAE,SAAS,EAA0D;IAC7F,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC3C,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IAE9C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC;YAAE,OAAM;QACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAA;QACnE,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAA;IAClC,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC,CAAA;IAEjD,OAAO,CACL,eACE,IAAI,EAAE,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,eACtC,KAAK,CAAC,IAAI,EACrB,SAAS,EAAC,4FAA4F,EACtG,KAAK,EAAE,EAAE,UAAU,EAAE,oCAAoC,EAAE,KAAK,EAAE,sBAAsB,EAAE,MAAM,EAAE,qCAAqC,EAAE,UAAU,EAAE,aAAa,KAAK,EAAE,EAAE,SAAS,EAAE,6BAA6B,EAAE,EACrN,YAAY,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,EACnC,YAAY,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,EACpC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,EAC9B,MAAM,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,aAE9B,eAAM,SAAS,EAAC,+CAA+C,iBAAa,MAAM,EAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,YAAG,IAAI,GAAQ,EACpI,cAAK,SAAS,EAAC,4BAA4B,YAAE,KAAK,CAAC,OAAO,GAAO,EACjE,iBAAQ,IAAI,EAAC,QAAQ,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,gBAAa,SAAS,EAAC,SAAS,EAAC,8BAA8B,YACrH,eAAM,SAAS,EAAC,2BAA2B,iBAAa,MAAM,EAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,sBAAc,GACjG,IACL,CACP,CAAA;AACH,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,aAAa,CAAC,EAAE,QAAQ,EAA2B;IACjE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAe,EAAE,CAAC,CAAA;IACtD,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,CAAA;IAExB,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,EAAU,EAAE,EAAE;QACzC,SAAS,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;IACpE,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,MAAM,GAAG,GAAG,OAAO,CAAW,GAAG,EAAE;QACjC,MAAM,IAAI,GAAG,CAAC,IAAe,EAAE,EAAE,CAAC,CAAC,OAAkB,EAAE,OAAsB,EAAE,EAAE;YAC/E,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,EAAE,CAAA;YAC3B,SAAS,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,IAAI,cAAc,EAAE,CAAC,CAAC,CAAA;YACpH,OAAO,EAAE,CAAA;QACX,CAAC,CAAA;QACD,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAA;IACxF,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAA;IAEb,OAAO,CACL,MAAC,YAAY,CAAC,QAAQ,IAAC,KAAK,EAAE,GAAG,aAC9B,QAAQ,EACR,YAAY,CACX,cACE,IAAI,EAAC,QAAQ,eACH,QAAQ,gBACP,eAAe,EAC1B,SAAS,EAAC,sGAAsG,EAChH,KAAK,EAAE,EAAE,MAAM,EAAE,aAAa,GAAG,CAAC,EAAE,YAEnC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAC,SAAS,IAAgB,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,IAA1C,KAAK,CAAC,EAAE,CAAsC,CAAC,GAClF,EACN,QAAQ,CAAC,IAAI,CACd,IACqB,CACzB,CAAA;AACH,CAAC"}
@@ -0,0 +1,10 @@
1
+ export { Alert, type AlertTone } from './Alert';
2
+ export { Field, type FieldControlProps } from './Field';
3
+ export { PageContainer, PageHeader } from './PageHeader';
4
+ export { QuickStartPanel, type QuickStartOption } from './QuickStartPanel';
5
+ export { Pagination } from './Pagination';
6
+ export { DataTable, DataTh, MAX_COLUMN_WIDTH, MIN_COLUMN_WIDTH, ResizeHandle, useTableSort, type SortDirection, type SortValue, type TableSort } from './DataTable';
7
+ export { EmptyState, EmptyStateLink, EmptyTableRow, ErrorState, LoadingState } from './StateViews';
8
+ export { Switch } from './Switch';
9
+ export { TOAST_DURATION, ToastProvider, useToast, type ToastApi, type ToastOptions, type ToastTone } from './Toast';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/ui/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,KAAK,SAAS,EAAE,MAAM,SAAS,CAAA;AAC/C,OAAO,EAAE,KAAK,EAAE,KAAK,iBAAiB,EAAE,MAAM,SAAS,CAAA;AACvD,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,EAAE,eAAe,EAAE,KAAK,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAC1E,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,YAAY,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAA;AACnK,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAClG,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACjC,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,QAAQ,EAAE,KAAK,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,SAAS,CAAA"}
@@ -0,0 +1,10 @@
1
+ export { Alert } from './Alert';
2
+ export { Field } from './Field';
3
+ export { PageContainer, PageHeader } from './PageHeader';
4
+ export { QuickStartPanel } from './QuickStartPanel';
5
+ export { Pagination } from './Pagination';
6
+ export { DataTable, DataTh, MAX_COLUMN_WIDTH, MIN_COLUMN_WIDTH, ResizeHandle, useTableSort } from './DataTable';
7
+ export { EmptyState, EmptyStateLink, EmptyTableRow, ErrorState, LoadingState } from './StateViews';
8
+ export { Switch } from './Switch';
9
+ export { TOAST_DURATION, ToastProvider, useToast } from './Toast';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/ui/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAkB,MAAM,SAAS,CAAA;AAC/C,OAAO,EAAE,KAAK,EAA0B,MAAM,SAAS,CAAA;AACvD,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,EAAE,eAAe,EAAyB,MAAM,mBAAmB,CAAA;AAC1E,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,YAAY,EAAE,YAAY,EAAsD,MAAM,aAAa,CAAA;AACnK,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAClG,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACjC,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,QAAQ,EAAoD,MAAM,SAAS,CAAA"}
@@ -0,0 +1,46 @@
1
+ export interface UiConfig {
2
+ /** Names what the interface keeps in the browser: keys in storage and window events start with it (`<prefix>-dark-mode`). */
3
+ storagePrefix: string;
4
+ /** Where the API answers. */
5
+ apiBase: string;
6
+ /** The cookie the server puts the CSRF token in; it is sent back in a header on every change. */
7
+ csrfCookie: string;
8
+ /** Where the interface is served, without a trailing slash (`/admin`): the pages to sign in and to change a password are below it. */
9
+ basePath: string;
10
+ /** For a user who does not belong in this interface (say, one who may only view a public page): the address to send them to instead. */
11
+ redirectAfterSignIn?: (user: {
12
+ role: string;
13
+ }) => string | null;
14
+ /** The names and pictures the application is known by. */
15
+ brand: {
16
+ name: string;
17
+ logoLight: string;
18
+ logoDark: string;
19
+ };
20
+ /** Wording that names things only the application knows. */
21
+ texts: {
22
+ /** What an API token can never manage, in the sentence "It cannot manage ..." (for example `users, single sign-on, vaults or other tokens`). */
23
+ tokenCannotManage: string;
24
+ /** What a token with the vault permission can attach a vault secret to (`a job or channel`). */
25
+ tokenVaultTargets: string;
26
+ /** Said when a test sign-in would create an account; `{user}` is replaced by the account. */
27
+ ssoNewAccount: string;
28
+ /** Added to the single sign-on settings to say who may sign in; empty adds nothing. */
29
+ ssoSignInHint: string;
30
+ /** The name of the application, as the interface calls it in sentences. */
31
+ appName: string;
32
+ /** What uses the secrets kept in a vault (`jobs`), in sentences like "... that jobs can use". */
33
+ secretConsumers: string;
34
+ /** An example of the path of a secret in an external vault. */
35
+ vaultPathExample: string;
36
+ };
37
+ }
38
+ /**
39
+ * Tells the interface what application it is part of. Call it before anything is rendered; what is read from storage
40
+ * is read on first use, after this.
41
+ */
42
+ export declare function configureUi(options: Partial<UiConfig>): void;
43
+ export declare const uiConfig: () => UiConfig;
44
+ /** The name the interface uses for `name` in storage and in window events. */
45
+ export declare const storageKey: (name: string) => string;
46
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,6HAA6H;IAC7H,aAAa,EAAE,MAAM,CAAA;IACrB,6BAA6B;IAC7B,OAAO,EAAE,MAAM,CAAA;IACf,iGAAiG;IACjG,UAAU,EAAE,MAAM,CAAA;IAClB,sIAAsI;IACtI,QAAQ,EAAE,MAAM,CAAA;IAChB,wIAAwI;IACxI,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,GAAG,IAAI,CAAA;IAC/D,0DAA0D;IAC1D,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;IAC5D,4DAA4D;IAC5D,KAAK,EAAE;QACL,gJAAgJ;QAChJ,iBAAiB,EAAE,MAAM,CAAA;QACzB,gGAAgG;QAChG,iBAAiB,EAAE,MAAM,CAAA;QACzB,6FAA6F;QAC7F,aAAa,EAAE,MAAM,CAAA;QACrB,uFAAuF;QACvF,aAAa,EAAE,MAAM,CAAA;QACrB,2EAA2E;QAC3E,OAAO,EAAE,MAAM,CAAA;QACf,iGAAiG;QACjG,eAAe,EAAE,MAAM,CAAA;QACvB,+DAA+D;QAC/D,gBAAgB,EAAE,MAAM,CAAA;KACzB,CAAA;CACF;AAID;;;GAGG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI,CAE5D;AAED,eAAO,MAAM,QAAQ,QAAO,QAAmB,CAAA;AAE/C,8EAA8E;AAC9E,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,KAAG,MAA4C,CAAA"}
package/dist/config.js ADDED
@@ -0,0 +1,12 @@
1
+ let current = { storagePrefix: 'better', apiBase: '/api/v1', csrfCookie: 'better_csrf', basePath: '', brand: { name: 'Better', logoLight: '', logoDark: '' }, texts: { ssoNewAccount: 'Creates the account {user} and links this identity-provider account to it.', ssoSignInHint: '', appName: 'This application', secretConsumers: 'the application', vaultPathExample: 'app/database', tokenCannotManage: 'users, single sign-on, vaults or other tokens', tokenVaultTargets: 'an object' } };
2
+ /**
3
+ * Tells the interface what application it is part of. Call it before anything is rendered; what is read from storage
4
+ * is read on first use, after this.
5
+ */
6
+ export function configureUi(options) {
7
+ current = { ...current, ...options };
8
+ }
9
+ export const uiConfig = () => current;
10
+ /** The name the interface uses for `name` in storage and in window events. */
11
+ export const storageKey = (name) => `${current.storagePrefix}-${name}`;
12
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAgCA,IAAI,OAAO,GAAa,EAAE,aAAa,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,aAAa,EAAE,4EAA4E,EAAE,aAAa,EAAE,EAAE,EAAE,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,cAAc,EAAE,iBAAiB,EAAE,+CAA+C,EAAE,iBAAiB,EAAE,WAAW,EAAE,EAAE,CAAA;AAE1e;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,OAA0B;IACpD,OAAO,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,OAAO,EAAE,CAAA;AACtC,CAAC;AAED,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAa,EAAE,CAAC,OAAO,CAAA;AAE/C,8EAA8E;AAC9E,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,GAAG,OAAO,CAAC,aAAa,IAAI,IAAI,EAAE,CAAA"}
@@ -0,0 +1,2 @@
1
+ export declare function useDarkMode(): [boolean, () => void];
2
+ //# sourceMappingURL=useDarkMode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDarkMode.d.ts","sourceRoot":"","sources":["../../src/hooks/useDarkMode.ts"],"names":[],"mappings":"AAMA,wBAAgB,WAAW,IAAI,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,CA+BnD"}
@@ -0,0 +1,37 @@
1
+ import { useState, useEffect } from 'react';
2
+ import { safeLocalStorage } from '@better-forge/contracts';
3
+ import { storageKey } from '../config';
4
+ // The public status app keeps a copy of this hook with the same behaviour, since it does not use this package.
5
+ export function useDarkMode() {
6
+ const [isDark, setIsDark] = useState(() => {
7
+ if (typeof window === 'undefined')
8
+ return false;
9
+ const stored = safeLocalStorage.get(storageKey('dark-mode'));
10
+ if (stored !== null)
11
+ return stored === 'true';
12
+ return window.matchMedia('(prefers-color-scheme: dark)').matches;
13
+ });
14
+ useEffect(() => {
15
+ const html = document.documentElement;
16
+ if (isDark) {
17
+ html.classList.add('dark');
18
+ }
19
+ else {
20
+ html.classList.remove('dark');
21
+ }
22
+ safeLocalStorage.set(storageKey('dark-mode'), String(isDark));
23
+ // Every mounted instance (e.g. the sidebar toggle and a page that swaps its logo) listens for this, so one toggle
24
+ // updates them all.
25
+ window.dispatchEvent(new CustomEvent(storageKey('dark-mode-change'), { detail: isDark }));
26
+ }, [isDark]);
27
+ useEffect(() => {
28
+ const handler = (e) => {
29
+ const dark = e.detail;
30
+ setIsDark(dark);
31
+ };
32
+ window.addEventListener(storageKey('dark-mode-change'), handler);
33
+ return () => window.removeEventListener(storageKey('dark-mode-change'), handler);
34
+ }, []);
35
+ return [isDark, () => setIsDark((d) => !d)];
36
+ }
37
+ //# sourceMappingURL=useDarkMode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDarkMode.js","sourceRoot":"","sources":["../../src/hooks/useDarkMode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAEtC,+GAA+G;AAE/G,MAAM,UAAU,WAAW;IACzB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE;QACxC,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO,KAAK,CAAA;QAC/C,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAA;QAC5D,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO,MAAM,KAAK,MAAM,CAAA;QAC7C,OAAO,MAAM,CAAC,UAAU,CAAC,8BAA8B,CAAC,CAAC,OAAO,CAAA;IAClE,CAAC,CAAC,CAAA;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,IAAI,GAAG,QAAQ,CAAC,eAAe,CAAA;QACrC,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;QAC5B,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;QAC/B,CAAC;QACD,gBAAgB,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAA;QAC7D,kHAAkH;QAClH,oBAAoB;QACpB,MAAM,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,UAAU,CAAC,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;IAC3F,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA;IAEZ,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,OAAO,GAAG,CAAC,CAAQ,EAAE,EAAE;YAC3B,MAAM,IAAI,GAAI,CAA0B,CAAC,MAAM,CAAA;YAC/C,SAAS,CAAC,IAAI,CAAC,CAAA;QACjB,CAAC,CAAA;QACD,MAAM,CAAC,gBAAgB,CAAC,UAAU,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC,CAAA;QAChE,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,UAAU,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC,CAAA;IAClF,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAC7C,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Returns `value` once it has stopped changing for `delay` ms, plus a `flush` that applies it immediately
3
+ * (e.g. on Enter) or sets an explicit value (e.g. clearing a search box).
4
+ */
5
+ export declare function useDebouncedValue<T>(value: T, delay?: number): [T, (next?: T) => void];
6
+ //# sourceMappingURL=useDebouncedValue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDebouncedValue.d.ts","sourceRoot":"","sources":["../../src/hooks/useDebouncedValue.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,SAAM,GAAG,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC,CAenF"}
@@ -0,0 +1,19 @@
1
+ import { useCallback, useEffect, useRef, useState } from 'react';
2
+ /**
3
+ * Returns `value` once it has stopped changing for `delay` ms, plus a `flush` that applies it immediately
4
+ * (e.g. on Enter) or sets an explicit value (e.g. clearing a search box).
5
+ */
6
+ export function useDebouncedValue(value, delay = 300) {
7
+ const [debounced, setDebounced] = useState(value);
8
+ const latest = useRef(value);
9
+ useEffect(() => {
10
+ latest.current = value;
11
+ const timer = setTimeout(() => setDebounced(value), delay);
12
+ return () => clearTimeout(timer);
13
+ }, [value, delay]);
14
+ const flush = useCallback((next) => {
15
+ setDebounced(next === undefined ? latest.current : next);
16
+ }, []);
17
+ return [debounced, flush];
18
+ }
19
+ //# sourceMappingURL=useDebouncedValue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDebouncedValue.js","sourceRoot":"","sources":["../../src/hooks/useDebouncedValue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAEhE;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAI,KAAQ,EAAE,KAAK,GAAG,GAAG;IACxD,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IACjD,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;IAE5B,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,CAAC,OAAO,GAAG,KAAK,CAAA;QACtB,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,CAAA;QAC1D,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAA;IAClC,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAA;IAElB,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,IAAQ,EAAE,EAAE;QACrC,YAAY,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;IAC1D,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;AAC3B,CAAC"}
@@ -0,0 +1,36 @@
1
+ export * from './components/ui';
2
+ export { ConfirmModal } from './components/ConfirmModal';
3
+ export { ConfirmIdentityModal } from './components/ConfirmIdentityModal';
4
+ export { ErrorBoundary, isChunkLoadError } from './components/ErrorBoundary';
5
+ export { CopyButton } from './components/CopyButton';
6
+ export { Modal, ModalFooter, ModalHeader, ModalShell, MODAL_BACKDROP, MODAL_Z_INDEX } from './components/ModalShell';
7
+ export { SidePanelFrame, SideTabStrip, type SidePanelLayout, type SidePanelMeta, type SideTab } from './components/SidePanel';
8
+ export { VaultTypePicker, VAULT_TYPE_ICONS, isReferenceVault, type VaultTypeValue } from './components/VaultTypePicker';
9
+ export { useDebouncedValue } from './hooks/useDebouncedValue';
10
+ export { compareVersions, parseChangelog, releasesBetween, summarizeRelease, type ReleaseGroup, type ReleaseItem, type ReleaseNotes, type ReleaseSummary } from './lib/changelog';
11
+ export { configureUi, storageKey } from './config';
12
+ export { useDarkMode } from './hooks/useDarkMode';
13
+ export { DATE_FORMATS, TIME_FORMATS, formatClock, formatDate, formatDateTime, formatDayMonth, getDatePrefs, setDatePrefs, useDatePrefs, type DateFormat, type DatePrefs, type TimeFormat, } from './lib/dateFormat';
14
+ export { uiConfig, type UiConfig } from './config';
15
+ export { navigation } from './navigation';
16
+ export { ApiError, api, clearSession, enterAfterSignIn, getCurrentUser, isAuthenticated, mustChangePassword, setSession, type AuthUser, } from './api/client';
17
+ export { WhatsNew, markWhatsNewSeen, pendingWhatsNew } from './components/WhatsNew';
18
+ export { createAdminShell, type AdminShellConfig, type ExternalLink, type NavItem, type NavSection } from './shell/AdminShell';
19
+ export { default as BackupsPage } from './pages/Backups';
20
+ export { default as ChangePasswordPage } from './pages/ChangePassword';
21
+ export { default as SettingsPage } from './pages/Settings';
22
+ export { default as SsoConfirmPage } from './pages/SsoConfirm';
23
+ export { default as SsoTestResultPage } from './pages/SsoTestResult';
24
+ export { ResetTwoFactorModal } from './components/ResetTwoFactorModal';
25
+ export { SingleSignOnModal } from './components/SingleSignOnModal';
26
+ export { ssoConfirmChannel, SsoConfirmationNote, isSsoConfirmationRequired, isSsoSession, useSsoConfirmation, type SsoConfirmationState, } from './components/SsoConfirmation';
27
+ export { default as ApiTokensPage } from './pages/ApiTokens';
28
+ export { default as AuditLogPage, type AuditEntities } from './pages/AuditLog';
29
+ export { default as UsersPage, type UserRole, type UsersPageAction, type UsersPageProps } from './pages/Users';
30
+ export { ConnectionStringSection, CredentialSection } from './components/CredentialSection';
31
+ export { JSON_MAPPING_FIELDS, Note, SectionDivider, toggleInSet, type SecretSummary, type VaultPickerProps, type VaultSummary } from './components/formParts';
32
+ export { default as VaultPage } from './pages/Vault';
33
+ export { default as LoginPage, type LoginPageProps } from './pages/Login';
34
+ export { default as SetupPage } from './pages/Setup';
35
+ export { RequireAuth, RequirePasswordChanged, SetupGate, createRoleGuard } from './shell/guards';
36
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAA;AACxE,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAA;AAC5E,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AACpD,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACpH,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,KAAK,eAAe,EAAE,KAAK,aAAa,EAAE,KAAK,OAAO,EAAE,MAAM,wBAAwB,CAAA;AAC7H,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,KAAK,cAAc,EAAE,MAAM,8BAA8B,CAAA;AACvH,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,EAAE,gBAAgB,EAAE,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAA;AACjL,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACjD,OAAO,EACL,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAC7H,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,GACjD,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,QAAQ,EAAE,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAA;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EACL,QAAQ,EAAE,GAAG,EAAE,YAAY,EAAE,gBAAgB,EAAE,cAAc,EAAE,eAAe,EAAE,kBAAkB,EAAE,UAAU,EAAE,KAAK,QAAQ,GAC9H,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACnF,OAAO,EAAE,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,KAAK,YAAY,EAAE,KAAK,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAC9H,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,iBAAiB,CAAA;AACxD,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AACtE,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC1D,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAC9D,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAA;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAClE,OAAO,EACL,iBAAiB,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,YAAY,EAAE,kBAAkB,EAAE,KAAK,oBAAoB,GAC/H,MAAM,8BAA8B,CAAA;AACrC,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAC5D,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAC9E,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,KAAK,QAAQ,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAA;AAC9G,OAAO,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAC3F,OAAO,EAAE,mBAAmB,EAAE,IAAI,EAAE,cAAc,EAAE,WAAW,EAAE,KAAK,aAAa,EAAE,KAAK,gBAAgB,EAAE,KAAK,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAC7J,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,eAAe,CAAA;AACpD,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAA;AACzE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,eAAe,CAAA;AACpD,OAAO,EAAE,WAAW,EAAE,sBAAsB,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,36 @@
1
+ export * from './components/ui';
2
+ export { ConfirmModal } from './components/ConfirmModal';
3
+ export { ConfirmIdentityModal } from './components/ConfirmIdentityModal';
4
+ export { ErrorBoundary, isChunkLoadError } from './components/ErrorBoundary';
5
+ export { CopyButton } from './components/CopyButton';
6
+ export { Modal, ModalFooter, ModalHeader, ModalShell, MODAL_BACKDROP, MODAL_Z_INDEX } from './components/ModalShell';
7
+ export { SidePanelFrame, SideTabStrip } from './components/SidePanel';
8
+ export { VaultTypePicker, VAULT_TYPE_ICONS, isReferenceVault } from './components/VaultTypePicker';
9
+ export { useDebouncedValue } from './hooks/useDebouncedValue';
10
+ export { compareVersions, parseChangelog, releasesBetween, summarizeRelease } from './lib/changelog';
11
+ export { configureUi, storageKey } from './config';
12
+ export { useDarkMode } from './hooks/useDarkMode';
13
+ export { DATE_FORMATS, TIME_FORMATS, formatClock, formatDate, formatDateTime, formatDayMonth, getDatePrefs, setDatePrefs, useDatePrefs, } from './lib/dateFormat';
14
+ export { uiConfig } from './config';
15
+ export { navigation } from './navigation';
16
+ export { ApiError, api, clearSession, enterAfterSignIn, getCurrentUser, isAuthenticated, mustChangePassword, setSession, } from './api/client';
17
+ export { WhatsNew, markWhatsNewSeen, pendingWhatsNew } from './components/WhatsNew';
18
+ export { createAdminShell } from './shell/AdminShell';
19
+ export { default as BackupsPage } from './pages/Backups';
20
+ export { default as ChangePasswordPage } from './pages/ChangePassword';
21
+ export { default as SettingsPage } from './pages/Settings';
22
+ export { default as SsoConfirmPage } from './pages/SsoConfirm';
23
+ export { default as SsoTestResultPage } from './pages/SsoTestResult';
24
+ export { ResetTwoFactorModal } from './components/ResetTwoFactorModal';
25
+ export { SingleSignOnModal } from './components/SingleSignOnModal';
26
+ export { ssoConfirmChannel, SsoConfirmationNote, isSsoConfirmationRequired, isSsoSession, useSsoConfirmation, } from './components/SsoConfirmation';
27
+ export { default as ApiTokensPage } from './pages/ApiTokens';
28
+ export { default as AuditLogPage } from './pages/AuditLog';
29
+ export { default as UsersPage } from './pages/Users';
30
+ export { ConnectionStringSection, CredentialSection } from './components/CredentialSection';
31
+ export { JSON_MAPPING_FIELDS, Note, SectionDivider, toggleInSet } from './components/formParts';
32
+ export { default as VaultPage } from './pages/Vault';
33
+ export { default as LoginPage } from './pages/Login';
34
+ export { default as SetupPage } from './pages/Setup';
35
+ export { RequireAuth, RequirePasswordChanged, SetupGate, createRoleGuard } from './shell/guards';
36
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ export interface ReleaseItem {
2
+ title: string;
3
+ summary: string;
4
+ }
5
+ export interface ReleaseGroup {
6
+ heading: string;
7
+ items: ReleaseItem[];
8
+ }
9
+ export interface ReleaseNotes {
10
+ version: string;
11
+ date: string;
12
+ groups: ReleaseGroup[];
13
+ }
14
+ /**
15
+ * Released sections of docs/changelog.md, newest first; each top-level bullet is cut down to its bold title and
16
+ * the first sentence of its text. The Unreleased section and nested bullets are left out.
17
+ */
18
+ export declare function parseChangelog(markdown: string): ReleaseNotes[];
19
+ /** Negative, zero or positive like a sort comparator; plain x.y.z versions only. */
20
+ export declare function compareVersions(a: string, b: string): number;
21
+ /** Releases after `seen` up to and including `current`, newest first. */
22
+ export declare function releasesBetween(releases: ReleaseNotes[], seen: string, current: string): ReleaseNotes[];
23
+ export interface ReleaseSummary {
24
+ version: string;
25
+ added: ReleaseItem[];
26
+ /** Changed, Removed and any other kind of entry that is not new or a fix. */
27
+ changed: ReleaseItem[];
28
+ fixed: ReleaseItem[];
29
+ }
30
+ /** One release sorted by the kind of change; fixes are only counted. */
31
+ export declare function summarizeRelease(release: ReleaseNotes): ReleaseSummary;
32
+ //# sourceMappingURL=changelog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"changelog.d.ts","sourceRoot":"","sources":["../../src/lib/changelog.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,WAAW,EAAE,CAAA;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,YAAY,EAAE,CAAA;CACvB;AAeD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,EAAE,CAwB/D;AAED,oFAAoF;AACpF,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAQ5D;AAED,yEAAyE;AACzE,wBAAgB,eAAe,CAAC,QAAQ,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,YAAY,EAAE,CAEvG;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,WAAW,EAAE,CAAA;IACpB,6EAA6E;IAC7E,OAAO,EAAE,WAAW,EAAE,CAAA;IACtB,KAAK,EAAE,WAAW,EAAE,CAAA;CACrB;AAED,wEAAwE;AACxE,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,YAAY,GAAG,cAAc,CAQtE"}