@opengovsg/oui 0.0.0-snapshot-20250311073924
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/LICENSE.md +13 -0
- package/dist/cjs/banner/banner.cjs +118 -0
- package/dist/cjs/banner/index.cjs +8 -0
- package/dist/cjs/button/button.cjs +86 -0
- package/dist/cjs/button/index.cjs +8 -0
- package/dist/cjs/combo-box/combo-box-fuzzy.cjs +107 -0
- package/dist/cjs/combo-box/combo-box.cjs +277 -0
- package/dist/cjs/combo-box/index.cjs +12 -0
- package/dist/cjs/field/field.cjs +63 -0
- package/dist/cjs/field/index.cjs +11 -0
- package/dist/cjs/govt-banner/govt-banner.cjs +259 -0
- package/dist/cjs/govt-banner/index.cjs +8 -0
- package/dist/cjs/hooks/index.cjs +8 -0
- package/dist/cjs/hooks/use-callback-ref.cjs +17 -0
- package/dist/cjs/hooks/use-controllable-state.cjs +37 -0
- package/dist/cjs/index.cjs +47 -0
- package/dist/cjs/input/index.cjs +8 -0
- package/dist/cjs/input/input.cjs +28 -0
- package/dist/cjs/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/Icon.cjs +48 -0
- package/dist/cjs/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/createLucideIcon.cjs +30 -0
- package/dist/cjs/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/defaultAttributes.cjs +24 -0
- package/dist/cjs/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/chevron-down.cjs +19 -0
- package/dist/cjs/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/chevron-up.cjs +19 -0
- package/dist/cjs/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/circle-alert.cjs +23 -0
- package/dist/cjs/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/external-link.cjs +23 -0
- package/dist/cjs/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/info.cjs +23 -0
- package/dist/cjs/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/landmark.cjs +26 -0
- package/dist/cjs/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/lock.cjs +22 -0
- package/dist/cjs/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/x.cjs +22 -0
- package/dist/cjs/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/shared/src/utils.cjs +16 -0
- package/dist/cjs/ripple/index.cjs +10 -0
- package/dist/cjs/ripple/ripple.cjs +70 -0
- package/dist/cjs/ripple/use-ripple.cjs +29 -0
- package/dist/cjs/skip-nav-link/index.cjs +8 -0
- package/dist/cjs/skip-nav-link/skip-nav-link.cjs +18 -0
- package/dist/cjs/spinner/index.cjs +10 -0
- package/dist/cjs/spinner/spinner.cjs +17 -0
- package/dist/cjs/spinner/use-spinner.cjs +38 -0
- package/dist/cjs/system/react-utils/context.cjs +31 -0
- package/dist/cjs/system/react-utils/index.cjs +8 -0
- package/dist/cjs/system/types.cjs +3 -0
- package/dist/cjs/system/utils.cjs +101 -0
- package/dist/cjs/tag-field/index.cjs +8 -0
- package/dist/cjs/tag-field/tag-field-list.cjs +73 -0
- package/dist/cjs/tag-field/tag-field-root.cjs +184 -0
- package/dist/cjs/tag-field/tag-field-state-context.cjs +11 -0
- package/dist/cjs/tag-field/tag-field-tag-list.cjs +70 -0
- package/dist/cjs/tag-field/tag-field-trigger.cjs +27 -0
- package/dist/cjs/tag-field/tag-field.cjs +106 -0
- package/dist/cjs/tag-field/types.cjs +3 -0
- package/dist/cjs/tag-field/use-tag-field-state.cjs +103 -0
- package/dist/cjs/tag-field/use-tag-field.cjs +188 -0
- package/dist/cjs/text-area/index.cjs +8 -0
- package/dist/cjs/text-area/text-area.cjs +28 -0
- package/dist/cjs/text-area-field/index.cjs +8 -0
- package/dist/cjs/text-area-field/text-area-field.cjs +48 -0
- package/dist/cjs/text-field/index.cjs +8 -0
- package/dist/cjs/text-field/text-field.cjs +48 -0
- package/dist/cjs/toggle/index.cjs +8 -0
- package/dist/cjs/toggle/toggle.cjs +48 -0
- package/dist/esm/banner/banner.js +116 -0
- package/dist/esm/banner/index.js +2 -0
- package/dist/esm/button/button.js +84 -0
- package/dist/esm/button/index.js +2 -0
- package/dist/esm/combo-box/combo-box-fuzzy.js +105 -0
- package/dist/esm/combo-box/combo-box.js +273 -0
- package/dist/esm/combo-box/index.js +3 -0
- package/dist/esm/field/field.js +58 -0
- package/dist/esm/field/index.js +2 -0
- package/dist/esm/govt-banner/govt-banner.js +257 -0
- package/dist/esm/govt-banner/index.js +2 -0
- package/dist/esm/hooks/index.js +2 -0
- package/dist/esm/hooks/use-callback-ref.js +15 -0
- package/dist/esm/hooks/use-controllable-state.js +35 -0
- package/dist/esm/index.js +19 -0
- package/dist/esm/input/index.js +2 -0
- package/dist/esm/input/input.js +26 -0
- package/dist/esm/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/Icon.js +44 -0
- package/dist/esm/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/createLucideIcon.js +26 -0
- package/dist/esm/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/defaultAttributes.js +20 -0
- package/dist/esm/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/chevron-down.js +14 -0
- package/dist/esm/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/chevron-up.js +14 -0
- package/dist/esm/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/circle-alert.js +18 -0
- package/dist/esm/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/external-link.js +18 -0
- package/dist/esm/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/info.js +18 -0
- package/dist/esm/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/landmark.js +21 -0
- package/dist/esm/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/lock.js +17 -0
- package/dist/esm/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/x.js +17 -0
- package/dist/esm/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/shared/src/utils.js +13 -0
- package/dist/esm/ripple/index.js +3 -0
- package/dist/esm/ripple/ripple.js +49 -0
- package/dist/esm/ripple/use-ripple.js +27 -0
- package/dist/esm/skip-nav-link/index.js +2 -0
- package/dist/esm/skip-nav-link/skip-nav-link.js +16 -0
- package/dist/esm/spinner/index.js +3 -0
- package/dist/esm/spinner/spinner.js +15 -0
- package/dist/esm/spinner/use-spinner.js +36 -0
- package/dist/esm/system/react-utils/context.js +29 -0
- package/dist/esm/system/react-utils/index.js +2 -0
- package/dist/esm/system/types.js +1 -0
- package/dist/esm/system/utils.js +94 -0
- package/dist/esm/tag-field/index.js +2 -0
- package/dist/esm/tag-field/tag-field-list.js +69 -0
- package/dist/esm/tag-field/tag-field-root.js +182 -0
- package/dist/esm/tag-field/tag-field-state-context.js +9 -0
- package/dist/esm/tag-field/tag-field-tag-list.js +68 -0
- package/dist/esm/tag-field/tag-field-trigger.js +24 -0
- package/dist/esm/tag-field/tag-field.js +104 -0
- package/dist/esm/tag-field/types.js +1 -0
- package/dist/esm/tag-field/use-tag-field-state.js +101 -0
- package/dist/esm/tag-field/use-tag-field.js +186 -0
- package/dist/esm/text-area/index.js +2 -0
- package/dist/esm/text-area/text-area.js +26 -0
- package/dist/esm/text-area-field/index.js +2 -0
- package/dist/esm/text-area-field/text-area-field.js +46 -0
- package/dist/esm/text-field/index.js +2 -0
- package/dist/esm/text-field/text-field.js +46 -0
- package/dist/esm/toggle/index.js +2 -0
- package/dist/esm/toggle/toggle.js +46 -0
- package/dist/types/banner/banner.d.ts +19 -0
- package/dist/types/banner/banner.d.ts.map +1 -0
- package/dist/types/banner/index.d.ts +2 -0
- package/dist/types/banner/index.d.ts.map +1 -0
- package/dist/types/button/button.d.ts +48 -0
- package/dist/types/button/button.d.ts.map +1 -0
- package/dist/types/button/index.d.ts +2 -0
- package/dist/types/button/index.d.ts.map +1 -0
- package/dist/types/combo-box/combo-box-fuzzy.d.ts +11 -0
- package/dist/types/combo-box/combo-box-fuzzy.d.ts.map +1 -0
- package/dist/types/combo-box/combo-box.d.ts +50 -0
- package/dist/types/combo-box/combo-box.d.ts.map +1 -0
- package/dist/types/combo-box/index.d.ts +3 -0
- package/dist/types/combo-box/index.d.ts.map +1 -0
- package/dist/types/field/field.d.ts +14 -0
- package/dist/types/field/field.d.ts.map +1 -0
- package/dist/types/field/index.d.ts +2 -0
- package/dist/types/field/index.d.ts.map +1 -0
- package/dist/types/govt-banner/govt-banner.d.ts +39 -0
- package/dist/types/govt-banner/govt-banner.d.ts.map +1 -0
- package/dist/types/govt-banner/index.d.ts +2 -0
- package/dist/types/govt-banner/index.d.ts.map +1 -0
- package/dist/types/hooks/index.d.ts +2 -0
- package/dist/types/hooks/index.d.ts.map +1 -0
- package/dist/types/hooks/use-callback-ref.d.ts +6 -0
- package/dist/types/hooks/use-callback-ref.d.ts.map +1 -0
- package/dist/types/hooks/use-controllable-state.d.ts +11 -0
- package/dist/types/hooks/use-controllable-state.d.ts.map +1 -0
- package/dist/types/index.d.mts +16 -0
- package/dist/types/index.d.ts +16 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/input/index.d.ts +2 -0
- package/dist/types/input/index.d.ts.map +1 -0
- package/dist/types/input/input.d.ts +9 -0
- package/dist/types/input/input.d.ts.map +1 -0
- package/dist/types/ripple/index.d.ts +3 -0
- package/dist/types/ripple/index.d.ts.map +1 -0
- package/dist/types/ripple/ripple.d.ts +10 -0
- package/dist/types/ripple/ripple.d.ts.map +1 -0
- package/dist/types/ripple/use-ripple.d.ts +15 -0
- package/dist/types/ripple/use-ripple.d.ts.map +1 -0
- package/dist/types/skip-nav-link/index.d.ts +2 -0
- package/dist/types/skip-nav-link/index.d.ts.map +1 -0
- package/dist/types/skip-nav-link/skip-nav-link.d.ts +11 -0
- package/dist/types/skip-nav-link/skip-nav-link.d.ts.map +1 -0
- package/dist/types/spinner/index.d.ts +3 -0
- package/dist/types/spinner/index.d.ts.map +1 -0
- package/dist/types/spinner/spinner.d.ts +4 -0
- package/dist/types/spinner/spinner.d.ts.map +1 -0
- package/dist/types/spinner/use-spinner.d.ts +66 -0
- package/dist/types/spinner/use-spinner.d.ts.map +1 -0
- package/dist/types/system/react-utils/context.d.ts +27 -0
- package/dist/types/system/react-utils/context.d.ts.map +1 -0
- package/dist/types/system/react-utils/index.d.ts +2 -0
- package/dist/types/system/react-utils/index.d.ts.map +1 -0
- package/dist/types/system/types.d.ts +63 -0
- package/dist/types/system/types.d.ts.map +1 -0
- package/dist/types/system/utils.d.ts +856 -0
- package/dist/types/system/utils.d.ts.map +1 -0
- package/dist/types/tag-field/index.d.ts +2 -0
- package/dist/types/tag-field/index.d.ts.map +1 -0
- package/dist/types/tag-field/tag-field-list.d.ts +22 -0
- package/dist/types/tag-field/tag-field-list.d.ts.map +1 -0
- package/dist/types/tag-field/tag-field-root.d.ts +14 -0
- package/dist/types/tag-field/tag-field-root.d.ts.map +1 -0
- package/dist/types/tag-field/tag-field-state-context.d.ts +12 -0
- package/dist/types/tag-field/tag-field-state-context.d.ts.map +1 -0
- package/dist/types/tag-field/tag-field-tag-list.d.ts +17 -0
- package/dist/types/tag-field/tag-field-tag-list.d.ts.map +1 -0
- package/dist/types/tag-field/tag-field-trigger.d.ts +8 -0
- package/dist/types/tag-field/tag-field-trigger.d.ts.map +1 -0
- package/dist/types/tag-field/tag-field.d.ts +3 -0
- package/dist/types/tag-field/tag-field.d.ts.map +1 -0
- package/dist/types/tag-field/types.d.ts +71 -0
- package/dist/types/tag-field/types.d.ts.map +1 -0
- package/dist/types/tag-field/use-tag-field-state.d.ts +35 -0
- package/dist/types/tag-field/use-tag-field-state.d.ts.map +1 -0
- package/dist/types/tag-field/use-tag-field.d.ts +48 -0
- package/dist/types/tag-field/use-tag-field.d.ts.map +1 -0
- package/dist/types/text-area/index.d.ts +2 -0
- package/dist/types/text-area/index.d.ts.map +1 -0
- package/dist/types/text-area/text-area.d.ts +9 -0
- package/dist/types/text-area/text-area.d.ts.map +1 -0
- package/dist/types/text-area-field/index.d.ts +2 -0
- package/dist/types/text-area-field/index.d.ts.map +1 -0
- package/dist/types/text-area-field/text-area-field.d.ts +12 -0
- package/dist/types/text-area-field/text-area-field.d.ts.map +1 -0
- package/dist/types/text-field/index.d.ts +2 -0
- package/dist/types/text-field/index.d.ts.map +1 -0
- package/dist/types/text-field/text-field.d.ts +12 -0
- package/dist/types/text-field/text-field.d.ts.map +1 -0
- package/dist/types/toggle/index.d.ts +2 -0
- package/dist/types/toggle/index.d.ts.map +1 -0
- package/dist/types/toggle/toggle.d.ts +22 -0
- package/dist/types/toggle/toggle.d.ts.map +1 -0
- package/package.json +93 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
import { jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { useMemo, useCallback, useRef, useState } from 'react';
|
|
4
|
+
import { useResizeObserver } from '@react-aria/utils';
|
|
5
|
+
import { get } from 'lodash-es';
|
|
6
|
+
import { useFilter } from 'react-aria';
|
|
7
|
+
import { useSlottedContext, FormContext, Provider, LabelContext, PopoverContext, InputContext, TextContext, GroupContext, FieldErrorContext } from 'react-aria-components';
|
|
8
|
+
import { removeDataAttributes } from '../system/utils.js';
|
|
9
|
+
import { TagFieldListContext } from './tag-field-list.js';
|
|
10
|
+
import { TagFieldStateContext } from './tag-field-state-context.js';
|
|
11
|
+
import { TagFieldTriggerContext } from './tag-field-trigger.js';
|
|
12
|
+
import { useTagField } from './use-tag-field.js';
|
|
13
|
+
import { useTagFieldState } from './use-tag-field-state.js';
|
|
14
|
+
|
|
15
|
+
const calculateEstimatedRowHeight = (size) => {
|
|
16
|
+
switch (size) {
|
|
17
|
+
case "xs":
|
|
18
|
+
return 44;
|
|
19
|
+
case "sm":
|
|
20
|
+
return 44;
|
|
21
|
+
case "md":
|
|
22
|
+
return 48;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
function TagFieldRoot({
|
|
26
|
+
children,
|
|
27
|
+
virtualRowHeight: _virtualRowHeight,
|
|
28
|
+
...props
|
|
29
|
+
}) {
|
|
30
|
+
const { itemToKey: defaultItemToKey, itemToText: defaultItemToText } = props;
|
|
31
|
+
const virtualRowHeight = useMemo(
|
|
32
|
+
() => _virtualRowHeight ?? calculateEstimatedRowHeight(props.size ?? "md"),
|
|
33
|
+
[_virtualRowHeight, props.size]
|
|
34
|
+
);
|
|
35
|
+
const { contains } = useFilter({ sensitivity: "base" });
|
|
36
|
+
const itemToText = useCallback(
|
|
37
|
+
(item) => {
|
|
38
|
+
if (defaultItemToText) return defaultItemToText(item);
|
|
39
|
+
return String(get(item, "textValue") ?? String(item));
|
|
40
|
+
},
|
|
41
|
+
[defaultItemToText]
|
|
42
|
+
);
|
|
43
|
+
const itemToKey = useCallback(
|
|
44
|
+
(item) => {
|
|
45
|
+
if (defaultItemToKey) return defaultItemToKey(item);
|
|
46
|
+
return String(get(item, "id") ?? String(item));
|
|
47
|
+
},
|
|
48
|
+
[defaultItemToKey]
|
|
49
|
+
);
|
|
50
|
+
const onSelectionChange = useCallback(
|
|
51
|
+
(nextItems) => {
|
|
52
|
+
if (props.onSelectionChange) {
|
|
53
|
+
props.onSelectionChange(new Set(nextItems.map(itemToKey)));
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
[props, itemToKey]
|
|
57
|
+
);
|
|
58
|
+
const state = useTagFieldState({
|
|
59
|
+
...props,
|
|
60
|
+
itemToKey,
|
|
61
|
+
itemToText,
|
|
62
|
+
onSelectionChange,
|
|
63
|
+
defaultFilter: props.defaultFilter || contains
|
|
64
|
+
});
|
|
65
|
+
const { validationBehavior: formValidationBehavior } = useSlottedContext(FormContext) || {};
|
|
66
|
+
props.validationBehavior ?? formValidationBehavior ?? "native";
|
|
67
|
+
const fieldRef = useRef(null);
|
|
68
|
+
const popoverRef = useRef(null);
|
|
69
|
+
const listBoxRef = useRef(null);
|
|
70
|
+
const labelRef = useRef(null);
|
|
71
|
+
const inputRef = useRef(null);
|
|
72
|
+
const buttonRef = useRef(null);
|
|
73
|
+
const {
|
|
74
|
+
tagFieldProps,
|
|
75
|
+
buttonProps,
|
|
76
|
+
inputProps,
|
|
77
|
+
labelProps,
|
|
78
|
+
listBoxProps,
|
|
79
|
+
descriptionProps,
|
|
80
|
+
errorMessageProps,
|
|
81
|
+
rowVirtualizer,
|
|
82
|
+
...validation
|
|
83
|
+
} = useTagField(
|
|
84
|
+
{
|
|
85
|
+
...removeDataAttributes(props),
|
|
86
|
+
virtualRowHeight,
|
|
87
|
+
itemToKey,
|
|
88
|
+
itemToText,
|
|
89
|
+
inputRef,
|
|
90
|
+
listBoxRef,
|
|
91
|
+
labelRef,
|
|
92
|
+
buttonRef},
|
|
93
|
+
state
|
|
94
|
+
);
|
|
95
|
+
const [menuWidth, setMenuWidth] = useState(null);
|
|
96
|
+
const onResize = useCallback(() => {
|
|
97
|
+
if (fieldRef.current) {
|
|
98
|
+
const fieldRect = fieldRef.current.getBoundingClientRect();
|
|
99
|
+
setMenuWidth(fieldRect.right - fieldRect.left + "px");
|
|
100
|
+
}
|
|
101
|
+
}, []);
|
|
102
|
+
useResizeObserver({
|
|
103
|
+
ref: fieldRef,
|
|
104
|
+
onResize
|
|
105
|
+
});
|
|
106
|
+
const renderPropsState = useMemo(
|
|
107
|
+
() => ({
|
|
108
|
+
isOpen: tagFieldProps.isOpen,
|
|
109
|
+
isDisabled: props.isDisabled || false,
|
|
110
|
+
isInvalid: validation.isInvalid || false,
|
|
111
|
+
isRequired: props.isRequired || false
|
|
112
|
+
}),
|
|
113
|
+
[
|
|
114
|
+
tagFieldProps.isOpen,
|
|
115
|
+
props.isDisabled,
|
|
116
|
+
props.isRequired,
|
|
117
|
+
validation.isInvalid
|
|
118
|
+
]
|
|
119
|
+
);
|
|
120
|
+
return /* @__PURE__ */ jsx(
|
|
121
|
+
Provider,
|
|
122
|
+
{
|
|
123
|
+
values: [
|
|
124
|
+
[
|
|
125
|
+
TagFieldStateContext,
|
|
126
|
+
{
|
|
127
|
+
...state,
|
|
128
|
+
...tagFieldProps,
|
|
129
|
+
size: props.size,
|
|
130
|
+
variant: props.variant
|
|
131
|
+
}
|
|
132
|
+
],
|
|
133
|
+
[LabelContext, labelProps],
|
|
134
|
+
[TagFieldListContext, { ...listBoxProps, rowVirtualizer }],
|
|
135
|
+
[TagFieldTriggerContext, buttonProps],
|
|
136
|
+
[
|
|
137
|
+
PopoverContext,
|
|
138
|
+
{
|
|
139
|
+
ref: popoverRef,
|
|
140
|
+
triggerRef: fieldRef,
|
|
141
|
+
scrollRef: listBoxRef,
|
|
142
|
+
placement: "bottom start",
|
|
143
|
+
isOpen: tagFieldProps.isOpen,
|
|
144
|
+
isNonModal: true,
|
|
145
|
+
trigger: "TagField",
|
|
146
|
+
style: { "--trigger-width": menuWidth }
|
|
147
|
+
}
|
|
148
|
+
],
|
|
149
|
+
[InputContext, inputProps],
|
|
150
|
+
[
|
|
151
|
+
TextContext,
|
|
152
|
+
{
|
|
153
|
+
slots: {
|
|
154
|
+
description: descriptionProps,
|
|
155
|
+
errorMessage: errorMessageProps
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
],
|
|
159
|
+
[
|
|
160
|
+
GroupContext,
|
|
161
|
+
{
|
|
162
|
+
isDisabled: props.isDisabled || false,
|
|
163
|
+
isInvalid: validation.isInvalid,
|
|
164
|
+
ref: fieldRef
|
|
165
|
+
}
|
|
166
|
+
],
|
|
167
|
+
[FieldErrorContext, validation]
|
|
168
|
+
],
|
|
169
|
+
children: typeof children === "function" ? children({
|
|
170
|
+
...renderPropsState,
|
|
171
|
+
defaultChildren: null,
|
|
172
|
+
items: state.items,
|
|
173
|
+
selectedItems: state.selectedItems,
|
|
174
|
+
highlightedIndex: tagFieldProps.highlightedIndex,
|
|
175
|
+
getSelectedItemProps: tagFieldProps.getSelectedItemProps,
|
|
176
|
+
removeSelectedItem: tagFieldProps.removeSelectedItem
|
|
177
|
+
}) : children
|
|
178
|
+
}
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export { TagFieldRoot };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { useContext, useCallback } from 'react';
|
|
4
|
+
import { TagFieldStateContext } from './tag-field-state-context.js';
|
|
5
|
+
import X from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/x.js';
|
|
6
|
+
|
|
7
|
+
const TagFieldTagList = ({
|
|
8
|
+
classNames,
|
|
9
|
+
...props
|
|
10
|
+
}) => {
|
|
11
|
+
const {
|
|
12
|
+
selectedItems,
|
|
13
|
+
getSelectedItemProps,
|
|
14
|
+
removeSelectedItem,
|
|
15
|
+
isDisabled,
|
|
16
|
+
isReadOnly
|
|
17
|
+
} = useContext(TagFieldStateContext);
|
|
18
|
+
const handleRemoveSelectedItem = useCallback(
|
|
19
|
+
(item) => () => {
|
|
20
|
+
if (isDisabled || isReadOnly) return;
|
|
21
|
+
removeSelectedItem(item);
|
|
22
|
+
},
|
|
23
|
+
[isDisabled, isReadOnly, removeSelectedItem]
|
|
24
|
+
);
|
|
25
|
+
if (props.children !== void 0 && typeof props.children !== "function") {
|
|
26
|
+
return props.children;
|
|
27
|
+
}
|
|
28
|
+
return selectedItems.map((selectedItem, index) => {
|
|
29
|
+
const itemProps = getSelectedItemProps({
|
|
30
|
+
disabled: isDisabled,
|
|
31
|
+
readOnly: isReadOnly,
|
|
32
|
+
selectedItem,
|
|
33
|
+
index
|
|
34
|
+
});
|
|
35
|
+
if (typeof props.children === "function") {
|
|
36
|
+
return props.children({
|
|
37
|
+
item: selectedItem,
|
|
38
|
+
removeSelectedItem: handleRemoveSelectedItem(selectedItem),
|
|
39
|
+
isDisabled,
|
|
40
|
+
isReadOnly,
|
|
41
|
+
itemProps
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return /* @__PURE__ */ jsxs(
|
|
45
|
+
"span",
|
|
46
|
+
{
|
|
47
|
+
className: classNames?.tag,
|
|
48
|
+
...itemProps,
|
|
49
|
+
children: [
|
|
50
|
+
/* @__PURE__ */ jsx("span", { className: classNames?.tagText, children: selectedItem.textValue }),
|
|
51
|
+
/* @__PURE__ */ jsx(
|
|
52
|
+
X,
|
|
53
|
+
{
|
|
54
|
+
className: classNames?.tagIcon,
|
|
55
|
+
onClick: (e) => {
|
|
56
|
+
e.stopPropagation();
|
|
57
|
+
handleRemoveSelectedItem(selectedItem)();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
)
|
|
61
|
+
]
|
|
62
|
+
},
|
|
63
|
+
`selected-item-${index}`
|
|
64
|
+
);
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export { TagFieldTagList };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
import { jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { createContext } from 'react';
|
|
4
|
+
import { useContextProps } from 'react-aria-components';
|
|
5
|
+
import { forwardRef } from '../system/utils.js';
|
|
6
|
+
|
|
7
|
+
const TagFieldTriggerContext = createContext({});
|
|
8
|
+
const TagFieldTrigger = forwardRef(
|
|
9
|
+
(props, ref) => {
|
|
10
|
+
[props, ref] = useContextProps(props, ref, TagFieldTriggerContext);
|
|
11
|
+
return /* @__PURE__ */ jsx(
|
|
12
|
+
"button",
|
|
13
|
+
{
|
|
14
|
+
"aria-label": "toggle menu",
|
|
15
|
+
type: "button",
|
|
16
|
+
...props,
|
|
17
|
+
slot: props.slot || void 0,
|
|
18
|
+
ref
|
|
19
|
+
}
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
export { TagFieldTrigger, TagFieldTriggerContext };
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
|
+
import { createElement } from 'react';
|
|
5
|
+
import { tagFieldStyles } from '@opengovsg/oui-theme';
|
|
6
|
+
import { composeRenderProps, Popover } from 'react-aria-components';
|
|
7
|
+
import { TagFieldList, TagFieldListItem } from './tag-field-list.js';
|
|
8
|
+
import { TagFieldRoot } from './tag-field-root.js';
|
|
9
|
+
import { TagFieldTagList } from './tag-field-tag-list.js';
|
|
10
|
+
import { TagFieldTrigger } from './tag-field-trigger.js';
|
|
11
|
+
import ChevronDown from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/chevron-down.js';
|
|
12
|
+
import { Label, FieldGroup, Description, FieldError } from '../field/field.js';
|
|
13
|
+
import { Input } from '../input/input.js';
|
|
14
|
+
|
|
15
|
+
function TagField({
|
|
16
|
+
classNames,
|
|
17
|
+
children,
|
|
18
|
+
...props
|
|
19
|
+
}) {
|
|
20
|
+
const styles = tagFieldStyles(props);
|
|
21
|
+
return /* @__PURE__ */ jsxs(TagFieldRoot, { ...props, children: [
|
|
22
|
+
/* @__PURE__ */ jsxs("div", { className: styles.root({ className: classNames?.root }), children: [
|
|
23
|
+
/* @__PURE__ */ jsx(
|
|
24
|
+
Label,
|
|
25
|
+
{
|
|
26
|
+
size: props.size,
|
|
27
|
+
className: styles.label({ className: classNames?.label }),
|
|
28
|
+
children: props.label
|
|
29
|
+
}
|
|
30
|
+
),
|
|
31
|
+
/* @__PURE__ */ jsxs(
|
|
32
|
+
FieldGroup,
|
|
33
|
+
{
|
|
34
|
+
className: composeRenderProps(
|
|
35
|
+
classNames?.group,
|
|
36
|
+
(className, renderProps) => styles.group({ className, ...renderProps })
|
|
37
|
+
),
|
|
38
|
+
children: [
|
|
39
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-row flex-wrap gap-1", children: [
|
|
40
|
+
/* @__PURE__ */ jsx(
|
|
41
|
+
TagFieldTagList,
|
|
42
|
+
{
|
|
43
|
+
classNames: {
|
|
44
|
+
tag: styles.tag({ className: classNames?.tag }),
|
|
45
|
+
tagText: styles.tagText({ className: classNames?.tagText }),
|
|
46
|
+
tagIcon: styles.tagIcon({ className: classNames?.tagIcon })
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
),
|
|
50
|
+
/* @__PURE__ */ jsx(
|
|
51
|
+
Input,
|
|
52
|
+
{
|
|
53
|
+
variant: "unstyled",
|
|
54
|
+
size: props.size,
|
|
55
|
+
className: composeRenderProps(
|
|
56
|
+
classNames?.field,
|
|
57
|
+
(className, renderProps) => styles.field({ className, ...renderProps })
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
)
|
|
61
|
+
] }),
|
|
62
|
+
/* @__PURE__ */ jsx(
|
|
63
|
+
TagFieldTrigger,
|
|
64
|
+
{
|
|
65
|
+
className: styles.trigger({ className: classNames?.trigger }),
|
|
66
|
+
children: /* @__PURE__ */ jsx(ChevronDown, {})
|
|
67
|
+
}
|
|
68
|
+
)
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
),
|
|
72
|
+
props.description && /* @__PURE__ */ jsx(
|
|
73
|
+
Description,
|
|
74
|
+
{
|
|
75
|
+
size: props.size,
|
|
76
|
+
className: styles.description({
|
|
77
|
+
className: classNames?.description
|
|
78
|
+
}),
|
|
79
|
+
children: props.description
|
|
80
|
+
}
|
|
81
|
+
),
|
|
82
|
+
/* @__PURE__ */ jsx(
|
|
83
|
+
FieldError,
|
|
84
|
+
{
|
|
85
|
+
size: props.size,
|
|
86
|
+
className: styles.error({
|
|
87
|
+
className: classNames?.error
|
|
88
|
+
}),
|
|
89
|
+
children: props.errorMessage
|
|
90
|
+
}
|
|
91
|
+
)
|
|
92
|
+
] }),
|
|
93
|
+
/* @__PURE__ */ jsx(Popover, { children: /* @__PURE__ */ jsx(
|
|
94
|
+
TagFieldList,
|
|
95
|
+
{
|
|
96
|
+
className: styles.list({ className: classNames?.list }),
|
|
97
|
+
itemClassNames: props.itemClassNames,
|
|
98
|
+
children: ({ key, ...props2 }) => children ? children({ key, ...props2 }) : /* @__PURE__ */ createElement(TagFieldListItem, { ...props2, key })
|
|
99
|
+
}
|
|
100
|
+
) })
|
|
101
|
+
] });
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export { TagField };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
import { useMemo, useCallback } from 'react';
|
|
3
|
+
import { useFormValidationState } from '@react-stately/form';
|
|
4
|
+
import { useControlledState } from '@react-stately/utils';
|
|
5
|
+
import { useControllableState } from '../hooks/use-controllable-state.js';
|
|
6
|
+
|
|
7
|
+
function useTagFieldState(props) {
|
|
8
|
+
const { itemToText, itemToKey, defaultFilter } = props;
|
|
9
|
+
const itemsByKey = useMemo(() => {
|
|
10
|
+
const items = props.items ?? props.defaultItems ?? [];
|
|
11
|
+
return items.reduce(
|
|
12
|
+
(acc, item) => {
|
|
13
|
+
acc[itemToKey(item)] = item;
|
|
14
|
+
return acc;
|
|
15
|
+
},
|
|
16
|
+
{}
|
|
17
|
+
) ?? {};
|
|
18
|
+
}, [itemToKey, props.defaultItems, props.items]);
|
|
19
|
+
const getSelectedItemsByKey = useCallback(
|
|
20
|
+
(keys) => {
|
|
21
|
+
if (!keys) return;
|
|
22
|
+
return [...keys].map((key) => itemsByKey[key]);
|
|
23
|
+
},
|
|
24
|
+
[itemsByKey]
|
|
25
|
+
);
|
|
26
|
+
const [selectedItems, setSelectedItems] = useControllableState({
|
|
27
|
+
defaultValue: getSelectedItemsByKey(props.defaultSelectedKeys) ?? [],
|
|
28
|
+
value: getSelectedItemsByKey(props.selectedKeys),
|
|
29
|
+
onChange: props.onSelectionChange
|
|
30
|
+
});
|
|
31
|
+
const defaultInputValue = props.defaultInputValue ?? "";
|
|
32
|
+
const [inputValue, setInputValue] = useControlledState(
|
|
33
|
+
props.inputValue,
|
|
34
|
+
defaultInputValue,
|
|
35
|
+
props.onInputChange
|
|
36
|
+
);
|
|
37
|
+
const controlledSelectedKeys = useMemo(
|
|
38
|
+
() => new Set(selectedItems.map(itemToKey)),
|
|
39
|
+
[itemToKey, selectedItems]
|
|
40
|
+
);
|
|
41
|
+
const validation = useFormValidationState({
|
|
42
|
+
...props,
|
|
43
|
+
value: useMemo(
|
|
44
|
+
() => ({
|
|
45
|
+
inputValue,
|
|
46
|
+
selectedKeys: controlledSelectedKeys
|
|
47
|
+
}),
|
|
48
|
+
[controlledSelectedKeys, inputValue]
|
|
49
|
+
)
|
|
50
|
+
});
|
|
51
|
+
const filteredItems = useMemo(
|
|
52
|
+
() => (
|
|
53
|
+
// No default filter if items are controlled.
|
|
54
|
+
!!props.items || !defaultFilter ? props.items ?? [] : filterItems({
|
|
55
|
+
items: props.defaultItems ?? [],
|
|
56
|
+
inputValue,
|
|
57
|
+
itemToText,
|
|
58
|
+
itemToKey,
|
|
59
|
+
selectedKeys: controlledSelectedKeys,
|
|
60
|
+
filter: defaultFilter
|
|
61
|
+
})
|
|
62
|
+
),
|
|
63
|
+
[
|
|
64
|
+
props.items,
|
|
65
|
+
props.defaultItems,
|
|
66
|
+
defaultFilter,
|
|
67
|
+
inputValue,
|
|
68
|
+
itemToText,
|
|
69
|
+
itemToKey,
|
|
70
|
+
controlledSelectedKeys
|
|
71
|
+
]
|
|
72
|
+
);
|
|
73
|
+
return {
|
|
74
|
+
items: filteredItems,
|
|
75
|
+
disabledKeys: props.disabledKeys,
|
|
76
|
+
inputValue,
|
|
77
|
+
setInputValue,
|
|
78
|
+
selectedItems,
|
|
79
|
+
setSelectedItems,
|
|
80
|
+
itemToText,
|
|
81
|
+
itemToKey,
|
|
82
|
+
...validation
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function filterItems({
|
|
86
|
+
items,
|
|
87
|
+
inputValue,
|
|
88
|
+
itemToText,
|
|
89
|
+
itemToKey,
|
|
90
|
+
filter,
|
|
91
|
+
selectedKeys
|
|
92
|
+
}) {
|
|
93
|
+
return items.filter((item) => {
|
|
94
|
+
const isSelected = selectedKeys ? selectedKeys.has(itemToKey(item)) : false;
|
|
95
|
+
if (isSelected) return false;
|
|
96
|
+
const matchesFilter = filter(itemToText(item), inputValue);
|
|
97
|
+
return matchesFilter;
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export { useTagFieldState };
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
import { useRef, useMemo, useCallback } from 'react';
|
|
3
|
+
import { mergeProps } from '@react-aria/utils';
|
|
4
|
+
import { useVirtualizer } from '@tanstack/react-virtual';
|
|
5
|
+
import { useMultipleSelection, useCombobox } from 'downshift';
|
|
6
|
+
import { omit } from 'lodash-es';
|
|
7
|
+
import { useTextField } from 'react-aria';
|
|
8
|
+
|
|
9
|
+
function useTagField(props, state) {
|
|
10
|
+
let { buttonRef } = props;
|
|
11
|
+
const {
|
|
12
|
+
inputRef,
|
|
13
|
+
listBoxRef,
|
|
14
|
+
labelRef,
|
|
15
|
+
shouldCloseOnBlur,
|
|
16
|
+
// TODO: Handle these states
|
|
17
|
+
isReadOnly,
|
|
18
|
+
isDisabled,
|
|
19
|
+
itemToKey,
|
|
20
|
+
itemToText,
|
|
21
|
+
label,
|
|
22
|
+
virtualRowHeight = 40
|
|
23
|
+
} = props;
|
|
24
|
+
const backupBtnRef = useRef(null);
|
|
25
|
+
buttonRef = buttonRef ?? backupBtnRef;
|
|
26
|
+
const {
|
|
27
|
+
selectedItems,
|
|
28
|
+
setSelectedItems,
|
|
29
|
+
inputValue,
|
|
30
|
+
setInputValue,
|
|
31
|
+
items,
|
|
32
|
+
disabledKeys
|
|
33
|
+
} = state;
|
|
34
|
+
const { getSelectedItemProps, getDropdownProps, removeSelectedItem } = useMultipleSelection({
|
|
35
|
+
selectedItems,
|
|
36
|
+
onStateChange({ selectedItems: newSelectedItems, type }) {
|
|
37
|
+
switch (type) {
|
|
38
|
+
case useMultipleSelection.stateChangeTypes.SelectedItemKeyDownBackspace:
|
|
39
|
+
case useMultipleSelection.stateChangeTypes.SelectedItemKeyDownDelete:
|
|
40
|
+
case useMultipleSelection.stateChangeTypes.DropdownKeyDownBackspace:
|
|
41
|
+
case useMultipleSelection.stateChangeTypes.FunctionRemoveSelectedItem: {
|
|
42
|
+
if (isDisabled) return;
|
|
43
|
+
setSelectedItems(newSelectedItems ?? []);
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
const disabledKeysSet = useMemo(() => {
|
|
50
|
+
return new Set(disabledKeys);
|
|
51
|
+
}, [disabledKeys]);
|
|
52
|
+
const rowVirtualizer = useVirtualizer({
|
|
53
|
+
count: items.length,
|
|
54
|
+
getScrollElement: () => listBoxRef.current,
|
|
55
|
+
estimateSize: () => virtualRowHeight,
|
|
56
|
+
getItemKey: useCallback(
|
|
57
|
+
(index) => itemToKey(items[index]),
|
|
58
|
+
[itemToKey, items]
|
|
59
|
+
),
|
|
60
|
+
overscan: 2
|
|
61
|
+
});
|
|
62
|
+
const {
|
|
63
|
+
isOpen,
|
|
64
|
+
getToggleButtonProps,
|
|
65
|
+
getLabelProps,
|
|
66
|
+
getMenuProps,
|
|
67
|
+
getInputProps,
|
|
68
|
+
highlightedIndex,
|
|
69
|
+
getItemProps
|
|
70
|
+
} = useCombobox({
|
|
71
|
+
itemToString: (item) => {
|
|
72
|
+
if (!item) {
|
|
73
|
+
return "";
|
|
74
|
+
}
|
|
75
|
+
return itemToText(item);
|
|
76
|
+
},
|
|
77
|
+
isItemDisabled: (item) => isDisabled || isReadOnly || disabledKeysSet.has(itemToKey(item)),
|
|
78
|
+
items,
|
|
79
|
+
scrollIntoView: () => {
|
|
80
|
+
},
|
|
81
|
+
onHighlightedIndexChange: ({ highlightedIndex: highlightedIndex2, type }) => {
|
|
82
|
+
if (type !== useCombobox.stateChangeTypes.MenuMouseLeave && highlightedIndex2 >= 0) {
|
|
83
|
+
rowVirtualizer.scrollToIndex(highlightedIndex2);
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
defaultHighlightedIndex: 0,
|
|
87
|
+
// after selection, highlight the first item.
|
|
88
|
+
selectedItem: null,
|
|
89
|
+
inputValue,
|
|
90
|
+
stateReducer(_state, actionAndChanges) {
|
|
91
|
+
const { changes, type } = actionAndChanges;
|
|
92
|
+
switch (type) {
|
|
93
|
+
case useCombobox.stateChangeTypes.ItemClick:
|
|
94
|
+
case useCombobox.stateChangeTypes.InputKeyDownEnter:
|
|
95
|
+
case useCombobox.stateChangeTypes.InputBlur: {
|
|
96
|
+
return {
|
|
97
|
+
...changes,
|
|
98
|
+
isOpen: shouldCloseOnBlur === false ? true : changes.isOpen
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
default:
|
|
102
|
+
return changes;
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
onStateChange({
|
|
106
|
+
inputValue: newInputValue,
|
|
107
|
+
type,
|
|
108
|
+
selectedItem: newSelectedItem
|
|
109
|
+
}) {
|
|
110
|
+
switch (type) {
|
|
111
|
+
case useCombobox.stateChangeTypes.InputBlur:
|
|
112
|
+
case useCombobox.stateChangeTypes.InputKeyDownEnter:
|
|
113
|
+
case useCombobox.stateChangeTypes.ItemClick: {
|
|
114
|
+
if (newSelectedItem) {
|
|
115
|
+
setSelectedItems((prev) => [.../* @__PURE__ */ new Set([...prev, newSelectedItem])]);
|
|
116
|
+
}
|
|
117
|
+
setInputValue("");
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
case useCombobox.stateChangeTypes.InputChange:
|
|
121
|
+
setInputValue(newInputValue ?? "");
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
const { isInvalid, validationErrors, validationDetails } = state.displayValidation;
|
|
127
|
+
const inputProps = getInputProps({
|
|
128
|
+
ref: inputRef,
|
|
129
|
+
"aria-label": props["aria-label"],
|
|
130
|
+
"aria-labelledby": props["aria-labelledby"],
|
|
131
|
+
...getDropdownProps({ preventKeyAction: isOpen }),
|
|
132
|
+
// Somehow adding this will allow the input to be updated properly, else
|
|
133
|
+
// it may sometimes lag behind a single state.
|
|
134
|
+
// Was also in the previous downshift docs but they removed it for some reason.
|
|
135
|
+
// See https://github.com/downshift-js/downshift/pull/1576/files#diff-d32b6994832dda99d96f207e964a0ef27102128c532ea9492949f21ec0cf58d3
|
|
136
|
+
onChange: (e) => setInputValue(e.target.value)
|
|
137
|
+
});
|
|
138
|
+
const {
|
|
139
|
+
labelProps,
|
|
140
|
+
inputProps: newInputProps,
|
|
141
|
+
descriptionProps,
|
|
142
|
+
errorMessageProps
|
|
143
|
+
} = useTextField(
|
|
144
|
+
{
|
|
145
|
+
isReadOnly,
|
|
146
|
+
isDisabled,
|
|
147
|
+
isInvalid,
|
|
148
|
+
errorMessage: props.errorMessage,
|
|
149
|
+
description: props.description,
|
|
150
|
+
label,
|
|
151
|
+
...inputProps,
|
|
152
|
+
onChange: () => {
|
|
153
|
+
},
|
|
154
|
+
value: state.inputValue
|
|
155
|
+
},
|
|
156
|
+
inputRef
|
|
157
|
+
);
|
|
158
|
+
return {
|
|
159
|
+
tagFieldProps: {
|
|
160
|
+
isDisabled: newInputProps.disabled ?? false,
|
|
161
|
+
isReadOnly: newInputProps.readOnly ?? false,
|
|
162
|
+
isInvalid,
|
|
163
|
+
getItemProps,
|
|
164
|
+
highlightedIndex,
|
|
165
|
+
isOpen,
|
|
166
|
+
getSelectedItemProps,
|
|
167
|
+
removeSelectedItem
|
|
168
|
+
},
|
|
169
|
+
labelProps: mergeProps(getLabelProps({ ref: labelRef }), labelProps),
|
|
170
|
+
// Remove onKeyDown from newInputProps to prevent it from being called twice, resulting in arrow keys moving two items.
|
|
171
|
+
inputProps: mergeProps(inputProps, omit(newInputProps, "onKeyDown")),
|
|
172
|
+
buttonProps: getToggleButtonProps({
|
|
173
|
+
ref: buttonRef,
|
|
174
|
+
disabled: isDisabled
|
|
175
|
+
}),
|
|
176
|
+
listBoxProps: getMenuProps({ ref: listBoxRef }, { suppressRefError: true }),
|
|
177
|
+
descriptionProps,
|
|
178
|
+
errorMessageProps,
|
|
179
|
+
isInvalid,
|
|
180
|
+
validationErrors,
|
|
181
|
+
validationDetails,
|
|
182
|
+
rowVirtualizer
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export { useTagField };
|