@drivenets/design-system 0.0.4 → 0.1.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 (235) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +51 -0
  3. package/dist/components/ds-alert-banner/ds-alert-banner.d.ts +5 -5
  4. package/dist/components/ds-alert-banner/ds-alert-banner.d.ts.map +1 -1
  5. package/dist/components/ds-button/ds-button.d.cts +2 -2
  6. package/dist/components/ds-button/ds-button.d.cts.map +1 -1
  7. package/dist/components/ds-button/versions/ds-button-new/ds-button-new.module.cjs +18 -18
  8. package/dist/components/ds-button/versions/ds-button-new/ds-button-new.module.js +18 -18
  9. package/dist/components/ds-button/versions/ds-button-new/ds-button-new.module.js.map +1 -1
  10. package/dist/components/ds-confirmation/ds-confirmation.d.cts +8 -8
  11. package/dist/components/ds-confirmation/ds-confirmation.d.ts +8 -8
  12. package/dist/components/ds-date-input/ds-date-input.cjs +352 -0
  13. package/dist/components/ds-date-input/ds-date-input.d.cts +31 -0
  14. package/dist/components/ds-date-input/ds-date-input.d.cts.map +1 -0
  15. package/dist/components/ds-date-input/ds-date-input.d.ts +31 -0
  16. package/dist/components/ds-date-input/ds-date-input.d.ts.map +1 -0
  17. package/dist/components/ds-date-input/ds-date-input.js +351 -0
  18. package/dist/components/ds-date-input/ds-date-input.js.map +1 -0
  19. package/dist/components/ds-date-input/ds-date-input.module.cjs +29 -0
  20. package/dist/components/ds-date-input/ds-date-input.module.js +29 -0
  21. package/dist/components/ds-date-input/ds-date-input.module.js.map +1 -0
  22. package/dist/components/ds-date-input/ds-date-input.types.d.cts +92 -0
  23. package/dist/components/ds-date-input/ds-date-input.types.d.cts.map +1 -0
  24. package/dist/components/ds-date-input/ds-date-input.types.d.ts +92 -0
  25. package/dist/components/ds-date-input/ds-date-input.types.d.ts.map +1 -0
  26. package/dist/components/ds-date-input/ds-date-input.utils.cjs +169 -0
  27. package/dist/components/ds-date-input/ds-date-input.utils.js +164 -0
  28. package/dist/components/ds-date-input/ds-date-input.utils.js.map +1 -0
  29. package/dist/components/ds-date-input/index.cjs +1 -0
  30. package/dist/components/ds-date-input/index.d.ts +2 -0
  31. package/dist/components/ds-date-input/index.js +1 -0
  32. package/dist/components/ds-divider/ds-divider.cjs +47 -0
  33. package/dist/components/ds-divider/ds-divider.d.cts +8 -0
  34. package/dist/components/ds-divider/ds-divider.d.cts.map +1 -0
  35. package/dist/components/ds-divider/ds-divider.d.ts +8 -0
  36. package/dist/components/ds-divider/ds-divider.d.ts.map +1 -0
  37. package/dist/components/ds-divider/ds-divider.js +46 -0
  38. package/dist/components/ds-divider/ds-divider.js.map +1 -0
  39. package/dist/components/ds-divider/ds-divider.module.cjs +10 -0
  40. package/dist/components/ds-divider/ds-divider.module.js +10 -0
  41. package/dist/components/ds-divider/ds-divider.module.js.map +1 -0
  42. package/dist/components/ds-divider/ds-divider.types.d.cts +25 -0
  43. package/dist/components/ds-divider/ds-divider.types.d.cts.map +1 -0
  44. package/dist/components/ds-divider/ds-divider.types.d.ts +25 -0
  45. package/dist/components/ds-divider/ds-divider.types.d.ts.map +1 -0
  46. package/dist/components/ds-divider/index.cjs +1 -0
  47. package/dist/components/ds-divider/index.d.ts +2 -0
  48. package/dist/components/ds-divider/index.js +1 -0
  49. package/dist/components/ds-drawer/ds-drawer.d.cts +9 -9
  50. package/dist/components/ds-drawer/ds-drawer.d.ts +9 -9
  51. package/dist/components/ds-dropdown-menu/ds-dropdown-menu.cjs +80 -24
  52. package/dist/components/ds-dropdown-menu/ds-dropdown-menu.d.cts +1 -0
  53. package/dist/components/ds-dropdown-menu/ds-dropdown-menu.d.cts.map +1 -1
  54. package/dist/components/ds-dropdown-menu/ds-dropdown-menu.d.ts +1 -0
  55. package/dist/components/ds-dropdown-menu/ds-dropdown-menu.d.ts.map +1 -1
  56. package/dist/components/ds-dropdown-menu/ds-dropdown-menu.js +80 -24
  57. package/dist/components/ds-dropdown-menu/ds-dropdown-menu.js.map +1 -1
  58. package/dist/components/ds-dropdown-menu/ds-dropdown-menu.module.cjs +20 -18
  59. package/dist/components/ds-dropdown-menu/ds-dropdown-menu.module.js +20 -18
  60. package/dist/components/ds-dropdown-menu/ds-dropdown-menu.module.js.map +1 -1
  61. package/dist/components/ds-dropdown-menu/ds-dropdown-menu.types.d.cts +5 -1
  62. package/dist/components/ds-dropdown-menu/ds-dropdown-menu.types.d.cts.map +1 -1
  63. package/dist/components/ds-dropdown-menu/ds-dropdown-menu.types.d.ts +5 -1
  64. package/dist/components/ds-dropdown-menu/ds-dropdown-menu.types.d.ts.map +1 -1
  65. package/dist/components/ds-dropdown-menu/index.d.ts +1 -1
  66. package/dist/components/ds-expandable-text-input/ds-expandable-text-input.d.cts +2 -2
  67. package/dist/components/ds-expandable-text-input/ds-expandable-text-input.d.ts +2 -2
  68. package/dist/components/ds-form-control/ds-form-control.cjs +3 -0
  69. package/dist/components/ds-form-control/ds-form-control.d.cts +9 -7
  70. package/dist/components/ds-form-control/ds-form-control.d.cts.map +1 -1
  71. package/dist/components/ds-form-control/ds-form-control.d.ts +10 -7
  72. package/dist/components/ds-form-control/ds-form-control.d.ts.map +1 -1
  73. package/dist/components/ds-form-control/ds-form-control.js +3 -0
  74. package/dist/components/ds-form-control/ds-form-control.js.map +1 -1
  75. package/dist/components/ds-modal/ds-modal.d.cts +8 -8
  76. package/dist/components/ds-modal/ds-modal.d.ts +8 -8
  77. package/dist/components/ds-modal/ds-modal.d.ts.map +1 -1
  78. package/dist/components/ds-panel/ds-panel.d.cts +2 -2
  79. package/dist/components/ds-panel/ds-panel.d.ts +2 -2
  80. package/dist/components/ds-radio-group/ds-radio-group.types.d.cts +1 -1
  81. package/dist/components/ds-radio-group/ds-radio-group.types.d.cts.map +1 -1
  82. package/dist/components/ds-radio-group/ds-radio-group.types.d.ts +1 -1
  83. package/dist/components/ds-radio-group/ds-radio-group.types.d.ts.map +1 -1
  84. package/dist/components/ds-segment-group/ds-segment-group.cjs +215 -0
  85. package/dist/components/ds-segment-group/ds-segment-group.d.cts +26 -0
  86. package/dist/components/ds-segment-group/ds-segment-group.d.cts.map +1 -0
  87. package/dist/components/ds-segment-group/ds-segment-group.d.ts +26 -0
  88. package/dist/components/ds-segment-group/ds-segment-group.d.ts.map +1 -0
  89. package/dist/components/ds-segment-group/ds-segment-group.js +214 -0
  90. package/dist/components/ds-segment-group/ds-segment-group.js.map +1 -0
  91. package/dist/components/ds-segment-group/ds-segment-group.module.cjs +12 -0
  92. package/dist/components/ds-segment-group/ds-segment-group.module.js +12 -0
  93. package/dist/components/ds-segment-group/ds-segment-group.module.js.map +1 -0
  94. package/dist/components/ds-segment-group/ds-segment-group.types.cjs +2 -0
  95. package/dist/components/ds-segment-group/ds-segment-group.types.d.cts +52 -0
  96. package/dist/components/ds-segment-group/ds-segment-group.types.d.cts.map +1 -0
  97. package/dist/components/ds-segment-group/ds-segment-group.types.d.ts +52 -0
  98. package/dist/components/ds-segment-group/ds-segment-group.types.d.ts.map +1 -0
  99. package/dist/components/ds-segment-group/ds-segment-group.types.js +2 -0
  100. package/dist/components/ds-segment-group/index.cjs +2 -0
  101. package/dist/components/ds-segment-group/index.d.ts +2 -0
  102. package/dist/components/ds-segment-group/index.js +2 -0
  103. package/dist/components/ds-select/ds-select.d.cts +2 -2
  104. package/dist/components/ds-select/ds-select.d.ts +2 -2
  105. package/dist/components/ds-smart-tabs/ds-smart-tabs.d.cts +2 -2
  106. package/dist/components/ds-smart-tabs/ds-smart-tabs.d.ts +2 -2
  107. package/dist/components/ds-stepper/components/ds-step-content.d.ts +2 -2
  108. package/dist/components/ds-stepper/components/ds-step-next-button.d.ts +2 -2
  109. package/dist/components/ds-stepper/components/ds-step.d.cts +2 -2
  110. package/dist/components/ds-stepper/components/ds-step.d.ts +2 -2
  111. package/dist/components/ds-stepper/ds-stepper.d.cts +2 -2
  112. package/dist/components/ds-stepper/ds-stepper.d.ts +2 -2
  113. package/dist/components/ds-table/components/ds-table-cell/ds-table-cell.types.d.cts +1 -0
  114. package/dist/components/ds-table/components/ds-table-cell/ds-table-cell.types.d.cts.map +1 -1
  115. package/dist/components/ds-table/components/ds-table-cell/ds-table-cell.types.d.ts +1 -1
  116. package/dist/components/ds-table/ds-table.d.cts +2 -2
  117. package/dist/components/ds-table/ds-table.d.ts +2 -2
  118. package/dist/components/ds-table/filters/adapters/create-checkbox-filter-adapter.cjs +55 -0
  119. package/dist/components/ds-table/filters/adapters/create-checkbox-filter-adapter.d.cts +49 -0
  120. package/dist/components/ds-table/filters/adapters/create-checkbox-filter-adapter.d.cts.map +1 -0
  121. package/dist/components/ds-table/filters/adapters/create-checkbox-filter-adapter.d.ts +50 -0
  122. package/dist/components/ds-table/filters/adapters/create-checkbox-filter-adapter.d.ts.map +1 -0
  123. package/dist/components/ds-table/filters/adapters/create-checkbox-filter-adapter.js +55 -0
  124. package/dist/components/ds-table/filters/adapters/create-checkbox-filter-adapter.js.map +1 -0
  125. package/dist/components/ds-table/filters/adapters/create-dual-range-filter-adapter.cjs +87 -0
  126. package/dist/components/ds-table/filters/adapters/create-dual-range-filter-adapter.d.cts +44 -0
  127. package/dist/components/ds-table/filters/adapters/create-dual-range-filter-adapter.d.cts.map +1 -0
  128. package/dist/components/ds-table/filters/adapters/create-dual-range-filter-adapter.d.ts +44 -0
  129. package/dist/components/ds-table/filters/adapters/create-dual-range-filter-adapter.d.ts.map +1 -0
  130. package/dist/components/ds-table/filters/adapters/create-dual-range-filter-adapter.js +87 -0
  131. package/dist/components/ds-table/filters/adapters/create-dual-range-filter-adapter.js.map +1 -0
  132. package/dist/components/ds-table/filters/adapters/create-filter-adapter.cjs +83 -0
  133. package/dist/components/ds-table/filters/adapters/create-filter-adapter.d.cts +111 -0
  134. package/dist/components/ds-table/filters/adapters/create-filter-adapter.d.cts.map +1 -0
  135. package/dist/components/ds-table/filters/adapters/create-filter-adapter.d.ts +111 -0
  136. package/dist/components/ds-table/filters/adapters/create-filter-adapter.d.ts.map +1 -0
  137. package/dist/components/ds-table/filters/adapters/create-filter-adapter.js +83 -0
  138. package/dist/components/ds-table/filters/adapters/create-filter-adapter.js.map +1 -0
  139. package/dist/components/ds-table/filters/adapters/index.cjs +3 -0
  140. package/dist/components/ds-table/filters/adapters/index.d.ts +3 -0
  141. package/dist/components/ds-table/filters/adapters/index.js +3 -0
  142. package/dist/components/ds-table/filters/components/checkbox-filter/checkbox-filter.cjs +22 -0
  143. package/dist/components/ds-table/filters/components/checkbox-filter/checkbox-filter.d.cts +17 -0
  144. package/dist/components/ds-table/filters/components/checkbox-filter/checkbox-filter.d.cts.map +1 -0
  145. package/dist/components/ds-table/filters/components/checkbox-filter/checkbox-filter.d.ts +18 -0
  146. package/dist/components/ds-table/filters/components/checkbox-filter/checkbox-filter.d.ts.map +1 -0
  147. package/dist/components/ds-table/filters/components/checkbox-filter/checkbox-filter.js +22 -0
  148. package/dist/components/ds-table/filters/components/checkbox-filter/checkbox-filter.js.map +1 -0
  149. package/dist/components/ds-table/filters/components/checkbox-filter/index.cjs +1 -0
  150. package/dist/components/ds-table/filters/components/checkbox-filter/index.d.ts +1 -0
  151. package/dist/components/ds-table/filters/components/checkbox-filter/index.js +1 -0
  152. package/dist/components/ds-table/filters/components/range-filter/index.cjs +1 -0
  153. package/dist/components/ds-table/filters/components/range-filter/index.d.ts +1 -0
  154. package/dist/components/ds-table/filters/components/range-filter/index.js +1 -0
  155. package/dist/components/ds-table/filters/components/range-filter/range-filter.cjs +177 -0
  156. package/dist/components/ds-table/filters/components/range-filter/range-filter.d.cts +14 -0
  157. package/dist/components/ds-table/filters/components/range-filter/range-filter.d.cts.map +1 -0
  158. package/dist/components/ds-table/filters/components/range-filter/range-filter.d.ts +16 -0
  159. package/dist/components/ds-table/filters/components/range-filter/range-filter.d.ts.map +1 -0
  160. package/dist/components/ds-table/filters/components/range-filter/range-filter.js +177 -0
  161. package/dist/components/ds-table/filters/components/range-filter/range-filter.js.map +1 -0
  162. package/dist/components/ds-table/filters/components/range-filter/range-filter.module.cjs +11 -0
  163. package/dist/components/ds-table/filters/components/range-filter/range-filter.module.js +11 -0
  164. package/dist/components/ds-table/filters/components/range-filter/range-filter.module.js.map +1 -0
  165. package/dist/components/ds-table/filters/hooks/index.cjs +1 -0
  166. package/dist/components/ds-table/filters/hooks/index.d.ts +1 -0
  167. package/dist/components/ds-table/filters/hooks/index.js +1 -0
  168. package/dist/components/ds-table/filters/hooks/use-table-filters.cjs +211 -0
  169. package/dist/components/ds-table/filters/hooks/use-table-filters.d.cts +65 -0
  170. package/dist/components/ds-table/filters/hooks/use-table-filters.d.cts.map +1 -0
  171. package/dist/components/ds-table/filters/hooks/use-table-filters.d.ts +66 -0
  172. package/dist/components/ds-table/filters/hooks/use-table-filters.d.ts.map +1 -0
  173. package/dist/components/ds-table/filters/hooks/use-table-filters.js +211 -0
  174. package/dist/components/ds-table/filters/hooks/use-table-filters.js.map +1 -0
  175. package/dist/components/ds-table/filters/index.cjs +6 -0
  176. package/dist/components/ds-table/filters/index.d.ts +11 -0
  177. package/dist/components/ds-table/filters/index.js +6 -0
  178. package/dist/components/ds-table/filters/types/filter-adapter.types.d.cts +101 -0
  179. package/dist/components/ds-table/filters/types/filter-adapter.types.d.cts.map +1 -0
  180. package/dist/components/ds-table/filters/types/filter-adapter.types.d.ts +102 -0
  181. package/dist/components/ds-table/filters/types/filter-adapter.types.d.ts.map +1 -0
  182. package/dist/components/ds-table/index.cjs +5 -0
  183. package/dist/components/ds-table/index.d.ts +8 -0
  184. package/dist/components/ds-table/index.js +5 -0
  185. package/dist/components/ds-toggle/ds-toggle.cjs +192 -0
  186. package/dist/components/ds-toggle/ds-toggle.d.cts +24 -0
  187. package/dist/components/ds-toggle/ds-toggle.d.cts.map +1 -0
  188. package/dist/components/ds-toggle/ds-toggle.d.ts +24 -0
  189. package/dist/components/ds-toggle/ds-toggle.d.ts.map +1 -0
  190. package/dist/components/ds-toggle/ds-toggle.js +191 -0
  191. package/dist/components/ds-toggle/ds-toggle.js.map +1 -0
  192. package/dist/components/ds-toggle/ds-toggle.module.cjs +13 -0
  193. package/dist/components/ds-toggle/ds-toggle.module.js +13 -0
  194. package/dist/components/ds-toggle/ds-toggle.module.js.map +1 -0
  195. package/dist/components/ds-toggle/ds-toggle.types.d.cts +67 -0
  196. package/dist/components/ds-toggle/ds-toggle.types.d.cts.map +1 -0
  197. package/dist/components/ds-toggle/ds-toggle.types.d.ts +67 -0
  198. package/dist/components/ds-toggle/ds-toggle.types.d.ts.map +1 -0
  199. package/dist/components/ds-toggle/index.cjs +1 -0
  200. package/dist/components/ds-toggle/index.d.ts +2 -0
  201. package/dist/components/ds-toggle/index.js +1 -0
  202. package/dist/components/ds-vertical-tabs/ds-vertical-tabs.d.cts +5 -5
  203. package/dist/components/ds-vertical-tabs/ds-vertical-tabs.d.ts +5 -5
  204. package/dist/index.cjs +20 -0
  205. package/dist/index.d.cts +17 -2
  206. package/dist/index.d.ts +21 -2
  207. package/dist/index.js +13 -1
  208. package/dist/index.min.css +1 -1
  209. package/package.json +3 -2
  210. package/src/components/ds-button/versions/ds-button-new/ds-button-new.module.scss +0 -1
  211. package/src/components/ds-date-input/ds-date-input.module.scss +246 -0
  212. package/src/components/ds-date-input/ds-date-input.tsx +309 -0
  213. package/src/components/ds-date-input/ds-date-input.types.tsx +104 -0
  214. package/src/components/ds-date-input/ds-date-input.utils.ts +242 -0
  215. package/src/components/ds-date-input/index.ts +2 -0
  216. package/src/components/ds-divider/ds-divider.module.scss +21 -0
  217. package/src/components/ds-divider/ds-divider.tsx +22 -0
  218. package/src/components/ds-divider/ds-divider.types.ts +21 -0
  219. package/src/components/ds-divider/index.ts +2 -0
  220. package/src/components/ds-dropdown-menu/ds-dropdown-menu.module.scss +11 -3
  221. package/src/components/ds-dropdown-menu/ds-dropdown-menu.tsx +17 -1
  222. package/src/components/ds-dropdown-menu/ds-dropdown-menu.types.tsx +5 -0
  223. package/src/components/ds-form-control/ds-form-control.tsx +2 -0
  224. package/src/components/ds-radio-group/ds-radio-group.types.tsx +1 -1
  225. package/src/components/ds-segment-group/ds-segment-group.module.scss +99 -0
  226. package/src/components/ds-segment-group/ds-segment-group.tsx +76 -0
  227. package/src/components/ds-segment-group/ds-segment-group.types.tsx +64 -0
  228. package/src/components/ds-segment-group/index.tsx +2 -0
  229. package/src/components/ds-table/filters/hooks/index.ts +1 -0
  230. package/src/components/ds-table/index.ts +2 -0
  231. package/src/components/ds-toggle/ds-toggle.module.scss +154 -0
  232. package/src/components/ds-toggle/ds-toggle.tsx +78 -0
  233. package/src/components/ds-toggle/ds-toggle.types.tsx +76 -0
  234. package/src/components/ds-toggle/index.tsx +2 -0
  235. package/src/index.ts +4 -0
@@ -0,0 +1,242 @@
1
+ import { type DateValue } from '@ark-ui/react/date-picker';
2
+ import { CalendarDate, parseDate } from '@internationalized/date';
3
+
4
+ /**
5
+ * Validation result for date input
6
+ */
7
+ interface DateInputValidation {
8
+ isValid: boolean;
9
+ error?: string;
10
+ }
11
+
12
+ /**
13
+ * Parsed date range result
14
+ */
15
+ interface ParsedDateRange {
16
+ start: string | null;
17
+ end: string | null;
18
+ isValid: boolean;
19
+ }
20
+
21
+ /**
22
+ * Convert ISO date string to DateValue
23
+ */
24
+ export const isoStringToDateValue = (isoDate: string): DateValue | undefined => {
25
+ try {
26
+ return parseDate(isoDate) as unknown as DateValue;
27
+ } catch {
28
+ return undefined;
29
+ }
30
+ };
31
+
32
+ /**
33
+ * Convert string or tuple to DateValue array (for internal use with Ark UI)
34
+ */
35
+ export const stringToDateValue = (dates: string | [string, string]): DateValue[] => {
36
+ const dateArray = Array.isArray(dates) ? dates : [dates];
37
+
38
+ return dateArray.map(isoStringToDateValue).filter((d) => !!d);
39
+ };
40
+
41
+ /**
42
+ * Convert DateValue array to string or tuple (for public API)
43
+ */
44
+ export const dateValuesToStrings = (dates: DateValue[], range: boolean): string | [string, string] => {
45
+ const values = dates.map((date) => date.toString());
46
+
47
+ return range ? [values[0], values[1]] : values[0];
48
+ };
49
+
50
+ /**
51
+ * Format a DateValue to string (MM/DD/YYYY)
52
+ */
53
+ const formatDateValue = (date: DateValue): string => {
54
+ const paddedMonth = String(date.month).padStart(2, '0');
55
+ const paddedDay = String(date.day).padStart(2, '0');
56
+
57
+ return `${paddedMonth}/${paddedDay}/${String(date.year)}`;
58
+ };
59
+
60
+ /**
61
+ * Format an array of DateValues to a unified string
62
+ * Single: "12/25/2024"
63
+ * Range: "12/01/2024 - 12/31/2024"
64
+ */
65
+ export const formatDateInputValue = (value: DateValue[], range: boolean): string => {
66
+ if (value.length === 0) {
67
+ return '';
68
+ }
69
+ const newValue = value.map(formatDateValue);
70
+
71
+ return range ? newValue.join(' - ') : newValue[0];
72
+ };
73
+
74
+ /**
75
+ * Parse a date string (MM/DD/YYYY) to DateValue
76
+ */
77
+ const parseDateString = (dateStr: string): DateValue | null => {
78
+ if (!dateStr || !dateStr.trim()) {
79
+ return null;
80
+ }
81
+
82
+ // Try MM/DD/YYYY format
83
+ const match = dateStr.trim().match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/);
84
+ if (!match) {
85
+ return null;
86
+ }
87
+
88
+ const [, month, day, year] = match;
89
+ const monthNum = parseInt(month, 10);
90
+ const dayNum = parseInt(day, 10);
91
+ const yearNum = parseInt(year, 10);
92
+
93
+ // Use native Date for proper validation (handles leap years, month lengths, etc.)
94
+ // Note: Date months are 0-indexed, so subtract 1
95
+ const date = new Date(yearNum, monthNum - 1, dayNum);
96
+
97
+ // Check if the date is valid and matches what we parsed
98
+ // (e.g., 02/31/2024 would roll over to 03/02/2024, so we detect that)
99
+ if (date.getFullYear() !== yearNum || date.getMonth() !== monthNum - 1 || date.getDate() !== dayNum) {
100
+ return null;
101
+ }
102
+
103
+ return new CalendarDate(yearNum, monthNum, dayNum) as unknown as DateValue;
104
+ };
105
+
106
+ /**
107
+ * Parse a range input string (MM/DD/YYYY - MM/DD/YYYY)
108
+ */
109
+ const parseRangeInput = (text: string): ParsedDateRange => {
110
+ if (!text.trim()) {
111
+ return { start: null, end: null, isValid: true }; // Empty is valid
112
+ }
113
+
114
+ // Check if it contains a dash separator
115
+ if (!text.includes('-')) {
116
+ // Single date format, treat as incomplete range
117
+ const date = parseDateString(text.trim());
118
+ return {
119
+ start: date ? formatDateValue(date) : null,
120
+ end: null,
121
+ isValid: false, // Incomplete range
122
+ };
123
+ }
124
+
125
+ // Split by dash
126
+ const parts = text.split('-').map((p) => p.trim());
127
+ if (parts.length !== 2) {
128
+ return { start: null, end: null, isValid: false };
129
+ }
130
+
131
+ const [startStr, endStr] = parts;
132
+ const startDate = parseDateString(startStr);
133
+ const endDate = parseDateString(endStr);
134
+
135
+ // Both must be valid dates
136
+ if (!startDate || !endDate) {
137
+ return {
138
+ start: startDate ? formatDateValue(startDate) : null,
139
+ end: endDate ? formatDateValue(endDate) : null,
140
+ isValid: false,
141
+ };
142
+ }
143
+
144
+ return {
145
+ start: formatDateValue(startDate),
146
+ end: formatDateValue(endDate),
147
+ isValid: true,
148
+ };
149
+ };
150
+
151
+ /**
152
+ * Parse input text based on range flag
153
+ */
154
+ export const parseInputText = (text: string, range: boolean): DateValue[] => {
155
+ if (!range) {
156
+ const date = parseDateString(text);
157
+ return date ? [date] : [];
158
+ }
159
+
160
+ // Range mode
161
+ const parsed = parseRangeInput(text);
162
+ if (!parsed.isValid || !parsed.start || !parsed.end) {
163
+ return [];
164
+ }
165
+
166
+ const startDate = parseDateString(parsed.start);
167
+ const endDate = parseDateString(parsed.end);
168
+
169
+ if (!startDate || !endDate) {
170
+ return [];
171
+ }
172
+
173
+ return [startDate, endDate];
174
+ };
175
+
176
+ /**
177
+ * Validate date input
178
+ */
179
+ export const validateDateString = ({
180
+ text,
181
+ range,
182
+ min,
183
+ max,
184
+ }: {
185
+ text: string;
186
+ range: boolean;
187
+ min?: DateValue;
188
+ max?: DateValue;
189
+ }): DateInputValidation => {
190
+ if (!text.trim()) {
191
+ return { isValid: true }; // Empty is valid (let required validation handle it)
192
+ }
193
+
194
+ if (!range) {
195
+ const date = parseDateString(text);
196
+ if (!date) {
197
+ return { isValid: false, error: 'Invalid date format. Use MM/DD/YYYY' };
198
+ }
199
+
200
+ // Check min/max
201
+ if (min && date.compare(min) < 0) {
202
+ return { isValid: false, error: 'Date is before minimum allowed date' };
203
+ }
204
+ if (max && date.compare(max) > 0) {
205
+ return { isValid: false, error: 'Date is after maximum allowed date' };
206
+ }
207
+
208
+ return { isValid: true };
209
+ }
210
+
211
+ // Range mode validation
212
+ const parsed = parseRangeInput(text);
213
+ if (!parsed.isValid) {
214
+ return { isValid: false, error: 'Invalid date range format. Use MM/DD/YYYY - MM/DD/YYYY' };
215
+ }
216
+
217
+ if (!parsed.start || !parsed.end) {
218
+ return { isValid: false, error: 'Both start and end dates are required' };
219
+ }
220
+
221
+ const startDate = parseDateString(parsed.start);
222
+ const endDate = parseDateString(parsed.end);
223
+
224
+ if (!startDate || !endDate) {
225
+ return { isValid: false, error: 'Invalid date format. Use MM/DD/YYYY' };
226
+ }
227
+
228
+ // Validate start <= end
229
+ if (startDate.compare(endDate) > 0) {
230
+ return { isValid: false, error: 'Start date must be before or equal to end date' };
231
+ }
232
+
233
+ // Check min/max
234
+ if (min && startDate.compare(min) < 0) {
235
+ return { isValid: false, error: 'Start date is before minimum allowed date' };
236
+ }
237
+ if (max && endDate.compare(max) > 0) {
238
+ return { isValid: false, error: 'End date is after maximum allowed date' };
239
+ }
240
+
241
+ return { isValid: true };
242
+ };
@@ -0,0 +1,2 @@
1
+ export { default as DsDateInput } from './ds-date-input';
2
+ export type { DsDateInputProps } from './ds-date-input.types';
@@ -0,0 +1,21 @@
1
+ .divider {
2
+ display: block;
3
+
4
+ border: 0;
5
+ padding: 0;
6
+ color: transparent;
7
+
8
+ background-color: var(--color-border-secondary);
9
+ flex-shrink: 0;
10
+ }
11
+
12
+ .horizontal {
13
+ width: 100%;
14
+ height: 1px;
15
+ }
16
+
17
+ .vertical {
18
+ width: 1px;
19
+ height: auto;
20
+ align-self: stretch;
21
+ }
@@ -0,0 +1,22 @@
1
+ import type React from 'react';
2
+ import classNames from 'classnames';
3
+ import styles from './ds-divider.module.scss';
4
+ import { type DsDividerProps } from './ds-divider.types';
5
+
6
+ const DsDivider: React.FC<DsDividerProps> = ({ orientation = 'horizontal', component, style, className }) => {
7
+ const isVertical = orientation === 'vertical';
8
+ const Component = component ?? (isVertical ? 'div' : 'hr');
9
+
10
+ const classes = classNames(
11
+ styles.divider,
12
+ {
13
+ [styles.vertical]: isVertical,
14
+ [styles.horizontal]: !isVertical,
15
+ },
16
+ className,
17
+ );
18
+
19
+ return <Component role="separator" aria-orientation={orientation} className={classes} style={style} />;
20
+ };
21
+
22
+ export default DsDivider;
@@ -0,0 +1,21 @@
1
+ import type React from 'react';
2
+
3
+ export interface DsDividerProps {
4
+ /**
5
+ * Controls orientation of the divider. Horizontal by default.
6
+ */
7
+ orientation?: 'horizontal' | 'vertical';
8
+ /**
9
+ * Underlying element/component to render.
10
+ * Examples: "hr", "div", "span", Link, etc.
11
+ */
12
+ component?: React.ElementType;
13
+ /**
14
+ * Additional CSS styles.
15
+ */
16
+ style?: React.CSSProperties;
17
+ /**
18
+ * Additional CSS classes.
19
+ */
20
+ className?: string;
21
+ }
@@ -0,0 +1,2 @@
1
+ export { default as DsDivider } from './ds-divider';
2
+ export * from './ds-divider.types';
@@ -8,6 +8,7 @@
8
8
  max-height: var(--available-height, 400px);
9
9
  overflow-y: auto;
10
10
  width: auto;
11
+ z-index: var(--layer-index);
11
12
 
12
13
  &:focus-visible {
13
14
  outline-offset: 2px;
@@ -29,9 +30,12 @@
29
30
 
30
31
  .item {
31
32
  @include dropdown.dropdown-item;
32
- display: flex;
33
- align-items: center;
34
- gap: var(--spacing-xs);
33
+
34
+ .triggerItem {
35
+ display: flex;
36
+ align-items: center;
37
+ gap: var(--spacing-xs);
38
+ }
35
39
 
36
40
  &.selected {
37
41
  .indicator {
@@ -105,6 +109,10 @@
105
109
  }
106
110
  }
107
111
 
112
+ .triggerItemIcon {
113
+ margin-left: auto;
114
+ }
115
+
108
116
  /** Legacy classes */
109
117
  .contentLegacy {
110
118
  @include dropdown.dropdown-content;
@@ -21,6 +21,7 @@ import type {
21
21
  DsDropdownMenuPositioning,
22
22
  DsDropdownMenuRootProps,
23
23
  DsDropdownMenuSeparatorProps,
24
+ DsDropdownMenuTriggerItemProps,
24
25
  DsDropdownMenuTriggerProps,
25
26
  } from './ds-dropdown-menu.types';
26
27
 
@@ -195,7 +196,7 @@ const ItemGroup: React.FC<DsDropdownMenuItemGroupProps> = ({
195
196
 
196
197
  return (
197
198
  <GroupContext.Provider value={{ collapsed, toggle }}>
198
- <Menu.ItemGroup className={classNames(styles.group, className)} style={style}>
199
+ <Menu.ItemGroup className={className} style={style}>
199
200
  {children}
200
201
  </Menu.ItemGroup>
201
202
  </GroupContext.Provider>
@@ -264,6 +265,20 @@ const Separator: React.FC<DsDropdownMenuSeparatorProps> = ({ className, style })
264
265
  return <Menu.Separator className={classNames(styles.separator, className)} style={style} />;
265
266
  };
266
267
 
268
+ /**
269
+ * TriggerItem component - triggers a nested submenu
270
+ */
271
+ const TriggerItem: React.FC<DsDropdownMenuTriggerItemProps> = ({ className, style, children, ...props }) => {
272
+ return (
273
+ <Menu.TriggerItem className={styles.item} {...props}>
274
+ <div className={classNames(styles.triggerItem, className)} style={style}>
275
+ {children}
276
+ </div>
277
+ <DsIcon className={styles.triggerItemIcon} icon="keyboard_arrow_right" />
278
+ </Menu.TriggerItem>
279
+ );
280
+ };
281
+
267
282
  /**
268
283
  * DEPRECATED: Legacy DsDropdownMenu component with options array
269
284
  * Use compound component pattern instead
@@ -387,6 +402,7 @@ export const DsDropdownMenu = {
387
402
  Content,
388
403
  Item,
389
404
  ItemIndicator,
405
+ TriggerItem,
390
406
  Header,
391
407
  Actions,
392
408
  ItemGroup,
@@ -260,3 +260,8 @@ export interface DsDropdownMenuItemGroupContentProps {
260
260
  * Props for the DsDropdownMenu Separator component
261
261
  */
262
262
  export type DsDropdownMenuSeparatorProps = Menu.SeparatorProps;
263
+
264
+ /**
265
+ * Props for the DsDropdownMenu TriggerItem component (for nested submenus)
266
+ */
267
+ export type DsDropdownMenuTriggerItemProps = Menu.TriggerItemProps;
@@ -9,6 +9,7 @@ import { DsNumberInput } from '../ds-number-input';
9
9
  import { DsPasswordInput } from '../ds-password-input';
10
10
  import type { DsFormControlDescriptionProps, DsFormControlProps } from './ds-form-control.types';
11
11
  import styles from './ds-form-control.module.scss';
12
+ import { DsDateInput } from '../ds-date-input';
12
13
 
13
14
  const FormControlContext = createContext<{ controlId: string } | null>(null);
14
15
 
@@ -87,6 +88,7 @@ const DsFormControl = ({
87
88
  DsFormControl.TextInput = controlify(DsTextInput);
88
89
  DsFormControl.NumberInput = controlify(DsNumberInput);
89
90
  DsFormControl.PasswordInput = controlify(DsPasswordInput);
91
+ DsFormControl.DateInput = controlify(DsDateInput);
90
92
  DsFormControl.Textarea = controlify(DsTextarea);
91
93
  DsFormControl.Select = controlify(DsSelect);
92
94
  DsFormControl.Description = DsFormControlDescription;
@@ -7,7 +7,7 @@ import { type RadioGroupItemProps, type RadioGroupRootProps } from '@ark-ui/reac
7
7
  */
8
8
  export interface DsRadioGroupRootProps extends Pick<
9
9
  RadioGroupRootProps,
10
- 'value' | 'defaultValue' | 'disabled' | 'name' | 'className' | 'style' | 'orientation' | 'children'
10
+ 'id' | 'value' | 'defaultValue' | 'disabled' | 'name' | 'className' | 'style' | 'orientation' | 'children'
11
11
  > {
12
12
  /**
13
13
  * Event handler called when the selected value changes
@@ -0,0 +1,99 @@
1
+ .segmentGroupRoot {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ position: relative;
5
+ background: var(--color-background-secondary);
6
+ border: 1px solid var(--color-border-contrast);
7
+ border-radius: 4px;
8
+ gap: var(--spacing-2xs);
9
+ height: 36px;
10
+ padding: var(--spacing-3xs);
11
+
12
+ &.small {
13
+ height: 28px;
14
+ padding: var(--spacing-4xs);
15
+
16
+ .segmentItem {
17
+ padding: var(--spacing-4xs) var(--spacing-xs);
18
+ }
19
+ }
20
+ }
21
+
22
+ .segmentItem {
23
+ position: relative;
24
+ display: flex;
25
+ align-items: center;
26
+ justify-content: center;
27
+ padding: var(--spacing-3xs) var(--spacing-sm);
28
+ gap: var(--spacing-2xs);
29
+ flex: 1;
30
+ z-index: 1;
31
+ cursor: pointer;
32
+ border-radius: 4px;
33
+
34
+ &[data-state='checked'] {
35
+ .segmentItemText {
36
+ color: var(--color-font-main);
37
+ font-weight: var(--font-weight-medium);
38
+ }
39
+ }
40
+
41
+ &[data-state='unchecked'] {
42
+ background: transparent;
43
+
44
+ .segmentItemText {
45
+ color: var(--color-background-action);
46
+ }
47
+
48
+ &:hover:not([data-disabled]) {
49
+ background: var(--color-background-action-secondary);
50
+ }
51
+
52
+ &:active:not([data-disabled]) {
53
+ background: var(--color-background);
54
+ border-color: var(--color-border-contrast);
55
+ }
56
+ }
57
+
58
+ &[data-disabled] {
59
+ cursor: not-allowed;
60
+ background: var(--color-background-secondary);
61
+
62
+ .segmentItemText {
63
+ color: var(--color-font-disabled);
64
+ }
65
+ }
66
+
67
+ &:focus-visible {
68
+ outline: 2px solid var(--color-border-action-secondary);
69
+ outline-offset: 2px;
70
+ }
71
+ }
72
+
73
+ [data-scope='segment-group'][data-part='item-control'] {
74
+ position: absolute;
75
+ inset: 0;
76
+ pointer-events: none;
77
+ }
78
+
79
+ .segmentItemText {
80
+ display: flex;
81
+ align-items: center;
82
+ justify-content: center;
83
+ white-space: nowrap;
84
+ transition: color 150ms ease-in-out;
85
+ }
86
+
87
+ .segmentIndicator {
88
+ position: absolute;
89
+ background: var(--color-background);
90
+ border: 1px solid var(--color-border-contrast);
91
+ border-radius: 4px;
92
+ box-shadow: 0 1.25px 4px 0 rgba(0, 0, 0, 0.25);
93
+ z-index: 0;
94
+ pointer-events: none;
95
+ width: var(--width);
96
+ height: var(--height);
97
+ left: var(--left);
98
+ top: var(--top);
99
+ }
@@ -0,0 +1,76 @@
1
+ import type React from 'react';
2
+ import { SegmentGroup } from '@ark-ui/react/segment-group';
3
+ import classNames from 'classnames';
4
+ import styles from './ds-segment-group.module.scss';
5
+ import DsTypography from '../ds-typography/ds-typography';
6
+ import {
7
+ type DsSegmentGroupItemProps,
8
+ type DsSegmentGroupItemTextProps,
9
+ type DsSegmentGroupRootProps,
10
+ } from './ds-segment-group.types';
11
+
12
+ /**
13
+ * Root component - provides segment group context
14
+ */
15
+ const Root: React.FC<DsSegmentGroupRootProps> = ({
16
+ className,
17
+ children,
18
+ onValueChange,
19
+ size = 'default',
20
+ ...props
21
+ }) => (
22
+ <SegmentGroup.Root
23
+ className={classNames(styles.segmentGroupRoot, size === 'small' && styles.small, className)}
24
+ onValueChange={(details) => onValueChange?.(details.value)}
25
+ {...props}
26
+ >
27
+ <SegmentGroup.Indicator className={styles.segmentIndicator} />
28
+ {children}
29
+ </SegmentGroup.Root>
30
+ );
31
+
32
+ /**
33
+ * Item component - renders a single segment button
34
+ */
35
+ const Item: React.FC<DsSegmentGroupItemProps> = ({ value, label, className, style, children, ...props }) => {
36
+ return (
37
+ <SegmentGroup.Item
38
+ value={value}
39
+ className={classNames(styles.segmentItem, className)}
40
+ style={style}
41
+ {...props}
42
+ >
43
+ {label ? <ItemText>{label}</ItemText> : children}
44
+ <SegmentGroup.ItemControl />
45
+ <SegmentGroup.ItemHiddenInput />
46
+ </SegmentGroup.Item>
47
+ );
48
+ };
49
+
50
+ /**
51
+ * ItemText component - renders text content within an item
52
+ */
53
+ const ItemText: React.FC<DsSegmentGroupItemTextProps> = ({ className, children, ...props }) => (
54
+ <SegmentGroup.ItemText className={classNames(styles.segmentItemText, className)} {...props} asChild>
55
+ <DsTypography variant="body-sm-reg">{children}</DsTypography>
56
+ </SegmentGroup.ItemText>
57
+ );
58
+
59
+ /**
60
+ * Design system SegmentGroup component
61
+ *
62
+ * @example
63
+ * <DsSegmentGroup.Root value={value} onValueChange={setValue} size="default">
64
+ * <DsSegmentGroup.Indicator />
65
+ * <DsSegmentGroup.Item value="option1" label="Option 1" />
66
+ * <DsSegmentGroup.Item value="option2">
67
+ * <DsIcon icon="settings" />
68
+ * <DsSegmentGroup.ItemText>Option 2</DsSegmentGroup.ItemText>
69
+ * </DsSegmentGroup.Item>
70
+ * </DsSegmentGroup.Root>
71
+ */
72
+ export const DsSegmentGroup = {
73
+ Root,
74
+ Item,
75
+ ItemText,
76
+ };
@@ -0,0 +1,64 @@
1
+ import { type ReactNode } from 'react';
2
+ import {
3
+ type SegmentGroupItemProps,
4
+ type SegmentGroupItemTextProps,
5
+ type SegmentGroupRootProps,
6
+ } from '@ark-ui/react/segment-group';
7
+
8
+ /**
9
+ * Size variants for the segment group
10
+ */
11
+ export type DsSegmentGroupSize = 'small' | 'default';
12
+
13
+ /**
14
+ * Props for the DsSegmentGroup Root component
15
+ */
16
+ export interface DsSegmentGroupRootProps extends Pick<
17
+ SegmentGroupRootProps,
18
+ 'value' | 'defaultValue' | 'disabled' | 'name' | 'className' | 'style' | 'children'
19
+ > {
20
+ /**
21
+ * Size variant of the segment group
22
+ * @default 'default'
23
+ */
24
+ size?: DsSegmentGroupSize;
25
+ /**
26
+ * Event handler called when the selected value changes
27
+ */
28
+ onValueChange?: (value: string | null) => void;
29
+ }
30
+
31
+ /**
32
+ * Props for the DsSegmentGroup Item component
33
+ */
34
+ export type DsSegmentGroupItemProps = Pick<
35
+ SegmentGroupItemProps,
36
+ 'id' | 'value' | 'disabled' | 'className' | 'style'
37
+ > &
38
+ (
39
+ | {
40
+ /**
41
+ * The segment group item content
42
+ */
43
+ children: ReactNode;
44
+ /**
45
+ * Optional label text for the segment item
46
+ */
47
+ label?: never;
48
+ }
49
+ | {
50
+ /**
51
+ * The segment group item content
52
+ */
53
+ children?: never;
54
+ /**
55
+ * Optional label text for the segment item
56
+ */
57
+ label: string;
58
+ }
59
+ );
60
+
61
+ /**
62
+ * Props for the DsSegmentGroup ItemText component
63
+ */
64
+ export type DsSegmentGroupItemTextProps = Pick<SegmentGroupItemTextProps, 'className' | 'style' | 'children'>;
@@ -0,0 +1,2 @@
1
+ export { DsSegmentGroup } from './ds-segment-group';
2
+ export * from './ds-segment-group.types';
@@ -1 +1,2 @@
1
+ export { useTableFilters } from './use-table-filters';
1
2
  export type { UseTableFiltersResult } from './use-table-filters';
@@ -1,4 +1,6 @@
1
1
  export type { SecondaryRowAction, RowAction } from './components/ds-table-cell';
2
2
 
3
+ export * from './filters';
4
+
3
5
  export { default as DsTable } from './ds-table';
4
6
  export * from './ds-table.types';