@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,202 @@
1
+ import { CalendarDate, isSameDay } from "@internationalized/date";
2
+ import { makePrefixer, useControlled } from "@salt-ds/core";
3
+ import { clsx } from "clsx";
4
+ import { isPlainObject } from "../utils/index.js";
5
+ import { useCalendarContext } from "./internal/CalendarContext.js";
6
+ function addOrRemoveFromArray(array, item) {
7
+ if (Array.isArray(array)) {
8
+ if (array.find((element)=>isSameDay(element, item))) return array.filter((element)=>!isSameDay(element, item));
9
+ return array.concat(item);
10
+ }
11
+ return [
12
+ item
13
+ ];
14
+ }
15
+ const defaultOffset = (date)=>date;
16
+ function isRangeOrOffsetSelectionValue(selectionValue) {
17
+ return null != selectionValue && isPlainObject(selectionValue);
18
+ }
19
+ function isRangeOrOffsetSelectionWithStartDate(selectionValue) {
20
+ return isRangeOrOffsetSelectionValue(selectionValue) && Object.prototype.hasOwnProperty.call(selectionValue, "startDate");
21
+ }
22
+ const withBaseName = makePrefixer("saltCalendarDay");
23
+ function useSelectionCalendar(props) {
24
+ const { hoveredDate: hoveredDateProp, selectedDate: selectedDateProp, defaultSelectedDate, onHoveredDateChange, isDaySelectable, selectionVariant } = props;
25
+ const [selectedDate, setSelectedDateState] = useControlled({
26
+ controlled: selectedDateProp,
27
+ default: defaultSelectedDate,
28
+ name: "Calendar",
29
+ state: "selectedDate"
30
+ });
31
+ const getStartDateOffset = (date)=>{
32
+ if ("offset" === props.selectionVariant && props.startDateOffset) return props.startDateOffset(date);
33
+ return defaultOffset(date);
34
+ };
35
+ const getEndDateOffset = (date)=>{
36
+ if ("offset" === props.selectionVariant && props.endDateOffset) return props.endDateOffset(date);
37
+ return defaultOffset(date);
38
+ };
39
+ const setSelectedDate = (event, newSelectedDate)=>{
40
+ if (isDaySelectable(newSelectedDate)) switch(props.selectionVariant){
41
+ case "default":
42
+ setSelectedDateState(newSelectedDate);
43
+ props.onSelectedDateChange?.(event, newSelectedDate);
44
+ break;
45
+ case "multiselect":
46
+ {
47
+ const newDates = addOrRemoveFromArray(selectedDate ?? [], newSelectedDate);
48
+ setSelectedDateState(newDates);
49
+ props.onSelectedDateChange?.(event, newDates);
50
+ break;
51
+ }
52
+ case "range":
53
+ {
54
+ let base = selectedDate;
55
+ base = isRangeOrOffsetSelectionValue(base) ? base?.startDate && base?.endDate ? {
56
+ startDate: newSelectedDate
57
+ } : base?.startDate && newSelectedDate.compare(base.startDate) > 0 ? {
58
+ ...base,
59
+ endDate: newSelectedDate
60
+ } : {
61
+ startDate: newSelectedDate
62
+ } : {
63
+ startDate: newSelectedDate
64
+ };
65
+ setSelectedDateState(base);
66
+ props.onSelectedDateChange?.(event, base);
67
+ break;
68
+ }
69
+ case "offset":
70
+ {
71
+ const newRange = {
72
+ startDate: getStartDateOffset(newSelectedDate),
73
+ endDate: getEndDateOffset(newSelectedDate)
74
+ };
75
+ setSelectedDateState(newRange);
76
+ props.onSelectedDateChange?.(event, newRange);
77
+ }
78
+ }
79
+ };
80
+ const isSelected = (date)=>{
81
+ switch(selectionVariant){
82
+ case "default":
83
+ return selectedDate instanceof CalendarDate && isSameDay(selectedDate, date);
84
+ case "multiselect":
85
+ return Array.isArray(selectedDate) && !!selectedDate.find((element)=>isSameDay(element, date));
86
+ default:
87
+ return false;
88
+ }
89
+ };
90
+ const [hoveredDate, setHoveredDateState] = useControlled({
91
+ controlled: hoveredDateProp,
92
+ default: void 0,
93
+ name: "Calendar",
94
+ state: "hoveredDate"
95
+ });
96
+ const setHoveredDate = (event, date)=>{
97
+ setHoveredDateState(date);
98
+ onHoveredDateChange?.(event, date);
99
+ };
100
+ const isHovered = (date)=>!!hoveredDate && isSameDay(date, hoveredDate);
101
+ const isSelectedSpan = (date)=>{
102
+ if (("range" === selectionVariant || "offset" === selectionVariant) && isRangeOrOffsetSelectionValue(selectedDate) && selectedDate?.startDate && selectedDate?.endDate) return date.compare(selectedDate.startDate) > 0 && date.compare(selectedDate.endDate) < 0;
103
+ return false;
104
+ };
105
+ const isHoveredSpan = (date)=>{
106
+ if (("range" === selectionVariant || "offset" === selectionVariant) && isRangeOrOffsetSelectionValue(selectedDate) && selectedDate.startDate && !selectedDate.endDate && hoveredDate) {
107
+ const isForwardRange = hoveredDate.compare(selectedDate.startDate) > 0 && (date.compare(selectedDate.startDate) > 0 && date.compare(hoveredDate) < 0 || isSameDay(date, hoveredDate));
108
+ const isValidDayHovered = isDaySelectable(hoveredDate);
109
+ return isForwardRange && isValidDayHovered;
110
+ }
111
+ return false;
112
+ };
113
+ const isSelectedStart = (date)=>{
114
+ if (("range" === selectionVariant || "offset" === selectionVariant) && isRangeOrOffsetSelectionValue(selectedDate) && selectedDate.startDate) return isSameDay(selectedDate.startDate, date);
115
+ return false;
116
+ };
117
+ const isSelectedEnd = (date)=>{
118
+ if (("range" === selectionVariant || "offset" === selectionVariant) && isRangeOrOffsetSelectionValue(selectedDate) && selectedDate.endDate) return isSameDay(selectedDate.endDate, date);
119
+ return false;
120
+ };
121
+ const isHoveredOffset = (date)=>{
122
+ if (hoveredDate && "offset" === selectionVariant) {
123
+ const startDate = getStartDateOffset(hoveredDate);
124
+ const endDate = getEndDateOffset(hoveredDate);
125
+ return date.compare(startDate) >= 0 && date.compare(endDate) <= 0 && isDaySelectable(date);
126
+ }
127
+ return false;
128
+ };
129
+ return {
130
+ state: {
131
+ selectedDate,
132
+ hoveredDate
133
+ },
134
+ helpers: {
135
+ setSelectedDate,
136
+ isSelected,
137
+ setHoveredDate,
138
+ isHovered,
139
+ isSelectedSpan,
140
+ isHoveredSpan,
141
+ isSelectedStart,
142
+ isSelectedEnd,
143
+ isHoveredOffset
144
+ }
145
+ };
146
+ }
147
+ function useSelectionDay({ date }) {
148
+ const { helpers: { setSelectedDate, isSelected, setHoveredDate, isSelectedSpan, isHoveredSpan, isSelectedStart, isSelectedEnd, isHovered, isHoveredOffset, isDayUnselectable } } = useCalendarContext();
149
+ const handleClick = (event)=>{
150
+ setSelectedDate(event, date);
151
+ };
152
+ const handleKeyDown = (event)=>{
153
+ switch(event.key){
154
+ case "Space":
155
+ case "Enter":
156
+ setSelectedDate(event, date);
157
+ event.preventDefault();
158
+ }
159
+ };
160
+ const handleMouseOver = (event)=>{
161
+ setHoveredDate(event, date);
162
+ };
163
+ const handleMouseLeave = (event)=>{
164
+ setHoveredDate(event, null);
165
+ };
166
+ const selected = isSelected(date);
167
+ const selectedSpan = isSelectedSpan(date);
168
+ const hoveredSpan = isHoveredSpan(date);
169
+ const selectedStart = isSelectedStart(date);
170
+ const selectedEnd = isSelectedEnd(date);
171
+ const hovered = isHovered(date);
172
+ const hoveredOffset = isHoveredOffset(date);
173
+ return {
174
+ handleClick,
175
+ handleKeyDown,
176
+ handleMouseOver,
177
+ handleMouseLeave,
178
+ status: {
179
+ selected,
180
+ selectedSpan,
181
+ hoveredSpan,
182
+ selectedStart,
183
+ selectedEnd,
184
+ hovered,
185
+ hoveredOffset
186
+ },
187
+ dayProps: {
188
+ className: clsx({
189
+ [withBaseName("selected")]: selected,
190
+ [withBaseName("selectedSpan")]: selectedSpan,
191
+ [withBaseName("hoveredSpan")]: hoveredSpan,
192
+ [withBaseName("selectedStart")]: selectedStart,
193
+ [withBaseName("selectedEnd")]: selectedEnd,
194
+ [withBaseName("hovered")]: hovered,
195
+ [withBaseName("hoveredOffset")]: hoveredOffset
196
+ }),
197
+ "aria-pressed": selected || selectedEnd || selectedStart || selectedSpan ? "true" : void 0,
198
+ "aria-disabled": isDayUnselectable(date) ? "true" : void 0
199
+ }
200
+ };
201
+ }
202
+ export { isRangeOrOffsetSelectionValue, isRangeOrOffsetSelectionWithStartDate, useSelectionCalendar, useSelectionDay };
@@ -0,0 +1,8 @@
1
+ const css = `
2
+ .vuuColumnPicker {
3
+ z-index: 100;
4
+ }
5
+
6
+
7
+ `;
8
+ export default css;
@@ -0,0 +1,108 @@
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { flip, size, useClick, useDismiss, useInteractions } from "@floating-ui/react";
3
+ import { useFloatingComponent, useFloatingUI, useForkRef, useIdMemo } from "@salt-ds/core";
4
+ import { useComponentCssInjection } from "@salt-ds/styles";
5
+ import { useWindow } from "@salt-ds/window";
6
+ import clsx from "clsx";
7
+ import { forwardRef, useState } from "react";
8
+ import { IconButton } from "../icon-button/index.js";
9
+ import { ColumnSearch } from "./ColumnSearch.js";
10
+ import ColumnPicker_0 from "./ColumnPicker.css";
11
+ const classBase = "vuuColumnPicker";
12
+ const ColumnPicker_FloatingColumnSearch = /*#__PURE__*/ forwardRef(function(props, ref) {
13
+ const { children, className, collapsed, open, ...rest } = props;
14
+ const { Component: FloatingComponent } = useFloatingComponent();
15
+ return /*#__PURE__*/ jsx(FloatingComponent, {
16
+ className: clsx(classBase, {
17
+ [`${classBase}-collapsed`]: collapsed
18
+ }, className),
19
+ role: "listbox",
20
+ open: open,
21
+ ...rest,
22
+ ref: ref,
23
+ children: children
24
+ });
25
+ });
26
+ const ColumnPicker_ColumnPicker = /*#__PURE__*/ forwardRef(function({ columns, icon = "add", iconSize, onSelectionChange, selected, ...htmlAttributes }, forwardedRef) {
27
+ const targetWindow = useWindow();
28
+ useComponentCssInjection({
29
+ testId: "vuu-column-picker",
30
+ css: ColumnPicker_0,
31
+ window: targetWindow
32
+ });
33
+ const [open, setOpen] = useState(false);
34
+ const listId = useIdMemo();
35
+ const { context, x, y, strategy, elements, floating, reference } = useFloatingUI({
36
+ open,
37
+ onOpenChange: setOpen,
38
+ placement: "bottom-start",
39
+ strategy: "fixed",
40
+ middleware: [
41
+ size({
42
+ apply ({ rects, elements, availableHeight }) {
43
+ Object.assign(elements.floating.style, {
44
+ minWidth: `${rects.reference.width}px`,
45
+ maxHeight: `max(calc(${availableHeight}px - var(--salt-spacing-100)), calc((var(--salt-size-base) + var(--salt-spacing-100)) * 5))`
46
+ });
47
+ }
48
+ }),
49
+ flip({
50
+ fallbackStrategy: "initialPlacement"
51
+ })
52
+ ]
53
+ });
54
+ const { getReferenceProps, getFloatingProps } = useInteractions([
55
+ useDismiss(context),
56
+ useClick(context, {
57
+ keyboardHandlers: false,
58
+ toggle: false
59
+ })
60
+ ]);
61
+ const handleButtonClick = ()=>{
62
+ setOpen((isOpen)=>!isOpen);
63
+ };
64
+ const forkedRef = useForkRef(reference, forwardedRef);
65
+ const handleChange = ()=>{
66
+ console.log("handleChange");
67
+ };
68
+ const handleReorderColumns = ()=>{
69
+ console.log("handleMoveListItem");
70
+ };
71
+ return /*#__PURE__*/ jsxs(Fragment, {
72
+ children: [
73
+ /*#__PURE__*/ jsx(IconButton, {
74
+ ...htmlAttributes,
75
+ ...getReferenceProps(),
76
+ icon: icon,
77
+ size: iconSize,
78
+ onClick: handleButtonClick,
79
+ ref: forkedRef,
80
+ variant: "secondary"
81
+ }),
82
+ /*#__PURE__*/ jsx(ColumnPicker_FloatingColumnSearch, {
83
+ ...getFloatingProps(),
84
+ open: open,
85
+ collapsed: !open,
86
+ id: listId,
87
+ left: x,
88
+ position: strategy,
89
+ ref: floating,
90
+ top: y,
91
+ width: elements.floating?.offsetWidth,
92
+ height: elements.floating?.offsetHeight,
93
+ children: /*#__PURE__*/ jsx(ColumnSearch, {
94
+ columns: columns,
95
+ onChange: handleChange,
96
+ onReorderColumns: handleReorderColumns,
97
+ onSelectionChange: onSelectionChange,
98
+ selected: selected,
99
+ style: {
100
+ width: 220,
101
+ height: 300
102
+ }
103
+ })
104
+ })
105
+ ]
106
+ });
107
+ });
108
+ export { ColumnPicker_ColumnPicker as ColumnPicker };
@@ -0,0 +1,61 @@
1
+ const css = `
2
+ .vuuColumnSearch {
3
+ --vuuList-borderWidth: 0;
4
+ --vuuColumnListItem-border: none;
5
+ --vuuMeasuredContainer-flex: 1 1 1px;
6
+ background: var(--salt-container-primary-background);
7
+ border: solid 1px var(--salt-container-primary-borderColor);
8
+ border-radius: 4px;
9
+ flex-direction: column;
10
+ height: 100%;
11
+ padding: 12px 4px 12px 12px;
12
+ display: flex;
13
+
14
+ & .vuuIcon, & .saltSwitch, & .vuuColumnList-header, & .vuuColumnList-colHeadings {
15
+ display: none;
16
+ }
17
+
18
+ & .vuuList-viewport {
19
+ padding-right: var(--salt-spacing-100);
20
+ }
21
+
22
+ & .vuuColumnListItem {
23
+ padding-left: var(--salt-spacing-100);
24
+ }
25
+
26
+ & ::-webkit-scrollbar {
27
+ width: 4px;
28
+ height: 4px;
29
+ }
30
+
31
+ & ::-webkit-scrollbar-track {
32
+ background: none;
33
+ margin-top: 15px;
34
+ margin-bottom: 15px;
35
+ }
36
+
37
+ & ::-webkit-scrollbar-thumb {
38
+ background: #d9d9d9;
39
+ border-radius: 4px;
40
+ }
41
+ }
42
+
43
+ .vuuColumnSearch-inputField {
44
+ --vuu-icon-size: 16px;
45
+ flex: 0 0 40px;
46
+ margin-right: 8px;
47
+ }
48
+
49
+ .vuuColumnSearch-list {
50
+ --vuuMeasuredContainer-flex: 1 1 1px;
51
+ background-color: var(--salt-container-primary-background);
52
+ flex: auto;
53
+ }
54
+
55
+ .vuuColumnSearch .vuuTableCell {
56
+ padding: 0;
57
+ }
58
+
59
+
60
+ `;
61
+ export default css;
@@ -0,0 +1,66 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { Checkbox, Input, ListBox, Option } from "@salt-ds/core";
3
+ import { useComponentCssInjection } from "@salt-ds/styles";
4
+ import { useWindow } from "@salt-ds/window";
5
+ import clsx from "clsx";
6
+ import { forwardRef, useCallback, useRef } from "react";
7
+ import ColumnSearch_0 from "./ColumnSearch.css";
8
+ import { queryClosest } from "@vuu-ui/vuu-utils";
9
+ const classBase = "vuuColumnSearch";
10
+ const searchIcon = /*#__PURE__*/ jsx("span", {
11
+ "data-icon": "search"
12
+ });
13
+ const ColumnSearch_ColumnSearch = /*#__PURE__*/ forwardRef(function({ autoFocus = false, className, columns, onChange, onSelectionChange, selected, ...htmlAttributes }, forwardedRef) {
14
+ const targetWindow = useWindow();
15
+ useComponentCssInjection({
16
+ testId: "vuu-column-picker",
17
+ css: ColumnSearch_0,
18
+ window: targetWindow
19
+ });
20
+ const selectedValues = useRef([]);
21
+ const searchCallbackRef = useCallback((el)=>{
22
+ setTimeout(()=>{
23
+ el?.querySelector("input")?.focus();
24
+ }, 100);
25
+ }, []);
26
+ const handleChange = useCallback((e)=>{
27
+ const input = e.target;
28
+ const { columnName } = queryClosest(input, "[data-column-name]", true).dataset;
29
+ if (columnName) {
30
+ if (input.checked) selectedValues.current = selectedValues.current.concat(columnName);
31
+ else selectedValues.current = selectedValues.current.filter((val)=>val !== columnName);
32
+ onSelectionChange?.(e, selectedValues.current);
33
+ }
34
+ }, [
35
+ onSelectionChange
36
+ ]);
37
+ return /*#__PURE__*/ jsxs("div", {
38
+ ...htmlAttributes,
39
+ className: clsx(classBase, className),
40
+ ref: forwardedRef,
41
+ children: [
42
+ /*#__PURE__*/ jsx("div", {
43
+ className: `${classBase}-inputField`,
44
+ children: /*#__PURE__*/ jsx(Input, {
45
+ startAdornment: searchIcon,
46
+ ref: autoFocus ? searchCallbackRef : null
47
+ })
48
+ }),
49
+ /*#__PURE__*/ jsx(ListBox, {
50
+ children: columns.map((column)=>/*#__PURE__*/ jsxs(Option, {
51
+ "data-column-name": column,
52
+ value: column,
53
+ children: [
54
+ /*#__PURE__*/ jsx(Checkbox, {
55
+ onChange: handleChange
56
+ }),
57
+ /*#__PURE__*/ jsx("span", {
58
+ children: column
59
+ })
60
+ ]
61
+ }, column))
62
+ })
63
+ ]
64
+ });
65
+ });
66
+ export { ColumnSearch_ColumnSearch as ColumnSearch };
@@ -0,0 +1,2 @@
1
+ export * from "./ColumnPicker.js";
2
+ export * from "./ColumnSearch.js";
@@ -0,0 +1,49 @@
1
+ import { WindowRange, metadataKeys } from "@vuu-ui/vuu-utils";
2
+ const { SELECTED: SELECTED } = metadataKeys;
3
+ class MovingWindow {
4
+ data;
5
+ rowCount = 0;
6
+ range;
7
+ constructor({ from, to }){
8
+ this.range = new WindowRange(from, to);
9
+ this.data = new Array(to - from);
10
+ this.rowCount = 0;
11
+ }
12
+ setRowCount = (rowCount)=>{
13
+ if (rowCount < this.data.length) this.data.length = rowCount;
14
+ this.rowCount = rowCount;
15
+ };
16
+ add(data) {
17
+ const [index] = data;
18
+ if (this.isWithinRange(index)) {
19
+ const internalIndex = index - this.range.from;
20
+ this.data[internalIndex] = data;
21
+ }
22
+ }
23
+ getAtIndex(index) {
24
+ return this.range.isWithin(index) && null != this.data[index - this.range.from] ? this.data[index - this.range.from] : void 0;
25
+ }
26
+ isWithinRange(index) {
27
+ return this.range.isWithin(index);
28
+ }
29
+ setRange({ from, to }) {
30
+ if (from !== this.range.from || to !== this.range.to) {
31
+ const [overlapFrom, overlapTo] = this.range.overlap(from, to);
32
+ const newData = new Array(Math.max(0, to - from));
33
+ for(let i = overlapFrom; i < overlapTo; i++){
34
+ const data = this.getAtIndex(i);
35
+ if (data) {
36
+ const index = i - from;
37
+ newData[index] = data;
38
+ }
39
+ }
40
+ this.data = newData;
41
+ this.range.from = from;
42
+ this.range.to = to;
43
+ }
44
+ }
45
+ getSelectedRows() {
46
+ return this.data.filter((row)=>0 !== row[SELECTED]);
47
+ }
48
+ }
49
+ export { MovingWindow };
@@ -0,0 +1,3 @@
1
+ export * from "./useControlled.js";
2
+ export * from "./use-resize-observer.js";
3
+ export * from "./selectionTypes.js";
@@ -0,0 +1,8 @@
1
+ const isSingleSelection = (s)=>void 0 === s || "default" === s || "deselectable" === s;
2
+ const isMultiSelection = (s)=>"multiple" === s || s?.startsWith("extended") === true;
3
+ const selectionIsDisallowed = (selection)=>"none" === selection;
4
+ const allowMultipleSelection = (selectionStrategy, specialKey = false)=>"multiple" === selectionStrategy || "multiple-special-key" === selectionStrategy && specialKey;
5
+ const deselectionIsAllowed = (selection)=>"none" !== selection && "default" !== selection;
6
+ const hasSelection = (selected)=>void 0 !== selected && selected.length > 0;
7
+ const getFirstSelectedItem = (selected)=>selected[0];
8
+ export { allowMultipleSelection, deselectionIsAllowed, getFirstSelectedItem, hasSelection, isMultiSelection, isSingleSelection, selectionIsDisallowed };
@@ -0,0 +1,122 @@
1
+ import { useCallback, useEffect, useLayoutEffect, useRef } from "react";
2
+ const WidthHeight = [
3
+ "height",
4
+ "width"
5
+ ];
6
+ const WidthOnly = [
7
+ "width"
8
+ ];
9
+ const HeightOnly = [
10
+ "height"
11
+ ];
12
+ const observedMap = new Map();
13
+ const getTargetSize = (element, size, dimension)=>{
14
+ switch(dimension){
15
+ case "height":
16
+ return size.height;
17
+ case "clientHeight":
18
+ return element.clientHeight;
19
+ case "clientWidth":
20
+ return element.clientWidth;
21
+ case "contentHeight":
22
+ return size.contentHeight;
23
+ case "contentWidth":
24
+ return size.contentWidth;
25
+ case "scrollHeight":
26
+ return Math.ceil(element.scrollHeight);
27
+ case "scrollWidth":
28
+ return Math.ceil(element.scrollWidth);
29
+ case "width":
30
+ return size.width;
31
+ default:
32
+ return 0;
33
+ }
34
+ };
35
+ const resizeObserver = new ResizeObserver((entries)=>{
36
+ for (const entry of entries){
37
+ const { target, borderBoxSize, contentBoxSize } = entry;
38
+ const observedTarget = observedMap.get(target);
39
+ if (observedTarget) {
40
+ const [{ blockSize: height, inlineSize: width }] = borderBoxSize;
41
+ const [{ blockSize: contentHeight, inlineSize: contentWidth }] = contentBoxSize;
42
+ const { onResize, measurements } = observedTarget;
43
+ let sizeChanged = false;
44
+ for (const [dimension, size] of Object.entries(measurements)){
45
+ const newSize = getTargetSize(target, {
46
+ height,
47
+ width,
48
+ contentHeight,
49
+ contentWidth
50
+ }, dimension);
51
+ if (newSize !== size) {
52
+ sizeChanged = true;
53
+ measurements[dimension] = newSize;
54
+ }
55
+ }
56
+ if (sizeChanged) onResize && onResize(measurements);
57
+ }
58
+ }
59
+ });
60
+ function useResizeObserver(ref, dimensions, onResize, reportInitialSize = false) {
61
+ const dimensionsRef = useRef(dimensions);
62
+ const target = ref.current;
63
+ const measure = useCallback((target)=>{
64
+ const { width, height } = target.getBoundingClientRect();
65
+ const { clientWidth: contentWidth, clientHeight: contentHeight } = target;
66
+ return dimensionsRef.current.reduce((map, dim)=>{
67
+ map[dim] = getTargetSize(target, {
68
+ width,
69
+ height,
70
+ contentHeight,
71
+ contentWidth
72
+ }, dim);
73
+ return map;
74
+ }, {});
75
+ }, []);
76
+ useLayoutEffect(()=>{
77
+ async function registerObserver() {
78
+ observedMap.set(target, {
79
+ measurements: {}
80
+ });
81
+ await document.fonts.ready;
82
+ const observedTarget = observedMap.get(target);
83
+ if (observedTarget) {
84
+ const measurements = measure(target);
85
+ observedTarget.measurements = measurements;
86
+ resizeObserver.observe(target);
87
+ if (reportInitialSize) onResize(measurements);
88
+ } else console.log("%cuseResizeObserver an target expected to be under observation wa snot found. This warrants investigation", "font-weight:bold; color:red;");
89
+ }
90
+ if (target) {
91
+ observedMap.has(target);
92
+ registerObserver();
93
+ }
94
+ return ()=>{
95
+ if (target && observedMap.has(target)) {
96
+ resizeObserver.unobserve(target);
97
+ observedMap.delete(target);
98
+ }
99
+ };
100
+ }, [
101
+ measure,
102
+ target
103
+ ]);
104
+ useEffect(()=>{
105
+ const target = ref.current;
106
+ const record = observedMap.get(target);
107
+ if (record) {
108
+ if (dimensionsRef.current !== dimensions) {
109
+ dimensionsRef.current = dimensions;
110
+ const measurements = measure(target);
111
+ record.measurements = measurements;
112
+ }
113
+ record.onResize = onResize;
114
+ }
115
+ }, [
116
+ dimensions,
117
+ measure,
118
+ ref,
119
+ onResize
120
+ ]);
121
+ }
122
+ export { HeightOnly, WidthHeight, WidthOnly, useResizeObserver };
@@ -0,0 +1,45 @@
1
+ import { isValidElement, useCallback, useEffect, useRef, useState } from "react";
2
+ function useControlled({ controlled, default: defaultProp, name, state = "value" }) {
3
+ const { current: isControlled } = useRef(void 0 !== controlled);
4
+ const [valueState, setValue] = useState(defaultProp);
5
+ const value = void 0 !== controlled ? controlled : valueState;
6
+ const { current: defaultValue } = useRef(defaultProp);
7
+ useEffect(()=>{
8
+ if ("production" !== process.env.NODE_ENV) {
9
+ if (isControlled !== (void 0 !== controlled)) console.error([
10
+ `Salt: A component is changing the ${isControlled ? "" : "un"}controlled ${state} state of ${name} to be ${isControlled ? "un" : ""}controlled.`,
11
+ "Elements should not switch from uncontrolled to controlled (or vice versa).",
12
+ `Decide between using a controlled or uncontrolled ${name} element for the lifetime of the component.`,
13
+ "The nature of the state is determined during the first render, it's considered controlled if the value is not `undefined`.",
14
+ "More info: https://fb.me/react-controlled-components"
15
+ ].join("\n"));
16
+ }
17
+ }, [
18
+ state,
19
+ name,
20
+ controlled
21
+ ]);
22
+ useEffect(()=>{
23
+ if ("production" !== process.env.NODE_ENV) {
24
+ if (!isControlled && defaultValue !== defaultProp) console.error([
25
+ `Salt: A component is changing the default ${state} state of an uncontrolled ${name} after being initialized. To suppress this warning opt to use a controlled ${name}.`
26
+ ].join("\n"));
27
+ }
28
+ }, [
29
+ JSON.stringify(defaultProp, ignoreReactElements)
30
+ ]);
31
+ const setValueIfUncontrolled = useCallback((newValue)=>{
32
+ if (!isControlled) setValue(newValue);
33
+ }, [
34
+ isControlled
35
+ ]);
36
+ return [
37
+ value,
38
+ setValueIfUncontrolled,
39
+ isControlled
40
+ ];
41
+ }
42
+ function ignoreReactElements(key, value) {
43
+ return isValidElement(value) ? null : value;
44
+ }
45
+ export { useControlled };