@firecms/ui 3.0.1 → 3.1.0-canary.9e89e98
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 +9 -7
- package/dist/components/Card.d.ts +1 -1
- package/dist/components/ColorPicker.d.ts +30 -0
- package/dist/components/DateTimeField.d.ts +7 -0
- package/dist/components/Dialog.d.ts +2 -1
- package/dist/components/FileUpload.d.ts +1 -1
- package/dist/components/Menu.d.ts +2 -1
- package/dist/components/Menubar.d.ts +2 -1
- package/dist/components/MultiSelect.d.ts +1 -0
- package/dist/components/SearchBar.d.ts +11 -1
- package/dist/components/Select.d.ts +1 -0
- package/dist/components/Sheet.d.ts +1 -0
- package/dist/components/ToggleButtonGroup.d.ts +30 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/hooks/PortalContainerContext.d.ts +31 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/index.css +57 -6
- package/dist/index.es.js +1603 -935
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +1603 -935
- package/dist/index.umd.js.map +1 -1
- package/dist/styles.d.ts +11 -11
- package/package.json +3 -3
- package/src/components/BooleanSwitch.tsx +3 -3
- package/src/components/Button.tsx +5 -5
- package/src/components/Card.tsx +7 -7
- package/src/components/Checkbox.tsx +1 -1
- package/src/components/ColorPicker.tsx +134 -0
- package/src/components/DateTimeField.tsx +123 -34
- package/src/components/Dialog.tsx +25 -16
- package/src/components/DialogActions.tsx +1 -1
- package/src/components/ExpandablePanel.tsx +1 -1
- package/src/components/FileUpload.tsx +25 -24
- package/src/components/IconButton.tsx +3 -2
- package/src/components/Menu.tsx +44 -30
- package/src/components/Menubar.tsx +14 -3
- package/src/components/MultiSelect.tsx +87 -68
- package/src/components/Popover.tsx +11 -3
- package/src/components/SearchBar.tsx +37 -19
- package/src/components/Select.tsx +30 -17
- package/src/components/Separator.tsx +2 -2
- package/src/components/Sheet.tsx +12 -3
- package/src/components/Slider.tsx +4 -4
- package/src/components/Table.tsx +1 -1
- package/src/components/Tabs.tsx +14 -17
- package/src/components/TextField.tsx +19 -8
- package/src/components/ToggleButtonGroup.tsx +67 -0
- package/src/components/Tooltip.tsx +9 -2
- package/src/components/index.tsx +2 -0
- package/src/hooks/PortalContainerContext.tsx +48 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useInjectStyles.tsx +12 -3
- package/src/index.css +57 -6
- package/src/styles.ts +11 -11
- package/src/util/cls.ts +1 -1
- package/tailwind.config.js +2 -3
package/README.md
CHANGED
|
@@ -67,16 +67,18 @@ export default {
|
|
|
67
67
|
Finally, you need to define your primary and secondary colors in your `index.css` file:
|
|
68
68
|
|
|
69
69
|
```css
|
|
70
|
-
@import
|
|
70
|
+
@import 'tailwindcss';
|
|
71
|
+
@import "@firecms/ui/index.css" layer(base);
|
|
71
72
|
|
|
72
|
-
@
|
|
73
|
-
|
|
74
|
-
@
|
|
73
|
+
@custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *));
|
|
74
|
+
|
|
75
|
+
@source "../index.html";
|
|
76
|
+
@source "./**/*.{js,ts,jsx,tsx}";
|
|
77
|
+
@source "../node_modules/@firecms/**/*.{js,ts,jsx,tsx}";
|
|
75
78
|
|
|
76
79
|
:root {
|
|
77
|
-
--
|
|
78
|
-
--
|
|
79
|
-
--fcms-secondary: #FF5B79;
|
|
80
|
+
--color-primary: #0070F4;
|
|
81
|
+
--color-secondary: #FF5B79;
|
|
80
82
|
}
|
|
81
83
|
```
|
|
82
84
|
|
|
@@ -2,7 +2,7 @@ import React from "react";
|
|
|
2
2
|
type CardProps = {
|
|
3
3
|
children: React.ReactNode;
|
|
4
4
|
style?: React.CSSProperties;
|
|
5
|
-
onClick?: () => void;
|
|
5
|
+
onClick?: (e?: React.MouseEvent) => void;
|
|
6
6
|
className?: string;
|
|
7
7
|
};
|
|
8
8
|
declare const Card: React.ForwardRefExoticComponent<CardProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ChipColorKey } from "./Chip";
|
|
2
|
+
export interface ColorPickerProps {
|
|
3
|
+
/**
|
|
4
|
+
* Currently selected color key
|
|
5
|
+
*/
|
|
6
|
+
value?: ChipColorKey;
|
|
7
|
+
/**
|
|
8
|
+
* Callback when color selection changes. Passes undefined when "Auto" is selected.
|
|
9
|
+
*/
|
|
10
|
+
onChange: (colorKey: ChipColorKey | undefined) => void;
|
|
11
|
+
/**
|
|
12
|
+
* Size of the color swatches
|
|
13
|
+
*/
|
|
14
|
+
size?: "small" | "medium";
|
|
15
|
+
/**
|
|
16
|
+
* Whether to show the "Auto" option that clears the selection
|
|
17
|
+
*/
|
|
18
|
+
allowClear?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Whether the picker is disabled
|
|
21
|
+
*/
|
|
22
|
+
disabled?: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A color picker component that displays a grid of predefined CHIP_COLORS.
|
|
26
|
+
* Used for selecting colors for enum values, tags, and other chip-based UI elements.
|
|
27
|
+
*
|
|
28
|
+
* @group Form components
|
|
29
|
+
*/
|
|
30
|
+
export declare function ColorPicker({ value, onChange, size, allowClear, disabled }: ColorPickerProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -13,5 +13,12 @@ export type DateTimeFieldProps = {
|
|
|
13
13
|
inputClassName?: string;
|
|
14
14
|
invisible?: boolean;
|
|
15
15
|
locale?: string;
|
|
16
|
+
/**
|
|
17
|
+
* IANA timezone string (e.g., "America/New_York", "Europe/London").
|
|
18
|
+
* Used to display and input dates in the specified timezone.
|
|
19
|
+
* The value passed to onChange will always be in UTC.
|
|
20
|
+
* If not provided, uses the user's local timezone.
|
|
21
|
+
*/
|
|
22
|
+
timezone?: string;
|
|
16
23
|
};
|
|
17
24
|
export declare const DateTimeField: React.FC<DateTimeFieldProps>;
|
|
@@ -19,6 +19,7 @@ export type DialogProps = {
|
|
|
19
19
|
* If `true`, the dialog will not focus the first focusable element when opened.
|
|
20
20
|
*/
|
|
21
21
|
disableInitialFocus?: boolean;
|
|
22
|
+
portalContainer?: HTMLElement | null;
|
|
22
23
|
};
|
|
23
24
|
declare const widthClasses: {
|
|
24
25
|
xs: string;
|
|
@@ -34,5 +35,5 @@ declare const widthClasses: {
|
|
|
34
35
|
"7xl": string;
|
|
35
36
|
full: string;
|
|
36
37
|
};
|
|
37
|
-
export declare const Dialog: ({ open, onOpenChange, children, className, containerClassName, fullWidth, fullHeight, fullScreen, scrollable, maxWidth, modal, onOpenAutoFocus, onEscapeKeyDown, onPointerDownOutside, onInteractOutside, disableInitialFocus }: DialogProps) => import("react/jsx-runtime").JSX.Element;
|
|
38
|
+
export declare const Dialog: ({ open, onOpenChange, children, className, containerClassName, fullWidth, fullHeight, fullScreen, scrollable, maxWidth, modal, onOpenAutoFocus, onEscapeKeyDown, onPointerDownOutside, onInteractOutside, disableInitialFocus, portalContainer }: DialogProps) => import("react/jsx-runtime").JSX.Element;
|
|
38
39
|
export {};
|
|
@@ -18,6 +18,6 @@ export type FileUploadProps = {
|
|
|
18
18
|
title?: React.ReactNode;
|
|
19
19
|
uploadDescription?: React.ReactNode;
|
|
20
20
|
preventDropOnDocument?: boolean;
|
|
21
|
-
size?: "medium" | "large";
|
|
21
|
+
size?: "small" | "medium" | "large";
|
|
22
22
|
};
|
|
23
23
|
export declare function FileUpload({ accept, onFilesAdded, onFilesRejected, maxSize, disabled, maxFiles, title, uploadDescription, children, preventDropOnDocument, size }: React.PropsWithChildren<FileUploadProps>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -16,7 +16,8 @@ export { Menu };
|
|
|
16
16
|
export type MenuItemProps = {
|
|
17
17
|
children: React.ReactNode;
|
|
18
18
|
dense?: boolean;
|
|
19
|
+
disabled?: boolean;
|
|
19
20
|
onClick?: (event: React.MouseEvent) => void;
|
|
20
21
|
className?: string;
|
|
21
22
|
};
|
|
22
|
-
export declare const MenuItem: React.MemoExoticComponent<({ children, dense, onClick, className }: MenuItemProps) => import("react/jsx-runtime").JSX.Element>;
|
|
23
|
+
export declare const MenuItem: React.MemoExoticComponent<({ children, dense, disabled, onClick, className }: MenuItemProps) => import("react/jsx-runtime").JSX.Element>;
|
|
@@ -12,8 +12,9 @@ export declare function MenubarTrigger({ children, onSelect, className }: {
|
|
|
12
12
|
onSelect?: (event: React.SyntheticEvent) => void;
|
|
13
13
|
className?: string;
|
|
14
14
|
}): import("react/jsx-runtime").JSX.Element;
|
|
15
|
-
export declare function MenubarPortal({ children, }: {
|
|
15
|
+
export declare function MenubarPortal({ children, portalContainer, }: {
|
|
16
16
|
children: React.ReactNode;
|
|
17
|
+
portalContainer?: HTMLElement | null;
|
|
17
18
|
}): import("react/jsx-runtime").JSX.Element;
|
|
18
19
|
export declare function MenubarContent({ children, className, align, sideOffset, alignOffset, onSelect, ...rest }: {
|
|
19
20
|
children: React.ReactNode;
|
|
@@ -36,6 +36,7 @@ interface MultiSelectProps<T extends MultiSelectValue = string> {
|
|
|
36
36
|
invisible?: boolean;
|
|
37
37
|
children: React.ReactNode;
|
|
38
38
|
renderValues?: (values: T[]) => React.ReactNode;
|
|
39
|
+
portalContainer?: HTMLElement | null;
|
|
39
40
|
}
|
|
40
41
|
export declare const MultiSelect: React.ForwardRefExoticComponent<MultiSelectProps<string> & React.RefAttributes<HTMLButtonElement>>;
|
|
41
42
|
export interface MultiSelectItemProps<T extends MultiSelectValue = string> {
|
|
@@ -4,6 +4,16 @@ interface SearchBarProps {
|
|
|
4
4
|
onTextSearch?: (searchString?: string) => void;
|
|
5
5
|
placeholder?: string;
|
|
6
6
|
expandable?: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Size of the search bar.
|
|
9
|
+
* - "small": 32px height (matches TextField small)
|
|
10
|
+
* - "medium": 44px height (matches TextField medium)
|
|
11
|
+
* @default "medium"
|
|
12
|
+
*/
|
|
13
|
+
size?: "small" | "medium";
|
|
14
|
+
/**
|
|
15
|
+
* @deprecated Use size="medium" or size="small" instead. This prop will be removed in a future version.
|
|
16
|
+
*/
|
|
7
17
|
large?: boolean;
|
|
8
18
|
innerClassName?: string;
|
|
9
19
|
className?: string;
|
|
@@ -12,5 +22,5 @@ interface SearchBarProps {
|
|
|
12
22
|
loading?: boolean;
|
|
13
23
|
inputRef?: React.Ref<HTMLInputElement>;
|
|
14
24
|
}
|
|
15
|
-
export declare function SearchBar({ onClick, onTextSearch, placeholder, expandable, large, innerClassName, className, autoFocus, disabled, loading, inputRef }: SearchBarProps): import("react/jsx-runtime").JSX.Element;
|
|
25
|
+
export declare function SearchBar({ onClick, onTextSearch, placeholder, expandable, size, large, innerClassName, className, autoFocus, disabled, loading, inputRef }: SearchBarProps): import("react/jsx-runtime").JSX.Element;
|
|
16
26
|
export {};
|
|
@@ -25,6 +25,7 @@ export type SelectProps<T extends SelectValue = string> = {
|
|
|
25
25
|
invisible?: boolean;
|
|
26
26
|
children?: React.ReactNode;
|
|
27
27
|
dataType?: "string" | "number" | "boolean";
|
|
28
|
+
portalContainer?: HTMLElement | null;
|
|
28
29
|
};
|
|
29
30
|
export declare const Select: React.ForwardRefExoticComponent<SelectProps<string> & React.RefAttributes<HTMLDivElement>>;
|
|
30
31
|
export type SelectItemProps<T extends SelectValue = string> = {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export type ToggleButtonOption<T extends string = string> = {
|
|
3
|
+
value: T;
|
|
4
|
+
label: string;
|
|
5
|
+
icon?: React.ReactNode;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
};
|
|
8
|
+
export type ToggleButtonGroupProps<T extends string = string> = {
|
|
9
|
+
/**
|
|
10
|
+
* Currently selected value
|
|
11
|
+
*/
|
|
12
|
+
value: T;
|
|
13
|
+
/**
|
|
14
|
+
* Callback when value changes
|
|
15
|
+
*/
|
|
16
|
+
onValueChange: (value: T) => void;
|
|
17
|
+
/**
|
|
18
|
+
* Options to display
|
|
19
|
+
*/
|
|
20
|
+
options: ToggleButtonOption<T>[];
|
|
21
|
+
/**
|
|
22
|
+
* Additional class names for the container
|
|
23
|
+
*/
|
|
24
|
+
className?: string;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* A toggle button group component for selecting one option from a set.
|
|
28
|
+
* Displays options as buttons in a horizontal row with active state styling.
|
|
29
|
+
*/
|
|
30
|
+
export declare function ToggleButtonGroup<T extends string = string>({ value, onValueChange, options, className }: ToggleButtonGroupProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -11,6 +11,7 @@ export * from "./Collapse";
|
|
|
11
11
|
export * from "./CircularProgress";
|
|
12
12
|
export * from "./Checkbox";
|
|
13
13
|
export * from "./Chip";
|
|
14
|
+
export * from "./ColorPicker";
|
|
14
15
|
export * from "./DateTimeField";
|
|
15
16
|
export * from "./Dialog";
|
|
16
17
|
export * from "./DialogActions";
|
|
@@ -44,3 +45,4 @@ export * from "./Popover";
|
|
|
44
45
|
export * from "./Badge";
|
|
45
46
|
export * from "./DebouncedTextField";
|
|
46
47
|
export * from "./Skeleton";
|
|
48
|
+
export * from "./ToggleButtonGroup";
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface PortalContainerContextType {
|
|
3
|
+
container: HTMLElement | null;
|
|
4
|
+
}
|
|
5
|
+
export interface PortalContainerProviderProps {
|
|
6
|
+
container: HTMLElement | null;
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Provider component that sets the portal container for all descendants.
|
|
11
|
+
* This can be used at any level of the tree to specify where portals should be attached.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* const containerRef = useRef<HTMLDivElement>(null);
|
|
16
|
+
*
|
|
17
|
+
* <div ref={containerRef}>
|
|
18
|
+
* <PortalContainerProvider container={containerRef.current}>
|
|
19
|
+
* <YourComponents />
|
|
20
|
+
* </PortalContainerProvider>
|
|
21
|
+
* </div>
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare function PortalContainerProvider({ container, children }: PortalContainerProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
25
|
+
/**
|
|
26
|
+
* Hook to access the portal container from context.
|
|
27
|
+
* Returns null if no provider is found in the tree.
|
|
28
|
+
*
|
|
29
|
+
* @returns The portal container element or null
|
|
30
|
+
*/
|
|
31
|
+
export declare function usePortalContainer(): HTMLElement | null;
|
package/dist/hooks/index.d.ts
CHANGED
package/dist/index.css
CHANGED
|
@@ -1,3 +1,59 @@
|
|
|
1
|
+
@theme {
|
|
2
|
+
/* Font Families */
|
|
3
|
+
--font-sans: 'Rubik', 'Roboto', 'Helvetica', 'Arial', sans-serif;
|
|
4
|
+
--font-headers: 'Rubik', 'Roboto', 'Helvetica', 'Arial', sans-serif;
|
|
5
|
+
--font-mono: 'JetBrains Mono', 'Space Mono', 'Lucida Console', monospace;
|
|
6
|
+
|
|
7
|
+
/* Colors */
|
|
8
|
+
--color-primary: #0070F4;
|
|
9
|
+
--color-primary-light: oklch(from var(--color-primary) calc(l + 0.15) c h);
|
|
10
|
+
--color-primary-dark: oklch(from var(--color-primary) calc(l - 0.15) c h);
|
|
11
|
+
--color-secondary: #FF5B79;
|
|
12
|
+
--color-secondary-light: oklch(from var(--color-secondary) calc(l + 0.15) c h);
|
|
13
|
+
--color-secondary-dark: oklch(from var(--color-secondary) calc(l - 0.15) c h);
|
|
14
|
+
|
|
15
|
+
--color-primary-bg: oklch(from var(--color-primary) l c h / 0.1);
|
|
16
|
+
--color-secondary-bg: oklch(from var(--color-secondary) l c h / 0.1);
|
|
17
|
+
|
|
18
|
+
/* Field Colors */
|
|
19
|
+
--color-field-disabled: rgb(224 224 226);
|
|
20
|
+
--color-field-disabled-dark: rgb(35 35 37);
|
|
21
|
+
|
|
22
|
+
/* Text Colors */
|
|
23
|
+
--color-text-primary: rgba(0, 0, 0, 0.87);
|
|
24
|
+
--color-text-secondary: rgba(0, 0, 0, 0.52);
|
|
25
|
+
--color-text-disabled: rgba(0, 0, 0, 0.38);
|
|
26
|
+
--color-text-primary-dark: #ffffff;
|
|
27
|
+
--color-text-secondary-dark: rgba(255, 255, 255, 0.6);
|
|
28
|
+
--color-text-disabled-dark: rgba(255, 255, 255, 0.48);
|
|
29
|
+
|
|
30
|
+
/* Surface Colors */
|
|
31
|
+
--color-surface-50: #f8f8fc;
|
|
32
|
+
--color-surface-100: #e7e7eb;
|
|
33
|
+
--color-surface-200: #cfcfd6;
|
|
34
|
+
--color-surface-300: #b7b7bf;
|
|
35
|
+
--color-surface-400: #a0a0a9;
|
|
36
|
+
--color-surface-500: #87878f;
|
|
37
|
+
--color-surface-600: #6b6b74;
|
|
38
|
+
--color-surface-700: #454552;
|
|
39
|
+
--color-surface-800: #292934;
|
|
40
|
+
--color-surface-900: #18181c;
|
|
41
|
+
--color-surface-950: #101013;
|
|
42
|
+
|
|
43
|
+
/* Surface Accent Colors */
|
|
44
|
+
--color-surface-accent-50: #f8fafc;
|
|
45
|
+
--color-surface-accent-100: #f1f5f9;
|
|
46
|
+
--color-surface-accent-200: #e2e8f0;
|
|
47
|
+
--color-surface-accent-300: #cbd5e1;
|
|
48
|
+
--color-surface-accent-400: #94a3b8;
|
|
49
|
+
--color-surface-accent-500: #64748b;
|
|
50
|
+
--color-surface-accent-600: #475569;
|
|
51
|
+
--color-surface-accent-700: #334155;
|
|
52
|
+
--color-surface-accent-800: #1e293b;
|
|
53
|
+
--color-surface-accent-900: #0f172a;
|
|
54
|
+
--color-surface-accent-950: #020617;
|
|
55
|
+
}
|
|
56
|
+
|
|
1
57
|
/* Chrome, Safari and Opera */
|
|
2
58
|
.no-scrollbar::-webkit-scrollbar {
|
|
3
59
|
display: none;
|
|
@@ -63,12 +119,7 @@
|
|
|
63
119
|
@apply text-sm font-semibold uppercase;
|
|
64
120
|
}
|
|
65
121
|
|
|
66
|
-
|
|
67
122
|
:focus-visible {
|
|
68
|
-
@apply outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
a {
|
|
72
|
-
@apply text-blue-600 dark:text-blue-400 dark:hover:text-blue-600 hover:text-blue-800
|
|
123
|
+
@apply outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-transparent
|
|
73
124
|
}
|
|
74
125
|
|