@umituz/web-dashboard 4.7.1 → 5.0.1

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 (49) hide show
  1. package/README.md +63 -88
  2. package/package.json +5 -7
  3. package/src/domains/analytics/components/AnalyticsCard.tsx +1 -6
  4. package/src/domains/analytics/components/AnalyticsChart.tsx +2 -14
  5. package/src/domains/analytics/components/AnalyticsLayout.tsx +3 -17
  6. package/src/domains/analytics/components/MetricCard.tsx +1 -6
  7. package/src/domains/analytics/utils/i18nKeys.ts +0 -9
  8. package/src/domains/auth/components/AuthLayout.tsx +1 -26
  9. package/src/domains/auth/components/ForgotPasswordForm.tsx +2 -14
  10. package/src/domains/auth/components/LoginForm.tsx +2 -15
  11. package/src/domains/auth/components/RegisterForm.tsx +3 -14
  12. package/src/domains/auth/components/ResetPasswordForm.tsx +3 -14
  13. package/src/domains/auth/components/shared/AuthErrorBanner.tsx +1 -11
  14. package/src/domains/auth/components/shared/EmailInput.tsx +2 -20
  15. package/src/domains/auth/components/shared/PasswordInput.tsx +3 -22
  16. package/src/domains/auth/components/shared/PasswordStrengthIndicator.tsx +1 -13
  17. package/src/domains/auth/components/shared/SocialLoginButtons.tsx +1 -15
  18. package/src/domains/auth/utils/i18nKeys.ts +0 -18
  19. package/src/domains/charts/components.tsx +2 -2
  20. package/src/domains/layouts/components/BrandLogo.tsx +7 -22
  21. package/src/domains/layouts/components/DashboardHeader.tsx +2 -23
  22. package/src/domains/layouts/components/DashboardLayout.tsx +2 -39
  23. package/src/domains/layouts/components/DashboardSidebar.tsx +3 -21
  24. package/src/domains/permissions/PermissionsContext.tsx +1 -17
  25. package/src/domains/permissions/utils/i18nKeys.ts +0 -5
  26. package/src/domains/session/DemoLogin.tsx +2 -10
  27. package/src/domains/session/OrgSwitcher.tsx +2 -10
  28. package/src/domains/settings/components/AuditLogList.tsx +1 -10
  29. package/src/domains/settings/components/PermissionMatrixScreen.tsx +1 -8
  30. package/src/domains/settings/components/SettingsLayout.tsx +1 -21
  31. package/src/domains/settings/components/SettingsSection.tsx +1 -13
  32. package/src/domains/settings/components/UserManagementTable.tsx +1 -8
  33. package/src/domains/settings/utils/i18nKeys.ts +0 -6
  34. package/src/index.ts +0 -17
  35. package/src/styles/dashboard.contract.test.ts +42 -0
  36. package/src/styles/dashboard.css +492 -920
  37. package/src/i18n/I18nContext.tsx +0 -33
  38. package/src/i18n/defaultT.test.ts +0 -43
  39. package/src/i18n/defaultT.ts +0 -34
  40. package/src/i18n/index.ts +0 -7
  41. package/src/i18n/types.ts +0 -13
  42. package/src/primitives/Button.tsx +0 -24
  43. package/src/primitives/Checkbox.tsx +0 -17
  44. package/src/primitives/Input.tsx +0 -23
  45. package/src/primitives/Skeleton.tsx +0 -6
  46. package/src/primitives/cn.ts +0 -10
  47. package/src/primitives/index.ts +0 -23
  48. package/src/styles/tokens.contract.test.ts +0 -91
  49. package/src/styles/tokens.css +0 -116
package/README.md CHANGED
@@ -1,56 +1,31 @@
1
1
  # @umituz/web-dashboard
2
2
 
3
- Installable app skeleton for SaaS dashboards: layouts, auth, onboarding,
4
- analytics, a content calendar, an i18n bridge, and a permissions/session/
5
- module registry. Every domain is an independent entry point — import only
6
- what your app uses. Camp-agnostic by construction: the package ships its
7
- own `udb-*` stylesheet driven by `--u-*` tokens, so it works identically in
8
- vanilla-CSS and Tailwind hosts.
3
+ Installable app skeleton for SaaS dashboards: layouts, auth, analytics, a
4
+ content calendar, and a permissions/session/module registry. Every domain is
5
+ an independent entry point — import only what your app uses. UI atoms and
6
+ design tokens come from [@umituz/web-design-system](https://github.com/umituz/web-design-system);
7
+ translations from [@umituz/web-localization](https://github.com/umituz/web-localization).
9
8
 
10
9
  The package is **source-distributed** (published as raw TypeScript in `src/`).
11
10
  Your bundler compiles it alongside your app; no prebuilt bundle ships.
12
11
 
13
- ## What changed in v4 (major)
14
-
15
- - **Billing moved to [@umituz/web-polar-payment](https://github.com/umituz/web-polar-payment)**
16
- under the `./portal` entry point. The old `./billing*` entry points are gone.
17
- - **Styling is shipped, not assumed.** Import `@umituz/web-dashboard/styles.css`
18
- once; all components use `udb-*` BEM classes.
19
- - **No i18n runtime.** `react-i18next` is out; hosts bridge their own `t` via
20
- `<DashboardI18nProvider t={i18n.t}>` (see below). Without a provider,
21
- keys humanize to readable English.
22
- - **No Firebase.** The calendar persists through the injected
23
- `ICalendarDatabase` seam; `createInMemoryCalendarDatabase()` is the default.
24
- - **recharts is out.** `AnalyticsChart` renders line/area/bar/pie/donut as
25
- dependency-free SVG with native `<title>` tooltips.
26
- - **New fleet modules**: `./permissions`, `./session`, `./modules` — the
27
- texora/visora pattern (one module list drives routes + nav + guards) as
28
- reusable building blocks.
29
-
30
- ## What changed in 4.1
31
-
32
- - **The design system is back — for real this time.** 4.0 dropped
33
- `@umituz/web-design-system` entirely; 4.1 makes it a runtime dependency
34
- again and actually renders it:
35
- - `./primitives` (`Button`, `Input`, `Checkbox`, `Skeleton`, `cn`) are thin
36
- adapters that **delegate to the DS components** — the dashboard prop API
37
- is unchanged, call sites need zero edits.
38
- - `UserManagementTable` renders the DS `DataTable`; `MetricCard` composes
39
- the DS `MetricCard`; `AnalyticsCard` is built on DS `Card` primitives.
40
- - `styles.css` imports `@umituz/web-design-system/styles.css` transitively
41
- (Tailwind v4 precompiled) — hosts still import only the dashboard
42
- stylesheet.
43
- - **`--u-*` tokens are now bridges.** `tokens.css` maps every color/radius/
44
- shadow token to the DS `--color-*`/`--radius-*` variables (with the old
45
- literal as fallback). Override either side; dark mode (`data-udb-theme="dark"`)
46
- now sets DS variables and the bridge flows through.
47
- - **Primitive base CSS is gone from `dashboard.css`.** Only dashboard-owned
48
- modifiers remain (`udb-btn__spinner`, `udb-input--error/--with-toggle`,
49
- `udb-skeleton--*`, `udb-card--sm/--lg`, `udb-table` for the permission
50
- matrix); bases come from the DS stylesheet.
51
- - **Peer footprint**: pulling the dashboard in transitively installs the DS's
52
- Radix UI peers (npm 7+ handles this automatically; only imported components
53
- end up in the bundle).
12
+ ## What changed in v5 (major)
13
+
14
+ - **No more local primitives.** The `./primitives` entry point is gone;
15
+ components import `@umituz/web-design-system` directly. Hosts that need
16
+ `Button`/`Input`/`Checkbox`/`Skeleton`/`cn` import them from the design
17
+ system.
18
+ - **No more `--u-*` token layer.** `tokens.css` is deleted. The `udb-*`
19
+ stylesheet consumes the design-system variables (`--color-*`, `--radius-*`,
20
+ `--font-*`, `--shadow-*`) directly; dashboard-specific knobs (typography
21
+ scale, sidebar geometry) are `--udb-*` custom properties defined in
22
+ `styles.css` itself.
23
+ - **No more local i18n copy.** The `./i18n` entry point is gone; `useT` now
24
+ comes from `@umituz/web-localization/react` (`I18nProvider` there replaces
25
+ `DashboardI18nProvider`, same `t` signature).
26
+ - **No bundled dark preset.** Dark mode follows the design system: hosts set
27
+ dark values on the DS variables under `[data-theme="dark"]` / `.dark`
28
+ (see the design system's `bridge.css` contract).
54
29
 
55
30
  ## Installation
56
31
 
@@ -60,7 +35,8 @@ import "@umituz/web-dashboard/styles.css";
60
35
  ```
61
36
 
62
37
  Peers: `react` + `react-dom` (^18 or ^19) and `react-router-dom` (^6 or ^7).
63
- Runtime deps: `@umituz/web-design-system` + `lucide-react`. Nothing else.
38
+ Runtime deps: `@umituz/web-design-system`, `@umituz/web-localization`,
39
+ `lucide-react`. Nothing else.
64
40
 
65
41
  ### Tailwind hosts
66
42
 
@@ -70,56 +46,53 @@ resets: import the package stylesheet **after** your base layer.
70
46
 
71
47
  ### Theming & dark mode
72
48
 
73
- `tokens.css` bridges every `--u-*` token to a design-system variable
74
- (`--u-color-primary: var(--color-primary, #2563eb)`), so you can theme two
75
- ways: override the `--u-*` bridge heads, or set the DS `--color-*`/`--radius-*`
76
- variables (e.g. from your own Tailwind `@theme`). Dark mode is host-driven:
77
- put `data-udb-theme="dark"` on any ancestor — the dashboard dark block sets
78
- the DS variables and both layers switch together.
49
+ `styles.css` imports `@umituz/web-design-system/styles.css` transitively and
50
+ reads its variables, so theming has exactly one path: set the DS variables.
51
+ Vanilla-CSS hosts define `--app-*` slots via the design system's `bridge.css`;
52
+ Tailwind hosts override `--color-*` from their own `@theme`. Dashboard-only
53
+ knobs (`--udb-font-size-*`, `--udb-space-*`, `--udb-sidebar-*`,
54
+ `--udb-header-height`, `--udb-border-strong`, `--udb-radius-pill`) can be overridden anywhere in the cascade.
79
55
 
80
56
  ## Entry points
81
57
 
82
58
  ```bash
83
59
  @umituz/web-dashboard/styles.css # component stylesheet (udb-* BEM)
84
- @umituz/web-dashboard/tokens.css # --u-* custom properties only
85
- @umituz/web-dashboard/primitives # Button, Input, Checkbox, Skeleton, cn
86
- @umituz/web-dashboard/i18n # DashboardI18nProvider, useT, defaultT
87
60
  @umituz/web-dashboard/permissions # PermissionMatrix, hasPermission, guards
88
61
  @umituz/web-dashboard/session # AuthAdapter, SessionProvider, OrgSwitcher, DemoLogin
89
62
  @umituz/web-dashboard/modules # DashboardModule, buildRoutes, buildNav
90
63
  @umituz/web-dashboard/layouts # DashboardLayout, DashboardSidebar, DashboardHeader
91
64
  @umituz/web-dashboard/settings # SettingsLayout, admin skeletons (users, matrix, audit)
92
- @umituz/web-dashboard/onboarding # OnboardingWizard + steps, useOnboarding
93
65
  @umituz/web-dashboard/auth # Login/Register/Forgot/Reset forms, AuthLayout
94
66
  @umituz/web-dashboard/analytics # AnalyticsLayout, SVG AnalyticsChart, services
95
67
  @umituz/web-dashboard/calendar # useCalendar, CalendarService (injected DB)
96
68
  @umituz/web-dashboard/config # dashboard config helpers
69
+ @umituz/web-dashboard/charts # dependency-free SVG chart components
97
70
  ```
98
71
 
99
72
  Each domain also exposes `components`, `hooks`, `utils`, `types`
100
- sub-entries (and `services` for analytics/calendar). The new v4 modules
73
+ sub-entries (and `services` for analytics/calendar). The v4 modules
101
74
  (`permissions`, `session`, `modules`) are **deep-entry only** — they are not
102
75
  re-exported from the root, so router-less hosts never pull router code in
103
76
  transitively.
104
77
 
105
- ## The v4 composition
78
+ ## The composition
106
79
 
107
80
  A host app assembles the skeleton from four seams:
108
81
 
109
82
  ```tsx
110
- import { DashboardI18nProvider } from "@umituz/web-dashboard/i18n";
83
+ import { I18nProvider } from "@umituz/web-localization/react";
111
84
  import { SessionProvider, createInMemoryAuthAdapter } from "@umituz/web-dashboard/session";
112
85
  import { PermissionsProvider } from "@umituz/web-dashboard/permissions";
113
86
 
114
87
  const adapter = createInMemoryAuthAdapter({ users: DEMO_USERS });
115
88
 
116
- <DashboardI18nProvider t={i18n.t}>
89
+ <I18nProvider t={i18n.t}>
117
90
  <SessionProvider adapter={adapter}>
118
91
  <PermissionsProvider matrix={ROLE_PERMISSIONS} role={user?.role}>
119
92
  <App />
120
93
  </PermissionsProvider>
121
94
  </SessionProvider>
122
- </DashboardI18nProvider>
95
+ </I18nProvider>
123
96
  ```
124
97
 
125
98
  ### One module list → routes + nav + guards
@@ -176,20 +149,20 @@ const demo = new CalendarService(createInMemoryCalendarDatabase());
176
149
 
177
150
  ### Analytics
178
151
 
179
- `AnalyticsChart` consumes the same `ChartConfig` as v3 for
180
- line/area/bar/pie/donut. Tooltips are native SVG `<title>` elements;
181
- legends are color chips; unsupported types render an empty state.
182
- `useAnalytics` stays dependency-injected (`createStubAnalyticsApiClient`).
152
+ `AnalyticsChart` consumes `ChartConfig` for line/area/bar/pie/donut. Tooltips
153
+ are native SVG `<title>` elements; legends are color chips; unsupported types
154
+ render an empty state. `useAnalytics` stays dependency-injected
155
+ (`createStubAnalyticsApiClient`).
183
156
 
184
157
  ## i18n contract
185
158
 
186
159
  Components render **i18n keys**, never English strings. Bridge your runtime
187
- once:
160
+ once with `@umituz/web-localization/react`:
188
161
 
189
162
  ```tsx
190
- import { DashboardI18nProvider } from "@umituz/web-dashboard/i18n";
163
+ import { I18nProvider } from "@umituz/web-localization/react";
191
164
 
192
- <DashboardI18nProvider t={i18n.t}> {/* i18next's t — signature already matches */}
165
+ <I18nProvider t={i18n.t}> {/* i18next's t — signature already matches */}
193
166
  ```
194
167
 
195
168
  Interpolation uses the standard `{{placeholder}}` syntax. Without a
@@ -200,7 +173,6 @@ readably. The per-domain key catalogs are the string contract:
200
173
  ```ts
201
174
  import { AUTH_KEYS } from "@umituz/web-dashboard/auth";
202
175
  import { ANALYTICS_KEYS } from "@umituz/web-dashboard/analytics";
203
- import { ONBOARDING_KEYS } from "@umituz/web-dashboard/onboarding";
204
176
  import { SETTINGS_ADMIN_KEYS } from "@umituz/web-dashboard/settings/utils";
205
177
  import { PERMISSIONS_KEYS } from "@umituz/web-dashboard/permissions";
206
178
  import { SESSION_KEYS } from "@umituz/web-dashboard/session";
@@ -223,23 +195,26 @@ npm test # vitest unit tests (pure utils + module builders)
223
195
  npm run test:watch
224
196
  ```
225
197
 
226
- CI runs lint + typecheck + test on every push/PR to `main`.
227
-
228
- ## Migration: 3.x → 4.0
229
-
230
- 1. Billing UI: switch imports to `@umituz/web-polar-payment/portal`.
231
- 2. Design-system imports: use `@umituz/web-dashboard/primitives`
232
- (`Button`/`Input`/`Checkbox`/`Skeleton` cover the used surface).
233
- 3. Styling: import `styles.css` once; Tailwind utility classes no longer
234
- exist inside the package. Config values that used to carry Tailwind
235
- strings changed: `PlatformOption.color` is a plain CSS color string,
236
- `PlanOption.badgeColor` became `badgeTone: "muted" | "primary" | "accent"`.
237
- 4. i18n: wrap your app in `DashboardI18nProvider t={i18n.t}`; the
238
- `react-i18next` peer is gone.
239
- 5. Calendar: pass your own `ICalendarDatabase` (or the in-memory default);
240
- the Firebase implementation was removed.
241
- 6. v3.2.5 behavioral notes still apply (opt-in mock auth, route skeletons
242
- off by default, `PerformanceService.startMonitoring()` explicit).
198
+ ## Migration: 4.x → 5.0
199
+
200
+ 1. `@umituz/web-dashboard/primitives` → import `Button`/`Input`/`Checkbox`/
201
+ `Skeleton` from `@umituz/web-design-system/atoms` and `cn` from
202
+ `@umituz/web-design-system/utils/cn`.
203
+ 2. `@umituz/web-dashboard/i18n` → `DashboardI18nProvider` becomes
204
+ `I18nProvider` from `@umituz/web-localization/react`; `useT`, `defaultT`
205
+ and `TranslateFn` come from the same entry point.
206
+ 3. `@umituz/web-dashboard/tokens.css` → drop the import; `styles.css` is the
207
+ only stylesheet. Migrate `--u-*` overrides to the DS variables
208
+ (`--u-color-primary` → `--color-primary`, `--u-color-surface` →
209
+ `--color-card`, `--u-color-bg` → `--color-background`, `--u-color-text` →
210
+ `--color-foreground`, `--u-color-muted` → `--color-muted-foreground`,
211
+ `--u-color-surface-muted` → `--color-muted`, `--u-color-danger` →
212
+ `--color-destructive`) and dashboard knobs to their `--udb-*` names
213
+ (`--u-font-size-*` → `--udb-font-size-*`, `--u-color-border-strong` →
214
+ `--udb-border-strong`, `--u-sidebar-*` → `--udb-sidebar-*`, `--u-space-*` →
215
+ `--udb-space-*`).
216
+ 4. Dark mode: replace `data-udb-theme="dark"` with the design-system
217
+ convention (`[data-theme="dark"]` / `.dark` + dark DS variable values).
243
218
 
244
219
  ## License
245
220
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@umituz/web-dashboard",
3
- "version": "4.7.1",
4
- "description": "Installable app skeleton for the fleet — layouts, auth, analytics (dependency-free SVG charts), calendar, i18n injection, permissions/session/module registry; ships its own udb-* stylesheet and --u-* tokens",
3
+ "version": "5.0.1",
4
+ "description": "Installable app skeleton for the fleet — layouts, auth, analytics (dependency-free SVG charts), calendar, i18n via @umituz/web-localization, permissions/session/module registry; udb-* stylesheet on design-system tokens",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
7
7
  "types": "./src/index.ts",
@@ -11,9 +11,6 @@
11
11
  "exports": {
12
12
  ".": "./src/index.ts",
13
13
  "./styles.css": "./src/styles/dashboard.css",
14
- "./tokens.css": "./src/styles/tokens.css",
15
- "./primitives": "./src/primitives/index.ts",
16
- "./i18n": "./src/i18n/index.ts",
17
14
  "./permissions": "./src/domains/permissions/index.ts",
18
15
  "./session": "./src/domains/session/index.ts",
19
16
  "./modules": "./src/domains/modules/index.ts",
@@ -67,8 +64,9 @@
67
64
  "react-router-dom": "^6.0.0 || ^7.0.0"
68
65
  },
69
66
  "dependencies": {
70
- "@umituz/web-design-system": "^4.5.3",
71
- "lucide-react": "^0.577.0"
67
+ "@umituz/web-design-system": "^4.8.1",
68
+ "lucide-react": "^0.577.0",
69
+ "@umituz/web-localization": "^1.2.1"
72
70
  },
73
71
  "devDependencies": {
74
72
  "@types/node": "^22.20.5",
@@ -1,8 +1,3 @@
1
- /**
2
- * Analytics Card — chart/metric container on the design-system Card.
3
- * Size modifiers ("sm"/"lg") are dashboard-owned padding overrides.
4
- */
5
-
6
1
  import { Loader2, AlertCircle } from "lucide-react";
7
2
  import {
8
3
  Card,
@@ -11,7 +6,7 @@ import {
11
6
  CardDescription,
12
7
  CardContent,
13
8
  } from "@umituz/web-design-system/organisms";
14
- import { cn } from "../../../primitives";
9
+ import { cn } from "@umituz/web-design-system/utils/cn";
15
10
  import type { AnalyticsCardProps } from "../types/analytics";
16
11
  import { MetricCard } from "./MetricCard";
17
12
  import { AnalyticsChart } from "./AnalyticsChart";
@@ -1,16 +1,6 @@
1
- /**
2
- * AnalyticsChart
3
- *
4
- * Dependency-free SVG chart renderer (line / area / bar / pie / donut).
5
- * Replaced the recharts wrapper in v4 — same ChartConfig contract,
6
- * colors from `--u-*`-friendly CSS color strings, geometry centered
7
- * here (no magic numbers at call sites). Tooltips are native SVG
8
- * <title> elements; unsupported types render the empty state.
9
- */
10
-
11
1
  import { useMemo } from "react";
12
- import { cn } from "../../../primitives";
13
- import { useT } from "../../../i18n";
2
+ import { cn } from "@umituz/web-design-system/utils/cn";
3
+ import { useT } from "@umituz/web-localization/react";
14
4
  import type { ChartConfig, ChartData, TimeSeriesData } from "../types/analytics";
15
5
  import { generateChartColors } from "../utils/analytics";
16
6
  import { ANALYTICS_KEYS } from "../utils/i18nKeys";
@@ -46,7 +36,6 @@ const toNumber = (value: unknown): number => {
46
36
  return Number.isFinite(num) ? num : 0;
47
37
  };
48
38
 
49
- /** Normalize config.data into labeled rows of series values. */
50
39
  const toRows = (
51
40
  data: TimeSeriesData[] | ChartData[],
52
41
  keys: string[],
@@ -66,7 +55,6 @@ const rowsDomain = (rows: ChartRow[]): { min: number; max: number } => {
66
55
  return { min, max };
67
56
  };
68
57
 
69
- /** Keep at most `X_LABEL_SAMPLE` x labels evenly spaced. */
70
58
  const shouldShowLabel = (index: number, count: number): boolean => {
71
59
  if (count <= X_LABEL_SAMPLE) return true;
72
60
  const step = Math.ceil((count - 1) / (X_LABEL_SAMPLE - 1));
@@ -1,27 +1,13 @@
1
- /**
2
- * AnalyticsLayout
3
- *
4
- * Top-level analytics page shell. All actions delegate to the
5
- * consumer via callbacks — no console.log, no no-op handlers.
6
- * The legacy "kpis" prop has been removed in favor of the typed
7
- * `metrics` array (breaking change called out in changelog).
8
- */
9
-
10
1
  import { useMemo } from "react";
11
2
  import { RefreshCw, Download, Calendar, Loader2 } from "lucide-react";
12
- import { useT } from "../../../i18n";
13
- import { cn } from "../../../primitives";
14
- import { Button } from "../../../primitives";
3
+ import { useT } from "@umituz/web-localization/react";
4
+ import { cn } from "@umituz/web-design-system/utils/cn";
5
+ import { Button } from "@umituz/web-design-system/atoms";
15
6
  import type { AnalyticsLayoutProps, AnalyticsPeriod } from "../types/analytics";
16
7
  import { AnalyticsCard } from "./AnalyticsCard";
17
8
  import { MetricCard } from "./MetricCard";
18
9
  import { ANALYTICS_KEYS } from "../utils/i18nKeys";
19
10
 
20
- /**
21
- * Map analytics period tokens to localized display labels.
22
- * Periods not in this map fall back to the raw token — better
23
- * to show the key than an empty select option.
24
- */
25
11
  const PERIOD_LABEL: Record<AnalyticsPeriod, string> = {
26
12
  '7d': ANALYTICS_KEYS.common.last7Days,
27
13
  '30d': ANALYTICS_KEYS.common.last30Days,
@@ -1,12 +1,7 @@
1
- /**
2
- * MetricCard — dashboard logic (growth, i18n, a11y) on top of the
3
- * design-system MetricCard presentation.
4
- */
5
-
6
1
  import {
7
2
  MetricCard as DSMetricCard,
8
3
  } from "@umituz/web-design-system/organisms";
9
- import { useT } from "../../../i18n";
4
+ import { useT } from "@umituz/web-localization/react";
10
5
  import type { MetricCardProps } from "../types/analytics";
11
6
  import { formatMetricValue, calculateGrowth, getTrend } from "../utils/analytics";
12
7
  import { ANALYTICS_KEYS } from "../utils/i18nKeys";
@@ -1,9 +1,4 @@
1
- /**
2
- * Analytics Domain i18n Keys
3
- */
4
-
5
1
  export const ANALYTICS_KEYS = {
6
- // Common
7
2
  common: {
8
3
  export: 'analytics.common.export',
9
4
  refresh: 'analytics.common.refresh',
@@ -16,23 +11,19 @@ export const ANALYTICS_KEYS = {
16
11
  loading: 'analytics.common.loading',
17
12
  },
18
13
 
19
- // Metric card
20
14
  metric: {
21
15
  noData: 'analytics.metric.noData',
22
16
  change: 'analytics.metric.change',
23
17
  },
24
18
 
25
- // Analytics card
26
19
  card: {
27
20
  title: 'analytics.card.title',
28
21
  },
29
22
 
30
- // Chart
31
23
  chart: {
32
24
  noData: 'analytics.chart.noData',
33
25
  },
34
26
 
35
- // Layout
36
27
  layout: {
37
28
  title: 'analytics.layout.title',
38
29
  export: 'analytics.layout.export',
@@ -1,22 +1,8 @@
1
- /**
2
- * Auth Layout Component
3
- *
4
- * Configurable layout wrapper for authentication pages.
5
- * Strings stay localizable via the optional `translate` prop; when it
6
- * is not provided the embedded English fallbacks are rendered.
7
- * Styling is entirely `udb-auth*` classes from the package stylesheet.
8
- */
9
-
10
1
  import { BrandLogo } from "../../layouts/components";
11
- import { cn } from "../../../primitives";
2
+ import { cn } from "@umituz/web-design-system/utils/cn";
12
3
  import { AUTH_KEYS } from "../utils/i18nKeys";
13
4
  import type { AuthLayoutProps, Translate } from "../types/auth";
14
5
 
15
- /**
16
- * Embedded fallbacks used when no `translate` prop is supplied.
17
- * Keys mirror the AUTH_KEYS catalog so consumers can override
18
- * every string via their own i18n setup.
19
- */
20
6
  const DEFAULT_STRINGS: Record<string, string> = {
21
7
  [AUTH_KEYS.layout.backToHome]: "Back to home",
22
8
  [AUTH_KEYS.layout.orContinueWith]: "Or continue with",
@@ -30,20 +16,17 @@ export const AuthLayout = ({
30
16
  children,
31
17
  }: AuthLayoutProps) => {
32
18
  const t: Translate = translate ?? ((key) => DEFAULT_STRINGS[key] ?? key);
33
- // Prefer an explicit home route; fall back to afterLoginRoute for backwards compatibility.
34
19
  const homeRoute = config.homeRoute ?? config.afterLoginRoute;
35
20
  const footerLinks = config.footerLinks ?? [];
36
21
 
37
22
  return (
38
23
  <div className="udb-root udb-auth">
39
- {/* Header */}
40
24
  <header className="udb-auth__header">
41
25
  <div className="udb-auth__brand">
42
26
  <BrandLogo size={32} />
43
27
  <span className="udb-auth__brand-name">{config.brandName}</span>
44
28
  </div>
45
29
 
46
- {/* Additional Header Content */}
47
30
  {homeRoute && (
48
31
  <a href={homeRoute} className="udb-auth__home-link">
49
32
  {t(AUTH_KEYS.layout.backToHome)}
@@ -51,33 +34,26 @@ export const AuthLayout = ({
51
34
  )}
52
35
  </header>
53
36
 
54
- {/* Main Content */}
55
37
  <main className="udb-auth__main">
56
38
  <div className="udb-auth__column">
57
- {/* Card Container */}
58
39
  <div className="udb-auth__card">
59
- {/* Tagline */}
60
40
  {config.brandTagline && (
61
41
  <p className="udb-auth__tagline">
62
42
  {config.brandTagline}
63
43
  </p>
64
44
  )}
65
45
 
66
- {/* Children Content (Forms) */}
67
46
  {children}
68
47
  </div>
69
48
 
70
- {/* Social Login */}
71
49
  {config.showSocialLogin && config.socialProviders && config.socialProviders.length > 0 && (
72
50
  <div className="udb-auth__social">
73
- {/* Divider */}
74
51
  <div className="udb-divider-row">
75
52
  <span className="udb-divider-row__label">
76
53
  {t(AUTH_KEYS.layout.orContinueWith)}
77
54
  </span>
78
55
  </div>
79
56
 
80
- {/* Social Buttons */}
81
57
  <div className="udb-social-grid">
82
58
  {config.socialProviders.map((provider) => (
83
59
  <button
@@ -96,7 +72,6 @@ export const AuthLayout = ({
96
72
  </div>
97
73
  </main>
98
74
 
99
- {/* Footer */}
100
75
  <footer className="udb-auth__footer">
101
76
  <div className="udb-auth__footer-inner">
102
77
  <p>
@@ -1,16 +1,8 @@
1
- /**
2
- * ForgotPasswordForm
3
- *
4
- * Composed of shared auth primitives (EmailInput, AuthErrorBanner).
5
- * All copy is i18n-keyed; the success state uses lucide icons
6
- * instead of the previous `✓` Unicode glyphs.
7
- */
8
-
9
1
  import { useState } from "react";
10
2
  import { useNavigate } from "react-router-dom";
11
- import { useT } from "../../../i18n";
3
+ import { useT } from "@umituz/web-localization/react";
12
4
  import { ArrowLeft, Loader2, CheckCircle2, Check } from "lucide-react";
13
- import { Button } from "../../../primitives";
5
+ import { Button } from "@umituz/web-design-system/atoms";
14
6
  import type { ForgotPasswordFormProps, Translate } from "../types/auth";
15
7
  import { validateForgotPassword } from "../utils/auth";
16
8
  import { AUTH_KEYS } from "../utils/i18nKeys";
@@ -64,10 +56,6 @@ export const ForgotPasswordForm = ({
64
56
 
65
57
  setIsLoading(true);
66
58
  try {
67
- // Hand off to the consumer's auth provider. The form has
68
- // no network knowledge of its own — it's pure orchestration.
69
- // The submitted email is passed through so the consumer can
70
- // actually trigger the reset email.
71
59
  await onSuccess?.({ email });
72
60
  setSuccess(true);
73
61
  } catch (err) {
@@ -1,15 +1,7 @@
1
- /**
2
- * LoginForm
3
- *
4
- * Composed from shared auth primitives (EmailInput, PasswordInput,
5
- * AuthErrorBanner, SocialLoginButtons). The form's job is to
6
- * orchestrate them — UI rendering and validation live elsewhere.
7
- */
8
-
9
1
  import { useState, useCallback } from "react";
10
2
  import { useNavigate } from "react-router-dom";
11
- import { useT } from "../../../i18n";
12
- import { Button, Checkbox } from "../../../primitives";
3
+ import { useT } from "@umituz/web-localization/react";
4
+ import { Button, Checkbox } from "@umituz/web-design-system/atoms";
13
5
  import { Loader2 } from "lucide-react";
14
6
  import { validateLogin } from "../utils/auth";
15
7
  import type {
@@ -68,11 +60,6 @@ export const LoginForm = ({
68
60
  const [loading, setLoading] = useState<boolean>(false);
69
61
  const [error, setError] = useState<string | null>(null);
70
62
 
71
- /**
72
- * Auth execution. A real provider is supplied via onLoginAttempt.
73
- * The mock path accepts ANY credentials and is therefore opt-in
74
- * (`enableMockAuth`) — never a silent default in production builds.
75
- */
76
63
  const performLogin = useCallback(
77
64
  async (credentials: LoginCredentials): Promise<User> => {
78
65
  if (onLoginAttempt) {
@@ -1,18 +1,9 @@
1
- /**
2
- * RegisterForm
3
- *
4
- * Composed from shared auth primitives (EmailInput, PasswordInput,
5
- * PasswordStrengthIndicator, AuthErrorBanner, SocialLoginButtons).
6
- * Hardcoded mock user data + 1s setTimeout are gone — the form is
7
- * pure orchestration over the consumer's `onRegisterAttempt` provider.
8
- */
9
-
10
1
  import { useState, useCallback } from "react";
11
2
  import { useNavigate } from "react-router-dom";
12
- import { useT } from "../../../i18n";
3
+ import { useT } from "@umituz/web-localization/react";
13
4
  import { Loader2 } from "lucide-react";
14
- import { Button, Checkbox, Input } from "../../../primitives";
15
- import { cn } from "../../../primitives";
5
+ import { Button, Checkbox, Input } from "@umituz/web-design-system/atoms";
6
+ import { cn } from "@umituz/web-design-system/utils/cn";
16
7
  import type { RegisterFormProps, RegisterData, Translate } from "../types/auth";
17
8
  import { validateRegister } from "../utils/auth";
18
9
  import { AUTH_KEYS } from "../utils/i18nKeys";
@@ -101,8 +92,6 @@ export const RegisterForm = ({
101
92
  setIsLoading(true);
102
93
  try {
103
94
  if (!onRegisterAttempt) {
104
- // The form has no auth provider — fail loud rather than
105
- // silently inserting a mock user.
106
95
  throw new Error('No register handler configured');
107
96
  }
108
97
  const registerData: RegisterData = { email, password, name };
@@ -1,16 +1,9 @@
1
- /**
2
- * ResetPasswordForm
3
- *
4
- * Composed from shared auth primitives (PasswordInput, PasswordStrengthIndicator,
5
- * AuthErrorBanner). All copy is i18n-keyed.
6
- */
7
-
8
1
  import { useState } from "react";
9
2
  import { useNavigate } from "react-router-dom";
10
- import { useT } from "../../../i18n";
3
+ import { useT } from "@umituz/web-localization/react";
11
4
  import { Loader2, CheckCircle2 } from "lucide-react";
12
- import { Button, Input } from "../../../primitives";
13
- import { cn } from "../../../primitives";
5
+ import { Button, Input } from "@umituz/web-design-system/atoms";
6
+ import { cn } from "@umituz/web-design-system/utils/cn";
14
7
  import type { ResetPasswordFormProps, Translate } from "../types/auth";
15
8
  import { validateResetPassword } from "../utils/auth";
16
9
  import { AUTH_KEYS } from "../utils/i18nKeys";
@@ -68,11 +61,7 @@ export const ResetPasswordForm = ({
68
61
 
69
62
  setIsLoading(true);
70
63
  try {
71
- // Hand off the actual reset to the consumer. The form is
72
- // pure orchestration; no network knowledge here. Token and the
73
- // new password are passed through so the consumer can persist it.
74
64
  await onSuccess?.({ token, password });
75
- // Don't keep the new password in component state after completion.
76
65
  setPassword("");
77
66
  setConfirmPassword("");
78
67
  setSuccess(true);
@@ -1,19 +1,9 @@
1
- /**
2
- * AuthErrorBanner
3
- *
4
- * Inline error display for auth forms. Renders an alert with the
5
- * provided i18n key resolved by the consumer's translation function.
6
- */
7
-
8
1
  import { AlertCircle } from "lucide-react";
9
- import { cn } from "../../../../primitives";
2
+ import { cn } from "@umituz/web-design-system/utils/cn";
10
3
 
11
4
  export interface AuthErrorBannerProps {
12
- /** i18n key for the message (already resolved by the consumer) */
13
5
  message?: string | null;
14
- /** Translation function used to resolve the key */
15
6
  translate: (key: string) => string;
16
- /** Optional className for layout integration */
17
7
  className?: string;
18
8
  }
19
9