@noya-app/noya-designsystem 0.1.50 → 0.1.52
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 -13
- package/CHANGELOG.md +19 -0
- package/dist/index.css +1 -1
- package/dist/index.d.mts +314 -203
- package/dist/index.d.ts +314 -203
- package/dist/index.js +6473 -12656
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +8399 -14605
- package/dist/index.mjs.map +1 -1
- package/package.json +15 -12
- package/postcss.config.js +7 -0
- package/src/components/ActionMenu.tsx +12 -5
- package/src/components/Banner.tsx +2 -2
- package/src/components/BaseToolbar.tsx +6 -2
- package/src/components/Breadcrumbs.tsx +32 -2
- package/src/components/Button.tsx +30 -19
- package/src/components/Chip.tsx +3 -0
- package/src/components/Collection.tsx +12 -3
- package/src/components/ColorSwatch.tsx +42 -0
- package/src/components/ColorSwatchControl.tsx +92 -0
- package/src/components/ComboboxMenu.tsx +10 -1
- package/src/components/Dialog.tsx +1 -1
- package/src/components/FillInputField.tsx +1 -1
- package/src/components/Grid.tsx +22 -12
- package/src/components/GridView.tsx +1 -1
- package/src/components/LabeledField.tsx +4 -1
- package/src/components/List.tsx +37 -26
- package/src/components/ListView.tsx +7 -4
- package/src/components/MediaThumbnail.tsx +63 -15
- package/src/components/Popover.tsx +1 -1
- package/src/components/SearchCompletionMenu.tsx +12 -12
- package/src/components/SegmentedControl.tsx +2 -2
- package/src/components/SelectionToolbar.tsx +70 -0
- package/src/components/Switch.tsx +1 -1
- package/src/components/Text.tsx +2 -2
- package/src/components/Toast.tsx +13 -7
- package/src/components/Toolbar.tsx +33 -11
- package/src/components/Tooltip.tsx +4 -2
- package/src/components/catppuccin/fileIcons.ts +2430 -0
- package/src/components/connected-users-menu/ConnectedUsersMenuLayout.tsx +3 -1
- package/src/components/file-explorer/FileExplorerLayout.tsx +12 -2
- package/src/components/internal/Menu.tsx +5 -4
- package/src/components/internal/MenuViewport.tsx +2 -0
- package/src/components/internal/TextInput.tsx +7 -2
- package/src/components/pipeline/PipelineResultLayout.tsx +18 -0
- package/src/contexts/DialogContext.tsx +20 -5
- package/src/index.css +103 -34
- package/src/index.tsx +3 -0
- package/src/theme/index.ts +7 -2
- package/src/theme/themeUtils.ts +10 -3
- package/src/utils/classNames.ts +4 -3
- package/src/utils/combobox.ts +18 -13
- package/src/utils/moveTreeItem.ts +4 -4
- package/tailwind.config.ts +2 -239
- package/tailwind.d.ts +1 -1
- package/tsup.config.ts +1 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@noya-app/noya-designsystem",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.52",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"module": "./dist/index.mjs",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"./index.css": "./dist/index.css"
|
|
15
15
|
},
|
|
16
16
|
"scripts": {
|
|
17
|
-
"build:css": "tailwindcss -i ./src/index.css -o ./dist/index.css",
|
|
17
|
+
"build:css": "tailwindcss -i ./src/index.css -o ./dist/index.css --postcss",
|
|
18
18
|
"build": "tsup",
|
|
19
19
|
"dev": "npm run build -- --watch",
|
|
20
20
|
"lint": "eslint . --max-warnings 0"
|
|
@@ -22,11 +22,12 @@
|
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@dnd-kit/core": "6.3.1",
|
|
24
24
|
"@dnd-kit/sortable": "10.0.0",
|
|
25
|
-
"@noya-app/noya-colorpicker": "0.1.
|
|
25
|
+
"@noya-app/noya-colorpicker": "0.1.20",
|
|
26
26
|
"@noya-app/noya-utils": "0.1.5",
|
|
27
|
-
"@noya-app/noya-geometry": "0.1.
|
|
28
|
-
"@noya-app/noya-icons": "0.1.
|
|
27
|
+
"@noya-app/noya-geometry": "0.1.11",
|
|
28
|
+
"@noya-app/noya-icons": "0.1.8",
|
|
29
29
|
"@noya-app/noya-keymap": "0.1.3",
|
|
30
|
+
"@noya-app/noya-tailwind-config": "0.1.3",
|
|
30
31
|
"@radix-ui/primitive": "^1.0.0",
|
|
31
32
|
"@radix-ui/react-avatar": "^1.0.1",
|
|
32
33
|
"@radix-ui/react-compose-refs": "^1.0.0",
|
|
@@ -43,23 +44,25 @@
|
|
|
43
44
|
"@radix-ui/react-tooltip": "^1.0.2",
|
|
44
45
|
"@radix-ui/react-utils": "^0.0.5",
|
|
45
46
|
"@radix-ui/react-select": "^2.1.1",
|
|
47
|
+
"@radix-ui/react-popper": "1.2.3",
|
|
48
|
+
"@radix-ui/utils": "0.0.3",
|
|
46
49
|
"immer": "9.0.5",
|
|
47
50
|
"kiwi.js": "^1.1.3",
|
|
48
51
|
"react-resizable-panels": "2.0.22",
|
|
49
52
|
"react-window": "^1.8.8",
|
|
50
|
-
"vscode-fuzzy-scorer": "^0.0.4"
|
|
53
|
+
"vscode-fuzzy-scorer": "^0.0.4",
|
|
54
|
+
"react-virtualized": "9.22.6"
|
|
51
55
|
},
|
|
52
56
|
"devDependencies": {
|
|
53
57
|
"@tailwindcss/container-queries": "^0.1.1",
|
|
54
58
|
"@types/react": "*",
|
|
55
59
|
"@types/react-dom": "*",
|
|
56
|
-
"@types/react-virtualized": "^9.21.
|
|
60
|
+
"@types/react-virtualized": "^9.21.30",
|
|
57
61
|
"@types/react-window": "^1.8.5",
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"tailwindcss": "^3.4.14"
|
|
62
|
+
"tailwindcss": "^3.4.17",
|
|
63
|
+
"postcss": "^8.5.3",
|
|
64
|
+
"autoprefixer": "^10.4.21",
|
|
65
|
+
"postcss-nested": "^7.0.2"
|
|
63
66
|
},
|
|
64
67
|
"peerDependencies": {
|
|
65
68
|
"react": "*",
|
|
@@ -8,10 +8,13 @@ import { MenuItem } from "./internal/Menu";
|
|
|
8
8
|
type ActionMenuProps<TMenu extends string> = {
|
|
9
9
|
menuItems: MenuItem<TMenu>[];
|
|
10
10
|
onSelect: (action: TMenu) => void;
|
|
11
|
-
selected
|
|
12
|
-
|
|
11
|
+
selected?: boolean;
|
|
12
|
+
disabled?: boolean;
|
|
13
|
+
onOpenChange?: (open: boolean) => void;
|
|
13
14
|
className?: string;
|
|
14
15
|
style?: React.CSSProperties;
|
|
16
|
+
variant?: "normal" | "bare";
|
|
17
|
+
color?: string;
|
|
15
18
|
};
|
|
16
19
|
|
|
17
20
|
export const ActionMenu = memoGeneric(function ActionMenu<
|
|
@@ -21,18 +24,21 @@ export const ActionMenu = memoGeneric(function ActionMenu<
|
|
|
21
24
|
onSelect,
|
|
22
25
|
selected,
|
|
23
26
|
onOpenChange,
|
|
27
|
+
disabled,
|
|
24
28
|
className,
|
|
25
29
|
style,
|
|
30
|
+
variant = "normal",
|
|
31
|
+
color,
|
|
26
32
|
}: ActionMenuProps<TMenu>) {
|
|
27
33
|
const internalStyle = useMemo(() => {
|
|
28
34
|
return {
|
|
29
35
|
backgroundColor: selected
|
|
30
36
|
? cssVars.colors.primaryPastel
|
|
31
37
|
: cssVars.colors.inputBackground,
|
|
32
|
-
padding: "
|
|
38
|
+
padding: variant === "bare" ? 0 : 4,
|
|
33
39
|
...style,
|
|
34
40
|
};
|
|
35
|
-
}, [selected, style]);
|
|
41
|
+
}, [selected, style, variant]);
|
|
36
42
|
|
|
37
43
|
return (
|
|
38
44
|
<DropdownMenu
|
|
@@ -44,7 +50,8 @@ export const ActionMenu = memoGeneric(function ActionMenu<
|
|
|
44
50
|
style={internalStyle}
|
|
45
51
|
className={className}
|
|
46
52
|
iconName="DotsVerticalIcon"
|
|
47
|
-
color={selected ? cssVars.colors.primary :
|
|
53
|
+
color={color ?? (selected ? cssVars.colors.primary : "currentColor")}
|
|
54
|
+
disabled={disabled}
|
|
48
55
|
/>
|
|
49
56
|
</DropdownMenu>
|
|
50
57
|
);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { CSSProperties } from "react";
|
|
1
|
+
import React, { CSSProperties, ReactNode } from "react";
|
|
2
2
|
import { cssVars } from "../theme";
|
|
3
3
|
import { cx } from "../utils/classNames";
|
|
4
4
|
import { Small } from "./Text";
|
|
@@ -9,7 +9,7 @@ const bannerStyles = {
|
|
|
9
9
|
};
|
|
10
10
|
|
|
11
11
|
export type BannerProps = {
|
|
12
|
-
label?:
|
|
12
|
+
label?: ReactNode;
|
|
13
13
|
className?: string;
|
|
14
14
|
style?: CSSProperties;
|
|
15
15
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { cssVars } from "../theme";
|
|
2
|
+
import { cssVarNames, cssVars } from "../theme";
|
|
3
3
|
import { Divider, DividerVertical } from "./Divider";
|
|
4
4
|
import { Spacer } from "./Spacer";
|
|
5
5
|
|
|
@@ -11,6 +11,10 @@ export interface BaseToolbarProps {
|
|
|
11
11
|
showDivider?: boolean;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
const toolbarStyle = {
|
|
15
|
+
[cssVarNames.colors.inputBackground]: "transparent",
|
|
16
|
+
};
|
|
17
|
+
|
|
14
18
|
export function BaseToolbar({
|
|
15
19
|
children,
|
|
16
20
|
left,
|
|
@@ -19,7 +23,7 @@ export function BaseToolbar({
|
|
|
19
23
|
showDivider = true,
|
|
20
24
|
}: BaseToolbarProps) {
|
|
21
25
|
return (
|
|
22
|
-
<div className="flex flex-col">
|
|
26
|
+
<div className="flex flex-col" style={toolbarStyle}>
|
|
23
27
|
<div
|
|
24
28
|
className="flex items-center pr-2.5 bg-sidebar-background flex-none relative @container/toolbar"
|
|
25
29
|
style={{
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { forwardRef } from "react";
|
|
2
2
|
|
|
3
3
|
import React from "react";
|
|
4
|
+
import { cssVars } from "../theme";
|
|
4
5
|
import { cx } from "../utils/classNames";
|
|
5
6
|
import { Text, TextProps } from "./Text";
|
|
6
7
|
|
|
@@ -10,7 +11,7 @@ type BreadcrumbTextProps = Omit<
|
|
|
10
11
|
>;
|
|
11
12
|
|
|
12
13
|
export const BreadcrumbText = forwardRef(function BreadcrumbText(
|
|
13
|
-
{ children, className, ...props }: BreadcrumbTextProps,
|
|
14
|
+
{ children, className, onClick, ...props }: BreadcrumbTextProps,
|
|
14
15
|
ref: React.ForwardedRef<HTMLSpanElement>
|
|
15
16
|
) {
|
|
16
17
|
return (
|
|
@@ -18,12 +19,41 @@ export const BreadcrumbText = forwardRef(function BreadcrumbText(
|
|
|
18
19
|
{...props}
|
|
19
20
|
variant="small"
|
|
20
21
|
className={cx(
|
|
21
|
-
"
|
|
22
|
+
"whitespace-pre leading-[15px] select-none",
|
|
23
|
+
onClick &&
|
|
24
|
+
"hover:text-breadcrumb-text-hover hover:cursor-pointer hover:whitespace-pre hover:select-none",
|
|
22
25
|
className
|
|
23
26
|
)}
|
|
24
27
|
ref={ref}
|
|
28
|
+
onClick={onClick}
|
|
25
29
|
>
|
|
26
30
|
{children}
|
|
27
31
|
</Text>
|
|
28
32
|
);
|
|
29
33
|
});
|
|
34
|
+
|
|
35
|
+
const slashStyle = {
|
|
36
|
+
margin: "0 3px",
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const BreadcrumbSlash = () => {
|
|
40
|
+
return (
|
|
41
|
+
<svg
|
|
42
|
+
width="7"
|
|
43
|
+
height="17"
|
|
44
|
+
viewBox="0 0 7 17"
|
|
45
|
+
fill="none"
|
|
46
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
47
|
+
opacity={0.5}
|
|
48
|
+
style={slashStyle}
|
|
49
|
+
>
|
|
50
|
+
<path
|
|
51
|
+
d="M1 16L6 1"
|
|
52
|
+
stroke={cssVars.colors.breadcrumbIcon}
|
|
53
|
+
strokeWidth="1.2"
|
|
54
|
+
strokeLinecap="round"
|
|
55
|
+
strokeLinejoin="round"
|
|
56
|
+
/>
|
|
57
|
+
</svg>
|
|
58
|
+
);
|
|
59
|
+
};
|
|
@@ -4,8 +4,9 @@ import React, {
|
|
|
4
4
|
forwardRef,
|
|
5
5
|
ReactNode,
|
|
6
6
|
useCallback,
|
|
7
|
+
useMemo,
|
|
7
8
|
} from "react";
|
|
8
|
-
import { cx } from "../utils/classNames";
|
|
9
|
+
import { cx, mergeConflictingClassNames } from "../utils/classNames";
|
|
9
10
|
import { Tooltip } from "./Tooltip";
|
|
10
11
|
|
|
11
12
|
type ButtonVariant =
|
|
@@ -61,6 +62,7 @@ export interface ButtonRootProps {
|
|
|
61
62
|
href?: string;
|
|
62
63
|
target?: string;
|
|
63
64
|
rel?: string;
|
|
65
|
+
download?: string;
|
|
64
66
|
}
|
|
65
67
|
|
|
66
68
|
export const Button = forwardRef(function Button(
|
|
@@ -82,28 +84,37 @@ export const Button = forwardRef(function Button(
|
|
|
82
84
|
}: ButtonRootProps,
|
|
83
85
|
forwardedRef: ForwardedRef<HTMLButtonElement>
|
|
84
86
|
) {
|
|
87
|
+
const baseClassName = cx(
|
|
88
|
+
"no-underline leading-[1] relative border-0 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",
|
|
89
|
+
disabled ? "opacity-25" : "",
|
|
90
|
+
!className?.includes("flex") ? "flex-none" : "",
|
|
91
|
+
active
|
|
92
|
+
? "bg-primary text-white hover:bg-primary-light active:bg-primary"
|
|
93
|
+
: variantStyles[variant],
|
|
94
|
+
sizeStyles[
|
|
95
|
+
variant === "thin"
|
|
96
|
+
? "thin"
|
|
97
|
+
: variant === "floating" && size !== "small"
|
|
98
|
+
? "floating"
|
|
99
|
+
: variant === "none"
|
|
100
|
+
? "none"
|
|
101
|
+
: size
|
|
102
|
+
]
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
const buttonClassName = useMemo(() => {
|
|
106
|
+
return className
|
|
107
|
+
? mergeConflictingClassNames([baseClassName, className], {
|
|
108
|
+
categories: ["position"],
|
|
109
|
+
})
|
|
110
|
+
: baseClassName;
|
|
111
|
+
}, [className, baseClassName]);
|
|
112
|
+
|
|
85
113
|
const buttonElement = (
|
|
86
114
|
<Component
|
|
87
115
|
ref={forwardedRef}
|
|
88
116
|
id={id}
|
|
89
|
-
className={
|
|
90
|
-
"no-underline leading-[1] relative border-0 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",
|
|
91
|
-
disabled ? "opacity-25" : "",
|
|
92
|
-
!className?.includes("flex") ? "flex-none" : "",
|
|
93
|
-
active
|
|
94
|
-
? "bg-primary text-white hover:bg-primary-light active:bg-primary"
|
|
95
|
-
: variantStyles[variant],
|
|
96
|
-
sizeStyles[
|
|
97
|
-
variant === "thin"
|
|
98
|
-
? "thin"
|
|
99
|
-
: variant === "floating" && size !== "small"
|
|
100
|
-
? "floating"
|
|
101
|
-
: variant === "none"
|
|
102
|
-
? "none"
|
|
103
|
-
: size
|
|
104
|
-
],
|
|
105
|
-
className
|
|
106
|
-
)}
|
|
117
|
+
className={buttonClassName}
|
|
107
118
|
style={style}
|
|
108
119
|
tabIndex={tabIndex}
|
|
109
120
|
disabled={disabled}
|
package/src/components/Chip.tsx
CHANGED
|
@@ -83,6 +83,7 @@ export interface ChipProps {
|
|
|
83
83
|
style?: React.CSSProperties;
|
|
84
84
|
tabIndex?: number;
|
|
85
85
|
role?: string;
|
|
86
|
+
disabled?: boolean;
|
|
86
87
|
}
|
|
87
88
|
|
|
88
89
|
export const Chip = memo(
|
|
@@ -103,6 +104,7 @@ export const Chip = memo(
|
|
|
103
104
|
onAdd,
|
|
104
105
|
onHoverDeleteChange,
|
|
105
106
|
className,
|
|
107
|
+
disabled,
|
|
106
108
|
...rest
|
|
107
109
|
}: ChipProps,
|
|
108
110
|
forwardedRef: React.ForwardedRef<HTMLSpanElement>
|
|
@@ -128,6 +130,7 @@ export const Chip = memo(
|
|
|
128
130
|
monospace && "font-mono",
|
|
129
131
|
variantClasses,
|
|
130
132
|
isInteractive && "cursor-pointer hover:opacity-85",
|
|
133
|
+
disabled && "opacity-50",
|
|
131
134
|
className
|
|
132
135
|
);
|
|
133
136
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { forwardRefGeneric } from "@noya-app/react-utils";
|
|
1
2
|
import React from "react";
|
|
2
|
-
import {
|
|
3
|
-
import { Grid, GridViewSize } from "../components/Grid";
|
|
3
|
+
import { Grid } from "../components/Grid";
|
|
4
4
|
import { MenuItem } from "../components/internal/Menu";
|
|
5
5
|
import {
|
|
6
6
|
ListView,
|
|
@@ -20,6 +20,7 @@ export type CollectionRef = {
|
|
|
20
20
|
export type CollectionThumbnailProps<T> = {
|
|
21
21
|
item: T;
|
|
22
22
|
selected: boolean;
|
|
23
|
+
size?: CollectionItemSize;
|
|
23
24
|
};
|
|
24
25
|
|
|
25
26
|
export type CollectionRenderActionProps<T> = {
|
|
@@ -51,6 +52,7 @@ export interface CollectionProps<T, M extends string = string> {
|
|
|
51
52
|
renderThumbnail?: ({
|
|
52
53
|
item,
|
|
53
54
|
selected,
|
|
55
|
+
size,
|
|
54
56
|
}: CollectionThumbnailProps<T>) => React.ReactNode;
|
|
55
57
|
renderAction?:
|
|
56
58
|
| "menu"
|
|
@@ -66,7 +68,7 @@ export interface CollectionProps<T, M extends string = string> {
|
|
|
66
68
|
/** Position of the detail content. Defaults to 'end'. */
|
|
67
69
|
detailPosition?: "end" | "below";
|
|
68
70
|
/** Size of the list items. Defaults to 'medium'. */
|
|
69
|
-
size?:
|
|
71
|
+
size?: CollectionItemSize;
|
|
70
72
|
/** Size of the thumbnail. Defaults to 'auto', which will be based on the size prop. */
|
|
71
73
|
thumbnailSize?: CollectionThumbnailSize;
|
|
72
74
|
/** For testing: Override the hover state with a specific item ID */
|
|
@@ -105,3 +107,10 @@ export const Collection = forwardRefGeneric(function Collection<
|
|
|
105
107
|
<List ref={ref} {...rest} />
|
|
106
108
|
);
|
|
107
109
|
});
|
|
110
|
+
export type CollectionItemSize =
|
|
111
|
+
| "xxs"
|
|
112
|
+
| "xs"
|
|
113
|
+
| "small"
|
|
114
|
+
| "medium"
|
|
115
|
+
| "large"
|
|
116
|
+
| "xl";
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React, { forwardRef } from "react";
|
|
2
|
+
|
|
3
|
+
export type ColorSwatchSize = "xsmall" | "small" | "medium" | "large";
|
|
4
|
+
|
|
5
|
+
export const colorSwatchSizeMap = {
|
|
6
|
+
xsmall: 21,
|
|
7
|
+
small: 27,
|
|
8
|
+
medium: 36,
|
|
9
|
+
large: 48,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
type ColorSwatchProps = {
|
|
13
|
+
color: string;
|
|
14
|
+
size?: ColorSwatchSize;
|
|
15
|
+
checked?: boolean;
|
|
16
|
+
} & React.ButtonHTMLAttributes<HTMLButtonElement>;
|
|
17
|
+
|
|
18
|
+
export const ColorSwatch = forwardRef(function ColorSwatch(
|
|
19
|
+
{ color, size = "small", checked, style, ...props }: ColorSwatchProps,
|
|
20
|
+
ref: React.ForwardedRef<HTMLButtonElement>
|
|
21
|
+
) {
|
|
22
|
+
const sizePx = colorSwatchSizeMap[size];
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<button
|
|
26
|
+
{...props}
|
|
27
|
+
ref={ref}
|
|
28
|
+
style={{
|
|
29
|
+
background: color,
|
|
30
|
+
width: sizePx,
|
|
31
|
+
height: sizePx,
|
|
32
|
+
borderRadius: "4px",
|
|
33
|
+
outline: checked
|
|
34
|
+
? "2px solid rgba(0,0,0,0.2)"
|
|
35
|
+
: "1px solid rgba(0,0,0,0.1)",
|
|
36
|
+
outlineOffset: -1,
|
|
37
|
+
boxShadow: checked ? `inset 0 0 0 2px rgba(0,0,0,0.2)` : undefined,
|
|
38
|
+
...style,
|
|
39
|
+
}}
|
|
40
|
+
/>
|
|
41
|
+
);
|
|
42
|
+
});
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group";
|
|
2
|
+
import React, { useMemo } from "react";
|
|
3
|
+
import { cx } from "../utils/classNames";
|
|
4
|
+
import {
|
|
5
|
+
ColorSwatch,
|
|
6
|
+
ColorSwatchSize,
|
|
7
|
+
colorSwatchSizeMap,
|
|
8
|
+
} from "./ColorSwatch";
|
|
9
|
+
|
|
10
|
+
export type TokenValue = string | { ref: string };
|
|
11
|
+
|
|
12
|
+
type ColorSwatchControlProps = {
|
|
13
|
+
options: TokenValue[];
|
|
14
|
+
value?: TokenValue;
|
|
15
|
+
/** @default "small" */
|
|
16
|
+
size?: ColorSwatchSize;
|
|
17
|
+
readOnly?: boolean;
|
|
18
|
+
onValueChange?: (value: TokenValue) => void;
|
|
19
|
+
onFocus?: React.FocusEventHandler<HTMLButtonElement>;
|
|
20
|
+
onBlur?: React.FocusEventHandler<HTMLButtonElement>;
|
|
21
|
+
className?: string;
|
|
22
|
+
id?: string;
|
|
23
|
+
style?: React.CSSProperties;
|
|
24
|
+
disabled?: boolean;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export function ColorSwatchControl(props: ColorSwatchControlProps) {
|
|
28
|
+
const {
|
|
29
|
+
options,
|
|
30
|
+
size = "small",
|
|
31
|
+
readOnly,
|
|
32
|
+
value,
|
|
33
|
+
onValueChange,
|
|
34
|
+
onFocus,
|
|
35
|
+
onBlur,
|
|
36
|
+
disabled,
|
|
37
|
+
className,
|
|
38
|
+
id,
|
|
39
|
+
style,
|
|
40
|
+
} = props;
|
|
41
|
+
const styles = useMemo(() => {
|
|
42
|
+
return {
|
|
43
|
+
display: "grid",
|
|
44
|
+
gridTemplateColumns: `repeat(auto-fill, minmax(${colorSwatchSizeMap[size]}px, 1fr))`,
|
|
45
|
+
gap: "6px",
|
|
46
|
+
...style,
|
|
47
|
+
};
|
|
48
|
+
}, [size, style]);
|
|
49
|
+
|
|
50
|
+
const content = (
|
|
51
|
+
<div className={className} id={id} style={styles}>
|
|
52
|
+
{options.map((option) => {
|
|
53
|
+
const item = (
|
|
54
|
+
<ColorSwatch
|
|
55
|
+
key={option as string}
|
|
56
|
+
color={option as string}
|
|
57
|
+
size={size}
|
|
58
|
+
onFocus={onFocus}
|
|
59
|
+
onBlur={onBlur}
|
|
60
|
+
disabled={disabled}
|
|
61
|
+
// TODO: decide on "checked" visual treatment
|
|
62
|
+
className={cx(readOnly ? "cursor-default" : "cursor-pointer")}
|
|
63
|
+
checked={value === option}
|
|
64
|
+
/>
|
|
65
|
+
);
|
|
66
|
+
return readOnly ? (
|
|
67
|
+
item
|
|
68
|
+
) : (
|
|
69
|
+
<ToggleGroupPrimitive.Item
|
|
70
|
+
asChild
|
|
71
|
+
value={option as string}
|
|
72
|
+
key={option as string}
|
|
73
|
+
>
|
|
74
|
+
{item}
|
|
75
|
+
</ToggleGroupPrimitive.Item>
|
|
76
|
+
);
|
|
77
|
+
})}
|
|
78
|
+
</div>
|
|
79
|
+
);
|
|
80
|
+
return readOnly ? (
|
|
81
|
+
content
|
|
82
|
+
) : (
|
|
83
|
+
<ToggleGroupPrimitive.Root
|
|
84
|
+
type="single"
|
|
85
|
+
value={value as string}
|
|
86
|
+
onValueChange={onValueChange}
|
|
87
|
+
className="w-full"
|
|
88
|
+
>
|
|
89
|
+
{content}
|
|
90
|
+
</ToggleGroupPrimitive.Root>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
@@ -25,6 +25,8 @@ interface ComboboxMenuProps<T extends string> {
|
|
|
25
25
|
listSize: Size;
|
|
26
26
|
style?: React.CSSProperties;
|
|
27
27
|
indented?: boolean;
|
|
28
|
+
/** @default right */
|
|
29
|
+
iconPosition?: "left" | "right";
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
export const ComboboxMenu = memoGeneric(
|
|
@@ -37,6 +39,7 @@ export const ComboboxMenu = memoGeneric(
|
|
|
37
39
|
listSize,
|
|
38
40
|
style,
|
|
39
41
|
indented,
|
|
42
|
+
iconPosition = "right",
|
|
40
43
|
}: ComboboxMenuProps<T>,
|
|
41
44
|
forwardedRef: ForwardedRef<IVirtualizedList>
|
|
42
45
|
) {
|
|
@@ -100,6 +103,12 @@ export const ComboboxMenu = memoGeneric(
|
|
|
100
103
|
size={CHECKBOX_WIDTH - CHECKBOX_RIGHT_INSET}
|
|
101
104
|
/>
|
|
102
105
|
) : null}
|
|
106
|
+
{iconPosition === "left" && item.icon && (
|
|
107
|
+
<>
|
|
108
|
+
{renderIcon(item.icon)}
|
|
109
|
+
<Spacer.Horizontal size={8} />
|
|
110
|
+
</>
|
|
111
|
+
)}
|
|
103
112
|
{tokens.map((token, j) => (
|
|
104
113
|
<span
|
|
105
114
|
key={`${item.value}-token-${j}`}
|
|
@@ -112,7 +121,7 @@ export const ComboboxMenu = memoGeneric(
|
|
|
112
121
|
</span>
|
|
113
122
|
))}
|
|
114
123
|
</div>
|
|
115
|
-
{(item.shortcut || item.icon) && (
|
|
124
|
+
{(item.shortcut || (item.icon && iconPosition === "right")) && (
|
|
116
125
|
<>
|
|
117
126
|
{item.shortcut ? (
|
|
118
127
|
<KeyboardShortcut shortcut={item.shortcut} />
|
|
@@ -35,7 +35,7 @@ const StyledContent = forwardRef<
|
|
|
35
35
|
w-[90vw] max-w-[450px] max-h-[85vh] p-dialog-padding rounded-[2px]
|
|
36
36
|
font-sans text-heading5 font-normal leading-[19px] text-text-muted
|
|
37
37
|
bg-popover-background pointer-events-all z-[1000] focus:outline-none
|
|
38
|
-
shadow-
|
|
38
|
+
shadow-dialog-shadow
|
|
39
39
|
flex flex-col
|
|
40
40
|
`,
|
|
41
41
|
className
|
|
@@ -11,7 +11,7 @@ const FillButton = forwardRef<
|
|
|
11
11
|
<button
|
|
12
12
|
ref={ref}
|
|
13
13
|
className={cx(
|
|
14
|
-
`outline-none p-0 w-[50px] h-input-height rounded overflow-hidden border-none shadow-[0_0_0_1px_var(--n-divider)_inset] bg-transparent relative focus:shadow-
|
|
14
|
+
`outline-none p-0 w-[50px] h-input-height rounded overflow-hidden border-none shadow-[0_0_0_1px_var(--n-divider)_inset] bg-transparent relative focus:shadow-active-input `,
|
|
15
15
|
className
|
|
16
16
|
)}
|
|
17
17
|
{...props}
|
package/src/components/Grid.tsx
CHANGED
|
@@ -1,23 +1,25 @@
|
|
|
1
|
-
import { useFileDropTarget } from "@noya-app/react-utils";
|
|
2
|
-
import React, { useImperativeHandle, useRef, useState } from "react";
|
|
3
1
|
import {
|
|
4
2
|
forwardRefGeneric,
|
|
5
3
|
memoGeneric,
|
|
6
|
-
|
|
4
|
+
useFileDropTarget,
|
|
5
|
+
} from "@noya-app/react-utils";
|
|
6
|
+
import React, { useImperativeHandle, useRef, useState } from "react";
|
|
7
7
|
import { cx } from "../utils/classNames";
|
|
8
8
|
import { updateSelection } from "../utils/selection";
|
|
9
9
|
import { ActionMenu } from "./ActionMenu";
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
CollectionItemSize,
|
|
12
|
+
CollectionProps,
|
|
13
|
+
CollectionRef,
|
|
14
|
+
} from "./Collection";
|
|
11
15
|
import { EditableText } from "./EditableText";
|
|
12
16
|
import { GridView } from "./GridView";
|
|
13
17
|
import { ListView } from "./ListView";
|
|
14
18
|
|
|
15
|
-
export
|
|
16
|
-
|
|
17
|
-
export const getGridSize = (size: GridViewSize) => {
|
|
19
|
+
export const getGridSize = (size: CollectionItemSize) => {
|
|
18
20
|
// Define size ranges that allow items to grow/shrink within bounds
|
|
19
21
|
const sizes: Record<
|
|
20
|
-
Exclude<
|
|
22
|
+
Exclude<CollectionItemSize, number>,
|
|
21
23
|
{
|
|
22
24
|
minColumnWidth: string;
|
|
23
25
|
gap: number;
|
|
@@ -152,7 +154,10 @@ export const Grid = memoGeneric(
|
|
|
152
154
|
scrollable={items.length > 0 && scrollable}
|
|
153
155
|
contentClassName={cx(items.length === 0 && "flex flex-1")}
|
|
154
156
|
gap={gap}
|
|
155
|
-
className={cx(
|
|
157
|
+
className={cx(
|
|
158
|
+
isDropTargetActive && "bg-selected-list-item-background",
|
|
159
|
+
className
|
|
160
|
+
)}
|
|
156
161
|
{...dropTargetProps}
|
|
157
162
|
ref={fileDropTargetRef}
|
|
158
163
|
>
|
|
@@ -173,6 +178,7 @@ export const Grid = memoGeneric(
|
|
|
173
178
|
const thumbnail = renderThumbnail?.({
|
|
174
179
|
item,
|
|
175
180
|
selected: isSelected,
|
|
181
|
+
size,
|
|
176
182
|
});
|
|
177
183
|
const onOpenChange = (open: boolean) => {
|
|
178
184
|
setDropdownOpenId(open ? id : undefined);
|
|
@@ -229,7 +235,7 @@ export const Grid = memoGeneric(
|
|
|
229
235
|
<span
|
|
230
236
|
{...props}
|
|
231
237
|
className={cx(
|
|
232
|
-
isSelected && "text-
|
|
238
|
+
isSelected && "text-selected-list-item-text",
|
|
233
239
|
"truncate select-none"
|
|
234
240
|
)}
|
|
235
241
|
/>
|
|
@@ -237,7 +243,11 @@ export const Grid = memoGeneric(
|
|
|
237
243
|
</EditableText>
|
|
238
244
|
}
|
|
239
245
|
subtitle={
|
|
240
|
-
<span
|
|
246
|
+
<span
|
|
247
|
+
className={cx(
|
|
248
|
+
isSelected && "text-selected-list-item-text"
|
|
249
|
+
)}
|
|
250
|
+
>
|
|
241
251
|
{renderDetail?.(item, isSelected)}
|
|
242
252
|
</span>
|
|
243
253
|
}
|
|
@@ -271,7 +281,7 @@ export const Grid = memoGeneric(
|
|
|
271
281
|
<div
|
|
272
282
|
className={cx(
|
|
273
283
|
"rounded overflow-hidden flex-none flex w-full",
|
|
274
|
-
isSelected && "text-
|
|
284
|
+
isSelected && "text-selected-list-item-text"
|
|
275
285
|
)}
|
|
276
286
|
tabIndex={-1}
|
|
277
287
|
>
|
|
@@ -166,7 +166,7 @@ const GridViewItem = forwardRefGeneric(function GridViewItem<
|
|
|
166
166
|
"flex flex-col relative rounded p-2 -m-2 text-text",
|
|
167
167
|
"cursor-pointer",
|
|
168
168
|
"active:opacity-70",
|
|
169
|
-
selected && "bg-
|
|
169
|
+
selected && "bg-selected-list-item-background",
|
|
170
170
|
hovered && "bg-list-view-hover-background",
|
|
171
171
|
disabled && "opacity-50",
|
|
172
172
|
showInsideDropIndicator && "ring-2 ring-primary ring-inset",
|