@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,211 @@
1
+ import { getElementByDataIndex } from "@vuu-ui/vuu-utils";
2
+ const NON_WRAPPED_ITEM = ".vuuOverflowContainer-item:not(.wrapped)";
3
+ const sortByScreenOrder = (elements)=>elements.sort((e1, e2)=>{
4
+ const { dataset: { index: idx1 = "?" } } = e1;
5
+ const { dataset: { index: idx2 = "?" } } = e2;
6
+ const isOverflowed1 = e1.classList.contains("wrapped");
7
+ const isOverflowed2 = e2.classList.contains("wrapped");
8
+ const isOverflowedIndicator1 = "overflow" === idx1;
9
+ const isOverflowedIndicator2 = "overflow" === idx2;
10
+ if (isOverflowed1 && !isOverflowed2) return 1;
11
+ if (!isOverflowed1 && isOverflowed2) return -1;
12
+ if (isOverflowedIndicator1) return 1;
13
+ if (isOverflowedIndicator2) return -1;
14
+ return parseInt(idx1) > parseInt(idx2) ? 1 : -1;
15
+ });
16
+ const NO_WRAPPED_ITEMS = [];
17
+ const getNonWrappedAndWrappedItems = (container, orientation)=>{
18
+ const nonWrappedItems = [];
19
+ const wrappedItems = [];
20
+ let currentPosition = -1;
21
+ let overflowed = false;
22
+ const sortedChildren = sortByScreenOrder(Array.from(container.children));
23
+ const positionAttribute = "vertical" === orientation ? "top" : "left";
24
+ for (const child of sortedChildren){
25
+ const element = child;
26
+ const { dataset: { index = "?", label = "?", overflowPriority = "0" } } = element;
27
+ const { [positionAttribute]: position } = element.getBoundingClientRect();
28
+ if (position <= currentPosition) {
29
+ if ("overflow" === index) wrappedItems.push(nonWrappedItems.pop());
30
+ else wrappedItems.push({
31
+ index,
32
+ label,
33
+ overflowPriority
34
+ });
35
+ overflowed = true;
36
+ } else if (overflowed) wrappedItems.push({
37
+ index,
38
+ label,
39
+ overflowPriority
40
+ });
41
+ else nonWrappedItems.push({
42
+ index,
43
+ label,
44
+ overflowPriority
45
+ });
46
+ currentPosition = position;
47
+ }
48
+ return [
49
+ nonWrappedItems,
50
+ wrappedItems
51
+ ];
52
+ };
53
+ const applyOverflowClassToWrappedItems = (container, overflowedItems, classBase)=>{
54
+ let ignoreOverflow = false;
55
+ const className = classBase ? `${classBase}-overflowed` : "overflow";
56
+ if (overflowedItems.find(({ index })=>"overflow" === index)) {
57
+ if (1 === overflowedItems.length) ignoreOverflow = true;
58
+ }
59
+ for (const element of container.children){
60
+ const { dataset: { index = "?" } } = element;
61
+ if (0 === overflowedItems.length || ignoreOverflow) container.classList.remove(className);
62
+ else container.classList.add(className);
63
+ if ("overflow" !== index && overflowedItems.find((item)=>item.index === index)) element.classList.add("wrapped");
64
+ else element.classList.remove("wrapped");
65
+ }
66
+ };
67
+ const maxPriority = (priority, { overflowPriority })=>Math.max(priority, parseInt(overflowPriority));
68
+ const minPriority = (priority, { overflowPriority })=>Math.min(priority, parseInt(overflowPriority));
69
+ const overflowIndicatorHasWrappedButShouldNotHave = (wrappedItems)=>wrappedItems.length > 1 && wrappedItems.at(-1)?.index === "overflow";
70
+ const getHighestPriorityItem = (overflowItems)=>{
71
+ let [highestPriorityItem] = overflowItems;
72
+ for(let i = 1; i < overflowItems.length; i++){
73
+ const item = overflowItems[i];
74
+ if (parseInt(item.overflowPriority) > parseInt(highestPriorityItem.overflowPriority)) highestPriorityItem = item;
75
+ }
76
+ return highestPriorityItem;
77
+ };
78
+ const highPriorityItemsHaveWrappedButShouldNotHave = (nonWrappedItems, wrappedItems)=>{
79
+ const minNonwrappedPriority = nonWrappedItems.reduce(minPriority, Number.MAX_SAFE_INTEGER);
80
+ const maxwrappedPriority = wrappedItems.reduce(maxPriority, 0);
81
+ if (maxwrappedPriority > minNonwrappedPriority) return true;
82
+ return wrappedItems.length > 1 && wrappedItems.at(-1)?.index === "overflow";
83
+ };
84
+ const correctForWrappedOverflowIndicator = (container, overflowedItems, orientation)=>new Promise((resolve)=>{
85
+ requestAnimationFrame(()=>{
86
+ const [, o2] = getNonWrappedAndWrappedItems(container, orientation);
87
+ const newlyOverflowed = getNewItems(overflowedItems, o2);
88
+ newlyOverflowed.forEach((item)=>markElementAsWrapped(container, item));
89
+ resolve(o2);
90
+ });
91
+ });
92
+ const correctForWrappedHighPriorityItems = (container, nonWrapped, wrapped, orientation)=>new Promise((resolve)=>{
93
+ requestAnimationFrame(()=>{
94
+ const [, o2] = getNonWrappedAndWrappedItems(container, orientation);
95
+ const highPriorityWrappedItem = getHighestPriorityItem(o2);
96
+ if (highPriorityWrappedItem) {
97
+ const [nonWrappedItems, wrappedItems] = switchWrappedItemIntoView(container, highPriorityWrappedItem, orientation);
98
+ resolve([
99
+ nonWrappedItems,
100
+ wrappedItems
101
+ ]);
102
+ } else resolve([
103
+ nonWrapped,
104
+ wrapped
105
+ ]);
106
+ });
107
+ });
108
+ const markElementAsWrapped = (container, item)=>{
109
+ const el = getElementByDataIndex(container, item.index);
110
+ if (el) el.classList.add("wrapped");
111
+ else throw Error(`markElementAsWrapped element item with index ${item.index} not found`);
112
+ };
113
+ const getElementsMarkedAsWrapped = (container)=>Array.from(container.querySelectorAll(".wrapped"));
114
+ const getNewItems = (items1, items2)=>{
115
+ const newItems = [];
116
+ for (const item of items2)if (!items1.find(({ index })=>index === item.index)) newItems.push(item);
117
+ return newItems;
118
+ };
119
+ const unmarkItemsWhichAreNoLongerWrapped = (container, wrappedItems)=>{
120
+ const elementssMarkedAsWrapped = getElementsMarkedAsWrapped(container);
121
+ elementssMarkedAsWrapped.forEach((el)=>{
122
+ const { dataset: { index = "?" } } = el;
123
+ if (!wrappedItems.find((i)=>i.index === index)) el.classList.remove("wrapped");
124
+ });
125
+ };
126
+ const getOverflowIndicator = (container)=>container.querySelector('[data-index="overflow"]');
127
+ const getOverflowedItem = (container)=>container.querySelector(".wrapped");
128
+ const getElementSize = (el, sizeProperty)=>{
129
+ const size = parseInt(getComputedStyle(el).getPropertyValue(sizeProperty));
130
+ const margin = "width" === sizeProperty ? parseInt(getComputedStyle(el).getPropertyValue("margin-left")) + parseInt(getComputedStyle(el).getPropertyValue("margin-right")) : parseInt(getComputedStyle(el).getPropertyValue("margin-top")) + parseInt(getComputedStyle(el).getPropertyValue("margin-bottom"));
131
+ return size + margin;
132
+ };
133
+ const getAvailableSpace = (container, overflowIndicator, orientation)=>{
134
+ if ("horizontal" === orientation) {
135
+ const { right: containerRight } = container.getBoundingClientRect();
136
+ const paddingRight = parseInt(getComputedStyle(container).getPropertyValue("padding-right"));
137
+ const { right: indicatorRight } = overflowIndicator.getBoundingClientRect();
138
+ return containerRight - paddingRight - indicatorRight;
139
+ }
140
+ {
141
+ const { bottom: containerBottom } = container.getBoundingClientRect();
142
+ const paddingBottom = parseInt(getComputedStyle(container).getPropertyValue("padding-bottom"));
143
+ const { bottom: indicatorBottom } = overflowIndicator.getBoundingClientRect();
144
+ return containerBottom - paddingBottom - indicatorBottom;
145
+ }
146
+ };
147
+ const removeOverflowIndicatorIfNoLongerNeeded = (container, orientation)=>{
148
+ const sizeProperty = "horizontal" === orientation ? "width" : "height";
149
+ const overflowIndicator = getOverflowIndicator(container);
150
+ const availableSpace = getAvailableSpace(container, overflowIndicator, orientation);
151
+ const indicatorWidth = getElementSize(overflowIndicator, sizeProperty);
152
+ const overflowedItem = getOverflowedItem(container);
153
+ const overflowWidth = getElementSize(overflowedItem, sizeProperty);
154
+ if (overflowWidth <= availableSpace + indicatorWidth) {
155
+ container.classList.remove("vuuOverflowContainer-wrapContainer-overflowed");
156
+ overflowedItem.classList.remove("wrapped");
157
+ return true;
158
+ }
159
+ return false;
160
+ };
161
+ const byPriorityDescending = (h1, h2)=>{
162
+ const { dataset: { index: i1 = "0", overflowPriority: p1 = "0" } } = h1;
163
+ const { dataset: { index: i2 = "0", overflowPriority: p2 = "0" } } = h2;
164
+ if (p1 > p2) return -1;
165
+ if (p1 < p2) return 1;
166
+ return parseInt(i1) - parseInt(i2);
167
+ };
168
+ const getNonwrappedItemsByPriority = (container)=>Array.from(container.querySelectorAll(NON_WRAPPED_ITEM)).sort(byPriorityDescending);
169
+ const switchWrappedItemIntoView = (container, overflowItem, orientation)=>{
170
+ const unwrappedItems = getNonwrappedItemsByPriority(container);
171
+ const targetElement = getElementByDataIndex(container, overflowItem.index, true);
172
+ let pos = -1;
173
+ let unwrappedItem = unwrappedItems.at(pos);
174
+ const sizeProperty = "horizontal" === orientation ? "width" : "height";
175
+ const itemWidth = getElementSize(unwrappedItem, sizeProperty);
176
+ const targetWidth = getElementSize(targetElement, sizeProperty);
177
+ const overflowIndicator = getOverflowIndicator(container);
178
+ let availableSpace = getAvailableSpace(container, overflowIndicator, orientation) + itemWidth;
179
+ if (availableSpace >= targetWidth) switchWrapOnElements(targetElement, unwrappedItem);
180
+ else {
181
+ const { left: lastLeft } = unwrappedItem.getBoundingClientRect();
182
+ const baseAvailableSpace = availableSpace;
183
+ const wrapTargets = [
184
+ unwrappedItem
185
+ ];
186
+ while(availableSpace < targetWidth){
187
+ pos -= 1;
188
+ unwrappedItem = unwrappedItems.at(pos);
189
+ wrapTargets.push(unwrappedItem);
190
+ const { left: nextLeft } = unwrappedItem.getBoundingClientRect();
191
+ const extraSpace = lastLeft - nextLeft;
192
+ availableSpace = baseAvailableSpace + extraSpace;
193
+ }
194
+ targetElement?.classList.remove("wrapped");
195
+ wrapTargets.forEach((item)=>{
196
+ item.classList.add("wrapped");
197
+ });
198
+ }
199
+ const [nonWrappedItems, wrappedItems] = getNonWrappedAndWrappedItems(container, orientation);
200
+ unmarkItemsWhichAreNoLongerWrapped(container, wrappedItems);
201
+ return [
202
+ nonWrappedItems,
203
+ wrappedItems
204
+ ];
205
+ };
206
+ const switchWrapOnElements = (wrappedElement, nonWrappedElement)=>{
207
+ if (!wrappedElement || !nonWrappedElement) throw Error("switchWrapOnElements, element undefined");
208
+ wrappedElement.classList.remove("wrapped");
209
+ nonWrappedElement.classList.add("wrapped");
210
+ };
211
+ export { NO_WRAPPED_ITEMS, applyOverflowClassToWrappedItems, correctForWrappedHighPriorityItems, correctForWrappedOverflowIndicator, getElementsMarkedAsWrapped, getNonWrappedAndWrappedItems, highPriorityItemsHaveWrappedButShouldNotHave, markElementAsWrapped, overflowIndicatorHasWrappedButShouldNotHave, removeOverflowIndicatorIfNoLongerNeeded, sortByScreenOrder, switchWrappedItemIntoView, unmarkItemsWhichAreNoLongerWrapped };
@@ -0,0 +1,108 @@
1
+ import { MEASURES, isValidNumber, useLayoutEffectSkipFirst } from "@vuu-ui/vuu-utils";
2
+ import { useCallback, useMemo, useRef, useState } from "react";
3
+ import { NO_WRAPPED_ITEMS, applyOverflowClassToWrappedItems, correctForWrappedHighPriorityItems, correctForWrappedOverflowIndicator, getNonWrappedAndWrappedItems, highPriorityItemsHaveWrappedButShouldNotHave, overflowIndicatorHasWrappedButShouldNotHave, removeOverflowIndicatorIfNoLongerNeeded, switchWrappedItemIntoView } from "./overflow-utils.js";
4
+ import { useDragDrop } from "../drag-drop/index.js";
5
+ const useOverflowContainer = ({ allowDragDrop = false, itemCount, onMoveItem, onSwitchWrappedItemIntoView, orientation })=>{
6
+ const [container, setContainer] = useState(null);
7
+ const wrappedItemsRef = useRef(NO_WRAPPED_ITEMS);
8
+ const containerRef = useRef(null);
9
+ const setOverflowTabIndex = useCallback((tabIndex)=>{
10
+ if (containerRef.current) containerRef.current.querySelector(".vuuOverflowContainer-OverflowIndicator button")?.setAttribute("tabindex", tabIndex);
11
+ }, []);
12
+ const handleResize = useCallback(async ()=>{
13
+ if (container) {
14
+ let [nonWrapped, wrapped] = getNonWrappedAndWrappedItems(container, orientation);
15
+ applyOverflowClassToWrappedItems(container, wrapped, "vuuOverflowContainer-wrapContainer");
16
+ if (overflowIndicatorHasWrappedButShouldNotHave(wrapped)) wrapped = await correctForWrappedOverflowIndicator(container, wrapped, orientation);
17
+ while(highPriorityItemsHaveWrappedButShouldNotHave(nonWrapped, wrapped))[nonWrapped, wrapped] = await correctForWrappedHighPriorityItems(container, nonWrapped, wrapped, orientation);
18
+ if (1 === wrapped.length) {
19
+ if (removeOverflowIndicatorIfNoLongerNeeded(container, orientation)) wrapped = NO_WRAPPED_ITEMS;
20
+ }
21
+ if (0 === wrappedItemsRef.current.length && wrapped.length > 0) setOverflowTabIndex("0");
22
+ else if (wrappedItemsRef.current.length > 0 && 0 === wrapped.length) setOverflowTabIndex("-1");
23
+ wrappedItemsRef.current = wrapped;
24
+ }
25
+ }, [
26
+ container,
27
+ orientation,
28
+ setOverflowTabIndex
29
+ ]);
30
+ const hasOverflowItem = (opt)=>"object" == typeof opt && null !== opt && "overflowItem" in opt;
31
+ const [menuBuilder, menuActionHandler] = useMemo(()=>[
32
+ ()=>{
33
+ const { current: menuItems } = wrappedItemsRef;
34
+ return menuItems.map((item)=>({
35
+ label: item.label,
36
+ id: `activate-item-${item.index}`,
37
+ options: {
38
+ overflowItem: item
39
+ }
40
+ }));
41
+ },
42
+ (menuItemId, options)=>{
43
+ if (container && hasOverflowItem(options)) {
44
+ const [, wrappedItems] = switchWrappedItemIntoView(container, options.overflowItem, orientation);
45
+ wrappedItemsRef.current = wrappedItems;
46
+ onSwitchWrappedItemIntoView?.(options.overflowItem);
47
+ }
48
+ return true;
49
+ }
50
+ ], [
51
+ container,
52
+ onSwitchWrappedItemIntoView,
53
+ orientation
54
+ ]);
55
+ const resizeObserver = useMemo(()=>{
56
+ const { sizeProp } = MEASURES[orientation];
57
+ let currentSize = 0;
58
+ return new ResizeObserver((entries)=>{
59
+ for (const entry of entries){
60
+ const { [sizeProp]: actualSize } = entry.contentRect;
61
+ const size = Math.round(actualSize);
62
+ if (isValidNumber(size) && currentSize !== size) {
63
+ currentSize = size;
64
+ handleResize();
65
+ }
66
+ }
67
+ });
68
+ }, [
69
+ handleResize,
70
+ orientation
71
+ ]);
72
+ useLayoutEffectSkipFirst(()=>{
73
+ handleResize();
74
+ }, [
75
+ handleResize,
76
+ itemCount
77
+ ]);
78
+ useMemo(()=>{
79
+ if (container) resizeObserver.observe(container);
80
+ }, [
81
+ container,
82
+ resizeObserver
83
+ ]);
84
+ const callbackRef = useCallback((el)=>{
85
+ setContainer(containerRef.current = el);
86
+ }, []);
87
+ const handleDrop = useCallback(({ fromIndex, toIndex })=>{
88
+ onMoveItem?.(fromIndex, toIndex);
89
+ }, [
90
+ onMoveItem
91
+ ]);
92
+ const { onMouseDown: dragDropHookHandleMouseDown, ...dragDropHook } = useDragDrop({
93
+ allowDragDrop,
94
+ containerRef,
95
+ draggableClassName: "vuuOverflowContainer",
96
+ onDrop: handleDrop,
97
+ orientation: "horizontal",
98
+ itemQuery: ".vuuOverflowContainer-item"
99
+ });
100
+ return {
101
+ menuActionHandler,
102
+ menuBuilder,
103
+ onItemMouseDown: dragDropHookHandleMouseDown,
104
+ rootRef: callbackRef,
105
+ ...dragDropHook
106
+ };
107
+ };
108
+ export { useOverflowContainer };
@@ -0,0 +1,32 @@
1
+ const css = `
2
+ @property --price-ticker-color {
3
+ syntax: "<color>";
4
+ inherits: false;
5
+ initial-value: #15171b;
6
+ }
7
+
8
+ .vuuPriceTicker {
9
+ font-size: var(--vuuPriceTicker-fontSize, var(--salt-text-fontSize));
10
+ font-weight: var(--vuuPriceTicker-fontWeight, 700);
11
+ align-items: center;
12
+ transition-property: color;
13
+ transition-duration: .3s;
14
+ display: flex;
15
+ }
16
+
17
+ .vuuPriceTicker.up1, .vuuPriceTicker.up2 {
18
+ --vuu-icon-color: var(--vuu-color-green-50);
19
+ color: var(--vuu-color-green-50);
20
+ animation-duration: 30s;
21
+ }
22
+
23
+ .vuuPriceTicker.down1, .vuuPriceTicker.down2 {
24
+ --vuu-icon-transform: rotate(180deg);
25
+ --vuu-icon-color: var(--vuu-color-red-50);
26
+ color: var(--vuu-color-red-50);
27
+ animation-duration: 30s;
28
+ }
29
+
30
+
31
+ `;
32
+ export default css;
@@ -0,0 +1,51 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { getMovingValueDirection, isValidNumber, numericFormatter } from "@vuu-ui/vuu-utils";
3
+ import { memo, useMemo, useRef } from "react";
4
+ import clsx from "clsx";
5
+ import { useComponentCssInjection } from "@salt-ds/styles";
6
+ import { useWindow } from "@salt-ds/window";
7
+ import PriceTicker from "./PriceTicker.css";
8
+ const classBase = "vuuPriceTicker";
9
+ const getValueFormatter = (decimals)=>numericFormatter({
10
+ type: {
11
+ name: "number",
12
+ formatting: {
13
+ decimals,
14
+ zeroPad: true
15
+ }
16
+ }
17
+ });
18
+ const INITIAL_VALUE = [
19
+ void 0,
20
+ void 0
21
+ ];
22
+ const PriceTicker_PriceTicker = /*#__PURE__*/ memo(({ className, decimals = 2, price, showArrow, ...htmlAttributes })=>{
23
+ const targetWindow = useWindow();
24
+ useComponentCssInjection({
25
+ testId: "vuu-price-ticker",
26
+ css: PriceTicker,
27
+ window: targetWindow
28
+ });
29
+ const ref = useRef(INITIAL_VALUE);
30
+ const [prevValue, prevDirection] = ref.current;
31
+ const formatNumber = useMemo(()=>getValueFormatter(decimals), [
32
+ decimals
33
+ ]);
34
+ const direction = isValidNumber(prevValue) ? getMovingValueDirection(price, prevDirection, prevValue, decimals) : "";
35
+ ref.current = [
36
+ price,
37
+ direction
38
+ ];
39
+ return /*#__PURE__*/ jsxs("div", {
40
+ ...htmlAttributes,
41
+ className: clsx(classBase, className, direction),
42
+ children: [
43
+ formatNumber(price),
44
+ showArrow ? /*#__PURE__*/ jsx("span", {
45
+ "data-icon": "price-arrow"
46
+ }) : null
47
+ ]
48
+ });
49
+ });
50
+ PriceTicker_PriceTicker.displayName = "PriceTicker";
51
+ export { PriceTicker_PriceTicker as PriceTicker };
@@ -0,0 +1 @@
1
+ export * from "./PriceTicker.js";
@@ -0,0 +1,48 @@
1
+ const css = `
2
+ .vuuPrompt {
3
+ min-height: var(--vuuPrompt-minHeight, 257px);
4
+ min-width: var(--vuuPrompt-minWidth, 380px);
5
+
6
+ & .saltDialogHeader {
7
+ & .vuuIcon {
8
+ --vuu-icon-size: 20px;
9
+ width: 24px;
10
+ }
11
+ }
12
+
13
+ & .saltDialogActions {
14
+ align-items: center;
15
+ }
16
+ }
17
+
18
+ .vuuPrompt.saltDialog-warning {
19
+ --salt-status-warning-borderColor: var(--vuu-color-yellow-20);
20
+ --variant-color: var(--vuu-color-yellow-20);
21
+ min-height: var(--vuuPrompt-minHeight, 150px);
22
+ min-width: var(--vuuPrompt-minWidth, 280px);
23
+ border-radius: 4px !important;
24
+ padding-top: 0 !important;
25
+
26
+ & .saltDialogHeader {
27
+ background-color: var(--variant-color);
28
+ padding-left: var(--salt-spacing-100);
29
+ padding-bottom: var(--salt-spacing-100);
30
+ padding-right: var(--salt-spacing-100);
31
+
32
+ & .saltDialogHeader-header {
33
+ align-items: end;
34
+ gap: var(--salt-spacing-100);
35
+ display: flex;
36
+ }
37
+ }
38
+
39
+ & .saltDialogContent {
40
+ justify-content: flex-start;
41
+ align-items: center;
42
+ display: flex;
43
+ }
44
+ }
45
+
46
+
47
+ `;
48
+ export default css;
@@ -0,0 +1,112 @@
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { Button, Dialog, DialogActions, DialogContent, DialogHeader } from "@salt-ds/core";
3
+ import clsx from "clsx";
4
+ import { useCallback } from "react";
5
+ import { Icon, IconButton } from "../icon-button/index.js";
6
+ import { useComponentCssInjection } from "@salt-ds/styles";
7
+ import { useWindow } from "@salt-ds/window";
8
+ import Prompt from "./Prompt.css";
9
+ const classBase = "vuuPrompt";
10
+ const Prompt_Prompt = ({ children, className, cancelButtonLabel = "Cancel", cancelButtonProps, confirmButtonLabel = "Confirm", confirmButtonProps, customAction = null, disableAccent, icon, initialFocusedItem, onCancel, onClose, onConfirm, onOpenChange, open, showCancelButton = true, showCloseButton = true, showConfirmButton = true, status, title, ...htmlAttributes })=>{
11
+ const targetWindow = useWindow();
12
+ useComponentCssInjection({
13
+ testId: "vuu-prompt-next",
14
+ css: Prompt,
15
+ window: targetWindow
16
+ });
17
+ const close = useCallback(()=>{
18
+ onClose?.();
19
+ onOpenChange?.(false);
20
+ }, [
21
+ onClose,
22
+ onOpenChange
23
+ ]);
24
+ const callbackRef = useCallback((el)=>{
25
+ if (el) {
26
+ let target = null;
27
+ if ("confirm" === initialFocusedItem && showConfirmButton) target = el.querySelector(".vuuPromptConfirmButton");
28
+ else if ("cancel" === initialFocusedItem && showCancelButton) target = el.querySelector(".vuuPromptCancelButton");
29
+ else if ("close" === initialFocusedItem && showCloseButton) target = el.querySelector(".vuuPromptCloseButton");
30
+ if (target) setTimeout(()=>{
31
+ target.focus();
32
+ }, 200);
33
+ }
34
+ }, [
35
+ initialFocusedItem,
36
+ showCancelButton,
37
+ showCloseButton,
38
+ showConfirmButton
39
+ ]);
40
+ const handleCancel = useCallback(()=>{
41
+ onCancel?.();
42
+ close();
43
+ }, [
44
+ close,
45
+ onCancel
46
+ ]);
47
+ const handleConfirm = useCallback(()=>{
48
+ if (onConfirm?.() !== false) close();
49
+ }, [
50
+ close,
51
+ onConfirm
52
+ ]);
53
+ const actions = showCloseButton ? /*#__PURE__*/ jsx(IconButton, {
54
+ appearance: "transparent",
55
+ className: "vuuPromptCloseButton",
56
+ "data-embedded": true,
57
+ icon: "close",
58
+ onClick: close
59
+ }) : null;
60
+ const header = icon ? /*#__PURE__*/ jsxs(Fragment, {
61
+ children: [
62
+ /*#__PURE__*/ jsx(Icon, {
63
+ name: icon
64
+ }),
65
+ /*#__PURE__*/ jsx("span", {
66
+ children: title
67
+ })
68
+ ]
69
+ }) : title;
70
+ return /*#__PURE__*/ jsxs(Dialog, {
71
+ ...htmlAttributes,
72
+ className: clsx(classBase, className),
73
+ onOpenChange: onOpenChange,
74
+ open: open,
75
+ ref: callbackRef,
76
+ status: status,
77
+ children: [
78
+ /*#__PURE__*/ jsx(DialogHeader, {
79
+ disableAccent: disableAccent,
80
+ header: header,
81
+ actions: actions
82
+ }),
83
+ /*#__PURE__*/ jsx(DialogContent, {
84
+ children: children
85
+ }),
86
+ /*#__PURE__*/ jsxs(DialogActions, {
87
+ children: [
88
+ customAction,
89
+ showCancelButton ? /*#__PURE__*/ jsx(Button, {
90
+ appearance: "solid",
91
+ className: "vuuPromptCancelButton",
92
+ disabled: cancelButtonProps?.disabled,
93
+ onClick: handleCancel,
94
+ ref: cancelButtonProps?.ref,
95
+ sentiment: "neutral",
96
+ children: cancelButtonProps?.label ?? cancelButtonLabel
97
+ }) : null,
98
+ showConfirmButton ? /*#__PURE__*/ jsx(Button, {
99
+ appearance: "solid",
100
+ className: "vuuPromptConfirmButton",
101
+ disabled: confirmButtonProps?.disabled,
102
+ sentiment: "accented",
103
+ onClick: handleConfirm,
104
+ ref: confirmButtonProps?.ref,
105
+ children: confirmButtonProps?.label ?? confirmButtonLabel
106
+ }) : null
107
+ ]
108
+ })
109
+ ]
110
+ });
111
+ };
112
+ export { Prompt_Prompt as Prompt };
@@ -0,0 +1,39 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { ListBox, Option } from "@salt-ds/core";
3
+ import { DragDropProvider, useSortable } from "@vuu-ui/vuu-utils";
4
+ import { useCallback, useRef } from "react";
5
+ const SortableOption = ({ id, index, value, ...optionProps })=>{
6
+ const { ref } = useSortable({
7
+ id,
8
+ index
9
+ });
10
+ return /*#__PURE__*/ jsx(Option, {
11
+ ...optionProps,
12
+ id: id,
13
+ ref: ref,
14
+ value: value
15
+ });
16
+ };
17
+ const SortableList = ({ children, onReorderListItems, ...listBoxProps })=>{
18
+ const listRef = useRef(null);
19
+ const handleDragEnd = useCallback(()=>{
20
+ setTimeout(()=>{
21
+ const listItems = listRef.current?.querySelectorAll(".saltOption");
22
+ if (listItems) {
23
+ const items = Array.from(listItems).map(({ id })=>id);
24
+ onReorderListItems?.(items);
25
+ }
26
+ }, 300);
27
+ }, [
28
+ onReorderListItems
29
+ ]);
30
+ return /*#__PURE__*/ jsx(DragDropProvider, {
31
+ onDragEnd: handleDragEnd,
32
+ children: /*#__PURE__*/ jsx(ListBox, {
33
+ ...listBoxProps,
34
+ ref: listRef,
35
+ children: children
36
+ })
37
+ });
38
+ };
39
+ export { SortableList, SortableOption };