@noya-app/noya-designsystem 0.1.64 → 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 (115) hide show
  1. package/.turbo/turbo-build.log +13 -10
  2. package/CHANGELOG.md +12 -0
  3. package/dist/index.css +1 -1
  4. package/dist/index.d.mts +501 -228
  5. package/dist/index.d.ts +501 -228
  6. package/dist/index.js +6738 -2571
  7. package/dist/index.js.map +1 -1
  8. package/dist/index.mjs +6697 -2499
  9. package/dist/index.mjs.map +1 -1
  10. package/package.json +6 -6
  11. package/src/components/ActivityIndicator.tsx +9 -4
  12. package/src/components/ActivityLog.tsx +197 -0
  13. package/src/components/AnimatePresence.tsx +37 -22
  14. package/src/components/Avatar.tsx +42 -25
  15. package/src/components/Banner.tsx +57 -11
  16. package/src/components/BaseToolbar.tsx +29 -7
  17. package/src/components/Breadcrumbs.tsx +2 -2
  18. package/src/components/Button.tsx +23 -24
  19. package/src/components/Checkbox.tsx +6 -35
  20. package/src/components/Chip.tsx +45 -33
  21. package/src/components/Collection.tsx +16 -11
  22. package/src/components/ColorSwatch.tsx +3 -3
  23. package/src/components/ColorSwatchControl.tsx +2 -2
  24. package/src/components/Combobox.tsx +6 -6
  25. package/src/components/ComboboxMenu.tsx +6 -5
  26. package/src/components/CommandPalette.tsx +1 -1
  27. package/src/components/Dialog.tsx +6 -12
  28. package/src/components/Divider.tsx +8 -8
  29. package/src/components/DraggableMenuButton.tsx +9 -5
  30. package/src/components/Drawer.tsx +5 -5
  31. package/src/components/DropdownMenu.tsx +1 -1
  32. package/src/components/EditableText.tsx +2 -2
  33. package/src/components/Fade.tsx +13 -13
  34. package/src/components/FileUploadIndicator.tsx +11 -11
  35. package/src/components/FloatingWindow.tsx +2 -2
  36. package/src/components/Grid.tsx +18 -11
  37. package/src/components/GridView.tsx +32 -25
  38. package/src/components/IVirtualizedList.tsx +5 -0
  39. package/src/components/Icons.tsx +24 -4
  40. package/src/components/InputField.tsx +19 -19
  41. package/src/components/InspectorContainer.tsx +2 -2
  42. package/src/components/InspectorPrimitives.tsx +15 -9
  43. package/src/components/Label.tsx +4 -3
  44. package/src/components/LabeledElementView.tsx +3 -3
  45. package/src/components/LabeledField.tsx +6 -6
  46. package/src/components/List.tsx +103 -45
  47. package/src/components/ListMenu.tsx +91 -0
  48. package/src/components/ListNavigator.tsx +106 -0
  49. package/src/components/ListView.tsx +20 -1158
  50. package/src/components/MediaThumbnail.tsx +56 -15
  51. package/src/components/Message.tsx +5 -5
  52. package/src/components/Navigator.tsx +461 -0
  53. package/src/components/NoyaLogo.tsx +1 -1
  54. package/src/components/Popover.tsx +9 -5
  55. package/src/components/Progress.tsx +19 -9
  56. package/src/components/ResizableContainer.tsx +187 -0
  57. package/src/components/RingProgress.tsx +128 -0
  58. package/src/components/ScrollArea.tsx +4 -4
  59. package/src/components/ScrollableSidebar.tsx +10 -0
  60. package/src/components/SearchCompletionMenu.tsx +3 -3
  61. package/src/components/Section.tsx +107 -57
  62. package/src/components/SegmentedControl.tsx +29 -29
  63. package/src/components/SelectMenu.tsx +13 -20
  64. package/src/components/SelectionToolbar.tsx +4 -3
  65. package/src/components/Slider.tsx +9 -9
  66. package/src/components/Spacer.tsx +2 -2
  67. package/src/components/StackNavigator.tsx +378 -0
  68. package/src/components/Stepper.tsx +88 -0
  69. package/src/components/Switch.tsx +4 -4
  70. package/src/components/Tabs.tsx +3 -3
  71. package/src/components/Text.tsx +23 -13
  72. package/src/components/TextArea.tsx +3 -3
  73. package/src/components/Toast.tsx +4 -4
  74. package/src/components/Toolbar.tsx +50 -9
  75. package/src/components/ToolbarDrawer.tsx +2 -2
  76. package/src/components/Tooltip.tsx +1 -1
  77. package/src/components/TreeView.tsx +11 -4
  78. package/src/components/UserPointer.tsx +4 -4
  79. package/src/components/ai-assistant/AIAssistantLayout.tsx +8 -8
  80. package/src/components/blocks/ImageBlockComponent.tsx +13 -7
  81. package/src/components/connected-users-menu/ConnectedUsersMenuLayout.tsx +4 -4
  82. package/src/components/file-explorer/FileExplorerLayout.tsx +20 -8
  83. package/src/components/internal/Checkmark.tsx +1 -1
  84. package/src/components/internal/Menu.tsx +22 -18
  85. package/src/components/internal/MenuViewport.tsx +13 -6
  86. package/src/components/internal/SelectItem.tsx +3 -3
  87. package/src/components/internal/TextInput.tsx +5 -1
  88. package/src/components/listView/ListViewContexts.tsx +68 -0
  89. package/src/components/listView/ListViewEditableRowTitle.tsx +55 -0
  90. package/src/components/listView/ListViewRoot.tsx +521 -0
  91. package/src/components/listView/ListViewRow.tsx +475 -0
  92. package/src/components/listView/ListViewRowTitle.tsx +21 -0
  93. package/src/components/listView/types.ts +11 -0
  94. package/src/components/pipeline/PipelineResultLayout.tsx +6 -6
  95. package/src/components/sorting/DragRegistration.tsx +2 -1
  96. package/src/components/sorting/SharedDragProvider.tsx +91 -9
  97. package/src/components/sorting/Sortable.tsx +71 -17
  98. package/src/components/workspace/DrawerWorkspaceLayout.tsx +5 -5
  99. package/src/components/workspace/PanelWorkspaceLayout.tsx +65 -49
  100. package/src/components/workspace/VerticalTabMenu.tsx +25 -15
  101. package/src/components/workspace/WorkspaceLayout.tsx +30 -21
  102. package/src/contexts/DialogContext.tsx +17 -5
  103. package/src/hooks/useIndent.ts +3 -8
  104. package/src/index.css +24 -10
  105. package/src/index.tsx +10 -5
  106. package/src/utils/classNames.ts +52 -6
  107. package/src/utils/editableBlockStyles.ts +2 -2
  108. package/src/utils/formatByteSize.ts +1 -0
  109. package/src/utils/inputs.ts +8 -6
  110. package/src/utils/sketchColor.ts +0 -34
  111. package/tailwind.config.ts +1 -0
  112. package/src/components/FillInputField.tsx +0 -37
  113. package/src/components/FillPreviewBackground.tsx +0 -134
  114. package/src/components/GradientPicker.tsx +0 -90
  115. package/src/utils/getGradientBackground.tsx +0 -31
@@ -9,7 +9,7 @@ import {
9
9
  SectionProps,
10
10
  } from "@noya-app/noya-designsystem";
11
11
  import { forwardRefGeneric } from "@noya-app/react-utils";
12
- import React from "react";
12
+ import React, { CSSProperties } from "react";
13
13
  import { cx } from "../../utils/classNames";
14
14
  import {
15
15
  Collection,
@@ -23,7 +23,7 @@ export const FileExplorerLayout = ({
23
23
  className,
24
24
  ...props
25
25
  }: SectionProps) => (
26
- <Section className={cx(className, "px-3 flex-1")} {...props}>
26
+ <Section className={cx(className, "n-px-3 n-flex-1")} {...props}>
27
27
  {children}
28
28
  </Section>
29
29
  );
@@ -39,7 +39,7 @@ export const FileExplorerUploadButton = ({
39
39
  isUploading?: boolean;
40
40
  children?: React.ReactNode;
41
41
  }) => (
42
- <div className="flex items-center gap-2">
42
+ <div className="n-flex n-items-center n-gap-2">
43
43
  {showUploadButton && (
44
44
  <Button
45
45
  icon={isUploading ? <ActivityIndicator size={15} /> : "UploadIcon"}
@@ -60,7 +60,9 @@ export const FileExplorerCollection = forwardRefGeneric(
60
60
  { ...props }: CollectionProps<T, M>,
61
61
  ref: React.ForwardedRef<CollectionRef>
62
62
  ) {
63
- return <Collection<T, M> ref={ref} className="-mx-3 flex-1" {...props} />;
63
+ return (
64
+ <Collection<T, M> ref={ref} className="-n-mx-3 n-flex-1" {...props} />
65
+ );
64
66
  }
65
67
  );
66
68
 
@@ -68,22 +70,32 @@ export const FileExplorerDetail = ({
68
70
  selected,
69
71
  size,
70
72
  children,
73
+ className,
74
+ style,
71
75
  }: {
72
76
  selected: boolean;
73
77
  children: React.ReactNode;
74
78
  size?: CollectionItemSize;
79
+ className?: string;
80
+ style?: CSSProperties;
75
81
  }) => (
76
82
  <span
77
83
  className={cx(
78
- size === "small" ? "text-list-small" : "text-sm",
79
- selected ? "text-primary" : "text-text-muted"
84
+ size === "small" ? "n-text-list-small" : "n-text-sm",
85
+ selected ? "n-text-primary" : "n-text-text-muted",
86
+ className
80
87
  )}
88
+ style={style}
81
89
  >
82
90
  {children}
83
91
  </span>
84
92
  );
85
93
 
86
94
  export const FileExplorerEmptyState = ({
87
- label = "No files",
95
+ children: label = "No files",
88
96
  ...props
89
- }: BannerProps) => <Banner label={label} className="mx-3" {...props} />;
97
+ }: BannerProps) => (
98
+ <Banner className="n-mx-3" {...props}>
99
+ {label}
100
+ </Banner>
101
+ );
@@ -12,7 +12,7 @@ export function Checkmark(props: React.SVGProps<SVGSVGElement>) {
12
12
  {...props}
13
13
  >
14
14
  <path
15
- className="scale-90 origin-center"
15
+ className="n-scale-90 n-origin-center"
16
16
  d="M3 8L6 11L12 5"
17
17
  strokeWidth="1.1"
18
18
  strokeLinecap="round"
@@ -148,6 +148,10 @@ export const isMenuItemSectionHeader = (
148
148
  item: MenuItem<string>
149
149
  ): item is SectionHeaderMenuItem => item.type === "sectionHeader";
150
150
 
151
+ export const isSubMenuItem = <T extends string>(
152
+ item: MenuItem<T>
153
+ ): item is SubMenuItem<T> => item.type === "submenu";
154
+
151
155
  export const isSelectableMenuItemWithScore = (
152
156
  item: MenuItem<string>
153
157
  ): item is ScoredSelectableMenuItem<string> =>
@@ -180,27 +184,27 @@ export const CHECKBOX_RIGHT_INSET = 6;
180
184
  export const CHECKBOX_INDENT_WIDTH = 6;
181
185
 
182
186
  export const styles = {
183
- separatorStyle: "h-px bg-divider mx-3 my-1",
187
+ separatorStyle: "n-h-px n-bg-divider n-mx-3 n-my-1",
184
188
  selectedItemStyle:
185
- "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",
186
190
  testSelectedItemStyle:
187
- "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",
188
192
  itemStyle: ({ disabled }: { disabled?: boolean }) => `
189
- flex-none select-none cursor-pointer rounded
190
- py-1.5 px-2
191
- transition-colors
192
- flex items-center
193
- font-sans text-button font-medium
194
- ${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" : ""}
195
199
  `,
196
200
  itemIndicator: {
197
- className: "flex items-center relative -left-2.5",
201
+ className: "n-flex n-items-center n-relative -n-left-2.5",
198
202
  style: {
199
203
  marginRight: -CHECKBOX_RIGHT_INSET,
200
204
  },
201
205
  },
202
206
  contentStyle:
203
- "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",
204
208
  };
205
209
 
206
210
  function getKeyboardShortcuts<T extends string>(
@@ -238,8 +242,8 @@ const ShortcutElement = ({
238
242
  <kbd
239
243
  className={cx(
240
244
  textStyles.small,
241
- "text-inherit opacity-60 tabular-nums",
242
- 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"
243
247
  )}
244
248
  >
245
249
  {children}
@@ -276,7 +280,7 @@ export const KeyboardShortcut = memo(function KeyboardShortcut({
276
280
  );
277
281
  });
278
282
 
279
- export const SectionHeader = memo(function SectionHeader({
283
+ export const SectionHeaderMenuItem = memo(function SectionHeaderMenuItem({
280
284
  title,
281
285
  variant = "normal",
282
286
  id,
@@ -292,10 +296,10 @@ export const SectionHeader = memo(function SectionHeader({
292
296
  className={mergeConflictingClassNames(
293
297
  [
294
298
  variant === "label"
295
- ? `text-label ${textStyles.label} font-bold text-text-disabled`
296
- : "font-sans text-heading5 font-normal",
297
- "bg-listview-raised-background flex items-center py-1.5 px-3",
298
- 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",
299
303
  ],
300
304
  {
301
305
  categories: ["font"],
@@ -1,15 +1,22 @@
1
1
  "use client";
2
2
 
3
3
  import { ChevronRightIcon } from "@noya-app/noya-icons";
4
- import { ContextMenu as RadixContextMenu } from "radix-ui";
5
- import { DropdownMenu as RadixDropdownMenu } from "radix-ui";
4
+ import {
5
+ ContextMenu as RadixContextMenu,
6
+ DropdownMenu as RadixDropdownMenu,
7
+ } from "radix-ui";
6
8
  import React from "react";
7
9
  import {
8
10
  portalScopeProps,
9
11
  usePortalScopeId,
10
12
  } from "../../contexts/PortalScopeContext";
11
13
  import { cx } from "../../utils/classNames";
12
- import { isSelectableMenuItem, MenuItem, SectionHeader, styles } from "./Menu";
14
+ import {
15
+ isSelectableMenuItem,
16
+ MenuItem,
17
+ SectionHeaderMenuItem,
18
+ styles,
19
+ } from "./Menu";
13
20
  import { SelectItem } from "./SelectItem";
14
21
 
15
22
  type MenuSeparatorComponent = React.FC<{ className?: string }>;
@@ -85,7 +92,7 @@ export const MenuViewport = <T extends string>({
85
92
 
86
93
  case "sectionHeader":
87
94
  return (
88
- <SectionHeader
95
+ <SectionHeaderMenuItem
89
96
  isFirst={index === 0}
90
97
  key={item.id}
91
98
  {...item}
@@ -125,10 +132,10 @@ export const MenuViewport = <T extends string>({
125
132
  indented={hasCheckedItem}
126
133
  disabled={item.disabled}
127
134
  >
128
- <div className="flex items-center flex-1">
135
+ <div className="n-flex n-items-center n-flex-1">
129
136
  {item.title}
130
137
  </div>
131
- <ChevronRightIcon className="-mr-1" />
138
+ <ChevronRightIcon className="-n-mr-1" />
132
139
  </SelectItem>
133
140
  </Components.SubTrigger>
134
141
  <Components.Portal>
@@ -56,7 +56,7 @@ export const SelectItem = React.forwardRef(
56
56
 
57
57
  if (checked && Components.CheckboxItem) {
58
58
  return (
59
- <div className="px-1">
59
+ <div className="n-px-1">
60
60
  <Components.CheckboxItem
61
61
  checked={checked}
62
62
  disabled={disabled}
@@ -93,7 +93,7 @@ export const SelectItem = React.forwardRef(
93
93
  }
94
94
 
95
95
  return (
96
- <div className="px-1">
96
+ <div className="n-px-1">
97
97
  <Components.Item
98
98
  className={cx(
99
99
  styles.itemStyle({ disabled }),
@@ -107,7 +107,7 @@ export const SelectItem = React.forwardRef(
107
107
  onSelect={handleSelectItem}
108
108
  {...props}
109
109
  >
110
- <div className="flex flex-1 items-center">
110
+ <div className="n-flex n-flex-1 n-items-center">
111
111
  {indented && <Spacer.Horizontal size={CHECKBOX_INDENT_WIDTH} />}
112
112
  {checked ? (
113
113
  <div {...styles.itemIndicator}>
@@ -55,7 +55,7 @@ const ReadOnlyTextInput = forwardRef(function ReadOnlyTextInput(
55
55
  value={value}
56
56
  onKeyDown={onKeyDown}
57
57
  readOnly
58
- className="focus:z-interactable"
58
+ className="focus:n-z-interactable"
59
59
  />
60
60
  );
61
61
  });
@@ -298,6 +298,10 @@ export default forwardRef(function TextInput(
298
298
  (event: React.MouseEvent) => event.stopPropagation(),
299
299
  []
300
300
  ),
301
+ onDoubleClick: useCallback(
302
+ (event: React.MouseEvent) => event.stopPropagation(),
303
+ []
304
+ ),
301
305
  autoComplete: "off",
302
306
  autoCapitalize: "off",
303
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
+ });