@noya-app/noya-designsystem 0.1.43 → 0.1.45
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 +12 -9
- package/CHANGELOG.md +15 -0
- package/dist/index.css +1 -1
- package/dist/index.d.mts +323 -80
- package/dist/index.d.ts +323 -80
- package/dist/index.js +2126 -1373
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2012 -1272
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/components/AnimatePresence.tsx +10 -1
- package/src/components/Avatar.tsx +2 -0
- package/src/components/Checkbox.tsx +6 -1
- package/src/components/Combobox.tsx +28 -14
- package/src/components/ComboboxMenu.tsx +30 -15
- package/src/components/CommandPalette.tsx +69 -0
- package/src/components/ContextMenu.tsx +33 -134
- package/src/components/DropdownMenu.tsx +47 -155
- package/src/components/Fade.tsx +62 -0
- package/src/components/InputField.tsx +109 -133
- package/src/components/Label.tsx +81 -7
- package/src/components/LabeledField.tsx +112 -0
- package/src/components/ListView.tsx +55 -52
- package/src/components/Popover.tsx +12 -1
- package/src/components/SearchCompletionMenu.tsx +206 -0
- package/src/components/SegmentedControl.tsx +5 -2
- package/src/components/SelectMenu.tsx +108 -124
- package/src/components/SidebarList.tsx +252 -0
- package/src/components/Slider.tsx +18 -26
- package/src/components/Text.tsx +1 -0
- package/src/components/TextArea.tsx +4 -1
- package/src/components/Toolbar.tsx +6 -2
- package/src/components/TreeView.tsx +3 -0
- package/src/components/WorkspaceLayout.tsx +38 -18
- package/src/components/internal/Menu.tsx +58 -10
- package/src/components/internal/MenuViewport.tsx +151 -0
- package/src/components/internal/SelectItem.tsx +111 -0
- package/src/hooks/useIndent.ts +12 -0
- package/src/hooks/useLabel.ts +51 -0
- package/src/hooks/usePreservePanelSize.tsx +50 -19
- package/src/index.tsx +12 -5
- package/src/utils/combobox.ts +4 -1
- package/src/utils/createSectionedMenu.ts +11 -8
- package/src/utils/selection.ts +36 -0
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { CheckIcon, ChevronRightIcon } from "@noya-app/noya-icons";
|
|
2
1
|
import { useKeyboardShortcuts } from "@noya-app/noya-keymap";
|
|
3
2
|
import { forwardRefGeneric, memoGeneric } from "@noya-app/react-utils";
|
|
4
3
|
import * as RadixDropdownMenu from "@radix-ui/react-dropdown-menu";
|
|
@@ -6,132 +5,46 @@ import React, {
|
|
|
6
5
|
ComponentProps,
|
|
7
6
|
ForwardedRef,
|
|
8
7
|
SyntheticEvent,
|
|
9
|
-
useCallback,
|
|
10
8
|
useMemo,
|
|
11
9
|
} from "react";
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
CHECKBOX_RIGHT_INSET,
|
|
17
|
-
CHECKBOX_WIDTH,
|
|
18
|
-
KeyboardShortcut,
|
|
19
|
-
SEPARATOR_ITEM,
|
|
20
|
-
getKeyboardShortcutsForMenuItems,
|
|
21
|
-
styles,
|
|
22
|
-
} from "./internal/Menu";
|
|
23
|
-
|
|
24
|
-
const DropdownMenuItem = memoGeneric(function ContextMenuItem<
|
|
25
|
-
T extends string,
|
|
26
|
-
>({
|
|
27
|
-
value,
|
|
28
|
-
children,
|
|
29
|
-
onSelect,
|
|
30
|
-
checked,
|
|
31
|
-
disabled,
|
|
32
|
-
indented,
|
|
33
|
-
icon,
|
|
34
|
-
items,
|
|
35
|
-
shortcut,
|
|
36
|
-
}: MenuItemProps<T>) {
|
|
37
|
-
const handleSelectItem = useCallback(() => {
|
|
38
|
-
if (!value) return;
|
|
39
|
-
|
|
40
|
-
onSelect(value);
|
|
41
|
-
}, [onSelect, value]);
|
|
42
|
-
|
|
43
|
-
if (checked) {
|
|
44
|
-
return (
|
|
45
|
-
<RadixDropdownMenu.CheckboxItem
|
|
46
|
-
checked={checked}
|
|
47
|
-
disabled={disabled}
|
|
48
|
-
onSelect={handleSelectItem}
|
|
49
|
-
className={styles.itemStyle({ disabled })}
|
|
50
|
-
>
|
|
51
|
-
<RadixDropdownMenu.ItemIndicator className={styles.itemIndicatorStyle}>
|
|
52
|
-
<CheckIcon />
|
|
53
|
-
</RadixDropdownMenu.ItemIndicator>
|
|
54
|
-
{icon && (
|
|
55
|
-
<>
|
|
56
|
-
{renderIcon(icon)}
|
|
57
|
-
<Spacer.Horizontal size={8} />
|
|
58
|
-
</>
|
|
59
|
-
)}
|
|
60
|
-
{children}
|
|
61
|
-
</RadixDropdownMenu.CheckboxItem>
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const element = (
|
|
66
|
-
<RadixDropdownMenu.Item
|
|
67
|
-
disabled={disabled}
|
|
68
|
-
onSelect={handleSelectItem}
|
|
69
|
-
className={styles.itemStyle({ disabled })}
|
|
70
|
-
>
|
|
71
|
-
{indented && (
|
|
72
|
-
<Spacer.Horizontal size={CHECKBOX_WIDTH - CHECKBOX_RIGHT_INSET} />
|
|
73
|
-
)}
|
|
74
|
-
{icon && (
|
|
75
|
-
<>
|
|
76
|
-
{renderIcon(icon)}
|
|
77
|
-
<Spacer.Horizontal size={8} />
|
|
78
|
-
</>
|
|
79
|
-
)}
|
|
80
|
-
{children}
|
|
81
|
-
{shortcut && (
|
|
82
|
-
<>
|
|
83
|
-
<Spacer.Horizontal />
|
|
84
|
-
<Spacer.Horizontal size={24} />
|
|
85
|
-
<KeyboardShortcut shortcut={shortcut} />
|
|
86
|
-
</>
|
|
87
|
-
)}
|
|
88
|
-
{items && items.length > 0 && (
|
|
89
|
-
<>
|
|
90
|
-
<Spacer.Horizontal />
|
|
91
|
-
<Spacer.Horizontal size={16} />
|
|
92
|
-
<ChevronRightIcon />
|
|
93
|
-
</>
|
|
94
|
-
)}
|
|
95
|
-
</RadixDropdownMenu.Item>
|
|
96
|
-
);
|
|
97
|
-
|
|
98
|
-
if (items && items.length > 0) {
|
|
99
|
-
return (
|
|
100
|
-
<DropdownMenuRoot
|
|
101
|
-
isNested
|
|
102
|
-
items={items}
|
|
103
|
-
onSelect={onSelect}
|
|
104
|
-
alignOffset={-5}
|
|
105
|
-
>
|
|
106
|
-
{element}
|
|
107
|
-
</DropdownMenuRoot>
|
|
108
|
-
);
|
|
109
|
-
} else {
|
|
110
|
-
return element;
|
|
111
|
-
}
|
|
112
|
-
});
|
|
10
|
+
import { MenuProps } from "./ContextMenu";
|
|
11
|
+
import { getKeyboardShortcutsForMenuItems, styles } from "./internal/Menu";
|
|
12
|
+
import { MenuViewport } from "./internal/MenuViewport";
|
|
113
13
|
|
|
114
14
|
/* ----------------------------------------------------------------------------
|
|
115
15
|
* Root
|
|
116
16
|
* ------------------------------------------------------------------------- */
|
|
117
17
|
|
|
118
|
-
type DropdownRootProps<T extends string> = MenuProps<T> & {
|
|
18
|
+
export type DropdownRootProps<T extends string> = MenuProps<T> & {
|
|
119
19
|
open?: boolean;
|
|
120
20
|
onCloseAutoFocus?: React.EventHandler<SyntheticEvent<unknown>>;
|
|
121
21
|
emptyState?: React.ReactNode;
|
|
22
|
+
contentStyle?: React.CSSProperties;
|
|
122
23
|
} & Pick<
|
|
123
24
|
ComponentProps<typeof RadixDropdownMenu.Content>,
|
|
124
25
|
"side" | "sideOffset" | "align" | "alignOffset" | "collisionPadding"
|
|
125
26
|
>;
|
|
126
27
|
|
|
28
|
+
const Components = {
|
|
29
|
+
Separator: RadixDropdownMenu.Separator,
|
|
30
|
+
ItemText: React.Fragment,
|
|
31
|
+
Item: RadixDropdownMenu.Item,
|
|
32
|
+
CheckboxItem: RadixDropdownMenu.CheckboxItem,
|
|
33
|
+
ItemIndicator: RadixDropdownMenu.ItemIndicator,
|
|
34
|
+
SubTrigger: RadixDropdownMenu.SubTrigger,
|
|
35
|
+
SubContent: RadixDropdownMenu.SubContent,
|
|
36
|
+
Sub: RadixDropdownMenu.Sub,
|
|
37
|
+
Portal: RadixDropdownMenu.Portal,
|
|
38
|
+
};
|
|
39
|
+
|
|
127
40
|
const DropdownMenuRoot = forwardRefGeneric(function DropdownMenuRoot<
|
|
128
41
|
T extends string,
|
|
129
|
-
>(
|
|
130
|
-
{
|
|
42
|
+
>(props: DropdownRootProps<T>, forwardedRef: ForwardedRef<HTMLElement>) {
|
|
43
|
+
const {
|
|
131
44
|
items,
|
|
132
45
|
children,
|
|
133
46
|
onSelect,
|
|
134
|
-
|
|
47
|
+
|
|
135
48
|
shouldBindKeyboardShortcuts,
|
|
136
49
|
onOpenChange,
|
|
137
50
|
open,
|
|
@@ -142,77 +55,56 @@ const DropdownMenuRoot = forwardRefGeneric(function DropdownMenuRoot<
|
|
|
142
55
|
alignOffset,
|
|
143
56
|
collisionPadding = 8,
|
|
144
57
|
emptyState,
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
) {
|
|
148
|
-
const hasCheckedItem = items.some(
|
|
149
|
-
(item) => item !== SEPARATOR_ITEM && item.checked
|
|
150
|
-
);
|
|
58
|
+
contentStyle,
|
|
59
|
+
} = props;
|
|
151
60
|
|
|
152
61
|
const keymap = useMemo(
|
|
153
62
|
() =>
|
|
154
|
-
|
|
63
|
+
shouldBindKeyboardShortcuts === false
|
|
155
64
|
? {}
|
|
156
65
|
: getKeyboardShortcutsForMenuItems(items, onSelect),
|
|
157
|
-
[
|
|
66
|
+
[items, onSelect, shouldBindKeyboardShortcuts]
|
|
158
67
|
);
|
|
159
68
|
|
|
160
69
|
useKeyboardShortcuts(keymap);
|
|
161
70
|
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
: RadixDropdownMenu.Content;
|
|
171
|
-
|
|
172
|
-
const contentStyle = useMemo(() => ({ zIndex: 1000 }), []);
|
|
71
|
+
const contentStyles = useMemo(
|
|
72
|
+
() => ({
|
|
73
|
+
maxHeight: "500px",
|
|
74
|
+
overflow: "auto",
|
|
75
|
+
...contentStyle,
|
|
76
|
+
}),
|
|
77
|
+
[contentStyle]
|
|
78
|
+
);
|
|
173
79
|
|
|
174
80
|
return (
|
|
175
|
-
<
|
|
176
|
-
<
|
|
81
|
+
<RadixDropdownMenu.Root onOpenChange={onOpenChange} open={open}>
|
|
82
|
+
<RadixDropdownMenu.Trigger
|
|
83
|
+
ref={forwardedRef as ForwardedRef<any>}
|
|
84
|
+
asChild
|
|
85
|
+
>
|
|
177
86
|
{children}
|
|
178
|
-
</
|
|
87
|
+
</RadixDropdownMenu.Trigger>
|
|
179
88
|
<RadixDropdownMenu.Portal>
|
|
180
|
-
<
|
|
89
|
+
<RadixDropdownMenu.Content
|
|
181
90
|
className={styles.contentStyle}
|
|
182
91
|
side={side}
|
|
183
92
|
sideOffset={sideOffset}
|
|
184
93
|
align={align}
|
|
185
94
|
alignOffset={alignOffset}
|
|
186
|
-
style={
|
|
95
|
+
style={contentStyles}
|
|
187
96
|
collisionPadding={collisionPadding}
|
|
188
97
|
{...({ onCloseAutoFocus } as any)}
|
|
189
98
|
>
|
|
190
99
|
{items.length === 0 ? emptyState : null}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
) : (
|
|
198
|
-
<DropdownMenuItem
|
|
199
|
-
key={item.value ?? index}
|
|
200
|
-
value={item.value}
|
|
201
|
-
indented={hasCheckedItem}
|
|
202
|
-
checked={item.checked ?? false}
|
|
203
|
-
disabled={item.disabled ?? false}
|
|
204
|
-
icon={item.icon}
|
|
205
|
-
onSelect={onSelect}
|
|
206
|
-
items={item.items}
|
|
207
|
-
shortcut={item.shortcut}
|
|
208
|
-
>
|
|
209
|
-
{item.title}
|
|
210
|
-
</DropdownMenuItem>
|
|
211
|
-
)
|
|
212
|
-
)}
|
|
213
|
-
</ContentComponent>
|
|
100
|
+
<MenuViewport
|
|
101
|
+
items={items}
|
|
102
|
+
Components={Components}
|
|
103
|
+
onSelect={onSelect}
|
|
104
|
+
/>
|
|
105
|
+
</RadixDropdownMenu.Content>
|
|
214
106
|
</RadixDropdownMenu.Portal>
|
|
215
|
-
</
|
|
107
|
+
</RadixDropdownMenu.Root>
|
|
216
108
|
);
|
|
217
109
|
});
|
|
218
110
|
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import React, { type ReactNode } from "react";
|
|
2
|
+
import { cx } from "../utils/classNames";
|
|
3
|
+
|
|
4
|
+
export type FadeDirection = "left" | "right" | "top" | "bottom";
|
|
5
|
+
|
|
6
|
+
export type FadeProps = {
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
direction?: FadeDirection;
|
|
9
|
+
width?: number;
|
|
10
|
+
height?: number;
|
|
11
|
+
className?: string;
|
|
12
|
+
zIndex?: number;
|
|
13
|
+
/**
|
|
14
|
+
* @default "front"
|
|
15
|
+
* If "back", the fade will be positioned behind the children
|
|
16
|
+
*/
|
|
17
|
+
position?: "front" | "back";
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const Fade = ({
|
|
21
|
+
children,
|
|
22
|
+
direction = "right",
|
|
23
|
+
width,
|
|
24
|
+
height,
|
|
25
|
+
className,
|
|
26
|
+
zIndex = 0,
|
|
27
|
+
position = "front",
|
|
28
|
+
}: FadeProps) => {
|
|
29
|
+
const gradientDirection = {
|
|
30
|
+
left: "to-l",
|
|
31
|
+
right: "to-r",
|
|
32
|
+
top: "to-t",
|
|
33
|
+
bottom: "to-b",
|
|
34
|
+
}[direction];
|
|
35
|
+
|
|
36
|
+
const positionClasses = {
|
|
37
|
+
left: "left-0 top-0 bottom-0",
|
|
38
|
+
right: "right-0 top-0 bottom-0",
|
|
39
|
+
top: "left-0 right-0 top-0",
|
|
40
|
+
bottom: "left-0 right-0 bottom-0",
|
|
41
|
+
}[direction];
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<div className={cx("relative", className)} style={{ height }}>
|
|
45
|
+
{position === "front" ? children : null}
|
|
46
|
+
<div
|
|
47
|
+
className={cx(
|
|
48
|
+
"absolute pointer-events-none",
|
|
49
|
+
positionClasses,
|
|
50
|
+
`bg-gradient-${gradientDirection}`,
|
|
51
|
+
"from-transparent to-background",
|
|
52
|
+
zIndex && `z-[${zIndex}]`
|
|
53
|
+
)}
|
|
54
|
+
style={{
|
|
55
|
+
width: width ?? "100%",
|
|
56
|
+
height: height ?? "100%",
|
|
57
|
+
}}
|
|
58
|
+
/>
|
|
59
|
+
{position === "back" ? children : null}
|
|
60
|
+
</div>
|
|
61
|
+
);
|
|
62
|
+
};
|