@noya-app/noya-designsystem 0.1.47 → 0.1.49

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 (55) hide show
  1. package/.turbo/turbo-build.log +10 -10
  2. package/CHANGELOG.md +18 -0
  3. package/dist/index.css +1 -1
  4. package/dist/index.d.mts +389 -241
  5. package/dist/index.d.ts +389 -241
  6. package/dist/index.js +4802 -3990
  7. package/dist/index.js.map +1 -1
  8. package/dist/index.mjs +4715 -3915
  9. package/dist/index.mjs.map +1 -1
  10. package/package.json +7 -7
  11. package/src/__tests__/validateDropIndicator.test.ts +263 -0
  12. package/src/components/ActionMenu.tsx +51 -0
  13. package/src/components/ActivityIndicator.tsx +7 -1
  14. package/src/components/BaseToolbar.tsx +2 -2
  15. package/src/components/Checkbox.tsx +2 -2
  16. package/src/components/Chip.tsx +7 -6
  17. package/src/components/Collection.tsx +30 -2
  18. package/src/components/Combobox.tsx +27 -15
  19. package/src/components/ComboboxMenu.tsx +15 -6
  20. package/src/components/Dialog.tsx +17 -12
  21. package/src/components/DimensionInput.tsx +14 -12
  22. package/src/components/Drawer.tsx +98 -0
  23. package/src/components/EditableText.tsx +3 -1
  24. package/src/components/FillInputField.tsx +2 -2
  25. package/src/components/Grid.tsx +161 -111
  26. package/src/components/GridView.tsx +73 -41
  27. package/src/components/InputField.tsx +148 -208
  28. package/src/components/Label.tsx +4 -68
  29. package/src/components/LabeledField.tsx +7 -1
  30. package/src/components/List.tsx +135 -50
  31. package/src/components/ListView.tsx +63 -43
  32. package/src/components/MediaThumbnail.tsx +117 -0
  33. package/src/components/Message.tsx +8 -8
  34. package/src/components/NoyaLogo.tsx +41 -0
  35. package/src/components/SearchCompletionMenu.tsx +30 -16
  36. package/src/components/SegmentedControl.tsx +1 -1
  37. package/src/components/SelectMenu.tsx +28 -21
  38. package/src/components/Slider.tsx +16 -7
  39. package/src/components/Sortable.tsx +125 -62
  40. package/src/components/internal/Menu.tsx +45 -25
  41. package/src/components/internal/MenuViewport.tsx +7 -1
  42. package/src/components/internal/SelectItem.tsx +53 -28
  43. package/src/components/internal/__tests__/Menu.test.tsx +12 -0
  44. package/src/components/workspace/DrawerWorkspaceLayout.tsx +86 -0
  45. package/src/components/workspace/PanelWorkspaceLayout.tsx +102 -0
  46. package/src/components/{WorkspaceLayout.tsx → workspace/WorkspaceLayout.tsx} +109 -106
  47. package/src/components/workspace/types.ts +31 -0
  48. package/src/contexts/DialogContext.tsx +49 -34
  49. package/src/hooks/usePreservePanelSize.tsx +1 -5
  50. package/src/index.css +8 -1
  51. package/src/index.tsx +6 -1
  52. package/src/theme/index.ts +2 -0
  53. package/src/utils/classNames.ts +51 -3
  54. package/src/utils/inputs.ts +21 -0
  55. package/tailwind.config.ts +8 -0
@@ -4,6 +4,7 @@ import React, {
4
4
  createContext,
5
5
  CSSProperties,
6
6
  ForwardedRef,
7
+ forwardRef,
7
8
  memo,
8
9
  ReactNode,
9
10
  useCallback,
@@ -11,7 +12,7 @@ import React, {
11
12
  useMemo,
12
13
  } from "react";
13
14
  import { useHover } from "../hooks/useHover";
14
- import { cx } from "../utils/classNames";
15
+ import { cx, mergeConflictingClassNames } from "../utils/classNames";
15
16
  import withSeparatorElements from "../utils/withSeparatorElements";
16
17
  import { ActivityIndicator } from "./ActivityIndicator";
17
18
  import { ContextMenu } from "./ContextMenu";
@@ -93,9 +94,10 @@ interface ItemProps<MenuItemType extends string = string> {
93
94
  onMenuOpenChange?: (open: boolean) => void;
94
95
  style?: CSSProperties;
95
96
  action?: ReactNode;
96
- testHoveredId?: string;
97
97
  onKeyDown?: (event: React.KeyboardEvent) => void;
98
98
  hovered?: boolean;
99
+ testShowInsideDropIndicator?: boolean;
100
+ role?: string;
99
101
  }
100
102
 
101
103
  const GridViewItem = forwardRefGeneric(function GridViewItem<
@@ -118,9 +120,10 @@ const GridViewItem = forwardRefGeneric(function GridViewItem<
118
120
  onMenuOpenChange,
119
121
  style,
120
122
  action,
121
- testHoveredId,
122
123
  onKeyDown,
123
124
  hovered = false,
125
+ testShowInsideDropIndicator: showInsideDropIndicator = false,
126
+ ...props
124
127
  }: ItemProps<MenuItemType>,
125
128
  forwardedRef: ForwardedRef<HTMLDivElement>
126
129
  ) {
@@ -128,8 +131,6 @@ const GridViewItem = forwardRefGeneric(function GridViewItem<
128
131
  onHoverChange,
129
132
  });
130
133
 
131
- const isHovered = testHoveredId ? testHoveredId === id : hovered;
132
-
133
134
  const { textPosition, bordered, disabled } = useContext(GridViewContext);
134
135
 
135
136
  const handleClick = useCallback(
@@ -160,28 +161,31 @@ const GridViewItem = forwardRefGeneric(function GridViewItem<
160
161
 
161
162
  let element = (
162
163
  <div
164
+ {...props}
163
165
  className={cx(
164
- "flex flex-col relative focus:shadow-[0px_0px_0px_1px_var(--sidebar-background),_0px_0px_0px_3px_var(--primary)] focus:outline-none rounded p-2 -m-2",
166
+ "flex flex-col relative rounded p-2 -m-2 text-text",
167
+ "cursor-pointer",
168
+ "active:opacity-70",
165
169
  selected && "bg-primary-pastel",
166
- isHovered && "ring-1 ring-primary ring-inset"
170
+ hovered && "bg-list-view-hover-background",
171
+ disabled && "opacity-50",
172
+ showInsideDropIndicator && "ring-2 ring-primary ring-inset",
173
+ "focus:ring-2 focus:ring-primary focus:ring-inset focus:outline-none"
167
174
  )}
168
175
  id={id}
169
176
  ref={forwardedRef}
170
177
  {...hoverProps}
171
178
  tabIndex={disabled ? undefined : 0}
172
179
  onKeyDown={handleKeyDown}
180
+ onClick={handleClick}
181
+ onDoubleClick={onDoubleClick}
182
+ onContextMenu={onContextMenu}
173
183
  >
174
184
  <div
175
185
  className={cx(
176
186
  "flex items-center justify-center rounded",
177
- "cursor-pointer",
178
- bordered ? "border border-divider" : "border border-transparent",
179
- disabled ? "opacity-50" : "hover:opacity-85 active:opacity-70",
180
- selected ? "bg-primary-pastel" : "bg-input-background text-text"
187
+ bordered ? "border border-divider" : "border border-transparent"
181
188
  )}
182
- onClick={handleClick}
183
- onDoubleClick={onDoubleClick}
184
- onContextMenu={onContextMenu}
185
189
  style={style}
186
190
  >
187
191
  {children}
@@ -193,7 +197,7 @@ const GridViewItem = forwardRefGeneric(function GridViewItem<
193
197
  <ItemDescription>{subtitle || " "}</ItemDescription>
194
198
  </>
195
199
  )}
196
- {textPosition === "overlay" && isHovered && (title || subtitle) && (
200
+ {textPosition === "overlay" && hovered && (title || subtitle) && (
197
201
  <div className="absolute inset-0 flex flex-col justify-end items-start p-1 pointer-events-none truncate gap-0.5">
198
202
  {title && <ItemTitle showBackground>{title}</ItemTitle>}
199
203
  {subtitle && (
@@ -265,19 +269,31 @@ interface GridViewRootProps extends Partial<GridViewContextValue> {
265
269
  onClick?: () => void;
266
270
  scrollable?: boolean;
267
271
  className?: string;
272
+ onDragOver?: React.DragEventHandler<HTMLDivElement>;
273
+ onDragEnter?: React.DragEventHandler<HTMLDivElement>;
274
+ onDragLeave?: React.DragEventHandler<HTMLDivElement>;
275
+ onDrop?: React.DragEventHandler<HTMLDivElement>;
276
+ role?: string;
277
+ renderEmptyState?: () => ReactNode;
278
+ contentClassName?: string;
268
279
  }
269
280
 
270
- function GridViewRoot({
271
- minColumnWidth = "220px",
272
- gap = 20,
273
- children,
274
- scrollable,
275
- onClick,
276
- textPosition = "below",
277
- bordered = false,
278
- disabled = false,
279
- className,
280
- }: GridViewRootProps) {
281
+ const GridViewRoot = forwardRef(function GridViewRoot(
282
+ {
283
+ minColumnWidth = "220px",
284
+ gap = 20,
285
+ children,
286
+ scrollable,
287
+ onClick,
288
+ textPosition = "below",
289
+ bordered = false,
290
+ disabled = false,
291
+ className,
292
+ contentClassName,
293
+ ...props
294
+ }: GridViewRootProps,
295
+ forwardedRef: ForwardedRef<HTMLDivElement>
296
+ ) {
281
297
  const handleClick = useCallback(
282
298
  (event: React.MouseEvent) => {
283
299
  event.stopPropagation();
@@ -299,34 +315,42 @@ function GridViewRoot({
299
315
  [bordered, disabled, gap, minColumnWidth, textPosition]
300
316
  );
301
317
 
318
+ const mergedClassName = useMemo(() => {
319
+ const baseClassName = cx(
320
+ "flex flex-col -mx-3",
321
+ scrollable ? "basis-0 min-h-0" : "flex-none",
322
+ className
323
+ );
324
+
325
+ return mergeConflictingClassNames([baseClassName, className], {
326
+ categories: ["flex"],
327
+ });
328
+ }, [className, scrollable]);
329
+
330
+ const content = <div className={cx("p-3", contentClassName)}>{children}</div>;
331
+
302
332
  return (
303
333
  <GridViewContext.Provider value={contextValue}>
304
334
  <div
305
335
  onClick={handleClick}
306
- className={cx(
307
- "flex flex-col -mx-3 -mb-1",
308
- scrollable ? "flex-1" : "flex-[0_0_auto]",
309
- className
310
- )}
336
+ className={mergedClassName}
337
+ {...props}
338
+ ref={forwardedRef}
311
339
  >
312
- {scrollable ? (
313
- <ScrollArea>
314
- <div className="p-3">{children}</div>
315
- </ScrollArea>
316
- ) : (
317
- <div className="p-3">{children}</div>
318
- )}
340
+ {scrollable ? <ScrollArea>{content}</ScrollArea> : content}
319
341
  </div>
320
342
  </GridViewContext.Provider>
321
343
  );
322
- }
344
+ });
323
345
 
324
346
  function GridViewSection({
325
347
  children,
326
348
  className,
349
+ renderEmptyState,
327
350
  }: {
328
351
  children?: ReactNode;
329
352
  className?: string;
353
+ renderEmptyState?: () => ReactNode;
330
354
  }) {
331
355
  const { minColumnWidth, gap } = useContext(GridViewContext);
332
356
 
@@ -335,8 +359,16 @@ function GridViewSection({
335
359
  gap: `${gap}px`,
336
360
  };
337
361
 
338
- return (
339
- <div className={cx("grid text-text", className)} style={styles}>
362
+ const isEmpty = React.Children.count(children) === 0;
363
+
364
+ return isEmpty && renderEmptyState ? (
365
+ renderEmptyState()
366
+ ) : (
367
+ <div
368
+ role="presentation"
369
+ className={cx("grid text-text", className)}
370
+ style={styles}
371
+ >
340
372
  {children}
341
373
  </div>
342
374
  );