@firecms/ui 3.0.0-beta.1 → 3.0.0-beta.10

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