@noya-app/noya-designsystem 0.0.15 → 0.1.0

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,22 +1,23 @@
1
1
  {
2
2
  "name": "@noya-app/noya-designsystem",
3
- "version": "0.0.15",
3
+ "version": "0.1.0",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.ts",
7
7
  "scripts": {
8
8
  "build": "tsup src/index.tsx --format cjs,esm --dts --sourcemap",
9
- "dev": "npm run build -- --watch"
9
+ "dev": "npm run build -- --watch",
10
+ "lint": "eslint . --max-warnings 0"
10
11
  },
11
12
  "dependencies": {
12
13
  "@dnd-kit/core": "3.1.1",
13
14
  "@dnd-kit/modifiers": "3.0.0",
14
15
  "@dnd-kit/sortable": "4.0.0",
15
- "@noya-app/noya-colorpicker": "0.0.9",
16
- "@noya-app/noya-utils": "0.0.12",
17
- "@noya-app/noya-geometry": "0.0.13",
18
- "@noya-app/noya-icons": "0.0.6",
19
- "@noya-app/noya-keymap": "0.0.8",
16
+ "@noya-app/noya-colorpicker": "0.1.0",
17
+ "@noya-app/noya-utils": "0.1.0",
18
+ "@noya-app/noya-geometry": "0.1.0",
19
+ "@noya-app/noya-icons": "0.1.0",
20
+ "@noya-app/noya-keymap": "0.1.0",
20
21
  "@radix-ui/primitive": "^1.0.0",
21
22
  "@radix-ui/react-avatar": "^1.0.1",
22
23
  "@radix-ui/react-compose-refs": "^1.0.0",
@@ -56,6 +56,7 @@ const ChipElement = styled.span<{
56
56
  : {
57
57
  fontSize: "9px",
58
58
  padding: "0px 4px",
59
+ lineHeight: "15px",
59
60
  }),
60
61
  ...(monospace && {
61
62
  fontFamily: theme.fonts.monospace,
@@ -80,6 +81,9 @@ const ChipElement = styled.span<{
80
81
  },
81
82
  ...(isInteractive && {
82
83
  cursor: "pointer",
84
+ "&:hover": {
85
+ opacity: 0.85,
86
+ },
83
87
  }),
84
88
  };
85
89
  });
@@ -116,19 +120,19 @@ const AddElement = styled(PlusIcon).withConfig({
116
120
  isOnlyChild: boolean;
117
121
  }>(({ size, isOnlyChild }) => ({
118
122
  position: "relative",
119
- marginRight: "-2px",
123
+ marginLeft: "-2px",
120
124
  cursor: "pointer",
121
125
  opacity: 0.5,
122
126
 
123
127
  ...(size === "medium"
124
128
  ? {
125
- marginLeft: "2px",
129
+ marginRight: "2px",
126
130
  top: "-1px",
127
131
  transform: "scale(0.75)",
128
132
  }
129
133
  : {
134
+ marginRight: "-2px",
130
135
  transform: "scale(0.6)",
131
- ...(isOnlyChild && { marginLeft: "-2px" }),
132
136
  }),
133
137
 
134
138
  "&:hover": {
@@ -193,20 +197,34 @@ export const Chip = memo(function Chip({
193
197
  isInteractive={!!handleClick}
194
198
  tabIndex={tabIndex}
195
199
  >
196
- {children}
197
- {deletable && (
198
- <DeleteElement
200
+ {addable && (
201
+ <AddElement
199
202
  size={size}
200
- {...(hoverDeleteProps as any)}
201
- onClick={onDelete}
203
+ isOnlyChild={!children && !deletable}
204
+ onClick={
205
+ onAdd
206
+ ? (event) => {
207
+ event.stopPropagation();
208
+ onAdd?.();
209
+ }
210
+ : undefined
211
+ }
202
212
  color={color}
203
213
  />
204
214
  )}
205
- {addable && (
206
- <AddElement
215
+ {children}
216
+ {deletable && (
217
+ <DeleteElement
207
218
  size={size}
208
- isOnlyChild={!children && !deletable}
209
- onClick={onAdd}
219
+ {...(hoverDeleteProps as any)}
220
+ onClick={
221
+ onDelete
222
+ ? (event) => {
223
+ event.stopPropagation();
224
+ onDelete?.();
225
+ }
226
+ : undefined
227
+ }
210
228
  color={color}
211
229
  />
212
230
  )}
@@ -0,0 +1,116 @@
1
+ import { DragHandleDots2Icon } from "@noya-app/noya-icons";
2
+ import React, { memo, useCallback, useState } from "react";
3
+ import styled from "styled-components";
4
+ import { useDesignSystemTheme } from "../contexts/DesignSystemConfiguration";
5
+ import { DropdownMenu } from "./DropdownMenu";
6
+ import { MenuItem } from "./internal/Menu";
7
+
8
+ const DotButtonElement = styled.div(({ theme }) => ({
9
+ cursor: "pointer",
10
+ borderRadius: "4px",
11
+ display: "flex",
12
+ alignItems: "center",
13
+ justifyContent: "center",
14
+ padding: "2px 0",
15
+ "&:hover": {
16
+ background: theme.colors.inputBackgroundLight,
17
+ },
18
+ "&:active": {
19
+ background: theme.colors.activeBackground,
20
+ },
21
+ }));
22
+
23
+ const TriggerElement = styled.div({
24
+ pointerEvents: "none",
25
+ height: "15px",
26
+ });
27
+
28
+ /**
29
+ * A button that opens a menu when clicked, but also allows dragging the
30
+ */
31
+ export const DraggableMenuButton = memo(function DraggableMenuButton<
32
+ T extends string,
33
+ >({
34
+ items,
35
+ onSelect,
36
+ isVisible = true,
37
+ }: {
38
+ items: MenuItem<T>[];
39
+ onSelect: (value: T) => void;
40
+ isVisible?: boolean;
41
+ }) {
42
+ const color = useDesignSystemTheme().colors.icon;
43
+ const [open, setOpen] = useState(false);
44
+ const [downPosition, setDownPosition] = React.useState<{
45
+ x: number;
46
+ y: number;
47
+ } | null>(null);
48
+
49
+ const handlePointerDownCapture = useCallback(
50
+ (event: React.PointerEvent) => {
51
+ if (open) {
52
+ setDownPosition(null);
53
+ return;
54
+ }
55
+
56
+ setDownPosition({
57
+ x: event.clientX,
58
+ y: event.clientY,
59
+ });
60
+ },
61
+ [open]
62
+ );
63
+
64
+ const handlePointerUp = useCallback(
65
+ (event: React.PointerEvent) => {
66
+ if (open || !downPosition) {
67
+ setDownPosition(null);
68
+ return;
69
+ }
70
+
71
+ const dx = event.clientX - downPosition.x;
72
+ const dy = event.clientY - downPosition.y;
73
+
74
+ const distance = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
75
+
76
+ if (distance < 5) {
77
+ setOpen(true);
78
+ }
79
+
80
+ setDownPosition(null);
81
+ },
82
+ [downPosition, open]
83
+ );
84
+
85
+ const handleOpenChange = useCallback(
86
+ (isOpen: boolean) => {
87
+ if (!isOpen) setOpen(false);
88
+ },
89
+ [setOpen]
90
+ );
91
+
92
+ return (
93
+ <DotButtonElement
94
+ onPointerDownCapture={handlePointerDownCapture}
95
+ onPointerUp={handlePointerUp}
96
+ onClick={(event) => {
97
+ event.stopPropagation();
98
+ event.preventDefault();
99
+ }}
100
+ >
101
+ <DropdownMenu
102
+ open={open}
103
+ onOpenChange={handleOpenChange}
104
+ items={items}
105
+ onSelect={onSelect}
106
+ shouldBindKeyboardShortcuts={false}
107
+ >
108
+ <TriggerElement>
109
+ <DragHandleDots2Icon
110
+ color={isVisible || open ? color : "transparent"}
111
+ />
112
+ </TriggerElement>
113
+ </DropdownMenu>
114
+ </DotButtonElement>
115
+ );
116
+ });