浏览代码

Adds style panel, styles

main
Steve Ruiz 4 年前
父节点
当前提交
6c8499309e

+ 0
- 1
components/canvas/misc.tsx 查看文件

3
 const DotCircle = styled("circle", {
3
 const DotCircle = styled("circle", {
4
   transform: "scale(var(--scale))",
4
   transform: "scale(var(--scale))",
5
   strokeWidth: "2",
5
   strokeWidth: "2",
6
-  fill: "#000",
7
 })
6
 })
8
 
7
 
9
 export { DotCircle }
8
 export { DotCircle }

+ 18
- 4
components/editor.tsx 查看文件

6
 import CodePanel from "./code-panel/code-panel"
6
 import CodePanel from "./code-panel/code-panel"
7
 import ControlsPanel from "./controls-panel/controls-panel"
7
 import ControlsPanel from "./controls-panel/controls-panel"
8
 import styled from "styles"
8
 import styled from "styles"
9
+import StylePanel from "./style-panel/style-panel"
9
 
10
 
10
 export default function Editor() {
11
 export default function Editor() {
11
   useKeyboardEvents()
12
   useKeyboardEvents()
20
         <CodePanel />
21
         <CodePanel />
21
         <ControlsPanel />
22
         <ControlsPanel />
22
       </LeftPanels>
23
       </LeftPanels>
24
+      <RightPanels>
25
+        <StylePanel />
26
+      </RightPanels>
23
     </Layout>
27
     </Layout>
24
   )
28
   )
25
 }
29
 }
32
   right: 0,
36
   right: 0,
33
   display: "grid",
37
   display: "grid",
34
   gridTemplateRows: "40px 1fr 40px",
38
   gridTemplateRows: "40px 1fr 40px",
35
-  gridTemplateColumns: "auto 1fr",
39
+  gridTemplateColumns: "minmax(50%, 400px) 1fr auto",
36
   gridTemplateAreas: `
40
   gridTemplateAreas: `
37
-    "toolbar toolbar"
38
-    "leftPanels main"
39
-    "statusbar statusbar"
41
+    "toolbar toolbar toolbar"
42
+    "leftPanels main rightPanels"
43
+    "statusbar statusbar statusbar"
40
   `,
44
   `,
41
 })
45
 })
42
 
46
 
47
   padding: 8,
51
   padding: 8,
48
   gap: 8,
52
   gap: 8,
49
 })
53
 })
54
+
55
+const RightPanels = styled("main", {
56
+  display: "grid",
57
+  gridArea: "rightPanels",
58
+  gridTemplateRows: "auto",
59
+  height: "fit-content",
60
+  justifyContent: "flex-end",
61
+  padding: 8,
62
+  gap: 8,
63
+})

+ 5
- 2
components/panel.tsx 查看文件

13
 
13
 
14
   variants: {
14
   variants: {
15
     isOpen: {
15
     isOpen: {
16
-      true: {},
16
+      true: {
17
+        width: "auto",
18
+        minWidth: 300,
19
+      },
17
       false: {
20
       false: {
18
         height: 34,
21
         height: 34,
19
         width: 34,
22
         width: 34,
28
   gridTemplateRows: "auto 1fr",
31
   gridTemplateRows: "auto 1fr",
29
   gridAutoRows: "28px",
32
   gridAutoRows: "28px",
30
   height: "100%",
33
   height: "100%",
31
-  width: 560,
34
+  width: "100%",
32
   minWidth: "100%",
35
   minWidth: "100%",
33
   maxWidth: 560,
36
   maxWidth: 560,
34
   overflow: "hidden",
37
   overflow: "hidden",

+ 1
- 1
components/shared.tsx 查看文件

16
   cursor: "pointer",
16
   cursor: "pointer",
17
 
17
 
18
   "&:hover:not(:disabled)": {
18
   "&:hover:not(:disabled)": {
19
-    backgroundColor: "$panel",
19
+    backgroundColor: "$hover",
20
   },
20
   },
21
 
21
 
22
   "&:disabled": {
22
   "&:disabled": {

+ 127
- 0
components/style-panel/color-picker.tsx 查看文件

1
+import * as DropdownMenu from "@radix-ui/react-dropdown-menu"
2
+import { Square } from "react-feather"
3
+import { colors } from "state/data"
4
+import styled from "styles"
5
+
6
+interface Props {
7
+  label: string
8
+  color: string
9
+  onChange: (color: string) => void
10
+}
11
+
12
+export default function ColorPicker({ label, color, onChange }: Props) {
13
+  return (
14
+    <DropdownMenu.Root>
15
+      <CurrentColor>
16
+        <h3>{label}</h3>
17
+        <ColorIcon color={color} />
18
+      </CurrentColor>
19
+      <Colors sideOffset={4}>
20
+        {Object.entries(colors).map(([name, color]) => (
21
+          <ColorButton key={name} title={name} onSelect={() => onChange(color)}>
22
+            <ColorIcon color={color} />
23
+          </ColorButton>
24
+        ))}
25
+      </Colors>
26
+    </DropdownMenu.Root>
27
+  )
28
+}
29
+
30
+function ColorIcon({ color }: { color: string }) {
31
+  return (
32
+    <Square
33
+      fill={color}
34
+      strokeDasharray={color === "transparent" ? "2, 3" : "none"}
35
+    />
36
+  )
37
+}
38
+
39
+const Colors = styled(DropdownMenu.Content, {
40
+  display: "grid",
41
+  padding: 4,
42
+  gridTemplateColumns: "repeat(6, 1fr)",
43
+  border: "1px solid $border",
44
+  backgroundColor: "$panel",
45
+  borderRadius: 4,
46
+  boxShadow: "0px 5px 15px -5px hsla(206,22%,7%,.15)",
47
+})
48
+
49
+const ColorButton = styled(DropdownMenu.Item, {
50
+  position: "relative",
51
+  cursor: "pointer",
52
+  height: 32,
53
+  width: 32,
54
+  border: "none",
55
+  padding: "none",
56
+  background: "none",
57
+  display: "flex",
58
+  alignItems: "center",
59
+  justifyContent: "center",
60
+
61
+  "&::before": {
62
+    content: "''",
63
+    position: "absolute",
64
+    top: 4,
65
+    left: 4,
66
+    right: 4,
67
+    bottom: 4,
68
+    pointerEvents: "none",
69
+    zIndex: 0,
70
+  },
71
+
72
+  "&:hover::before": {
73
+    backgroundColor: "$hover",
74
+    borderRadius: 4,
75
+  },
76
+
77
+  "& svg": {
78
+    position: "relative",
79
+    stroke: "rgba(0,0,0,.2)",
80
+    strokeWidth: 1,
81
+    zIndex: 1,
82
+  },
83
+})
84
+
85
+const CurrentColor = styled(DropdownMenu.Trigger, {
86
+  position: "relative",
87
+  display: "flex",
88
+  width: "100%",
89
+  background: "none",
90
+  border: "none",
91
+  cursor: "pointer",
92
+  outline: "none",
93
+  alignItems: "center",
94
+  justifyContent: "space-between",
95
+  padding: "8px 8px 8px 12px",
96
+
97
+  "&::before": {
98
+    content: "''",
99
+    position: "absolute",
100
+    top: 4,
101
+    left: 4,
102
+    right: 4,
103
+    bottom: 4,
104
+    pointerEvents: "none",
105
+    zIndex: -1,
106
+  },
107
+
108
+  "&:hover::before": {
109
+    backgroundColor: "$hover",
110
+    borderRadius: 4,
111
+  },
112
+
113
+  "& h3": {
114
+    fontFamily: "$ui",
115
+    fontSize: "$2",
116
+    fontWeight: "$1",
117
+    margin: 0,
118
+    padding: 0,
119
+  },
120
+
121
+  "& svg": {
122
+    position: "relative",
123
+    stroke: "rgba(0,0,0,.2)",
124
+    strokeWidth: 1,
125
+    zIndex: 1,
126
+  },
127
+})

+ 119
- 0
components/style-panel/style-panel.tsx 查看文件

1
+import styled from "styles"
2
+import state, { useSelector } from "state"
3
+import * as Panel from "components/panel"
4
+import { useRef } from "react"
5
+import { IconButton } from "components/shared"
6
+import { Circle, Square, Trash, X } from "react-feather"
7
+import { deepCompare, deepCompareArrays, getSelectedShapes } from "utils/utils"
8
+import { colors } from "state/data"
9
+
10
+import ColorPicker from "./color-picker"
11
+import { ShapeByType, ShapeStyles } from "types"
12
+
13
+export default function StylePanel() {
14
+  const rContainer = useRef<HTMLDivElement>(null)
15
+  const isOpen = useSelector((s) => s.data.settings.isStyleOpen)
16
+
17
+  return (
18
+    <StylePanelRoot ref={rContainer} isOpen={isOpen}>
19
+      {isOpen ? (
20
+        <SelectedShapeStyles />
21
+      ) : (
22
+        <IconButton onClick={() => state.send("TOGGLED_STYLE_PANEL_OPEN")}>
23
+          <Circle />
24
+        </IconButton>
25
+      )}
26
+    </StylePanelRoot>
27
+  )
28
+}
29
+
30
+// This panel is going to be hard to keep cool, as we're selecting computed
31
+// information, based on the user's current selection. We might have to keep
32
+// track of this data manually within our state.
33
+
34
+function SelectedShapeStyles({}: {}) {
35
+  const selectedIds = useSelector(
36
+    (s) => Array.from(s.data.selectedIds.values()),
37
+    deepCompareArrays
38
+  )
39
+
40
+  const shapesStyle = useSelector((s) => {
41
+    const { currentStyle } = s.data
42
+    const shapes = getSelectedShapes(s.data)
43
+
44
+    if (shapes.length === 0) {
45
+      return currentStyle
46
+    }
47
+
48
+    const style: Partial<ShapeStyles> = {}
49
+    const overrides = new Set<string>([])
50
+
51
+    for (const shape of shapes) {
52
+      for (let key in currentStyle) {
53
+        if (overrides.has(key)) continue
54
+        if (style[key] === undefined) {
55
+          style[key] = shape.style[key]
56
+        } else {
57
+          if (style[key] === shape.style[key]) continue
58
+          style[key] = currentStyle[key]
59
+          overrides.add(key)
60
+        }
61
+      }
62
+    }
63
+
64
+    return style
65
+  }, deepCompare)
66
+
67
+  return (
68
+    <Panel.Layout>
69
+      <Panel.Header>
70
+        <IconButton onClick={() => state.send("TOGGLED_STYLE_PANEL_OPEN")}>
71
+          <X />
72
+        </IconButton>
73
+        <h3>Style</h3>
74
+        <Panel.ButtonsGroup>
75
+          <IconButton onClick={() => state.send("DELETED")}>
76
+            <Trash />
77
+          </IconButton>
78
+        </Panel.ButtonsGroup>
79
+      </Panel.Header>
80
+      <Panel.Content>
81
+        <ColorsRow>
82
+          <ColorPicker
83
+            label="Fill"
84
+            color={shapesStyle.fill}
85
+            onChange={(color) => state.send("CHANGED_STYLE", { fill: color })}
86
+          />
87
+          <ColorPicker
88
+            label="Stroke"
89
+            color={shapesStyle.stroke}
90
+            onChange={(color) => state.send("CHANGED_STYLE", { stroke: color })}
91
+          />
92
+        </ColorsRow>
93
+      </Panel.Content>
94
+    </Panel.Layout>
95
+  )
96
+}
97
+
98
+const StylePanelRoot = styled(Panel.Root, {
99
+  maxWidth: 260,
100
+  position: "relative",
101
+
102
+  variants: {
103
+    isOpen: {
104
+      true: {
105
+        width: "auto",
106
+        minWidth: 300,
107
+      },
108
+      false: {
109
+        height: 34,
110
+        width: 34,
111
+      },
112
+    },
113
+  },
114
+})
115
+
116
+const ColorsRow = styled("div", {
117
+  display: "grid",
118
+  gridTemplateColumns: "1fr 1fr",
119
+})

+ 3
- 3
lib/code/index.ts 查看文件

29
   }
29
   }
30
 
30
 
31
   moveTo(point: Vector) {
31
   moveTo(point: Vector) {
32
-    this.utils.translate(this._shape, vectorToPoint(point))
32
+    this.utils.translateTo(this._shape, vectorToPoint(point))
33
     return this
33
     return this
34
   }
34
   }
35
 
35
 
36
   translate(delta: Vector) {
36
   translate(delta: Vector) {
37
-    this.utils.translate(
37
+    this.utils.translateTo(
38
       this._shape,
38
       this._shape,
39
       vec.add(this._shape.point, vectorToPoint(delta))
39
       vec.add(this._shape.point, vectorToPoint(delta))
40
     )
40
     )
42
   }
42
   }
43
 
43
 
44
   rotate(rotation: number) {
44
   rotate(rotation: number) {
45
-    this.utils.rotate(this._shape, rotation)
45
+    this.utils.rotateTo(this._shape, rotation)
46
     return this
46
     return this
47
   }
47
   }
48
 
48
 

+ 1
- 0
lib/code/rectangle.ts 查看文件

18
       point: [0, 0],
18
       point: [0, 0],
19
       size: [100, 100],
19
       size: [100, 100],
20
       rotation: 0,
20
       rotation: 0,
21
+      radius: 2,
21
       style: {
22
       style: {
22
         fill: "#c6cacb",
23
         fill: "#c6cacb",
23
         stroke: "#000",
24
         stroke: "#000",

+ 6
- 1
lib/shape-utils/circle.tsx 查看文件

20
       childIndex: 0,
20
       childIndex: 0,
21
       point: [0, 0],
21
       point: [0, 0],
22
       rotation: 0,
22
       rotation: 0,
23
-      radius: 20,
23
+      radius: 1,
24
       style: {
24
       style: {
25
         fill: "#c6cacb",
25
         fill: "#c6cacb",
26
         stroke: "#000",
26
         stroke: "#000",
33
     return <circle id={id} cx={radius} cy={radius} r={radius} />
33
     return <circle id={id} cx={radius} cy={radius} r={radius} />
34
   },
34
   },
35
 
35
 
36
+  applyStyles(shape, style) {
37
+    Object.assign(shape.style, style)
38
+    return this
39
+  },
40
+
36
   getBounds(shape) {
41
   getBounds(shape) {
37
     if (!this.boundsCache.has(shape)) {
42
     if (!this.boundsCache.has(shape)) {
38
       const { radius } = shape
43
       const { radius } = shape

+ 5
- 0
lib/shape-utils/dot.tsx 查看文件

32
     return <DotCircle id={id} cx={0} cy={0} r={4} />
32
     return <DotCircle id={id} cx={0} cy={0} r={4} />
33
   },
33
   },
34
 
34
 
35
+  applyStyles(shape, style) {
36
+    Object.assign(shape.style, style)
37
+    return this
38
+  },
39
+
35
   getBounds(shape) {
40
   getBounds(shape) {
36
     if (!this.boundsCache.has(shape)) {
41
     if (!this.boundsCache.has(shape)) {
37
       const bounds = {
42
       const bounds = {

+ 7
- 2
lib/shape-utils/ellipse.tsx 查看文件

24
       parentId: "page0",
24
       parentId: "page0",
25
       childIndex: 0,
25
       childIndex: 0,
26
       point: [0, 0],
26
       point: [0, 0],
27
-      radiusX: 20,
28
-      radiusY: 20,
27
+      radiusX: 1,
28
+      radiusY: 1,
29
       rotation: 0,
29
       rotation: 0,
30
       style: {
30
       style: {
31
         fill: "#c6cacb",
31
         fill: "#c6cacb",
41
     )
41
     )
42
   },
42
   },
43
 
43
 
44
+  applyStyles(shape, style) {
45
+    Object.assign(shape.style, style)
46
+    return this
47
+  },
48
+
44
   getBounds(shape) {
49
   getBounds(shape) {
45
     if (!this.boundsCache.has(shape)) {
50
     if (!this.boundsCache.has(shape)) {
46
       const { radiusX, radiusY } = shape
51
       const { radiusX, radiusY } = shape

+ 7
- 0
lib/shape-utils/index.tsx 查看文件

7
   Corner,
7
   Corner,
8
   Edge,
8
   Edge,
9
   ShapeByType,
9
   ShapeByType,
10
+  ShapeStyles,
10
 } from "types"
11
 } from "types"
11
 import circle from "./circle"
12
 import circle from "./circle"
12
 import dot from "./dot"
13
 import dot from "./dot"
40
   // Create a new shape.
41
   // Create a new shape.
41
   create(props: Partial<K>): K
42
   create(props: Partial<K>): K
42
 
43
 
44
+  applyStyles(
45
+    this: ShapeUtility<K>,
46
+    shape: K,
47
+    style: ShapeStyles
48
+  ): ShapeUtility<K>
49
+
43
   // Set the shape's point.
50
   // Set the shape's point.
44
   translateTo(this: ShapeUtility<K>, shape: K, delta: number[]): ShapeUtility<K>
51
   translateTo(this: ShapeUtility<K>, shape: K, delta: number[]): ShapeUtility<K>
45
 
52
 

+ 5
- 0
lib/shape-utils/line.tsx 查看文件

41
     )
41
     )
42
   },
42
   },
43
 
43
 
44
+  applyStyles(shape, style) {
45
+    Object.assign(shape.style, style)
46
+    return this
47
+  },
48
+
44
   getBounds(shape) {
49
   getBounds(shape) {
45
     if (!this.boundsCache.has(shape)) {
50
     if (!this.boundsCache.has(shape)) {
46
       const bounds = {
51
       const bounds = {

+ 5
- 0
lib/shape-utils/polyline.tsx 查看文件

33
     return <polyline id={id} points={points.toString()} />
33
     return <polyline id={id} points={points.toString()} />
34
   },
34
   },
35
 
35
 
36
+  applyStyles(shape, style) {
37
+    Object.assign(shape.style, style)
38
+    return this
39
+  },
40
+
36
   getBounds(shape) {
41
   getBounds(shape) {
37
     if (!this.boundsCache.has(shape)) {
42
     if (!this.boundsCache.has(shape)) {
38
       const bounds = getBoundsFromPoints(shape.points)
43
       const bounds = getBoundsFromPoints(shape.points)

+ 5
- 0
lib/shape-utils/ray.tsx 查看文件

41
     )
41
     )
42
   },
42
   },
43
 
43
 
44
+  applyStyles(shape, style) {
45
+    Object.assign(shape.style, style)
46
+    return this
47
+  },
48
+
44
   getRotatedBounds(shape) {
49
   getRotatedBounds(shape) {
45
     return this.getBounds(shape)
50
     return this.getBounds(shape)
46
   },
51
   },

+ 14
- 2
lib/shape-utils/rectangle.tsx 查看文件

22
       childIndex: 0,
22
       childIndex: 0,
23
       point: [0, 0],
23
       point: [0, 0],
24
       size: [1, 1],
24
       size: [1, 1],
25
+      radius: 2,
25
       rotation: 0,
26
       rotation: 0,
26
       style: {
27
       style: {
27
         fill: "#c6cacb",
28
         fill: "#c6cacb",
31
     }
32
     }
32
   },
33
   },
33
 
34
 
34
-  render({ id, size, parentId, childIndex }) {
35
+  render({ id, size, radius, childIndex }) {
35
     return (
36
     return (
36
       <g id={id}>
37
       <g id={id}>
37
-        <rect id={id} width={size[0]} height={size[1]} />
38
+        <rect
39
+          id={id}
40
+          width={size[0]}
41
+          height={size[1]}
42
+          rx={radius}
43
+          ry={radius}
44
+        />
38
         <text
45
         <text
39
           y={4}
46
           y={4}
40
           x={4}
47
           x={4}
50
     )
57
     )
51
   },
58
   },
52
 
59
 
60
+  applyStyles(shape, style) {
61
+    Object.assign(shape.style, style)
62
+    return this
63
+  },
64
+
53
   getBounds(shape) {
65
   getBounds(shape) {
54
     if (!this.boundsCache.has(shape)) {
66
     if (!this.boundsCache.has(shape)) {
55
       const [width, height] = shape.size
67
       const [width, height] = shape.size

lib/shape-utils/ShapeTest.tsx → lib/shape-utils/utils-next.tsx 查看文件


+ 3
- 2
package.json 查看文件

9
   },
9
   },
10
   "dependencies": {
10
   "dependencies": {
11
     "@monaco-editor/react": "^4.1.3",
11
     "@monaco-editor/react": "^4.1.3",
12
+    "@radix-ui/react-dropdown-menu": "^0.0.19",
12
     "@state-designer/react": "^1.7.1",
13
     "@state-designer/react": "^1.7.1",
13
     "@stitches/react": "^0.1.9",
14
     "@stitches/react": "^0.1.9",
14
     "framer-motion": "^4.1.16",
15
     "framer-motion": "^4.1.16",
16
     "next": "10.2.0",
17
     "next": "10.2.0",
17
     "perfect-freehand": "^0.4.7",
18
     "perfect-freehand": "^0.4.7",
18
     "prettier": "^2.3.0",
19
     "prettier": "^2.3.0",
20
+    "react": "17.0.2",
19
     "react-dom": "17.0.2",
21
     "react-dom": "17.0.2",
20
     "react-feather": "^2.0.9",
22
     "react-feather": "^2.0.9",
21
-    "react": "17.0.2",
22
     "uuid": "^8.3.2"
23
     "uuid": "^8.3.2"
23
   },
24
   },
24
   "devDependencies": {
25
   "devDependencies": {
25
     "@types/next": "^9.0.0",
26
     "@types/next": "^9.0.0",
26
-    "@types/react-dom": "^17.0.3",
27
     "@types/react": "^17.0.5",
27
     "@types/react": "^17.0.5",
28
+    "@types/react-dom": "^17.0.3",
28
     "@types/uuid": "^8.3.0",
29
     "@types/uuid": "^8.3.0",
29
     "cypress": "^7.3.0",
30
     "cypress": "^7.3.0",
30
     "monaco-editor": "^0.24.0",
31
     "monaco-editor": "^0.24.0",

+ 2
- 0
state/commands/index.ts 查看文件

5
 import direct from "./direct"
5
 import direct from "./direct"
6
 import rotate from "./rotate"
6
 import rotate from "./rotate"
7
 import move from "./move"
7
 import move from "./move"
8
+import style from "./style"
8
 import deleteSelected from "./delete-selected"
9
 import deleteSelected from "./delete-selected"
9
 
10
 
10
 const commands = {
11
 const commands = {
15
   direct,
16
   direct,
16
   rotate,
17
   rotate,
17
   move,
18
   move,
19
+  style,
18
   deleteSelected,
20
   deleteSelected,
19
 }
21
 }
20
 
22
 

+ 36
- 0
state/commands/style.ts 查看文件

1
+import Command from "./command"
2
+import history from "../history"
3
+import { Data, ShapeStyles } from "types"
4
+import { getPage, getSelectedShapes } from "utils/utils"
5
+import { getShapeUtils } from "lib/shape-utils"
6
+import { current } from "immer"
7
+
8
+export default function styleCommand(data: Data, styles: ShapeStyles) {
9
+  const { currentPageId } = data
10
+  const initialShapes = getSelectedShapes(current(data))
11
+
12
+  history.execute(
13
+    data,
14
+    new Command({
15
+      name: "changed_style",
16
+      category: "canvas",
17
+      manualSelection: true,
18
+      do(data) {
19
+        const { shapes } = getPage(data, currentPageId)
20
+
21
+        for (const { id } of initialShapes) {
22
+          const shape = shapes[id]
23
+          getShapeUtils(shape).applyStyles(shape, styles)
24
+        }
25
+      },
26
+      undo(data) {
27
+        const { shapes } = getPage(data, currentPageId)
28
+
29
+        for (const { id, style } of initialShapes) {
30
+          const shape = shapes[id]
31
+          getShapeUtils(shape).applyStyles(shape, style)
32
+        }
33
+      },
34
+    })
35
+  )
36
+}

+ 33
- 27
state/data.ts 查看文件

15
           childIndex: 3,
15
           childIndex: 3,
16
           point: [300, 300],
16
           point: [300, 300],
17
           direction: [0.5, 0.5],
17
           direction: [0.5, 0.5],
18
-          style: {
19
-            fill: "#AAA",
20
-            stroke: "#c6cacb",
21
-            strokeWidth: 1,
22
-          },
23
         }),
18
         }),
24
         // shape3: shapeUtils[ShapeType.Dot].create({
19
         // shape3: shapeUtils[ShapeType.Dot].create({
25
         //   id: "shape3",
20
         //   id: "shape3",
38
           childIndex: 1,
33
           childIndex: 1,
39
           point: [100, 600],
34
           point: [100, 600],
40
           radius: 50,
35
           radius: 50,
41
-          style: {
42
-            fill: "#AAA",
43
-            stroke: "#c6cacb",
44
-            strokeWidth: 1,
45
-          },
46
         }),
36
         }),
47
         shape5: shapeUtils[ShapeType.Ellipse].create({
37
         shape5: shapeUtils[ShapeType.Ellipse].create({
48
           id: "shape5",
38
           id: "shape5",
51
           point: [400, 600],
41
           point: [400, 600],
52
           radiusX: 50,
42
           radiusX: 50,
53
           radiusY: 30,
43
           radiusY: 30,
54
-          style: {
55
-            fill: "#AAA",
56
-            stroke: "#c6cacb",
57
-            strokeWidth: 1,
58
-          },
59
         }),
44
         }),
60
         // shape7: shapeUtils[ShapeType.Ellipse].create({
45
         // shape7: shapeUtils[ShapeType.Ellipse].create({
61
         //   id: "shape7",
46
         //   id: "shape7",
88
         //     strokeLinejoin: "round",
73
         //     strokeLinejoin: "round",
89
         //   },
74
         //   },
90
         // }),
75
         // }),
91
-        shape1: shapeUtils[ShapeType.Rectangle].create({
92
-          id: "shape1",
93
-          name: "Shape 1",
94
-          childIndex: 1,
95
-          point: [400, 600],
96
-          size: [200, 200],
97
-          style: {
98
-            fill: "#AAA",
99
-            stroke: "#c6cacb",
100
-            strokeWidth: 1,
101
-          },
102
-        }),
76
+        // shape1: shapeUtils[ShapeType.Rectangle].create({
77
+        //   id: "shape1",
78
+        //   name: "Shape 1",
79
+        //   childIndex: 1,
80
+        //   point: [400, 600],
81
+        //   size: [200, 200],
82
+        //   style: {
83
+        //     fill: "#AAA",
84
+        //     stroke: "#c6cacb",
85
+        //     strokeWidth: 1,
86
+        //   },
87
+        // }),
103
         // shape6: shapeUtils[ShapeType.Line].create({
88
         // shape6: shapeUtils[ShapeType.Line].create({
104
         //   id: "shape6",
89
         //   id: "shape6",
105
         //   name: "Shape 6",
90
         //   name: "Shape 6",
152
     },
137
     },
153
   },
138
   },
154
 }
139
 }
140
+
141
+export const colors = {
142
+  transparent: "transparent",
143
+  white: "rgba(248, 249, 250, 1.000)",
144
+  lightGray: "rgba(224, 226, 230, 1.000)",
145
+  gray: "rgba(172, 181, 189, 1.000)",
146
+  darkGray: "rgba(52, 58, 64, 1.000)",
147
+  black: "rgba(0,0,0, 1.000)",
148
+  lime: "rgba(115, 184, 23, 1.000)",
149
+  green: "rgba(54, 178, 77, 1.000)",
150
+  teal: "rgba(9, 167, 120, 1.000)",
151
+  cyan: "rgba(14, 152, 173, 1.000)",
152
+  blue: "rgba(28, 126, 214, 1.000)",
153
+  indigo: "rgba(66, 99, 235, 1.000)",
154
+  violet: "rgba(112, 72, 232, 1.000)",
155
+  grape: "rgba(174, 62, 200, 1.000)",
156
+  pink: "rgba(214, 51, 108, 1.000)",
157
+  red: "rgba(240, 63, 63, 1.000)",
158
+  orange: "rgba(247, 103, 6, 1.000)",
159
+  yellow: "rgba(245, 159, 0, 1.000)",
160
+}

+ 72
- 80
state/state.ts 查看文件

1
 import { createSelectorHook, createState } from "@state-designer/react"
1
 import { createSelectorHook, createState } from "@state-designer/react"
2
+import * as vec from "utils/vec"
3
+import inputs from "./inputs"
4
+import { colors, defaultDocument } from "./data"
5
+import { createShape, getShapeUtils } from "lib/shape-utils"
6
+import history from "state/history"
7
+import * as Sessions from "./sessions"
8
+import commands from "./commands"
9
+import { updateFromCode } from "lib/code/generate"
2
 import {
10
 import {
3
   clamp,
11
   clamp,
4
-  getBoundsCenter,
5
   getChildren,
12
   getChildren,
6
   getCommonBounds,
13
   getCommonBounds,
14
+  getCurrent,
7
   getPage,
15
   getPage,
8
   getSelectedBounds,
16
   getSelectedBounds,
9
-  getSelectedShapes,
10
   getShape,
17
   getShape,
11
-  getSiblings,
12
   screenToWorld,
18
   screenToWorld,
13
   setZoomCSS,
19
   setZoomCSS,
14
 } from "utils/utils"
20
 } from "utils/utils"
15
-import * as vec from "utils/vec"
16
 import {
21
 import {
17
   Data,
22
   Data,
18
   PointerInfo,
23
   PointerInfo,
22
   Edge,
27
   Edge,
23
   CodeControl,
28
   CodeControl,
24
   MoveType,
29
   MoveType,
30
+  ShapeStyles,
25
 } from "types"
31
 } from "types"
26
-import inputs from "./inputs"
27
-import { defaultDocument } from "./data"
28
-import shapeUtilityMap, { getShapeUtils } from "lib/shape-utils"
29
-import history from "state/history"
30
-import * as Sessions from "./sessions"
31
-import commands from "./commands"
32
-import { updateFromCode } from "lib/code/generate"
33
 
32
 
34
 const initialData: Data = {
33
 const initialData: Data = {
35
   isReadOnly: false,
34
   isReadOnly: false,
37
     fontSize: 13,
36
     fontSize: 13,
38
     isDarkMode: false,
37
     isDarkMode: false,
39
     isCodeOpen: false,
38
     isCodeOpen: false,
39
+    isStyleOpen: false,
40
+  },
41
+  currentStyle: {
42
+    fill: colors.lightGray,
43
+    stroke: colors.darkGray,
40
   },
44
   },
41
   camera: {
45
   camera: {
42
     point: [0, 0],
46
     point: [0, 0],
71
     SELECTED_POLYLINE_TOOL: { unless: "isReadOnly", to: "polyline" },
75
     SELECTED_POLYLINE_TOOL: { unless: "isReadOnly", to: "polyline" },
72
     SELECTED_RECTANGLE_TOOL: { unless: "isReadOnly", to: "rectangle" },
76
     SELECTED_RECTANGLE_TOOL: { unless: "isReadOnly", to: "rectangle" },
73
     TOGGLED_CODE_PANEL_OPEN: "toggleCodePanel",
77
     TOGGLED_CODE_PANEL_OPEN: "toggleCodePanel",
78
+    TOGGLED_STYLE_PANEL_OPEN: "toggleStylePanel",
79
+    CHANGED_STYLE: ["updateStyles", "applyStylesToSelection"],
74
     RESET_CAMERA: "resetCamera",
80
     RESET_CAMERA: "resetCamera",
75
     ZOOMED_TO_FIT: "zoomCameraToFit",
81
     ZOOMED_TO_FIT: "zoomCameraToFit",
76
     ZOOMED_TO_SELECTION: {
82
     ZOOMED_TO_SELECTION: {
442
     },
448
     },
443
   },
449
   },
444
   results: {
450
   results: {
445
-    // Dot
446
-    newDot(data, payload: PointerInfo) {
447
-      return shapeUtilityMap[ShapeType.Dot].create({
448
-        point: screenToWorld(payload.point, data),
449
-      })
451
+    newDot() {
452
+      return ShapeType.Dot
450
     },
453
     },
451
-
452
-    // Ray
453
-    newRay(data, payload: PointerInfo) {
454
-      return shapeUtilityMap[ShapeType.Ray].create({
455
-        point: screenToWorld(payload.point, data),
456
-      })
454
+    newRay() {
455
+      return ShapeType.Ray
457
     },
456
     },
458
-
459
-    // Line
460
-    newLine(data, payload: PointerInfo) {
461
-      return shapeUtilityMap[ShapeType.Line].create({
462
-        point: screenToWorld(payload.point, data),
463
-        direction: [0, 1],
464
-      })
457
+    newLine() {
458
+      return ShapeType.Line
465
     },
459
     },
466
-
467
-    newCircle(data, payload: PointerInfo) {
468
-      return shapeUtilityMap[ShapeType.Circle].create({
469
-        point: screenToWorld(payload.point, data),
470
-        radius: 1,
471
-      })
460
+    newCircle() {
461
+      return ShapeType.Circle
472
     },
462
     },
473
-
474
-    newEllipse(data, payload: PointerInfo) {
475
-      return shapeUtilityMap[ShapeType.Ellipse].create({
476
-        point: screenToWorld(payload.point, data),
477
-        radiusX: 1,
478
-        radiusY: 1,
479
-      })
463
+    newEllipse() {
464
+      return ShapeType.Ellipse
480
     },
465
     },
481
-
482
-    newRectangle(data, payload: PointerInfo) {
483
-      return shapeUtilityMap[ShapeType.Rectangle].create({
484
-        point: screenToWorld(payload.point, data),
485
-        size: [1, 1],
486
-      })
466
+    newRectangle() {
467
+      return ShapeType.Rectangle
487
     },
468
     },
488
   },
469
   },
489
   conditions: {
470
   conditions: {
528
   },
509
   },
529
   actions: {
510
   actions: {
530
     /* --------------------- Shapes --------------------- */
511
     /* --------------------- Shapes --------------------- */
531
-    createShape(data, payload, shape: Shape) {
512
+    createShape(data, payload, type: ShapeType) {
513
+      const shape = createShape(type, {
514
+        point: screenToWorld(payload.point, data),
515
+        style: getCurrent(data.currentStyle),
516
+      })
517
+
532
       const siblings = getChildren(data, shape.parentId)
518
       const siblings = getChildren(data, shape.parentId)
533
       const childIndex = siblings.length
519
       const childIndex = siblings.length
534
         ? siblings[siblings.length - 1].childIndex + 1
520
         ? siblings[siblings.length - 1].childIndex + 1
710
 
696
 
711
       document.documentElement.style.setProperty("--camera-zoom", "1")
697
       document.documentElement.style.setProperty("--camera-zoom", "1")
712
     },
698
     },
713
-    zoomCameraToSelection(data) {
699
+    zoomCameraToActual(data) {
714
       const { camera } = data
700
       const { camera } = data
715
 
701
 
716
-      const bounds = getSelectedBounds(data)
717
-
718
-      const zoom =
719
-        bounds.width < bounds.height
720
-          ? (window.innerWidth - 128) / bounds.width
721
-          : (window.innerHeight - 128) / bounds.height
722
-
723
-      const mx = window.innerWidth - bounds.width * zoom
724
-      const my = window.innerHeight - bounds.height * zoom
725
-
726
-      camera.zoom = zoom
702
+      const center = [window.innerWidth / 2, window.innerHeight / 2]
727
 
703
 
728
-      camera.point = vec.add(
729
-        [-bounds.minX, -bounds.minY],
730
-        [mx / 2 / zoom, my / 2 / zoom]
731
-      )
704
+      const p0 = screenToWorld(center, data)
705
+      camera.zoom = 1
706
+      const p1 = screenToWorld(center, data)
707
+      camera.point = vec.add(camera.point, vec.sub(p1, p0))
732
 
708
 
733
       setZoomCSS(camera.zoom)
709
       setZoomCSS(camera.zoom)
734
     },
710
     },
737
 
713
 
738
       const bounds = getSelectedBounds(data)
714
       const bounds = getSelectedBounds(data)
739
 
715
 
740
-      const mx = window.innerWidth - bounds.width
741
-      const my = window.innerHeight - bounds.height
716
+      const mx = (window.innerWidth - bounds.width) / 2
717
+      const my = (window.innerHeight - bounds.height) / 2
742
 
718
 
743
       camera.zoom = 1
719
       camera.zoom = 1
720
+      camera.point = vec.add([-bounds.minX, -bounds.minY], [mx, my])
744
 
721
 
745
-      camera.point = vec.add([-bounds.minX, -bounds.minY], [mx / 2, my / 2])
746
       setZoomCSS(camera.zoom)
722
       setZoomCSS(camera.zoom)
747
     },
723
     },
748
-    zoomCameraToActual(data) {
724
+    zoomCameraToSelection(data) {
749
       const { camera } = data
725
       const { camera } = data
750
 
726
 
751
-      const center = [window.innerWidth / 2, window.innerHeight / 2]
727
+      const bounds = getSelectedBounds(data)
752
 
728
 
753
-      const p0 = screenToWorld(center, data)
754
-      camera.zoom = 1
755
-      const p1 = screenToWorld(center, data)
756
-      camera.point = vec.add(camera.point, vec.sub(p1, p0))
729
+      const zoom =
730
+        bounds.width > bounds.height
731
+          ? (window.innerWidth - 128) / bounds.width
732
+          : (window.innerHeight - 128) / bounds.height
733
+
734
+      const mx = (window.innerWidth - bounds.width * zoom) / 2 / zoom
735
+      const my = (window.innerHeight - bounds.height * zoom) / 2 / zoom
736
+
737
+      camera.zoom = zoom
738
+      camera.point = vec.add([-bounds.minX, -bounds.minY], [mx, my])
757
 
739
 
758
       setZoomCSS(camera.zoom)
740
       setZoomCSS(camera.zoom)
759
     },
741
     },
774
       )
756
       )
775
 
757
 
776
       const zoom =
758
       const zoom =
777
-        bounds.width < bounds.height
759
+        bounds.width > bounds.height
778
           ? (window.innerWidth - 128) / bounds.width
760
           ? (window.innerWidth - 128) / bounds.width
779
           : (window.innerHeight - 128) / bounds.height
761
           : (window.innerHeight - 128) / bounds.height
780
 
762
 
788
     },
770
     },
789
     zoomCamera(data, payload: { delta: number; point: number[] }) {
771
     zoomCamera(data, payload: { delta: number; point: number[] }) {
790
       const { camera } = data
772
       const { camera } = data
773
+      const next = camera.zoom - (payload.delta / 100) * camera.zoom
774
+
791
       const p0 = screenToWorld(payload.point, data)
775
       const p0 = screenToWorld(payload.point, data)
792
-      camera.zoom = clamp(
793
-        camera.zoom - (payload.delta / 100) * camera.zoom,
794
-        0.1,
795
-        3
796
-      )
776
+      camera.zoom = clamp(next, 0.1, 3)
797
       const p1 = screenToWorld(payload.point, data)
777
       const p1 = screenToWorld(payload.point, data)
798
       camera.point = vec.add(camera.point, vec.sub(p1, p0))
778
       camera.point = vec.add(camera.point, vec.sub(p1, p0))
799
 
779
 
832
       history.redo(data)
812
       history.redo(data)
833
     },
813
     },
834
 
814
 
815
+    /* --------------------- Styles --------------------- */
816
+
817
+    toggleStylePanel(data) {
818
+      data.settings.isStyleOpen = !data.settings.isStyleOpen
819
+    },
820
+    updateStyles(data, payload: Partial<ShapeStyles>) {
821
+      Object.assign(data.currentStyle, payload)
822
+    },
823
+    applyStylesToSelection(data, payload: Partial<ShapeStyles>) {
824
+      commands.style(data, payload)
825
+    },
826
+
835
     /* ---------------------- Code ---------------------- */
827
     /* ---------------------- Code ---------------------- */
836
     closeCodePanel(data) {
828
     closeCodePanel(data) {
837
       data.settings.isCodeOpen = false
829
       data.settings.isCodeOpen = false

+ 1
- 0
styles/stitches.config.ts 查看文件

14
       boundsBg: "rgba(65, 132, 244, 0.100)",
14
       boundsBg: "rgba(65, 132, 244, 0.100)",
15
       border: "#aaa",
15
       border: "#aaa",
16
       panel: "#fefefe",
16
       panel: "#fefefe",
17
+      hover: "#efefef",
17
       text: "#000",
18
       text: "#000",
18
       input: "#f3f3f3",
19
       input: "#f3f3f3",
19
       inputBorder: "#ddd",
20
       inputBorder: "#ddd",

+ 6
- 1
types.ts 查看文件

12
     fontSize: number
12
     fontSize: number
13
     isDarkMode: boolean
13
     isDarkMode: boolean
14
     isCodeOpen: boolean
14
     isCodeOpen: boolean
15
+    isStyleOpen: boolean
15
   }
16
   }
17
+  currentStyle: ShapeStyles
16
   camera: {
18
   camera: {
17
     point: number[]
19
     point: number[]
18
     zoom: number
20
     zoom: number
59
 // Cubic = "cubic",
61
 // Cubic = "cubic",
60
 // Conic = "conic",
62
 // Conic = "conic",
61
 
63
 
64
+export type ShapeStyles = Partial<React.SVGProps<SVGUseElement>>
65
+
62
 export interface BaseShape {
66
 export interface BaseShape {
63
   id: string
67
   id: string
64
   type: ShapeType
68
   type: ShapeType
68
   name: string
72
   name: string
69
   point: number[]
73
   point: number[]
70
   rotation: number
74
   rotation: number
71
-  style: Partial<React.SVGProps<SVGUseElement>>
75
+  style: ShapeStyles
72
 }
76
 }
73
 
77
 
74
 export interface DotShape extends BaseShape {
78
 export interface DotShape extends BaseShape {
104
 export interface RectangleShape extends BaseShape {
108
 export interface RectangleShape extends BaseShape {
105
   type: ShapeType.Rectangle
109
   type: ShapeType.Rectangle
106
   size: number[]
110
   size: number[]
111
+  radius: number
107
 }
112
 }
108
 
113
 
109
 export type MutableShape =
114
 export type MutableShape =

+ 7
- 1
utils/utils.ts 查看文件

1
 import Vector from "lib/code/vector"
1
 import Vector from "lib/code/vector"
2
 import React from "react"
2
 import React from "react"
3
-import { Data, Bounds, Edge, Corner, Shape } from "types"
3
+import { Data, Bounds, Edge, Corner, Shape, ShapeStyles } from "types"
4
 import * as vec from "./vec"
4
 import * as vec from "./vec"
5
 import _isMobile from "ismobilejs"
5
 import _isMobile from "ismobilejs"
6
 import { getShapeUtils } from "lib/shape-utils"
6
 import { getShapeUtils } from "lib/shape-utils"
1486
 export function setZoomCSS(zoom: number) {
1486
 export function setZoomCSS(zoom: number) {
1487
   document.documentElement.style.setProperty("--camera-zoom", zoom.toString())
1487
   document.documentElement.style.setProperty("--camera-zoom", zoom.toString())
1488
 }
1488
 }
1489
+
1490
+export function getCurrent<T extends object>(source: T): T {
1491
+  return Object.fromEntries(
1492
+    Object.entries(source).map(([key, value]) => [key, value])
1493
+  ) as T
1494
+}

+ 321
- 4
yarn.lock 查看文件

879
   dependencies:
879
   dependencies:
880
     regenerator-runtime "^0.13.4"
880
     regenerator-runtime "^0.13.4"
881
 
881
 
882
-"@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4":
882
+"@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.13.10", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4":
883
   version "7.14.0"
883
   version "7.14.0"
884
   resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.0.tgz#46794bc20b612c5f75e62dd071e24dfd95f1cbe6"
884
   resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.0.tgz#46794bc20b612c5f75e62dd071e24dfd95f1cbe6"
885
   integrity sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==
885
   integrity sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==
1259
   resolved "https://registry.yarnpkg.com/@opentelemetry/context-base/-/context-base-0.14.0.tgz#c67fc20a4d891447ca1a855d7d70fa79a3533001"
1259
   resolved "https://registry.yarnpkg.com/@opentelemetry/context-base/-/context-base-0.14.0.tgz#c67fc20a4d891447ca1a855d7d70fa79a3533001"
1260
   integrity sha512-sDOAZcYwynHFTbLo6n8kIbLiVF3a3BLkrmehJUyEbT9F+Smbi47kLGS2gG2g0fjBLR/Lr1InPD7kXL7FaTqEkw==
1260
   integrity sha512-sDOAZcYwynHFTbLo6n8kIbLiVF3a3BLkrmehJUyEbT9F+Smbi47kLGS2gG2g0fjBLR/Lr1InPD7kXL7FaTqEkw==
1261
 
1261
 
1262
+"@radix-ui/popper@0.0.10":
1263
+  version "0.0.10"
1264
+  resolved "https://registry.yarnpkg.com/@radix-ui/popper/-/popper-0.0.10.tgz#9f707d9cec8762423f81acaf8e650e40a554cb73"
1265
+  integrity sha512-YFKuPqQPKscreQid7NuB4it3PMzSwGg03vgrud6sVliHkI43QNAOHyrHyMNo015jg6QK5GVDn+7J2W5uygqSGA==
1266
+  dependencies:
1267
+    "@babel/runtime" "^7.13.10"
1268
+    csstype "^3.0.4"
1269
+
1270
+"@radix-ui/primitive@0.0.5":
1271
+  version "0.0.5"
1272
+  resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-0.0.5.tgz#8464fb4db04401bde72d36e27e05714080668d40"
1273
+  integrity sha512-VeL6A5LpKYRJhDDj5tCTnzP3zm+FnvybsAkgBHQ4LUPPBnqRdWLoyKpZhlwFze/z22QHINaTIcE9Z/fTcrUR1g==
1274
+  dependencies:
1275
+    "@babel/runtime" "^7.13.10"
1276
+
1277
+"@radix-ui/react-arrow@0.0.13":
1278
+  version "0.0.13"
1279
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-0.0.13.tgz#06b5a17f33bbc1af1c88d2827f25f37be95daa38"
1280
+  integrity sha512-BHBAULgQYmj36BrJ+1AGhC5p4QjJaE+szJgJ1a1EYOM3G6QOeIQKYvIm8TPEdKAiJhAivK+jZFccsE4Blzqc9g==
1281
+  dependencies:
1282
+    "@babel/runtime" "^7.13.10"
1283
+    "@radix-ui/react-polymorphic" "0.0.11"
1284
+    "@radix-ui/react-primitive" "0.0.13"
1285
+
1286
+"@radix-ui/react-collection@0.0.12":
1287
+  version "0.0.12"
1288
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-0.0.12.tgz#5cd09312cdec34fdbbe1d31affaba69eb768e342"
1289
+  integrity sha512-jUP99/wCHpXm7ytbmpcjhhxFHBsr2lptEzKO8DUkD2CrJBS4Q3XHMKBDOvNQQzIqJhsz0A5JP6Fo0Vgd8Ld3FQ==
1290
+  dependencies:
1291
+    "@babel/runtime" "^7.13.10"
1292
+    "@radix-ui/react-compose-refs" "0.0.5"
1293
+    "@radix-ui/react-slot" "0.0.10"
1294
+
1295
+"@radix-ui/react-compose-refs@0.0.5":
1296
+  version "0.0.5"
1297
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-0.0.5.tgz#0f71f0de1dec341f30cebd420b6bc3d12a3037dd"
1298
+  integrity sha512-O9mH9X/2EwuAEEoZXrU4alcrRbAhhZHGpIJ5bOH6rmRcokhaoWRBY1tOEe2lgHdb/bkKrY+viLi4Zq8Ju6/09Q==
1299
+  dependencies:
1300
+    "@babel/runtime" "^7.13.10"
1301
+
1302
+"@radix-ui/react-context@0.0.5":
1303
+  version "0.0.5"
1304
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-0.0.5.tgz#7c15f46795d7765dabfaf6f9c53791ad28c521c2"
1305
+  integrity sha512-bwrzAc0qc2EPepSTLBT4+93uCiI9wP78VSmPg2K+k71O/vpx7dPs0VqrewwCBNCHT54NIwaRr2hEsm2uqYi02A==
1306
+  dependencies:
1307
+    "@babel/runtime" "^7.13.10"
1308
+
1309
+"@radix-ui/react-dismissable-layer@0.0.13":
1310
+  version "0.0.13"
1311
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-0.0.13.tgz#7c4be6170a14d8a66c48680a8a8c987bc29bcf05"
1312
+  integrity sha512-g0zhxdZzCJhVeRumaU8ODptRFhYorSRPsLwD30sz9slYaW0yg6lHvMQicRNtgFX0WnsbmrUVY6NMrwWpSHJXbg==
1313
+  dependencies:
1314
+    "@babel/runtime" "^7.13.10"
1315
+    "@radix-ui/react-use-body-pointer-events" "0.0.6"
1316
+    "@radix-ui/react-use-callback-ref" "0.0.5"
1317
+    "@radix-ui/react-use-escape-keydown" "0.0.6"
1318
+
1319
+"@radix-ui/react-dropdown-menu@^0.0.19":
1320
+  version "0.0.19"
1321
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-0.0.19.tgz#fbc3106bcda65d3060b280f4af3a9c45324ab474"
1322
+  integrity sha512-7UhT6PIXl9fr8Ai9DkXMtxPNQFh8emrklgY5jcad9NHKWAztgfL6Fm+Ns0GEYUkd5OpJLEaIj/EUkwFM73SrGw==
1323
+  dependencies:
1324
+    "@babel/runtime" "^7.13.10"
1325
+    "@radix-ui/primitive" "0.0.5"
1326
+    "@radix-ui/react-compose-refs" "0.0.5"
1327
+    "@radix-ui/react-context" "0.0.5"
1328
+    "@radix-ui/react-id" "0.0.6"
1329
+    "@radix-ui/react-menu" "0.0.18"
1330
+    "@radix-ui/react-polymorphic" "0.0.11"
1331
+    "@radix-ui/react-primitive" "0.0.13"
1332
+    "@radix-ui/react-use-controllable-state" "0.0.6"
1333
+
1334
+"@radix-ui/react-focus-guards@0.0.7":
1335
+  version "0.0.7"
1336
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-0.0.7.tgz#285ed081c877587acd4ee7e6d8260bdf9044e922"
1337
+  integrity sha512-enAsmrUunptHVzPLTuZqwTP/X3WFBnyJ/jP9W+0g+bRvI3o7V1kxNc+T2Rp1eRTFBW+lUNnt08qkugPytyTRog==
1338
+  dependencies:
1339
+    "@babel/runtime" "^7.13.10"
1340
+
1341
+"@radix-ui/react-focus-scope@0.0.13":
1342
+  version "0.0.13"
1343
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-0.0.13.tgz#06dd6781d457b272601d4c087ac1240907824443"
1344
+  integrity sha512-PelAuc+7HSGruBraSzuHogwaKqCvmO288ecIm3cCAkrJqPQ7hoKSd/LfLfoa/EvjqK9azmm7NQ6LSPoteQvOGQ==
1345
+  dependencies:
1346
+    "@babel/runtime" "^7.13.10"
1347
+    "@radix-ui/react-use-callback-ref" "0.0.5"
1348
+
1349
+"@radix-ui/react-id@0.0.6":
1350
+  version "0.0.6"
1351
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-0.0.6.tgz#c4b27d11861805e91ac296e7758ab47e3947b65c"
1352
+  integrity sha512-PzmraF34fYggsYvTIZVJ5S68WMp3aKUN3HkSmGnz4zn9zpRjkAbbg7Xn3ueQI3FQsLWKgyUfnpsmWFDndpcqYg==
1353
+  dependencies:
1354
+    "@babel/runtime" "^7.13.10"
1355
+
1356
+"@radix-ui/react-menu@0.0.18":
1357
+  version "0.0.18"
1358
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-menu/-/react-menu-0.0.18.tgz#b36f7657eb6757c623ffc688c48a4781ffd82351"
1359
+  integrity sha512-js5hFzoxNOnHV8g7RPoPl/GncUCW2aCOuNt9Qh6WznRmxmsETPUWZZe4kADJnZmYbIxG07EEl0iv3E1rmsqNMw==
1360
+  dependencies:
1361
+    "@babel/runtime" "^7.13.10"
1362
+    "@radix-ui/primitive" "0.0.5"
1363
+    "@radix-ui/react-collection" "0.0.12"
1364
+    "@radix-ui/react-compose-refs" "0.0.5"
1365
+    "@radix-ui/react-context" "0.0.5"
1366
+    "@radix-ui/react-dismissable-layer" "0.0.13"
1367
+    "@radix-ui/react-focus-guards" "0.0.7"
1368
+    "@radix-ui/react-focus-scope" "0.0.13"
1369
+    "@radix-ui/react-polymorphic" "0.0.11"
1370
+    "@radix-ui/react-popper" "0.0.16"
1371
+    "@radix-ui/react-portal" "0.0.13"
1372
+    "@radix-ui/react-presence" "0.0.14"
1373
+    "@radix-ui/react-primitive" "0.0.13"
1374
+    "@radix-ui/react-roving-focus" "0.0.13"
1375
+    "@radix-ui/react-slot" "0.0.10"
1376
+    "@radix-ui/react-use-callback-ref" "0.0.5"
1377
+    aria-hidden "^1.1.1"
1378
+    react-remove-scroll "^2.4.0"
1379
+
1380
+"@radix-ui/react-polymorphic@0.0.11":
1381
+  version "0.0.11"
1382
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-polymorphic/-/react-polymorphic-0.0.11.tgz#23f26b14e67a0e57cd981c37618d603b952af80d"
1383
+  integrity sha512-CztM4962esOx3i1ls6GuY9RBYIY2Df1Bmp5emHRTxZi8owyCZwZYPctYaDuMO0qIGikPiKD8HBion/m7VWUyEA==
1384
+  dependencies:
1385
+    "@babel/runtime" "^7.13.10"
1386
+
1387
+"@radix-ui/react-popper@0.0.16":
1388
+  version "0.0.16"
1389
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-0.0.16.tgz#62cccb7d920dc89e076bbdc3421db8c84078f428"
1390
+  integrity sha512-njciQ/eIKaDF9h+27Pwi1H6NliQbzTgaHOsT0w/Lxx4vfMe8zcHtiEigYVGErNR4zAYlbW72KzLjtngtNnaorg==
1391
+  dependencies:
1392
+    "@babel/runtime" "^7.13.10"
1393
+    "@radix-ui/popper" "0.0.10"
1394
+    "@radix-ui/react-arrow" "0.0.13"
1395
+    "@radix-ui/react-compose-refs" "0.0.5"
1396
+    "@radix-ui/react-context" "0.0.5"
1397
+    "@radix-ui/react-polymorphic" "0.0.11"
1398
+    "@radix-ui/react-primitive" "0.0.13"
1399
+    "@radix-ui/react-use-rect" "0.0.7"
1400
+    "@radix-ui/react-use-size" "0.0.6"
1401
+    "@radix-ui/rect" "0.0.5"
1402
+
1403
+"@radix-ui/react-portal@0.0.13":
1404
+  version "0.0.13"
1405
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-0.0.13.tgz#8e60e9ee9b1594f98ee4a8f24a9851ef7ef2ad31"
1406
+  integrity sha512-Mw5hrxds2T9HTGwdDbvlKGvTUfcuKhPtqxLnizOrM685e80j+pfjAAfMSXSyfmra9KFQvk3XxmUP0d4U6+kzMg==
1407
+  dependencies:
1408
+    "@babel/runtime" "^7.13.10"
1409
+    "@radix-ui/react-polymorphic" "0.0.11"
1410
+    "@radix-ui/react-primitive" "0.0.13"
1411
+    "@radix-ui/react-use-layout-effect" "0.0.5"
1412
+
1413
+"@radix-ui/react-presence@0.0.14":
1414
+  version "0.0.14"
1415
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-0.0.14.tgz#6a86058bbbf46234dd8840dacd620b3ac5797025"
1416
+  integrity sha512-ufof9B76DHXV0sC8H7Lswh2AepdJFG8qEtF32JWrbA9N1bl2Jnf9px76KsagyC0MA8crGEZO5A96wizGuSgGWQ==
1417
+  dependencies:
1418
+    "@babel/runtime" "^7.13.10"
1419
+    "@radix-ui/react-compose-refs" "0.0.5"
1420
+
1421
+"@radix-ui/react-primitive@0.0.13":
1422
+  version "0.0.13"
1423
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-0.0.13.tgz#79c606c3e7da9c377b77a7b3f4ec879b45de47a2"
1424
+  integrity sha512-6xxWzw67t7ZuN9Ikn9NNQdb/HSF7dNHPN3kPcgjiVgTEZa3tKk1xjSxGjjQztE61g9GrnTLpu7mBjmEuZDI/lA==
1425
+  dependencies:
1426
+    "@babel/runtime" "^7.13.10"
1427
+    "@radix-ui/react-polymorphic" "0.0.11"
1428
+
1429
+"@radix-ui/react-roving-focus@0.0.13":
1430
+  version "0.0.13"
1431
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-0.0.13.tgz#c72f503832577979c4caa9efcfd59140730c2f80"
1432
+  integrity sha512-jTx3TBMYEdj9SFzRDryO62M9ZK28pYvKKxj/mxWMpMbIjF4q6L+yJmDxtv6glHgCRkwBEyulFVGCjjDg+qxYRA==
1433
+  dependencies:
1434
+    "@babel/runtime" "^7.13.10"
1435
+    "@radix-ui/primitive" "0.0.5"
1436
+    "@radix-ui/react-collection" "0.0.12"
1437
+    "@radix-ui/react-compose-refs" "0.0.5"
1438
+    "@radix-ui/react-context" "0.0.5"
1439
+    "@radix-ui/react-id" "0.0.6"
1440
+    "@radix-ui/react-polymorphic" "0.0.11"
1441
+    "@radix-ui/react-primitive" "0.0.13"
1442
+    "@radix-ui/react-use-callback-ref" "0.0.5"
1443
+    "@radix-ui/react-use-controllable-state" "0.0.6"
1444
+
1445
+"@radix-ui/react-slot@0.0.10":
1446
+  version "0.0.10"
1447
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-0.0.10.tgz#27a17cad7064872117aeb68113fa934bc5d34c37"
1448
+  integrity sha512-p0jJj6lTz1RV2imavnclk8Gda002ZSDR4/zPJ4EQBhspGnx7Y8l6G59c8lxJrT7c7F46F2eRNjpTTjFqqir6EQ==
1449
+  dependencies:
1450
+    "@babel/runtime" "^7.13.10"
1451
+    "@radix-ui/primitive" "0.0.5"
1452
+    "@radix-ui/react-compose-refs" "0.0.5"
1453
+
1454
+"@radix-ui/react-use-body-pointer-events@0.0.6":
1455
+  version "0.0.6"
1456
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-use-body-pointer-events/-/react-use-body-pointer-events-0.0.6.tgz#30b21301880417e7dbb345871ff5a83f2abe0d8d"
1457
+  integrity sha512-ouYb7u1+K9TsiEcNs3HceNUBUgB2PV41EyD5O6y6ZPMxl1lW/QAy5dfyfJMRyaRWQ6kxwmGoKlCSb4uPTruzuQ==
1458
+  dependencies:
1459
+    "@babel/runtime" "^7.13.10"
1460
+    "@radix-ui/react-use-layout-effect" "0.0.5"
1461
+
1462
+"@radix-ui/react-use-callback-ref@0.0.5":
1463
+  version "0.0.5"
1464
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-0.0.5.tgz#fa8db050229cda573dfeeae213d74ef06f6130db"
1465
+  integrity sha512-z1AI221vmq9f3vsDyrCsGLCatKagbM1YeCGdRMhMsUBzFFCaJ+Axyoe/ndVqW8wwsraGWr1zYVAhIEdlC0GvPg==
1466
+  dependencies:
1467
+    "@babel/runtime" "^7.13.10"
1468
+
1469
+"@radix-ui/react-use-controllable-state@0.0.6":
1470
+  version "0.0.6"
1471
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-0.0.6.tgz#c4b16bc911a25889333388a684a04df937e5fec7"
1472
+  integrity sha512-fBk4hUSKc4N7X/NAaifWYfKKfNuOB9xvj0MBQQYS5oOTNRgg4y8/Ax3jZ0adsplXDm7ix75sxqWm0nrvUoAjcw==
1473
+  dependencies:
1474
+    "@babel/runtime" "^7.13.10"
1475
+    "@radix-ui/react-use-callback-ref" "0.0.5"
1476
+
1477
+"@radix-ui/react-use-escape-keydown@0.0.6":
1478
+  version "0.0.6"
1479
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-0.0.6.tgz#1ad1c81b99961b7dbe376ef54151ebc8bef627a0"
1480
+  integrity sha512-MJpVj21BYwWllmp2xbXPqpKPssJ1WWrZi+Qx7PY5hVcBhQr5Jo6yKwIX677pH5Yql95ENTTT5LW3q+LVFYIISw==
1481
+  dependencies:
1482
+    "@babel/runtime" "^7.13.10"
1483
+    "@radix-ui/react-use-callback-ref" "0.0.5"
1484
+
1485
+"@radix-ui/react-use-layout-effect@0.0.5":
1486
+  version "0.0.5"
1487
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-0.0.5.tgz#cbbd059090edc765749da00d9f562a9abd43cbac"
1488
+  integrity sha512-bNPW2JNOr/p2hXr0hfKKqrEy5deNSRF17sw3l9Z7qlEnvIbBtQ7iwY/wrxIz5P7XFyYGoXodIUDH5G8PEucE3A==
1489
+  dependencies:
1490
+    "@babel/runtime" "^7.13.10"
1491
+
1492
+"@radix-ui/react-use-rect@0.0.7":
1493
+  version "0.0.7"
1494
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-0.0.7.tgz#e3a55fa7183ef436042198787bf38f8c9befcc14"
1495
+  integrity sha512-OmaeFTgyiGNAchaxzDu+kFLz4Ly8RUcT5nwfoz4Nddd86I8Zdq93iNFnOpVLoVYqBnFEmvR6zexHXNFATrMbbQ==
1496
+  dependencies:
1497
+    "@babel/runtime" "^7.13.10"
1498
+    "@radix-ui/rect" "0.0.5"
1499
+
1500
+"@radix-ui/react-use-size@0.0.6":
1501
+  version "0.0.6"
1502
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-0.0.6.tgz#998eaf6e8871b868f81f3b7faac06c3e896c37a0"
1503
+  integrity sha512-kP4RIb2I5oHQzwzXJ21Hu8htNqf+sdaRzywxQpbj+hmqeUhpvIkhoq+ShNWV9wE/3c1T7gPnka8/nKYsKaKdCg==
1504
+  dependencies:
1505
+    "@babel/runtime" "^7.13.10"
1506
+
1507
+"@radix-ui/rect@0.0.5":
1508
+  version "0.0.5"
1509
+  resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-0.0.5.tgz#6000d8d800288114af4bbc5863e6b58755d7d978"
1510
+  integrity sha512-gXw171KbjyttA7K1DRIvPguLmKsg8raitB67MIcsdZwcquy+a1O2w3xY21NIKEqGhJwqJkECPUmMJDXgMNYuAg==
1511
+  dependencies:
1512
+    "@babel/runtime" "^7.13.10"
1513
+
1262
 "@rollup/plugin-babel@^5.1.0":
1514
 "@rollup/plugin-babel@^5.1.0":
1263
   version "5.3.0"
1515
   version "5.3.0"
1264
   resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-5.3.0.tgz#9cb1c5146ddd6a4968ad96f209c50c62f92f9879"
1516
   resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-5.3.0.tgz#9cb1c5146ddd6a4968ad96f209c50c62f92f9879"
1731
   dependencies:
1983
   dependencies:
1732
     sprintf-js "~1.0.2"
1984
     sprintf-js "~1.0.2"
1733
 
1985
 
1986
+aria-hidden@^1.1.1:
1987
+  version "1.1.3"
1988
+  resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.1.3.tgz#bb48de18dc84787a3c6eee113709c473c64ec254"
1989
+  integrity sha512-RhVWFtKH5BiGMycI72q2RAFMLQi8JP9bLuQXgR5a8Znp7P5KOIADSJeyfI8PCVxLEp067B2HbP5JIiI/PXIZeA==
1990
+  dependencies:
1991
+    tslib "^1.0.0"
1992
+
1734
 aria-query@^4.2.2:
1993
 aria-query@^4.2.2:
1735
   version "4.2.2"
1994
   version "4.2.2"
1736
   resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b"
1995
   resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b"
2800
   dependencies:
3059
   dependencies:
2801
     cssom "~0.3.6"
3060
     cssom "~0.3.6"
2802
 
3061
 
2803
-csstype@^3.0.2:
3062
+csstype@^3.0.2, csstype@^3.0.4:
2804
   version "3.0.8"
3063
   version "3.0.8"
2805
   resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.8.tgz#d2266a792729fb227cd216fb572f43728e1ad340"
3064
   resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.8.tgz#d2266a792729fb227cd216fb572f43728e1ad340"
2806
   integrity sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==
3065
   integrity sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==
2993
   resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651"
3252
   resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651"
2994
   integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==
3253
   integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==
2995
 
3254
 
3255
+detect-node-es@^1.1.0:
3256
+  version "1.1.0"
3257
+  resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493"
3258
+  integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==
3259
+
2996
 diff-sequences@^25.2.6:
3260
 diff-sequences@^25.2.6:
2997
   version "25.2.6"
3261
   version "25.2.6"
2998
   resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-25.2.6.tgz#5f467c00edd35352b7bca46d7927d60e687a76dd"
3262
   resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-25.2.6.tgz#5f467c00edd35352b7bca46d7927d60e687a76dd"
3818
     has "^1.0.3"
4082
     has "^1.0.3"
3819
     has-symbols "^1.0.1"
4083
     has-symbols "^1.0.1"
3820
 
4084
 
4085
+get-nonce@^1.0.0:
4086
+  version "1.0.1"
4087
+  resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3"
4088
+  integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==
4089
+
3821
 get-orientation@1.1.2:
4090
 get-orientation@1.1.2:
3822
   version "1.1.2"
4091
   version "1.1.2"
3823
   resolved "https://registry.yarnpkg.com/get-orientation/-/get-orientation-1.1.2.tgz#20507928951814f8a91ded0a0e67b29dfab98947"
4092
   resolved "https://registry.yarnpkg.com/get-orientation/-/get-orientation-1.1.2.tgz#20507928951814f8a91ded0a0e67b29dfab98947"
4213
   resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e"
4482
   resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e"
4214
   integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==
4483
   integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==
4215
 
4484
 
4485
+invariant@^2.2.4:
4486
+  version "2.2.4"
4487
+  resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
4488
+  integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==
4489
+  dependencies:
4490
+    loose-envify "^1.0.0"
4491
+
4216
 ip-regex@^2.1.0:
4492
 ip-regex@^2.1.0:
4217
   version "2.1.0"
4493
   version "2.1.0"
4218
   resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9"
4494
   resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9"
5349
   dependencies:
5625
   dependencies:
5350
     "@sinonjs/commons" "^1.7.0"
5626
     "@sinonjs/commons" "^1.7.0"
5351
 
5627
 
5352
-loose-envify@^1.1.0, loose-envify@^1.4.0:
5628
+loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
5353
   version "1.4.0"
5629
   version "1.4.0"
5354
   resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
5630
   resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
5355
   integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
5631
   integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
6388
   resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f"
6664
   resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f"
6389
   integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==
6665
   integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==
6390
 
6666
 
6667
+react-remove-scroll-bar@^2.1.0:
6668
+  version "2.2.0"
6669
+  resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.2.0.tgz#d4d545a7df024f75d67e151499a6ab5ac97c8cdd"
6670
+  integrity sha512-UU9ZBP1wdMR8qoUs7owiVcpaPwsQxUDC2lypP6mmixaGlARZa7ZIBx1jcuObLdhMOvCsnZcvetOho0wzPa9PYg==
6671
+  dependencies:
6672
+    react-style-singleton "^2.1.0"
6673
+    tslib "^1.0.0"
6674
+
6675
+react-remove-scroll@^2.4.0:
6676
+  version "2.4.2"
6677
+  resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.4.2.tgz#5b7e3eb8c3389d3636234716d2feb618729fc4d9"
6678
+  integrity sha512-mMSIZYQF3jS2uRJXeFDRaVGA+BGs/hIryV64YUKsHFtpgwZloOUcdu0oW8K6OU8uLHt/kM5d0lUZbdpIVwgXtQ==
6679
+  dependencies:
6680
+    react-remove-scroll-bar "^2.1.0"
6681
+    react-style-singleton "^2.1.0"
6682
+    tslib "^1.0.0"
6683
+    use-callback-ref "^1.2.3"
6684
+    use-sidecar "^1.0.1"
6685
+
6686
+react-style-singleton@^2.1.0:
6687
+  version "2.1.1"
6688
+  resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.1.1.tgz#ce7f90b67618be2b6b94902a30aaea152ce52e66"
6689
+  integrity sha512-jNRp07Jza6CBqdRKNgGhT3u9umWvils1xsuMOjZlghBDH2MU0PL2WZor4PGYjXpnRCa9DQSlHMs/xnABWOwYbA==
6690
+  dependencies:
6691
+    get-nonce "^1.0.0"
6692
+    invariant "^2.2.4"
6693
+    tslib "^1.0.0"
6694
+
6391
 react@17.0.2:
6695
 react@17.0.2:
6392
   version "17.0.2"
6696
   version "17.0.2"
6393
   resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
6697
   resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
7696
   resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.1.tgz#410eb0d113e5b6356490eec749603725b021b43e"
8000
   resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.1.tgz#410eb0d113e5b6356490eec749603725b021b43e"
7697
   integrity sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==
8001
   integrity sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==
7698
 
8002
 
7699
-tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
8003
+tslib@^1.0.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
7700
   version "1.14.1"
8004
   version "1.14.1"
7701
   resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
8005
   resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
7702
   integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
8006
   integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
7880
     punycode "1.3.2"
8184
     punycode "1.3.2"
7881
     querystring "0.2.0"
8185
     querystring "0.2.0"
7882
 
8186
 
8187
+use-callback-ref@^1.2.3:
8188
+  version "1.2.5"
8189
+  resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.2.5.tgz#6115ed242cfbaed5915499c0a9842ca2912f38a5"
8190
+  integrity sha512-gN3vgMISAgacF7sqsLPByqoePooY3n2emTH59Ur5d/M8eg4WTWu1xp8i8DHjohftIyEx0S08RiYxbffr4j8Peg==
8191
+
8192
+use-sidecar@^1.0.1:
8193
+  version "1.0.5"
8194
+  resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.0.5.tgz#ffff2a17c1df42e348624b699ba6e5c220527f2b"
8195
+  integrity sha512-k9jnrjYNwN6xYLj1iaGhonDghfvmeTmYjAiGvOr7clwKfPjMXJf4/HOr7oT5tJwYafgp2tG2l3eZEOfoELiMcA==
8196
+  dependencies:
8197
+    detect-node-es "^1.1.0"
8198
+    tslib "^1.9.3"
8199
+
7883
 use-subscription@1.5.1:
8200
 use-subscription@1.5.1:
7884
   version "1.5.1"
8201
   version "1.5.1"
7885
   resolved "https://registry.yarnpkg.com/use-subscription/-/use-subscription-1.5.1.tgz#73501107f02fad84c6dd57965beb0b75c68c42d1"
8202
   resolved "https://registry.yarnpkg.com/use-subscription/-/use-subscription-1.5.1.tgz#73501107f02fad84c6dd57965beb0b75c68c42d1"

正在加载...
取消
保存