@firecms/ui 3.0.0-beta.12 → 3.0.0-beta.14
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/Autocomplete.d.ts +4 -2
- 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 +11 -9
- package/dist/components/TextField.d.ts +20 -4
- package/dist/index.css +1 -0
- package/dist/index.es.js +651 -559
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +651 -559
- package/dist/index.umd.js.map +1 -1
- package/package.json +4 -3
- package/src/components/Autocomplete.tsx +10 -5
- 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/LoadingButton.tsx +1 -1
- package/src/components/Menubar.tsx +1 -1
- package/src/components/MultiSelect.tsx +55 -53
- package/src/components/Select.tsx +62 -42
- package/src/components/TextField.tsx +26 -14
- package/src/icons/Icon.tsx +1 -1
- package/src/index.css +1 -0
- package/src/material-icons.woff2 +0 -0
|
@@ -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,
|
|
@@ -36,6 +38,7 @@ export type SelectProps = {
|
|
|
36
38
|
padding?: boolean,
|
|
37
39
|
invisible?: boolean,
|
|
38
40
|
children?: React.ReactNode;
|
|
41
|
+
dataType?: "string" | "number" | "boolean";
|
|
39
42
|
};
|
|
40
43
|
|
|
41
44
|
export const Select = forwardRef<HTMLDivElement, SelectProps>(({
|
|
@@ -61,6 +64,7 @@ export const Select = forwardRef<HTMLDivElement, SelectProps>(({
|
|
|
61
64
|
endAdornment,
|
|
62
65
|
invisible,
|
|
63
66
|
children,
|
|
67
|
+
dataType = "string",
|
|
64
68
|
...props
|
|
65
69
|
}, ref) => {
|
|
66
70
|
|
|
@@ -71,24 +75,35 @@ export const Select = forwardRef<HTMLDivElement, SelectProps>(({
|
|
|
71
75
|
}, [open]);
|
|
72
76
|
|
|
73
77
|
const onValueChangeInternal = useCallback((newValue: string) => {
|
|
74
|
-
|
|
78
|
+
|
|
79
|
+
let typedValue: SelectValue = newValue;
|
|
80
|
+
if (dataType === "boolean") {
|
|
81
|
+
if (newValue === "true") typedValue = true;
|
|
82
|
+
else if (newValue === "false") typedValue = false;
|
|
83
|
+
} else if (dataType === "number") {
|
|
84
|
+
if (!isNaN(Number(newValue)) && newValue.trim() !== "") typedValue = Number(newValue);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
onValueChange?.(typedValue as any);
|
|
75
88
|
if (onChange) {
|
|
76
89
|
const event = {
|
|
77
90
|
target: {
|
|
78
91
|
name,
|
|
79
|
-
value:
|
|
92
|
+
value: typedValue
|
|
80
93
|
}
|
|
81
|
-
} as ChangeEvent<HTMLSelectElement>;
|
|
94
|
+
} as unknown as ChangeEvent<HTMLSelectElement>;
|
|
82
95
|
onChange(event);
|
|
83
96
|
}
|
|
84
|
-
}, [onChange,
|
|
97
|
+
}, [onChange, onValueChange, name]);
|
|
85
98
|
|
|
86
99
|
const hasValue = Array.isArray(value) ? value.length > 0 : (value != null && value !== "" && value !== undefined);
|
|
100
|
+
// Convert non-string values to strings for Radix UI
|
|
101
|
+
const stringValue = value !== undefined ? String(value) : undefined;
|
|
87
102
|
|
|
88
103
|
return (
|
|
89
104
|
<SelectPrimitive.Root
|
|
90
105
|
name={name}
|
|
91
|
-
value={
|
|
106
|
+
value={stringValue}
|
|
92
107
|
open={openInternal}
|
|
93
108
|
disabled={disabled}
|
|
94
109
|
onValueChange={onValueChangeInternal}
|
|
@@ -105,7 +120,8 @@ export const Select = forwardRef<HTMLDivElement, SelectProps>(({
|
|
|
105
120
|
"relative flex items-center",
|
|
106
121
|
className,
|
|
107
122
|
{
|
|
108
|
-
"min-h-[28px]": size === "
|
|
123
|
+
"min-h-[28px]": size === "smallest",
|
|
124
|
+
"min-h-[32px]": size === "small",
|
|
109
125
|
"min-h-[42px]": size === "medium",
|
|
110
126
|
"min-h-[64px]": size === "large",
|
|
111
127
|
"w-fit": !fullWidth,
|
|
@@ -122,7 +138,7 @@ export const Select = forwardRef<HTMLDivElement, SelectProps>(({
|
|
|
122
138
|
padding ? {
|
|
123
139
|
"px-4": size === "large",
|
|
124
140
|
"px-3": size === "medium",
|
|
125
|
-
"px-2": size === "small"
|
|
141
|
+
"px-2": size === "small" || size === "smallest",
|
|
126
142
|
} : "",
|
|
127
143
|
"outline-none focus:outline-none",
|
|
128
144
|
"select-none rounded-md text-sm",
|
|
@@ -131,7 +147,8 @@ export const Select = forwardRef<HTMLDivElement, SelectProps>(({
|
|
|
131
147
|
disabled ? "text-surface-accent-600 dark:text-surface-accent-400" : "text-surface-accent-800 dark:text-white",
|
|
132
148
|
"relative flex flex-row items-center",
|
|
133
149
|
{
|
|
134
|
-
"min-h-[28px]": size === "
|
|
150
|
+
"min-h-[28px]": size === "smallest",
|
|
151
|
+
"min-h-[32px]": size === "small",
|
|
135
152
|
"min-h-[42px]": size === "medium",
|
|
136
153
|
"min-h-[64px]": size === "large",
|
|
137
154
|
"w-full": fullWidth,
|
|
@@ -145,7 +162,8 @@ export const Select = forwardRef<HTMLDivElement, SelectProps>(({
|
|
|
145
162
|
"flex-grow max-w-full flex flex-row gap-2 items-center",
|
|
146
163
|
"overflow-visible",
|
|
147
164
|
{
|
|
148
|
-
"min-h-[28px]": size === "
|
|
165
|
+
"min-h-[28px]": size === "smallest",
|
|
166
|
+
"min-h-[32px]": size === "small",
|
|
149
167
|
"min-h-[42px]": size === "medium",
|
|
150
168
|
"min-h-[64px]": size === "large"
|
|
151
169
|
}
|
|
@@ -157,10 +175,9 @@ export const Select = forwardRef<HTMLDivElement, SelectProps>(({
|
|
|
157
175
|
}}
|
|
158
176
|
placeholder={placeholder}
|
|
159
177
|
className={"w-full"}>
|
|
160
|
-
{hasValue && value && renderValue ? renderValue(value) : placeholder}
|
|
178
|
+
{hasValue && value !== undefined && renderValue ? renderValue(value) : placeholder}
|
|
161
179
|
{/*{hasValue && !renderValue && value}*/}
|
|
162
180
|
{hasValue && !renderValue && (() => {
|
|
163
|
-
|
|
164
181
|
// @ts-ignore
|
|
165
182
|
const childrenProps: SelectItemProps[] = Children.map(children, (child) => {
|
|
166
183
|
if (React.isValidElement(child)) {
|
|
@@ -168,33 +185,33 @@ export const Select = forwardRef<HTMLDivElement, SelectProps>(({
|
|
|
168
185
|
}
|
|
169
186
|
}).filter(Boolean);
|
|
170
187
|
|
|
171
|
-
const option = childrenProps.find((o) => o.value === value);
|
|
188
|
+
const option = childrenProps.find((o) => String(o.value) === String(value));
|
|
172
189
|
return option?.children;
|
|
173
190
|
})()}
|
|
174
191
|
|
|
175
192
|
</SelectPrimitive.Value>
|
|
176
193
|
</div>
|
|
177
194
|
|
|
178
|
-
{endAdornment && (
|
|
179
|
-
<div
|
|
180
|
-
className={cls("h-full flex items-center")}
|
|
181
|
-
onClick={(e) => {
|
|
182
|
-
e.preventDefault();
|
|
183
|
-
e.stopPropagation();
|
|
184
|
-
}}>
|
|
185
|
-
{endAdornment}
|
|
186
|
-
</div>
|
|
187
|
-
)}
|
|
188
195
|
<SelectPrimitive.Icon asChild>
|
|
189
|
-
<KeyboardArrowDownIcon size={"medium"}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
196
|
+
<KeyboardArrowDownIcon size={size === "large" ? "medium" : "small"}
|
|
197
|
+
className={cls("transition", open ? "rotate-180" : "", {
|
|
198
|
+
"px-2": size === "large",
|
|
199
|
+
"px-1": size === "medium" || size === "small",
|
|
200
|
+
})}/>
|
|
194
201
|
</SelectPrimitive.Icon>
|
|
195
202
|
</div>
|
|
196
203
|
</SelectPrimitive.Trigger>
|
|
197
204
|
|
|
205
|
+
{endAdornment && (
|
|
206
|
+
<div
|
|
207
|
+
className={cls("h-full flex items-center absolute right-0 pr-12",)}
|
|
208
|
+
onClick={(e) => {
|
|
209
|
+
e.preventDefault();
|
|
210
|
+
e.stopPropagation();
|
|
211
|
+
}}>
|
|
212
|
+
{endAdornment}
|
|
213
|
+
</div>
|
|
214
|
+
)}
|
|
198
215
|
</div>
|
|
199
216
|
<SelectPrimitive.Portal>
|
|
200
217
|
<SelectPrimitive.Content position={position}
|
|
@@ -211,22 +228,25 @@ export const Select = forwardRef<HTMLDivElement, SelectProps>(({
|
|
|
211
228
|
|
|
212
229
|
Select.displayName = "Select";
|
|
213
230
|
|
|
214
|
-
export type SelectItemProps = {
|
|
215
|
-
value:
|
|
231
|
+
export type SelectItemProps<T extends SelectValue = string> = {
|
|
232
|
+
value: T,
|
|
216
233
|
children?: React.ReactNode,
|
|
217
234
|
disabled?: boolean,
|
|
218
235
|
className?: string,
|
|
219
236
|
};
|
|
220
237
|
|
|
221
|
-
export function SelectItem({
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
238
|
+
export function SelectItem<T extends SelectValue = string>({
|
|
239
|
+
value,
|
|
240
|
+
children,
|
|
241
|
+
disabled,
|
|
242
|
+
className
|
|
243
|
+
}: SelectItemProps<T>) {
|
|
244
|
+
// Convert value to string for Radix UI
|
|
245
|
+
const stringValue = String(value);
|
|
246
|
+
|
|
227
247
|
return <SelectPrimitive.Item
|
|
228
|
-
key={
|
|
229
|
-
value={
|
|
248
|
+
key={stringValue}
|
|
249
|
+
value={stringValue}
|
|
230
250
|
disabled={disabled}
|
|
231
251
|
className={cls(
|
|
232
252
|
"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
|
>
|
package/src/icons/Icon.tsx
CHANGED
|
@@ -54,11 +54,11 @@ export const Icon = React.forwardRef<HTMLSpanElement, IconProps & { iconKey: str
|
|
|
54
54
|
ref={ref} // Attach the ref to the span
|
|
55
55
|
style={{
|
|
56
56
|
fontSize: `${sizeInPx}px`,
|
|
57
|
+
verticalAlign: "middle",
|
|
57
58
|
...style
|
|
58
59
|
}}
|
|
59
60
|
className={
|
|
60
61
|
cls("material-icons",
|
|
61
|
-
"block",
|
|
62
62
|
color ? colorClassesMapping[color] : "",
|
|
63
63
|
"select-none",
|
|
64
64
|
className)}
|
package/src/index.css
CHANGED
|
Binary file
|