@salt-ds/lab 1.0.0-alpha.62 → 1.0.0-alpha.63

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 (178) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/css/salt-lab.css +462 -347
  3. package/dist-cjs/date-picker/DatePicker.js +4 -3
  4. package/dist-cjs/date-picker/DatePicker.js.map +1 -1
  5. package/dist-cjs/date-picker/DatePickerActions.js +1 -1
  6. package/dist-cjs/date-picker/DatePickerActions.js.map +1 -1
  7. package/dist-cjs/date-picker/DatePickerContext.js.map +1 -1
  8. package/dist-cjs/date-picker/DatePickerOverlay.js +0 -4
  9. package/dist-cjs/date-picker/DatePickerOverlay.js.map +1 -1
  10. package/dist-cjs/date-picker/DatePickerOverlayProvider.js +65 -43
  11. package/dist-cjs/date-picker/DatePickerOverlayProvider.js.map +1 -1
  12. package/dist-cjs/date-picker/DatePickerRangeInput.js +9 -26
  13. package/dist-cjs/date-picker/DatePickerRangeInput.js.map +1 -1
  14. package/dist-cjs/date-picker/DatePickerSingleInput.js +7 -14
  15. package/dist-cjs/date-picker/DatePickerSingleInput.js.map +1 -1
  16. package/dist-cjs/date-picker/useDatePicker.js +10 -7
  17. package/dist-cjs/date-picker/useDatePicker.js.map +1 -1
  18. package/dist-cjs/date-picker/useKeyboard.js +23 -0
  19. package/dist-cjs/date-picker/useKeyboard.js.map +1 -0
  20. package/dist-cjs/index.js +13 -8
  21. package/dist-cjs/index.js.map +1 -1
  22. package/dist-cjs/number-input/NumberInput.css.js +6 -0
  23. package/dist-cjs/number-input/NumberInput.css.js.map +1 -0
  24. package/dist-cjs/{stepper-input/StepperInput.js → number-input/NumberInput.js} +15 -15
  25. package/dist-cjs/number-input/NumberInput.js.map +1 -0
  26. package/dist-cjs/number-input/internal/useActivateWhileMouseDown.js.map +1 -0
  27. package/dist-cjs/number-input/internal/useInterval.js.map +1 -0
  28. package/dist-cjs/number-input/internal/utils.js.map +1 -0
  29. package/dist-cjs/{stepper-input/useStepperInput.js → number-input/useNumberInput.js} +3 -3
  30. package/dist-cjs/number-input/useNumberInput.js.map +1 -0
  31. package/dist-cjs/slider/RangeSlider.js +161 -0
  32. package/dist-cjs/slider/RangeSlider.js.map +1 -0
  33. package/dist-cjs/slider/Slider.js +104 -70
  34. package/dist-cjs/slider/Slider.js.map +1 -1
  35. package/dist-cjs/slider/internal/SliderThumb.css.js +6 -0
  36. package/dist-cjs/slider/internal/SliderThumb.css.js.map +1 -0
  37. package/dist-cjs/slider/internal/SliderThumb.js +136 -70
  38. package/dist-cjs/slider/internal/SliderThumb.js.map +1 -1
  39. package/dist-cjs/slider/internal/SliderTooltip.css.js +6 -0
  40. package/dist-cjs/slider/internal/SliderTooltip.css.js.map +1 -0
  41. package/dist-cjs/slider/internal/SliderTooltip.js +43 -0
  42. package/dist-cjs/slider/internal/SliderTooltip.js.map +1 -0
  43. package/dist-cjs/slider/internal/SliderTrack.css.js +6 -0
  44. package/dist-cjs/slider/internal/SliderTrack.css.js.map +1 -0
  45. package/dist-cjs/slider/internal/SliderTrack.js +160 -80
  46. package/dist-cjs/slider/internal/SliderTrack.js.map +1 -1
  47. package/dist-cjs/slider/internal/useRangeSliderThumb.js +194 -0
  48. package/dist-cjs/slider/internal/useRangeSliderThumb.js.map +1 -0
  49. package/dist-cjs/slider/internal/useSliderThumb.js +123 -0
  50. package/dist-cjs/slider/internal/useSliderThumb.js.map +1 -0
  51. package/dist-cjs/slider/internal/utils.js +97 -72
  52. package/dist-cjs/slider/internal/utils.js.map +1 -1
  53. package/dist-cjs/tabs-next/TabOverflowList.css.js +1 -1
  54. package/dist-cjs/tabs-next/TabOverflowList.js +2 -1
  55. package/dist-cjs/tabs-next/TabOverflowList.js.map +1 -1
  56. package/dist-es/date-picker/DatePicker.js +4 -3
  57. package/dist-es/date-picker/DatePicker.js.map +1 -1
  58. package/dist-es/date-picker/DatePickerActions.js +1 -1
  59. package/dist-es/date-picker/DatePickerActions.js.map +1 -1
  60. package/dist-es/date-picker/DatePickerContext.js.map +1 -1
  61. package/dist-es/date-picker/DatePickerOverlay.js +0 -4
  62. package/dist-es/date-picker/DatePickerOverlay.js.map +1 -1
  63. package/dist-es/date-picker/DatePickerOverlayProvider.js +67 -45
  64. package/dist-es/date-picker/DatePickerOverlayProvider.js.map +1 -1
  65. package/dist-es/date-picker/DatePickerRangeInput.js +9 -26
  66. package/dist-es/date-picker/DatePickerRangeInput.js.map +1 -1
  67. package/dist-es/date-picker/DatePickerSingleInput.js +7 -14
  68. package/dist-es/date-picker/DatePickerSingleInput.js.map +1 -1
  69. package/dist-es/date-picker/useDatePicker.js +10 -7
  70. package/dist-es/date-picker/useDatePicker.js.map +1 -1
  71. package/dist-es/date-picker/useKeyboard.js +21 -0
  72. package/dist-es/date-picker/useKeyboard.js.map +1 -0
  73. package/dist-es/index.js +6 -4
  74. package/dist-es/index.js.map +1 -1
  75. package/dist-es/number-input/NumberInput.css.js +4 -0
  76. package/dist-es/number-input/NumberInput.css.js.map +1 -0
  77. package/dist-es/{stepper-input/StepperInput.js → number-input/NumberInput.js} +14 -14
  78. package/dist-es/number-input/NumberInput.js.map +1 -0
  79. package/dist-es/number-input/internal/useActivateWhileMouseDown.js.map +1 -0
  80. package/dist-es/number-input/internal/useInterval.js.map +1 -0
  81. package/dist-es/number-input/internal/utils.js.map +1 -0
  82. package/dist-es/{stepper-input/useStepperInput.js → number-input/useNumberInput.js} +3 -3
  83. package/dist-es/number-input/useNumberInput.js.map +1 -0
  84. package/dist-es/slider/RangeSlider.js +159 -0
  85. package/dist-es/slider/RangeSlider.js.map +1 -0
  86. package/dist-es/slider/Slider.js +107 -73
  87. package/dist-es/slider/Slider.js.map +1 -1
  88. package/dist-es/slider/internal/SliderThumb.css.js +4 -0
  89. package/dist-es/slider/internal/SliderThumb.css.js.map +1 -0
  90. package/dist-es/slider/internal/SliderThumb.js +138 -72
  91. package/dist-es/slider/internal/SliderThumb.js.map +1 -1
  92. package/dist-es/slider/internal/SliderTooltip.css.js +4 -0
  93. package/dist-es/slider/internal/SliderTooltip.css.js.map +1 -0
  94. package/dist-es/slider/internal/SliderTooltip.js +41 -0
  95. package/dist-es/slider/internal/SliderTooltip.js.map +1 -0
  96. package/dist-es/slider/internal/SliderTrack.css.js +4 -0
  97. package/dist-es/slider/internal/SliderTrack.css.js.map +1 -0
  98. package/dist-es/slider/internal/SliderTrack.js +164 -84
  99. package/dist-es/slider/internal/SliderTrack.js.map +1 -1
  100. package/dist-es/slider/internal/useRangeSliderThumb.js +192 -0
  101. package/dist-es/slider/internal/useRangeSliderThumb.js.map +1 -0
  102. package/dist-es/slider/internal/useSliderThumb.js +121 -0
  103. package/dist-es/slider/internal/useSliderThumb.js.map +1 -0
  104. package/dist-es/slider/internal/utils.js +91 -63
  105. package/dist-es/slider/internal/utils.js.map +1 -1
  106. package/dist-es/tabs-next/TabOverflowList.css.js +1 -1
  107. package/dist-es/tabs-next/TabOverflowList.js +3 -2
  108. package/dist-es/tabs-next/TabOverflowList.js.map +1 -1
  109. package/dist-types/date-picker/DatePicker.d.ts +6 -1
  110. package/dist-types/date-picker/DatePickerContext.d.ts +2 -1
  111. package/dist-types/date-picker/DatePickerOverlayProvider.d.ts +18 -4
  112. package/dist-types/date-picker/DatePickerRangeInput.d.ts +1 -1
  113. package/dist-types/date-picker/index.d.ts +1 -0
  114. package/dist-types/date-picker/useKeyboard.d.ts +14 -0
  115. package/dist-types/index.d.ts +4 -4
  116. package/dist-types/{stepper-input/StepperInput.d.ts → number-input/NumberInput.d.ts} +7 -7
  117. package/dist-types/number-input/index.d.ts +2 -0
  118. package/dist-types/{stepper-input/useStepperInput.d.ts → number-input/useNumberInput.d.ts} +2 -2
  119. package/dist-types/slider/RangeSlider.d.ts +91 -0
  120. package/dist-types/slider/Slider.d.ts +74 -15
  121. package/dist-types/slider/index.d.ts +1 -1
  122. package/dist-types/slider/internal/SliderThumb.d.ts +20 -7
  123. package/dist-types/slider/internal/SliderTooltip.d.ts +6 -0
  124. package/dist-types/slider/internal/SliderTrack.d.ts +23 -3
  125. package/dist-types/slider/internal/useRangeSliderThumb.d.ts +26 -0
  126. package/dist-types/slider/internal/useSliderThumb.d.ts +24 -0
  127. package/dist-types/slider/internal/utils.d.ts +17 -15
  128. package/package.json +1 -1
  129. package/dist-cjs/slider/Slider.css.js +0 -6
  130. package/dist-cjs/slider/Slider.css.js.map +0 -1
  131. package/dist-cjs/slider/internal/SliderContext.js +0 -19
  132. package/dist-cjs/slider/internal/SliderContext.js.map +0 -1
  133. package/dist-cjs/slider/internal/SliderMarks.js +0 -29
  134. package/dist-cjs/slider/internal/SliderMarks.js.map +0 -1
  135. package/dist-cjs/slider/internal/SliderSelection.js +0 -33
  136. package/dist-cjs/slider/internal/SliderSelection.js.map +0 -1
  137. package/dist-cjs/slider/internal/useKeyDownThumb.js +0 -50
  138. package/dist-cjs/slider/internal/useKeyDownThumb.js.map +0 -1
  139. package/dist-cjs/stepper-input/StepperInput.css.js +0 -6
  140. package/dist-cjs/stepper-input/StepperInput.css.js.map +0 -1
  141. package/dist-cjs/stepper-input/StepperInput.js.map +0 -1
  142. package/dist-cjs/stepper-input/internal/useActivateWhileMouseDown.js.map +0 -1
  143. package/dist-cjs/stepper-input/internal/useInterval.js.map +0 -1
  144. package/dist-cjs/stepper-input/internal/utils.js.map +0 -1
  145. package/dist-cjs/stepper-input/useStepperInput.js.map +0 -1
  146. package/dist-es/slider/Slider.css.js +0 -4
  147. package/dist-es/slider/Slider.css.js.map +0 -1
  148. package/dist-es/slider/internal/SliderContext.js +0 -16
  149. package/dist-es/slider/internal/SliderContext.js.map +0 -1
  150. package/dist-es/slider/internal/SliderMarks.js +0 -27
  151. package/dist-es/slider/internal/SliderMarks.js.map +0 -1
  152. package/dist-es/slider/internal/SliderSelection.js +0 -31
  153. package/dist-es/slider/internal/SliderSelection.js.map +0 -1
  154. package/dist-es/slider/internal/useKeyDownThumb.js +0 -48
  155. package/dist-es/slider/internal/useKeyDownThumb.js.map +0 -1
  156. package/dist-es/stepper-input/StepperInput.css.js +0 -4
  157. package/dist-es/stepper-input/StepperInput.css.js.map +0 -1
  158. package/dist-es/stepper-input/StepperInput.js.map +0 -1
  159. package/dist-es/stepper-input/internal/useActivateWhileMouseDown.js.map +0 -1
  160. package/dist-es/stepper-input/internal/useInterval.js.map +0 -1
  161. package/dist-es/stepper-input/internal/utils.js.map +0 -1
  162. package/dist-es/stepper-input/useStepperInput.js.map +0 -1
  163. package/dist-types/slider/internal/SliderContext.d.ts +0 -11
  164. package/dist-types/slider/internal/SliderMarks.d.ts +0 -7
  165. package/dist-types/slider/internal/SliderSelection.d.ts +0 -4
  166. package/dist-types/slider/internal/index.d.ts +0 -3
  167. package/dist-types/slider/internal/useKeyDownThumb.d.ts +0 -2
  168. package/dist-types/slider/types.d.ts +0 -4
  169. package/dist-types/stepper-input/index.d.ts +0 -2
  170. /package/dist-cjs/{stepper-input → number-input}/internal/useActivateWhileMouseDown.js +0 -0
  171. /package/dist-cjs/{stepper-input → number-input}/internal/useInterval.js +0 -0
  172. /package/dist-cjs/{stepper-input → number-input}/internal/utils.js +0 -0
  173. /package/dist-es/{stepper-input → number-input}/internal/useActivateWhileMouseDown.js +0 -0
  174. /package/dist-es/{stepper-input → number-input}/internal/useInterval.js +0 -0
  175. /package/dist-es/{stepper-input → number-input}/internal/utils.js +0 -0
  176. /package/dist-types/{stepper-input → number-input}/internal/useActivateWhileMouseDown.d.ts +0 -0
  177. /package/dist-types/{stepper-input → number-input}/internal/useInterval.d.ts +0 -0
  178. /package/dist-types/{stepper-input → number-input}/internal/utils.d.ts +0 -0
@@ -1,75 +1,103 @@
1
- const getValue = (trackRef, min, max, step, clientX) => {
2
- const { width, x } = trackRef.current.getBoundingClientRect();
3
- const localX = clientX - x;
4
- const normaliseBetweenValues = localX / width * (max - min) + min;
5
- const roundedToStep = roundToStep(normaliseBetweenValues, step);
6
- const decimals = countDecimalPlaces(step);
7
- const rounded = Number(roundedToStep.toFixed(decimals));
8
- const value = clampValue(rounded, [min, max]);
9
- return value;
10
- };
11
- const setValue = (value, newValue, index, onChange) => {
12
- if (value.length === 2) {
13
- const newValueArray = [...value];
14
- newValueArray.splice(index, 1, newValue);
15
- onChange(newValueArray);
16
- return;
1
+ const toFloat = (value) => typeof value === "string" ? Number.parseFloat(value) : value;
2
+ const calculateMarkPosition = (value, max, min) => {
3
+ if (min === max) {
4
+ return 0;
17
5
  }
18
- onChange([newValue]);
6
+ const clampedValue = Number.isNaN(toFloat(value)) ? min : Math.min(Math.max(toFloat(value), min), max);
7
+ const markPosition = (clampedValue - min) / (max - min) * 100;
8
+ return Math.round(markPosition * 100) / 100;
19
9
  };
20
- const roundToStep = (value, step) => Math.round(value / step) * step;
21
- const clampValue = (value, [min, max]) => {
22
- if (value > max) {
23
- return max;
24
- }
25
- if (value < min) {
10
+ const calculatePercentage = (value, max, min) => (value - min) / (max - min) * 100;
11
+ const clamp = (value, max, min, step, decimalPlaces, marks, restrictToMarks) => {
12
+ if (Number.isNaN(value)) {
26
13
  return min;
27
14
  }
28
- return value;
29
- };
30
- const getPercentage = (min, max, value) => {
31
- const percentage = (value - min) / (max - min) * 100;
32
- return Math.min(Math.max(percentage, 0), 100);
33
- };
34
- const countDecimalPlaces = (num) => {
35
- const parts = num.toString().split(".");
36
- return parts.length > 1 ? parts[1].length : 0;
15
+ const clampedValue = Math.min(Math.max(value, min), max);
16
+ if (restrictToMarks && marks) {
17
+ let closestMark = marks[0].value;
18
+ let smallestDifference = Math.abs(clampedValue - closestMark);
19
+ for (let i = 1; i < marks.length; i++) {
20
+ const currentDifference = Math.abs(clampedValue - marks[i].value);
21
+ if (currentDifference < smallestDifference) {
22
+ smallestDifference = currentDifference;
23
+ closestMark = marks[i].value;
24
+ }
25
+ }
26
+ return closestMark;
27
+ }
28
+ let roundedValue = Math.round(clampedValue / step) * step;
29
+ if (roundedValue > max) {
30
+ roundedValue = max;
31
+ }
32
+ return Number.parseFloat(roundedValue.toFixed(decimalPlaces));
37
33
  };
38
- const getMarkStyles = (min, max, step) => {
39
- const marks = [];
40
- for (let i = min; i <= max; i = Number((i + step).toPrecision(4))) {
41
- const value = Number(i.toPrecision(4));
42
- const position = `${getPercentage(min, max, value)}%`;
43
- marks.push({ value, position });
34
+ const clampRange = (range, max, min, step, decimalPlaces, marks, restrictToMarks) => {
35
+ let [start, end] = range;
36
+ if (Number.isNaN(start)) {
37
+ start = min;
38
+ }
39
+ if (Number.isNaN(end)) {
40
+ end = max;
41
+ }
42
+ if (start > end) {
43
+ [start, end] = [end, start];
44
44
  }
45
- const decimals = Math.max(
46
- ...marks.map((mark) => countDecimalPlaces(mark.value))
45
+ start = clamp(start, max, min, step, decimalPlaces, marks, restrictToMarks);
46
+ end = clamp(end, max, min, step, decimalPlaces, marks, restrictToMarks);
47
+ return [start, end];
48
+ };
49
+ const getClickedPosition = (sliderRef, clientX, max, min, step, decimalPlaces, marks, restrictToMarks) => {
50
+ if (!sliderRef.current) return;
51
+ const sliderRect = sliderRef.current.getBoundingClientRect();
52
+ const rawValue = (clientX - sliderRect.left) / sliderRect.width * (max - min) + min;
53
+ const steppedValue = Math.round(rawValue / step) * step;
54
+ return clamp(
55
+ steppedValue,
56
+ max,
57
+ min,
58
+ step,
59
+ decimalPlaces,
60
+ marks,
61
+ restrictToMarks
47
62
  );
48
- return marks.map((mark) => ({
49
- ...mark,
50
- label: mark.value.toFixed(decimals)
51
- }));
52
63
  };
53
- const getNearestIndex = (value, newValue) => {
54
- if (value.length === 1) return 0;
55
- if (value[0] === value[1]) {
56
- if (newValue < value[0]) return 0;
57
- return 1;
64
+ const getKeyboardValue = (event, value, step, stepMultiplier, max, min, restrictToMarks, marks) => {
65
+ let newValue = value;
66
+ if (restrictToMarks && marks && marks.length >= 1) {
67
+ const currentIndex = marks.findIndex((mark) => mark.value === value);
68
+ switch (event.key) {
69
+ case "ArrowUp":
70
+ case "ArrowRight":
71
+ case "PageUp":
72
+ if (currentIndex < marks.length - 1) {
73
+ newValue = marks[currentIndex + 1].value;
74
+ }
75
+ break;
76
+ case "ArrowDown":
77
+ case "ArrowLeft":
78
+ case "PageDown":
79
+ if (currentIndex > 0) {
80
+ newValue = marks[currentIndex - 1].value;
81
+ }
82
+ break;
83
+ default:
84
+ return newValue;
85
+ }
86
+ } else {
87
+ switch (event.key) {
88
+ case "PageUp":
89
+ newValue = Math.min(value + step * stepMultiplier, max);
90
+ break;
91
+ case "PageDown":
92
+ newValue = Math.max(value - step * stepMultiplier, min);
93
+ break;
94
+ default:
95
+ return newValue;
96
+ }
58
97
  }
59
- const distances = value.map((value2) => Math.abs(newValue - value2));
60
- const minDistance = Math.min(...distances);
61
- const nearestIndex = distances.indexOf(minDistance);
62
- return nearestIndex;
63
- };
64
- const preventOverlappingValues = (value, newValue, index) => value.length === 2 ? index === 0 ? Math.min(newValue, value[1]) : Math.max(newValue, value[0]) : newValue;
65
- const parseValueProp = (value, min, max) => {
66
- if (typeof value === "undefined" || value.length < 1) return;
67
- const a = clampValue(value[0], [min, max]);
68
- if (value.length === 1) return [a];
69
- const b = clampValue(value[1], [min, max]);
70
- if (a > b) return [a, a];
71
- return [a, b];
98
+ event.preventDefault();
99
+ return newValue;
72
100
  };
73
101
 
74
- export { clampValue, countDecimalPlaces, getMarkStyles, getNearestIndex, getPercentage, getValue, parseValueProp, preventOverlappingValues, roundToStep, setValue };
102
+ export { calculateMarkPosition, calculatePercentage, clamp, clampRange, getClickedPosition, getKeyboardValue, toFloat };
75
103
  //# sourceMappingURL=utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sources":["../src/slider/internal/utils.ts"],"sourcesContent":["import type { RefObject } from \"react\";\nimport type { SliderChangeHandler, SliderValue, ThumbIndex } from \"../types\";\n\nexport const getValue = (\n trackRef: RefObject<Element>,\n min: number,\n max: number,\n step: number,\n clientX: number,\n) => {\n const { width, x } = trackRef.current!.getBoundingClientRect();\n const localX = clientX - x;\n const normaliseBetweenValues = (localX / width) * (max - min) + min;\n const roundedToStep = roundToStep(normaliseBetweenValues, step);\n const decimals = countDecimalPlaces(step);\n const rounded = Number(roundedToStep.toFixed(decimals));\n const value = clampValue(rounded, [min, max]);\n return value;\n};\n\nexport const setValue = (\n value: SliderValue,\n newValue: number,\n index: ThumbIndex,\n onChange: SliderChangeHandler,\n) => {\n if (value.length === 2) {\n const newValueArray = [...value];\n newValueArray.splice(index, 1, newValue);\n onChange(newValueArray as SliderValue);\n return;\n }\n onChange([newValue]);\n};\n\nexport const roundToStep = (value: number, step: number) =>\n Math.round(value / step) * step;\n\nexport const clampValue = (value: number, [min, max]: number[]) => {\n if (value > max) {\n return max;\n }\n if (value < min) {\n return min;\n }\n return value;\n};\n\nexport const getPercentage = (min: number, max: number, value: number) => {\n const percentage = ((value - min) / (max - min)) * 100;\n return Math.min(Math.max(percentage, 0), 100);\n};\n\nexport const getPercentageDifference = (\n min: number,\n max: number,\n value: number[],\n) => {\n const valueDiff = value[1] - value[0];\n const percentage = ((valueDiff - min) / (max - min)) * 100;\n return `${Math.min(Math.max(percentage, 0), 100)}%`;\n};\n\nexport const getPercentageOffset = (\n min: number,\n max: number,\n value: number[],\n) => {\n const offsetLeft = ((value[0] - min) / (max - min)) * 100;\n return `${Math.min(Math.max(offsetLeft, 0), 100)}%`;\n};\n\nexport const countDecimalPlaces = (num: number) => {\n const parts = num.toString().split(\".\");\n return parts.length > 1 ? parts[1].length : 0;\n};\n\nexport const getMarkStyles = (min: number, max: number, step: number) => {\n const marks = [];\n for (let i = min; i <= max; i = Number((i + step).toPrecision(4))) {\n const value = Number(i.toPrecision(4));\n const position = `${getPercentage(min, max, value)}%`;\n marks.push({ value, position });\n }\n const decimals = Math.max(\n ...marks.map((mark) => countDecimalPlaces(mark.value)),\n );\n return marks.map((mark) => ({\n ...mark,\n label: mark.value.toFixed(decimals),\n }));\n};\n\nexport const getNearestIndex = (value: SliderValue, newValue: number) => {\n if (value.length === 1) return 0;\n\n if (value[0] === value[1]) {\n if (newValue < value[0]) return 0;\n return 1;\n }\n\n const distances = value.map((value) => Math.abs(newValue - value));\n const minDistance = Math.min(...distances);\n const nearestIndex = distances.indexOf(minDistance);\n\n return nearestIndex as ThumbIndex;\n};\n\nexport const preventOverlappingValues = (\n value: SliderValue,\n newValue: number,\n index: ThumbIndex,\n) =>\n value.length === 2\n ? index === 0\n ? Math.min(newValue, value[1])\n : Math.max(newValue, value[0])\n : newValue;\n\nexport const parseValueProp = (\n value: number[] | undefined,\n min: number,\n max: number,\n) => {\n if (typeof value === \"undefined\" || value.length < 1) return;\n const a = clampValue(value[0], [min, max]);\n if (value.length === 1) return [a] as SliderValue;\n const b = clampValue(value[1], [min, max]);\n if (a > b) return [a, a] as SliderValue;\n return [a, b] as SliderValue;\n};\n"],"names":["value"],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","sources":["../src/slider/internal/utils.ts"],"sourcesContent":["import type { RefObject } from \"react\";\n\nexport const toFloat = (value: number | string) =>\n typeof value === \"string\" ? Number.parseFloat(value) : value;\n\nexport const calculateMarkPosition = (\n value: number | string,\n max: number,\n min: number,\n) => {\n if (min === max) {\n return 0;\n }\n const clampedValue = Number.isNaN(toFloat(value))\n ? min\n : Math.min(Math.max(toFloat(value), min), max);\n const markPosition = ((clampedValue - min) / (max - min)) * 100;\n return Math.round(markPosition * 100) / 100;\n};\n\nexport const calculatePercentage = (value: number, max: number, min: number) =>\n ((value - min) / (max - min)) * 100;\n\nexport const clamp = (\n value: number,\n max: number,\n min: number,\n step: number,\n decimalPlaces: number,\n marks?: { value: number; label: string }[],\n restrictToMarks?: boolean,\n) => {\n if (Number.isNaN(value)) {\n return min;\n }\n // Clamp the value between min and max\n const clampedValue = Math.min(Math.max(value, min), max);\n if (restrictToMarks && marks) {\n // Find the closest mark value\n let closestMark = marks[0].value;\n let smallestDifference = Math.abs(clampedValue - closestMark);\n for (let i = 1; i < marks.length; i++) {\n const currentDifference = Math.abs(clampedValue - marks[i].value);\n if (currentDifference < smallestDifference) {\n smallestDifference = currentDifference;\n closestMark = marks[i].value;\n }\n }\n return closestMark;\n }\n // Round to the nearest multiple of the step\n let roundedValue = Math.round(clampedValue / step) * step;\n // Ensure the rounded value does not exceed max\n if (roundedValue > max) {\n roundedValue = max;\n }\n return Number.parseFloat(roundedValue.toFixed(decimalPlaces));\n};\n\nexport const clampRange = (\n range: [number, number],\n max: number,\n min: number,\n step: number,\n decimalPlaces: number,\n marks?: { value: number; label: string }[],\n restrictToMarks?: boolean,\n) => {\n let [start, end] = range;\n\n if (Number.isNaN(start)) {\n start = min;\n }\n if (Number.isNaN(end)) {\n end = max;\n }\n if (start > end) {\n [start, end] = [end, start];\n }\n start = clamp(start, max, min, step, decimalPlaces, marks, restrictToMarks);\n end = clamp(end, max, min, step, decimalPlaces, marks, restrictToMarks);\n return [start, end] as [number, number];\n};\n\nexport const getClickedPosition = (\n sliderRef: RefObject<HTMLDivElement>,\n clientX: number,\n max: number,\n min: number,\n step: number,\n decimalPlaces: number,\n marks?: { label: string; value: number }[],\n restrictToMarks?: boolean,\n) => {\n if (!sliderRef.current) return;\n\n const sliderRect = sliderRef.current.getBoundingClientRect();\n const rawValue =\n ((clientX - sliderRect.left) / sliderRect.width) * (max - min) + min;\n const steppedValue = Math.round(rawValue / step) * step;\n return clamp(\n steppedValue,\n max,\n min,\n step,\n decimalPlaces,\n marks,\n restrictToMarks,\n );\n};\n\nexport const getKeyboardValue = (\n event: React.KeyboardEvent,\n value: number,\n step: number,\n stepMultiplier: number,\n max: number,\n min: number,\n restrictToMarks?: boolean,\n marks?: { label: string; value: number }[],\n) => {\n let newValue = value;\n\n if (restrictToMarks && marks && marks.length >= 1) {\n const currentIndex = marks.findIndex((mark) => mark.value === value);\n\n switch (event.key) {\n case \"ArrowUp\":\n case \"ArrowRight\":\n case \"PageUp\":\n if (currentIndex < marks.length - 1) {\n newValue = marks[currentIndex + 1].value;\n }\n break;\n case \"ArrowDown\":\n case \"ArrowLeft\":\n case \"PageDown\":\n if (currentIndex > 0) {\n newValue = marks[currentIndex - 1].value;\n }\n break;\n default:\n return newValue;\n }\n } else {\n switch (event.key) {\n case \"PageUp\":\n newValue = Math.min(value + step * stepMultiplier, max);\n break;\n case \"PageDown\":\n newValue = Math.max(value - step * stepMultiplier, min);\n break;\n default:\n return newValue;\n }\n }\n\n event.preventDefault();\n return newValue;\n};\n"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- var css_248z = ".saltTabOverflow {\n position: relative;\n}\n\n.saltTabOverflow-list {\n background: var(--salt-container-primary-background);\n border: var(--salt-size-border) var(--salt-selectable-borderStyle-selected) var(--salt-selectable-borderColor-selected);\n overflow: hidden;\n overflow-y: auto;\n position: absolute;\n z-index: var(--salt-zIndex-flyover);\n box-shadow: var(--salt-overlayable-shadow-popout);\n box-sizing: border-box;\n border-radius: var(--salt-palette-corner, 0);\n}\n\n.saltTabOverflow-listContainer {\n display: flex;\n flex-direction: column;\n gap: var(--salt-size-border);\n max-height: inherit;\n min-height: inherit;\n}\n\n.saltTabOverflow-list[data-hidden=\"true\"] {\n opacity: 0;\n pointer-events: none;\n}\n\n.saltTabOverflow-list .saltTabNext {\n color: var(--salt-content-primary-foreground);\n background: var(--salt-selectable-background);\n font-size: var(--salt-text-fontSize);\n font-weight: var(--salt-text-fontWeight);\n min-height: calc(var(--salt-size-base) + var(--salt-spacing-100));\n padding-left: var(--salt-spacing-100);\n padding-right: var(--salt-spacing-100);\n display: flex;\n gap: var(--salt-spacing-100);\n position: relative;\n align-items: center;\n cursor: var(--salt-selectable-cursor-hover);\n box-sizing: border-box;\n flex-shrink: 0;\n justify-content: flex-start;\n}\n\n.saltTabOverflow-list .saltTabNext .saltTabNextTrigger {\n justify-content: start;\n}\n\n.saltTabOverflow-list .saltTabNext::after {\n display: none;\n}\n\n.saltTabOverflow-list .saltTabNext[aria-disabled=\"true\"] {\n color: var(--salt-content-primary-foreground-disabled);\n cursor: var(--salt-selectable-cursor-disabled);\n}\n\n.saltTabOverflow-list .saltTabNext-focusVisible {\n outline: var(--salt-focused-outline);\n outline-offset: calc(var(--salt-size-border) * -2);\n}\n\n.saltTabOverflow-list .saltTabNext:hover {\n background: var(--salt-selectable-background-hover);\n}\n\n.saltTabOverflow-list .saltTabNext:active {\n background: var(--salt-selectable-background-selected);\n box-shadow: 0 calc(var(--salt-size-border) * -1) 0 0 var(--salt-selectable-borderColor-selected), 0 var(--salt-size-border) 0 0 var(--salt-selectable-borderColor-selected);\n}\n";
1
+ var css_248z = ".saltTabOverflow {\n position: relative;\n}\n\n.saltTabOverflow-list {\n background: var(--salt-container-primary-background);\n border: var(--salt-size-border) var(--salt-selectable-borderStyle-selected) var(--salt-selectable-borderColor-selected);\n overflow: hidden;\n overflow-y: auto;\n position: absolute;\n z-index: var(--salt-zIndex-flyover);\n box-shadow: var(--salt-overlayable-shadow-popout);\n box-sizing: border-box;\n border-radius: var(--salt-palette-corner, 0);\n}\n\n.saltTabOverflow-listContainer {\n display: flex;\n flex-direction: column;\n gap: var(--salt-size-border);\n max-height: inherit;\n min-height: inherit;\n}\n\n.saltTabOverflow-list[data-hidden=\"true\"] {\n opacity: 0;\n pointer-events: none;\n /* Avoid causing page to overflow with the hidden elements */\n width: 1px;\n height: 1px;\n}\n\n.saltTabOverflow-list .saltTabNext {\n color: var(--salt-content-primary-foreground);\n background: var(--salt-selectable-background);\n font-size: var(--salt-text-fontSize);\n font-weight: var(--salt-text-fontWeight);\n min-height: calc(var(--salt-size-base) + var(--salt-spacing-100));\n padding-left: var(--salt-spacing-100);\n padding-right: var(--salt-spacing-100);\n display: flex;\n gap: var(--salt-spacing-100);\n position: relative;\n align-items: center;\n cursor: var(--salt-selectable-cursor-hover);\n box-sizing: border-box;\n flex-shrink: 0;\n justify-content: flex-start;\n}\n\n.saltTabOverflow-list .saltTabNext .saltTabNextTrigger {\n justify-content: start;\n}\n\n.saltTabOverflow-list .saltTabNext::after {\n display: none;\n}\n\n.saltTabOverflow-list .saltTabNext[aria-disabled=\"true\"] {\n color: var(--salt-content-primary-foreground-disabled);\n cursor: var(--salt-selectable-cursor-disabled);\n}\n\n.saltTabOverflow-list .saltTabNext-focusVisible {\n outline: var(--salt-focused-outline);\n outline-offset: calc(var(--salt-size-border) * -2);\n}\n\n.saltTabOverflow-list .saltTabNext:hover {\n background: var(--salt-selectable-background-hover);\n}\n\n.saltTabOverflow-list .saltTabNext:active {\n background: var(--salt-selectable-background-selected);\n box-shadow: 0 calc(var(--salt-size-border) * -1) 0 0 var(--salt-selectable-borderColor-selected), 0 var(--salt-size-border) 0 0 var(--salt-selectable-borderColor-selected);\n}\n";
2
2
 
3
3
  export { css_248z as default };
4
4
  //# sourceMappingURL=TabOverflowList.css.js.map
@@ -1,5 +1,5 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
- import { offset, size, useInteractions, useDismiss, FloatingTree } from '@floating-ui/react';
2
+ import { offset, size, flip, useInteractions, useDismiss, FloatingTree } from '@floating-ui/react';
3
3
  import { makePrefixer, useIcon, useFloatingUI, useForkRef, useId, Button } from '@salt-ds/core';
4
4
  import { useComponentCssInjection } from '@salt-ds/styles';
5
5
  import { useWindow } from '@salt-ds/window';
@@ -52,7 +52,8 @@ const TabOverflowList = forwardRef(
52
52
  maxHeight: `max(calc((var(--salt-size-base) + var(--salt-spacing-100)) * 5), calc(${availableHeight}px - var(--salt-spacing-100)))`
53
53
  });
54
54
  }
55
- })
55
+ }),
56
+ flip()
56
57
  ]
57
58
  });
58
59
  const { getFloatingProps } = useInteractions([useDismiss(context)]);
@@ -1 +1 @@
1
- {"version":3,"file":"TabOverflowList.js","sources":["../src/tabs-next/TabOverflowList.tsx"],"sourcesContent":["import {\n FloatingTree,\n offset,\n size,\n useDismiss,\n useInteractions,\n} from \"@floating-ui/react\";\nimport {\n Button,\n makePrefixer,\n useFloatingUI,\n useForkRef,\n useIcon,\n useId,\n} from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport {\n Children,\n type ComponentPropsWithoutRef,\n type Dispatch,\n type ReactNode,\n type Ref,\n type RefObject,\n type SetStateAction,\n forwardRef,\n useCallback,\n useRef,\n} from \"react\";\nimport tabOverflowListCss from \"./TabOverflowList.css\";\nimport { useFocusOutside } from \"./hooks/useFocusOutside\";\n\ninterface TabOverflowListProps extends ComponentPropsWithoutRef<\"button\"> {\n buttonRef?: Ref<HTMLButtonElement>;\n tabstripRef: RefObject<HTMLDivElement>;\n children?: ReactNode;\n isMeasuring?: boolean;\n open: boolean;\n setOpen: Dispatch<SetStateAction<boolean>>;\n}\n\nconst withBaseName = makePrefixer(\"saltTabOverflow\");\n\nexport const TabOverflowList = forwardRef<HTMLDivElement, TabOverflowListProps>(\n function TabOverflowList(props, ref) {\n const {\n buttonRef,\n tabstripRef,\n children,\n isMeasuring,\n open,\n setOpen,\n ...rest\n } = props;\n\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-tabs-next-overflow-list\",\n css: tabOverflowListCss,\n window: targetWindow,\n });\n\n const { OverflowIcon } = useIcon();\n\n const { refs, x, y, strategy, context } = useFloatingUI({\n open: open,\n onOpenChange(open, _, reason) {\n if (reason === \"escape-key\") {\n queueMicrotask(() => {\n const allTabs =\n tabstripRef.current?.querySelectorAll<HTMLElement>(\n '[role=\"tab\"]:not([aria-hidden])',\n ) ?? [];\n const numberOfTabsInOverflow =\n listRef.current?.querySelectorAll<HTMLElement>('[role=\"tab\"]')\n .length ?? 0;\n\n allTabs[allTabs.length - numberOfTabsInOverflow - 1]?.focus({\n preventScroll: true,\n });\n });\n }\n\n setOpen(open);\n },\n placement: \"bottom-start\",\n middleware: [\n offset(1),\n size({\n apply({ elements, availableHeight }) {\n Object.assign(elements.floating.style, {\n maxHeight: `max(calc((var(--salt-size-base) + var(--salt-spacing-100)) * 5), calc(${availableHeight}px - var(--salt-spacing-100)))`,\n });\n },\n }),\n ],\n });\n\n const { getFloatingProps } = useInteractions([useDismiss(context)]);\n\n const rootRef = useRef<HTMLDivElement>(null);\n const handleRootRef = useForkRef(rootRef, ref);\n const listRef = useRef<HTMLDivElement>(null);\n const handleListRef = useForkRef<HTMLDivElement>(listRef, refs.setFloating);\n\n const handleFocusOutside = useCallback(() => {\n setOpen(false);\n }, [setOpen]);\n\n useFocusOutside(\n rootRef,\n handleFocusOutside,\n open,\n \"[data-floating-ui-portal]\",\n );\n\n const handleClick = () => {\n if (!open) {\n listRef.current\n ?.querySelectorAll<HTMLElement>('[role=\"tab\"]')[0]\n ?.focus({ preventScroll: true });\n } else {\n setOpen(false);\n }\n };\n\n const handleFocus = () => {\n setOpen(true);\n };\n\n const handleButtonRef = useForkRef<HTMLButtonElement>(\n buttonRef,\n refs.setReference,\n );\n\n const listId = useId();\n\n const childCount = Children.count(children);\n if (childCount === 0 && !isMeasuring) return null;\n\n return (\n <div className={withBaseName()} ref={handleRootRef} data-overflow>\n <Button\n data-overflowbutton\n tabIndex={-1}\n appearance=\"transparent\"\n sentiment=\"neutral\"\n onClick={handleClick}\n ref={handleButtonRef}\n aria-label={`Overflow menu. ${childCount} tabs hidden`}\n aria-expanded={open}\n aria-controls={listId}\n aria-hidden=\"true\"\n role=\"tab\"\n aria-haspopup\n {...rest}\n >\n <OverflowIcon aria-hidden />\n </Button>\n <FloatingTree>\n <div\n ref={handleListRef}\n {...getFloatingProps({\n onFocus: handleFocus,\n role: \"presentation\",\n })}\n className={withBaseName(\"list\")}\n data-hidden={!open}\n style={\n open\n ? { left: x ?? 0, top: y ?? 0, position: strategy }\n : undefined\n }\n id={listId}\n >\n <div className={withBaseName(\"listContainer\")}>{children}</div>\n </div>\n </FloatingTree>\n </div>\n );\n },\n);\n"],"names":["TabOverflowList","tabOverflowListCss","open"],"mappings":"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"}
1
+ {"version":3,"file":"TabOverflowList.js","sources":["../src/tabs-next/TabOverflowList.tsx"],"sourcesContent":["import {\n FloatingTree,\n flip,\n offset,\n size,\n useDismiss,\n useInteractions,\n} from \"@floating-ui/react\";\nimport {\n Button,\n makePrefixer,\n useFloatingUI,\n useForkRef,\n useIcon,\n useId,\n} from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport {\n Children,\n type ComponentPropsWithoutRef,\n type Dispatch,\n type ReactNode,\n type Ref,\n type RefObject,\n type SetStateAction,\n forwardRef,\n useCallback,\n useRef,\n} from \"react\";\nimport tabOverflowListCss from \"./TabOverflowList.css\";\nimport { useFocusOutside } from \"./hooks/useFocusOutside\";\n\ninterface TabOverflowListProps extends ComponentPropsWithoutRef<\"button\"> {\n buttonRef?: Ref<HTMLButtonElement>;\n tabstripRef: RefObject<HTMLDivElement>;\n children?: ReactNode;\n isMeasuring?: boolean;\n open: boolean;\n setOpen: Dispatch<SetStateAction<boolean>>;\n}\n\nconst withBaseName = makePrefixer(\"saltTabOverflow\");\n\nexport const TabOverflowList = forwardRef<HTMLDivElement, TabOverflowListProps>(\n function TabOverflowList(props, ref) {\n const {\n buttonRef,\n tabstripRef,\n children,\n isMeasuring,\n open,\n setOpen,\n ...rest\n } = props;\n\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-tabs-next-overflow-list\",\n css: tabOverflowListCss,\n window: targetWindow,\n });\n\n const { OverflowIcon } = useIcon();\n\n const { refs, x, y, strategy, context } = useFloatingUI({\n open: open,\n onOpenChange(open, _, reason) {\n if (reason === \"escape-key\") {\n queueMicrotask(() => {\n const allTabs =\n tabstripRef.current?.querySelectorAll<HTMLElement>(\n '[role=\"tab\"]:not([aria-hidden])',\n ) ?? [];\n const numberOfTabsInOverflow =\n listRef.current?.querySelectorAll<HTMLElement>('[role=\"tab\"]')\n .length ?? 0;\n\n allTabs[allTabs.length - numberOfTabsInOverflow - 1]?.focus({\n preventScroll: true,\n });\n });\n }\n\n setOpen(open);\n },\n placement: \"bottom-start\",\n middleware: [\n offset(1),\n size({\n apply({ elements, availableHeight }) {\n Object.assign(elements.floating.style, {\n maxHeight: `max(calc((var(--salt-size-base) + var(--salt-spacing-100)) * 5), calc(${availableHeight}px - var(--salt-spacing-100)))`,\n });\n },\n }),\n flip(),\n ],\n });\n\n const { getFloatingProps } = useInteractions([useDismiss(context)]);\n\n const rootRef = useRef<HTMLDivElement>(null);\n const handleRootRef = useForkRef(rootRef, ref);\n const listRef = useRef<HTMLDivElement>(null);\n const handleListRef = useForkRef<HTMLDivElement>(listRef, refs.setFloating);\n\n const handleFocusOutside = useCallback(() => {\n setOpen(false);\n }, [setOpen]);\n\n useFocusOutside(\n rootRef,\n handleFocusOutside,\n open,\n \"[data-floating-ui-portal]\",\n );\n\n const handleClick = () => {\n if (!open) {\n listRef.current\n ?.querySelectorAll<HTMLElement>('[role=\"tab\"]')[0]\n ?.focus({ preventScroll: true });\n } else {\n setOpen(false);\n }\n };\n\n const handleFocus = () => {\n setOpen(true);\n };\n\n const handleButtonRef = useForkRef<HTMLButtonElement>(\n buttonRef,\n refs.setReference,\n );\n\n const listId = useId();\n\n const childCount = Children.count(children);\n if (childCount === 0 && !isMeasuring) return null;\n\n return (\n <div className={withBaseName()} ref={handleRootRef} data-overflow>\n <Button\n data-overflowbutton\n tabIndex={-1}\n appearance=\"transparent\"\n sentiment=\"neutral\"\n onClick={handleClick}\n ref={handleButtonRef}\n aria-label={`Overflow menu. ${childCount} tabs hidden`}\n aria-expanded={open}\n aria-controls={listId}\n aria-hidden=\"true\"\n role=\"tab\"\n aria-haspopup\n {...rest}\n >\n <OverflowIcon aria-hidden />\n </Button>\n <FloatingTree>\n <div\n ref={handleListRef}\n {...getFloatingProps({\n onFocus: handleFocus,\n role: \"presentation\",\n })}\n className={withBaseName(\"list\")}\n data-hidden={!open}\n style={\n open\n ? { left: x ?? 0, top: y ?? 0, position: strategy }\n : undefined\n }\n id={listId}\n >\n <div className={withBaseName(\"listContainer\")}>{children}</div>\n </div>\n </FloatingTree>\n </div>\n );\n },\n);\n"],"names":["TabOverflowList","tabOverflowListCss","open"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import type { DateFrameworkType } from "@salt-ds/date-adapters";
2
2
  import { type ReactNode } from "react";
3
+ import { type DatePickerOpenChangeReason } from "./DatePickerOverlayProvider";
3
4
  import { type UseDatePickerRangeProps, type UseDatePickerSingleProps } from "./useDatePicker";
4
5
  /**
5
6
  * Base props for DatePicker.
@@ -9,11 +10,15 @@ export interface DatePickerBaseProps {
9
10
  children?: ReactNode;
10
11
  /** the open/close state of the overlay. The open/close state will be controlled when this prop is provided. */
11
12
  open?: boolean;
13
+ /** When `open` is uncontrolled, set this to `true` to open on click */
14
+ openOnClick?: boolean;
12
15
  /**
13
16
  * Handler for when open state changes
14
17
  * @param newOpen - true when opened
18
+ * @param event - event that triggered the state change
19
+ * @param reason - reason for the the state change
15
20
  */
16
- onOpen?: (newOpen: boolean) => void;
21
+ onOpenChange?: (newOpen: boolean, event?: Event, reason?: DatePickerOpenChangeReason) => void;
17
22
  /**
18
23
  * the initial open/close state of the overlay, when the open/close state is un-controlled.
19
24
  */
@@ -45,8 +45,9 @@ interface DatePickerBaseState<TDate extends DateFrameworkType> {
45
45
  helpers: {
46
46
  /**
47
47
  * Cancels the DatePicker action.
48
+ * @param event - event that triggered the state change
48
49
  */
49
- cancel: () => void;
50
+ cancel: (event?: Event) => void;
50
51
  /**
51
52
  * Sets the enableApply state.
52
53
  * @param newEnableApply - The new value for enableApply.
@@ -1,6 +1,8 @@
1
- import { useInteractions } from "@floating-ui/react";
1
+ import { type ElementProps, type FloatingContext, type OpenChangeReason as FloatingUIOpenChangeReason, useInteractions } from "@floating-ui/react";
2
2
  import { useFloatingUI } from "@salt-ds/core";
3
3
  import { type ReactNode } from "react";
4
+ /** Reason for overlay state change, can be a custom reason */
5
+ export declare type DatePickerOpenChangeReason = FloatingUIOpenChangeReason | "apply" | "cancel" | string;
4
6
  /**
5
7
  * Interface representing the state for a DatePicker overlay.
6
8
  */
@@ -29,13 +31,15 @@ interface DatePickerOverlayHelpers {
29
31
  /**
30
32
  * Sets the open state of the overlay.
31
33
  * @param newOpen - The new value for the open state.
34
+ * @param event - event that triggered the state change
35
+ * @param reason - reason for the the state change
32
36
  */
33
- setOpen: (newOpen: boolean) => void;
37
+ setOpen: (newOpen: boolean, event?: Event, reason?: DatePickerOpenChangeReason) => void;
34
38
  /**~
35
39
  * Register a callback for when onDismiss is called
36
40
  * @param onDismissCallback
37
41
  */
38
- setOnDismiss: (onDismissCallback: () => void) => void;
42
+ setOnDismiss: (onDismissCallback: (event?: Event) => void) => void;
39
43
  }
40
44
  /**
41
45
  * Interface representing the context type for a DatePicker overlay.
@@ -58,11 +62,17 @@ interface DatePickerOverlayProviderProps {
58
62
  * If `true`, the overlay is open.
59
63
  */
60
64
  open?: boolean;
65
+ /**
66
+ * When `open` is uncontrolled, set this to `true` to open on click
67
+ */
68
+ openOnClick?: boolean;
61
69
  /**
62
70
  * Handler for when open state changes
63
71
  * @param newOpen - true when opened
72
+ * @param event - event that triggered the state change
73
+ * @param reason - reason for the the state change
64
74
  */
65
- onOpen?: (newOpen: boolean) => void;
75
+ onOpenChange?: (newOpen: boolean, event?: Event, reason?: DatePickerOpenChangeReason) => void;
66
76
  /**
67
77
  * The default open state of the overlay.
68
78
  */
@@ -71,6 +81,10 @@ interface DatePickerOverlayProviderProps {
71
81
  * The content to be rendered inside the overlay provider.
72
82
  */
73
83
  children: ReactNode;
84
+ /**
85
+ * A factory method to create a set of interaction, if provided overrides the default interactions
86
+ */
87
+ interactions?: (context: FloatingContext) => Array<ElementProps>;
74
88
  /**
75
89
  * When true, shouldn't open the overlay.
76
90
  */
@@ -13,5 +13,5 @@ export interface DatePickerRangeInputProps<TDate extends DateFrameworkType> exte
13
13
  */
14
14
  validate?: (date: DateRangeSelection<TDate> | null, details: DateInputRangeDetails) => DateInputRangeDetails;
15
15
  }
16
- export declare function defaultRangeValidator<TDate extends DateFrameworkType>(dateAdapter: SaltDateAdapter<TDate>, date: DateRangeSelection<TDate> | null, details: DateInputRangeDetails, minDate: TDate | undefined, maxDate: TDate | undefined): DateInputRangeDetails;
16
+ export declare function defaultRangeValidator<TDate extends DateFrameworkType>(dateAdapter: SaltDateAdapter<TDate>, date: DateRangeSelection<TDate> | null, details: DateInputRangeDetails, minDate?: TDate, maxDate?: TDate): DateInputRangeDetails;
17
17
  export declare const DatePickerRangeInput: import("react").ForwardRefExoticComponent<DatePickerRangeInputProps<unknown> & import("react").RefAttributes<HTMLDivElement>>;
@@ -2,6 +2,7 @@ export * from "./DatePicker";
2
2
  export * from "./DatePickerActions";
3
3
  export * from "./DatePickerContext";
4
4
  export * from "./DatePickerOverlay";
5
+ export * from "./DatePickerOverlayProvider";
5
6
  export * from "./DatePickerRangeInput";
6
7
  export * from "./DatePickerRangePanel";
7
8
  export * from "./DatePickerSingleInput";
@@ -0,0 +1,14 @@
1
+ import type { ElementProps, FloatingContext } from "@floating-ui/react";
2
+ export interface UseKeyboardProps {
3
+ /**
4
+ * Whether the hook is enabled
5
+ * @default true
6
+ */
7
+ enabled?: boolean;
8
+ }
9
+ /**
10
+ * Floating UI Interactions hook, that will open DatePicker on keydown
11
+ * @param context
12
+ * @param props
13
+ */
14
+ export declare function useKeyboard(context: FloatingContext, props: UseKeyboardProps): ElementProps;
@@ -1,6 +1,6 @@
1
1
  export type { SelectHandler, SelectionChangeHandler, SelectionStrategy, useCollectionItems, } from "./common-hooks";
2
- export type { ListChangeHandler as ListChangeHandlerDeprecated, ListSelectHandler as ListSelectHandlerDeprecated, } from "./list-deprecated";
3
2
  export { ListItemBase as ListItemBaseDeprecated, useListItem as useListItemDeprecated, } from "./list-deprecated";
3
+ export type { ListChangeHandler as ListChangeHandlerDeprecated, ListSelectHandler as ListSelectHandlerDeprecated, } from "./list-deprecated";
4
4
  export * from "./app-header";
5
5
  export * from "./breadcrumbs";
6
6
  export * from "./button-bar";
@@ -19,11 +19,11 @@ export * from "./deck-layout";
19
19
  export * from "./dialog";
20
20
  export * from "./dropdown";
21
21
  export * from "./editable-label";
22
- export { FormFieldLegacy as FormField, type FormFieldLegacyProps as FormFieldProps, FormLabel, } from "./form-field-legacy";
23
22
  export * from "./form-field-context-legacy";
23
+ export { FormFieldLegacy as FormField, FormLabel, type FormFieldLegacyProps as FormFieldProps, } from "./form-field-legacy";
24
24
  export * from "./form-group";
25
25
  export * from "./formatted-input";
26
- export { InputLegacy as Input, type InputLegacyProps as InputProps, StaticInputAdornment, } from "./input-legacy";
26
+ export { InputLegacy as Input, StaticInputAdornment, type InputLegacyProps as InputProps, } from "./input-legacy";
27
27
  export * from "./layer-layout";
28
28
  export * from "./list";
29
29
  export * from "./list-next";
@@ -31,6 +31,7 @@ export * from "./localization-provider";
31
31
  export * from "./logo";
32
32
  export * from "./menu-button";
33
33
  export * from "./metric";
34
+ export * from "./number-input";
34
35
  export * from "./overlay";
35
36
  export * from "./portal";
36
37
  export * from "./query-input";
@@ -40,7 +41,6 @@ export * from "./slider";
40
41
  export * from "./splitter";
41
42
  export * from "./static-list";
42
43
  export * from "./stepped-tracker";
43
- export * from "./stepper-input";
44
44
  export * from "./system-status";
45
45
  export * from "./tabs";
46
46
  export * from "./tabs-next";
@@ -1,6 +1,6 @@
1
1
  import { type ValidationStatus } from "@salt-ds/core";
2
2
  import { type ComponentPropsWithoutRef, type InputHTMLAttributes, type ReactNode, type Ref, type SyntheticEvent } from "react";
3
- export interface StepperInputProps extends Omit<ComponentPropsWithoutRef<"div">, "onChange"> {
3
+ export interface NumberInputProps extends Omit<ComponentPropsWithoutRef<"div">, "onChange"> {
4
4
  /**
5
5
  * A boolean. When `true`, the input will receive a full border.
6
6
  */
@@ -14,7 +14,7 @@ export interface StepperInputProps extends Omit<ComponentPropsWithoutRef<"div">,
14
14
  */
15
15
  defaultValue?: number | string;
16
16
  /**
17
- * If `true`, the stepper input will be disabled.
17
+ * If `true`, the number input will be disabled.
18
18
  */
19
19
  disabled?: boolean;
20
20
  /**
@@ -28,7 +28,7 @@ export interface StepperInputProps extends Omit<ComponentPropsWithoutRef<"div">,
28
28
  */
29
29
  endAdornment?: ReactNode;
30
30
  /**
31
- * Whether to hide the stepper buttons. Defaults to `false`.
31
+ * Whether to hide the number buttons. Defaults to `false`.
32
32
  * @default false
33
33
  */
34
34
  hideButtons?: boolean;
@@ -51,7 +51,7 @@ export interface StepperInputProps extends Omit<ComponentPropsWithoutRef<"div">,
51
51
  */
52
52
  min?: number;
53
53
  /**
54
- * Callback when stepper input value is changed.
54
+ * Callback when number input value is changed.
55
55
  * @param event - the event triggers value change, could be undefined during increment / decrement button long press
56
56
  */
57
57
  onChange?: (event: SyntheticEvent | undefined, value: number | string) => void;
@@ -68,7 +68,7 @@ export interface StepperInputProps extends Omit<ComponentPropsWithoutRef<"div">,
68
68
  */
69
69
  startAdornment?: ReactNode;
70
70
  /**
71
- * The amount to increment or decrement the value by when using the stepper buttons or Up Arrow and Down Arrow keys. Default to 1.
71
+ * The amount to increment or decrement the value by when using the number buttons or Up Arrow and Down Arrow keys. Default to 1.
72
72
  * @default 1
73
73
  */
74
74
  step?: number;
@@ -93,8 +93,8 @@ export interface StepperInputProps extends Omit<ComponentPropsWithoutRef<"div">,
93
93
  */
94
94
  variant?: "primary" | "secondary";
95
95
  /**
96
- * The value of the stepper input. The component will be controlled if this prop is provided.
96
+ * The value of the number input. The component will be controlled if this prop is provided.
97
97
  */
98
98
  value?: number | string | undefined;
99
99
  }
100
- export declare const StepperInput: import("react").ForwardRefExoticComponent<StepperInputProps & import("react").RefAttributes<HTMLDivElement>>;
100
+ export declare const NumberInput: import("react").ForwardRefExoticComponent<NumberInputProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,2 @@
1
+ export * from "./useNumberInput";
2
+ export * from "./NumberInput";
@@ -1,9 +1,9 @@
1
1
  import { type Dispatch, type MouseEvent, type MutableRefObject, type SetStateAction, type SyntheticEvent } from "react";
2
- import type { StepperInputProps } from "./StepperInput";
2
+ import type { NumberInputProps } from "./NumberInput";
3
3
  /**
4
4
  * Manages increment / decrement logic
5
5
  */
6
- export declare const useStepperInput: ({ decimalPlaces, disabled, inputRef, max, min, onChange, readOnly, setValue, step, stepBlock, value, }: Pick<StepperInputProps, "value" | "max" | "min" | "onChange" | "disabled" | "readOnly" | "step" | "inputRef" | "decimalPlaces" | "stepBlock"> & {
6
+ export declare const useNumberInput: ({ decimalPlaces, disabled, inputRef, max, min, onChange, readOnly, setValue, step, stepBlock, value, }: Pick<NumberInputProps, "value" | "max" | "min" | "onChange" | "disabled" | "readOnly" | "step" | "inputRef" | "decimalPlaces" | "stepBlock"> & {
7
7
  setValue: Dispatch<SetStateAction<string | number | undefined>>;
8
8
  inputRef: MutableRefObject<HTMLInputElement | null>;
9
9
  }) => {