@firecms/ui 3.0.0-canary.12 → 3.0.0-canary.121

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 (103) hide show
  1. package/README.md +1 -1
  2. package/dist/components/Avatar.d.ts +1 -0
  3. package/dist/components/BooleanSwitch.d.ts +1 -1
  4. package/dist/components/CenteredView.d.ts +4 -2
  5. package/dist/components/Checkbox.d.ts +3 -2
  6. package/dist/components/Chip.d.ts +3 -2
  7. package/dist/components/DateTimeField.d.ts +3 -4
  8. package/dist/components/Dialog.d.ts +4 -1
  9. package/dist/components/InputLabel.d.ts +2 -2
  10. package/dist/components/Label.d.ts +4 -1
  11. package/dist/components/Markdown.d.ts +1 -0
  12. package/dist/components/Menu.d.ts +6 -2
  13. package/dist/components/Menubar.d.ts +79 -0
  14. package/dist/components/MultiSelect.d.ts +31 -16
  15. package/dist/components/Popover.d.ts +2 -1
  16. package/dist/components/RadioGroup.d.ts +26 -3
  17. package/dist/components/Select.d.ts +6 -10
  18. package/dist/components/Separator.d.ts +2 -1
  19. package/dist/components/Sheet.d.ts +4 -0
  20. package/dist/components/Table.d.ts +10 -10
  21. package/dist/components/TextField.d.ts +1 -1
  22. package/dist/components/TextareaAutosize.d.ts +3 -34
  23. package/dist/components/Tooltip.d.ts +5 -2
  24. package/dist/components/_MultiSelect.d.ts +0 -0
  25. package/dist/components/index.d.ts +1 -1
  26. package/dist/hooks/index.d.ts +4 -0
  27. package/dist/hooks/useLocaleConfig.d.ts +1 -0
  28. package/dist/icons/Icon.d.ts +3 -3
  29. package/dist/index.css +77 -0
  30. package/dist/index.d.ts +1 -0
  31. package/dist/index.es.js +13176 -13540
  32. package/dist/index.es.js.map +1 -1
  33. package/dist/index.umd.js +19685 -49
  34. package/dist/index.umd.js.map +1 -1
  35. package/dist/styles.d.ts +7 -7
  36. package/dist/util/{cn.d.ts → cls.d.ts} +4 -0
  37. package/dist/util/index.d.ts +1 -3
  38. package/package.json +109 -118
  39. package/src/components/Alert.tsx +2 -2
  40. package/src/components/Autocomplete.tsx +4 -3
  41. package/src/components/Avatar.tsx +7 -6
  42. package/src/components/Badge.tsx +1 -1
  43. package/src/components/BooleanSwitch.tsx +15 -15
  44. package/src/components/BooleanSwitchWithLabel.tsx +8 -8
  45. package/src/components/Button.tsx +11 -13
  46. package/src/components/Card.tsx +3 -3
  47. package/src/components/CenteredView.tsx +25 -15
  48. package/src/components/Checkbox.tsx +11 -9
  49. package/src/components/Chip.tsx +8 -5
  50. package/src/components/CircularProgress.tsx +2 -2
  51. package/src/components/Collapse.tsx +3 -2
  52. package/src/components/Container.tsx +2 -2
  53. package/src/components/DateTimeField.tsx +38 -48
  54. package/src/components/Dialog.tsx +15 -6
  55. package/src/components/DialogActions.tsx +2 -2
  56. package/src/components/DialogContent.tsx +2 -2
  57. package/src/components/ExpandablePanel.tsx +10 -8
  58. package/src/components/FileUpload.tsx +6 -9
  59. package/src/components/IconButton.tsx +4 -6
  60. package/src/components/InfoLabel.tsx +2 -2
  61. package/src/components/InputLabel.tsx +12 -9
  62. package/src/components/Label.tsx +17 -4
  63. package/src/components/Markdown.tsx +14 -3
  64. package/src/components/Menu.tsx +49 -31
  65. package/src/components/Menubar.tsx +322 -0
  66. package/src/components/MultiSelect.tsx +336 -165
  67. package/src/components/Paper.tsx +2 -2
  68. package/src/components/Popover.tsx +17 -14
  69. package/src/components/RadioGroup.tsx +41 -9
  70. package/src/components/SearchBar.tsx +7 -8
  71. package/src/components/Select.tsx +105 -124
  72. package/src/components/Separator.tsx +10 -4
  73. package/src/components/Sheet.tsx +45 -28
  74. package/src/components/Skeleton.tsx +9 -6
  75. package/src/components/Table.tsx +50 -32
  76. package/src/components/Tabs.tsx +6 -7
  77. package/src/components/TextField.tsx +10 -13
  78. package/src/components/TextareaAutosize.tsx +3 -3
  79. package/src/components/Tooltip.tsx +27 -13
  80. package/src/components/Typography.tsx +34 -19
  81. package/src/components/_MultiSelect.tsx +222 -0
  82. package/src/components/common/SelectInputLabel.tsx +2 -2
  83. package/src/components/index.tsx +1 -1
  84. package/src/hooks/index.ts +4 -0
  85. package/src/hooks/useLocaleConfig.tsx +18 -0
  86. package/src/icons/Icon.tsx +46 -43
  87. package/src/icons/icon_keys.ts +114 -1301
  88. package/src/index.css +77 -0
  89. package/src/index.ts +1 -0
  90. package/src/scripts/generateIconKeys.ts +20 -11
  91. package/src/styles.ts +7 -7
  92. package/src/util/cls.ts +14 -0
  93. package/src/util/index.ts +1 -3
  94. package/tailwind.config.js +8 -6
  95. package/dist/components/Spinner.d.ts +0 -1
  96. package/src/components/Spinner.tsx +0 -18
  97. package/src/util/cn.ts +0 -6
  98. /package/dist/{util → hooks}/useDebounceValue.d.ts +0 -0
  99. /package/dist/{util → hooks}/useInjectStyles.d.ts +0 -0
  100. /package/dist/{util → hooks}/useOutsideAlerter.d.ts +0 -0
  101. /package/src/{util → hooks}/useDebounceValue.tsx +0 -0
  102. /package/src/{util → hooks}/useInjectStyles.tsx +0 -0
  103. /package/src/{util → hooks}/useOutsideAlerter.tsx +0 -0
@@ -1,15 +1,36 @@
1
1
  import * as React from "react"
2
2
  import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"
3
- import { cn } from "../util";
4
- import { CircleIcon } from "../icons";
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
- React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>
9
- >(({ className, ...props }, ref) => {
26
+ RadioGroupProps
27
+ >(({
28
+ className,
29
+ ...props
30
+ }, ref) => {
10
31
  return (
11
32
  <RadioGroupPrimitive.Root
12
- className={cn("grid gap-2", 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
- React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>
23
- >(({ className, ...props }, ref) => {
51
+ RadioGroupItemProps
52
+ >(({
53
+ className,
54
+ ...props
55
+ }, ref) => {
24
56
  return (
25
57
  <RadioGroupPrimitive.Item
26
58
  ref={ref}
27
- className={cn(
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, focusedMixin } from "../styles";
3
+ import { defaultBorderMixin } from "../styles";
4
4
  import { CircularProgress, IconButton } from "./index";
5
5
  import { ClearIcon, SearchIcon } from "../icons";
6
- import { cn } from "../util";
7
- import { useDebounceValue } from "../util/useDebounceValue";
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={cn("relative",
63
+ className={cls("relative",
64
64
  large ? "h-14" : "h-[42px]",
65
- "bg-slate-50 dark:bg-gray-800 transition duration-150 ease-in-out border",
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 absolute pointer-events-none flex items-center justify-center top-0">
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={cn(
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
  />
@@ -1,15 +1,14 @@
1
- import React, { useEffect } from "react";
2
-
1
+ import React, { ChangeEvent, forwardRef, useCallback, useEffect, useState } from "react";
3
2
  import * as SelectPrimitive from "@radix-ui/react-select";
4
3
  import {
4
+ defaultBorderMixin,
5
5
  fieldBackgroundDisabledMixin,
6
6
  fieldBackgroundHoverMixin,
7
7
  fieldBackgroundInvisibleMixin,
8
- fieldBackgroundMixin,
9
- focusedMixin
8
+ fieldBackgroundMixin
10
9
  } from "../styles";
11
10
  import { CheckIcon, ExpandMoreIcon } from "../icons";
12
- import { cn } from "../util";
11
+ import { cls } from "../util";
13
12
  import { SelectInputLabel } from "./common/SelectInputLabel";
14
13
 
15
14
  export type SelectProps = {
@@ -17,89 +16,75 @@ export type SelectProps = {
17
16
  name?: string,
18
17
  id?: string,
19
18
  onOpenChange?: (open: boolean) => void,
20
- value?: string | string[],
19
+ value?: string,
21
20
  className?: string,
22
21
  inputClassName?: string,
23
- onChange?: React.EventHandler<React.ChangeEvent<HTMLSelectElement>>,
22
+ onChange?: React.EventHandler<ChangeEvent<HTMLSelectElement>>,
24
23
  onValueChange?: (updatedValue: string) => void,
25
- onMultiValueChange?: (updatedValue: string[]) => void,
26
24
  placeholder?: React.ReactNode,
27
- renderValue?: (value: string, index: number) => React.ReactNode,
28
- renderValues?: (values: string[]) => React.ReactNode,
25
+ renderValue?: (value: string) => React.ReactNode,
29
26
  size?: "small" | "medium",
30
- label?: React.ReactNode,
27
+ label?: React.ReactNode | string,
31
28
  disabled?: boolean,
32
29
  error?: boolean,
33
30
  position?: "item-aligned" | "popper",
34
31
  endAdornment?: React.ReactNode,
35
- multiple?: boolean,
36
32
  inputRef?: React.RefObject<HTMLButtonElement>,
37
33
  padding?: boolean,
38
- includeFocusOutline?: boolean,
39
34
  invisible?: boolean,
40
- children?: React.ReactNode
35
+ children?: React.ReactNode;
41
36
  };
42
37
 
43
- export function Select({
44
- inputRef,
45
- open,
46
- name,
47
- id,
48
- onOpenChange,
49
- value,
50
- onChange,
51
- onValueChange,
52
- onMultiValueChange,
53
- className,
54
- inputClassName,
55
- placeholder,
56
- renderValue,
57
- renderValues,
58
- label,
59
- size = "medium",
60
- includeFocusOutline = true,
61
- error,
62
- disabled,
63
- padding = true,
64
- position = "item-aligned",
65
- endAdornment,
66
- multiple,
67
- invisible,
68
- children,
69
- ...props
70
- }: SelectProps) {
38
+ export const Select = forwardRef<HTMLDivElement, SelectProps>(({
39
+ inputRef,
40
+ open,
41
+ name,
42
+ id,
43
+ onOpenChange,
44
+ value,
45
+ onChange,
46
+ onValueChange,
47
+ className,
48
+ inputClassName,
49
+ placeholder,
50
+ renderValue,
51
+ label,
52
+ size = "medium",
53
+ error,
54
+ disabled,
55
+ padding = true,
56
+ position = "item-aligned",
57
+ endAdornment,
58
+ invisible,
59
+ children,
60
+ ...props
61
+ }, ref) => {
62
+
63
+ const [openInternal, setOpenInternal] = useState(open ?? false);
71
64
 
72
- const [openInternal, setOpenInternal] = React.useState(false);
73
65
  useEffect(() => {
74
66
  setOpenInternal(open ?? false);
75
67
  }, [open]);
76
68
 
77
- const onValueChangeInternal = React.useCallback((newValue: string) => {
78
- if (multiple) {
79
- if (Array.isArray(value) && value.includes(newValue)) {
80
- onMultiValueChange?.(value.filter(v => v !== newValue));
81
- } else {
82
- onMultiValueChange?.([...(value as string[] ?? []), newValue]);
83
- }
84
- } else {
85
- onValueChange?.(newValue);
86
- }
87
- if (!multiple && onChange) {
69
+ const onValueChangeInternal = useCallback((newValue: string) => {
70
+ onValueChange?.(newValue);
71
+ if (onChange) {
88
72
  const event = {
89
73
  target: {
90
74
  name,
91
75
  value: newValue
92
76
  }
93
- } as React.ChangeEvent<HTMLSelectElement>;
77
+ } as ChangeEvent<HTMLSelectElement>;
94
78
  onChange(event);
95
79
  }
96
- }, [multiple, onChange, value, onMultiValueChange, onValueChange]);
80
+ }, [onChange, value, onValueChange]);
81
+
82
+ const hasValue = Array.isArray(value) ? value.length > 0 : value != null;
97
83
 
98
84
  return (
99
85
  <SelectPrimitive.Root
100
86
  name={name}
101
- value={Array.isArray(value) ? undefined : value}
102
- defaultOpen={open}
87
+ value={value}
103
88
  open={openInternal}
104
89
  disabled={disabled}
105
90
  onValueChange={onValueChangeInternal}
@@ -107,23 +92,22 @@ export function Select({
107
92
  onOpenChange?.(open);
108
93
  setOpenInternal(open);
109
94
  }}
110
- {...props}>
111
-
95
+ {...props}
96
+ >
112
97
  {typeof label === "string" ? <SelectInputLabel error={error}>{label}</SelectInputLabel> : label}
113
-
114
- <div
115
- className={cn(
116
- size === "small" ? "min-h-[42px]" : "min-h-[64px]",
117
- "select-none rounded-md text-sm",
118
- invisible ? fieldBackgroundInvisibleMixin : fieldBackgroundMixin,
119
- disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin,
120
- "relative flex items-center",
121
- className)}>
122
-
98
+ <div className={cls(
99
+ size === "small" ? "min-h-[42px]" : "min-h-[64px]",
100
+ "select-none rounded-md text-sm",
101
+ invisible ? fieldBackgroundInvisibleMixin : fieldBackgroundMixin,
102
+ disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin,
103
+ "relative flex items-center",
104
+ className
105
+ )}
106
+ >
123
107
  <SelectPrimitive.Trigger
124
108
  ref={inputRef}
125
109
  id={id}
126
- className={cn(
110
+ className={cls(
127
111
  "w-full h-full",
128
112
  size === "small" ? "h-[42px]" : "h-[64px]",
129
113
  padding ? "px-4 " : "",
@@ -133,65 +117,63 @@ export function Select({
133
117
  error ? "border border-red-500 dark:border-red-600" : "",
134
118
  disabled ? "text-slate-600 dark:text-slate-400" : "text-slate-800 dark:text-white",
135
119
  "relative flex items-center",
136
- includeFocusOutline ? focusedMixin : "",
137
120
  inputClassName
138
- )}>
139
-
140
- <div className={cn(
141
- "flex-grow w-full max-w-full flex flex-row gap-2 items-center",
142
- "overflow-visible",
143
- size === "small" ? "h-[42px]" : "h-[64px]"
144
- )}>
145
- <SelectPrimitive.Value >
146
- {renderValue &&
147
- (value && Array.isArray(value)
148
- ? value.map((v, i) => (
149
- <div key={v} className={"flex items-center gap-1 max-w-full"}>
150
- {renderValue ? renderValue(v, i) : v}
151
- </div>))
152
- : (typeof value === "string" ? (renderValue ? renderValue(value, 0) : value) : placeholder))}
153
-
154
- {renderValues && (!value || Array.isArray(value))
155
- ? renderValues(value as string[] ?? [])
156
- : null}
157
-
158
- {!renderValue && !renderValues && value}
159
-
160
- </SelectPrimitive.Value>
121
+ )}
122
+
123
+ onClick={(e) => {
124
+ e.preventDefault();
125
+ e.stopPropagation();
126
+ }}
127
+ >
128
+ <div
129
+ ref={ref}
130
+ className={cls(
131
+ "flex-grow w-full max-w-full flex flex-row gap-2 items-center",
132
+ "overflow-visible",
133
+ size === "small" ? "h-[42px]" : "h-[64px]"
134
+ )}
135
+ >
136
+ <SelectPrimitive.Value
137
+ onClick={(e) => {
138
+ e.preventDefault();
139
+ e.stopPropagation();
140
+ }}
141
+ placeholder={placeholder}
142
+ className={"w-full"}>
143
+ {!hasValue && placeholder}
144
+ {hasValue && value && renderValue ? renderValue(value) : placeholder}
145
+ {hasValue && !renderValue && value}
146
+ </SelectPrimitive.Value>
161
147
  </div>
162
-
163
- <SelectPrimitive.Icon className={cn(
164
- "px-2 h-full flex items-center",
165
- )}>
166
- <ExpandMoreIcon size={"small"}
167
- className={cn("transition", open ? "rotate-180" : "")}/>
148
+ <SelectPrimitive.Icon className={cls("px-2 h-full flex items-center")}>
149
+ <ExpandMoreIcon size={"small"} className={cls("transition", open ? "rotate-180" : "")}/>
168
150
  </SelectPrimitive.Icon>
169
-
170
151
  </SelectPrimitive.Trigger>
171
-
172
- {endAdornment && <div className={cn("absolute h-full flex items-center",
173
- size === "small" ? "right-10" : "right-14")}
174
- onClick={(e) => e.stopPropagation()}>
175
- {endAdornment}
176
- </div>}
177
-
152
+ {endAdornment && (
153
+ <div
154
+ className={cls("absolute h-full flex items-center", size === "small" ? "right-10" : "right-14")}
155
+ onClick={(e) => {
156
+ e.preventDefault();
157
+ e.stopPropagation();
158
+ }}>
159
+ {endAdornment}
160
+ </div>
161
+ )}
178
162
  </div>
179
163
  <SelectPrimitive.Portal>
180
- <SelectPrimitive.Content
181
- position={position}
182
- className="z-50 relative overflow-hidden border border-slate-200 dark:border-slate-800 bg-white dark:bg-slate-800 p-2 rounded-lg shadow-lg">
183
- <SelectPrimitive.Viewport
184
- className={"p-1"}
185
- style={{
186
- maxHeight: "var(--radix-select-content-available-height)"
187
- }}>
164
+ <SelectPrimitive.Content position={position}
165
+ className={cls("z-50 relative overflow-hidden border bg-white dark:bg-gray-900 p-2 rounded-lg", defaultBorderMixin)}>
166
+ <SelectPrimitive.Viewport className={"p-1"}
167
+ style={{ maxHeight: "var(--radix-select-content-available-height)" }}>
188
168
  {children}
189
169
  </SelectPrimitive.Viewport>
190
170
  </SelectPrimitive.Content>
191
171
  </SelectPrimitive.Portal>
192
172
  </SelectPrimitive.Root>
193
173
  );
194
- }
174
+ });
175
+
176
+ Select.displayName = "Select";
195
177
 
196
178
  export type SelectItemProps = {
197
179
  value: string,
@@ -214,13 +196,12 @@ export function SelectItem({
214
196
  e.preventDefault();
215
197
  e.stopPropagation();
216
198
  }}
217
- className={cn(
199
+ className={cls(
218
200
  "w-full",
219
- "relative relative flex items-center p-2 rounded-md text-sm text-slate-700 dark:text-slate-300",
220
- focusedMixin,
201
+ "relative flex items-center p-2 rounded-md text-sm text-slate-700 dark:text-slate-300",
221
202
  "focus:z-10",
222
- "data-[state=checked]:bg-slate-100 data-[state=checked]:dark:bg-slate-900 focus:bg-slate-100 dark:focus:bg-slate-950",
223
- "data-[state=checked]:focus:bg-slate-200 data-[state=checked]:dark:focus:bg-slate-950",
203
+ "data-[state=checked]:bg-slate-100 data-[state=checked]:dark:bg-slate-800 focus:bg-slate-100 dark:focus:bg-gray-950",
204
+ "data-[state=checked]:focus:bg-slate-200 data-[state=checked]:dark:focus:bg-gray-950",
224
205
  disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer",
225
206
  "[&>*]:w-full",
226
207
  "overflow-visible",
@@ -248,7 +229,7 @@ export function SelectGroup({
248
229
  }: SelectGroupProps) {
249
230
  return <>
250
231
  <SelectPrimitive.Group
251
- className={cn(
232
+ className={cls(
252
233
  "text-xs text-slate-900 dark:text-white uppercase tracking-wider font-bold mt-6 first:mt-2",
253
234
  "px-2 py-2",
254
235
  className
@@ -1,20 +1,26 @@
1
1
  import * as SeparatorPrimitive from "@radix-ui/react-separator";
2
+ import { cls } from "../util";
2
3
 
3
- export function Separator({ orientation, decorative }: {
4
+ export function Separator({
5
+ orientation,
6
+ decorative,
7
+ className
8
+ }: {
4
9
  orientation: "horizontal" | "vertical",
5
- decorative?: boolean
10
+ decorative?: boolean,
11
+ className?: string
6
12
  }) {
7
13
  if (orientation === "horizontal")
8
14
  return (
9
15
  <SeparatorPrimitive.Root
10
16
  decorative={decorative}
11
17
  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]"/>
18
+ className={cls("dark:bg-opacity-80 dark:bg-gray-800 bg-gray-100 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px my-4", className)}/>
13
19
  );
14
20
  else
15
21
  return (
16
22
  <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]"
23
+ className={cls("dark:bg-opacity-80 dark:bg-gray-800 bg-gray-100 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px mx-4", className)}
18
24
  decorative={decorative}
19
25
  orientation="vertical"
20
26
  />
@@ -1,37 +1,38 @@
1
- import React, { useEffect } from "react";
1
+ import React, { useEffect, useState } from "react";
2
+ import { cls } from "../util";
3
+ import { defaultBorderMixin } from "../styles";
2
4
  import * as DialogPrimitive from "@radix-ui/react-dialog";
3
- import { cn } from "../util";
4
5
 
5
6
  interface SheetProps {
6
7
  children: React.ReactNode;
7
8
  open: boolean;
9
+ title?: string;
8
10
  side?: "top" | "bottom" | "left" | "right";
11
+ darkBackground?: boolean;
9
12
  transparent?: boolean;
10
13
  onOpenChange?: (open: boolean) => void;
14
+ className?: string;
15
+ overlayClassName?: string;
11
16
  }
12
17
 
13
18
  export const Sheet: React.FC<SheetProps> = ({
14
19
  children,
15
20
  side = "right",
21
+ title,
16
22
  open,
17
23
  onOpenChange,
18
24
  transparent,
25
+ className,
26
+ overlayClassName,
19
27
  ...props
20
28
  }) => {
21
-
22
- const [displayed, setDisplayed] = React.useState(false);
29
+ const [displayed, setDisplayed] = useState(false);
23
30
 
24
31
  useEffect(() => {
25
- if (!open) {
26
- const timeout = setTimeout(() => {
27
- setDisplayed(false);
28
- }, 250);
29
- return () => clearTimeout(timeout);
30
- } else {
31
- setDisplayed(true);
32
- return () => {
33
- };
34
- }
32
+ const timeout = setTimeout(() => {
33
+ setDisplayed(open);
34
+ }, 1);
35
+ return () => clearTimeout(timeout);
35
36
  }, [open]);
36
37
 
37
38
  const transformValue: Record<string, string> = {
@@ -41,36 +42,52 @@ export const Sheet: React.FC<SheetProps> = ({
41
42
  right: "translate-x-full"
42
43
  };
43
44
 
44
- return (
45
+ const borderClass: Record<string, string> = {
46
+ top: "border-b",
47
+ bottom: "border-t",
48
+ left: "border-r",
49
+ right: "border-l"
50
+ };
45
51
 
52
+ return (
46
53
  <DialogPrimitive.Root open={displayed || open}
47
54
  onOpenChange={onOpenChange}>
48
55
  <DialogPrimitive.Portal>
56
+ <DialogPrimitive.Title>
57
+ {title ?? "Sheet"}
58
+ </DialogPrimitive.Title>
49
59
  <DialogPrimitive.Overlay
50
- className={cn(
51
- "fixed inset-0 transition-opacity z-20 ease-in-out duration-200 backdrop-blur-sm",
52
- transparent ? "bg-white bg-opacity-80" : "bg-black bg-opacity-50",
53
- "dark:bg-black dark:bg-opacity-60",
54
- displayed && open ? "opacity-100" : "opacity-0"
60
+ className={cls(
61
+ "fixed inset-0 transition-opacity z-20 ease-in-out duration-100 backdrop-blur-sm",
62
+ "bg-black bg-opacity-50",
63
+ "dark:bg-gray-900 dark:bg-opacity-60",
64
+ displayed && open ? "opacity-100" : "opacity-0",
65
+ overlayClassName
55
66
  )}
56
67
  style={{
57
- pointerEvents: displayed ? "auto" : "none",
68
+ pointerEvents: displayed ? "auto" : "none"
58
69
  }}
70
+ onClick={() => onOpenChange && onOpenChange(false)}
59
71
  />
60
72
  <DialogPrimitive.Content
61
73
  {...props}
62
- className={cn(
63
- // "transform-gpu",
74
+ onFocusCapture={(event) => event.preventDefault()}
75
+ className={cls(
76
+ borderClass[side],
77
+ defaultBorderMixin,
78
+ "transform-gpu",
64
79
  "will-change-transform",
65
80
  "text-slate-900 dark:text-white",
66
- "fixed transform z-20 transition-all duration-[240ms] ease-in-out",
81
+ "fixed transform z-20 transition-all ease-in-out",
82
+ !displayed ? "duration-150" : "duration-100",
67
83
  "outline-none focus:outline-none",
68
- !transparent ? "shadow-md" : "",
84
+ transparent ? "" : "shadow-md bg-white dark:bg-gray-950",
69
85
  side === "top" || side === "bottom" ? "w-full" : "h-full",
70
86
  side === "left" || side === "top" ? "left-0 top-0" : "right-0 bottom-0",
71
- displayed && open ? "opacity-100" : "opacity-0",
72
- !displayed || !open ? transformValue[side] : "")
73
- }
87
+ displayed && open ? "opacity-100" : "opacity-50",
88
+ !displayed || !open ? transformValue[side] : "",
89
+ className
90
+ )}
74
91
  >
75
92
  {children}
76
93
  </DialogPrimitive.Content>
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { cn } from "../util";
2
+ import { cls } from "../util";
3
3
 
4
4
  export type SkeletonProps = {
5
5
  width?: number;
@@ -12,13 +12,16 @@ export function Skeleton({
12
12
  height,
13
13
  className
14
14
  }: SkeletonProps) {
15
- return <span className={
16
- cn(
15
+ return <span
16
+ style={{
17
+ width: width ? `${width}px` : "100%",
18
+ height: height ? `${height}px` : "12px"
19
+ }}
20
+ className={
21
+ cls(
17
22
  "block",
18
- "bg-slate-200 dark:bg-slate-800 rounded",
23
+ "bg-slate-200 dark:bg-slate-800 rounded-md",
19
24
  "animate-pulse",
20
- width ? `w-[${width}px]` : "w-full",
21
- height ? `h-[${height}px]` : "h-3",
22
25
  "max-w-full max-h-full",
23
26
  className)
24
27
  }/>;