@noya-app/noya-designsystem 0.1.48 → 0.1.50
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 +19 -0
- package/dist/index.css +1 -1
- package/dist/index.d.mts +347 -173
- package/dist/index.d.ts +347 -173
- package/dist/index.js +3602 -2811
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4761 -3993
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -5
- package/src/__tests__/validateDropIndicator.test.ts +4 -4
- package/src/components/ActionMenu.tsx +15 -4
- package/src/components/Avatar.tsx +2 -2
- package/src/components/Banner.tsx +29 -0
- package/src/components/BaseToolbar.tsx +2 -2
- package/src/components/Button.tsx +2 -2
- package/src/components/Checkbox.tsx +2 -2
- package/src/components/Chip.tsx +15 -14
- package/src/components/Collection.tsx +25 -2
- package/src/components/Combobox.tsx +22 -23
- package/src/components/ComboboxMenu.tsx +1 -1
- package/src/components/Dialog.tsx +2 -2
- package/src/components/DimensionInput.tsx +14 -12
- package/src/components/EditableText.tsx +3 -1
- package/src/components/FillInputField.tsx +2 -2
- package/src/components/Grid.tsx +131 -113
- package/src/components/GridView.tsx +36 -18
- package/src/components/InputField.tsx +116 -171
- package/src/components/Label.tsx +14 -73
- package/src/components/LabeledField.tsx +13 -2
- package/src/components/List.tsx +106 -47
- package/src/components/ListView.tsx +52 -31
- package/src/components/MediaThumbnail.tsx +14 -6
- package/src/components/Message.tsx +8 -8
- package/src/components/NoyaLogo.tsx +41 -0
- package/src/components/Popover.tsx +9 -6
- package/src/components/Section.tsx +172 -0
- package/src/components/SegmentedControl.tsx +1 -1
- package/src/components/SelectMenu.tsx +9 -4
- package/src/components/Slider.tsx +16 -7
- package/src/components/Sortable.tsx +186 -47
- package/src/components/UserPointer.tsx +1 -1
- package/src/components/ai-assistant/AIAssistantLayout.tsx +102 -0
- package/src/components/connected-users-menu/ConnectedUsersMenuLayout.tsx +71 -0
- package/src/components/file-explorer/FileExplorerLayout.tsx +71 -0
- package/src/components/internal/Menu.tsx +20 -10
- package/src/components/internal/SelectItem.tsx +3 -2
- package/src/components/pipeline/PipelineResultLayout.tsx +32 -0
- package/src/index.css +118 -112
- package/src/index.tsx +9 -0
- package/src/theme/index.ts +2 -0
- package/src/utils/classNames.ts +76 -3
- package/src/utils/inputs.ts +21 -0
- package/src/utils/moveTreeItem.ts +99 -0
- package/tailwind.config.ts +82 -75
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { cssVars } from "@noya-app/noya-designsystem";
|
|
2
|
+
import React, { forwardRef } from "react";
|
|
3
|
+
|
|
4
|
+
export const Logo = forwardRef(function Logo(
|
|
5
|
+
props: React.ComponentProps<"svg">,
|
|
6
|
+
ref: React.Ref<SVGSVGElement>
|
|
7
|
+
) {
|
|
8
|
+
const fill = props.fill || cssVars.colors.logoFill;
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<svg
|
|
12
|
+
ref={ref}
|
|
13
|
+
viewBox="0 0 24 26"
|
|
14
|
+
fill="none"
|
|
15
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
16
|
+
{...props}
|
|
17
|
+
className="w-6 aspect-[24/26]"
|
|
18
|
+
>
|
|
19
|
+
<path
|
|
20
|
+
d="M6.5 3H2V12H5V6H6.5C7.32843 6 8 6.67157 8 7.5V12H11V7.5C11 5.01472 8.98528 3 6.5 3Z"
|
|
21
|
+
fill={fill}
|
|
22
|
+
/>
|
|
23
|
+
<path
|
|
24
|
+
fillRule="evenodd"
|
|
25
|
+
clipRule="evenodd"
|
|
26
|
+
d="M17.5 12C19.9853 12 22 9.98528 22 7.5C22 5.01472 19.9853 3 17.5 3C15.0147 3 13 5.01472 13 7.5C13 9.98528 15.0147 12 17.5 12ZM17.5 9C18.3284 9 19 8.32843 19 7.5C19 6.67157 18.3284 6 17.5 6C16.6716 6 16 6.67157 16 7.5C16 8.32843 16.6716 9 17.5 9Z"
|
|
27
|
+
fill={fill}
|
|
28
|
+
/>
|
|
29
|
+
<path
|
|
30
|
+
d="M5 14H2V18.5C2 20.9853 4.01472 23 6.5 23H8V26H11V17H8V20H6.5C5.67157 20 5 19.3284 5 18.5V14Z"
|
|
31
|
+
fill={fill}
|
|
32
|
+
/>
|
|
33
|
+
<path
|
|
34
|
+
fillRule="evenodd"
|
|
35
|
+
clipRule="evenodd"
|
|
36
|
+
d="M17.5 23C15.0147 23 13 20.9853 13 18.5C13 16.0147 15.0147 14 17.5 14C19.9853 14 22 16.0147 22 18.5V23H17.5ZM17.5 20C18.3284 20 19 19.3284 19 18.5C19 17.6716 18.3284 17 17.5 17C16.6716 17 16 17.6716 16 18.5C16 19.3284 16.6716 20 17.5 20Z"
|
|
37
|
+
fill={fill}
|
|
38
|
+
/>
|
|
39
|
+
</svg>
|
|
40
|
+
);
|
|
41
|
+
});
|
|
@@ -32,6 +32,12 @@ interface Props
|
|
|
32
32
|
className?: string;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
export const popoverStyle = {
|
|
36
|
+
base: "rounded font-[14px] bg-popover-background shadow-[0_2px_4px_rgba(0,0,0,0.2),0_0_12px_rgba(0,0,0,0.1)] max-h-[600px] overflow-y-auto text-text-muted z-[1000]",
|
|
37
|
+
large: "w-[680px]",
|
|
38
|
+
normal: "w-[240px]",
|
|
39
|
+
};
|
|
40
|
+
|
|
35
41
|
export function Popover({
|
|
36
42
|
children,
|
|
37
43
|
trigger,
|
|
@@ -56,12 +62,9 @@ export function Popover({
|
|
|
56
62
|
<PopoverPrimitive.Portal>
|
|
57
63
|
<PopoverPrimitive.Content
|
|
58
64
|
className={cx(
|
|
59
|
-
|
|
60
|
-
variant === "large"
|
|
61
|
-
|
|
62
|
-
: variant === "normal"
|
|
63
|
-
? "w-[240px]"
|
|
64
|
-
: "",
|
|
65
|
+
popoverStyle.base,
|
|
66
|
+
variant === "large" && popoverStyle.large,
|
|
67
|
+
variant === "normal" && popoverStyle.normal,
|
|
65
68
|
className
|
|
66
69
|
)}
|
|
67
70
|
side={side}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Button,
|
|
3
|
+
IconButton,
|
|
4
|
+
IndentContext,
|
|
5
|
+
INPUT_HEIGHT,
|
|
6
|
+
InspectorPrimitives,
|
|
7
|
+
Spacer,
|
|
8
|
+
textStyles,
|
|
9
|
+
} from "@noya-app/noya-designsystem";
|
|
10
|
+
import { clientStorage, usePersistentStateString } from "@noya-app/react-utils";
|
|
11
|
+
import React, { CSSProperties, memo, useMemo } from "react";
|
|
12
|
+
|
|
13
|
+
type TitleIconOptions = {
|
|
14
|
+
inlineBlockWrapper?: boolean;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type SectionProps = {
|
|
18
|
+
children: React.ReactNode;
|
|
19
|
+
title?: React.ReactNode;
|
|
20
|
+
onClickTitle?: () => void;
|
|
21
|
+
titleTextStyle?: "small" | "heading5" | "heading4" | "heading3";
|
|
22
|
+
right?: React.ReactNode;
|
|
23
|
+
hideRightWhenCollapsed?: boolean;
|
|
24
|
+
extraPadding?: boolean;
|
|
25
|
+
className?: string;
|
|
26
|
+
style?: CSSProperties;
|
|
27
|
+
titleIcon?: React.ReactNode;
|
|
28
|
+
titleIconOptions?: TitleIconOptions;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const titleIconStyle: CSSProperties = {
|
|
32
|
+
marginRight: "8px",
|
|
33
|
+
alignSelf: "flex-start",
|
|
34
|
+
position: "relative",
|
|
35
|
+
top: "2px",
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const titleIconWrapperStyle: CSSProperties = {
|
|
39
|
+
display: "inline-block",
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const SectionInternal = ({
|
|
43
|
+
children,
|
|
44
|
+
title,
|
|
45
|
+
onClickTitle,
|
|
46
|
+
titleTextStyle = "heading4",
|
|
47
|
+
right,
|
|
48
|
+
extraPadding,
|
|
49
|
+
className,
|
|
50
|
+
style: styleProp,
|
|
51
|
+
titleIcon,
|
|
52
|
+
titleIconOptions = {
|
|
53
|
+
inlineBlockWrapper: true,
|
|
54
|
+
},
|
|
55
|
+
}: SectionProps) => {
|
|
56
|
+
const style: CSSProperties = useMemo(
|
|
57
|
+
() => ({
|
|
58
|
+
display: "flex",
|
|
59
|
+
flexDirection: "column",
|
|
60
|
+
gap: "8px",
|
|
61
|
+
paddingTop:
|
|
62
|
+
titleTextStyle === "heading3"
|
|
63
|
+
? "12px"
|
|
64
|
+
: title && extraPadding
|
|
65
|
+
? "24px"
|
|
66
|
+
: "12px",
|
|
67
|
+
paddingBottom:
|
|
68
|
+
titleTextStyle === "heading3"
|
|
69
|
+
? "12px"
|
|
70
|
+
: title && extraPadding
|
|
71
|
+
? "12px"
|
|
72
|
+
: "12px",
|
|
73
|
+
...styleProp,
|
|
74
|
+
}),
|
|
75
|
+
[titleTextStyle, title, extraPadding, styleProp]
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
const hasChildren = React.Children.toArray(children).some((child) => !!child);
|
|
79
|
+
|
|
80
|
+
const headerStyle: CSSProperties = useMemo(
|
|
81
|
+
() => ({
|
|
82
|
+
marginBottom: hasChildren ? "4px" : undefined,
|
|
83
|
+
minHeight: INPUT_HEIGHT,
|
|
84
|
+
}),
|
|
85
|
+
[hasChildren]
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<div style={style} className={className}>
|
|
90
|
+
{(title || titleIcon || right) && (
|
|
91
|
+
<InspectorPrimitives.SectionHeader style={headerStyle}>
|
|
92
|
+
{titleIcon && (
|
|
93
|
+
<div style={titleIconStyle} className={textStyles[titleTextStyle]}>
|
|
94
|
+
{titleIconOptions.inlineBlockWrapper ? (
|
|
95
|
+
<div style={titleIconWrapperStyle}>{titleIcon}</div>
|
|
96
|
+
) : (
|
|
97
|
+
titleIcon
|
|
98
|
+
)}
|
|
99
|
+
</div>
|
|
100
|
+
)}
|
|
101
|
+
{title && (
|
|
102
|
+
<>
|
|
103
|
+
{onClickTitle ? (
|
|
104
|
+
<Button variant="none" onClick={onClickTitle}>
|
|
105
|
+
<InspectorPrimitives.Title $textStyle={titleTextStyle}>
|
|
106
|
+
{title}
|
|
107
|
+
</InspectorPrimitives.Title>
|
|
108
|
+
</Button>
|
|
109
|
+
) : (
|
|
110
|
+
<InspectorPrimitives.Title $textStyle={titleTextStyle}>
|
|
111
|
+
{title}
|
|
112
|
+
</InspectorPrimitives.Title>
|
|
113
|
+
)}
|
|
114
|
+
</>
|
|
115
|
+
)}
|
|
116
|
+
<Spacer.Horizontal />
|
|
117
|
+
{right}
|
|
118
|
+
</InspectorPrimitives.SectionHeader>
|
|
119
|
+
)}
|
|
120
|
+
<IndentContext.Provider value={{ indentLevel: 1 }}>
|
|
121
|
+
{children}
|
|
122
|
+
</IndentContext.Provider>
|
|
123
|
+
</div>
|
|
124
|
+
);
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
type ExpandableSectionProps = {
|
|
128
|
+
storageKey: string;
|
|
129
|
+
initialVisibility?: "show" | "hide";
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const ExpandableSection = ({
|
|
133
|
+
storageKey,
|
|
134
|
+
initialVisibility = "show",
|
|
135
|
+
...props
|
|
136
|
+
}: SectionProps & ExpandableSectionProps) => {
|
|
137
|
+
const [visibility, setVisibility] = usePersistentStateString<"show" | "hide">(
|
|
138
|
+
clientStorage,
|
|
139
|
+
storageKey,
|
|
140
|
+
initialVisibility
|
|
141
|
+
);
|
|
142
|
+
const expanded = visibility === "show";
|
|
143
|
+
|
|
144
|
+
return (
|
|
145
|
+
<SectionInternal
|
|
146
|
+
{...props}
|
|
147
|
+
right={!props.hideRightWhenCollapsed || expanded ? props.right : null}
|
|
148
|
+
title={
|
|
149
|
+
<div className="flex gap-1 items-center">
|
|
150
|
+
{props.title}
|
|
151
|
+
<IconButton
|
|
152
|
+
iconName={expanded ? "ChevronDownIcon2" : "ChevronRightIcon2"}
|
|
153
|
+
onClick={() => setVisibility(expanded ? "hide" : "show")}
|
|
154
|
+
/>
|
|
155
|
+
</div>
|
|
156
|
+
}
|
|
157
|
+
>
|
|
158
|
+
{expanded && props.children}
|
|
159
|
+
</SectionInternal>
|
|
160
|
+
);
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
export const Section = memo(function InspectorSection({
|
|
164
|
+
storageKey,
|
|
165
|
+
...props
|
|
166
|
+
}: SectionProps & Partial<ExpandableSectionProps>) {
|
|
167
|
+
return storageKey ? (
|
|
168
|
+
<ExpandableSection {...props} storageKey={storageKey} />
|
|
169
|
+
) : (
|
|
170
|
+
<SectionInternal {...props} />
|
|
171
|
+
);
|
|
172
|
+
});
|
|
@@ -141,7 +141,7 @@ export const SegmentedControl = memoGeneric(function SegmentedControl<
|
|
|
141
141
|
value={value}
|
|
142
142
|
onValueChange={handleValueChange}
|
|
143
143
|
className={cx(
|
|
144
|
-
`flex items-stretch flex-auto appearance-none relative outline-none min-h-
|
|
144
|
+
`flex items-stretch flex-auto appearance-none relative outline-none min-h-input-height rounded bg-input-background py-[2px] px-[2px]`,
|
|
145
145
|
className
|
|
146
146
|
)}
|
|
147
147
|
style={style}
|
|
@@ -15,6 +15,7 @@ import React, {
|
|
|
15
15
|
import { useLabel, useLabelPosition } from "../hooks/useLabel";
|
|
16
16
|
import { cx } from "../utils/classNames";
|
|
17
17
|
|
|
18
|
+
import { getInsetEndStyles } from "../utils/inputs";
|
|
18
19
|
import { Button } from "./Button";
|
|
19
20
|
import { renderIcon } from "./Icons";
|
|
20
21
|
import {
|
|
@@ -24,7 +25,7 @@ import {
|
|
|
24
25
|
styles,
|
|
25
26
|
} from "./internal/Menu";
|
|
26
27
|
import { MenuComponents, MenuViewport } from "./internal/MenuViewport";
|
|
27
|
-
import {
|
|
28
|
+
import { Label } from "./Label";
|
|
28
29
|
|
|
29
30
|
type Props<T extends string> = {
|
|
30
31
|
id?: string;
|
|
@@ -57,6 +58,8 @@ const scrollButtonStyles = `
|
|
|
57
58
|
hover:text-text
|
|
58
59
|
`;
|
|
59
60
|
|
|
61
|
+
const insetEndStyles = getInsetEndStyles();
|
|
62
|
+
|
|
60
63
|
interface SelectMenuTriggerProps {
|
|
61
64
|
id?: string;
|
|
62
65
|
style?: React.CSSProperties;
|
|
@@ -101,9 +104,11 @@ const SelectMenuTrigger = memoGeneric(function SelectMenuTrigger({
|
|
|
101
104
|
>
|
|
102
105
|
{icon && <span className="pr-1.5">{renderIcon(icon)}</span>}
|
|
103
106
|
{label && labelPosition === "inset" && (
|
|
104
|
-
<
|
|
105
|
-
{
|
|
106
|
-
|
|
107
|
+
<div className={insetEndStyles}>
|
|
108
|
+
<Label className="pr-4 text-text-disabled" htmlFor={id}>
|
|
109
|
+
{label}
|
|
110
|
+
</Label>
|
|
111
|
+
</div>
|
|
107
112
|
)}
|
|
108
113
|
<span className="flex-1 flex">
|
|
109
114
|
<Select.Value placeholder={placeholder} />
|
|
@@ -2,7 +2,8 @@ import * as RadixSlider from "@radix-ui/react-slider";
|
|
|
2
2
|
import React, { FocusEventHandler, memo, useCallback, useMemo } from "react";
|
|
3
3
|
import { useLabel, useLabelPosition } from "../hooks/useLabel";
|
|
4
4
|
import { cx } from "../utils/classNames";
|
|
5
|
-
import {
|
|
5
|
+
import { getInsetEndStyles } from "../utils/inputs";
|
|
6
|
+
import { Label } from "./Label";
|
|
6
7
|
|
|
7
8
|
type ColorScheme = "primary" | "secondary";
|
|
8
9
|
|
|
@@ -28,6 +29,8 @@ const thumbStyle = {
|
|
|
28
29
|
width: THUMB_WIDTH,
|
|
29
30
|
};
|
|
30
31
|
|
|
32
|
+
const insetEndStyles = getInsetEndStyles();
|
|
33
|
+
|
|
31
34
|
export const Slider = memo(function Slider({
|
|
32
35
|
style,
|
|
33
36
|
className,
|
|
@@ -95,7 +98,7 @@ export const Slider = memo(function Slider({
|
|
|
95
98
|
value={arrayValue}
|
|
96
99
|
onValueChange={handleValueChange}
|
|
97
100
|
className={cx(
|
|
98
|
-
"flex relative items-center select-none touch-none h-
|
|
101
|
+
"flex relative items-center select-none touch-none h-input-height rounded overflow-hidden flex-grow max-h-input-height",
|
|
99
102
|
className
|
|
100
103
|
)}
|
|
101
104
|
style={style}
|
|
@@ -105,7 +108,11 @@ export const Slider = memo(function Slider({
|
|
|
105
108
|
>
|
|
106
109
|
<RadixSlider.Track className="flex-grow h-full rounded overflow-hidden bg-input-background">
|
|
107
110
|
{label && labelPosition === "inset" && (
|
|
108
|
-
<
|
|
111
|
+
<div className={insetEndStyles}>
|
|
112
|
+
<Label htmlFor={id} className="text-text-disabled">
|
|
113
|
+
{label}
|
|
114
|
+
</Label>
|
|
115
|
+
</div>
|
|
109
116
|
)}
|
|
110
117
|
<div
|
|
111
118
|
style={trackFillStyle}
|
|
@@ -117,14 +124,16 @@ export const Slider = memo(function Slider({
|
|
|
117
124
|
/>
|
|
118
125
|
</RadixSlider.Track>
|
|
119
126
|
{label && labelPosition === "inset" && colorScheme !== undefined && (
|
|
120
|
-
<
|
|
121
|
-
{
|
|
122
|
-
|
|
127
|
+
<div className={insetEndStyles}>
|
|
128
|
+
<Label className="text-white overflow-hidden" style={labelStyle}>
|
|
129
|
+
{label}
|
|
130
|
+
</Label>
|
|
131
|
+
</div>
|
|
123
132
|
)}
|
|
124
133
|
<RadixSlider.Thumb
|
|
125
134
|
style={thumbStyle}
|
|
126
135
|
className={cx(
|
|
127
|
-
"block h-
|
|
136
|
+
"block h-input-height rounded border border-solid bg-slider-thumb-background transition-colors focus:border-primary focus:border-2 outline-none",
|
|
128
137
|
colorScheme === undefined && "border-slider-border",
|
|
129
138
|
colorScheme === "primary" && "border-primary",
|
|
130
139
|
colorScheme === "secondary" && "border-secondary"
|