@umituz/web-design-system 5.3.0 → 6.0.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 (150) hide show
  1. package/dist/styles.css +1 -1
  2. package/package.json +1 -1
  3. package/src/__tests__/cn.test.ts +0 -3
  4. package/src/__tests__/component-slots.test.tsx +0 -4
  5. package/src/__tests__/components.smoke.test.tsx +3 -11
  6. package/src/__tests__/money.test.tsx +0 -3
  7. package/src/__tests__/productivity-components.test.tsx +135 -0
  8. package/src/__tests__/styles.contract.test.ts +0 -13
  9. package/src/domain/tokens/index.ts +0 -7
  10. package/src/domain/tokens/responsive-map.tokens.ts +18 -107
  11. package/src/domain/types/breakpoint.types.ts +9 -13
  12. package/src/domain/types/component.types.ts +0 -4
  13. package/src/domain/types/index.ts +0 -5
  14. package/src/global.d.ts +0 -4
  15. package/src/index.ts +82 -29
  16. package/src/infrastructure/constants/breakpoint.constants.ts +0 -31
  17. package/src/infrastructure/constants/component.constants.ts +0 -4
  18. package/src/infrastructure/constants/index.ts +0 -5
  19. package/src/infrastructure/constants/size-variant.constants.ts +0 -33
  20. package/src/infrastructure/constants/spacing.constants.ts +34 -63
  21. package/src/infrastructure/constants/timing.constants.ts +0 -18
  22. package/src/infrastructure/constants/typography.constants.ts +22 -54
  23. package/src/infrastructure/utils/calculation.utils.ts +0 -9
  24. package/src/infrastructure/utils/cn.util.ts +0 -18
  25. package/src/infrastructure/utils/hash.util.ts +0 -5
  26. package/src/infrastructure/utils/index.ts +0 -5
  27. package/src/infrastructure/utils/money.utils.ts +0 -7
  28. package/src/infrastructure/utils/responsive.utils.ts +0 -66
  29. package/src/presentation/atoms/AspectRatio.tsx +0 -10
  30. package/src/presentation/atoms/Badge.tsx +0 -5
  31. package/src/presentation/atoms/BatteryPill.tsx +0 -5
  32. package/src/presentation/atoms/Button.tsx +0 -2
  33. package/src/presentation/atoms/Checkbox.tsx +0 -4
  34. package/src/presentation/atoms/CopyButton.tsx +93 -0
  35. package/src/presentation/atoms/Divider.tsx +0 -4
  36. package/src/presentation/atoms/HeatmapStrip.tsx +0 -10
  37. package/src/presentation/atoms/Hide.tsx +0 -24
  38. package/src/presentation/atoms/Icon.tsx +0 -4
  39. package/src/presentation/atoms/IconButton.tsx +0 -4
  40. package/src/presentation/atoms/Input.tsx +0 -4
  41. package/src/presentation/atoms/Kbd.tsx +0 -4
  42. package/src/presentation/atoms/Label.tsx +0 -4
  43. package/src/presentation/atoms/Link.tsx +0 -4
  44. package/src/presentation/atoms/Money.tsx +0 -6
  45. package/src/presentation/atoms/Progress.tsx +0 -6
  46. package/src/presentation/atoms/Radio.tsx +0 -4
  47. package/src/presentation/atoms/Separator.tsx +0 -4
  48. package/src/presentation/atoms/Show.tsx +0 -24
  49. package/src/presentation/atoms/Skeleton.tsx +0 -4
  50. package/src/presentation/atoms/Slider.tsx +0 -4
  51. package/src/presentation/atoms/Sparkline.tsx +0 -4
  52. package/src/presentation/atoms/Spinner.tsx +0 -4
  53. package/src/presentation/atoms/StatusDot.tsx +79 -0
  54. package/src/presentation/atoms/Switch.tsx +0 -4
  55. package/src/presentation/atoms/Text.tsx +0 -4
  56. package/src/presentation/atoms/Textarea.tsx +0 -4
  57. package/src/presentation/atoms/Toggle.tsx +0 -4
  58. package/src/presentation/atoms/Tooltip.tsx +0 -4
  59. package/src/presentation/atoms/index.ts +9 -9
  60. package/src/presentation/hooks/index.ts +0 -5
  61. package/src/presentation/hooks/useClickOutside.ts +0 -6
  62. package/src/presentation/hooks/useClipboard.ts +0 -4
  63. package/src/presentation/hooks/useDebounce.ts +0 -8
  64. package/src/presentation/hooks/useKeyboard.ts +0 -6
  65. package/src/presentation/hooks/useLocalStorage.ts +0 -4
  66. package/src/presentation/hooks/useMediaQuery.ts +0 -37
  67. package/src/presentation/hooks/useScrollLock.ts +0 -5
  68. package/src/presentation/hooks/useTheme.ts +9 -13
  69. package/src/presentation/hooks/useToggle.ts +0 -4
  70. package/src/presentation/molecules/ActiveFilterTags.tsx +0 -4
  71. package/src/presentation/molecules/Avatar.tsx +0 -5
  72. package/src/presentation/molecules/BookmarkButton.tsx +0 -15
  73. package/src/presentation/molecules/CheckboxGroup.tsx +0 -4
  74. package/src/presentation/molecules/Chip.tsx +0 -5
  75. package/src/presentation/molecules/CodeBlock.tsx +0 -5
  76. package/src/presentation/molecules/ConfirmButton.tsx +125 -0
  77. package/src/presentation/molecules/Field.tsx +0 -7
  78. package/src/presentation/molecules/FormField.tsx +1 -5
  79. package/src/presentation/molecules/InputGroup.tsx +0 -4
  80. package/src/presentation/molecules/ListItem.tsx +0 -4
  81. package/src/presentation/molecules/OptionTile.tsx +0 -10
  82. package/src/presentation/molecules/PasswordInput.tsx +43 -0
  83. package/src/presentation/molecules/RadioGroup.tsx +0 -4
  84. package/src/presentation/molecules/RatingStars.tsx +0 -8
  85. package/src/presentation/molecules/ScrollArea.tsx +0 -4
  86. package/src/presentation/molecules/SearchBox.tsx +0 -4
  87. package/src/presentation/molecules/SearchInput.tsx +110 -0
  88. package/src/presentation/molecules/Select.tsx +0 -4
  89. package/src/presentation/molecules/StatPill.tsx +0 -5
  90. package/src/presentation/molecules/TagInput.tsx +0 -7
  91. package/src/presentation/molecules/Textarea.tsx +0 -4
  92. package/src/presentation/molecules/Toggle.tsx +0 -4
  93. package/src/presentation/molecules/Toolbar.tsx +36 -0
  94. package/src/presentation/molecules/index.ts +25 -8
  95. package/src/presentation/organisms/Accordion.tsx +0 -4
  96. package/src/presentation/organisms/Alert.tsx +0 -4
  97. package/src/presentation/organisms/AvatarStack.tsx +0 -5
  98. package/src/presentation/organisms/Breadcrumb.tsx +0 -7
  99. package/src/presentation/organisms/Card.tsx +0 -6
  100. package/src/presentation/organisms/Checklist.tsx +0 -4
  101. package/src/presentation/organisms/Collapsible.tsx +0 -4
  102. package/src/presentation/organisms/ConfirmDialog.tsx +0 -8
  103. package/src/presentation/organisms/CoverArt.tsx +0 -9
  104. package/src/presentation/organisms/DataTable.tsx +0 -8
  105. package/src/presentation/organisms/DateRangePicker.tsx +0 -9
  106. package/src/presentation/organisms/DescriptionList.tsx +113 -0
  107. package/src/presentation/organisms/Dialog.tsx +0 -4
  108. package/src/presentation/organisms/Drawer.tsx +0 -6
  109. package/src/presentation/organisms/DropdownMenu.tsx +0 -4
  110. package/src/presentation/organisms/ErrorBoundary.tsx +0 -12
  111. package/src/presentation/organisms/FileUploader.tsx +0 -9
  112. package/src/presentation/organisms/FilterPopover.tsx +0 -8
  113. package/src/presentation/organisms/FormModal.tsx +0 -5
  114. package/src/presentation/organisms/HoverCard.tsx +0 -4
  115. package/src/presentation/organisms/KeyValueList.tsx +0 -4
  116. package/src/presentation/organisms/KpiCard.tsx +0 -6
  117. package/src/presentation/organisms/Lightbox.tsx +0 -7
  118. package/src/presentation/organisms/LoadingState.tsx +0 -4
  119. package/src/presentation/organisms/MapPreview.tsx +0 -9
  120. package/src/presentation/organisms/MetricCard.tsx +1 -5
  121. package/src/presentation/organisms/Modal.tsx +0 -4
  122. package/src/presentation/organisms/PhotoGallery.tsx +0 -9
  123. package/src/presentation/organisms/PlanPicker.tsx +0 -5
  124. package/src/presentation/organisms/Popover.tsx +0 -4
  125. package/src/presentation/organisms/Sheet.tsx +0 -4
  126. package/src/presentation/organisms/StatCard.tsx +0 -5
  127. package/src/presentation/organisms/StatsGrid.tsx +110 -0
  128. package/src/presentation/organisms/StatusBadge.tsx +0 -12
  129. package/src/presentation/organisms/Stepper.tsx +0 -5
  130. package/src/presentation/organisms/Table.tsx +0 -4
  131. package/src/presentation/organisms/Tabs.tsx +0 -7
  132. package/src/presentation/organisms/Timeline.tsx +0 -8
  133. package/src/presentation/organisms/Toaster.tsx +0 -9
  134. package/src/presentation/organisms/ToggleGroup.tsx +0 -4
  135. package/src/presentation/organisms/index.ts +10 -11
  136. package/src/presentation/templates/CrudPageTemplate.tsx +69 -0
  137. package/src/presentation/templates/Form.tsx +0 -4
  138. package/src/presentation/templates/List.tsx +0 -4
  139. package/src/presentation/templates/PageHeader.tsx +0 -4
  140. package/src/presentation/templates/PageLayout.tsx +0 -4
  141. package/src/presentation/templates/ProjectSkeleton.tsx +0 -4
  142. package/src/presentation/templates/ResponsiveContainer.tsx +0 -43
  143. package/src/presentation/templates/Section.tsx +0 -4
  144. package/src/presentation/templates/SettingsLayout.tsx +102 -0
  145. package/src/presentation/templates/index.ts +7 -6
  146. package/src/styles/app.css +0 -18
  147. package/src/styles/bridge.css +0 -34
  148. package/src/styles/compile.css +0 -13
  149. package/src/styles/source.css +0 -12
  150. package/src/styles/theme.css +0 -27
@@ -1,7 +1,3 @@
1
- /**
2
- * LoadingState Component (Organism)
3
- * @description Component for displaying loading states (Responsive)
4
- */
5
1
 
6
2
  import { forwardRef } from 'react';
7
3
  import { cn, getSpacing, getGap } from '../../infrastructure/utils';
@@ -1,20 +1,11 @@
1
- /**
2
- * MapPreview Component (Organism)
3
- * @description Static map stand-in drawn with a contour motif — a neutral
4
- * placeholder for locations until a real GIS integration exists. Colors
5
- * come from the semantic tokens, so it adapts to every host theme.
6
- */
7
1
 
8
2
  import { MapPin } from 'lucide-react';
9
3
 
10
4
  export interface MapPreviewProps {
11
- /** Location caption, e.g. "Torba, Bodrum". */
12
5
  label: string;
13
6
  coordinates?: { lat: number; lng: number };
14
7
  height?: number;
15
- /** Secondary caption line, e.g. an integration note. */
16
8
  hint?: string;
17
- /** Degrees formatting for the coordinate readout; defaults to 4 decimals. */
18
9
  formatCoordinate?: (value: number) => string;
19
10
  }
20
11
 
@@ -1,7 +1,3 @@
1
- /**
2
- * MetricCard Component (Organism)
3
- * @description Card component for displaying metrics and statistics with trend indicators (Responsive)
4
- */
5
1
 
6
2
  import { forwardRef } from 'react';
7
3
  import { cn, getSpacing, getIconSize, getTextSize, getGap } from '../../infrastructure/utils';
@@ -21,7 +17,7 @@ export interface MetricCardProps extends BaseProps {
21
17
  variant?: ColorVariant;
22
18
  trendValueFormatter?: (value: number) => string;
23
19
  onClick?: () => void;
24
- responsiveLayout?: boolean; // Enable responsive layout changes
20
+ responsiveLayout?: boolean;
25
21
  }
26
22
 
27
23
  const trendColors: Record<ColorVariant, { positive: string; negative: string; bg: string }> = {
@@ -1,7 +1,3 @@
1
- /**
2
- * Modal Component (Organism)
3
- * @description Convenience modal with title, description, size and footer presets
4
- */
5
1
 
6
2
  import type { ReactNode } from 'react';
7
3
  import { AlertTriangle } from 'lucide-react';
@@ -1,20 +1,11 @@
1
- /**
2
- * PhotoGallery Component (Organism)
3
- * @description Placeholder photo gallery — renders tinted tiles with a
4
- * caption bar for photos that have no storage backend yet. When a host
5
- * wires real image URLs it can render them inside the same tile frame.
6
- */
7
1
 
8
2
  import { Image as ImageIcon, ImageOff } from 'lucide-react';
9
3
  import { cn } from '../../infrastructure/utils';
10
4
 
11
5
  export interface PhotoTile {
12
6
  id: string;
13
- /** Primary caption, e.g. the photo title. */
14
7
  label?: string;
15
- /** Secondary caption line, e.g. a kind tag or a date. */
16
8
  meta?: string;
17
- /** Optional image URL — rendered in place of the placeholder mark. */
18
9
  src?: string;
19
10
  }
20
11
 
@@ -1,8 +1,3 @@
1
- /**
2
- * PlanPicker Component (Organism)
3
- * @description Pricing plan card group with an optional billing cycle switch;
4
- * money stays caller-computed — price and features are plain nodes
5
- */
6
1
 
7
2
  import type { KeyboardEvent, ReactNode } from 'react';
8
3
  import { Check } from 'lucide-react';
@@ -1,7 +1,3 @@
1
- /**
2
- * Popover Component (Organism)
3
- * @description Popover dialog (Shadcn/ui compatible)
4
- */
5
1
 
6
2
  import * as React from 'react';
7
3
  import * as PopoverPrimitive from '@radix-ui/react-popover';
@@ -1,7 +1,3 @@
1
- /**
2
- * Sheet Component (Organism)
3
- * @description Slide-over sheet dialog (Shadcn/ui compatible)
4
- */
5
1
 
6
2
  import * as SheetPrimitive from '@radix-ui/react-dialog';
7
3
  import { X } from 'lucide-react';
@@ -1,7 +1,3 @@
1
- /**
2
- * StatCard Component (Organism)
3
- * @description Enhanced metric card with progress bar and target tracking (Responsive)
4
- */
5
1
 
6
2
  import { forwardRef, type ComponentType } from 'react';
7
3
  import { cn, getSpacing, getIconSize, getContainerSize, getTextSize, getSpaceY, getGap } from '../../infrastructure/utils';
@@ -20,7 +16,6 @@ export interface StatCardProps extends BaseProps {
20
16
  value: number;
21
17
  label?: string;
22
18
  };
23
- /** Secondary context line rendered under the title. */
24
19
  meta?: string;
25
20
  target?: {
26
21
  value: string;
@@ -0,0 +1,110 @@
1
+ import * as React from 'react';
2
+ import { Card } from './Card';
3
+ import { Skeleton } from '../atoms/Skeleton';
4
+ import { TrendingUp, TrendingDown, Minus } from 'lucide-react';
5
+ import { cn } from '../../infrastructure/utils';
6
+
7
+ export interface StatItem {
8
+ id?: string;
9
+ title: string;
10
+ value: string | number;
11
+ change?: string;
12
+ trend?: 'up' | 'down' | 'neutral';
13
+ icon?: React.ReactNode;
14
+ description?: string;
15
+ }
16
+
17
+ export interface StatsGridProps extends React.HTMLAttributes<HTMLDivElement> {
18
+ stats: StatItem[];
19
+ columns?: 2 | 3 | 4;
20
+ loading?: boolean;
21
+ }
22
+
23
+ const colStyles = {
24
+ 2: 'grid-cols-1 sm:grid-cols-2',
25
+ 3: 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3',
26
+ 4: 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-4',
27
+ };
28
+
29
+ export const StatsGrid = React.forwardRef<HTMLDivElement, StatsGridProps>(
30
+ ({ stats, columns = 4, loading = false, className, ...props }, ref) => {
31
+ if (loading) {
32
+ return (
33
+ <div
34
+ ref={ref}
35
+ className={cn('grid gap-4 w-full', colStyles[columns], className)}
36
+ {...props}
37
+ >
38
+ {Array.from({ length: columns }).map((_, i) => (
39
+ <Card key={i} className="p-5 flex flex-col gap-3">
40
+ <Skeleton className="h-4 w-24" />
41
+ <Skeleton className="h-8 w-32" />
42
+ <Skeleton className="h-3 w-40" />
43
+ </Card>
44
+ ))}
45
+ </div>
46
+ );
47
+ }
48
+
49
+ return (
50
+ <div
51
+ ref={ref}
52
+ className={cn('grid gap-4 w-full', colStyles[columns], className)}
53
+ {...props}
54
+ >
55
+ {stats.map((stat, idx) => {
56
+ const isUp = stat.trend === 'up';
57
+ const isDown = stat.trend === 'down';
58
+
59
+ return (
60
+ <Card
61
+ key={stat.id ?? idx}
62
+ className="p-5 flex flex-col justify-between transition-shadow hover:shadow-md"
63
+ >
64
+ <div className="flex items-start justify-between gap-2">
65
+ <span className="text-sm font-medium text-muted-foreground truncate">
66
+ {stat.title}
67
+ </span>
68
+ {stat.icon && (
69
+ <div className="size-9 rounded-lg bg-accent/60 flex items-center justify-center text-foreground shrink-0 [&_svg]:size-4">
70
+ {stat.icon}
71
+ </div>
72
+ )}
73
+ </div>
74
+
75
+ <div className="mt-3 flex items-baseline justify-between gap-2">
76
+ <div className="text-2xl font-bold tracking-tight text-foreground">
77
+ {stat.value}
78
+ </div>
79
+
80
+ {stat.change && (
81
+ <span
82
+ className={cn(
83
+ 'inline-flex items-center gap-1 text-xs font-semibold px-2 py-0.5 rounded-full',
84
+ isUp && 'bg-emerald-500/10 text-emerald-600 dark:text-emerald-400',
85
+ isDown && 'bg-rose-500/10 text-rose-600 dark:text-rose-400',
86
+ !isUp && !isDown && 'bg-accent text-muted-foreground'
87
+ )}
88
+ >
89
+ {isUp && <TrendingUp className="size-3" />}
90
+ {isDown && <TrendingDown className="size-3" />}
91
+ {!isUp && !isDown && <Minus className="size-3" />}
92
+ <span>{stat.change}</span>
93
+ </span>
94
+ )}
95
+ </div>
96
+
97
+ {stat.description && (
98
+ <p className="mt-2 text-xs text-muted-foreground line-clamp-1">
99
+ {stat.description}
100
+ </p>
101
+ )}
102
+ </Card>
103
+ );
104
+ })}
105
+ </div>
106
+ );
107
+ }
108
+ );
109
+
110
+ StatsGrid.displayName = 'StatsGrid';
@@ -1,9 +1,3 @@
1
- /**
2
- * StatusBadge Component (Organism)
3
- * @description Vocab-driven status badge — resolves a raw value against a
4
- * status map (label + tone), falling back to a neutral badge with the
5
- * raw value as its label.
6
- */
7
1
 
8
2
  import type { ReactNode } from 'react';
9
3
  import { Badge } from '../atoms/Badge';
@@ -17,11 +11,6 @@ export interface StatusEntry {
17
11
 
18
12
  export type StatusVocab = Record<string, StatusEntry>;
19
13
 
20
- /**
21
- * Status vocab fabric — build a vocab from a domain label map (raw value →
22
- * display label) plus an optional tone table (raw value → badge tone).
23
- * Entries without a tone render neutral.
24
- */
25
14
  export function statusVocab(
26
15
  labels: Record<string, string>,
27
16
  tones: Record<string, BadgeVariant> = {},
@@ -36,7 +25,6 @@ export function statusVocab(
36
25
  export interface StatusBadgeProps {
37
26
  vocab: StatusVocab;
38
27
  value: string;
39
- /** Render text in place of the vocab entry's label (tone still comes from the vocab). */
40
28
  label?: ReactNode;
41
29
  dot?: boolean;
42
30
  mono?: boolean;
@@ -1,8 +1,3 @@
1
- /**
2
- * Stepper Component (Organism)
3
- * @description Horizontal or vertical step indicator with derived status,
4
- * optional click navigation and per-step override/lock control
5
- */
6
1
 
7
2
  import type { ReactNode } from 'react';
8
3
  import { Check } from 'lucide-react';
@@ -1,7 +1,3 @@
1
- /**
2
- * Table Component (Organism)
3
- * @description Data table component
4
- */
5
1
 
6
2
  import { forwardRef, type HTMLAttributes, type TdHTMLAttributes, type ThHTMLAttributes } from 'react';
7
3
  import React from 'react';
@@ -1,7 +1,3 @@
1
- /**
2
- * Tabs Component (Organism)
3
- * @description Tabbed interface
4
- */
5
1
 
6
2
  import { useRef, useState, useCallback, type KeyboardEvent, type ReactNode, type HTMLAttributes } from 'react';
7
3
  import { cn } from '../../infrastructure/utils';
@@ -23,7 +19,6 @@ export interface TabsProps extends HTMLAttributes<HTMLDivElement>, BaseProps {
23
19
  variant?: 'default' | 'pills' | 'underline';
24
20
  ariaLabel?: string;
25
21
  panelId?: string;
26
- /** Render only the tab list (e.g. URL-driven tabs whose content lives elsewhere). */
27
22
  showPanel?: boolean;
28
23
  }
29
24
 
@@ -95,7 +90,6 @@ export function Tabs({ tabs, defaultValue, value, onValueChange, variant = 'defa
95
90
 
96
91
  return (
97
92
  <div className={cn('w-full', className)} {...props}>
98
- {/* Tab List */}
99
93
  <div
100
94
  ref={listRef}
101
95
  role="tablist"
@@ -138,7 +132,6 @@ export function Tabs({ tabs, defaultValue, value, onValueChange, variant = 'defa
138
132
  })}
139
133
  </div>
140
134
 
141
- {/* Tab Content */}
142
135
  {showPanel && (
143
136
  <div
144
137
  role="tabpanel"
@@ -1,7 +1,3 @@
1
- /**
2
- * Timeline Component (Organism)
3
- * @description Vertical activity timeline: meta line, title, optional body, tone dot
4
- */
5
1
 
6
2
  import { forwardRef } from 'react';
7
3
  import type { HTMLAttributes, ReactNode } from 'react';
@@ -11,21 +7,17 @@ import type { BaseProps } from '../../domain/types';
11
7
  export type TimelineTone = 'primary' | 'success' | 'warning' | 'destructive' | 'info' | 'neutral' | 'violet';
12
8
 
13
9
  export interface TimelineItem {
14
- /** ISO timestamp rendered as the meta line unless `meta` overrides it. */
15
10
  at: string;
16
11
  title: ReactNode;
17
12
  body?: ReactNode;
18
13
  tone?: TimelineTone;
19
14
  meta?: ReactNode;
20
- /** Replaces the tone dot with an icon, tinted by `tone` (or muted when omitted). */
21
15
  icon?: ReactNode;
22
- /** Replaces the tone dot with an avatar (e.g. the acting user); takes precedence over `icon`. */
23
16
  avatar?: ReactNode;
24
17
  }
25
18
 
26
19
  export interface TimelineProps extends HTMLAttributes<HTMLOListElement>, BaseProps {
27
20
  items: TimelineItem[];
28
- /** Render newest first (default) instead of the given order. */
29
21
  newestFirst?: boolean;
30
22
  }
31
23
 
@@ -1,9 +1,3 @@
1
- /**
2
- * Toaster Component (Organism)
3
- * @description Toast notification system. ToastProvider wraps the app root
4
- * ONCE and renders the viewport (bottom-right stack, max 4, auto-dismiss
5
- * 4.2 s); pages fire toasts via useToast()({ kind, title, description }).
6
- */
7
1
 
8
2
  import { createContext, useCallback, useContext, useMemo, useRef, useState } from 'react';
9
3
  import type { ReactNode } from 'react';
@@ -24,10 +18,8 @@ export interface ToastShorthandOptions {
24
18
  }
25
19
 
26
20
  interface ToastApi {
27
- /** Fire a toast — after every mutating action is the fleet idiom. */
28
21
  toast: {
29
22
  (t: ToastOptions): void;
30
- /** Shorthand call: toast('Saved', { tone: 'success', message: '…' }). */
31
23
  (title: string, options?: ToastShorthandOptions): void;
32
24
  };
33
25
  }
@@ -38,7 +30,6 @@ interface ToastEntry extends ToastOptions {
38
30
 
39
31
  const ToastContext = createContext<ToastApi>({ toast: () => {} });
40
32
 
41
- /** Consume from any page below the provider: const { toast } = useToast(); */
42
33
  export function useToast(): ToastApi {
43
34
  return useContext(ToastContext);
44
35
  }
@@ -1,7 +1,3 @@
1
- /**
2
- * Toggle Group Component (Organism) - Shadcn/ui format
3
- * @description Group of toggle buttons with single or multiple selection
4
- */
5
1
 
6
2
  import * as React from 'react';
7
3
  import * as ToggleGroupPrimitive from '@radix-ui/react-toggle-group';
@@ -1,9 +1,3 @@
1
- /**
2
- * Organisms Export
3
- * @description Organism components - complex UI combinations
4
- * Subpath: @umituz/web-design-system/organisms
5
- */
6
-
7
1
  export { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from './Card';
8
2
  export type { CardProps, CardHeaderProps } from './Card';
9
3
 
@@ -18,7 +12,7 @@ export {
18
12
  TableRow,
19
13
  TableHead,
20
14
  TableCell,
21
- TableCaption
15
+ TableCaption,
22
16
  } from './Table';
23
17
  export type { TableProps } from './Table';
24
18
 
@@ -41,10 +35,10 @@ export {
41
35
  } from './Dialog';
42
36
 
43
37
  export { CommandPalette } from './CommandPalette';
38
+ export type { CommandPaletteProps, CommandGroup, CommandItem } from './CommandPalette';
44
39
 
45
40
  export { ErrorBoundary } from './ErrorBoundary';
46
41
  export type { ErrorBoundaryProps } from './ErrorBoundary';
47
- export type { CommandPaletteProps, CommandGroup, CommandItem } from './CommandPalette';
48
42
 
49
43
  export { Breadcrumbs } from './Breadcrumb';
50
44
  export type { BreadcrumbsProps, BreadcrumbItem } from './Breadcrumb';
@@ -117,7 +111,7 @@ export {
117
111
  export { ToggleGroup, ToggleGroupItem } from './ToggleGroup';
118
112
 
119
113
  export { ToastProvider, useToast } from './Toaster';
120
- export type { ToastKind, ToastOptions } from './Toaster';
114
+ export type { ToastKind, ToastOptions, ToastShorthandOptions } from './Toaster';
121
115
 
122
116
  export { KeyValueList } from './KeyValueList';
123
117
  export type { KeyValueListProps, KeyValueItem } from './KeyValueList';
@@ -154,8 +148,6 @@ export type { PhotoGalleryProps, PhotoTile } from './PhotoGallery';
154
148
  export { Lightbox } from './Lightbox';
155
149
  export type { LightboxProps } from './Lightbox';
156
150
 
157
- export type { ToastShorthandOptions } from './Toaster';
158
-
159
151
  export { Timeline } from './Timeline';
160
152
  export type { TimelineProps, TimelineItem, TimelineTone } from './Timeline';
161
153
 
@@ -186,3 +178,10 @@ export type { PlanPickerProps, PlanPickerPlan, PlanPickerCycle } from './PlanPic
186
178
 
187
179
  export { CoverArt } from './CoverArt';
188
180
  export type { CoverArtProps } from './CoverArt';
181
+
182
+ // New Productivity Organisms
183
+ export { StatsGrid } from './StatsGrid';
184
+ export type { StatsGridProps, StatItem } from './StatsGrid';
185
+
186
+ export { DescriptionList } from './DescriptionList';
187
+ export type { DescriptionListProps, DescriptionItem } from './DescriptionList';
@@ -0,0 +1,69 @@
1
+ import * as React from 'react';
2
+ import { Breadcrumbs, type BreadcrumbItem } from '../organisms/Breadcrumb';
3
+ import { cn } from '../../infrastructure/utils';
4
+
5
+ export interface CrudPageTemplateProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {
6
+ title: React.ReactNode;
7
+ description?: React.ReactNode;
8
+ breadcrumbItems?: BreadcrumbItem[];
9
+ actions?: React.ReactNode;
10
+ stats?: React.ReactNode;
11
+ toolbar?: React.ReactNode;
12
+ children: React.ReactNode;
13
+ }
14
+
15
+ export const CrudPageTemplate = React.forwardRef<HTMLDivElement, CrudPageTemplateProps>(
16
+ (
17
+ {
18
+ title,
19
+ description,
20
+ breadcrumbItems,
21
+ actions,
22
+ stats,
23
+ toolbar,
24
+ children,
25
+ className,
26
+ ...props
27
+ },
28
+ ref
29
+ ) => {
30
+ return (
31
+ <div
32
+ ref={ref}
33
+ className={cn('w-full flex flex-col gap-6 p-4 sm:p-6 lg:p-8', className)}
34
+ {...props}
35
+ >
36
+ {/* Breadcrumbs */}
37
+ {breadcrumbItems && breadcrumbItems.length > 0 && (
38
+ <div>
39
+ <Breadcrumbs items={breadcrumbItems} />
40
+ </div>
41
+ )}
42
+
43
+ {/* Page Header */}
44
+ <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
45
+ <div>
46
+ <h1 className="text-2xl sm:text-3xl font-bold tracking-tight text-foreground">
47
+ {title}
48
+ </h1>
49
+ {description && (
50
+ <p className="text-sm text-muted-foreground mt-1">{description}</p>
51
+ )}
52
+ </div>
53
+ {actions && <div className="flex items-center gap-2 shrink-0">{actions}</div>}
54
+ </div>
55
+
56
+ {/* Optional Stats Grid */}
57
+ {stats && <div>{stats}</div>}
58
+
59
+ {/* Optional Search / Filter Toolbar */}
60
+ {toolbar && <div>{toolbar}</div>}
61
+
62
+ {/* Main Content (Table / List / Cards) */}
63
+ <div className="w-full">{children}</div>
64
+ </div>
65
+ );
66
+ }
67
+ );
68
+
69
+ CrudPageTemplate.displayName = 'CrudPageTemplate';
@@ -1,7 +1,3 @@
1
- /**
2
- * Form Template (Template)
3
- * @description Complete form structure
4
- */
5
1
 
6
2
  import { forwardRef, type FormHTMLAttributes, type HTMLAttributes } from 'react';
7
3
  import { cn } from '../../infrastructure/utils';
@@ -1,7 +1,3 @@
1
- /**
2
- * List Template (Template)
3
- * @description Structured list container
4
- */
5
1
 
6
2
  import { forwardRef, type HTMLAttributes } from 'react';
7
3
  import { cn } from '../../infrastructure/utils';
@@ -1,7 +1,3 @@
1
- /**
2
- * PageHeader Template Component
3
- * @description Centralized page header with consistent heading styling
4
- */
5
1
 
6
2
  import { forwardRef, type HTMLAttributes } from 'react';
7
3
  import { type ReactNode } from 'react';
@@ -1,7 +1,3 @@
1
- /**
2
- * PageLayout Template Component
3
- * @description Centralized page layout with consistent padding, max-width, and theme integration
4
- */
5
1
 
6
2
  import { forwardRef, type HTMLAttributes } from 'react';
7
3
  import { cn } from '../../infrastructure/utils';
@@ -1,7 +1,3 @@
1
- /**
2
- * ProjectSkeleton Template Component
3
- * @description Loading skeleton for project cards
4
- */
5
1
 
6
2
  import { forwardRef, type HTMLAttributes } from 'react';
7
3
  import { cn } from '../../infrastructure/utils';
@@ -1,7 +1,3 @@
1
- /**
2
- * ResponsiveContainer Template Component
3
- * @description Responsive wrapper with mobile/desktop optimizations
4
- */
5
1
 
6
2
  import { forwardRef, type HTMLAttributes, type ReactNode } from 'react';
7
3
  import { cn } from '../../infrastructure/utils';
@@ -14,58 +10,22 @@ export interface ResponsiveContainerProps
14
10
  extends Omit<HTMLAttributes<HTMLDivElement>, 'children'>,
15
11
  BaseProps {
16
12
  children?: ReactNode;
17
- /**
18
- * Maximum width on mobile devices
19
- * @default 'full'
20
- */
21
13
  mobileMaxWidth?: ResponsiveSize;
22
14
 
23
- /**
24
- * Maximum width on tablet devices
25
- * @default 'lg'
26
- */
27
15
  tabletMaxWidth?: ResponsiveSize;
28
16
 
29
- /**
30
- * Maximum width on desktop devices
31
- * @default 'xl'
32
- */
33
17
  desktopMaxWidth?: ResponsiveSize;
34
18
 
35
- /**
36
- * Padding on mobile devices
37
- * @default true
38
- */
39
19
  mobilePadding?: boolean;
40
20
 
41
- /**
42
- * Padding on tablet devices
43
- * @default true
44
- */
45
21
  tabletPadding?: boolean;
46
22
 
47
- /**
48
- * Padding on desktop devices
49
- * @default true
50
- */
51
23
  desktopPadding?: boolean;
52
24
 
53
- /**
54
- * Center content horizontally
55
- * @default true
56
- */
57
25
  centered?: boolean;
58
26
 
59
- /**
60
- * Background gradient
61
- * @default false
62
- */
63
27
  gradient?: boolean;
64
28
 
65
- /**
66
- * Minimum height
67
- * @default 'auto'
68
- */
69
29
  minHeight?: 'auto' | 'screen' | 'full';
70
30
  }
71
31
 
@@ -100,7 +60,6 @@ export const ResponsiveContainer = forwardRef<
100
60
  ) => {
101
61
  const { currentBreakpoint: breakpoint } = useBreakpoint();
102
62
 
103
- // Determine current max width based on breakpoint
104
63
  const getCurrentMaxWidth = (): string => {
105
64
  if (!breakpoint) return maxWidthClasses[mobileMaxWidth];
106
65
 
@@ -113,7 +72,6 @@ export const ResponsiveContainer = forwardRef<
113
72
  return maxWidthClasses[desktopMaxWidth];
114
73
  };
115
74
 
116
- // Determine current padding based on breakpoint
117
75
  const getCurrentPadding = (): string => {
118
76
  if (!breakpoint) return mobilePadding ? 'px-4' : '';
119
77
 
@@ -126,7 +84,6 @@ export const ResponsiveContainer = forwardRef<
126
84
  return desktopPadding ? 'px-8' : '';
127
85
  };
128
86
 
129
- // Determine current py padding based on breakpoint
130
87
  const getCurrentPyPadding = (): string => {
131
88
  if (!breakpoint) return 'py-8';
132
89
 
@@ -1,7 +1,3 @@
1
- /**
2
- * Section Template (Template)
3
- * @description Content section with header
4
- */
5
1
 
6
2
  import { forwardRef, type HTMLAttributes } from 'react';
7
3
  import { cn } from '../../infrastructure/utils';