@noya-app/noya-designsystem 0.1.23 → 0.1.25

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noya-app/noya-designsystem",
3
- "version": "0.1.23",
3
+ "version": "0.1.25",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.ts",
@@ -5,7 +5,7 @@ import { useDesignSystemTheme } from "../contexts/DesignSystemConfiguration";
5
5
  import { useHover } from "../hooks/useHover";
6
6
 
7
7
  type ChipColorScheme = "primary" | "secondary" | "error";
8
- type ChipSize = "small" | "medium";
8
+ type ChipSize = "small" | "medium" | "large";
9
9
  type ChipVariant = "solid" | "outlined" | "ghost";
10
10
 
11
11
  const ChipElement = styled.span<{
@@ -49,15 +49,20 @@ const ChipElement = styled.span<{
49
49
  // lineHeight: "1.4",
50
50
  lineHeight: "15px",
51
51
  whiteSpace: "pre",
52
- ...($size === "medium"
52
+ ...($size === "large"
53
53
  ? {
54
54
  fontSize: "11px",
55
55
  padding: "4px 8px",
56
56
  }
57
- : {
58
- fontSize: "9px",
59
- padding: "0px 4px",
60
- }),
57
+ : $size === "medium"
58
+ ? {
59
+ fontSize: "10px",
60
+ padding: "2px 6px",
61
+ }
62
+ : {
63
+ fontSize: "9px",
64
+ padding: "0px 4px",
65
+ }),
61
66
  ...($monospace && {
62
67
  fontFamily: theme.fonts.monospace,
63
68
  }),
@@ -96,7 +101,7 @@ const DeleteElement = styled(Cross1Icon)<{
96
101
  cursor: "pointer",
97
102
  opacity: 0.5,
98
103
 
99
- ...(size === "medium"
104
+ ...(size === "large"
100
105
  ? {
101
106
  marginLeft: "2px",
102
107
  // top: '-1px',
@@ -124,7 +129,7 @@ const AddElement = styled(PlusIcon).withConfig({
124
129
  cursor: "pointer",
125
130
  opacity: 0.5,
126
131
 
127
- ...(size === "medium"
132
+ ...(size === "large"
128
133
  ? {
129
134
  marginRight: "2px",
130
135
  top: "-1px",
@@ -168,7 +173,7 @@ export const Chip = memo(
168
173
  addable,
169
174
  clickable,
170
175
  style,
171
- size = "medium",
176
+ size = "large",
172
177
  variant = "solid",
173
178
  monospace = false,
174
179
  tabIndex,
@@ -3,6 +3,7 @@ import { useKeyboardShortcuts } from "@noya-app/noya-keymap";
3
3
  import * as RadixContextMenu from "@radix-ui/react-context-menu";
4
4
  import React, { ReactNode, memo, useCallback, useMemo } from "react";
5
5
  import styled from "styled-components";
6
+ import { renderIcon } from "./Icons";
6
7
  import { Spacer } from "./Spacer";
7
8
  import {
8
9
  CHECKBOX_RIGHT_INSET,
@@ -98,7 +99,7 @@ const ContextMenuItem = memo(function ContextMenuItem<T extends string>({
98
99
  )}
99
100
  {icon && (
100
101
  <>
101
- {icon}
102
+ {renderIcon(icon)}
102
103
  <Spacer.Horizontal size={8} />
103
104
  </>
104
105
  )}
@@ -12,6 +12,7 @@ import React, {
12
12
  } from "react";
13
13
  import styled from "styled-components";
14
14
  import { MenuItemProps, MenuProps } from "./ContextMenu";
15
+ import { renderIcon } from "./Icons";
15
16
  import { Spacer } from "./Spacer";
16
17
  import {
17
18
  CHECKBOX_RIGHT_INSET,
@@ -73,7 +74,7 @@ const DropdownMenuItem = memo(function ContextMenuItem<T extends string>({
73
74
  </StyledItemIndicator>
74
75
  {icon && (
75
76
  <>
76
- {icon}
77
+ {renderIcon(icon)}
77
78
  <Spacer.Horizontal size={8} />
78
79
  </>
79
80
  )}
@@ -89,7 +90,7 @@ const DropdownMenuItem = memo(function ContextMenuItem<T extends string>({
89
90
  )}
90
91
  {icon && (
91
92
  <>
92
- {icon}
93
+ {renderIcon(icon)}
93
94
  <Spacer.Horizontal size={8} />
94
95
  </>
95
96
  )}
@@ -1,4 +1,3 @@
1
- import * as Icons from "@noya-app/noya-icons";
2
1
  import React, {
3
2
  CSSProperties,
4
3
  ForwardedRef,
@@ -8,9 +7,10 @@ import React, {
8
7
  } from "react";
9
8
  import { useTheme } from "styled-components";
10
9
  import { Button, ButtonRootProps } from "./Button";
10
+ import { IconName, Icons } from "./Icons";
11
11
 
12
12
  type Props = Omit<ButtonRootProps, "children" | "variant" | "flex" | "size"> & {
13
- iconName: keyof typeof Icons;
13
+ iconName: IconName;
14
14
  className?: string;
15
15
  style?: CSSProperties;
16
16
  selected?: boolean;
@@ -0,0 +1,18 @@
1
+ import * as Icons from "@noya-app/noya-icons";
2
+ import React, { ReactNode } from "react";
3
+
4
+ export type IconName = keyof typeof Icons;
5
+
6
+ export { Icons };
7
+
8
+ export function renderIcon(
9
+ iconName: Exclude<ReactNode, string> | IconName
10
+ ): ReactNode {
11
+ if (typeof iconName === "string") {
12
+ const Icon = Icons[iconName as IconName];
13
+
14
+ return <Icon />;
15
+ }
16
+
17
+ return iconName;
18
+ }
@@ -662,6 +662,39 @@ function InputFieldRoot({
662
662
  );
663
663
  }
664
664
 
665
+ const PrimitiveInputField = styled.input(({ theme, readOnly, disabled }) => {
666
+ return {
667
+ // placeholder
668
+ "&::placeholder": {
669
+ color: theme.colors.textDisabled,
670
+ },
671
+ ...theme.textStyles.small,
672
+ color: readOnly
673
+ ? theme.colors.textMuted
674
+ : disabled
675
+ ? theme.colors.textDisabled
676
+ : theme.colors.text,
677
+ width: "0px", // Reset intrinsic width
678
+ flex: "1 1 0px",
679
+ position: "relative",
680
+ border: "0",
681
+ outline: "none",
682
+ minWidth: "0",
683
+ alignSelf: "stretch",
684
+ borderRadius: "4px",
685
+ paddingTop: "4px",
686
+ paddingBottom: "4px",
687
+ paddingLeft: "6px",
688
+ paddingRight: "6px",
689
+ background: theme.colors.inputBackground,
690
+ "&:focus": {
691
+ boxShadow: `0 0 0 2px ${theme.colors.primary}`,
692
+ },
693
+ userSelect: "all",
694
+ pointerEvents: "all",
695
+ };
696
+ });
697
+
665
698
  export namespace InputField {
666
699
  export const Root = memo(InputFieldRoot);
667
700
  export const Input = memo(InputFieldInput);
@@ -670,4 +703,5 @@ export namespace InputField {
670
703
  export const DropdownMenu = InputFieldDropdownMenu;
671
704
  export const Button = InputFieldButton;
672
705
  export const Label = InputFieldLabel;
706
+ export const PrimitiveElement = PrimitiveInputField;
673
707
  }
@@ -66,14 +66,15 @@ type ListRowContextValue = {
66
66
  // The dragged item isn't passed a context value (doing so causes an infinite loop),
67
67
  // so we pass this separately. Rows need the indentation to look correct when dragging,
68
68
  // and the dragged row doesn't have a ListRowContextValue.
69
- type DraggingContextValue = {
69
+ type ListViewDraggingContextValue = {
70
70
  indentation: number;
71
71
  isDragging?: boolean;
72
72
  };
73
73
 
74
- const DraggingContext = createContext<DraggingContextValue>({
74
+ const ListViewDraggingContext = createContext<ListViewDraggingContextValue>({
75
75
  indentation: 12,
76
76
  });
77
+ (ListViewDraggingContext as any).displayName = "ListViewDraggingContext";
77
78
 
78
79
  const ListRowContext = createContext<ListRowContextValue>({
79
80
  marginType: "none",
@@ -88,6 +89,7 @@ const ListRowContext = createContext<ListRowContextValue>({
88
89
  isSectionHeader: false,
89
90
  colorScheme: "primary",
90
91
  });
92
+ (ListRowContext as any).displayName = "ListRowContext";
91
93
 
92
94
  /* ----------------------------------------------------------------------------
93
95
  * RowTitle
@@ -386,7 +388,7 @@ const ListViewRow = forwardRef(function ListViewRow<
386
388
  const { hoverProps } = useHover({
387
389
  onHoverChange,
388
390
  });
389
- const { indentation, isDragging } = useContext(DraggingContext);
391
+ const { indentation, isDragging } = useContext(ListViewDraggingContext);
390
392
 
391
393
  const handlePress = useCallback(
392
394
  (event: React.MouseEvent) => {
@@ -524,6 +526,7 @@ const ListViewRow = forwardRef(function ListViewRow<
524
526
  const RenderItemContext = createContext<(index: number) => ReactNode>(
525
527
  () => null
526
528
  );
529
+ (RenderItemContext as any).displayName = "RenderItemContext";
527
530
 
528
531
  const VirtualizedListRow = memo(function VirtualizedListRow({
529
532
  index,
@@ -761,8 +764,29 @@ const ListViewRootInner = forwardRef(function ListViewRootInner<T>(
761
764
  [data, renderItem]
762
765
  );
763
766
 
767
+ // TODO: Do we still use section header properties anywhere?
768
+ const defaultContextValue = useMemo(
769
+ (): ListRowContextValue => ({
770
+ colorScheme,
771
+ marginType: "none",
772
+ selectedPosition: "only",
773
+ sortable,
774
+ expandable,
775
+ divider,
776
+ pressEventName,
777
+ variant,
778
+ gap,
779
+ sectionHeaderVariant: "normal",
780
+ isSectionHeader: false,
781
+ }),
782
+ [colorScheme, sortable, expandable, divider, pressEventName, variant, gap]
783
+ );
784
+
764
785
  const getItemContextValue = useCallback(
765
786
  (i: number): ListRowContextValue | undefined => {
787
+ if (variant === "bare" || variant === "normal")
788
+ return defaultContextValue;
789
+
766
790
  const current = renderChild(i);
767
791
 
768
792
  if (!isValidElement(current)) return;
@@ -827,6 +851,8 @@ const ListViewRootInner = forwardRef(function ListViewRootInner<T>(
827
851
  };
828
852
  },
829
853
  [
854
+ variant,
855
+ defaultContextValue,
830
856
  renderChild,
831
857
  data.length,
832
858
  colorScheme,
@@ -834,7 +860,6 @@ const ListViewRootInner = forwardRef(function ListViewRootInner<T>(
834
860
  expandable,
835
861
  divider,
836
862
  pressEventName,
837
- variant,
838
863
  sectionHeaderVariant,
839
864
  gap,
840
865
  ]
@@ -848,9 +873,9 @@ const ListViewRootInner = forwardRef(function ListViewRootInner<T>(
848
873
  const renderOverlay = useCallback(
849
874
  (index: number) => (
850
875
  <div style={{ opacity: 0.25 }}>
851
- <DraggingContext.Provider value={draggingContextOverlayValue}>
876
+ <ListViewDraggingContext.Provider value={draggingContextOverlayValue}>
852
877
  {renderItem(data[index], index, { isDragging: true })}
853
- </DraggingContext.Provider>
878
+ </ListViewDraggingContext.Provider>
854
879
  </div>
855
880
  ),
856
881
  [draggingContextOverlayValue, renderItem, data]
@@ -916,7 +941,7 @@ const ListViewRootInner = forwardRef(function ListViewRootInner<T>(
916
941
  const draggingContextValue = useMemo(() => ({ indentation }), [indentation]);
917
942
 
918
943
  return (
919
- <DraggingContext.Provider value={draggingContextValue}>
944
+ <ListViewDraggingContext.Provider value={draggingContextValue}>
920
945
  <RootContainer
921
946
  id={id}
922
947
  className={className}
@@ -945,7 +970,7 @@ const ListViewRootInner = forwardRef(function ListViewRootInner<T>(
945
970
  )
946
971
  )}
947
972
  </RootContainer>
948
- </DraggingContext.Provider>
973
+ </ListViewDraggingContext.Provider>
949
974
  );
950
975
  });
951
976
 
@@ -1,8 +1,9 @@
1
1
  import { DropdownChevronIcon } from "@noya-app/noya-icons";
2
2
  import * as Select from "@radix-ui/react-select";
3
- import React, { memo } from "react";
3
+ import React, { CSSProperties, memo } from "react";
4
4
  import { styled } from "styled-components";
5
5
  import { Button } from "./Button";
6
+ import { renderIcon } from "./Icons";
6
7
  import { Spacer } from "./Spacer";
7
8
  import { MenuItem, RegularMenuItem, styles } from "./internal/Menu";
8
9
 
@@ -14,6 +15,13 @@ type Props<T extends string> = {
14
15
  value: T;
15
16
  onSelect?: (value: T) => void;
16
17
  placeholder?: string;
18
+ disabled?: boolean;
19
+ readOnly?: boolean;
20
+ };
21
+
22
+ const readOnlyStyle: CSSProperties = {
23
+ justifyContent: "flex-start",
24
+ textAlign: "left",
17
25
  };
18
26
 
19
27
  export const SelectMenu = memo(function SelectMenu<T extends string = string>({
@@ -24,6 +32,8 @@ export const SelectMenu = memo(function SelectMenu<T extends string = string>({
24
32
  value,
25
33
  onSelect,
26
34
  placeholder,
35
+ disabled,
36
+ readOnly,
27
37
  }: Props<T>) {
28
38
  const selectedItem = menuItems.find(
29
39
  (item): item is RegularMenuItem<T> =>
@@ -31,13 +41,33 @@ export const SelectMenu = memo(function SelectMenu<T extends string = string>({
31
41
  );
32
42
  const icon = selectedItem?.icon;
33
43
 
44
+ if (readOnly) {
45
+ return (
46
+ <Button
47
+ id={id}
48
+ style={style}
49
+ contentStyle={readOnlyStyle}
50
+ className={className}
51
+ disabled={disabled}
52
+ >
53
+ {icon && (
54
+ <>
55
+ {renderIcon(icon)}
56
+ <Spacer.Horizontal size={8} />
57
+ </>
58
+ )}
59
+ {selectedItem?.title ?? value}
60
+ </Button>
61
+ );
62
+ }
63
+
34
64
  return (
35
65
  <Select.Root value={value} onValueChange={onSelect}>
36
66
  <Select.SelectTrigger asChild>
37
- <Button id={id} style={style} className={className}>
67
+ <Button id={id} style={style} className={className} disabled={disabled}>
38
68
  {icon && (
39
69
  <>
40
- {icon}
70
+ {renderIcon(icon)}
41
71
  <Spacer.Horizontal size={8} />
42
72
  </>
43
73
  )}
@@ -86,7 +116,7 @@ const SelectItem = React.forwardRef(
86
116
  <StyledItem {...props} ref={forwardedRef}>
87
117
  {icon && (
88
118
  <>
89
- {icon}
119
+ {renderIcon(icon)}
90
120
  <Spacer.Horizontal size={8} />
91
121
  </>
92
122
  )}
@@ -45,17 +45,20 @@ interface Props {
45
45
  value: boolean;
46
46
  onChange: (value: boolean) => void;
47
47
  colorScheme?: SwitchColorScheme;
48
+ disabled?: boolean;
48
49
  }
49
50
 
50
51
  export const Switch = function Switch({
51
52
  value,
52
53
  onChange,
53
54
  colorScheme = "normal",
55
+ disabled,
54
56
  }: Props) {
55
57
  return (
56
58
  <SwitchRoot
57
59
  $colorScheme={colorScheme}
58
60
  checked={value}
61
+ disabled={disabled}
59
62
  onCheckedChange={(newValue) => {
60
63
  onChange(newValue);
61
64
  }}
@@ -7,6 +7,7 @@ import React, {
7
7
  useContext,
8
8
  } from "react";
9
9
  import { IconButton } from "./IconButton";
10
+ import { IconName, renderIcon } from "./Icons";
10
11
  import { ListView } from "./ListView";
11
12
  import { Spacer } from "./Spacer";
12
13
 
@@ -15,7 +16,7 @@ import { Spacer } from "./Spacer";
15
16
  * ------------------------------------------------------------------------- */
16
17
 
17
18
  type TreeRowBaseProps = {
18
- icon?: ReactNode;
19
+ icon?: Exclude<ReactNode, string> | IconName;
19
20
  expanded?: boolean;
20
21
  onClickChevron?: ({ altKey }: { altKey: boolean }) => void;
21
22
  };
@@ -61,7 +62,7 @@ const TreeRow = forwardRef(function TreeRow<MenuItemType extends string>(
61
62
  )}
62
63
  {icon && (
63
64
  <>
64
- {icon}
65
+ {renderIcon(icon)}
65
66
  <Spacer.Horizontal size={10} />
66
67
  </>
67
68
  )}
@@ -4,6 +4,7 @@ import styled, { CSSObject } from "styled-components";
4
4
  import { useDesignSystemConfiguration } from "../../contexts/DesignSystemConfiguration";
5
5
  import { Theme } from "../../theme";
6
6
  import withSeparatorElements from "../../utils/withSeparatorElements";
7
+ import { IconName } from "../Icons";
7
8
 
8
9
  export const SEPARATOR_ITEM = "separator";
9
10
 
@@ -63,7 +64,7 @@ export type RegularMenuItem<T extends string> = {
63
64
  shortcut?: string;
64
65
  checked?: boolean;
65
66
  disabled?: boolean;
66
- icon?: ReactNode;
67
+ icon?: Exclude<ReactNode, string> | IconName;
67
68
  items?: MenuItem<T>[];
68
69
  role?: MenuItemRole;
69
70
  };