@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
package/src/components/Grid.tsx
CHANGED
|
@@ -82,6 +82,7 @@ export const Grid = memoGeneric(
|
|
|
82
82
|
size = "medium",
|
|
83
83
|
testHoveredId,
|
|
84
84
|
testRenamingId,
|
|
85
|
+
testShowDropIndicatorId,
|
|
85
86
|
scrollable = false,
|
|
86
87
|
// acceptsDrop,
|
|
87
88
|
// onMoveItem,
|
|
@@ -90,6 +91,7 @@ export const Grid = memoGeneric(
|
|
|
90
91
|
onClickItem,
|
|
91
92
|
onDoubleClickItem,
|
|
92
93
|
renderEmptyState,
|
|
94
|
+
// getDropTargetParentIndex,
|
|
93
95
|
} = props;
|
|
94
96
|
|
|
95
97
|
const [hoveredId, setHoveredId] = useState<string>();
|
|
@@ -143,130 +145,146 @@ export const Grid = memoGeneric(
|
|
|
143
145
|
|
|
144
146
|
return (
|
|
145
147
|
<GridView.Root
|
|
148
|
+
role="listbox"
|
|
149
|
+
aria-orientation="horizontal"
|
|
150
|
+
aria-multiselectable={true}
|
|
146
151
|
minColumnWidth={minColumnWidth}
|
|
147
|
-
scrollable={scrollable}
|
|
152
|
+
scrollable={items.length > 0 && scrollable}
|
|
153
|
+
contentClassName={cx(items.length === 0 && "flex flex-1")}
|
|
148
154
|
gap={gap}
|
|
149
155
|
className={cx(isDropTargetActive && "bg-primary-pastel", className)}
|
|
150
156
|
{...dropTargetProps}
|
|
151
157
|
ref={fileDropTargetRef}
|
|
152
158
|
>
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
menuItems && (
|
|
174
|
-
<ActionMenu
|
|
175
|
-
menuItems={menuItems}
|
|
176
|
-
onSelect={(action) => handleMenuAction(action, item)}
|
|
177
|
-
selected={isSelected}
|
|
178
|
-
onOpenChange={(open) => {
|
|
179
|
-
setDropdownOpenId(open ? id : undefined);
|
|
159
|
+
{items.length > 0 ? (
|
|
160
|
+
<GridView.Section>
|
|
161
|
+
{items.map((item) => {
|
|
162
|
+
const id = getId(item);
|
|
163
|
+
const isDropdownOpen = dropdownOpenId === id;
|
|
164
|
+
const isHovered =
|
|
165
|
+
testHoveredId === id ||
|
|
166
|
+
currentHoveredId === id ||
|
|
167
|
+
isDropdownOpen;
|
|
168
|
+
const itemIsRenamable = getRenamable?.(item) ?? renamable;
|
|
169
|
+
const isSelected = selectedIds.includes(id);
|
|
170
|
+
const isRenaming =
|
|
171
|
+
itemIsRenamable && onRename && renamingId === id;
|
|
172
|
+
const isTestingRenaming = testRenamingId === id;
|
|
173
|
+
const thumbnail = renderThumbnail?.({
|
|
174
|
+
item,
|
|
175
|
+
selected: isSelected,
|
|
176
|
+
});
|
|
177
|
+
const onOpenChange = (open: boolean) => {
|
|
178
|
+
setDropdownOpenId(open ? id : undefined);
|
|
180
179
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
180
|
+
if (open && !isSelected) {
|
|
181
|
+
handleSelect(id);
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
const action =
|
|
185
|
+
(isHovered || isSelected) &&
|
|
186
|
+
!isRenaming &&
|
|
187
|
+
(typeof renderAction === "function"
|
|
188
|
+
? renderAction({ item, selected: isSelected, onOpenChange })
|
|
189
|
+
: renderAction === "menu" &&
|
|
190
|
+
menuItems && (
|
|
191
|
+
<ActionMenu
|
|
192
|
+
menuItems={menuItems}
|
|
193
|
+
onSelect={(action) => handleMenuAction(action, item)}
|
|
194
|
+
selected={isSelected}
|
|
195
|
+
onOpenChange={onOpenChange}
|
|
196
|
+
/>
|
|
197
|
+
));
|
|
187
198
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
199
|
+
return (
|
|
200
|
+
<GridView.Item<M>
|
|
201
|
+
key={id}
|
|
202
|
+
id={id}
|
|
203
|
+
role="option"
|
|
204
|
+
aria-selected={isSelected}
|
|
205
|
+
aria-label={getName(item)}
|
|
206
|
+
hovered={isHovered}
|
|
207
|
+
testShowInsideDropIndicator={testShowDropIndicatorId === id}
|
|
208
|
+
onHoverChange={(isHovering) => {
|
|
209
|
+
setHoveredId(isHovering ? id : undefined);
|
|
210
|
+
}}
|
|
211
|
+
title={
|
|
212
|
+
<EditableText
|
|
213
|
+
tabIndex={isRenaming ? undefined : -1}
|
|
214
|
+
value={getName(item)}
|
|
215
|
+
focused={isRenaming}
|
|
216
|
+
testFocused={isTestingRenaming}
|
|
217
|
+
readOnly={!itemIsRenamable || !onRename}
|
|
218
|
+
onSubmit={(value) => {
|
|
204
219
|
onRename?.(item, value);
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
</EditableText>
|
|
224
|
-
}
|
|
225
|
-
subtitle={
|
|
226
|
-
<span className={cx(isSelected && "text-primary")}>
|
|
227
|
-
{renderDetail?.(item, isSelected)}
|
|
228
|
-
</span>
|
|
229
|
-
}
|
|
230
|
-
loading={false}
|
|
231
|
-
selected={isSelected}
|
|
232
|
-
onClick={() => {
|
|
233
|
-
onClickItem?.(id);
|
|
234
|
-
}}
|
|
235
|
-
onSelect={(event) => {
|
|
236
|
-
handleSelect(id, event);
|
|
237
|
-
}}
|
|
238
|
-
onKeyDown={(event) => {
|
|
239
|
-
if (event.key === "Enter") {
|
|
240
|
-
setRenamingId(id);
|
|
220
|
+
setRenamingId(undefined);
|
|
221
|
+
}}
|
|
222
|
+
onBlur={() => {
|
|
223
|
+
setRenamingId(undefined);
|
|
224
|
+
}}
|
|
225
|
+
// max height ensures preview text and input are one line
|
|
226
|
+
textClassName="bg-listview-editing-background max-h-input-height"
|
|
227
|
+
>
|
|
228
|
+
{(props) => (
|
|
229
|
+
<span
|
|
230
|
+
{...props}
|
|
231
|
+
className={cx(
|
|
232
|
+
isSelected && "text-primary",
|
|
233
|
+
"truncate select-none"
|
|
234
|
+
)}
|
|
235
|
+
/>
|
|
236
|
+
)}
|
|
237
|
+
</EditableText>
|
|
241
238
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
menuItems={menuItems}
|
|
247
|
-
onSelectMenuItem={(action) => handleMenuAction(action, item)}
|
|
248
|
-
action={action}
|
|
249
|
-
onMenuOpenChange={(open: boolean) => {
|
|
250
|
-
if (open && !isSelected) {
|
|
251
|
-
handleSelect(id);
|
|
239
|
+
subtitle={
|
|
240
|
+
<span className={cx(isSelected && "text-primary")}>
|
|
241
|
+
{renderDetail?.(item, isSelected)}
|
|
242
|
+
</span>
|
|
252
243
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
244
|
+
loading={false}
|
|
245
|
+
selected={isSelected}
|
|
246
|
+
onClick={() => {
|
|
247
|
+
onClickItem?.(id);
|
|
248
|
+
}}
|
|
249
|
+
onSelect={(event) => {
|
|
250
|
+
handleSelect(id, event);
|
|
251
|
+
}}
|
|
252
|
+
onKeyDown={(event) => {
|
|
253
|
+
if (event.key === "Enter") {
|
|
254
|
+
setRenamingId(id);
|
|
255
|
+
}
|
|
256
|
+
}}
|
|
257
|
+
onDoubleClick={() => {
|
|
258
|
+
onDoubleClickItem?.(id);
|
|
259
|
+
}}
|
|
260
|
+
menuItems={menuItems}
|
|
261
|
+
onSelectMenuItem={(action) => handleMenuAction(action, item)}
|
|
262
|
+
action={action}
|
|
263
|
+
onMenuOpenChange={(open: boolean) => {
|
|
264
|
+
if (open && !isSelected) {
|
|
265
|
+
handleSelect(id);
|
|
266
|
+
}
|
|
267
|
+
}}
|
|
268
|
+
// getDropTargetParentIndex={getDropTargetParentIndex}
|
|
269
|
+
>
|
|
270
|
+
{thumbnail && (
|
|
271
|
+
<div
|
|
272
|
+
className={cx(
|
|
273
|
+
"rounded overflow-hidden flex-none flex w-full",
|
|
274
|
+
isSelected && "text-primary"
|
|
275
|
+
)}
|
|
276
|
+
tabIndex={-1}
|
|
277
|
+
>
|
|
278
|
+
{thumbnail}
|
|
279
|
+
</div>
|
|
280
|
+
)}
|
|
281
|
+
</GridView.Item>
|
|
282
|
+
);
|
|
283
|
+
})}
|
|
284
|
+
</GridView.Section>
|
|
285
|
+
) : (
|
|
286
|
+
renderEmptyState?.()
|
|
287
|
+
)}
|
|
270
288
|
</GridView.Root>
|
|
271
289
|
);
|
|
272
290
|
})
|
|
@@ -12,7 +12,7 @@ import React, {
|
|
|
12
12
|
useMemo,
|
|
13
13
|
} from "react";
|
|
14
14
|
import { useHover } from "../hooks/useHover";
|
|
15
|
-
import { cx } from "../utils/classNames";
|
|
15
|
+
import { cx, mergeConflictingClassNames } from "../utils/classNames";
|
|
16
16
|
import withSeparatorElements from "../utils/withSeparatorElements";
|
|
17
17
|
import { ActivityIndicator } from "./ActivityIndicator";
|
|
18
18
|
import { ContextMenu } from "./ContextMenu";
|
|
@@ -96,6 +96,8 @@ interface ItemProps<MenuItemType extends string = string> {
|
|
|
96
96
|
action?: ReactNode;
|
|
97
97
|
onKeyDown?: (event: React.KeyboardEvent) => void;
|
|
98
98
|
hovered?: boolean;
|
|
99
|
+
testShowInsideDropIndicator?: boolean;
|
|
100
|
+
role?: string;
|
|
99
101
|
}
|
|
100
102
|
|
|
101
103
|
const GridViewItem = forwardRefGeneric(function GridViewItem<
|
|
@@ -120,6 +122,8 @@ const GridViewItem = forwardRefGeneric(function GridViewItem<
|
|
|
120
122
|
action,
|
|
121
123
|
onKeyDown,
|
|
122
124
|
hovered = false,
|
|
125
|
+
testShowInsideDropIndicator: showInsideDropIndicator = false,
|
|
126
|
+
...props
|
|
123
127
|
}: ItemProps<MenuItemType>,
|
|
124
128
|
forwardedRef: ForwardedRef<HTMLDivElement>
|
|
125
129
|
) {
|
|
@@ -157,13 +161,16 @@ const GridViewItem = forwardRefGeneric(function GridViewItem<
|
|
|
157
161
|
|
|
158
162
|
let element = (
|
|
159
163
|
<div
|
|
164
|
+
{...props}
|
|
160
165
|
className={cx(
|
|
161
|
-
"flex flex-col relative
|
|
166
|
+
"flex flex-col relative rounded p-2 -m-2 text-text",
|
|
162
167
|
"cursor-pointer",
|
|
163
168
|
"active:opacity-70",
|
|
164
169
|
selected && "bg-primary-pastel",
|
|
170
|
+
hovered && "bg-list-view-hover-background",
|
|
165
171
|
disabled && "opacity-50",
|
|
166
|
-
|
|
172
|
+
showInsideDropIndicator && "ring-2 ring-primary ring-inset",
|
|
173
|
+
"focus:ring-2 focus:ring-primary focus:ring-inset focus:outline-none"
|
|
167
174
|
)}
|
|
168
175
|
id={id}
|
|
169
176
|
ref={forwardedRef}
|
|
@@ -177,8 +184,7 @@ const GridViewItem = forwardRefGeneric(function GridViewItem<
|
|
|
177
184
|
<div
|
|
178
185
|
className={cx(
|
|
179
186
|
"flex items-center justify-center rounded",
|
|
180
|
-
bordered ? "border border-divider" : "border border-transparent"
|
|
181
|
-
selected ? "bg-primary-pastel" : "bg-input-background text-text"
|
|
187
|
+
bordered ? "border border-divider" : "border border-transparent"
|
|
182
188
|
)}
|
|
183
189
|
style={style}
|
|
184
190
|
>
|
|
@@ -267,6 +273,9 @@ interface GridViewRootProps extends Partial<GridViewContextValue> {
|
|
|
267
273
|
onDragEnter?: React.DragEventHandler<HTMLDivElement>;
|
|
268
274
|
onDragLeave?: React.DragEventHandler<HTMLDivElement>;
|
|
269
275
|
onDrop?: React.DragEventHandler<HTMLDivElement>;
|
|
276
|
+
role?: string;
|
|
277
|
+
renderEmptyState?: () => ReactNode;
|
|
278
|
+
contentClassName?: string;
|
|
270
279
|
}
|
|
271
280
|
|
|
272
281
|
const GridViewRoot = forwardRef(function GridViewRoot(
|
|
@@ -280,6 +289,7 @@ const GridViewRoot = forwardRef(function GridViewRoot(
|
|
|
280
289
|
bordered = false,
|
|
281
290
|
disabled = false,
|
|
282
291
|
className,
|
|
292
|
+
contentClassName,
|
|
283
293
|
...props
|
|
284
294
|
}: GridViewRootProps,
|
|
285
295
|
forwardedRef: ForwardedRef<HTMLDivElement>
|
|
@@ -305,25 +315,29 @@ const GridViewRoot = forwardRef(function GridViewRoot(
|
|
|
305
315
|
[bordered, disabled, gap, minColumnWidth, textPosition]
|
|
306
316
|
);
|
|
307
317
|
|
|
318
|
+
const mergedClassName = useMemo(() => {
|
|
319
|
+
const baseClassName = cx(
|
|
320
|
+
"flex flex-col -mx-3",
|
|
321
|
+
scrollable ? "basis-0 min-h-0" : "flex-none",
|
|
322
|
+
className
|
|
323
|
+
);
|
|
324
|
+
|
|
325
|
+
return mergeConflictingClassNames([baseClassName, className], {
|
|
326
|
+
categories: ["flex"],
|
|
327
|
+
});
|
|
328
|
+
}, [className, scrollable]);
|
|
329
|
+
|
|
330
|
+
const content = <div className={cx("p-3", contentClassName)}>{children}</div>;
|
|
331
|
+
|
|
308
332
|
return (
|
|
309
333
|
<GridViewContext.Provider value={contextValue}>
|
|
310
334
|
<div
|
|
311
335
|
onClick={handleClick}
|
|
312
|
-
className={
|
|
313
|
-
"flex flex-col -mx-3 -mb-1",
|
|
314
|
-
scrollable ? "basis-0 min-h-0" : "flex-none",
|
|
315
|
-
className
|
|
316
|
-
)}
|
|
336
|
+
className={mergedClassName}
|
|
317
337
|
{...props}
|
|
318
338
|
ref={forwardedRef}
|
|
319
339
|
>
|
|
320
|
-
{scrollable ?
|
|
321
|
-
<ScrollArea>
|
|
322
|
-
<div className="p-3">{children}</div>
|
|
323
|
-
</ScrollArea>
|
|
324
|
-
) : (
|
|
325
|
-
<div className="p-3">{children}</div>
|
|
326
|
-
)}
|
|
340
|
+
{scrollable ? <ScrollArea>{content}</ScrollArea> : content}
|
|
327
341
|
</div>
|
|
328
342
|
</GridViewContext.Provider>
|
|
329
343
|
);
|
|
@@ -350,7 +364,11 @@ function GridViewSection({
|
|
|
350
364
|
return isEmpty && renderEmptyState ? (
|
|
351
365
|
renderEmptyState()
|
|
352
366
|
) : (
|
|
353
|
-
<div
|
|
367
|
+
<div
|
|
368
|
+
role="presentation"
|
|
369
|
+
className={cx("grid text-text", className)}
|
|
370
|
+
style={styles}
|
|
371
|
+
>
|
|
354
372
|
{children}
|
|
355
373
|
</div>
|
|
356
374
|
);
|