@firecms/ui 3.0.0-canary.15 → 3.0.0-canary.150

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