@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,8 +1,3 @@
1
- /**
2
- * StatPill Component (Molecule)
3
- * @description Compact inline stat — bold value over a muted label, for
4
- * dense rows and summary strips where a stat card is too heavy.
5
- */
6
1
 
7
2
  import { forwardRef } from 'react';
8
3
  import type { ReactNode } from 'react';
@@ -1,9 +1,3 @@
1
- /**
2
- * TagInput Component (Molecule)
3
- * @description Controlled free-form tag entry rendered as removable chips.
4
- * Type and press Enter (or comma) to commit, Backspace on an empty draft removes the last tag,
5
- * duplicates are ignored, and blur commits by default.
6
- */
7
1
 
8
2
  import { forwardRef, useState } from 'react';
9
3
  import type { InputHTMLAttributes } from 'react';
@@ -16,7 +10,6 @@ export interface TagInputProps
16
10
  BaseProps {
17
11
  tags: string[];
18
12
  onTagsChange: (tags: string[]) => void;
19
- /** Commit the draft on blur (default true). */
20
13
  commitOnBlur?: boolean;
21
14
  }
22
15
 
@@ -1,7 +1,3 @@
1
- /**
2
- * Textarea Component (Molecule)
3
- * @description Multi-line text input with optional label and helper text
4
- */
5
1
 
6
2
  import { forwardRef, useId, type ReactNode, type TextareaHTMLAttributes } from 'react';
7
3
  import { cn } from '../../infrastructure/utils';
@@ -1,7 +1,3 @@
1
- /**
2
- * Toggle Component (Molecule)
3
- * @description Switch/toggle button
4
- */
5
1
 
6
2
  import { forwardRef, type ButtonHTMLAttributes } from 'react';
7
3
  import { cn } from '../../infrastructure/utils';
@@ -0,0 +1,36 @@
1
+ import * as React from 'react';
2
+ import { cn } from '../../infrastructure/utils';
3
+
4
+ export interface ToolbarProps extends React.HTMLAttributes<HTMLDivElement> {
5
+ search?: React.ReactNode;
6
+ filters?: React.ReactNode;
7
+ actions?: React.ReactNode;
8
+ }
9
+
10
+ export const Toolbar = React.forwardRef<HTMLDivElement, ToolbarProps>(
11
+ ({ search, filters, actions, children, className, ...props }, ref) => {
12
+ return (
13
+ <div
14
+ ref={ref}
15
+ className={cn(
16
+ 'flex flex-col sm:flex-row items-stretch sm:items-center justify-between gap-3 w-full',
17
+ className
18
+ )}
19
+ {...props}
20
+ >
21
+ <div className="flex flex-1 flex-wrap items-center gap-2">
22
+ {search && <div className="w-full sm:w-72 max-w-full">{search}</div>}
23
+ {filters && <div className="flex flex-wrap items-center gap-2">{filters}</div>}
24
+ {children}
25
+ </div>
26
+ {actions && (
27
+ <div className="flex items-center gap-2 shrink-0 justify-end">
28
+ {actions}
29
+ </div>
30
+ )}
31
+ </div>
32
+ );
33
+ }
34
+ );
35
+
36
+ Toolbar.displayName = 'Toolbar';
@@ -1,9 +1,3 @@
1
- /**
2
- * Molecules Export
3
- * @description Molecule components - combinations of atoms
4
- * Subpath: @umituz/web-design-system/molecules
5
- */
6
-
7
1
  export { FormField } from './FormField';
8
2
  export type { FormFieldProps } from './FormField';
9
3
 
@@ -22,7 +16,18 @@ export type { ChipProps } from './Chip';
22
16
  export { Toggle } from './Toggle';
23
17
  export type { ToggleProps } from './Toggle';
24
18
 
25
- export { Select, SelectGroup, SelectValue, SelectTrigger, SelectContent, SelectLabel, SelectItem, SelectSeparator, SelectScrollUpButton, SelectScrollDownButton } from './Select';
19
+ export {
20
+ Select,
21
+ SelectGroup,
22
+ SelectValue,
23
+ SelectTrigger,
24
+ SelectContent,
25
+ SelectLabel,
26
+ SelectItem,
27
+ SelectSeparator,
28
+ SelectScrollUpButton,
29
+ SelectScrollDownButton,
30
+ } from './Select';
26
31
 
27
32
  export { Textarea } from './Textarea';
28
33
  export type { TextareaProps } from './Textarea';
@@ -41,7 +46,6 @@ export { ScrollArea, ScrollBar } from './ScrollArea';
41
46
  export { ListItem } from './ListItem';
42
47
  export type { ListItemProps } from './ListItem';
43
48
 
44
- // NEW: Filter & Navigation Components
45
49
  export { ActiveFilterTags } from './ActiveFilterTags';
46
50
  export type { ActiveFilterTagsProps } from './ActiveFilterTags';
47
51
 
@@ -70,3 +74,16 @@ export type { TagInputProps } from './TagInput';
70
74
 
71
75
  export { MarkdownText } from './MarkdownText';
72
76
  export type { MarkdownTextProps } from './MarkdownText';
77
+
78
+ // New Productivity Molecules
79
+ export { PasswordInput } from './PasswordInput';
80
+ export type { PasswordInputProps } from './PasswordInput';
81
+
82
+ export { SearchInput } from './SearchInput';
83
+ export type { SearchInputProps } from './SearchInput';
84
+
85
+ export { ConfirmButton } from './ConfirmButton';
86
+ export type { ConfirmButtonProps } from './ConfirmButton';
87
+
88
+ export { Toolbar } from './Toolbar';
89
+ export type { ToolbarProps } from './Toolbar';
@@ -1,7 +1,3 @@
1
- /**
2
- * Accordion Component (Organism)
3
- * @description Collapsible content sections (Shadcn/ui compatible)
4
- */
5
1
 
6
2
  import * as React from 'react';
7
3
  import * as AccordionPrimitive from '@radix-ui/react-accordion';
@@ -1,7 +1,3 @@
1
- /**
2
- * Alert Component (Organism)
3
- * @description Feedback message (Shadcn/ui compatible)
4
- */
5
1
 
6
2
  import * as React from 'react';
7
3
  import { cn } from '../../infrastructure/utils';
@@ -1,7 +1,3 @@
1
- /**
2
- * AvatarStack Component (Organism)
3
- * @description Overlapping avatar row built on the Avatar molecule with an overflow count badge
4
- */
5
1
 
6
2
  import { forwardRef } from 'react';
7
3
  import { cn } from '../../infrastructure/utils';
@@ -16,7 +12,6 @@ export interface AvatarPerson {
16
12
 
17
13
  export interface AvatarStackProps extends BaseProps {
18
14
  people: AvatarPerson[];
19
- /** Avatars shown before the +N badge (default 4). */
20
15
  max?: number;
21
16
  size?: ExtendedSizes;
22
17
  }
@@ -1,7 +1,3 @@
1
- /**
2
- * Breadcrumb Component (Organism)
3
- * @description Navigation breadcrumb trail
4
- */
5
1
 
6
2
  import { forwardRef, type HTMLAttributes, type ReactNode } from 'react';
7
3
  import { cn } from '../../infrastructure/utils';
@@ -13,9 +9,6 @@ export interface BreadcrumbItem {
13
9
  label: string;
14
10
  href?: string;
15
11
  icon?: ReactNode;
16
- /** Renders this node instead of the default anchor — for hosts that need
17
- * SPA router links (react-router `Link`, Next `Link`, …). When set, label
18
- * and href are ignored for rendering. */
19
12
  content?: ReactNode;
20
13
  }
21
14
 
@@ -1,7 +1,3 @@
1
- /**
2
- * Card Component (Organism)
3
- * @description Content container with header, body, footer
4
- */
5
1
 
6
2
  import { forwardRef, type HTMLAttributes } from 'react';
7
3
  import React from 'react';
@@ -11,9 +7,7 @@ import type { BaseProps } from '../../domain/types';
11
7
 
12
8
  export interface CardProps extends HTMLAttributes<HTMLDivElement>, BaseProps {
13
9
  variant?: 'default' | 'outlined' | 'elevated';
14
- /** Render as the single child element (e.g. a router Link) instead of a div. */
15
10
  asChild?: boolean;
16
- /** Interactive card: pointer cursor, hover border and a visible focus ring. */
17
11
  interactive?: boolean;
18
12
  }
19
13
 
@@ -1,7 +1,3 @@
1
- /**
2
- * Checklist Component (Organism)
3
- * @description Toggleable checklist with completion progress and done-by metadata
4
- */
5
1
 
6
2
  import { forwardRef } from 'react';
7
3
  import type { HTMLAttributes, ReactNode } from 'react';
@@ -1,7 +1,3 @@
1
- /**
2
- * Collapsible Component (Organism)
3
- * @description Collapsible content (Shadcn/ui compatible)
4
- */
5
1
 
6
2
  import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
7
3
 
@@ -1,8 +1,3 @@
1
- /**
2
- * ConfirmDialog Component (Organism)
3
- * @description Destructive/primary confirmation built on Modal: title, body and
4
- * Cancel + confirm actions; unmounts itself after confirming
5
- */
6
1
 
7
2
  import type { ReactNode } from 'react';
8
3
  import { Button } from '../atoms/Button';
@@ -13,11 +8,8 @@ export interface ConfirmDialogProps {
13
8
  body?: ReactNode;
14
9
  confirmLabel?: string;
15
10
  cancelLabel?: string;
16
- /** Visual weight of the confirm action; defaults to danger. */
17
11
  tone?: 'danger' | 'primary' | 'success';
18
- /** Renders nothing when false; defaults to true (conditional mounting also works). */
19
12
  open?: boolean;
20
- /** While true the confirm action is locked and shows its loading state; the caller owns dismissal. */
21
13
  busy?: boolean;
22
14
  onConfirm: () => void;
23
15
  onClose: () => void;
@@ -1,9 +1,3 @@
1
- /**
2
- * CoverArt Component (Organism)
3
- * @description Deterministic generated artwork for entities without
4
- * photography — the seed always resolves to the same gradient, replaced by
5
- * real imagery once a media service exists
6
- */
7
1
 
8
2
  import type { ReactNode } from 'react';
9
3
  import { cn } from '../../infrastructure/utils';
@@ -11,13 +5,10 @@ import { hashSeed } from '../../infrastructure/utils/hash.util';
11
5
  import type { BaseProps } from '../../domain/types';
12
6
 
13
7
  export interface CoverArtProps extends BaseProps {
14
- /** Any stable entity id/name — the same seed always renders the same gradient. */
15
8
  seed: string;
16
9
  ratio?: '16/9' | '3/2' | '4/3' | '1/1' | '21/9';
17
10
  rounded?: 'none' | 'md' | 'lg' | 'top';
18
- /** Brand palette override ([from, to]); wins over the seeded gradient. */
19
11
  colors?: readonly [string, string];
20
- /** Accessible description; omit for purely decorative usage. */
21
12
  alt?: string;
22
13
  children?: ReactNode;
23
14
  }
@@ -51,17 +51,14 @@ export interface SortState {
51
51
  export interface Column<T> {
52
52
  id: string;
53
53
  header: ReactNode;
54
- /** Data source; optional when the column renders through `cell` only. */
55
54
  accessor?: keyof T | ((row: T) => ReactNode);
56
55
  cell?: (row: T) => ReactNode;
57
56
  sortValue?: (row: T) => string | number;
58
57
  sortable?: boolean;
59
58
  align?: ColumnAlign;
60
59
  hideBelow?: ColumnHideBelow;
61
- /** Pixels when numeric. */
62
60
  width?: string | number;
63
61
  className?: string;
64
- /** Hidden until the reader enables it from the built-in columns menu. */
65
62
  optional?: boolean;
66
63
  }
67
64
 
@@ -71,12 +68,9 @@ export interface TablePaginationProps extends BaseProps {
71
68
  onPage: (page: number) => void;
72
69
  label?: ReactNode;
73
70
  hideWhenSingle?: boolean;
74
- /** Page-size choices offered in the rows-per-page select. */
75
71
  pageSizeOptions?: readonly number[];
76
- /** Currently selected page size; required with `pageSizeOptions`. */
77
72
  pageSize?: number;
78
73
  onPageSize?: (size: number) => void;
79
- /** Accessible label for the rows-per-page select (default "Rows per page"). */
80
74
  pageSizeLabel?: ReactNode;
81
75
  }
82
76
 
@@ -103,7 +97,6 @@ export interface DataTableProps<T> extends BaseProps {
103
97
  stackable?: boolean;
104
98
  paginated?: boolean;
105
99
  pageSize?: number;
106
- /** Page-size choices offered in the footer rows-per-page select. */
107
100
  pageSizeOptions?: readonly number[];
108
101
  onPageSizeChange?: (size: number) => void;
109
102
  emptyState?: {
@@ -112,7 +105,6 @@ export interface DataTableProps<T> extends BaseProps {
112
105
  };
113
106
  onRowClick?: (row: T) => void;
114
107
  rowLabel?: (row: T) => string;
115
- /** Row-level class, e.g. a tone accent for overdue rows. */
116
108
  rowClass?: (row: T) => string | undefined;
117
109
  }
118
110
 
@@ -1,8 +1,3 @@
1
- /**
2
- * DateRangePicker Component (Organism)
3
- * @description Compact preset-driven date range picker with custom date
4
- * inputs, built on the DropdownMenu + Input atoms.
5
- */
6
1
 
7
2
  import { useState } from 'react';
8
3
  import { CalendarRange } from 'lucide-react';
@@ -20,7 +15,6 @@ import {
20
15
  export interface DateRange {
21
16
  from: string;
22
17
  to: string;
23
- /** preset id when the range was chosen from the preset list */
24
18
  preset?: RangePreset;
25
19
  }
26
20
 
@@ -56,7 +50,6 @@ function shiftMonths(iso: string, months: number): string {
56
50
  return d.toISOString().slice(0, 10);
57
51
  }
58
52
 
59
- /** Resolve a preset id into a concrete range around `today` (ISO date). */
60
53
  export function presetRange(preset: RangePreset, today: string = isoToday()): DateRange {
61
54
  switch (preset) {
62
55
  case '7d':
@@ -79,9 +72,7 @@ export function presetRange(preset: RangePreset, today: string = isoToday()): Da
79
72
  export interface DateRangePickerProps {
80
73
  value: DateRange;
81
74
  onChange: (range: DateRange) => void;
82
- /** Preset list shown above the custom inputs; defaults to DEFAULT_RANGE_PRESETS. */
83
75
  presets?: readonly RangePresetOption[];
84
- /** Day formatter for the trigger label; defaults to the raw ISO date. */
85
76
  formatDay?: (iso: string) => string;
86
77
  'aria-label'?: string;
87
78
  }
@@ -0,0 +1,113 @@
1
+ import * as React from 'react';
2
+ import { Card } from './Card';
3
+ import { Badge, type BadgeVariant } from '../atoms/Badge';
4
+ import { CopyButton } from '../atoms/CopyButton';
5
+ import { cn } from '../../infrastructure/utils';
6
+
7
+ export interface DescriptionItem {
8
+ key?: string;
9
+ label: string;
10
+ value: React.ReactNode;
11
+ copyable?: boolean;
12
+ copyText?: string;
13
+ badge?: string;
14
+ badgeVariant?: BadgeVariant;
15
+ hint?: string;
16
+ }
17
+
18
+ export interface DescriptionListProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {
19
+ title?: React.ReactNode;
20
+ description?: React.ReactNode;
21
+ action?: React.ReactNode;
22
+ items: DescriptionItem[];
23
+ columns?: 1 | 2;
24
+ bordered?: boolean;
25
+ }
26
+
27
+ export const DescriptionList = React.forwardRef<HTMLDivElement, DescriptionListProps>(
28
+ (
29
+ {
30
+ title,
31
+ description,
32
+ action,
33
+ items,
34
+ columns = 1,
35
+ bordered = true,
36
+ className,
37
+ ...props
38
+ },
39
+ ref
40
+ ) => {
41
+ const content = (
42
+ <div
43
+ ref={ref}
44
+ className={cn('w-full flex flex-col gap-4', className)}
45
+ {...props}
46
+ >
47
+ {(title || action || description) && (
48
+ <div className="flex items-start justify-between gap-4 pb-3 border-b border-border">
49
+ <div>
50
+ {title && (
51
+ <h3 className="text-base font-semibold text-foreground tracking-tight">
52
+ {title}
53
+ </h3>
54
+ )}
55
+ {description && (
56
+ <p className="text-sm text-muted-foreground mt-0.5">
57
+ {description}
58
+ </p>
59
+ )}
60
+ </div>
61
+ {action && <div className="shrink-0">{action}</div>}
62
+ </div>
63
+ )}
64
+
65
+ <dl
66
+ className={cn(
67
+ 'grid gap-x-6 gap-y-3',
68
+ columns === 2 ? 'grid-cols-1 sm:grid-cols-2' : 'grid-cols-1'
69
+ )}
70
+ >
71
+ {items.map((item, idx) => {
72
+ const rawCopyText = item.copyText ?? (typeof item.value === 'string' ? item.value : '');
73
+
74
+ return (
75
+ <div
76
+ key={item.key ?? idx}
77
+ className="flex items-center justify-between py-2 border-b border-border/60 last:border-0 gap-3"
78
+ >
79
+ <dt className="text-sm font-medium text-muted-foreground shrink-0">
80
+ {item.label}
81
+ {item.hint && (
82
+ <span className="block text-xs font-normal text-muted-foreground/75">
83
+ {item.hint}
84
+ </span>
85
+ )}
86
+ </dt>
87
+ <dd className="text-sm font-medium text-foreground flex items-center gap-2 text-right break-all">
88
+ {item.value}
89
+ {item.badge && (
90
+ <Badge variant={item.badgeVariant ?? 'secondary'} size="sm">
91
+ {item.badge}
92
+ </Badge>
93
+ )}
94
+ {item.copyable && rawCopyText && (
95
+ <CopyButton text={rawCopyText} size="xs" />
96
+ )}
97
+ </dd>
98
+ </div>
99
+ );
100
+ })}
101
+ </dl>
102
+ </div>
103
+ );
104
+
105
+ if (bordered) {
106
+ return <Card className="p-5">{content}</Card>;
107
+ }
108
+
109
+ return content;
110
+ }
111
+ );
112
+
113
+ DescriptionList.displayName = 'DescriptionList';
@@ -1,7 +1,3 @@
1
- /**
2
- * Dialog Component (Organism)
3
- * @description Modal dialog (Shadcn/ui compatible)
4
- */
5
1
 
6
2
  import * as React from 'react';
7
3
  import * as DialogPrimitive from '@radix-ui/react-dialog';
@@ -1,8 +1,3 @@
1
- /**
2
- * Drawer Component (Organism)
3
- * @description Slide-over panel built on the Sheet compound with a
4
- * Modal-like prop surface (title, footer, side presets, wide variant)
5
- */
6
1
 
7
2
  import type { ReactNode } from 'react';
8
3
  import { cn } from '../../infrastructure/utils';
@@ -21,7 +16,6 @@ export interface DrawerProps {
21
16
  open: boolean;
22
17
  onClose: () => void;
23
18
  title?: ReactNode;
24
- /** Small overline above the title, e.g. an entity code. */
25
19
  eyebrow?: ReactNode;
26
20
  subtitle?: ReactNode;
27
21
  description?: ReactNode;
@@ -1,7 +1,3 @@
1
- /**
2
- * Dropdown Menu Component (Organism) - Shadcn/ui format
3
- * @description Dropdown menu component using Radix UI
4
- */
5
1
 
6
2
  import * as React from 'react';
7
3
  import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
@@ -1,8 +1,3 @@
1
- /**
2
- * ErrorBoundary Component (Organism)
3
- * @description Route/tree-level crash catcher — catches render errors and
4
- * shows an honest recovery screen instead of a blank page.
5
- */
6
1
 
7
2
  import { Component, type ErrorInfo, type ReactNode } from 'react';
8
3
  import { AlertTriangle } from 'lucide-react';
@@ -10,19 +5,12 @@ import { Button } from '../atoms/Button';
10
5
 
11
6
  export interface ErrorBoundaryProps {
12
7
  children: ReactNode;
13
- /** Small kicker line above the title (e.g. "Something broke"). */
14
8
  kicker?: string;
15
- /** Heading on the crash screen. */
16
9
  title?: string;
17
- /** Secondary line — defaults to the caught error's message. */
18
10
  description?: ReactNode;
19
- /** Reset (retry) button label; omit to hide the button. */
20
11
  resetLabel?: string;
21
- /** Extra action rendered next to reset (e.g. a link back home). */
22
12
  action?: ReactNode;
23
- /** Fully custom crash screen — receives the error and the reset handler. */
24
13
  fallback?: (error: Error, reset: () => void) => ReactNode;
25
- /** Side-channel for logging services (defaults to console.error). */
26
14
  onError?: (error: Error, info: ErrorInfo) => void;
27
15
  }
28
16
 
@@ -1,8 +1,3 @@
1
- /**
2
- * FileUploader Component (Organism)
3
- * @description Keyboard-accessible drag-and-drop file picker with a queued
4
- * file preview list. Visual only — storage wiring belongs to the host.
5
- */
6
1
 
7
2
  import { useRef, useState, type DragEvent } from 'react';
8
3
  import { UploadCloud } from 'lucide-react';
@@ -10,15 +5,11 @@ import { Button } from '../atoms/Button';
10
5
  import { cn } from '../../infrastructure/utils';
11
6
 
12
7
  export interface FileUploaderProps {
13
- /** Drop-zone headline. */
14
8
  label?: string;
15
- /** Secondary line under the headline. */
16
9
  hint?: string;
17
10
  accept?: string;
18
11
  multiple?: boolean;
19
- /** Called with the picked/dropped files. */
20
12
  onFiles?: (files: File[]) => void;
21
- /** How many queued names to list before stopping (visual cap only). */
22
13
  maxPreview?: number;
23
14
  }
24
15
 
@@ -1,8 +1,3 @@
1
- /**
2
- * FilterPopover Component (Organism)
3
- * @description List-toolbar filter trigger with an active-filter count badge;
4
- * hosts arbitrary filter controls inside a Popover
5
- */
6
1
 
7
2
  import { useState, type ReactNode } from 'react';
8
3
  import { Filter } from 'lucide-react';
@@ -11,11 +6,8 @@ import { Button } from '../atoms/Button';
11
6
  import { Popover, PopoverContent, PopoverTrigger } from './Popover';
12
7
 
13
8
  export interface FilterPopoverProps {
14
- /** Trigger caption; defaults to "Filters". */
15
9
  label?: string;
16
- /** Active filter count; rendered as a badge when greater than zero. */
17
10
  count?: number;
18
- /** Popover alignment relative to the trigger; defaults to "start". */
19
11
  align?: 'start' | 'center' | 'end';
20
12
  children: ReactNode;
21
13
  className?: string;
@@ -65,8 +65,6 @@ export interface FormModalMessages {
65
65
  invalidNumber: string;
66
66
  }
67
67
 
68
- /** Resolves a field's options — static arrays pass through, functions
69
- * receive the current values so a select can depend on earlier fields. */
70
68
  function fieldOptions(f: FormModalField, values: FormModalValues): FormModalOption[] {
71
69
  return typeof f.options === 'function' ? f.options(values) : (f.options ?? []);
72
70
  }
@@ -118,8 +116,6 @@ export function FormModal(
118
116
  const set = (name: string, val: string | number | boolean) => {
119
117
  const next: FormModalValues = { ...values, [name]: val };
120
118
  const cleared = [name];
121
- // A dependent select must never hold a value its resolved options no
122
- // longer contain — snap it to the first option (or '') and clear its error.
123
119
  for (const s of steps) {
124
120
  for (const f of s.fields) {
125
121
  if (f.type !== 'select' || typeof f.options !== 'function') continue;
@@ -215,7 +211,6 @@ export function FormModal(
215
211
  {f.label}
216
212
  {f.required && (
217
213
  <span className="ml-0.5 text-destructive" aria-hidden="true">
218
- *
219
214
  </span>
220
215
  )}
221
216
  </label>
@@ -1,7 +1,3 @@
1
- /**
2
- * HoverCard Component (Organism)
3
- * @description Hover-triggered card (Shadcn/ui compatible)
4
- */
5
1
 
6
2
  import * as React from 'react';
7
3
  import * as HoverCardPrimitive from '@radix-ui/react-hover-card';
@@ -1,7 +1,3 @@
1
- /**
2
- * KeyValueList Component (Organism)
3
- * @description Definition list of label → value rows (drawers, detail panels).
4
- */
5
1
 
6
2
  import { forwardRef } from 'react';
7
3
  import type { HTMLAttributes, ReactNode } from 'react';
@@ -1,7 +1,3 @@
1
- /**
2
- * KpiCard Component (Organism)
3
- * @description Compact key-metric card: label, value, delta badge, hint and sparkline
4
- */
5
1
 
6
2
  import { forwardRef, type HTMLAttributes, type ReactNode } from 'react';
7
3
  import { TrendingUp, TrendingDown } from 'lucide-react';
@@ -34,11 +30,9 @@ export interface KpiCardProps extends HTMLAttributes<HTMLDivElement>, BaseProps
34
30
  hint?: ReactNode;
35
31
  icon?: ReactNode;
36
32
  iconTone?: KpiIconTone;
37
- /** Paints the metric value itself, e.g. red for an over-budget figure. */
38
33
  valueTone?: KpiIconTone;
39
34
  spark?: readonly number[];
40
35
  sparkTone?: KpiIconTone;
41
- /** Danger emphasis for metrics that need attention, e.g. open incidents. */
42
36
  alert?: boolean;
43
37
  onClick?: () => void;
44
38
  }
@@ -1,8 +1,3 @@
1
- /**
2
- * Lightbox Component (Organism)
3
- * @description Media overlay on the Dialog primitives — click to zoom,
4
- * caption below, close button in the corner.
5
- */
6
1
 
7
2
  import { useState } from 'react';
8
3
  import type { ReactNode } from 'react';
@@ -12,10 +7,8 @@ import { Dialog, DialogContent, DialogTitle } from './Dialog';
12
7
  export interface LightboxProps {
13
8
  open: boolean;
14
9
  onClose: () => void;
15
- /** Accessible name for the media being shown. */
16
10
  alt: string;
17
11
  caption?: ReactNode;
18
- /** Toggle zoom on media click; default true. */
19
12
  zoomable?: boolean;
20
13
  children?: ReactNode;
21
14
  className?: string;