@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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drivenets/design-system",
3
- "version": "0.0.4",
3
+ "version": "0.1.0",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "types": "./dist/index.d.cts",
@@ -57,6 +57,7 @@
57
57
  "classnames": "^2.5.1"
58
58
  },
59
59
  "peerDependencies": {
60
+ "@internationalized/date": "^3.0.0",
60
61
  "react": "^19"
61
62
  },
62
63
  "devDependencies": {
@@ -97,7 +98,7 @@
97
98
  "vite": "^7.3.0",
98
99
  "vitest": "^4.0.16",
99
100
  "zod": "^3.24.2",
100
- "@drivenets/vite-plugin-design-system": "0.0.3"
101
+ "@drivenets/vite-plugin-design-system": "0.0.4"
101
102
  },
102
103
  "scripts": {
103
104
  "lint": "eslint --max-warnings=0 .",
@@ -15,7 +15,6 @@ $button-size-large: 40px;
15
15
  outline: none;
16
16
  padding-block: 0;
17
17
  padding-inline: 0;
18
- align-self: stretch;
19
18
  border: 2px solid transparent;
20
19
  border-radius: var(--exo-spacing-2x-small);
21
20
 
@@ -0,0 +1,246 @@
1
+ @use '../../styles/shared/input';
2
+ @use '../../styles/shared/dropdown';
3
+
4
+ .dateInputControl {
5
+ @include input.base-input-container;
6
+ @include input.input-container-states;
7
+ max-height: input.$input-text-height-default;
8
+ justify-content: space-between;
9
+ padding: var(--spacing-xs) var(--spacing-sm);
10
+ gap: var(--spacing-3xs);
11
+
12
+ border-color: var(--form-control-border-color, var(--color-border));
13
+
14
+ &:hover:not(.disabled) {
15
+ border-color: var(--form-control-border-color, var(--color-border-hover));
16
+ }
17
+
18
+ &:focus-within {
19
+ border-color: var(--form-control-border-color, var(--color-border-action));
20
+ }
21
+
22
+ &.disabled {
23
+ color: var(--color-background-deselected);
24
+ background: var(--color-background-secondary);
25
+ border-color: var(--color-border-disabled);
26
+ cursor: not-allowed;
27
+
28
+ .input {
29
+ color: var(--color-font-disabled);
30
+ }
31
+
32
+ .dateInputButton {
33
+ color: var(--color-background-disable);
34
+ cursor: not-allowed;
35
+ }
36
+ }
37
+
38
+ &.readOnly {
39
+ background: var(--color-background-secondary);
40
+ cursor: default;
41
+ }
42
+ }
43
+
44
+ .input {
45
+ @include input.base-input;
46
+ min-width: 0;
47
+ flex: 1;
48
+ padding: 0;
49
+ }
50
+
51
+ .dateInputButton {
52
+ @include input.icon-button;
53
+ display: flex;
54
+ align-items: center;
55
+ cursor: pointer;
56
+ padding: 0;
57
+ transition: color 0.2s ease;
58
+
59
+ &:hover:not(:disabled) {
60
+ color: var(--color-background-action-hover);
61
+ }
62
+
63
+ &:disabled {
64
+ color: var(--color-background-disable);
65
+ cursor: not-allowed;
66
+ }
67
+ }
68
+
69
+ .positioner {
70
+ @include dropdown.dropdown-viewport;
71
+ }
72
+
73
+ .content {
74
+ @include dropdown.dropdown-content;
75
+ padding: var(--spacing-standard);
76
+ }
77
+
78
+ .viewControl {
79
+ display: flex;
80
+ justify-content: space-between;
81
+ align-items: center;
82
+ margin-bottom: var(--spacing-xs);
83
+ }
84
+
85
+ .viewTrigger {
86
+ flex: 1;
87
+ display: flex;
88
+ align-items: center;
89
+ justify-content: center;
90
+ background: transparent;
91
+ border: none;
92
+ cursor: pointer;
93
+ padding: var(--spacing-2xs) var(--spacing-xs);
94
+ border-radius: var(--spacing-2xs);
95
+ color: var(--color-font-main);
96
+ transition: background-color 0.2s;
97
+
98
+ &:hover {
99
+ background: var(--color-background-hover);
100
+ }
101
+ }
102
+
103
+ .prevTrigger,
104
+ .nextTrigger {
105
+ display: flex;
106
+ align-items: center;
107
+ justify-content: center;
108
+ background: transparent;
109
+ border: none;
110
+ cursor: pointer;
111
+ padding: var(--spacing-2xs);
112
+ border-radius: var(--spacing-2xs);
113
+ color: var(--color-font-secondary);
114
+ transition: all 0.2s;
115
+
116
+ &:hover {
117
+ background: var(--color-background-hover);
118
+ color: var(--color-font-main);
119
+ }
120
+
121
+ &:disabled {
122
+ cursor: not-allowed;
123
+ opacity: 0.5;
124
+ }
125
+ }
126
+
127
+ .calendarView {
128
+ display: flex;
129
+ flex-direction: column;
130
+ gap: var(--spacing-xs);
131
+ }
132
+
133
+ .table {
134
+ width: 100%;
135
+ border-collapse: collapse;
136
+
137
+ .tableBody .tableRow .tableCellTrigger:focus-visible {
138
+ .tableCellTriggerValue {
139
+ outline: 2px solid var(--color-background-action-hover);
140
+ border-radius: var(--spacing-2xs);
141
+ border-width: 0;
142
+ }
143
+ }
144
+ }
145
+
146
+ .tableHead {
147
+ border-bottom: 1px solid var(--color-border);
148
+ }
149
+
150
+ .tableHeader {
151
+ text-align: center;
152
+ padding: var(--spacing-2xs);
153
+ color: var(--color-font-secondary);
154
+ font-weight: var(--font-weight-medium);
155
+ }
156
+
157
+ .tableRow {
158
+ &:first-child {
159
+ .tableCellTrigger {
160
+ margin-top: var(--spacing-xs);
161
+ }
162
+ }
163
+ }
164
+
165
+ .tableCellTrigger {
166
+ display: flex;
167
+ align-items: center;
168
+ justify-content: center;
169
+ cursor: pointer;
170
+ user-select: none;
171
+ -webkit-tap-highlight-color: transparent;
172
+ outline: none;
173
+
174
+ .tableCellTriggerValue {
175
+ display: flex;
176
+ align-items: center;
177
+ justify-content: center;
178
+ width: var(--spacing-xl);
179
+ height: var(--spacing-xl);
180
+ margin: var(--spacing-3xs);
181
+ color: var(--color-font-main);
182
+ border-radius: var(--spacing-xs);
183
+ }
184
+
185
+ &:hover:not([data-disabled], [data-selected], [data-in-range], [data-in-hover-range])
186
+ .tableCellTriggerValue {
187
+ outline: 1px solid var(--color-border);
188
+ background: var(--color-background-action-hover-weak);
189
+ }
190
+
191
+ &[data-outside-range] .tableCellTriggerValue {
192
+ color: var(--color-font-disabled);
193
+ }
194
+
195
+ &[data-selected] .tableCellTriggerValue {
196
+ background: var(--color-background-selected);
197
+ color: var(--color-font-on-action);
198
+ }
199
+
200
+ &[data-in-range]:not([data-selected]) {
201
+ position: relative;
202
+
203
+ .tableCellTriggerValue {
204
+ background: var(--color-background-action-secondary-hover);
205
+ }
206
+ }
207
+
208
+ &[data-today]:not([data-selected], [data-in-range]):hover .tableCellTriggerValue {
209
+ border-radius: var(--spacing-xs);
210
+ }
211
+
212
+ &[data-today]:not([data-selected]) .tableCellTriggerValue {
213
+ position: relative;
214
+
215
+ &::after {
216
+ content: '';
217
+ position: absolute;
218
+ width: 75%;
219
+ bottom: 4px;
220
+ border-bottom: 1px solid var(--color-background-brand);
221
+ }
222
+ }
223
+
224
+ &[data-today][data-selected] .tableCellTriggerValue {
225
+ position: relative;
226
+
227
+ &::after {
228
+ content: '';
229
+ position: absolute;
230
+ width: 75%;
231
+ bottom: 4px;
232
+ border-bottom: 1px solid var(--color-background);
233
+ }
234
+ }
235
+
236
+ &[data-disabled] .tableCellTriggerValue {
237
+ color: var(--color-font-disabled);
238
+ cursor: not-allowed;
239
+ opacity: 0.5;
240
+ }
241
+
242
+ &[data-unavailable] .tableCellTriggerValue {
243
+ text-decoration: line-through;
244
+ opacity: 0.4;
245
+ }
246
+ }
@@ -0,0 +1,309 @@
1
+ import { type ChangeEvent, Fragment, useRef, useState } from 'react';
2
+ import { DatePicker } from '@ark-ui/react/date-picker';
3
+ import { Portal } from '@ark-ui/react/portal';
4
+ import classNames from 'classnames';
5
+ import type { DsDateInputProps } from './ds-date-input.types';
6
+ import {
7
+ dateValuesToStrings,
8
+ formatDateInputValue,
9
+ isoStringToDateValue,
10
+ parseInputText,
11
+ stringToDateValue,
12
+ validateDateString,
13
+ } from './ds-date-input.utils';
14
+ import { DsIcon } from '../ds-icon';
15
+ import { DsTypography } from '../ds-typography';
16
+ import styles from './ds-date-input.module.scss';
17
+
18
+ /**
19
+ * Design system date input component with integrated calendar picker.
20
+ *
21
+ * Supports both single date and date range selection with a single text input field.
22
+ * Features built-in validation, manual text entry, and calendar selection.
23
+ */
24
+ const DsDateInput = ({
25
+ range = false,
26
+ placeholder,
27
+ style,
28
+ className,
29
+ disablePortal = false,
30
+ onValueChange,
31
+ onOpenChange,
32
+ value: _value,
33
+ defaultValue: _defaultValue,
34
+ min: _min,
35
+ max: _max,
36
+ disabled,
37
+ readOnly,
38
+ id,
39
+ ...datePickerProps
40
+ }: DsDateInputProps) => {
41
+ const min = _min ? isoStringToDateValue(_min) : undefined;
42
+ const max = _max ? isoStringToDateValue(_max) : undefined;
43
+
44
+ // Convert public API (string | [string, string]) to internal API (DateValue[])
45
+ const value = _value ? stringToDateValue(_value) : [];
46
+ const defaultValue = _defaultValue ? stringToDateValue(_defaultValue) : [];
47
+
48
+ // Local state for manual text editing
49
+ const [isFocused, setIsFocused] = useState(false);
50
+ const [isOpen, setIsOpen] = useState(false);
51
+
52
+ const prevValue = useRef<string | null>(null);
53
+ const inputRef = useRef<HTMLInputElement>(null);
54
+
55
+ // Reformat the input value on every value change
56
+ // We don't format when the input is focused since the date value might get updated while the user is typing
57
+ // but we don't want to reformat the input text for him while he's typing.
58
+ if (!isFocused && prevValue.current !== JSON.stringify(value)) {
59
+ prevValue.current = JSON.stringify(value);
60
+
61
+ if (inputRef.current) {
62
+ inputRef.current.value = formatDateInputValue(value, range);
63
+ }
64
+ }
65
+
66
+ const clear = () => {
67
+ if (inputRef.current) {
68
+ inputRef.current.value = '';
69
+ }
70
+
71
+ onValueChange?.(undefined);
72
+ };
73
+
74
+ const handleInputChange = (e: ChangeEvent<HTMLInputElement>) => {
75
+ const text = e.target.value;
76
+
77
+ // Try to parse and validate as the user types
78
+ const validation = validateDateString({ text, range, min, max });
79
+
80
+ if (validation.isValid) {
81
+ const parsedValue = parseInputText(text, range);
82
+ onValueChange?.(dateValuesToStrings(parsedValue, range) as never);
83
+ }
84
+ };
85
+
86
+ const handleBlur = () => {
87
+ setIsFocused(false);
88
+
89
+ const text = inputRef.current?.value || '';
90
+ const validation = validateDateString({ text, range, min, max });
91
+
92
+ // Clear invalid input on blur
93
+ if (!validation.isValid) {
94
+ clear();
95
+ return;
96
+ }
97
+
98
+ const parsedValue = parseInputText(text, range);
99
+
100
+ onValueChange?.(dateValuesToStrings(parsedValue, range) as never);
101
+ };
102
+
103
+ const showClearButton = !disabled && !readOnly && !!(value.length > 0 ? value : defaultValue).length;
104
+ const Wrapper = disablePortal ? Fragment : Portal;
105
+
106
+ return (
107
+ <DatePicker.Root
108
+ value={value}
109
+ defaultValue={defaultValue}
110
+ onValueChange={(details) => {
111
+ onValueChange?.(dateValuesToStrings(details.value, range) as never);
112
+ }}
113
+ selectionMode={range ? 'range' : 'single'}
114
+ positioning={{ placement: 'bottom-start', gutter: 4 }}
115
+ closeOnSelect={!range}
116
+ min={min}
117
+ max={max}
118
+ disabled={disabled}
119
+ readOnly={readOnly}
120
+ open={isOpen}
121
+ onOpenChange={(details) => {
122
+ // Don't close the calendar when the user is typing
123
+ if (!isFocused) {
124
+ setIsOpen(details.open);
125
+ onOpenChange?.(details.open);
126
+ }
127
+ }}
128
+ {...datePickerProps}
129
+ >
130
+ <DatePicker.Control
131
+ style={style}
132
+ className={classNames(
133
+ styles.dateInputControl,
134
+ disabled && styles.disabled,
135
+ readOnly && styles.readOnly,
136
+ className,
137
+ )}
138
+ >
139
+ <DatePicker.Trigger asChild>
140
+ <button
141
+ type="button"
142
+ className={styles.dateInputButton}
143
+ disabled={disabled}
144
+ aria-label="Open calendar"
145
+ >
146
+ <DsIcon icon="calendar_month" size="small" />
147
+ </button>
148
+ </DatePicker.Trigger>
149
+
150
+ <input
151
+ ref={inputRef}
152
+ id={id}
153
+ type="text"
154
+ className={styles.input}
155
+ placeholder={placeholder ?? (range ? 'MM/DD/YYYY - MM/DD/YYYY' : 'MM/DD/YYYY')}
156
+ defaultValue={formatDateInputValue(value.length > 0 ? value : defaultValue, range)}
157
+ onChange={handleInputChange}
158
+ onBlur={handleBlur}
159
+ onFocus={() => setIsFocused(true)}
160
+ disabled={disabled}
161
+ readOnly={readOnly}
162
+ />
163
+
164
+ {showClearButton && (
165
+ <button
166
+ type="button"
167
+ className={styles.dateInputButton}
168
+ onClick={clear}
169
+ aria-label={range ? 'Clear date range' : 'Clear date'}
170
+ >
171
+ <DsIcon icon="close" size="small" />
172
+ </button>
173
+ )}
174
+ </DatePicker.Control>
175
+
176
+ <Wrapper>
177
+ <DatePicker.Positioner className={styles.positioner}>
178
+ <DatePicker.Content className={styles.content}>
179
+ <CalendarViewControl />
180
+ <div className={styles.calendarView}>
181
+ <DayView />
182
+ <MonthView />
183
+ <YearView />
184
+ </div>
185
+ </DatePicker.Content>
186
+ </DatePicker.Positioner>
187
+ </Wrapper>
188
+ </DatePicker.Root>
189
+ );
190
+ };
191
+
192
+ /**
193
+ * Calendar view control with navigation buttons
194
+ */
195
+ const CalendarViewControl = () => (
196
+ <DatePicker.ViewControl className={styles.viewControl}>
197
+ <DatePicker.PrevTrigger className={styles.prevTrigger}>
198
+ <DsIcon icon="chevron_left" size="small" />
199
+ </DatePicker.PrevTrigger>
200
+ <DatePicker.ViewTrigger className={styles.viewTrigger} asChild>
201
+ <button type="button">
202
+ <DsTypography variant="body-md-md" asChild>
203
+ <DatePicker.RangeText />
204
+ </DsTypography>
205
+ </button>
206
+ </DatePicker.ViewTrigger>
207
+ <DatePicker.NextTrigger className={styles.nextTrigger}>
208
+ <DsIcon icon="chevron_right" size="small" />
209
+ </DatePicker.NextTrigger>
210
+ </DatePicker.ViewControl>
211
+ );
212
+
213
+ /**
214
+ * Day view - displays calendar grid with days of the month
215
+ */
216
+ const DayView = () => (
217
+ <DatePicker.View view="day">
218
+ <DatePicker.Context>
219
+ {(datePicker) => (
220
+ <DatePicker.Table className={styles.table}>
221
+ <DatePicker.TableHead className={styles.tableHead}>
222
+ <DatePicker.TableRow className={styles.tableRow}>
223
+ {datePicker.weekDays.map((weekDay, id) => (
224
+ <DatePicker.TableHeader key={id} className={styles.tableHeader}>
225
+ <DsTypography variant="body-md-md">{weekDay.short}</DsTypography>
226
+ </DatePicker.TableHeader>
227
+ ))}
228
+ </DatePicker.TableRow>
229
+ </DatePicker.TableHead>
230
+ <DatePicker.TableBody className={styles.tableBody}>
231
+ {datePicker.weeks.map((week, weekId) => (
232
+ <DatePicker.TableRow key={weekId} className={styles.tableRow}>
233
+ {week.map((day, dayId) => (
234
+ <DatePicker.TableCell key={dayId} value={day}>
235
+ <DatePicker.TableCellTrigger className={styles.tableCellTrigger}>
236
+ <DsTypography className={styles.tableCellTriggerValue} variant="body-md-md">
237
+ {day.day}
238
+ </DsTypography>
239
+ </DatePicker.TableCellTrigger>
240
+ </DatePicker.TableCell>
241
+ ))}
242
+ </DatePicker.TableRow>
243
+ ))}
244
+ </DatePicker.TableBody>
245
+ </DatePicker.Table>
246
+ )}
247
+ </DatePicker.Context>
248
+ </DatePicker.View>
249
+ );
250
+
251
+ /**
252
+ * Month view - displays grid with months of the year
253
+ */
254
+ const MonthView = () => (
255
+ <DatePicker.View view="month">
256
+ <DatePicker.Context>
257
+ {(datePicker) => (
258
+ <DatePicker.Table className={styles.table}>
259
+ <DatePicker.TableBody className={styles.tableBody}>
260
+ {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, rowId) => (
261
+ <DatePicker.TableRow key={rowId} className={styles.tableRow}>
262
+ {months.map((month, monthId) => (
263
+ <DatePicker.TableCell key={monthId} value={month.value}>
264
+ <DatePicker.TableCellTrigger className={styles.tableCellTrigger}>
265
+ <DsTypography className={styles.tableCellTriggerValue} variant="body-md-md">
266
+ {month.label}
267
+ </DsTypography>
268
+ </DatePicker.TableCellTrigger>
269
+ </DatePicker.TableCell>
270
+ ))}
271
+ </DatePicker.TableRow>
272
+ ))}
273
+ </DatePicker.TableBody>
274
+ </DatePicker.Table>
275
+ )}
276
+ </DatePicker.Context>
277
+ </DatePicker.View>
278
+ );
279
+
280
+ /**
281
+ * Year view - displays grid with years in a decade
282
+ */
283
+ const YearView = () => (
284
+ <DatePicker.View view="year">
285
+ <DatePicker.Context>
286
+ {(datePicker) => (
287
+ <DatePicker.Table className={styles.table}>
288
+ <DatePicker.TableBody className={styles.tableBody}>
289
+ {datePicker.getYearsGrid({ columns: 4 }).map((years, rowId) => (
290
+ <DatePicker.TableRow key={rowId} className={styles.tableRow}>
291
+ {years.map((year, yearId) => (
292
+ <DatePicker.TableCell key={yearId} value={year.value}>
293
+ <DatePicker.TableCellTrigger className={styles.tableCellTrigger}>
294
+ <DsTypography className={styles.tableCellTriggerValue} variant="body-md-md">
295
+ {year.label}
296
+ </DsTypography>
297
+ </DatePicker.TableCellTrigger>
298
+ </DatePicker.TableCell>
299
+ ))}
300
+ </DatePicker.TableRow>
301
+ ))}
302
+ </DatePicker.TableBody>
303
+ </DatePicker.Table>
304
+ )}
305
+ </DatePicker.Context>
306
+ </DatePicker.View>
307
+ );
308
+
309
+ export default DsDateInput;
@@ -0,0 +1,104 @@
1
+ import { type DatePickerRootProps } from '@ark-ui/react/date-picker';
2
+
3
+ /**
4
+ * Range-specific props with discriminated union for type safety
5
+ */
6
+ type DsDateInputRangeProps =
7
+ | {
8
+ /**
9
+ * Whether to enable range selection
10
+ * @default false
11
+ */
12
+ range?: false;
13
+
14
+ /**
15
+ * Controlled value as ISO date string (YYYY-MM-DD)
16
+ * @example '2024-12-25'
17
+ */
18
+ value?: string;
19
+
20
+ /**
21
+ * Default value for uncontrolled mode
22
+ * @example '2024-12-25'
23
+ */
24
+ defaultValue?: string;
25
+
26
+ /**
27
+ * Callback when the value changes
28
+ * @param value - ISO date string (YYYY-MM-DD) or undefined when empty
29
+ * @example '2024-12-25'
30
+ */
31
+ onValueChange?: (value: string | undefined) => void;
32
+ }
33
+ | {
34
+ /**
35
+ * Whether to enable range selection
36
+ */
37
+ range: true;
38
+
39
+ /**
40
+ * Controlled value as ISO date string tuple (YYYY-MM-DD)
41
+ * @example ['2024-12-01', '2024-12-31']
42
+ */
43
+ value?: [string, string];
44
+
45
+ /**
46
+ * Default value for uncontrolled mode
47
+ * @example ['2024-12-01', '2024-12-31']
48
+ */
49
+ defaultValue?: [string, string];
50
+
51
+ /**
52
+ * Callback when the value changes
53
+ * @param value - ISO date string tuple (YYYY-MM-DD) or undefined when empty
54
+ * @example ['2024-12-01', '2024-12-31']
55
+ */
56
+ onValueChange?: (value: [string, string] | undefined) => void;
57
+ };
58
+
59
+ /**
60
+ * Base props shared across all modes
61
+ */
62
+ type DsDateInputBaseProps = Pick<
63
+ DatePickerRootProps,
64
+ 'disabled' | 'readOnly' | 'id' | 'open' | 'name' | 'style'
65
+ > & {
66
+ /**
67
+ * Callback when the open state changes
68
+ * @param open - Whether the calendar is open
69
+ */
70
+ onOpenChange?: (open: boolean) => void;
71
+ /**
72
+ * Minimum allowed date as ISO string (YYYY-MM-DD)
73
+ * @example '2024-01-01'
74
+ */
75
+ min?: string;
76
+
77
+ /**
78
+ * Maximum allowed date as ISO string (YYYY-MM-DD)
79
+ * @example '2024-12-31'
80
+ */
81
+ max?: string;
82
+
83
+ /**
84
+ * Placeholder text for the input
85
+ * @default 'MM/DD/YYYY' for single date, 'MM/DD/YYYY - MM/DD/YYYY' for range
86
+ */
87
+ placeholder?: string;
88
+
89
+ /**
90
+ * Custom class name for the root container
91
+ */
92
+ className?: string;
93
+
94
+ /**
95
+ * Whether to disable the portal for the calendar content
96
+ * @default false
97
+ */
98
+ disablePortal?: boolean;
99
+ };
100
+
101
+ /**
102
+ * Props for the DsDateInput component
103
+ */
104
+ export type DsDateInputProps = DsDateInputBaseProps & DsDateInputRangeProps;