@firecms/ui 3.0.0-canary.16 → 3.0.0-canary.160

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 (111) hide show
  1. package/README.md +60 -150
  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/DialogContent.d.ts +2 -1
  12. package/dist/components/DialogTitle.d.ts +10 -0
  13. package/dist/components/ExpandablePanel.d.ts +2 -1
  14. package/dist/components/FileUpload.d.ts +2 -2
  15. package/dist/components/InputLabel.d.ts +2 -2
  16. package/dist/components/Label.d.ts +4 -1
  17. package/dist/components/Markdown.d.ts +1 -0
  18. package/dist/components/Menu.d.ts +6 -2
  19. package/dist/components/Menubar.d.ts +79 -0
  20. package/dist/components/MultiSelect.d.ts +32 -16
  21. package/dist/components/Popover.d.ts +2 -1
  22. package/dist/components/RadioGroup.d.ts +26 -3
  23. package/dist/components/Select.d.ts +8 -11
  24. package/dist/components/Separator.d.ts +2 -1
  25. package/dist/components/Sheet.d.ts +6 -0
  26. package/dist/components/Slider.d.ts +21 -0
  27. package/dist/components/Table.d.ts +10 -10
  28. package/dist/components/Tabs.d.ts +4 -2
  29. package/dist/components/TextField.d.ts +1 -1
  30. package/dist/components/TextareaAutosize.d.ts +3 -34
  31. package/dist/components/Tooltip.d.ts +6 -2
  32. package/dist/components/Typography.d.ts +5 -4
  33. package/dist/components/index.d.ts +3 -1
  34. package/dist/hooks/index.d.ts +3 -0
  35. package/dist/icons/Icon.d.ts +3 -3
  36. package/dist/index.css +73 -0
  37. package/dist/index.d.ts +1 -0
  38. package/dist/index.es.js +50174 -20590
  39. package/dist/index.es.js.map +1 -1
  40. package/dist/index.umd.js +50441 -857
  41. package/dist/index.umd.js.map +1 -1
  42. package/dist/styles.d.ts +9 -9
  43. package/dist/util/{cn.d.ts → cls.d.ts} +4 -0
  44. package/dist/util/index.d.ts +1 -3
  45. package/package.json +119 -118
  46. package/src/components/Alert.tsx +4 -4
  47. package/src/components/Autocomplete.tsx +7 -5
  48. package/src/components/Avatar.tsx +41 -26
  49. package/src/components/Badge.tsx +2 -2
  50. package/src/components/BooleanSwitch.tsx +14 -13
  51. package/src/components/BooleanSwitchWithLabel.tsx +17 -8
  52. package/src/components/Button.tsx +31 -23
  53. package/src/components/Card.tsx +4 -3
  54. package/src/components/CenteredView.tsx +26 -15
  55. package/src/components/Checkbox.tsx +16 -14
  56. package/src/components/Chip.tsx +13 -10
  57. package/src/components/CircularProgress.tsx +3 -3
  58. package/src/components/Collapse.tsx +4 -2
  59. package/src/components/Container.tsx +3 -2
  60. package/src/components/DateTimeField.tsx +144 -921
  61. package/src/components/DebouncedTextField.tsx +1 -0
  62. package/src/components/Dialog.tsx +17 -7
  63. package/src/components/DialogActions.tsx +3 -3
  64. package/src/components/DialogContent.tsx +7 -3
  65. package/src/components/DialogTitle.tsx +41 -0
  66. package/src/components/ExpandablePanel.tsx +20 -12
  67. package/src/components/FileUpload.tsx +11 -13
  68. package/src/components/IconButton.tsx +7 -11
  69. package/src/components/InfoLabel.tsx +2 -2
  70. package/src/components/InputLabel.tsx +12 -9
  71. package/src/components/Label.tsx +18 -4
  72. package/src/components/Markdown.tsx +15 -3
  73. package/src/components/Menu.tsx +50 -31
  74. package/src/components/Menubar.tsx +322 -0
  75. package/src/components/MultiSelect.tsx +341 -167
  76. package/src/components/Paper.tsx +2 -2
  77. package/src/components/Popover.tsx +19 -15
  78. package/src/components/RadioGroup.tsx +42 -9
  79. package/src/components/SearchBar.tsx +12 -11
  80. package/src/components/Select.tsx +142 -130
  81. package/src/components/Separator.tsx +10 -4
  82. package/src/components/Sheet.tsx +53 -31
  83. package/src/components/Skeleton.tsx +9 -6
  84. package/src/components/Slider.tsx +110 -0
  85. package/src/components/Table.tsx +54 -35
  86. package/src/components/Tabs.tsx +17 -15
  87. package/src/components/TextField.tsx +25 -23
  88. package/src/components/TextareaAutosize.tsx +4 -3
  89. package/src/components/Tooltip.tsx +33 -16
  90. package/src/components/Typography.tsx +42 -26
  91. package/src/components/common/SelectInputLabel.tsx +3 -3
  92. package/src/components/index.tsx +3 -1
  93. package/src/hooks/index.ts +3 -0
  94. package/src/{util → hooks}/useDebounceValue.tsx +2 -0
  95. package/src/{util → hooks}/useInjectStyles.tsx +1 -0
  96. package/src/{util → hooks}/useOutsideAlerter.tsx +2 -0
  97. package/src/icons/Icon.tsx +48 -43
  98. package/src/icons/icon_keys.ts +114 -1301
  99. package/src/index.css +73 -0
  100. package/src/index.ts +1 -0
  101. package/src/scripts/generateIconKeys.ts +20 -11
  102. package/src/styles.ts +9 -9
  103. package/src/util/cls.ts +14 -0
  104. package/src/util/index.ts +1 -3
  105. package/tailwind.config.js +42 -26
  106. package/dist/components/Spinner.d.ts +0 -1
  107. package/src/components/Spinner.tsx +0 -18
  108. package/src/util/cn.ts +0 -6
  109. /package/dist/{util → hooks}/useDebounceValue.d.ts +0 -0
  110. /package/dist/{util → hooks}/useInjectStyles.d.ts +0 -0
  111. /package/dist/{util → hooks}/useOutsideAlerter.d.ts +0 -0
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import React, { ChangeEvent, useCallback, useDeferredValue, useEffect } from "react";
2
3
  import { TextField, TextFieldProps } from "./index";
3
4
 
@@ -1,7 +1,8 @@
1
+ "use client";
1
2
  import React, { useEffect, useState } from "react";
2
3
  import * as DialogPrimitive from "@radix-ui/react-dialog";
3
4
  import { paperMixin } from "../styles";
4
- import { cn } from "../util";
5
+ import { cls } from "../util";
5
6
 
6
7
  export type DialogProps = {
7
8
  open?: boolean;
@@ -15,6 +16,9 @@ export type DialogProps = {
15
16
  maxWidth?: keyof typeof widthClasses;
16
17
  modal?: boolean;
17
18
  onOpenAutoFocus?: (e: Event) => void;
19
+ onEscapeKeyDown?: (e: KeyboardEvent) => void;
20
+ onPointerDownOutside?: (e: Event) => void;
21
+ onInteractOutside?: (e: Event) => void;
18
22
  };
19
23
 
20
24
  const widthClasses = {
@@ -43,7 +47,10 @@ export const Dialog = ({
43
47
  scrollable = true,
44
48
  maxWidth = "lg",
45
49
  modal = true,
46
- onOpenAutoFocus
50
+ onOpenAutoFocus,
51
+ onEscapeKeyDown,
52
+ onPointerDownOutside,
53
+ onInteractOutside
47
54
  }: DialogProps) => {
48
55
  const [displayed, setDisplayed] = useState(false);
49
56
 
@@ -51,7 +58,7 @@ export const Dialog = ({
51
58
  if (!open) {
52
59
  const timeout = setTimeout(() => {
53
60
  setDisplayed(false);
54
- }, 250);
61
+ }, 150);
55
62
  return () => clearTimeout(timeout);
56
63
  } else {
57
64
  setDisplayed(true);
@@ -69,7 +76,7 @@ export const Dialog = ({
69
76
  <div className={"fixed inset-0 z-30"}>
70
77
 
71
78
  <DialogPrimitive.Overlay
72
- className={cn("fixed inset-0 transition-opacity z-20 ease-in-out duration-200 bg-black bg-opacity-50 dark:bg-opacity-60 backdrop-blur-sm ",
79
+ className={cls("fixed inset-0 transition-opacity z-20 ease-in-out duration-200 bg-black bg-opacity-50 dark:bg-opacity-60 backdrop-blur-sm ",
73
80
  displayed && open ? "opacity-100" : "opacity-0",
74
81
  "z-20 fixed top-0 left-0 w-full h-full flex justify-center items-center"
75
82
  )}
@@ -79,17 +86,20 @@ export const Dialog = ({
79
86
  />
80
87
 
81
88
  <DialogPrimitive.Content
89
+ onEscapeKeyDown={onEscapeKeyDown}
82
90
  onOpenAutoFocus={onOpenAutoFocus}
83
- className={cn("h-full outline-none flex justify-center items-center z-40 opacity-100 transition-all duration-200 ease-in-out")}
91
+ onPointerDownOutside={onPointerDownOutside}
92
+ onInteractOutside={onInteractOutside}
93
+ className={cls("h-full outline-none flex justify-center items-center z-40 opacity-100 transition-all duration-200 ease-in-out")}
84
94
  >
85
95
  <div
86
- className={cn(paperMixin,
96
+ className={cls(paperMixin,
87
97
  "z-30",
88
98
  "relative",
89
99
  "outline-none focus:outline-none",
90
100
  fullWidth && !fullScreen ? "w-11/12" : undefined,
91
101
  fullHeight && !fullScreen ? "h-full" : undefined,
92
- "text-slate-900 dark:text-white",
102
+ "text-surface-accent-900 dark:text-white",
93
103
  "justify-center items-center",
94
104
  fullScreen ? "h-screen w-screen" : "max-h-[90vh] shadow-xl",
95
105
  "ease-in-out duration-200",
@@ -1,6 +1,6 @@
1
1
  import React from "react";
2
2
  import { defaultBorderMixin } from "../styles";
3
- import { cn } from "../util";
3
+ import { cls } from "../util";
4
4
 
5
5
  export function DialogActions({
6
6
  children,
@@ -15,11 +15,11 @@ export function DialogActions({
15
15
  }) {
16
16
 
17
17
  return <div
18
- className={cn(
18
+ className={cls(
19
19
  defaultBorderMixin,
20
20
  "py-3 px-4 border-t flex flex-row items-center justify-end bottom-0 right-0 left-0 text-right z-2 gap-2",
21
21
  position,
22
- "bg-white bg-opacity-60 dark:bg-gray-900 dark:bg-opacity-60",
22
+ "bg-white bg-opacity-60 dark:bg-surface-900 dark:bg-opacity-60",
23
23
  translucent ? "backdrop-blur-sm" : "",
24
24
  className)}>
25
25
  {children}
@@ -1,12 +1,14 @@
1
1
  import React from "react";
2
- import { cn } from "../util";
2
+ import { cls } from "../util";
3
3
 
4
4
  export function DialogContent({
5
5
  children,
6
6
  className,
7
- fullHeight
7
+ fullHeight,
8
+ includeMargin = true
8
9
  }: {
9
10
  children: React.ReactNode,
11
+ includeMargin?: boolean,
10
12
  fullHeight?: boolean,
11
13
  className?: string
12
14
  }) {
@@ -17,7 +19,9 @@ export function DialogContent({
17
19
  </div>;
18
20
 
19
21
  return <div
20
- className={cn("py-6 px-6 h-full flex-grow", className)}>
22
+ className={cls("h-full flex-grow",
23
+ { "my-6 mx-6": includeMargin },
24
+ className)}>
21
25
  {children}
22
26
  </div>;
23
27
  }
@@ -0,0 +1,41 @@
1
+ "use client";
2
+
3
+ import React from "react";
4
+ import * as DialogPrimitive from "@radix-ui/react-dialog";
5
+ import * as VisuallyHidden from "@radix-ui/react-visually-hidden";
6
+ import { Typography, TypographyProps, TypographyVariant } from "./Typography";
7
+ import { cls } from "../util";
8
+
9
+ export type DialogContentProps = TypographyProps & {
10
+ children: React.ReactNode,
11
+ hidden?: boolean,
12
+ className?: string,
13
+ includeMargin?: boolean,
14
+ variant?: TypographyVariant
15
+ };
16
+
17
+ export function DialogTitle({
18
+ children,
19
+ hidden,
20
+ className,
21
+ variant = "subtitle2",
22
+ gutterBottom = true,
23
+ includeMargin = true,
24
+ ...props
25
+ }: DialogContentProps) {
26
+
27
+ const title = <DialogPrimitive.Title asChild>
28
+ <Typography variant={variant}
29
+ className={cls({ "mt-8 mx-6": includeMargin }, className)}
30
+ gutterBottom={gutterBottom}
31
+ {...props}>
32
+ {children}
33
+ </Typography>
34
+ </DialogPrimitive.Title>;
35
+
36
+ if (hidden) {
37
+ return <VisuallyHidden.Root>{title}</VisuallyHidden.Root>
38
+ }
39
+
40
+ return title;
41
+ }
@@ -1,9 +1,11 @@
1
+ "use client";
1
2
  import React, { PropsWithChildren, useEffect, useState } from "react";
2
3
 
3
4
  import * as Collapsible from "@radix-ui/react-collapsible";
4
- import { defaultBorderMixin, fieldBackgroundMixin, focusedMixin } from "../styles";
5
+ import { defaultBorderMixin, fieldBackgroundMixin } from "../styles";
5
6
  import { ExpandMoreIcon } from "../icons";
6
- import { cn, useInjectStyles } from "../util";
7
+ import { cls } from "../util";
8
+ import { useInjectStyles } from "../hooks";
7
9
 
8
10
  export function ExpandablePanel({
9
11
  title,
@@ -14,7 +16,8 @@ export function ExpandablePanel({
14
16
  initiallyExpanded = true,
15
17
  titleClassName,
16
18
  asField,
17
- className
19
+ className,
20
+ innerClassName
18
21
  }: PropsWithChildren<{
19
22
  title: React.ReactNode,
20
23
  invisible?: boolean,
@@ -23,7 +26,8 @@ export function ExpandablePanel({
23
26
  onExpandedChange?: (expanded: boolean) => void,
24
27
  titleClassName?: string,
25
28
  asField?: boolean,
26
- className?: string
29
+ className?: string,
30
+ innerClassName?: string
27
31
  }>) {
28
32
 
29
33
  useInjectStyles("ExpandablePanel", `
@@ -75,9 +79,11 @@ export function ExpandablePanel({
75
79
 
76
80
  return (<>
77
81
  <Collapsible.Root
78
- className={cn(
82
+ className={cls(
79
83
  !invisible && defaultBorderMixin + " border",
80
- "rounded-md"
84
+ "rounded-md",
85
+ "w-full",
86
+ className
81
87
  )}
82
88
  open={open}
83
89
  onOpenChange={(updatedOpen: boolean) => {
@@ -86,26 +92,28 @@ export function ExpandablePanel({
86
92
  }}>
87
93
 
88
94
  <Collapsible.Trigger
89
- className={cn(focusedMixin,
90
- "rounded flex items-center justify-between w-full min-h-[52px]",
91
- "hover:bg-slate-50 dark:hover:bg-gray-800 dark:hover:bg-opacity-10",
95
+ className={cls(
96
+ "rounded-t flex items-center justify-between w-full min-h-[52px]",
97
+ "hover:bg-surface-accent-200 hover:bg-opacity-20 dark:hover:bg-surface-800 dark:hover:bg-opacity-20",
92
98
  invisible ? "border-b px-2" : "p-4",
99
+ open ? "py-6" : "py-4",
100
+ "transition-all duration-200",
93
101
  invisible && defaultBorderMixin,
94
102
  asField && fieldBackgroundMixin,
95
103
  titleClassName
96
104
  )}
97
105
  >
98
106
  {title}
99
- <ExpandMoreIcon className={cn("transition", open ? "rotate-180" : "")}/>
107
+ <ExpandMoreIcon className={cls("transition", open ? "rotate-180" : "")}/>
100
108
  </Collapsible.Trigger>
101
109
 
102
110
  <Collapsible.Content
103
- className={cn("CollapsibleContent")}
111
+ className={cls("CollapsibleContent")}
104
112
  style={{
105
113
  overflow: allowOverflow ? "visible" : "hidden"
106
114
  }}
107
115
  >
108
- <div className={className}>
116
+ <div className={innerClassName}>
109
117
  {children}
110
118
  </div>
111
119
  </Collapsible.Content>
@@ -1,7 +1,8 @@
1
+ "use client";
1
2
  import React from "react";
2
3
  import { useDropzone } from "react-dropzone";
3
- import { fieldBackgroundHoverMixin, fieldBackgroundMixin, focusedMixin } from "../styles";
4
- import { cn } from "../util";
4
+ import { fieldBackgroundHoverMixin, fieldBackgroundMixin } from "../styles";
5
+ import { cls } from "../util";
5
6
  import { Typography } from "./Typography";
6
7
 
7
8
  export interface FileUploadError {
@@ -11,7 +12,7 @@ export interface FileUploadError {
11
12
 
12
13
  export type OnFileUploadRejected = (fileRejections: {
13
14
  file: File;
14
- errors: FileUploadError[];
15
+ errors: readonly FileUploadError[];
15
16
  }[], event: object) => void;
16
17
 
17
18
  export type OnFilesUploadAdded = (files: File[]) => void;
@@ -27,7 +28,7 @@ export type FileUploadProps = {
27
28
  title?: React.ReactNode;
28
29
  uploadDescription?: React.ReactNode;
29
30
  preventDropOnDocument?: boolean;
30
- size?: "small" | "medium";
31
+ size?: "medium" | "large";
31
32
  };
32
33
 
33
34
  export function FileUpload({
@@ -38,7 +39,7 @@ export function FileUpload({
38
39
  disabled,
39
40
  maxFiles,
40
41
  title,
41
- uploadDescription = "Drag and drop a file here or click",
42
+ uploadDescription,
42
43
  children,
43
44
  preventDropOnDocument = true,
44
45
  size
@@ -63,21 +64,18 @@ export function FileUpload({
63
64
  );
64
65
  return <div
65
66
  {...getRootProps()}
66
- className={cn(
67
+ className={cls(
67
68
  fieldBackgroundMixin,
68
- fieldBackgroundHoverMixin,
69
- focusedMixin,
70
69
  "flex gap-2",
71
70
  "p-4 box-border relative items-center border-2 border-solid border-transparent outline-none rounded-md duration-200 ease-[cubic-bezier(0.4,0,0.2,1)] focus:border-primary-solid",
72
71
  {
73
- "h-44": size === "medium",
74
- "h-28": size === "small",
72
+ "h-44": size === "large",
73
+ "h-28": size === "medium",
75
74
  "cursor-pointer": !disabled,
76
- "hover:bg-field-hover dark:hover:bg-field-hover-dark": !isDragActive,
75
+ [fieldBackgroundHoverMixin]: !isDragActive,
77
76
  "transition-colors duration-200 ease-[cubic-bezier(0,0,0.2,1)] border-red-500": isDragReject,
78
77
  "transition-colors duration-200 ease-[cubic-bezier(0,0,0.2,1)] border-green-500": isDragAccept,
79
- })}
80
- >
78
+ })}>
81
79
 
82
80
  <Typography variant={"caption"} color={"secondary"} className={"absolute top-2 left-3.5 cursor-inherit"}>
83
81
  {title}
@@ -1,6 +1,6 @@
1
+ "use client";
1
2
  import React from "react";
2
- import { focusedMixin } from "../styles";
3
- import { cn } from "../util";
3
+ import { cls } from "../util";
4
4
 
5
5
  export type IconButtonProps<C extends React.ElementType> =
6
6
  Omit<(C extends "button" ? React.ButtonHTMLAttributes<HTMLButtonElement> : React.ComponentProps<C>), "onClick">
@@ -14,11 +14,9 @@ export type IconButtonProps<C extends React.ElementType> =
14
14
  onClick?: React.MouseEventHandler<any>
15
15
  }
16
16
 
17
- const buttonClasses =
18
- "hover:bg-slate-200 hover:bg-opacity-75 dark:hover:bg-gray-700 dark:hover:bg-opacity-50";
19
- const baseClasses =
20
- "inline-flex items-center justify-center p-2 text-sm font-medium focus:outline-none transition-colors ease-in-out duration-150";
21
- const colorClasses = "text-slate-600 visited:text-slate-600 dark:text-slate-300 dark:visited:text-gray-300";
17
+ const buttonClasses = "hover:bg-surface-accent-200 hover:bg-opacity-75 dark:hover:bg-surface-accent-800 hover:scale-110 transition-transform";
18
+ const baseClasses = "inline-flex items-center justify-center p-2 text-sm font-medium focus:outline-none transition-colors ease-in-out duration-150";
19
+ const colorClasses = "text-surface-accent-600 visited:text-surface-accent-600 dark:text-surface-accent-300 dark:visited:text-surface-300";
22
20
  const sizeClasses = {
23
21
  medium: "w-10 !h-10 min-w-10 min-h-10",
24
22
  small: "w-8 !h-8 min-w-8 min-h-8",
@@ -42,15 +40,14 @@ const IconButtonInner = <C extends React.ElementType = "button">({
42
40
  ...props
43
41
  }: IconButtonProps<C>, ref: React.ForwardedRef<HTMLButtonElement>) => {
44
42
 
45
- const bgClasses = variant === "ghost" ? "bg-transparent" : "bg-slate-50 dark:bg-gray-950 dark:bg-opacity-50";
43
+ const bgClasses = variant === "ghost" ? "bg-transparent" : "bg-surface-accent-200 bg-opacity-50 dark:bg-surface-950 dark:bg-opacity-50";
46
44
  const Component: React.ElementType<any> = component || "button";
47
45
  return (
48
46
  <Component
49
47
  type="button"
50
48
  ref={ref}
51
49
  {...props}
52
- className={cn(
53
- focusedMixin,
50
+ className={cls(
54
51
  disabled ? "opacity-50 pointer-events-none" : "cursor-pointer",
55
52
  toggled ? "outline outline-2 outline-primary" : "",
56
53
  colorClasses,
@@ -65,6 +62,5 @@ const IconButtonInner = <C extends React.ElementType = "button">({
65
62
  </Component>
66
63
  );
67
64
  };
68
- // React.ForwardRefRenderFunction<HTMLButtonElement, IconButtonProps<C>>
69
65
 
70
66
  export const IconButton = React.forwardRef(IconButtonInner as React.ForwardRefRenderFunction<HTMLButtonElement, IconButtonProps<any>>) as React.ComponentType<IconButtonProps<any>>;
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { cn } from "../util";
2
+ import { cls } from "../util";
3
3
 
4
4
  const colorClasses = {
5
5
  info: "bg-sky-200 dark:bg-teal-900",
@@ -16,7 +16,7 @@ export function InfoLabel({
16
16
 
17
17
  return (
18
18
  <div
19
- className={cn("my-3 py-2 px-4 rounded", colorClasses[mode])}>
19
+ className={cls("my-3 py-2 px-4 rounded", colorClasses[mode])}>
20
20
  {children}
21
21
  </div>
22
22
  )
@@ -1,5 +1,7 @@
1
+ "use client";
1
2
  import * as React from "react";
2
- import { cn } from "../util";
3
+ import { cls } from "../util";
4
+ import { defaultBorderMixin } from "../styles";
3
5
 
4
6
  export type InputLabelProps = {
5
7
  children?: React.ReactNode;
@@ -7,6 +9,12 @@ export type InputLabelProps = {
7
9
  shrink?: boolean;
8
10
  } & React.LabelHTMLAttributes<HTMLLabelElement>;
9
11
 
12
+ const defaultClasses = {
13
+ root: "origin-left transition-transform block whitespace-nowrap overflow-hidden text-overflow-ellipsis max-w-full",
14
+ shrink: "transform translate-y-[2px] scale-75 translate-x-[12px]",
15
+ expanded: "translate-x-[16px] top-0 transform translate-y-[16px] scale-100"
16
+ };
17
+
10
18
  export const InputLabel = React.forwardRef<HTMLLabelElement, InputLabelProps>(function InputLabel(inProps, ref) {
11
19
  const {
12
20
  shrink,
@@ -14,13 +22,7 @@ export const InputLabel = React.forwardRef<HTMLLabelElement, InputLabelProps>(fu
14
22
  ...other
15
23
  } = inProps;
16
24
 
17
- const defaultClasses = {
18
- root: "origin-left transition-transform block whitespace-nowrap overflow-hidden text-overflow-ellipsis max-w-full",
19
- shrink: "transform translate-y-[2px] scale-75 translate-x-[12px]",
20
- expanded: "translate-x-[16px] top-0 transform translate-y-[16px] scale-100"
21
- };
22
-
23
- const computedClassName = cn(defaultClasses.root,
25
+ const computedClassName = cls(defaultClasses.root,
24
26
  {
25
27
  [defaultClasses.shrink]: shrink,
26
28
  [defaultClasses.expanded]: !shrink
@@ -28,9 +30,10 @@ export const InputLabel = React.forwardRef<HTMLLabelElement, InputLabelProps>(fu
28
30
 
29
31
  return (
30
32
  <label
33
+ className={cls("text-sm font-medium peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
34
+ defaultBorderMixin, computedClassName)}
31
35
  data-shrink={shrink}
32
36
  ref={ref}
33
- className={computedClassName}
34
37
  {...other}
35
38
  />
36
39
  );
@@ -1,15 +1,29 @@
1
+ "use client";
1
2
  import * as React from "react"
2
3
  import * as LabelPrimitive from "@radix-ui/react-label"
3
- import { cn } from "../util";
4
+ import { cls } from "../util";
4
5
  import { defaultBorderMixin } from "../styles";
5
6
 
7
+ type LabelProps = React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> & {
8
+ border?: boolean,
9
+ onClick?: React.MouseEventHandler<HTMLLabelElement>
10
+ };
6
11
  const Label = React.forwardRef<
7
12
  React.ElementRef<typeof LabelPrimitive.Root>,
8
- React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>
9
- >(({ className, ...props }, ref) => (
13
+ LabelProps
14
+ >(({
15
+ className,
16
+ border,
17
+ onClick,
18
+ ...props
19
+ }, ref) => (
10
20
  <LabelPrimitive.Root
11
21
  ref={ref}
12
- className={cn("text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70", defaultBorderMixin, className)}
22
+ onClick={onClick}
23
+ className={cls("text-sm font-medium peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
24
+ border && "border border-surface-300 dark:border-surface-700 rounded-md px-3 py-1.5",
25
+ onClick && "hover:cursor-pointer hover:bg-surface-200 dark:hover:bg-surface-800",
26
+ defaultBorderMixin, className)}
13
27
  {...props}
14
28
  />
15
29
  ))
@@ -1,28 +1,40 @@
1
+ "use client";
1
2
  import React, { useMemo } from "react";
2
3
  import equal from "react-fast-compare"
3
4
 
4
5
  // @ts-ignore
5
6
  import MarkdownIt from "markdown-it";
7
+ import { cls } from "../util";
6
8
 
7
9
  export interface MarkdownProps {
8
10
  source: string,
11
+ size?: "small" | "medium" | "large" | "xl" | "2xl";
9
12
  className?: string
10
13
  }
11
14
 
12
- const md = new MarkdownIt({ html: true, });
15
+ const proseClasses = {
16
+ small: "prose-sm typography-body2",
17
+ medium: "prose typography-body1",
18
+ large: "prose-lg",
19
+ xl: "prose-xl",
20
+ "2xl": "prose-2xl"
21
+ };
22
+
23
+ const md = new MarkdownIt({ html: true });
13
24
  /**
14
25
  * @group Preview components
15
26
  */
16
27
  export const Markdown = React.memo<MarkdownProps>(function Markdown({
17
28
  source,
18
- className
29
+ className,
30
+ size = "medium"
19
31
  }: MarkdownProps) {
20
32
  const html = useMemo(() => {
21
33
  return md.render(typeof source === "string" ? source : "");
22
34
  }, [source]);
23
35
 
24
36
  return <div
25
- className={className}
37
+ className={cls(proseClasses[size], "dark:prose-invert prose-headings:font-title", className)}
26
38
  dangerouslySetInnerHTML={{ __html: html }}
27
39
  />;
28
40
  }
@@ -1,7 +1,8 @@
1
+ "use client";
1
2
  import React from "react";
2
3
  import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
3
- import { focusedMixin, paperMixin } from "../styles";
4
- import { cn } from "../util";
4
+ import { focusedDisabled, paperMixin } from "../styles";
5
+ import { cls } from "../util";
5
6
 
6
7
  export type MenuProps = {
7
8
  children: React.ReactNode;
@@ -12,49 +13,67 @@ export type MenuProps = {
12
13
  onOpenChange?(open: boolean): void;
13
14
 
14
15
  portalContainer?: HTMLElement | null;
16
+ side?: "top" | "right" | "bottom" | "left";
17
+ align?: "start" | "center" | "end";
15
18
  }
16
19
 
17
- export function Menu({
18
- children,
19
- trigger,
20
- open,
21
- defaultOpen,
22
- onOpenChange,
23
- portalContainer
24
- }: MenuProps) {
25
- return (
26
- <DropdownMenu.Root
27
- open={open}
28
- defaultOpen={defaultOpen}
29
- onOpenChange={onOpenChange}>
30
- <DropdownMenu.Trigger asChild>
31
- {trigger}
32
- </DropdownMenu.Trigger>
33
- <DropdownMenu.Portal container={portalContainer}>
34
- <DropdownMenu.Content className={cn(paperMixin, "shadow py-2 z-30")}>
35
- {children}
36
- </DropdownMenu.Content>
37
- </DropdownMenu.Portal>
38
- </DropdownMenu.Root>
39
- );
40
- }
20
+ const Menu = React.forwardRef<
21
+ React.ElementRef<typeof DropdownMenu.Trigger>,
22
+ MenuProps
23
+ >(({
24
+ children,
25
+ trigger,
26
+ open,
27
+ defaultOpen,
28
+ side,
29
+ align,
30
+ onOpenChange,
31
+ portalContainer
32
+ }, ref) => (
33
+ <DropdownMenu.Root
34
+ open={open}
35
+ defaultOpen={defaultOpen}
36
+ onOpenChange={onOpenChange}>
37
+ <DropdownMenu.Trigger
38
+ ref={ref}
39
+ asChild>
40
+ {trigger}
41
+ </DropdownMenu.Trigger>
42
+ <DropdownMenu.Portal container={portalContainer}>
43
+ <DropdownMenu.Content
44
+ side={side}
45
+ align={align}
46
+ className={cls(paperMixin, focusedDisabled, "shadow py-2 z-30")}>
47
+ {children}
48
+ </DropdownMenu.Content>
49
+ </DropdownMenu.Portal>
50
+ </DropdownMenu.Root>
51
+ ))
52
+ Menu.displayName = "Menu"
53
+
54
+ export { Menu }
41
55
 
42
56
  export type MenuItemProps = {
43
57
  children: React.ReactNode;
44
58
  dense?: boolean;
45
59
  onClick?: (event: React.MouseEvent) => void;
46
- }
60
+ };
47
61
 
48
62
  export function MenuItem({
49
63
  children,
50
- dense,
64
+ dense = false, // Default value is false if not provided
51
65
  onClick
52
66
  }: MenuItemProps) {
67
+ // Dynamically adjusting the class based on the "dense" prop
68
+ const classNames = cls(
69
+ onClick && "cursor-pointer",
70
+ "rounded-md text-sm font-medium text-surface-accent-700 dark:text-surface-accent-300 hover:bg-surface-accent-100 dark:hover:bg-surface-accent-900 flex items-center gap-4",
71
+ dense ? "px-3 py-1.5" : "px-4 py-2"
72
+ );
73
+
53
74
  return (
54
75
  <DropdownMenu.Item
55
- className={cn(focusedMixin,
56
- onClick && "cursor-pointer",
57
- "rounded-md px-4 py-2 text-sm font-medium text-slate-700 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-900 flex items-center gap-4")}
76
+ className={classNames}
58
77
  onClick={onClick}>
59
78
  {children}
60
79
  </DropdownMenu.Item>