@vuu-ui/vuu-ui-controls 2.1.19-beta.1 → 2.1.19-beta.2

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 (180) hide show
  1. package/package.json +12 -13
  2. package/src/calendar/Calendar.css.js +10 -0
  3. package/src/calendar/Calendar.js +70 -0
  4. package/src/calendar/index.js +4 -0
  5. package/src/calendar/internal/CalendarCarousel.css.js +19 -0
  6. package/src/calendar/internal/CalendarCarousel.js +73 -0
  7. package/src/calendar/internal/CalendarContext.js +9 -0
  8. package/src/calendar/internal/CalendarDay.css.js +116 -0
  9. package/src/calendar/internal/CalendarDay.js +64 -0
  10. package/src/calendar/internal/CalendarMonth.css.js +13 -0
  11. package/src/calendar/internal/CalendarMonth.js +43 -0
  12. package/src/calendar/internal/CalendarNavigation.css.js +24 -0
  13. package/src/calendar/internal/CalendarNavigation.js +185 -0
  14. package/src/calendar/internal/CalendarWeekHeader.css.js +23 -0
  15. package/src/calendar/internal/CalendarWeekHeader.js +31 -0
  16. package/src/calendar/internal/useFocusManagement.js +66 -0
  17. package/src/calendar/internal/utils.js +57 -0
  18. package/src/calendar/useCalendar.js +116 -0
  19. package/src/calendar/useCalendarDay.js +74 -0
  20. package/src/calendar/useSelection.js +202 -0
  21. package/src/column-picker/ColumnPicker.css.js +8 -0
  22. package/src/column-picker/ColumnPicker.js +108 -0
  23. package/src/column-picker/ColumnSearch.css.js +61 -0
  24. package/src/column-picker/ColumnSearch.js +66 -0
  25. package/src/column-picker/index.js +2 -0
  26. package/src/column-picker/moving-window.js +49 -0
  27. package/src/common-hooks/index.js +3 -0
  28. package/src/common-hooks/selectionTypes.js +8 -0
  29. package/src/common-hooks/use-resize-observer.js +122 -0
  30. package/src/common-hooks/useControlled.js +45 -0
  31. package/src/context-panel-provider/ContextPanelProvider.js +80 -0
  32. package/src/cycle-state-button/CycleStateButton.js +30 -0
  33. package/src/cycle-state-button/index.js +1 -0
  34. package/src/date-input/DateInput.css.js +195 -0
  35. package/src/date-input/DateInput.js +210 -0
  36. package/src/date-input/index.js +1 -0
  37. package/src/date-picker/DatePicker.js +137 -0
  38. package/src/date-picker/DatePickerContext.js +20 -0
  39. package/src/date-picker/DatePickerPanel.css.js +25 -0
  40. package/src/date-picker/DatePickerPanel.js +124 -0
  41. package/src/date-picker/index.js +1 -0
  42. package/src/drag-drop/DragDropProvider.js +123 -0
  43. package/src/drag-drop/DragDropState.js +25 -0
  44. package/src/drag-drop/Draggable.css.js +57 -0
  45. package/src/drag-drop/Draggable.js +77 -0
  46. package/src/drag-drop/DropIndicator.css.js +11 -0
  47. package/src/drag-drop/DropIndicator.js +28 -0
  48. package/src/drag-drop/dragDropTypes.js +3 -0
  49. package/src/drag-drop/drop-target-utils.js +199 -0
  50. package/src/drag-drop/index.js +6 -0
  51. package/src/drag-drop/useAutoScroll.js +53 -0
  52. package/src/drag-drop/useDragDisplacers.js +126 -0
  53. package/src/drag-drop/useDragDrop.js +435 -0
  54. package/src/drag-drop/useDragDropCopy.js +22 -0
  55. package/src/drag-drop/useDragDropIndicator.js +182 -0
  56. package/src/drag-drop/useDragDropNaturalMovement.js +205 -0
  57. package/src/drag-drop/useDropIndicator.js +21 -0
  58. package/src/drag-drop/useGlobalDragDrop.js +67 -0
  59. package/src/drag-drop/useTransition.js +11 -0
  60. package/src/editable/index.js +1 -0
  61. package/src/editable/useEditableText.js +199 -0
  62. package/src/editable-label/EditableLabel.css.js +81 -0
  63. package/src/editable-label/EditableLabel.js +125 -0
  64. package/src/editable-label/index.js +1 -0
  65. package/src/expando-input/ExpandoInput.css.js +67 -0
  66. package/src/expando-input/ExpandoInput.js +40 -0
  67. package/src/expando-input/index.js +1 -0
  68. package/src/highlighter/Highlighter.css.js +8 -0
  69. package/src/highlighter/Highlighter.js +27 -0
  70. package/src/highlighter/index.js +1 -0
  71. package/src/hover-overlay/HoverOverlay.js +92 -0
  72. package/src/icon-button/Icon.css.js +8 -0
  73. package/src/icon-button/Icon.js +26 -0
  74. package/src/icon-button/IconButton.css.js +10 -0
  75. package/src/icon-button/IconButton.js +28 -0
  76. package/src/icon-button/ToggleIconButton.css.js +47 -0
  77. package/src/icon-button/ToggleIconButton.js +26 -0
  78. package/src/icon-button/index.js +3 -0
  79. package/src/index.js +31 -0
  80. package/src/instrument-picker/SearchCell.css.js +17 -0
  81. package/src/instrument-picker/SearchCell.js +29 -0
  82. package/src/instrument-picker/TablePicker.css.js +23 -0
  83. package/src/instrument-picker/TablePicker.js +89 -0
  84. package/src/instrument-picker/index.js +1 -0
  85. package/src/instrument-picker/moving-window.js +49 -0
  86. package/src/instrument-picker/useDataSource.js +38 -0
  87. package/src/instrument-picker/useTablePicker.js +136 -0
  88. package/src/measured-container/MeasuredContainer.css.js +11 -0
  89. package/src/measured-container/MeasuredContainer.js +50 -0
  90. package/src/measured-container/index.js +2 -0
  91. package/src/measured-container/useMeasuredContainer.js +156 -0
  92. package/src/modal-provider/ModalProvider.js +147 -0
  93. package/src/overflow-container/OverflowContainer.css.js +135 -0
  94. package/src/overflow-container/OverflowContainer.js +87 -0
  95. package/src/overflow-container/index.js +2 -0
  96. package/src/overflow-container/overflow-utils.js +211 -0
  97. package/src/overflow-container/useOverflowContainer.js +108 -0
  98. package/src/price-ticker/PriceTicker.css.js +32 -0
  99. package/src/price-ticker/PriceTicker.js +51 -0
  100. package/src/price-ticker/index.js +1 -0
  101. package/src/prompt/Prompt.css.js +48 -0
  102. package/src/prompt/Prompt.js +112 -0
  103. package/src/sortable-list/SortableList.js +39 -0
  104. package/src/split-button/SplitButton.css.js +117 -0
  105. package/src/split-button/SplitButton.js +60 -0
  106. package/src/split-button/SplitStateButton.css.js +66 -0
  107. package/src/split-button/SplitStateButton.js +23 -0
  108. package/src/split-button/index.js +2 -0
  109. package/src/split-button/useSplitButton.js +61 -0
  110. package/src/table-search/SearchCell.css.js +20 -0
  111. package/src/table-search/SearchCell.js +26 -0
  112. package/src/table-search/TableSearch.css.js +27 -0
  113. package/src/table-search/TableSearch.js +81 -0
  114. package/src/table-search/index.js +1 -0
  115. package/src/table-search/moving-window.js +49 -0
  116. package/src/table-search/useTableSearch.js +30 -0
  117. package/src/tabs-next/TabBar.css.js +26 -0
  118. package/src/tabs-next/TabBar.js +27 -0
  119. package/src/tabs-next/TabListNext.css.js +36 -0
  120. package/src/tabs-next/TabListNext.js +94 -0
  121. package/src/tabs-next/TabNext.css.js +76 -0
  122. package/src/tabs-next/TabNext.js +91 -0
  123. package/src/tabs-next/TabNextAction.js +26 -0
  124. package/src/tabs-next/TabNextContext.js +14 -0
  125. package/src/tabs-next/TabNextPanel.css.js +17 -0
  126. package/src/tabs-next/TabNextPanel.js +69 -0
  127. package/src/tabs-next/TabNextTrigger.css.js +22 -0
  128. package/src/tabs-next/TabNextTrigger.js +66 -0
  129. package/src/tabs-next/TabOverflowList.css.js +77 -0
  130. package/src/tabs-next/TabOverflowList.js +115 -0
  131. package/src/tabs-next/TabsNext.js +149 -0
  132. package/src/tabs-next/TabsNextContext.js +28 -0
  133. package/src/tabs-next/hooks/useCollection.js +80 -0
  134. package/src/tabs-next/hooks/useFocusOutside.js +23 -0
  135. package/src/tabs-next/hooks/useOverflow.js +118 -0
  136. package/src/tabs-next/index.js +7 -0
  137. package/src/tabstrip/Tab.css.js +148 -0
  138. package/src/tabstrip/Tab.js +107 -0
  139. package/src/tabstrip/TabMenu.css.js +8 -0
  140. package/src/tabstrip/TabMenu.js +48 -0
  141. package/src/tabstrip/TabMenuOptions.js +14 -0
  142. package/src/tabstrip/TabsTypes.js +0 -0
  143. package/src/tabstrip/Tabstrip.css.js +121 -0
  144. package/src/tabstrip/Tabstrip.js +106 -0
  145. package/src/tabstrip/ThemeTabstrip.css.js +20 -0
  146. package/src/tabstrip/index.js +4 -0
  147. package/src/tabstrip/tabstrip-dom-utils.js +11 -0
  148. package/src/tabstrip/useAnimatedSelectionThumb.js +68 -0
  149. package/src/tabstrip/useKeyboardNavigation.js +191 -0
  150. package/src/tabstrip/useSelection.js +50 -0
  151. package/src/tabstrip/useTabstrip.js +181 -0
  152. package/src/time-input/MaskedInput.js +285 -0
  153. package/src/time-input/TimeInput.css.js +39 -0
  154. package/src/time-input/TimeInput.js +37 -0
  155. package/src/time-input/useTimeInput.js +82 -0
  156. package/src/toolbar/Toolbar.css.js +46 -0
  157. package/src/toolbar/Toolbar.js +62 -0
  158. package/src/toolbar/index.js +1 -0
  159. package/src/toolbar/toolbar-dom-utils.js +11 -0
  160. package/src/toolbar/useKeyboardNavigation.js +240 -0
  161. package/src/toolbar/useSelection.js +82 -0
  162. package/src/toolbar/useToolbar.js +73 -0
  163. package/src/utils/deprecated-types.js +0 -0
  164. package/src/utils/escapeRegExp.js +5 -0
  165. package/src/utils/forwardCallbackProps.js +15 -0
  166. package/src/utils/index.js +5 -0
  167. package/src/utils/isOverflowElement.js +2 -0
  168. package/src/utils/isPlainObject.js +2 -0
  169. package/src/vuu-date-picker/VuuDatePicker.js +92 -0
  170. package/src/vuu-date-picker/index.js +1 -0
  171. package/src/vuu-input/VuuInput.css.js +13 -0
  172. package/src/vuu-input/VuuInput.js +85 -0
  173. package/src/vuu-input/index.js +1 -0
  174. package/src/vuu-time-picker/TimeRangePicker.js +0 -0
  175. package/src/vuu-time-picker/VuuTimePicker.css.js +14 -0
  176. package/src/vuu-time-picker/VuuTimePicker.js +26 -0
  177. package/src/vuu-typeahead-input/VuuTypeaheadInput.css.js +49 -0
  178. package/src/vuu-typeahead-input/VuuTypeaheadInput.js +46 -0
  179. package/src/vuu-typeahead-input/index.js +1 -0
  180. package/src/vuu-typeahead-input/useVuuTypeaheadInput.js +140 -0
@@ -0,0 +1,185 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { Button, Dropdown, Option, Tooltip, makePrefixer, useListControlContext } from "@salt-ds/core";
3
+ import { ChevronLeftIcon, ChevronRightIcon } from "@salt-ds/icons";
4
+ import { clsx } from "clsx";
5
+ import { forwardRef } from "react";
6
+ import { useCalendarContext } from "./CalendarContext.js";
7
+ import { isSameMonth, isSameYear } from "@internationalized/date";
8
+ import { useComponentCssInjection } from "@salt-ds/styles";
9
+ import { useWindow } from "@salt-ds/window";
10
+ import CalendarNavigation_0 from "./CalendarNavigation.css";
11
+ import { formatDate, monthDiff, monthsForLocale } from "./utils.js";
12
+ const withBaseName = makePrefixer("saltCalendarNavigation");
13
+ function useCalendarNavigation() {
14
+ const { state: { visibleMonth, minDate, maxDate }, helpers: { setVisibleMonth, isDayVisible, isOutsideAllowedYears, isOutsideAllowedMonths } } = useCalendarContext();
15
+ const moveToNextMonth = (event)=>{
16
+ setVisibleMonth(event, visibleMonth.add({
17
+ months: 1
18
+ }));
19
+ };
20
+ const moveToPreviousMonth = (event)=>{
21
+ setVisibleMonth(event, visibleMonth.subtract({
22
+ months: 1
23
+ }));
24
+ };
25
+ const moveToMonth = (event, month)=>{
26
+ let newMonth = month;
27
+ if (!isOutsideAllowedYears(newMonth)) {
28
+ if (isOutsideAllowedMonths(newMonth)) {
29
+ const navigableMonths = monthsForLocale(visibleMonth).filter((n)=>!isOutsideAllowedMonths(n));
30
+ newMonth = navigableMonths.reduce((closestMonth, currentMonth)=>Math.abs(monthDiff(currentMonth, newMonth)) < Math.abs(monthDiff(closestMonth, newMonth)) ? currentMonth : closestMonth);
31
+ }
32
+ setVisibleMonth(event, newMonth);
33
+ }
34
+ };
35
+ const months = monthsForLocale(visibleMonth);
36
+ const years = [
37
+ -2,
38
+ -1,
39
+ 0,
40
+ 1,
41
+ 2
42
+ ].map((delta)=>visibleMonth.add({
43
+ years: delta
44
+ })).filter((year)=>!isOutsideAllowedYears(year));
45
+ const selectedMonth = months.find((month)=>isSameMonth(month, visibleMonth));
46
+ const selectedYear = years.find((year)=>isSameYear(year, visibleMonth));
47
+ const canNavigatePrevious = !(minDate && isDayVisible(minDate));
48
+ const canNavigateNext = !(maxDate && isDayVisible(maxDate));
49
+ return {
50
+ moveToNextMonth,
51
+ moveToPreviousMonth,
52
+ moveToMonth,
53
+ visibleMonth,
54
+ months,
55
+ years,
56
+ canNavigateNext,
57
+ canNavigatePrevious,
58
+ selectedMonth,
59
+ selectedYear,
60
+ isOutsideAllowedMonths
61
+ };
62
+ }
63
+ const OptionWithTooltip = ({ value, children, disabled, tooltipContent })=>{
64
+ const { activeState, openState } = useListControlContext();
65
+ const open = activeState?.value === value;
66
+ return /*#__PURE__*/ jsx(Tooltip, {
67
+ placement: "right",
68
+ open: open && openState,
69
+ disabled: !disabled,
70
+ content: tooltipContent,
71
+ enterDelay: 0,
72
+ leaveDelay: 0,
73
+ children: /*#__PURE__*/ jsx(Option, {
74
+ value: value,
75
+ disabled: disabled,
76
+ children: children
77
+ })
78
+ });
79
+ };
80
+ const CalendarNavigation_CalendarNavigation = /*#__PURE__*/ forwardRef(function(props, ref) {
81
+ const { className, MonthDropdownProps, YearDropdownProps, hideYearDropdown, borderedDropdown, ...rest } = props;
82
+ const targetWindow = useWindow();
83
+ useComponentCssInjection({
84
+ testId: "salt-calendar-navigation",
85
+ css: CalendarNavigation_0,
86
+ window: targetWindow
87
+ });
88
+ const { moveToPreviousMonth, moveToNextMonth, moveToMonth, months, years, canNavigateNext, canNavigatePrevious, selectedMonth, selectedYear, isOutsideAllowedMonths } = useCalendarNavigation();
89
+ const handleNavigatePrevious = (event)=>{
90
+ moveToPreviousMonth(event);
91
+ };
92
+ const handleNavigateNext = (event)=>{
93
+ moveToNextMonth(event);
94
+ };
95
+ const handleMonthSelect = (event, month)=>{
96
+ moveToMonth(event, month[0]);
97
+ };
98
+ const handleYearSelect = (event, year)=>{
99
+ moveToMonth(event, year[0]);
100
+ };
101
+ const formatMonth = (date)=>date ? formatDate(date, {
102
+ month: hideYearDropdown ? "long" : "short"
103
+ }) : "";
104
+ const formatYear = (date)=>date ? formatDate(date, {
105
+ year: "numeric"
106
+ }) : "";
107
+ return /*#__PURE__*/ jsxs("div", {
108
+ className: clsx(withBaseName(), {
109
+ [withBaseName("hideYearDropdown")]: hideYearDropdown
110
+ }, className),
111
+ ref: ref,
112
+ ...rest,
113
+ children: [
114
+ /*#__PURE__*/ jsx(Tooltip, {
115
+ placement: "top",
116
+ disabled: canNavigatePrevious,
117
+ content: "Past dates are out of range",
118
+ enterDelay: 0,
119
+ leaveDelay: 0,
120
+ children: /*#__PURE__*/ jsx(Button, {
121
+ disabled: !canNavigatePrevious,
122
+ variant: "secondary",
123
+ onClick: handleNavigatePrevious,
124
+ focusableWhenDisabled: true,
125
+ children: /*#__PURE__*/ jsx(ChevronLeftIcon, {
126
+ "aria-label": "Previous Month"
127
+ })
128
+ })
129
+ }),
130
+ /*#__PURE__*/ jsxs("div", {
131
+ className: withBaseName("dropdowns"),
132
+ children: [
133
+ /*#__PURE__*/ jsx(Dropdown, {
134
+ bordered: borderedDropdown,
135
+ "aria-label": "Month Dropdown",
136
+ selected: selectedMonth ? [
137
+ selectedMonth
138
+ ] : [],
139
+ value: formatMonth(selectedMonth),
140
+ onSelectionChange: handleMonthSelect,
141
+ ...MonthDropdownProps,
142
+ children: months.map((month)=>/*#__PURE__*/ jsx(OptionWithTooltip, {
143
+ value: month,
144
+ disabled: isOutsideAllowedMonths(month),
145
+ tooltipContent: "This month is out of range",
146
+ children: formatMonth(month)
147
+ }, formatMonth(month)))
148
+ }),
149
+ !hideYearDropdown && /*#__PURE__*/ jsx(Dropdown, {
150
+ "aria-label": "Year Dropdown",
151
+ selected: selectedYear ? [
152
+ selectedYear
153
+ ] : [],
154
+ value: formatYear(selectedYear),
155
+ onSelectionChange: handleYearSelect,
156
+ bordered: borderedDropdown,
157
+ ...YearDropdownProps,
158
+ children: years.map((year)=>/*#__PURE__*/ jsx(OptionWithTooltip, {
159
+ value: year,
160
+ tooltipContent: "This year is out of range",
161
+ children: formatYear(year)
162
+ }, formatYear(year)))
163
+ })
164
+ ]
165
+ }),
166
+ /*#__PURE__*/ jsx(Tooltip, {
167
+ placement: "top",
168
+ disabled: canNavigateNext,
169
+ content: "Future dates are out of range",
170
+ enterDelay: 0,
171
+ leaveDelay: 0,
172
+ children: /*#__PURE__*/ jsx(Button, {
173
+ disabled: !canNavigateNext,
174
+ variant: "secondary",
175
+ onClick: handleNavigateNext,
176
+ focusableWhenDisabled: true,
177
+ children: /*#__PURE__*/ jsx(ChevronRightIcon, {
178
+ "aria-label": "Next Month"
179
+ })
180
+ })
181
+ })
182
+ ]
183
+ });
184
+ });
185
+ export { CalendarNavigation_CalendarNavigation as CalendarNavigation };
@@ -0,0 +1,23 @@
1
+ const css = `
2
+ .saltCalendarWeekHeader {
3
+ gap: var(--salt-size-border);
4
+ grid-template-columns: repeat(7, var(--salt-size-base));
5
+ text-align: center;
6
+ height: var(--salt-size-base);
7
+ margin: var(--salt-size-border);
8
+ align-items: center;
9
+ display: grid;
10
+ }
11
+
12
+ .saltCalendarWeekHeader-dayOfWeek {
13
+ width: var(--salt-size-base);
14
+ color: var(--salt-content-secondary-foreground);
15
+ font-family: var(--salt-text-fontFamily);
16
+ font-weight: var(--salt-text-fontWeight);
17
+ font-size: var(--salt-text-fontSize);
18
+ line-height: var(--salt-text-lineHeight);
19
+ }
20
+
21
+
22
+ `;
23
+ export default css;
@@ -0,0 +1,31 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { makePrefixer } from "@salt-ds/core";
3
+ import { clsx } from "clsx";
4
+ import { forwardRef } from "react";
5
+ import { daysForLocale } from "./utils.js";
6
+ import { useComponentCssInjection } from "@salt-ds/styles";
7
+ import { useWindow } from "@salt-ds/window";
8
+ import CalendarWeekHeader_0 from "./CalendarWeekHeader.css";
9
+ const withBaseName = makePrefixer("saltCalendarWeekHeader");
10
+ const CalendarWeekHeader_CalendarWeekHeader = /*#__PURE__*/ forwardRef(function({ className, ...rest }, ref) {
11
+ const weekdaysShort = daysForLocale("narrow");
12
+ const weekdaysLong = daysForLocale("long");
13
+ const targetWindow = useWindow();
14
+ useComponentCssInjection({
15
+ testId: "salt-calendar",
16
+ css: CalendarWeekHeader_0,
17
+ window: targetWindow
18
+ });
19
+ return /*#__PURE__*/ jsx("div", {
20
+ "data-testid": "CalendarWeekHeader",
21
+ className: clsx(withBaseName(), className),
22
+ ref: ref,
23
+ ...rest,
24
+ children: weekdaysShort.map((day, index)=>/*#__PURE__*/ jsx("small", {
25
+ "aria-hidden": true,
26
+ className: withBaseName("dayOfWeek"),
27
+ children: day
28
+ }, weekdaysLong[index]))
29
+ });
30
+ });
31
+ export { CalendarWeekHeader_CalendarWeekHeader as CalendarWeekHeader };
@@ -0,0 +1,66 @@
1
+ import { endOfWeek, startOfWeek } from "@internationalized/date";
2
+ import { useCalendarContext } from "./CalendarContext.js";
3
+ import { getCurrentLocale } from "./utils.js";
4
+ function useFocusManagement({ date }) {
5
+ const { helpers: { setFocusedDate } } = useCalendarContext();
6
+ const handleClick = (event)=>{
7
+ setFocusedDate(event, date);
8
+ };
9
+ const handleKeyDown = (event)=>{
10
+ let newDate = date;
11
+ switch(event.key){
12
+ case "ArrowUp":
13
+ newDate = date.subtract({
14
+ weeks: 1
15
+ });
16
+ break;
17
+ case "ArrowDown":
18
+ newDate = date.add({
19
+ weeks: 1
20
+ });
21
+ break;
22
+ case "ArrowLeft":
23
+ newDate = date.subtract({
24
+ days: 1
25
+ });
26
+ break;
27
+ case "ArrowRight":
28
+ newDate = date.add({
29
+ days: 1
30
+ });
31
+ break;
32
+ case "Home":
33
+ newDate = startOfWeek(date, getCurrentLocale());
34
+ break;
35
+ case "End":
36
+ newDate = endOfWeek(date, getCurrentLocale());
37
+ break;
38
+ case "PageUp":
39
+ newDate = event.shiftKey ? date.subtract({
40
+ years: 1
41
+ }) : date.subtract({
42
+ months: 1
43
+ });
44
+ break;
45
+ case "PageDown":
46
+ newDate = event.shiftKey ? date.add({
47
+ years: 1
48
+ }) : date.add({
49
+ months: 1
50
+ });
51
+ break;
52
+ default:
53
+ }
54
+ if (0 !== newDate.compare(date)) event.preventDefault();
55
+ setFocusedDate(event, newDate);
56
+ };
57
+ const handleFocus = (event)=>{
58
+ setFocusedDate(event, date);
59
+ };
60
+ return {
61
+ handleClick,
62
+ handleKeyDown,
63
+ handleFocus
64
+ };
65
+ }
66
+ export { useFocusManagement };
@@ -0,0 +1,57 @@
1
+ import { DateFormatter, createCalendar, getLocalTimeZone, isSameMonth, startOfMonth, startOfWeek, startOfYear, today } from "@internationalized/date";
2
+ const localTimezone = getLocalTimeZone();
3
+ function getCurrentLocale() {
4
+ return navigator.languages[0];
5
+ }
6
+ function getDateFormatter(options) {
7
+ return new DateFormatter(getCurrentLocale(), options);
8
+ }
9
+ function formatDate(date, options) {
10
+ const formatter = getDateFormatter(options);
11
+ return formatter.format(date.toDate(localTimezone));
12
+ }
13
+ function getCalender() {
14
+ const calendarIdentifier = getDateFormatter().resolvedOptions().calendar;
15
+ return createCalendar(calendarIdentifier);
16
+ }
17
+ function daysForLocale(weekday = "long") {
18
+ return [
19
+ ...Array(7).keys()
20
+ ].map((day)=>formatDate(startOfWeek(today(getLocalTimeZone()), getCurrentLocale()).add({
21
+ days: day
22
+ }), {
23
+ weekday
24
+ }));
25
+ }
26
+ function monthsForLocale(currentYear) {
27
+ const calendar = getCalender();
28
+ return [
29
+ ...Array(calendar.getMonthsInYear(currentYear)).keys()
30
+ ].map((month)=>startOfYear(currentYear).add({
31
+ months: month
32
+ }));
33
+ }
34
+ function mapDate(currentDate, currentMonth) {
35
+ return {
36
+ date: currentDate,
37
+ dateOfMonth: currentDate.month,
38
+ isCurrentMonth: isSameMonth(currentDate, currentMonth)
39
+ };
40
+ }
41
+ function generateVisibleDays(currentMonth) {
42
+ const totalDays = 42;
43
+ const currentLocale = getCurrentLocale();
44
+ const startDate = startOfWeek(startOfMonth(currentMonth), currentLocale);
45
+ return [
46
+ ...Array(totalDays).keys()
47
+ ].map((dayDelta)=>{
48
+ const day = startDate.add({
49
+ days: dayDelta
50
+ });
51
+ return mapDate(day, currentMonth);
52
+ });
53
+ }
54
+ function monthDiff(a, b) {
55
+ return b.month - a.month + 12 * (b.year - a.year);
56
+ }
57
+ export { daysForLocale, formatDate, generateVisibleDays, getCalender, getCurrentLocale, getDateFormatter, monthDiff, monthsForLocale };
@@ -0,0 +1,116 @@
1
+ import { endOfMonth, endOfYear, getLocalTimeZone, isSameDay, isSameMonth, startOfMonth, startOfYear, today } from "@internationalized/date";
2
+ import { useControlled } from "@salt-ds/core";
3
+ import { useCallback, useEffect, useState } from "react";
4
+ import { isRangeOrOffsetSelectionWithStartDate, useSelectionCalendar } from "./useSelection.js";
5
+ const defaultIsDayUnselectable = ()=>false;
6
+ const defaultIsDayHighlighted = ()=>false;
7
+ const defaultIsDayDisabled = ()=>false;
8
+ function useCalendar(props) {
9
+ const { selectedDate, defaultSelectedDate, visibleMonth: visibleMonthProp, hideYearDropdown, hideOutOfRangeDates, defaultVisibleMonth = today(getLocalTimeZone()), onSelectedDateChange, onVisibleMonthChange, isDayUnselectable = defaultIsDayUnselectable, isDayHighlighted = defaultIsDayHighlighted, isDayDisabled = defaultIsDayDisabled, minDate = hideYearDropdown ? startOfYear(today(getLocalTimeZone())) : void 0, maxDate = hideYearDropdown ? endOfYear(today(getLocalTimeZone())) : void 0, selectionVariant, onHoveredDateChange, hoveredDate } = props;
10
+ const [visibleMonth, setVisibleMonthState] = useControlled({
11
+ controlled: visibleMonthProp ? startOfMonth(visibleMonthProp) : void 0,
12
+ default: startOfMonth(defaultVisibleMonth),
13
+ name: "Calendar",
14
+ state: "visibleMonth"
15
+ });
16
+ const isOutsideAllowedDates = useCallback((date)=>null != minDate && date.compare(minDate) < 0 || null != maxDate && date.compare(maxDate) > 0, [
17
+ maxDate,
18
+ minDate
19
+ ]);
20
+ const isOutsideAllowedMonths = (date)=>null != minDate && endOfMonth(date).compare(minDate) < 0 || null != maxDate && startOfMonth(date).compare(maxDate) > 0;
21
+ const isOutsideAllowedYears = (date)=>null != minDate && endOfYear(date).compare(minDate) < 0 || null != maxDate && startOfYear(date).compare(maxDate) > 0;
22
+ const isDaySelectable = useCallback((date)=>!(date && (isDayUnselectable(date) || isDayDisabled(date) || isOutsideAllowedDates(date))), [
23
+ isDayUnselectable,
24
+ isDayDisabled,
25
+ isOutsideAllowedDates
26
+ ]);
27
+ const selectionManager = useSelectionCalendar({
28
+ defaultSelectedDate: defaultSelectedDate,
29
+ selectedDate,
30
+ onSelectedDateChange,
31
+ startDateOffset: "offset" === props.selectionVariant ? props.startDateOffset : (date)=>date,
32
+ endDateOffset: "offset" === props.selectionVariant ? props.endDateOffset : (date)=>date,
33
+ isDaySelectable,
34
+ selectionVariant,
35
+ onHoveredDateChange,
36
+ hoveredDate
37
+ });
38
+ const [calendarFocused, setCalendarFocused] = useState(false);
39
+ const isInVisibleMonth = (date)=>null != date && isSameMonth(date, visibleMonth);
40
+ const getInitialFocusedDate = ()=>{
41
+ const selectedDate = selectionManager.state.selectedDate;
42
+ if (("range" === selectionVariant || "offset" === selectionVariant) && isRangeOrOffsetSelectionWithStartDate(selectedDate)) {
43
+ if (isInVisibleMonth(selectedDate?.startDate)) return selectedDate.startDate;
44
+ if (isInVisibleMonth(selectedDate?.endDate)) return selectedDate.endDate;
45
+ if (selectedDate?.startDate && selectedDate?.endDate && visibleMonth.compare(selectedDate.startDate) < 0 && visibleMonth.compare(selectedDate.endDate) > 0) return startOfMonth(visibleMonth);
46
+ }
47
+ if ("multiselect" === selectionVariant && Array.isArray(selectedDate)) {
48
+ const selectionInMonth = selectedDate.filter((day)=>isInVisibleMonth(day)).sort((a, b)=>a.compare(b));
49
+ if (selectionInMonth.length > 0) return selectionInMonth[0];
50
+ }
51
+ if ("default" === selectionVariant && !isRangeOrOffsetSelectionWithStartDate(selectedDate) && !Array.isArray(selectedDate) && isInVisibleMonth(selectedDate)) return selectedDate;
52
+ if (isInVisibleMonth(today(getLocalTimeZone()))) return today(getLocalTimeZone());
53
+ return startOfMonth(visibleMonth);
54
+ };
55
+ const [focusedDate, setFocusedDateState] = useState(getInitialFocusedDate);
56
+ const isDayVisible = useCallback((date)=>{
57
+ const startInsideDays = startOfMonth(visibleMonth);
58
+ if (date.compare(startInsideDays) < 0) return false;
59
+ const endInsideDays = endOfMonth(visibleMonth);
60
+ return !(date.compare(endInsideDays) > 0);
61
+ }, [
62
+ visibleMonth
63
+ ]);
64
+ const setVisibleMonth = useCallback((event, newVisibleMonth)=>{
65
+ setVisibleMonthState(newVisibleMonth);
66
+ onVisibleMonthChange?.(event, newVisibleMonth);
67
+ }, [
68
+ onVisibleMonthChange,
69
+ setVisibleMonthState
70
+ ]);
71
+ const setFocusedDate = useCallback((event, date)=>{
72
+ if (isSameDay(date, focusedDate) || isOutsideAllowedDates(date)) return;
73
+ setFocusedDateState(date);
74
+ const shouldTransition = !isDayVisible(date) && isDaySelectable(date) && !isOutsideAllowedDates(date);
75
+ if (shouldTransition) setVisibleMonth(event, startOfMonth(date));
76
+ }, [
77
+ focusedDate,
78
+ isDaySelectable,
79
+ isDayVisible,
80
+ isOutsideAllowedDates,
81
+ setVisibleMonth
82
+ ]);
83
+ useEffect(()=>{
84
+ if (!isDayVisible(focusedDate)) setFocusedDateState(getInitialFocusedDate());
85
+ }, [
86
+ isDayVisible,
87
+ focusedDate,
88
+ visibleMonth
89
+ ]);
90
+ return {
91
+ state: {
92
+ visibleMonth,
93
+ focusedDate,
94
+ minDate,
95
+ maxDate,
96
+ selectionVariant,
97
+ hideOutOfRangeDates,
98
+ calendarFocused,
99
+ ...selectionManager.state
100
+ },
101
+ helpers: {
102
+ setVisibleMonth,
103
+ setFocusedDate,
104
+ setCalendarFocused,
105
+ isDayUnselectable,
106
+ isDayHighlighted,
107
+ isDayDisabled,
108
+ isDayVisible,
109
+ isOutsideAllowedDates,
110
+ isOutsideAllowedMonths,
111
+ isOutsideAllowedYears,
112
+ ...selectionManager.helpers
113
+ }
114
+ };
115
+ }
116
+ export { useCalendar };
@@ -0,0 +1,74 @@
1
+ import { getLocalTimeZone, isSameDay, isSameMonth, isToday } from "@internationalized/date";
2
+ import { useEffect } from "react";
3
+ import { useCalendarContext } from "./internal/CalendarContext.js";
4
+ import { useFocusManagement } from "./internal/useFocusManagement.js";
5
+ import { useSelectionDay } from "./useSelection.js";
6
+ function useCalendarDay({ date, month }, ref) {
7
+ const { state: { focusedDate, hideOutOfRangeDates, calendarFocused }, helpers: { isDayUnselectable, isDayHighlighted, isDayDisabled, isOutsideAllowedMonths } } = useCalendarContext();
8
+ const selectionManager = useSelectionDay({
9
+ date
10
+ });
11
+ const focusManager = useFocusManagement({
12
+ date
13
+ });
14
+ const handleClick = (event)=>{
15
+ selectionManager?.handleClick(event);
16
+ focusManager.handleClick(event);
17
+ };
18
+ const handleKeyDown = (event)=>{
19
+ focusManager.handleKeyDown(event);
20
+ selectionManager?.handleKeyDown(event);
21
+ };
22
+ const handleFocus = (event)=>{
23
+ focusManager.handleFocus(event);
24
+ };
25
+ const handleMouseOver = (event)=>{
26
+ selectionManager.handleMouseOver?.(event);
27
+ };
28
+ const eventHandlers = {
29
+ onClick: handleClick,
30
+ onKeyDown: handleKeyDown,
31
+ onFocus: handleFocus,
32
+ onMouseOver: handleMouseOver
33
+ };
34
+ const outOfRange = !isSameMonth(date, month);
35
+ const focused = isSameDay(date, focusedDate) && calendarFocused && !outOfRange;
36
+ const tabIndex = isSameDay(date, focusedDate) && !outOfRange ? 0 : -1;
37
+ const today = isToday(date, getLocalTimeZone());
38
+ const unselectableReason = isDayUnselectable(date);
39
+ const highlightedReason = isDayHighlighted(date);
40
+ const disabled = isDayDisabled(date) || outOfRange && isOutsideAllowedMonths(date);
41
+ const unselectable = Boolean(unselectableReason);
42
+ const highlighted = Boolean(highlightedReason);
43
+ const hidden = hideOutOfRangeDates && outOfRange;
44
+ useEffect(()=>{
45
+ if (focused) ref.current?.focus({
46
+ preventScroll: true
47
+ });
48
+ }, [
49
+ ref,
50
+ focused
51
+ ]);
52
+ return {
53
+ status: {
54
+ outOfRange,
55
+ today,
56
+ unselectable,
57
+ focused,
58
+ hidden,
59
+ disabled,
60
+ highlighted,
61
+ ...selectionManager.status
62
+ },
63
+ dayProps: {
64
+ tabIndex,
65
+ "aria-current": today ? "date" : void 0,
66
+ "aria-hidden": hidden ? "true" : void 0,
67
+ ...eventHandlers,
68
+ ...selectionManager.dayProps
69
+ },
70
+ unselectableReason,
71
+ highlightedReason
72
+ };
73
+ }
74
+ export { useCalendarDay };