@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
|
@@ -13,20 +13,22 @@ import { CheckIcon, KeyboardArrowDownIcon } from "../icons";
|
|
|
13
13
|
import { cls } from "../util";
|
|
14
14
|
import { SelectInputLabel } from "./common/SelectInputLabel";
|
|
15
15
|
|
|
16
|
-
export type
|
|
16
|
+
export type SelectValue = string | number | boolean;
|
|
17
|
+
|
|
18
|
+
export type SelectProps<T extends SelectValue = string> = {
|
|
17
19
|
open?: boolean,
|
|
18
20
|
name?: string,
|
|
19
21
|
fullWidth?: boolean,
|
|
20
22
|
id?: string,
|
|
21
23
|
onOpenChange?: (open: boolean) => void,
|
|
22
|
-
value?:
|
|
24
|
+
value?: T,
|
|
23
25
|
className?: string,
|
|
24
26
|
inputClassName?: string,
|
|
25
27
|
onChange?: React.EventHandler<ChangeEvent<HTMLSelectElement>>,
|
|
26
|
-
onValueChange?: (updatedValue:
|
|
28
|
+
onValueChange?: (updatedValue: T) => void,
|
|
27
29
|
placeholder?: React.ReactNode,
|
|
28
|
-
renderValue?: (value:
|
|
29
|
-
size?: "small" | "medium" | "large",
|
|
30
|
+
renderValue?: (value: T) => React.ReactNode,
|
|
31
|
+
size?: "smallest" | "small" | "medium" | "large",
|
|
30
32
|
label?: React.ReactNode | string,
|
|
31
33
|
disabled?: boolean,
|
|
32
34
|
error?: boolean,
|
|
@@ -39,30 +41,30 @@ export type SelectProps = {
|
|
|
39
41
|
};
|
|
40
42
|
|
|
41
43
|
export const Select = forwardRef<HTMLDivElement, SelectProps>(({
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
44
|
+
inputRef,
|
|
45
|
+
open,
|
|
46
|
+
name,
|
|
47
|
+
fullWidth = false,
|
|
48
|
+
id,
|
|
49
|
+
onOpenChange,
|
|
50
|
+
value,
|
|
51
|
+
onChange,
|
|
52
|
+
onValueChange,
|
|
53
|
+
className,
|
|
54
|
+
inputClassName,
|
|
55
|
+
placeholder,
|
|
56
|
+
renderValue,
|
|
57
|
+
label,
|
|
58
|
+
size = "large",
|
|
59
|
+
error,
|
|
60
|
+
disabled,
|
|
61
|
+
padding = true,
|
|
62
|
+
position = "item-aligned",
|
|
63
|
+
endAdornment,
|
|
64
|
+
invisible,
|
|
65
|
+
children,
|
|
66
|
+
...props
|
|
67
|
+
}, ref) => {
|
|
66
68
|
|
|
67
69
|
const [openInternal, setOpenInternal] = useState(open ?? false);
|
|
68
70
|
|
|
@@ -71,24 +73,32 @@ export const Select = forwardRef<HTMLDivElement, SelectProps>(({
|
|
|
71
73
|
}, [open]);
|
|
72
74
|
|
|
73
75
|
const onValueChangeInternal = useCallback((newValue: string) => {
|
|
74
|
-
|
|
76
|
+
// Convert string value to appropriate type
|
|
77
|
+
let typedValue: SelectValue = newValue;
|
|
78
|
+
if (newValue === "true") typedValue = true;
|
|
79
|
+
else if (newValue === "false") typedValue = false;
|
|
80
|
+
else if (!isNaN(Number(newValue)) && newValue.trim() !== '') typedValue = Number(newValue);
|
|
81
|
+
|
|
82
|
+
onValueChange?.(typedValue as any);
|
|
75
83
|
if (onChange) {
|
|
76
84
|
const event = {
|
|
77
85
|
target: {
|
|
78
86
|
name,
|
|
79
|
-
value:
|
|
87
|
+
value: typedValue
|
|
80
88
|
}
|
|
81
|
-
} as ChangeEvent<HTMLSelectElement>;
|
|
89
|
+
} as unknown as ChangeEvent<HTMLSelectElement>;
|
|
82
90
|
onChange(event);
|
|
83
91
|
}
|
|
84
|
-
}, [onChange,
|
|
92
|
+
}, [onChange, onValueChange, name]);
|
|
85
93
|
|
|
86
94
|
const hasValue = Array.isArray(value) ? value.length > 0 : (value != null && value !== "" && value !== undefined);
|
|
95
|
+
// Convert non-string values to strings for Radix UI
|
|
96
|
+
const stringValue = value !== undefined ? String(value) : undefined;
|
|
87
97
|
|
|
88
98
|
return (
|
|
89
99
|
<SelectPrimitive.Root
|
|
90
100
|
name={name}
|
|
91
|
-
value={
|
|
101
|
+
value={stringValue}
|
|
92
102
|
open={openInternal}
|
|
93
103
|
disabled={disabled}
|
|
94
104
|
onValueChange={onValueChangeInternal}
|
|
@@ -105,7 +115,8 @@ export const Select = forwardRef<HTMLDivElement, SelectProps>(({
|
|
|
105
115
|
"relative flex items-center",
|
|
106
116
|
className,
|
|
107
117
|
{
|
|
108
|
-
"min-h-[28px]": size === "
|
|
118
|
+
"min-h-[28px]": size === "smallest",
|
|
119
|
+
"min-h-[32px]": size === "small",
|
|
109
120
|
"min-h-[42px]": size === "medium",
|
|
110
121
|
"min-h-[64px]": size === "large",
|
|
111
122
|
"w-fit": !fullWidth,
|
|
@@ -122,7 +133,7 @@ export const Select = forwardRef<HTMLDivElement, SelectProps>(({
|
|
|
122
133
|
padding ? {
|
|
123
134
|
"px-4": size === "large",
|
|
124
135
|
"px-3": size === "medium",
|
|
125
|
-
"px-2": size === "small"
|
|
136
|
+
"px-2": size === "small" || size === "smallest",
|
|
126
137
|
} : "",
|
|
127
138
|
"outline-none focus:outline-none",
|
|
128
139
|
"select-none rounded-md text-sm",
|
|
@@ -131,7 +142,8 @@ export const Select = forwardRef<HTMLDivElement, SelectProps>(({
|
|
|
131
142
|
disabled ? "text-surface-accent-600 dark:text-surface-accent-400" : "text-surface-accent-800 dark:text-white",
|
|
132
143
|
"relative flex flex-row items-center",
|
|
133
144
|
{
|
|
134
|
-
"min-h-[28px]": size === "
|
|
145
|
+
"min-h-[28px]": size === "smallest",
|
|
146
|
+
"min-h-[32px]": size === "small",
|
|
135
147
|
"min-h-[42px]": size === "medium",
|
|
136
148
|
"min-h-[64px]": size === "large",
|
|
137
149
|
"w-full": fullWidth,
|
|
@@ -145,7 +157,8 @@ export const Select = forwardRef<HTMLDivElement, SelectProps>(({
|
|
|
145
157
|
"flex-grow max-w-full flex flex-row gap-2 items-center",
|
|
146
158
|
"overflow-visible",
|
|
147
159
|
{
|
|
148
|
-
"min-h-[28px]": size === "
|
|
160
|
+
"min-h-[28px]": size === "smallest",
|
|
161
|
+
"min-h-[32px]": size === "small",
|
|
149
162
|
"min-h-[42px]": size === "medium",
|
|
150
163
|
"min-h-[64px]": size === "large"
|
|
151
164
|
}
|
|
@@ -157,10 +170,9 @@ export const Select = forwardRef<HTMLDivElement, SelectProps>(({
|
|
|
157
170
|
}}
|
|
158
171
|
placeholder={placeholder}
|
|
159
172
|
className={"w-full"}>
|
|
160
|
-
{hasValue && value && renderValue ? renderValue(value) : placeholder}
|
|
173
|
+
{hasValue && value !== undefined && renderValue ? renderValue(value) : placeholder}
|
|
161
174
|
{/*{hasValue && !renderValue && value}*/}
|
|
162
175
|
{hasValue && !renderValue && (() => {
|
|
163
|
-
|
|
164
176
|
// @ts-ignore
|
|
165
177
|
const childrenProps: SelectItemProps[] = Children.map(children, (child) => {
|
|
166
178
|
if (React.isValidElement(child)) {
|
|
@@ -168,7 +180,7 @@ export const Select = forwardRef<HTMLDivElement, SelectProps>(({
|
|
|
168
180
|
}
|
|
169
181
|
}).filter(Boolean);
|
|
170
182
|
|
|
171
|
-
const option = childrenProps.find((o) => o.value === value);
|
|
183
|
+
const option = childrenProps.find((o) => String(o.value) === String(value));
|
|
172
184
|
return option?.children;
|
|
173
185
|
})()}
|
|
174
186
|
|
|
@@ -187,10 +199,10 @@ export const Select = forwardRef<HTMLDivElement, SelectProps>(({
|
|
|
187
199
|
)}
|
|
188
200
|
<SelectPrimitive.Icon asChild>
|
|
189
201
|
<KeyboardArrowDownIcon size={"medium"}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
202
|
+
className={cls("transition", open ? "rotate-180" : "", {
|
|
203
|
+
"px-2": size === "large",
|
|
204
|
+
"px-1": size === "medium" || size === "small",
|
|
205
|
+
})}/>
|
|
194
206
|
</SelectPrimitive.Icon>
|
|
195
207
|
</div>
|
|
196
208
|
</SelectPrimitive.Trigger>
|
|
@@ -211,22 +223,25 @@ export const Select = forwardRef<HTMLDivElement, SelectProps>(({
|
|
|
211
223
|
|
|
212
224
|
Select.displayName = "Select";
|
|
213
225
|
|
|
214
|
-
export type SelectItemProps = {
|
|
215
|
-
value:
|
|
226
|
+
export type SelectItemProps<T extends SelectValue = string> = {
|
|
227
|
+
value: T,
|
|
216
228
|
children?: React.ReactNode,
|
|
217
229
|
disabled?: boolean,
|
|
218
230
|
className?: string,
|
|
219
231
|
};
|
|
220
232
|
|
|
221
|
-
export function SelectItem({
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
233
|
+
export function SelectItem<T extends SelectValue = string>({
|
|
234
|
+
value,
|
|
235
|
+
children,
|
|
236
|
+
disabled,
|
|
237
|
+
className
|
|
238
|
+
}: SelectItemProps<T>) {
|
|
239
|
+
// Convert value to string for Radix UI
|
|
240
|
+
const stringValue = String(value);
|
|
241
|
+
|
|
227
242
|
return <SelectPrimitive.Item
|
|
228
|
-
key={
|
|
229
|
-
value={
|
|
243
|
+
key={stringValue}
|
|
244
|
+
value={stringValue}
|
|
230
245
|
disabled={disabled}
|
|
231
246
|
className={cls(
|
|
232
247
|
"w-full",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import React, {
|
|
2
|
+
import React, { ForwardedRef, forwardRef, useEffect, useRef } from "react";
|
|
3
3
|
|
|
4
4
|
import { TextareaAutosize } from "./TextareaAutosize";
|
|
5
5
|
import {
|
|
@@ -33,19 +33,27 @@ export type TextFieldProps<T extends string | number> = {
|
|
|
33
33
|
onChange?: (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
|
|
34
34
|
label?: React.ReactNode;
|
|
35
35
|
multiline?: boolean;
|
|
36
|
-
rows?: number;
|
|
37
36
|
disabled?: boolean;
|
|
38
37
|
invisible?: boolean;
|
|
39
38
|
error?: boolean;
|
|
40
39
|
endAdornment?: React.ReactNode;
|
|
41
40
|
autoFocus?: boolean;
|
|
42
41
|
placeholder?: string;
|
|
43
|
-
size?: "small" | "medium" | "large";
|
|
42
|
+
size?: "smallest" | "small" | "medium" | "large";
|
|
44
43
|
className?: string;
|
|
45
44
|
style?: React.CSSProperties;
|
|
46
45
|
inputClassName?: string;
|
|
47
46
|
inputStyle?: React.CSSProperties;
|
|
48
47
|
inputRef?: React.ForwardedRef<any>;
|
|
48
|
+
/**
|
|
49
|
+
* Maximum number of rows to display.
|
|
50
|
+
*/
|
|
51
|
+
maxRows?: number | string;
|
|
52
|
+
/**
|
|
53
|
+
* Minimum number of rows to display.
|
|
54
|
+
* @default 1
|
|
55
|
+
*/
|
|
56
|
+
minRows?: number | string;
|
|
49
57
|
} & Omit<React.InputHTMLAttributes<HTMLInputElement>, "size">;
|
|
50
58
|
|
|
51
59
|
export const TextField = forwardRef<HTMLDivElement, TextFieldProps<string | number>>(
|
|
@@ -57,7 +65,8 @@ export const TextField = forwardRef<HTMLDivElement, TextFieldProps<string | numb
|
|
|
57
65
|
type = "text",
|
|
58
66
|
multiline = false,
|
|
59
67
|
invisible,
|
|
60
|
-
|
|
68
|
+
maxRows,
|
|
69
|
+
minRows,
|
|
61
70
|
disabled,
|
|
62
71
|
error,
|
|
63
72
|
endAdornment,
|
|
@@ -101,7 +110,8 @@ export const TextField = forwardRef<HTMLDivElement, TextFieldProps<string | numb
|
|
|
101
110
|
ref={inputRef}
|
|
102
111
|
placeholder={focused || hasValue || !label ? placeholder : undefined}
|
|
103
112
|
autoFocus={autoFocus}
|
|
104
|
-
|
|
113
|
+
minRows={minRows}
|
|
114
|
+
maxRows={maxRows}
|
|
105
115
|
value={value ?? ""}
|
|
106
116
|
onChange={onChange}
|
|
107
117
|
style={inputStyle}
|
|
@@ -124,11 +134,12 @@ export const TextField = forwardRef<HTMLDivElement, TextFieldProps<string | numb
|
|
|
124
134
|
"focused:text-text-primary focused:dark:text-text-primary-dark",
|
|
125
135
|
invisible ? focusedInvisibleMixin : "",
|
|
126
136
|
disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin,
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
: size === "
|
|
130
|
-
|
|
131
|
-
|
|
137
|
+
{
|
|
138
|
+
"min-h-[28px]": size === "smallest",
|
|
139
|
+
"min-h-[32px]": size === "small",
|
|
140
|
+
"min-h-[42px]": size === "medium",
|
|
141
|
+
"min-h-[64px]": size === "large",
|
|
142
|
+
},
|
|
132
143
|
label
|
|
133
144
|
? size === "large"
|
|
134
145
|
? "pt-8 pb-2"
|
|
@@ -158,9 +169,10 @@ export const TextField = forwardRef<HTMLDivElement, TextFieldProps<string | numb
|
|
|
158
169
|
disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin,
|
|
159
170
|
error ? "border border-red-500 dark:border-red-600" : "",
|
|
160
171
|
{
|
|
161
|
-
"min-h-[
|
|
162
|
-
"min-h-[
|
|
163
|
-
"min-h-[
|
|
172
|
+
"min-h-[28px]": size === "smallest",
|
|
173
|
+
"min-h-[32px]": size === "small",
|
|
174
|
+
"min-h-[42px]": size === "medium",
|
|
175
|
+
"min-h-[64px]": size === "large",
|
|
164
176
|
},
|
|
165
177
|
className
|
|
166
178
|
)}
|
|
@@ -193,7 +205,7 @@ export const TextField = forwardRef<HTMLDivElement, TextFieldProps<string | numb
|
|
|
193
205
|
{
|
|
194
206
|
"mr-4": size === "large",
|
|
195
207
|
"mr-3": size === "medium",
|
|
196
|
-
"mr-2": size === "small",
|
|
208
|
+
"mr-2": size === "small" || size === "smallest",
|
|
197
209
|
}
|
|
198
210
|
)}
|
|
199
211
|
>
|