@noya-app/noya-designsystem 0.1.63 → 0.1.65

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.
Files changed (143) hide show
  1. package/.turbo/turbo-build.log +13 -10
  2. package/CHANGELOG.md +25 -0
  3. package/dist/index.css +1 -1
  4. package/dist/index.d.mts +648 -333
  5. package/dist/index.d.ts +648 -333
  6. package/dist/index.js +13813 -9157
  7. package/dist/index.js.map +1 -1
  8. package/dist/index.mjs +13949 -9269
  9. package/dist/index.mjs.map +1 -1
  10. package/package.json +10 -22
  11. package/src/__tests__/validateDropIndicator.test.ts +26 -41
  12. package/src/__tests__/workspaceLayout.test.ts +281 -0
  13. package/src/components/ActionMenu.tsx +2 -0
  14. package/src/components/ActivityIndicator.tsx +13 -6
  15. package/src/components/ActivityLog.tsx +197 -0
  16. package/src/components/AnimatePresence.tsx +43 -26
  17. package/src/components/Avatar.tsx +45 -26
  18. package/src/components/Banner.tsx +57 -11
  19. package/src/components/BaseToolbar.tsx +67 -34
  20. package/src/components/Breadcrumbs.tsx +4 -2
  21. package/src/components/Button.tsx +28 -23
  22. package/src/components/Checkbox.tsx +6 -35
  23. package/src/components/Chip.tsx +47 -33
  24. package/src/components/Collection.tsx +20 -12
  25. package/src/components/ColorSwatch.tsx +42 -22
  26. package/src/components/ColorSwatchControl.tsx +7 -5
  27. package/src/components/Combobox.tsx +8 -6
  28. package/src/components/ComboboxMenu.tsx +6 -5
  29. package/src/components/CommandPalette.tsx +3 -1
  30. package/src/components/ContextMenu.tsx +3 -1
  31. package/src/components/Dialog.tsx +9 -13
  32. package/src/components/DimensionInput.tsx +2 -0
  33. package/src/components/Divider.tsx +18 -14
  34. package/src/components/DraggableMenuButton.tsx +11 -5
  35. package/src/components/Drawer.tsx +14 -6
  36. package/src/components/DropdownMenu.tsx +4 -2
  37. package/src/components/EditableText.tsx +4 -2
  38. package/src/components/Fade.tsx +13 -13
  39. package/src/components/FileUploadIndicator.tsx +108 -0
  40. package/src/components/FloatingWindow.tsx +4 -2
  41. package/src/components/Grid.tsx +58 -42
  42. package/src/components/GridView.tsx +65 -36
  43. package/src/components/IVirtualizedList.tsx +5 -0
  44. package/src/components/IconButton.tsx +2 -0
  45. package/src/components/Icons.tsx +24 -4
  46. package/src/components/InputField.tsx +21 -19
  47. package/src/components/InspectorContainer.tsx +2 -2
  48. package/src/components/InspectorPrimitives.tsx +15 -9
  49. package/src/components/Label.tsx +4 -3
  50. package/src/components/LabeledElementView.tsx +9 -5
  51. package/src/components/LabeledField.tsx +8 -6
  52. package/src/components/List.tsx +112 -46
  53. package/src/components/ListMenu.tsx +91 -0
  54. package/src/components/ListNavigator.tsx +106 -0
  55. package/src/components/ListView.tsx +22 -1147
  56. package/src/components/MediaThumbnail.tsx +84 -14
  57. package/src/components/Message.tsx +11 -12
  58. package/src/components/Navigator.tsx +461 -0
  59. package/src/components/NoyaLogo.tsx +1 -1
  60. package/src/components/Popover.tsx +12 -6
  61. package/src/components/Progress.tsx +31 -8
  62. package/src/components/ResizableContainer.tsx +187 -0
  63. package/src/components/RingProgress.tsx +128 -0
  64. package/src/components/ScrollArea.tsx +7 -5
  65. package/src/components/ScrollableSidebar.tsx +10 -0
  66. package/src/components/SearchCompletionMenu.tsx +5 -3
  67. package/src/components/Section.tsx +109 -57
  68. package/src/components/SegmentedControl.tsx +51 -25
  69. package/src/components/SelectMenu.tsx +16 -21
  70. package/src/components/SelectionToolbar.tsx +7 -4
  71. package/src/components/Slider.tsx +12 -10
  72. package/src/components/Spacer.tsx +2 -2
  73. package/src/components/StackNavigator.tsx +378 -0
  74. package/src/components/Stepper.tsx +88 -0
  75. package/src/components/Switch.tsx +7 -5
  76. package/src/components/Tabs.tsx +6 -4
  77. package/src/components/Text.tsx +29 -18
  78. package/src/components/TextArea.tsx +5 -3
  79. package/src/components/Toast.tsx +5 -5
  80. package/src/components/Toolbar.tsx +57 -10
  81. package/src/components/ToolbarDrawer.tsx +29 -0
  82. package/src/components/Tooltip.tsx +2 -2
  83. package/src/components/TreeView.tsx +13 -4
  84. package/src/components/UserPointer.tsx +6 -4
  85. package/src/components/ai-assistant/AIAssistantLayout.tsx +10 -8
  86. package/src/components/blocks/ImageBlockComponent.tsx +162 -0
  87. package/src/components/connected-users-menu/ConnectedUsersMenuLayout.tsx +6 -4
  88. package/src/components/file-explorer/FileExplorerLayout.tsx +22 -8
  89. package/src/components/internal/Checkmark.tsx +24 -0
  90. package/src/components/internal/Menu.tsx +24 -19
  91. package/src/components/internal/MenuViewport.tsx +15 -6
  92. package/src/components/internal/SelectItem.tsx +7 -26
  93. package/src/components/internal/TextInput.tsx +7 -1
  94. package/src/components/listView/ListViewContexts.tsx +68 -0
  95. package/src/components/listView/ListViewEditableRowTitle.tsx +55 -0
  96. package/src/components/listView/ListViewRoot.tsx +521 -0
  97. package/src/components/listView/ListViewRow.tsx +475 -0
  98. package/src/components/listView/ListViewRowTitle.tsx +21 -0
  99. package/src/components/listView/types.ts +11 -0
  100. package/src/components/pipeline/PipelineResultLayout.tsx +6 -6
  101. package/src/components/sorting/DragRegistration.tsx +10 -5
  102. package/src/components/sorting/SharedDragProvider.tsx +134 -27
  103. package/src/components/sorting/Sortable.tsx +90 -27
  104. package/src/components/sorting/createSharedDrag.tsx +7 -6
  105. package/src/components/sorting/sorting.ts +6 -9
  106. package/src/components/workspace/DrawerWorkspaceLayout.tsx +110 -29
  107. package/src/components/workspace/PanelWorkspaceLayout.tsx +148 -99
  108. package/src/components/workspace/VerticalTabMenu.tsx +46 -0
  109. package/src/components/workspace/WorkspaceLayout.tsx +76 -63
  110. package/src/components/workspace/constants.ts +4 -0
  111. package/src/components/workspace/panelStorage.ts +216 -0
  112. package/src/components/workspace/types.ts +11 -4
  113. package/src/contexts/DesignSystemConfiguration.tsx +12 -5
  114. package/src/contexts/DialogContext.tsx +19 -5
  115. package/src/contexts/FloatingWindowContext.tsx +2 -0
  116. package/src/contexts/GlobalInputBlurContext.tsx +2 -0
  117. package/src/contexts/ImageDataContext.tsx +2 -0
  118. package/src/contexts/LinkComponentContext.tsx +17 -0
  119. package/src/contexts/OpenPortalsContext.tsx +2 -0
  120. package/src/contexts/PortalScopeContext.tsx +2 -0
  121. package/src/hooks/mergeEventHandlers.ts +1 -1
  122. package/src/hooks/useHover.ts +30 -17
  123. package/src/hooks/useIndent.ts +5 -8
  124. package/src/hooks/useLabel.ts +2 -0
  125. package/src/hooks/useObjectURL.ts +5 -3
  126. package/src/hooks/usePlatform.ts +5 -3
  127. package/src/hooks/useTheme.ts +3 -1
  128. package/src/index.css +43 -10
  129. package/src/index.tsx +15 -7
  130. package/src/utils/classNames.ts +56 -9
  131. package/src/utils/combobox.ts +2 -0
  132. package/src/utils/editableBlockStyles.ts +2 -2
  133. package/src/utils/formatByteSize.ts +9 -0
  134. package/src/utils/inputs.ts +8 -6
  135. package/src/utils/sketchColor.ts +0 -34
  136. package/src/utils/withSeparatorElements.ts +1 -1
  137. package/tailwind.config.ts +1 -0
  138. package/src/components/FillInputField.tsx +0 -37
  139. package/src/components/FillPreviewBackground.tsx +0 -132
  140. package/src/components/GradientPicker.tsx +0 -88
  141. package/src/hooks/usePreservePanelSize.tsx +0 -183
  142. package/src/mediaQuery.ts +0 -13
  143. package/src/utils/getGradientBackground.tsx +0 -31
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import { DropdownChevronIcon } from "@noya-app/noya-icons";
2
4
  import { forwardRefGeneric, memoGeneric } from "@noya-app/react-utils";
3
5
  import React, {
@@ -464,8 +466,8 @@ export const Combobox = memoGeneric(
464
466
  >
465
467
  <DropdownChevronIcon
466
468
  className={cx(
467
- "transition-transform duration-100",
468
- shouldShowMenu ? "rotate-180" : "rotate-0"
469
+ "n-transition-transform n-duration-100",
470
+ shouldShowMenu ? "n-rotate-180" : "n-rotate-0"
469
471
  )}
470
472
  />
471
473
  </InputField.Button>
@@ -486,8 +488,8 @@ export const Combobox = memoGeneric(
486
488
  return (
487
489
  <div
488
490
  className={cx(
489
- "flex-col",
490
- shouldShowMenu && !readOnly ? "flex" : "hidden"
491
+ "n-flex-col",
492
+ shouldShowMenu && !readOnly ? "n-flex" : "n-hidden"
491
493
  )}
492
494
  >
493
495
  {filteredItems.length > 0 && !loading ? (
@@ -504,8 +506,8 @@ export const Combobox = memoGeneric(
504
506
  indented={hasCheckedItems}
505
507
  />
506
508
  ) : (
507
- <div className="flex flex-col h-[50px] p-5 items-center justify-center">
508
- <Small className="text-text-disabled">
509
+ <div className="n-flex n-flex-col n-h-[50px] n-p-5 n-items-center n-justify-center">
510
+ <Small className="n-text-text-disabled">
509
511
  {loading ? "Loading..." : "No results"}
510
512
  </Small>
511
513
  </div>
@@ -6,8 +6,6 @@ import { cx } from "../utils/classNames";
6
6
 
7
7
  import { fuzzyTokenize } from "../utils/fuzzyScorer";
8
8
  import { renderIcon } from "./Icons";
9
- import { IVirtualizedList, ListView } from "./ListView";
10
- import { Spacer } from "./Spacer";
11
9
  import {
12
10
  CHECKBOX_INDENT_WIDTH,
13
11
  CHECKBOX_RIGHT_INSET,
@@ -16,6 +14,9 @@ import {
16
14
  ScoredMenuItem,
17
15
  styles,
18
16
  } from "./internal/Menu";
17
+ import { IVirtualizedList } from "./IVirtualizedList";
18
+ import { ListView } from "./ListView";
19
+ import { Spacer } from "./Spacer";
19
20
 
20
21
  interface ComboboxMenuProps<T extends string> {
21
22
  items: ScoredMenuItem<T>[];
@@ -92,7 +93,7 @@ export const ComboboxMenu = memoGeneric(
92
93
  }
93
94
  }}
94
95
  >
95
- <div className="flex flex-1 min-w-0 items-center">
96
+ <div className="n-flex n-flex-1 n-min-w-0 n-items-center">
96
97
  {indented && <Spacer.Horizontal size={CHECKBOX_INDENT_WIDTH} />}
97
98
  {item.checked ? (
98
99
  <div {...styles.itemIndicator}>
@@ -113,8 +114,8 @@ export const ComboboxMenu = memoGeneric(
113
114
  <span
114
115
  key={`${item.value}-token-${j}`}
115
116
  className={cx(
116
- token.type === "match" ? "font-bold" : "font-normal",
117
- "whitespace-pre truncate"
117
+ token.type === "match" ? "n-font-bold" : "n-font-normal",
118
+ "n-whitespace-pre n-truncate"
118
119
  )}
119
120
  >
120
121
  {token.text}
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import { Dialog } from "@noya-app/noya-designsystem";
2
4
  import { AutoSizer } from "@noya-app/react-utils";
3
5
  import React, { memo } from "react";
@@ -50,7 +52,7 @@ export const CommandPalette = memo(function CommandPalette({
50
52
  }, 0);
51
53
  }}
52
54
  >
53
- <div className="flex flex-col flex-1">
55
+ <div className="n-flex n-flex-col n-flex-1">
54
56
  <AutoSizer>
55
57
  {(size) => (
56
58
  <SearchCompletionMenu
@@ -1,6 +1,8 @@
1
+ "use client";
2
+
1
3
  import { useKeyboardShortcuts } from "@noya-app/noya-keymap";
2
4
  import { memoGeneric } from "@noya-app/react-utils";
3
- import * as RadixContextMenu from "@radix-ui/react-context-menu";
5
+ import { ContextMenu as RadixContextMenu } from "radix-ui";
4
6
  import React, { ReactNode, useCallback, useMemo } from "react";
5
7
  import {
6
8
  portalScopeProps,
@@ -1,4 +1,6 @@
1
- import * as DialogPrimitive from "@radix-ui/react-dialog";
1
+ "use client";
2
+
3
+ import { Dialog as DialogPrimitive } from "radix-ui";
2
4
  import React, {
3
5
  ComponentProps,
4
6
  ForwardedRef,
@@ -17,7 +19,7 @@ const StyledOverlay = forwardRef<
17
19
  >(({ className, ...props }, ref) => (
18
20
  <DialogPrimitive.Overlay
19
21
  ref={ref}
20
- className={cx(`fixed inset-0 bg-[rgba(0,0,0,0.5)] `, className)}
22
+ className={cx(`n-fixed n-inset-0 n-bg-[rgba(0,0,0,0.5)]`, className)}
21
23
  {...props}
22
24
  />
23
25
  ));
@@ -30,13 +32,7 @@ const StyledContent = forwardRef<
30
32
  <DialogPrimitive.Content
31
33
  ref={ref}
32
34
  className={cx(
33
- `fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2
34
- w-[90vw] max-w-[550px] max-h-[85vh] p-dialog-padding rounded-[2px]
35
- font-sans text-heading5 font-normal leading-[19px] text-text-muted
36
- bg-popover-background pointer-events-all z-[1000] focus:outline-none
37
- shadow-dialog-shadow
38
- flex flex-col
39
- `,
35
+ `n-fixed n-top-1/2 n-left-1/2 -n-translate-x-1/2 -n-translate-y-1/2 n-w-[90vw] n-max-w-[550px] n-max-h-[85vh] n-p-dialog-padding n-rounded-[2px] n-font-sans n-text-heading5 n-font-normal n-leading-[19px] n-text-text-muted n-bg-popover-background n-pointer-events-all n-z-[1000] focus:n-outline-none n-shadow-dialog-shadow n-flex n-flex-col`,
40
36
  className
41
37
  )}
42
38
  {...props}
@@ -53,7 +49,7 @@ const StyledTitle = forwardRef<
53
49
  <DialogPrimitive.Title
54
50
  ref={ref}
55
51
  className={cx(
56
- `m-0 font-sans text-heading3 font-medium leading-[1.4] text-text `,
52
+ `n-m-0 n-font-sans n-text-heading3 n-font-medium n-leading-[1.4] n-text-text`,
57
53
  className
58
54
  )}
59
55
  {...props}
@@ -67,7 +63,7 @@ const StyledDescription = forwardRef<
67
63
  <DialogPrimitive.Description
68
64
  ref={ref}
69
65
  className={cx(
70
- `m-0 font-sans text-heading5 font-normal leading-[19px] text-text-muted `,
66
+ `n-m-0 n-font-sans n-text-heading5 n-font-normal n-leading-[19px] n-text-text-muted`,
71
67
  className
72
68
  )}
73
69
  {...props}
@@ -134,7 +130,7 @@ export const Dialog = forwardRef(function Dialog(
134
130
  <DialogPrimitive.Close asChild>
135
131
  <IconButton
136
132
  iconName="Cross1Icon"
137
- className="z-[1]"
133
+ className="n-z-[1]"
138
134
  style={{
139
135
  position: "absolute",
140
136
  top: "var(--n-dialog-padding)",
@@ -168,7 +164,7 @@ export const FullscreenDialog = forwardRef(function FullscreenDialog(
168
164
  return (
169
165
  <Dialog
170
166
  ref={forwardedRef}
171
- className="w-full h-full max-w-full max-h-full top-0 left-0 translate-none flex flex-col p-0"
167
+ className="n-w-full n-h-full n-max-w-full n-max-h-full n-top-0 n-left-0 n-translate-none n-flex n-flex-col n-p-0"
172
168
  style={style}
173
169
  {...rest}
174
170
  />
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import { round } from "@noya-app/noya-utils";
2
4
  import * as React from "react";
3
5
  import { InputField } from "./InputField";
@@ -12,7 +12,7 @@ interface DividerProps {
12
12
 
13
13
  export const Divider = memo(function Divider({
14
14
  variant = "normal",
15
- overflow = 0,
15
+ overflow,
16
16
  className,
17
17
  style,
18
18
  ...props
@@ -20,17 +20,19 @@ export const Divider = memo(function Divider({
20
20
  return (
21
21
  <div
22
22
  className={cx(
23
- `h-px min-h-px self-stretch`,
23
+ `n-h-px n-min-h-px n-self-stretch`,
24
24
  variant === "strong"
25
- ? "bg-divider-strong"
25
+ ? "n-bg-divider-strong"
26
26
  : variant === "subtle"
27
- ? "bg-divider-subtle"
28
- : "bg-divider",
27
+ ? "n-bg-divider-subtle"
28
+ : "n-bg-divider",
29
29
  className
30
30
  )}
31
31
  style={{
32
- marginLeft: `-${overflow}px`,
33
- marginRight: `-${overflow}px`,
32
+ ...(typeof overflow === "number" && {
33
+ marginLeft: `-${overflow}px`,
34
+ marginRight: `-${overflow}px`,
35
+ }),
34
36
  ...style,
35
37
  }}
36
38
  {...props}
@@ -40,7 +42,7 @@ export const Divider = memo(function Divider({
40
42
 
41
43
  export const DividerVertical = memo(function DividerVertical({
42
44
  variant = "normal",
43
- overflow = 0,
45
+ overflow,
44
46
  className,
45
47
  style,
46
48
  ...props
@@ -48,17 +50,19 @@ export const DividerVertical = memo(function DividerVertical({
48
50
  return (
49
51
  <div
50
52
  className={cx(
51
- `w-px min-w-px self-stretch`,
53
+ `n-w-px n-min-w-px n-self-stretch`,
52
54
  variant === "strong"
53
- ? "bg-divider-strong"
55
+ ? "n-bg-divider-strong"
54
56
  : variant === "subtle"
55
- ? "bg-divider-subtle"
56
- : "bg-divider",
57
+ ? "n-bg-divider-subtle"
58
+ : "n-bg-divider",
57
59
  className
58
60
  )}
59
61
  style={{
60
- marginTop: `-${overflow}px`,
61
- marginBottom: `-${overflow}px`,
62
+ ...(typeof overflow === "number" && {
63
+ marginTop: `-${overflow}px`,
64
+ marginBottom: `-${overflow}px`,
65
+ }),
62
66
  ...style,
63
67
  }}
64
68
  {...props}
@@ -1,4 +1,5 @@
1
- import { DragHandleDots2Icon } from "@noya-app/noya-icons";
1
+ "use client";
2
+
2
3
  import {
3
4
  memoGeneric,
4
5
  useControlledOrUncontrolled,
@@ -7,6 +8,7 @@ import React, { useCallback, useState } from "react";
7
8
  import { cssVars } from "../theme";
8
9
  import { cx } from "../utils/classNames";
9
10
  import { DropdownMenu } from "./DropdownMenu";
11
+ import { Icon, IconName } from "./Icons";
10
12
  import { MenuItem } from "./internal/Menu";
11
13
 
12
14
  /**
@@ -23,6 +25,7 @@ export const DraggableMenuButton = memoGeneric(function DraggableMenuButton<
23
25
  isVisible = true,
24
26
  className,
25
27
  style,
28
+ iconName = "DragHandleDots2Icon",
26
29
  ...rest
27
30
  }: {
28
31
  open?: boolean;
@@ -33,6 +36,7 @@ export const DraggableMenuButton = memoGeneric(function DraggableMenuButton<
33
36
  isVisible?: boolean;
34
37
  className?: string;
35
38
  style?: React.CSSProperties;
39
+ iconName?: IconName;
36
40
  } & Omit<
37
41
  React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>,
38
42
  "onSelect"
@@ -93,7 +97,7 @@ export const DraggableMenuButton = memoGeneric(function DraggableMenuButton<
93
97
  <div
94
98
  {...rest}
95
99
  className={cx(
96
- "cursor-pointer rounded flex items-center justify-center py-[2px] hover:bg-input-background-light active:bg-active-background ",
100
+ "n-cursor-pointer n-rounded n-flex n-items-center n-justify-center n-py-[2px] hover:n-bg-input-background-light active:n-bg-active-background",
97
101
  className
98
102
  )}
99
103
  style={style}
@@ -113,14 +117,16 @@ export const DraggableMenuButton = memoGeneric(function DraggableMenuButton<
113
117
  onSelect={onSelect}
114
118
  shouldBindKeyboardShortcuts={false}
115
119
  >
116
- <div className="pointer-events-none h-[15px]">
117
- <DragHandleDots2Icon
120
+ <div className="n-pointer-events-none n-h-[15px]">
121
+ <Icon
122
+ name={iconName}
118
123
  color={isVisible || open ? cssVars.colors.icon : "transparent"}
119
124
  />
120
125
  </div>
121
126
  </DropdownMenu>
122
127
  ) : (
123
- <DragHandleDots2Icon
128
+ <Icon
129
+ name={iconName}
124
130
  color={isVisible || open ? cssVars.colors.icon : "transparent"}
125
131
  />
126
132
  )}
@@ -1,5 +1,7 @@
1
+ "use client";
2
+
1
3
  import { useControlledOrUncontrolled } from "@noya-app/react-utils";
2
- import * as Dialog from "@radix-ui/react-dialog";
4
+ import { Dialog } from "radix-ui";
3
5
  import * as React from "react";
4
6
  import { useImperativeHandle } from "react";
5
7
  import { cx } from "../utils/classNames";
@@ -14,6 +16,8 @@ export type DrawerProps = {
14
16
  className?: string;
15
17
  id?: string;
16
18
  style?: React.CSSProperties;
19
+ overlayClassName?: string;
20
+ overlayStyle?: React.CSSProperties;
17
21
  positioning?: "fixed" | "absolute";
18
22
  side?: "left" | "right";
19
23
  portalled?: boolean;
@@ -35,6 +39,8 @@ export const Drawer = React.memo(
35
39
  side = "left",
36
40
  portalled = true,
37
41
  portalContainer,
42
+ overlayClassName,
43
+ overlayStyle,
38
44
  }: DrawerProps,
39
45
  forwardedRef: React.ForwardedRef<SidebarRef>
40
46
  ) {
@@ -60,17 +66,19 @@ export const Drawer = React.memo(
60
66
  <>
61
67
  <Dialog.Overlay
62
68
  className={cx(
63
- "inset-0 bg-black/50",
64
- positioning === "absolute" ? "absolute" : "fixed"
69
+ "n-inset-0 n-bg-black/50",
70
+ positioning === "absolute" ? "n-absolute" : "n-fixed",
71
+ overlayClassName
65
72
  )}
73
+ style={overlayStyle}
66
74
  />
67
75
  <Dialog.Content
68
76
  id={id}
69
77
  style={style}
70
78
  className={cx(
71
- `top-0 bottom-0 z-50 overflow-y-auto bg-sidebar-background rounded-none max-h-none max-w-none sm:max-w-sm w-full border-divider-strong`,
72
- positioning === "absolute" ? "absolute" : "fixed",
73
- side === "left" ? "left-0 border-r" : "right-0 border-l",
79
+ `n-top-0 n-bottom-0 n-z-50 n-overflow-y-auto n-bg-sidebar-background n-rounded-none n-max-h-none n-max-w-none sm:!n-max-w-sm n-w-full n-border-divider-strong`,
80
+ positioning === "absolute" ? "n-absolute" : "n-fixed",
81
+ side === "left" ? "n-left-0 n-border-r" : "n-right-0 n-border-l",
74
82
  className
75
83
  )}
76
84
  >
@@ -1,10 +1,12 @@
1
+ "use client";
2
+
1
3
  import { useKeyboardShortcuts } from "@noya-app/noya-keymap";
2
4
  import {
3
5
  forwardRefGeneric,
4
6
  memoGeneric,
5
7
  useControlledOrUncontrolled,
6
8
  } from "@noya-app/react-utils";
7
- import * as RadixDropdownMenu from "@radix-ui/react-dropdown-menu";
9
+ import { DropdownMenu as RadixDropdownMenu } from "radix-ui";
8
10
  import React, {
9
11
  ComponentProps,
10
12
  ForwardedRef,
@@ -16,7 +18,7 @@ import {
16
18
  portalScopeProps,
17
19
  usePortalScopeId,
18
20
  } from "../contexts/PortalScopeContext";
19
- import Button, { ButtonProps } from "./Button";
21
+ import { Button, ButtonProps } from "./Button";
20
22
  import { MenuProps } from "./ContextMenu";
21
23
  import { getKeyboardShortcutsForMenuItems, styles } from "./internal/Menu";
22
24
  import { MenuViewport } from "./internal/MenuViewport";
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import { cx, InputField } from "@noya-app/noya-designsystem";
2
4
  import React, {
3
5
  forwardRef,
@@ -149,7 +151,7 @@ export const EditableText = memo(
149
151
  });
150
152
 
151
153
  const input = (
152
- <div className="flex absolute inset-0 -mx-1.5 -my-1">
154
+ <div className="n-flex n-absolute n-inset-0 -mx-1.5 -n-my-1">
153
155
  <InputField.Root onFocusChange={setFocused}>
154
156
  <InputField.Input
155
157
  ref={inputRef}
@@ -196,7 +198,7 @@ export const EditableText = memo(
196
198
  );
197
199
 
198
200
  return (
199
- <div className={cx("flex relative", className)} style={style}>
201
+ <div className={cx("n-flex n-relative", className)} style={style}>
200
202
  {preview}
201
203
  {focused && !readOnly && input}
202
204
  </div>
@@ -27,29 +27,29 @@ export const Fade = ({
27
27
  position = "front",
28
28
  }: FadeProps) => {
29
29
  const gradientDirection = {
30
- left: "to-l",
31
- right: "to-r",
32
- top: "to-t",
33
- bottom: "to-b",
30
+ left: "n-bg-gradient-to-l",
31
+ right: "n-bg-gradient-to-r",
32
+ top: "n-bg-gradient-to-t",
33
+ bottom: "n-bg-gradient-to-b",
34
34
  }[direction];
35
35
 
36
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",
37
+ left: "n-left-0 n-top-0 n-bottom-0",
38
+ right: "n-right-0 n-top-0 n-bottom-0",
39
+ top: "n-left-0 n-right-0 n-top-0",
40
+ bottom: "n-left-0 n-right-0 n-bottom-0",
41
41
  }[direction];
42
42
 
43
43
  return (
44
- <div className={cx("relative", className)} style={{ height }}>
44
+ <div className={cx("n-relative", className)} style={{ height }}>
45
45
  {position === "front" ? children : null}
46
46
  <div
47
47
  className={cx(
48
- "absolute pointer-events-none",
48
+ "n-absolute n-pointer-events-none",
49
49
  positionClasses,
50
- `bg-gradient-${gradientDirection}`,
51
- "from-transparent to-background",
52
- zIndex && `z-[${zIndex}]`
50
+ gradientDirection,
51
+ "n-from-transparent n-to-background",
52
+ zIndex && `n-z-[${zIndex}]`
53
53
  )}
54
54
  style={{
55
55
  width: width ?? "100%",
@@ -0,0 +1,108 @@
1
+ import React from "react";
2
+ import { formatByteSize } from "../utils/formatByteSize";
3
+ import { ActivityIndicator } from "./ActivityIndicator";
4
+ import { Divider } from "./Divider";
5
+ import { MediaThumbnail } from "./MediaThumbnail";
6
+ import { Progress } from "./Progress";
7
+ import { Heading5, Small } from "./Text";
8
+ import { Checkmark } from "./internal/Checkmark";
9
+
10
+ type FileUploadIndicatorProps = {
11
+ name?: string;
12
+ percent?: number;
13
+ total?: number;
14
+ contentType?: string;
15
+ };
16
+
17
+ export function FileUploadIndicator({
18
+ name,
19
+ percent,
20
+ total,
21
+ contentType,
22
+ }: FileUploadIndicatorProps) {
23
+ const done = percent === 1;
24
+ const value = typeof percent === "number" ? Math.round(percent) : 0;
25
+
26
+ return (
27
+ <div className="n-flex n-items-center n-gap-2">
28
+ <div className="n-w-12 n-h-12 n-bg-background n-rounded-md n-overflow-hidden">
29
+ <MediaThumbnail
30
+ size="medium"
31
+ fileName={name}
32
+ contentType={contentType}
33
+ />
34
+ </div>
35
+ <div className="n-flex n-flex-col n-flex-1 n-justify-center n-gap-1 n-min-w-0">
36
+ {name && (
37
+ <Small color="text" className="n-truncate n-leading-none">
38
+ {name}
39
+ </Small>
40
+ )}
41
+ {typeof total === "number" && typeof percent === "number" && (
42
+ <Small
43
+ color="textSubtle"
44
+ className="n-leading-none"
45
+ style={{ fontSize: "11px" }}
46
+ >
47
+ {formatByteSize(Math.round((percent / 100) * total))} /{" "}
48
+ {formatByteSize(total)}
49
+ </Small>
50
+ )}
51
+ {typeof value === "number" && (
52
+ <Progress
53
+ value={value}
54
+ style={{ marginTop: "3px", height: "3px" }}
55
+ className="n-rounded-sm"
56
+ colorScheme="secondary"
57
+ />
58
+ )}
59
+ </div>
60
+ <div className="n-flex n-items-center n-justify-center n-gap-2">
61
+ {typeof value === "number" && (
62
+ <Small
63
+ color="textSubtle"
64
+ style={{ lineHeight: "1", fontSize: "13px" }}
65
+ className="n-tabular-nums n-text-right n-w-10"
66
+ >
67
+ {value}%
68
+ </Small>
69
+ )}
70
+ {done ? (
71
+ <div className="n-w-[15px] n-h-[15px] n-bg-secondary n-rounded-full n-flex n-items-center n-justify-center n-text-white">
72
+ <Checkmark />
73
+ </div>
74
+ ) : (
75
+ <ActivityIndicator size={15} />
76
+ )}
77
+ </div>
78
+ </div>
79
+ );
80
+ }
81
+
82
+ export function FileUploadList({
83
+ uploads,
84
+ }: {
85
+ uploads: (FileUploadIndicatorProps & { id: string })[];
86
+ }) {
87
+ return (
88
+ <>
89
+ <div className="n-flex n-items-center n-gap-2 n-py-2 n-px-4">
90
+ <Heading5>
91
+ Uploading {uploads.length} {uploads.length === 1 ? "asset" : "assets"}
92
+ </Heading5>
93
+ </div>
94
+ <Divider />
95
+ <div className="n-flex n-flex-col n-gap-3 n-max-h-[500px] n-overflow-y-auto n-overflow-x-hidden n-py-4 n-px-4">
96
+ {uploads.map((upload) => (
97
+ <FileUploadIndicator
98
+ key={upload.id}
99
+ name={upload?.name}
100
+ percent={upload?.percent}
101
+ total={upload?.total}
102
+ contentType={upload?.contentType}
103
+ />
104
+ ))}
105
+ </div>
106
+ </>
107
+ );
108
+ }
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import {
2
4
  cssVars,
3
5
  Divider,
@@ -125,11 +127,11 @@ function defaultRenderToolbar({
125
127
  }) {
126
128
  return (
127
129
  <>
128
- <Small className="flex-1 font-medium text-text">{title}</Small>
130
+ <Small className="n-flex-1 n-font-medium n-text-text">{title}</Small>
129
131
  {toolbarContent}
130
132
  <IconButton
131
133
  iconName="Cross3Icon"
132
- className="h-8 w-8 rounded-full"
134
+ className="n-h-8 n-w-8 n-rounded-full"
133
135
  onClick={onClose}
134
136
  size={20}
135
137
  style={{