@helpwave/hightide 0.1.18 → 0.1.20
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.
- package/dist/components/branding/HelpwaveBadge.js +7 -7
- package/dist/components/branding/HelpwaveBadge.js.map +1 -1
- package/dist/components/branding/HelpwaveBadge.mjs +7 -7
- package/dist/components/branding/HelpwaveBadge.mjs.map +1 -1
- package/dist/components/date/DatePicker.js +67 -39
- package/dist/components/date/DatePicker.js.map +1 -1
- package/dist/components/date/DatePicker.mjs +56 -28
- package/dist/components/date/DatePicker.mjs.map +1 -1
- package/dist/components/date/DayPicker.js +3 -3
- package/dist/components/date/DayPicker.js.map +1 -1
- package/dist/components/date/DayPicker.mjs +3 -3
- package/dist/components/date/DayPicker.mjs.map +1 -1
- package/dist/components/date/TimePicker.js +4 -4
- package/dist/components/date/TimePicker.js.map +1 -1
- package/dist/components/date/TimePicker.mjs +4 -4
- package/dist/components/date/TimePicker.mjs.map +1 -1
- package/dist/components/date/YearMonthPicker.js +48 -20
- package/dist/components/date/YearMonthPicker.js.map +1 -1
- package/dist/components/date/YearMonthPicker.mjs +46 -18
- package/dist/components/date/YearMonthPicker.mjs.map +1 -1
- package/dist/components/dialogs/ConfirmDialog.js +32 -28
- package/dist/components/dialogs/ConfirmDialog.js.map +1 -1
- package/dist/components/dialogs/ConfirmDialog.mjs +18 -14
- package/dist/components/dialogs/ConfirmDialog.mjs.map +1 -1
- package/dist/components/icons-and-geometry/Avatar.js +2 -2
- package/dist/components/icons-and-geometry/Avatar.js.map +1 -1
- package/dist/components/icons-and-geometry/Avatar.mjs +2 -2
- package/dist/components/icons-and-geometry/Avatar.mjs.map +1 -1
- package/dist/components/icons-and-geometry/Ring.js +2 -2
- package/dist/components/icons-and-geometry/Ring.js.map +1 -1
- package/dist/components/icons-and-geometry/Ring.mjs +2 -2
- package/dist/components/icons-and-geometry/Ring.mjs.map +1 -1
- package/dist/components/layout-and-navigation/BreadCrumb.js +1 -1
- package/dist/components/layout-and-navigation/BreadCrumb.js.map +1 -1
- package/dist/components/layout-and-navigation/BreadCrumb.mjs +1 -1
- package/dist/components/layout-and-navigation/BreadCrumb.mjs.map +1 -1
- package/dist/components/layout-and-navigation/Carousel.js +84 -15
- package/dist/components/layout-and-navigation/Carousel.js.map +1 -1
- package/dist/components/layout-and-navigation/Carousel.mjs +76 -7
- package/dist/components/layout-and-navigation/Carousel.mjs.map +1 -1
- package/dist/components/layout-and-navigation/Chip.js +1 -1
- package/dist/components/layout-and-navigation/Chip.js.map +1 -1
- package/dist/components/layout-and-navigation/Chip.mjs +1 -1
- package/dist/components/layout-and-navigation/Chip.mjs.map +1 -1
- package/dist/components/layout-and-navigation/Expandable.d.mts +10 -1
- package/dist/components/layout-and-navigation/Expandable.d.ts +10 -1
- package/dist/components/layout-and-navigation/Expandable.js +38 -10
- package/dist/components/layout-and-navigation/Expandable.js.map +1 -1
- package/dist/components/layout-and-navigation/Expandable.mjs +38 -11
- package/dist/components/layout-and-navigation/Expandable.mjs.map +1 -1
- package/dist/components/layout-and-navigation/FAQSection.js +36 -12
- package/dist/components/layout-and-navigation/FAQSection.js.map +1 -1
- package/dist/components/layout-and-navigation/FAQSection.mjs +38 -14
- package/dist/components/layout-and-navigation/FAQSection.mjs.map +1 -1
- package/dist/components/layout-and-navigation/Overlay.js +92 -19
- package/dist/components/layout-and-navigation/Overlay.js.map +1 -1
- package/dist/components/layout-and-navigation/Overlay.mjs +81 -8
- package/dist/components/layout-and-navigation/Overlay.mjs.map +1 -1
- package/dist/components/layout-and-navigation/Pagination.js +82 -9
- package/dist/components/layout-and-navigation/Pagination.js.map +1 -1
- package/dist/components/layout-and-navigation/Pagination.mjs +79 -6
- package/dist/components/layout-and-navigation/Pagination.mjs.map +1 -1
- package/dist/components/layout-and-navigation/SearchableList.js +127 -25
- package/dist/components/layout-and-navigation/SearchableList.js.map +1 -1
- package/dist/components/layout-and-navigation/SearchableList.mjs +126 -24
- package/dist/components/layout-and-navigation/SearchableList.mjs.map +1 -1
- package/dist/components/layout-and-navigation/StepperBar.js +22 -16
- package/dist/components/layout-and-navigation/StepperBar.js.map +1 -1
- package/dist/components/layout-and-navigation/StepperBar.mjs +19 -13
- package/dist/components/layout-and-navigation/StepperBar.mjs.map +1 -1
- package/dist/components/layout-and-navigation/TextImage.js +7 -3
- package/dist/components/layout-and-navigation/TextImage.js.map +1 -1
- package/dist/components/layout-and-navigation/TextImage.mjs +7 -3
- package/dist/components/layout-and-navigation/TextImage.mjs.map +1 -1
- package/dist/components/layout-and-navigation/Tile.d.mts +2 -2
- package/dist/components/layout-and-navigation/Tile.d.ts +2 -2
- package/dist/components/layout-and-navigation/Tile.js +7 -7
- package/dist/components/layout-and-navigation/Tile.js.map +1 -1
- package/dist/components/layout-and-navigation/Tile.mjs +7 -7
- package/dist/components/layout-and-navigation/Tile.mjs.map +1 -1
- package/dist/components/loading-states/ErrorComponent.js +1 -1
- package/dist/components/loading-states/ErrorComponent.js.map +1 -1
- package/dist/components/loading-states/ErrorComponent.mjs +1 -1
- package/dist/components/loading-states/ErrorComponent.mjs.map +1 -1
- package/dist/components/loading-states/LoadingAndErrorComponent.d.mts +5 -10
- package/dist/components/loading-states/LoadingAndErrorComponent.d.ts +5 -10
- package/dist/components/loading-states/LoadingAndErrorComponent.js +14 -327
- package/dist/components/loading-states/LoadingAndErrorComponent.js.map +1 -1
- package/dist/components/loading-states/LoadingAndErrorComponent.mjs +15 -318
- package/dist/components/loading-states/LoadingAndErrorComponent.mjs.map +1 -1
- package/dist/components/loading-states/LoadingAnimation.js +5 -1
- package/dist/components/loading-states/LoadingAnimation.js.map +1 -1
- package/dist/components/loading-states/LoadingAnimation.mjs +5 -1
- package/dist/components/loading-states/LoadingAnimation.mjs.map +1 -1
- package/dist/components/loading-states/LoadingButton.js +8 -6
- package/dist/components/loading-states/LoadingButton.js.map +1 -1
- package/dist/components/loading-states/LoadingButton.mjs +8 -6
- package/dist/components/loading-states/LoadingButton.mjs.map +1 -1
- package/dist/components/loading-states/LoadingContainer.d.mts +8 -0
- package/dist/components/loading-states/LoadingContainer.d.ts +8 -0
- package/dist/components/loading-states/LoadingContainer.js +34 -0
- package/dist/components/loading-states/LoadingContainer.js.map +1 -0
- package/dist/components/loading-states/LoadingContainer.mjs +10 -0
- package/dist/components/loading-states/LoadingContainer.mjs.map +1 -0
- package/dist/components/modals/ConfirmModal.js +32 -28
- package/dist/components/modals/ConfirmModal.js.map +1 -1
- package/dist/components/modals/ConfirmModal.mjs +18 -14
- package/dist/components/modals/ConfirmModal.mjs.map +1 -1
- package/dist/components/modals/DiscardChangesModal.js +28 -24
- package/dist/components/modals/DiscardChangesModal.js.map +1 -1
- package/dist/components/modals/DiscardChangesModal.mjs +18 -14
- package/dist/components/modals/DiscardChangesModal.mjs.map +1 -1
- package/dist/components/modals/InputModal.js +32 -28
- package/dist/components/modals/InputModal.js.map +1 -1
- package/dist/components/modals/InputModal.mjs +18 -14
- package/dist/components/modals/InputModal.mjs.map +1 -1
- package/dist/components/modals/LanguageModal.js +729 -434
- package/dist/components/modals/LanguageModal.js.map +1 -1
- package/dist/components/modals/LanguageModal.mjs +729 -430
- package/dist/components/modals/LanguageModal.mjs.map +1 -1
- package/dist/components/modals/ThemeModal.js +733 -438
- package/dist/components/modals/ThemeModal.js.map +1 -1
- package/dist/components/modals/ThemeModal.mjs +732 -433
- package/dist/components/modals/ThemeModal.mjs.map +1 -1
- package/dist/components/properties/CheckboxProperty.js +110 -35
- package/dist/components/properties/CheckboxProperty.js.map +1 -1
- package/dist/components/properties/CheckboxProperty.mjs +110 -35
- package/dist/components/properties/CheckboxProperty.mjs.map +1 -1
- package/dist/components/properties/DateProperty.js +118 -41
- package/dist/components/properties/DateProperty.js.map +1 -1
- package/dist/components/properties/DateProperty.mjs +114 -37
- package/dist/components/properties/DateProperty.mjs.map +1 -1
- package/dist/components/properties/MultiSelectProperty.d.mts +10 -3
- package/dist/components/properties/MultiSelectProperty.d.ts +10 -3
- package/dist/components/properties/MultiSelectProperty.js +916 -463
- package/dist/components/properties/MultiSelectProperty.js.map +1 -1
- package/dist/components/properties/MultiSelectProperty.mjs +921 -464
- package/dist/components/properties/MultiSelectProperty.mjs.map +1 -1
- package/dist/components/properties/NumberProperty.js +101 -18
- package/dist/components/properties/NumberProperty.js.map +1 -1
- package/dist/components/properties/NumberProperty.mjs +101 -18
- package/dist/components/properties/NumberProperty.mjs.map +1 -1
- package/dist/components/properties/PropertyBase.js +103 -20
- package/dist/components/properties/PropertyBase.js.map +1 -1
- package/dist/components/properties/PropertyBase.mjs +99 -16
- package/dist/components/properties/PropertyBase.mjs.map +1 -1
- package/dist/components/properties/SelectProperty.d.mts +9 -2
- package/dist/components/properties/SelectProperty.d.ts +9 -2
- package/dist/components/properties/SelectProperty.js +683 -243
- package/dist/components/properties/SelectProperty.js.map +1 -1
- package/dist/components/properties/SelectProperty.mjs +687 -243
- package/dist/components/properties/SelectProperty.mjs.map +1 -1
- package/dist/components/properties/TextProperty.js +133 -46
- package/dist/components/properties/TextProperty.js.map +1 -1
- package/dist/components/properties/TextProperty.mjs +133 -46
- package/dist/components/properties/TextProperty.mjs.map +1 -1
- package/dist/components/table/Table.js +285 -185
- package/dist/components/table/Table.js.map +1 -1
- package/dist/components/table/Table.mjs +270 -166
- package/dist/components/table/Table.mjs.map +1 -1
- package/dist/components/table/TableFilterButton.js +179 -78
- package/dist/components/table/TableFilterButton.js.map +1 -1
- package/dist/components/table/TableFilterButton.mjs +160 -55
- package/dist/components/table/TableFilterButton.mjs.map +1 -1
- package/dist/components/table/TableSortButton.js +72 -3
- package/dist/components/table/TableSortButton.js.map +1 -1
- package/dist/components/table/TableSortButton.mjs +72 -3
- package/dist/components/table/TableSortButton.mjs.map +1 -1
- package/dist/components/user-action/Button.d.mts +15 -2
- package/dist/components/user-action/Button.d.ts +15 -2
- package/dist/components/user-action/Button.js +12 -12
- package/dist/components/user-action/Button.js.map +1 -1
- package/dist/components/user-action/Button.mjs +12 -12
- package/dist/components/user-action/Button.mjs.map +1 -1
- package/dist/components/user-action/Checkbox.js +6 -15
- package/dist/components/user-action/Checkbox.js.map +1 -1
- package/dist/components/user-action/Checkbox.mjs +6 -15
- package/dist/components/user-action/Checkbox.mjs.map +1 -1
- package/dist/components/user-action/CopyToClipboardWrapper.js +6 -2
- package/dist/components/user-action/CopyToClipboardWrapper.js.map +1 -1
- package/dist/components/user-action/CopyToClipboardWrapper.mjs +6 -2
- package/dist/components/user-action/CopyToClipboardWrapper.mjs.map +1 -1
- package/dist/components/user-action/DateAndTimePicker.js +81 -49
- package/dist/components/user-action/DateAndTimePicker.js.map +1 -1
- package/dist/components/user-action/DateAndTimePicker.mjs +67 -35
- package/dist/components/user-action/DateAndTimePicker.mjs.map +1 -1
- package/dist/components/user-action/Menu.d.mts +11 -6
- package/dist/components/user-action/Menu.d.ts +11 -6
- package/dist/components/user-action/Menu.js +128 -31
- package/dist/components/user-action/Menu.js.map +1 -1
- package/dist/components/user-action/Menu.mjs +134 -33
- package/dist/components/user-action/Menu.mjs.map +1 -1
- package/dist/components/user-action/MultiSelect.d.mts +17 -7
- package/dist/components/user-action/MultiSelect.d.ts +17 -7
- package/dist/components/user-action/MultiSelect.js +797 -375
- package/dist/components/user-action/MultiSelect.js.map +1 -1
- package/dist/components/user-action/MultiSelect.mjs +782 -356
- package/dist/components/user-action/MultiSelect.mjs.map +1 -1
- package/dist/components/user-action/ScrollPicker.js +2 -2
- package/dist/components/user-action/ScrollPicker.js.map +1 -1
- package/dist/components/user-action/ScrollPicker.mjs +2 -2
- package/dist/components/user-action/ScrollPicker.mjs.map +1 -1
- package/dist/components/user-action/SearchBar.d.mts +14 -0
- package/dist/components/user-action/SearchBar.d.ts +14 -0
- package/dist/components/user-action/SearchBar.js +673 -0
- package/dist/components/user-action/SearchBar.js.map +1 -0
- package/dist/components/user-action/SearchBar.mjs +637 -0
- package/dist/components/user-action/SearchBar.mjs.map +1 -0
- package/dist/components/user-action/Select.d.mts +18 -5
- package/dist/components/user-action/Select.d.ts +18 -5
- package/dist/components/user-action/Select.js +765 -355
- package/dist/components/user-action/Select.js.map +1 -1
- package/dist/components/user-action/Select.mjs +762 -349
- package/dist/components/user-action/Select.mjs.map +1 -1
- package/dist/components/user-action/Textarea.d.mts +1 -1
- package/dist/components/user-action/Textarea.d.ts +1 -1
- package/dist/components/user-action/Textarea.js +13 -3
- package/dist/components/user-action/Textarea.js.map +1 -1
- package/dist/components/user-action/Textarea.mjs +13 -3
- package/dist/components/user-action/Textarea.mjs.map +1 -1
- package/dist/components/user-action/ToggleableInput.js +2 -2
- package/dist/components/user-action/ToggleableInput.js.map +1 -1
- package/dist/components/user-action/ToggleableInput.mjs +2 -2
- package/dist/components/user-action/ToggleableInput.mjs.map +1 -1
- package/dist/css/globals.css +284 -113
- package/dist/css/uncompiled/globals.css +19 -13
- package/dist/css/uncompiled/theme/colors-component.css +12 -3
- package/dist/css/uncompiled/theme/colors-semantic.css +10 -7
- package/dist/css/uncompiled/utitlity/animation.css +96 -1
- package/dist/css/uncompiled/utitlity/general.css +16 -0
- package/dist/hooks/usePopoverPosition.d.mts +15 -0
- package/dist/hooks/usePopoverPosition.d.ts +15 -0
- package/dist/hooks/usePopoverPosition.js +81 -0
- package/dist/hooks/usePopoverPosition.js.map +1 -0
- package/dist/hooks/usePopoverPosition.mjs +57 -0
- package/dist/hooks/usePopoverPosition.mjs.map +1 -0
- package/dist/hooks/useSearch.d.mts +7 -2
- package/dist/hooks/useSearch.d.ts +7 -2
- package/dist/hooks/useSearch.js +44 -15
- package/dist/hooks/useSearch.js.map +1 -1
- package/dist/hooks/useSearch.mjs +45 -16
- package/dist/hooks/useSearch.mjs.map +1 -1
- package/dist/index.d.mts +7 -4
- package/dist/index.d.ts +7 -4
- package/dist/index.js +1197 -902
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1048 -754
- package/dist/index.mjs.map +1 -1
- package/dist/localization/defaults/form.d.mts +2 -0
- package/dist/localization/defaults/form.d.ts +2 -0
- package/dist/localization/defaults/form.js +4 -0
- package/dist/localization/defaults/form.js.map +1 -1
- package/dist/localization/defaults/form.mjs +4 -0
- package/dist/localization/defaults/form.mjs.map +1 -1
- package/dist/util/simpleSearch.d.mts +1 -1
- package/dist/util/simpleSearch.d.ts +1 -1
- package/dist/util/simpleSearch.js +4 -1
- package/dist/util/simpleSearch.js.map +1 -1
- package/dist/util/simpleSearch.mjs +4 -1
- package/dist/util/simpleSearch.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -111,7 +111,62 @@ var BagFunctionUtil = {
|
|
|
111
111
|
resolve
|
|
112
112
|
};
|
|
113
113
|
|
|
114
|
+
// src/hooks/usePopoverPosition.ts
|
|
115
|
+
var defaultPopoverPositionOptions = {
|
|
116
|
+
edgePadding: 16,
|
|
117
|
+
outerGap: 4,
|
|
118
|
+
horizontalAlignment: "leftInside",
|
|
119
|
+
verticalAlignment: "bottomOutside",
|
|
120
|
+
disabled: false
|
|
121
|
+
};
|
|
122
|
+
var usePopoverPosition = (trigger, options) => {
|
|
123
|
+
const {
|
|
124
|
+
edgePadding,
|
|
125
|
+
outerGap,
|
|
126
|
+
verticalAlignment,
|
|
127
|
+
horizontalAlignment,
|
|
128
|
+
disabled
|
|
129
|
+
} = { ...defaultPopoverPositionOptions, ...options };
|
|
130
|
+
if (disabled || !trigger) {
|
|
131
|
+
return {};
|
|
132
|
+
}
|
|
133
|
+
const left = {
|
|
134
|
+
leftOutside: trigger.left - outerGap,
|
|
135
|
+
leftInside: trigger.left,
|
|
136
|
+
rightOutside: trigger.right + outerGap,
|
|
137
|
+
rightInside: trigger.right,
|
|
138
|
+
center: trigger.left + trigger.width / 2
|
|
139
|
+
}[horizontalAlignment];
|
|
140
|
+
const top = {
|
|
141
|
+
topOutside: trigger.top - outerGap,
|
|
142
|
+
topInside: trigger.top,
|
|
143
|
+
bottomOutside: trigger.bottom + outerGap,
|
|
144
|
+
bottomInside: trigger.bottom,
|
|
145
|
+
center: trigger.top + trigger.height / 2
|
|
146
|
+
}[verticalAlignment];
|
|
147
|
+
const translateX = {
|
|
148
|
+
leftOutside: "-100%",
|
|
149
|
+
leftInside: void 0,
|
|
150
|
+
rightOutside: void 0,
|
|
151
|
+
rightInside: "-100%",
|
|
152
|
+
center: "-50%"
|
|
153
|
+
}[horizontalAlignment];
|
|
154
|
+
const translateY = {
|
|
155
|
+
topOutside: "-100%",
|
|
156
|
+
topInside: void 0,
|
|
157
|
+
bottomOutside: void 0,
|
|
158
|
+
bottomInside: "-100%",
|
|
159
|
+
center: "-50%"
|
|
160
|
+
}[verticalAlignment];
|
|
161
|
+
return {
|
|
162
|
+
left: Math.max(left, edgePadding),
|
|
163
|
+
top: Math.max(top, edgePadding),
|
|
164
|
+
translate: [translateX ?? "0", translateY ?? "0"].join(" ")
|
|
165
|
+
};
|
|
166
|
+
};
|
|
167
|
+
|
|
114
168
|
// src/components/user-action/Menu.tsx
|
|
169
|
+
var import_react_dom = require("react-dom");
|
|
115
170
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
116
171
|
var MenuItem = ({
|
|
117
172
|
children,
|
|
@@ -122,7 +177,7 @@ var MenuItem = ({
|
|
|
122
177
|
}) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
123
178
|
"div",
|
|
124
179
|
{
|
|
125
|
-
className: (0, import_clsx.default)("block px-3 py-1.5
|
|
180
|
+
className: (0, import_clsx.default)("block px-3 py-1.5 first:rounded-t-md last:rounded-b-md text-sm font-semibold", {
|
|
126
181
|
"text-right": alignment === "right",
|
|
127
182
|
"text-left": alignment === "left",
|
|
128
183
|
"text-disabled-text cursor-not-allowed": isDisabled,
|
|
@@ -133,47 +188,89 @@ var MenuItem = ({
|
|
|
133
188
|
children
|
|
134
189
|
}
|
|
135
190
|
);
|
|
191
|
+
function getScrollableParents(element) {
|
|
192
|
+
const scrollables = [];
|
|
193
|
+
let parent = element.parentElement;
|
|
194
|
+
while (parent) {
|
|
195
|
+
scrollables.push(parent);
|
|
196
|
+
parent = parent.parentElement;
|
|
197
|
+
}
|
|
198
|
+
return scrollables;
|
|
199
|
+
}
|
|
136
200
|
var Menu = ({
|
|
137
201
|
trigger,
|
|
138
202
|
children,
|
|
139
|
-
|
|
203
|
+
alignmentHorizontal = "leftInside",
|
|
204
|
+
alignmentVertical = "bottomOutside",
|
|
140
205
|
showOnHover = false,
|
|
206
|
+
disabled = false,
|
|
141
207
|
menuClassName = ""
|
|
142
208
|
}) => {
|
|
143
|
-
const { isHovered: isOpen, setIsHovered: setIsOpen
|
|
209
|
+
const { isHovered: isOpen, setIsHovered: setIsOpen } = useHoverState({ isDisabled: !showOnHover || disabled });
|
|
144
210
|
const triggerRef = (0, import_react3.useRef)(null);
|
|
145
211
|
const menuRef = (0, import_react3.useRef)(null);
|
|
146
212
|
useOutsideClick([triggerRef, menuRef], () => setIsOpen(false));
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
213
|
+
const [isHidden, setIsHidden] = (0, import_react3.useState)(true);
|
|
214
|
+
const bag = {
|
|
215
|
+
isOpen,
|
|
216
|
+
close: () => setIsOpen(false),
|
|
217
|
+
toggleOpen: () => setIsOpen((prevState) => !prevState),
|
|
218
|
+
disabled
|
|
219
|
+
};
|
|
220
|
+
const menuPosition = usePopoverPosition(
|
|
221
|
+
triggerRef.current?.getBoundingClientRect(),
|
|
222
|
+
{ verticalAlignment: alignmentVertical, horizontalAlignment: alignmentHorizontal, disabled }
|
|
223
|
+
);
|
|
224
|
+
(0, import_react3.useEffect)(() => {
|
|
225
|
+
if (!isOpen) return;
|
|
226
|
+
const triggerEl = triggerRef.current;
|
|
227
|
+
if (!triggerEl) return;
|
|
228
|
+
const scrollableParents = getScrollableParents(triggerEl);
|
|
229
|
+
const close = () => setIsOpen(false);
|
|
230
|
+
scrollableParents.forEach((parent) => {
|
|
231
|
+
parent.addEventListener("scroll", close);
|
|
232
|
+
});
|
|
233
|
+
window.addEventListener("resize", close);
|
|
234
|
+
return () => {
|
|
235
|
+
scrollableParents.forEach((parent) => {
|
|
236
|
+
parent.removeEventListener("scroll", close);
|
|
237
|
+
});
|
|
238
|
+
window.removeEventListener("resize", close);
|
|
239
|
+
};
|
|
240
|
+
}, [isOpen, setIsOpen]);
|
|
241
|
+
(0, import_react3.useEffect)(() => {
|
|
242
|
+
if (isOpen) {
|
|
243
|
+
setIsHidden(false);
|
|
244
|
+
}
|
|
245
|
+
}, [isOpen]);
|
|
246
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
247
|
+
trigger(bag, triggerRef),
|
|
248
|
+
(0, import_react_dom.createPortal)(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
249
|
+
"div",
|
|
250
|
+
{
|
|
251
|
+
ref: menuRef,
|
|
252
|
+
onClick: (e) => e.stopPropagation(),
|
|
253
|
+
className: (0, import_clsx.default)(
|
|
254
|
+
"absolute rounded-md bg-menu-background text-menu-text shadow-around-lg z-10",
|
|
157
255
|
{
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
"hidden": !isOpen
|
|
168
|
-
},
|
|
169
|
-
menuClassName
|
|
170
|
-
),
|
|
171
|
-
children: BagFunctionUtil.resolve(children, bag)
|
|
256
|
+
"animate-pop-in": isOpen,
|
|
257
|
+
"animate-pop-out": !isOpen,
|
|
258
|
+
"hidden": isHidden
|
|
259
|
+
},
|
|
260
|
+
menuClassName
|
|
261
|
+
),
|
|
262
|
+
onAnimationEnd: () => {
|
|
263
|
+
if (!isOpen) {
|
|
264
|
+
setIsHidden(true);
|
|
172
265
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
266
|
+
},
|
|
267
|
+
style: {
|
|
268
|
+
...menuPosition
|
|
269
|
+
},
|
|
270
|
+
children: BagFunctionUtil.resolve(children, bag)
|
|
271
|
+
}
|
|
272
|
+
), document.body)
|
|
273
|
+
] });
|
|
177
274
|
};
|
|
178
275
|
// Annotate the CommonJS export names for ESM import in node:
|
|
179
276
|
0 && (module.exports = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/user-action/Menu.tsx","../../../src/hooks/useOutsideClick.ts","../../../src/hooks/useHoverState.ts","../../../src/util/PropsWithFunctionChildren.ts"],"sourcesContent":["import { type PropsWithChildren, type ReactNode, type RefObject, useRef } from 'react'\nimport clsx from 'clsx'\nimport { useOutsideClick } from '../../hooks/useOutsideClick'\nimport { useHoverState } from '../../hooks/useHoverState'\nimport type { PropsWithBagFunctionOrChildren } from '../../util/PropsWithFunctionChildren'\nimport { BagFunctionUtil } from '../../util/PropsWithFunctionChildren'\n\nexport type MenuItemProps = {\n onClick?: () => void,\n alignment?: 'left' | 'right',\n isDisabled?: boolean,\n className?: string,\n}\nexport const MenuItem = ({\n children,\n onClick,\n alignment = 'left',\n isDisabled = false,\n className\n }: PropsWithChildren<MenuItemProps>) => (\n <div\n className={clsx('block px-3 py-1.5 bg-menu-background first:rounded-t-lg last:rounded-b-lg text-sm font-semibold', {\n 'text-right': alignment === 'right',\n 'text-left': alignment === 'left',\n 'text-disabled-text cursor-not-allowed': isDisabled,\n 'text-menu-text hover:bg-primary/20': !isDisabled,\n 'cursor-pointer': !!onClick,\n }, className)}\n onClick={onClick}\n >\n {children}\n </div>\n)\n\ntype MenuBag = {\n isOpen: boolean,\n close: () => void,\n}\n\nexport type MenuProps<T> = PropsWithBagFunctionOrChildren<MenuBag> & {\n trigger: (onClick: () => void, ref: RefObject<T>) => ReactNode,\n /**\n * @default 'tl'\n */\n alignment?: 'tl' | 'tr' | 'bl' | 'br' | '_l' | '_r' | 't_' | 'b_',\n showOnHover?: boolean,\n menuClassName?: string,\n}\n\n/**\n * A Menu Component to allow the user to see different functions\n */\nexport const Menu = <T extends HTMLElement>({\n trigger,\n children,\n alignment = 'tl',\n showOnHover = false,\n menuClassName = '',\n }: MenuProps<T>) => {\n const { isHovered: isOpen, setIsHovered: setIsOpen, handlers } = useHoverState({ isDisabled: !showOnHover })\n const triggerRef = useRef<T>(null)\n const menuRef = useRef<HTMLDivElement>(null)\n useOutsideClick([triggerRef, menuRef], () => setIsOpen(false))\n\n const bag: MenuBag = { isOpen, close: () => setIsOpen(false) }\n\n return (\n <div\n className=\"relative\"\n {...handlers}\n >\n {trigger(() => setIsOpen(!isOpen), triggerRef)}\n <div\n ref={menuRef}\n onClick={e => e.stopPropagation()}\n className={clsx(\n 'absolute top-full mt-1 min-w-40 rounded-lg bg-menu-background text-menu-text shadow-around-lg z-10',\n {\n 'top-0': alignment[0] === 't',\n 'bottom-0': alignment[0] === 'b',\n 'left-0': alignment[1] === 'l',\n 'right-0': alignment[1] === 'r',\n 'hidden': !isOpen,\n },\n menuClassName\n )}\n >\n {BagFunctionUtil.resolve<MenuBag>(children, bag)}\n </div>\n </div>\n )\n}","import type { RefObject } from 'react'\nimport { useEffect } from 'react'\n\nexport const useOutsideClick = <Ts extends RefObject<HTMLElement>[]>(refs: Ts, handler: () => void) => {\n useEffect(() => {\n const listener = (event: MouseEvent | TouchEvent) => {\n // returning means not \"not clicking outside\"\n\n // if no target exists, return\n if (event.target === null) return\n // if the target is a ref's element or descendent thereof, return\n if (refs.some((ref) => !ref.current || ref.current.contains(event.target as Node))) {\n return\n }\n\n handler()\n }\n document.addEventListener('mousedown', listener)\n document.addEventListener('touchstart', listener)\n return () => {\n document.removeEventListener('mousedown', listener)\n document.removeEventListener('touchstart', listener)\n }\n }, [refs, handler])\n}\n","import type { Dispatch, SetStateAction } from 'react'\nimport { useEffect, useState } from 'react'\n\ntype UseHoverStateProps = {\n /**\n * The delay after which the menu is closed in milliseconds\n *\n * default: 200ms\n */\n closingDelay: number,\n /**\n * Whether the hover state management should be disabled\n *\n * default: false\n */\n isDisabled: boolean,\n}\n\ntype UseHoverStateReturnType = {\n /**\n * Whether the element is hovered\n */\n isHovered: boolean,\n /**\n * Function to change the current hover status\n */\n setIsHovered: Dispatch<SetStateAction<boolean>>,\n /**\n * Handlers to pass on to the component that should be hovered\n */\n handlers: {\n onMouseEnter: () => void,\n onMouseLeave: () => void,\n },\n}\n\nconst defaultUseHoverStateProps: UseHoverStateProps = {\n closingDelay: 200,\n isDisabled: false,\n}\n\n/**\n * @param props See UseHoverStateProps\n *\n * A react hook for managing the hover state of a component. The handlers provided should be\n * forwarded to the component which should be hovered over\n */\nexport const useHoverState = (props: Partial<UseHoverStateProps> | undefined = undefined): UseHoverStateReturnType => {\n const { closingDelay, isDisabled } = { ...defaultUseHoverStateProps, ...props }\n\n const [isHovered, setIsHovered] = useState(false)\n const [timer, setTimer] = useState<NodeJS.Timeout>()\n\n const onMouseEnter = () => {\n if (isDisabled) {\n return\n }\n clearTimeout(timer)\n setIsHovered(true)\n }\n\n const onMouseLeave = () => {\n if (isDisabled) {\n return\n }\n setTimer(setTimeout(() => {\n setIsHovered(false)\n }, closingDelay))\n }\n\n useEffect(() => {\n if (timer) {\n return () => {\n clearTimeout(timer)\n }\n }\n })\n\n useEffect(() => {\n if (timer) {\n clearTimeout(timer)\n }\n }, [isDisabled]) // eslint-disable-line react-hooks/exhaustive-deps\n\n return {\n isHovered, setIsHovered, handlers: { onMouseEnter, onMouseLeave }\n }\n}\n","import type { ReactNode } from 'react'\n\nexport type BagFunction<T> = (bag: T) => ReactNode\n\nexport type PropsWithBagFunction<T, P = unknown> = P & { children?: BagFunction<T> }\n\nexport type PropsWithBagFunctionOrChildren<T, P = unknown> = P & { children?: BagFunction<T> | ReactNode }\n\nconst resolve = <T>(children: BagFunction<T> | ReactNode, bag: T): ReactNode => {\n if (typeof children === 'function') {\n return (children as BagFunction<T>)(bag)\n }\n\n return children ?? undefined\n}\n\nexport const BagFunctionUtil = {\n resolve\n}"],"mappings":"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","names":["import_react","import_react","clsx"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/user-action/Menu.tsx","../../../src/hooks/useOutsideClick.ts","../../../src/hooks/useHoverState.ts","../../../src/util/PropsWithFunctionChildren.ts","../../../src/hooks/usePopoverPosition.ts"],"sourcesContent":["import {\n type PropsWithChildren,\n type ReactNode,\n type RefObject,\n useEffect,\n useRef, useState\n} from 'react'\nimport clsx from 'clsx'\nimport { useOutsideClick } from '../../hooks/useOutsideClick'\nimport { useHoverState } from '../../hooks/useHoverState'\nimport type { PropsWithBagFunctionOrChildren } from '../../util/PropsWithFunctionChildren'\nimport { BagFunctionUtil } from '../../util/PropsWithFunctionChildren'\nimport type { PopoverHorizontalAlignment, PopoverVerticalAlignment } from '../../hooks/usePopoverPosition'\nimport { usePopoverPosition } from '../../hooks/usePopoverPosition'\nimport { createPortal } from 'react-dom'\n\nexport type MenuItemProps = {\n onClick?: () => void,\n alignment?: 'left' | 'right',\n isDisabled?: boolean,\n className?: string,\n}\nexport const MenuItem = ({\n children,\n onClick,\n alignment = 'left',\n isDisabled = false,\n className\n }: PropsWithChildren<MenuItemProps>) => (\n <div\n className={clsx('block px-3 py-1.5 first:rounded-t-md last:rounded-b-md text-sm font-semibold', {\n 'text-right': alignment === 'right',\n 'text-left': alignment === 'left',\n 'text-disabled-text cursor-not-allowed': isDisabled,\n 'text-menu-text hover:bg-primary/20': !isDisabled,\n 'cursor-pointer': !!onClick,\n }, className)}\n onClick={onClick}\n >\n {children}\n </div>\n)\n\nfunction getScrollableParents(element) {\n const scrollables = []\n let parent = element.parentElement\n while (parent) {\n scrollables.push(parent)\n parent = parent.parentElement\n }\n return scrollables\n}\n\nexport type MenuBag = {\n isOpen: boolean,\n disabled: boolean,\n toggleOpen: () => void,\n close: () => void,\n}\n\nexport type MenuProps<T> = PropsWithBagFunctionOrChildren<MenuBag> & {\n trigger: (bag: MenuBag, ref: RefObject<T>) => ReactNode,\n /**\n * @default 'l'\n */\n alignmentHorizontal?: PopoverHorizontalAlignment,\n alignmentVertical?: PopoverVerticalAlignment,\n showOnHover?: boolean,\n menuClassName?: string,\n disabled?: boolean,\n}\n\n/**\n * A Menu Component to allow the user to see different functions\n */\nexport const Menu = <T extends HTMLElement>({\n trigger,\n children,\n alignmentHorizontal = 'leftInside',\n alignmentVertical = 'bottomOutside',\n showOnHover = false,\n disabled = false,\n menuClassName = '',\n }: MenuProps<T>) => {\n const { isHovered: isOpen, setIsHovered: setIsOpen } = useHoverState({ isDisabled: !showOnHover || disabled })\n const triggerRef = useRef<T>(null)\n const menuRef = useRef<HTMLDivElement>(null)\n useOutsideClick([triggerRef, menuRef], () => setIsOpen(false))\n\n const [isHidden, setIsHidden] = useState<boolean>(true)\n const bag: MenuBag = {\n isOpen,\n close: () => setIsOpen(false),\n toggleOpen: () => setIsOpen(prevState => !prevState),\n disabled,\n }\n\n const menuPosition = usePopoverPosition(\n triggerRef.current?.getBoundingClientRect(),\n { verticalAlignment: alignmentVertical, horizontalAlignment: alignmentHorizontal, disabled }\n )\n\n useEffect(() => {\n if (!isOpen) return\n\n const triggerEl = triggerRef.current\n if (!triggerEl) return\n\n const scrollableParents = getScrollableParents(triggerEl)\n\n const close = () => setIsOpen(false)\n scrollableParents.forEach((parent) => {\n parent.addEventListener('scroll', close)\n })\n window.addEventListener('resize', close)\n\n return () => {\n scrollableParents.forEach((parent) => {\n parent.removeEventListener('scroll', close)\n })\n window.removeEventListener('resize', close)\n }\n }, [isOpen, setIsOpen])\n\n useEffect(() => {\n if (isOpen) {\n setIsHidden(false)\n }\n }, [isOpen])\n\n return (\n <>\n {trigger(bag, triggerRef)}\n {createPortal((<div\n ref={menuRef}\n onClick={e => e.stopPropagation()}\n className={clsx(\n 'absolute rounded-md bg-menu-background text-menu-text shadow-around-lg z-10',\n {\n 'animate-pop-in': isOpen,\n 'animate-pop-out': !isOpen,\n 'hidden': isHidden,\n },\n menuClassName\n )}\n onAnimationEnd={() => {\n if (!isOpen) {\n setIsHidden(true)\n }\n }}\n style={{\n ...menuPosition\n }}\n >\n {BagFunctionUtil.resolve<MenuBag>(children, bag)}\n </div>), document.body)}\n </>\n )\n}\n\n","import type { RefObject } from 'react'\nimport { useEffect } from 'react'\n\nexport const useOutsideClick = <Ts extends RefObject<HTMLElement>[]>(refs: Ts, handler: () => void) => {\n useEffect(() => {\n const listener = (event: MouseEvent | TouchEvent) => {\n // returning means not \"not clicking outside\"\n\n // if no target exists, return\n if (event.target === null) return\n // if the target is a ref's element or descendent thereof, return\n if (refs.some((ref) => !ref.current || ref.current.contains(event.target as Node))) {\n return\n }\n\n handler()\n }\n document.addEventListener('mousedown', listener)\n document.addEventListener('touchstart', listener)\n return () => {\n document.removeEventListener('mousedown', listener)\n document.removeEventListener('touchstart', listener)\n }\n }, [refs, handler])\n}\n","import type { Dispatch, SetStateAction } from 'react'\nimport { useEffect, useState } from 'react'\n\ntype UseHoverStateProps = {\n /**\n * The delay after which the menu is closed in milliseconds\n *\n * default: 200ms\n */\n closingDelay: number,\n /**\n * Whether the hover state management should be disabled\n *\n * default: false\n */\n isDisabled: boolean,\n}\n\ntype UseHoverStateReturnType = {\n /**\n * Whether the element is hovered\n */\n isHovered: boolean,\n /**\n * Function to change the current hover status\n */\n setIsHovered: Dispatch<SetStateAction<boolean>>,\n /**\n * Handlers to pass on to the component that should be hovered\n */\n handlers: {\n onMouseEnter: () => void,\n onMouseLeave: () => void,\n },\n}\n\nconst defaultUseHoverStateProps: UseHoverStateProps = {\n closingDelay: 200,\n isDisabled: false,\n}\n\n/**\n * @param props See UseHoverStateProps\n *\n * A react hook for managing the hover state of a component. The handlers provided should be\n * forwarded to the component which should be hovered over\n */\nexport const useHoverState = (props: Partial<UseHoverStateProps> | undefined = undefined): UseHoverStateReturnType => {\n const { closingDelay, isDisabled } = { ...defaultUseHoverStateProps, ...props }\n\n const [isHovered, setIsHovered] = useState(false)\n const [timer, setTimer] = useState<NodeJS.Timeout>()\n\n const onMouseEnter = () => {\n if (isDisabled) {\n return\n }\n clearTimeout(timer)\n setIsHovered(true)\n }\n\n const onMouseLeave = () => {\n if (isDisabled) {\n return\n }\n setTimer(setTimeout(() => {\n setIsHovered(false)\n }, closingDelay))\n }\n\n useEffect(() => {\n if (timer) {\n return () => {\n clearTimeout(timer)\n }\n }\n })\n\n useEffect(() => {\n if (timer) {\n clearTimeout(timer)\n }\n }, [isDisabled]) // eslint-disable-line react-hooks/exhaustive-deps\n\n return {\n isHovered, setIsHovered, handlers: { onMouseEnter, onMouseLeave }\n }\n}\n","import type { ReactNode } from 'react'\n\nexport type BagFunction<T> = (bag: T) => ReactNode\n\nexport type PropsWithBagFunction<T, P = unknown> = P & { children?: BagFunction<T> }\n\nexport type PropsWithBagFunctionOrChildren<T, P = unknown> = P & { children?: BagFunction<T> | ReactNode }\n\nconst resolve = <T>(children: BagFunction<T> | ReactNode, bag: T): ReactNode => {\n if (typeof children === 'function') {\n return (children as BagFunction<T>)(bag)\n }\n\n return children ?? undefined\n}\n\nexport const BagFunctionUtil = {\n resolve\n}","import type { CSSProperties } from 'react'\n\nexport type PopoverHorizontalAlignment = 'leftOutside' | 'leftInside' | 'rightOutside' | 'rightInside' | 'center'\nexport type PopoverVerticalAlignment = 'topOutside' | 'topInside' | 'bottomOutside' | 'bottomInside' | 'center'\n\ntype PopoverPositionOptionsResolved = {\n edgePadding: number,\n outerGap: number,\n verticalAlignment: PopoverVerticalAlignment,\n horizontalAlignment: PopoverHorizontalAlignment,\n disabled: boolean,\n}\n\ntype PopoverPositionOptions = Partial<PopoverPositionOptionsResolved>\n\nconst defaultPopoverPositionOptions: PopoverPositionOptionsResolved = {\n edgePadding: 16,\n outerGap: 4,\n horizontalAlignment: 'leftInside',\n verticalAlignment: 'bottomOutside',\n disabled: false,\n}\n\nexport const usePopoverPosition = (trigger?: DOMRect, options?: PopoverPositionOptions): CSSProperties => {\n const {\n edgePadding,\n outerGap,\n verticalAlignment,\n horizontalAlignment,\n disabled\n }: PopoverPositionOptionsResolved = { ...defaultPopoverPositionOptions, ...options }\n\n if (disabled || !trigger) {\n return {}\n }\n\n const left: number = {\n leftOutside: trigger.left - outerGap,\n leftInside: trigger.left,\n rightOutside: trigger.right + outerGap,\n rightInside: trigger.right,\n center: trigger.left + trigger.width / 2,\n }[horizontalAlignment]\n\n const top: number = {\n topOutside: trigger.top - outerGap,\n topInside: trigger.top,\n bottomOutside: trigger.bottom + outerGap,\n bottomInside: trigger.bottom,\n center: trigger.top + trigger.height / 2,\n }[verticalAlignment]\n\n const translateX: string | undefined = {\n leftOutside: '-100%',\n leftInside: undefined,\n rightOutside: undefined,\n rightInside: '-100%',\n center: '-50%',\n }[horizontalAlignment]\n\n const translateY: string | undefined = {\n topOutside: '-100%',\n topInside: undefined,\n bottomOutside: undefined,\n bottomInside: '-100%',\n center: '-50%',\n }[verticalAlignment]\n\n return {\n left: Math.max(left, edgePadding),\n top: Math.max(top, edgePadding),\n translate: [translateX ?? '0', translateY ?? '0'].join(' ')\n }\n}"],"mappings":"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","names":["import_react","import_react","clsx"]}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
// src/components/user-action/Menu.tsx
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
useEffect as useEffect3,
|
|
4
|
+
useRef,
|
|
5
|
+
useState as useState2
|
|
6
|
+
} from "react";
|
|
3
7
|
import clsx from "clsx";
|
|
4
8
|
|
|
5
9
|
// src/hooks/useOutsideClick.ts
|
|
@@ -77,8 +81,63 @@ var BagFunctionUtil = {
|
|
|
77
81
|
resolve
|
|
78
82
|
};
|
|
79
83
|
|
|
84
|
+
// src/hooks/usePopoverPosition.ts
|
|
85
|
+
var defaultPopoverPositionOptions = {
|
|
86
|
+
edgePadding: 16,
|
|
87
|
+
outerGap: 4,
|
|
88
|
+
horizontalAlignment: "leftInside",
|
|
89
|
+
verticalAlignment: "bottomOutside",
|
|
90
|
+
disabled: false
|
|
91
|
+
};
|
|
92
|
+
var usePopoverPosition = (trigger, options) => {
|
|
93
|
+
const {
|
|
94
|
+
edgePadding,
|
|
95
|
+
outerGap,
|
|
96
|
+
verticalAlignment,
|
|
97
|
+
horizontalAlignment,
|
|
98
|
+
disabled
|
|
99
|
+
} = { ...defaultPopoverPositionOptions, ...options };
|
|
100
|
+
if (disabled || !trigger) {
|
|
101
|
+
return {};
|
|
102
|
+
}
|
|
103
|
+
const left = {
|
|
104
|
+
leftOutside: trigger.left - outerGap,
|
|
105
|
+
leftInside: trigger.left,
|
|
106
|
+
rightOutside: trigger.right + outerGap,
|
|
107
|
+
rightInside: trigger.right,
|
|
108
|
+
center: trigger.left + trigger.width / 2
|
|
109
|
+
}[horizontalAlignment];
|
|
110
|
+
const top = {
|
|
111
|
+
topOutside: trigger.top - outerGap,
|
|
112
|
+
topInside: trigger.top,
|
|
113
|
+
bottomOutside: trigger.bottom + outerGap,
|
|
114
|
+
bottomInside: trigger.bottom,
|
|
115
|
+
center: trigger.top + trigger.height / 2
|
|
116
|
+
}[verticalAlignment];
|
|
117
|
+
const translateX = {
|
|
118
|
+
leftOutside: "-100%",
|
|
119
|
+
leftInside: void 0,
|
|
120
|
+
rightOutside: void 0,
|
|
121
|
+
rightInside: "-100%",
|
|
122
|
+
center: "-50%"
|
|
123
|
+
}[horizontalAlignment];
|
|
124
|
+
const translateY = {
|
|
125
|
+
topOutside: "-100%",
|
|
126
|
+
topInside: void 0,
|
|
127
|
+
bottomOutside: void 0,
|
|
128
|
+
bottomInside: "-100%",
|
|
129
|
+
center: "-50%"
|
|
130
|
+
}[verticalAlignment];
|
|
131
|
+
return {
|
|
132
|
+
left: Math.max(left, edgePadding),
|
|
133
|
+
top: Math.max(top, edgePadding),
|
|
134
|
+
translate: [translateX ?? "0", translateY ?? "0"].join(" ")
|
|
135
|
+
};
|
|
136
|
+
};
|
|
137
|
+
|
|
80
138
|
// src/components/user-action/Menu.tsx
|
|
81
|
-
import {
|
|
139
|
+
import { createPortal } from "react-dom";
|
|
140
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
82
141
|
var MenuItem = ({
|
|
83
142
|
children,
|
|
84
143
|
onClick,
|
|
@@ -88,7 +147,7 @@ var MenuItem = ({
|
|
|
88
147
|
}) => /* @__PURE__ */ jsx(
|
|
89
148
|
"div",
|
|
90
149
|
{
|
|
91
|
-
className: clsx("block px-3 py-1.5
|
|
150
|
+
className: clsx("block px-3 py-1.5 first:rounded-t-md last:rounded-b-md text-sm font-semibold", {
|
|
92
151
|
"text-right": alignment === "right",
|
|
93
152
|
"text-left": alignment === "left",
|
|
94
153
|
"text-disabled-text cursor-not-allowed": isDisabled,
|
|
@@ -99,47 +158,89 @@ var MenuItem = ({
|
|
|
99
158
|
children
|
|
100
159
|
}
|
|
101
160
|
);
|
|
161
|
+
function getScrollableParents(element) {
|
|
162
|
+
const scrollables = [];
|
|
163
|
+
let parent = element.parentElement;
|
|
164
|
+
while (parent) {
|
|
165
|
+
scrollables.push(parent);
|
|
166
|
+
parent = parent.parentElement;
|
|
167
|
+
}
|
|
168
|
+
return scrollables;
|
|
169
|
+
}
|
|
102
170
|
var Menu = ({
|
|
103
171
|
trigger,
|
|
104
172
|
children,
|
|
105
|
-
|
|
173
|
+
alignmentHorizontal = "leftInside",
|
|
174
|
+
alignmentVertical = "bottomOutside",
|
|
106
175
|
showOnHover = false,
|
|
176
|
+
disabled = false,
|
|
107
177
|
menuClassName = ""
|
|
108
178
|
}) => {
|
|
109
|
-
const { isHovered: isOpen, setIsHovered: setIsOpen
|
|
179
|
+
const { isHovered: isOpen, setIsHovered: setIsOpen } = useHoverState({ isDisabled: !showOnHover || disabled });
|
|
110
180
|
const triggerRef = useRef(null);
|
|
111
181
|
const menuRef = useRef(null);
|
|
112
182
|
useOutsideClick([triggerRef, menuRef], () => setIsOpen(false));
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
183
|
+
const [isHidden, setIsHidden] = useState2(true);
|
|
184
|
+
const bag = {
|
|
185
|
+
isOpen,
|
|
186
|
+
close: () => setIsOpen(false),
|
|
187
|
+
toggleOpen: () => setIsOpen((prevState) => !prevState),
|
|
188
|
+
disabled
|
|
189
|
+
};
|
|
190
|
+
const menuPosition = usePopoverPosition(
|
|
191
|
+
triggerRef.current?.getBoundingClientRect(),
|
|
192
|
+
{ verticalAlignment: alignmentVertical, horizontalAlignment: alignmentHorizontal, disabled }
|
|
193
|
+
);
|
|
194
|
+
useEffect3(() => {
|
|
195
|
+
if (!isOpen) return;
|
|
196
|
+
const triggerEl = triggerRef.current;
|
|
197
|
+
if (!triggerEl) return;
|
|
198
|
+
const scrollableParents = getScrollableParents(triggerEl);
|
|
199
|
+
const close = () => setIsOpen(false);
|
|
200
|
+
scrollableParents.forEach((parent) => {
|
|
201
|
+
parent.addEventListener("scroll", close);
|
|
202
|
+
});
|
|
203
|
+
window.addEventListener("resize", close);
|
|
204
|
+
return () => {
|
|
205
|
+
scrollableParents.forEach((parent) => {
|
|
206
|
+
parent.removeEventListener("scroll", close);
|
|
207
|
+
});
|
|
208
|
+
window.removeEventListener("resize", close);
|
|
209
|
+
};
|
|
210
|
+
}, [isOpen, setIsOpen]);
|
|
211
|
+
useEffect3(() => {
|
|
212
|
+
if (isOpen) {
|
|
213
|
+
setIsHidden(false);
|
|
214
|
+
}
|
|
215
|
+
}, [isOpen]);
|
|
216
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
217
|
+
trigger(bag, triggerRef),
|
|
218
|
+
createPortal(/* @__PURE__ */ jsx(
|
|
219
|
+
"div",
|
|
220
|
+
{
|
|
221
|
+
ref: menuRef,
|
|
222
|
+
onClick: (e) => e.stopPropagation(),
|
|
223
|
+
className: clsx(
|
|
224
|
+
"absolute rounded-md bg-menu-background text-menu-text shadow-around-lg z-10",
|
|
123
225
|
{
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
"hidden": !isOpen
|
|
134
|
-
},
|
|
135
|
-
menuClassName
|
|
136
|
-
),
|
|
137
|
-
children: BagFunctionUtil.resolve(children, bag)
|
|
226
|
+
"animate-pop-in": isOpen,
|
|
227
|
+
"animate-pop-out": !isOpen,
|
|
228
|
+
"hidden": isHidden
|
|
229
|
+
},
|
|
230
|
+
menuClassName
|
|
231
|
+
),
|
|
232
|
+
onAnimationEnd: () => {
|
|
233
|
+
if (!isOpen) {
|
|
234
|
+
setIsHidden(true);
|
|
138
235
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
236
|
+
},
|
|
237
|
+
style: {
|
|
238
|
+
...menuPosition
|
|
239
|
+
},
|
|
240
|
+
children: BagFunctionUtil.resolve(children, bag)
|
|
241
|
+
}
|
|
242
|
+
), document.body)
|
|
243
|
+
] });
|
|
143
244
|
};
|
|
144
245
|
export {
|
|
145
246
|
Menu,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/user-action/Menu.tsx","../../../src/hooks/useOutsideClick.ts","../../../src/hooks/useHoverState.ts","../../../src/util/PropsWithFunctionChildren.ts"],"sourcesContent":["import { type PropsWithChildren, type ReactNode, type RefObject, useRef } from 'react'\nimport clsx from 'clsx'\nimport { useOutsideClick } from '../../hooks/useOutsideClick'\nimport { useHoverState } from '../../hooks/useHoverState'\nimport type { PropsWithBagFunctionOrChildren } from '../../util/PropsWithFunctionChildren'\nimport { BagFunctionUtil } from '../../util/PropsWithFunctionChildren'\n\nexport type MenuItemProps = {\n onClick?: () => void,\n alignment?: 'left' | 'right',\n isDisabled?: boolean,\n className?: string,\n}\nexport const MenuItem = ({\n children,\n onClick,\n alignment = 'left',\n isDisabled = false,\n className\n }: PropsWithChildren<MenuItemProps>) => (\n <div\n className={clsx('block px-3 py-1.5 bg-menu-background first:rounded-t-lg last:rounded-b-lg text-sm font-semibold', {\n 'text-right': alignment === 'right',\n 'text-left': alignment === 'left',\n 'text-disabled-text cursor-not-allowed': isDisabled,\n 'text-menu-text hover:bg-primary/20': !isDisabled,\n 'cursor-pointer': !!onClick,\n }, className)}\n onClick={onClick}\n >\n {children}\n </div>\n)\n\ntype MenuBag = {\n isOpen: boolean,\n close: () => void,\n}\n\nexport type MenuProps<T> = PropsWithBagFunctionOrChildren<MenuBag> & {\n trigger: (onClick: () => void, ref: RefObject<T>) => ReactNode,\n /**\n * @default 'tl'\n */\n alignment?: 'tl' | 'tr' | 'bl' | 'br' | '_l' | '_r' | 't_' | 'b_',\n showOnHover?: boolean,\n menuClassName?: string,\n}\n\n/**\n * A Menu Component to allow the user to see different functions\n */\nexport const Menu = <T extends HTMLElement>({\n trigger,\n children,\n alignment = 'tl',\n showOnHover = false,\n menuClassName = '',\n }: MenuProps<T>) => {\n const { isHovered: isOpen, setIsHovered: setIsOpen, handlers } = useHoverState({ isDisabled: !showOnHover })\n const triggerRef = useRef<T>(null)\n const menuRef = useRef<HTMLDivElement>(null)\n useOutsideClick([triggerRef, menuRef], () => setIsOpen(false))\n\n const bag: MenuBag = { isOpen, close: () => setIsOpen(false) }\n\n return (\n <div\n className=\"relative\"\n {...handlers}\n >\n {trigger(() => setIsOpen(!isOpen), triggerRef)}\n <div\n ref={menuRef}\n onClick={e => e.stopPropagation()}\n className={clsx(\n 'absolute top-full mt-1 min-w-40 rounded-lg bg-menu-background text-menu-text shadow-around-lg z-10',\n {\n 'top-0': alignment[0] === 't',\n 'bottom-0': alignment[0] === 'b',\n 'left-0': alignment[1] === 'l',\n 'right-0': alignment[1] === 'r',\n 'hidden': !isOpen,\n },\n menuClassName\n )}\n >\n {BagFunctionUtil.resolve<MenuBag>(children, bag)}\n </div>\n </div>\n )\n}","import type { RefObject } from 'react'\nimport { useEffect } from 'react'\n\nexport const useOutsideClick = <Ts extends RefObject<HTMLElement>[]>(refs: Ts, handler: () => void) => {\n useEffect(() => {\n const listener = (event: MouseEvent | TouchEvent) => {\n // returning means not \"not clicking outside\"\n\n // if no target exists, return\n if (event.target === null) return\n // if the target is a ref's element or descendent thereof, return\n if (refs.some((ref) => !ref.current || ref.current.contains(event.target as Node))) {\n return\n }\n\n handler()\n }\n document.addEventListener('mousedown', listener)\n document.addEventListener('touchstart', listener)\n return () => {\n document.removeEventListener('mousedown', listener)\n document.removeEventListener('touchstart', listener)\n }\n }, [refs, handler])\n}\n","import type { Dispatch, SetStateAction } from 'react'\nimport { useEffect, useState } from 'react'\n\ntype UseHoverStateProps = {\n /**\n * The delay after which the menu is closed in milliseconds\n *\n * default: 200ms\n */\n closingDelay: number,\n /**\n * Whether the hover state management should be disabled\n *\n * default: false\n */\n isDisabled: boolean,\n}\n\ntype UseHoverStateReturnType = {\n /**\n * Whether the element is hovered\n */\n isHovered: boolean,\n /**\n * Function to change the current hover status\n */\n setIsHovered: Dispatch<SetStateAction<boolean>>,\n /**\n * Handlers to pass on to the component that should be hovered\n */\n handlers: {\n onMouseEnter: () => void,\n onMouseLeave: () => void,\n },\n}\n\nconst defaultUseHoverStateProps: UseHoverStateProps = {\n closingDelay: 200,\n isDisabled: false,\n}\n\n/**\n * @param props See UseHoverStateProps\n *\n * A react hook for managing the hover state of a component. The handlers provided should be\n * forwarded to the component which should be hovered over\n */\nexport const useHoverState = (props: Partial<UseHoverStateProps> | undefined = undefined): UseHoverStateReturnType => {\n const { closingDelay, isDisabled } = { ...defaultUseHoverStateProps, ...props }\n\n const [isHovered, setIsHovered] = useState(false)\n const [timer, setTimer] = useState<NodeJS.Timeout>()\n\n const onMouseEnter = () => {\n if (isDisabled) {\n return\n }\n clearTimeout(timer)\n setIsHovered(true)\n }\n\n const onMouseLeave = () => {\n if (isDisabled) {\n return\n }\n setTimer(setTimeout(() => {\n setIsHovered(false)\n }, closingDelay))\n }\n\n useEffect(() => {\n if (timer) {\n return () => {\n clearTimeout(timer)\n }\n }\n })\n\n useEffect(() => {\n if (timer) {\n clearTimeout(timer)\n }\n }, [isDisabled]) // eslint-disable-line react-hooks/exhaustive-deps\n\n return {\n isHovered, setIsHovered, handlers: { onMouseEnter, onMouseLeave }\n }\n}\n","import type { ReactNode } from 'react'\n\nexport type BagFunction<T> = (bag: T) => ReactNode\n\nexport type PropsWithBagFunction<T, P = unknown> = P & { children?: BagFunction<T> }\n\nexport type PropsWithBagFunctionOrChildren<T, P = unknown> = P & { children?: BagFunction<T> | ReactNode }\n\nconst resolve = <T>(children: BagFunction<T> | ReactNode, bag: T): ReactNode => {\n if (typeof children === 'function') {\n return (children as BagFunction<T>)(bag)\n }\n\n return children ?? undefined\n}\n\nexport const BagFunctionUtil = {\n resolve\n}"],"mappings":"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","names":["useEffect"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/user-action/Menu.tsx","../../../src/hooks/useOutsideClick.ts","../../../src/hooks/useHoverState.ts","../../../src/util/PropsWithFunctionChildren.ts","../../../src/hooks/usePopoverPosition.ts"],"sourcesContent":["import {\n type PropsWithChildren,\n type ReactNode,\n type RefObject,\n useEffect,\n useRef, useState\n} from 'react'\nimport clsx from 'clsx'\nimport { useOutsideClick } from '../../hooks/useOutsideClick'\nimport { useHoverState } from '../../hooks/useHoverState'\nimport type { PropsWithBagFunctionOrChildren } from '../../util/PropsWithFunctionChildren'\nimport { BagFunctionUtil } from '../../util/PropsWithFunctionChildren'\nimport type { PopoverHorizontalAlignment, PopoverVerticalAlignment } from '../../hooks/usePopoverPosition'\nimport { usePopoverPosition } from '../../hooks/usePopoverPosition'\nimport { createPortal } from 'react-dom'\n\nexport type MenuItemProps = {\n onClick?: () => void,\n alignment?: 'left' | 'right',\n isDisabled?: boolean,\n className?: string,\n}\nexport const MenuItem = ({\n children,\n onClick,\n alignment = 'left',\n isDisabled = false,\n className\n }: PropsWithChildren<MenuItemProps>) => (\n <div\n className={clsx('block px-3 py-1.5 first:rounded-t-md last:rounded-b-md text-sm font-semibold', {\n 'text-right': alignment === 'right',\n 'text-left': alignment === 'left',\n 'text-disabled-text cursor-not-allowed': isDisabled,\n 'text-menu-text hover:bg-primary/20': !isDisabled,\n 'cursor-pointer': !!onClick,\n }, className)}\n onClick={onClick}\n >\n {children}\n </div>\n)\n\nfunction getScrollableParents(element) {\n const scrollables = []\n let parent = element.parentElement\n while (parent) {\n scrollables.push(parent)\n parent = parent.parentElement\n }\n return scrollables\n}\n\nexport type MenuBag = {\n isOpen: boolean,\n disabled: boolean,\n toggleOpen: () => void,\n close: () => void,\n}\n\nexport type MenuProps<T> = PropsWithBagFunctionOrChildren<MenuBag> & {\n trigger: (bag: MenuBag, ref: RefObject<T>) => ReactNode,\n /**\n * @default 'l'\n */\n alignmentHorizontal?: PopoverHorizontalAlignment,\n alignmentVertical?: PopoverVerticalAlignment,\n showOnHover?: boolean,\n menuClassName?: string,\n disabled?: boolean,\n}\n\n/**\n * A Menu Component to allow the user to see different functions\n */\nexport const Menu = <T extends HTMLElement>({\n trigger,\n children,\n alignmentHorizontal = 'leftInside',\n alignmentVertical = 'bottomOutside',\n showOnHover = false,\n disabled = false,\n menuClassName = '',\n }: MenuProps<T>) => {\n const { isHovered: isOpen, setIsHovered: setIsOpen } = useHoverState({ isDisabled: !showOnHover || disabled })\n const triggerRef = useRef<T>(null)\n const menuRef = useRef<HTMLDivElement>(null)\n useOutsideClick([triggerRef, menuRef], () => setIsOpen(false))\n\n const [isHidden, setIsHidden] = useState<boolean>(true)\n const bag: MenuBag = {\n isOpen,\n close: () => setIsOpen(false),\n toggleOpen: () => setIsOpen(prevState => !prevState),\n disabled,\n }\n\n const menuPosition = usePopoverPosition(\n triggerRef.current?.getBoundingClientRect(),\n { verticalAlignment: alignmentVertical, horizontalAlignment: alignmentHorizontal, disabled }\n )\n\n useEffect(() => {\n if (!isOpen) return\n\n const triggerEl = triggerRef.current\n if (!triggerEl) return\n\n const scrollableParents = getScrollableParents(triggerEl)\n\n const close = () => setIsOpen(false)\n scrollableParents.forEach((parent) => {\n parent.addEventListener('scroll', close)\n })\n window.addEventListener('resize', close)\n\n return () => {\n scrollableParents.forEach((parent) => {\n parent.removeEventListener('scroll', close)\n })\n window.removeEventListener('resize', close)\n }\n }, [isOpen, setIsOpen])\n\n useEffect(() => {\n if (isOpen) {\n setIsHidden(false)\n }\n }, [isOpen])\n\n return (\n <>\n {trigger(bag, triggerRef)}\n {createPortal((<div\n ref={menuRef}\n onClick={e => e.stopPropagation()}\n className={clsx(\n 'absolute rounded-md bg-menu-background text-menu-text shadow-around-lg z-10',\n {\n 'animate-pop-in': isOpen,\n 'animate-pop-out': !isOpen,\n 'hidden': isHidden,\n },\n menuClassName\n )}\n onAnimationEnd={() => {\n if (!isOpen) {\n setIsHidden(true)\n }\n }}\n style={{\n ...menuPosition\n }}\n >\n {BagFunctionUtil.resolve<MenuBag>(children, bag)}\n </div>), document.body)}\n </>\n )\n}\n\n","import type { RefObject } from 'react'\nimport { useEffect } from 'react'\n\nexport const useOutsideClick = <Ts extends RefObject<HTMLElement>[]>(refs: Ts, handler: () => void) => {\n useEffect(() => {\n const listener = (event: MouseEvent | TouchEvent) => {\n // returning means not \"not clicking outside\"\n\n // if no target exists, return\n if (event.target === null) return\n // if the target is a ref's element or descendent thereof, return\n if (refs.some((ref) => !ref.current || ref.current.contains(event.target as Node))) {\n return\n }\n\n handler()\n }\n document.addEventListener('mousedown', listener)\n document.addEventListener('touchstart', listener)\n return () => {\n document.removeEventListener('mousedown', listener)\n document.removeEventListener('touchstart', listener)\n }\n }, [refs, handler])\n}\n","import type { Dispatch, SetStateAction } from 'react'\nimport { useEffect, useState } from 'react'\n\ntype UseHoverStateProps = {\n /**\n * The delay after which the menu is closed in milliseconds\n *\n * default: 200ms\n */\n closingDelay: number,\n /**\n * Whether the hover state management should be disabled\n *\n * default: false\n */\n isDisabled: boolean,\n}\n\ntype UseHoverStateReturnType = {\n /**\n * Whether the element is hovered\n */\n isHovered: boolean,\n /**\n * Function to change the current hover status\n */\n setIsHovered: Dispatch<SetStateAction<boolean>>,\n /**\n * Handlers to pass on to the component that should be hovered\n */\n handlers: {\n onMouseEnter: () => void,\n onMouseLeave: () => void,\n },\n}\n\nconst defaultUseHoverStateProps: UseHoverStateProps = {\n closingDelay: 200,\n isDisabled: false,\n}\n\n/**\n * @param props See UseHoverStateProps\n *\n * A react hook for managing the hover state of a component. The handlers provided should be\n * forwarded to the component which should be hovered over\n */\nexport const useHoverState = (props: Partial<UseHoverStateProps> | undefined = undefined): UseHoverStateReturnType => {\n const { closingDelay, isDisabled } = { ...defaultUseHoverStateProps, ...props }\n\n const [isHovered, setIsHovered] = useState(false)\n const [timer, setTimer] = useState<NodeJS.Timeout>()\n\n const onMouseEnter = () => {\n if (isDisabled) {\n return\n }\n clearTimeout(timer)\n setIsHovered(true)\n }\n\n const onMouseLeave = () => {\n if (isDisabled) {\n return\n }\n setTimer(setTimeout(() => {\n setIsHovered(false)\n }, closingDelay))\n }\n\n useEffect(() => {\n if (timer) {\n return () => {\n clearTimeout(timer)\n }\n }\n })\n\n useEffect(() => {\n if (timer) {\n clearTimeout(timer)\n }\n }, [isDisabled]) // eslint-disable-line react-hooks/exhaustive-deps\n\n return {\n isHovered, setIsHovered, handlers: { onMouseEnter, onMouseLeave }\n }\n}\n","import type { ReactNode } from 'react'\n\nexport type BagFunction<T> = (bag: T) => ReactNode\n\nexport type PropsWithBagFunction<T, P = unknown> = P & { children?: BagFunction<T> }\n\nexport type PropsWithBagFunctionOrChildren<T, P = unknown> = P & { children?: BagFunction<T> | ReactNode }\n\nconst resolve = <T>(children: BagFunction<T> | ReactNode, bag: T): ReactNode => {\n if (typeof children === 'function') {\n return (children as BagFunction<T>)(bag)\n }\n\n return children ?? undefined\n}\n\nexport const BagFunctionUtil = {\n resolve\n}","import type { CSSProperties } from 'react'\n\nexport type PopoverHorizontalAlignment = 'leftOutside' | 'leftInside' | 'rightOutside' | 'rightInside' | 'center'\nexport type PopoverVerticalAlignment = 'topOutside' | 'topInside' | 'bottomOutside' | 'bottomInside' | 'center'\n\ntype PopoverPositionOptionsResolved = {\n edgePadding: number,\n outerGap: number,\n verticalAlignment: PopoverVerticalAlignment,\n horizontalAlignment: PopoverHorizontalAlignment,\n disabled: boolean,\n}\n\ntype PopoverPositionOptions = Partial<PopoverPositionOptionsResolved>\n\nconst defaultPopoverPositionOptions: PopoverPositionOptionsResolved = {\n edgePadding: 16,\n outerGap: 4,\n horizontalAlignment: 'leftInside',\n verticalAlignment: 'bottomOutside',\n disabled: false,\n}\n\nexport const usePopoverPosition = (trigger?: DOMRect, options?: PopoverPositionOptions): CSSProperties => {\n const {\n edgePadding,\n outerGap,\n verticalAlignment,\n horizontalAlignment,\n disabled\n }: PopoverPositionOptionsResolved = { ...defaultPopoverPositionOptions, ...options }\n\n if (disabled || !trigger) {\n return {}\n }\n\n const left: number = {\n leftOutside: trigger.left - outerGap,\n leftInside: trigger.left,\n rightOutside: trigger.right + outerGap,\n rightInside: trigger.right,\n center: trigger.left + trigger.width / 2,\n }[horizontalAlignment]\n\n const top: number = {\n topOutside: trigger.top - outerGap,\n topInside: trigger.top,\n bottomOutside: trigger.bottom + outerGap,\n bottomInside: trigger.bottom,\n center: trigger.top + trigger.height / 2,\n }[verticalAlignment]\n\n const translateX: string | undefined = {\n leftOutside: '-100%',\n leftInside: undefined,\n rightOutside: undefined,\n rightInside: '-100%',\n center: '-50%',\n }[horizontalAlignment]\n\n const translateY: string | undefined = {\n topOutside: '-100%',\n topInside: undefined,\n bottomOutside: undefined,\n bottomInside: '-100%',\n center: '-50%',\n }[verticalAlignment]\n\n return {\n left: Math.max(left, edgePadding),\n top: Math.max(top, edgePadding),\n translate: [translateX ?? '0', translateY ?? '0'].join(' ')\n }\n}"],"mappings":"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","names":["useEffect","useState","useEffect","useState","useEffect"]}
|
|
@@ -4,7 +4,12 @@ import { PropsForTranslation } from '../../localization/useTranslation.mjs';
|
|
|
4
4
|
import { LabelProps } from './Label.mjs';
|
|
5
5
|
import { SelectOption } from './Select.mjs';
|
|
6
6
|
import { FormTranslationType } from '../../localization/defaults/form.mjs';
|
|
7
|
+
import { MenuProps, MenuBag } from './Menu.mjs';
|
|
8
|
+
import { UseSearchProps } from '../../hooks/useSearch.mjs';
|
|
7
9
|
import '../../localization/util.mjs';
|
|
10
|
+
import '../layout-and-navigation/Tile.mjs';
|
|
11
|
+
import '../../util/PropsWithFunctionChildren.mjs';
|
|
12
|
+
import '../../hooks/usePopoverPosition.mjs';
|
|
8
13
|
|
|
9
14
|
type MultiSelectAddonTranslation = {
|
|
10
15
|
selected: string;
|
|
@@ -13,21 +18,26 @@ type MultiSelectTranslation = MultiSelectAddonTranslation & FormTranslationType;
|
|
|
13
18
|
type MultiSelectOption<T> = SelectOption<T> & {
|
|
14
19
|
selected: boolean;
|
|
15
20
|
};
|
|
16
|
-
type
|
|
21
|
+
type MultiSelectBag = MenuBag & {
|
|
22
|
+
search: string;
|
|
23
|
+
};
|
|
24
|
+
type MultiSelectProps<T> = Omit<MenuProps<HTMLButtonElement>, 'trigger' | 'children'> & {
|
|
17
25
|
options: MultiSelectOption<T>[];
|
|
18
26
|
label?: LabelProps;
|
|
19
27
|
onChange: (options: MultiSelectOption<T>[]) => void;
|
|
20
28
|
hintText?: string;
|
|
21
|
-
isDisabled?: boolean;
|
|
22
|
-
isSearchEnabled?: boolean;
|
|
23
|
-
className?: string;
|
|
24
|
-
useChipDisplay?: boolean;
|
|
25
29
|
selectedDisplayOverwrite?: ReactNode;
|
|
30
|
+
searchOptions?: Omit<UseSearchProps<SelectOption<T>>, 'list' | 'searchMapping'>;
|
|
31
|
+
additionalItems?: (bag: MultiSelectBag) => ReactNode;
|
|
32
|
+
useChipDisplay?: boolean;
|
|
33
|
+
className?: string;
|
|
34
|
+
triggerClassName?: string;
|
|
35
|
+
hintTextClassName?: string;
|
|
26
36
|
};
|
|
27
37
|
/**
|
|
28
38
|
* A Component for multi selection
|
|
29
39
|
*/
|
|
30
|
-
declare const MultiSelect: <T>({ overwriteTranslation,
|
|
40
|
+
declare const MultiSelect: <T>({ overwriteTranslation, label, options, onChange, hintText, selectedDisplayOverwrite, searchOptions, additionalItems, useChipDisplay, className, triggerClassName, hintTextClassName, ...menuProps }: PropsForTranslation<MultiSelectTranslation, MultiSelectProps<T>>) => react_jsx_runtime.JSX.Element;
|
|
31
41
|
declare const MultiSelectUncontrolled: <T>({ options, onChange, ...props }: PropsForTranslation<MultiSelectTranslation, MultiSelectProps<T>>) => react_jsx_runtime.JSX.Element;
|
|
32
42
|
|
|
33
|
-
export { MultiSelect, type MultiSelectOption, type MultiSelectProps, MultiSelectUncontrolled };
|
|
43
|
+
export { MultiSelect, type MultiSelectBag, type MultiSelectOption, type MultiSelectProps, MultiSelectUncontrolled };
|
|
@@ -4,7 +4,12 @@ import { PropsForTranslation } from '../../localization/useTranslation.js';
|
|
|
4
4
|
import { LabelProps } from './Label.js';
|
|
5
5
|
import { SelectOption } from './Select.js';
|
|
6
6
|
import { FormTranslationType } from '../../localization/defaults/form.js';
|
|
7
|
+
import { MenuProps, MenuBag } from './Menu.js';
|
|
8
|
+
import { UseSearchProps } from '../../hooks/useSearch.js';
|
|
7
9
|
import '../../localization/util.js';
|
|
10
|
+
import '../layout-and-navigation/Tile.js';
|
|
11
|
+
import '../../util/PropsWithFunctionChildren.js';
|
|
12
|
+
import '../../hooks/usePopoverPosition.js';
|
|
8
13
|
|
|
9
14
|
type MultiSelectAddonTranslation = {
|
|
10
15
|
selected: string;
|
|
@@ -13,21 +18,26 @@ type MultiSelectTranslation = MultiSelectAddonTranslation & FormTranslationType;
|
|
|
13
18
|
type MultiSelectOption<T> = SelectOption<T> & {
|
|
14
19
|
selected: boolean;
|
|
15
20
|
};
|
|
16
|
-
type
|
|
21
|
+
type MultiSelectBag = MenuBag & {
|
|
22
|
+
search: string;
|
|
23
|
+
};
|
|
24
|
+
type MultiSelectProps<T> = Omit<MenuProps<HTMLButtonElement>, 'trigger' | 'children'> & {
|
|
17
25
|
options: MultiSelectOption<T>[];
|
|
18
26
|
label?: LabelProps;
|
|
19
27
|
onChange: (options: MultiSelectOption<T>[]) => void;
|
|
20
28
|
hintText?: string;
|
|
21
|
-
isDisabled?: boolean;
|
|
22
|
-
isSearchEnabled?: boolean;
|
|
23
|
-
className?: string;
|
|
24
|
-
useChipDisplay?: boolean;
|
|
25
29
|
selectedDisplayOverwrite?: ReactNode;
|
|
30
|
+
searchOptions?: Omit<UseSearchProps<SelectOption<T>>, 'list' | 'searchMapping'>;
|
|
31
|
+
additionalItems?: (bag: MultiSelectBag) => ReactNode;
|
|
32
|
+
useChipDisplay?: boolean;
|
|
33
|
+
className?: string;
|
|
34
|
+
triggerClassName?: string;
|
|
35
|
+
hintTextClassName?: string;
|
|
26
36
|
};
|
|
27
37
|
/**
|
|
28
38
|
* A Component for multi selection
|
|
29
39
|
*/
|
|
30
|
-
declare const MultiSelect: <T>({ overwriteTranslation,
|
|
40
|
+
declare const MultiSelect: <T>({ overwriteTranslation, label, options, onChange, hintText, selectedDisplayOverwrite, searchOptions, additionalItems, useChipDisplay, className, triggerClassName, hintTextClassName, ...menuProps }: PropsForTranslation<MultiSelectTranslation, MultiSelectProps<T>>) => react_jsx_runtime.JSX.Element;
|
|
31
41
|
declare const MultiSelectUncontrolled: <T>({ options, onChange, ...props }: PropsForTranslation<MultiSelectTranslation, MultiSelectProps<T>>) => react_jsx_runtime.JSX.Element;
|
|
32
42
|
|
|
33
|
-
export { MultiSelect, type MultiSelectOption, type MultiSelectProps, MultiSelectUncontrolled };
|
|
43
|
+
export { MultiSelect, type MultiSelectBag, type MultiSelectOption, type MultiSelectProps, MultiSelectUncontrolled };
|