@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
@@ -1,21 +1,12 @@
1
- /**
2
- * AuditLogList — admin skeleton for the audit trail screen.
3
- * Entries arrive as props; the list is display-only.
4
- */
5
-
6
1
  import { ScrollText } from "lucide-react";
7
- import { useT } from "../../../i18n";
2
+ import { useT } from "@umituz/web-localization/react";
8
3
  import { SETTINGS_ADMIN_KEYS } from "../utils/i18nKeys";
9
4
 
10
5
  export interface AuditEntry {
11
6
  id: string;
12
- /** Who performed the action. */
13
7
  actor: string;
14
- /** What happened, e.g. "role.changed". */
15
8
  action: string;
16
- /** Optional target of the action (user, invoice...). */
17
9
  target?: string;
18
- /** ISO timestamp. */
19
10
  at: string;
20
11
  }
21
12
 
@@ -1,11 +1,5 @@
1
- /**
2
- * PermissionMatrixScreen — admin skeleton rendering the role x
3
- * permission matrix. Read-only by default; pass `onToggle` to make
4
- * cells interactive (delegated — persistence is the host's job).
5
- */
6
-
7
1
  import { Check, Minus } from "lucide-react";
8
- import { cn } from "../../../primitives";
2
+ import { cn } from "@umituz/web-design-system/utils/cn";
9
3
  import { hasPermission } from "../../permissions/hasPermission";
10
4
  import type {
11
5
  Permission,
@@ -16,7 +10,6 @@ import type {
16
10
  export interface PermissionMatrixScreenProps {
17
11
  matrix: PermissionMatrix;
18
12
  roles: RoleInfo[];
19
- /** Permission column keys, in display order. */
20
13
  permissions: Permission[];
21
14
  onToggle?: (role: string, permission: Permission, granted: boolean) => void;
22
15
  }
@@ -1,28 +1,15 @@
1
1
  import { useEffect, useState } from "react";
2
2
  import { Outlet, useLocation, useNavigate } from "react-router-dom";
3
- import { Skeleton, Button } from "../../../primitives";
3
+ import { Skeleton, Button } from "@umituz/web-design-system/atoms";
4
4
  import { ChevronLeft, Menu } from "lucide-react";
5
5
  import { SettingsSection } from "./SettingsSection";
6
6
  import type { SettingsConfig } from "../types/settings";
7
7
 
8
8
  interface SettingsLayoutProps {
9
- /** Settings configuration */
10
9
  config: SettingsConfig;
11
- /**
12
- * Artificial route-transition skeleton duration in ms (default: 0 = off).
13
- * Content renders immediately by default; set > 0 only if you want
14
- * a skeleton to mask route swaps.
15
- */
16
10
  routeTransitionMs?: number;
17
11
  }
18
12
 
19
- /**
20
- * Settings Layout Component
21
- *
22
- * Main layout wrapper for settings pages.
23
- * Provides sidebar navigation and content area. Styling is entirely
24
- * `udb-settings*` classes from the package stylesheet.
25
- */
26
13
  export const SettingsLayout = ({
27
14
  config,
28
15
  routeTransitionMs = 0,
@@ -33,9 +20,6 @@ export const SettingsLayout = ({
33
20
  const [mobileOpen, setMobileOpen] = useState(false);
34
21
  const [loading, setLoading] = useState(routeTransitionMs > 0);
35
22
 
36
- // Optional route-change skeleton. Cleanup is essential: setTimeout must be
37
- // cancelled on unmount/route change. With routeTransitionMs = 0 (default)
38
- // no artificial delay is applied at all.
39
23
  useEffect(() => {
40
24
  if (routeTransitionMs <= 0) {
41
25
  setLoading(false);
@@ -78,7 +62,6 @@ export const SettingsLayout = ({
78
62
 
79
63
  return (
80
64
  <div className="udb-root udb-settings">
81
- {/* Desktop Sidebar */}
82
65
  <aside className={`udb-settings__sidebar${collapsed ? " udb-settings__sidebar--collapsed" : ""}`}>
83
66
  {renderSidebarHeader(() => setCollapsed((prev) => !prev), false)}
84
67
  <nav className="udb-settings__nav">
@@ -94,7 +77,6 @@ export const SettingsLayout = ({
94
77
  </nav>
95
78
  </aside>
96
79
 
97
- {/* Mobile Menu Overlay */}
98
80
  {mobileOpen && (
99
81
  <div className="udb-settings__mobile">
100
82
  <div
@@ -118,9 +100,7 @@ export const SettingsLayout = ({
118
100
  </div>
119
101
  )}
120
102
 
121
- {/* Main Content Area */}
122
103
  <div className="udb-settings__main">
123
- {/* Mobile Header */}
124
104
  <header className="udb-settings__mobile-header">
125
105
  <div className="udb-settings__mobile-lead">
126
106
  <Button
@@ -1,27 +1,16 @@
1
1
  import { useMemo } from "react";
2
2
  import { Link } from "react-router-dom";
3
3
  import { ChevronRight } from "lucide-react";
4
- import { cn } from "../../../primitives";
4
+ import { cn } from "@umituz/web-design-system/utils/cn";
5
5
  import type { SettingsSection as SettingsSectionType } from "../types/settings";
6
6
 
7
7
  interface SettingsSectionProps {
8
- /** Section configuration */
9
8
  section: SettingsSectionType;
10
- /** Current path */
11
9
  currentPath?: string;
12
- /** On navigate callback */
13
10
  onNavigate?: (path: string) => void;
14
- /** Collapsed state */
15
11
  collapsed?: boolean;
16
12
  }
17
13
 
18
- /**
19
- * Settings Section Component
20
- *
21
- * Displays a section of settings items.
22
- * Items without a path and without an onClick handler are hidden
23
- * (an empty interactive element violates a11y and is dead code).
24
- */
25
14
  export const SettingsSection = ({
26
15
  section,
27
16
  currentPath,
@@ -48,7 +37,6 @@ export const SettingsSection = ({
48
37
  const isActive = currentPath === item.path;
49
38
  const hasNavigation = Boolean(item.path) || Boolean(item.onClick);
50
39
 
51
- // Skip rendering items that have neither a path nor a click handler.
52
40
  if (!hasNavigation) {
53
41
  return null;
54
42
  }
@@ -1,11 +1,5 @@
1
- /**
2
- * UserManagementTable — admin skeleton for the users screen.
3
- * Config-driven: rows and role catalog come in as props, role
4
- * changes delegate out.
5
- */
6
-
7
1
  import { DataTable, type Column } from "@umituz/web-design-system/organisms";
8
- import { useT } from "../../../i18n";
2
+ import { useT } from "@umituz/web-localization/react";
9
3
  import { SETTINGS_ADMIN_KEYS } from "../utils/i18nKeys";
10
4
  import type { RoleKey, RoleInfo } from "../../permissions/types";
11
5
 
@@ -20,7 +14,6 @@ export interface ManagedUser {
20
14
  export interface UserManagementTableProps {
21
15
  users: ManagedUser[];
22
16
  roles: RoleInfo[];
23
- /** Provide to render an editable role select per row. */
24
17
  onRoleChange?: (userId: string, role: RoleKey) => void;
25
18
  }
26
19
 
@@ -1,9 +1,3 @@
1
- /**
2
- * Settings domain i18n keys (admin skeleton screens) — the
3
- * documented string contract. Column titles and role labels come
4
- * from props; only empty/denied states fall back to these keys.
5
- */
6
-
7
1
  export const SETTINGS_ADMIN_KEYS = {
8
2
  users: {
9
3
  empty: "settings.users.empty",
package/src/index.ts CHANGED
@@ -1,13 +1,3 @@
1
- /**
2
- * @umituz/web-dashboard
3
- *
4
- * Dashboard Layout System - Customizable, themeable dashboard layouts
5
- * with comprehensive analytics services and config-based architecture.
6
- *
7
- * @version 3.0.0
8
- */
9
-
10
- // Core domains with complete public API
11
1
  export * from './domains/layouts';
12
2
  export * from './domains/settings';
13
3
  export * from './domains/calendar';
@@ -21,7 +11,6 @@ export {
21
11
  type User,
22
12
  } from './domains/auth';
23
13
 
24
- // Analytics with conflict resolution
25
14
  export {
26
15
  useAnalytics,
27
16
  MetricCard,
@@ -46,7 +35,6 @@ export {
46
35
  roundTo,
47
36
  generateColor,
48
37
  generateChartColors,
49
- // Types
50
38
  type Metric,
51
39
  type TimeSeriesData,
52
40
  type ChartData,
@@ -66,13 +54,10 @@ export {
66
54
  type AnalyticsExportOptions,
67
55
  } from './domains/analytics';
68
56
 
69
- // Calendar
70
57
  export {
71
58
  useCalendar,
72
59
  calendarService,
73
- // Services
74
60
  CalendarService,
75
- // Utils
76
61
  getWeekDates,
77
62
  getMonthDays,
78
63
  isDateInRange,
@@ -80,7 +65,6 @@ export {
80
65
  isSameDay,
81
66
  getViewRange,
82
67
  generateTimeSlots,
83
- // Types
84
68
  type ContentItem,
85
69
  DEFAULT_CALENDAR_CONFIG,
86
70
  type CalendarEvent,
@@ -94,7 +78,6 @@ export {
94
78
  type ICalendarService,
95
79
  } from './domains/calendar';
96
80
 
97
- // Config with renamed exports to avoid conflicts
98
81
  export {
99
82
  DEFAULT_DASHBOARD_CONFIG,
100
83
  type AnalyticsServiceType,
@@ -0,0 +1,42 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { describe, expect, it } from "vitest";
3
+
4
+ const css = readFileSync(new URL("./dashboard.css", import.meta.url), "utf8");
5
+
6
+ const defined = new Set([...css.matchAll(/(--udb-[a-z0-9-]+)\s*:/g)].map((m) => m[1]));
7
+ const used = new Set([...css.matchAll(/var\((--udb-[a-z0-9-]+)\)/g)].map((m) => m[1]));
8
+
9
+ describe("dashboard stylesheet contract", () => {
10
+ it("defines every --udb variable it uses", () => {
11
+ expect([...used].filter((v) => !defined.has(v))).toEqual([]);
12
+ });
13
+
14
+ it("imports the design-system stylesheet", () => {
15
+ expect(css).toContain('@import "@umituz/web-design-system/styles.css";');
16
+ });
17
+
18
+ it("carries no legacy --u-* tokens", () => {
19
+ expect(css.match(/--u-[a-z0-9-]+/g) ?? []).toEqual([]);
20
+ });
21
+
22
+ it("reads only design-system variables that exist or are documented optional slots", () => {
23
+ const optional = new Set([
24
+ "--color-primary-hover",
25
+ "--color-primary-soft",
26
+ "--color-destructive-hover",
27
+ "--color-destructive-soft",
28
+ "--color-success-soft",
29
+ "--color-warning-soft",
30
+ ]);
31
+ const dsCss = readFileSync(
32
+ new URL("../../node_modules/@umituz/web-design-system/dist/styles.css", import.meta.url),
33
+ "utf8",
34
+ );
35
+ const dsDefined = new Set([...dsCss.matchAll(/(--[a-z][a-z0-9-]*)\s*:/g)].map((m) => m[1]));
36
+ const read = new Set([...css.matchAll(/var\((--[a-z][a-z0-9-]*)[,)]/g)].map((m) => m[1]));
37
+ const missing = [...read].filter(
38
+ (v) => !v.startsWith("--udb-") && !dsDefined.has(v) && !optional.has(v),
39
+ );
40
+ expect(missing).toEqual([]);
41
+ });
42
+ });