@pixum/combobox 5.10.4-alpha.22 → 5.10.4-alpha.24
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/lib/ComboBox.d.ts +28 -6
- package/lib/ComboBox.js +177 -78
- package/lib/ComboBox.js.map +1 -1
- package/lib/ComboBox.module.css +1 -1
- package/lib/hooks/index.d.ts +2 -0
- package/lib/hooks/index.js +2 -0
- package/lib/hooks/index.js.map +1 -1
- package/lib/hooks/useComboBox.js +1 -0
- package/lib/hooks/useComboBox.js.map +1 -1
- package/lib/hooks/useComboBoxFocus.js +1 -0
- package/lib/hooks/useComboBoxFocus.js.map +1 -1
- package/lib/hooks/useIsDesktopScreenWidth.d.ts +5 -0
- package/lib/hooks/useIsDesktopScreenWidth.js +34 -24
- package/lib/hooks/useIsDesktopScreenWidth.js.map +1 -1
- package/lib/index.d.ts +4 -4
- package/lib/index.js +2 -3
- package/lib/index.js.map +1 -1
- package/lib/partials/ComboBoxOptions.d.ts +15 -4
- package/lib/partials/ComboBoxOptions.js +25 -21
- package/lib/partials/ComboBoxOptions.js.map +1 -1
- package/lib/partials/ComboBoxOptionsItems.d.ts +32 -17
- package/lib/partials/ComboBoxOptionsItems.js +46 -14
- package/lib/partials/ComboBoxOptionsItems.js.map +1 -1
- package/lib/partials/ComboBoxOptionsSlot.d.ts +17 -16
- package/lib/partials/ComboBoxOptionsSlot.js +26 -11
- package/lib/partials/ComboBoxOptionsSlot.js.map +1 -1
- package/lib/partials/index.d.ts +2 -1
- package/lib/partials/index.js +2 -1
- package/lib/partials/index.js.map +1 -1
- package/lib/types.d.ts +122 -51
- package/lib/utils/index.d.ts +1 -2
- package/lib/utils/index.js +1 -2
- package/lib/utils/index.js.map +1 -1
- package/lib/utils/options.d.ts +38 -1
- package/lib/utils/options.js +62 -2
- package/lib/utils/options.js.map +1 -1
- package/package.json +8 -8
|
@@ -1,29 +1,33 @@
|
|
|
1
|
-
import { jsx as _jsx,
|
|
2
|
-
import { useEffect } from 'react';
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
2
|
import Menu from '@pixum/menu';
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
3
|
+
import Text, { TEXT_VARIANT } from '@pixum/text';
|
|
4
|
+
import clsx from 'clsx';
|
|
5
|
+
import { groupOptions } from '../utils';
|
|
6
|
+
import { ComboBoxOptionsGroup } from './ComboBoxOptionsGroup';
|
|
7
|
+
import styles from '../ComboBox.module.css';
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
9
|
+
* Renders the options panel of the ComboBox.
|
|
10
|
+
*
|
|
11
|
+
* The panel is split in two: the `Menu` provides the visible box, the element
|
|
12
|
+
* inside it carries the `listbox` role and is the only part that scrolls. That
|
|
13
|
+
* keeps `optionDetails` a real footer - it stays visible without
|
|
14
|
+
* `position: sticky` and can no longer cover the active option - and it keeps
|
|
15
|
+
* the listbox free of anything that is not an option or a group, as ARIA
|
|
16
|
+
* requires.
|
|
17
|
+
*
|
|
18
|
+
* Flat and grouped options share one render path: the options arrive already
|
|
19
|
+
* normalised, `groupOptions` only splits them into their visual groups again.
|
|
20
|
+
* The listbox is not focusable - the focus stays in the input field, the active
|
|
21
|
+
* option is announced through `aria-activedescendant`.
|
|
11
22
|
*
|
|
12
23
|
* @param props - The props for the ComboBoxOptions component
|
|
13
|
-
* @returns
|
|
24
|
+
* @returns The options panel
|
|
14
25
|
*/
|
|
15
|
-
export function ComboBoxOptions({ options,
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
// Wait for next browser frame to ensure DOM is fully rendered
|
|
21
|
-
const frameId = requestAnimationFrame(() => {
|
|
22
|
-
scrollOptionToViewport(isDesktop);
|
|
23
|
-
});
|
|
24
|
-
return () => cancelAnimationFrame(frameId);
|
|
25
|
-
}, [isDesktop, selectedOption]);
|
|
26
|
-
return (_jsxs(Menu, { className: "combobox__options scrollable", "data-tappable": "true", children: [optionsWithoutGroup ? (_jsx(ComboBoxOptionsItems, { items: options, selectedOption: selectedOption, onClick: onClick, leadingType: leadingType })) : (_jsx(_Fragment, { children: optionsWithGroup.map(([group, items]) => (_jsx(ComboxBoxOptionsWithGrouping, { group: group, items: items, selectedOption: selectedOption, onClick: onClick, leadingType: leadingType }, `combobox__options-group-${group}`))) })), optionDetails && (_jsx("div", { className: "combobox__option-details text--caption", children: optionDetails }))] }));
|
|
26
|
+
export function ComboBoxOptions({ options, listboxAriaProps, selectedValues, activeOptionId, leadingType, optionDetails, onOptionClick, }) {
|
|
27
|
+
return (_jsxs(Menu, { className: styles.panel, "data-tappable": "true", children: [_jsx("div", Object.assign({ className: clsx(styles.options, 'scrollable'), tabIndex: -1 }, listboxAriaProps, { children: groupOptions(options).map(group => {
|
|
28
|
+
var _a;
|
|
29
|
+
return (_jsx(ComboBoxOptionsGroup, { group: group.group, options: group.options, selectedValues: selectedValues, activeOptionId: activeOptionId, leadingType: leadingType, onOptionClick: onOptionClick }, `combobox__options-group-${(_a = group.group) !== null && _a !== void 0 ? _a : 'default'}`));
|
|
30
|
+
}) })), optionDetails && (_jsx(Text, { variant: TEXT_VARIANT.CAPTION, className: styles.optionDetails, children: optionDetails }))] }));
|
|
27
31
|
}
|
|
28
32
|
export default ComboBoxOptions;
|
|
29
33
|
//# sourceMappingURL=ComboBoxOptions.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComboBoxOptions.js","sourceRoot":"","sources":["../../src/partials/ComboBoxOptions.tsx"],"names":[],"mappings":";AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"ComboBoxOptions.js","sourceRoot":"","sources":["../../src/partials/ComboBoxOptions.tsx"],"names":[],"mappings":";AAAA,OAAO,IAAI,MAAM,aAAa,CAAA;AAC9B,OAAO,IAAI,EAAE,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAChD,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AACvC,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAC7D,OAAO,MAAM,MAAM,wBAAwB,CAAA;AAG3C;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,eAAe,CAAC,EAC9B,OAAO,EACP,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,WAAW,EACX,aAAa,EACb,aAAa,GACQ;IACrB,OAAO,CACL,MAAC,IAAI,IAAC,SAAS,EAAE,MAAM,CAAC,KAAK,mBAAgB,MAAM,aACjD,4BACE,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,YAAY,CAAC,EAC7C,QAAQ,EAAE,CAAC,CAAC,IACR,gBAAgB,cAEnB,YAAY,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;;oBAAC,OAAA,CAClC,KAAC,oBAAoB,IAEnB,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,OAAO,EAAE,KAAK,CAAC,OAAO,EACtB,cAAc,EAAE,cAAc,EAC9B,cAAc,EAAE,cAAc,EAC9B,WAAW,EAAE,WAAW,EACxB,aAAa,EAAE,aAAa,IANvB,2BAA2B,MAAA,KAAK,CAAC,KAAK,mCAAI,SAAS,EAAE,CAO1D,CACH,CAAA;iBAAA,CAAC,IACE,EAEL,aAAa,IAAI,CAChB,KAAC,IAAI,IAAC,OAAO,EAAE,YAAY,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,aAAa,YACjE,aAAa,GACT,CACR,IACI,CACR,CAAA;AACH,CAAC;AAED,eAAe,eAAe,CAAA"}
|
|
@@ -1,24 +1,39 @@
|
|
|
1
1
|
import { LeadingType } from '@pixum/menu-item';
|
|
2
|
-
import type {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
/** Callback fired when an option is clicked */
|
|
12
|
-
onClick?: (value: string) => void;
|
|
13
|
-
/** Type of leading element to display (icon, avatar, etc.) */
|
|
2
|
+
import type { ComboBoxOption } from '../types';
|
|
3
|
+
export interface ComboBoxOptionsItemsProps {
|
|
4
|
+
/** Normalised options to render. */
|
|
5
|
+
options: ComboBoxOption[];
|
|
6
|
+
/** Values that are currently selected. */
|
|
7
|
+
selectedValues: string[];
|
|
8
|
+
/** DOM id of the active option (`aria-activedescendant`). */
|
|
9
|
+
activeOptionId?: string;
|
|
10
|
+
/** Type of the leading element, e.g. a checkbox for multi select. */
|
|
14
11
|
leadingType?: LeadingType;
|
|
12
|
+
/** Called with the value of the clicked option. */
|
|
13
|
+
onOptionClick: (value: string) => void;
|
|
15
14
|
}
|
|
16
15
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
16
|
+
* Renders the individual options.
|
|
17
|
+
*
|
|
18
|
+
* The options are deliberately not focusable: the focus stays in the input
|
|
19
|
+
* field and the highlight is driven by `aria-activedescendant`. Checkbox
|
|
20
|
+
* options are ordinary options with `aria-selected` - inside a listbox that is
|
|
21
|
+
* the state screen readers announce, and it keeps mouse and keyboard selection
|
|
22
|
+
* on exactly the same code path.
|
|
23
|
+
*
|
|
24
|
+
* An option is a `MenuItemProps` object, so everything except the ComboBox
|
|
25
|
+
* specific `key` and `disabled` is spread onto the `MenuItem` unchanged.
|
|
26
|
+
* Consumers that pass further MenuItem props keep working without the ComboBox
|
|
27
|
+
* having to know about them; only `selected`, `tabIndex` and the keyboard
|
|
28
|
+
* handling are owned by the ComboBox and therefore not overridable.
|
|
29
|
+
*
|
|
30
|
+
* Styling hooks: every option carries its state as a data attribute
|
|
31
|
+
* (`data-selected`, `data-active`, `data-disabled`), so consumers can style
|
|
32
|
+
* options without knowing the hashed module class names. The selection state is
|
|
33
|
+
* left to `MenuItem` itself - the component does not add a `selected` class of
|
|
34
|
+
* its own, which would be impossible to override from the outside.
|
|
19
35
|
*
|
|
20
36
|
* @param props - The props for the ComboBoxOptionsItems component
|
|
21
|
-
* @returns A list of
|
|
37
|
+
* @returns A list of selectable options
|
|
22
38
|
*/
|
|
23
|
-
export declare function ComboBoxOptionsItems({
|
|
24
|
-
export {};
|
|
39
|
+
export declare function ComboBoxOptionsItems({ options, selectedValues, activeOptionId, leadingType, onOptionClick, }: ComboBoxOptionsItemsProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,24 +1,56 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import MenuItem from '@pixum/menu-item';
|
|
2
|
+
import MenuItem, { LeadingType } from '@pixum/menu-item';
|
|
3
3
|
import clsx from 'clsx';
|
|
4
|
+
import { toMenuItemProps } from '../utils';
|
|
5
|
+
import styles from '../ComboBox.module.css';
|
|
4
6
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
+
* Renders the individual options.
|
|
8
|
+
*
|
|
9
|
+
* The options are deliberately not focusable: the focus stays in the input
|
|
10
|
+
* field and the highlight is driven by `aria-activedescendant`. Checkbox
|
|
11
|
+
* options are ordinary options with `aria-selected` - inside a listbox that is
|
|
12
|
+
* the state screen readers announce, and it keeps mouse and keyboard selection
|
|
13
|
+
* on exactly the same code path.
|
|
14
|
+
*
|
|
15
|
+
* An option is a `MenuItemProps` object, so everything except the ComboBox
|
|
16
|
+
* specific `key` and `disabled` is spread onto the `MenuItem` unchanged.
|
|
17
|
+
* Consumers that pass further MenuItem props keep working without the ComboBox
|
|
18
|
+
* having to know about them; only `selected`, `tabIndex` and the keyboard
|
|
19
|
+
* handling are owned by the ComboBox and therefore not overridable.
|
|
20
|
+
*
|
|
21
|
+
* Styling hooks: every option carries its state as a data attribute
|
|
22
|
+
* (`data-selected`, `data-active`, `data-disabled`), so consumers can style
|
|
23
|
+
* options without knowing the hashed module class names. The selection state is
|
|
24
|
+
* left to `MenuItem` itself - the component does not add a `selected` class of
|
|
25
|
+
* its own, which would be impossible to override from the outside.
|
|
7
26
|
*
|
|
8
27
|
* @param props - The props for the ComboBoxOptionsItems component
|
|
9
|
-
* @returns A list of
|
|
28
|
+
* @returns A list of selectable options
|
|
10
29
|
*/
|
|
11
|
-
export function ComboBoxOptionsItems({
|
|
12
|
-
|
|
30
|
+
export function ComboBoxOptionsItems({ options, selectedValues, activeOptionId, leadingType, onOptionClick, }) {
|
|
31
|
+
const isCheckbox = leadingType === LeadingType.CheckBox;
|
|
32
|
+
return (_jsx(_Fragment, { children: options.map(({ item, id, value, disabled }) => {
|
|
13
33
|
var _a;
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
34
|
+
const isSelected = selectedValues.includes(value);
|
|
35
|
+
const isActive = id === activeOptionId;
|
|
36
|
+
const menuItemProps = toMenuItemProps(item);
|
|
37
|
+
return (_jsx("div", { id: id, className: clsx(styles.option, isCheckbox && styles.optionCheckbox, isActive && styles.optionActive), role: "option", "aria-selected": isSelected, "aria-disabled": disabled || undefined, "data-selected": isSelected, "data-active": isActive, "data-disabled": disabled || undefined, onMouseDown: event => {
|
|
38
|
+
// Keeps the focus in the input field ...
|
|
39
|
+
event.preventDefault();
|
|
40
|
+
// ... and keeps the bottom sheet's drag handler out of it.
|
|
41
|
+
event.stopPropagation();
|
|
42
|
+
}, onPointerDown: event => event.stopPropagation(),
|
|
43
|
+
// No preventDefault on touchstart, scrolling in the sheet must work.
|
|
44
|
+
onTouchStart: event => event.stopPropagation(), onClickCapture: event => {
|
|
45
|
+
event.stopPropagation();
|
|
46
|
+
if (disabled)
|
|
47
|
+
return;
|
|
48
|
+
onOptionClick(value);
|
|
49
|
+
}, children: _jsx(MenuItem, Object.assign({}, menuItemProps, { tabIndex: -1, disableKeyboardNav: true,
|
|
50
|
+
// A leading type set on the ComboBox wins over the option's own
|
|
51
|
+
// one: it is what makes multi select look like a checkbox list.
|
|
52
|
+
leadingProps: leadingType
|
|
53
|
+
? Object.assign(Object.assign({}, menuItemProps.leadingProps), { name: value, type: leadingType }) : menuItemProps.leadingProps, selected: isSelected })) }, (_a = item.key) !== null && _a !== void 0 ? _a : `combobox-item-wrapper-${id}`));
|
|
22
54
|
}) }));
|
|
23
55
|
}
|
|
24
56
|
//# sourceMappingURL=ComboBoxOptionsItems.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComboBoxOptionsItems.js","sourceRoot":"","sources":["../../src/partials/ComboBoxOptionsItems.tsx"],"names":[],"mappings":";AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"ComboBoxOptionsItems.js","sourceRoot":"","sources":["../../src/partials/ComboBoxOptionsItems.tsx"],"names":[],"mappings":";AAAA,OAAO,QAAQ,EAAE,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AACxD,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC1C,OAAO,MAAM,MAAM,wBAAwB,CAAA;AAgB3C;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,oBAAoB,CAAC,EACnC,OAAO,EACP,cAAc,EACd,cAAc,EACd,WAAW,EACX,aAAa,GACa;IAC1B,MAAM,UAAU,GAAG,WAAW,KAAK,WAAW,CAAC,QAAQ,CAAA;IAEvD,OAAO,CACL,4BACG,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE;;YAC7C,MAAM,UAAU,GAAG,cAAc,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;YACjD,MAAM,QAAQ,GAAG,EAAE,KAAK,cAAc,CAAA;YACtC,MAAM,aAAa,GAAG,eAAe,CAAC,IAAI,CAAC,CAAA;YAE3C,OAAO,CACL,cAEE,EAAE,EAAE,EAAE,EACN,SAAS,EAAE,IAAI,CACb,MAAM,CAAC,MAAM,EACb,UAAU,IAAI,MAAM,CAAC,cAAc,EACnC,QAAQ,IAAI,MAAM,CAAC,YAAY,CAChC,EACD,IAAI,EAAC,QAAQ,mBACE,UAAU,mBACV,QAAQ,IAAI,SAAS,mBACrB,UAAU,iBACZ,QAAQ,mBACN,QAAQ,IAAI,SAAS,EACpC,WAAW,EAAE,KAAK,CAAC,EAAE;oBACnB,yCAAyC;oBACzC,KAAK,CAAC,cAAc,EAAE,CAAA;oBACtB,2DAA2D;oBAC3D,KAAK,CAAC,eAAe,EAAE,CAAA;gBACzB,CAAC,EACD,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,eAAe,EAAE;gBAC/C,qEAAqE;gBACrE,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,eAAe,EAAE,EAC9C,cAAc,EAAE,KAAK,CAAC,EAAE;oBACtB,KAAK,CAAC,eAAe,EAAE,CAAA;oBAEvB,IAAI,QAAQ;wBAAE,OAAM;oBAEpB,aAAa,CAAC,KAAK,CAAC,CAAA;gBACtB,CAAC,YAED,KAAC,QAAQ,oBACH,aAAa,IACjB,QAAQ,EAAE,CAAC,CAAC,EACZ,kBAAkB;oBAClB,gEAAgE;oBAChE,gEAAgE;oBAChE,YAAY,EACV,WAAW;wBACT,CAAC,iCACM,aAAa,CAAC,YAAY,KAC7B,IAAI,EAAE,KAAK,EACX,IAAI,EAAE,WAAW,IAErB,CAAC,CAAC,aAAa,CAAC,YAAY,EAEhC,QAAQ,EAAE,UAAU,IACpB,IA9CG,MAAA,IAAI,CAAC,GAAG,mCAAI,yBAAyB,EAAE,EAAE,CA+C1C,CACP,CAAA;QACH,CAAC,CAAC,GACD,CACJ,CAAA;AACH,CAAC"}
|
|
@@ -1,34 +1,35 @@
|
|
|
1
|
-
import type { ReactNode } from 'react';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
/** The content to render inside the options slot */
|
|
1
|
+
import type { ElementType, HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export interface ComboBoxOptionsSlotProps extends HTMLAttributes<HTMLElement> {
|
|
3
|
+
/** The content to render inside the options slot. */
|
|
5
4
|
children: ReactNode;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
tag?: 'div' | 'ul' | 'ol' | 'dl';
|
|
5
|
+
/** Element the slot renders as. */
|
|
6
|
+
tag?: Extract<ElementType, 'div' | 'ul' | 'ol' | 'dl'>;
|
|
9
7
|
}
|
|
10
8
|
/**
|
|
11
|
-
* Styled container for optionsSlot content.
|
|
9
|
+
* Styled container for `optionsSlot` content.
|
|
12
10
|
*
|
|
13
|
-
* Applies the standard ComboBox dropdown appearance
|
|
14
|
-
* border
|
|
15
|
-
*
|
|
11
|
+
* Applies the standard ComboBox dropdown appearance - background, border,
|
|
12
|
+
* border radius, box shadow and top margin - so consumers do not have to
|
|
13
|
+
* replicate it in every `optionsSlot` implementation. Every other prop
|
|
14
|
+
* (`role`, `aria-*`, ...) is forwarded, because the slot content owns its own
|
|
15
|
+
* accessibility semantics.
|
|
16
16
|
*
|
|
17
|
-
*
|
|
17
|
+
* A slot replaces the built-in options list and therefore also its keyboard
|
|
18
|
+
* navigation: content rendered here has to bring its own key handling.
|
|
18
19
|
*
|
|
19
20
|
* ```tsx
|
|
20
21
|
* import ComboBox, { ComboBoxOptionsSlot } from '@pixum/combobox'
|
|
21
22
|
*
|
|
22
23
|
* <ComboBox
|
|
23
24
|
* optionsSlot={
|
|
24
|
-
* <ComboBoxOptionsSlot>
|
|
25
|
+
* <ComboBoxOptionsSlot role="listbox" aria-label="Pickup points">
|
|
25
26
|
* <MyCustomOptionsList />
|
|
26
27
|
* </ComboBoxOptionsSlot>
|
|
27
28
|
* }
|
|
28
29
|
* />
|
|
29
30
|
* ```
|
|
30
31
|
*
|
|
31
|
-
* @param
|
|
32
|
-
* @returns A styled wrapper
|
|
32
|
+
* @param props - The props for the ComboBoxOptionsSlot component
|
|
33
|
+
* @returns A styled wrapper matching the ComboBox dropdown look
|
|
33
34
|
*/
|
|
34
|
-
export declare function ComboBoxOptionsSlot({ children, className,
|
|
35
|
+
export declare function ComboBoxOptionsSlot({ children, className, tag, ...rest }: ComboBoxOptionsSlotProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,32 +1,47 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
1
12
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import '../styles.css';
|
|
3
13
|
import Menu from '@pixum/menu';
|
|
4
14
|
import clsx from 'clsx';
|
|
15
|
+
import styles from '../ComboBox.module.css';
|
|
5
16
|
/**
|
|
6
|
-
* Styled container for optionsSlot content.
|
|
17
|
+
* Styled container for `optionsSlot` content.
|
|
7
18
|
*
|
|
8
|
-
* Applies the standard ComboBox dropdown appearance
|
|
9
|
-
* border
|
|
10
|
-
*
|
|
19
|
+
* Applies the standard ComboBox dropdown appearance - background, border,
|
|
20
|
+
* border radius, box shadow and top margin - so consumers do not have to
|
|
21
|
+
* replicate it in every `optionsSlot` implementation. Every other prop
|
|
22
|
+
* (`role`, `aria-*`, ...) is forwarded, because the slot content owns its own
|
|
23
|
+
* accessibility semantics.
|
|
11
24
|
*
|
|
12
|
-
*
|
|
25
|
+
* A slot replaces the built-in options list and therefore also its keyboard
|
|
26
|
+
* navigation: content rendered here has to bring its own key handling.
|
|
13
27
|
*
|
|
14
28
|
* ```tsx
|
|
15
29
|
* import ComboBox, { ComboBoxOptionsSlot } from '@pixum/combobox'
|
|
16
30
|
*
|
|
17
31
|
* <ComboBox
|
|
18
32
|
* optionsSlot={
|
|
19
|
-
* <ComboBoxOptionsSlot>
|
|
33
|
+
* <ComboBoxOptionsSlot role="listbox" aria-label="Pickup points">
|
|
20
34
|
* <MyCustomOptionsList />
|
|
21
35
|
* </ComboBoxOptionsSlot>
|
|
22
36
|
* }
|
|
23
37
|
* />
|
|
24
38
|
* ```
|
|
25
39
|
*
|
|
26
|
-
* @param
|
|
27
|
-
* @returns A styled wrapper
|
|
40
|
+
* @param props - The props for the ComboBoxOptionsSlot component
|
|
41
|
+
* @returns A styled wrapper matching the ComboBox dropdown look
|
|
28
42
|
*/
|
|
29
|
-
export function ComboBoxOptionsSlot(
|
|
30
|
-
|
|
43
|
+
export function ComboBoxOptionsSlot(_a) {
|
|
44
|
+
var { children, className, tag = 'ul' } = _a, rest = __rest(_a, ["children", "className", "tag"]);
|
|
45
|
+
return (_jsx(Menu, Object.assign({ tag: tag, className: clsx(styles.optionsSlot, className) }, rest, { children: children })));
|
|
31
46
|
}
|
|
32
47
|
//# sourceMappingURL=ComboBoxOptionsSlot.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComboBoxOptionsSlot.js","sourceRoot":"","sources":["../../src/partials/ComboBoxOptionsSlot.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ComboBoxOptionsSlot.js","sourceRoot":"","sources":["../../src/partials/ComboBoxOptionsSlot.tsx"],"names":[],"mappings":";;;;;;;;;;;;AACA,OAAO,IAAI,MAAM,aAAa,CAAA;AAC9B,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,MAAM,MAAM,wBAAwB,CAAA;AAU3C;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAKT;QALS,EAClC,QAAQ,EACR,SAAS,EACT,GAAG,GAAG,IAAI,OAEe,EADtB,IAAI,cAJ2B,gCAKnC,CADQ;IAEP,OAAO,CACL,KAAC,IAAI,kBAAC,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,SAAS,CAAC,IAAM,IAAI,cACrE,QAAQ,IACJ,CACR,CAAA;AACH,CAAC"}
|
package/lib/partials/index.d.ts
CHANGED
package/lib/partials/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from './ComboBoxOptions';
|
|
2
|
-
export * from './
|
|
2
|
+
export * from './ComboBoxOptionsGroup';
|
|
3
3
|
export * from './ComboBoxOptionsItems';
|
|
4
4
|
export * from './ComboBoxOptionsSlot';
|
|
5
|
+
export * from './ComboBoxNoResults';
|
|
5
6
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/partials/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/partials/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc,wBAAwB,CAAA;AACtC,cAAc,wBAAwB,CAAA;AACtC,cAAc,uBAAuB,CAAA;AACrC,cAAc,qBAAqB,CAAA"}
|
package/lib/types.d.ts
CHANGED
|
@@ -1,78 +1,149 @@
|
|
|
1
|
-
import { LeadingType, MenuItemProps } from '@pixum/menu-item';
|
|
2
|
-
import { ThemeType } from '@pixum/theme-provider';
|
|
3
|
-
import { InputModesType } from '@pixum/web-input';
|
|
1
|
+
import type { LeadingType, MenuItemProps } from '@pixum/menu-item';
|
|
2
|
+
import type { ThemeType } from '@pixum/theme-provider';
|
|
3
|
+
import type { InputModesType } from '@pixum/web-input';
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* An option as handed in by the consumer.
|
|
6
|
+
*
|
|
7
|
+
* Everything a `MenuItem` understands is accepted and forwarded unchanged -
|
|
8
|
+
* the ComboBox only adds `key` and `disabled` on top. That keeps existing
|
|
9
|
+
* consumers working: they pass their MenuItem props as they always did, and
|
|
10
|
+
* props the ComboBox does not know about still reach the `MenuItem`.
|
|
6
11
|
*/
|
|
12
|
+
export interface ComboBoxOptionItemProps extends MenuItemProps {
|
|
13
|
+
/** Unique key for the option item */
|
|
14
|
+
key?: string;
|
|
15
|
+
/** Disabled options are rendered, but skipped by mouse and keyboard. */
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/** Options are accepted either as a flat list or grouped by a group headline. */
|
|
19
|
+
export type ComboBoxOptionsInput = ComboBoxOptionItemProps[] | Record<string, ComboBoxOptionItemProps[]>;
|
|
20
|
+
/**
|
|
21
|
+
* An option after normalisation. Flat and grouped options are reduced to this
|
|
22
|
+
* shape once, so keyboard navigation, rendering and ARIA ids all work on the
|
|
23
|
+
* very same list in the very same order.
|
|
24
|
+
*/
|
|
25
|
+
export interface ComboBoxOption {
|
|
26
|
+
/** The original option as handed in by the consumer. */
|
|
27
|
+
item: ComboBoxOptionItemProps;
|
|
28
|
+
/**
|
|
29
|
+
* Stable value of the option, reported by `onOptionItemClick` and compared
|
|
30
|
+
* against `value`. Resolved by `resolveOptionValue`: the option's `text` when
|
|
31
|
+
* it is a string, otherwise `key`, otherwise the render index.
|
|
32
|
+
*/
|
|
33
|
+
value: string;
|
|
34
|
+
/** Position in render order. Drives the DOM id and the keyboard navigation. */
|
|
35
|
+
index: number;
|
|
36
|
+
/** DOM id, referenced by `aria-activedescendant`. */
|
|
37
|
+
id: string;
|
|
38
|
+
/** Group headline the option belongs to, `undefined` for flat lists. */
|
|
39
|
+
group?: string;
|
|
40
|
+
/** Whether the option can be activated. */
|
|
41
|
+
disabled: boolean;
|
|
42
|
+
}
|
|
43
|
+
/** Options of one render group, produced by `groupOptions`. */
|
|
44
|
+
export interface ComboBoxOptionGroup {
|
|
45
|
+
/** Group headline, `undefined` for flat lists. */
|
|
46
|
+
group?: string;
|
|
47
|
+
/** Options of this group, still carrying their global render index. */
|
|
48
|
+
options: ComboBoxOption[];
|
|
49
|
+
}
|
|
50
|
+
/** ARIA props for the element that owns the `combobox` role. */
|
|
51
|
+
export interface ComboBoxAriaProps {
|
|
52
|
+
role: 'combobox';
|
|
53
|
+
'aria-expanded': boolean;
|
|
54
|
+
'aria-haspopup': 'listbox';
|
|
55
|
+
'aria-controls': string | undefined;
|
|
56
|
+
'aria-activedescendant': string | undefined;
|
|
57
|
+
'aria-autocomplete': 'list' | 'none';
|
|
58
|
+
}
|
|
59
|
+
/** ARIA props for the element that owns the `listbox` role. */
|
|
60
|
+
export interface ListboxAriaProps {
|
|
61
|
+
role: 'listbox';
|
|
62
|
+
id: string;
|
|
63
|
+
/** Only set for multi select; single select listboxes omit it. */
|
|
64
|
+
'aria-multiselectable'?: boolean;
|
|
65
|
+
}
|
|
66
|
+
/** Props of the rendered options list. */
|
|
7
67
|
export interface ComboBoxOptionsProps {
|
|
8
|
-
/**
|
|
9
|
-
options:
|
|
10
|
-
/**
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
|
|
14
|
-
/**
|
|
68
|
+
/** Normalised options in render order. */
|
|
69
|
+
options: ComboBoxOption[];
|
|
70
|
+
/** ARIA props of the listbox element. */
|
|
71
|
+
listboxAriaProps: ListboxAriaProps;
|
|
72
|
+
/** Values that are currently selected. */
|
|
73
|
+
selectedValues: string[];
|
|
74
|
+
/** DOM id of the active option (`aria-activedescendant`). */
|
|
75
|
+
activeOptionId?: string;
|
|
76
|
+
/** Type of the leading element, e.g. a checkbox for multi select. */
|
|
15
77
|
leadingType?: LeadingType;
|
|
16
|
-
/** Additional details
|
|
78
|
+
/** Additional details rendered as a sticky footer below the options. */
|
|
17
79
|
optionDetails?: React.ReactNode;
|
|
80
|
+
/** Called with the value of the clicked option. */
|
|
81
|
+
onOptionClick: (value: string) => void;
|
|
18
82
|
}
|
|
19
|
-
/**
|
|
20
|
-
|
|
21
|
-
*/
|
|
22
|
-
export interface ComboBoxProps extends ComboBoxOptionsProps {
|
|
23
|
-
/** Additional CSS class name for the component */
|
|
83
|
+
/** Props of the ComboBox component. */
|
|
84
|
+
export interface ComboBoxProps {
|
|
85
|
+
/** Additional CSS class name for the trigger field. */
|
|
24
86
|
className?: string;
|
|
25
|
-
/** Name attribute for the input field */
|
|
87
|
+
/** Name attribute for the input field. */
|
|
26
88
|
name?: string;
|
|
27
|
-
/** Headline text displayed in mobile bottom sheet */
|
|
89
|
+
/** Headline text displayed in the mobile bottom sheet. */
|
|
28
90
|
headline?: string;
|
|
29
|
-
/** Helper text displayed below the input */
|
|
91
|
+
/** Helper text displayed below the input field. */
|
|
30
92
|
helperText?: string;
|
|
31
|
-
/**
|
|
32
|
-
id?: string;
|
|
33
|
-
/** Label text for the input field */
|
|
93
|
+
/** Label text for the input field. */
|
|
34
94
|
label?: string;
|
|
35
|
-
/**
|
|
95
|
+
/** Options to display, either flat or grouped. */
|
|
96
|
+
options: ComboBoxOptionsInput;
|
|
97
|
+
/** Whether the popover / bottom sheet is currently open. */
|
|
36
98
|
isOpen: boolean;
|
|
37
|
-
/** State setter
|
|
99
|
+
/** State setter that controls the open state. */
|
|
38
100
|
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
|
39
|
-
/**
|
|
40
|
-
|
|
41
|
-
|
|
101
|
+
/**
|
|
102
|
+
* Selected value: a string for single select, an array of strings when
|
|
103
|
+
* `multiple` is set.
|
|
104
|
+
*/
|
|
105
|
+
value?: string | string[];
|
|
106
|
+
/** Allows selecting several options; combine with a checkbox `leadingType`. */
|
|
107
|
+
multiple?: boolean;
|
|
108
|
+
/** Called with the value of the selected (in multi select: toggled) option. */
|
|
42
109
|
onOptionItemClick?: (value: string) => void;
|
|
43
|
-
/**
|
|
110
|
+
/** Called when the search input value changes. */
|
|
111
|
+
onChange?: (value: string) => void;
|
|
112
|
+
/** Called when the user clicks outside of the component. */
|
|
44
113
|
onOutsideClick?: () => void;
|
|
45
|
-
/**
|
|
114
|
+
/** Called when the trigger field is clicked. */
|
|
46
115
|
onClick?: () => void;
|
|
47
|
-
/**
|
|
116
|
+
/** Called when the bottom sheet has been closed. */
|
|
48
117
|
onSheetClose?: () => void;
|
|
49
|
-
/** Placeholder text for the input field */
|
|
118
|
+
/** Placeholder text for the input field. */
|
|
50
119
|
placeholder?: string;
|
|
51
|
-
/** Search pattern
|
|
120
|
+
/** Search pattern for input validation. */
|
|
52
121
|
searchPattern?: string;
|
|
53
|
-
/**
|
|
54
|
-
value?: string;
|
|
55
|
-
/** Text to display when no results are found */
|
|
122
|
+
/** Text to display when there is no option to show. */
|
|
56
123
|
noResultsText?: string;
|
|
57
|
-
/** Input mode for mobile keyboards
|
|
124
|
+
/** Input mode for mobile keyboards. */
|
|
58
125
|
inputMode?: InputModesType;
|
|
59
|
-
/**
|
|
126
|
+
/** Renders a search input inside the popover / bottom sheet. */
|
|
60
127
|
withSearch?: boolean;
|
|
61
|
-
/**
|
|
128
|
+
/** Enter opens the closed list. Disable it inside forms with implicit submit. */
|
|
129
|
+
openOnEnter?: boolean;
|
|
130
|
+
/** Whether the combobox is disabled. */
|
|
62
131
|
disabled?: boolean;
|
|
63
|
-
/**
|
|
132
|
+
/** Disabled style plus shimmer animation while content is loading. */
|
|
64
133
|
loading?: boolean;
|
|
65
|
-
/**
|
|
134
|
+
/** Type of the leading element of an option (icon, avatar, checkbox …). */
|
|
135
|
+
leadingType?: LeadingType;
|
|
136
|
+
/** Additional details rendered below the options. */
|
|
137
|
+
optionDetails?: React.ReactNode;
|
|
138
|
+
/** Theme configuration for the component. */
|
|
66
139
|
theme?: ThemeType;
|
|
67
|
-
/** Custom slot that replaces the standard options/no-results block */
|
|
140
|
+
/** Custom slot that replaces the standard options / no-results block. */
|
|
68
141
|
optionsSlot?: React.ReactNode;
|
|
69
|
-
/** Icon element displayed at the leading
|
|
70
|
-
leadingIcon?: React.
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
/** Unique key for the option item */
|
|
77
|
-
key?: string;
|
|
142
|
+
/** Icon element displayed at the leading side of the trigger input. */
|
|
143
|
+
leadingIcon?: React.ReactElement | null;
|
|
144
|
+
/**
|
|
145
|
+
* Formats the selected values for the trigger field.
|
|
146
|
+
* Defaults to the labels of the selected options joined by a comma.
|
|
147
|
+
*/
|
|
148
|
+
renderValue?: (labels: string[]) => string;
|
|
78
149
|
}
|
package/lib/utils/index.d.ts
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export * from './
|
|
2
|
-
export * from './scrollOptionToViewport';
|
|
1
|
+
export * from './options';
|
package/lib/utils/index.js
CHANGED
package/lib/utils/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA"}
|
package/lib/utils/options.d.ts
CHANGED
|
@@ -1,4 +1,41 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { MenuItemProps } from '@pixum/menu-item';
|
|
2
|
+
import type { ComboBoxOption, ComboBoxOptionGroup, ComboBoxOptionItemProps, ComboBoxOptionsInput } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Resolves the stable value of an option.
|
|
5
|
+
*
|
|
6
|
+
* `MenuItemProps` does not guarantee a plain string `text`, so the value is
|
|
7
|
+
* resolved in three steps: the visible label first - that is the value existing
|
|
8
|
+
* consumers pass in as `value` and get back from `onOptionItemClick` -, then
|
|
9
|
+
* the explicit `key`, and finally the render index as a last resort so that
|
|
10
|
+
* options without a label still get a unique value.
|
|
11
|
+
*
|
|
12
|
+
* @param item - The option as handed in by the consumer
|
|
13
|
+
* @param index - Position of the option in render order
|
|
14
|
+
* @returns The stable value of the option
|
|
15
|
+
*/
|
|
16
|
+
export declare function resolveOptionValue(item: ComboBoxOptionItemProps, index: number): string;
|
|
17
|
+
/**
|
|
18
|
+
* Returns the label of an option for the trigger field.
|
|
19
|
+
*
|
|
20
|
+
* Falls back to the resolved value when the option renders a custom node
|
|
21
|
+
* instead of a plain string.
|
|
22
|
+
*
|
|
23
|
+
* @param option - A normalised option
|
|
24
|
+
* @returns The label to display in the trigger field
|
|
25
|
+
*/
|
|
26
|
+
export declare function getOptionLabel(option: ComboBoxOption): string;
|
|
27
|
+
/**
|
|
28
|
+
* Strips the ComboBox specific props from an option so the rest can be spread
|
|
29
|
+
* onto the `MenuItem`.
|
|
30
|
+
*
|
|
31
|
+
* `key` is a reserved React prop and `disabled` is handled by the option
|
|
32
|
+
* wrapper (`aria-disabled` plus the click guard); everything else belongs to
|
|
33
|
+
* `MenuItem` and is forwarded untouched.
|
|
34
|
+
*
|
|
35
|
+
* @param item - The option as handed in by the consumer
|
|
36
|
+
* @returns The props meant for the `MenuItem`
|
|
37
|
+
*/
|
|
38
|
+
export declare function toMenuItemProps({ key, disabled, ...menuItemProps }: ComboBoxOptionItemProps): MenuItemProps;
|
|
2
39
|
/**
|
|
3
40
|
* Normalises flat and grouped options into one list in render order.
|
|
4
41
|
*
|