@noya-app/noya-designsystem 0.0.13 → 0.0.15

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.
@@ -1,4 +1,4 @@
1
- import { KeyModifiers } from '@noya-app/noya-keymap';
1
+ import { KeyModifiers } from "@noya-app/noya-keymap";
2
2
  import React, {
3
3
  createContext,
4
4
  CSSProperties,
@@ -9,19 +9,19 @@ import React, {
9
9
  useCallback,
10
10
  useContext,
11
11
  useMemo,
12
- } from 'react';
13
- import styled, { keyframes } from 'styled-components';
14
- import { useHover } from '../hooks/useHover';
15
- import withSeparatorElements from '../utils/withSeparatorElements';
16
- import { ActivityIndicator } from './ActivityIndicator';
17
- import { ContextMenu } from './ContextMenu';
18
- import { MenuItem } from './internal/Menu';
19
- import { ScrollArea } from './ScrollArea';
20
- import { Spacer } from './Spacer';
21
- import { Stack } from './Stack';
22
- import { Tooltip } from './Tooltip';
23
-
24
- export type GridViewSize = 'xxs' | 'xs' | 'small' | 'large';
12
+ } from "react";
13
+ import styled, { keyframes } from "styled-components";
14
+ import { useHover } from "../hooks/useHover";
15
+ import withSeparatorElements from "../utils/withSeparatorElements";
16
+ import { ActivityIndicator } from "./ActivityIndicator";
17
+ import { ContextMenu } from "./ContextMenu";
18
+ import { MenuItem } from "./internal/Menu";
19
+ import { ScrollArea } from "./ScrollArea";
20
+ import { Spacer } from "./Spacer";
21
+ import { Stack } from "./Stack";
22
+ import { Tooltip } from "./Tooltip";
23
+
24
+ export type GridViewSize = "xxs" | "xs" | "small" | "medium" | "large" | "xl";
25
25
 
26
26
  const sizes: Record<
27
27
  GridViewSize,
@@ -46,20 +46,30 @@ const sizes: Record<
46
46
  itemHeight: 170,
47
47
  gap: 20,
48
48
  },
49
+ medium: {
50
+ itemWidth: 220,
51
+ itemHeight: 220,
52
+ gap: 16,
53
+ },
49
54
  large: {
50
55
  itemWidth: 280,
51
56
  itemHeight: 280,
52
- gap: 20,
57
+ gap: 24,
58
+ },
59
+ xl: {
60
+ itemWidth: 400,
61
+ itemHeight: 400,
62
+ gap: 32,
53
63
  },
54
64
  };
55
65
 
56
66
  const Grid = styled.div<{
57
67
  size: GridViewSize;
58
- padding: CSSProperties['padding'];
68
+ padding: CSSProperties["padding"];
59
69
  }>(({ theme, size, padding }) => {
60
70
  return {
61
71
  color: theme.colors.text,
62
- display: 'grid',
72
+ display: "grid",
63
73
  gridTemplateColumns: `repeat(auto-fill, minmax(${sizes[size].itemWidth}px, 1fr))`,
64
74
  // gridAutoRows: `${sizes[size].itemHeight}px`,
65
75
  gap: `${sizes[size].gap}px`,
@@ -75,10 +85,10 @@ const Grid = styled.div<{
75
85
 
76
86
  const Container = styled.div<{ scrollable: boolean }>(
77
87
  ({ theme, scrollable }) => ({
78
- flex: scrollable ? '1' : '0 0 auto',
79
- display: 'flex',
80
- flexDirection: 'column',
81
- }),
88
+ flex: scrollable ? "1" : "0 0 auto",
89
+ display: "flex",
90
+ flexDirection: "column",
91
+ })
82
92
  );
83
93
 
84
94
  const ContentContainer = styled.div<{
@@ -87,83 +97,83 @@ const ContentContainer = styled.div<{
87
97
  bordered: boolean;
88
98
  disabled: boolean;
89
99
  }>(({ theme, selected, hovered, bordered, disabled }) => ({
90
- display: 'flex',
91
- flex: '1',
100
+ display: "flex",
101
+ flex: "1",
92
102
  backgroundColor: theme.colors.sidebar.background,
93
- alignItems: 'center',
94
- justifyContent: 'center',
95
- borderRadius: '2px',
103
+ alignItems: "center",
104
+ justifyContent: "center",
105
+ borderRadius: "2px",
96
106
  border: `1px solid ${
97
107
  selected
98
108
  ? theme.colors.primary
99
109
  : // : hovered
100
- // ? `rgb(132, 63, 255, 0.5)`
101
- bordered
102
- ? theme.colors.divider
103
- : 'transparent'
110
+ // ? `rgb(132, 63, 255, 0.5)`
111
+ bordered
112
+ ? theme.colors.divider
113
+ : "transparent"
104
114
  }`,
105
- overflow: 'hidden',
115
+ overflow: "hidden",
106
116
 
107
- cursor: 'pointer',
117
+ cursor: "pointer",
108
118
  ...(disabled
109
119
  ? { opacity: 0.5 }
110
120
  : {
111
- '&:hover': { opacity: 0.85 },
112
- '&:active': { opacity: 0.7 },
121
+ "&:hover": { opacity: 0.85 },
122
+ "&:active": { opacity: 0.7 },
113
123
  }),
114
124
  }));
115
125
 
116
126
  const ItemContainer = styled.div(({ theme }) => ({
117
- display: 'flex',
118
- flexDirection: 'column',
119
- position: 'relative',
127
+ display: "flex",
128
+ flexDirection: "column",
129
+ position: "relative",
120
130
 
121
- '&:focus': {
131
+ "&:focus": {
122
132
  boxShadow: `0 0 0 1px ${theme.colors.sidebar.background}, 0 0 0 3px ${theme.colors.primary}`,
123
- outline: 'none',
133
+ outline: "none",
124
134
  },
125
135
  }));
126
136
 
127
137
  const ItemTitle = styled.span<{ showBackground: boolean }>(
128
138
  ({ theme, showBackground }) => ({
129
139
  ...theme.textStyles.small,
130
- lineHeight: '1',
140
+ lineHeight: "1",
131
141
  color: theme.colors.text,
132
142
  fontWeight: 500,
133
- userSelect: 'none',
134
- whiteSpace: 'pre',
135
- overflow: 'hidden',
136
- textOverflow: 'ellipsis',
143
+ userSelect: "none",
144
+ whiteSpace: "pre",
145
+ overflow: "hidden",
146
+ textOverflow: "ellipsis",
137
147
 
138
148
  ...(showBackground && {
139
149
  background: theme.colors.sidebar.background,
140
150
  // border: `1px solid ${theme.colors.dividerSubtle}`,
141
- padding: '2px 4px',
142
- borderRadius: '2px',
143
- backdropFilter: 'blur(4px)',
151
+ padding: "2px 4px",
152
+ borderRadius: "2px",
153
+ backdropFilter: "blur(4px)",
144
154
  }),
145
- }),
155
+ })
146
156
  );
147
157
 
148
158
  const ItemDescription = styled.span<{ showBackground: boolean }>(
149
159
  ({ theme, showBackground }) => ({
150
160
  ...theme.textStyles.small,
151
- fontSize: '0.7rem',
152
- lineHeight: '1',
161
+ fontSize: "0.7rem",
162
+ lineHeight: "1",
153
163
  color: theme.colors.textMuted,
154
- userSelect: 'none',
155
- whiteSpace: 'pre',
156
- overflow: 'hidden',
157
- textOverflow: 'ellipsis',
164
+ userSelect: "none",
165
+ whiteSpace: "pre",
166
+ overflow: "hidden",
167
+ textOverflow: "ellipsis",
158
168
 
159
169
  ...(showBackground && {
160
170
  background: theme.colors.sidebar.background,
161
171
  // border: `1px solid ${theme.colors.dividerSubtle}`,
162
- padding: '2px 4px',
163
- borderRadius: '2px',
164
- backdropFilter: 'blur(4px)',
172
+ padding: "2px 4px",
173
+ borderRadius: "2px",
174
+ backdropFilter: "blur(4px)",
165
175
  }),
166
- }),
176
+ })
167
177
  );
168
178
 
169
179
  const SectionTitle = styled.span<{ last?: boolean }>(
@@ -171,39 +181,39 @@ const SectionTitle = styled.span<{ last?: boolean }>(
171
181
  ...theme.textStyles.heading3,
172
182
  color: last ? theme.colors.text : theme.colors.textMuted,
173
183
  fontWeight: 500,
174
- userSelect: 'none',
175
- whiteSpace: 'pre',
176
- overflow: 'hidden',
177
- textOverflow: 'ellipsis',
178
- lineHeight: '1',
179
- }),
184
+ userSelect: "none",
185
+ whiteSpace: "pre",
186
+ overflow: "hidden",
187
+ textOverflow: "ellipsis",
188
+ lineHeight: "1",
189
+ })
180
190
  );
181
191
 
182
192
  const SectionHeaderContainer = styled.div(({ theme }) => ({
183
- padding: '0 20px',
193
+ padding: "0 20px",
184
194
  }));
185
195
 
186
196
  const TextOverlay = styled.div({
187
- position: 'absolute',
197
+ position: "absolute",
188
198
  inset: 0,
189
- display: 'flex',
190
- flexDirection: 'column',
191
- justifyContent: 'end',
192
- alignItems: 'start',
193
- padding: '4px',
194
- pointerEvents: 'none',
195
- overflow: 'hidden',
196
- textOverflow: 'ellipsis',
197
- whiteSpace: 'nowrap',
198
- gap: '2px',
199
+ display: "flex",
200
+ flexDirection: "column",
201
+ justifyContent: "end",
202
+ alignItems: "start",
203
+ padding: "4px",
204
+ pointerEvents: "none",
205
+ overflow: "hidden",
206
+ textOverflow: "ellipsis",
207
+ whiteSpace: "nowrap",
208
+ gap: "2px",
199
209
  });
200
210
 
201
211
  const shimmer = keyframes({
202
- '0%': {
203
- backgroundPosition: '-200% 0',
212
+ "0%": {
213
+ backgroundPosition: "-200% 0",
204
214
  },
205
- '100%': {
206
- backgroundPosition: '200% 0',
215
+ "100%": {
216
+ backgroundPosition: "200% 0",
207
217
  },
208
218
  });
209
219
 
@@ -240,6 +250,7 @@ interface ItemProps<MenuItemType extends string = string> {
240
250
  menuItems?: MenuItem<MenuItemType>[];
241
251
  onSelectMenuItem?: (value: MenuItemType) => void;
242
252
  onContextMenu?: () => void;
253
+ style?: CSSProperties;
243
254
  }
244
255
 
245
256
  const GridViewItem = forwardRef(function GridViewItem<
@@ -259,8 +270,9 @@ const GridViewItem = forwardRef(function GridViewItem<
259
270
  menuItems,
260
271
  onSelectMenuItem,
261
272
  onContextMenu,
273
+ style,
262
274
  }: ItemProps<MenuItemType>,
263
- forwardedRef: ForwardedRef<HTMLDivElement>,
275
+ forwardedRef: ForwardedRef<HTMLDivElement>
264
276
  ) {
265
277
  const [hovered, setHovered] = React.useState(false);
266
278
 
@@ -281,12 +293,12 @@ const GridViewItem = forwardRef(function GridViewItem<
281
293
  onClick?.(event);
282
294
  onPress?.(event);
283
295
  },
284
- [onClick, onPress],
296
+ [onClick, onPress]
285
297
  );
286
298
 
287
299
  const handleKeyDown = useCallback(
288
300
  (event: React.KeyboardEvent) => {
289
- if (event.key === 'Enter' || event.key === ' ') {
301
+ if (event.key === "Enter" || event.key === " ") {
290
302
  event.stopPropagation();
291
303
  event.preventDefault();
292
304
 
@@ -295,7 +307,7 @@ const GridViewItem = forwardRef(function GridViewItem<
295
307
  return;
296
308
  }
297
309
  },
298
- [onPress],
310
+ [onPress]
299
311
  );
300
312
 
301
313
  let element = (
@@ -314,19 +326,20 @@ const GridViewItem = forwardRef(function GridViewItem<
314
326
  onClick={handleClick}
315
327
  onDoubleClick={onDoubleClick}
316
328
  onContextMenu={onContextMenu}
329
+ style={style}
317
330
  >
318
331
  {children}
319
332
  </ContentContainer>
320
- {textPosition === 'below' && (
333
+ {textPosition === "below" && (
321
334
  <>
322
335
  <Spacer.Vertical size={8} />
323
- <ItemTitle showBackground={false}>{title || ' '}</ItemTitle>
336
+ <ItemTitle showBackground={false}>{title || " "}</ItemTitle>
324
337
  <ItemDescription showBackground={false}>
325
- {subtitle || ' '}
338
+ {subtitle || " "}
326
339
  </ItemDescription>
327
340
  </>
328
341
  )}
329
- {textPosition === 'overlay' && hovered && (title || subtitle) && (
342
+ {textPosition === "overlay" && hovered && (title || subtitle) && (
330
343
  <TextOverlay>
331
344
  {title && <ItemTitle showBackground>{title}</ItemTitle>}
332
345
  {subtitle && (
@@ -350,7 +363,7 @@ const GridViewItem = forwardRef(function GridViewItem<
350
363
  );
351
364
  }
352
365
 
353
- if (textPosition === 'toolip') {
366
+ if (textPosition === "toolip") {
354
367
  element = (
355
368
  <Tooltip
356
369
  content={
@@ -370,14 +383,14 @@ const GridViewItem = forwardRef(function GridViewItem<
370
383
 
371
384
  type GridViewContextValue = {
372
385
  size: GridViewSize;
373
- textPosition: 'overlay' | 'below' | 'toolip';
386
+ textPosition: "overlay" | "below" | "toolip";
374
387
  bordered: boolean;
375
388
  disabled: boolean;
376
389
  };
377
390
 
378
391
  const GridViewContext = createContext<GridViewContextValue>({
379
- size: 'small',
380
- textPosition: 'below',
392
+ size: "small",
393
+ textPosition: "below",
381
394
  bordered: false,
382
395
  disabled: false,
383
396
  });
@@ -389,11 +402,11 @@ interface GridViewRootProps extends Partial<GridViewContextValue> {
389
402
  }
390
403
 
391
404
  function GridViewRoot({
392
- size = 'small',
405
+ size = "small",
393
406
  children,
394
407
  scrollable = true,
395
408
  onClick,
396
- textPosition = 'below',
409
+ textPosition = "below",
397
410
  bordered = false,
398
411
  disabled = false,
399
412
  }: GridViewRootProps) {
@@ -404,7 +417,7 @@ function GridViewRoot({
404
417
 
405
418
  onClick?.();
406
419
  },
407
- [onClick],
420
+ [onClick]
408
421
  );
409
422
 
410
423
  const contextValue = useMemo(
@@ -414,7 +427,7 @@ function GridViewRoot({
414
427
  bordered,
415
428
  disabled,
416
429
  }),
417
- [bordered, disabled, size, textPosition],
430
+ [bordered, disabled, size, textPosition]
418
431
  );
419
432
 
420
433
  return (
@@ -428,10 +441,10 @@ function GridViewRoot({
428
441
 
429
442
  function GridViewSection({
430
443
  children,
431
- padding = '20px',
444
+ padding = "20px",
432
445
  }: {
433
446
  children?: ReactNode;
434
- padding?: CSSProperties['padding'];
447
+ padding?: CSSProperties["padding"];
435
448
  }) {
436
449
  const { size } = useContext(GridViewContext);
437
450
 
@@ -443,7 +456,7 @@ function GridViewSection({
443
456
  }
444
457
 
445
458
  function GridViewSectionHeader({ title }: { title: string }) {
446
- const grouped = title.split('/');
459
+ const grouped = title.split("/");
447
460
 
448
461
  return (
449
462
  <SectionHeaderContainer>
@@ -454,7 +467,7 @@ function GridViewSectionHeader({ title }: { title: string }) {
454
467
  {title}
455
468
  </SectionTitle>
456
469
  )),
457
- <SectionTitle> / </SectionTitle>,
470
+ <SectionTitle> / </SectionTitle>
458
471
  )}
459
472
  </SectionHeaderContainer>
460
473
  );
@@ -1,16 +1,18 @@
1
- import * as Icons from '@noya-app/noya-icons';
1
+ import * as Icons from "@noya-app/noya-icons";
2
2
  import React, {
3
3
  CSSProperties,
4
4
  ForwardedRef,
5
5
  forwardRef,
6
6
  memo,
7
7
  useMemo,
8
- } from 'react';
9
- import { useTheme } from 'styled-components';
10
- import { Button, ButtonRootProps } from './Button';
8
+ } from "react";
9
+ import { useTheme } from "styled-components";
10
+ import { Button, ButtonRootProps } from "./Button";
11
11
 
12
- type Props = Omit<ButtonRootProps, 'children' | 'variant' | 'flex' | 'size'> & {
12
+ type Props = Omit<ButtonRootProps, "children" | "variant" | "flex" | "size"> & {
13
13
  iconName: keyof typeof Icons;
14
+ className?: string;
15
+ style?: CSSProperties;
14
16
  selected?: boolean;
15
17
  color?: string;
16
18
  size?: number;
@@ -19,7 +21,7 @@ type Props = Omit<ButtonRootProps, 'children' | 'variant' | 'flex' | 'size'> & {
19
21
  export const IconButton = memo(
20
22
  forwardRef(function IconButton(
21
23
  { selected, iconName, color, size, contentStyle, ...props }: Props,
22
- forwardedRef: ForwardedRef<HTMLButtonElement>,
24
+ forwardedRef: ForwardedRef<HTMLButtonElement>
23
25
  ) {
24
26
  const { icon: iconColor, iconSelected: iconSelectedColor } =
25
27
  useTheme().colors;
@@ -28,7 +30,7 @@ export const IconButton = memo(
28
30
 
29
31
  const style = useMemo((): CSSProperties => {
30
32
  return {
31
- padding: '0 2px',
33
+ padding: "0 2px",
32
34
  ...(size && { minHeight: size }),
33
35
  ...contentStyle,
34
36
  };
@@ -42,5 +44,5 @@ export const IconButton = memo(
42
44
  />
43
45
  </Button>
44
46
  );
45
- }),
47
+ })
46
48
  );
@@ -157,6 +157,7 @@ type Props = {
157
157
  onDeleteWhenEmpty?: () => void;
158
158
  size?: InputFieldSize;
159
159
  style?: React.CSSProperties;
160
+ className?: string;
160
161
  children?: React.ReactNode;
161
162
  hideChildrenWhenFocused?: boolean;
162
163
  hideMenuWhenEmptyValue?: boolean;
@@ -177,6 +178,7 @@ export const InputFieldWithCompletions = memo(
177
178
  onBlur,
178
179
  onDeleteWhenEmpty,
179
180
  style,
181
+ className,
180
182
  children,
181
183
  hideChildrenWhenFocused = false,
182
184
  hideMenuWhenEmptyValue = false,
@@ -421,6 +423,7 @@ export const InputFieldWithCompletions = memo(
421
423
  onFocusCapture={handleFocus}
422
424
  onKeyDown={handleKeyDown}
423
425
  style={style}
426
+ className={className}
424
427
  autoCapitalize="off"
425
428
  autoComplete="off"
426
429
  autoCorrect="off"
@@ -50,7 +50,7 @@ export const Column = styled.div(({ theme }) => ({
50
50
  flex: "1",
51
51
  display: "flex",
52
52
  flexDirection: "column",
53
- gap: "2px",
53
+ gap: "4px",
54
54
  }));
55
55
 
56
56
  export const Checkbox = styled.input(({ theme }) => ({
@@ -1,20 +1,20 @@
1
- import * as SwitchPrimitive from '@radix-ui/react-switch';
2
- import React from 'react';
3
- import styled from 'styled-components';
1
+ import * as SwitchPrimitive from "@radix-ui/react-switch";
2
+ import React from "react";
3
+ import styled from "styled-components";
4
4
 
5
- type SwitchVariant = 'normal' | 'primary' | 'secondary';
5
+ type SwitchColorScheme = "normal" | "primary" | "secondary";
6
6
 
7
7
  const SwitchRoot = styled(SwitchPrimitive.Root)<{
8
- variant: SwitchVariant;
9
- }>(({ theme, variant }) => ({
10
- all: 'unset',
8
+ colorScheme: SwitchColorScheme;
9
+ }>(({ theme, colorScheme: variant }) => ({
10
+ all: "unset",
11
11
  width: 32,
12
12
  height: 19,
13
13
  backgroundColor: theme.colors.activeBackground,
14
- borderRadius: '9999px',
15
- position: 'relative',
16
- WebkitTapHighlightColor: 'rgba(0, 0, 0, 0)',
17
- cursor: 'pointer',
14
+ borderRadius: "9999px",
15
+ position: "relative",
16
+ WebkitTapHighlightColor: "rgba(0, 0, 0, 0)",
17
+ cursor: "pointer",
18
18
  // '&:focus': {
19
19
  // boxShadow: `0 0 0 1px ${
20
20
  // variant === 'secondary' ? theme.colors.secondary : theme.colors.primary
@@ -22,40 +22,40 @@ const SwitchRoot = styled(SwitchPrimitive.Root)<{
22
22
  // },
23
23
  '&[data-state="checked"]': {
24
24
  backgroundColor:
25
- variant === 'primary'
25
+ variant === "primary"
26
26
  ? theme.colors.primary
27
- : variant === 'secondary'
28
- ? theme.colors.secondary
29
- : undefined,
27
+ : variant === "secondary"
28
+ ? theme.colors.secondary
29
+ : undefined,
30
30
  },
31
31
  }));
32
32
 
33
33
  const SwitchThumb = styled(SwitchPrimitive.Thumb)({
34
- display: 'block',
34
+ display: "block",
35
35
  width: 15,
36
36
  height: 15,
37
- backgroundColor: 'white',
38
- borderRadius: '9999px',
39
- transition: 'transform 100ms',
40
- transform: 'translateX(2px)',
41
- willChange: 'transform',
42
- '&[data-state="checked"]': { transform: 'translateX(15px)' },
37
+ backgroundColor: "white",
38
+ borderRadius: "9999px",
39
+ transition: "transform 100ms",
40
+ transform: "translateX(2px)",
41
+ willChange: "transform",
42
+ '&[data-state="checked"]': { transform: "translateX(15px)" },
43
43
  });
44
44
 
45
45
  interface Props {
46
46
  value: boolean;
47
47
  onChange: (value: boolean) => void;
48
- variant?: SwitchVariant;
48
+ colorScheme?: SwitchColorScheme;
49
49
  }
50
50
 
51
51
  export const Switch = function Switch({
52
52
  value,
53
53
  onChange,
54
- variant = 'normal',
54
+ colorScheme = "normal",
55
55
  }: Props) {
56
56
  return (
57
57
  <SwitchRoot
58
- variant={variant}
58
+ colorScheme={colorScheme}
59
59
  checked={value}
60
60
  onCheckedChange={(newValue) => {
61
61
  onChange(newValue);