@acusti/dropdown 0.55.0 → 0.56.0

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/README.md CHANGED
@@ -98,10 +98,24 @@ This means the dropdown tends to:
98
98
  Internally, the dropdown renders:
99
99
 
100
100
  - `.uktdropdown-body` as the anchored outer shell
101
- - `.uktdropdown-content` as the scrollable inner region
101
+ - `.uktdropdown-content` as the scrollable inner region with default
102
+ padding
102
103
 
103
- Custom padding and overflow styling usually belongs on the content region,
104
- not the outer shell.
104
+ Custom padding and overflow styling belongs on the content region, not the
105
+ outer shell. Note that `.uktdropdown-content` already applies default
106
+ padding (see the `--uktdd-body-pad-*` variables below), so your body
107
+ element does **not** need its own padding:
108
+
109
+ ```tsx
110
+ // ✗ Don’t double-pad — the content region already has padding
111
+ <Dropdown>
112
+ <button>Open</button>
113
+ <div style={{ padding: 16 }}>…</div>
114
+ </Dropdown>
115
+
116
+ // ✓ Override default padding via CSS variables if needed
117
+ // .my-dropdown { --uktdd-body-pad-top: 16px; /* etc */ }
118
+ ```
105
119
 
106
120
  For the most reliable anchor-positioning behavior:
107
121
 
@@ -111,6 +125,12 @@ For the most reliable anchor-positioning behavior:
111
125
  - prefer CSS variable overrides over custom `top`/`left`/`right` inset
112
126
  rules
113
127
 
128
+ For placement recipes, see
129
+ [Placement Customization](#placement-customization-with-css-variables)
130
+ below. If your trigger sits near the right edge of the viewport, the
131
+ [End-Aligned, Content-Sized Menu](#end-aligned-content-sized-menu) example
132
+ is the one you want.
133
+
114
134
  ## API Reference
115
135
 
116
136
  ### Props
@@ -337,12 +357,17 @@ function MultiSelectDropdown() {
337
357
 
338
358
  ### Dropdown with Interactive Content
339
359
 
360
+ For dropdowns whose body is a form (inputs, date pickers, buttons that
361
+ aren’t meant to submit a value), pass `hasItems={false}`. This disables the
362
+ item-selection keyboard model and, importantly, prevents clicks inside the
363
+ body from closing the dropdown via `onSubmitItem`.
364
+
340
365
  ```tsx
341
366
  function InteractiveDropdown() {
342
367
  return (
343
368
  <Dropdown hasItems={false}>
344
369
  <button>Settings</button>
345
- <div style={{ padding: '16px' }}>
370
+ <div>
346
371
  <label>
347
372
  Full name:{' '}
348
373
  <input
@@ -437,3 +462,18 @@ For accessibility, the component focuses on semantic HTML structure and
437
462
  keyboard navigation. It works best when you use appropriate HTML elements
438
463
  in your dropdown content (like `<ul>` and `<li>` for lists, `<button>`
439
464
  elements for actions, etc.).
465
+
466
+ ### ARIA attributes
467
+
468
+ The trigger automatically receives `aria-haspopup`, `aria-expanded`, and
469
+ `aria-controls` pointing to the open body. The popup role is chosen based
470
+ on the dropdown’s mode:
471
+
472
+ - `aria-haspopup="listbox"` when `isSearchable` is true (combobox pattern)
473
+ - `aria-haspopup="menu"` when `hasItems` is true (the default)
474
+ - `aria-haspopup="dialog"` when `hasItems={false}` (interactive content)
475
+
476
+ The open body element also receives a matching `role` and an `id` so screen
477
+ readers can associate the trigger with its popup. If your custom trigger
478
+ already specifies any of these ARIA props, your values win — the component
479
+ only fills in what you haven’t set.
@@ -1,4 +1,4 @@
1
- import { CSSProperties, JSX, MouseEvent as ReactMouseEvent, ReactNode, SyntheticEvent } from 'react';
1
+ import { CSSProperties, MouseEvent as ReactMouseEvent, ReactElement, ReactNode, SyntheticEvent } from 'react';
2
2
  export type Item = {
3
3
  element: MaybeHTMLElement;
4
4
  event: Event | SyntheticEvent<HTMLElement>;
@@ -19,7 +19,7 @@ export type Props = {
19
19
  /**
20
20
  * Can take a single React element or exactly two renderable children.
21
21
  */
22
- children: ChildrenTuple | JSX.Element;
22
+ children: ChildrenTuple | ReactElement;
23
23
  className?: string;
24
24
  disabled?: boolean;
25
25
  /**
package/dist/Dropdown.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import { c } from "react/compiler-runtime";
2
2
  import useKeyboardEvents, { isEventTargetUsingKeyEvent } from "@acusti/use-keyboard-events";
3
3
  import clsx from "clsx";
4
- import { Children, Fragment, isValidElement, useEffect, useRef, useState } from "react";
4
+ import { Children, Fragment, cloneElement, isValidElement, useEffect, useId, useRef, useState } from "react";
5
5
  import { getBestMatch } from "@acusti/matchmaking";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
7
7
  //#region src/Dropdown.css?inline
8
- var Dropdown_default = ":root{--uktdd-font-family:system-ui, Segoe UI, Roboto, Oxygen-Sans, Ubuntu, Cantarell, Helvetica Neue, Helvetica, Arial, sans-serif;--uktdd-body-bg-color:#fff;--uktdd-body-bg-color-hover:#69a2f9;--uktdd-body-color-hover:#fff;--uktdd-body-buffer:10px;--uktdd-body-max-height:calc(100dvh - var(--uktdd-body-buffer));--uktdd-body-max-width:calc(100dvw - var(--uktdd-body-buffer));--uktdd-body-min-height:30px;--uktdd-body-pad-bottom:9px;--uktdd-body-pad-left:12px;--uktdd-body-pad-right:12px;--uktdd-body-pad-top:9px;--uktdd-body-min-width:min(50px, 100%);--uktdd-body-position-area:bottom span-right;--uktdd-body-position-try-fallbacks:--uktdd-top-left, --uktdd-bottom-right, --uktdd-top-right;--uktdd-body-translate:0 0;--uktdd-label-pad-right:10px}.uktdropdown,.uktdropdown-trigger{font-family:var(--uktdd-font-family)}.uktdropdown{anchor-scope:--uktdd-anchor;width:max-content}.uktdropdown.disabled{pointer-events:none}.uktdropdown>*{cursor:default}.uktdropdown>:first-child{anchor-name:--uktdd-anchor}.uktdropdown-label{align-items:center;display:flex}.uktdropdown-label-text{padding-right:var(--uktdd-label-pad-right)}.uktdropdown-body{box-sizing:border-box;position-anchor:--uktdd-anchor;position-area:var(--uktdd-body-position-area);position-try-order:most-height;position-try-fallbacks:var(--uktdd-body-position-try-fallbacks);min-block-size:min(var(--uktdd-body-min-height), var(--uktdd-body-max-height));max-block-size:min(var(--uktdd-body-max-height), 100%);min-inline-size:min(var(--uktdd-body-min-width), var(--uktdd-body-max-width));max-inline-size:var(--uktdd-body-max-width);inline-size:max-content;translate:var(--uktdd-body-translate);z-index:2;background-color:var(--uktdd-body-bg-color);flex-direction:column;display:flex;position:fixed;overflow:hidden;box-shadow:0 8px 18px #00000040}.uktdropdown-body.has-items{-webkit-user-select:none;user-select:none}.uktdropdown-body [data-ukt-active]{background-color:var(--uktdd-body-bg-color-hover);color:var(--uktdd-body-color-hover)}.uktdropdown-content{box-sizing:border-box;overscroll-behavior:contain;scrollbar-gutter:stable;min-block-size:0;padding:var(--uktdd-body-pad-top) var(--uktdd-body-pad-right) var(--uktdd-body-pad-bottom) var(--uktdd-body-pad-left);overflow:auto}@position-try --uktdd-top-left{position-area: top span-right;}@position-try --uktdd-bottom-left{position-area: bottom span-right;}@position-try --uktdd-bottom-right{position-area: bottom span-left;}@position-try --uktdd-top-right{position-area: top span-left;}";
8
+ var Dropdown_default = ":root{--uktdd-font-family:system-ui, Segoe UI, Roboto, Oxygen-Sans, Ubuntu, Cantarell, Helvetica Neue, Helvetica, Arial, sans-serif;--uktdd-body-bg-color:#fff;--uktdd-body-bg-color-hover:#69a2f9;--uktdd-body-color-hover:#fff;--uktdd-body-buffer:10px;--uktdd-body-max-height:calc(100dvh - var(--uktdd-body-buffer));--uktdd-body-max-width:calc(100dvw - var(--uktdd-body-buffer));--uktdd-body-min-height:30px;--uktdd-body-pad-bottom:9px;--uktdd-body-pad-left:12px;--uktdd-body-pad-right:12px;--uktdd-body-pad-top:9px;--uktdd-body-min-width:min(50px, 100%);--uktdd-body-position-area:bottom span-right;--uktdd-body-position-try-fallbacks:--uktdd-top-left, --uktdd-bottom-right, --uktdd-top-right;--uktdd-body-translate:0 0;--uktdd-label-pad-right:10px}.uktdropdown,.uktdropdown-trigger{font-family:var(--uktdd-font-family)}.uktdropdown{anchor-scope:--uktdd-anchor;width:max-content}.uktdropdown.disabled{pointer-events:none}.uktdropdown>*{cursor:default}.uktdropdown>:first-child{anchor-name:--uktdd-anchor}.uktdropdown-label{align-items:center;display:flex}.uktdropdown-label-text{padding-right:var(--uktdd-label-pad-right)}.uktdropdown-body{box-sizing:border-box;position-anchor:--uktdd-anchor;position-area:var(--uktdd-body-position-area);position-try-order:most-height;position-try-fallbacks:var(--uktdd-body-position-try-fallbacks);min-block-size:min(var(--uktdd-body-min-height), var(--uktdd-body-max-height));max-block-size:min(var(--uktdd-body-max-height), 100%);min-inline-size:min(var(--uktdd-body-min-width), var(--uktdd-body-max-width));max-inline-size:var(--uktdd-body-max-width);inline-size:max-content;translate:var(--uktdd-body-translate);z-index:2;background-color:var(--uktdd-body-bg-color);flex-direction:column;display:flex;position:fixed;overflow:hidden;box-shadow:0 8px 18px #00000040}.uktdropdown-body.has-items{-webkit-user-select:none;user-select:none}.uktdropdown-body [data-ukt-active]{background-color:var(--uktdd-body-bg-color-hover);color:var(--uktdd-body-color-hover)}.uktdropdown-content{box-sizing:border-box;overscroll-behavior:contain;min-block-size:0;padding:var(--uktdd-body-pad-top) var(--uktdd-body-pad-right) var(--uktdd-body-pad-bottom) var(--uktdd-body-pad-left);overflow:auto}@position-try --uktdd-top-left{position-area: top span-right;}@position-try --uktdd-bottom-left{position-area: bottom span-right;}@position-try --uktdd-bottom-right{position-area: bottom span-left;}@position-try --uktdd-top-right{position-area: top span-left;}";
9
9
  //#endregion
10
10
  //#region src/helpers.ts
11
11
  var ITEM_SELECTOR = `[data-ukt-item], [data-ukt-value]`;
@@ -99,12 +99,11 @@ var CHILDREN_ERROR = "@acusti/dropdown requires either 1 child (the dropdown bod
99
99
  var CLICKABLE_SELECTOR = "button, a[href], input[type=\"button\"], input[type=\"submit\"]";
100
100
  var TEXT_INPUT_SELECTOR = "input:not([type=radio]):not([type=checkbox]):not([type=range]),textarea";
101
101
  function Dropdown(t0) {
102
- const $ = c(82);
103
- const { allowCreate, allowEmpty: t1, children, className, disabled, hasItems: t2, isOpenOnMount, isSearchable, keepOpenOnSubmit: t3, label, minHeightBody: t4, minWidthBody, name, onActiveItem, onClick, onClose, onMouseDown, onMouseUp, onOpen, onSubmitItem, placeholder, style: styleFromProps, tabIndex, value } = t0;
102
+ const $ = c(95);
103
+ const { allowCreate, allowEmpty: t1, children, className, disabled, hasItems: t2, isOpenOnMount, isSearchable, keepOpenOnSubmit: t3, label, minHeightBody, minWidthBody, name, onActiveItem, onClick, onClose, onMouseDown, onMouseUp, onOpen, onSubmitItem, placeholder, style: styleFromProps, tabIndex, value } = t0;
104
104
  const allowEmpty = t1 === void 0 ? true : t1;
105
105
  const hasItems = t2 === void 0 ? true : t2;
106
106
  const keepOpenOnSubmit = t3 === void 0 ? !hasItems : t3;
107
- const minHeightBody = t4 === void 0 ? 30 : t4;
108
107
  const childrenCount = Children.count(children);
109
108
  if (childrenCount !== 1 && childrenCount !== 2) {
110
109
  if (childrenCount === 0) throw new Error(CHILDREN_ERROR + " Received no children.");
@@ -115,6 +114,8 @@ function Dropdown(t0) {
115
114
  const [isOpen, setIsOpen] = useState(isOpenOnMount ?? false);
116
115
  const [isOpening, setIsOpening] = useState(!isOpenOnMount);
117
116
  const [dropdownElement, setDropdownElement] = useState(null);
117
+ const bodyId = useId();
118
+ const popupRole = isSearchable ? "listbox" : hasItems ? "menu" : "dialog";
118
119
  const inputElementRef = useRef(null);
119
120
  const closingTimerRef = useRef(null);
120
121
  const isOpeningTimerRef = useRef(null);
@@ -132,10 +133,10 @@ function Dropdown(t0) {
132
133
  const onOpenRef = useRef(onOpen);
133
134
  const onSubmitItemRef = useRef(onSubmitItem);
134
135
  const valueRef = useRef(value);
136
+ let t4;
135
137
  let t5;
136
- let t6;
137
138
  if ($[0] !== allowCreate || $[1] !== allowEmpty || $[2] !== hasItems || $[3] !== isOpen || $[4] !== isOpening || $[5] !== keepOpenOnSubmit || $[6] !== onClose || $[7] !== onOpen || $[8] !== onSubmitItem || $[9] !== value) {
138
- t5 = () => {
139
+ t4 = () => {
139
140
  allowCreateRef.current = allowCreate;
140
141
  allowEmptyRef.current = allowEmpty;
141
142
  hasItemsRef.current = hasItems;
@@ -147,7 +148,7 @@ function Dropdown(t0) {
147
148
  onSubmitItemRef.current = onSubmitItem;
148
149
  valueRef.current = value;
149
150
  };
150
- t6 = [
151
+ t5 = [
151
152
  allowCreate,
152
153
  allowEmpty,
153
154
  hasItems,
@@ -169,18 +170,18 @@ function Dropdown(t0) {
169
170
  $[7] = onOpen;
170
171
  $[8] = onSubmitItem;
171
172
  $[9] = value;
172
- $[10] = t5;
173
- $[11] = t6;
173
+ $[10] = t4;
174
+ $[11] = t5;
174
175
  } else {
175
- t5 = $[10];
176
- t6 = $[11];
176
+ t4 = $[10];
177
+ t5 = $[11];
177
178
  }
178
- useEffect(t5, t6);
179
+ useEffect(t4, t5);
179
180
  const isMountedRef = useRef(false);
181
+ let t6;
180
182
  let t7;
181
- let t8;
182
183
  if ($[12] !== isOpen) {
183
- t7 = () => {
184
+ t6 = () => {
184
185
  if (!isMountedRef.current) {
185
186
  isMountedRef.current = true;
186
187
  if (isOpenRef.current && onOpenRef.current) onOpenRef.current();
@@ -189,18 +190,18 @@ function Dropdown(t0) {
189
190
  if (isOpen && onOpenRef.current) onOpenRef.current();
190
191
  else if (!isOpen && onCloseRef.current) onCloseRef.current();
191
192
  };
192
- t8 = [isOpen];
193
+ t7 = [isOpen];
193
194
  $[12] = isOpen;
194
- $[13] = t7;
195
- $[14] = t8;
195
+ $[13] = t6;
196
+ $[14] = t7;
196
197
  } else {
197
- t7 = $[13];
198
- t8 = $[14];
198
+ t6 = $[13];
199
+ t7 = $[14];
199
200
  }
200
- useEffect(t7, t8);
201
- let t9;
201
+ useEffect(t6, t7);
202
+ let t8;
202
203
  if ($[15] === Symbol.for("react.memo_cache_sentinel")) {
203
- t9 = () => {
204
+ t8 = () => {
204
205
  setIsOpen(false);
205
206
  setIsOpening(false);
206
207
  mouseDownPositionRef.current = null;
@@ -209,12 +210,12 @@ function Dropdown(t0) {
209
210
  closingTimerRef.current = null;
210
211
  }
211
212
  };
212
- $[15] = t9;
213
- } else t9 = $[15];
214
- const closeDropdown = t9;
215
- let t10;
213
+ $[15] = t8;
214
+ } else t8 = $[15];
215
+ const closeDropdown = t8;
216
+ let t9;
216
217
  if ($[16] !== dropdownElement) {
217
- t10 = (event) => {
218
+ t9 = (event) => {
218
219
  if (isOpenRef.current && !keepOpenOnSubmitRef.current) closingTimerRef.current = setTimeout(closeDropdown, 90);
219
220
  if (!hasItemsRef.current) return;
220
221
  const element = getActiveItemElement(dropdownElement);
@@ -250,25 +251,25 @@ function Dropdown(t0) {
250
251
  });
251
252
  };
252
253
  $[16] = dropdownElement;
253
- $[17] = t10;
254
- } else t10 = $[17];
255
- const handleSubmitItem = t10;
256
- let t11;
254
+ $[17] = t9;
255
+ } else t9 = $[17];
256
+ const handleSubmitItem = t9;
257
+ let t10;
257
258
  if ($[18] === Symbol.for("react.memo_cache_sentinel")) {
258
- t11 = (t12) => {
259
- const { clientX, clientY } = t12;
259
+ t10 = (t11) => {
260
+ const { clientX, clientY } = t11;
260
261
  currentInputMethodRef.current = "mouse";
261
262
  const initialPosition = mouseDownPositionRef.current;
262
263
  if (!initialPosition) return;
263
264
  if (Math.abs(initialPosition.clientX - clientX) < 12 && Math.abs(initialPosition.clientY - clientY) < 12) return;
264
265
  setIsOpening(false);
265
266
  };
266
- $[18] = t11;
267
- } else t11 = $[18];
268
- const handleMouseMove = t11;
269
- let t12;
267
+ $[18] = t10;
268
+ } else t10 = $[18];
269
+ const handleMouseMove = t10;
270
+ let t11;
270
271
  if ($[19] !== dropdownElement || $[20] !== onActiveItem) {
271
- t12 = (event_0) => {
272
+ t11 = (event_0) => {
272
273
  if (!hasItemsRef.current) return;
273
274
  if (currentInputMethodRef.current !== "mouse") return;
274
275
  if (!dropdownElement) return;
@@ -288,12 +289,12 @@ function Dropdown(t0) {
288
289
  };
289
290
  $[19] = dropdownElement;
290
291
  $[20] = onActiveItem;
291
- $[21] = t12;
292
- } else t12 = $[21];
293
- const handleMouseOver = t12;
294
- let t13;
292
+ $[21] = t11;
293
+ } else t11 = $[21];
294
+ const handleMouseOver = t11;
295
+ let t12;
295
296
  if ($[22] !== dropdownElement) {
296
- t13 = (event_1) => {
297
+ t12 = (event_1) => {
297
298
  if (!hasItemsRef.current) return;
298
299
  const activeItem = getActiveItemElement(dropdownElement);
299
300
  if (!activeItem) return;
@@ -302,12 +303,12 @@ function Dropdown(t0) {
302
303
  delete activeItem.dataset.uktActive;
303
304
  };
304
305
  $[22] = dropdownElement;
305
- $[23] = t13;
306
- } else t13 = $[23];
307
- const handleMouseOut = t13;
308
- let t14;
306
+ $[23] = t12;
307
+ } else t12 = $[23];
308
+ const handleMouseOut = t12;
309
+ let t13;
309
310
  if ($[24] !== onMouseDown) {
310
- t14 = (event_2) => {
311
+ t13 = (event_2) => {
311
312
  if (onMouseDown) onMouseDown(event_2);
312
313
  if (isOpenRef.current) return;
313
314
  setIsOpen(true);
@@ -322,12 +323,12 @@ function Dropdown(t0) {
322
323
  }, 1e3);
323
324
  };
324
325
  $[24] = onMouseDown;
325
- $[25] = t14;
326
- } else t14 = $[25];
327
- const handleMouseDown = t14;
328
- let t15;
326
+ $[25] = t13;
327
+ } else t13 = $[25];
328
+ const handleMouseDown = t13;
329
+ let t14;
329
330
  if ($[26] !== handleSubmitItem || $[27] !== onMouseUp) {
330
- t15 = (event_3) => {
331
+ t14 = (event_3) => {
331
332
  if (onMouseUp) onMouseUp(event_3);
332
333
  if (isOpeningRef.current || !isOpenRef.current || closingTimerRef.current != null) return;
333
334
  const eventTarget_1 = event_3.target;
@@ -340,12 +341,12 @@ function Dropdown(t0) {
340
341
  };
341
342
  $[26] = handleSubmitItem;
342
343
  $[27] = onMouseUp;
343
- $[28] = t15;
344
- } else t15 = $[28];
345
- const handleMouseUp = t15;
346
- let t16;
344
+ $[28] = t14;
345
+ } else t14 = $[28];
346
+ const handleMouseUp = t14;
347
+ let t15;
347
348
  if ($[29] !== dropdownElement || $[30] !== handleSubmitItem || $[31] !== onActiveItem) {
348
- t16 = (event_4) => {
349
+ t15 = (event_4) => {
349
350
  const { altKey, ctrlKey, key, metaKey } = event_4;
350
351
  const eventTarget_2 = event_4.target;
351
352
  if (!dropdownElement) return;
@@ -433,22 +434,22 @@ function Dropdown(t0) {
433
434
  $[29] = dropdownElement;
434
435
  $[30] = handleSubmitItem;
435
436
  $[31] = onActiveItem;
436
- $[32] = t16;
437
- } else t16 = $[32];
438
- const handleKeyDown = t16;
439
- let t17;
437
+ $[32] = t15;
438
+ } else t15 = $[32];
439
+ const handleKeyDown = t15;
440
+ let t16;
440
441
  if ($[33] !== handleKeyDown) {
441
- t17 = {
442
+ t16 = {
442
443
  ignoreUsedKeyboardEvents: false,
443
444
  onKeyDown: handleKeyDown
444
445
  };
445
446
  $[33] = handleKeyDown;
446
- $[34] = t17;
447
- } else t17 = $[34];
448
- useKeyboardEvents(t17);
449
- let t18;
447
+ $[34] = t16;
448
+ } else t16 = $[34];
449
+ useKeyboardEvents(t16);
450
+ let t17;
450
451
  if ($[35] !== isOpenOnMount || $[36] !== onActiveItem) {
451
- t18 = (ref) => {
452
+ t17 = (ref) => {
452
453
  setDropdownElement(ref);
453
454
  if (!ref) return;
454
455
  const { ownerDocument } = ref;
@@ -458,13 +459,13 @@ function Dropdown(t0) {
458
459
  else inputElement = ref.firstElementChild.querySelector(TEXT_INPUT_SELECTOR);
459
460
  inputElementRef.current = inputElement;
460
461
  }
461
- const handleGlobalMouseDown = (t19) => {
462
- const { target } = t19;
462
+ const handleGlobalMouseDown = (t18) => {
463
+ const { target } = t18;
463
464
  const eventTarget_3 = target;
464
465
  if (!ref.contains(eventTarget_3)) closeDropdown();
465
466
  };
466
- const handleGlobalMouseUp = (t20) => {
467
- const { target: target_0 } = t20;
467
+ const handleGlobalMouseUp = (t19) => {
468
+ const { target: target_0 } = t19;
468
469
  if (!isOpenRef.current || closingTimerRef.current != null) return;
469
470
  if (isOpeningRef.current) {
470
471
  setIsOpening(false);
@@ -477,8 +478,8 @@ function Dropdown(t0) {
477
478
  const eventTarget_4 = target_0;
478
479
  if (!ref.contains(eventTarget_4)) closeDropdown();
479
480
  };
480
- const handleGlobalFocusIn = (t21) => {
481
- const { target: target_1 } = t21;
481
+ const handleGlobalFocusIn = (t20) => {
482
+ const { target: target_1 } = t20;
482
483
  if (!isOpenRef.current) return;
483
484
  const eventTarget_5 = target_1;
484
485
  if (ref.contains(eventTarget_5) || eventTarget_5.contains(ref)) return;
@@ -522,140 +523,177 @@ function Dropdown(t0) {
522
523
  };
523
524
  $[35] = isOpenOnMount;
524
525
  $[36] = onActiveItem;
525
- $[37] = t18;
526
- } else t18 = $[37];
527
- const handleRef = t18;
526
+ $[37] = t17;
527
+ } else t17 = $[37];
528
+ const handleRef = t17;
528
529
  if (!isValidElement(trigger)) if (isSearchable) {
529
- const t19 = value ?? "";
530
- let t20;
530
+ const t18 = value ?? "";
531
+ let t19;
531
532
  if ($[38] === Symbol.for("react.memo_cache_sentinel")) {
532
- t20 = () => setIsOpen(true);
533
- $[38] = t20;
534
- } else t20 = $[38];
535
- let t21;
536
- if ($[39] !== disabled || $[40] !== name || $[41] !== placeholder || $[42] !== t19 || $[43] !== tabIndex) {
537
- t21 = /* @__PURE__ */ jsx("input", {
533
+ t19 = () => setIsOpen(true);
534
+ $[38] = t19;
535
+ } else t19 = $[38];
536
+ let t20;
537
+ if ($[39] !== bodyId || $[40] !== disabled || $[41] !== isOpen || $[42] !== name || $[43] !== placeholder || $[44] !== popupRole || $[45] !== t18 || $[46] !== tabIndex) {
538
+ t20 = /* @__PURE__ */ jsx("input", {
539
+ "aria-controls": bodyId,
540
+ "aria-expanded": isOpen,
541
+ "aria-haspopup": popupRole,
538
542
  autoComplete: "off",
539
543
  className: "uktdropdown-trigger",
540
- defaultValue: t19,
544
+ defaultValue: t18,
541
545
  disabled,
542
546
  name,
543
- onFocus: t20,
547
+ onFocus: t19,
544
548
  placeholder,
545
549
  ref: inputElementRef,
546
550
  tabIndex,
547
551
  type: "text"
548
552
  });
549
- $[39] = disabled;
550
- $[40] = name;
551
- $[41] = placeholder;
552
- $[42] = t19;
553
- $[43] = tabIndex;
554
- $[44] = t21;
555
- } else t21 = $[44];
556
- trigger = t21;
553
+ $[39] = bodyId;
554
+ $[40] = disabled;
555
+ $[41] = isOpen;
556
+ $[42] = name;
557
+ $[43] = placeholder;
558
+ $[44] = popupRole;
559
+ $[45] = t18;
560
+ $[46] = tabIndex;
561
+ $[47] = t20;
562
+ } else t20 = $[47];
563
+ trigger = t20;
557
564
  } else {
558
- let t19;
559
- if ($[45] !== trigger) {
560
- t19 = /* @__PURE__ */ jsx("button", {
565
+ let t18;
566
+ if ($[48] !== bodyId || $[49] !== isOpen || $[50] !== popupRole || $[51] !== trigger) {
567
+ t18 = /* @__PURE__ */ jsx("button", {
568
+ "aria-controls": bodyId,
569
+ "aria-expanded": isOpen,
570
+ "aria-haspopup": popupRole,
561
571
  className: "uktdropdown-trigger",
562
572
  tabIndex: 0,
563
573
  type: "button",
564
574
  children: trigger
565
575
  });
566
- $[45] = trigger;
567
- $[46] = t19;
568
- } else t19 = $[46];
569
- trigger = t19;
576
+ $[48] = bodyId;
577
+ $[49] = isOpen;
578
+ $[50] = popupRole;
579
+ $[51] = trigger;
580
+ $[52] = t18;
581
+ } else t18 = $[52];
582
+ trigger = t18;
583
+ }
584
+ else {
585
+ const triggerProps = trigger.props;
586
+ const t18 = trigger;
587
+ const t19 = triggerProps["aria-controls"] ?? bodyId;
588
+ const t20 = triggerProps["aria-expanded"] ?? isOpen;
589
+ const t21 = triggerProps["aria-haspopup"] ?? popupRole;
590
+ let t22;
591
+ if ($[53] !== t18 || $[54] !== t19 || $[55] !== t20 || $[56] !== t21) {
592
+ t22 = cloneElement(t18, {
593
+ "aria-controls": t19,
594
+ "aria-expanded": t20,
595
+ "aria-haspopup": t21
596
+ });
597
+ $[53] = t18;
598
+ $[54] = t19;
599
+ $[55] = t20;
600
+ $[56] = t21;
601
+ $[57] = t22;
602
+ } else t22 = $[57];
603
+ trigger = t22;
570
604
  }
571
605
  if (label != null) {
572
- let t19;
573
- if ($[47] !== label) {
574
- t19 = /* @__PURE__ */ jsx("div", {
606
+ let t18;
607
+ if ($[58] !== label) {
608
+ t18 = /* @__PURE__ */ jsx("div", {
575
609
  className: "uktdropdown-label-text",
576
610
  children: label
577
611
  });
578
- $[47] = label;
579
- $[48] = t19;
580
- } else t19 = $[48];
581
- let t20;
582
- if ($[49] !== t19 || $[50] !== trigger) {
583
- t20 = /* @__PURE__ */ jsxs("label", {
612
+ $[58] = label;
613
+ $[59] = t18;
614
+ } else t18 = $[59];
615
+ let t19;
616
+ if ($[60] !== t18 || $[61] !== trigger) {
617
+ t19 = /* @__PURE__ */ jsxs("label", {
584
618
  className: "uktdropdown-label",
585
- children: [t19, trigger]
619
+ children: [t18, trigger]
586
620
  });
587
- $[49] = t19;
588
- $[50] = trigger;
589
- $[51] = t20;
590
- } else t20 = $[51];
591
- trigger = t20;
621
+ $[60] = t18;
622
+ $[61] = trigger;
623
+ $[62] = t19;
624
+ } else t19 = $[62];
625
+ trigger = t19;
592
626
  }
627
+ let t18;
628
+ if ($[63] !== minHeightBody) {
629
+ t18 = minHeightBody != null && minHeightBody > 0 ? { "--uktdd-body-min-height": `${minHeightBody}px` } : null;
630
+ $[63] = minHeightBody;
631
+ $[64] = t18;
632
+ } else t18 = $[64];
593
633
  let t19;
594
- if ($[52] !== minHeightBody) {
595
- t19 = minHeightBody != null && minHeightBody > 0 ? { "--uktdd-body-min-height": `${minHeightBody}px` } : null;
596
- $[52] = minHeightBody;
597
- $[53] = t19;
598
- } else t19 = $[53];
634
+ if ($[65] !== minWidthBody) {
635
+ t19 = minWidthBody != null && minWidthBody > 0 ? { "--uktdd-body-min-width": `${minWidthBody}px` } : null;
636
+ $[65] = minWidthBody;
637
+ $[66] = t19;
638
+ } else t19 = $[66];
599
639
  let t20;
600
- if ($[54] !== minWidthBody) {
601
- t20 = minWidthBody != null && minWidthBody > 0 ? { "--uktdd-body-min-width": `${minWidthBody}px` } : null;
602
- $[54] = minWidthBody;
603
- $[55] = t20;
604
- } else t20 = $[55];
605
- let t21;
606
- if ($[56] !== styleFromProps || $[57] !== t19 || $[58] !== t20) {
607
- t21 = {
640
+ if ($[67] !== styleFromProps || $[68] !== t18 || $[69] !== t19) {
641
+ t20 = {
608
642
  ...styleFromProps,
609
- ...t19,
610
- ...t20
643
+ ...t18,
644
+ ...t19
611
645
  };
612
- $[56] = styleFromProps;
613
- $[57] = t19;
614
- $[58] = t20;
615
- $[59] = t21;
616
- } else t21 = $[59];
617
- const style = t21;
618
- let t22;
619
- if ($[60] === Symbol.for("react.memo_cache_sentinel")) {
620
- t22 = /* @__PURE__ */ jsx("style", {
646
+ $[67] = styleFromProps;
647
+ $[68] = t18;
648
+ $[69] = t19;
649
+ $[70] = t20;
650
+ } else t20 = $[70];
651
+ const style = t20;
652
+ let t21;
653
+ if ($[71] === Symbol.for("react.memo_cache_sentinel")) {
654
+ t21 = /* @__PURE__ */ jsx("style", {
621
655
  href: "@acusti/dropdown/Dropdown",
622
656
  precedence: "medium",
623
657
  children: Dropdown_default
624
658
  });
625
- $[60] = t22;
626
- } else t22 = $[60];
627
- let t23;
628
- if ($[61] !== className || $[62] !== disabled || $[63] !== isOpen || $[64] !== isSearchable) {
629
- t23 = clsx("uktdropdown", className, {
659
+ $[71] = t21;
660
+ } else t21 = $[71];
661
+ let t22;
662
+ if ($[72] !== className || $[73] !== disabled || $[74] !== isOpen || $[75] !== isSearchable) {
663
+ t22 = clsx("uktdropdown", className, {
630
664
  disabled,
631
665
  "is-open": isOpen,
632
666
  "is-searchable": isSearchable
633
667
  });
634
- $[61] = className;
635
- $[62] = disabled;
636
- $[63] = isOpen;
637
- $[64] = isSearchable;
638
- $[65] = t23;
639
- } else t23 = $[65];
640
- let t24;
641
- if ($[66] !== children || $[67] !== childrenCount || $[68] !== hasItems || $[69] !== isOpen) {
642
- t24 = isOpen ? /* @__PURE__ */ jsx("div", {
668
+ $[72] = className;
669
+ $[73] = disabled;
670
+ $[74] = isOpen;
671
+ $[75] = isSearchable;
672
+ $[76] = t22;
673
+ } else t22 = $[76];
674
+ let t23;
675
+ if ($[77] !== bodyId || $[78] !== children || $[79] !== childrenCount || $[80] !== hasItems || $[81] !== isOpen || $[82] !== popupRole) {
676
+ t23 = isOpen ? /* @__PURE__ */ jsx("div", {
643
677
  className: clsx("uktdropdown-body", { "has-items": hasItems }),
678
+ id: bodyId,
679
+ role: popupRole,
644
680
  children: /* @__PURE__ */ jsx("div", {
645
681
  className: "uktdropdown-content",
646
682
  children: childrenCount > 1 ? children[1] : children
647
683
  })
648
684
  }) : null;
649
- $[66] = children;
650
- $[67] = childrenCount;
651
- $[68] = hasItems;
652
- $[69] = isOpen;
653
- $[70] = t24;
654
- } else t24 = $[70];
655
- let t25;
656
- if ($[71] !== handleMouseDown || $[72] !== handleMouseOut || $[73] !== handleMouseOver || $[74] !== handleMouseUp || $[75] !== handleRef || $[76] !== onClick || $[77] !== style || $[78] !== t23 || $[79] !== t24 || $[80] !== trigger) {
657
- t25 = /* @__PURE__ */ jsxs(Fragment, { children: [t22, /* @__PURE__ */ jsxs("div", {
658
- className: t23,
685
+ $[77] = bodyId;
686
+ $[78] = children;
687
+ $[79] = childrenCount;
688
+ $[80] = hasItems;
689
+ $[81] = isOpen;
690
+ $[82] = popupRole;
691
+ $[83] = t23;
692
+ } else t23 = $[83];
693
+ let t24;
694
+ if ($[84] !== handleMouseDown || $[85] !== handleMouseOut || $[86] !== handleMouseOver || $[87] !== handleMouseUp || $[88] !== handleRef || $[89] !== onClick || $[90] !== style || $[91] !== t22 || $[92] !== t23 || $[93] !== trigger) {
695
+ t24 = /* @__PURE__ */ jsxs(Fragment, { children: [t21, /* @__PURE__ */ jsxs("div", {
696
+ className: t22,
659
697
  onClick,
660
698
  onMouseDown: handleMouseDown,
661
699
  onMouseMove: handleMouseMove,
@@ -664,21 +702,21 @@ function Dropdown(t0) {
664
702
  onMouseUp: handleMouseUp,
665
703
  ref: handleRef,
666
704
  style,
667
- children: [trigger, t24]
705
+ children: [trigger, t23]
668
706
  })] });
669
- $[71] = handleMouseDown;
670
- $[72] = handleMouseOut;
671
- $[73] = handleMouseOver;
672
- $[74] = handleMouseUp;
673
- $[75] = handleRef;
674
- $[76] = onClick;
675
- $[77] = style;
676
- $[78] = t23;
677
- $[79] = t24;
678
- $[80] = trigger;
679
- $[81] = t25;
680
- } else t25 = $[81];
681
- return t25;
707
+ $[84] = handleMouseDown;
708
+ $[85] = handleMouseOut;
709
+ $[86] = handleMouseOver;
710
+ $[87] = handleMouseUp;
711
+ $[88] = handleRef;
712
+ $[89] = onClick;
713
+ $[90] = style;
714
+ $[91] = t22;
715
+ $[92] = t23;
716
+ $[93] = trigger;
717
+ $[94] = t24;
718
+ } else t24 = $[94];
719
+ return t24;
682
720
  }
683
721
  //#endregion
684
722
  export { Dropdown as default };
@@ -1 +1 @@
1
- {"version":3,"file":"Dropdown.js","names":["getBestMatch","SyntheticEvent","Item","ITEM_SELECTOR","getItemElements","dropdownElement","HTMLElement","bodyElement","querySelector","items","HTMLCollection","NodeListOf","Element","querySelectorAll","length","children","getActiveItemElement","clearItemElementsState","itemElements","Array","forEach","itemElement","hasAttribute","dataset","uktActive","BaseSetActiveItemPayload","element","event","Event","index","indexAddend","isExactMatch","onActiveItem","payload","text","setActiveItem","Omit","from","lastIndex","currentActiveIndex","findIndex","nextActiveIndex","Math","max","min","itemTexts","map","innerText","textToCompare","toLowerCase","itemText","startsWith","bestMatch","nextActiveItem","setAttribute","label","value","uktValue","parentElement","scrollableParent","isScrollable","scrollHeight","clientHeight","parentRect","getBoundingClientRect","itemRect","isAboveTop","top","isBelowBottom","bottom","scrollTop","useKeyboardEvents","isEventTargetUsingKeyEvent","clsx","Children","CSSProperties","Fragment","isValidElement","JSX","MouseEvent","ReactMouseEvent","ReactNode","SyntheticEvent","useEffect","useRef","useState","styles","getActiveItemElement","getItemElements","ITEM_SELECTOR","setActiveItem","Item","element","MaybeHTMLElement","event","Event","HTMLElement","label","value","Props","allowCreate","allowEmpty","children","ChildrenTuple","Element","className","disabled","group","hasItems","isOpenOnMount","isSearchable","keepOpenOnSubmit","minHeightBody","minWidthBody","name","onActiveItem","payload","onClick","onClose","onMouseDown","onMouseUp","onOpen","onSubmitItem","placeholder","style","tabIndex","MousePosition","clientX","clientY","TimeoutID","ReturnType","setTimeout","CHILDREN_ERROR","CLICKABLE_SELECTOR","TEXT_INPUT_SELECTOR","Dropdown","t0","$","_c","t1","t2","t3","t4","styleFromProps","undefined","childrenCount","count","Error","console","error","trigger","isOpen","setIsOpen","isOpening","setIsOpening","dropdownElement","setDropdownElement","inputElementRef","closingTimerRef","isOpeningTimerRef","currentInputMethodRef","clearEnteredCharactersTimerRef","enteredCharactersRef","mouseDownPositionRef","allowCreateRef","allowEmptyRef","hasItemsRef","isOpenRef","isOpeningRef","keepOpenOnSubmitRef","onCloseRef","onOpenRef","onSubmitItemRef","valueRef","t5","t6","current","isMountedRef","t7","t8","t9","Symbol","for","clearTimeout","closeDropdown","t10","itemLabel","innerText","ownerDocument","activeElement","blur","nextValue","dataset","uktValue","eventTarget","target","matches","contains","click","clickableElements","querySelectorAll","length","clickableElement","handleSubmitItem","t11","t12","initialPosition","Math","abs","handleMouseMove","event_0","itemElements","eventTarget_0","item","closest","element_0","itemElement","handleMouseOver","t13","event_1","activeItem","eventRelatedTarget","relatedTarget","uktActive","handleMouseOut","t14","event_2","handleMouseDown","t15","event_3","eventTarget_1","handleMouseUp","t16","event_4","altKey","ctrlKey","key","metaKey","eventTarget_2","onEventHandled","stopPropagation","preventDefault","isEventTargetingDropdown","isTargetUsingKeyEvents","isEditingCharacters","test","slice","isExactMatch","text","index","indexAddend","handleKeyDown","t17","ignoreUsedKeyboardEvents","onKeyDown","t18","ref","inputElement","firstElementChild","HTMLInputElement","querySelector","handleGlobalMouseDown","t19","eventTarget_3","handleGlobalMouseUp","t20","target_0","eventTarget_4","handleGlobalFocusIn","t21","target_1","eventTarget_5","document","addEventListener","focus","handleInput","event_5","input","isDeleting","removeEventListener","handleRef","t22","t23","t24","t25"],"sources":["../src/Dropdown.css?inline","../src/helpers.ts","../src/Dropdown.tsx"],"sourcesContent":[":root {\n --uktdd-font-family:\n system-ui, Segoe UI, Roboto, Oxygen-Sans, Ubuntu, Cantarell, Helvetica Neue,\n Helvetica, Arial, sans-serif;\n --uktdd-body-bg-color: #fff;\n --uktdd-body-bg-color-hover: rgb(105, 162, 249);\n --uktdd-body-color-hover: #fff;\n --uktdd-body-buffer: 10px;\n --uktdd-body-max-height: calc(100dvh - var(--uktdd-body-buffer));\n --uktdd-body-max-width: calc(100dvw - var(--uktdd-body-buffer));\n --uktdd-body-min-height: 30px;\n --uktdd-body-pad-bottom: 9px;\n --uktdd-body-pad-left: 12px;\n --uktdd-body-pad-right: 12px;\n --uktdd-body-pad-top: 9px;\n --uktdd-body-min-width: min(50px, 100%);\n --uktdd-body-position-area: bottom span-right;\n --uktdd-body-position-try-fallbacks:\n --uktdd-top-left, --uktdd-bottom-right, --uktdd-top-right;\n --uktdd-body-translate: 0 0;\n --uktdd-label-pad-right: 10px;\n}\n\n.uktdropdown,\n.uktdropdown-trigger {\n font-family: var(--uktdd-font-family);\n}\n\n.uktdropdown {\n width: max-content;\n anchor-scope: --uktdd-anchor;\n\n &.disabled {\n pointer-events: none;\n }\n\n > * {\n cursor: default;\n }\n\n > :first-child {\n anchor-name: --uktdd-anchor;\n }\n}\n\n.uktdropdown-label {\n display: flex;\n align-items: center;\n}\n\n.uktdropdown-label-text {\n padding-right: var(--uktdd-label-pad-right);\n}\n\n.uktdropdown-body {\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n position: fixed;\n position-anchor: --uktdd-anchor;\n position-area: var(--uktdd-body-position-area);\n position-try-order: most-height;\n position-try-fallbacks: var(--uktdd-body-position-try-fallbacks);\n min-block-size: min(var(--uktdd-body-min-height), var(--uktdd-body-max-height));\n max-block-size: min(var(--uktdd-body-max-height), 100%);\n min-inline-size: min(var(--uktdd-body-min-width), var(--uktdd-body-max-width));\n max-inline-size: var(--uktdd-body-max-width);\n inline-size: max-content;\n overflow: hidden;\n translate: var(--uktdd-body-translate);\n z-index: 2;\n background-color: var(--uktdd-body-bg-color);\n box-shadow: 0 8px 18px rgba(0, 0, 0, 0.25);\n\n &.has-items {\n user-select: none;\n }\n\n [data-ukt-active] {\n background-color: var(--uktdd-body-bg-color-hover);\n color: var(--uktdd-body-color-hover);\n }\n}\n\n.uktdropdown-content {\n box-sizing: border-box;\n min-block-size: 0;\n overflow: auto;\n overscroll-behavior: contain;\n scrollbar-gutter: stable;\n padding: var(--uktdd-body-pad-top) var(--uktdd-body-pad-right)\n var(--uktdd-body-pad-bottom) var(--uktdd-body-pad-left);\n}\n\n@position-try --uktdd-top-left {\n position-area: top span-right;\n}\n\n@position-try --uktdd-bottom-left {\n position-area: bottom span-right;\n}\n\n@position-try --uktdd-bottom-right {\n position-area: bottom span-left;\n}\n\n@position-try --uktdd-top-right {\n position-area: top span-left;\n}\n","import { getBestMatch } from '@acusti/matchmaking';\nimport { type SyntheticEvent } from 'react';\n\nimport { type Item } from './Dropdown.js';\n\nexport const ITEM_SELECTOR = `[data-ukt-item], [data-ukt-value]`;\n\nexport const getItemElements = (dropdownElement: HTMLElement | null) => {\n if (!dropdownElement) return null;\n\n const bodyElement = dropdownElement.querySelector('.uktdropdown-body');\n if (!bodyElement) return null;\n\n let items: HTMLCollection | NodeListOf<Element> =\n bodyElement.querySelectorAll(ITEM_SELECTOR);\n\n if (items.length) return items;\n // If no items found via [data-ukt-item] or [data-ukt-value] selector,\n // use first instance of multiple children found\n items = bodyElement.children;\n while (items.length === 1) {\n if (items[0].children == null) break;\n items = items[0].children;\n }\n // If unable to find an element with more than one child, treat direct child as items\n if (items.length === 1) {\n items = bodyElement.children;\n }\n return items;\n};\n\nexport const getActiveItemElement = (dropdownElement: HTMLElement | null) => {\n if (!dropdownElement) return null;\n return dropdownElement.querySelector('[data-ukt-active]') as HTMLElement | null;\n};\n\nconst clearItemElementsState = (itemElements: Array<HTMLElement>) => {\n itemElements.forEach((itemElement) => {\n if (itemElement.hasAttribute('data-ukt-active')) {\n delete itemElement.dataset.uktActive;\n }\n });\n};\n\ntype BaseSetActiveItemPayload = {\n dropdownElement: HTMLElement;\n element?: null;\n event: Event | SyntheticEvent<HTMLElement>;\n index?: null;\n indexAddend?: null;\n isExactMatch?: null;\n onActiveItem?: (payload: Item) => void;\n text?: null;\n};\n\nexport const setActiveItem = ({\n dropdownElement,\n element,\n event,\n index,\n indexAddend,\n isExactMatch,\n onActiveItem,\n text,\n}:\n | ({\n element: HTMLElement;\n } & Omit<BaseSetActiveItemPayload, 'element'>)\n | ({\n index: number;\n } & Omit<BaseSetActiveItemPayload, 'index'>)\n | ({\n indexAddend: number;\n } & Omit<BaseSetActiveItemPayload, 'indexAddend'>)\n | ({\n isExactMatch?: boolean;\n text: string;\n } & Omit<BaseSetActiveItemPayload, 'isExactMatch' | 'text'>)) => {\n const items = getItemElements(dropdownElement);\n if (!items) return;\n\n const itemElements = Array.from(items) as Array<HTMLElement>;\n if (!itemElements.length) return;\n\n const lastIndex = itemElements.length - 1;\n const currentActiveIndex = itemElements.findIndex((itemElement) =>\n itemElement.hasAttribute('data-ukt-active'),\n );\n\n let nextActiveIndex = currentActiveIndex;\n if (typeof index === 'number') {\n // Negative index means count back from the end\n nextActiveIndex = index < 0 ? itemElements.length + index : index;\n }\n\n if (element) {\n nextActiveIndex = itemElements.findIndex(\n (itemElement) => itemElement === element,\n );\n } else if (typeof indexAddend === 'number') {\n // If there’s no currentActiveIndex and we are handling -1, start at lastIndex\n if (currentActiveIndex === -1 && indexAddend === -1) {\n nextActiveIndex = lastIndex;\n } else {\n nextActiveIndex += indexAddend;\n }\n // Keep it within the bounds of the items list\n nextActiveIndex = Math.max(0, Math.min(nextActiveIndex, lastIndex));\n } else if (typeof text === 'string') {\n // If text is empty, clear existing active items and early return\n if (!text) {\n clearItemElementsState(itemElements);\n return;\n }\n\n const itemTexts = itemElements.map((itemElement) => itemElement.innerText);\n if (isExactMatch) {\n const textToCompare = text.toLowerCase();\n nextActiveIndex = itemTexts.findIndex((itemText) =>\n itemText.toLowerCase().startsWith(textToCompare),\n );\n // If isExactMatch is required and no exact match was found, clear active items\n if (nextActiveIndex === -1) {\n clearItemElementsState(itemElements);\n }\n } else {\n const bestMatch = getBestMatch({ items: itemTexts, text });\n nextActiveIndex = itemTexts.findIndex((itemText) => itemText === bestMatch);\n }\n }\n\n const nextActiveItem = items[nextActiveIndex] as HTMLElement | null;\n if (nextActiveItem == null || nextActiveIndex === currentActiveIndex) return;\n\n // Clear any existing active dropdown body item state\n clearItemElementsState(itemElements);\n nextActiveItem.setAttribute('data-ukt-active', '');\n const label = nextActiveItem.innerText;\n const value = nextActiveItem.dataset.uktValue ?? label;\n onActiveItem?.({ element: nextActiveItem, event, label, value });\n // Find closest scrollable parent and ensure that next active item is visible\n let { parentElement } = nextActiveItem;\n let scrollableParent = null;\n while (!scrollableParent && parentElement && parentElement !== dropdownElement) {\n const isScrollable = parentElement.scrollHeight > parentElement.clientHeight + 15;\n if (isScrollable) {\n scrollableParent = parentElement;\n } else {\n parentElement = parentElement.parentElement;\n }\n }\n\n if (scrollableParent) {\n const parentRect = scrollableParent.getBoundingClientRect();\n const itemRect = nextActiveItem.getBoundingClientRect();\n const isAboveTop = itemRect.top < parentRect.top;\n const isBelowBottom = itemRect.bottom > parentRect.bottom;\n if (isAboveTop || isBelowBottom) {\n let { scrollTop } = scrollableParent;\n // Item isn’t fully visible; adjust scrollTop to put item within closest edge\n if (isAboveTop) {\n scrollTop -= parentRect.top - itemRect.top;\n } else {\n scrollTop += itemRect.bottom - parentRect.bottom;\n }\n scrollableParent.scrollTop = scrollTop;\n }\n }\n};\n","/* eslint-disable jsx-a11y/click-events-have-key-events, jsx-a11y/mouse-events-have-key-events, jsx-a11y/no-static-element-interactions */\nimport useKeyboardEvents, {\n isEventTargetUsingKeyEvent,\n} from '@acusti/use-keyboard-events';\nimport clsx from 'clsx';\nimport {\n Children,\n type CSSProperties,\n Fragment,\n isValidElement,\n type JSX,\n type MouseEvent as ReactMouseEvent,\n type ReactNode,\n type SyntheticEvent,\n useEffect,\n useRef,\n useState,\n} from 'react';\n\nimport styles from './Dropdown.css?inline';\nimport {\n getActiveItemElement,\n getItemElements,\n ITEM_SELECTOR,\n setActiveItem,\n} from './helpers.js';\n\nexport type Item = {\n element: MaybeHTMLElement;\n event: Event | SyntheticEvent<HTMLElement>;\n label: string;\n value: string;\n};\n\nexport type Props = {\n /**\n * Boolean indicating if the user can submit a value not already in the\n * dropdown.\n */\n allowCreate?: boolean;\n /**\n * Boolean indicating if the user can submit an empty value (i.e. clear\n * the value). Defaults to true.\n */\n allowEmpty?: boolean;\n /**\n * Can take a single React element or exactly two renderable children.\n */\n children: ChildrenTuple | JSX.Element;\n className?: string;\n disabled?: boolean;\n /**\n * Group identifier string links dropdowns together into a menu\n * (like macOS top menubar).\n */\n group?: string;\n hasItems?: boolean;\n isOpenOnMount?: boolean;\n isSearchable?: boolean;\n keepOpenOnSubmit?: boolean;\n label?: ReactNode;\n minHeightBody?: number;\n minWidthBody?: number;\n /**\n * Only usable in conjunction with {isSearchable: true}.\n * Used as search input’s name.\n */\n name?: string;\n onActiveItem?: (payload: Item) => void;\n onClick?: (event: ReactMouseEvent<HTMLElement>) => unknown;\n onClose?: () => unknown;\n onMouseDown?: (event: ReactMouseEvent<HTMLElement>) => unknown;\n onMouseUp?: (event: ReactMouseEvent<HTMLElement>) => unknown;\n onOpen?: () => unknown;\n onSubmitItem?: (payload: Item) => void;\n /**\n * Only usable in conjunction with {isSearchable: true}.\n * Used as search input’s placeholder.\n */\n placeholder?: string;\n style?: CSSProperties;\n /**\n * Only usable in conjunction with {isSearchable: true}.\n * Used as search input’s tabIndex.\n */\n tabIndex?: number;\n /**\n * Used as search input’s value if props.isSearchable === true\n * Used to determine if value has changed to avoid triggering onSubmitItem if not\n */\n value?: string;\n};\n\ntype ChildrenTuple = [ReactNode, ReactNode] | readonly [ReactNode, ReactNode];\n\ntype MaybeHTMLElement = HTMLElement | null;\n\ntype MousePosition = { clientX: number; clientY: number };\n\ntype TimeoutID = ReturnType<typeof setTimeout>;\n\nconst CHILDREN_ERROR =\n '@acusti/dropdown requires either 1 child (the dropdown body) or 2 children: the dropdown trigger and the dropdown body.';\nconst CLICKABLE_SELECTOR = 'button, a[href], input[type=\"button\"], input[type=\"submit\"]';\nconst TEXT_INPUT_SELECTOR =\n 'input:not([type=radio]):not([type=checkbox]):not([type=range]),textarea';\n\nexport default function Dropdown({\n allowCreate,\n allowEmpty = true,\n children,\n className,\n disabled,\n hasItems = true,\n isOpenOnMount,\n isSearchable,\n keepOpenOnSubmit = !hasItems,\n label,\n minHeightBody = 30,\n minWidthBody,\n name,\n onActiveItem,\n onClick,\n onClose,\n onMouseDown,\n onMouseUp,\n onOpen,\n onSubmitItem,\n placeholder,\n style: styleFromProps,\n tabIndex,\n value,\n}: Props) {\n const childrenCount = Children.count(children);\n if (childrenCount !== 1 && childrenCount !== 2) {\n if (childrenCount === 0) {\n throw new Error(CHILDREN_ERROR + ' Received no children.');\n }\n console.error(`${CHILDREN_ERROR} Received ${childrenCount} children.`);\n }\n\n let trigger: React.ReactNode;\n if (childrenCount > 1) {\n trigger = (children as ChildrenTuple)[0];\n }\n\n const [isOpen, setIsOpen] = useState<boolean>(isOpenOnMount ?? false);\n const [isOpening, setIsOpening] = useState<boolean>(!isOpenOnMount);\n const [dropdownElement, setDropdownElement] = useState<MaybeHTMLElement>(null);\n const inputElementRef = useRef<HTMLInputElement | null>(null);\n const closingTimerRef = useRef<null | TimeoutID>(null);\n const isOpeningTimerRef = useRef<null | TimeoutID>(null);\n const currentInputMethodRef = useRef<'keyboard' | 'mouse'>('mouse');\n const clearEnteredCharactersTimerRef = useRef<null | TimeoutID>(null);\n const enteredCharactersRef = useRef<string>('');\n const mouseDownPositionRef = useRef<MousePosition | null>(null);\n\n const allowCreateRef = useRef(allowCreate);\n const allowEmptyRef = useRef(allowEmpty);\n const hasItemsRef = useRef(hasItems);\n const isOpenRef = useRef(isOpen);\n const isOpeningRef = useRef(isOpening);\n const keepOpenOnSubmitRef = useRef(keepOpenOnSubmit);\n const onCloseRef = useRef(onClose);\n const onOpenRef = useRef(onOpen);\n const onSubmitItemRef = useRef(onSubmitItem);\n const valueRef = useRef(value);\n\n useEffect(() => {\n allowCreateRef.current = allowCreate;\n allowEmptyRef.current = allowEmpty;\n hasItemsRef.current = hasItems;\n isOpenRef.current = isOpen;\n isOpeningRef.current = isOpening;\n keepOpenOnSubmitRef.current = keepOpenOnSubmit;\n onCloseRef.current = onClose;\n onOpenRef.current = onOpen;\n onSubmitItemRef.current = onSubmitItem;\n valueRef.current = value;\n }, [\n allowCreate,\n allowEmpty,\n hasItems,\n isOpen,\n isOpening,\n keepOpenOnSubmit,\n onClose,\n onOpen,\n onSubmitItem,\n value,\n ]);\n\n const isMountedRef = useRef(false);\n\n useEffect(() => {\n if (!isMountedRef.current) {\n isMountedRef.current = true;\n // If isOpenOnMount, trigger onOpen right away\n if (isOpenRef.current && onOpenRef.current) {\n onOpenRef.current();\n }\n return;\n }\n\n if (isOpen && onOpenRef.current) {\n onOpenRef.current();\n } else if (!isOpen && onCloseRef.current) {\n onCloseRef.current();\n }\n }, [isOpen]);\n\n const closeDropdown = () => {\n setIsOpen(false);\n setIsOpening(false);\n mouseDownPositionRef.current = null;\n if (closingTimerRef.current != null) {\n clearTimeout(closingTimerRef.current);\n closingTimerRef.current = null;\n }\n };\n\n const handleSubmitItem = (event: Event | React.SyntheticEvent<HTMLElement>) => {\n if (isOpenRef.current && !keepOpenOnSubmitRef.current) {\n // A short timeout before closing is better UX when user selects an item so dropdown\n // doesn’t close before expected. It also enables using <Link />s in the dropdown body.\n closingTimerRef.current = setTimeout(closeDropdown, 90);\n }\n\n if (!hasItemsRef.current) return;\n\n const element = getActiveItemElement(dropdownElement);\n if (!element && !allowCreateRef.current) {\n // If not allowEmpty, don’t allow submitting an empty item\n if (!allowEmptyRef.current) return;\n // If we have an input element as trigger & the user didn’t clear the text, do nothing\n if (inputElementRef.current?.value) return;\n }\n\n let itemLabel = element?.innerText ?? '';\n if (inputElementRef.current) {\n if (!element) {\n itemLabel = inputElementRef.current.value;\n } else {\n inputElementRef.current.value = itemLabel;\n }\n\n if (\n inputElementRef.current ===\n inputElementRef.current.ownerDocument.activeElement\n ) {\n inputElementRef.current.blur();\n }\n }\n\n const nextValue = element?.dataset.uktValue ?? itemLabel;\n // If parent is controlling Dropdown via props.value and nextValue is the same, do nothing\n if (valueRef.current && valueRef.current === nextValue) return;\n\n // If the item is clickable or contains exactly one clickable element, invoke it\n // (but only if the event didn’t already originate from that element)\n if (element) {\n const eventTarget = event.target as HTMLElement;\n\n if (element.matches(CLICKABLE_SELECTOR)) {\n // The item element itself is clickable (e.g., <button data-ukt-value=\"…\">)\n if (element !== eventTarget && !element.contains(eventTarget)) {\n element.click();\n }\n } else {\n // Check if item contains exactly one clickable child element\n const clickableElements = element.querySelectorAll(CLICKABLE_SELECTOR);\n if (clickableElements.length === 1) {\n const clickableElement = clickableElements[0] as HTMLElement;\n if (\n clickableElement !== eventTarget &&\n !clickableElement.contains(eventTarget)\n ) {\n clickableElement.click();\n }\n }\n }\n }\n\n onSubmitItemRef.current?.({\n element,\n event,\n label: itemLabel,\n value: nextValue,\n });\n };\n\n const handleMouseMove = ({ clientX, clientY }: ReactMouseEvent<HTMLElement>) => {\n currentInputMethodRef.current = 'mouse';\n const initialPosition = mouseDownPositionRef.current;\n if (!initialPosition) return;\n if (\n Math.abs(initialPosition.clientX - clientX) < 12 &&\n Math.abs(initialPosition.clientY - clientY) < 12\n ) {\n return;\n }\n setIsOpening(false);\n };\n\n const handleMouseOver = (event: ReactMouseEvent<HTMLElement>) => {\n if (!hasItemsRef.current) return;\n\n // If user isn’t currently using the mouse to navigate the dropdown, do nothing\n if (currentInputMethodRef.current !== 'mouse') return;\n\n // Ensure we have the dropdown root HTMLElement\n if (!dropdownElement) return;\n\n const itemElements = getItemElements(dropdownElement);\n if (!itemElements) return;\n\n const eventTarget = event.target as HTMLElement;\n const item = eventTarget.closest(ITEM_SELECTOR) as MaybeHTMLElement;\n const element = item ?? eventTarget;\n for (const itemElement of itemElements) {\n if (itemElement === element) {\n setActiveItem({ dropdownElement, element, event, onActiveItem });\n return;\n }\n }\n };\n\n const handleMouseOut = (event: ReactMouseEvent<HTMLElement>) => {\n if (!hasItemsRef.current) return;\n const activeItem = getActiveItemElement(dropdownElement);\n if (!activeItem) return;\n const eventRelatedTarget = event.relatedTarget as HTMLElement;\n if (activeItem !== event.target || activeItem.contains(eventRelatedTarget)) {\n return;\n }\n // If user moused out of activeItem (not into a descendant), it’s no longer active\n delete activeItem.dataset.uktActive;\n };\n\n const handleMouseDown = (event: ReactMouseEvent<HTMLElement>) => {\n if (onMouseDown) onMouseDown(event);\n if (isOpenRef.current) return;\n\n setIsOpen(true);\n setIsOpening(true);\n mouseDownPositionRef.current = {\n clientX: event.clientX,\n clientY: event.clientY,\n };\n isOpeningTimerRef.current = setTimeout(() => {\n setIsOpening(false);\n isOpeningTimerRef.current = null;\n }, 1000);\n };\n\n const handleMouseUp = (event: ReactMouseEvent<HTMLElement>) => {\n if (onMouseUp) onMouseUp(event);\n // If dropdown is still opening or isn’t open or is closing, do nothing\n if (\n isOpeningRef.current ||\n !isOpenRef.current ||\n closingTimerRef.current != null\n ) {\n return;\n }\n\n const eventTarget = event.target as HTMLElement;\n // If click was outside dropdown body, don’t trigger submit\n if (!eventTarget.closest('.uktdropdown-body')) {\n // Don’t close dropdown if isOpening or search input is focused\n if (\n !isOpeningRef.current &&\n inputElementRef.current !== eventTarget.ownerDocument.activeElement\n ) {\n closeDropdown();\n }\n return;\n }\n\n // If dropdown has no items and click was within dropdown body, do nothing\n if (!hasItemsRef.current) return;\n\n handleSubmitItem(event);\n };\n\n const handleKeyDown = (event: KeyboardEvent) => {\n const { altKey, ctrlKey, key, metaKey } = event;\n const eventTarget = event.target as HTMLElement;\n if (!dropdownElement) return;\n\n const onEventHandled = () => {\n event.stopPropagation();\n event.preventDefault();\n currentInputMethodRef.current = 'keyboard';\n };\n\n const isEventTargetingDropdown = dropdownElement.contains(eventTarget);\n\n if (!isOpenRef.current) {\n // If dropdown is closed, don’t handle key events if event target isn’t within dropdown\n if (!isEventTargetingDropdown) return;\n // Open the dropdown on spacebar, enter, or if isSearchable and user hits the ↑/↓ arrows\n if (\n key === ' ' ||\n key === 'Enter' ||\n (hasItemsRef.current && (key === 'ArrowUp' || key === 'ArrowDown'))\n ) {\n onEventHandled();\n setIsOpen(true);\n }\n return;\n }\n\n const isTargetUsingKeyEvents = isEventTargetUsingKeyEvent(event);\n\n // If dropdown isOpen + hasItems & eventTargetNotUsingKeyEvents, handle characters\n if (hasItemsRef.current && !isTargetUsingKeyEvents) {\n let isEditingCharacters = !ctrlKey && !metaKey && /^[A-Za-z0-9]$/.test(key);\n // User could also be editing characters if there are already characters entered\n // and they are hitting delete or spacebar\n if (!isEditingCharacters && enteredCharactersRef.current) {\n isEditingCharacters = key === ' ' || key === 'Backspace';\n }\n\n if (isEditingCharacters) {\n onEventHandled();\n if (key === 'Backspace') {\n enteredCharactersRef.current = enteredCharactersRef.current.slice(\n 0,\n -1,\n );\n } else {\n enteredCharactersRef.current += key;\n }\n\n setActiveItem({\n dropdownElement,\n event,\n // If props.allowCreate, only override the input’s value with an\n // exact text match so user can enter a value not in items\n isExactMatch: allowCreateRef.current,\n onActiveItem,\n text: enteredCharactersRef.current,\n });\n\n if (clearEnteredCharactersTimerRef.current != null) {\n clearTimeout(clearEnteredCharactersTimerRef.current);\n }\n\n clearEnteredCharactersTimerRef.current = setTimeout(() => {\n enteredCharactersRef.current = '';\n clearEnteredCharactersTimerRef.current = null;\n }, 1500);\n\n return;\n }\n }\n\n // If dropdown isOpen, handle submitting the value\n if (key === 'Enter' || (key === ' ' && !inputElementRef.current)) {\n onEventHandled();\n handleSubmitItem(event);\n return;\n }\n\n // If dropdown isOpen, handle closing it on escape or spacebar if !hasItems\n if (\n key === 'Escape' ||\n (isEventTargetingDropdown && key === ' ' && !hasItemsRef.current)\n ) {\n // Close dropdown if hasItems or event target not using key events\n if (hasItemsRef.current || !isTargetUsingKeyEvents) {\n closeDropdown();\n }\n return;\n }\n\n // Handle ↑/↓ arrows\n if (hasItemsRef.current) {\n if (key === 'ArrowUp') {\n onEventHandled();\n if (altKey || metaKey) {\n setActiveItem({ dropdownElement, event, index: 0, onActiveItem });\n } else {\n setActiveItem({\n dropdownElement,\n event,\n indexAddend: -1,\n onActiveItem,\n });\n }\n return;\n }\n if (key === 'ArrowDown') {\n onEventHandled();\n if (altKey || metaKey) {\n // Using a negative index counts back from the end\n setActiveItem({ dropdownElement, event, index: -1, onActiveItem });\n } else {\n setActiveItem({\n dropdownElement,\n event,\n indexAddend: 1,\n onActiveItem,\n });\n }\n return;\n }\n }\n };\n\n useKeyboardEvents({ ignoreUsedKeyboardEvents: false, onKeyDown: handleKeyDown });\n\n const handleRef = (ref: HTMLDivElement | null): (() => void) | void => {\n setDropdownElement(ref);\n if (!ref) return;\n\n const { ownerDocument } = ref;\n let inputElement = inputElementRef.current;\n // Check if trigger is a textual input or textarea element\n if (!inputElement && ref.firstElementChild) {\n if (ref.firstElementChild.matches(TEXT_INPUT_SELECTOR)) {\n inputElement = ref.firstElementChild as HTMLInputElement;\n } else {\n inputElement = ref.firstElementChild.querySelector(TEXT_INPUT_SELECTOR);\n }\n inputElementRef.current = inputElement;\n }\n\n const handleGlobalMouseDown = ({ target }: MouseEvent) => {\n const eventTarget = target as HTMLElement;\n if (!ref.contains(eventTarget)) {\n // Close dropdown on an outside click\n closeDropdown();\n }\n };\n\n const handleGlobalMouseUp = ({ target }: MouseEvent) => {\n if (!isOpenRef.current || closingTimerRef.current != null) return;\n\n // If still isOpening (gets set false 1s after open triggers), set it to false onMouseUp\n if (isOpeningRef.current) {\n setIsOpening(false);\n if (isOpeningTimerRef.current != null) {\n clearTimeout(isOpeningTimerRef.current);\n isOpeningTimerRef.current = null;\n }\n return;\n }\n\n const eventTarget = target as HTMLElement;\n // Only handle mouseup events from outside the dropdown here\n if (!ref.contains(eventTarget)) {\n closeDropdown();\n }\n };\n\n // Close dropdown if any element is focused outside of this dropdown\n const handleGlobalFocusIn = ({ target }: Event) => {\n if (!isOpenRef.current) return;\n\n const eventTarget = target as HTMLElement;\n // If focused element is a descendant or a parent of the dropdown, do nothing\n if (ref.contains(eventTarget) || eventTarget.contains(ref)) {\n return;\n }\n\n closeDropdown();\n };\n\n document.addEventListener('focusin', handleGlobalFocusIn);\n document.addEventListener('mousedown', handleGlobalMouseDown);\n document.addEventListener('mouseup', handleGlobalMouseUp);\n\n if (ownerDocument !== document) {\n ownerDocument.addEventListener('focusin', handleGlobalFocusIn);\n ownerDocument.addEventListener('mousedown', handleGlobalMouseDown);\n ownerDocument.addEventListener('mouseup', handleGlobalMouseUp);\n }\n\n // If dropdown should be open on mount, focus it\n if (isOpenOnMount) {\n ref.focus();\n }\n\n const handleInput = (event: Event) => {\n if (!isOpenRef.current) setIsOpen(true);\n\n const input = event.target as HTMLInputElement;\n const isDeleting = enteredCharactersRef.current.length > input.value.length;\n enteredCharactersRef.current = input.value;\n // When deleting text, if there’s already an active item and\n // input isn’t empty, preserve the active item, else update it\n if (isDeleting && input.value.length && getActiveItemElement(ref)) {\n return;\n }\n\n setActiveItem({\n dropdownElement: ref,\n event,\n // If props.allowCreate, only override the input’s value with an\n // exact text match so user can enter a value not in items\n isExactMatch: allowCreateRef.current,\n onActiveItem,\n text: enteredCharactersRef.current,\n });\n };\n\n if (inputElement) {\n inputElement.addEventListener('input', handleInput);\n }\n\n return () => {\n document.removeEventListener('focusin', handleGlobalFocusIn);\n document.removeEventListener('mousedown', handleGlobalMouseDown);\n document.removeEventListener('mouseup', handleGlobalMouseUp);\n\n if (ownerDocument !== document) {\n ownerDocument.removeEventListener('focusin', handleGlobalFocusIn);\n ownerDocument.removeEventListener('mousedown', handleGlobalMouseDown);\n ownerDocument.removeEventListener('mouseup', handleGlobalMouseUp);\n }\n\n if (inputElement) {\n inputElement.removeEventListener('input', handleInput);\n }\n };\n };\n\n if (!isValidElement(trigger)) {\n if (isSearchable) {\n trigger = (\n <input\n autoComplete=\"off\"\n className=\"uktdropdown-trigger\"\n defaultValue={value ?? ''}\n disabled={disabled}\n name={name}\n onFocus={() => setIsOpen(true)}\n placeholder={placeholder}\n ref={inputElementRef}\n tabIndex={tabIndex}\n type=\"text\"\n />\n );\n } else {\n trigger = (\n <button className=\"uktdropdown-trigger\" tabIndex={0} type=\"button\">\n {trigger}\n </button>\n );\n }\n }\n\n if (label != null) {\n trigger = (\n <label className=\"uktdropdown-label\">\n <div className=\"uktdropdown-label-text\">{label}</div>\n {trigger}\n </label>\n );\n }\n\n const style = {\n ...styleFromProps,\n ...(minHeightBody != null && minHeightBody > 0\n ? { '--uktdd-body-min-height': `${minHeightBody}px` }\n : null),\n ...(minWidthBody != null && minWidthBody > 0\n ? { '--uktdd-body-min-width': `${minWidthBody}px` }\n : null),\n };\n\n return (\n <Fragment>\n <style href=\"@acusti/dropdown/Dropdown\" precedence=\"medium\">\n {styles}\n </style>\n <div\n className={clsx('uktdropdown', className, {\n disabled,\n 'is-open': isOpen,\n 'is-searchable': isSearchable,\n })}\n onClick={onClick}\n onMouseDown={handleMouseDown}\n onMouseMove={handleMouseMove}\n onMouseOut={handleMouseOut}\n onMouseOver={handleMouseOver}\n onMouseUp={handleMouseUp}\n ref={handleRef}\n style={style}\n >\n {trigger}\n {/* TODO next version of Dropdown should use <Activity> for body https://react.dev/reference/react/Activity */}\n {isOpen ? (\n <div\n className={clsx('uktdropdown-body', {\n 'has-items': hasItems,\n })}\n >\n <div className=\"uktdropdown-content\">\n {childrenCount > 1\n ? (children as ChildrenTuple)[1]\n : children}\n </div>\n </div>\n ) : null}\n </div>\n </Fragment>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"Dropdown.js","names":["getBestMatch","SyntheticEvent","Item","ITEM_SELECTOR","getItemElements","dropdownElement","HTMLElement","bodyElement","querySelector","items","HTMLCollection","NodeListOf","Element","querySelectorAll","length","children","getActiveItemElement","clearItemElementsState","itemElements","Array","forEach","itemElement","hasAttribute","dataset","uktActive","BaseSetActiveItemPayload","element","event","Event","index","indexAddend","isExactMatch","onActiveItem","payload","text","setActiveItem","Omit","from","lastIndex","currentActiveIndex","findIndex","nextActiveIndex","Math","max","min","itemTexts","map","innerText","textToCompare","toLowerCase","itemText","startsWith","bestMatch","nextActiveItem","setAttribute","label","value","uktValue","parentElement","scrollableParent","isScrollable","scrollHeight","clientHeight","parentRect","getBoundingClientRect","itemRect","isAboveTop","top","isBelowBottom","bottom","scrollTop","useKeyboardEvents","isEventTargetUsingKeyEvent","clsx","Children","cloneElement","CSSProperties","Fragment","isValidElement","MouseEvent","ReactMouseEvent","ReactElement","ReactNode","SyntheticEvent","useEffect","useId","useRef","useState","styles","getActiveItemElement","getItemElements","ITEM_SELECTOR","setActiveItem","Item","element","MaybeHTMLElement","event","Event","HTMLElement","label","value","Props","allowCreate","allowEmpty","children","ChildrenTuple","className","disabled","group","hasItems","isOpenOnMount","isSearchable","keepOpenOnSubmit","minHeightBody","minWidthBody","name","onActiveItem","payload","onClick","onClose","onMouseDown","onMouseUp","onOpen","onSubmitItem","placeholder","style","tabIndex","MousePosition","clientX","clientY","TimeoutID","ReturnType","setTimeout","CHILDREN_ERROR","CLICKABLE_SELECTOR","TEXT_INPUT_SELECTOR","Dropdown","t0","$","_c","t1","t2","t3","styleFromProps","undefined","childrenCount","count","Error","console","error","trigger","isOpen","setIsOpen","isOpening","setIsOpening","dropdownElement","setDropdownElement","bodyId","popupRole","inputElementRef","closingTimerRef","isOpeningTimerRef","currentInputMethodRef","clearEnteredCharactersTimerRef","enteredCharactersRef","mouseDownPositionRef","allowCreateRef","allowEmptyRef","hasItemsRef","isOpenRef","isOpeningRef","keepOpenOnSubmitRef","onCloseRef","onOpenRef","onSubmitItemRef","valueRef","t4","t5","current","isMountedRef","t6","t7","t8","Symbol","for","clearTimeout","closeDropdown","t9","itemLabel","innerText","ownerDocument","activeElement","blur","nextValue","dataset","uktValue","eventTarget","target","matches","contains","click","clickableElements","querySelectorAll","length","clickableElement","handleSubmitItem","t10","t11","initialPosition","Math","abs","handleMouseMove","event_0","itemElements","eventTarget_0","item","closest","element_0","itemElement","handleMouseOver","t12","event_1","activeItem","eventRelatedTarget","relatedTarget","uktActive","handleMouseOut","t13","event_2","handleMouseDown","t14","event_3","eventTarget_1","handleMouseUp","t15","event_4","altKey","ctrlKey","key","metaKey","eventTarget_2","onEventHandled","stopPropagation","preventDefault","isEventTargetingDropdown","isTargetUsingKeyEvents","isEditingCharacters","test","slice","isExactMatch","text","index","indexAddend","handleKeyDown","t16","ignoreUsedKeyboardEvents","onKeyDown","t17","ref","inputElement","firstElementChild","HTMLInputElement","querySelector","handleGlobalMouseDown","t18","eventTarget_3","handleGlobalMouseUp","t19","target_0","eventTarget_4","handleGlobalFocusIn","t20","target_1","eventTarget_5","document","addEventListener","focus","handleInput","event_5","input","isDeleting","removeEventListener","handleRef","triggerProps","props","Record","t21","t22","t23","t24"],"sources":["../src/Dropdown.css?inline","../src/helpers.ts","../src/Dropdown.tsx"],"sourcesContent":[":root {\n --uktdd-font-family:\n system-ui, Segoe UI, Roboto, Oxygen-Sans, Ubuntu, Cantarell, Helvetica Neue,\n Helvetica, Arial, sans-serif;\n --uktdd-body-bg-color: #fff;\n --uktdd-body-bg-color-hover: rgb(105, 162, 249);\n --uktdd-body-color-hover: #fff;\n --uktdd-body-buffer: 10px;\n --uktdd-body-max-height: calc(100dvh - var(--uktdd-body-buffer));\n --uktdd-body-max-width: calc(100dvw - var(--uktdd-body-buffer));\n --uktdd-body-min-height: 30px;\n --uktdd-body-pad-bottom: 9px;\n --uktdd-body-pad-left: 12px;\n --uktdd-body-pad-right: 12px;\n --uktdd-body-pad-top: 9px;\n --uktdd-body-min-width: min(50px, 100%);\n --uktdd-body-position-area: bottom span-right;\n --uktdd-body-position-try-fallbacks:\n --uktdd-top-left, --uktdd-bottom-right, --uktdd-top-right;\n --uktdd-body-translate: 0 0;\n --uktdd-label-pad-right: 10px;\n}\n\n.uktdropdown,\n.uktdropdown-trigger {\n font-family: var(--uktdd-font-family);\n}\n\n.uktdropdown {\n width: max-content;\n anchor-scope: --uktdd-anchor;\n\n &.disabled {\n pointer-events: none;\n }\n\n > * {\n cursor: default;\n }\n\n > :first-child {\n anchor-name: --uktdd-anchor;\n }\n}\n\n.uktdropdown-label {\n display: flex;\n align-items: center;\n}\n\n.uktdropdown-label-text {\n padding-right: var(--uktdd-label-pad-right);\n}\n\n.uktdropdown-body {\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n position: fixed;\n position-anchor: --uktdd-anchor;\n position-area: var(--uktdd-body-position-area);\n position-try-order: most-height;\n position-try-fallbacks: var(--uktdd-body-position-try-fallbacks);\n min-block-size: min(var(--uktdd-body-min-height), var(--uktdd-body-max-height));\n max-block-size: min(var(--uktdd-body-max-height), 100%);\n min-inline-size: min(var(--uktdd-body-min-width), var(--uktdd-body-max-width));\n max-inline-size: var(--uktdd-body-max-width);\n inline-size: max-content;\n overflow: hidden;\n translate: var(--uktdd-body-translate);\n z-index: 2;\n background-color: var(--uktdd-body-bg-color);\n box-shadow: 0 8px 18px rgba(0, 0, 0, 0.25);\n\n &.has-items {\n user-select: none;\n }\n\n [data-ukt-active] {\n background-color: var(--uktdd-body-bg-color-hover);\n color: var(--uktdd-body-color-hover);\n }\n}\n\n.uktdropdown-content {\n box-sizing: border-box;\n min-block-size: 0;\n overflow: auto;\n overscroll-behavior: contain;\n padding: var(--uktdd-body-pad-top) var(--uktdd-body-pad-right)\n var(--uktdd-body-pad-bottom) var(--uktdd-body-pad-left);\n}\n\n@position-try --uktdd-top-left {\n position-area: top span-right;\n}\n\n@position-try --uktdd-bottom-left {\n position-area: bottom span-right;\n}\n\n@position-try --uktdd-bottom-right {\n position-area: bottom span-left;\n}\n\n@position-try --uktdd-top-right {\n position-area: top span-left;\n}\n","import { getBestMatch } from '@acusti/matchmaking';\nimport { type SyntheticEvent } from 'react';\n\nimport { type Item } from './Dropdown.js';\n\nexport const ITEM_SELECTOR = `[data-ukt-item], [data-ukt-value]`;\n\nexport const getItemElements = (dropdownElement: HTMLElement | null) => {\n if (!dropdownElement) return null;\n\n const bodyElement = dropdownElement.querySelector('.uktdropdown-body');\n if (!bodyElement) return null;\n\n let items: HTMLCollection | NodeListOf<Element> =\n bodyElement.querySelectorAll(ITEM_SELECTOR);\n\n if (items.length) return items;\n // If no items found via [data-ukt-item] or [data-ukt-value] selector,\n // use first instance of multiple children found\n items = bodyElement.children;\n while (items.length === 1) {\n if (items[0].children == null) break;\n items = items[0].children;\n }\n // If unable to find an element with more than one child, treat direct child as items\n if (items.length === 1) {\n items = bodyElement.children;\n }\n return items;\n};\n\nexport const getActiveItemElement = (dropdownElement: HTMLElement | null) => {\n if (!dropdownElement) return null;\n return dropdownElement.querySelector('[data-ukt-active]') as HTMLElement | null;\n};\n\nconst clearItemElementsState = (itemElements: Array<HTMLElement>) => {\n itemElements.forEach((itemElement) => {\n if (itemElement.hasAttribute('data-ukt-active')) {\n delete itemElement.dataset.uktActive;\n }\n });\n};\n\ntype BaseSetActiveItemPayload = {\n dropdownElement: HTMLElement;\n element?: null;\n event: Event | SyntheticEvent<HTMLElement>;\n index?: null;\n indexAddend?: null;\n isExactMatch?: null;\n onActiveItem?: (payload: Item) => void;\n text?: null;\n};\n\nexport const setActiveItem = ({\n dropdownElement,\n element,\n event,\n index,\n indexAddend,\n isExactMatch,\n onActiveItem,\n text,\n}:\n | ({\n element: HTMLElement;\n } & Omit<BaseSetActiveItemPayload, 'element'>)\n | ({\n index: number;\n } & Omit<BaseSetActiveItemPayload, 'index'>)\n | ({\n indexAddend: number;\n } & Omit<BaseSetActiveItemPayload, 'indexAddend'>)\n | ({\n isExactMatch?: boolean;\n text: string;\n } & Omit<BaseSetActiveItemPayload, 'isExactMatch' | 'text'>)) => {\n const items = getItemElements(dropdownElement);\n if (!items) return;\n\n const itemElements = Array.from(items) as Array<HTMLElement>;\n if (!itemElements.length) return;\n\n const lastIndex = itemElements.length - 1;\n const currentActiveIndex = itemElements.findIndex((itemElement) =>\n itemElement.hasAttribute('data-ukt-active'),\n );\n\n let nextActiveIndex = currentActiveIndex;\n if (typeof index === 'number') {\n // Negative index means count back from the end\n nextActiveIndex = index < 0 ? itemElements.length + index : index;\n }\n\n if (element) {\n nextActiveIndex = itemElements.findIndex(\n (itemElement) => itemElement === element,\n );\n } else if (typeof indexAddend === 'number') {\n // If there’s no currentActiveIndex and we are handling -1, start at lastIndex\n if (currentActiveIndex === -1 && indexAddend === -1) {\n nextActiveIndex = lastIndex;\n } else {\n nextActiveIndex += indexAddend;\n }\n // Keep it within the bounds of the items list\n nextActiveIndex = Math.max(0, Math.min(nextActiveIndex, lastIndex));\n } else if (typeof text === 'string') {\n // If text is empty, clear existing active items and early return\n if (!text) {\n clearItemElementsState(itemElements);\n return;\n }\n\n const itemTexts = itemElements.map((itemElement) => itemElement.innerText);\n if (isExactMatch) {\n const textToCompare = text.toLowerCase();\n nextActiveIndex = itemTexts.findIndex((itemText) =>\n itemText.toLowerCase().startsWith(textToCompare),\n );\n // If isExactMatch is required and no exact match was found, clear active items\n if (nextActiveIndex === -1) {\n clearItemElementsState(itemElements);\n }\n } else {\n const bestMatch = getBestMatch({ items: itemTexts, text });\n nextActiveIndex = itemTexts.findIndex((itemText) => itemText === bestMatch);\n }\n }\n\n const nextActiveItem = items[nextActiveIndex] as HTMLElement | null;\n if (nextActiveItem == null || nextActiveIndex === currentActiveIndex) return;\n\n // Clear any existing active dropdown body item state\n clearItemElementsState(itemElements);\n nextActiveItem.setAttribute('data-ukt-active', '');\n const label = nextActiveItem.innerText;\n const value = nextActiveItem.dataset.uktValue ?? label;\n onActiveItem?.({ element: nextActiveItem, event, label, value });\n // Find closest scrollable parent and ensure that next active item is visible\n let { parentElement } = nextActiveItem;\n let scrollableParent = null;\n while (!scrollableParent && parentElement && parentElement !== dropdownElement) {\n const isScrollable = parentElement.scrollHeight > parentElement.clientHeight + 15;\n if (isScrollable) {\n scrollableParent = parentElement;\n } else {\n parentElement = parentElement.parentElement;\n }\n }\n\n if (scrollableParent) {\n const parentRect = scrollableParent.getBoundingClientRect();\n const itemRect = nextActiveItem.getBoundingClientRect();\n const isAboveTop = itemRect.top < parentRect.top;\n const isBelowBottom = itemRect.bottom > parentRect.bottom;\n if (isAboveTop || isBelowBottom) {\n let { scrollTop } = scrollableParent;\n // Item isn’t fully visible; adjust scrollTop to put item within closest edge\n if (isAboveTop) {\n scrollTop -= parentRect.top - itemRect.top;\n } else {\n scrollTop += itemRect.bottom - parentRect.bottom;\n }\n scrollableParent.scrollTop = scrollTop;\n }\n }\n};\n","/* eslint-disable jsx-a11y/click-events-have-key-events, jsx-a11y/mouse-events-have-key-events, jsx-a11y/no-static-element-interactions */\nimport useKeyboardEvents, {\n isEventTargetUsingKeyEvent,\n} from '@acusti/use-keyboard-events';\nimport clsx from 'clsx';\nimport {\n Children,\n cloneElement,\n type CSSProperties,\n Fragment,\n isValidElement,\n type MouseEvent as ReactMouseEvent,\n type ReactElement,\n type ReactNode,\n type SyntheticEvent,\n useEffect,\n useId,\n useRef,\n useState,\n} from 'react';\n\nimport styles from './Dropdown.css?inline';\nimport {\n getActiveItemElement,\n getItemElements,\n ITEM_SELECTOR,\n setActiveItem,\n} from './helpers.js';\n\nexport type Item = {\n element: MaybeHTMLElement;\n event: Event | SyntheticEvent<HTMLElement>;\n label: string;\n value: string;\n};\n\nexport type Props = {\n /**\n * Boolean indicating if the user can submit a value not already in the\n * dropdown.\n */\n allowCreate?: boolean;\n /**\n * Boolean indicating if the user can submit an empty value (i.e. clear\n * the value). Defaults to true.\n */\n allowEmpty?: boolean;\n /**\n * Can take a single React element or exactly two renderable children.\n */\n children: ChildrenTuple | ReactElement;\n className?: string;\n disabled?: boolean;\n /**\n * Group identifier string links dropdowns together into a menu\n * (like macOS top menubar).\n */\n group?: string;\n hasItems?: boolean;\n isOpenOnMount?: boolean;\n isSearchable?: boolean;\n keepOpenOnSubmit?: boolean;\n label?: ReactNode;\n minHeightBody?: number;\n minWidthBody?: number;\n /**\n * Only usable in conjunction with {isSearchable: true}.\n * Used as search input’s name.\n */\n name?: string;\n onActiveItem?: (payload: Item) => void;\n onClick?: (event: ReactMouseEvent<HTMLElement>) => unknown;\n onClose?: () => unknown;\n onMouseDown?: (event: ReactMouseEvent<HTMLElement>) => unknown;\n onMouseUp?: (event: ReactMouseEvent<HTMLElement>) => unknown;\n onOpen?: () => unknown;\n onSubmitItem?: (payload: Item) => void;\n /**\n * Only usable in conjunction with {isSearchable: true}.\n * Used as search input’s placeholder.\n */\n placeholder?: string;\n style?: CSSProperties;\n /**\n * Only usable in conjunction with {isSearchable: true}.\n * Used as search input’s tabIndex.\n */\n tabIndex?: number;\n /**\n * Used as search input’s value if props.isSearchable === true\n * Used to determine if value has changed to avoid triggering onSubmitItem if not\n */\n value?: string;\n};\n\ntype ChildrenTuple = [ReactNode, ReactNode] | readonly [ReactNode, ReactNode];\n\ntype MaybeHTMLElement = HTMLElement | null;\n\ntype MousePosition = { clientX: number; clientY: number };\n\ntype TimeoutID = ReturnType<typeof setTimeout>;\n\nconst CHILDREN_ERROR =\n '@acusti/dropdown requires either 1 child (the dropdown body) or 2 children: the dropdown trigger and the dropdown body.';\nconst CLICKABLE_SELECTOR = 'button, a[href], input[type=\"button\"], input[type=\"submit\"]';\nconst TEXT_INPUT_SELECTOR =\n 'input:not([type=radio]):not([type=checkbox]):not([type=range]),textarea';\n\nexport default function Dropdown({\n allowCreate,\n allowEmpty = true,\n children,\n className,\n disabled,\n hasItems = true,\n isOpenOnMount,\n isSearchable,\n keepOpenOnSubmit = !hasItems,\n label,\n minHeightBody,\n minWidthBody,\n name,\n onActiveItem,\n onClick,\n onClose,\n onMouseDown,\n onMouseUp,\n onOpen,\n onSubmitItem,\n placeholder,\n style: styleFromProps,\n tabIndex,\n value,\n}: Props) {\n const childrenCount = Children.count(children);\n if (childrenCount !== 1 && childrenCount !== 2) {\n if (childrenCount === 0) {\n throw new Error(CHILDREN_ERROR + ' Received no children.');\n }\n console.error(`${CHILDREN_ERROR} Received ${childrenCount} children.`);\n }\n\n let trigger: React.ReactNode;\n if (childrenCount > 1) {\n trigger = (children as ChildrenTuple)[0];\n }\n\n const [isOpen, setIsOpen] = useState<boolean>(isOpenOnMount ?? false);\n const [isOpening, setIsOpening] = useState<boolean>(!isOpenOnMount);\n const [dropdownElement, setDropdownElement] = useState<MaybeHTMLElement>(null);\n const bodyId = useId();\n const popupRole = isSearchable ? 'listbox' : hasItems ? 'menu' : 'dialog';\n const inputElementRef = useRef<HTMLInputElement | null>(null);\n const closingTimerRef = useRef<null | TimeoutID>(null);\n const isOpeningTimerRef = useRef<null | TimeoutID>(null);\n const currentInputMethodRef = useRef<'keyboard' | 'mouse'>('mouse');\n const clearEnteredCharactersTimerRef = useRef<null | TimeoutID>(null);\n const enteredCharactersRef = useRef<string>('');\n const mouseDownPositionRef = useRef<MousePosition | null>(null);\n\n const allowCreateRef = useRef(allowCreate);\n const allowEmptyRef = useRef(allowEmpty);\n const hasItemsRef = useRef(hasItems);\n const isOpenRef = useRef(isOpen);\n const isOpeningRef = useRef(isOpening);\n const keepOpenOnSubmitRef = useRef(keepOpenOnSubmit);\n const onCloseRef = useRef(onClose);\n const onOpenRef = useRef(onOpen);\n const onSubmitItemRef = useRef(onSubmitItem);\n const valueRef = useRef(value);\n\n useEffect(() => {\n allowCreateRef.current = allowCreate;\n allowEmptyRef.current = allowEmpty;\n hasItemsRef.current = hasItems;\n isOpenRef.current = isOpen;\n isOpeningRef.current = isOpening;\n keepOpenOnSubmitRef.current = keepOpenOnSubmit;\n onCloseRef.current = onClose;\n onOpenRef.current = onOpen;\n onSubmitItemRef.current = onSubmitItem;\n valueRef.current = value;\n }, [\n allowCreate,\n allowEmpty,\n hasItems,\n isOpen,\n isOpening,\n keepOpenOnSubmit,\n onClose,\n onOpen,\n onSubmitItem,\n value,\n ]);\n\n const isMountedRef = useRef(false);\n\n useEffect(() => {\n if (!isMountedRef.current) {\n isMountedRef.current = true;\n // If isOpenOnMount, trigger onOpen right away\n if (isOpenRef.current && onOpenRef.current) {\n onOpenRef.current();\n }\n return;\n }\n\n if (isOpen && onOpenRef.current) {\n onOpenRef.current();\n } else if (!isOpen && onCloseRef.current) {\n onCloseRef.current();\n }\n }, [isOpen]);\n\n const closeDropdown = () => {\n setIsOpen(false);\n setIsOpening(false);\n mouseDownPositionRef.current = null;\n if (closingTimerRef.current != null) {\n clearTimeout(closingTimerRef.current);\n closingTimerRef.current = null;\n }\n };\n\n const handleSubmitItem = (event: Event | React.SyntheticEvent<HTMLElement>) => {\n if (isOpenRef.current && !keepOpenOnSubmitRef.current) {\n // A short timeout before closing is better UX when user selects an item so dropdown\n // doesn’t close before expected. It also enables using <Link />s in the dropdown body.\n closingTimerRef.current = setTimeout(closeDropdown, 90);\n }\n\n if (!hasItemsRef.current) return;\n\n const element = getActiveItemElement(dropdownElement);\n if (!element && !allowCreateRef.current) {\n // If not allowEmpty, don’t allow submitting an empty item\n if (!allowEmptyRef.current) return;\n // If we have an input element as trigger & the user didn’t clear the text, do nothing\n if (inputElementRef.current?.value) return;\n }\n\n let itemLabel = element?.innerText ?? '';\n if (inputElementRef.current) {\n if (!element) {\n itemLabel = inputElementRef.current.value;\n } else {\n inputElementRef.current.value = itemLabel;\n }\n\n if (\n inputElementRef.current ===\n inputElementRef.current.ownerDocument.activeElement\n ) {\n inputElementRef.current.blur();\n }\n }\n\n const nextValue = element?.dataset.uktValue ?? itemLabel;\n // If parent is controlling Dropdown via props.value and nextValue is the same, do nothing\n if (valueRef.current && valueRef.current === nextValue) return;\n\n // If the item is clickable or contains exactly one clickable element, invoke it\n // (but only if the event didn’t already originate from that element)\n if (element) {\n const eventTarget = event.target as HTMLElement;\n\n if (element.matches(CLICKABLE_SELECTOR)) {\n // The item element itself is clickable (e.g., <button data-ukt-value=\"…\">)\n if (element !== eventTarget && !element.contains(eventTarget)) {\n element.click();\n }\n } else {\n // Check if item contains exactly one clickable child element\n const clickableElements = element.querySelectorAll(CLICKABLE_SELECTOR);\n if (clickableElements.length === 1) {\n const clickableElement = clickableElements[0] as HTMLElement;\n if (\n clickableElement !== eventTarget &&\n !clickableElement.contains(eventTarget)\n ) {\n clickableElement.click();\n }\n }\n }\n }\n\n onSubmitItemRef.current?.({\n element,\n event,\n label: itemLabel,\n value: nextValue,\n });\n };\n\n const handleMouseMove = ({ clientX, clientY }: ReactMouseEvent<HTMLElement>) => {\n currentInputMethodRef.current = 'mouse';\n const initialPosition = mouseDownPositionRef.current;\n if (!initialPosition) return;\n if (\n Math.abs(initialPosition.clientX - clientX) < 12 &&\n Math.abs(initialPosition.clientY - clientY) < 12\n ) {\n return;\n }\n setIsOpening(false);\n };\n\n const handleMouseOver = (event: ReactMouseEvent<HTMLElement>) => {\n if (!hasItemsRef.current) return;\n\n // If user isn’t currently using the mouse to navigate the dropdown, do nothing\n if (currentInputMethodRef.current !== 'mouse') return;\n\n // Ensure we have the dropdown root HTMLElement\n if (!dropdownElement) return;\n\n const itemElements = getItemElements(dropdownElement);\n if (!itemElements) return;\n\n const eventTarget = event.target as HTMLElement;\n const item = eventTarget.closest(ITEM_SELECTOR) as MaybeHTMLElement;\n const element = item ?? eventTarget;\n for (const itemElement of itemElements) {\n if (itemElement === element) {\n setActiveItem({ dropdownElement, element, event, onActiveItem });\n return;\n }\n }\n };\n\n const handleMouseOut = (event: ReactMouseEvent<HTMLElement>) => {\n if (!hasItemsRef.current) return;\n const activeItem = getActiveItemElement(dropdownElement);\n if (!activeItem) return;\n const eventRelatedTarget = event.relatedTarget as HTMLElement;\n if (activeItem !== event.target || activeItem.contains(eventRelatedTarget)) {\n return;\n }\n // If user moused out of activeItem (not into a descendant), it’s no longer active\n delete activeItem.dataset.uktActive;\n };\n\n const handleMouseDown = (event: ReactMouseEvent<HTMLElement>) => {\n if (onMouseDown) onMouseDown(event);\n if (isOpenRef.current) return;\n\n setIsOpen(true);\n setIsOpening(true);\n mouseDownPositionRef.current = {\n clientX: event.clientX,\n clientY: event.clientY,\n };\n isOpeningTimerRef.current = setTimeout(() => {\n setIsOpening(false);\n isOpeningTimerRef.current = null;\n }, 1000);\n };\n\n const handleMouseUp = (event: ReactMouseEvent<HTMLElement>) => {\n if (onMouseUp) onMouseUp(event);\n // If dropdown is still opening or isn’t open or is closing, do nothing\n if (\n isOpeningRef.current ||\n !isOpenRef.current ||\n closingTimerRef.current != null\n ) {\n return;\n }\n\n const eventTarget = event.target as HTMLElement;\n // If click was outside dropdown body, don’t trigger submit\n if (!eventTarget.closest('.uktdropdown-body')) {\n // Don’t close dropdown if isOpening or search input is focused\n if (\n !isOpeningRef.current &&\n inputElementRef.current !== eventTarget.ownerDocument.activeElement\n ) {\n closeDropdown();\n }\n return;\n }\n\n // If dropdown has no items and click was within dropdown body, do nothing\n if (!hasItemsRef.current) return;\n\n handleSubmitItem(event);\n };\n\n const handleKeyDown = (event: KeyboardEvent) => {\n const { altKey, ctrlKey, key, metaKey } = event;\n const eventTarget = event.target as HTMLElement;\n if (!dropdownElement) return;\n\n const onEventHandled = () => {\n event.stopPropagation();\n event.preventDefault();\n currentInputMethodRef.current = 'keyboard';\n };\n\n const isEventTargetingDropdown = dropdownElement.contains(eventTarget);\n\n if (!isOpenRef.current) {\n // If dropdown is closed, don’t handle key events if event target isn’t within dropdown\n if (!isEventTargetingDropdown) return;\n // Open the dropdown on spacebar, enter, or if isSearchable and user hits the ↑/↓ arrows\n if (\n key === ' ' ||\n key === 'Enter' ||\n (hasItemsRef.current && (key === 'ArrowUp' || key === 'ArrowDown'))\n ) {\n onEventHandled();\n setIsOpen(true);\n }\n return;\n }\n\n const isTargetUsingKeyEvents = isEventTargetUsingKeyEvent(event);\n\n // If dropdown isOpen + hasItems & eventTargetNotUsingKeyEvents, handle characters\n if (hasItemsRef.current && !isTargetUsingKeyEvents) {\n let isEditingCharacters = !ctrlKey && !metaKey && /^[A-Za-z0-9]$/.test(key);\n // User could also be editing characters if there are already characters entered\n // and they are hitting delete or spacebar\n if (!isEditingCharacters && enteredCharactersRef.current) {\n isEditingCharacters = key === ' ' || key === 'Backspace';\n }\n\n if (isEditingCharacters) {\n onEventHandled();\n if (key === 'Backspace') {\n enteredCharactersRef.current = enteredCharactersRef.current.slice(\n 0,\n -1,\n );\n } else {\n enteredCharactersRef.current += key;\n }\n\n setActiveItem({\n dropdownElement,\n event,\n // If props.allowCreate, only override the input’s value with an\n // exact text match so user can enter a value not in items\n isExactMatch: allowCreateRef.current,\n onActiveItem,\n text: enteredCharactersRef.current,\n });\n\n if (clearEnteredCharactersTimerRef.current != null) {\n clearTimeout(clearEnteredCharactersTimerRef.current);\n }\n\n clearEnteredCharactersTimerRef.current = setTimeout(() => {\n enteredCharactersRef.current = '';\n clearEnteredCharactersTimerRef.current = null;\n }, 1500);\n\n return;\n }\n }\n\n // If dropdown isOpen, handle submitting the value\n if (key === 'Enter' || (key === ' ' && !inputElementRef.current)) {\n onEventHandled();\n handleSubmitItem(event);\n return;\n }\n\n // If dropdown isOpen, handle closing it on escape or spacebar if !hasItems\n if (\n key === 'Escape' ||\n (isEventTargetingDropdown && key === ' ' && !hasItemsRef.current)\n ) {\n // Close dropdown if hasItems or event target not using key events\n if (hasItemsRef.current || !isTargetUsingKeyEvents) {\n closeDropdown();\n }\n return;\n }\n\n // Handle ↑/↓ arrows\n if (hasItemsRef.current) {\n if (key === 'ArrowUp') {\n onEventHandled();\n if (altKey || metaKey) {\n setActiveItem({ dropdownElement, event, index: 0, onActiveItem });\n } else {\n setActiveItem({\n dropdownElement,\n event,\n indexAddend: -1,\n onActiveItem,\n });\n }\n return;\n }\n if (key === 'ArrowDown') {\n onEventHandled();\n if (altKey || metaKey) {\n // Using a negative index counts back from the end\n setActiveItem({ dropdownElement, event, index: -1, onActiveItem });\n } else {\n setActiveItem({\n dropdownElement,\n event,\n indexAddend: 1,\n onActiveItem,\n });\n }\n return;\n }\n }\n };\n\n useKeyboardEvents({ ignoreUsedKeyboardEvents: false, onKeyDown: handleKeyDown });\n\n const handleRef = (ref: HTMLDivElement | null): (() => void) | void => {\n setDropdownElement(ref);\n if (!ref) return;\n\n const { ownerDocument } = ref;\n let inputElement = inputElementRef.current;\n // Check if trigger is a textual input or textarea element\n if (!inputElement && ref.firstElementChild) {\n if (ref.firstElementChild.matches(TEXT_INPUT_SELECTOR)) {\n inputElement = ref.firstElementChild as HTMLInputElement;\n } else {\n inputElement = ref.firstElementChild.querySelector(TEXT_INPUT_SELECTOR);\n }\n inputElementRef.current = inputElement;\n }\n\n const handleGlobalMouseDown = ({ target }: MouseEvent) => {\n const eventTarget = target as HTMLElement;\n if (!ref.contains(eventTarget)) {\n // Close dropdown on an outside click\n closeDropdown();\n }\n };\n\n const handleGlobalMouseUp = ({ target }: MouseEvent) => {\n if (!isOpenRef.current || closingTimerRef.current != null) return;\n\n // If still isOpening (gets set false 1s after open triggers), set it to false onMouseUp\n if (isOpeningRef.current) {\n setIsOpening(false);\n if (isOpeningTimerRef.current != null) {\n clearTimeout(isOpeningTimerRef.current);\n isOpeningTimerRef.current = null;\n }\n return;\n }\n\n const eventTarget = target as HTMLElement;\n // Only handle mouseup events from outside the dropdown here\n if (!ref.contains(eventTarget)) {\n closeDropdown();\n }\n };\n\n // Close dropdown if any element is focused outside of this dropdown\n const handleGlobalFocusIn = ({ target }: Event) => {\n if (!isOpenRef.current) return;\n\n const eventTarget = target as HTMLElement;\n // If focused element is a descendant or a parent of the dropdown, do nothing\n if (ref.contains(eventTarget) || eventTarget.contains(ref)) {\n return;\n }\n\n closeDropdown();\n };\n\n document.addEventListener('focusin', handleGlobalFocusIn);\n document.addEventListener('mousedown', handleGlobalMouseDown);\n document.addEventListener('mouseup', handleGlobalMouseUp);\n\n if (ownerDocument !== document) {\n ownerDocument.addEventListener('focusin', handleGlobalFocusIn);\n ownerDocument.addEventListener('mousedown', handleGlobalMouseDown);\n ownerDocument.addEventListener('mouseup', handleGlobalMouseUp);\n }\n\n // If dropdown should be open on mount, focus it\n if (isOpenOnMount) {\n ref.focus();\n }\n\n const handleInput = (event: Event) => {\n if (!isOpenRef.current) setIsOpen(true);\n\n const input = event.target as HTMLInputElement;\n const isDeleting = enteredCharactersRef.current.length > input.value.length;\n enteredCharactersRef.current = input.value;\n // When deleting text, if there’s already an active item and\n // input isn’t empty, preserve the active item, else update it\n if (isDeleting && input.value.length && getActiveItemElement(ref)) {\n return;\n }\n\n setActiveItem({\n dropdownElement: ref,\n event,\n // If props.allowCreate, only override the input’s value with an\n // exact text match so user can enter a value not in items\n isExactMatch: allowCreateRef.current,\n onActiveItem,\n text: enteredCharactersRef.current,\n });\n };\n\n if (inputElement) {\n inputElement.addEventListener('input', handleInput);\n }\n\n return () => {\n document.removeEventListener('focusin', handleGlobalFocusIn);\n document.removeEventListener('mousedown', handleGlobalMouseDown);\n document.removeEventListener('mouseup', handleGlobalMouseUp);\n\n if (ownerDocument !== document) {\n ownerDocument.removeEventListener('focusin', handleGlobalFocusIn);\n ownerDocument.removeEventListener('mousedown', handleGlobalMouseDown);\n ownerDocument.removeEventListener('mouseup', handleGlobalMouseUp);\n }\n\n if (inputElement) {\n inputElement.removeEventListener('input', handleInput);\n }\n };\n };\n\n if (!isValidElement(trigger)) {\n if (isSearchable) {\n trigger = (\n <input\n aria-controls={bodyId}\n aria-expanded={isOpen}\n aria-haspopup={popupRole}\n autoComplete=\"off\"\n className=\"uktdropdown-trigger\"\n defaultValue={value ?? ''}\n disabled={disabled}\n name={name}\n onFocus={() => setIsOpen(true)}\n placeholder={placeholder}\n ref={inputElementRef}\n tabIndex={tabIndex}\n type=\"text\"\n />\n );\n } else {\n trigger = (\n <button\n aria-controls={bodyId}\n aria-expanded={isOpen}\n aria-haspopup={popupRole}\n className=\"uktdropdown-trigger\"\n tabIndex={0}\n type=\"button\"\n >\n {trigger}\n </button>\n );\n }\n } else {\n // For a consumer-provided trigger, add ARIA props (letting the consumer\n // override by specifying their own).\n const triggerProps = trigger.props as Record<string, unknown>;\n trigger = cloneElement(trigger as ReactElement<Record<string, unknown>>, {\n 'aria-controls': triggerProps['aria-controls'] ?? bodyId,\n 'aria-expanded': triggerProps['aria-expanded'] ?? isOpen,\n 'aria-haspopup': triggerProps['aria-haspopup'] ?? popupRole,\n });\n }\n\n if (label != null) {\n trigger = (\n <label className=\"uktdropdown-label\">\n <div className=\"uktdropdown-label-text\">{label}</div>\n {trigger}\n </label>\n );\n }\n\n const style = {\n ...styleFromProps,\n ...(minHeightBody != null && minHeightBody > 0\n ? { '--uktdd-body-min-height': `${minHeightBody}px` }\n : null),\n ...(minWidthBody != null && minWidthBody > 0\n ? { '--uktdd-body-min-width': `${minWidthBody}px` }\n : null),\n };\n\n return (\n <Fragment>\n <style href=\"@acusti/dropdown/Dropdown\" precedence=\"medium\">\n {styles}\n </style>\n <div\n className={clsx('uktdropdown', className, {\n disabled,\n 'is-open': isOpen,\n 'is-searchable': isSearchable,\n })}\n onClick={onClick}\n onMouseDown={handleMouseDown}\n onMouseMove={handleMouseMove}\n onMouseOut={handleMouseOut}\n onMouseOver={handleMouseOver}\n onMouseUp={handleMouseUp}\n ref={handleRef}\n style={style}\n >\n {trigger}\n {/* TODO next version of Dropdown should use <Activity> for body https://react.dev/reference/react/Activity */}\n {isOpen ? (\n <div\n className={clsx('uktdropdown-body', {\n 'has-items': hasItems,\n })}\n id={bodyId}\n role={popupRole}\n >\n <div className=\"uktdropdown-content\">\n {childrenCount > 1\n ? (children as ChildrenTuple)[1]\n : children}\n </div>\n </div>\n ) : null}\n </div>\n </Fragment>\n );\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,46 +1,51 @@
1
1
  {
2
2
  "name": "@acusti/dropdown",
3
- "version": "0.55.0",
4
- "type": "module",
5
- "sideEffects": false,
6
- "exports": "./dist/Dropdown.js",
7
- "main": "./dist/Dropdown.js",
8
- "types": "./dist/Dropdown.d.ts",
9
- "files": [
10
- "dist"
11
- ],
3
+ "version": "0.56.0",
12
4
  "description": "React component that renders a dropdown with a trigger and supports searching, keyboard access, and more",
13
5
  "keywords": [
14
- "react",
15
- "react-component",
16
- "dropdown",
17
- "menu",
18
- "combobox",
19
- "search",
20
- "typeahead",
21
6
  "a11y",
22
7
  "accessibility",
8
+ "combobox",
9
+ "dropdown",
23
10
  "key-navigation",
11
+ "menu",
12
+ "react",
13
+ "react-component",
14
+ "search",
24
15
  "ssr",
25
- "typescript",
26
- "ts"
16
+ "ts",
17
+ "typeahead",
18
+ "typescript"
27
19
  ],
28
- "scripts": {
29
- "test": "vitest",
30
- "build": "vite build",
31
- "tsc": "tsc --noEmit"
20
+ "homepage": "https://github.com/acusti/uikit/tree/main/packages/dropdown#readme",
21
+ "bugs": {
22
+ "url": "https://github.com/acusti/uikit/issues"
32
23
  },
24
+ "license": "Unlicense",
25
+ "author": "andrew patton <andrew@acusti.ca> (https://www.acusti.ca)",
33
26
  "repository": {
34
27
  "type": "git",
35
28
  "url": "https://github.com/acusti/uikit.git",
36
29
  "directory": "packages/dropdown"
37
30
  },
38
- "author": "andrew patton <andrew@acusti.ca> (https://www.acusti.ca)",
39
- "license": "Unlicense",
40
- "bugs": {
41
- "url": "https://github.com/acusti/uikit/issues"
31
+ "files": [
32
+ "dist"
33
+ ],
34
+ "type": "module",
35
+ "sideEffects": false,
36
+ "main": "./dist/Dropdown.js",
37
+ "types": "./dist/Dropdown.d.ts",
38
+ "exports": "./dist/Dropdown.js",
39
+ "scripts": {
40
+ "test": "vitest",
41
+ "build": "vite build",
42
+ "tsc": "tsc --noEmit"
43
+ },
44
+ "dependencies": {
45
+ "@acusti/matchmaking": "^0.10.0",
46
+ "@acusti/use-keyboard-events": "^0.11.0",
47
+ "clsx": "^2"
42
48
  },
43
- "homepage": "https://github.com/acusti/uikit/tree/main/packages/dropdown#readme",
44
49
  "devDependencies": {
45
50
  "@testing-library/dom": "^10.4.1",
46
51
  "@testing-library/react": "^16.3.2",
@@ -56,11 +61,6 @@
56
61
  "vite": "^8.0.0-0",
57
62
  "vitest": "^4"
58
63
  },
59
- "dependencies": {
60
- "@acusti/matchmaking": "^0.10.0",
61
- "@acusti/use-keyboard-events": "^0.11.0",
62
- "clsx": "^2"
63
- },
64
64
  "peerDependencies": {
65
65
  "react": "^19 || ~0.0.0-experimental < 0.0.0-f",
66
66
  "react-dom": "^19 || ~0.0.0-experimental < 0.0.0-f"