@festo-ui/react 9.0.1-dev.772 → 9.0.1-dev.775
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/forms/combobox/ComboBox.css +3 -42
- package/dist/forms/combobox/ComboBox.js +16 -15
- package/dist/forms/multi-select/MultiSelect.d.ts +20 -0
- package/dist/forms/multi-select/MultiSelect.js +189 -0
- package/dist/forms/multi-select/MultiSelect.module.js +8 -0
- package/dist/forms/multi-select/MultiSelect_module.css +13 -0
- package/dist/forms/select/Select.d.ts +12 -13
- package/dist/forms/select/Select.js +74 -82
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/package.json +1 -1
- package/dist/forms/select/Select.css +0 -160
- package/dist/forms/select/internal/HiddenInput.d.ts +0 -8
- package/dist/forms/select/internal/HiddenInput.js +0 -15
- package/dist/forms/select/internal/ListItem.d.ts +0 -18
- package/dist/forms/select/internal/ListItem.js +0 -69
- package/dist/forms/select/internal/SelectButton.d.ts +0 -12
- package/dist/forms/select/internal/SelectButton.js +0 -49
- package/dist/forms/select/internal/SelectButtonContent.d.ts +0 -7
- package/dist/forms/select/internal/SelectButtonContent.js +0 -31
- package/dist/forms/select/internal/SelectCheckbox.d.ts +0 -4
- package/dist/forms/select/internal/SelectCheckbox.js +0 -13
- package/dist/forms/select/internal/SelectLabel.d.ts +0 -7
- package/dist/forms/select/internal/SelectLabel.js +0 -12
- package/dist/forms/select/internal/SelectOptionsContainer.d.ts +0 -17
- package/dist/forms/select/internal/SelectOptionsContainer.js +0 -103
- package/dist/forms/select/internal/SelectScrollContainer.d.ts +0 -8
- package/dist/forms/select/internal/SelectScrollContainer.js +0 -15
- package/dist/forms/select/internal/SelectWrapper.d.ts +0 -6
- package/dist/forms/select/internal/SelectWrapper.js +0 -12
- package/dist/forms/select/internal/index.d.ts +0 -6
- package/dist/forms/select/internal/index.js +0 -7
- package/dist/forms/select/internal/utils.d.ts +0 -7
- package/dist/forms/select/internal/utils.js +0 -30
- package/dist/forms/select/select-option/SelectOption.d.ts +0 -14
- package/dist/forms/select/select-option/SelectOption.js +0 -12
- package/dist/forms/select/utils.d.ts +0 -2
- package/dist/forms/select/utils.js +0 -12
|
@@ -106,57 +106,18 @@
|
|
|
106
106
|
display: none;
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
.
|
|
110
|
-
background-color: var(--fwe-white);
|
|
111
|
-
border: 1px solid var(--fwe-gray-200);
|
|
112
|
-
border-radius: 4px;
|
|
113
|
-
max-width: 100%;
|
|
114
|
-
margin: 0;
|
|
115
|
-
padding: 8px;
|
|
116
|
-
list-style: none;
|
|
117
|
-
box-shadow: 0 1px 4px #00000029;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
.fr-combobox-option {
|
|
121
|
-
cursor: pointer;
|
|
122
|
-
min-height: 24px;
|
|
123
|
-
padding: 12px 8px;
|
|
124
|
-
line-height: 24px;
|
|
125
|
-
position: relative;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
.fr-combobox-option:hover, .fr-combobox-option.fr-focus, .fr-combobox-option.fr-selected {
|
|
129
|
-
background-color: var(--fwe-gray-100);
|
|
130
|
-
outline: none;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
.fr-combobox-option:last-child {
|
|
134
|
-
border-bottom: none;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
.fr-combobox-option.fr-disabled {
|
|
138
|
-
color: var(--fwe-text-disabled);
|
|
139
|
-
cursor: default;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
.fr-combobox-option.fr-disabled:hover, .fr-combobox-option.fr-disabled:focus, .fr-combobox-option.fr-disabled.fr-focus {
|
|
143
|
-
background-color: #0000;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
.fr-combobox-option-content {
|
|
109
|
+
.fwe-combobox-option-content {
|
|
147
110
|
white-space: nowrap;
|
|
148
111
|
text-overflow: ellipsis;
|
|
149
|
-
min-height: 24px;
|
|
150
|
-
line-height: 24px;
|
|
151
112
|
display: block;
|
|
152
113
|
overflow: hidden;
|
|
153
114
|
}
|
|
154
115
|
|
|
155
|
-
.
|
|
116
|
+
.fwe-combobox-highlight {
|
|
156
117
|
color: var(--fwe-hero);
|
|
157
118
|
}
|
|
158
119
|
|
|
159
|
-
.
|
|
120
|
+
.fwe-combobox-empty {
|
|
160
121
|
cursor: default;
|
|
161
122
|
color: var(--fwe-text-disabled);
|
|
162
123
|
}
|
|
@@ -2,7 +2,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import "./ComboBox.css";
|
|
3
3
|
import { Combobox, ComboboxButton, ComboboxInput, ComboboxOption, ComboboxOptions } from "@headlessui/react";
|
|
4
4
|
import classnames from "classnames";
|
|
5
|
-
import { forwardRef, useMemo,
|
|
5
|
+
import { forwardRef, useMemo, useState } from "react";
|
|
6
6
|
import { useControlled } from "../../utils/useControlled.js";
|
|
7
7
|
import { useId } from "../../utils/useId.js";
|
|
8
8
|
function getHighlightedLabel(label, query) {
|
|
@@ -39,7 +39,6 @@ function getHighlightedLabel(label, query) {
|
|
|
39
39
|
}
|
|
40
40
|
function ComboBoxComponent({ defaultValue = '', value: controlled, label, options = [], onChange, required = false, disabled, name, id: idProp, hint, error, placeholder, onInputChange, emptyMessage = 'No results found', className, ...props }, ref) {
|
|
41
41
|
const id = useId(idProp);
|
|
42
|
-
const controlRef = useRef(null);
|
|
43
42
|
const [value, setValue] = useControlled({
|
|
44
43
|
controlled,
|
|
45
44
|
default: defaultValue,
|
|
@@ -88,13 +87,12 @@ function ComboBoxComponent({ defaultValue = '', value: controlled, label, option
|
|
|
88
87
|
...props,
|
|
89
88
|
children: [
|
|
90
89
|
/*#__PURE__*/ jsx("label", {
|
|
91
|
-
className:
|
|
90
|
+
className: "fr-combobox-label",
|
|
92
91
|
htmlFor: id,
|
|
93
92
|
children: label || ''
|
|
94
93
|
}),
|
|
95
94
|
/*#__PURE__*/ jsxs("div", {
|
|
96
95
|
className: "fr-combobox-control",
|
|
97
|
-
ref: controlRef,
|
|
98
96
|
children: [
|
|
99
97
|
/*#__PURE__*/ jsx(ComboboxInput, {
|
|
100
98
|
className: inputClasses,
|
|
@@ -115,19 +113,22 @@ function ComboBoxComponent({ defaultValue = '', value: controlled, label, option
|
|
|
115
113
|
]
|
|
116
114
|
}),
|
|
117
115
|
/*#__PURE__*/ jsxs(ComboboxOptions, {
|
|
118
|
-
className: "
|
|
116
|
+
className: "fwe-options-container",
|
|
119
117
|
as: "ul",
|
|
120
118
|
portal: false,
|
|
119
|
+
style: {
|
|
120
|
+
minWidth: 'var(--input-width)'
|
|
121
|
+
},
|
|
121
122
|
anchor: {
|
|
122
123
|
to: 'bottom start',
|
|
123
|
-
gap:
|
|
124
|
+
gap: 12,
|
|
124
125
|
padding: 8
|
|
125
126
|
},
|
|
126
127
|
children: [
|
|
127
128
|
0 === filteredOptions.length && /*#__PURE__*/ jsx("li", {
|
|
128
|
-
className: "
|
|
129
|
+
className: "fwe-combobox-option fwe-combobox-empty",
|
|
129
130
|
children: /*#__PURE__*/ jsx("span", {
|
|
130
|
-
className: "
|
|
131
|
+
className: "fwe-combobox-option-content",
|
|
131
132
|
children: emptyMessage
|
|
132
133
|
})
|
|
133
134
|
}),
|
|
@@ -135,17 +136,17 @@ function ComboBoxComponent({ defaultValue = '', value: controlled, label, option
|
|
|
135
136
|
value: option,
|
|
136
137
|
disabled: option.disabled,
|
|
137
138
|
as: "li",
|
|
138
|
-
className: ({ focus, selected, disabled: isDisabled })=>classnames('
|
|
139
|
-
'
|
|
140
|
-
'
|
|
141
|
-
'
|
|
139
|
+
className: ({ focus, selected, disabled: isDisabled })=>classnames('fwe-combobox-option', {
|
|
140
|
+
'fwe-selected': selected,
|
|
141
|
+
'fwe-focus': focus,
|
|
142
|
+
'fwe-disabled': isDisabled
|
|
142
143
|
}),
|
|
143
144
|
children: /*#__PURE__*/ jsx("span", {
|
|
144
|
-
className: "
|
|
145
|
-
"data-testid": "
|
|
145
|
+
className: "fwe-combobox-option-content",
|
|
146
|
+
"data-testid": "fwe-combobox-option-content",
|
|
146
147
|
children: getHighlightedLabel(option.label, query).map((part, index)=>/*#__PURE__*/ jsx("span", {
|
|
147
148
|
className: classnames({
|
|
148
|
-
'
|
|
149
|
+
'fwe-combobox-highlight': part.highlighted
|
|
149
150
|
}),
|
|
150
151
|
children: part.text
|
|
151
152
|
}, `${part.text}-${index}`))
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Ref } from 'react';
|
|
2
|
+
import type { ComponentBase } from '../../utils/types';
|
|
3
|
+
import type { SelectOption } from '../select/Select';
|
|
4
|
+
export interface MultiSelectProps<T> extends ComponentBase {
|
|
5
|
+
readonly defaultValue?: T[];
|
|
6
|
+
readonly value?: T[];
|
|
7
|
+
readonly label?: string;
|
|
8
|
+
readonly options?: SelectOption<T>[];
|
|
9
|
+
readonly onChange?: (value: T[]) => void;
|
|
10
|
+
readonly disabled?: boolean;
|
|
11
|
+
readonly name?: string;
|
|
12
|
+
readonly hint?: string;
|
|
13
|
+
readonly error?: string;
|
|
14
|
+
readonly placeholder?: string;
|
|
15
|
+
}
|
|
16
|
+
declare function MultiSelectComponent<T>({ defaultValue, value: controlled, label, options, onChange, disabled, name, id: idProp, hint, error, placeholder, className, ...props }: MultiSelectProps<T>, ref: Ref<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
export declare const MultiSelect: <T>(props: MultiSelectProps<T> & {
|
|
18
|
+
ref?: Ref<HTMLDivElement>;
|
|
19
|
+
}) => ReturnType<typeof MultiSelectComponent>;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Listbox, ListboxButton, ListboxOption, ListboxOptions } from "@headlessui/react";
|
|
3
|
+
import classnames from "classnames";
|
|
4
|
+
import { forwardRef, useCallback, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
5
|
+
import { useControlled } from "../../utils/useControlled.js";
|
|
6
|
+
import { useId } from "../../utils/useId.js";
|
|
7
|
+
import MultiSelect_module from "./MultiSelect.module.js";
|
|
8
|
+
function MultiSelectComponent({ defaultValue = [], value: controlled, label, options = [], onChange, disabled, name, id: idProp, hint, error, placeholder, className, ...props }, ref) {
|
|
9
|
+
const id = useId(idProp);
|
|
10
|
+
const labelId = `${id}-label`;
|
|
11
|
+
const [value, setValue] = useControlled({
|
|
12
|
+
controlled,
|
|
13
|
+
default: defaultValue,
|
|
14
|
+
onChange
|
|
15
|
+
});
|
|
16
|
+
const selectedOptions = useMemo(()=>options.filter((option)=>!option.disabled && (value ?? []).includes(option.data)), [
|
|
17
|
+
options,
|
|
18
|
+
value
|
|
19
|
+
]);
|
|
20
|
+
function handleChange(nextOptions) {
|
|
21
|
+
setValue(nextOptions.map((option)=>option.data));
|
|
22
|
+
}
|
|
23
|
+
const chipsRef = useRef(null);
|
|
24
|
+
const [overflowCount, setOverflowCount] = useState(0);
|
|
25
|
+
const measureOverflow = useCallback((optionCount)=>{
|
|
26
|
+
const container = chipsRef.current;
|
|
27
|
+
if (!container) return void setOverflowCount(0);
|
|
28
|
+
const allChildren = Array.from(container.children);
|
|
29
|
+
const optionChildren = allChildren.filter((child)=>'true' === child.dataset.optionChip);
|
|
30
|
+
for (const child of optionChildren)child.style.display = '';
|
|
31
|
+
const containerRect = container.getBoundingClientRect();
|
|
32
|
+
const isOverflow = optionChildren.some((child)=>{
|
|
33
|
+
const childRect = child.getBoundingClientRect();
|
|
34
|
+
return childRect.right > containerRect.right;
|
|
35
|
+
});
|
|
36
|
+
if (isOverflow && optionCount > 1) {
|
|
37
|
+
let remainingWidth = containerRect.width - 64;
|
|
38
|
+
let count = 0;
|
|
39
|
+
for (const child of optionChildren){
|
|
40
|
+
const width = child.getBoundingClientRect().width + 8;
|
|
41
|
+
if (width <= remainingWidth) {
|
|
42
|
+
remainingWidth -= width;
|
|
43
|
+
child.style.display = '';
|
|
44
|
+
} else {
|
|
45
|
+
count++;
|
|
46
|
+
child.style.display = 'none';
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
setOverflowCount(count);
|
|
50
|
+
} else setOverflowCount(0);
|
|
51
|
+
}, []);
|
|
52
|
+
useLayoutEffect(()=>{
|
|
53
|
+
measureOverflow(selectedOptions.length);
|
|
54
|
+
const container = chipsRef.current;
|
|
55
|
+
if (!container) return;
|
|
56
|
+
const observer = new ResizeObserver(()=>{
|
|
57
|
+
measureOverflow(selectedOptions.length);
|
|
58
|
+
});
|
|
59
|
+
observer.observe(container);
|
|
60
|
+
return ()=>observer.disconnect();
|
|
61
|
+
}, [
|
|
62
|
+
selectedOptions,
|
|
63
|
+
measureOverflow
|
|
64
|
+
]);
|
|
65
|
+
return /*#__PURE__*/ jsx(Listbox, {
|
|
66
|
+
value: selectedOptions,
|
|
67
|
+
onChange: handleChange,
|
|
68
|
+
disabled: disabled,
|
|
69
|
+
name: name,
|
|
70
|
+
multiple: true,
|
|
71
|
+
children: /*#__PURE__*/ jsxs("div", {
|
|
72
|
+
className: classnames(className, 'fwe-select-wrapper', {
|
|
73
|
+
'fwe-disabled': disabled
|
|
74
|
+
}),
|
|
75
|
+
ref: ref,
|
|
76
|
+
...props,
|
|
77
|
+
children: [
|
|
78
|
+
/*#__PURE__*/ jsx(ListboxButton, {
|
|
79
|
+
className: classnames('fwe-select', {
|
|
80
|
+
'fwe-invalid': error
|
|
81
|
+
}),
|
|
82
|
+
id: id,
|
|
83
|
+
"aria-labelledby": label ? labelId : void 0,
|
|
84
|
+
disabled: disabled,
|
|
85
|
+
children: selectedOptions.length > 0 ? /*#__PURE__*/ jsxs("span", {
|
|
86
|
+
ref: chipsRef,
|
|
87
|
+
className: MultiSelect_module["chip-container"],
|
|
88
|
+
children: [
|
|
89
|
+
selectedOptions.map((o)=>/*#__PURE__*/ jsx("span", {
|
|
90
|
+
"data-option-chip": "true",
|
|
91
|
+
className: classnames('fwe-chip', {
|
|
92
|
+
'fwe-disabled': disabled
|
|
93
|
+
}),
|
|
94
|
+
style: {
|
|
95
|
+
minWidth: 0,
|
|
96
|
+
flexShrink: 1 === selectedOptions.length ? 1 : 0
|
|
97
|
+
},
|
|
98
|
+
children: /*#__PURE__*/ jsx("span", {
|
|
99
|
+
className: MultiSelect_module["chip-ellipsis"],
|
|
100
|
+
children: o.label
|
|
101
|
+
})
|
|
102
|
+
}, String(o.data))),
|
|
103
|
+
overflowCount > 0 && /*#__PURE__*/ jsxs(Fragment, {
|
|
104
|
+
children: [
|
|
105
|
+
/*#__PURE__*/ jsx("span", {
|
|
106
|
+
children: "..."
|
|
107
|
+
}),
|
|
108
|
+
/*#__PURE__*/ jsxs("span", {
|
|
109
|
+
className: "fwe-chip",
|
|
110
|
+
children: [
|
|
111
|
+
"+ ",
|
|
112
|
+
overflowCount
|
|
113
|
+
]
|
|
114
|
+
})
|
|
115
|
+
]
|
|
116
|
+
})
|
|
117
|
+
]
|
|
118
|
+
}) : placeholder ?? ''
|
|
119
|
+
}),
|
|
120
|
+
/*#__PURE__*/ jsx("label", {
|
|
121
|
+
className: "fwe-select-label",
|
|
122
|
+
id: labelId,
|
|
123
|
+
htmlFor: id,
|
|
124
|
+
children: label || ''
|
|
125
|
+
}),
|
|
126
|
+
/*#__PURE__*/ jsx(ListboxOptions, {
|
|
127
|
+
className: "fwe-options-container fwe-options-container--multi-select",
|
|
128
|
+
as: "ul",
|
|
129
|
+
portal: false,
|
|
130
|
+
style: {
|
|
131
|
+
minWidth: 'var(--button-width)'
|
|
132
|
+
},
|
|
133
|
+
anchor: {
|
|
134
|
+
to: 'bottom start',
|
|
135
|
+
gap: 12,
|
|
136
|
+
padding: 8
|
|
137
|
+
},
|
|
138
|
+
children: options.map((option)=>/*#__PURE__*/ jsx(ListboxOption, {
|
|
139
|
+
value: option,
|
|
140
|
+
disabled: option.disabled,
|
|
141
|
+
as: "li",
|
|
142
|
+
style: {
|
|
143
|
+
cursor: option.disabled ? 'default' : 'pointer'
|
|
144
|
+
},
|
|
145
|
+
children: ({ selected })=>/*#__PURE__*/ jsxs("label", {
|
|
146
|
+
className: classnames('fwe-checkbox', {
|
|
147
|
+
'fwe-disabled': option.disabled
|
|
148
|
+
}),
|
|
149
|
+
style: {
|
|
150
|
+
pointerEvents: 'none',
|
|
151
|
+
cursor: 'pointer'
|
|
152
|
+
},
|
|
153
|
+
children: [
|
|
154
|
+
/*#__PURE__*/ jsx("input", {
|
|
155
|
+
type: "checkbox",
|
|
156
|
+
checked: selected,
|
|
157
|
+
disabled: option.disabled,
|
|
158
|
+
readOnly: true,
|
|
159
|
+
tabIndex: -1,
|
|
160
|
+
style: {
|
|
161
|
+
pointerEvents: 'none',
|
|
162
|
+
cursor: 'pointer'
|
|
163
|
+
}
|
|
164
|
+
}),
|
|
165
|
+
/*#__PURE__*/ jsx("span", {
|
|
166
|
+
className: "fwe-checkbox-checkmark"
|
|
167
|
+
}),
|
|
168
|
+
/*#__PURE__*/ jsx("span", {
|
|
169
|
+
className: "fwe-checkbox-label-content",
|
|
170
|
+
children: option.label
|
|
171
|
+
})
|
|
172
|
+
]
|
|
173
|
+
})
|
|
174
|
+
}, String(option.data)))
|
|
175
|
+
}),
|
|
176
|
+
hint && !error && /*#__PURE__*/ jsx("div", {
|
|
177
|
+
className: "fwe-select-description",
|
|
178
|
+
children: hint
|
|
179
|
+
}),
|
|
180
|
+
error && /*#__PURE__*/ jsx("div", {
|
|
181
|
+
className: "fwe-select-invalid",
|
|
182
|
+
children: error
|
|
183
|
+
})
|
|
184
|
+
]
|
|
185
|
+
})
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
const MultiSelect = /*#__PURE__*/ forwardRef(MultiSelectComponent);
|
|
189
|
+
export { MultiSelect };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import "./MultiSelect_module.css";
|
|
2
|
+
const MultiSelect_module = {
|
|
3
|
+
"chip-container": "chip-container-VYPHrz",
|
|
4
|
+
chipContainer: "chip-container-VYPHrz",
|
|
5
|
+
"chip-ellipsis": "chip-ellipsis-AW26fc",
|
|
6
|
+
chipEllipsis: "chip-ellipsis-AW26fc"
|
|
7
|
+
};
|
|
8
|
+
export { MultiSelect_module as default };
|
|
@@ -1,25 +1,24 @@
|
|
|
1
|
-
import '
|
|
2
|
-
import { type
|
|
3
|
-
import type {
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import { type Ref } from 'react';
|
|
3
|
+
import type { ComponentBase } from '../../utils/types';
|
|
4
|
+
export interface SelectOption<T> {
|
|
5
|
+
readonly data: T;
|
|
6
|
+
readonly label: ReactNode;
|
|
7
|
+
readonly disabled?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface SelectProps<T> extends ComponentBase {
|
|
6
10
|
readonly defaultValue?: T;
|
|
7
|
-
readonly defaultOpen?: boolean;
|
|
8
|
-
readonly open?: boolean;
|
|
9
11
|
readonly value?: T;
|
|
10
12
|
readonly label?: string;
|
|
11
|
-
readonly options?:
|
|
12
|
-
readonly required?: boolean;
|
|
13
|
+
readonly options?: SelectOption<T>[];
|
|
13
14
|
readonly onChange?: (value: T) => void;
|
|
14
|
-
readonly config?: SelectConfiguration;
|
|
15
15
|
readonly disabled?: boolean;
|
|
16
16
|
readonly name?: string;
|
|
17
17
|
readonly hint?: string;
|
|
18
18
|
readonly error?: string;
|
|
19
|
-
readonly
|
|
20
|
-
readonly renderLabelContent?: (label?: string | string[]) => JSX.Element;
|
|
19
|
+
readonly placeholder?: string;
|
|
21
20
|
}
|
|
22
|
-
declare function SelectComponent<T>({ defaultValue,
|
|
21
|
+
declare function SelectComponent<T>({ defaultValue, value: controlled, label, options, onChange, disabled, name, id: idProp, hint, error, placeholder, className, ...props }: SelectProps<T>, ref: Ref<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
|
|
23
22
|
export declare const Select: <T>(props: SelectProps<T> & {
|
|
24
23
|
ref?: Ref<HTMLDivElement>;
|
|
25
24
|
}) => ReturnType<typeof SelectComponent>;
|
|
@@ -1,94 +1,86 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import "
|
|
3
|
-
import
|
|
4
|
-
import
|
|
2
|
+
import { Listbox, ListboxButton, ListboxOption, ListboxOptions } from "@headlessui/react";
|
|
3
|
+
import classnames from "classnames";
|
|
4
|
+
import { forwardRef, useMemo } from "react";
|
|
5
5
|
import { useControlled } from "../../utils/useControlled.js";
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
function SelectComponent({ defaultValue = '', open, defaultOpen = false, value: controlled, label, options, onChange, required = false, config, disabled, name, id, children, hint, error, onOpenChange, renderLabelContent, ...props }, ref) {
|
|
6
|
+
import { useId } from "../../utils/useId.js";
|
|
7
|
+
function SelectComponent({ defaultValue = '', value: controlled, label, options = [], onChange, disabled, name, id: idProp, hint, error, placeholder, className, ...props }, ref) {
|
|
8
|
+
const id = useId(idProp);
|
|
9
|
+
const labelId = `${id}-label`;
|
|
11
10
|
const [value, setValue] = useControlled({
|
|
12
11
|
controlled,
|
|
13
12
|
default: defaultValue,
|
|
14
13
|
onChange
|
|
15
14
|
});
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
setFocused(false);
|
|
28
|
-
buttonEl?.current?.focus();
|
|
29
|
-
};
|
|
30
|
-
const handleOptionChange = (newOption)=>{
|
|
31
|
-
let newValue = newOption.data;
|
|
32
|
-
if (Array.isArray(value)) newValue = value.includes(newValue) ? value.filter((item)=>item !== newValue) : [
|
|
33
|
-
...value,
|
|
34
|
-
newValue
|
|
35
|
-
];
|
|
36
|
-
setValue(newValue);
|
|
37
|
-
if (!multiple) refocusButton();
|
|
38
|
-
};
|
|
39
|
-
const removeChip = (chipLabel)=>{
|
|
40
|
-
const chipOption = usedOptions.find((option)=>option.label === chipLabel);
|
|
41
|
-
if (chipOption) handleOptionChange(chipOption);
|
|
42
|
-
};
|
|
43
|
-
const selectedLabel = multiple ? usedOptions.filter((option)=>value.includes(option.data))?.map((option)=>option.label) : usedOptions.find((option)=>option.data === value)?.label;
|
|
44
|
-
return /*#__PURE__*/ jsxs(SelectWrapper, {
|
|
15
|
+
const selectedOption = useMemo(()=>options.find((option)=>option.data === value && !option.disabled), [
|
|
16
|
+
options,
|
|
17
|
+
value
|
|
18
|
+
]);
|
|
19
|
+
function handleChange(option) {
|
|
20
|
+
if (!option || option.disabled) return;
|
|
21
|
+
setValue(option.data);
|
|
22
|
+
}
|
|
23
|
+
return /*#__PURE__*/ jsx(Listbox, {
|
|
24
|
+
value: selectedOption ?? null,
|
|
25
|
+
onChange: handleChange,
|
|
45
26
|
disabled: disabled,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
onChange: handleOptionChange,
|
|
51
|
-
options: usedOptions,
|
|
52
|
-
value: value
|
|
53
|
-
}),
|
|
54
|
-
/*#__PURE__*/ jsx(SelectButton, {
|
|
55
|
-
ref: buttonEl,
|
|
56
|
-
onToggle: ()=>setFocused((prev)=>!prev),
|
|
57
|
-
error: error,
|
|
58
|
-
disabled: disabled,
|
|
59
|
-
focused: focused,
|
|
60
|
-
required: required,
|
|
61
|
-
onChipClick: removeChip,
|
|
62
|
-
label: selectedLabel,
|
|
63
|
-
renderLabelContent: renderLabelContent
|
|
64
|
-
}),
|
|
65
|
-
/*#__PURE__*/ jsx(SelectLabel, {
|
|
66
|
-
hideLabel: config?.hideLabel,
|
|
67
|
-
label: label,
|
|
68
|
-
id: id
|
|
69
|
-
}),
|
|
70
|
-
/*#__PURE__*/ jsx("div", {
|
|
71
|
-
className: "fwe-select-underline"
|
|
72
|
-
}),
|
|
73
|
-
hint && !error && /*#__PURE__*/ jsx("div", {
|
|
74
|
-
className: "fwe-select-description",
|
|
75
|
-
children: hint
|
|
76
|
-
}),
|
|
77
|
-
error && /*#__PURE__*/ jsx("div", {
|
|
78
|
-
className: "fwe-select-invalid",
|
|
79
|
-
children: error
|
|
27
|
+
name: name,
|
|
28
|
+
children: /*#__PURE__*/ jsxs("div", {
|
|
29
|
+
className: classnames(className, 'fwe-select-wrapper', {
|
|
30
|
+
'fwe-disabled': disabled
|
|
80
31
|
}),
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
32
|
+
ref: ref,
|
|
33
|
+
...props,
|
|
34
|
+
children: [
|
|
35
|
+
/*#__PURE__*/ jsx(ListboxButton, {
|
|
36
|
+
className: classnames('fwe-select', {
|
|
37
|
+
'fwe-invalid': error
|
|
38
|
+
}),
|
|
39
|
+
id: id,
|
|
40
|
+
"aria-labelledby": label ? labelId : void 0,
|
|
41
|
+
disabled: disabled,
|
|
42
|
+
children: selectedOption ? selectedOption.label : placeholder ?? ''
|
|
43
|
+
}),
|
|
44
|
+
/*#__PURE__*/ jsx("label", {
|
|
45
|
+
className: "fwe-select-label",
|
|
46
|
+
id: labelId,
|
|
47
|
+
htmlFor: id,
|
|
48
|
+
children: label || ''
|
|
49
|
+
}),
|
|
50
|
+
/*#__PURE__*/ jsx(ListboxOptions, {
|
|
51
|
+
className: "fwe-options-container",
|
|
52
|
+
as: "ul",
|
|
53
|
+
portal: false,
|
|
54
|
+
style: {
|
|
55
|
+
minWidth: 'var(--button-width)'
|
|
56
|
+
},
|
|
57
|
+
anchor: {
|
|
58
|
+
to: 'bottom start',
|
|
59
|
+
gap: 12,
|
|
60
|
+
padding: 8
|
|
61
|
+
},
|
|
62
|
+
children: options.map((option)=>/*#__PURE__*/ jsx(ListboxOption, {
|
|
63
|
+
value: option,
|
|
64
|
+
disabled: option.disabled,
|
|
65
|
+
as: "li",
|
|
66
|
+
className: ({ focus, selected, disabled: isDisabled })=>classnames('fwe-combobox-option', {
|
|
67
|
+
'fwe-selected': selected,
|
|
68
|
+
'fwe-focus': focus,
|
|
69
|
+
'fwe-disabled': isDisabled
|
|
70
|
+
}),
|
|
71
|
+
children: option.label
|
|
72
|
+
}, String(option.data)))
|
|
73
|
+
}),
|
|
74
|
+
hint && !error && /*#__PURE__*/ jsx("div", {
|
|
75
|
+
className: "fwe-select-description",
|
|
76
|
+
children: hint
|
|
77
|
+
}),
|
|
78
|
+
error && /*#__PURE__*/ jsx("div", {
|
|
79
|
+
className: "fwe-select-invalid",
|
|
80
|
+
children: error
|
|
81
|
+
})
|
|
82
|
+
]
|
|
83
|
+
})
|
|
92
84
|
});
|
|
93
85
|
}
|
|
94
86
|
const Select = /*#__PURE__*/ forwardRef(SelectComponent);
|
package/dist/index.d.ts
CHANGED
|
@@ -46,12 +46,12 @@ export { TabPane, type TabPaneProps } from './components/tab/tab-pane/TabPane';
|
|
|
46
46
|
export { TableHeaderCell, type TableHeaderCellProps, } from './components/table-header-cell/TableHeaderCell';
|
|
47
47
|
export { Checkbox, type CheckboxProps } from './forms/checkbox/Checkbox';
|
|
48
48
|
export { ComboBox, type ComboBoxOption, type ComboBoxProps, } from './forms/combobox/ComboBox';
|
|
49
|
+
export { MultiSelect, type MultiSelectProps, } from './forms/multi-select/MultiSelect';
|
|
49
50
|
export { RadioButton, type RadioButtonProps, } from './forms/radio/RadioButton';
|
|
50
51
|
export { RadioGroup, type RadioGroupProps } from './forms/radio/RadioGroup';
|
|
51
52
|
export { Segment, type SegmentConfiguration, type SegmentProps, } from './forms/segment/Segment';
|
|
52
53
|
export { SegmentControl, type SegmentControlProps, } from './forms/segment/segment-control/SegmentControl';
|
|
53
|
-
export { Select, type SelectProps } from './forms/select/Select';
|
|
54
|
-
export { SelectOption, type SelectOptionProps, type SelectOptionType, } from './forms/select/select-option/SelectOption';
|
|
54
|
+
export { Select, type SelectOption, type SelectProps, } from './forms/select/Select';
|
|
55
55
|
export { Slider, type SliderProps } from './forms/slider/Slider';
|
|
56
56
|
export { Switch, type SwitchProps } from './forms/switch/Switch';
|
|
57
57
|
export { TextArea, type TextAreaProps } from './forms/text-area/TextArea';
|
package/dist/index.js
CHANGED
|
@@ -46,15 +46,15 @@ import { TabPane } from "./components/tab/tab-pane/TabPane.js";
|
|
|
46
46
|
import { TableHeaderCell } from "./components/table-header-cell/TableHeaderCell.js";
|
|
47
47
|
import { Checkbox } from "./forms/checkbox/Checkbox.js";
|
|
48
48
|
import { ComboBox } from "./forms/combobox/ComboBox.js";
|
|
49
|
+
import { MultiSelect } from "./forms/multi-select/MultiSelect.js";
|
|
49
50
|
import { RadioButton } from "./forms/radio/RadioButton.js";
|
|
50
51
|
import { RadioGroup } from "./forms/radio/RadioGroup.js";
|
|
51
52
|
import { Segment } from "./forms/segment/Segment.js";
|
|
52
53
|
import { SegmentControl } from "./forms/segment/segment-control/SegmentControl.js";
|
|
53
54
|
import { Select } from "./forms/select/Select.js";
|
|
54
|
-
import { SelectOption } from "./forms/select/select-option/SelectOption.js";
|
|
55
55
|
import { Slider } from "./forms/slider/Slider.js";
|
|
56
56
|
import { Switch } from "./forms/switch/Switch.js";
|
|
57
57
|
import { TextArea } from "./forms/text-area/TextArea.js";
|
|
58
58
|
import { TextInput } from "./forms/text-input/TextInput.js";
|
|
59
59
|
import { TimePicker } from "./forms/time-picker/TimePicker.js";
|
|
60
|
-
export { Accordion, AccordionHeader, AccordionItem, AccordionItemBody, AccordionItemHeader, AlertModal, BottomSheet, Breadcrumb, Button, Card, CardBody, CardHeader, CardNotification, Checkbox, Chip, ChipContainer, ChipType, ComboBox, ConfirmModal, CustomModal, ImageGallery, ImageGalleryContent, ImageGallerySwiper, ImageGalleryThumbsSwiper, Legend, LoadingIndicator, MobileFlyout, MobileFlyoutItem, MobileFlyoutPage, Pagination, Popover, PopoverMenu, PopoverMenuContext, PopoverMenuItem, Progress, Prompt, RadioButton, RadioGroup, SearchInput, SearchSuggestion, Segment, SegmentControl, Select,
|
|
60
|
+
export { Accordion, AccordionHeader, AccordionItem, AccordionItemBody, AccordionItemHeader, AlertModal, BottomSheet, Breadcrumb, Button, Card, CardBody, CardHeader, CardNotification, Checkbox, Chip, ChipContainer, ChipType, ComboBox, ConfirmModal, CustomModal, ImageGallery, ImageGalleryContent, ImageGallerySwiper, ImageGalleryThumbsSwiper, Legend, LoadingIndicator, MobileFlyout, MobileFlyoutItem, MobileFlyoutPage, MultiSelect, Pagination, Popover, PopoverMenu, PopoverMenuContext, PopoverMenuItem, Progress, Prompt, RadioButton, RadioGroup, SearchInput, SearchSuggestion, Segment, SegmentControl, Select, Slider, Snackbar, SnackbarProvider, StepHorizontal, StepVertical, StepperHorizontal, StepperVertical, Switch, TabPane, TableHeaderCell, Tabs, TextArea, TextInput, TimePicker, Tooltip, addSnackbar, useSnackbar };
|
package/package.json
CHANGED