@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/List.tsx
CHANGED
|
@@ -3,16 +3,18 @@ import {
|
|
|
3
3
|
memoGeneric,
|
|
4
4
|
useFileDropTarget,
|
|
5
5
|
} from "@noya-app/react-utils";
|
|
6
|
-
import React, { useImperativeHandle, useRef, useState } from "react";
|
|
6
|
+
import React, { memo, useImperativeHandle, useRef, useState } from "react";
|
|
7
7
|
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
11
|
import { CollectionProps, CollectionRef } from "./Collection";
|
|
12
|
-
import {
|
|
12
|
+
import { GridViewSize } from "./Grid";
|
|
13
|
+
import { ListView, ListViewItemInfo } from "./ListView";
|
|
13
14
|
import { TreeView } from "./TreeView";
|
|
15
|
+
|
|
14
16
|
const cssVarOverrides = {
|
|
15
|
-
"--icon-selected": cssVars.colors.primary,
|
|
17
|
+
"--n-icon-selected": cssVars.colors.primary,
|
|
16
18
|
};
|
|
17
19
|
|
|
18
20
|
const emptyArray: string[] = [];
|
|
@@ -42,8 +44,10 @@ export const List = memoGeneric(
|
|
|
42
44
|
itemRoleDescription = "clickable item",
|
|
43
45
|
detailPosition = "end",
|
|
44
46
|
size = "medium",
|
|
47
|
+
thumbnailSize = "auto",
|
|
45
48
|
testHoveredId,
|
|
46
49
|
testRenamingId,
|
|
50
|
+
testShowDropIndicatorId,
|
|
47
51
|
scrollable = false,
|
|
48
52
|
acceptsDrop,
|
|
49
53
|
onMoveItem,
|
|
@@ -52,6 +56,11 @@ export const List = memoGeneric(
|
|
|
52
56
|
renamable,
|
|
53
57
|
selectedIds = emptyArray,
|
|
54
58
|
renderEmptyState,
|
|
59
|
+
sortable,
|
|
60
|
+
getDropTargetParentIndex,
|
|
61
|
+
getPlaceholder,
|
|
62
|
+
onClickItem,
|
|
63
|
+
dragIndicatorStyle,
|
|
55
64
|
} = props;
|
|
56
65
|
|
|
57
66
|
const [internalHoveredId, setHoveredId] = useState<string>();
|
|
@@ -116,19 +125,21 @@ export const List = memoGeneric(
|
|
|
116
125
|
aria-orientation="vertical"
|
|
117
126
|
aria-multiselectable={true}
|
|
118
127
|
expandable={expandable}
|
|
119
|
-
sortable={
|
|
128
|
+
sortable={sortable}
|
|
120
129
|
acceptsDrop={acceptsDrop}
|
|
121
130
|
onMoveItem={onMoveItem}
|
|
122
131
|
renderEmptyState={renderEmptyState}
|
|
132
|
+
getDropTargetParentIndex={getDropTargetParentIndex}
|
|
123
133
|
{...dropTargetProps}
|
|
124
134
|
renderItem={(
|
|
125
135
|
item: T,
|
|
126
136
|
_: number,
|
|
127
|
-
{
|
|
137
|
+
{ isDragOverlay }: ListViewItemInfo
|
|
128
138
|
) => {
|
|
129
139
|
const id = getId(item);
|
|
130
140
|
const isDropdownOpen = dropdownOpenId === id;
|
|
131
|
-
const isHovered =
|
|
141
|
+
const isHovered =
|
|
142
|
+
(hoveredId === id || isDropdownOpen) && !isDragOverlay;
|
|
132
143
|
const expanded = getExpanded?.(item);
|
|
133
144
|
const itemIsRenamable = getRenamable?.(item) ?? renamable;
|
|
134
145
|
const isSelected = selectedIds.includes(id);
|
|
@@ -139,24 +150,25 @@ export const List = memoGeneric(
|
|
|
139
150
|
item,
|
|
140
151
|
selected: isSelected,
|
|
141
152
|
});
|
|
153
|
+
const onOpenChange = (open: boolean) => {
|
|
154
|
+
setDropdownOpenId(open ? id : undefined);
|
|
155
|
+
|
|
156
|
+
if (open && !isSelected) {
|
|
157
|
+
handleSelect(id);
|
|
158
|
+
}
|
|
159
|
+
};
|
|
142
160
|
const action =
|
|
143
161
|
(isHovered || isSelected) &&
|
|
144
162
|
!isRenaming &&
|
|
145
163
|
(typeof renderAction === "function"
|
|
146
|
-
? renderAction(item, isSelected)
|
|
164
|
+
? renderAction({ item, selected: isSelected, onOpenChange })
|
|
147
165
|
: renderAction === "menu" &&
|
|
148
166
|
menuItems && (
|
|
149
167
|
<ActionMenu
|
|
150
168
|
menuItems={menuItems}
|
|
151
169
|
onSelect={(action) => handleMenuAction(action, item)}
|
|
152
170
|
selected={isSelected}
|
|
153
|
-
onOpenChange={
|
|
154
|
-
setDropdownOpenId(open ? id : undefined);
|
|
155
|
-
|
|
156
|
-
if (open && !isSelected) {
|
|
157
|
-
handleSelect(id);
|
|
158
|
-
}
|
|
159
|
-
}}
|
|
171
|
+
onOpenChange={onOpenChange}
|
|
160
172
|
/>
|
|
161
173
|
));
|
|
162
174
|
|
|
@@ -171,14 +183,17 @@ export const List = memoGeneric(
|
|
|
171
183
|
id={id}
|
|
172
184
|
key={id}
|
|
173
185
|
role="option"
|
|
174
|
-
sortable={
|
|
186
|
+
sortable={sortable}
|
|
175
187
|
aria-roledescription={itemRoleDescription}
|
|
176
188
|
aria-label={getName(item)}
|
|
177
189
|
aria-selected={isSelected}
|
|
178
|
-
className={cx("cursor-pointer
|
|
190
|
+
className={cx("cursor-pointer rounded px-1", pyMap[size])}
|
|
179
191
|
backgroundColor={
|
|
180
192
|
isSelected ? cssVars.colors.primaryPastel : undefined
|
|
181
193
|
}
|
|
194
|
+
testRelativeDropPosition={
|
|
195
|
+
testShowDropIndicatorId === id ? "inside" : undefined
|
|
196
|
+
}
|
|
182
197
|
chevronClassName={cx(expandable && "relative left-2")}
|
|
183
198
|
style={cssVarOverrides as React.CSSProperties}
|
|
184
199
|
hovered={isHovered}
|
|
@@ -190,6 +205,7 @@ export const List = memoGeneric(
|
|
|
190
205
|
}
|
|
191
206
|
onPress={(e: ListView.ClickInfo) => {
|
|
192
207
|
handleSelect(id, e);
|
|
208
|
+
onClickItem?.(id);
|
|
193
209
|
}}
|
|
194
210
|
onDoubleClick={() => {
|
|
195
211
|
onDoubleClickItem?.(id);
|
|
@@ -214,45 +230,44 @@ export const List = memoGeneric(
|
|
|
214
230
|
if (!expandable) return;
|
|
215
231
|
setExpanded?.(item, !expanded);
|
|
216
232
|
}}
|
|
233
|
+
dragIndicatorStyle={dragIndicatorStyle}
|
|
217
234
|
>
|
|
218
|
-
<div
|
|
235
|
+
<div
|
|
236
|
+
className={cx("flex flex-1 items-center px-2", rowGapMap[size])}
|
|
237
|
+
>
|
|
219
238
|
{thumbnail && (
|
|
220
239
|
<div
|
|
221
240
|
className={cx(
|
|
222
241
|
"rounded overflow-hidden flex-none flex items-center justify-center",
|
|
223
|
-
|
|
242
|
+
thumbnailSize === "auto" && thumbnailSizeMap[size],
|
|
224
243
|
isSelected && "text-primary"
|
|
225
244
|
)}
|
|
226
|
-
style={{
|
|
227
|
-
backgroundColor: isSelected
|
|
228
|
-
? cssVars.colors.primaryPastel
|
|
229
|
-
: cssVars.colors.inputBackground,
|
|
230
|
-
}}
|
|
231
245
|
tabIndex={-1}
|
|
232
246
|
>
|
|
233
247
|
{thumbnail}
|
|
234
248
|
</div>
|
|
235
249
|
)}
|
|
236
250
|
<div className="flex flex-col flex-1 w-0">
|
|
237
|
-
<div className="flex items-center min-h-
|
|
251
|
+
<div className="flex items-center min-h-input-height flex-1 gap-2">
|
|
238
252
|
<div className="flex-1 w-0 flex items-center" tabIndex={-1}>
|
|
239
253
|
{isRenaming ? (
|
|
240
254
|
<ViewComponent.EditableRowTitle
|
|
241
255
|
value={getName(item)}
|
|
242
|
-
placeholder="Enter name"
|
|
243
|
-
className=
|
|
256
|
+
placeholder={getPlaceholder?.(item) ?? "Enter name"}
|
|
257
|
+
className={fontStyleMap[size]}
|
|
244
258
|
autoFocus={!isTestingRenaming}
|
|
245
259
|
onSubmitEditing={(value: string) => {
|
|
246
|
-
|
|
247
|
-
onRename?.(item, value);
|
|
248
|
-
}
|
|
260
|
+
onRename?.(item, value);
|
|
249
261
|
setRenamingId(undefined);
|
|
250
262
|
}}
|
|
263
|
+
onKeyDown={(e: React.KeyboardEvent) => {
|
|
264
|
+
e.stopPropagation();
|
|
265
|
+
}}
|
|
251
266
|
/>
|
|
252
267
|
) : (
|
|
253
268
|
<ViewComponent.RowTitle
|
|
254
269
|
className={cx(
|
|
255
|
-
|
|
270
|
+
fontStyleMap[size],
|
|
256
271
|
isSelected && "text-primary"
|
|
257
272
|
)}
|
|
258
273
|
>
|
|
@@ -260,30 +275,21 @@ export const List = memoGeneric(
|
|
|
260
275
|
</ViewComponent.RowTitle>
|
|
261
276
|
)}
|
|
262
277
|
</div>
|
|
263
|
-
{end && (
|
|
264
|
-
<
|
|
265
|
-
className={cx(
|
|
266
|
-
"flex items-center gap-2",
|
|
267
|
-
isSelected && "text-primary"
|
|
268
|
-
)}
|
|
269
|
-
tabIndex={-1}
|
|
270
|
-
>
|
|
278
|
+
{end && detailPosition === "end" && (
|
|
279
|
+
<DetailContainer selected={isSelected}>
|
|
271
280
|
{end}
|
|
272
|
-
</
|
|
281
|
+
</DetailContainer>
|
|
273
282
|
)}
|
|
274
283
|
</div>
|
|
275
284
|
{below && (
|
|
276
|
-
<
|
|
277
|
-
className={cx(
|
|
278
|
-
"flex items-center",
|
|
279
|
-
isSelected && "text-primary"
|
|
280
|
-
)}
|
|
281
|
-
tabIndex={-1}
|
|
282
|
-
>
|
|
285
|
+
<DetailContainer selected={isSelected}>
|
|
283
286
|
{below}
|
|
284
|
-
</
|
|
287
|
+
</DetailContainer>
|
|
285
288
|
)}
|
|
286
289
|
</div>
|
|
290
|
+
{end && detailPosition === "below" && (
|
|
291
|
+
<DetailContainer selected={isSelected}>{end}</DetailContainer>
|
|
292
|
+
)}
|
|
287
293
|
</div>
|
|
288
294
|
</ViewComponent.Row>
|
|
289
295
|
);
|
|
@@ -292,3 +298,56 @@ export const List = memoGeneric(
|
|
|
292
298
|
);
|
|
293
299
|
})
|
|
294
300
|
);
|
|
301
|
+
|
|
302
|
+
const DetailContainer = memo(function DetailContainer({
|
|
303
|
+
children,
|
|
304
|
+
selected,
|
|
305
|
+
}: {
|
|
306
|
+
children: React.ReactNode;
|
|
307
|
+
selected: boolean;
|
|
308
|
+
}) {
|
|
309
|
+
return (
|
|
310
|
+
<div
|
|
311
|
+
className={cx("flex items-center gap-2", selected && "text-primary")}
|
|
312
|
+
tabIndex={-1}
|
|
313
|
+
>
|
|
314
|
+
{children}
|
|
315
|
+
</div>
|
|
316
|
+
);
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
const pyMap: Record<GridViewSize, string> = {
|
|
320
|
+
xxs: "py-1",
|
|
321
|
+
xs: "py-1",
|
|
322
|
+
small: "py-1",
|
|
323
|
+
medium: "py-1",
|
|
324
|
+
large: "py-2",
|
|
325
|
+
xl: "py-3",
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
const thumbnailSizeMap: Record<GridViewSize, string> = {
|
|
329
|
+
xxs: "w-4 h-4",
|
|
330
|
+
xs: "w-4 h-4",
|
|
331
|
+
small: "w-6 h-6",
|
|
332
|
+
medium: "w-8 h-8",
|
|
333
|
+
large: "w-16 h-16",
|
|
334
|
+
xl: "w-24 h-24",
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
const rowGapMap: Record<GridViewSize, string> = {
|
|
338
|
+
xxs: "gap-3",
|
|
339
|
+
xs: "gap-3",
|
|
340
|
+
small: "gap-3",
|
|
341
|
+
medium: "gap-3",
|
|
342
|
+
large: "gap-3",
|
|
343
|
+
xl: "gap-4",
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
const fontStyleMap: Record<GridViewSize, string> = {
|
|
347
|
+
xxs: "font-medium",
|
|
348
|
+
xs: "font-medium",
|
|
349
|
+
small: "font-medium",
|
|
350
|
+
medium: "font-medium",
|
|
351
|
+
large: "font-medium",
|
|
352
|
+
xl: "font-medium text-heading4 text-text",
|
|
353
|
+
};
|
|
@@ -25,17 +25,18 @@ import { WindowScroller, WindowScrollerChildProps } from "react-virtualized";
|
|
|
25
25
|
import { ListChildComponentProps, VariableSizeList } from "react-window";
|
|
26
26
|
import { mergeEventHandlers } from "../hooks/mergeEventHandlers";
|
|
27
27
|
import { useHover } from "../hooks/useHover";
|
|
28
|
-
import { cssVars } from "../theme";
|
|
29
|
-
import { cx } from "../utils/classNames";
|
|
28
|
+
import { cssVars, INPUT_HEIGHT } from "../theme";
|
|
29
|
+
import { cx, mergeConflictingClassNames } from "../utils/classNames";
|
|
30
30
|
import { ContextMenu } from "./ContextMenu";
|
|
31
31
|
import { InputField } from "./InputField";
|
|
32
32
|
import { MenuItem } from "./internal/Menu";
|
|
33
33
|
import { ScrollArea } from "./ScrollArea";
|
|
34
34
|
import {
|
|
35
35
|
DropValidator,
|
|
36
|
-
|
|
36
|
+
normalizeListTargetIndex,
|
|
37
37
|
RelativeDropPosition,
|
|
38
38
|
Sortable,
|
|
39
|
+
type SortableItemContextProps,
|
|
39
40
|
} from "./Sortable";
|
|
40
41
|
import { Spacer } from "./Spacer";
|
|
41
42
|
|
|
@@ -43,7 +44,7 @@ export type ListRowMarginType = "none" | "top" | "bottom" | "vertical";
|
|
|
43
44
|
export type ListRowPosition = "only" | "first" | "middle" | "last";
|
|
44
45
|
|
|
45
46
|
const ROW_HEIGHT = 31;
|
|
46
|
-
const SECTION_HEADER_LABEL_HEIGHT =
|
|
47
|
+
const SECTION_HEADER_LABEL_HEIGHT = INPUT_HEIGHT;
|
|
47
48
|
|
|
48
49
|
type ListColorScheme = "primary" | "secondary";
|
|
49
50
|
|
|
@@ -71,7 +72,7 @@ type ListRowContextValue = {
|
|
|
71
72
|
// and the dragged row doesn't have a ListRowContextValue.
|
|
72
73
|
type ListViewDraggingContextValue = {
|
|
73
74
|
indentation: number;
|
|
74
|
-
|
|
75
|
+
isDragOverlay?: boolean;
|
|
75
76
|
};
|
|
76
77
|
|
|
77
78
|
const ListViewDraggingContext = createContext<ListViewDraggingContextValue>({
|
|
@@ -127,6 +128,7 @@ export interface EditableRowProps {
|
|
|
127
128
|
autoFocus: boolean;
|
|
128
129
|
placeholder?: string;
|
|
129
130
|
className?: string;
|
|
131
|
+
onKeyDown?: (e: React.KeyboardEvent) => void;
|
|
130
132
|
}
|
|
131
133
|
|
|
132
134
|
function ListViewEditableRowTitle({
|
|
@@ -135,6 +137,7 @@ function ListViewEditableRowTitle({
|
|
|
135
137
|
autoFocus,
|
|
136
138
|
placeholder,
|
|
137
139
|
className,
|
|
140
|
+
onKeyDown,
|
|
138
141
|
}: EditableRowProps) {
|
|
139
142
|
const inputRef = useRef<HTMLInputElement | null>(null);
|
|
140
143
|
|
|
@@ -161,6 +164,7 @@ function ListViewEditableRowTitle({
|
|
|
161
164
|
onSubmit={onSubmitEditing}
|
|
162
165
|
allowSubmittingWithSameValue
|
|
163
166
|
className={cx("-mx-1.5 -my-1 bg-listview-editing-background", className)}
|
|
167
|
+
onKeyDown={onKeyDown}
|
|
164
168
|
/>
|
|
165
169
|
);
|
|
166
170
|
}
|
|
@@ -266,9 +270,10 @@ const RowContainer = forwardRef<
|
|
|
266
270
|
borderBottomRightRadius: "0px",
|
|
267
271
|
borderBottomLeftRadius: "0px",
|
|
268
272
|
}),
|
|
269
|
-
...($hovered &&
|
|
270
|
-
|
|
271
|
-
|
|
273
|
+
...($hovered &&
|
|
274
|
+
!$selected && {
|
|
275
|
+
background: cssVars.colors.listViewHoverBackground,
|
|
276
|
+
}),
|
|
272
277
|
...($showsActiveState && {
|
|
273
278
|
"&:active": {
|
|
274
279
|
backgroundColor: $selected
|
|
@@ -301,7 +306,7 @@ const RowContainer = forwardRef<
|
|
|
301
306
|
const ListViewDragIndicatorElement = forwardRef<
|
|
302
307
|
HTMLDivElement,
|
|
303
308
|
React.HTMLAttributes<HTMLDivElement> & {
|
|
304
|
-
$relativeDropPosition
|
|
309
|
+
$relativeDropPosition?: RelativeDropPosition;
|
|
305
310
|
$gap: number;
|
|
306
311
|
$offsetLeft: number;
|
|
307
312
|
$colorScheme: ListColorScheme;
|
|
@@ -371,7 +376,7 @@ interface ListViewClickInfo {
|
|
|
371
376
|
ctrlKey: boolean;
|
|
372
377
|
}
|
|
373
378
|
|
|
374
|
-
interface ListViewRowProps<MenuItemType extends string = string> {
|
|
379
|
+
export interface ListViewRowProps<MenuItemType extends string = string> {
|
|
375
380
|
id?: string;
|
|
376
381
|
tabIndex?: number;
|
|
377
382
|
role?: string;
|
|
@@ -398,13 +403,16 @@ interface ListViewRowProps<MenuItemType extends string = string> {
|
|
|
398
403
|
className?: string;
|
|
399
404
|
dragIndicatorStyle?:
|
|
400
405
|
| CSSProperties
|
|
401
|
-
| ((props:
|
|
402
|
-
|
|
403
|
-
indentation: number;
|
|
404
|
-
position: RelativeDropPosition;
|
|
405
|
-
}) => CSSProperties);
|
|
406
|
+
| ((props: DragIndicatorStyleProps) => CSSProperties);
|
|
407
|
+
testRelativeDropPosition?: RelativeDropPosition;
|
|
406
408
|
}
|
|
407
409
|
|
|
410
|
+
export type DragIndicatorStyleProps = {
|
|
411
|
+
depth: number;
|
|
412
|
+
indentation: number;
|
|
413
|
+
position: RelativeDropPosition;
|
|
414
|
+
};
|
|
415
|
+
|
|
408
416
|
const ListViewRow = forwardRefGeneric(function ListViewRow<
|
|
409
417
|
MenuItemType extends string,
|
|
410
418
|
>(
|
|
@@ -432,6 +440,7 @@ const ListViewRow = forwardRefGeneric(function ListViewRow<
|
|
|
432
440
|
style,
|
|
433
441
|
dragIndicatorStyle,
|
|
434
442
|
className,
|
|
443
|
+
testRelativeDropPosition,
|
|
435
444
|
}: ListViewRowProps<MenuItemType>,
|
|
436
445
|
forwardedRef: ForwardedRef<HTMLElement>
|
|
437
446
|
) {
|
|
@@ -451,7 +460,7 @@ const ListViewRow = forwardRefGeneric(function ListViewRow<
|
|
|
451
460
|
const { hoverProps } = useHover({
|
|
452
461
|
onHoverChange,
|
|
453
462
|
});
|
|
454
|
-
const { indentation,
|
|
463
|
+
const { indentation, isDragOverlay } = useContext(ListViewDraggingContext);
|
|
455
464
|
|
|
456
465
|
const handlePress = useCallback(
|
|
457
466
|
(event: React.MouseEvent) => {
|
|
@@ -478,7 +487,7 @@ const ListViewRow = forwardRefGeneric(function ListViewRow<
|
|
|
478
487
|
);
|
|
479
488
|
|
|
480
489
|
const mergedStyle = useMemo(() => {
|
|
481
|
-
return
|
|
490
|
+
return isDragOverlay
|
|
482
491
|
? {
|
|
483
492
|
// TODO: Where do these offsets actually come from?
|
|
484
493
|
transform: `translate3d(-36px, -6px, 0)`,
|
|
@@ -486,11 +495,11 @@ const ListViewRow = forwardRefGeneric(function ListViewRow<
|
|
|
486
495
|
...style,
|
|
487
496
|
}
|
|
488
497
|
: style;
|
|
489
|
-
}, [
|
|
498
|
+
}, [isDragOverlay, style]);
|
|
490
499
|
|
|
491
500
|
const renderContent = (
|
|
492
501
|
{
|
|
493
|
-
relativeDropPosition,
|
|
502
|
+
relativeDropPosition: relativeDropPositionProp,
|
|
494
503
|
...renderProps
|
|
495
504
|
}: React.ComponentProps<typeof RowContainer> & {
|
|
496
505
|
relativeDropPosition?: RelativeDropPosition;
|
|
@@ -498,6 +507,8 @@ const ListViewRow = forwardRefGeneric(function ListViewRow<
|
|
|
498
507
|
ref: Ref<HTMLElement>
|
|
499
508
|
) => {
|
|
500
509
|
const Component = RowContainer;
|
|
510
|
+
const relativeDropPosition =
|
|
511
|
+
testRelativeDropPosition ?? relativeDropPositionProp;
|
|
501
512
|
|
|
502
513
|
const element = (
|
|
503
514
|
<Component
|
|
@@ -520,7 +531,7 @@ const ListViewRow = forwardRefGeneric(function ListViewRow<
|
|
|
520
531
|
$selectedPosition={selectedPosition}
|
|
521
532
|
$showsActiveState={pressEventName === "onClick"}
|
|
522
533
|
aria-selected={selected}
|
|
523
|
-
$divider={!
|
|
534
|
+
$divider={!isDragOverlay && divider}
|
|
524
535
|
onKeyDown={onKeyDown}
|
|
525
536
|
style={mergedStyle}
|
|
526
537
|
{...(renderProps as Partial<React.ComponentProps<typeof RowContainer>>)}
|
|
@@ -534,9 +545,10 @@ const ListViewRow = forwardRefGeneric(function ListViewRow<
|
|
|
534
545
|
>
|
|
535
546
|
{relativeDropPosition && (
|
|
536
547
|
<ListViewDragIndicatorElement
|
|
548
|
+
key={relativeDropPosition}
|
|
537
549
|
$colorScheme={colorScheme}
|
|
538
550
|
$relativeDropPosition={relativeDropPosition}
|
|
539
|
-
$offsetLeft={
|
|
551
|
+
$offsetLeft={depth * indentation}
|
|
540
552
|
$gap={listGap + (divider ? 1 : 0)}
|
|
541
553
|
style={
|
|
542
554
|
typeof dragIndicatorStyle === "function"
|
|
@@ -724,8 +736,9 @@ const VirtualizedList = memo(
|
|
|
724
736
|
* Root
|
|
725
737
|
* ------------------------------------------------------------------------- */
|
|
726
738
|
|
|
727
|
-
type ListViewItemInfo = {
|
|
728
|
-
|
|
739
|
+
export type ListViewItemInfo = {
|
|
740
|
+
isDragOverlay: boolean;
|
|
741
|
+
activeDragIndex?: number;
|
|
729
742
|
};
|
|
730
743
|
|
|
731
744
|
type ChildrenProps = {
|
|
@@ -762,7 +775,7 @@ export type ListViewRootProps = {
|
|
|
762
775
|
expandable?: boolean;
|
|
763
776
|
onMoveItem?: (
|
|
764
777
|
sourceIndex: number,
|
|
765
|
-
|
|
778
|
+
targetIndex: number,
|
|
766
779
|
position: RelativeDropPosition
|
|
767
780
|
) => void;
|
|
768
781
|
indentation?: number;
|
|
@@ -779,6 +792,7 @@ export type ListViewRootProps = {
|
|
|
779
792
|
onDragLeave?: React.DragEventHandler<HTMLDivElement>;
|
|
780
793
|
onDrop?: React.DragEventHandler<HTMLDivElement>;
|
|
781
794
|
renderEmptyState?: () => ReactNode;
|
|
795
|
+
getDropTargetParentIndex?: SortableItemContextProps["getDropTargetParentIndex"];
|
|
782
796
|
};
|
|
783
797
|
|
|
784
798
|
const ListViewRootInner = forwardRefGeneric(function ListViewRootInner<T>(
|
|
@@ -813,6 +827,7 @@ const ListViewRootInner = forwardRefGeneric(function ListViewRootInner<T>(
|
|
|
813
827
|
onDragLeave,
|
|
814
828
|
onDrop,
|
|
815
829
|
renderEmptyState,
|
|
830
|
+
getDropTargetParentIndex,
|
|
816
831
|
}: RenderProps<T> & ListViewRootProps,
|
|
817
832
|
forwardedRef: ForwardedRef<IVirtualizedList>
|
|
818
833
|
) {
|
|
@@ -834,7 +849,7 @@ const ListViewRootInner = forwardRefGeneric(function ListViewRootInner<T>(
|
|
|
834
849
|
);
|
|
835
850
|
|
|
836
851
|
const renderChild = useCallback(
|
|
837
|
-
(index: number) => renderItem(data[index], index, {
|
|
852
|
+
(index: number) => renderItem(data[index], index, { isDragOverlay: false }),
|
|
838
853
|
[data, renderItem]
|
|
839
854
|
);
|
|
840
855
|
|
|
@@ -949,7 +964,7 @@ const ListViewRootInner = forwardRefGeneric(function ListViewRootInner<T>(
|
|
|
949
964
|
);
|
|
950
965
|
|
|
951
966
|
const draggingContextOverlayValue = useMemo(
|
|
952
|
-
() => ({ indentation,
|
|
967
|
+
(): ListViewDraggingContextValue => ({ indentation, isDragOverlay: true }),
|
|
953
968
|
[indentation]
|
|
954
969
|
);
|
|
955
970
|
|
|
@@ -957,7 +972,7 @@ const ListViewRootInner = forwardRefGeneric(function ListViewRootInner<T>(
|
|
|
957
972
|
(index: number) => (
|
|
958
973
|
<div style={{ opacity: 0.25 }}>
|
|
959
974
|
<ListViewDraggingContext.Provider value={draggingContextOverlayValue}>
|
|
960
|
-
{renderItem(data[index], index, {
|
|
975
|
+
{renderItem(data[index], index, { isDragOverlay: true })}
|
|
961
976
|
</ListViewDraggingContext.Provider>
|
|
962
977
|
</div>
|
|
963
978
|
),
|
|
@@ -989,6 +1004,7 @@ const ListViewRootInner = forwardRefGeneric(function ListViewRootInner<T>(
|
|
|
989
1004
|
keys={ids}
|
|
990
1005
|
renderOverlay={renderOverlay}
|
|
991
1006
|
acceptsDrop={acceptsDrop}
|
|
1007
|
+
getDropTargetParentIndex={getDropTargetParentIndex}
|
|
992
1008
|
>
|
|
993
1009
|
{children}
|
|
994
1010
|
</Sortable.Root>
|
|
@@ -1028,9 +1044,14 @@ const ListViewRootInner = forwardRefGeneric(function ListViewRootInner<T>(
|
|
|
1028
1044
|
aria-labelledby={ariaLabelledby}
|
|
1029
1045
|
aria-orientation={ariaOrientation}
|
|
1030
1046
|
aria-multiselectable={ariaMultiselectable}
|
|
1031
|
-
className={
|
|
1032
|
-
|
|
1033
|
-
|
|
1047
|
+
className={mergeConflictingClassNames(
|
|
1048
|
+
[
|
|
1049
|
+
`flex flex-col text-text-muted ${scrollable ? "flex-1" : "flex-none"} `,
|
|
1050
|
+
className,
|
|
1051
|
+
],
|
|
1052
|
+
{
|
|
1053
|
+
categories: ["flex"],
|
|
1054
|
+
}
|
|
1034
1055
|
)}
|
|
1035
1056
|
style={{ ...gapStyle, ...style }}
|
|
1036
1057
|
{...{
|
|
@@ -1140,5 +1161,5 @@ export namespace ListView {
|
|
|
1140
1161
|
menuItemsCount * rowHeight + sectionHeaderCount * sectionHeaderLabelHeight
|
|
1141
1162
|
);
|
|
1142
1163
|
};
|
|
1143
|
-
export const
|
|
1164
|
+
export const normalizeTargetIndex = normalizeListTargetIndex;
|
|
1144
1165
|
}
|
|
@@ -4,7 +4,7 @@ import { cssVars } from "../theme";
|
|
|
4
4
|
import { cx } from "../utils/classNames";
|
|
5
5
|
import { IconName, Icons } from "./Icons";
|
|
6
6
|
|
|
7
|
-
type ColorScheme = "primary" | "icon" | "warning";
|
|
7
|
+
type ColorScheme = "primary" | "secondary" | "icon" | "warning";
|
|
8
8
|
|
|
9
9
|
type AssetType = "image" | "video" | "audio";
|
|
10
10
|
|
|
@@ -31,7 +31,10 @@ type MediaThumbnailProps = {
|
|
|
31
31
|
iconName?: IconName;
|
|
32
32
|
};
|
|
33
33
|
|
|
34
|
-
const
|
|
34
|
+
export const getThumbnailColors = (
|
|
35
|
+
colorScheme: ColorScheme,
|
|
36
|
+
selected: boolean
|
|
37
|
+
) => {
|
|
35
38
|
if (selected) {
|
|
36
39
|
return {
|
|
37
40
|
icon: cssVars.colors.primary,
|
|
@@ -43,18 +46,23 @@ const getColors = (colorScheme: ColorScheme, selected: boolean) => {
|
|
|
43
46
|
case "primary":
|
|
44
47
|
return {
|
|
45
48
|
icon: cssVars.colors.primary,
|
|
46
|
-
background: cssVars.colors.
|
|
49
|
+
background: cssVars.colors.listViewThumbnailBackground,
|
|
50
|
+
};
|
|
51
|
+
case "secondary":
|
|
52
|
+
return {
|
|
53
|
+
icon: cssVars.colors.secondary,
|
|
54
|
+
background: cssVars.colors.secondaryPastel,
|
|
47
55
|
};
|
|
48
56
|
case "warning":
|
|
49
57
|
return {
|
|
50
58
|
icon: cssVars.colors.warning,
|
|
51
|
-
background: cssVars.colors.
|
|
59
|
+
background: cssVars.colors.listViewThumbnailBackground,
|
|
52
60
|
};
|
|
53
61
|
case "icon":
|
|
54
62
|
default:
|
|
55
63
|
return {
|
|
56
64
|
icon: cssVars.colors.icon,
|
|
57
|
-
background: cssVars.colors.
|
|
65
|
+
background: cssVars.colors.listViewThumbnailBackground,
|
|
58
66
|
};
|
|
59
67
|
}
|
|
60
68
|
};
|
|
@@ -72,7 +80,7 @@ export const MediaThumbnail = memo(function MediaThumbnail({
|
|
|
72
80
|
url,
|
|
73
81
|
iconName = "FileIcon",
|
|
74
82
|
}: MediaThumbnailProps) {
|
|
75
|
-
const { icon: iconColor, background: backgroundColor } =
|
|
83
|
+
const { icon: iconColor, background: backgroundColor } = getThumbnailColors(
|
|
76
84
|
colorScheme,
|
|
77
85
|
selected
|
|
78
86
|
);
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
import { MultiplayerUser } from "@noya-app/noya-multiplayer-react";
|
|
1
2
|
import React, { forwardRef, memo, useMemo } from "react";
|
|
2
|
-
import {
|
|
3
|
-
import { Avatar } from "./Avatar";
|
|
3
|
+
import { cssVars, INPUT_HEIGHT } from "../theme";
|
|
4
4
|
import { cx } from "../utils/classNames";
|
|
5
|
-
import { Text } from "./Text";
|
|
6
|
-
import { MultiplayerUser } from "@noya-app/noya-multiplayer-react";
|
|
7
5
|
import { colorFromString } from "../utils/colorFromString";
|
|
8
|
-
import {
|
|
6
|
+
import { Avatar } from "./Avatar";
|
|
7
|
+
import { Logo } from "./NoyaLogo";
|
|
8
|
+
import { Text } from "./Text";
|
|
9
9
|
|
|
10
10
|
export type MessageProps = {
|
|
11
11
|
role: "user" | "assistant" | "system" | "data";
|
|
@@ -17,7 +17,7 @@ export type MessageProps = {
|
|
|
17
17
|
|
|
18
18
|
export const Message = memo(
|
|
19
19
|
forwardRef(function Message(
|
|
20
|
-
{ role, children, user, avatarSize =
|
|
20
|
+
{ role, children, user, avatarSize = INPUT_HEIGHT }: MessageProps,
|
|
21
21
|
ref: React.ForwardedRef<HTMLDivElement>
|
|
22
22
|
) {
|
|
23
23
|
const randomId = crypto.randomUUID();
|
|
@@ -42,9 +42,9 @@ export const Message = memo(
|
|
|
42
42
|
<Avatar
|
|
43
43
|
name="Assistant"
|
|
44
44
|
size={avatarSize}
|
|
45
|
-
backgroundColor={cssVars.colors.
|
|
45
|
+
backgroundColor={cssVars.colors.primaryPastel}
|
|
46
46
|
>
|
|
47
|
-
<
|
|
47
|
+
<Logo style={{ width: 15 }} fill={cssVars.colors.primary} />
|
|
48
48
|
</Avatar>
|
|
49
49
|
) : (
|
|
50
50
|
<Avatar
|