@acusti/dropdown 1.1.0 → 1.2.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 +19 -6
- package/dist/Dropdown.d.ts +2 -1
- package/dist/Dropdown.js +10 -12
- package/dist/Dropdown.js.map +1 -1
- package/dist/helpers.d.ts +2 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -325,7 +325,8 @@ type Props = {
|
|
|
325
325
|
* multi-select. Defaults to !hasItems: a menu closes on submit, while a
|
|
326
326
|
* hasItems={false} dialog stays open. In a hasItems={false} dropdown, a
|
|
327
327
|
* submit is a form in the body being submitted, or Enter in a
|
|
328
|
-
* single-line input
|
|
328
|
+
* single-line input that appears in the body with no form or in the
|
|
329
|
+
* trigger.
|
|
329
330
|
*/
|
|
330
331
|
keepOpenOnSubmit?: boolean;
|
|
331
332
|
/**
|
|
@@ -726,12 +727,17 @@ while it’s open, as when it opened on hover. Escape closes the dropdown
|
|
|
726
727
|
unless focus is in a text field (a text input, a textarea, or an editable
|
|
727
728
|
element). On the trigger, Space and Enter open the dropdown and, unless
|
|
728
729
|
focus is in a text field or a checkbox there, close it again, as a click
|
|
729
|
-
there does.
|
|
730
|
+
there does. Once it is open, Enter in a textarea or an editable element
|
|
731
|
+
used as the trigger adds a line break there. Enter in a single-line input
|
|
732
|
+
used as the trigger is a submit, whether or not a form owns it: the
|
|
733
|
+
dropdown takes the key, so a form around the trigger isn’t submitted from
|
|
734
|
+
that input while the dropdown is open.
|
|
730
735
|
|
|
731
736
|
A `hasItems={false}` dropdown stays open until it is dismissed. Pass
|
|
732
737
|
`keepOpenOnSubmit={false}` to close it when its content is submitted. A
|
|
733
738
|
submit is a form in the body being submitted, by Enter in one of its inputs
|
|
734
|
-
or by its submit button, or Enter in a single-line input
|
|
739
|
+
or by its submit button, or Enter in a single-line input, either one in the
|
|
740
|
+
body that no form owns or one used as the trigger:
|
|
735
741
|
|
|
736
742
|
```tsx
|
|
737
743
|
<Dropdown hasItems={false} keepOpenOnSubmit={false}>
|
|
@@ -753,9 +759,9 @@ empty. To keep it open after a submit that your own checks reject, call
|
|
|
753
759
|
check that finishes later, such as a server round trip or a form library
|
|
754
760
|
that validates asynchronously, can’t keep it open.
|
|
755
761
|
|
|
756
|
-
Enter in an input
|
|
757
|
-
not when a handler has prevented the key, as a combobox
|
|
758
|
-
option, and not when it commits an IME composition.
|
|
762
|
+
Enter in such an input, in the body or the trigger, counts the way a form
|
|
763
|
+
would count it: not when a handler has prevented the key, as a combobox
|
|
764
|
+
does to pick an option, and not when it commits an IME composition.
|
|
759
765
|
|
|
760
766
|
When a submit closes the dropdown while focus is in its body, focus returns
|
|
761
767
|
to the trigger, as it does on Escape.
|
|
@@ -1330,6 +1336,13 @@ highlight into it.
|
|
|
1330
1336
|
input, or one inside a custom trigger), where they move the caret instead
|
|
1331
1337
|
- **Type characters**: Jump to the best-matching item in the current level
|
|
1332
1338
|
|
|
1339
|
+
While text is being composed with an IME, in a searchable dropdown’s input
|
|
1340
|
+
or a text field in a custom trigger, the dropdown ignores every keydown
|
|
1341
|
+
that the browser reports as part of the composition. With a Japanese IME,
|
|
1342
|
+
the Enter that commits the text doesn’t submit (the next Enter is an
|
|
1343
|
+
ordinary one), and the arrow keys and Escape don’t move the highlight or
|
|
1344
|
+
close the dropdown. Other IMEs can report their keys differently.
|
|
1345
|
+
|
|
1333
1346
|
For accessibility, the component focuses on semantic HTML structure and
|
|
1334
1347
|
keyboard navigation. It works best when you use appropriate HTML elements
|
|
1335
1348
|
in your dropdown content (like `<ul>` and `<li>` for lists, `<button>`
|
package/dist/Dropdown.d.ts
CHANGED
|
@@ -101,7 +101,8 @@ export type Props = {
|
|
|
101
101
|
* multi-select. Defaults to !hasItems: a menu closes on submit, while a
|
|
102
102
|
* hasItems={false} dialog stays open. In a hasItems={false} dropdown, a
|
|
103
103
|
* submit is a form in the body being submitted, or Enter in a
|
|
104
|
-
* single-line input
|
|
104
|
+
* single-line input that appears in the body with no form or in the
|
|
105
|
+
* trigger.
|
|
105
106
|
*/
|
|
106
107
|
keepOpenOnSubmit?: boolean;
|
|
107
108
|
/**
|
package/dist/Dropdown.js
CHANGED
|
@@ -4,14 +4,12 @@ import clsx from "clsx";
|
|
|
4
4
|
import { Children, Fragment, cloneElement, createContext, isValidElement, useContext, useEffect, useEffectEvent, useId, useLayoutEffect, useReducer, useRef, useState } from "react";
|
|
5
5
|
import { getBestMatch } from "@acusti/matchmaking";
|
|
6
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
-
|
|
7
|
+
// src/context.ts
|
|
8
8
|
var DropdownContext = createContext(null);
|
|
9
9
|
var MenubarContext = createContext(null);
|
|
10
|
-
|
|
11
|
-
//#region src/Dropdown.css?inline
|
|
10
|
+
// src/Dropdown.css?inline
|
|
12
11
|
var Dropdown_default = ":root{--uktdd-font-family:system-ui, Segoe UI, Roboto, Oxygen-Sans, Ubuntu, Cantarell, Helvetica Neue, Helvetica, Arial, sans-serif;--uktdd-color-scheme:inherit;--uktdd-body-bg-color:Canvas;--uktdd-body-bg-color-hover:Highlight;--uktdd-body-color-hover:HighlightText;--uktdd-body-bg-color-selected:color-mix(in oklab, currentColor 6%, transparent);--uktdd-body-box-shadow:0 8px 18px #00000040;--uktdd-body-border-color:color-mix(in oklab, currentColor 15%, transparent);--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-block-start:.5em;--uktdd-body-pad-block-end:.5em;--uktdd-body-pad-inline-start:.6875em;--uktdd-body-pad-inline-end:.6875em;--uktdd-body-min-width:min(50px, 100%);--uktdd-body-position-area:block-end span-inline-end;--uktdd-body-position-try-fallback-1:--uktdd-top-start;--uktdd-body-position-try-fallback-2:--uktdd-bottom-end;--uktdd-body-fill-fallbacks:--uktdd-fill-bottom, --uktdd-fill-top;--uktdd-body-gap:0px;--uktdd-body-color:CanvasText;--uktdd-body-color-path:currentColor;--uktdd-label-gap:.625em;--uktdd-submenu-position-area:inline-end span-block-end;--uktdd-submenu-position-try-fallback:--uktdd-submenu-inline-start;--uktdd-submenu-fill-fallbacks:--uktdd-submenu-fill, --uktdd-submenu-fill flip-inline;--uktdd-submenu-gap:0px;--uktdd-menubar-trigger-bg-color-active:color-mix(in oklab, currentColor 12%, transparent)}.uktdropdown,.uktdropdown-trigger{font-family:var(--uktdd-font-family)}.uktdropdown{anchor-scope:--uktdd-anchor;width:max-content}.uktdropdown.is-disabled{pointer-events:none}.uktdropdown>*{cursor:default}.uktdropdown>:first-child{anchor-name:--uktdd-anchor}.uktdropdown-label{align-items:center;gap:var(--uktdd-label-gap);display:flex}.uktdropdown-body{box-sizing:border-box;position-anchor:--uktdd-anchor;position-area:var(--uktdd-body-position-area);position-try-fallbacks:var(--uktdd-body-position-try-fallback-1), var(--uktdd-body-position-try-fallback-2), var(--uktdd-body-fill-fallbacks);min-block-size:min(var(--uktdd-body-min-height), var(--uktdd-body-max-height));max-block-size:var(--uktdd-body-max-height);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;color:var(--uktdd-body-color);color-scheme:var(--uktdd-color-scheme);background-color:var(--uktdd-body-bg-color);box-shadow:var(--uktdd-body-box-shadow);flex-direction:column;display:flex;position:fixed;overflow:hidden}.uktdropdown-body.has-items{-webkit-user-select:none;user-select:none}.uktdropdown-body [aria-selected=true]{background-color:var(--uktdd-body-bg-color-selected)}@media (forced-colors:active){.uktdropdown-body [aria-selected=true]{outline-offset:-2px;outline:2px solid}}.uktdropdown-body [data-ukt-active]{background-color:var(--uktdd-body-bg-color-hover);color:var(--uktdd-body-color-hover)}:is(.uktdropdown-body [data-ukt-active]:has([data-ukt-submenu] [data-ukt-active]),.uktdropdown-body [data-ukt-active]:has([data-ukt-submenu]:hover)){background-color:var(--uktdd-body-bg-color-path,color-mix(in oklab, var(--uktdd-body-color) 12%, var(--uktdd-body-bg-color)));color:var(--uktdd-body-color-path)}.uktdropdown-body [data-ukt-item][aria-disabled=true]{opacity:.5;pointer-events:none}.uktdropdown-body [data-ukt-item]{anchor-scope:--uktdd-submenu-anchor}.uktdropdown-body :is([data-ukt-item],[data-ukt-value])[aria-haspopup=menu]{padding-inline-end:2em;position:relative}.uktdropdown-body :is([data-ukt-item],[data-ukt-value])[aria-haspopup=menu]:after{content:\"\";border-block-start:.14em solid;border-inline-end:.14em solid;block-size:.3em;inline-size:.3em;position:absolute;inset-block-start:50%;inset-inline-end:.9em;translate:0 -50%;rotate:45deg}.uktdropdown-body :is([data-ukt-item],[data-ukt-value])[aria-haspopup=menu]:is(:lang(ae),:lang(ar),:lang(arc),:lang(bcc),:lang(bqi),:lang(ckb),:lang(dv),:lang(fa),:lang(glk),:lang(he),:lang(ku),:lang(mzn),:lang(nqo),:lang(pnb),:lang(ps),:lang(sd),:lang(ug),:lang(ur),:lang(yi)):after{rotate:-45deg}.uktdropdown-body [data-ukt-item][aria-expanded=true]{anchor-name:--uktdd-submenu-anchor}.uktdropdown-body [data-ukt-submenu]:not([popover]){display:none}.uktdropdown-body [data-ukt-submenu]{box-sizing:border-box;border:1px solid var(--uktdd-body-border-color);block-size:auto;color:var(--uktdd-body-color);position-anchor:--uktdd-submenu-anchor;position-area:var(--uktdd-submenu-position-area);position-try-fallbacks:var(--uktdd-submenu-position-try-fallback), var(--uktdd-submenu-fill-fallbacks);z-index:2;margin-block:0;margin-inline:var(--uktdd-submenu-gap);--uktdd-body-gap:0px;padding-block:var(--uktdd-body-pad-block-start) var(--uktdd-body-pad-block-end);padding-inline:var(--uktdd-body-pad-inline-start) var(--uktdd-body-pad-inline-end);inline-size:max-content;max-inline-size:var(--uktdd-body-max-width);min-block-size:min(var(--uktdd-body-min-height), var(--uktdd-body-max-height));max-block-size:var(--uktdd-body-max-height);overscroll-behavior:contain;background-color:var(--uktdd-body-bg-color);box-shadow:var(--uktdd-body-box-shadow);list-style:none;position:fixed;inset:auto;overflow:auto}div.uktdropdown-body{block-size:auto;margin-block:var(--uktdd-body-gap);border:1px solid var(--uktdd-body-border-color);margin-inline:0;padding:0;inset:auto}.uktmenubar{width:max-content;font-family:var(--uktdd-font-family);align-items:stretch;display:flex}.uktmenubar .uktdropdown.is-open .uktdropdown-trigger{box-shadow:inset 0 0 0 100vmax var(--uktdd-menubar-trigger-bg-color-active)}.uktdropdown-content{box-sizing:border-box;overscroll-behavior:contain;min-block-size:0;padding-block:var(--uktdd-body-pad-block-start) var(--uktdd-body-pad-block-end);padding-inline:var(--uktdd-body-pad-inline-start) var(--uktdd-body-pad-inline-end);overflow:auto}@position-try --uktdd-noop{}@position-try --uktdd-top-start{position-area:block-start span-inline-end}@position-try --uktdd-bottom-start{position-area:block-end span-inline-end}@position-try --uktdd-bottom-end{position-area:block-end span-inline-start}@position-try --uktdd-top-end{position-area:block-start span-inline-start}@position-try --uktdd-submenu-inline-start{position-area:inline-start span-block-end}@position-try --uktdd-fill-bottom{position-area:block-end;block-size:calc(100% - var(--uktdd-body-gap) * 2);min-block-size:min(var(--uktdd-body-min-height), var(--uktdd-body-max-height), calc((100dvb - anchor-size(block)) / 2 - var(--uktdd-body-gap) * 2));justify-self:anchor-center}@position-try --uktdd-fill-top{position-area:block-start;block-size:calc(100% - var(--uktdd-body-gap) * 2);min-block-size:min(var(--uktdd-body-min-height), var(--uktdd-body-max-height), calc((100dvb - anchor-size(block)) / 2 - var(--uktdd-body-gap) * 2));justify-self:anchor-center}@position-try --uktdd-fill{block-size:calc(100% - var(--uktdd-body-gap) * 2)}@position-try --uktdd-submenu-fill{position-area:inline-end;block-size:calc(100% - var(--uktdd-body-gap) * 2);align-self:anchor-center}@position-try --uktdd-fill-cover{position-area:span-all span-inline-end;block-size:calc(100% - var(--uktdd-body-gap) * 2);align-self:anchor-center}";
|
|
13
|
-
|
|
14
|
-
//#region src/helpers.ts
|
|
12
|
+
// src/helpers.ts
|
|
15
13
|
var BODY_SELECTOR = ".uktdropdown-body";
|
|
16
14
|
var ITEM_SELECTOR = "[data-ukt-item], [data-ukt-value]";
|
|
17
15
|
var SUBMENU_SELECTOR = "[data-ukt-submenu]";
|
|
@@ -28,7 +26,9 @@ var isFormlessTextInput = (element) => {
|
|
|
28
26
|
const { form, type } = element;
|
|
29
27
|
return form == null && !NON_TEXT_INPUT_TYPES.includes(type);
|
|
30
28
|
};
|
|
31
|
-
var
|
|
29
|
+
var isMultilineTextField = (element) => element.tagName === "TEXTAREA" || element.isContentEditable;
|
|
30
|
+
var isIMEKeyEvent = (event) => event.isComposing || event.keyCode === 229;
|
|
31
|
+
var isSubmitKey = (event) => event.key === "Enter" && !event.defaultPrevented;
|
|
32
32
|
var getLevelRoot = (element) => element.closest(SUBMENU_SELECTOR);
|
|
33
33
|
var getSubmenuOfItem = (item) => {
|
|
34
34
|
const submenu = item.querySelector(SUBMENU_SELECTOR);
|
|
@@ -317,8 +317,7 @@ var isPointInTriangle = (p, a, b, c) => {
|
|
|
317
317
|
const d3 = cross(p, c, a);
|
|
318
318
|
return !((d1 < 0 || d2 < 0 || d3 < 0) && (d1 > 0 || d2 > 0 || d3 > 0));
|
|
319
319
|
};
|
|
320
|
-
|
|
321
|
-
//#region src/Menubar.tsx
|
|
320
|
+
// src/Menubar.tsx
|
|
322
321
|
var compareDocumentOrder = (a, b) => {
|
|
323
322
|
if (a.element === b.element) return 0;
|
|
324
323
|
const position = a.element.compareDocumentPosition(b.element);
|
|
@@ -519,8 +518,7 @@ function _temp2(member_3) {
|
|
|
519
518
|
function _temp(count) {
|
|
520
519
|
return count + 1;
|
|
521
520
|
}
|
|
522
|
-
|
|
523
|
-
//#region src/Dropdown.tsx
|
|
521
|
+
// src/Dropdown.tsx
|
|
524
522
|
var CHILDREN_ERROR = "Dropdown requires either 1 child (the dropdown body) or 2 children: the dropdown trigger and the dropdown body.";
|
|
525
523
|
var CLICKABLE_SELECTOR = "button, a[href], input[type=\"button\"], input[type=\"submit\"]";
|
|
526
524
|
var TEXT_INPUT_SELECTOR = `input${NON_TEXT_INPUT_TYPES.map((type) => `:not([type=${type}])`).join("")},textarea`;
|
|
@@ -1259,6 +1257,7 @@ function RootDropdown(t0) {
|
|
|
1259
1257
|
const { altKey, ctrlKey, key: key_0, metaKey } = event_7;
|
|
1260
1258
|
const eventTarget_2 = event_7.target;
|
|
1261
1259
|
if (!dropdownElement) return;
|
|
1260
|
+
if (isIMEKeyEvent(event_7)) return;
|
|
1262
1261
|
const onEventHandled = () => {
|
|
1263
1262
|
event_7.stopPropagation();
|
|
1264
1263
|
event_7.preventDefault();
|
|
@@ -1311,7 +1310,7 @@ function RootDropdown(t0) {
|
|
|
1311
1310
|
if (!event_7.repeat) closeDropdown();
|
|
1312
1311
|
return;
|
|
1313
1312
|
}
|
|
1314
|
-
if (
|
|
1313
|
+
if (isMultilineTextField(eventTarget_2) || !isSubmitKey(event_7)) return;
|
|
1315
1314
|
} else if (isTargetUsingKeyEvents || !eventTarget_2.contains(dropdownElement)) return;
|
|
1316
1315
|
}
|
|
1317
1316
|
if (key_0 === "Enter" || key_0 === " " && !inputElementRef.current) {
|
|
@@ -1885,7 +1884,6 @@ function SubmenuDropdown(props) {
|
|
|
1885
1884
|
} else t5 = $[20];
|
|
1886
1885
|
return t5;
|
|
1887
1886
|
}
|
|
1888
|
-
//#endregion
|
|
1889
1887
|
export { Menubar, Dropdown as default };
|
|
1890
1888
|
|
|
1891
1889
|
//# sourceMappingURL=Dropdown.js.map
|