@firecms/ui 3.0.0-canary.12 → 3.0.0-canary.120
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/README.md +1 -1
- package/dist/components/Avatar.d.ts +1 -0
- package/dist/components/BooleanSwitch.d.ts +1 -1
- package/dist/components/CenteredView.d.ts +4 -2
- package/dist/components/Checkbox.d.ts +3 -2
- package/dist/components/Chip.d.ts +3 -2
- package/dist/components/DateTimeField.d.ts +3 -4
- package/dist/components/Dialog.d.ts +4 -1
- package/dist/components/InputLabel.d.ts +2 -2
- package/dist/components/Label.d.ts +4 -1
- package/dist/components/Markdown.d.ts +1 -0
- package/dist/components/Menu.d.ts +6 -2
- package/dist/components/Menubar.d.ts +79 -0
- package/dist/components/MultiSelect.d.ts +1 -4
- package/dist/components/NewMultiSelect.d.ts +60 -0
- package/dist/components/Popover.d.ts +2 -1
- package/dist/components/RadioGroup.d.ts +26 -3
- package/dist/components/Select.d.ts +4 -4
- package/dist/components/Sheet.d.ts +4 -0
- package/dist/components/Table.d.ts +10 -10
- package/dist/components/TextField.d.ts +1 -1
- package/dist/components/TextareaAutosize.d.ts +3 -34
- package/dist/components/Tooltip.d.ts +5 -2
- package/dist/components/index.d.ts +2 -1
- package/dist/hooks/index.d.ts +4 -0
- package/dist/hooks/useLocaleConfig.d.ts +1 -0
- package/dist/icons/Icon.d.ts +3 -3
- package/dist/index.css +77 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.es.js +13290 -13511
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +19828 -49
- package/dist/index.umd.js.map +1 -1
- package/dist/styles.d.ts +7 -7
- package/dist/util/{cn.d.ts → cls.d.ts} +4 -0
- package/dist/util/index.d.ts +1 -3
- package/package.json +109 -118
- package/src/components/Alert.tsx +2 -2
- package/src/components/Autocomplete.tsx +4 -3
- package/src/components/Avatar.tsx +7 -6
- package/src/components/Badge.tsx +1 -1
- package/src/components/BooleanSwitch.tsx +15 -15
- package/src/components/BooleanSwitchWithLabel.tsx +8 -8
- package/src/components/Button.tsx +11 -13
- package/src/components/Card.tsx +3 -3
- package/src/components/CenteredView.tsx +25 -15
- package/src/components/Checkbox.tsx +11 -9
- package/src/components/Chip.tsx +8 -5
- package/src/components/CircularProgress.tsx +2 -2
- package/src/components/Collapse.tsx +3 -2
- package/src/components/Container.tsx +2 -2
- package/src/components/DateTimeField.tsx +38 -48
- package/src/components/Dialog.tsx +15 -6
- package/src/components/DialogActions.tsx +2 -2
- package/src/components/DialogContent.tsx +2 -2
- package/src/components/ExpandablePanel.tsx +10 -8
- package/src/components/FileUpload.tsx +6 -9
- package/src/components/IconButton.tsx +4 -6
- package/src/components/InfoLabel.tsx +2 -2
- package/src/components/InputLabel.tsx +12 -9
- package/src/components/Label.tsx +17 -4
- package/src/components/Markdown.tsx +14 -3
- package/src/components/Menu.tsx +49 -31
- package/src/components/Menubar.tsx +322 -0
- package/src/components/MultiSelect.tsx +12 -14
- package/src/components/NewMultiSelect.tsx +370 -0
- package/src/components/Paper.tsx +2 -2
- package/src/components/Popover.tsx +17 -14
- package/src/components/RadioGroup.tsx +41 -9
- package/src/components/SearchBar.tsx +7 -8
- package/src/components/Select.tsx +92 -104
- package/src/components/Sheet.tsx +45 -28
- package/src/components/Skeleton.tsx +9 -6
- package/src/components/Table.tsx +50 -32
- package/src/components/Tabs.tsx +6 -7
- package/src/components/TextField.tsx +10 -13
- package/src/components/TextareaAutosize.tsx +3 -3
- package/src/components/Tooltip.tsx +27 -13
- package/src/components/Typography.tsx +34 -19
- package/src/components/common/SelectInputLabel.tsx +2 -2
- package/src/components/index.tsx +2 -1
- package/src/hooks/index.ts +4 -0
- package/src/hooks/useLocaleConfig.tsx +18 -0
- package/src/icons/Icon.tsx +46 -43
- package/src/icons/icon_keys.ts +114 -1301
- package/src/index.css +77 -0
- package/src/index.ts +1 -0
- package/src/scripts/generateIconKeys.ts +20 -11
- package/src/styles.ts +7 -7
- package/src/util/cls.ts +14 -0
- package/src/util/index.ts +1 -3
- package/tailwind.config.js +5 -3
- package/dist/components/Spinner.d.ts +0 -1
- package/src/components/Spinner.tsx +0 -18
- package/src/util/cn.ts +0 -6
- /package/dist/{util → hooks}/useDebounceValue.d.ts +0 -0
- /package/dist/{util → hooks}/useInjectStyles.d.ts +0 -0
- /package/dist/{util → hooks}/useOutsideAlerter.d.ts +0 -0
- /package/src/{util → hooks}/useDebounceValue.tsx +0 -0
- /package/src/{util → hooks}/useInjectStyles.tsx +0 -0
- /package/src/{util → hooks}/useOutsideAlerter.tsx +0 -0
@@ -0,0 +1,370 @@
|
|
1
|
+
// src/components/multi-select.tsx
|
2
|
+
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
3
|
+
|
4
|
+
import * as React from "react";
|
5
|
+
import { Command as CommandPrimitive } from "cmdk";
|
6
|
+
import { cls } from "../util";
|
7
|
+
import { CloseIcon, ExpandMoreIcon } from "../icons";
|
8
|
+
import { Separator } from "./Separator";
|
9
|
+
import { Checkbox } from "./Checkbox";
|
10
|
+
import { Chip } from "./Chip";
|
11
|
+
import {
|
12
|
+
defaultBorderMixin,
|
13
|
+
fieldBackgroundDisabledMixin,
|
14
|
+
fieldBackgroundHoverMixin,
|
15
|
+
fieldBackgroundInvisibleMixin,
|
16
|
+
fieldBackgroundMixin,
|
17
|
+
focusedDisabled
|
18
|
+
} from "../styles";
|
19
|
+
|
20
|
+
/**
|
21
|
+
* Props for MultiSelect component
|
22
|
+
*/
|
23
|
+
interface MultiSelectProps
|
24
|
+
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
25
|
+
/**
|
26
|
+
* An array of option objects to be displayed in the multi-select component.
|
27
|
+
* Each option object has a label, value, and an optional icon.
|
28
|
+
*/
|
29
|
+
options: {
|
30
|
+
/** The text to display for the option. */
|
31
|
+
label: string;
|
32
|
+
/** The unique value associated with the option. */
|
33
|
+
value: string;
|
34
|
+
}[];
|
35
|
+
|
36
|
+
/**
|
37
|
+
* Callback function triggered when the selected values change.
|
38
|
+
* Receives an array of the new selected values.
|
39
|
+
*/
|
40
|
+
onValueChange: (value: string[]) => void;
|
41
|
+
|
42
|
+
/** The default selected values when the component mounts. */
|
43
|
+
defaultValue: string[];
|
44
|
+
|
45
|
+
/**
|
46
|
+
* Placeholder text to be displayed when no values are selected.
|
47
|
+
* Optional, defaults to "Select options".
|
48
|
+
*/
|
49
|
+
placeholder?: string;
|
50
|
+
|
51
|
+
/**
|
52
|
+
* Animation duration in seconds for the visual effects (e.g., bouncing badges).
|
53
|
+
* Optional, defaults to 0 (no animation).
|
54
|
+
*/
|
55
|
+
animation?: number;
|
56
|
+
|
57
|
+
/**
|
58
|
+
* Maximum number of items to display. Extra selected items will be summarized.
|
59
|
+
* Optional, defaults to 3.
|
60
|
+
*/
|
61
|
+
maxCount?: number;
|
62
|
+
|
63
|
+
/**
|
64
|
+
* The modality of the popover. When set to true, interaction with outside elements
|
65
|
+
* will be disabled and only popover content will be visible to screen readers.
|
66
|
+
* Optional, defaults to false.
|
67
|
+
*/
|
68
|
+
modalPopover?: boolean;
|
69
|
+
|
70
|
+
/**
|
71
|
+
* If true, renders the multi-select component as a child of another component.
|
72
|
+
* Optional, defaults to false.
|
73
|
+
*/
|
74
|
+
asChild?: boolean;
|
75
|
+
|
76
|
+
/**
|
77
|
+
* Additional class names to apply custom styles to the multi-select component.
|
78
|
+
* Optional, can be used to add custom styles.
|
79
|
+
*/
|
80
|
+
className?: string;
|
81
|
+
|
82
|
+
size?: "small" | "medium",
|
83
|
+
|
84
|
+
invisible?: boolean;
|
85
|
+
disabled?: boolean;
|
86
|
+
|
87
|
+
variant?: "default" | "secondary" | "destructive";
|
88
|
+
}
|
89
|
+
|
90
|
+
export const NewMultiSelect = React.forwardRef<
|
91
|
+
HTMLButtonElement,
|
92
|
+
MultiSelectProps
|
93
|
+
>(
|
94
|
+
(
|
95
|
+
{
|
96
|
+
size,
|
97
|
+
options,
|
98
|
+
onValueChange,
|
99
|
+
invisible,
|
100
|
+
disabled,
|
101
|
+
variant,
|
102
|
+
defaultValue = [],
|
103
|
+
placeholder = "Select options",
|
104
|
+
animation = 0,
|
105
|
+
maxCount = 3,
|
106
|
+
modalPopover = false,
|
107
|
+
asChild = false,
|
108
|
+
className,
|
109
|
+
...props
|
110
|
+
},
|
111
|
+
ref
|
112
|
+
) => {
|
113
|
+
const [selectedValues, setSelectedValues] =
|
114
|
+
React.useState<string[]>(defaultValue);
|
115
|
+
const [isPopoverOpen, setIsPopoverOpen] = React.useState(false);
|
116
|
+
// const [isAnimating, setIsAnimating] = React.useState(false);
|
117
|
+
|
118
|
+
React.useEffect(() => {
|
119
|
+
setSelectedValues(defaultValue);
|
120
|
+
}, [defaultValue]);
|
121
|
+
|
122
|
+
const handleInputKeyDown = (
|
123
|
+
event: React.KeyboardEvent<HTMLInputElement>
|
124
|
+
) => {
|
125
|
+
if (event.key === "Enter") {
|
126
|
+
setIsPopoverOpen(true);
|
127
|
+
} else if (event.key === "Backspace" && !event.currentTarget.value) {
|
128
|
+
const newSelectedValues = [...selectedValues];
|
129
|
+
newSelectedValues.pop();
|
130
|
+
setSelectedValues(newSelectedValues);
|
131
|
+
onValueChange(newSelectedValues);
|
132
|
+
}
|
133
|
+
};
|
134
|
+
|
135
|
+
const toggleOption = (value: string) => {
|
136
|
+
const newSelectedValues = selectedValues.includes(value)
|
137
|
+
? selectedValues.filter((v) => v !== value)
|
138
|
+
: [...selectedValues, value];
|
139
|
+
setSelectedValues(newSelectedValues);
|
140
|
+
onValueChange(newSelectedValues);
|
141
|
+
};
|
142
|
+
|
143
|
+
const handleClear = () => {
|
144
|
+
setSelectedValues([]);
|
145
|
+
onValueChange([]);
|
146
|
+
};
|
147
|
+
|
148
|
+
const handleTogglePopover = () => {
|
149
|
+
setIsPopoverOpen((prev) => !prev);
|
150
|
+
};
|
151
|
+
|
152
|
+
const clearExtraOptions = () => {
|
153
|
+
const newSelectedValues = selectedValues.slice(0, maxCount);
|
154
|
+
setSelectedValues(newSelectedValues);
|
155
|
+
onValueChange(newSelectedValues);
|
156
|
+
};
|
157
|
+
|
158
|
+
const toggleAll = () => {
|
159
|
+
if (selectedValues.length === options.length) {
|
160
|
+
handleClear();
|
161
|
+
} else {
|
162
|
+
const allValues = options.map((option) => option.value);
|
163
|
+
setSelectedValues(allValues);
|
164
|
+
onValueChange(allValues);
|
165
|
+
}
|
166
|
+
};
|
167
|
+
|
168
|
+
return (
|
169
|
+
<PopoverPrimitive.Root
|
170
|
+
open={isPopoverOpen}
|
171
|
+
onOpenChange={setIsPopoverOpen}
|
172
|
+
modal={modalPopover}
|
173
|
+
>
|
174
|
+
<PopoverPrimitive.Trigger asChild>
|
175
|
+
<button
|
176
|
+
ref={ref}
|
177
|
+
{...props}
|
178
|
+
onClick={handleTogglePopover}
|
179
|
+
className={cls(
|
180
|
+
size === "small" ? "min-h-[42px]" : "min-h-[64px]",
|
181
|
+
"select-none rounded-md text-sm",
|
182
|
+
invisible ? fieldBackgroundInvisibleMixin : fieldBackgroundMixin,
|
183
|
+
disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin,
|
184
|
+
"relative flex items-center",
|
185
|
+
className
|
186
|
+
)}
|
187
|
+
>
|
188
|
+
{selectedValues.length > 0 ? (
|
189
|
+
<div className="flex justify-between items-center w-full">
|
190
|
+
<div className="flex flex-wrap items-center">
|
191
|
+
{selectedValues.slice(0, maxCount).map((value) => {
|
192
|
+
const option = options.find((o) => o.value === value);
|
193
|
+
return (
|
194
|
+
<Chip
|
195
|
+
key={value}
|
196
|
+
className={cls(
|
197
|
+
"m-1 transition ease-in-out delay-150 hover:-translate-y-1 hover:scale-110 duration-300",
|
198
|
+
{
|
199
|
+
"border-foreground/10 text-foreground bg-card hover:bg-card/80": variant === "default",
|
200
|
+
"border-foreground/10 bg-secondary text-secondary-foreground hover:bg-secondary/80": variant === "secondary",
|
201
|
+
"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80": variant === "destructive",
|
202
|
+
}
|
203
|
+
)}
|
204
|
+
style={{ animationDuration: `${animation}s` }}
|
205
|
+
>
|
206
|
+
{option?.label}
|
207
|
+
<CloseIcon
|
208
|
+
size={"smallest"}
|
209
|
+
onClick={(event) => {
|
210
|
+
event.stopPropagation();
|
211
|
+
toggleOption(value);
|
212
|
+
}}
|
213
|
+
/>
|
214
|
+
</Chip>
|
215
|
+
);
|
216
|
+
})}
|
217
|
+
{selectedValues.length > maxCount && (
|
218
|
+
<Chip
|
219
|
+
className={cls(
|
220
|
+
"bg-transparent text-foreground border-foreground/1 hover:bg-transparent",
|
221
|
+
"m-1 transition ease-in-out delay-150 hover:-translate-y-1 hover:scale-110 duration-300",
|
222
|
+
{
|
223
|
+
"border-foreground/10 text-foreground bg-card hover:bg-card/80": variant === "default",
|
224
|
+
"border-foreground/10 bg-secondary text-secondary-foreground hover:bg-secondary/80": variant === "secondary",
|
225
|
+
"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80": variant === "destructive",
|
226
|
+
}
|
227
|
+
)}
|
228
|
+
style={{ animationDuration: `${animation}s` }}
|
229
|
+
>
|
230
|
+
{`+ ${selectedValues.length - maxCount} more`}
|
231
|
+
<CloseIcon
|
232
|
+
size={"smallest"}
|
233
|
+
onClick={(event) => {
|
234
|
+
event.stopPropagation();
|
235
|
+
clearExtraOptions();
|
236
|
+
}}
|
237
|
+
/>
|
238
|
+
</Chip>
|
239
|
+
)}
|
240
|
+
</div>
|
241
|
+
<div className="flex items-center justify-between">
|
242
|
+
<CloseIcon
|
243
|
+
size={"small"}
|
244
|
+
onClick={(event) => {
|
245
|
+
event.stopPropagation();
|
246
|
+
handleClear();
|
247
|
+
}}
|
248
|
+
/>
|
249
|
+
<Separator
|
250
|
+
orientation="vertical"
|
251
|
+
/>
|
252
|
+
|
253
|
+
<div className={cls("px-2 h-full flex items-center")}>
|
254
|
+
<ExpandMoreIcon size={"small"}
|
255
|
+
className={cls("transition", isPopoverOpen ? "rotate-180" : "")}/>
|
256
|
+
</div>
|
257
|
+
</div>
|
258
|
+
</div>
|
259
|
+
) : (
|
260
|
+
<div className="flex items-center justify-between w-full mx-auto">
|
261
|
+
<span className="text-sm text-muted-foreground mx-3">
|
262
|
+
{placeholder}
|
263
|
+
</span>
|
264
|
+
<div className={cls("px-2 h-full flex items-center")}>
|
265
|
+
<ExpandMoreIcon size={"small"}
|
266
|
+
className={cls("transition", isPopoverOpen ? "rotate-180" : "")}/>
|
267
|
+
</div>
|
268
|
+
</div>
|
269
|
+
)}
|
270
|
+
</button>
|
271
|
+
</PopoverPrimitive.Trigger>
|
272
|
+
<PopoverPrimitive.Content
|
273
|
+
className={cls("z-50 relative overflow-hidden border bg-white dark:bg-gray-900 p-2 rounded-lg", defaultBorderMixin)}
|
274
|
+
align="start"
|
275
|
+
onEscapeKeyDown={() => setIsPopoverOpen(false)}
|
276
|
+
>
|
277
|
+
<CommandPrimitive>
|
278
|
+
<CommandPrimitive.Input
|
279
|
+
className={cls(focusedDisabled, "bg-transparent outline-none flex-1 h-full w-full m-4")}
|
280
|
+
placeholder="Search..."
|
281
|
+
onKeyDown={handleInputKeyDown}
|
282
|
+
/>
|
283
|
+
<CommandPrimitive.List>
|
284
|
+
<CommandPrimitive.Empty>No results found.</CommandPrimitive.Empty>
|
285
|
+
<CommandPrimitive.Group>
|
286
|
+
<CommandPrimitive.Item
|
287
|
+
key="all"
|
288
|
+
onSelect={toggleAll}
|
289
|
+
className={
|
290
|
+
cls(
|
291
|
+
// (fieldValue ?? []).includes(value) ? "bg-slate-200 dark:bg-slate-950" : "",
|
292
|
+
"cursor-pointer",
|
293
|
+
"flex flex-row items-center gap-2",
|
294
|
+
"ring-offset-transparent",
|
295
|
+
"p-1 rounded aria-[selected=true]:outline-none aria-[selected=true]:ring-2 aria-[selected=true]:ring-primary aria-[selected=true]:ring-opacity-75 aria-[selected=true]:ring-offset-2",
|
296
|
+
"aria-[selected=true]:bg-slate-100 aria-[selected=true]:dark:bg-slate-900",
|
297
|
+
"cursor-pointer p-1 rounded aria-[selected=true]:bg-slate-100 aria-[selected=true]:dark:bg-slate-900",
|
298
|
+
className
|
299
|
+
)
|
300
|
+
}
|
301
|
+
>
|
302
|
+
<Checkbox checked={selectedValues.length === options.length} size={"small"}/>
|
303
|
+
<span>(Select All)</span>
|
304
|
+
</CommandPrimitive.Item>
|
305
|
+
{options.map((option) => {
|
306
|
+
const isSelected = selectedValues.includes(option.value);
|
307
|
+
return (
|
308
|
+
<CommandPrimitive.Item
|
309
|
+
key={option.value}
|
310
|
+
onSelect={() => toggleOption(option.value)}
|
311
|
+
className={cls(
|
312
|
+
// (fieldValue ?? []).includes(value) ? "bg-slate-200 dark:bg-slate-950" : "",
|
313
|
+
"cursor-pointer",
|
314
|
+
"flex flex-row items-center gap-2",
|
315
|
+
"ring-offset-transparent",
|
316
|
+
"p-1 rounded aria-[selected=true]:outline-none aria-[selected=true]:ring-2 aria-[selected=true]:ring-primary aria-[selected=true]:ring-opacity-75 aria-[selected=true]:ring-offset-2",
|
317
|
+
"aria-[selected=true]:bg-slate-100 aria-[selected=true]:dark:bg-slate-900",
|
318
|
+
"cursor-pointer p-1 rounded aria-[selected=true]:bg-slate-100 aria-[selected=true]:dark:bg-slate-900",
|
319
|
+
className
|
320
|
+
)}
|
321
|
+
>
|
322
|
+
|
323
|
+
<Checkbox checked={isSelected} size={"small"}/>
|
324
|
+
<span>{option.label}</span>
|
325
|
+
</CommandPrimitive.Item>
|
326
|
+
);
|
327
|
+
})}
|
328
|
+
</CommandPrimitive.Group>
|
329
|
+
<CommandPrimitive.Separator/>
|
330
|
+
<CommandPrimitive.Group>
|
331
|
+
<div className="flex items-center justify-between">
|
332
|
+
{selectedValues.length > 0 && (
|
333
|
+
<>
|
334
|
+
<CommandPrimitive.Item
|
335
|
+
onSelect={handleClear}
|
336
|
+
className="flex-1 justify-center cursor-pointer"
|
337
|
+
>
|
338
|
+
Clear
|
339
|
+
</CommandPrimitive.Item>
|
340
|
+
<Separator
|
341
|
+
orientation="vertical"
|
342
|
+
/>
|
343
|
+
</>
|
344
|
+
)}
|
345
|
+
<CommandPrimitive.Item
|
346
|
+
onSelect={() => setIsPopoverOpen(false)}
|
347
|
+
className="flex-1 justify-center cursor-pointer max-w-full"
|
348
|
+
>
|
349
|
+
Close
|
350
|
+
</CommandPrimitive.Item>
|
351
|
+
</div>
|
352
|
+
</CommandPrimitive.Group>
|
353
|
+
</CommandPrimitive.List>
|
354
|
+
</CommandPrimitive>
|
355
|
+
</PopoverPrimitive.Content>
|
356
|
+
{/*{animation > 0 && selectedValues.length > 0 && (*/}
|
357
|
+
{/* <WandSparkles*/}
|
358
|
+
{/* className={cls(*/}
|
359
|
+
{/* "cursor-pointer my-2 text-foreground bg-background w-3 h-3",*/}
|
360
|
+
{/* isAnimating ? "" : "text-muted-foreground"*/}
|
361
|
+
{/* )}*/}
|
362
|
+
{/* onClick={() => setIsAnimating(!isAnimating)}*/}
|
363
|
+
{/* />*/}
|
364
|
+
{/*)}*/}
|
365
|
+
</PopoverPrimitive.Root>
|
366
|
+
);
|
367
|
+
}
|
368
|
+
);
|
369
|
+
|
370
|
+
NewMultiSelect.displayName = "MultiSelect";
|
package/src/components/Paper.tsx
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
import React from "react";
|
2
2
|
|
3
3
|
import { paperMixin } from "../styles";
|
4
|
-
import {
|
4
|
+
import { cls } from "../util";
|
5
5
|
|
6
6
|
export function Paper({
|
7
7
|
children,
|
@@ -15,7 +15,7 @@ export function Paper({
|
|
15
15
|
}) {
|
16
16
|
return (
|
17
17
|
<div
|
18
|
-
className={
|
18
|
+
className={cls(paperMixin, className)}
|
19
19
|
style={style}>
|
20
20
|
{children}
|
21
21
|
</div>
|
@@ -2,7 +2,8 @@ import React from "react";
|
|
2
2
|
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
3
3
|
|
4
4
|
import { paperMixin } from "../styles";
|
5
|
-
import {
|
5
|
+
import { cls } from "../util";
|
6
|
+
import { useInjectStyles } from "../hooks";
|
6
7
|
|
7
8
|
export type PopoverSide = "top" | "right" | "bottom" | "left";
|
8
9
|
export type PopoverAlign = "start" | "center" | "end";
|
@@ -23,6 +24,7 @@ export interface PopoverProps {
|
|
23
24
|
enabled?: boolean;
|
24
25
|
modal?: boolean;
|
25
26
|
className?: string;
|
27
|
+
portalContainer?: HTMLElement | null;
|
26
28
|
}
|
27
29
|
|
28
30
|
export function Popover({
|
@@ -40,6 +42,7 @@ export function Popover({
|
|
40
42
|
avoidCollisions,
|
41
43
|
enabled = true,
|
42
44
|
modal = false,
|
45
|
+
portalContainer,
|
43
46
|
className
|
44
47
|
}: PopoverProps) {
|
45
48
|
|
@@ -50,22 +53,22 @@ export function Popover({
|
|
50
53
|
|
51
54
|
return <PopoverPrimitive.Root open={open}
|
52
55
|
onOpenChange={onOpenChange}
|
53
|
-
modal={modal}
|
54
|
-
>
|
56
|
+
modal={modal}>
|
55
57
|
<PopoverPrimitive.Trigger asChild>
|
56
58
|
{trigger}
|
57
59
|
</PopoverPrimitive.Trigger>
|
58
|
-
<PopoverPrimitive.Portal>
|
59
|
-
<PopoverPrimitive.Content
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
60
|
+
<PopoverPrimitive.Portal container={portalContainer}>
|
61
|
+
<PopoverPrimitive.Content
|
62
|
+
className={cls(paperMixin,
|
63
|
+
"PopoverContent shadow z-40", className)}
|
64
|
+
side={side}
|
65
|
+
sideOffset={sideOffset}
|
66
|
+
align={align}
|
67
|
+
alignOffset={alignOffset}
|
68
|
+
arrowPadding={arrowPadding}
|
69
|
+
sticky={sticky}
|
70
|
+
hideWhenDetached={hideWhenDetached}
|
71
|
+
avoidCollisions={avoidCollisions}>
|
69
72
|
|
70
73
|
{children}
|
71
74
|
<PopoverPrimitive.Arrow className="fill-white dark:fill-slate-950"/>
|
@@ -1,15 +1,36 @@
|
|
1
1
|
import * as React from "react"
|
2
2
|
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"
|
3
|
-
import {
|
4
|
-
|
3
|
+
import { cls } from "../util";
|
4
|
+
|
5
|
+
export interface RadioGroupProps {
|
6
|
+
id?: string;
|
7
|
+
children: React.ReactNode;
|
8
|
+
name?: string
|
9
|
+
required?: boolean;
|
10
|
+
disabled?: boolean;
|
11
|
+
/**
|
12
|
+
* Whether keyboard navigation should loop around
|
13
|
+
* @defaultValue false
|
14
|
+
*/
|
15
|
+
loop?: boolean;
|
16
|
+
defaultValue?: string;
|
17
|
+
value?: string;
|
18
|
+
|
19
|
+
onValueChange?(value: string): void;
|
20
|
+
|
21
|
+
className?: string;
|
22
|
+
}
|
5
23
|
|
6
24
|
const RadioGroup = React.forwardRef<
|
7
25
|
React.ElementRef<typeof RadioGroupPrimitive.Root>,
|
8
|
-
|
9
|
-
>(({
|
26
|
+
RadioGroupProps
|
27
|
+
>(({
|
28
|
+
className,
|
29
|
+
...props
|
30
|
+
}, ref) => {
|
10
31
|
return (
|
11
32
|
<RadioGroupPrimitive.Root
|
12
|
-
className={
|
33
|
+
className={cls("grid gap-2", className)}
|
13
34
|
{...props}
|
14
35
|
ref={ref}
|
15
36
|
/>
|
@@ -17,21 +38,32 @@ const RadioGroup = React.forwardRef<
|
|
17
38
|
})
|
18
39
|
RadioGroup.displayName = RadioGroupPrimitive.Root.displayName
|
19
40
|
|
41
|
+
export interface RadioGroupItemProps {
|
42
|
+
id?: string;
|
43
|
+
value: string;
|
44
|
+
checked?: boolean;
|
45
|
+
required?: boolean;
|
46
|
+
className?: string;
|
47
|
+
disabled?: boolean;
|
48
|
+
}
|
20
49
|
const RadioGroupItem = React.forwardRef<
|
21
50
|
React.ElementRef<typeof RadioGroupPrimitive.Item>,
|
22
|
-
|
23
|
-
>(({
|
51
|
+
RadioGroupItemProps
|
52
|
+
>(({
|
53
|
+
className,
|
54
|
+
...props
|
55
|
+
}, ref) => {
|
24
56
|
return (
|
25
57
|
<RadioGroupPrimitive.Item
|
26
58
|
ref={ref}
|
27
|
-
className={
|
59
|
+
className={cls(
|
28
60
|
"aspect-square h-4 w-4 rounded-full border border-primary text-primary ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
29
61
|
className
|
30
62
|
)}
|
31
63
|
{...props}
|
32
64
|
>
|
33
65
|
<RadioGroupPrimitive.Indicator className="flex items-center justify-center">
|
34
|
-
<div className="h-2.5 w-2.5 fill-current text-current bg-primary rounded-lg"
|
66
|
+
<div className="h-2.5 w-2.5 fill-current text-current bg-primary rounded-lg"/>
|
35
67
|
</RadioGroupPrimitive.Indicator>
|
36
68
|
</RadioGroupPrimitive.Item>
|
37
69
|
)
|
@@ -1,10 +1,10 @@
|
|
1
1
|
import React, { useCallback, useState } from "react";
|
2
2
|
|
3
|
-
import { defaultBorderMixin
|
3
|
+
import { defaultBorderMixin } from "../styles";
|
4
4
|
import { CircularProgress, IconButton } from "./index";
|
5
5
|
import { ClearIcon, SearchIcon } from "../icons";
|
6
|
-
import {
|
7
|
-
import { useDebounceValue } from "../
|
6
|
+
import { cls } from "../util";
|
7
|
+
import { useDebounceValue } from "../hooks";
|
8
8
|
|
9
9
|
interface SearchBarProps {
|
10
10
|
onClick?: () => void;
|
@@ -60,14 +60,14 @@ export function SearchBar({
|
|
60
60
|
return (
|
61
61
|
<div
|
62
62
|
onClick={onClick}
|
63
|
-
className={
|
63
|
+
className={cls("relative",
|
64
64
|
large ? "h-14" : "h-[42px]",
|
65
|
-
"bg-slate-50 dark:bg-gray-800
|
65
|
+
"bg-slate-50 dark:bg-gray-800 border",
|
66
66
|
defaultBorderMixin,
|
67
67
|
"rounded",
|
68
68
|
className)}>
|
69
69
|
<div
|
70
|
-
className="absolute p-0 px-4 h-full
|
70
|
+
className="absolute p-0 px-4 h-full pointer-events-none flex items-center justify-center top-0">
|
71
71
|
{loading ? <CircularProgress size={"small"}/> : <SearchIcon className={"text-slate-500 dark:text-gray-500"}/>}
|
72
72
|
</div>
|
73
73
|
<input
|
@@ -84,12 +84,11 @@ export function SearchBar({
|
|
84
84
|
autoFocus={autoFocus}
|
85
85
|
onFocus={() => setActive(true)}
|
86
86
|
onBlur={() => setActive(false)}
|
87
|
-
className={
|
87
|
+
className={cls(
|
88
88
|
(disabled || loading) && "pointer-events-none",
|
89
89
|
"relative flex items-center rounded transition-all bg-transparent outline-none appearance-none border-none",
|
90
90
|
"pl-12 h-full text-current ",
|
91
91
|
expandable ? (active ? "w-[220px]" : "w-[180px]") : "",
|
92
|
-
focusedMixin,
|
93
92
|
innerClassName
|
94
93
|
)}
|
95
94
|
/>
|