@rebasepro/ui 0.17.3 → 0.18.1

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 (127) hide show
  1. package/README.md +4 -0
  2. package/dist/components/MultiSelect.d.ts +10 -0
  3. package/dist/index.es.js +2 -1
  4. package/dist/index.es.js.map +1 -1
  5. package/package.json +32 -23
  6. package/src/components/Alert.tsx +0 -118
  7. package/src/components/Autocomplete.tsx +0 -93
  8. package/src/components/Avatar.tsx +0 -73
  9. package/src/components/Badge.tsx +0 -44
  10. package/src/components/BooleanSwitch.tsx +0 -116
  11. package/src/components/BooleanSwitchWithLabel.tsx +0 -120
  12. package/src/components/Button.tsx +0 -110
  13. package/src/components/Card.tsx +0 -43
  14. package/src/components/CenteredView.tsx +0 -35
  15. package/src/components/Checkbox.tsx +0 -129
  16. package/src/components/Chip.tsx +0 -131
  17. package/src/components/CircularProgress.tsx +0 -53
  18. package/src/components/CircularProgressCenter.tsx +0 -27
  19. package/src/components/Collapse.tsx +0 -66
  20. package/src/components/ColorPicker.tsx +0 -140
  21. package/src/components/Container.tsx +0 -51
  22. package/src/components/DateTimeField.tsx +0 -363
  23. package/src/components/DebouncedTextField.tsx +0 -76
  24. package/src/components/Dialog.tsx +0 -159
  25. package/src/components/DialogActions.tsx +0 -29
  26. package/src/components/DialogContent.tsx +0 -27
  27. package/src/components/DialogTitle.tsx +0 -41
  28. package/src/components/ErrorBoundary.tsx +0 -236
  29. package/src/components/ExpandablePanel.tsx +0 -130
  30. package/src/components/FileUpload.tsx +0 -103
  31. package/src/components/FilterChip.tsx +0 -89
  32. package/src/components/IconButton.tsx +0 -101
  33. package/src/components/InfoLabel.tsx +0 -23
  34. package/src/components/InputLabel.tsx +0 -40
  35. package/src/components/Label.tsx +0 -32
  36. package/src/components/LoadingButton.tsx +0 -32
  37. package/src/components/Markdown.tsx +0 -55
  38. package/src/components/Menu.tsx +0 -114
  39. package/src/components/Menubar.tsx +0 -355
  40. package/src/components/MultiSelect.tsx +0 -433
  41. package/src/components/Paper.tsx +0 -23
  42. package/src/components/Popover.tsx +0 -162
  43. package/src/components/RadioGroup.tsx +0 -74
  44. package/src/components/ResizablePanels.tsx +0 -189
  45. package/src/components/SearchBar.tsx +0 -136
  46. package/src/components/Select.tsx +0 -326
  47. package/src/components/Separator.tsx +0 -28
  48. package/src/components/Sheet.tsx +0 -135
  49. package/src/components/Skeleton.tsx +0 -54
  50. package/src/components/Slider.tsx +0 -110
  51. package/src/components/Table.tsx +0 -178
  52. package/src/components/Tabs.tsx +0 -185
  53. package/src/components/TextField.tsx +0 -270
  54. package/src/components/TextareaAutosize.tsx +0 -368
  55. package/src/components/ToggleButtonGroup.tsx +0 -69
  56. package/src/components/Tooltip.tsx +0 -153
  57. package/src/components/Typography.tsx +0 -132
  58. package/src/components/VirtualTable/VirtualTable.performance.test.tsx +0 -90
  59. package/src/components/VirtualTable/VirtualTable.tsx +0 -700
  60. package/src/components/VirtualTable/VirtualTableCell.tsx +0 -59
  61. package/src/components/VirtualTable/VirtualTableHeader.tsx +0 -327
  62. package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +0 -250
  63. package/src/components/VirtualTable/VirtualTableProps.tsx +0 -339
  64. package/src/components/VirtualTable/VirtualTableRow.tsx +0 -51
  65. package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +0 -44
  66. package/src/components/VirtualTable/fields/VirtualTableInput.tsx +0 -89
  67. package/src/components/VirtualTable/fields/VirtualTableNumberInput.tsx +0 -71
  68. package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +0 -107
  69. package/src/components/VirtualTable/fields/VirtualTableSwitch.tsx +0 -28
  70. package/src/components/VirtualTable/index.tsx +0 -10
  71. package/src/components/VirtualTable/selection/SelectionContext.tsx +0 -36
  72. package/src/components/VirtualTable/selection/SelectionStore.ts +0 -54
  73. package/src/components/VirtualTable/types.tsx +0 -47
  74. package/src/components/common/SelectInputLabel.tsx +0 -23
  75. package/src/components/index.tsx +0 -62
  76. package/src/hooks/PortalContainerContext.tsx +0 -50
  77. package/src/hooks/index.ts +0 -7
  78. package/src/hooks/useDebounceCallback.tsx +0 -21
  79. package/src/hooks/useDebounceValue.tsx +0 -20
  80. package/src/hooks/useDebouncedCallback.ts +0 -39
  81. package/src/hooks/useInjectStyles.tsx +0 -31
  82. package/src/hooks/useOutsideAlerter.tsx +0 -46
  83. package/src/icons/GitHubIcon.tsx +0 -21
  84. package/src/icons/HandleIcon.tsx +0 -23
  85. package/src/icons/Icon.tsx +0 -33
  86. package/src/icons/LucideIconByName.tsx +0 -117
  87. package/src/icons/cool_icon_keys.ts +0 -12
  88. package/src/icons/icon_keys.ts +0 -1936
  89. package/src/icons/index.ts +0 -179
  90. package/src/index.css +0 -169
  91. package/src/index.ts +0 -47
  92. package/src/scripts/fixIconSizes.cjs +0 -92
  93. package/src/scripts/fixIconSizesToConst.cjs +0 -106
  94. package/src/scripts/generateIconKeys.ts +0 -41
  95. package/src/scripts/generateIcons.ts +0 -4
  96. package/src/scripts/saveIconFiles.ts +0 -89
  97. package/src/styles.ts +0 -141
  98. package/src/theme.css +0 -168
  99. package/src/util/chip_colors.ts +0 -242
  100. package/src/util/cls.ts +0 -8
  101. package/src/util/debounce.ts +0 -28
  102. package/src/util/hash.ts +0 -11
  103. package/src/util/index.ts +0 -4
  104. package/src/util/key_to_icon_component.ts +0 -11
  105. package/src/util/lazy_chunk.ts +0 -101
  106. package/src/views/CardView.tsx +0 -281
  107. package/src/views/CollectionView/CollectionCardView.tsx +0 -265
  108. package/src/views/CollectionView/CollectionKanbanView.tsx +0 -246
  109. package/src/views/CollectionView/CollectionListView.tsx +0 -240
  110. package/src/views/CollectionView/CollectionTableView.tsx +0 -229
  111. package/src/views/CollectionView/CollectionView.tsx +0 -450
  112. package/src/views/CollectionView/CollectionViewToolbar.tsx +0 -242
  113. package/src/views/CollectionView/CollectionViewTypes.ts +0 -181
  114. package/src/views/CollectionView/DefaultCellRenderer.tsx +0 -404
  115. package/src/views/CollectionView/index.ts +0 -39
  116. package/src/views/CollectionView/resolveTitleProperty.ts +0 -52
  117. package/src/views/CollectionView/utils.ts +0 -14
  118. package/src/views/Kanban/Board.tsx +0 -384
  119. package/src/views/Kanban/BoardColumn.tsx +0 -138
  120. package/src/views/Kanban/BoardColumnTitle.tsx +0 -47
  121. package/src/views/Kanban/BoardSortableList.tsx +0 -182
  122. package/src/views/Kanban/board_types.ts +0 -80
  123. package/src/views/Kanban/index.tsx +0 -5
  124. package/src/views/Kanban/placement.ts +0 -62
  125. package/src/views/KanbanView.tsx +0 -32
  126. package/src/views/ListView.tsx +0 -296
  127. package/src/views/index.ts +0 -5
@@ -1,103 +0,0 @@
1
- "use client";
2
- import React from "react";
3
- import { useDropzone } from "react-dropzone";
4
- import { fieldBackgroundHoverMixin, fieldBackgroundMixin } from "../styles";
5
- import { cls } from "../util";
6
- import { Typography } from "./Typography";
7
-
8
- export interface FileUploadError {
9
- message: string;
10
- code: string;
11
- }
12
-
13
- export type OnFileUploadRejected = (fileRejections: {
14
- file: File;
15
- errors: readonly FileUploadError[];
16
- }[], event: object) => void;
17
-
18
- export type OnFilesUploadAdded = (files: File[]) => void;
19
-
20
- export type FileUploadProps = {
21
- // e.g. accept={{ "*/image": [] }}
22
- accept?: Record<string, string[]>,
23
- onFilesAdded: OnFilesUploadAdded,
24
- onFilesRejected?: OnFileUploadRejected,
25
- maxSize?: number,
26
- disabled?: boolean;
27
- maxFiles?: number;
28
- title?: React.ReactNode;
29
- uploadDescription?: React.ReactNode;
30
- preventDropOnDocument?: boolean;
31
- size?: "small" | "medium" | "large";
32
- };
33
-
34
- export function FileUpload({
35
- accept,
36
- onFilesAdded,
37
- onFilesRejected,
38
- maxSize,
39
- disabled,
40
- maxFiles,
41
- title,
42
- uploadDescription,
43
- children,
44
- preventDropOnDocument = true,
45
- size
46
- }: React.PropsWithChildren<FileUploadProps>) {
47
-
48
- const {
49
- getRootProps,
50
- getInputProps,
51
- isDragActive,
52
- isDragAccept,
53
- isDragReject
54
- } = useDropzone({
55
- accept,
56
- noDragEventsBubbling: true,
57
- maxSize,
58
- onDrop: onFilesAdded,
59
- onDropRejected: onFilesRejected,
60
- disabled,
61
- maxFiles,
62
- preventDropOnDocument
63
- }
64
- );
65
- return <div
66
- {...getRootProps()}
67
- role="button"
68
- aria-label={typeof title === "string" ? title : (typeof uploadDescription === "string" ? uploadDescription : "Upload file")}
69
- aria-disabled={disabled || undefined}
70
- className={cls(
71
- fieldBackgroundMixin,
72
- "flex gap-2",
73
- "p-4 box-border relative items-center border-2 border-solid border-transparent outline-hidden rounded-lg duration-200 ease-[cubic-bezier(0.4,0,0.2,1)] focus:border-primary-solid",
74
- {
75
- "h-44": size === "large",
76
- "h-28": size === "medium",
77
- "h-16": size === "small",
78
- "cursor-pointer": !disabled,
79
- [fieldBackgroundHoverMixin]: !isDragActive,
80
- "transition-colors duration-200 ease-[cubic-bezier(0,0,0.2,1)] border-red-500": isDragReject,
81
- "transition-colors duration-200 ease-[cubic-bezier(0,0,0.2,1)] border-green-500": isDragAccept
82
- })}>
83
-
84
- <Typography variant={"caption"} color={"secondary"} className={"absolute top-2 left-3.5 cursor-inherit"}>
85
- {title}
86
- </Typography>
87
-
88
- <input
89
- {...getInputProps()}/>
90
-
91
- {children}
92
-
93
- <div
94
- className="grow h-28 box-border flex flex-col items-center justify-center text-center">
95
- <Typography align={"center"}
96
- variant={"label"}
97
- className={"flex flex-row gap-2 justify-center"}>
98
- {uploadDescription}
99
- </Typography>
100
- </div>
101
-
102
- </div>
103
- }
@@ -1,89 +0,0 @@
1
- import React from "react";
2
- import { cls } from "../util";
3
-
4
- export interface FilterChipProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "children"> {
5
- /**
6
- * The text label displayed on the chip.
7
- */
8
- children: React.ReactNode;
9
- /**
10
- * Whether the chip is currently in an active/selected state.
11
- */
12
- active?: boolean;
13
- /**
14
- * Optional icon rendered before the label.
15
- */
16
- icon?: React.ReactNode;
17
- /**
18
- * Size variant.
19
- * @default "medium"
20
- */
21
- size?: "small" | "medium";
22
- /**
23
- * Whether the chip is disabled.
24
- */
25
- disabled?: boolean;
26
- }
27
-
28
- const sizeClasses = {
29
- small: "px-2 py-0.5 text-xs",
30
- medium: "px-2.5 py-1 text-xs"
31
- };
32
-
33
- /**
34
- * A toggle chip used for filter presets and similar multi-select controls.
35
- *
36
- * Uses an inset box-shadow for the active ring instead of `border` so the
37
- * chip size stays stable across states and the ring cannot be clipped by
38
- * parent `overflow-hidden` containers.
39
- *
40
- * @group Interactive components
41
- */
42
- export const FilterChip = React.forwardRef<HTMLButtonElement, FilterChipProps>(function FilterChip({
43
- children,
44
- active = false,
45
- onClick,
46
- icon,
47
- size = "medium",
48
- className,
49
- disabled = false,
50
- ...rest
51
- }: FilterChipProps, ref) {
52
- return (
53
- <button
54
- ref={ref}
55
- type="button"
56
- onClick={onClick}
57
- disabled={disabled}
58
- className={cls(
59
- "inline-flex items-center gap-1 rounded-full",
60
- "font-medium whitespace-nowrap select-none shrink-0",
61
- "transition-colors duration-150",
62
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50",
63
- sizeClasses[size],
64
- !disabled && "cursor-pointer",
65
- // Hover is one step along the same ramp the chip already sits
66
- // on, the way every other hoverable surface here moves. It used
67
- // to be `hover:bg-primary/5` for the inactive chip, which
68
- // *replaces* the resting fill with a tint fainter than it — so
69
- // pointing at a chip made its background vanish. The active chip
70
- // had no hover state at all.
71
- active
72
- ? cls(
73
- "bg-primary/12 text-primary dark:bg-primary/20 dark:text-primary shadow-[inset_0_0_0_1.5px_var(--color-primary)]",
74
- !disabled && "hover:bg-primary/20 dark:hover:bg-primary/30"
75
- )
76
- : cls(
77
- "bg-surface-accent-100 text-text-secondary dark:bg-surface-accent-800 dark:text-text-secondary-dark",
78
- !disabled && "hover:bg-surface-accent-200 dark:hover:bg-surface-accent-700"
79
- ),
80
- disabled && "opacity-50 cursor-not-allowed",
81
- className
82
- )}
83
- {...rest}
84
- >
85
- {icon}
86
- {children}
87
- </button>
88
- );
89
- });
@@ -1,101 +0,0 @@
1
- "use client";
2
- import React from "react";
3
- import { cls } from "../util";
4
-
5
- export type IconButtonProps<C extends React.ElementType> =
6
- Omit<(C extends "button" ? React.ButtonHTMLAttributes<HTMLButtonElement> : React.ComponentProps<C>), "onClick">
7
- & {
8
- size?: "medium" | "small" | "smallest" | "large";
9
- variant?: "ghost" | "filled",
10
- shape?: "circular" | "square",
11
- disabled?: boolean;
12
- toggled?: boolean;
13
- component?: C;
14
- onClick?: React.MouseEventHandler<any>;
15
- "aria-label"?: string;
16
- }
17
-
18
- const buttonClasses = "hover:bg-surface-accent-200 hover:bg-opacity-75 hover:bg-surface-accent-200/75 dark:hover:bg-surface-accent-800 hover:scale-[1.04] active:scale-95 transition-transform";
19
- // `[&>svg]:shrink-0` is load-bearing: without it flex compresses the icon to
20
- // whatever width is left after padding, so an 18px icon in a 28px button
21
- // rendered 12x18 — visibly squashed rather than merely small.
22
- const baseClasses = "inline-flex items-center justify-center text-sm font-medium focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 transition-colors ease-in-out duration-150 [&>svg]:shrink-0";
23
- const colorClasses = "text-surface-accent-500 visited:text-surface-accent-500 dark:text-surface-accent-300 dark:visited:text-surface-accent-300";
24
- // Padding stays a flat p-2 (as it always was). Callers pass their own icon
25
- // sizes, so tightening it here shrinks the content box under an icon that was
26
- // sized for the old one and makes the icon overflow. `shrink-0` above is what
27
- // actually fixes the squashing — the icon keeps its own dimensions and simply
28
- // eats into the padding.
29
- const sizeClasses = {
30
- medium: "w-10 !h-10 min-w-10 min-h-10 p-2",
31
- small: "w-8 !h-8 min-w-8 min-h-8 p-2",
32
- smallest: "w-7 !h-7 min-w-7 min-h-7 p-2",
33
- large: "w-12 !h-12 min-w-12 min-h-12 p-2"
34
- }
35
- const shapeClasses = {
36
- circular: "rounded-full",
37
- square: "rounded-md"
38
- }
39
-
40
- /** Icon size used when the caller doesn't set one on the child. */
41
- const defaultIconSize = {
42
- smallest: 16,
43
- small: 18,
44
- medium: 20,
45
- large: 24
46
- } as const;
47
-
48
- const IconButtonInner = <C extends React.ElementType = "button">({
49
- children,
50
- className,
51
- size = "medium",
52
- variant = "ghost",
53
- shape = "circular",
54
- disabled,
55
- toggled,
56
- component,
57
- ...props
58
- }: IconButtonProps<C>, ref: React.ForwardedRef<HTMLButtonElement>) => {
59
-
60
- const bgClasses = variant === "ghost" ? "bg-transparent" : "bg-surface-accent-200 bg-opacity-50 bg-surface-accent-200/50 dark:bg-surface-900 dark:bg-opacity-50 dark:bg-surface-900/50";
61
- const Component: React.ElementType<any> = component || "button";
62
- const isNativeButton = Component === "button";
63
-
64
- // Give the icon a size that matches the button when the caller didn't pick
65
- // one. Without this a bare <IconButton size="smallest"><PencilIcon/></…>
66
- // renders lucide's 24px default inside a 28px button, so icon size ended up
67
- // depending on whether each call site happened to pass one — which is what
68
- // made a row of icon buttons look randomly sized. An explicit `size` on the
69
- // child always wins.
70
- const sizedChildren = React.Children.map(children, (child) => {
71
- if (!React.isValidElement(child)) return child;
72
- if ((child.props as { size?: unknown }).size !== undefined) return child;
73
- return React.cloneElement(child as React.ReactElement<{ size?: number }>,
74
- { size: defaultIconSize[size] });
75
- });
76
- return (
77
- <Component
78
- type={isNativeButton ? "button" : undefined}
79
- role={isNativeButton ? undefined : "button"}
80
- ref={ref}
81
- aria-disabled={disabled || undefined}
82
- tabIndex={disabled ? -1 : undefined}
83
- {...props}
84
- className={cls(
85
- disabled ? "opacity-50 pointer-events-none" : "cursor-pointer",
86
- toggled ? "outline outline-2 outline-primary" : "",
87
- "text-inherit dark:text-inherit",
88
- colorClasses,
89
- bgClasses,
90
- baseClasses,
91
- buttonClasses,
92
- shapeClasses[shape],
93
- sizeClasses[size],
94
- className
95
- )}>
96
- {sizedChildren}
97
- </Component>
98
- );
99
- };
100
-
101
- export const IconButton = React.forwardRef(IconButtonInner as React.ForwardRefRenderFunction<HTMLButtonElement, IconButtonProps<any>>) as React.ComponentType<IconButtonProps<any>>;
@@ -1,23 +0,0 @@
1
- import React from "react";
2
- import { cls } from "../util";
3
-
4
- const colorClasses = {
5
- info: "bg-blue-500/8 dark:bg-blue-500/12 text-blue-800 dark:text-blue-200 border border-blue-500/20 dark:border-blue-500/25",
6
- warn: "bg-amber-500/8 dark:bg-amber-500/12 text-amber-800 dark:text-amber-200 border border-amber-500/20 dark:border-amber-500/25"
7
- }
8
-
9
- export function InfoLabel({
10
- children,
11
- mode = "info"
12
- }: {
13
- children: React.ReactNode,
14
- mode?: "info" | "warn"
15
- }) {
16
-
17
- return (
18
- <div
19
- className={cls("my-3 py-2 px-4 rounded-lg text-sm font-medium leading-snug", colorClasses[mode])}>
20
- {children}
21
- </div>
22
- )
23
- }
@@ -1,40 +0,0 @@
1
- "use client";
2
- import * as React from "react";
3
- import { cls } from "../util";
4
- import { defaultBorderMixin } from "../styles";
5
-
6
- export type InputLabelProps = {
7
- children?: React.ReactNode;
8
- className?: string;
9
- shrink?: boolean;
10
- } & React.LabelHTMLAttributes<HTMLLabelElement>;
11
-
12
- const defaultClasses = {
13
- root: "origin-left transition-transform block whitespace-nowrap overflow-hidden text-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
-
18
- export const InputLabel = React.forwardRef<HTMLLabelElement, InputLabelProps>(function InputLabel(inProps, ref) {
19
- const {
20
- shrink,
21
- className,
22
- ...other
23
- } = inProps;
24
-
25
- const computedClassName = cls(defaultClasses.root,
26
- {
27
- [defaultClasses.shrink]: shrink,
28
- [defaultClasses.expanded]: !shrink
29
- }, className);
30
-
31
- return (
32
- <label
33
- className={cls("text-sm font-medium peer-disabled:cursor-not-allowed",
34
- defaultBorderMixin, computedClassName)}
35
- data-shrink={shrink}
36
- ref={ref}
37
- {...other}
38
- />
39
- );
40
- });
@@ -1,32 +0,0 @@
1
- "use client";
2
- import * as React from "react"
3
- import * as LabelPrimitive from "@radix-ui/react-label"
4
- import { cls } from "../util";
5
- import { defaultBorderMixin } from "../styles";
6
-
7
- type LabelProps = React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> & {
8
- border?: boolean,
9
- onClick?: React.MouseEventHandler<HTMLLabelElement>
10
- };
11
- const Label = React.forwardRef<
12
- React.ElementRef<typeof LabelPrimitive.Root>,
13
- LabelProps
14
- >(({
15
- className,
16
- border,
17
- onClick,
18
- ...props
19
- }, ref) => (
20
- <LabelPrimitive.Root
21
- ref={ref}
22
- onClick={onClick}
23
- className={cls("text-sm font-medium peer-disabled:cursor-not-allowed",
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)}
27
- {...props}
28
- />
29
- ))
30
- Label.displayName = LabelPrimitive.Root.displayName
31
-
32
- export { Label }
@@ -1,32 +0,0 @@
1
- import React from "react";
2
- import { Button, ButtonProps } from "./Button";
3
- import { CircularProgress } from "./CircularProgress";
4
-
5
- export type LoadingButtonProps<P extends React.ElementType> = ButtonProps<P> & {
6
- startIcon?: React.ReactNode;
7
- loading?: boolean;
8
- }
9
-
10
- export function LoadingButton<P extends React.ElementType = "button">({
11
- children,
12
- loading,
13
- disabled,
14
- onClick,
15
- startIcon,
16
- ...props
17
- }: LoadingButtonProps<P>) {
18
- return (
19
- <Button
20
- disabled={loading || disabled}
21
- onClick={onClick}
22
- component={props.component as React.ElementType}
23
- {...props}
24
- >
25
- {loading && (
26
- <CircularProgress size={"smallest"}/>
27
- )}
28
- {!loading && startIcon}
29
- {children}
30
- </Button>
31
- );
32
- };
@@ -1,55 +0,0 @@
1
- "use client";
2
- import React, { useMemo } from "react";
3
- import { deepEqual as equal } from "fast-equals"
4
-
5
- import MarkdownIt from "markdown-it";
6
- import { cls } from "../util";
7
-
8
- export interface MarkdownProps {
9
- source: string,
10
- size?: "small" | "medium" | "large" | "xl" | "2xl";
11
- className?: string
12
- }
13
-
14
- const proseClasses = {
15
- small: "prose prose-sm typography-body2",
16
- medium: "prose typography-body1",
17
- large: "prose prose-lg",
18
- xl: "prose prose-xl",
19
- "2xl": "prose prose-2xl"
20
- };
21
-
22
- /**
23
- * Tailwind typography-plugin weight overrides.
24
- * The plugin defaults to very heavy weights (h1: 800, h2: 700, h3/h4: 600,
25
- * strong: 600, code: 600) which clash with the Rebase design-system that uses
26
- * font-light (300) / font-normal (400) for headings.
27
- * We reset them here so rendered markdown matches the rest of the UI.
28
- */
29
- const proseWeightOverrides = [
30
- "prose-headings:font-normal",
31
- "prose-strong:font-semibold",
32
- "prose-code:font-normal",
33
- "prose-blockquote:font-normal",
34
- "prose-a:font-normal"
35
- ].join(" ");
36
-
37
- const md = new MarkdownIt({ html: false });
38
- /**
39
- * @group Preview components
40
- */
41
- export const Markdown = React.memo<MarkdownProps>(function Markdown({
42
- source,
43
- className,
44
- size = "medium"
45
- }: MarkdownProps) {
46
- const html = useMemo(() => {
47
- return md.render(typeof source === "string" ? source : "");
48
- }, [source]);
49
-
50
- return <div
51
- className={cls(proseClasses[size], "dark:prose-invert prose-headings:font-title", proseWeightOverrides, className)}
52
- dangerouslySetInnerHTML={{ __html: html }}
53
- />;
54
- }
55
- , equal) as React.FunctionComponent<MarkdownProps>;
@@ -1,114 +0,0 @@
1
- "use client";
2
- import React from "react";
3
- import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
4
- import { focusedDisabled, paperMixin } from "../styles";
5
- import { cls } from "../util";
6
- import { usePortalContainer } from "../hooks/PortalContainerContext";
7
-
8
- export type MenuProps = {
9
- children: React.ReactNode;
10
- trigger: React.ReactNode;
11
-
12
- open?: boolean;
13
- defaultOpen?: boolean;
14
- onOpenChange?(open: boolean): void;
15
-
16
- portalContainer?: HTMLElement | null;
17
- side?: "top" | "right" | "bottom" | "left";
18
- align?: "start" | "center" | "end";
19
-
20
- sideOffset?: number;
21
- className?: string;
22
- }
23
-
24
- const Menu = React.forwardRef<
25
- React.ElementRef<typeof DropdownMenu.Trigger>,
26
- MenuProps
27
- >(({
28
- children,
29
- trigger,
30
- open,
31
- defaultOpen,
32
- side,
33
- align,
34
- onOpenChange,
35
- portalContainer,
36
- sideOffset = 4,
37
- className
38
- }, ref) => {
39
- // Get the portal container from context
40
- const contextContainer = usePortalContainer();
41
-
42
- // Prioritize manual prop, fallback to context container
43
- const finalContainer = (portalContainer ?? contextContainer ?? undefined) as HTMLElement | undefined;
44
-
45
- return (
46
- <DropdownMenu.Root
47
- open={open}
48
- defaultOpen={defaultOpen}
49
- onOpenChange={onOpenChange}>
50
- <DropdownMenu.Trigger
51
- ref={ref}
52
- asChild>
53
- {trigger}
54
- </DropdownMenu.Trigger>
55
- <DropdownMenu.Portal container={finalContainer}>
56
- <DropdownMenu.Content
57
- side={side}
58
- sideOffset={sideOffset}
59
- align={align}
60
- // `z-50` is the floating layer — the tier `Dialog`, `Sheet`,
61
- // `Select` and `Tooltip` all sit on. Radix copies this value
62
- // onto the popper wrapper it portals next to them, so at any
63
- // lower value the menu opens *behind* the dialog or sheet it
64
- // was opened from: visible in the DOM, painted under the
65
- // overlay, and unclickable. Peers on this tier stack by mount
66
- // order, which is what puts a menu above the dialog holding
67
- // its trigger, and a dialog that menu opens above them both.
68
- className={cls(paperMixin, focusedDisabled, "py-2 z-50", className)}>
69
- {children}
70
- </DropdownMenu.Content>
71
- </DropdownMenu.Portal>
72
- </DropdownMenu.Root>
73
- );
74
- })
75
- Menu.displayName = "Menu"
76
-
77
- export { Menu }
78
-
79
- export type MenuItemProps = {
80
- children: React.ReactNode;
81
- dense?: boolean;
82
- disabled?: boolean;
83
- onClick?: (event: React.MouseEvent) => void;
84
- className?: string;
85
- };
86
-
87
- export const MenuItem = React.memo(({
88
- children,
89
- dense = false, // Default value is false if not provided
90
- disabled = false,
91
- onClick,
92
- className
93
- }: MenuItemProps) => {
94
- // Dynamically adjusting the class based on the "dense" prop
95
- const classNames = cls(
96
- onClick && !disabled && "cursor-pointer",
97
- disabled && "opacity-50 cursor-not-allowed",
98
- "rounded-md text-sm font-medium text-surface-accent-700 dark:text-surface-accent-300 flex items-center gap-4 transition-colors duration-150",
99
- !disabled && "hover:bg-surface-accent-100 dark:hover:bg-surface-accent-900",
100
- dense ? "px-4 py-1.5" : "px-4 py-2",
101
- className
102
- );
103
-
104
- return (
105
- <DropdownMenu.Item
106
- className={classNames}
107
- disabled={disabled}
108
- onClick={disabled ? undefined : onClick}>
109
- {children}
110
- </DropdownMenu.Item>
111
- );
112
- });
113
-
114
- MenuItem.displayName = "MenuItem";