@firecms/ui 3.0.0-beta.8 → 3.0.0-beta.9

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.
Files changed (59) hide show
  1. package/dist/components/BooleanSwitch.d.ts +1 -1
  2. package/dist/components/Checkbox.d.ts +1 -1
  3. package/dist/components/Chip.d.ts +3 -2
  4. package/dist/components/DateTimeField.d.ts +2 -3
  5. package/dist/components/Dialog.d.ts +4 -1
  6. package/dist/components/Menu.d.ts +4 -1
  7. package/dist/components/Menubar.d.ts +19 -9
  8. package/dist/components/MultiSelect.d.ts +31 -16
  9. package/dist/components/Popover.d.ts +2 -1
  10. package/dist/components/RadioGroup.d.ts +1 -0
  11. package/dist/components/Select.d.ts +5 -9
  12. package/dist/components/Separator.d.ts +2 -1
  13. package/dist/components/Sheet.d.ts +4 -0
  14. package/dist/components/Table.d.ts +10 -10
  15. package/dist/components/Tooltip.d.ts +6 -2
  16. package/dist/components/_MultiSelect.d.ts +0 -0
  17. package/dist/icons/Icon.d.ts +1 -1
  18. package/dist/index.css +77 -0
  19. package/dist/index.es.js +13036 -13690
  20. package/dist/index.es.js.map +1 -1
  21. package/dist/index.umd.js +19684 -49
  22. package/dist/index.umd.js.map +1 -1
  23. package/dist/styles.d.ts +3 -3
  24. package/package.json +109 -106
  25. package/src/components/Avatar.tsx +0 -2
  26. package/src/components/BooleanSwitch.tsx +11 -11
  27. package/src/components/BooleanSwitchWithLabel.tsx +4 -4
  28. package/src/components/Button.tsx +6 -8
  29. package/src/components/Card.tsx +2 -2
  30. package/src/components/Checkbox.tsx +5 -5
  31. package/src/components/Chip.tsx +7 -4
  32. package/src/components/DateTimeField.tsx +30 -41
  33. package/src/components/Dialog.tsx +11 -2
  34. package/src/components/ExpandablePanel.tsx +3 -3
  35. package/src/components/FileUpload.tsx +1 -2
  36. package/src/components/IconButton.tsx +1 -3
  37. package/src/components/InputLabel.tsx +4 -2
  38. package/src/components/Menu.tsx +38 -26
  39. package/src/components/Menubar.tsx +42 -7
  40. package/src/components/MultiSelect.tsx +333 -164
  41. package/src/components/Popover.tsx +15 -13
  42. package/src/components/RadioGroup.tsx +1 -0
  43. package/src/components/SearchBar.tsx +1 -2
  44. package/src/components/Select.tsx +98 -119
  45. package/src/components/Separator.tsx +10 -4
  46. package/src/components/Sheet.tsx +39 -22
  47. package/src/components/Skeleton.tsx +1 -1
  48. package/src/components/Table.tsx +48 -30
  49. package/src/components/Tabs.tsx +2 -3
  50. package/src/components/TextField.tsx +2 -6
  51. package/src/components/Tooltip.tsx +26 -11
  52. package/src/components/Typography.tsx +14 -16
  53. package/src/components/_MultiSelect.tsx +222 -0
  54. package/src/icons/Icon.tsx +2 -2
  55. package/src/icons/icon_keys.ts +114 -1301
  56. package/src/index.css +77 -0
  57. package/src/scripts/generateIconKeys.ts +20 -10
  58. package/src/styles.ts +3 -3
  59. package/tailwind.config.js +3 -3
@@ -7,7 +7,6 @@ import {
7
7
  fieldBackgroundInvisibleMixin,
8
8
  fieldBackgroundMixin,
9
9
  focusedInvisibleMixin,
10
- focusedMixin
11
10
  } from "../styles";
12
11
  import { InputLabel } from "./InputLabel";
13
12
  import { cls } from "../util";
@@ -70,7 +69,6 @@ export function TextField<T extends string | number>({
70
69
  ...inputProps
71
70
  }: TextFieldProps<T>) {
72
71
 
73
- // eslint-disable-next-line react-hooks/rules-of-hooks
74
72
  const inputRef = inputRefProp ?? useRef(null);
75
73
 
76
74
  // @ts-ignore
@@ -106,13 +104,11 @@ export function TextField<T extends string | number>({
106
104
  placeholder={focused || hasValue || !label ? placeholder : undefined}
107
105
  autoFocus={autoFocus}
108
106
  rows={rows}
109
- // onFocus={() => setFocused(true)}
110
- // onBlur={() => setFocused(false)}
111
107
  value={value ?? ""}
112
108
  onChange={onChange}
113
109
  style={inputStyle}
114
110
  className={cls(
115
- invisible ? focusedInvisibleMixin : focusedMixin,
111
+ invisible ? focusedInvisibleMixin : "",
116
112
  "rounded-md resize-none w-full outline-none p-[32px] text-base bg-transparent min-h-[64px] px-3 pt-[28px]",
117
113
  disabled && "border border-transparent outline-none opacity-50 text-slate-600 dark:text-slate-500"
118
114
  )}
@@ -126,7 +122,7 @@ export function TextField<T extends string | number>({
126
122
  className={cls(
127
123
  "w-full outline-none bg-transparent leading-normal px-3",
128
124
  "rounded-md",
129
- invisible ? focusedInvisibleMixin : focusedMixin,
125
+ invisible ? focusedInvisibleMixin : "",
130
126
  disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin,
131
127
  size === "smallest" ? "min-h-[32px]" : (size === "small" ? "min-h-[48px]" : "min-h-[64px]"),
132
128
  label ? (size === "medium" ? "pt-[28px] pb-2" : "pt-4 pb-2") : "py-2",
@@ -6,30 +6,38 @@ import { useInjectStyles } from "../hooks";
6
6
 
7
7
  export type TooltipProps = {
8
8
  open?: boolean,
9
+ defaultOpen?: boolean,
9
10
  onOpenChange?: (open: boolean) => void,
10
11
  side?: "top" | "bottom" | "left" | "right",
11
12
  align?: "start" | "center" | "end",
12
13
  sideOffset?: number,
13
14
  title?: string | React.ReactNode,
14
15
  delayDuration?: number;
15
- className?: string,
16
+ asChild?: boolean;
16
17
  tooltipClassName?: string,
18
+ tooltipStyle?: React.CSSProperties;
17
19
  children: React.ReactNode,
20
+ className?: string,
21
+ container?: HTMLElement,
18
22
  style?: React.CSSProperties;
19
23
  };
20
24
 
21
25
  export const Tooltip = ({
22
26
  open,
27
+ defaultOpen,
23
28
  side = "bottom",
24
29
  delayDuration = 200,
25
30
  sideOffset,
26
31
  align,
27
32
  onOpenChange,
28
33
  title,
29
- className,
30
- style,
31
34
  tooltipClassName,
32
- children
35
+ tooltipStyle,
36
+ children,
37
+ asChild = false,
38
+ container,
39
+ className,
40
+ style
33
41
  }: TooltipProps) => {
34
42
 
35
43
  useInjectStyles("Tooltip", styles);
@@ -37,20 +45,27 @@ export const Tooltip = ({
37
45
  if (!title)
38
46
  return <>{children}</>;
39
47
 
48
+ const trigger = asChild
49
+ ? <TooltipPrimitive.Trigger asChild={true}>
50
+ {children}
51
+ </TooltipPrimitive.Trigger>
52
+ : <TooltipPrimitive.Trigger asChild={true}>
53
+ <div style={style} className={className}>
54
+ {children}
55
+ </div>
56
+ </TooltipPrimitive.Trigger>;
57
+
40
58
  return (
41
59
  <TooltipPrimitive.Provider delayDuration={delayDuration}>
42
- <TooltipPrimitive.Root open={open} onOpenChange={onOpenChange}>
43
- <TooltipPrimitive.Trigger asChild>
44
- <div className={className} style={style}>
45
- {children}
46
- </div>
47
- </TooltipPrimitive.Trigger>
48
- <TooltipPrimitive.Portal>
60
+ <TooltipPrimitive.Root open={open} onOpenChange={onOpenChange} defaultOpen={defaultOpen}>
61
+ {trigger}
62
+ <TooltipPrimitive.Portal container={container}>
49
63
  <TooltipPrimitive.Content
50
64
  className={cls("TooltipContent",
51
65
  "max-w-lg leading-relaxed",
52
66
  "z-50 rounded px-3 py-2 text-xs leading-none bg-slate-700 dark:bg-slate-800 bg-opacity-90 font-medium text-slate-50 shadow-2xl select-none duration-400 ease-in transform opacity-100",
53
67
  tooltipClassName)}
68
+ style={tooltipStyle}
54
69
  sideOffset={sideOffset === undefined ? 4 : sideOffset}
55
70
  align={align}
56
71
  side={side}>
@@ -1,5 +1,4 @@
1
1
  import React, { ReactEventHandler } from "react";
2
- import { focusedMixin } from "../styles";
3
2
  import { cls } from "../util";
4
3
 
5
4
  export type TextProps<C extends React.ElementType> = {
@@ -61,20 +60,20 @@ const gutterBottomClasses = {
61
60
  };
62
61
 
63
62
  const variantToClasses = {
64
- h1: "text-6xl font-headers font-light",
65
- h2: "text-5xl font-headers font-light",
66
- h3: "text-4xl font-headers font-normal",
67
- h4: "text-3xl font-headers font-normal",
68
- h5: "text-2xl font-headers font-normal",
69
- h6: "text-xl font-headers font-medium",
70
- subtitle1: "text-lg font-headers font-medium",
71
- subtitle2: "text-base font-headers font-medium",
72
- body1: "text-base",
73
- body2: "text-sm",
74
- label: "text-sm font-medium text-slate-500",
75
- inherit: "text-inherit",
76
- caption: "text-xs",
77
- button: "text-sm font-medium"
63
+ h1: "typography-h1",
64
+ h2: "typography-h2",
65
+ h3: "typography-h3",
66
+ h4: "typography-h4",
67
+ h5: "typography-h5",
68
+ h6: "typography-h6",
69
+ subtitle1: "typography-subtitle1",
70
+ subtitle2: "typography-subtitle2",
71
+ body1: "typography-body1",
72
+ body2: "typography-body2",
73
+ label: "typography-label",
74
+ inherit: "typography-inherit",
75
+ caption: "typography-caption",
76
+ button: "typography-button"
78
77
  };
79
78
 
80
79
  export function Typography<C extends React.ElementType>(
@@ -100,7 +99,6 @@ export function Typography<C extends React.ElementType>(
100
99
  "span";
101
100
 
102
101
  const classes = cls(
103
- focusedMixin,
104
102
  variantToClasses[variant],
105
103
  color ? colorToClasses[color] : "",
106
104
  align !== "inherit" && `text-${align}`,
@@ -0,0 +1,222 @@
1
+ // import * as React from "react";
2
+ // import { useEffect } from "react";
3
+ // import * as Dialog from "@radix-ui/react-dialog";
4
+ //
5
+ // import { Command as CommandPrimitive } from "cmdk";
6
+ //
7
+ // import { ExpandMoreIcon } from "../icons";
8
+ // import { fieldBackgroundDisabledMixin, fieldBackgroundHoverMixin, fieldBackgroundMixin, focusedDisabled } from "../styles";
9
+ // import { cls } from "../util";
10
+ // import { SelectInputLabel } from "./common/SelectInputLabel";
11
+ // import { useOutsideAlerter } from "../hooks";
12
+ //
13
+ // export type MultiSelectProps = {
14
+ // open?: boolean,
15
+ // name?: string,
16
+ // id?: string,
17
+ // onOpenChange?: (open: boolean) => void,
18
+ // value?: string[],
19
+ // containerClassName?: string,
20
+ // className?: string,
21
+ // inputClassName?: string,
22
+ // onMultiValueChange?: (updatedValue: string[]) => void,
23
+ // placeholder?: React.ReactNode,
24
+ // renderValue?: (values: string, index:number) => React.ReactNode,
25
+ // renderValues?: (values: string[]) => React.ReactNode,
26
+ // size?: "small" | "medium",
27
+ // label?: React.ReactNode,
28
+ // disabled?: boolean,
29
+ // error?: boolean,
30
+ // position?: "item-aligned" | "popper",
31
+ // inputRef?: React.RefObject<HTMLButtonElement>,
32
+ // children?: React.ReactNode,
33
+ // };
34
+ //
35
+ // interface MultiSelectContextProps {
36
+ // fieldValue?: string[];
37
+ // setInputValue: (v: string) => void;
38
+ // onValueChangeInternal: (v: string) => void;
39
+ // }
40
+ //
41
+ // export const MultiSelectContext = React.createContext<MultiSelectContextProps>({} as any);
42
+ //
43
+ // export function MultiSelect({
44
+ // value,
45
+ // open,
46
+ // onMultiValueChange,
47
+ // size = "medium",
48
+ // label,
49
+ // disabled,
50
+ // renderValue,
51
+ // renderValues,
52
+ // containerClassName,
53
+ // className,
54
+ // children,
55
+ // error
56
+ // }: MultiSelectProps) {
57
+ //
58
+ // const containerRef = React.useRef<HTMLInputElement>(null);
59
+ // const inputRef = React.useRef<HTMLInputElement>(null);
60
+ // const listRef = React.useRef<HTMLDivElement>(null);
61
+ // useOutsideAlerter(listRef, () => setOpenInternal(false));
62
+ //
63
+ // const [openInternal, setOpenInternal] = React.useState(false);
64
+ // useEffect(() => {
65
+ // setOpenInternal(open ?? false);
66
+ // }, [open]);
67
+ //
68
+ // const onValueChangeInternal = React.useCallback((newValue: string) => {
69
+ // if (Array.isArray(value) && value.includes(newValue)) {
70
+ // onMultiValueChange?.(value.filter(v => v !== newValue));
71
+ // } else {
72
+ // onMultiValueChange?.([...(value ?? []), newValue]);
73
+ // }
74
+ // }, [value, onMultiValueChange]);
75
+ //
76
+ // const [inputValue, setInputValue] = React.useState("");
77
+ // const [boundingRect, setBoundingRect] = React.useState<DOMRect | null>(null);
78
+ //
79
+ // const handleKeyDown = React.useCallback((e: React.KeyboardEvent<HTMLDivElement>) => {
80
+ // const input = inputRef.current
81
+ // if (input) {
82
+ // if (e.key === "Delete" || e.key === "Backspace") {
83
+ // if (input.value === "") {
84
+ // const newSelected = [...(value ?? [])];
85
+ // newSelected.pop();
86
+ // onMultiValueChange?.(newSelected);
87
+ // }
88
+ // }
89
+ // // This is not a default behaviour of the <input /> field
90
+ // if (e.key === "Escape") {
91
+ // input.blur();
92
+ // setOpenInternal(false);
93
+ // e.stopPropagation();
94
+ // }
95
+ // }
96
+ // }, [onMultiValueChange, value]);
97
+ //
98
+ // const openDialog = React.useCallback(() => {
99
+ // setBoundingRect(containerRef.current?.getBoundingClientRect() ?? null);
100
+ // setOpenInternal(true);
101
+ // }, []);
102
+ //
103
+ // const usedBoundingRect = boundingRect ?? containerRef.current?.getBoundingClientRect();
104
+ // const maxHeight = window.innerHeight - (usedBoundingRect?.top ?? 0) - (usedBoundingRect?.height ?? 0) - 16;
105
+ //
106
+ // return (<>
107
+ //
108
+ // {typeof label === "string" ? <SelectInputLabel error={error}>{label}</SelectInputLabel> : label}
109
+ //
110
+ // <CommandPrimitive onKeyDown={handleKeyDown}
111
+ // onClick={() => {
112
+ // inputRef.current?.focus();
113
+ // openDialog()
114
+ // }}
115
+ // className={cls("relative overflow-visible bg-transparent", containerClassName)}>
116
+ // <div
117
+ // ref={containerRef}
118
+ // className={cls(
119
+ // "flex flex-row",
120
+ // size === "small" ? "min-h-[42px]" : "min-h-[64px]",
121
+ // "select-none rounded-md text-sm",
122
+ // fieldBackgroundMixin,
123
+ // disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin,
124
+ // "relative flex items-center",
125
+ // "p-4",
126
+ // error ? "text-red-500 dark:text-red-600" : "focus:text-text-primary dark:focus:text-text-primary-dark",
127
+ // error ? "border border-red-500 dark:border-red-600" : "",
128
+ // className)}
129
+ // >
130
+ // <div className={cls("flex-grow flex gap-1.5 flex-wrap items-center")}>
131
+ // {renderValue && (value ?? []).map((v, i) => renderValue(v, i))}
132
+ // {renderValues && renderValues(value ?? [])}
133
+ // <CommandPrimitive.Input
134
+ // ref={inputRef}
135
+ // value={inputValue}
136
+ // onValueChange={setInputValue}
137
+ // // onBlur={() => setOpenInternal(false)}
138
+ // onFocus={openDialog}
139
+ // className={cls("ml-2 bg-transparent outline-none flex-1 h-full w-full ", focusedDisabled)}
140
+ // />
141
+ // </div>
142
+ // <div className={"px-2 h-full flex items-center"}>
143
+ // <ExpandMoreIcon size={"small"}
144
+ // className={cls("transition ", openInternal ? "rotate-180" : "")}/>
145
+ // </div>
146
+ //
147
+ // </div>
148
+ //
149
+ // <Dialog.Root open={openInternal}
150
+ // modal={true}
151
+ // onOpenChange={setOpenInternal}>
152
+ // <Dialog.Portal>
153
+ // <MultiSelectContext.Provider
154
+ // value={{
155
+ // fieldValue: value,
156
+ // setInputValue,
157
+ // onValueChangeInternal
158
+ // }}>
159
+ // <div
160
+ // ref={listRef}
161
+ // className={"z-50 absolute overflow-auto outline-none"}
162
+ // style={{
163
+ // pointerEvents: openInternal ? "auto" : "none",
164
+ // top: (usedBoundingRect?.top ?? 0) + (usedBoundingRect?.height ?? 0),
165
+ // left: usedBoundingRect?.left,
166
+ // width: usedBoundingRect?.width,
167
+ // maxHeight: maxHeight,
168
+ //
169
+ // }}>
170
+ //
171
+ // <CommandPrimitive.Group
172
+ // className="mt-2 text-slate-900 dark:text-white animate-in z-50 border border-slate-200 dark:border-slate-800 bg-white dark:bg-slate-800 p-2 rounded-lg shadow-lg flex flex-col outline-none w-full"
173
+ // >
174
+ //
175
+ // {children}
176
+ // </CommandPrimitive.Group>
177
+ //
178
+ // </div>
179
+ // </MultiSelectContext.Provider>
180
+ // </Dialog.Portal>
181
+ // </Dialog.Root>
182
+ // </CommandPrimitive>
183
+ //
184
+ // </>
185
+ // )
186
+ // }
187
+ //
188
+ // export interface MultiSelectItemProps {
189
+ // value: string;
190
+ // children?: React.ReactNode,
191
+ // className?: string;
192
+ // }
193
+ //
194
+ // export function MultiSelectItem({ children, value, className }: MultiSelectItemProps) {
195
+ //
196
+ // const context = React.useContext(MultiSelectContext);
197
+ // if (!context) throw new Error("MultiSelectItem must be used inside a MultiSelect");
198
+ // const { fieldValue, setInputValue, onValueChangeInternal } = context;
199
+ //
200
+ // return <CommandPrimitive.Item
201
+ // onMouseDown={(e) => {
202
+ // e.preventDefault();
203
+ // e.stopPropagation();
204
+ // }}
205
+ // onSelect={(_) => {
206
+ // setInputValue("");
207
+ // onValueChangeInternal(value);
208
+ // }}
209
+ // className={cls(
210
+ // (fieldValue ?? []).includes(value) ? "bg-slate-200 dark:bg-slate-950" : "",
211
+ // "cursor-pointer",
212
+ // "m-1",
213
+ // "ring-offset-transparent",
214
+ // "p-2 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",
215
+ // "aria-[selected=true]:bg-slate-100 aria-[selected=true]:dark:bg-slate-900",
216
+ // "cursor-pointer p-2 rounded aria-[selected=true]:bg-slate-100 aria-[selected=true]:dark:bg-slate-900",
217
+ // className
218
+ // )}
219
+ // >
220
+ // {children}
221
+ // </CommandPrimitive.Item>;
222
+ // }
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
- import "@material-design-icons/font/filled.css";
3
2
  import { cls } from "../util";
3
+ import 'material-icons/iconfont/filled.css';
4
4
 
5
5
  export type IconColor = "inherit" | "primary" | "secondary" | "disabled" | "error" | "success" | "warning";
6
6
  export type IconProps = {
@@ -17,7 +17,7 @@ const colorClassesMapping: Record<IconColor, string> = {
17
17
  success: "text-green-500",
18
18
  warning: "text-yellow-500",
19
19
  secondary: "text-secondary",
20
- disabled: "text-disabled dark:text-disabled-dark",
20
+ disabled: "text-text-disabled dark:text-text-disabled-dark",
21
21
  error: "text-red-500"
22
22
  }
23
23