@noya-app/noya-designsystem 0.1.50 → 0.1.51
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 +8 -0
- package/dist/index.css +1 -1
- package/dist/index.d.mts +36 -197
- package/dist/index.d.ts +36 -197
- package/dist/index.js +1258 -10127
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4458 -13349
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
- package/src/components/ActionMenu.tsx +4 -2
- package/src/components/Collection.tsx +12 -3
- package/src/components/ComboboxMenu.tsx +10 -1
- package/src/components/Grid.tsx +11 -8
- package/src/components/List.tsx +26 -20
- package/src/components/MediaThumbnail.tsx +20 -6
- package/src/components/SearchCompletionMenu.tsx +12 -12
- package/src/components/SegmentedControl.tsx +1 -1
- package/src/components/Toolbar.tsx +22 -10
- package/src/components/file-explorer/FileExplorerLayout.tsx +12 -2
- package/src/components/internal/TextInput.tsx +7 -2
- package/src/index.css +7 -0
- package/src/theme/index.ts +1 -1
- package/src/utils/classNames.ts +1 -1
- package/src/utils/combobox.ts +18 -13
- package/tailwind.config.ts +2 -239
- package/tailwind.d.ts +1 -1
- package/tsup.config.ts +0 -3
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.51",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"module": "./dist/index.mjs",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"@noya-app/noya-geometry": "0.1.10",
|
|
28
28
|
"@noya-app/noya-icons": "0.1.7",
|
|
29
29
|
"@noya-app/noya-keymap": "0.1.3",
|
|
30
|
+
"@noya-app/noya-tailwind-config": "0.1.2",
|
|
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",
|
|
@@ -47,17 +48,16 @@
|
|
|
47
48
|
"kiwi.js": "^1.1.3",
|
|
48
49
|
"react-resizable-panels": "2.0.22",
|
|
49
50
|
"react-window": "^1.8.8",
|
|
50
|
-
"vscode-fuzzy-scorer": "^0.0.4"
|
|
51
|
+
"vscode-fuzzy-scorer": "^0.0.4",
|
|
52
|
+
"react-virtualized": "9.22.6"
|
|
51
53
|
},
|
|
52
54
|
"devDependencies": {
|
|
53
55
|
"@tailwindcss/container-queries": "^0.1.1",
|
|
54
56
|
"@types/react": "*",
|
|
55
57
|
"@types/react-dom": "*",
|
|
56
|
-
"@types/react-virtualized": "^9.21.
|
|
58
|
+
"@types/react-virtualized": "^9.21.30",
|
|
57
59
|
"@types/react-window": "^1.8.5",
|
|
58
|
-
"esbuild-plugin-react-virtualized": "1.0.4",
|
|
59
60
|
"esbuild-plugin-tailwindcss": "^1.2.1",
|
|
60
|
-
"react-virtualized": "9.22.5",
|
|
61
61
|
"tailwind-merge": "^2.5.4",
|
|
62
62
|
"tailwindcss": "^3.4.14"
|
|
63
63
|
},
|
|
@@ -12,6 +12,7 @@ type ActionMenuProps<TMenu extends string> = {
|
|
|
12
12
|
onOpenChange: (open: boolean) => void;
|
|
13
13
|
className?: string;
|
|
14
14
|
style?: React.CSSProperties;
|
|
15
|
+
variant?: "normal" | "bare";
|
|
15
16
|
};
|
|
16
17
|
|
|
17
18
|
export const ActionMenu = memoGeneric(function ActionMenu<
|
|
@@ -23,16 +24,17 @@ export const ActionMenu = memoGeneric(function ActionMenu<
|
|
|
23
24
|
onOpenChange,
|
|
24
25
|
className,
|
|
25
26
|
style,
|
|
27
|
+
variant = "normal",
|
|
26
28
|
}: ActionMenuProps<TMenu>) {
|
|
27
29
|
const internalStyle = useMemo(() => {
|
|
28
30
|
return {
|
|
29
31
|
backgroundColor: selected
|
|
30
32
|
? cssVars.colors.primaryPastel
|
|
31
33
|
: cssVars.colors.inputBackground,
|
|
32
|
-
padding: "
|
|
34
|
+
padding: variant === "bare" ? 0 : 4,
|
|
33
35
|
...style,
|
|
34
36
|
};
|
|
35
|
-
}, [selected, style]);
|
|
37
|
+
}, [selected, style, variant]);
|
|
36
38
|
|
|
37
39
|
return (
|
|
38
40
|
<DropdownMenu
|
|
@@ -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";
|
|
@@ -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} />
|
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;
|
|
@@ -173,6 +175,7 @@ export const Grid = memoGeneric(
|
|
|
173
175
|
const thumbnail = renderThumbnail?.({
|
|
174
176
|
item,
|
|
175
177
|
selected: isSelected,
|
|
178
|
+
size,
|
|
176
179
|
});
|
|
177
180
|
const onOpenChange = (open: boolean) => {
|
|
178
181
|
setDropdownOpenId(open ? id : undefined);
|
package/src/components/List.tsx
CHANGED
|
@@ -8,8 +8,11 @@ import { cssVars } from "../theme";
|
|
|
8
8
|
import { cx } from "../utils/classNames";
|
|
9
9
|
import { updateSelection } from "../utils/selection";
|
|
10
10
|
import { ActionMenu } from "./ActionMenu";
|
|
11
|
-
import {
|
|
12
|
-
|
|
11
|
+
import {
|
|
12
|
+
CollectionItemSize,
|
|
13
|
+
CollectionProps,
|
|
14
|
+
CollectionRef,
|
|
15
|
+
} from "./Collection";
|
|
13
16
|
import { ListView, ListViewItemInfo } from "./ListView";
|
|
14
17
|
import { TreeView } from "./TreeView";
|
|
15
18
|
|
|
@@ -149,6 +152,7 @@ export const List = memoGeneric(
|
|
|
149
152
|
const thumbnail = renderThumbnail?.({
|
|
150
153
|
item,
|
|
151
154
|
selected: isSelected,
|
|
155
|
+
size,
|
|
152
156
|
});
|
|
153
157
|
const onOpenChange = (open: boolean) => {
|
|
154
158
|
setDropdownOpenId(open ? id : undefined);
|
|
@@ -169,6 +173,7 @@ export const List = memoGeneric(
|
|
|
169
173
|
onSelect={(action) => handleMenuAction(action, item)}
|
|
170
174
|
selected={isSelected}
|
|
171
175
|
onOpenChange={onOpenChange}
|
|
176
|
+
variant="bare"
|
|
172
177
|
/>
|
|
173
178
|
));
|
|
174
179
|
|
|
@@ -238,9 +243,10 @@ export const List = memoGeneric(
|
|
|
238
243
|
{thumbnail && (
|
|
239
244
|
<div
|
|
240
245
|
className={cx(
|
|
241
|
-
"
|
|
246
|
+
"overflow-hidden flex-none flex items-center justify-center",
|
|
242
247
|
thumbnailSize === "auto" && thumbnailSizeMap[size],
|
|
243
|
-
isSelected && "text-primary"
|
|
248
|
+
isSelected && "text-primary",
|
|
249
|
+
size === "small" ? "rounded-sm" : "rounded"
|
|
244
250
|
)}
|
|
245
251
|
tabIndex={-1}
|
|
246
252
|
>
|
|
@@ -316,37 +322,37 @@ const DetailContainer = memo(function DetailContainer({
|
|
|
316
322
|
);
|
|
317
323
|
});
|
|
318
324
|
|
|
319
|
-
const pyMap: Record<
|
|
320
|
-
xxs: "py-
|
|
321
|
-
xs: "py-
|
|
322
|
-
small: "py-
|
|
325
|
+
const pyMap: Record<CollectionItemSize, string> = {
|
|
326
|
+
xxs: "py-0.5",
|
|
327
|
+
xs: "py-0.5",
|
|
328
|
+
small: "py-0.5",
|
|
323
329
|
medium: "py-1",
|
|
324
330
|
large: "py-2",
|
|
325
331
|
xl: "py-3",
|
|
326
332
|
};
|
|
327
333
|
|
|
328
|
-
const thumbnailSizeMap: Record<
|
|
329
|
-
xxs: "w-
|
|
330
|
-
xs: "w-
|
|
331
|
-
small: "w-
|
|
334
|
+
const thumbnailSizeMap: Record<CollectionItemSize, string> = {
|
|
335
|
+
xxs: "w-5 h-5",
|
|
336
|
+
xs: "w-5 h-5",
|
|
337
|
+
small: "w-5 h-5",
|
|
332
338
|
medium: "w-8 h-8",
|
|
333
339
|
large: "w-16 h-16",
|
|
334
340
|
xl: "w-24 h-24",
|
|
335
341
|
};
|
|
336
342
|
|
|
337
|
-
const rowGapMap: Record<
|
|
338
|
-
xxs: "gap-
|
|
339
|
-
xs: "gap-
|
|
340
|
-
small: "gap-
|
|
343
|
+
const rowGapMap: Record<CollectionItemSize, string> = {
|
|
344
|
+
xxs: "gap-2",
|
|
345
|
+
xs: "gap-2",
|
|
346
|
+
small: "gap-2",
|
|
341
347
|
medium: "gap-3",
|
|
342
348
|
large: "gap-3",
|
|
343
349
|
xl: "gap-4",
|
|
344
350
|
};
|
|
345
351
|
|
|
346
|
-
const fontStyleMap: Record<
|
|
347
|
-
xxs: "font-medium",
|
|
348
|
-
xs: "font-medium",
|
|
349
|
-
small: "font-medium",
|
|
352
|
+
const fontStyleMap: Record<CollectionItemSize, string> = {
|
|
353
|
+
xxs: "font-medium text-list-small",
|
|
354
|
+
xs: "font-medium text-list-small",
|
|
355
|
+
small: "font-medium text-list-small",
|
|
350
356
|
medium: "font-medium",
|
|
351
357
|
large: "font-medium",
|
|
352
358
|
xl: "font-medium text-heading4 text-text",
|
|
@@ -2,6 +2,7 @@ import { ImageIcon, SpeakerLoudIcon, VideoIcon } from "@noya-app/noya-icons";
|
|
|
2
2
|
import React, { memo, useMemo } from "react";
|
|
3
3
|
import { cssVars } from "../theme";
|
|
4
4
|
import { cx } from "../utils/classNames";
|
|
5
|
+
import { CollectionItemSize } from "./Collection";
|
|
5
6
|
import { IconName, Icons } from "./Icons";
|
|
6
7
|
|
|
7
8
|
type ColorScheme = "primary" | "secondary" | "icon" | "warning";
|
|
@@ -29,6 +30,7 @@ type MediaThumbnailProps = {
|
|
|
29
30
|
* If provided, use this icon instead of the default one for the asset type
|
|
30
31
|
*/
|
|
31
32
|
iconName?: IconName;
|
|
33
|
+
size?: CollectionItemSize;
|
|
32
34
|
};
|
|
33
35
|
|
|
34
36
|
export const getThumbnailColors = (
|
|
@@ -67,11 +69,6 @@ export const getThumbnailColors = (
|
|
|
67
69
|
}
|
|
68
70
|
};
|
|
69
71
|
|
|
70
|
-
const iconStyles = {
|
|
71
|
-
width: "max(15px, 20%)",
|
|
72
|
-
height: "max(15px, 20%)",
|
|
73
|
-
};
|
|
74
|
-
|
|
75
72
|
export const MediaThumbnail = memo(function MediaThumbnail({
|
|
76
73
|
contentType: contentTypeProp,
|
|
77
74
|
selected = false,
|
|
@@ -79,12 +76,20 @@ export const MediaThumbnail = memo(function MediaThumbnail({
|
|
|
79
76
|
colorScheme = "icon",
|
|
80
77
|
url,
|
|
81
78
|
iconName = "FileIcon",
|
|
79
|
+
size = "medium",
|
|
82
80
|
}: MediaThumbnailProps) {
|
|
83
81
|
const { icon: iconColor, background: backgroundColor } = getThumbnailColors(
|
|
84
82
|
colorScheme,
|
|
85
83
|
selected
|
|
86
84
|
);
|
|
87
85
|
const contentType = getAssetType(contentTypeProp);
|
|
86
|
+
const iconStyles = useMemo(
|
|
87
|
+
() => ({
|
|
88
|
+
width: iconSizeMap[size],
|
|
89
|
+
height: iconSizeMap[size],
|
|
90
|
+
}),
|
|
91
|
+
[size]
|
|
92
|
+
);
|
|
88
93
|
|
|
89
94
|
const content = useMemo(() => {
|
|
90
95
|
switch (contentType) {
|
|
@@ -109,7 +114,7 @@ export const MediaThumbnail = memo(function MediaThumbnail({
|
|
|
109
114
|
const Icon = Icons[iconName];
|
|
110
115
|
return <Icon color={iconColor} style={iconStyles} />;
|
|
111
116
|
}
|
|
112
|
-
}, [contentType, url, iconColor, iconName]);
|
|
117
|
+
}, [contentType, url, iconColor, iconStyles, iconName]);
|
|
113
118
|
|
|
114
119
|
return (
|
|
115
120
|
<div
|
|
@@ -123,3 +128,12 @@ export const MediaThumbnail = memo(function MediaThumbnail({
|
|
|
123
128
|
</div>
|
|
124
129
|
);
|
|
125
130
|
});
|
|
131
|
+
|
|
132
|
+
const iconSizeMap: Record<CollectionItemSize, number | string> = {
|
|
133
|
+
xxs: 12,
|
|
134
|
+
xs: 12,
|
|
135
|
+
small: 12,
|
|
136
|
+
medium: "max(15px, 20%)",
|
|
137
|
+
large: "max(15px, 20%)",
|
|
138
|
+
xl: "max(15px, 20%)",
|
|
139
|
+
};
|
|
@@ -119,21 +119,21 @@ export const SearchCompletionMenu = forwardRef(function SearchCompletionMenu(
|
|
|
119
119
|
(event: React.KeyboardEvent<HTMLInputElement>) => {
|
|
120
120
|
handleKeyboardEvent(event.nativeEvent, getCurrentPlatform(navigator), {
|
|
121
121
|
ArrowUp: () => {
|
|
122
|
-
const nextIndex = getNextIndex(
|
|
123
|
-
results,
|
|
124
|
-
index,
|
|
125
|
-
"previous",
|
|
126
|
-
(item) => item.disabled ?? false
|
|
127
|
-
);
|
|
122
|
+
const nextIndex = getNextIndex({
|
|
123
|
+
items: results,
|
|
124
|
+
currentIndex: index,
|
|
125
|
+
direction: "previous",
|
|
126
|
+
isDisabled: (item) => item.disabled ?? false,
|
|
127
|
+
});
|
|
128
128
|
setIndex(nextIndex);
|
|
129
129
|
},
|
|
130
130
|
ArrowDown: () => {
|
|
131
|
-
const nextIndex = getNextIndex(
|
|
132
|
-
results,
|
|
133
|
-
index,
|
|
134
|
-
"next",
|
|
135
|
-
(item) => item.disabled ?? false
|
|
136
|
-
);
|
|
131
|
+
const nextIndex = getNextIndex({
|
|
132
|
+
items: results,
|
|
133
|
+
currentIndex: index,
|
|
134
|
+
direction: "next",
|
|
135
|
+
isDisabled: (item) => item.disabled ?? false,
|
|
136
|
+
});
|
|
137
137
|
setIndex(nextIndex);
|
|
138
138
|
},
|
|
139
139
|
Tab: () => selectAndClose(results[index]!),
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { memoGeneric } from "@noya-app/react-utils";
|
|
1
2
|
import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group";
|
|
2
3
|
import React, {
|
|
3
4
|
createContext,
|
|
@@ -7,7 +8,6 @@ import React, {
|
|
|
7
8
|
useContext,
|
|
8
9
|
useMemo,
|
|
9
10
|
} from "react";
|
|
10
|
-
import { memoGeneric } from "../../../noya-react-utils/src/utils/reactGenerics";
|
|
11
11
|
import { useLabel } from "../hooks/useLabel";
|
|
12
12
|
import { cx } from "../utils/classNames";
|
|
13
13
|
import { renderIcon } from "./Icons";
|
|
@@ -2,8 +2,11 @@ import { DropdownChevronIcon } from "@noya-app/noya-icons";
|
|
|
2
2
|
import { useKeyboardShortcuts } from "@noya-app/noya-keymap";
|
|
3
3
|
import React from "react";
|
|
4
4
|
|
|
5
|
+
import { memoGeneric } from "@noya-app/react-utils";
|
|
6
|
+
import { cssVars } from "../theme";
|
|
5
7
|
import { BaseToolbar } from "./BaseToolbar";
|
|
6
8
|
import { Button } from "./Button";
|
|
9
|
+
import { DividerVertical } from "./Divider";
|
|
7
10
|
import { DropdownMenu } from "./DropdownMenu";
|
|
8
11
|
import { renderIcon } from "./Icons";
|
|
9
12
|
import {
|
|
@@ -76,7 +79,11 @@ export function Toolbar<T extends string = string>({
|
|
|
76
79
|
);
|
|
77
80
|
}
|
|
78
81
|
|
|
79
|
-
|
|
82
|
+
const activeButtonStyle = {
|
|
83
|
+
backgroundColor: cssVars.colors.primaryPastel,
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export const ToolbarMenu = memoGeneric(function ToolbarMenu<T extends string>({
|
|
80
87
|
items,
|
|
81
88
|
onSelectMenuItem,
|
|
82
89
|
}: {
|
|
@@ -86,14 +93,18 @@ export function ToolbarMenu<T extends string>({
|
|
|
86
93
|
return (
|
|
87
94
|
<>
|
|
88
95
|
{items.map((item, i) => {
|
|
89
|
-
if (item.type === "separator") return null;
|
|
90
96
|
if (item.type === "sectionHeader") return null;
|
|
91
97
|
|
|
98
|
+
if (item.type === "separator") {
|
|
99
|
+
return <DividerVertical key={i} overflow={4} />;
|
|
100
|
+
}
|
|
101
|
+
|
|
92
102
|
if (isSelectableMenuItem(item)) {
|
|
93
103
|
return (
|
|
94
104
|
<Button
|
|
95
105
|
key={i}
|
|
96
106
|
disabled={item.disabled}
|
|
107
|
+
style={item.checked ? activeButtonStyle : undefined}
|
|
97
108
|
onClick={() => {
|
|
98
109
|
if (onSelectMenuItem && item.value) {
|
|
99
110
|
onSelectMenuItem(item.value);
|
|
@@ -101,12 +112,8 @@ export function ToolbarMenu<T extends string>({
|
|
|
101
112
|
}}
|
|
102
113
|
>
|
|
103
114
|
{item.title}
|
|
104
|
-
{item.icon &&
|
|
105
|
-
|
|
106
|
-
<Spacer.Horizontal inline size={6} />
|
|
107
|
-
{renderIcon(item.icon)}
|
|
108
|
-
</>
|
|
109
|
-
)}
|
|
115
|
+
{item.title && item.icon && <Spacer.Horizontal inline size={6} />}
|
|
116
|
+
{item.icon && renderIcon(item.icon)}
|
|
110
117
|
</Button>
|
|
111
118
|
);
|
|
112
119
|
}
|
|
@@ -121,8 +128,13 @@ export function ToolbarMenu<T extends string>({
|
|
|
121
128
|
}
|
|
122
129
|
}}
|
|
123
130
|
>
|
|
124
|
-
<Button
|
|
131
|
+
<Button
|
|
132
|
+
disabled={item.disabled}
|
|
133
|
+
style={item.checked ? activeButtonStyle : undefined}
|
|
134
|
+
>
|
|
125
135
|
{item.title}
|
|
136
|
+
{item.title && item.icon && <Spacer.Horizontal inline size={6} />}
|
|
137
|
+
{item.icon && renderIcon(item.icon)}
|
|
126
138
|
<Spacer.Horizontal size={6} />
|
|
127
139
|
<DropdownChevronIcon />
|
|
128
140
|
</Button>
|
|
@@ -131,4 +143,4 @@ export function ToolbarMenu<T extends string>({
|
|
|
131
143
|
})}
|
|
132
144
|
</>
|
|
133
145
|
);
|
|
134
|
-
}
|
|
146
|
+
});
|
|
@@ -8,7 +8,12 @@ import {
|
|
|
8
8
|
import { forwardRefGeneric } from "@noya-app/react-utils";
|
|
9
9
|
import React from "react";
|
|
10
10
|
import { cx } from "../../utils/classNames";
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
Collection,
|
|
13
|
+
CollectionItemSize,
|
|
14
|
+
CollectionProps,
|
|
15
|
+
CollectionRef,
|
|
16
|
+
} from "../Collection";
|
|
12
17
|
|
|
13
18
|
export const FileExplorerLayout = ({
|
|
14
19
|
children,
|
|
@@ -53,13 +58,18 @@ export const FileExplorerCollection = forwardRefGeneric(
|
|
|
53
58
|
|
|
54
59
|
export const FileExplorerDetail = ({
|
|
55
60
|
selected,
|
|
61
|
+
size,
|
|
56
62
|
children,
|
|
57
63
|
}: {
|
|
58
64
|
selected: boolean;
|
|
59
65
|
children: React.ReactNode;
|
|
66
|
+
size?: CollectionItemSize;
|
|
60
67
|
}) => (
|
|
61
68
|
<span
|
|
62
|
-
className={cx(
|
|
69
|
+
className={cx(
|
|
70
|
+
size === "small" ? "text-list-small" : "text-sm",
|
|
71
|
+
selected ? "text-primary" : "text-text-muted"
|
|
72
|
+
)}
|
|
63
73
|
>
|
|
64
74
|
{children}
|
|
65
75
|
</span>
|
|
@@ -126,6 +126,8 @@ type SubmittableProps = Props & {
|
|
|
126
126
|
onSubmit: (value: string) => void;
|
|
127
127
|
allowSubmittingWithSameValue?: boolean;
|
|
128
128
|
submitAutomaticallyAfterDelay?: number;
|
|
129
|
+
/** @default true */
|
|
130
|
+
submitOnBlur?: boolean;
|
|
129
131
|
};
|
|
130
132
|
|
|
131
133
|
const SubmittableTextInput = forwardRef(function SubmittableTextInput(
|
|
@@ -138,6 +140,7 @@ const SubmittableTextInput = forwardRef(function SubmittableTextInput(
|
|
|
138
140
|
onFocusCapture,
|
|
139
141
|
allowSubmittingWithSameValue = false,
|
|
140
142
|
submitAutomaticallyAfterDelay,
|
|
143
|
+
submitOnBlur = true,
|
|
141
144
|
...rest
|
|
142
145
|
}: SubmittableProps,
|
|
143
146
|
forwardedRef: ForwardedRef<HTMLInputElement>
|
|
@@ -218,9 +221,11 @@ const SubmittableTextInput = forwardRef(function SubmittableTextInput(
|
|
|
218
221
|
|
|
219
222
|
onFocusChange?.(false);
|
|
220
223
|
|
|
221
|
-
|
|
224
|
+
if (submitOnBlur) {
|
|
225
|
+
handleSubmit();
|
|
226
|
+
}
|
|
222
227
|
},
|
|
223
|
-
[onBlur, onFocusChange, handleSubmit]
|
|
228
|
+
[onBlur, onFocusChange, handleSubmit, submitOnBlur]
|
|
224
229
|
);
|
|
225
230
|
|
|
226
231
|
const handleFocusCapture = useCallback(
|
package/src/index.css
CHANGED
|
@@ -82,6 +82,7 @@
|
|
|
82
82
|
--n-floating-button: rgb(248, 248, 250);
|
|
83
83
|
--n-block-border: rgb(184, 201, 218);
|
|
84
84
|
--n-block-highlight: rgb(255, 165, 0);
|
|
85
|
+
--n-visual-editor-line-placeholder-content: "Write or press / for commands";
|
|
85
86
|
}
|
|
86
87
|
|
|
87
88
|
[data-theme="dark"] {
|
|
@@ -125,3 +126,9 @@
|
|
|
125
126
|
--n-table-row-background: var(--n-sidebar-background);
|
|
126
127
|
--n-floating-button: #333333;
|
|
127
128
|
}
|
|
129
|
+
|
|
130
|
+
.visual-editor-line-placeholder::after {
|
|
131
|
+
content: var(--n-visual-editor-line-placeholder-content);
|
|
132
|
+
color: var(--n-text-disabled);
|
|
133
|
+
pointer-events: none;
|
|
134
|
+
}
|
package/src/theme/index.ts
CHANGED
package/src/utils/classNames.ts
CHANGED
package/src/utils/combobox.ts
CHANGED
|
@@ -168,12 +168,12 @@ export class ComboboxState<T extends string> {
|
|
|
168
168
|
|
|
169
169
|
moveSelection(direction: "up" | "down") {
|
|
170
170
|
const filteredItems = this.getFilteredItems();
|
|
171
|
-
this.selectedIndex = getNextIndex(
|
|
172
|
-
filteredItems,
|
|
173
|
-
this.selectedIndex,
|
|
174
|
-
direction === "down" ? "next" : "previous",
|
|
175
|
-
(item) => isNonSelectableMenuItem(item)
|
|
176
|
-
);
|
|
171
|
+
this.selectedIndex = getNextIndex({
|
|
172
|
+
items: filteredItems,
|
|
173
|
+
currentIndex: this.selectedIndex,
|
|
174
|
+
direction: direction === "down" ? "next" : "previous",
|
|
175
|
+
isDisabled: (item) => isNonSelectableMenuItem(item),
|
|
176
|
+
});
|
|
177
177
|
this.notifyChange();
|
|
178
178
|
}
|
|
179
179
|
|
|
@@ -257,7 +257,7 @@ export class ComboboxState<T extends string> {
|
|
|
257
257
|
}
|
|
258
258
|
}
|
|
259
259
|
|
|
260
|
-
function filterWithGroupedSections<T extends string>(
|
|
260
|
+
export function filterWithGroupedSections<T extends string>(
|
|
261
261
|
items: MenuItem<T>[],
|
|
262
262
|
query: string
|
|
263
263
|
): ScoredMenuItem<T>[] {
|
|
@@ -341,12 +341,17 @@ function filterWithGroupedSections<T extends string>(
|
|
|
341
341
|
return result;
|
|
342
342
|
}
|
|
343
343
|
|
|
344
|
-
export function getNextIndex<T>(
|
|
345
|
-
items
|
|
346
|
-
currentIndex
|
|
347
|
-
direction
|
|
348
|
-
isDisabled
|
|
349
|
-
|
|
344
|
+
export function getNextIndex<T>({
|
|
345
|
+
items,
|
|
346
|
+
currentIndex,
|
|
347
|
+
direction,
|
|
348
|
+
isDisabled,
|
|
349
|
+
}: {
|
|
350
|
+
items: T[];
|
|
351
|
+
currentIndex: number;
|
|
352
|
+
direction: "next" | "previous";
|
|
353
|
+
isDisabled: (item: T) => boolean;
|
|
354
|
+
}): number {
|
|
350
355
|
// Make sure the current index is within bounds
|
|
351
356
|
currentIndex =
|
|
352
357
|
currentIndex < 0
|