@noya-app/noya-designsystem 0.1.8 → 0.1.10

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.8",
3
+ "version": "0.1.10",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.ts",
@@ -13,11 +13,11 @@
13
13
  "@dnd-kit/core": "3.1.1",
14
14
  "@dnd-kit/modifiers": "3.0.0",
15
15
  "@dnd-kit/sortable": "4.0.0",
16
- "@noya-app/noya-colorpicker": "0.1.6",
16
+ "@noya-app/noya-colorpicker": "0.1.7",
17
17
  "@noya-app/noya-utils": "0.1.0",
18
18
  "@noya-app/noya-geometry": "0.1.2",
19
19
  "@noya-app/noya-icons": "0.1.2",
20
- "@noya-app/noya-keymap": "0.1.0",
20
+ "@noya-app/noya-keymap": "0.1.1",
21
21
  "@radix-ui/primitive": "^1.0.0",
22
22
  "@radix-ui/react-avatar": "^1.0.1",
23
23
  "@radix-ui/react-compose-refs": "^1.0.0",
@@ -30,107 +30,120 @@ export const ButtonElement = styled.button<{
30
30
  variant: ButtonVariant;
31
31
  size: ButtonSize;
32
32
  flex?: CSSProperties["flex"];
33
- }>(({ theme, active, disabled, variant, size, flex }) => ({
34
- ...(size === "large" ? theme.textStyles.heading4 : theme.textStyles.small),
35
- textDecoration: "none",
36
- lineHeight: "1",
37
- flex: flex ?? "0 0 auto",
38
- position: "relative",
39
- border: "0",
40
- outline: "none",
41
- WebkitAppRegion: "no-drag",
42
- userSelect: "none",
43
- minWidth: variant === "normal" ? "31px" : undefined,
44
- textAlign: "left",
45
- borderRadius: "4px",
46
- paddingTop: variant === "none" ? "0px" : "4px",
47
- paddingRight: variant === "none" ? "0px" : variant === "thin" ? "1px" : "8px",
48
- paddingBottom: variant === "none" ? "0px" : "4px",
49
- paddingLeft: variant === "none" ? "0px" : variant === "thin" ? "1px" : "8px",
50
- ...(size === "large" && {
51
- paddingTop: "12px",
52
- paddingRight: "16px",
53
- paddingBottom: "12px",
54
- paddingLeft: "16px",
55
- }),
56
- background: active
57
- ? theme.colors.primary
58
- : variant === "primaryGradient"
59
- ? `linear-gradient(90deg, ${theme.colors.primary}, ${theme.colors.primaryLight})`
60
- : variant === "none" || variant === "thin"
61
- ? "transparent"
62
- : theme.colors.inputBackground,
63
- color: active ? "white" : theme.colors.text,
64
- opacity: disabled ? 0.25 : 1,
65
- "&:focus": {
66
- boxShadow: `0 0 0 1px ${theme.colors.sidebar.background}, 0 0 0 3px ${theme.colors.primary}`,
67
- },
68
- "&:hover": {
69
- background:
70
- variant === "primaryGradient" || active
71
- ? theme.colors.primaryLight
72
- : theme.colors.inputBackgroundLight,
73
- },
74
- "&:active": {
75
- background:
76
- variant === "primaryGradient"
77
- ? theme.colors.primary
78
- : theme.colors.activeBackground,
79
- },
80
- ...(variant === "primary" && {
81
- background: theme.colors.primary,
82
- color: "white",
83
- "&:hover": {
84
- background: theme.colors.primaryLight,
85
- },
86
- "&:active": {
87
- background: theme.colors.primary,
88
- },
89
- }),
90
- ...(variant === "secondary" && {
91
- background: theme.colors.secondary,
92
- color: "white",
93
- "&:hover": {
94
- background: theme.colors.secondaryLight,
95
- },
96
- "&:active": {
97
- background: theme.colors.secondary,
98
- },
99
- }),
100
- ...(variant === "secondaryBright" && {
101
- background: "#0ab557",
102
- color: "white",
103
- "&:hover": {
104
- opacity: 0.8,
105
- },
106
- "&:active": {
107
- opacity: 0.9,
33
+ defaultBackground?: string;
34
+ }>(
35
+ ({
36
+ theme,
37
+ active,
38
+ disabled,
39
+ variant,
40
+ size,
41
+ flex,
42
+ defaultBackground = theme.colors.inputBackground,
43
+ }) => ({
44
+ ...(size === "large" ? theme.textStyles.heading4 : theme.textStyles.small),
45
+ textDecoration: "none",
46
+ lineHeight: "1",
47
+ flex: flex ?? "0 0 auto",
48
+ position: "relative",
49
+ border: "0",
50
+ outline: "none",
51
+ WebkitAppRegion: "no-drag",
52
+ userSelect: "none",
53
+ minWidth: variant === "normal" ? "31px" : undefined,
54
+ textAlign: "left",
55
+ borderRadius: "4px",
56
+ paddingTop: variant === "none" ? "0px" : "4px",
57
+ paddingRight:
58
+ variant === "none" ? "0px" : variant === "thin" ? "1px" : "8px",
59
+ paddingBottom: variant === "none" ? "0px" : "4px",
60
+ paddingLeft:
61
+ variant === "none" ? "0px" : variant === "thin" ? "1px" : "8px",
62
+ ...(size === "large" && {
63
+ paddingTop: "12px",
64
+ paddingRight: "16px",
65
+ paddingBottom: "12px",
66
+ paddingLeft: "16px",
67
+ }),
68
+ background: active
69
+ ? theme.colors.primary
70
+ : variant === "primaryGradient"
71
+ ? `linear-gradient(90deg, ${theme.colors.primary}, ${theme.colors.primaryLight})`
72
+ : variant === "none" || variant === "thin"
73
+ ? "transparent"
74
+ : defaultBackground,
75
+ color: active ? "white" : theme.colors.text,
76
+ opacity: disabled ? 0.25 : 1,
77
+ "&:focus": {
78
+ boxShadow: `0 0 0 1px ${theme.colors.sidebar.background}, 0 0 0 3px ${theme.colors.primary}`,
108
79
  },
109
- }),
110
- ...(variant === "white" && {
111
- background: "white",
112
80
  "&:hover": {
113
- opacity: 0.8,
81
+ background:
82
+ variant === "primaryGradient" || active
83
+ ? theme.colors.primaryLight
84
+ : theme.colors.inputBackgroundLight,
114
85
  },
115
86
  "&:active": {
116
- opacity: 0.9,
87
+ background:
88
+ variant === "primaryGradient" || active
89
+ ? theme.colors.primary
90
+ : theme.colors.activeBackground,
117
91
  },
118
- }),
119
- ...(variant === "floating" && {
120
- background: "white",
121
- color: theme.colors.text,
122
- boxShadow: "0 1px 2px rgba(0, 0, 0, 0.1)",
123
- fontSize: "12px",
124
- padding: "0px 4px",
125
- }),
126
- display: "flex",
127
- alignItems: "center",
128
- justifyContent: "center",
92
+ ...(variant === "primary" && {
93
+ background: theme.colors.primary,
94
+ color: "white",
95
+ "&:hover": {
96
+ background: theme.colors.primaryLight,
97
+ },
98
+ "&:active": {
99
+ background: theme.colors.primary,
100
+ },
101
+ }),
102
+ ...(variant === "secondary" && {
103
+ background: theme.colors.secondary,
104
+ color: "white",
105
+ "&:hover": {
106
+ background: theme.colors.secondaryLight,
107
+ },
108
+ "&:active": {
109
+ background: theme.colors.secondary,
110
+ },
111
+ }),
112
+ ...(variant === "secondaryBright" && {
113
+ background: "#0ab557",
114
+ color: "white",
115
+ "&:hover": {
116
+ opacity: 0.8,
117
+ },
118
+ "&:active": {
119
+ opacity: 0.9,
120
+ },
121
+ }),
122
+ ...(variant === "white" && {
123
+ background: "white",
124
+ "&:hover": {
125
+ opacity: 0.8,
126
+ },
127
+ "&:active": {
128
+ opacity: 0.9,
129
+ },
130
+ }),
131
+ ...(variant === "floating" && {
132
+ background: "white",
133
+ color: theme.colors.text,
134
+ boxShadow: "0 1px 2px rgba(0, 0, 0, 0.1)",
135
+ fontSize: "12px",
136
+ padding: "0px 4px",
137
+ }),
138
+ display: "flex",
139
+ alignItems: "center",
140
+ justifyContent: "center",
129
141
 
130
- "& *": {
131
- pointerEvents: "none",
132
- },
133
- }));
142
+ "& *": {
143
+ pointerEvents: "none",
144
+ },
145
+ })
146
+ );
134
147
 
135
148
  /* ----------------------------------------------------------------------------
136
149
  * Content
@@ -168,6 +181,7 @@ export interface ButtonRootProps {
168
181
  onClick?: (event: React.MouseEvent) => void;
169
182
  onPointerDown?: (event: React.PointerEvent) => void;
170
183
  contentStyle?: CSSProperties;
184
+ defaultBackground?: string;
171
185
  as?: React.ElementType;
172
186
  href?: string;
173
187
  target?: string;
@@ -187,6 +201,7 @@ export const Button = forwardRef(function Button(
187
201
  variant = "normal",
188
202
  size = "normal",
189
203
  contentStyle,
204
+ defaultBackground,
190
205
  onClick,
191
206
  children,
192
207
  ...rest // Propagate any other props so this component works as a Slot
@@ -205,6 +220,7 @@ export const Button = forwardRef(function Button(
205
220
  disabled={disabled}
206
221
  variant={variant}
207
222
  size={size}
223
+ defaultBackground={defaultBackground}
208
224
  onClick={onClick}
209
225
  // Prevent double clicking a button from triggering any callbacks in ancestors
210
226
  onDoubleClick={useCallback((event: React.MouseEvent) => {
@@ -1,17 +1,18 @@
1
- import { CheckIcon, ChevronRightIcon } from '@noya-app/noya-icons';
2
- import { useKeyboardShortcuts } from '@noya-app/noya-keymap';
3
- import * as RadixDropdownMenu from '@radix-ui/react-dropdown-menu';
1
+ import { CheckIcon, ChevronRightIcon } from "@noya-app/noya-icons";
2
+ import { useKeyboardShortcuts } from "@noya-app/noya-keymap";
3
+ import * as RadixDropdownMenu from "@radix-ui/react-dropdown-menu";
4
4
  import React, {
5
+ ComponentProps,
5
6
  ForwardedRef,
6
7
  SyntheticEvent,
7
8
  forwardRef,
8
9
  memo,
9
10
  useCallback,
10
11
  useMemo,
11
- } from 'react';
12
- import styled from 'styled-components';
13
- import { MenuItemProps, MenuProps } from './ContextMenu';
14
- import { Spacer } from './Spacer';
12
+ } from "react";
13
+ import styled from "styled-components";
14
+ import { MenuItemProps, MenuProps } from "./ContextMenu";
15
+ import { Spacer } from "./Spacer";
15
16
  import {
16
17
  CHECKBOX_RIGHT_INSET,
17
18
  CHECKBOX_WIDTH,
@@ -19,14 +20,14 @@ import {
19
20
  SEPARATOR_ITEM,
20
21
  getKeyboardShortcutsForMenuItems,
21
22
  styles,
22
- } from './internal/Menu';
23
+ } from "./internal/Menu";
23
24
 
24
25
  /* ----------------------------------------------------------------------------
25
26
  * Separator
26
27
  * ------------------------------------------------------------------------- */
27
28
 
28
29
  const SeparatorElement = styled(RadixDropdownMenu.Separator)(
29
- styles.separatorStyle,
30
+ styles.separatorStyle
30
31
  );
31
32
 
32
33
  /* ----------------------------------------------------------------------------
@@ -36,11 +37,11 @@ const SeparatorElement = styled(RadixDropdownMenu.Separator)(
36
37
  const ItemElement = styled(RadixDropdownMenu.Item)(styles.itemStyle);
37
38
 
38
39
  const CheckboxItemElement = styled(RadixDropdownMenu.CheckboxItem)(
39
- styles.itemStyle,
40
+ styles.itemStyle
40
41
  );
41
42
 
42
43
  const StyledItemIndicator = styled(RadixDropdownMenu.ItemIndicator)(
43
- styles.itemIndicatorStyle,
44
+ styles.itemIndicatorStyle
44
45
  );
45
46
 
46
47
  const DropdownMenuItem = memo(function ContextMenuItem<T extends string>({
@@ -112,7 +113,12 @@ const DropdownMenuItem = memo(function ContextMenuItem<T extends string>({
112
113
 
113
114
  if (items && items.length > 0) {
114
115
  return (
115
- <DropdownMenuRoot isNested items={items} onSelect={onSelect}>
116
+ <DropdownMenuRoot
117
+ isNested
118
+ items={items}
119
+ onSelect={onSelect}
120
+ alignOffset={-5}
121
+ >
116
122
  {element}
117
123
  </DropdownMenuRoot>
118
124
  );
@@ -138,14 +144,22 @@ const DropdownMenuRoot = forwardRef(function DropdownMenuRoot<T extends string>(
138
144
  onOpenChange,
139
145
  open,
140
146
  onCloseAutoFocus,
147
+ side,
148
+ sideOffset = 4,
149
+ align,
150
+ alignOffset,
151
+ collisionPadding = 8,
141
152
  }: MenuProps<T> & {
142
153
  open?: boolean;
143
154
  onCloseAutoFocus?: React.EventHandler<SyntheticEvent<unknown>>;
144
- },
145
- forwardedRef: ForwardedRef<HTMLElement>,
155
+ } & Pick<
156
+ ComponentProps<typeof RadixDropdownMenu.Content>,
157
+ "side" | "sideOffset" | "align" | "alignOffset" | "collisionPadding"
158
+ >,
159
+ forwardedRef: ForwardedRef<HTMLElement>
146
160
  ) {
147
161
  const hasCheckedItem = items.some(
148
- (item) => item !== SEPARATOR_ITEM && item.checked,
162
+ (item) => item !== SEPARATOR_ITEM && item.checked
149
163
  );
150
164
 
151
165
  const keymap = useMemo(
@@ -153,7 +167,7 @@ const DropdownMenuRoot = forwardRef(function DropdownMenuRoot<T extends string>(
153
167
  isNested || shouldBindKeyboardShortcuts === false
154
168
  ? {}
155
169
  : getKeyboardShortcutsForMenuItems(items, onSelect),
156
- [isNested, items, onSelect, shouldBindKeyboardShortcuts],
170
+ [isNested, items, onSelect, shouldBindKeyboardShortcuts]
157
171
  );
158
172
 
159
173
  useKeyboardShortcuts(keymap);
@@ -175,9 +189,12 @@ const DropdownMenuRoot = forwardRef(function DropdownMenuRoot<T extends string>(
175
189
  </TriggerComponent>
176
190
  <RadixDropdownMenu.Portal>
177
191
  <ContentComponent
178
- sideOffset={4}
192
+ side={side}
193
+ sideOffset={sideOffset}
194
+ align={align}
195
+ alignOffset={alignOffset}
179
196
  style={contentStyle}
180
- collisionPadding={8}
197
+ collisionPadding={collisionPadding}
181
198
  {...({ onCloseAutoFocus } as any)}
182
199
  >
183
200
  {items.map((item, index) =>
@@ -197,7 +214,7 @@ const DropdownMenuRoot = forwardRef(function DropdownMenuRoot<T extends string>(
197
214
  >
198
215
  {item.title}
199
216
  </DropdownMenuItem>
200
- ),
217
+ )
201
218
  )}
202
219
  </ContentComponent>
203
220
  </RadixDropdownMenu.Portal>
@@ -83,7 +83,7 @@ export const styles = {
83
83
  separatorStyle: ({ theme }: { theme: Theme }): CSSObject => ({
84
84
  height: "1px",
85
85
  backgroundColor: theme.colors.divider,
86
- margin: "4px 8px",
86
+ margin: "4px -4px",
87
87
  }),
88
88
 
89
89
  itemStyle: ({
@@ -100,7 +100,7 @@ export const styles = {
100
100
  userSelect: "none",
101
101
  cursor: "pointer",
102
102
  borderRadius: "3px",
103
- padding: "4px 8px",
103
+ padding: "6px 8px",
104
104
  ...(disabled && {
105
105
  color: theme.colors.textDisabled,
106
106
  }),