@noya-app/noya-designsystem 0.1.63 → 0.1.64
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 +13 -0
- package/dist/index.css +1 -1
- package/dist/index.d.mts +169 -127
- package/dist/index.d.ts +169 -127
- package/dist/index.js +3131 -2642
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2941 -2459
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -22
- package/src/__tests__/validateDropIndicator.test.ts +26 -41
- package/src/__tests__/workspaceLayout.test.ts +281 -0
- package/src/components/ActionMenu.tsx +2 -0
- package/src/components/ActivityIndicator.tsx +5 -3
- package/src/components/AnimatePresence.tsx +6 -4
- package/src/components/Avatar.tsx +4 -2
- package/src/components/BaseToolbar.tsx +45 -34
- package/src/components/Breadcrumbs.tsx +2 -0
- package/src/components/Button.tsx +9 -3
- package/src/components/Chip.tsx +2 -0
- package/src/components/Collection.tsx +4 -1
- package/src/components/ColorSwatch.tsx +42 -22
- package/src/components/ColorSwatchControl.tsx +5 -3
- package/src/components/Combobox.tsx +2 -0
- package/src/components/CommandPalette.tsx +2 -0
- package/src/components/ContextMenu.tsx +3 -1
- package/src/components/Dialog.tsx +3 -1
- package/src/components/DimensionInput.tsx +2 -0
- package/src/components/Divider.tsx +10 -6
- package/src/components/DraggableMenuButton.tsx +2 -0
- package/src/components/Drawer.tsx +11 -3
- package/src/components/DropdownMenu.tsx +3 -1
- package/src/components/EditableText.tsx +2 -0
- package/src/components/FileUploadIndicator.tsx +108 -0
- package/src/components/FillPreviewBackground.tsx +2 -0
- package/src/components/FloatingWindow.tsx +2 -0
- package/src/components/GradientPicker.tsx +2 -0
- package/src/components/Grid.tsx +47 -38
- package/src/components/GridView.tsx +33 -11
- package/src/components/IconButton.tsx +2 -0
- package/src/components/Icons.tsx +1 -1
- package/src/components/InputField.tsx +2 -0
- package/src/components/Label.tsx +1 -1
- package/src/components/LabeledElementView.tsx +6 -2
- package/src/components/LabeledField.tsx +2 -0
- package/src/components/List.tsx +10 -2
- package/src/components/ListView.tsx +27 -14
- package/src/components/MediaThumbnail.tsx +31 -2
- package/src/components/Message.tsx +8 -9
- package/src/components/Popover.tsx +3 -1
- package/src/components/Progress.tsx +20 -7
- package/src/components/ScrollArea.tsx +3 -1
- package/src/components/SearchCompletionMenu.tsx +2 -0
- package/src/components/Section.tsx +2 -0
- package/src/components/SegmentedControl.tsx +42 -16
- package/src/components/SelectMenu.tsx +3 -1
- package/src/components/SelectionToolbar.tsx +3 -1
- package/src/components/Slider.tsx +3 -1
- package/src/components/Switch.tsx +3 -1
- package/src/components/Tabs.tsx +3 -1
- package/src/components/Text.tsx +6 -5
- package/src/components/TextArea.tsx +2 -0
- package/src/components/Toast.tsx +1 -1
- package/src/components/Toolbar.tsx +8 -2
- package/src/components/ToolbarDrawer.tsx +29 -0
- package/src/components/Tooltip.tsx +1 -1
- package/src/components/TreeView.tsx +2 -0
- package/src/components/UserPointer.tsx +2 -0
- package/src/components/ai-assistant/AIAssistantLayout.tsx +2 -0
- package/src/components/blocks/ImageBlockComponent.tsx +156 -0
- package/src/components/connected-users-menu/ConnectedUsersMenuLayout.tsx +2 -0
- package/src/components/file-explorer/FileExplorerLayout.tsx +2 -0
- package/src/components/internal/Checkmark.tsx +24 -0
- package/src/components/internal/Menu.tsx +2 -1
- package/src/components/internal/MenuViewport.tsx +4 -2
- package/src/components/internal/SelectItem.tsx +4 -23
- package/src/components/internal/TextInput.tsx +2 -0
- package/src/components/sorting/DragRegistration.tsx +8 -4
- package/src/components/sorting/SharedDragProvider.tsx +43 -18
- package/src/components/sorting/Sortable.tsx +19 -10
- package/src/components/sorting/createSharedDrag.tsx +7 -6
- package/src/components/sorting/sorting.ts +6 -9
- package/src/components/workspace/DrawerWorkspaceLayout.tsx +107 -26
- package/src/components/workspace/PanelWorkspaceLayout.tsx +98 -65
- package/src/components/workspace/VerticalTabMenu.tsx +36 -0
- package/src/components/workspace/WorkspaceLayout.tsx +46 -42
- package/src/components/workspace/constants.ts +4 -0
- package/src/components/workspace/panelStorage.ts +216 -0
- package/src/components/workspace/types.ts +11 -4
- package/src/contexts/DesignSystemConfiguration.tsx +12 -5
- package/src/contexts/DialogContext.tsx +2 -0
- package/src/contexts/FloatingWindowContext.tsx +2 -0
- package/src/contexts/GlobalInputBlurContext.tsx +2 -0
- package/src/contexts/ImageDataContext.tsx +2 -0
- package/src/contexts/LinkComponentContext.tsx +17 -0
- package/src/contexts/OpenPortalsContext.tsx +2 -0
- package/src/contexts/PortalScopeContext.tsx +2 -0
- package/src/hooks/mergeEventHandlers.ts +1 -1
- package/src/hooks/useHover.ts +30 -17
- package/src/hooks/useIndent.ts +2 -0
- package/src/hooks/useLabel.ts +2 -0
- package/src/hooks/useObjectURL.ts +5 -3
- package/src/hooks/usePlatform.ts +5 -3
- package/src/hooks/useTheme.ts +3 -1
- package/src/index.css +19 -0
- package/src/index.tsx +5 -2
- package/src/utils/classNames.ts +4 -3
- package/src/utils/combobox.ts +2 -0
- package/src/utils/formatByteSize.ts +8 -0
- package/src/utils/withSeparatorElements.ts +1 -1
- package/src/hooks/usePreservePanelSize.tsx +0 -183
- package/src/mediaQuery.ts +0 -13
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import { KeyModifiers } from "@noya-app/noya-keymap";
|
|
2
4
|
import { forwardRefGeneric, memoGeneric } from "@noya-app/react-utils";
|
|
3
5
|
import React, {
|
|
@@ -11,6 +13,7 @@ import React, {
|
|
|
11
13
|
useContext,
|
|
12
14
|
useMemo,
|
|
13
15
|
} from "react";
|
|
16
|
+
import { useLinkComponent } from "../contexts/LinkComponentContext";
|
|
14
17
|
import { useHover } from "../hooks/useHover";
|
|
15
18
|
import { cx, mergeConflictingClassNames } from "../utils/classNames";
|
|
16
19
|
import withSeparatorElements from "../utils/withSeparatorElements";
|
|
@@ -79,6 +82,7 @@ const SectionTitle = ({
|
|
|
79
82
|
|
|
80
83
|
interface ItemProps<MenuItemType extends string = string> {
|
|
81
84
|
id: string;
|
|
85
|
+
href?: string;
|
|
82
86
|
title?: ReactNode;
|
|
83
87
|
subtitle?: ReactNode;
|
|
84
88
|
loading?: boolean;
|
|
@@ -105,6 +109,7 @@ const GridViewItem = forwardRefGeneric(function GridViewItem<
|
|
|
105
109
|
>(
|
|
106
110
|
{
|
|
107
111
|
id,
|
|
112
|
+
href,
|
|
108
113
|
title,
|
|
109
114
|
subtitle,
|
|
110
115
|
loading,
|
|
@@ -125,23 +130,27 @@ const GridViewItem = forwardRefGeneric(function GridViewItem<
|
|
|
125
130
|
testShowInsideDropIndicator: showInsideDropIndicator = false,
|
|
126
131
|
...props
|
|
127
132
|
}: ItemProps<MenuItemType>,
|
|
128
|
-
forwardedRef: ForwardedRef<
|
|
133
|
+
forwardedRef: ForwardedRef<HTMLElement>
|
|
129
134
|
) {
|
|
130
135
|
const { hoverProps } = useHover({
|
|
131
136
|
onHoverChange,
|
|
132
137
|
});
|
|
133
138
|
|
|
134
|
-
const { textPosition, bordered, disabled } =
|
|
139
|
+
const { textPosition, bordered, disabled, alwaysShowSubtitles } =
|
|
140
|
+
useContext(GridViewContext);
|
|
135
141
|
|
|
136
142
|
const handleClick = useCallback(
|
|
137
143
|
(event: React.MouseEvent) => {
|
|
138
144
|
event.stopPropagation();
|
|
139
|
-
|
|
145
|
+
|
|
146
|
+
if (!href) {
|
|
147
|
+
event.preventDefault();
|
|
148
|
+
}
|
|
140
149
|
|
|
141
150
|
onClick?.(event);
|
|
142
151
|
onSelect?.(event);
|
|
143
152
|
},
|
|
144
|
-
[onClick, onSelect]
|
|
153
|
+
[href, onClick, onSelect]
|
|
145
154
|
);
|
|
146
155
|
|
|
147
156
|
const handleKeyDown = useCallback(
|
|
@@ -159,8 +168,11 @@ const GridViewItem = forwardRefGeneric(function GridViewItem<
|
|
|
159
168
|
[onSelect, onKeyDown]
|
|
160
169
|
);
|
|
161
170
|
|
|
171
|
+
const LinkComponent = useLinkComponent();
|
|
172
|
+
const Component = typeof href === "string" ? LinkComponent : "div";
|
|
173
|
+
|
|
162
174
|
let element = (
|
|
163
|
-
<
|
|
175
|
+
<Component
|
|
164
176
|
{...props}
|
|
165
177
|
className={cx(
|
|
166
178
|
"flex flex-col relative rounded p-2 -m-2 text-text",
|
|
@@ -173,7 +185,8 @@ const GridViewItem = forwardRefGeneric(function GridViewItem<
|
|
|
173
185
|
"focus:ring-2 focus:ring-primary focus:ring-inset focus:outline-none"
|
|
174
186
|
)}
|
|
175
187
|
id={id}
|
|
176
|
-
|
|
188
|
+
href={href}
|
|
189
|
+
ref={forwardedRef as ForwardedRef<HTMLAnchorElement & HTMLDivElement>}
|
|
177
190
|
{...hoverProps}
|
|
178
191
|
tabIndex={disabled ? undefined : 0}
|
|
179
192
|
onKeyDown={handleKeyDown}
|
|
@@ -194,8 +207,12 @@ const GridViewItem = forwardRefGeneric(function GridViewItem<
|
|
|
194
207
|
<>
|
|
195
208
|
<Spacer.Vertical size={8} />
|
|
196
209
|
<ItemTitle>{title || " "}</ItemTitle>
|
|
197
|
-
|
|
198
|
-
|
|
210
|
+
{(alwaysShowSubtitles || subtitle) && (
|
|
211
|
+
<>
|
|
212
|
+
<Spacer.Vertical size={2} />
|
|
213
|
+
<ItemDescription>{subtitle || " "}</ItemDescription>
|
|
214
|
+
</>
|
|
215
|
+
)}
|
|
199
216
|
</>
|
|
200
217
|
)}
|
|
201
218
|
{textPosition === "overlay" && hovered && (title || subtitle) && (
|
|
@@ -216,7 +233,7 @@ const GridViewItem = forwardRefGeneric(function GridViewItem<
|
|
|
216
233
|
<ActivityIndicator opacity={0.5} size={13} />
|
|
217
234
|
</div>
|
|
218
235
|
)}
|
|
219
|
-
</
|
|
236
|
+
</Component>
|
|
220
237
|
);
|
|
221
238
|
|
|
222
239
|
if (menuItems && onSelectMenuItem) {
|
|
@@ -255,6 +272,7 @@ type GridViewContextValue = {
|
|
|
255
272
|
bordered: boolean;
|
|
256
273
|
disabled: boolean;
|
|
257
274
|
gap: number;
|
|
275
|
+
alwaysShowSubtitles: boolean;
|
|
258
276
|
};
|
|
259
277
|
|
|
260
278
|
const GridViewContext = createContext<GridViewContextValue>({
|
|
@@ -263,6 +281,7 @@ const GridViewContext = createContext<GridViewContextValue>({
|
|
|
263
281
|
bordered: false,
|
|
264
282
|
disabled: false,
|
|
265
283
|
gap: 0,
|
|
284
|
+
alwaysShowSubtitles: false,
|
|
266
285
|
});
|
|
267
286
|
|
|
268
287
|
interface GridViewRootProps extends Partial<GridViewContextValue> {
|
|
@@ -277,6 +296,7 @@ interface GridViewRootProps extends Partial<GridViewContextValue> {
|
|
|
277
296
|
role?: string;
|
|
278
297
|
renderEmptyState?: () => ReactNode;
|
|
279
298
|
contentClassName?: string;
|
|
299
|
+
alwaysShowSubtitles?: boolean;
|
|
280
300
|
}
|
|
281
301
|
|
|
282
302
|
const GridViewRoot = forwardRef(function GridViewRoot(
|
|
@@ -291,6 +311,7 @@ const GridViewRoot = forwardRef(function GridViewRoot(
|
|
|
291
311
|
disabled = false,
|
|
292
312
|
className,
|
|
293
313
|
contentClassName,
|
|
314
|
+
alwaysShowSubtitles = false,
|
|
294
315
|
...props
|
|
295
316
|
}: GridViewRootProps,
|
|
296
317
|
forwardedRef: ForwardedRef<HTMLDivElement>
|
|
@@ -306,14 +327,15 @@ const GridViewRoot = forwardRef(function GridViewRoot(
|
|
|
306
327
|
);
|
|
307
328
|
|
|
308
329
|
const contextValue = useMemo(
|
|
309
|
-
() => ({
|
|
330
|
+
(): GridViewContextValue => ({
|
|
310
331
|
minColumnWidth,
|
|
311
332
|
textPosition,
|
|
312
333
|
bordered,
|
|
313
334
|
disabled,
|
|
314
335
|
gap,
|
|
336
|
+
alwaysShowSubtitles,
|
|
315
337
|
}),
|
|
316
|
-
[bordered, disabled, gap, minColumnWidth, textPosition]
|
|
338
|
+
[bordered, disabled, gap, minColumnWidth, textPosition, alwaysShowSubtitles]
|
|
317
339
|
);
|
|
318
340
|
|
|
319
341
|
const mergedClassName = useMemo(() => {
|
package/src/components/Icons.tsx
CHANGED
package/src/components/Label.tsx
CHANGED
|
@@ -5,7 +5,7 @@ export interface LabelProps extends LabelHTMLAttributes<HTMLLabelElement> {}
|
|
|
5
5
|
|
|
6
6
|
const labelStyles = "flex items-center select-none z-label relative";
|
|
7
7
|
const labelTextStyles =
|
|
8
|
-
"font-sans text-label uppercase leading-
|
|
8
|
+
"font-sans text-label uppercase leading-none font-bold text-text-muted";
|
|
9
9
|
|
|
10
10
|
export const Label = memo(
|
|
11
11
|
forwardRef<HTMLLabelElement, LabelProps>(function Label(
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import * as kiwi from "kiwi.js";
|
|
2
4
|
import * as React from "react";
|
|
3
5
|
|
|
@@ -13,11 +15,13 @@ export const LabeledElementView = React.memo(function LabeledElementView({
|
|
|
13
15
|
const elementIds: string[] = React.Children.toArray(children)
|
|
14
16
|
.flatMap((child) =>
|
|
15
17
|
React.isValidElement(child) && child.type === React.Fragment
|
|
16
|
-
? (child.props.children as React.ReactNode[])
|
|
18
|
+
? ((child as any).props.children as React.ReactNode[])
|
|
17
19
|
: [child]
|
|
18
20
|
)
|
|
19
21
|
.map((child) =>
|
|
20
|
-
React.isValidElement(child) && "id" in child
|
|
22
|
+
React.isValidElement(child) && "id" in (child as any).props
|
|
23
|
+
? (child as any).props.id
|
|
24
|
+
: null
|
|
21
25
|
)
|
|
22
26
|
.filter((id) => !!id);
|
|
23
27
|
const serializedIds = elementIds.join(",");
|
package/src/components/List.tsx
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import {
|
|
2
4
|
forwardRefGeneric,
|
|
3
5
|
memoGeneric,
|
|
4
6
|
useFileDropTarget,
|
|
5
7
|
} from "@noya-app/react-utils";
|
|
6
8
|
import React, { memo, useImperativeHandle, useRef, useState } from "react";
|
|
9
|
+
import { useLinkComponent } from "../contexts/LinkComponentContext";
|
|
7
10
|
import { cssVars } from "../theme";
|
|
8
11
|
import { cx } from "../utils/classNames";
|
|
9
12
|
import { updateSelection } from "../utils/selection";
|
|
@@ -32,6 +35,7 @@ export const List = memoGeneric(
|
|
|
32
35
|
items,
|
|
33
36
|
getId,
|
|
34
37
|
getName,
|
|
38
|
+
getHref,
|
|
35
39
|
expandable,
|
|
36
40
|
getExpanded,
|
|
37
41
|
getRenamable,
|
|
@@ -101,8 +105,9 @@ export const List = memoGeneric(
|
|
|
101
105
|
};
|
|
102
106
|
|
|
103
107
|
const ViewComponent = expandable ? TreeView : ListView;
|
|
108
|
+
const LinkComponent = useLinkComponent();
|
|
104
109
|
|
|
105
|
-
const fileDropTargetRef = useRef<HTMLDivElement>(null);
|
|
110
|
+
const fileDropTargetRef = useRef<HTMLDivElement | null>(null);
|
|
106
111
|
const { isDropTargetActive, dropTargetProps } = useFileDropTarget(
|
|
107
112
|
fileDropTargetRef,
|
|
108
113
|
onFilesDrop
|
|
@@ -144,6 +149,7 @@ export const List = memoGeneric(
|
|
|
144
149
|
{ isDragOverlay }: ListViewItemInfo
|
|
145
150
|
) => {
|
|
146
151
|
const id = getId(item);
|
|
152
|
+
const href = getHref?.(item);
|
|
147
153
|
const isDropdownOpen = dropdownOpenId === id;
|
|
148
154
|
const isHovered =
|
|
149
155
|
(hoveredId === id || isDropdownOpen) && !isDragOverlay;
|
|
@@ -197,6 +203,8 @@ export const List = memoGeneric(
|
|
|
197
203
|
|
|
198
204
|
return (
|
|
199
205
|
<ViewComponent.Row
|
|
206
|
+
as={typeof href === "string" ? LinkComponent : undefined}
|
|
207
|
+
href={href}
|
|
200
208
|
id={id}
|
|
201
209
|
key={id}
|
|
202
210
|
role="option"
|
|
@@ -355,7 +363,7 @@ const rowGapMap: Record<CollectionItemSize, string> = {
|
|
|
355
363
|
xxs: "gap-2",
|
|
356
364
|
xs: "gap-2",
|
|
357
365
|
small: "gap-2",
|
|
358
|
-
medium: "gap-
|
|
366
|
+
medium: "gap-2",
|
|
359
367
|
mediumLarge: "gap-3",
|
|
360
368
|
large: "gap-3",
|
|
361
369
|
xl: "gap-4",
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import { Size } from "@noya-app/noya-geometry";
|
|
2
4
|
import { range } from "@noya-app/noya-utils";
|
|
3
5
|
import { forwardRefGeneric, memoGeneric } from "@noya-app/react-utils";
|
|
@@ -192,10 +194,14 @@ const RowContainer = forwardRef<
|
|
|
192
194
|
$gap: number;
|
|
193
195
|
$backgroundColor?: CSSProperties["backgroundColor"];
|
|
194
196
|
$clickable?: boolean;
|
|
197
|
+
href?: string;
|
|
198
|
+
as?: React.ElementType;
|
|
195
199
|
}
|
|
196
200
|
>(
|
|
197
201
|
(
|
|
198
202
|
{
|
|
203
|
+
as: Component = "div",
|
|
204
|
+
href,
|
|
199
205
|
className,
|
|
200
206
|
$marginType,
|
|
201
207
|
$selected,
|
|
@@ -222,8 +228,9 @@ const RowContainer = forwardRef<
|
|
|
222
228
|
ref
|
|
223
229
|
) => {
|
|
224
230
|
return (
|
|
225
|
-
<
|
|
231
|
+
<Component
|
|
226
232
|
ref={ref}
|
|
233
|
+
href={href}
|
|
227
234
|
role={role}
|
|
228
235
|
aria-label={ariaLabel}
|
|
229
236
|
aria-roledescription={ariaRoleDescription}
|
|
@@ -363,7 +370,7 @@ const ListViewDragIndicatorElement = forwardRef<
|
|
|
363
370
|
backgroundColor:
|
|
364
371
|
$colorScheme === "secondary"
|
|
365
372
|
? cssVars.colors.secondary
|
|
366
|
-
: cssVars.colors.
|
|
373
|
+
: cssVars.colors.dragOutline,
|
|
367
374
|
border: `2px solid white`,
|
|
368
375
|
boxShadow: "0 0 2px rgba(0,0,0,0.5)",
|
|
369
376
|
}),
|
|
@@ -410,6 +417,8 @@ export interface ListViewRowProps<MenuItemType extends string = string> {
|
|
|
410
417
|
| CSSProperties
|
|
411
418
|
| ((props: DragIndicatorStyleProps) => CSSProperties);
|
|
412
419
|
testRelativeDropPosition?: RelativeDropPosition;
|
|
420
|
+
href?: string;
|
|
421
|
+
as?: React.ElementType;
|
|
413
422
|
}
|
|
414
423
|
|
|
415
424
|
export type DragIndicatorStyleProps = {
|
|
@@ -446,6 +455,8 @@ const ListViewRow = forwardRefGeneric(function ListViewRow<
|
|
|
446
455
|
dragIndicatorStyle,
|
|
447
456
|
className,
|
|
448
457
|
testRelativeDropPosition,
|
|
458
|
+
href,
|
|
459
|
+
as,
|
|
449
460
|
}: ListViewRowProps<MenuItemType>,
|
|
450
461
|
forwardedRef: ForwardedRef<HTMLElement>
|
|
451
462
|
) {
|
|
@@ -472,7 +483,7 @@ const ListViewRow = forwardRefGeneric(function ListViewRow<
|
|
|
472
483
|
// We use preventDefault as a hack to mark this event as handled. We check for
|
|
473
484
|
// this in the ListView.Root. We can't stopPropagation here or existing ContextMenus
|
|
474
485
|
// won't close (onPointerDownOutside won't fire).
|
|
475
|
-
event.preventDefault();
|
|
486
|
+
// event.preventDefault();
|
|
476
487
|
|
|
477
488
|
// We only want to handle left clicks
|
|
478
489
|
if (event.button !== 0) return;
|
|
@@ -517,6 +528,8 @@ const ListViewRow = forwardRefGeneric(function ListViewRow<
|
|
|
517
528
|
|
|
518
529
|
const element = (
|
|
519
530
|
<Component
|
|
531
|
+
as={as}
|
|
532
|
+
href={href}
|
|
520
533
|
ref={ref as any}
|
|
521
534
|
$colorScheme={colorScheme}
|
|
522
535
|
onContextMenu={onContextMenu}
|
|
@@ -787,7 +800,7 @@ export type ListViewRootProps = {
|
|
|
787
800
|
divider?: boolean;
|
|
788
801
|
gap?: number;
|
|
789
802
|
colorScheme?: ListColorScheme;
|
|
790
|
-
containerRef?: React.RefObject<HTMLDivElement>;
|
|
803
|
+
containerRef?: React.RefObject<HTMLDivElement | null>;
|
|
791
804
|
onDragOver?: React.DragEventHandler<HTMLDivElement>;
|
|
792
805
|
onDragEnter?: React.DragEventHandler<HTMLDivElement>;
|
|
793
806
|
onDragLeave?: React.DragEventHandler<HTMLDivElement>;
|
|
@@ -897,18 +910,18 @@ const ListViewRootInner = forwardRefGeneric(function ListViewRootInner<T>(
|
|
|
897
910
|
const prevChild = i - 1 >= 0 && renderChild(i - 1);
|
|
898
911
|
const nextChild = i + 1 < data.length && renderChild(i + 1);
|
|
899
912
|
|
|
900
|
-
const next: ReactElement | undefined = isValidElement(nextChild)
|
|
913
|
+
const next: ReactElement<any> | undefined = isValidElement(nextChild)
|
|
901
914
|
? nextChild
|
|
902
915
|
: undefined;
|
|
903
|
-
const prev: ReactElement | undefined = isValidElement(prevChild)
|
|
916
|
+
const prev: ReactElement<any> | undefined = isValidElement(prevChild)
|
|
904
917
|
? prevChild
|
|
905
918
|
: undefined;
|
|
906
919
|
|
|
907
920
|
const hasMarginTop = !prev;
|
|
908
921
|
const hasMarginBottom =
|
|
909
922
|
!next ||
|
|
910
|
-
current.props.isSectionHeader ||
|
|
911
|
-
(next && next.props.isSectionHeader);
|
|
923
|
+
(current as any).props.isSectionHeader ||
|
|
924
|
+
(next && (next as any).props.isSectionHeader);
|
|
912
925
|
|
|
913
926
|
let marginType: ListRowMarginType;
|
|
914
927
|
|
|
@@ -924,11 +937,11 @@ const ListViewRootInner = forwardRefGeneric(function ListViewRootInner<T>(
|
|
|
924
937
|
|
|
925
938
|
let selectedPosition: ListRowPosition = "only";
|
|
926
939
|
|
|
927
|
-
if (current.props.selected) {
|
|
940
|
+
if ((current as any).props.selected) {
|
|
928
941
|
const nextSelected =
|
|
929
|
-
next && !next.props.isSectionHeader && next.props.selected;
|
|
942
|
+
next && !next.props.isSectionHeader && (next as any).props.selected;
|
|
930
943
|
const prevSelected =
|
|
931
|
-
prev && !prev.props.isSectionHeader && prev.props.selected;
|
|
944
|
+
prev && !prev.props.isSectionHeader && (prev as any).props.selected;
|
|
932
945
|
|
|
933
946
|
if (nextSelected && prevSelected) {
|
|
934
947
|
selectedPosition = "middle";
|
|
@@ -949,7 +962,7 @@ const ListViewRootInner = forwardRefGeneric(function ListViewRootInner<T>(
|
|
|
949
962
|
pressEventName,
|
|
950
963
|
variant,
|
|
951
964
|
sectionHeaderVariant,
|
|
952
|
-
isSectionHeader: current.props.isSectionHeader,
|
|
965
|
+
isSectionHeader: (current as any).props.isSectionHeader,
|
|
953
966
|
gap,
|
|
954
967
|
};
|
|
955
968
|
},
|
|
@@ -1100,7 +1113,7 @@ const ChildrenListViewInner = forwardRef(function ChildrenListViewInner(
|
|
|
1100
1113
|
{ children, ...rest }: ChildrenProps & ListViewRootProps,
|
|
1101
1114
|
forwardedRef: ForwardedRef<IVirtualizedList>
|
|
1102
1115
|
) {
|
|
1103
|
-
const items: ReactElement[] = useMemo(
|
|
1116
|
+
const items: ReactElement<any>[] = useMemo(
|
|
1104
1117
|
() =>
|
|
1105
1118
|
Children.toArray(children).flatMap((child) =>
|
|
1106
1119
|
isValidElement(child) ? [child] : []
|
|
@@ -1118,7 +1131,7 @@ const ChildrenListViewInner = forwardRef(function ChildrenListViewInner(
|
|
|
1118
1131
|
typeof key === "string" ? key : (key ?? index).toString(),
|
|
1119
1132
|
[]
|
|
1120
1133
|
)}
|
|
1121
|
-
renderItem={useCallback((item: ReactElement) => item, [])}
|
|
1134
|
+
renderItem={useCallback((item: ReactElement<any>) => item, [])}
|
|
1122
1135
|
/>
|
|
1123
1136
|
);
|
|
1124
1137
|
});
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import {
|
|
2
4
|
FileIcon,
|
|
3
5
|
ImageIcon,
|
|
6
|
+
NoyaIcon,
|
|
4
7
|
SpeakerLoudIcon,
|
|
5
8
|
VideoIcon,
|
|
6
9
|
} from "@noya-app/noya-icons";
|
|
@@ -23,7 +26,12 @@ const getAssetType = (contentType?: string): AssetType | undefined => {
|
|
|
23
26
|
return undefined;
|
|
24
27
|
};
|
|
25
28
|
|
|
26
|
-
type
|
|
29
|
+
export type RenderThumbnailIconProps = {
|
|
30
|
+
fileName?: string;
|
|
31
|
+
contentType?: string;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export type MediaThumbnailProps = {
|
|
27
35
|
contentType?: string;
|
|
28
36
|
url?: string;
|
|
29
37
|
selected?: boolean;
|
|
@@ -39,6 +47,7 @@ type MediaThumbnailProps = {
|
|
|
39
47
|
size?: CollectionItemSize;
|
|
40
48
|
|
|
41
49
|
fileName?: string;
|
|
50
|
+
renderThumbnailIcon?: (props: RenderThumbnailIconProps) => React.ReactNode;
|
|
42
51
|
};
|
|
43
52
|
|
|
44
53
|
export const getThumbnailColors = (
|
|
@@ -86,6 +95,7 @@ export const MediaThumbnail = memo(function MediaThumbnail({
|
|
|
86
95
|
iconName,
|
|
87
96
|
size = "medium",
|
|
88
97
|
fileName,
|
|
98
|
+
renderThumbnailIcon,
|
|
89
99
|
}: MediaThumbnailProps) {
|
|
90
100
|
const { icon: iconColor, background: backgroundColor } = getThumbnailColors(
|
|
91
101
|
colorScheme,
|
|
@@ -101,6 +111,12 @@ export const MediaThumbnail = memo(function MediaThumbnail({
|
|
|
101
111
|
);
|
|
102
112
|
|
|
103
113
|
const content = useMemo(() => {
|
|
114
|
+
if (renderThumbnailIcon) {
|
|
115
|
+
const rendered = renderThumbnailIcon({ fileName, contentType });
|
|
116
|
+
|
|
117
|
+
if (rendered) return rendered;
|
|
118
|
+
}
|
|
119
|
+
|
|
104
120
|
switch (contentType) {
|
|
105
121
|
case "image":
|
|
106
122
|
if (!url) return <ImageIcon color={iconColor} style={iconStyles} />;
|
|
@@ -124,7 +140,12 @@ export const MediaThumbnail = memo(function MediaThumbnail({
|
|
|
124
140
|
}
|
|
125
141
|
|
|
126
142
|
if (fileName) {
|
|
143
|
+
if (fileName.endsWith(".noya")) {
|
|
144
|
+
return <NoyaIcon color={iconColor} style={iconStyles} />;
|
|
145
|
+
}
|
|
146
|
+
|
|
127
147
|
const fileIcon = findFileIcon(fileName);
|
|
148
|
+
|
|
128
149
|
if (fileIcon) {
|
|
129
150
|
return (
|
|
130
151
|
<img
|
|
@@ -138,7 +159,15 @@ export const MediaThumbnail = memo(function MediaThumbnail({
|
|
|
138
159
|
|
|
139
160
|
return <FileIcon color={iconColor} style={iconStyles} />;
|
|
140
161
|
}
|
|
141
|
-
}, [
|
|
162
|
+
}, [
|
|
163
|
+
contentType,
|
|
164
|
+
url,
|
|
165
|
+
iconColor,
|
|
166
|
+
iconStyles,
|
|
167
|
+
iconName,
|
|
168
|
+
renderThumbnailIcon,
|
|
169
|
+
fileName,
|
|
170
|
+
]);
|
|
142
171
|
|
|
143
172
|
return (
|
|
144
173
|
<div
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import { MultiplayerUser } from "@noya-app/noya-multiplayer-react";
|
|
4
|
+
import { uuid } from "@noya-app/noya-utils";
|
|
2
5
|
import React, { forwardRef, memo, useMemo } from "react";
|
|
3
6
|
import { cssVars, INPUT_HEIGHT } from "../theme";
|
|
4
7
|
import { cx } from "../utils/classNames";
|
|
5
8
|
import { colorFromString } from "../utils/colorFromString";
|
|
6
9
|
import { Avatar } from "./Avatar";
|
|
7
10
|
import { Logo } from "./NoyaLogo";
|
|
8
|
-
import { Text } from "./Text";
|
|
9
11
|
|
|
10
12
|
export type MessageProps = {
|
|
11
13
|
role: "user" | "assistant" | "system" | "data";
|
|
@@ -20,7 +22,7 @@ export const Message = memo(
|
|
|
20
22
|
{ role, children, user, avatarSize = INPUT_HEIGHT }: MessageProps,
|
|
21
23
|
ref: React.ForwardedRef<HTMLDivElement>
|
|
22
24
|
) {
|
|
23
|
-
const randomId =
|
|
25
|
+
const randomId = uuid();
|
|
24
26
|
const userMessageBackgroundColor = colorFromString(user?.id ?? randomId);
|
|
25
27
|
const styles = useMemo(
|
|
26
28
|
() =>
|
|
@@ -56,18 +58,15 @@ export const Message = memo(
|
|
|
56
58
|
)}
|
|
57
59
|
<div
|
|
58
60
|
className={cx(
|
|
59
|
-
"
|
|
61
|
+
"markdown-message",
|
|
62
|
+
"flex flex-row gap-2 rounded-lg py-2 px-3 transition-all duration-200 max-w-[70%] text-sm",
|
|
63
|
+
role === "user" ? "text-white" : "text-text",
|
|
60
64
|
role === "user" ? "ml-auto" : "bg-input-background"
|
|
61
65
|
)}
|
|
62
66
|
style={styles}
|
|
63
67
|
ref={ref}
|
|
64
68
|
>
|
|
65
|
-
|
|
66
|
-
variant="small"
|
|
67
|
-
className={role === "user" ? "text-white" : "text-text"}
|
|
68
|
-
>
|
|
69
|
-
{children}
|
|
70
|
-
</Text>
|
|
69
|
+
{children}
|
|
71
70
|
</div>
|
|
72
71
|
</div>
|
|
73
72
|
);
|
|
@@ -1,18 +1,22 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import { clamp } from "@noya-app/noya-utils";
|
|
2
|
-
import
|
|
4
|
+
import { Progress as ProgressPrimitive } from "radix-ui";
|
|
3
5
|
import * as React from "react";
|
|
4
6
|
import { cx } from "../utils/classNames";
|
|
5
7
|
|
|
6
|
-
type
|
|
8
|
+
type ColorScheme = "normal" | "warning" | "primary" | "secondary";
|
|
7
9
|
|
|
8
10
|
export function Progress({
|
|
9
11
|
value,
|
|
10
|
-
|
|
12
|
+
colorScheme = "normal",
|
|
11
13
|
className,
|
|
14
|
+
style,
|
|
12
15
|
}: {
|
|
13
16
|
value: number;
|
|
14
|
-
|
|
17
|
+
colorScheme?: ColorScheme;
|
|
15
18
|
className?: string;
|
|
19
|
+
style?: React.CSSProperties;
|
|
16
20
|
}) {
|
|
17
21
|
const clampedValue = clamp(value, 0, 100);
|
|
18
22
|
const transformStyles = React.useMemo(
|
|
@@ -24,12 +28,21 @@ export function Progress({
|
|
|
24
28
|
|
|
25
29
|
return (
|
|
26
30
|
<ProgressPrimitive.Root
|
|
27
|
-
className={cx(
|
|
28
|
-
|
|
31
|
+
className={cx(
|
|
32
|
+
`relative overflow-hidden bg-input-background h-[5px]`,
|
|
33
|
+
className
|
|
34
|
+
)}
|
|
35
|
+
style={{ transform: "translateZ(0)", ...style }}
|
|
29
36
|
value={clampedValue}
|
|
30
37
|
>
|
|
31
38
|
<ProgressPrimitive.Indicator
|
|
32
|
-
className={
|
|
39
|
+
className={cx(
|
|
40
|
+
"transition-[transform_660ms_cubic-bezier(0.65,0,0.35,1) w-full h-full",
|
|
41
|
+
colorScheme === "primary" && "bg-primary",
|
|
42
|
+
colorScheme === "secondary" && "bg-secondary",
|
|
43
|
+
colorScheme === "warning" && "bg-warning",
|
|
44
|
+
colorScheme === "normal" && "bg-text"
|
|
45
|
+
)}
|
|
33
46
|
style={transformStyles}
|
|
34
47
|
/>
|
|
35
48
|
</ProgressPrimitive.Root>
|