@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,5 +1,7 @@
1
+ "use client";
2
+
1
3
  import { useControlledOrUncontrolled } from "@noya-app/react-utils";
2
- import * as PopoverPrimitive from "@radix-ui/react-popover";
4
+ import { Popover as PopoverPrimitive } from "radix-ui";
3
5
  import React, {
4
6
  ComponentProps,
5
7
  useCallback,
@@ -44,13 +46,15 @@ interface Props
44
46
  onClickClose?: () => void;
45
47
  showArrow?: boolean;
46
48
  className?: string;
49
+ style?: React.CSSProperties;
47
50
  portalContainer?: HTMLElement | null;
48
51
  }
49
52
 
50
53
  export const popoverStyle = {
51
- base: "rounded font-[14px] bg-popover-background shadow-popover max-h-[600px] overflow-y-auto text-text-muted z-[1000]",
52
- large: "w-[680px]",
53
- normal: "w-[240px]",
54
+ base:
55
+ "n-rounded n-font-[14px] n-bg-popover-background n-shadow-popover n-max-h-[600px] n-overflow-y-auto n-text-text-muted n-z-[1000]",
56
+ large: "n-w-[680px]",
57
+ normal: "n-w-[240px]",
54
58
  };
55
59
 
56
60
  export function Popover({
@@ -71,6 +75,7 @@ export function Popover({
71
75
  onClickClose,
72
76
  className,
73
77
  portalContainer,
78
+ style,
74
79
  }: Props) {
75
80
  const defaultId = useId();
76
81
  const portalScopeId = usePortalScopeId();
@@ -101,6 +106,7 @@ export function Popover({
101
106
  <PopoverPrimitive.Content
102
107
  {...portalScopeProps(portalScopeId)}
103
108
  ref={contentRef}
109
+ style={style}
104
110
  className={cx(
105
111
  popoverStyle.base,
106
112
  variant === "large" && popoverStyle.large,
@@ -138,11 +144,11 @@ export function Popover({
138
144
  >
139
145
  {typeof children === "function" ? children({ close }) : children}
140
146
  {showArrow && (
141
- <PopoverPrimitive.Arrow className="fill-popover-background" />
147
+ <PopoverPrimitive.Arrow className="n-fill-popover-background" />
142
148
  )}
143
149
  {closable && (
144
150
  <PopoverPrimitive.Close
145
- className="rounded-full h-[25px] w-[25px] inline-flex items-center justify-center absolute top-[5px] right-[5px]"
151
+ className="n-rounded-full n-h-[25px] n-w-[25px] n-inline-flex n-items-center n-justify-center n-absolute n-top-[5px] n-right-[5px]"
146
152
  style={closeStyles}
147
153
  >
148
154
  <IconButton iconName="Cross2Icon" onClick={onClickClose} />
@@ -1,35 +1,58 @@
1
+ "use client";
2
+
1
3
  import { clamp } from "@noya-app/noya-utils";
2
- import * as ProgressPrimitive from "@radix-ui/react-progress";
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 ProgressVariant = "normal" | "warning" | "primary" | "secondary";
8
+ type ColorScheme = "normal" | "warning" | "primary" | "secondary";
7
9
 
8
10
  export function Progress({
9
11
  value,
10
- variant = "normal",
12
+ colorScheme = "normal",
13
+ color,
11
14
  className,
15
+ style: styleProp,
12
16
  }: {
17
+ /** A value between 0 and 100. */
13
18
  value: number;
14
- variant?: ProgressVariant;
19
+
20
+ colorScheme?: ColorScheme;
21
+ color?: string;
15
22
  className?: string;
23
+ style?: React.CSSProperties;
16
24
  }) {
17
25
  const clampedValue = clamp(value, 0, 100);
18
26
  const transformStyles = React.useMemo(
19
27
  () => ({
20
28
  transform: `translateX(-${100 - clampedValue}%)`,
29
+ backgroundColor: color,
21
30
  }),
22
- [clampedValue]
31
+ [color, clampedValue]
32
+ );
33
+
34
+ const style = React.useMemo(
35
+ () => ({ transform: "translateZ(0)", ...styleProp }),
36
+ [styleProp]
23
37
  );
24
38
 
25
39
  return (
26
40
  <ProgressPrimitive.Root
27
- className={cx(`relative hidden bg-input-background h-[5px] `, className)}
28
- style={{ transform: "translateZ(0)" }}
41
+ className={cx(
42
+ `n-relative n-overflow-hidden n-bg-input-background n-h-[5px]`,
43
+ className
44
+ )}
45
+ style={style}
29
46
  value={clampedValue}
30
47
  >
31
48
  <ProgressPrimitive.Indicator
32
- className={`${variant === "primary" ? "bg-primary" : variant === "secondary" ? "bg-secondary" : variant === "warning" ? "bg-warning" : "bg-text"} transition-[transform_660ms_cubic-bezier(0.65,0,0.35,1) w-full h-full`}
49
+ className={cx(
50
+ "n-transition-[transform_660ms_cubic-bezier(0.65,0,0.35,1)] n-w-full n-h-full",
51
+ colorScheme === "primary" && "n-bg-primary",
52
+ colorScheme === "secondary" && "n-bg-secondary",
53
+ colorScheme === "warning" && "n-bg-warning",
54
+ colorScheme === "normal" && "n-bg-text"
55
+ )}
33
56
  style={transformStyles}
34
57
  />
35
58
  </ProgressPrimitive.Root>
@@ -0,0 +1,187 @@
1
+ "use client";
2
+ import { createClickCounter } from "@noya-app/react-utils";
3
+ import React, { ReactNode, useCallback, useRef, useState } from "react";
4
+
5
+ interface ResizableContainerProps {
6
+ children: ReactNode | ((children: { width?: number }) => ReactNode);
7
+ minWidth: number;
8
+ maxWidth?: number;
9
+ style?: React.CSSProperties;
10
+ innerStyle?: React.CSSProperties;
11
+ handleContainerStyle?: React.CSSProperties;
12
+ handleStyle?: React.CSSProperties;
13
+ className?: string;
14
+ onChangeWidth?: (width: number) => void;
15
+ shouldResetWidthOnGestureEnd?: boolean;
16
+ }
17
+
18
+ export const ResizableContainer: React.FC<ResizableContainerProps> = ({
19
+ children,
20
+ minWidth,
21
+ maxWidth,
22
+ style,
23
+ innerStyle,
24
+ handleContainerStyle,
25
+ handleStyle,
26
+ className,
27
+ onChangeWidth,
28
+ shouldResetWidthOnGestureEnd: shouldResetWidth,
29
+ }) => {
30
+ const containerRef = useRef<HTMLDivElement | null>(null);
31
+ const resizeableRef = useRef<HTMLDivElement | null>(null);
32
+ const handleRef = useRef<HTMLDivElement | null>(null);
33
+ const clickCounter = useRef(createClickCounter({ delay: 250 }));
34
+
35
+ const [width, setWidth] = useState<number>();
36
+ const [drag, setDrag] = useState<{
37
+ startX: number;
38
+ initialWidth: number;
39
+ minWidth: number;
40
+ maxWidth: number;
41
+ }>();
42
+
43
+ const handlePointerDown = useCallback(
44
+ (event: React.PointerEvent<HTMLDivElement>) => {
45
+ const containerWidth =
46
+ containerRef.current?.getBoundingClientRect().width;
47
+ const resizeableWidth =
48
+ resizeableRef.current?.getBoundingClientRect().width;
49
+
50
+ if (containerWidth === undefined) return;
51
+ if (resizeableWidth === undefined) return;
52
+
53
+ // start pointer capture
54
+ handleRef.current?.setPointerCapture(event.pointerId);
55
+
56
+ setDrag({
57
+ startX: event.clientX,
58
+ initialWidth: resizeableWidth,
59
+ minWidth: minWidth,
60
+ maxWidth: maxWidth ?? containerWidth,
61
+ });
62
+
63
+ event.preventDefault();
64
+ event.stopPropagation();
65
+ },
66
+ [maxWidth, minWidth]
67
+ );
68
+
69
+ const handlePointerMove = useCallback(
70
+ (event: React.PointerEvent<HTMLDivElement>) => {
71
+ if (!drag) return;
72
+
73
+ const delta = event.clientX - drag.startX;
74
+
75
+ let newWidth = clamp(
76
+ drag.initialWidth + delta,
77
+ drag.minWidth,
78
+ drag.maxWidth
79
+ );
80
+
81
+ setWidth(newWidth);
82
+ onChangeWidth?.(newWidth);
83
+
84
+ event.preventDefault();
85
+ event.stopPropagation();
86
+ },
87
+ [drag, onChangeWidth]
88
+ );
89
+
90
+ const handlePointerUp = useCallback(
91
+ (event: React.PointerEvent<HTMLDivElement>) => {
92
+ setDrag(undefined);
93
+
94
+ // Release pointer
95
+ handleRef.current?.releasePointerCapture(event.pointerId);
96
+
97
+ event.preventDefault();
98
+ event.stopPropagation();
99
+
100
+ const clickCount = clickCounter.current.handleClick({
101
+ x: event.clientX,
102
+ y: event.clientY,
103
+ });
104
+
105
+ if (clickCount >= 2 || shouldResetWidth) {
106
+ setWidth(undefined);
107
+ }
108
+ },
109
+ [shouldResetWidth]
110
+ );
111
+
112
+ return (
113
+ <div
114
+ ref={containerRef}
115
+ id={"resize"}
116
+ style={{ position: "relative", ...style }}
117
+ className={className}
118
+ >
119
+ <div
120
+ ref={resizeableRef}
121
+ style={{
122
+ position: "relative",
123
+ width: width !== undefined ? `${width}px` : "auto",
124
+ ...innerStyle,
125
+ }}
126
+ >
127
+ {typeof children === "function" ? children({ width }) : children}
128
+ <div
129
+ ref={handleRef}
130
+ style={{
131
+ position: "absolute",
132
+ right: "-1.25rem",
133
+ bottom: 0,
134
+ top: 0,
135
+ display: "flex",
136
+ width: "1rem",
137
+ cursor: "ew-resize",
138
+ touchAction: "none",
139
+ flexDirection: "column",
140
+ justifyContent: "center",
141
+ paddingLeft: "5px",
142
+ paddingRight: "5px",
143
+ opacity: 1,
144
+ ...handleContainerStyle,
145
+ }}
146
+ onPointerDown={handlePointerDown}
147
+ onPointerMove={handlePointerMove}
148
+ onPointerUp={handlePointerUp}
149
+ onPointerCancel={handlePointerUp}
150
+ >
151
+ <div
152
+ style={{
153
+ position: "relative",
154
+ display: "flex",
155
+ height: "2.5rem",
156
+ width: "100%",
157
+ flexDirection: "column",
158
+ alignItems: "center",
159
+ justifyContent: "center",
160
+ borderRadius: "9999px",
161
+ backgroundColor: "rgba(17, 24, 39, 0.5)",
162
+ ...handleStyle,
163
+ }}
164
+ ></div>
165
+ </div>
166
+ {/* Prevent iframe from capturing pointer events */}
167
+ {drag && (
168
+ <div
169
+ style={{
170
+ position: "fixed",
171
+ inset: 0,
172
+ zIndex: 50,
173
+ cursor: "ew-resize",
174
+ }}
175
+ onPointerMove={handlePointerMove}
176
+ onPointerUp={handlePointerUp}
177
+ onPointerCancel={handlePointerUp}
178
+ />
179
+ )}
180
+ </div>
181
+ </div>
182
+ );
183
+ };
184
+
185
+ function clamp(value: number, min: number, max: number) {
186
+ return Math.min(Math.max(value, min), max);
187
+ }
@@ -0,0 +1,128 @@
1
+ "use client";
2
+
3
+ import { clamp } from "@noya-app/noya-utils";
4
+ import * as React from "react";
5
+ import { cx } from "../utils/classNames";
6
+
7
+ type ColorScheme = "normal" | "warning" | "primary" | "secondary";
8
+
9
+ export function RingProgress({
10
+ value,
11
+ dividedBy = 100,
12
+ size = 24,
13
+ thickness = 3,
14
+ colorScheme = "normal",
15
+ color,
16
+ trackColor,
17
+ className,
18
+ style,
19
+ ariaLabel,
20
+ }: {
21
+ /** Current value (numerator). */
22
+ value: number;
23
+ /** Total value representing 100%. Defaults to 100. */
24
+ dividedBy?: number;
25
+ /** Diameter in pixels of the ring (outer size). */
26
+ size?: number;
27
+ /** Stroke width of the ring in pixels. */
28
+ thickness?: number;
29
+ /** Ring color scheme, aligned with Progress component. */
30
+ colorScheme?: ColorScheme;
31
+ /** Optional custom color overrides. */
32
+ color?: string;
33
+ trackColor?: string;
34
+ className?: string;
35
+ style?: React.CSSProperties;
36
+ /** Optional aria-label when no visible label is adjacent. */
37
+ ariaLabel?: string;
38
+ }) {
39
+ const safeDivisor = dividedBy > 0 ? dividedBy : 1;
40
+ const clampedRaw = clamp(value, 0, safeDivisor);
41
+ const clampedPercent = (clampedRaw / safeDivisor) * 100;
42
+
43
+ // Geometry
44
+ const radius = React.useMemo(() => (size - thickness) / 2, [size, thickness]);
45
+ const circumference = React.useMemo(() => 2 * Math.PI * radius, [radius]);
46
+ const dashOffset = React.useMemo(
47
+ () => ((100 - clampedPercent) / 100) * circumference,
48
+ [circumference, clampedPercent]
49
+ );
50
+
51
+ // Colors: prefer explicit color props, fall back to colorScheme tokens (with safe fallbacks)
52
+ const trackStroke =
53
+ trackColor ?? "var(--n-input-background, rgba(0,0,0,0.08))";
54
+ const colorClass = React.useMemo(() => {
55
+ switch (colorScheme) {
56
+ case "primary":
57
+ return "n-stroke-primary";
58
+ case "secondary":
59
+ return "n-stroke-secondary";
60
+ case "warning":
61
+ return "n-stroke-warning";
62
+ case "normal":
63
+ default:
64
+ return "n-stroke-text";
65
+ }
66
+ }, [colorScheme]);
67
+
68
+ const computedStroke = React.useMemo(() => {
69
+ if (color) return color;
70
+ switch (colorScheme) {
71
+ case "primary":
72
+ return "var(--n-primary, currentColor)";
73
+ case "secondary":
74
+ return "var(--n-secondary, currentColor)";
75
+ case "warning":
76
+ return "var(--n-warning, currentColor)";
77
+ case "normal":
78
+ default:
79
+ return "var(--n-text, currentColor)";
80
+ }
81
+ }, [color, colorScheme]);
82
+
83
+ return (
84
+ <span
85
+ className={cx("n-inline-flex n-items-center n-justify-center", className)}
86
+ style={style}
87
+ role="progressbar"
88
+ aria-valuenow={clampedRaw}
89
+ aria-valuemin={0}
90
+ aria-valuemax={safeDivisor}
91
+ aria-label={ariaLabel}
92
+ >
93
+ <svg
94
+ width={size}
95
+ height={size}
96
+ viewBox={`0 0 ${size} ${size}`}
97
+ style={{ display: "block" }}
98
+ >
99
+ {/* Track */}
100
+ <circle
101
+ cx={size / 2}
102
+ cy={size / 2}
103
+ r={radius}
104
+ fill="none"
105
+ stroke={trackStroke}
106
+ strokeWidth={thickness}
107
+ />
108
+ {/* Indicator */}
109
+ <circle
110
+ cx={size / 2}
111
+ cy={size / 2}
112
+ r={radius}
113
+ fill="none"
114
+ className={cx(
115
+ "n-transition-[stroke-dashoffset] n-duration-500 n-ease-[cubic-bezier(0.65,0,0.35,1)]",
116
+ !color && colorClass
117
+ )}
118
+ style={{ stroke: computedStroke }}
119
+ strokeWidth={thickness}
120
+ strokeLinecap="round"
121
+ strokeDasharray={`${circumference} ${circumference}`}
122
+ strokeDashoffset={dashOffset}
123
+ transform={`rotate(-90 ${size / 2} ${size / 2})`}
124
+ />
125
+ </svg>
126
+ </span>
127
+ );
128
+ }
@@ -1,4 +1,6 @@
1
- import * as RadixScrollArea from "@radix-ui/react-scroll-area";
1
+ "use client";
2
+
3
+ import { ScrollArea as RadixScrollArea } from "radix-ui";
2
4
  import * as React from "react";
3
5
 
4
6
  interface Props {
@@ -12,10 +14,10 @@ export const ScrollArea = React.memo(function ScrollArea({ children }: Props) {
12
14
  React.useState<HTMLDivElement | null>(null);
13
15
 
14
16
  return (
15
- <div className="flex-1 min-h-0">
17
+ <div className="n-flex-1 n-min-h-0">
16
18
  <RadixScrollArea.Root style={{ width: "100%", height: "100%" }}>
17
19
  <RadixScrollArea.Viewport
18
- className="w-full h-full [&>div]:block"
20
+ className="n-w-full n-h-full [&>div]:n-block"
19
21
  ref={React.useCallback(
20
22
  (ref: HTMLDivElement | null) => setScrollElementRef(ref),
21
23
  []
@@ -29,9 +31,9 @@ export const ScrollArea = React.memo(function ScrollArea({ children }: Props) {
29
31
  </RadixScrollArea.Viewport>
30
32
  <RadixScrollArea.Scrollbar
31
33
  orientation="vertical"
32
- className="scroll-component flex p-[3px] data-[orientation=vertical]:w-[10px]"
34
+ className="n-scroll-component n-flex n-p-[3px] data-[orientation=vertical]:n-w-[10px]"
33
35
  >
34
- <RadixScrollArea.Thumb className="scroll-component flex-1 rounded-[10px] bg-scrollbar" />
36
+ <RadixScrollArea.Thumb className="n-scroll-component n-flex-1 n-rounded-[10px] n-bg-scrollbar" />
35
37
  </RadixScrollArea.Scrollbar>
36
38
  </RadixScrollArea.Root>
37
39
  </div>
@@ -0,0 +1,10 @@
1
+ import React from "react";
2
+ import { ScrollArea } from "./ScrollArea";
3
+
4
+ export function ScrollableSidebar({ children }: { children: React.ReactNode }) {
5
+ return (
6
+ <div className="n-relative n-flex n-flex-col n-flex-1 n-max-h-full">
7
+ <ScrollArea>{children}</ScrollArea>
8
+ </div>
9
+ );
10
+ }
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import { getCurrentPlatform, handleKeyboardEvent } from "@noya-app/noya-keymap";
2
4
  import React, {
3
5
  forwardRef,
@@ -153,8 +155,8 @@ export const SearchCompletionMenu = forwardRef(function SearchCompletionMenu(
153
155
  }));
154
156
 
155
157
  return (
156
- <div {...elementSize} className="flex flex-col overflow-hidden">
157
- <InputField.Root className="flex flex-0">
158
+ <div {...elementSize} className="n-flex n-flex-col n-overflow-hidden">
159
+ <InputField.Root className="n-flex n-flex-0">
158
160
  <InputField.Input
159
161
  ref={inputRef}
160
162
  value={search}
@@ -194,7 +196,7 @@ export const SearchCompletionMenu = forwardRef(function SearchCompletionMenu(
194
196
  ) : (
195
197
  <div
196
198
  {...listSize}
197
- className="flex flex-col p-20 items-center justify-center"
199
+ className="n-flex n-flex-col n-p-20 n-items-center n-justify-center"
198
200
  >
199
201
  <Small color="textDisabled">No results</Small>
200
202
  </div>