@noya-app/noya-designsystem 0.1.63 → 0.1.64
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.
- package/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +13 -0
- package/dist/index.css +1 -1
- package/dist/index.d.mts +169 -127
- package/dist/index.d.ts +169 -127
- package/dist/index.js +3131 -2642
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2941 -2459
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -22
- package/src/__tests__/validateDropIndicator.test.ts +26 -41
- package/src/__tests__/workspaceLayout.test.ts +281 -0
- package/src/components/ActionMenu.tsx +2 -0
- package/src/components/ActivityIndicator.tsx +5 -3
- package/src/components/AnimatePresence.tsx +6 -4
- package/src/components/Avatar.tsx +4 -2
- package/src/components/BaseToolbar.tsx +45 -34
- package/src/components/Breadcrumbs.tsx +2 -0
- package/src/components/Button.tsx +9 -3
- package/src/components/Chip.tsx +2 -0
- package/src/components/Collection.tsx +4 -1
- package/src/components/ColorSwatch.tsx +42 -22
- package/src/components/ColorSwatchControl.tsx +5 -3
- package/src/components/Combobox.tsx +2 -0
- package/src/components/CommandPalette.tsx +2 -0
- package/src/components/ContextMenu.tsx +3 -1
- package/src/components/Dialog.tsx +3 -1
- package/src/components/DimensionInput.tsx +2 -0
- package/src/components/Divider.tsx +10 -6
- package/src/components/DraggableMenuButton.tsx +2 -0
- package/src/components/Drawer.tsx +11 -3
- package/src/components/DropdownMenu.tsx +3 -1
- package/src/components/EditableText.tsx +2 -0
- package/src/components/FileUploadIndicator.tsx +108 -0
- package/src/components/FillPreviewBackground.tsx +2 -0
- package/src/components/FloatingWindow.tsx +2 -0
- package/src/components/GradientPicker.tsx +2 -0
- package/src/components/Grid.tsx +47 -38
- package/src/components/GridView.tsx +33 -11
- package/src/components/IconButton.tsx +2 -0
- package/src/components/Icons.tsx +1 -1
- package/src/components/InputField.tsx +2 -0
- package/src/components/Label.tsx +1 -1
- package/src/components/LabeledElementView.tsx +6 -2
- package/src/components/LabeledField.tsx +2 -0
- package/src/components/List.tsx +10 -2
- package/src/components/ListView.tsx +27 -14
- package/src/components/MediaThumbnail.tsx +31 -2
- package/src/components/Message.tsx +8 -9
- package/src/components/Popover.tsx +3 -1
- package/src/components/Progress.tsx +20 -7
- package/src/components/ScrollArea.tsx +3 -1
- package/src/components/SearchCompletionMenu.tsx +2 -0
- package/src/components/Section.tsx +2 -0
- package/src/components/SegmentedControl.tsx +42 -16
- package/src/components/SelectMenu.tsx +3 -1
- package/src/components/SelectionToolbar.tsx +3 -1
- package/src/components/Slider.tsx +3 -1
- package/src/components/Switch.tsx +3 -1
- package/src/components/Tabs.tsx +3 -1
- package/src/components/Text.tsx +6 -5
- package/src/components/TextArea.tsx +2 -0
- package/src/components/Toast.tsx +1 -1
- package/src/components/Toolbar.tsx +8 -2
- package/src/components/ToolbarDrawer.tsx +29 -0
- package/src/components/Tooltip.tsx +1 -1
- package/src/components/TreeView.tsx +2 -0
- package/src/components/UserPointer.tsx +2 -0
- package/src/components/ai-assistant/AIAssistantLayout.tsx +2 -0
- package/src/components/blocks/ImageBlockComponent.tsx +156 -0
- package/src/components/connected-users-menu/ConnectedUsersMenuLayout.tsx +2 -0
- package/src/components/file-explorer/FileExplorerLayout.tsx +2 -0
- package/src/components/internal/Checkmark.tsx +24 -0
- package/src/components/internal/Menu.tsx +2 -1
- package/src/components/internal/MenuViewport.tsx +4 -2
- package/src/components/internal/SelectItem.tsx +4 -23
- package/src/components/internal/TextInput.tsx +2 -0
- package/src/components/sorting/DragRegistration.tsx +8 -4
- package/src/components/sorting/SharedDragProvider.tsx +43 -18
- package/src/components/sorting/Sortable.tsx +19 -10
- package/src/components/sorting/createSharedDrag.tsx +7 -6
- package/src/components/sorting/sorting.ts +6 -9
- package/src/components/workspace/DrawerWorkspaceLayout.tsx +107 -26
- package/src/components/workspace/PanelWorkspaceLayout.tsx +98 -65
- package/src/components/workspace/VerticalTabMenu.tsx +36 -0
- package/src/components/workspace/WorkspaceLayout.tsx +46 -42
- package/src/components/workspace/constants.ts +4 -0
- package/src/components/workspace/panelStorage.ts +216 -0
- package/src/components/workspace/types.ts +11 -4
- package/src/contexts/DesignSystemConfiguration.tsx +12 -5
- package/src/contexts/DialogContext.tsx +2 -0
- package/src/contexts/FloatingWindowContext.tsx +2 -0
- package/src/contexts/GlobalInputBlurContext.tsx +2 -0
- package/src/contexts/ImageDataContext.tsx +2 -0
- package/src/contexts/LinkComponentContext.tsx +17 -0
- package/src/contexts/OpenPortalsContext.tsx +2 -0
- package/src/contexts/PortalScopeContext.tsx +2 -0
- package/src/hooks/mergeEventHandlers.ts +1 -1
- package/src/hooks/useHover.ts +30 -17
- package/src/hooks/useIndent.ts +2 -0
- package/src/hooks/useLabel.ts +2 -0
- package/src/hooks/useObjectURL.ts +5 -3
- package/src/hooks/usePlatform.ts +5 -3
- package/src/hooks/useTheme.ts +3 -1
- package/src/index.css +19 -0
- package/src/index.tsx +5 -2
- package/src/utils/classNames.ts +4 -3
- package/src/utils/combobox.ts +2 -0
- package/src/utils/formatByteSize.ts +8 -0
- package/src/utils/withSeparatorElements.ts +1 -1
- package/src/hooks/usePreservePanelSize.tsx +0 -183
- package/src/mediaQuery.ts +0 -13
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import React, {
|
|
2
4
|
CSSProperties,
|
|
3
5
|
ForwardedRef,
|
|
@@ -12,7 +14,7 @@ import { Spacer } from "./Spacer";
|
|
|
12
14
|
import { Tooltip } from "./Tooltip";
|
|
13
15
|
import type { MenuItemIcon } from "./internal/Menu";
|
|
14
16
|
|
|
15
|
-
type ButtonVariant = "normal" | "thin" | "floating" | "none";
|
|
17
|
+
type ButtonVariant = "normal" | "thin" | "floating" | "none" | "ghost";
|
|
16
18
|
|
|
17
19
|
type ButtonSize = "small" | "normal" | "large" | "floating";
|
|
18
20
|
|
|
@@ -32,6 +34,7 @@ const variantStyles: Record<ButtonVariant, string> = {
|
|
|
32
34
|
"bg-floating-button text-text shadow-[0_1px_2px_rgba(0,0,0,0.1)] hover:opacity-80 active:opacity-90",
|
|
33
35
|
thin: "bg-transparent text-text hover:bg-input-background-light",
|
|
34
36
|
none: "bg-transparent text-text hover:bg-input-background-light",
|
|
37
|
+
ghost: "bg-transparent text-text hover:bg-input-background-light",
|
|
35
38
|
};
|
|
36
39
|
|
|
37
40
|
const sizeStyles: Record<ButtonSize | "thin" | "none", string> = {
|
|
@@ -97,7 +100,8 @@ export const Button = forwardRef(function Button(
|
|
|
97
100
|
const colorScheme = colorSchemeProp ?? "default";
|
|
98
101
|
|
|
99
102
|
const baseClassName = cx(
|
|
100
|
-
"no-underline leading-[1] relative
|
|
103
|
+
"no-underline leading-[1] relative outline-none select-none text-left rounded flex items-center justify-center [&>*]:pointer-events-none [-webkit-app-region:no-drag] focus:ring-2 focus:ring-primary focus:shadow-[0_0_0_1px_var(--n-popover-background)_inset] transition-all",
|
|
104
|
+
variant === "ghost" ? "border" : "border-0",
|
|
101
105
|
disabled ? "opacity-25" : "",
|
|
102
106
|
!className?.includes("flex") ? "flex-none" : "",
|
|
103
107
|
active
|
|
@@ -113,7 +117,9 @@ export const Button = forwardRef(function Button(
|
|
|
113
117
|
: size
|
|
114
118
|
],
|
|
115
119
|
variant === "normal" && (children ? "min-w-[31px]" : "min-w-[27px]"),
|
|
116
|
-
|
|
120
|
+
variant === "ghost"
|
|
121
|
+
? "border-solid border-input-background hover:bg-input-background-light"
|
|
122
|
+
: colorSchemeStyles[colorScheme],
|
|
117
123
|
!children && (icon || iconRight) && !(icon && iconRight) && "w-[27px]"
|
|
118
124
|
);
|
|
119
125
|
|
package/src/components/Chip.tsx
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import { forwardRefGeneric } from "@noya-app/react-utils";
|
|
2
4
|
import React from "react";
|
|
3
5
|
import { Grid } from "../components/Grid";
|
|
@@ -35,6 +37,7 @@ export interface CollectionProps<T, M extends string = string> {
|
|
|
35
37
|
items: T[];
|
|
36
38
|
getId: (item: T) => string;
|
|
37
39
|
getName: (item: T) => string;
|
|
40
|
+
getHref?: (item: T) => string;
|
|
38
41
|
getExpanded?: (item: T) => boolean | undefined;
|
|
39
42
|
getPlaceholder?: (item: T) => string;
|
|
40
43
|
/**
|
|
@@ -90,7 +93,7 @@ export interface CollectionProps<T, M extends string = string> {
|
|
|
90
93
|
viewType?: CollectionViewType;
|
|
91
94
|
onClickItem?: (itemId: string) => void;
|
|
92
95
|
onDoubleClickItem?: (itemId: string) => void;
|
|
93
|
-
renderEmptyState?: () => React.ReactElement
|
|
96
|
+
renderEmptyState?: () => React.ReactElement<any>;
|
|
94
97
|
/** @default false */
|
|
95
98
|
sortable?: boolean;
|
|
96
99
|
dragIndicatorStyle?: ListViewRowProps<M>["dragIndicatorStyle"];
|
|
@@ -1,9 +1,16 @@
|
|
|
1
|
+
import { getContrastColorForBackground } from "@noya-app/noya-colorpicker";
|
|
2
|
+
import { CheckIcon } from "@noya-app/noya-icons";
|
|
1
3
|
import React, { forwardRef } from "react";
|
|
2
|
-
import { cssVars } from "../theme";
|
|
3
4
|
|
|
4
|
-
export type ColorSwatchSize =
|
|
5
|
+
export type ColorSwatchSize =
|
|
6
|
+
| "xxsmall"
|
|
7
|
+
| "xsmall"
|
|
8
|
+
| "small"
|
|
9
|
+
| "medium"
|
|
10
|
+
| "large";
|
|
5
11
|
|
|
6
|
-
export const colorSwatchSizeMap = {
|
|
12
|
+
export const colorSwatchSizeMap: Record<ColorSwatchSize, number> = {
|
|
13
|
+
xxsmall: 15,
|
|
7
14
|
xsmall: 21,
|
|
8
15
|
small: 27,
|
|
9
16
|
medium: 36,
|
|
@@ -14,32 +21,45 @@ type ColorSwatchProps = {
|
|
|
14
21
|
color: string;
|
|
15
22
|
size?: ColorSwatchSize;
|
|
16
23
|
checked?: boolean;
|
|
24
|
+
as?: React.ElementType;
|
|
17
25
|
} & React.ButtonHTMLAttributes<HTMLButtonElement>;
|
|
18
26
|
|
|
19
27
|
export const ColorSwatch = forwardRef(function ColorSwatch(
|
|
20
|
-
{
|
|
28
|
+
{
|
|
29
|
+
color,
|
|
30
|
+
size = "small",
|
|
31
|
+
checked,
|
|
32
|
+
style,
|
|
33
|
+
as: Component = "button",
|
|
34
|
+
...props
|
|
35
|
+
}: ColorSwatchProps,
|
|
21
36
|
ref: React.ForwardedRef<HTMLButtonElement>
|
|
22
37
|
) {
|
|
23
38
|
const sizePx = colorSwatchSizeMap[size];
|
|
39
|
+
const checkedColor = getContrastColorForBackground(color);
|
|
24
40
|
|
|
25
41
|
return (
|
|
26
|
-
<
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
: "1px solid rgba(0,0,0,0.1)",
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
<div className="relative" style={{ width: sizePx, height: sizePx }}>
|
|
43
|
+
<Component
|
|
44
|
+
{...props}
|
|
45
|
+
ref={ref}
|
|
46
|
+
style={{
|
|
47
|
+
display: "inline-block",
|
|
48
|
+
background: color,
|
|
49
|
+
width: sizePx,
|
|
50
|
+
height: sizePx,
|
|
51
|
+
borderRadius: "4px",
|
|
52
|
+
outline: "1px solid rgba(0,0,0,0.1)",
|
|
53
|
+
outlineOffset: -1,
|
|
54
|
+
...style,
|
|
55
|
+
}}
|
|
56
|
+
/>
|
|
57
|
+
{checked && (
|
|
58
|
+
<CheckIcon
|
|
59
|
+
color={checkedColor}
|
|
60
|
+
className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2"
|
|
61
|
+
/>
|
|
62
|
+
)}
|
|
63
|
+
</div>
|
|
44
64
|
);
|
|
45
65
|
});
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { ToggleGroup as ToggleGroupPrimitive } from "radix-ui";
|
|
2
4
|
import React, { useMemo } from "react";
|
|
3
5
|
import { cx } from "../utils/classNames";
|
|
4
6
|
import {
|
|
@@ -52,7 +54,7 @@ export function ColorSwatchControl(props: ColorSwatchControlProps) {
|
|
|
52
54
|
{options.map((option) => {
|
|
53
55
|
const item = (
|
|
54
56
|
<ColorSwatch
|
|
55
|
-
key={option as string}
|
|
57
|
+
key={`${option as string}-color-swatch`}
|
|
56
58
|
color={option as string}
|
|
57
59
|
size={size}
|
|
58
60
|
onFocus={onFocus}
|
|
@@ -67,7 +69,7 @@ export function ColorSwatchControl(props: ColorSwatchControlProps) {
|
|
|
67
69
|
<ToggleGroupPrimitive.Item
|
|
68
70
|
asChild
|
|
69
71
|
value={option as string}
|
|
70
|
-
key={option as string}
|
|
72
|
+
key={`${option as string}-toggle-group-item`}
|
|
71
73
|
disabled={readOnly}
|
|
72
74
|
>
|
|
73
75
|
{item}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import { useKeyboardShortcuts } from "@noya-app/noya-keymap";
|
|
2
4
|
import { memoGeneric } from "@noya-app/react-utils";
|
|
3
|
-
import
|
|
5
|
+
import { ContextMenu as RadixContextMenu } from "radix-ui";
|
|
4
6
|
import React, { ReactNode, useCallback, useMemo } from "react";
|
|
5
7
|
import {
|
|
6
8
|
portalScopeProps,
|
|
@@ -12,7 +12,7 @@ interface DividerProps {
|
|
|
12
12
|
|
|
13
13
|
export const Divider = memo(function Divider({
|
|
14
14
|
variant = "normal",
|
|
15
|
-
overflow
|
|
15
|
+
overflow,
|
|
16
16
|
className,
|
|
17
17
|
style,
|
|
18
18
|
...props
|
|
@@ -29,8 +29,10 @@ export const Divider = memo(function Divider({
|
|
|
29
29
|
className
|
|
30
30
|
)}
|
|
31
31
|
style={{
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
...(typeof overflow === "number" && {
|
|
33
|
+
marginLeft: `-${overflow}px`,
|
|
34
|
+
marginRight: `-${overflow}px`,
|
|
35
|
+
}),
|
|
34
36
|
...style,
|
|
35
37
|
}}
|
|
36
38
|
{...props}
|
|
@@ -40,7 +42,7 @@ export const Divider = memo(function Divider({
|
|
|
40
42
|
|
|
41
43
|
export const DividerVertical = memo(function DividerVertical({
|
|
42
44
|
variant = "normal",
|
|
43
|
-
overflow
|
|
45
|
+
overflow,
|
|
44
46
|
className,
|
|
45
47
|
style,
|
|
46
48
|
...props
|
|
@@ -57,8 +59,10 @@ export const DividerVertical = memo(function DividerVertical({
|
|
|
57
59
|
className
|
|
58
60
|
)}
|
|
59
61
|
style={{
|
|
60
|
-
|
|
61
|
-
|
|
62
|
+
...(typeof overflow === "number" && {
|
|
63
|
+
marginTop: `-${overflow}px`,
|
|
64
|
+
marginBottom: `-${overflow}px`,
|
|
65
|
+
}),
|
|
62
66
|
...style,
|
|
63
67
|
}}
|
|
64
68
|
{...props}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import { useControlledOrUncontrolled } from "@noya-app/react-utils";
|
|
2
|
-
import
|
|
4
|
+
import { Dialog } from "radix-ui";
|
|
3
5
|
import * as React from "react";
|
|
4
6
|
import { useImperativeHandle } from "react";
|
|
5
7
|
import { cx } from "../utils/classNames";
|
|
@@ -14,6 +16,8 @@ export type DrawerProps = {
|
|
|
14
16
|
className?: string;
|
|
15
17
|
id?: string;
|
|
16
18
|
style?: React.CSSProperties;
|
|
19
|
+
overlayClassName?: string;
|
|
20
|
+
overlayStyle?: React.CSSProperties;
|
|
17
21
|
positioning?: "fixed" | "absolute";
|
|
18
22
|
side?: "left" | "right";
|
|
19
23
|
portalled?: boolean;
|
|
@@ -35,6 +39,8 @@ export const Drawer = React.memo(
|
|
|
35
39
|
side = "left",
|
|
36
40
|
portalled = true,
|
|
37
41
|
portalContainer,
|
|
42
|
+
overlayClassName,
|
|
43
|
+
overlayStyle,
|
|
38
44
|
}: DrawerProps,
|
|
39
45
|
forwardedRef: React.ForwardedRef<SidebarRef>
|
|
40
46
|
) {
|
|
@@ -61,14 +67,16 @@ export const Drawer = React.memo(
|
|
|
61
67
|
<Dialog.Overlay
|
|
62
68
|
className={cx(
|
|
63
69
|
"inset-0 bg-black/50",
|
|
64
|
-
positioning === "absolute" ? "absolute" : "fixed"
|
|
70
|
+
positioning === "absolute" ? "absolute" : "fixed",
|
|
71
|
+
overlayClassName
|
|
65
72
|
)}
|
|
73
|
+
style={overlayStyle}
|
|
66
74
|
/>
|
|
67
75
|
<Dialog.Content
|
|
68
76
|
id={id}
|
|
69
77
|
style={style}
|
|
70
78
|
className={cx(
|
|
71
|
-
`top-0 bottom-0 z-50 overflow-y-auto bg-sidebar-background rounded-none max-h-none max-w-none sm
|
|
79
|
+
`top-0 bottom-0 z-50 overflow-y-auto bg-sidebar-background rounded-none max-h-none max-w-none sm:!max-w-sm w-full border-divider-strong`,
|
|
72
80
|
positioning === "absolute" ? "absolute" : "fixed",
|
|
73
81
|
side === "left" ? "left-0 border-r" : "right-0 border-l",
|
|
74
82
|
className
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import { useKeyboardShortcuts } from "@noya-app/noya-keymap";
|
|
2
4
|
import {
|
|
3
5
|
forwardRefGeneric,
|
|
4
6
|
memoGeneric,
|
|
5
7
|
useControlledOrUncontrolled,
|
|
6
8
|
} from "@noya-app/react-utils";
|
|
7
|
-
import
|
|
9
|
+
import { DropdownMenu as RadixDropdownMenu } from "radix-ui";
|
|
8
10
|
import React, {
|
|
9
11
|
ComponentProps,
|
|
10
12
|
ForwardedRef,
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { formatByteSize } from "../utils/formatByteSize";
|
|
3
|
+
import { ActivityIndicator } from "./ActivityIndicator";
|
|
4
|
+
import { Divider } from "./Divider";
|
|
5
|
+
import { MediaThumbnail } from "./MediaThumbnail";
|
|
6
|
+
import { Progress } from "./Progress";
|
|
7
|
+
import { Heading5, Small } from "./Text";
|
|
8
|
+
import { Checkmark } from "./internal/Checkmark";
|
|
9
|
+
|
|
10
|
+
type FileUploadIndicatorProps = {
|
|
11
|
+
name?: string;
|
|
12
|
+
percent?: number;
|
|
13
|
+
total?: number;
|
|
14
|
+
contentType?: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export function FileUploadIndicator({
|
|
18
|
+
name,
|
|
19
|
+
percent,
|
|
20
|
+
total,
|
|
21
|
+
contentType,
|
|
22
|
+
}: FileUploadIndicatorProps) {
|
|
23
|
+
const done = percent === 1;
|
|
24
|
+
const value = typeof percent === "number" ? Math.round(percent) : 0;
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<div className="flex items-center gap-2">
|
|
28
|
+
<div className="w-12 h-12 bg-background rounded-md overflow-hidden">
|
|
29
|
+
<MediaThumbnail
|
|
30
|
+
size="medium"
|
|
31
|
+
fileName={name}
|
|
32
|
+
contentType={contentType}
|
|
33
|
+
/>
|
|
34
|
+
</div>
|
|
35
|
+
<div className="flex flex-col flex-1 justify-center gap-1 min-w-0">
|
|
36
|
+
{name && (
|
|
37
|
+
<Small color="text" className="truncate leading-none">
|
|
38
|
+
{name}
|
|
39
|
+
</Small>
|
|
40
|
+
)}
|
|
41
|
+
{typeof total === "number" && typeof percent === "number" && (
|
|
42
|
+
<Small
|
|
43
|
+
color="textSubtle"
|
|
44
|
+
className="leading-none"
|
|
45
|
+
style={{ fontSize: "11px" }}
|
|
46
|
+
>
|
|
47
|
+
{formatByteSize(Math.round((percent / 100) * total))} /{" "}
|
|
48
|
+
{formatByteSize(total)}
|
|
49
|
+
</Small>
|
|
50
|
+
)}
|
|
51
|
+
{typeof value === "number" && (
|
|
52
|
+
<Progress
|
|
53
|
+
value={value}
|
|
54
|
+
style={{ marginTop: "3px", height: "3px" }}
|
|
55
|
+
className="rounded-sm"
|
|
56
|
+
colorScheme="secondary"
|
|
57
|
+
/>
|
|
58
|
+
)}
|
|
59
|
+
</div>
|
|
60
|
+
<div className="flex items-center justify-center gap-2">
|
|
61
|
+
{typeof value === "number" && (
|
|
62
|
+
<Small
|
|
63
|
+
color="textSubtle"
|
|
64
|
+
style={{ lineHeight: "1", fontSize: "13px" }}
|
|
65
|
+
className="tabular-nums text-right w-10"
|
|
66
|
+
>
|
|
67
|
+
{value}%
|
|
68
|
+
</Small>
|
|
69
|
+
)}
|
|
70
|
+
{done ? (
|
|
71
|
+
<div className="w-[15px] h-[15px] bg-secondary rounded-full flex items-center justify-center text-white">
|
|
72
|
+
<Checkmark />
|
|
73
|
+
</div>
|
|
74
|
+
) : (
|
|
75
|
+
<ActivityIndicator size={15} />
|
|
76
|
+
)}
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function FileUploadList({
|
|
83
|
+
uploads,
|
|
84
|
+
}: {
|
|
85
|
+
uploads: (FileUploadIndicatorProps & { id: string })[];
|
|
86
|
+
}) {
|
|
87
|
+
return (
|
|
88
|
+
<>
|
|
89
|
+
<div className="flex items-center gap-2 py-2 px-4">
|
|
90
|
+
<Heading5>
|
|
91
|
+
Uploading {uploads.length} {uploads.length === 1 ? "asset" : "assets"}
|
|
92
|
+
</Heading5>
|
|
93
|
+
</div>
|
|
94
|
+
<Divider />
|
|
95
|
+
<div className="flex flex-col gap-3 max-h-[500px] overflow-y-auto overflow-x-hidden py-4 px-4">
|
|
96
|
+
{uploads.map((upload) => (
|
|
97
|
+
<FileUploadIndicator
|
|
98
|
+
key={upload.id}
|
|
99
|
+
name={upload?.name}
|
|
100
|
+
percent={upload?.percent}
|
|
101
|
+
total={upload?.total}
|
|
102
|
+
contentType={upload?.contentType}
|
|
103
|
+
/>
|
|
104
|
+
))}
|
|
105
|
+
</div>
|
|
106
|
+
</>
|
|
107
|
+
);
|
|
108
|
+
}
|
package/src/components/Grid.tsx
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import {
|
|
2
4
|
forwardRefGeneric,
|
|
3
5
|
memoGeneric,
|
|
@@ -70,6 +72,7 @@ export const Grid = memoGeneric(
|
|
|
70
72
|
items,
|
|
71
73
|
getId,
|
|
72
74
|
getName,
|
|
75
|
+
getHref,
|
|
73
76
|
// expandable,
|
|
74
77
|
// getExpanded,
|
|
75
78
|
getRenamable,
|
|
@@ -84,7 +87,7 @@ export const Grid = memoGeneric(
|
|
|
84
87
|
onSelectionChange,
|
|
85
88
|
selectedIds = emptyArray,
|
|
86
89
|
// itemRoleDescription = "clickable item",
|
|
87
|
-
|
|
90
|
+
detailPosition = "below",
|
|
88
91
|
size = "medium",
|
|
89
92
|
testHoveredId,
|
|
90
93
|
testRenamingId,
|
|
@@ -169,6 +172,7 @@ export const Grid = memoGeneric(
|
|
|
169
172
|
<GridView.Section>
|
|
170
173
|
{items.map((item) => {
|
|
171
174
|
const id = getId(item);
|
|
175
|
+
const href = getHref?.(item);
|
|
172
176
|
const isDropdownOpen = dropdownOpenId === id;
|
|
173
177
|
const isHovered =
|
|
174
178
|
testHoveredId === id ||
|
|
@@ -206,9 +210,18 @@ export const Grid = memoGeneric(
|
|
|
206
210
|
/>
|
|
207
211
|
));
|
|
208
212
|
|
|
213
|
+
const subtitle = (
|
|
214
|
+
<span
|
|
215
|
+
className={cx(isSelected && "text-selected-list-item-text")}
|
|
216
|
+
>
|
|
217
|
+
{renderDetail?.(item, isSelected)}
|
|
218
|
+
</span>
|
|
219
|
+
);
|
|
220
|
+
|
|
209
221
|
return (
|
|
210
222
|
<GridView.Item<M>
|
|
211
223
|
key={id}
|
|
224
|
+
href={href}
|
|
212
225
|
id={id}
|
|
213
226
|
role="option"
|
|
214
227
|
aria-selected={isSelected}
|
|
@@ -219,44 +232,40 @@ export const Grid = memoGeneric(
|
|
|
219
232
|
setHoveredId(isHovering ? id : undefined);
|
|
220
233
|
}}
|
|
221
234
|
title={
|
|
222
|
-
<
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
onRename
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
isSelected && "text-selected-list-item-text"
|
|
255
|
-
)}
|
|
256
|
-
>
|
|
257
|
-
{renderDetail?.(item, isSelected)}
|
|
258
|
-
</span>
|
|
235
|
+
<div className="flex items-center gap-2 flex-row">
|
|
236
|
+
<EditableText
|
|
237
|
+
className={cx(detailPosition === "end" && "flex-1")}
|
|
238
|
+
tabIndex={isRenaming ? undefined : -1}
|
|
239
|
+
value={getName(item)}
|
|
240
|
+
focused={isRenaming}
|
|
241
|
+
testFocused={isTestingRenaming}
|
|
242
|
+
readOnly={!itemIsRenamable || !onRename}
|
|
243
|
+
onSubmit={(value) => {
|
|
244
|
+
onRename?.(item, value);
|
|
245
|
+
setRenamingId(undefined);
|
|
246
|
+
}}
|
|
247
|
+
onBlur={() => {
|
|
248
|
+
setRenamingId(undefined);
|
|
249
|
+
}}
|
|
250
|
+
// max height ensures preview text and input are one line
|
|
251
|
+
textClassName="bg-listview-editing-background max-h-input-height"
|
|
252
|
+
>
|
|
253
|
+
{(props) => (
|
|
254
|
+
<span
|
|
255
|
+
{...props}
|
|
256
|
+
className={cx(
|
|
257
|
+
isSelected
|
|
258
|
+
? "text-selected-list-item-text"
|
|
259
|
+
: "text-text",
|
|
260
|
+
"truncate select-none"
|
|
261
|
+
)}
|
|
262
|
+
/>
|
|
263
|
+
)}
|
|
264
|
+
</EditableText>
|
|
265
|
+
{detailPosition === "end" && subtitle}
|
|
266
|
+
</div>
|
|
259
267
|
}
|
|
268
|
+
subtitle={detailPosition === "below" && subtitle}
|
|
260
269
|
loading={false}
|
|
261
270
|
selected={isSelected}
|
|
262
271
|
onClick={() => {
|