@firecms/ui 3.0.0-beta.2-pre.5 → 3.0.0-beta.3
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/Button.d.ts +2 -1
- package/dist/components/IconButton.d.ts +1 -1
- package/dist/components/Separator.d.ts +4 -0
- package/dist/components/TextField.d.ts +1 -1
- package/dist/components/Tooltip.d.ts +1 -1
- package/dist/components/index.d.ts +2 -1
- package/dist/icons/HandleIcon.d.ts +1 -0
- package/dist/icons/index.d.ts +1 -0
- package/dist/index.es.js +7594 -7528
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +10 -10
- package/dist/index.umd.js.map +1 -1
- package/package.json +11 -2
- package/src/components/Alert.tsx +2 -1
- package/src/components/Button.tsx +64 -30
- package/src/components/ExpandablePanel.tsx +1 -0
- package/src/components/IconButton.tsx +4 -3
- package/src/components/Popover.tsx +2 -1
- package/src/components/Separator.tsx +22 -0
- package/src/components/Tabs.tsx +1 -1
- package/src/components/TextField.tsx +23 -8
- package/src/components/Tooltip.tsx +1 -1
- package/src/components/index.tsx +2 -1
- package/src/icons/HandleIcon.tsx +10 -0
- package/src/icons/index.ts +1 -0
- package/src/scripts/saveIconFiles.ts +1 -1
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.3",
|
5
5
|
"description": "Awesome Firebase/Firestore-based headless open-source CMS",
|
6
6
|
"funding": {
|
7
7
|
"url": "https://github.com/sponsors/firecmsco"
|
@@ -27,6 +27,14 @@
|
|
27
27
|
"headless cms",
|
28
28
|
"content manager"
|
29
29
|
],
|
30
|
+
"exports": {
|
31
|
+
".": {
|
32
|
+
"import": "./dist/index.es.js",
|
33
|
+
"require": "./dist/index.umd.js",
|
34
|
+
"types": "./dist/src/index.d.ts"
|
35
|
+
},
|
36
|
+
"./package.json": "./package.json"
|
37
|
+
},
|
30
38
|
"scripts": {
|
31
39
|
"watch": "vite build --watch",
|
32
40
|
"build": "vite build && tsc --emitDeclarationOnly",
|
@@ -47,6 +55,7 @@
|
|
47
55
|
"@radix-ui/react-portal": "^1.0.4",
|
48
56
|
"@radix-ui/react-scroll-area": "^1.0.5",
|
49
57
|
"@radix-ui/react-select": "^1.2.2",
|
58
|
+
"@radix-ui/react-separator": "^1.0.3",
|
50
59
|
"@radix-ui/react-switch": "^1.0.3",
|
51
60
|
"@radix-ui/react-tabs": "^1.0.4",
|
52
61
|
"@radix-ui/react-tooltip": "^1.0.7",
|
@@ -101,7 +110,7 @@
|
|
101
110
|
"dist",
|
102
111
|
"src"
|
103
112
|
],
|
104
|
-
"gitHead": "
|
113
|
+
"gitHead": "33cceff5d5bc2a7002cc5a3904b787e70bfb9c6e",
|
105
114
|
"publishConfig": {
|
106
115
|
"access": "public"
|
107
116
|
}
|
package/src/components/Alert.tsx
CHANGED
@@ -29,7 +29,7 @@ const getColorClasses = (severity: string) => {
|
|
29
29
|
case "warning":
|
30
30
|
return "bg-amber-50 dark:bg-amber-800 dark:text-amber-100 text-amber-900";
|
31
31
|
case "info":
|
32
|
-
return "bg-blue-
|
32
|
+
return "bg-blue-100 dark:bg-blue-800 dark:text-blue-100 text-blue-900";
|
33
33
|
case "success":
|
34
34
|
return "bg-emerald-50 dark:bg-emerald-800 dark:text-emerald-100 text-emerald-900";
|
35
35
|
case "base":
|
@@ -55,6 +55,7 @@ export const Alert: React.FC<AlertProps> = ({
|
|
55
55
|
className={cn(
|
56
56
|
getSizeClasses(size),
|
57
57
|
"w-full",
|
58
|
+
"font-medium",
|
58
59
|
"rounded-md flex items-center gap-2",
|
59
60
|
classes,
|
60
61
|
className)}>
|
@@ -1,13 +1,14 @@
|
|
1
1
|
import React from "react";
|
2
2
|
|
3
|
-
import {
|
4
|
-
import {
|
3
|
+
import {focusedMixin} from "../styles";
|
4
|
+
import {cn} from "../util";
|
5
5
|
|
6
6
|
export type ButtonProps<P extends React.ElementType> =
|
7
7
|
Omit<(P extends "button" ? React.ButtonHTMLAttributes<HTMLButtonElement> : React.ComponentProps<P>), "onClick">
|
8
8
|
& {
|
9
9
|
variant?: "filled" | "outlined" | "text";
|
10
10
|
disabled?: boolean;
|
11
|
+
color?: "primary" | "secondary" | "text" | "error";
|
11
12
|
size?: "small" | "medium" | "large";
|
12
13
|
startIcon?: React.ReactNode;
|
13
14
|
fullWidth?: boolean;
|
@@ -15,32 +16,57 @@ export type ButtonProps<P extends React.ElementType> =
|
|
15
16
|
onClick?: React.MouseEventHandler<any>
|
16
17
|
};
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
19
|
+
const ButtonInner = React.forwardRef<
|
20
|
+
ButtonProps<React.ElementType<any>>
|
21
|
+
>(({
|
22
|
+
children,
|
23
|
+
className,
|
24
|
+
variant = "filled",
|
25
|
+
disabled = false,
|
26
|
+
size = "medium",
|
27
|
+
startIcon = null,
|
28
|
+
fullWidth = false,
|
29
|
+
component: Component,
|
30
|
+
color = "primary",
|
31
|
+
...props
|
32
|
+
}: ButtonProps<any>, ref) => {
|
29
33
|
|
30
34
|
const baseClasses =
|
31
|
-
"h-fit rounded-md
|
35
|
+
"h-fit rounded-md uppercase inline-flex items-center justify-center p-2 px-4 text-sm font-medium focus:outline-none transition ease-in-out duration-150 gap-2";
|
32
36
|
|
33
|
-
const buttonClasses = cn(
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
);
|
37
|
+
// const buttonClasses = cn(
|
38
|
+
// {
|
39
|
+
// "w-full": fullWidth,
|
40
|
+
// "w-fit": !fullWidth,
|
41
|
+
// "border-transparent bg-primary hover:bg-primary-dark focus:ring-primary !text-white shadow hover:ring-1 hover:ring-primary": variant === "filled" && !disabled,
|
42
|
+
// "border-transparent !text-primary !hover:text-primary-dark hover:bg-primary hover:bg-primary-bg": variant === "text" && !disabled,
|
43
|
+
// "border-primary !text-primary hover:bg-primary-bg hover:border-primary-dark !hover:text-primary-dark focus:ring-primary hover:ring-1 hover:ring-primary": variant === "outlined" && !disabled,
|
44
|
+
// "border-primary-dark border-opacity-50 dark:border-primary dark:border-opacity-50 opacity-50 !text-primary-dark !dark:text-primary text-opacity-50 dark:text-opacity-50": variant === "outlined" && disabled,
|
45
|
+
// "border-transparent outline-none opacity-50 !text-slate-600 !dark:text-slate-500": (variant === "filled" || variant === "text") && disabled
|
46
|
+
// }
|
47
|
+
// );
|
48
|
+
|
49
|
+
const buttonClasses = cn({
|
50
|
+
"w-full": fullWidth,
|
51
|
+
"w-fit": !fullWidth,
|
52
|
+
// Filled Variants
|
53
|
+
"border border-transparent bg-primary hover:bg-primary-dark focus:ring-primary shadow hover:ring-1 hover:ring-primary text-white": variant === "filled" && color === "primary" && !disabled,
|
54
|
+
"border border-transparent bg-secondary hover:bg-secondary-dark focus:ring-secondary shadow hover:ring-1 hover:ring-secondary text-white": variant === "filled" && color === "secondary" && !disabled,
|
55
|
+
"border border-transparent bg-red-500 hover:bg-red-500 focus:ring-red-500 shadow hover:ring-1 hover:ring-red-600 text-white": variant === "filled" && color === "error" && !disabled,
|
56
|
+
"border border-transparent bg-slate-200 hover:bg-slate-300 focus:ring-slate-400 shadow hover:ring-1 hover:ring-slate-400 text-text-primary dark:text-text-primary-dark": variant === "filled" && color === "text" && !disabled,
|
57
|
+
// Text Variants
|
58
|
+
"border border-transparent text-primary hover:bg-slate-200 dark:hover:bg-gray-900": variant === "text" && color === "primary" && !disabled,
|
59
|
+
"border border-transparent text-secondary hover:bg-secondary-bg": variant === "text" && color === "secondary" && !disabled,
|
60
|
+
"border border-transparent text-red-500 hover:bg-red-500 hover:bg-opacity-10": variant === "text" && color === "error" && !disabled,
|
61
|
+
"border border-transparent text-text-primary dark:text-text-primary-dark hover:bg-slate-200 hover:dark:bg-gray-700": variant === "text" && color === "text" && !disabled,
|
62
|
+
// Outlined Variants
|
63
|
+
"border border-primary text-primary hover:bg-primary-bg": variant === "outlined" && color === "primary" && !disabled,
|
64
|
+
"border border-secondary text-secondary hover:bg-secondary-bg": variant === "outlined" && color === "secondary" && !disabled,
|
65
|
+
"border border-red-500 text-red-500 hover:bg-red-500": variant === "outlined" && color === "error" && !disabled,
|
66
|
+
"border border-slate-400 text-text-primary dark:text-text-primary-dark hover:bg-slate-200": variant === "outlined" && color === "text" && !disabled,
|
67
|
+
// Disabled states for all variants
|
68
|
+
"border border-transparent opacity-50": disabled
|
69
|
+
});
|
44
70
|
|
45
71
|
const sizeClasses = cn(
|
46
72
|
{
|
@@ -52,9 +78,11 @@ export function Button<P extends React.ElementType>({
|
|
52
78
|
|
53
79
|
if (Component) {
|
54
80
|
return (
|
55
|
-
<Component
|
56
|
-
|
57
|
-
|
81
|
+
<Component
|
82
|
+
ref={ref}
|
83
|
+
onClick={props.onClick}
|
84
|
+
className={cn(focusedMixin, startIcon ? "pl-3" : "", baseClasses, buttonClasses, sizeClasses, className)}
|
85
|
+
{...(props as React.ComponentPropsWithRef<any>)}>
|
58
86
|
{startIcon}
|
59
87
|
{children}
|
60
88
|
</Component>
|
@@ -62,7 +90,8 @@ export function Button<P extends React.ElementType>({
|
|
62
90
|
}
|
63
91
|
|
64
92
|
return (
|
65
|
-
<button
|
93
|
+
<button ref={ref as any}
|
94
|
+
type={props.type ?? "button"}
|
66
95
|
onClick={props.onClick}
|
67
96
|
className={cn(focusedMixin, startIcon ? "pl-3" : "", baseClasses, buttonClasses, sizeClasses, className)}
|
68
97
|
disabled={disabled}
|
@@ -71,4 +100,9 @@ export function Button<P extends React.ElementType>({
|
|
71
100
|
{children}
|
72
101
|
</button>
|
73
102
|
);
|
74
|
-
|
103
|
+
|
104
|
+
});
|
105
|
+
|
106
|
+
ButtonInner.displayName = "Button"
|
107
|
+
|
108
|
+
export const Button = ButtonInner as React.FC<ButtonProps<any>>;
|
@@ -88,6 +88,7 @@ export function ExpandablePanel({
|
|
88
88
|
<Collapsible.Trigger
|
89
89
|
className={cn(focusedMixin,
|
90
90
|
"rounded flex items-center justify-between w-full min-h-[52px]",
|
91
|
+
"hover:bg-gray-100 dark:hover:bg-gray-800 dark:hover:bg-opacity-10",
|
91
92
|
invisible ? "border-b px-2" : "p-4",
|
92
93
|
invisible && defaultBorderMixin,
|
93
94
|
asField && fieldBackgroundMixin,
|
@@ -5,7 +5,7 @@ import { cn } from "../util";
|
|
5
5
|
export type IconButtonProps<C extends React.ElementType> =
|
6
6
|
Omit<(C extends "button" ? React.ButtonHTMLAttributes<HTMLButtonElement> : React.ComponentProps<C>), "onClick">
|
7
7
|
& {
|
8
|
-
size?: "medium" | "small" | "large";
|
8
|
+
size?: "medium" | "small" | "smallest" | "large";
|
9
9
|
variant?: "ghost" | "filled",
|
10
10
|
shape?: "circular" | "square",
|
11
11
|
disabled?: boolean;
|
@@ -15,13 +15,14 @@ export type IconButtonProps<C extends React.ElementType> =
|
|
15
15
|
}
|
16
16
|
|
17
17
|
const buttonClasses =
|
18
|
-
"hover:bg-slate-200 hover:bg-opacity-75 dark:hover:bg-
|
18
|
+
"hover:bg-slate-200 hover:bg-opacity-75 dark:hover:bg-gray-700 dark:hover:bg-opacity-50";
|
19
19
|
const baseClasses =
|
20
20
|
"inline-flex items-center justify-center p-2 text-sm font-medium focus:outline-none transition-colors ease-in-out duration-150";
|
21
21
|
const colorClasses = "text-slate-600 visited:text-slate-600 dark:text-slate-300 dark:visited:text-slate-300";
|
22
22
|
const sizeClasses = {
|
23
23
|
medium: "w-10 !h-10 min-w-10 min-h-10",
|
24
24
|
small: "w-8 !h-8 min-w-8 min-h-8",
|
25
|
+
smallest: "w-6 !h-6 min-w-6 min-h-6",
|
25
26
|
large: "w-12 !h-12 min-w-12 min-h-12"
|
26
27
|
}
|
27
28
|
const shapeClasses = {
|
@@ -41,7 +42,7 @@ const IconButtonInner = <C extends React.ElementType = "button">({
|
|
41
42
|
...props
|
42
43
|
}: IconButtonProps<C>, ref: React.ForwardedRef<HTMLButtonElement>) => {
|
43
44
|
|
44
|
-
const bgClasses = variant === "ghost" ? "bg-transparent" : "bg-slate-50 dark:bg-
|
45
|
+
const bgClasses = variant === "ghost" ? "bg-transparent" : "bg-slate-50 dark:bg-gray-950 dark:bg-opacity-50";
|
45
46
|
const Component: React.ElementType<any> = component || "button";
|
46
47
|
return (
|
47
48
|
<Component
|
@@ -56,7 +56,8 @@ export function Popover({
|
|
56
56
|
{trigger}
|
57
57
|
</PopoverPrimitive.Trigger>
|
58
58
|
<PopoverPrimitive.Portal>
|
59
|
-
<PopoverPrimitive.Content className={cn(paperMixin,
|
59
|
+
<PopoverPrimitive.Content className={cn(paperMixin,
|
60
|
+
"PopoverContent shadow z-40", className)}
|
60
61
|
side={side}
|
61
62
|
sideOffset={sideOffset}
|
62
63
|
align={align}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
import * as SeparatorPrimitive from "@radix-ui/react-separator";
|
2
|
+
|
3
|
+
export function Separator({ orientation, decorative }: {
|
4
|
+
orientation: "horizontal" | "vertical",
|
5
|
+
decorative?: boolean
|
6
|
+
}) {
|
7
|
+
if (orientation === "horizontal")
|
8
|
+
return (
|
9
|
+
<SeparatorPrimitive.Root
|
10
|
+
decorative={decorative}
|
11
|
+
orientation="horizontal"
|
12
|
+
className="dark:bg-opacity-50 bg-opacity-50 dark:bg-gray-600 bg-gray-300 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px my-[8px]"/>
|
13
|
+
);
|
14
|
+
else
|
15
|
+
return (
|
16
|
+
<SeparatorPrimitive.Root
|
17
|
+
className="dark:bg-opacity-50 bg-opacity-50 dark:bg-gray-600 bg-gray-300 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px mx-[8px]"
|
18
|
+
decorative={decorative}
|
19
|
+
orientation="vertical"
|
20
|
+
/>
|
21
|
+
);
|
22
|
+
}
|
package/src/components/Tabs.tsx
CHANGED
@@ -19,7 +19,7 @@ export function Tabs({
|
|
19
19
|
|
20
20
|
return <TabsPrimitive.Root value={value} onValueChange={onValueChange}>
|
21
21
|
<TabsPrimitive.List className={cn(
|
22
|
-
"flex text-sm font-medium text-center text-slate-800 dark:text-slate-200",
|
22
|
+
"flex text-sm font-medium text-center text-slate-800 dark:text-slate-200 max-w-full overflow-auto no-scrollbar",
|
23
23
|
className)
|
24
24
|
}>
|
25
25
|
{children}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import React, { useCallback, useRef } from "react";
|
1
|
+
import React, { useCallback, useEffect, useRef } from "react";
|
2
2
|
|
3
3
|
import { TextareaAutosize } from "./TextareaAutosize";
|
4
4
|
import {
|
@@ -45,7 +45,7 @@ export type TextFieldProps<T extends string | number> = {
|
|
45
45
|
style?: React.CSSProperties,
|
46
46
|
inputClassName?: string,
|
47
47
|
inputStyle?: React.CSSProperties,
|
48
|
-
inputRef?: React.
|
48
|
+
inputRef?: React.ForwardedRef<any>
|
49
49
|
} & Omit<React.InputHTMLAttributes<HTMLInputElement>, "size">;
|
50
50
|
|
51
51
|
export function TextField<T extends string | number>({
|
@@ -77,12 +77,26 @@ export function TextField<T extends string | number>({
|
|
77
77
|
const [focused, setFocused] = React.useState(document.activeElement === inputRef.current);
|
78
78
|
const hasValue = value !== undefined && value !== null && value !== "";
|
79
79
|
|
80
|
+
useEffect(() => {
|
81
|
+
if (type !== "number") return;
|
82
|
+
const handleWheel = (event: any) => {
|
83
|
+
event.preventDefault(); // Prevent scrolling the number input
|
84
|
+
};
|
85
|
+
|
86
|
+
// Current input element
|
87
|
+
const element = "current" in inputRef ? inputRef.current : inputRef;
|
88
|
+
|
89
|
+
// Add the event listener
|
90
|
+
element.addEventListener("wheel", handleWheel);
|
91
|
+
|
92
|
+
// Remove event listener on cleanup
|
93
|
+
return () => {
|
94
|
+
element.removeEventListener("wheel", handleWheel);
|
95
|
+
};
|
96
|
+
}, [inputRef, type]);
|
97
|
+
|
80
98
|
const numberInputOnWheelPreventChange = useCallback((e: any) => {
|
81
|
-
e.
|
82
|
-
e.stopPropagation()
|
83
|
-
setTimeout(() => {
|
84
|
-
e.target.focus()
|
85
|
-
}, 0)
|
99
|
+
e.preventDefault()
|
86
100
|
}, []);
|
87
101
|
|
88
102
|
const input = multiline
|
@@ -159,7 +173,8 @@ export function TextField<T extends string | number>({
|
|
159
173
|
|
160
174
|
{input}
|
161
175
|
|
162
|
-
{endAdornment && <div
|
176
|
+
{endAdornment && <div
|
177
|
+
className="flex flex-row justify-center items-center absolute h-full right-0 top-0 mr-4 ">{endAdornment}</div>}
|
163
178
|
|
164
179
|
</div>
|
165
180
|
);
|
@@ -8,7 +8,7 @@ export type TooltipProps = {
|
|
8
8
|
onOpenChange?: (open: boolean) => void,
|
9
9
|
side?: "top" | "bottom" | "left" | "right",
|
10
10
|
sideOffset?: number,
|
11
|
-
title?: string,
|
11
|
+
title?: string | React.ReactNode,
|
12
12
|
delayDuration?: number;
|
13
13
|
className?: string,
|
14
14
|
tooltipClassName?: string,
|
package/src/components/index.tsx
CHANGED
@@ -25,8 +25,9 @@ export * from "./Markdown";
|
|
25
25
|
export * from "./Menu";
|
26
26
|
export * from "./MultiSelect";
|
27
27
|
export * from "./Paper";
|
28
|
-
export * from "./Select";
|
29
28
|
export * from "./SearchBar";
|
29
|
+
export * from "./Select";
|
30
|
+
export * from "./Separator";
|
30
31
|
export * from "./Sheet";
|
31
32
|
export * from "./Spinner";
|
32
33
|
export * from "./TextareaAutosize";
|
@@ -0,0 +1,10 @@
|
|
1
|
+
export function HandleIcon() {
|
2
|
+
return <svg width="24" height="24" viewBox="0 0 100 100" fill="none">
|
3
|
+
<circle cx="28" cy="50" r="9" fill={"currentColor"}/>
|
4
|
+
<circle cx="28" cy="21" r="9" fill={"currentColor"}/>
|
5
|
+
<circle cx="71" cy="21" r="9" fill={"currentColor"}/>
|
6
|
+
<circle cx="71" cy="50" r="9" fill={"currentColor"}/>
|
7
|
+
<circle cx="71" cy="78" r="9" fill={"currentColor"}/>
|
8
|
+
<circle cx="28" cy="78" r="9" fill={"currentColor"}/>
|
9
|
+
</svg>;
|
10
|
+
}
|
package/src/icons/index.ts
CHANGED
@@ -2,6 +2,7 @@ export * from "./icon_keys";
|
|
2
2
|
export * from "./cool_icon_keys";
|
3
3
|
export * from "./Icon";
|
4
4
|
export * from "./GitHubIcon";
|
5
|
+
export * from "./HandleIcon";
|
5
6
|
export * from "./components/_10kIcon";
|
6
7
|
export * from "./components/_10mpIcon";
|
7
8
|
export * from "./components/_11mpIcon";
|
@@ -18,7 +18,7 @@ export function saveIconFiles(iconKeys: string[]) {
|
|
18
18
|
fs.mkdirSync(path.join(__dirname, "../icons/components"), { recursive: true });
|
19
19
|
|
20
20
|
// create empty index file
|
21
|
-
fs.writeFileSync(path.join(__dirname, "../icons/index.ts"), "export * from \"./icon_keys\";\nexport * from \"./cool_icon_keys\";\nexport * from \"./Icon\";\nexport * from \"./GitHubIcon\";\n");
|
21
|
+
fs.writeFileSync(path.join(__dirname, "../icons/index.ts"), "export * from \"./icon_keys\";\nexport * from \"./cool_icon_keys\";\nexport * from \"./Icon\";\nexport * from \"./GitHubIcon\";\nexport * from \"./HandleIcon\";\n");
|
22
22
|
|
23
23
|
// for each key, generate a file with an Icon ts component
|
24
24
|
iconKeys.forEach((key: string) => {
|