@altruist03/ui 0.1.0 → 0.2.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 (207) hide show
  1. package/assets/images/noData.webp +0 -0
  2. package/dist/index.js +15237 -650
  3. package/dist/index.js.map +1 -1
  4. package/dist/noData-XPRHKMFR.webp +0 -0
  5. package/package.json +21 -7
  6. package/src/ThemeProvider/ThemeContext.tsx +75 -0
  7. package/src/ThemeProvider/index.ts +7 -0
  8. package/src/assets/images/noData.webp +0 -0
  9. package/src/assets.d.ts +10 -0
  10. package/src/components/Accordion/Accordion.stories.tsx +64 -0
  11. package/src/components/Accordion/Accordion.tsx +219 -0
  12. package/src/components/Accordion/Accordion.types.ts +16 -0
  13. package/src/components/Avatar/Avatar.stories.tsx +304 -0
  14. package/src/components/Avatar/Avatar.tsx +211 -0
  15. package/src/components/Avatar/Avatar.types.ts +33 -0
  16. package/src/components/Badge/Badge.stories.tsx +143 -0
  17. package/src/components/Badge/Badge.tsx +138 -0
  18. package/src/components/Badge/Badge.types.ts +24 -0
  19. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +114 -0
  20. package/src/components/Breadcrumb/Breadcrumb.tsx +120 -0
  21. package/src/components/Breadcrumb/Breadcrumb.types.ts +22 -0
  22. package/src/components/Button/Button.stories.tsx +457 -0
  23. package/src/components/Button/Button.tsx +202 -0
  24. package/src/components/Button/Button.types.ts +18 -0
  25. package/src/components/Checkbox/Checkbox.stories.tsx +254 -0
  26. package/src/components/Checkbox/Checkbox.tsx +352 -0
  27. package/src/components/Checkbox/Checkbox.types.ts +123 -0
  28. package/src/components/CloseButton/CloseButton.stories.tsx +100 -0
  29. package/src/components/CloseButton/CloseButton.tsx +117 -0
  30. package/src/components/CloseButton/CloseButton.types.ts +15 -0
  31. package/src/components/CollapsibleSearch/CollapsibleSearch.tsx +120 -0
  32. package/src/components/DataTable/DataTable.stories.tsx +233 -0
  33. package/src/components/DataTable/DataTable.tsx +968 -0
  34. package/src/components/DataTable/DataTable.types.ts +49 -0
  35. package/src/components/DatePicker/DatePicker.stories.tsx +341 -0
  36. package/src/components/DatePicker/DatePicker.tsx +669 -0
  37. package/src/components/DatePicker/DatePicker.types.ts +105 -0
  38. package/src/components/DatePicker/DateTimePicker.tsx +35 -0
  39. package/src/components/DateRangePicker/DateRangePicker.tsx +179 -0
  40. package/src/components/DateRangePicker/DateRangePicker.types.ts +34 -0
  41. package/src/components/Drawer/Drawer.stories.tsx +243 -0
  42. package/src/components/Drawer/Drawer.tsx +196 -0
  43. package/src/components/Drawer/Drawer.types.ts +60 -0
  44. package/src/components/FileUpload/FileUpload.stories.tsx +162 -0
  45. package/src/components/FileUpload/FileUpload.tsx +216 -0
  46. package/src/components/FileUpload/FileUpload.types.ts +80 -0
  47. package/src/components/FilterPopover/FilterPopover.stories.tsx +173 -0
  48. package/src/components/FilterPopover/FilterPopover.tsx +310 -0
  49. package/src/components/FilterPopover/FilterPopover.types.ts +26 -0
  50. package/src/components/ImageViewer/ImageViewerToolbar.jsx +81 -0
  51. package/src/components/ImageViewer/useImagePanRotate.js +102 -0
  52. package/src/components/IpWhitelistField/IpWhitelistField.stories.tsx +138 -0
  53. package/src/components/IpWhitelistField/IpWhitelistField.tsx +164 -0
  54. package/src/components/IpWhitelistField/IpWhitelistField.types.ts +42 -0
  55. package/src/components/Loader/Loader.stories.tsx +95 -0
  56. package/src/components/Loader/Loader.tsx +132 -0
  57. package/src/components/Loader/Loader.types.ts +6 -0
  58. package/src/components/Menu/Menu.tsx +143 -0
  59. package/src/components/Menu/Menu.types.ts +28 -0
  60. package/src/components/MenuButton/MenuButton.stories.tsx +140 -0
  61. package/src/components/MenuButton/MenuButton.tsx +45 -0
  62. package/src/components/MenuButton/MenuButton.types.ts +21 -0
  63. package/src/components/Modal/Modal.stories.tsx +266 -0
  64. package/src/components/Modal/Modal.tsx +399 -0
  65. package/src/components/Modal/index.ts +2 -0
  66. package/src/components/Modal/types.ts +126 -0
  67. package/src/components/Pagination/Pagination.stories.tsx +167 -0
  68. package/src/components/Pagination/Pagination.tsx +266 -0
  69. package/src/components/Pagination/Pagination.types.ts +20 -0
  70. package/src/components/PeriodSelector/PeriodSelector.stories.tsx +50 -0
  71. package/src/components/PeriodSelector/PeriodSelector.tsx +47 -0
  72. package/src/components/PeriodSelector/PeriodSelector.types.ts +10 -0
  73. package/src/components/PhoneField/PhoneField.stories.tsx +141 -0
  74. package/src/components/PhoneField/PhoneField.tsx +284 -0
  75. package/src/components/PhoneField/PhoneField.types.ts +89 -0
  76. package/src/components/PhoneField/countryCodes.ts +236 -0
  77. package/src/components/Progress/Progress.stories.tsx +83 -0
  78. package/src/components/Progress/Progress.tsx +91 -0
  79. package/src/components/Progress/Progress.types.ts +22 -0
  80. package/src/components/RadioButton/RadioButton.stories.tsx +332 -0
  81. package/src/components/RadioButton/RadioButton.tsx +427 -0
  82. package/src/components/RadioButton/RadioButton.types.ts +117 -0
  83. package/src/components/ReportCard/ReportCard.tsx +183 -0
  84. package/src/components/ReportCard/ReportCard.types.ts +17 -0
  85. package/src/components/SectionIcon/SectionIcon.tsx +87 -0
  86. package/src/components/SectionIcon/SectionIcon.types.ts +23 -0
  87. package/src/components/SegmentedInputField/SegmentedInputField.stories.tsx +165 -0
  88. package/src/components/SegmentedInputField/SegmentedInputField.tsx +174 -0
  89. package/src/components/SegmentedInputField/SegmentedInputField.types.ts +51 -0
  90. package/src/components/SelectScroll/SelectScroll.stories.tsx +336 -0
  91. package/src/components/SelectScroll/SelectScroll.tsx +1119 -0
  92. package/src/components/SelectScroll/SelectScroll.types.ts +60 -0
  93. package/src/components/Selector/Selector.stories.tsx +382 -0
  94. package/src/components/Selector/Selector.tsx +1310 -0
  95. package/src/components/Selector/Selector.types.ts +71 -0
  96. package/src/components/Skeleton/Skeleton.stories.tsx +133 -0
  97. package/src/components/Skeleton/Skeleton.tsx +20 -0
  98. package/src/components/Skeleton/Skeleton.types.ts +3 -0
  99. package/src/components/Spinner/Spinner.stories.tsx +84 -0
  100. package/src/components/Spinner/Spinner.tsx +79 -0
  101. package/src/components/Spinner/Spinner.types.ts +8 -0
  102. package/src/components/StatCard/StatCard.stories.tsx +125 -0
  103. package/src/components/StatCard/StatCard.tsx +167 -0
  104. package/src/components/StatCard/StatCard.types.ts +20 -0
  105. package/src/components/StatusBadge/StatusBadge.stories.tsx +179 -0
  106. package/src/components/StatusBadge/StatusBadge.tsx +74 -0
  107. package/src/components/StatusBadge/StatusBadge.types.ts +23 -0
  108. package/src/components/Stepper/Stepper.stories.tsx +85 -0
  109. package/src/components/Stepper/Stepper.tsx +138 -0
  110. package/src/components/Stepper/Stepper.types.ts +16 -0
  111. package/src/components/SubTabs/SubTabs.stories.tsx +128 -0
  112. package/src/components/SubTabs/SubTabs.tsx +279 -0
  113. package/src/components/SubTabs/SubTabs.types.ts +44 -0
  114. package/src/components/SummaryCard/SummaryCard.stories.tsx +100 -0
  115. package/src/components/SummaryCard/SummaryCard.tsx +141 -0
  116. package/src/components/SummaryCard/SummaryCard.types.ts +22 -0
  117. package/src/components/Switch/Switch.stories.tsx +59 -0
  118. package/src/components/Switch/Switch.tsx +217 -0
  119. package/src/components/Switch/Switch.types.ts +22 -0
  120. package/src/components/Tabs/Tabs.stories.tsx +178 -0
  121. package/src/components/Tabs/Tabs.tsx +197 -0
  122. package/src/components/Tabs/Tabs.types.ts +34 -0
  123. package/src/components/TextField/TextField.stories.tsx +249 -0
  124. package/src/components/TextField/TextField.tsx +462 -0
  125. package/src/components/TextField/TextField.types.ts +141 -0
  126. package/src/components/Toast/Toast.stories.tsx +237 -0
  127. package/src/components/Toast/Toast.tsx +246 -0
  128. package/src/components/Toast/Toast.types.ts +31 -0
  129. package/src/components/ToggleButton/ToggleButton.stories.tsx +105 -0
  130. package/src/components/ToggleButton/ToggleButton.tsx +267 -0
  131. package/src/components/ToggleButton/ToggleButton.types.ts +19 -0
  132. package/src/components/UploadDropzone/UploadDropzone.jsx +78 -0
  133. package/src/components/UploadDropzone2/UploadDropzone.stories.tsx +94 -0
  134. package/src/components/UploadDropzone2/UploadDropzone.tsx +222 -0
  135. package/src/components/UploadDropzone2/UploadDropzone.types.ts +54 -0
  136. package/src/components/ViewEditToggle/ViewEditToggle.stories.tsx +40 -0
  137. package/src/components/ViewEditToggle/ViewEditToggle.tsx +239 -0
  138. package/src/components/ViewEditToggle/ViewEditToggle.types.ts +27 -0
  139. package/src/components/index.ts +157 -0
  140. package/src/icons/ReportDollarIcon.tsx +71 -0
  141. package/src/icons/index.ts +27 -0
  142. package/src/index.ts +214 -0
  143. package/src/storybook/preview.tsx +64 -0
  144. package/src/theme/index.ts +4 -0
  145. package/src/theme/types.d.ts +1 -0
  146. package/src/themes/cpc.ts +4 -0
  147. package/src/themes/firebird.ts +4 -0
  148. package/src/tokens/brands/cpc/themes/dark.json +82 -0
  149. package/src/tokens/brands/cpc/themes/light.json +1 -0
  150. package/src/tokens/brands/default/brand.json +20 -0
  151. package/src/tokens/brands/firebird/themes/dark.json +28 -0
  152. package/src/tokens/brands/firebird/themes/light.json +20 -0
  153. package/src/tokens/button.ts +24 -0
  154. package/src/tokens/components/accordion.json +52 -0
  155. package/src/tokens/components/avatar.json +40 -0
  156. package/src/tokens/components/badge.json +41 -0
  157. package/src/tokens/components/breadcrumb.json +13 -0
  158. package/src/tokens/components/button.json +67 -0
  159. package/src/tokens/components/card.json +39 -0
  160. package/src/tokens/components/checkbox.json +64 -0
  161. package/src/tokens/components/closebutton.json +55 -0
  162. package/src/tokens/components/datatable.json +40 -0
  163. package/src/tokens/components/datepicker.json +99 -0
  164. package/src/tokens/components/drawer.json +23 -0
  165. package/src/tokens/components/field.json +29 -0
  166. package/src/tokens/components/fileupload.json +57 -0
  167. package/src/tokens/components/filterpopover.json +29 -0
  168. package/src/tokens/components/input.json +31 -0
  169. package/src/tokens/components/ipwhitelistfield.json +16 -0
  170. package/src/tokens/components/loader.json +15 -0
  171. package/src/tokens/components/menu.json +21 -0
  172. package/src/tokens/components/modal.json +25 -0
  173. package/src/tokens/components/pagination.json +45 -0
  174. package/src/tokens/components/phonefield.json +41 -0
  175. package/src/tokens/components/progress.json +12 -0
  176. package/src/tokens/components/radio.json +87 -0
  177. package/src/tokens/components/reportcard.json +17 -0
  178. package/src/tokens/components/selector.json +87 -0
  179. package/src/tokens/components/selectscroll.json +65 -0
  180. package/src/tokens/components/skeleton.json +6 -0
  181. package/src/tokens/components/stepper.json +38 -0
  182. package/src/tokens/components/subtabs.json +45 -0
  183. package/src/tokens/components/switch.json +55 -0
  184. package/src/tokens/components/tabs.json +38 -0
  185. package/src/tokens/components/textfield.json +59 -0
  186. package/src/tokens/components/togglebutton.json +48 -0
  187. package/src/tokens/components/uploaddropzone.json +61 -0
  188. package/src/tokens/drawer.ts +37 -0
  189. package/src/tokens/foundation/breakpoints.json +10 -0
  190. package/src/tokens/foundation/colors.json +122 -0
  191. package/src/tokens/foundation/opacity.json +16 -0
  192. package/src/tokens/foundation/radius.json +14 -0
  193. package/src/tokens/foundation/size.json +38 -0
  194. package/src/tokens/foundation/spacing.json +19 -0
  195. package/src/tokens/foundation/typography.json +43 -0
  196. package/src/tokens/index.ts +3665 -0
  197. package/src/tokens/modal.ts +42 -0
  198. package/src/tokens/semantic/color.json +148 -0
  199. package/src/tokens/semantic/field.json +28 -0
  200. package/src/tokens/semantic/opacity.json +5 -0
  201. package/src/tokens/semantic/size.json +722 -0
  202. package/src/tokens/semantic/spacing.json +27 -0
  203. package/src/tokens/semantic/typography.json +87 -0
  204. package/src/utils/scrollLock.ts +44 -0
  205. package/dist/index.css +0 -514
  206. package/dist/index.css.map +0 -1
  207. package/dist/index.d.ts +0 -289
@@ -0,0 +1,105 @@
1
+ export type DatePickerSize = "sm" | "md" | "lg";
2
+
3
+ export type DatePickerIconPosition = "start" | "end";
4
+
5
+ export interface DatePickerProps {
6
+ /**
7
+ * Field label shown above the input
8
+ */
9
+ label: string;
10
+ /**
11
+ * Current value (for controlled usage)
12
+ */
13
+ value?: Date | null;
14
+ /**
15
+ * Default value (for uncontrolled usage)
16
+ */
17
+ defaultValue?: Date | null;
18
+ /**
19
+ * Placeholder text inside the input
20
+ */
21
+ placeholder?: string;
22
+ /**
23
+ * Helper or error text displayed below the field
24
+ */
25
+ helperText?: string;
26
+ /**
27
+ * Marks the field as required and appends "*" to the label
28
+ */
29
+ required?: boolean;
30
+ /**
31
+ * Shows error state and styles
32
+ */
33
+ error?: boolean;
34
+ /**
35
+ * Disables the field
36
+ */
37
+ disabled?: boolean;
38
+ /**
39
+ * Makes the field stretch to full container width
40
+ */
41
+ fullWidth?: boolean;
42
+ /**
43
+ * Size of the date picker field
44
+ */
45
+ size?: DatePickerSize;
46
+ /**
47
+ * Icon element to render inside the input
48
+ *
49
+ * Example:
50
+ * import CalendarTodayIcon from "@mui/icons-material/CalendarToday";
51
+ * <DatePicker icon={<CalendarTodayIcon />} />
52
+ *
53
+ * If you prefer naming convention like `calendar_icon`, you can wrap it:
54
+ * const calendar_icon = <CalendarTodayIcon />;
55
+ * <DatePicker icon={calendar_icon} />
56
+ */
57
+ icon?: React.ReactNode;
58
+ /**
59
+ * Position of the icon inside the input
60
+ */
61
+ iconPosition?: DatePickerIconPosition;
62
+ /**
63
+ * Input name attribute
64
+ */
65
+ name?: string;
66
+ /**
67
+ * HTML id attribute (used to link label and input)
68
+ */
69
+ id?: string;
70
+ /**
71
+ * onChange handler
72
+ */
73
+ onChange?: (value: Date | null) => void;
74
+ /**
75
+ * onBlur handler
76
+ */
77
+ onBlur?: (event: React.FocusEvent<HTMLInputElement>) => void;
78
+ /**
79
+ * onFocus handler
80
+ */
81
+ onFocus?: (event: React.FocusEvent<HTMLInputElement>) => void;
82
+ /**
83
+ * Minimum selectable date
84
+ */
85
+ minDate?: Date;
86
+ /**
87
+ * Maximum selectable date
88
+ */
89
+ maxDate?: Date;
90
+ /**
91
+ * Format string for displaying the date
92
+ */
93
+ format?: string;
94
+ /**
95
+ * Format string for input parsing (if different from display format)
96
+ * If not provided, will use the `format` prop value
97
+ */
98
+ inputFormat?: string;
99
+ /**
100
+ * Allow users to type the date directly in the input field
101
+ * If false, users can only select dates from the calendar picker
102
+ * @default true
103
+ */
104
+ allowKeyboardInput?: boolean;
105
+ }
@@ -0,0 +1,35 @@
1
+ import { DatePicker } from './DatePicker';
2
+ import type { DatePickerWrapperProps } from './DatePicker';
3
+
4
+ export type DateTimePickerProps = DatePickerWrapperProps & {
5
+ /** Display format for date and time (default: yyyy/MM/dd HH:mm) */
6
+ dateFormat?: string;
7
+ /** Minute step in the time list (default: 1) */
8
+ timeIntervals?: number;
9
+ };
10
+
11
+ /**
12
+ * Date and time picker built on the design-system DatePicker (24-hour format).
13
+ */
14
+ export function DateTimePicker({
15
+ dateFormat = 'yyyy/MM/dd HH:mm',
16
+ timeFormat = 'HH:mm',
17
+ timeIntervals = 1,
18
+ timeCaption = 'Time',
19
+ placeholderText = 'Select date and time',
20
+ ...props
21
+ }: DateTimePickerProps) {
22
+ return (
23
+ <DatePicker
24
+ {...props}
25
+ showTimeSelect
26
+ timeFormat={timeFormat}
27
+ timeIntervals={timeIntervals}
28
+ timeCaption={timeCaption}
29
+ dateFormat={dateFormat}
30
+ placeholderText={placeholderText}
31
+ />
32
+ );
33
+ }
34
+
35
+ export default DateTimePicker;
@@ -0,0 +1,179 @@
1
+ import { useCallback, type CSSProperties, forwardRef } from 'react';
2
+ import ArrowForwardIcon from '@mui/icons-material/ArrowForward';
3
+ import { DatePicker, ExampleCustomInput } from '../DatePicker/DatePicker';
4
+ import type { DateRangePickerProps } from './DateRangePicker.types';
5
+
6
+ const FIELD_HEIGHT: Record<NonNullable<DateRangePickerProps['size']>, number> = {
7
+ sm: 32,
8
+ md: 40,
9
+ lg: 48,
10
+ };
11
+
12
+ const RangeInput = forwardRef<HTMLDivElement, any>((props, ref) => {
13
+ const {
14
+ startLabel,
15
+ endLabel,
16
+ startPlaceholder,
17
+ endPlaceholder,
18
+ disabled,
19
+ wrapperStyle,
20
+ fieldGroupStyle,
21
+ inlineLabelStyle,
22
+ fieldStyle,
23
+ startDate,
24
+ endDate,
25
+ onClick,
26
+ isOpen,
27
+ onToggleOpen,
28
+ onToggleClose,
29
+ mouseDownOnFieldRef,
30
+ className,
31
+ } = props;
32
+ const size = (props.size || 'sm') as NonNullable<DateRangePickerProps['size']>;
33
+
34
+ // If date-fns format is used, we can just do a very simple slice for now or use toLocaleDateString
35
+ const valStart = startDate ? startDate.toLocaleDateString() : '';
36
+ const valEnd = endDate ? endDate.toLocaleDateString() : '';
37
+
38
+ return (
39
+ <div className={className} style={wrapperStyle} ref={ref}>
40
+ <div style={fieldGroupStyle}>
41
+ <span style={inlineLabelStyle}>{startLabel}</span>
42
+ <div style={fieldStyle}>
43
+ <ExampleCustomInput
44
+ value={valStart}
45
+ placeholder={startPlaceholder}
46
+ disabled={disabled}
47
+ size={size}
48
+ iconName="calendar"
49
+ onClick={onClick}
50
+ isOpen={isOpen}
51
+ onToggleOpen={onToggleOpen}
52
+ onToggleClose={onToggleClose}
53
+ mouseDownOnFieldRef={mouseDownOnFieldRef}
54
+ />
55
+ </div>
56
+ </div>
57
+
58
+ <span
59
+ aria-hidden
60
+ style={{
61
+ display: 'inline-flex',
62
+ alignItems: 'center',
63
+ color: '#6B7280',
64
+ height: FIELD_HEIGHT[size],
65
+ }}
66
+ >
67
+ <ArrowForwardIcon sx={{ fontSize: 18 }} />
68
+ </span>
69
+
70
+ <div style={fieldGroupStyle}>
71
+ <span style={inlineLabelStyle}>{endLabel}</span>
72
+ <div style={fieldStyle}>
73
+ <ExampleCustomInput
74
+ value={valEnd}
75
+ placeholder={endPlaceholder}
76
+ disabled={disabled}
77
+ size={size}
78
+ iconName="calendar"
79
+ onClick={onClick}
80
+ isOpen={isOpen}
81
+ onToggleOpen={onToggleOpen}
82
+ onToggleClose={onToggleClose}
83
+ mouseDownOnFieldRef={mouseDownOnFieldRef}
84
+ />
85
+ </div>
86
+ </div>
87
+ </div>
88
+ );
89
+ });
90
+
91
+ export function DateRangePicker({
92
+ startDate,
93
+ endDate,
94
+ onChange,
95
+ startLabel = 'From',
96
+ endLabel = 'To',
97
+ dateFormat = 'MMM dd, yyyy',
98
+ startPlaceholder = 'From',
99
+ endPlaceholder = 'To',
100
+ size = 'sm',
101
+ minDate,
102
+ maxDate,
103
+ disabled,
104
+ className,
105
+ style,
106
+ }: DateRangePickerProps) {
107
+ const handleRangeChange = useCallback(
108
+ (dates: any) => {
109
+ if (Array.isArray(dates)) {
110
+ const [nextStart, nextEnd] = dates;
111
+ onChange({ startDate: nextStart, endDate: nextEnd });
112
+ } else {
113
+ onChange({ startDate: dates, endDate: null });
114
+ }
115
+ },
116
+ [onChange]
117
+ );
118
+
119
+ const wrapperStyle: CSSProperties = {
120
+ display: 'inline-flex',
121
+ alignItems: 'center',
122
+ gap: 12,
123
+ ...style,
124
+ };
125
+
126
+ const fieldGroupStyle: CSSProperties = {
127
+ display: 'inline-flex',
128
+ alignItems: 'center',
129
+ gap: 8,
130
+ };
131
+
132
+ const inlineLabelStyle: CSSProperties = {
133
+ fontSize: size === 'lg' ? 14 : 13,
134
+ fontWeight: 500,
135
+ color: disabled ? '#9CA3AF' : '#374151',
136
+ whiteSpace: 'nowrap',
137
+ };
138
+
139
+ const fieldWidth =
140
+ size === 'lg' ? 220
141
+ : size === 'md' ? 200
142
+ : 188;
143
+ const fieldStyle: CSSProperties = {
144
+ width: fieldWidth,
145
+ };
146
+
147
+ const DatePickerAny = DatePicker as any;
148
+
149
+ return (
150
+ <div className={className}>
151
+ <DatePickerAny
152
+ selectsRange={true}
153
+ startDate={startDate}
154
+ endDate={endDate}
155
+ onChange={handleRangeChange}
156
+ dateFormat={dateFormat}
157
+ minDate={minDate}
158
+ maxDate={maxDate}
159
+ disabled={disabled}
160
+ customInput={
161
+ <RangeInput
162
+ startLabel={startLabel}
163
+ endLabel={endLabel}
164
+ startPlaceholder={startPlaceholder}
165
+ endPlaceholder={endPlaceholder}
166
+ size={size}
167
+ disabled={disabled}
168
+ wrapperStyle={wrapperStyle}
169
+ fieldGroupStyle={fieldGroupStyle}
170
+ inlineLabelStyle={inlineLabelStyle}
171
+ fieldStyle={fieldStyle}
172
+ startDate={startDate}
173
+ endDate={endDate}
174
+ />
175
+ }
176
+ />
177
+ </div>
178
+ );
179
+ }
@@ -0,0 +1,34 @@
1
+ import type { CSSProperties } from 'react';
2
+
3
+ export type DateRangePickerSize = 'sm' | 'md' | 'lg';
4
+
5
+ export interface DateRangePickerProps {
6
+ /** Currently selected start date. */
7
+ startDate: Date | null;
8
+ /** Currently selected end date. */
9
+ endDate: Date | null;
10
+ /** Fired whenever either date changes. */
11
+ onChange: (range: { startDate: Date | null; endDate: Date | null }) => void;
12
+ /** Label rendered above the start-date picker. Defaults to "Start date". */
13
+ startLabel?: string;
14
+ /** Label rendered above the end-date picker. Defaults to "End date". */
15
+ endLabel?: string;
16
+ /** Display format passed through to the underlying DatePickers. */
17
+ dateFormat?: string;
18
+ /** Placeholder shown in the start input when empty. */
19
+ startPlaceholder?: string;
20
+ /** Placeholder shown in the end input when empty. */
21
+ endPlaceholder?: string;
22
+ /** Size of each underlying DatePicker. */
23
+ size?: DateRangePickerSize;
24
+ /** Minimum selectable date for the start picker. */
25
+ minDate?: Date;
26
+ /** Maximum selectable date for the end picker. */
27
+ maxDate?: Date;
28
+ /** Disable both fields. */
29
+ disabled?: boolean;
30
+ /** Optional className applied to the outer wrapper. */
31
+ className?: string;
32
+ /** Optional inline style applied to the outer wrapper. */
33
+ style?: CSSProperties;
34
+ }
@@ -0,0 +1,243 @@
1
+ import { useState } from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ import { Drawer } from './Drawer';
4
+ import type { DrawerProps } from './Drawer.types';
5
+ import { Button } from '../Button/Button';
6
+
7
+ const meta: Meta<typeof Drawer> = {
8
+ title: 'Design System/Drawer',
9
+ component: Drawer,
10
+ tags: [],
11
+ decorators: [
12
+ (Story) => (
13
+ <div style={{ padding: '24px', fontFamily: 'Inter, sans-serif' }}>
14
+ <Story />
15
+ </div>
16
+ ),
17
+ ],
18
+ args: {
19
+ anchor: 'right',
20
+ size: 'lg',
21
+ disableBackdropClose: false,
22
+ transitionDuration: 300,
23
+ } as DrawerProps,
24
+ argTypes: {
25
+ anchor: {
26
+ control: { type: 'radio' },
27
+ options: ['left', 'right', 'top', 'bottom'],
28
+ description: 'Side from which the drawer slides in',
29
+ },
30
+ size: {
31
+ control: { type: 'radio' },
32
+ options: ['sm', 'md', 'lg'],
33
+ description: 'Size preset for drawer width (left/right) or height (top/bottom)',
34
+ },
35
+ width: {
36
+ control: { type: 'number' },
37
+ description: 'Custom width/height in pixels (overrides size when set)',
38
+ },
39
+ disableBackdropClose: {
40
+ control: { type: 'boolean' },
41
+ description: 'Prevent closing when clicking the backdrop',
42
+ },
43
+ transitionDuration: {
44
+ control: { type: 'number' },
45
+ description: 'Animation duration in milliseconds',
46
+ },
47
+ },
48
+ };
49
+
50
+ export default meta;
51
+
52
+ type Story = StoryObj<typeof Drawer>;
53
+
54
+ const DrawerContent = ({ title, description }: { title: string; description: string }) => (
55
+ <div style={{ padding: '24px' }}>
56
+ <h3 style={{ margin: '0 0 16px' }}>{title}</h3>
57
+ <p style={{ margin: 0 }}>{description}</p>
58
+ </div>
59
+ );
60
+
61
+ export const Playground: Story = {
62
+ args: {
63
+ anchor: 'right',
64
+ size: 'lg',
65
+ },
66
+ };
67
+
68
+ const PlaygroundComponent = (args: DrawerProps) => {
69
+ const [open, setOpen] = useState(false);
70
+ return (
71
+ <>
72
+ <Button onClick={() => setOpen(true)}>Open Drawer</Button>
73
+ <Drawer {...args} open={open} onClose={() => setOpen(false)}>
74
+ <DrawerContent
75
+ title="Drawer Content"
76
+ description="Adjust anchor, size, and other properties through the Storybook controls."
77
+ />
78
+ <div style={{ padding: '0 24px 24px' }}>
79
+ <Button variant="grey" onClick={() => setOpen(false)}>
80
+ Close
81
+ </Button>
82
+ </div>
83
+ </Drawer>
84
+ </>
85
+ );
86
+ };
87
+
88
+ Playground.render = (args) => <PlaygroundComponent {...args} />;
89
+
90
+ const ShowcaseComponent = () => {
91
+ const [openRight, setOpenRight] = useState(false);
92
+ const [openLeft, setOpenLeft] = useState(false);
93
+ const [openTop, setOpenTop] = useState(false);
94
+ const [openBottom, setOpenBottom] = useState(false);
95
+ const [openSm, setOpenSm] = useState(false);
96
+ const [openMd, setOpenMd] = useState(false);
97
+ const [openLg, setOpenLg] = useState(false);
98
+ const [openCustom, setOpenCustom] = useState(false);
99
+ const [openNoBackdrop, setOpenNoBackdrop] = useState(false);
100
+
101
+ return (
102
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '24px' }}>
103
+ {/* Right anchor (default) */}
104
+ <div>
105
+ <Button onClick={() => setOpenRight(true)}>Open Right Drawer</Button>
106
+ <Drawer anchor="right" size="lg" open={openRight} onClose={() => setOpenRight(false)}>
107
+ <DrawerContent
108
+ title="Right Drawer"
109
+ description="Drawer slides in from the right (default)."
110
+ />
111
+ <div style={{ padding: '0 24px 24px' }}>
112
+ <Button variant="grey" onClick={() => setOpenRight(false)}>
113
+ Close
114
+ </Button>
115
+ </div>
116
+ </Drawer>
117
+ </div>
118
+
119
+ {/* Left anchor */}
120
+ <div>
121
+ <Button onClick={() => setOpenLeft(true)}>Open Left Drawer</Button>
122
+ <Drawer anchor="left" size="md" open={openLeft} onClose={() => setOpenLeft(false)}>
123
+ <DrawerContent
124
+ title="Left Drawer"
125
+ description="Drawer slides in from the left (useful for RTL layouts)."
126
+ />
127
+ <div style={{ padding: '0 24px 24px' }}>
128
+ <Button variant="grey" onClick={() => setOpenLeft(false)}>
129
+ Close
130
+ </Button>
131
+ </div>
132
+ </Drawer>
133
+ </div>
134
+
135
+ {/* Top anchor */}
136
+ <div>
137
+ <Button onClick={() => setOpenTop(true)}>Open Top Drawer</Button>
138
+ <Drawer anchor="top" size="md" open={openTop} onClose={() => setOpenTop(false)}>
139
+ <DrawerContent title="Top Drawer" description="Drawer slides in from the top." />
140
+ <div style={{ padding: '0 24px 24px' }}>
141
+ <Button variant="grey" onClick={() => setOpenTop(false)}>
142
+ Close
143
+ </Button>
144
+ </div>
145
+ </Drawer>
146
+ </div>
147
+
148
+ {/* Bottom anchor */}
149
+ <div>
150
+ <Button onClick={() => setOpenBottom(true)}>Open Bottom Drawer</Button>
151
+ <Drawer anchor="bottom" size="md" open={openBottom} onClose={() => setOpenBottom(false)}>
152
+ <DrawerContent title="Bottom Drawer" description="Drawer slides in from the bottom." />
153
+ <div style={{ padding: '0 24px 24px' }}>
154
+ <Button variant="grey" onClick={() => setOpenBottom(false)}>
155
+ Close
156
+ </Button>
157
+ </div>
158
+ </Drawer>
159
+ </div>
160
+
161
+ {/* Small size */}
162
+ <div>
163
+ <Button onClick={() => setOpenSm(true)}>Open Small (550px)</Button>
164
+ <Drawer anchor="right" size="sm" open={openSm} onClose={() => setOpenSm(false)}>
165
+ <DrawerContent title="Small Drawer" description="Size preset: sm (550px width)." />
166
+ <div style={{ padding: '0 24px 24px' }}>
167
+ <Button variant="grey" onClick={() => setOpenSm(false)}>
168
+ Close
169
+ </Button>
170
+ </div>
171
+ </Drawer>
172
+ </div>
173
+
174
+ {/* Medium size */}
175
+ <div>
176
+ <Button onClick={() => setOpenMd(true)}>Open Medium (800px)</Button>
177
+ <Drawer anchor="right" size="md" open={openMd} onClose={() => setOpenMd(false)}>
178
+ <DrawerContent title="Medium Drawer" description="Size preset: md (800px width)." />
179
+ <div style={{ padding: '0 24px 24px' }}>
180
+ <Button variant="grey" onClick={() => setOpenMd(false)}>
181
+ Close
182
+ </Button>
183
+ </div>
184
+ </Drawer>
185
+ </div>
186
+
187
+ {/* Large size */}
188
+ <div>
189
+ <Button onClick={() => setOpenLg(true)}>Open Large (1200px)</Button>
190
+ <Drawer anchor="right" size="lg" open={openLg} onClose={() => setOpenLg(false)}>
191
+ <DrawerContent title="Large Drawer" description="Size preset: lg (1200px width)." />
192
+ <div style={{ padding: '0 24px 24px' }}>
193
+ <Button variant="grey" onClick={() => setOpenLg(false)}>
194
+ Close
195
+ </Button>
196
+ </div>
197
+ </Drawer>
198
+ </div>
199
+
200
+ {/* Custom width */}
201
+ <div>
202
+ <Button onClick={() => setOpenCustom(true)}>Open Custom (1200px)</Button>
203
+ <Drawer anchor="right" width={1200} open={openCustom} onClose={() => setOpenCustom(false)}>
204
+ <DrawerContent
205
+ title="Custom Width Drawer"
206
+ description="Fixed width of 1200px via the width prop."
207
+ />
208
+ <div style={{ padding: '0 24px 24px' }}>
209
+ <Button variant="grey" onClick={() => setOpenCustom(false)}>
210
+ Close
211
+ </Button>
212
+ </div>
213
+ </Drawer>
214
+ </div>
215
+
216
+ {/* Disable backdrop close */}
217
+ <div>
218
+ <Button onClick={() => setOpenNoBackdrop(true)}>Open (Backdrop Click Disabled)</Button>
219
+ <Drawer
220
+ anchor="right"
221
+ size="md"
222
+ open={openNoBackdrop}
223
+ onClose={() => setOpenNoBackdrop(false)}
224
+ disableBackdropClose
225
+ >
226
+ <DrawerContent
227
+ title="No Backdrop Close"
228
+ description="Clicking the backdrop will not close this drawer. Use the Close button or Escape key."
229
+ />
230
+ <div style={{ padding: '0 24px 24px' }}>
231
+ <Button variant="grey" onClick={() => setOpenNoBackdrop(false)}>
232
+ Close
233
+ </Button>
234
+ </div>
235
+ </Drawer>
236
+ </div>
237
+ </div>
238
+ );
239
+ };
240
+
241
+ export const Showcase: Story = {
242
+ render: () => <ShowcaseComponent />,
243
+ };