@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
@@ -68,7 +68,7 @@ export const separator: SeparatorItem = {
68
68
 
69
69
  type FalsyReactNode = false | "" | null | undefined;
70
70
 
71
- export type MenuItemIcon = IconName | React.ReactElement | FalsyReactNode;
71
+ export type MenuItemIcon = IconName | React.ReactElement<any> | FalsyReactNode;
72
72
 
73
73
  type BaseMenuItem = {
74
74
  checked?: boolean;
@@ -93,6 +93,7 @@ export type SelectableMenuItem<T extends string> = BaseMenuItem & {
93
93
  value: T;
94
94
  testSelected?: boolean;
95
95
  tooltip?: ReactNode;
96
+ drawer?: ReactNode;
96
97
  };
97
98
 
98
99
  export type SubMenuItem<T extends string> = BaseMenuItem & {
@@ -147,6 +148,10 @@ export const isMenuItemSectionHeader = (
147
148
  item: MenuItem<string>
148
149
  ): item is SectionHeaderMenuItem => item.type === "sectionHeader";
149
150
 
151
+ export const isSubMenuItem = <T extends string>(
152
+ item: MenuItem<T>
153
+ ): item is SubMenuItem<T> => item.type === "submenu";
154
+
150
155
  export const isSelectableMenuItemWithScore = (
151
156
  item: MenuItem<string>
152
157
  ): item is ScoredSelectableMenuItem<string> =>
@@ -179,27 +184,27 @@ export const CHECKBOX_RIGHT_INSET = 6;
179
184
  export const CHECKBOX_INDENT_WIDTH = 6;
180
185
 
181
186
  export const styles = {
182
- separatorStyle: "h-px bg-divider mx-3 my-1",
187
+ separatorStyle: "n-h-px n-bg-divider n-mx-3 n-my-1",
183
188
  selectedItemStyle:
184
- "focus:outline-none focus:text-selected-list-item-text focus:bg-selected-list-item-background focus:kbd:text-selected-list-item-text",
189
+ "focus:n-outline-none focus:n-text-selected-list-item-text focus:n-bg-selected-list-item-background focus:kbd:n-text-selected-list-item-text",
185
190
  testSelectedItemStyle:
186
- "outline-none text-selected-list-item-text bg-selected-list-item-background kbd:text-selected-list-item-text",
191
+ "n-outline-none n-text-selected-list-item-text n-bg-selected-list-item-background kbd:n-text-selected-list-item-text",
187
192
  itemStyle: ({ disabled }: { disabled?: boolean }) => `
188
- flex-none select-none cursor-pointer rounded
189
- py-1.5 px-2
190
- transition-colors
191
- flex items-center
192
- font-sans text-button font-medium
193
- ${disabled ? "text-text-disabled" : ""}
193
+ n-flex-none n-select-none n-cursor-pointer n-rounded
194
+ n-py-1.5 n-px-2
195
+ n-transition-colors
196
+ n-flex n-items-center
197
+ n-font-sans n-text-button n-font-medium
198
+ ${disabled ? "n-text-text-disabled" : ""}
194
199
  `,
195
200
  itemIndicator: {
196
- className: "flex items-center relative -left-2.5",
201
+ className: "n-flex n-items-center n-relative -n-left-2.5",
197
202
  style: {
198
203
  marginRight: -CHECKBOX_RIGHT_INSET,
199
204
  },
200
205
  },
201
206
  contentStyle:
202
- "rounded bg-popover-background text-text shadow-popover z-menu py-1",
207
+ "n-rounded n-bg-popover-background n-text-text n-shadow-popover n-z-menu n-py-1",
203
208
  };
204
209
 
205
210
  function getKeyboardShortcuts<T extends string>(
@@ -237,8 +242,8 @@ const ShortcutElement = ({
237
242
  <kbd
238
243
  className={cx(
239
244
  textStyles.small,
240
- "text-inherit opacity-60 tabular-nums",
241
- fixedWidth && "w-[0.9rem] text-center"
245
+ "n-text-inherit n-opacity-60 n-tabular-nums",
246
+ fixedWidth && "n-w-[0.9rem] n-text-center"
242
247
  )}
243
248
  >
244
249
  {children}
@@ -275,7 +280,7 @@ export const KeyboardShortcut = memo(function KeyboardShortcut({
275
280
  );
276
281
  });
277
282
 
278
- export const SectionHeader = memo(function SectionHeader({
283
+ export const SectionHeaderMenuItem = memo(function SectionHeaderMenuItem({
279
284
  title,
280
285
  variant = "normal",
281
286
  id,
@@ -291,10 +296,10 @@ export const SectionHeader = memo(function SectionHeader({
291
296
  className={mergeConflictingClassNames(
292
297
  [
293
298
  variant === "label"
294
- ? `text-label ${textStyles.label} font-bold text-text-disabled`
295
- : "font-sans text-heading5 font-normal",
296
- "bg-listview-raised-background flex items-center py-1.5 px-3",
297
- isFirst && "-mt-1",
299
+ ? `${textStyles.label} n-font-bold n-text-text-disabled`
300
+ : "n-font-sans n-text-heading5 n-font-normal",
301
+ "n-bg-listview-raised-background n-flex n-items-center n-py-1.5 n-px-3",
302
+ isFirst && "-n-mt-1",
298
303
  ],
299
304
  {
300
305
  categories: ["font"],
@@ -1,13 +1,22 @@
1
+ "use client";
2
+
1
3
  import { ChevronRightIcon } from "@noya-app/noya-icons";
2
- import * as RadixContextMenu from "@radix-ui/react-context-menu";
3
- import * as RadixDropdownMenu from "@radix-ui/react-dropdown-menu";
4
+ import {
5
+ ContextMenu as RadixContextMenu,
6
+ DropdownMenu as RadixDropdownMenu,
7
+ } from "radix-ui";
4
8
  import React from "react";
5
9
  import {
6
10
  portalScopeProps,
7
11
  usePortalScopeId,
8
12
  } from "../../contexts/PortalScopeContext";
9
13
  import { cx } from "../../utils/classNames";
10
- import { isSelectableMenuItem, MenuItem, SectionHeader, styles } from "./Menu";
14
+ import {
15
+ isSelectableMenuItem,
16
+ MenuItem,
17
+ SectionHeaderMenuItem,
18
+ styles,
19
+ } from "./Menu";
11
20
  import { SelectItem } from "./SelectItem";
12
21
 
13
22
  type MenuSeparatorComponent = React.FC<{ className?: string }>;
@@ -83,7 +92,7 @@ export const MenuViewport = <T extends string>({
83
92
 
84
93
  case "sectionHeader":
85
94
  return (
86
- <SectionHeader
95
+ <SectionHeaderMenuItem
87
96
  isFirst={index === 0}
88
97
  key={item.id}
89
98
  {...item}
@@ -123,10 +132,10 @@ export const MenuViewport = <T extends string>({
123
132
  indented={hasCheckedItem}
124
133
  disabled={item.disabled}
125
134
  >
126
- <div className="flex items-center flex-1">
135
+ <div className="n-flex n-items-center n-flex-1">
127
136
  {item.title}
128
137
  </div>
129
- <ChevronRightIcon className="-mr-1" />
138
+ <ChevronRightIcon className="-n-mr-1" />
130
139
  </SelectItem>
131
140
  </Components.SubTrigger>
132
141
  <Components.Portal>
@@ -1,9 +1,12 @@
1
+ "use client";
2
+
1
3
  import { renderIcon } from "../Icons";
2
4
 
3
- import * as Select from "@radix-ui/react-select";
5
+ import { Select } from "radix-ui";
4
6
  import React, { useCallback } from "react";
5
7
  import { cx } from "../../utils/classNames";
6
8
  import { Spacer } from "../Spacer";
9
+ import { Checkmark } from "./Checkmark";
7
10
  import {
8
11
  CHECKBOX_INDENT_WIDTH,
9
12
  CHECKBOX_RIGHT_INSET,
@@ -53,7 +56,7 @@ export const SelectItem = React.forwardRef(
53
56
 
54
57
  if (checked && Components.CheckboxItem) {
55
58
  return (
56
- <div className="px-1">
59
+ <div className="n-px-1">
57
60
  <Components.CheckboxItem
58
61
  checked={checked}
59
62
  disabled={disabled}
@@ -90,7 +93,7 @@ export const SelectItem = React.forwardRef(
90
93
  }
91
94
 
92
95
  return (
93
- <div className="px-1">
96
+ <div className="n-px-1">
94
97
  <Components.Item
95
98
  className={cx(
96
99
  styles.itemStyle({ disabled }),
@@ -104,7 +107,7 @@ export const SelectItem = React.forwardRef(
104
107
  onSelect={handleSelectItem}
105
108
  {...props}
106
109
  >
107
- <div className="flex flex-1 items-center">
110
+ <div className="n-flex n-flex-1 n-items-center">
108
111
  {indented && <Spacer.Horizontal size={CHECKBOX_INDENT_WIDTH} />}
109
112
  {checked ? (
110
113
  <div {...styles.itemIndicator}>
@@ -133,25 +136,3 @@ export const SelectItem = React.forwardRef(
133
136
  );
134
137
  }
135
138
  );
136
-
137
- function Checkmark() {
138
- return (
139
- <svg
140
- viewBox="0 0 15 15"
141
- fill="none"
142
- xmlns="http://www.w3.org/2000/svg"
143
- aria-hidden="true"
144
- width={15}
145
- height={15}
146
- >
147
- <path
148
- className="scale-90 origin-center"
149
- d="M3 8L6 11L12 5"
150
- strokeWidth="1.1"
151
- strokeLinecap="round"
152
- strokeLinejoin="round"
153
- stroke="currentColor"
154
- />
155
- </svg>
156
- );
157
- }
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import { composeRefs } from "@radix-ui/react-compose-refs";
2
4
  import React, {
3
5
  AriaRole,
@@ -53,7 +55,7 @@ const ReadOnlyTextInput = forwardRef(function ReadOnlyTextInput(
53
55
  value={value}
54
56
  onKeyDown={onKeyDown}
55
57
  readOnly
56
- className="focus:z-interactable"
58
+ className="focus:n-z-interactable"
57
59
  />
58
60
  );
59
61
  });
@@ -296,6 +298,10 @@ export default forwardRef(function TextInput(
296
298
  (event: React.MouseEvent) => event.stopPropagation(),
297
299
  []
298
300
  ),
301
+ onDoubleClick: useCallback(
302
+ (event: React.MouseEvent) => event.stopPropagation(),
303
+ []
304
+ ),
299
305
  autoComplete: "off",
300
306
  autoCapitalize: "off",
301
307
  autoCorrect: "off",
@@ -0,0 +1,68 @@
1
+ "use client";
2
+
3
+ import { createContext, ReactNode } from "react";
4
+ import {
5
+ ListColorScheme,
6
+ ListRowMarginType,
7
+ ListRowPosition,
8
+ ListViewSectionHeaderVariant,
9
+ ListViewVariant,
10
+ PressEventName,
11
+ } from "./types";
12
+
13
+ export type ListViewContextValue = {
14
+ pressEventName: PressEventName;
15
+ colorScheme: ListColorScheme;
16
+ gap: number;
17
+ sectionHeaderVariant: ListViewSectionHeaderVariant;
18
+ variant: ListViewVariant;
19
+ divider: boolean;
20
+ sortable: boolean;
21
+ expandable: boolean; // Used only by TreeView
22
+ indentation: number;
23
+ };
24
+
25
+ export const ListViewContext = createContext<ListViewContextValue>({
26
+ pressEventName: "onClick",
27
+ colorScheme: "primary",
28
+ gap: 0,
29
+ sectionHeaderVariant: "normal",
30
+ variant: "normal",
31
+ divider: false,
32
+ sortable: false,
33
+ expandable: true,
34
+ indentation: 12,
35
+ });
36
+ (ListViewContext as any).displayName = "ListViewContext";
37
+
38
+ // TODO: Some of these could be passed in a single context value that's
39
+ // the same for all rows. But doing this seems to cause an infinite loop and
40
+ // prevents drag and drop from working.
41
+ export type ListRowContextValue = {
42
+ marginType: ListRowMarginType;
43
+ selectedPosition: ListRowPosition;
44
+ isSectionHeader: boolean;
45
+ };
46
+
47
+ // The dragged item isn't passed a context value (doing so causes an infinite loop),
48
+ // so we pass this separately. Rows need the indentation to look correct when dragging,
49
+ // and the dragged row doesn't have a ListRowContextValue.
50
+ export type ListViewDraggingContextValue = {
51
+ isDragOverlay?: boolean;
52
+ };
53
+
54
+ export const ListViewDraggingContext =
55
+ createContext<ListViewDraggingContextValue>({});
56
+ (ListViewDraggingContext as any).displayName = "ListViewDraggingContext";
57
+
58
+ export const ListRowContext = createContext<ListRowContextValue>({
59
+ marginType: "none",
60
+ selectedPosition: "only",
61
+ isSectionHeader: false,
62
+ });
63
+ (ListRowContext as any).displayName = "ListRowContext";
64
+
65
+ export const RenderItemContext = createContext<(index: number) => ReactNode>(
66
+ () => null
67
+ );
68
+ (RenderItemContext as any).displayName = "RenderItemContext";
@@ -0,0 +1,55 @@
1
+ "use client";
2
+
3
+ import React, { memo, useLayoutEffect, useRef } from "react";
4
+ import { cx } from "../../utils/classNames";
5
+ import { InputField } from "../InputField";
6
+
7
+ export interface EditableRowTitleProps {
8
+ value: string;
9
+ onSubmitEditing: (value: string) => void;
10
+ autoFocus: boolean;
11
+ placeholder?: string;
12
+ className?: string;
13
+ onKeyDown?: (e: React.KeyboardEvent) => void;
14
+ }
15
+
16
+ export const ListViewEditableRowTitle = memo(function ListViewEditableRowTitle({
17
+ value,
18
+ onSubmitEditing,
19
+ autoFocus,
20
+ placeholder,
21
+ className,
22
+ onKeyDown,
23
+ }: EditableRowTitleProps) {
24
+ const inputRef = useRef<HTMLInputElement | null>(null);
25
+
26
+ useLayoutEffect(() => {
27
+ const element = inputRef.current;
28
+
29
+ if (!element || !autoFocus) return;
30
+
31
+ // Calling `focus` is necessary, in addition to `select`, to ensure
32
+ // the `onBlur` fires correctly.
33
+ element.focus();
34
+
35
+ // must be a delay of 1ms or more to ensure any radix ui components have finished any focus behaviors
36
+ setTimeout(() => {
37
+ element.select();
38
+ }, 1);
39
+ }, [autoFocus]);
40
+
41
+ return (
42
+ <InputField.Input
43
+ ref={inputRef}
44
+ value={value}
45
+ placeholder={placeholder}
46
+ onSubmit={onSubmitEditing}
47
+ allowSubmittingWithSameValue
48
+ className={cx(
49
+ "-n-mx-1.5 -n-my-1 n-bg-listview-editing-background",
50
+ className
51
+ )}
52
+ onKeyDown={onKeyDown}
53
+ />
54
+ );
55
+ });