@firecms/ui 3.0.0-beta.12 → 3.0.0-beta.13
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/components/BooleanSwitch.d.ts +1 -1
- package/dist/components/BooleanSwitchWithLabel.d.ts +1 -1
- package/dist/components/Button.d.ts +6 -4
- package/dist/components/DateTimeField.d.ts +1 -1
- package/dist/components/Dialog.d.ts +2 -1
- package/dist/components/MultiSelect.d.ts +14 -22
- package/dist/components/Select.d.ts +10 -9
- package/dist/components/TextField.d.ts +20 -4
- package/dist/index.es.js +554 -483
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +554 -483
- package/dist/index.umd.js.map +1 -1
- package/package.json +3 -2
- package/src/components/BooleanSwitch.tsx +1 -1
- package/src/components/BooleanSwitchWithLabel.tsx +7 -2
- package/src/components/Button.tsx +16 -17
- package/src/components/DateTimeField.tsx +11 -5
- package/src/components/Dialog.tsx +3 -1
- package/src/components/Menubar.tsx +1 -1
- package/src/components/MultiSelect.tsx +54 -51
- package/src/components/Select.tsx +70 -55
- package/src/components/TextField.tsx +26 -14
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@firecms/ui",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "3.0.0-beta.
|
|
4
|
+
"version": "3.0.0-beta.13",
|
|
5
5
|
"description": "Awesome Firebase/Firestore-based headless open-source CMS",
|
|
6
6
|
"funding": {
|
|
7
7
|
"url": "https://github.com/sponsors/firecmsco"
|
|
@@ -85,6 +85,7 @@
|
|
|
85
85
|
},
|
|
86
86
|
"devDependencies": {
|
|
87
87
|
"@jest/globals": "^29.7.0",
|
|
88
|
+
"@tailwindcss/postcss": "^4.1.4",
|
|
88
89
|
"@testing-library/jest-dom": "^6.6.3",
|
|
89
90
|
"@testing-library/react": "^16.2.0",
|
|
90
91
|
"@testing-library/user-event": "^14.6.1",
|
|
@@ -115,7 +116,7 @@
|
|
|
115
116
|
"index.css",
|
|
116
117
|
"tailwind.config.js"
|
|
117
118
|
],
|
|
118
|
-
"gitHead": "
|
|
119
|
+
"gitHead": "26d5e1f33a7ac00c78e45cd3cb3c397f4ba00821",
|
|
119
120
|
"publishConfig": {
|
|
120
121
|
"access": "public"
|
|
121
122
|
}
|
|
@@ -6,7 +6,7 @@ export type BooleanSwitchProps = {
|
|
|
6
6
|
value: boolean | null;
|
|
7
7
|
className?: string;
|
|
8
8
|
disabled?: boolean;
|
|
9
|
-
size?: "small" | "medium" | "large";
|
|
9
|
+
size?: "smallest" | "small" | "medium" | "large";
|
|
10
10
|
} & ({
|
|
11
11
|
allowIndeterminate: true;
|
|
12
12
|
onValueChange?: (newValue: boolean | null) => void;
|
|
@@ -27,13 +27,13 @@ export type BooleanSwitchWithLabelProps = BooleanSwitchProps & {
|
|
|
27
27
|
export const BooleanSwitchWithLabel = function BooleanSwitchWithLabel({
|
|
28
28
|
value,
|
|
29
29
|
position = "end",
|
|
30
|
+
size = "medium",
|
|
30
31
|
invisible,
|
|
31
32
|
onValueChange,
|
|
32
33
|
error,
|
|
33
34
|
label,
|
|
34
35
|
autoFocus,
|
|
35
36
|
disabled,
|
|
36
|
-
size,
|
|
37
37
|
className,
|
|
38
38
|
fullWidth = true,
|
|
39
39
|
inputClassName,
|
|
@@ -67,7 +67,12 @@ export const BooleanSwitchWithLabel = function BooleanSwitchWithLabel({
|
|
|
67
67
|
"rounded-md max-w-full justify-between box-border relative inline-flex items-center",
|
|
68
68
|
!invisible && focus && !disabled ? focusedClasses : "",
|
|
69
69
|
error ? "text-red-500 dark:text-red-600" : (focus && !disabled ? "text-primary" : (!disabled ? "text-text-primary dark:text-text-primary-dark" : "text-text-secondary dark:text-text-secondary-dark")),
|
|
70
|
-
|
|
70
|
+
{
|
|
71
|
+
"min-h-[28px]": size === "smallest",
|
|
72
|
+
"min-h-[32px]": size === "small",
|
|
73
|
+
"min-h-[42px]": size === "medium",
|
|
74
|
+
"min-h-[64px]": size === "large",
|
|
75
|
+
},
|
|
71
76
|
size === "small" ? "pl-2" : "pl-4",
|
|
72
77
|
size === "small" ? "pr-4" : "pr-6",
|
|
73
78
|
position === "end" ? "flex-row-reverse" : "flex-row",
|
|
@@ -2,21 +2,22 @@
|
|
|
2
2
|
import React from "react";
|
|
3
3
|
import { cls } from "../util";
|
|
4
4
|
|
|
5
|
-
export type ButtonProps<
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
variant?: "filled" | "neutral" | "outlined" | "text";
|
|
5
|
+
export type ButtonProps<C extends React.ElementType = "button"> = {
|
|
6
|
+
children?: React.ReactNode;
|
|
7
|
+
variant?: "filled" | "outlined" | "text";
|
|
9
8
|
disabled?: boolean;
|
|
10
|
-
color?: "primary" | "secondary" | "text" | "error";
|
|
9
|
+
color?: "primary" | "secondary" | "text" | "error" | "neutral";
|
|
11
10
|
size?: "small" | "medium" | "large" | "xl" | "2xl";
|
|
12
11
|
startIcon?: React.ReactNode;
|
|
13
12
|
fullWidth?: boolean;
|
|
14
13
|
className?: string;
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
component?: C;
|
|
15
|
+
onClick?: React.MouseEventHandler<any>;
|
|
16
|
+
} & React.ComponentPropsWithoutRef<C>;
|
|
17
17
|
|
|
18
18
|
const ButtonInner = React.forwardRef<
|
|
19
|
-
|
|
19
|
+
HTMLButtonElement,
|
|
20
|
+
ButtonProps<React.ElementType>
|
|
20
21
|
>(({
|
|
21
22
|
children,
|
|
22
23
|
className,
|
|
@@ -42,29 +43,27 @@ const ButtonInner = React.forwardRef<
|
|
|
42
43
|
"border border-secondary bg-secondary focus:ring-secondary shadow hover:ring-1 hover:ring-secondary text-white hover:text-white": variant === "filled" && color === "secondary" && !disabled,
|
|
43
44
|
"border border-red-500 bg-red-500 hover:bg-red-500 focus:ring-red-500 shadow hover:ring-1 hover:ring-red-600 text-white hover:text-white": variant === "filled" && color === "error" && !disabled,
|
|
44
45
|
"border border-surface-accent-200 bg-surface-accent-200 hover:bg-surface-accent-300 focus:ring-surface-accent-400 shadow hover:ring-1 hover:ring-surface-accent-400 text-text-primary hover:text-text-primary dark:text-text-primary-dark hover:dark:text-text-primary-dark": variant === "filled" && color === "text" && !disabled,
|
|
46
|
+
"border border-transparent bg-surface-100 hover:bg-surface-accent-200 text-text-primary dark:bg-surface-800 dark:hover:bg-surface-accent-700 dark:text-text-primary-dark": variant === "filled" && color === "neutral" && !disabled,
|
|
45
47
|
|
|
46
48
|
// Text Variants
|
|
47
|
-
"border border-transparent text-primary hover:text-primary hover:bg-surface-accent-200 dark:hover:bg-surface-
|
|
48
|
-
"border border-transparent text-secondary hover:text-secondary hover:bg-
|
|
49
|
+
"border border-transparent text-primary hover:text-primary hover:bg-surface-accent-200 hover:bg-opacity-75 dark:hover:bg-surface-accent-800": variant === "text" && color === "primary" && !disabled,
|
|
50
|
+
"border border-transparent text-secondary hover:text-secondary hover:bg-surface-accent-200 hover:bg-opacity-75 dark:hover:bg-surface-accent-800": variant === "text" && color === "secondary" && !disabled,
|
|
49
51
|
"border border-transparent text-red-500 hover:text-red-500 hover:bg-red-500 hover:bg-opacity-10": variant === "text" && color === "error" && !disabled,
|
|
50
52
|
"border border-transparent text-text-primary hover:text-text-primary dark:text-text-primary-dark hover:dark:text-text-primary-dark hover:bg-surface-accent-200 hover:dark:bg-surface-700": variant === "text" && color === "text" && !disabled,
|
|
53
|
+
"border border-transparent text-text-primary hover:text-text-primary hover:bg-surface-accent-200 dark:text-text-primary-dark dark:hover:bg-surface-accent-700": variant === "text" && color === "neutral" && !disabled,
|
|
51
54
|
|
|
52
55
|
// Outlined Variants
|
|
53
56
|
"border border-primary text-primary hover:text-primary hover:bg-primary-bg": variant === "outlined" && color === "primary" && !disabled,
|
|
54
57
|
"border border-secondary text-secondary hover:text-secondary hover:bg-secondary-bg": variant === "outlined" && color === "secondary" && !disabled,
|
|
55
58
|
"border border-red-500 text-red-500 hover:text-red-500 hover:bg-red-500 hover:text-white": variant === "outlined" && color === "error" && !disabled,
|
|
56
59
|
"border border-surface-accent-400 text-text-primary hover:text-text-primary dark:text-text-primary-dark hover:bg-surface-accent-200": variant === "outlined" && color === "text" && !disabled,
|
|
57
|
-
|
|
58
|
-
// Neutral Variants
|
|
59
|
-
"border border-transparent bg-surface-100 hover:bg-surface-accent-200 text-text-primary dark:bg-surface-800 dark:hover:bg-surface-accent-700 dark:text-white": variant === "neutral" && (color === "primary" || color === "text") && !disabled,
|
|
60
|
-
"border border-transparent bg-surface-100 hover:bg-surface-accent-200 text-text-secondary dark:bg-surface-800 dark:hover:bg-surface-accent-700 dark:text-white": variant === "neutral" && color === "secondary" && !disabled,
|
|
61
|
-
"border border-transparent bg-surface-100 hover:bg-surface-accent-200 text-error dark:bg-surface-800 dark:hover:bg-surface-accent-700 dark:text-error": variant === "neutral" && color === "error" && !disabled,
|
|
60
|
+
"border border-surface-400 text-text-primary hover:bg-surface-accent-200 dark:border-surface-600 dark:text-text-primary-dark dark:hover:bg-surface-accent-700": variant === "outlined" && color === "neutral" && !disabled,
|
|
62
61
|
|
|
63
62
|
// Disabled states for all variants
|
|
64
63
|
"text-text-disabled dark:text-text-disabled-dark": disabled,
|
|
65
64
|
"border border-transparent opacity-50": variant === "text" && disabled,
|
|
66
65
|
"border border-surface-500 opacity-50": variant === "outlined" && disabled,
|
|
67
|
-
"border border-transparent bg-surface-300 dark:bg-surface-500 opacity-40":
|
|
66
|
+
"border border-transparent bg-surface-300 dark:bg-surface-500 opacity-40": variant === "filled" && disabled,
|
|
68
67
|
});
|
|
69
68
|
|
|
70
69
|
const sizeClasses = cls(
|
|
@@ -83,7 +82,7 @@ const ButtonInner = React.forwardRef<
|
|
|
83
82
|
ref={ref}
|
|
84
83
|
onClick={props.onClick}
|
|
85
84
|
className={cls(startIcon ? "pl-3" : "", baseClasses, buttonClasses, sizeClasses, className)}
|
|
86
|
-
{...
|
|
85
|
+
{...props}>
|
|
87
86
|
{startIcon}
|
|
88
87
|
{children}
|
|
89
88
|
</Component>
|
|
@@ -16,7 +16,7 @@ export type DateTimeFieldProps = {
|
|
|
16
16
|
disabled?: boolean;
|
|
17
17
|
clearable?: boolean;
|
|
18
18
|
error?: boolean;
|
|
19
|
-
size?: "medium" | "large";
|
|
19
|
+
size?: "smallest" | "small" | "medium" | "large";
|
|
20
20
|
label?: React.ReactNode;
|
|
21
21
|
className?: string;
|
|
22
22
|
style?: React.CSSProperties;
|
|
@@ -38,7 +38,6 @@ export const DateTimeField: React.FC<DateTimeFieldProps> = ({
|
|
|
38
38
|
style,
|
|
39
39
|
inputClassName,
|
|
40
40
|
invisible,
|
|
41
|
-
locale, // Note: The 'locale' prop is not utilized with native inputs as they are managed by the browser.
|
|
42
41
|
}) => {
|
|
43
42
|
const inputRef = useRef<HTMLInputElement>(null);
|
|
44
43
|
const [focused, setFocused] = useState(false);
|
|
@@ -111,7 +110,9 @@ export const DateTimeField: React.FC<DateTimeFieldProps> = ({
|
|
|
111
110
|
!invisible && fieldBackgroundMixin,
|
|
112
111
|
disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin,
|
|
113
112
|
{
|
|
114
|
-
"min-h-[
|
|
113
|
+
"min-h-[28px]": size === "smallest",
|
|
114
|
+
"min-h-[32px]": size === "small",
|
|
115
|
+
"min-h-[42px]": size === "medium",
|
|
115
116
|
"min-h-[64px]": size === "large",
|
|
116
117
|
},
|
|
117
118
|
className
|
|
@@ -153,7 +154,12 @@ export const DateTimeField: React.FC<DateTimeFieldProps> = ({
|
|
|
153
154
|
"w-full outline-none bg-transparent leading-normal text-base px-3",
|
|
154
155
|
clearable ? "pr-14" : "pr-12",
|
|
155
156
|
"rounded-md",
|
|
156
|
-
|
|
157
|
+
{
|
|
158
|
+
"min-h-[28px]": size === "smallest",
|
|
159
|
+
"min-h-[32px]": size === "small",
|
|
160
|
+
"min-h-[42px]": size === "medium",
|
|
161
|
+
"min-h-[64px]": size === "large",
|
|
162
|
+
},
|
|
157
163
|
label ? "pt-8 pb-2" : "py-2",
|
|
158
164
|
inputClassName,
|
|
159
165
|
disabled &&
|
|
@@ -180,7 +186,7 @@ export const DateTimeField: React.FC<DateTimeFieldProps> = ({
|
|
|
180
186
|
</div>
|
|
181
187
|
{invalidValue && (
|
|
182
188
|
<div className="flex items-center m-2">
|
|
183
|
-
<ErrorIcon size={"
|
|
189
|
+
<ErrorIcon size={"small"} color={"error"}/>
|
|
184
190
|
<div className="pl-2">
|
|
185
191
|
<Typography variant={"body2"}>
|
|
186
192
|
Invalid date value for this field
|
|
@@ -9,6 +9,7 @@ export type DialogProps = {
|
|
|
9
9
|
onOpenChange?: (open: boolean) => void;
|
|
10
10
|
children: React.ReactNode;
|
|
11
11
|
className?: string;
|
|
12
|
+
containerClassName?: string;
|
|
12
13
|
fullWidth?: boolean;
|
|
13
14
|
fullHeight?: boolean;
|
|
14
15
|
fullScreen?: boolean;
|
|
@@ -41,6 +42,7 @@ export const Dialog = ({
|
|
|
41
42
|
onOpenChange,
|
|
42
43
|
children,
|
|
43
44
|
className,
|
|
45
|
+
containerClassName,
|
|
44
46
|
fullWidth = true,
|
|
45
47
|
fullHeight,
|
|
46
48
|
fullScreen,
|
|
@@ -73,7 +75,7 @@ export const Dialog = ({
|
|
|
73
75
|
onOpenChange={onOpenChange}>
|
|
74
76
|
<DialogPrimitive.Portal>
|
|
75
77
|
|
|
76
|
-
<div className={"fixed inset-0 z-30"}>
|
|
78
|
+
<div className={cls("fixed inset-0 z-30", containerClassName)}>
|
|
77
79
|
|
|
78
80
|
<DialogPrimitive.Overlay
|
|
79
81
|
className={cls("fixed inset-0 transition-opacity z-20 ease-in-out duration-200 bg-black bg-opacity-50 dark:bg-opacity-60 backdrop-blur-sm ",
|
|
@@ -44,7 +44,7 @@ export function MenubarTrigger({
|
|
|
44
44
|
return (
|
|
45
45
|
<MenubarPrimitive.Trigger
|
|
46
46
|
onSelect={onSelect}
|
|
47
|
-
className={cls("py-2 px-3 outline-none select-none font-medium leading-none rounded text-text-primary dark:text-text-primary-dark text-[13px] flex items-center justify-between gap-[2px] data-[highlighted]:bg-surface-accent-100 data-[highlighted]:dark:bg-surface-800 data-[state=open]:bg-surface-accent-100 data-[state=open]:dark:bg-surface-800 hover:bg-surface-accent-200 hover:bg-opacity-75 dark:hover:bg-surface-
|
|
47
|
+
className={cls("py-2 px-3 outline-none select-none font-medium leading-none rounded text-text-primary dark:text-text-primary-dark text-[13px] flex items-center justify-between gap-[2px] data-[highlighted]:bg-surface-accent-100 data-[highlighted]:dark:bg-surface-800 data-[state=open]:bg-surface-accent-100 data-[state=open]:dark:bg-surface-800 hover:bg-surface-accent-200 hover:bg-opacity-75 dark:hover:bg-surface-accent-800",
|
|
48
48
|
className)}>
|
|
49
49
|
{children}
|
|
50
50
|
</MenubarPrimitive.Trigger>
|
|
@@ -18,41 +18,33 @@ import {
|
|
|
18
18
|
} from "../styles";
|
|
19
19
|
import { useInjectStyles } from "../hooks";
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
export type MultiSelectValue = string | number | boolean;
|
|
22
|
+
|
|
23
|
+
// Make the context properly generic
|
|
24
|
+
interface MultiSelectContextProps<T extends MultiSelectValue = string> {
|
|
25
|
+
fieldValue?: T[];
|
|
26
|
+
onItemClick: (v: T) => void;
|
|
24
27
|
}
|
|
25
28
|
|
|
26
|
-
|
|
29
|
+
// Create a proper generic context
|
|
30
|
+
export const MultiSelectContext = React.createContext<MultiSelectContextProps<any>>({} as any);
|
|
27
31
|
|
|
28
32
|
/**
|
|
29
33
|
* Props for MultiSelect component
|
|
30
34
|
*/
|
|
31
|
-
interface MultiSelectProps {
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* The modality of the popover. When set to true, interaction with outside elements
|
|
35
|
-
* will be disabled and only popover content will be visible to screen readers.
|
|
36
|
-
* Optional, defaults to false.
|
|
37
|
-
*/
|
|
35
|
+
interface MultiSelectProps<T extends MultiSelectValue = string> {
|
|
38
36
|
modalPopover?: boolean;
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Additional class names to apply custom styles to the multi-select component.
|
|
42
|
-
* Optional, can be used to add custom styles.
|
|
43
|
-
*/
|
|
44
37
|
className?: string;
|
|
45
|
-
|
|
46
38
|
open?: boolean,
|
|
47
39
|
name?: string,
|
|
48
40
|
id?: string,
|
|
49
41
|
onOpenChange?: (open: boolean) => void,
|
|
50
|
-
value?:
|
|
42
|
+
value?: T[],
|
|
51
43
|
inputClassName?: string,
|
|
52
44
|
onChange?: React.EventHandler<ChangeEvent<HTMLSelectElement>>,
|
|
53
|
-
onValueChange?: (updatedValue:
|
|
45
|
+
onValueChange?: (updatedValue: T[]) => void,
|
|
54
46
|
placeholder?: React.ReactNode,
|
|
55
|
-
size?: "small" | "medium",
|
|
47
|
+
size?: "smallest" | "small" | "medium" | "large",
|
|
56
48
|
useChips?: boolean,
|
|
57
49
|
label?: React.ReactNode | string,
|
|
58
50
|
disabled?: boolean,
|
|
@@ -66,9 +58,10 @@ interface MultiSelectProps {
|
|
|
66
58
|
padding?: boolean,
|
|
67
59
|
invisible?: boolean,
|
|
68
60
|
children: React.ReactNode;
|
|
69
|
-
renderValues?: (values:
|
|
61
|
+
renderValues?: (values: T[]) => React.ReactNode;
|
|
70
62
|
}
|
|
71
63
|
|
|
64
|
+
// Use generic type for the forwarded ref
|
|
72
65
|
export const MultiSelect = React.forwardRef<
|
|
73
66
|
HTMLButtonElement,
|
|
74
67
|
MultiSelectProps
|
|
@@ -76,7 +69,7 @@ export const MultiSelect = React.forwardRef<
|
|
|
76
69
|
(
|
|
77
70
|
{
|
|
78
71
|
value,
|
|
79
|
-
size,
|
|
72
|
+
size = "large",
|
|
80
73
|
label,
|
|
81
74
|
error,
|
|
82
75
|
onValueChange,
|
|
@@ -95,8 +88,9 @@ export const MultiSelect = React.forwardRef<
|
|
|
95
88
|
},
|
|
96
89
|
ref
|
|
97
90
|
) => {
|
|
91
|
+
// Properly type the state variables to match the generic props
|
|
98
92
|
const [isPopoverOpen, setIsPopoverOpen] = React.useState(open ?? false);
|
|
99
|
-
const [selectedValues, setSelectedValues] = React.useState<
|
|
93
|
+
const [selectedValues, setSelectedValues] = React.useState<any[]>(value ?? []);
|
|
100
94
|
|
|
101
95
|
const onPopoverOpenChange = (open: boolean) => {
|
|
102
96
|
setIsPopoverOpen(open);
|
|
@@ -115,24 +109,24 @@ export const MultiSelect = React.forwardRef<
|
|
|
115
109
|
return child.props.value;
|
|
116
110
|
}
|
|
117
111
|
return null;
|
|
118
|
-
}).filter(Boolean) as
|
|
112
|
+
}).filter(Boolean) as any[]
|
|
119
113
|
: [];
|
|
120
114
|
|
|
121
115
|
React.useEffect(() => {
|
|
122
116
|
setSelectedValues(value ?? []);
|
|
123
117
|
}, [value]);
|
|
124
118
|
|
|
125
|
-
function onItemClick(newValue:
|
|
126
|
-
let newSelectedValues:
|
|
127
|
-
if (selectedValues.
|
|
128
|
-
newSelectedValues = selectedValues.filter(
|
|
119
|
+
function onItemClick(newValue: any) {
|
|
120
|
+
let newSelectedValues: any[];
|
|
121
|
+
if (selectedValues.some(v => String(v) === String(newValue))) {
|
|
122
|
+
newSelectedValues = selectedValues.filter(v => String(v) !== String(newValue));
|
|
129
123
|
} else {
|
|
130
124
|
newSelectedValues = [...selectedValues, newValue];
|
|
131
125
|
}
|
|
132
126
|
updateValues(newSelectedValues);
|
|
133
127
|
}
|
|
134
128
|
|
|
135
|
-
function updateValues(values:
|
|
129
|
+
function updateValues(values: any[]) {
|
|
136
130
|
setSelectedValues(values);
|
|
137
131
|
onValueChange?.(values);
|
|
138
132
|
}
|
|
@@ -149,9 +143,9 @@ export const MultiSelect = React.forwardRef<
|
|
|
149
143
|
}
|
|
150
144
|
};
|
|
151
145
|
|
|
152
|
-
const toggleOption = (value:
|
|
153
|
-
const newSelectedValues = selectedValues.
|
|
154
|
-
? selectedValues.filter(
|
|
146
|
+
const toggleOption = (value: any) => {
|
|
147
|
+
const newSelectedValues = selectedValues.some(v => String(v) === String(value))
|
|
148
|
+
? selectedValues.filter(v => String(v) !== String(value))
|
|
155
149
|
: [...selectedValues, value];
|
|
156
150
|
updateValues(newSelectedValues);
|
|
157
151
|
};
|
|
@@ -199,9 +193,20 @@ export const MultiSelect = React.forwardRef<
|
|
|
199
193
|
ref={ref}
|
|
200
194
|
onClick={handleTogglePopover}
|
|
201
195
|
className={cls(
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
196
|
+
{
|
|
197
|
+
"min-h-[28px]": size === "smallest",
|
|
198
|
+
"min-h-[32px]": size === "small",
|
|
199
|
+
"min-h-[42px]": size === "medium",
|
|
200
|
+
"min-h-[64px]": size === "large",
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
"py-1": size === "small" || size === "smallest",
|
|
204
|
+
"py-2": size === "medium" || size === "large",
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
"px-2": size === "small" || size === "smallest",
|
|
208
|
+
"px-4": size === "medium" || size === "large",
|
|
209
|
+
},
|
|
205
210
|
"select-none rounded-md text-sm",
|
|
206
211
|
invisible ? fieldBackgroundInvisibleMixin : fieldBackgroundMixin,
|
|
207
212
|
disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin,
|
|
@@ -222,14 +227,14 @@ export const MultiSelect = React.forwardRef<
|
|
|
222
227
|
}
|
|
223
228
|
}).filter(Boolean);
|
|
224
229
|
|
|
225
|
-
const option = childrenProps.find((o) => o.value === value);
|
|
230
|
+
const option = childrenProps.find((o) => String(o.value) === String(value));
|
|
226
231
|
if (!useChips) {
|
|
227
232
|
return option?.children;
|
|
228
233
|
}
|
|
229
234
|
return (
|
|
230
235
|
<Chip
|
|
231
236
|
size={"medium"}
|
|
232
|
-
key={value}
|
|
237
|
+
key={String(value)}
|
|
233
238
|
className={cls("flex flex-row items-center p-1")}
|
|
234
239
|
>
|
|
235
240
|
{option?.children}
|
|
@@ -255,7 +260,7 @@ export const MultiSelect = React.forwardRef<
|
|
|
255
260
|
/>}
|
|
256
261
|
<div className={cls("px-2 h-full flex items-center")}>
|
|
257
262
|
<KeyboardArrowDownIcon size={"small"}
|
|
258
|
-
|
|
263
|
+
className={cls("transition", isPopoverOpen ? "rotate-180" : "")}/>
|
|
259
264
|
</div>
|
|
260
265
|
</div>
|
|
261
266
|
</div>
|
|
@@ -266,7 +271,7 @@ export const MultiSelect = React.forwardRef<
|
|
|
266
271
|
</span>
|
|
267
272
|
<div className={cls("px-2 h-full flex items-center")}>
|
|
268
273
|
<KeyboardArrowDownIcon size={"small"}
|
|
269
|
-
|
|
274
|
+
className={cls("transition", isPopoverOpen ? "rotate-180" : "")}/>
|
|
270
275
|
</div>
|
|
271
276
|
</div>
|
|
272
277
|
)}
|
|
@@ -319,7 +324,6 @@ export const MultiSelect = React.forwardRef<
|
|
|
319
324
|
</CommandPrimitive.Item>}
|
|
320
325
|
{children}
|
|
321
326
|
</CommandPrimitive.Group>
|
|
322
|
-
|
|
323
327
|
</CommandPrimitive.List>
|
|
324
328
|
</CommandPrimitive>
|
|
325
329
|
</PopoverPrimitive.Content>
|
|
@@ -331,18 +335,17 @@ export const MultiSelect = React.forwardRef<
|
|
|
331
335
|
|
|
332
336
|
MultiSelect.displayName = "MultiSelect";
|
|
333
337
|
|
|
334
|
-
export interface MultiSelectItemProps {
|
|
335
|
-
value:
|
|
338
|
+
export interface MultiSelectItemProps<T extends MultiSelectValue = string> {
|
|
339
|
+
value: T;
|
|
336
340
|
children?: React.ReactNode,
|
|
337
341
|
className?: string;
|
|
338
342
|
}
|
|
339
343
|
|
|
340
|
-
export function MultiSelectItem({
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
344
|
+
export function MultiSelectItem<T extends MultiSelectValue = string>({
|
|
345
|
+
children,
|
|
346
|
+
value,
|
|
347
|
+
className
|
|
348
|
+
}: MultiSelectItemProps<T>) {
|
|
346
349
|
const context = React.useContext(MultiSelectContext);
|
|
347
350
|
if (!context) throw new Error("MultiSelectItem must be used inside a MultiSelect");
|
|
348
351
|
const {
|
|
@@ -350,9 +353,9 @@ export function MultiSelectItem({
|
|
|
350
353
|
onItemClick
|
|
351
354
|
} = context;
|
|
352
355
|
|
|
353
|
-
const isSelected = (fieldValue ?? []).
|
|
356
|
+
const isSelected = (fieldValue ?? []).some(v => String(v) === String(value));
|
|
357
|
+
|
|
354
358
|
return <CommandPrimitive.Item
|
|
355
|
-
// value={value}
|
|
356
359
|
onMouseDown={(e) => {
|
|
357
360
|
e.preventDefault();
|
|
358
361
|
e.stopPropagation();
|
|
@@ -375,9 +378,9 @@ export function MultiSelectItem({
|
|
|
375
378
|
<InnerCheckBox checked={isSelected}/>
|
|
376
379
|
{children}
|
|
377
380
|
</CommandPrimitive.Item>;
|
|
378
|
-
|
|
379
381
|
}
|
|
380
382
|
|
|
383
|
+
|
|
381
384
|
function InnerCheckBox({ checked }: { checked: boolean }) {
|
|
382
385
|
return <div className={cls(
|
|
383
386
|
"p-2",
|