kopia lustrzana https://github.com/Tldraw/Tldraw
Adds style panel, styles
rodzic
def8f665d3
commit
6c8499309e
|
@ -3,7 +3,6 @@ import styled from "styles"
|
||||||
const DotCircle = styled("circle", {
|
const DotCircle = styled("circle", {
|
||||||
transform: "scale(var(--scale))",
|
transform: "scale(var(--scale))",
|
||||||
strokeWidth: "2",
|
strokeWidth: "2",
|
||||||
fill: "#000",
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export { DotCircle }
|
export { DotCircle }
|
||||||
|
|
|
@ -6,6 +6,7 @@ import Toolbar from "./toolbar"
|
||||||
import CodePanel from "./code-panel/code-panel"
|
import CodePanel from "./code-panel/code-panel"
|
||||||
import ControlsPanel from "./controls-panel/controls-panel"
|
import ControlsPanel from "./controls-panel/controls-panel"
|
||||||
import styled from "styles"
|
import styled from "styles"
|
||||||
|
import StylePanel from "./style-panel/style-panel"
|
||||||
|
|
||||||
export default function Editor() {
|
export default function Editor() {
|
||||||
useKeyboardEvents()
|
useKeyboardEvents()
|
||||||
|
@ -20,6 +21,9 @@ export default function Editor() {
|
||||||
<CodePanel />
|
<CodePanel />
|
||||||
<ControlsPanel />
|
<ControlsPanel />
|
||||||
</LeftPanels>
|
</LeftPanels>
|
||||||
|
<RightPanels>
|
||||||
|
<StylePanel />
|
||||||
|
</RightPanels>
|
||||||
</Layout>
|
</Layout>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -32,11 +36,11 @@ const Layout = styled("div", {
|
||||||
right: 0,
|
right: 0,
|
||||||
display: "grid",
|
display: "grid",
|
||||||
gridTemplateRows: "40px 1fr 40px",
|
gridTemplateRows: "40px 1fr 40px",
|
||||||
gridTemplateColumns: "auto 1fr",
|
gridTemplateColumns: "minmax(50%, 400px) 1fr auto",
|
||||||
gridTemplateAreas: `
|
gridTemplateAreas: `
|
||||||
"toolbar toolbar"
|
"toolbar toolbar toolbar"
|
||||||
"leftPanels main"
|
"leftPanels main rightPanels"
|
||||||
"statusbar statusbar"
|
"statusbar statusbar statusbar"
|
||||||
`,
|
`,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -47,3 +51,13 @@ const LeftPanels = styled("main", {
|
||||||
padding: 8,
|
padding: 8,
|
||||||
gap: 8,
|
gap: 8,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const RightPanels = styled("main", {
|
||||||
|
display: "grid",
|
||||||
|
gridArea: "rightPanels",
|
||||||
|
gridTemplateRows: "auto",
|
||||||
|
height: "fit-content",
|
||||||
|
justifyContent: "flex-end",
|
||||||
|
padding: 8,
|
||||||
|
gap: 8,
|
||||||
|
})
|
||||||
|
|
|
@ -13,7 +13,10 @@ export const Root = styled("div", {
|
||||||
|
|
||||||
variants: {
|
variants: {
|
||||||
isOpen: {
|
isOpen: {
|
||||||
true: {},
|
true: {
|
||||||
|
width: "auto",
|
||||||
|
minWidth: 300,
|
||||||
|
},
|
||||||
false: {
|
false: {
|
||||||
height: 34,
|
height: 34,
|
||||||
width: 34,
|
width: 34,
|
||||||
|
@ -28,7 +31,7 @@ export const Layout = styled("div", {
|
||||||
gridTemplateRows: "auto 1fr",
|
gridTemplateRows: "auto 1fr",
|
||||||
gridAutoRows: "28px",
|
gridAutoRows: "28px",
|
||||||
height: "100%",
|
height: "100%",
|
||||||
width: 560,
|
width: "100%",
|
||||||
minWidth: "100%",
|
minWidth: "100%",
|
||||||
maxWidth: 560,
|
maxWidth: 560,
|
||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
|
|
|
@ -16,7 +16,7 @@ export const IconButton = styled("button", {
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
|
|
||||||
"&:hover:not(:disabled)": {
|
"&:hover:not(:disabled)": {
|
||||||
backgroundColor: "$panel",
|
backgroundColor: "$hover",
|
||||||
},
|
},
|
||||||
|
|
||||||
"&:disabled": {
|
"&:disabled": {
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
import * as DropdownMenu from "@radix-ui/react-dropdown-menu"
|
||||||
|
import { Square } from "react-feather"
|
||||||
|
import { colors } from "state/data"
|
||||||
|
import styled from "styles"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
label: string
|
||||||
|
color: string
|
||||||
|
onChange: (color: string) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ColorPicker({ label, color, onChange }: Props) {
|
||||||
|
return (
|
||||||
|
<DropdownMenu.Root>
|
||||||
|
<CurrentColor>
|
||||||
|
<h3>{label}</h3>
|
||||||
|
<ColorIcon color={color} />
|
||||||
|
</CurrentColor>
|
||||||
|
<Colors sideOffset={4}>
|
||||||
|
{Object.entries(colors).map(([name, color]) => (
|
||||||
|
<ColorButton key={name} title={name} onSelect={() => onChange(color)}>
|
||||||
|
<ColorIcon color={color} />
|
||||||
|
</ColorButton>
|
||||||
|
))}
|
||||||
|
</Colors>
|
||||||
|
</DropdownMenu.Root>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function ColorIcon({ color }: { color: string }) {
|
||||||
|
return (
|
||||||
|
<Square
|
||||||
|
fill={color}
|
||||||
|
strokeDasharray={color === "transparent" ? "2, 3" : "none"}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const Colors = styled(DropdownMenu.Content, {
|
||||||
|
display: "grid",
|
||||||
|
padding: 4,
|
||||||
|
gridTemplateColumns: "repeat(6, 1fr)",
|
||||||
|
border: "1px solid $border",
|
||||||
|
backgroundColor: "$panel",
|
||||||
|
borderRadius: 4,
|
||||||
|
boxShadow: "0px 5px 15px -5px hsla(206,22%,7%,.15)",
|
||||||
|
})
|
||||||
|
|
||||||
|
const ColorButton = styled(DropdownMenu.Item, {
|
||||||
|
position: "relative",
|
||||||
|
cursor: "pointer",
|
||||||
|
height: 32,
|
||||||
|
width: 32,
|
||||||
|
border: "none",
|
||||||
|
padding: "none",
|
||||||
|
background: "none",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
|
||||||
|
"&::before": {
|
||||||
|
content: "''",
|
||||||
|
position: "absolute",
|
||||||
|
top: 4,
|
||||||
|
left: 4,
|
||||||
|
right: 4,
|
||||||
|
bottom: 4,
|
||||||
|
pointerEvents: "none",
|
||||||
|
zIndex: 0,
|
||||||
|
},
|
||||||
|
|
||||||
|
"&:hover::before": {
|
||||||
|
backgroundColor: "$hover",
|
||||||
|
borderRadius: 4,
|
||||||
|
},
|
||||||
|
|
||||||
|
"& svg": {
|
||||||
|
position: "relative",
|
||||||
|
stroke: "rgba(0,0,0,.2)",
|
||||||
|
strokeWidth: 1,
|
||||||
|
zIndex: 1,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const CurrentColor = styled(DropdownMenu.Trigger, {
|
||||||
|
position: "relative",
|
||||||
|
display: "flex",
|
||||||
|
width: "100%",
|
||||||
|
background: "none",
|
||||||
|
border: "none",
|
||||||
|
cursor: "pointer",
|
||||||
|
outline: "none",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
padding: "8px 8px 8px 12px",
|
||||||
|
|
||||||
|
"&::before": {
|
||||||
|
content: "''",
|
||||||
|
position: "absolute",
|
||||||
|
top: 4,
|
||||||
|
left: 4,
|
||||||
|
right: 4,
|
||||||
|
bottom: 4,
|
||||||
|
pointerEvents: "none",
|
||||||
|
zIndex: -1,
|
||||||
|
},
|
||||||
|
|
||||||
|
"&:hover::before": {
|
||||||
|
backgroundColor: "$hover",
|
||||||
|
borderRadius: 4,
|
||||||
|
},
|
||||||
|
|
||||||
|
"& h3": {
|
||||||
|
fontFamily: "$ui",
|
||||||
|
fontSize: "$2",
|
||||||
|
fontWeight: "$1",
|
||||||
|
margin: 0,
|
||||||
|
padding: 0,
|
||||||
|
},
|
||||||
|
|
||||||
|
"& svg": {
|
||||||
|
position: "relative",
|
||||||
|
stroke: "rgba(0,0,0,.2)",
|
||||||
|
strokeWidth: 1,
|
||||||
|
zIndex: 1,
|
||||||
|
},
|
||||||
|
})
|
|
@ -0,0 +1,119 @@
|
||||||
|
import styled from "styles"
|
||||||
|
import state, { useSelector } from "state"
|
||||||
|
import * as Panel from "components/panel"
|
||||||
|
import { useRef } from "react"
|
||||||
|
import { IconButton } from "components/shared"
|
||||||
|
import { Circle, Square, Trash, X } from "react-feather"
|
||||||
|
import { deepCompare, deepCompareArrays, getSelectedShapes } from "utils/utils"
|
||||||
|
import { colors } from "state/data"
|
||||||
|
|
||||||
|
import ColorPicker from "./color-picker"
|
||||||
|
import { ShapeByType, ShapeStyles } from "types"
|
||||||
|
|
||||||
|
export default function StylePanel() {
|
||||||
|
const rContainer = useRef<HTMLDivElement>(null)
|
||||||
|
const isOpen = useSelector((s) => s.data.settings.isStyleOpen)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StylePanelRoot ref={rContainer} isOpen={isOpen}>
|
||||||
|
{isOpen ? (
|
||||||
|
<SelectedShapeStyles />
|
||||||
|
) : (
|
||||||
|
<IconButton onClick={() => state.send("TOGGLED_STYLE_PANEL_OPEN")}>
|
||||||
|
<Circle />
|
||||||
|
</IconButton>
|
||||||
|
)}
|
||||||
|
</StylePanelRoot>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// This panel is going to be hard to keep cool, as we're selecting computed
|
||||||
|
// information, based on the user's current selection. We might have to keep
|
||||||
|
// track of this data manually within our state.
|
||||||
|
|
||||||
|
function SelectedShapeStyles({}: {}) {
|
||||||
|
const selectedIds = useSelector(
|
||||||
|
(s) => Array.from(s.data.selectedIds.values()),
|
||||||
|
deepCompareArrays
|
||||||
|
)
|
||||||
|
|
||||||
|
const shapesStyle = useSelector((s) => {
|
||||||
|
const { currentStyle } = s.data
|
||||||
|
const shapes = getSelectedShapes(s.data)
|
||||||
|
|
||||||
|
if (shapes.length === 0) {
|
||||||
|
return currentStyle
|
||||||
|
}
|
||||||
|
|
||||||
|
const style: Partial<ShapeStyles> = {}
|
||||||
|
const overrides = new Set<string>([])
|
||||||
|
|
||||||
|
for (const shape of shapes) {
|
||||||
|
for (let key in currentStyle) {
|
||||||
|
if (overrides.has(key)) continue
|
||||||
|
if (style[key] === undefined) {
|
||||||
|
style[key] = shape.style[key]
|
||||||
|
} else {
|
||||||
|
if (style[key] === shape.style[key]) continue
|
||||||
|
style[key] = currentStyle[key]
|
||||||
|
overrides.add(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return style
|
||||||
|
}, deepCompare)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Panel.Layout>
|
||||||
|
<Panel.Header>
|
||||||
|
<IconButton onClick={() => state.send("TOGGLED_STYLE_PANEL_OPEN")}>
|
||||||
|
<X />
|
||||||
|
</IconButton>
|
||||||
|
<h3>Style</h3>
|
||||||
|
<Panel.ButtonsGroup>
|
||||||
|
<IconButton onClick={() => state.send("DELETED")}>
|
||||||
|
<Trash />
|
||||||
|
</IconButton>
|
||||||
|
</Panel.ButtonsGroup>
|
||||||
|
</Panel.Header>
|
||||||
|
<Panel.Content>
|
||||||
|
<ColorsRow>
|
||||||
|
<ColorPicker
|
||||||
|
label="Fill"
|
||||||
|
color={shapesStyle.fill}
|
||||||
|
onChange={(color) => state.send("CHANGED_STYLE", { fill: color })}
|
||||||
|
/>
|
||||||
|
<ColorPicker
|
||||||
|
label="Stroke"
|
||||||
|
color={shapesStyle.stroke}
|
||||||
|
onChange={(color) => state.send("CHANGED_STYLE", { stroke: color })}
|
||||||
|
/>
|
||||||
|
</ColorsRow>
|
||||||
|
</Panel.Content>
|
||||||
|
</Panel.Layout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const StylePanelRoot = styled(Panel.Root, {
|
||||||
|
maxWidth: 260,
|
||||||
|
position: "relative",
|
||||||
|
|
||||||
|
variants: {
|
||||||
|
isOpen: {
|
||||||
|
true: {
|
||||||
|
width: "auto",
|
||||||
|
minWidth: 300,
|
||||||
|
},
|
||||||
|
false: {
|
||||||
|
height: 34,
|
||||||
|
width: 34,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const ColorsRow = styled("div", {
|
||||||
|
display: "grid",
|
||||||
|
gridTemplateColumns: "1fr 1fr",
|
||||||
|
})
|
|
@ -29,12 +29,12 @@ export default class CodeShape<T extends Shape> {
|
||||||
}
|
}
|
||||||
|
|
||||||
moveTo(point: Vector) {
|
moveTo(point: Vector) {
|
||||||
this.utils.translate(this._shape, vectorToPoint(point))
|
this.utils.translateTo(this._shape, vectorToPoint(point))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
translate(delta: Vector) {
|
translate(delta: Vector) {
|
||||||
this.utils.translate(
|
this.utils.translateTo(
|
||||||
this._shape,
|
this._shape,
|
||||||
vec.add(this._shape.point, vectorToPoint(delta))
|
vec.add(this._shape.point, vectorToPoint(delta))
|
||||||
)
|
)
|
||||||
|
@ -42,7 +42,7 @@ export default class CodeShape<T extends Shape> {
|
||||||
}
|
}
|
||||||
|
|
||||||
rotate(rotation: number) {
|
rotate(rotation: number) {
|
||||||
this.utils.rotate(this._shape, rotation)
|
this.utils.rotateTo(this._shape, rotation)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ export default class Rectangle extends CodeShape<RectangleShape> {
|
||||||
point: [0, 0],
|
point: [0, 0],
|
||||||
size: [100, 100],
|
size: [100, 100],
|
||||||
rotation: 0,
|
rotation: 0,
|
||||||
|
radius: 2,
|
||||||
style: {
|
style: {
|
||||||
fill: "#c6cacb",
|
fill: "#c6cacb",
|
||||||
stroke: "#000",
|
stroke: "#000",
|
||||||
|
|
|
@ -20,7 +20,7 @@ const circle = registerShapeUtils<CircleShape>({
|
||||||
childIndex: 0,
|
childIndex: 0,
|
||||||
point: [0, 0],
|
point: [0, 0],
|
||||||
rotation: 0,
|
rotation: 0,
|
||||||
radius: 20,
|
radius: 1,
|
||||||
style: {
|
style: {
|
||||||
fill: "#c6cacb",
|
fill: "#c6cacb",
|
||||||
stroke: "#000",
|
stroke: "#000",
|
||||||
|
@ -33,6 +33,11 @@ const circle = registerShapeUtils<CircleShape>({
|
||||||
return <circle id={id} cx={radius} cy={radius} r={radius} />
|
return <circle id={id} cx={radius} cy={radius} r={radius} />
|
||||||
},
|
},
|
||||||
|
|
||||||
|
applyStyles(shape, style) {
|
||||||
|
Object.assign(shape.style, style)
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
|
||||||
getBounds(shape) {
|
getBounds(shape) {
|
||||||
if (!this.boundsCache.has(shape)) {
|
if (!this.boundsCache.has(shape)) {
|
||||||
const { radius } = shape
|
const { radius } = shape
|
||||||
|
|
|
@ -32,6 +32,11 @@ const dot = registerShapeUtils<DotShape>({
|
||||||
return <DotCircle id={id} cx={0} cy={0} r={4} />
|
return <DotCircle id={id} cx={0} cy={0} r={4} />
|
||||||
},
|
},
|
||||||
|
|
||||||
|
applyStyles(shape, style) {
|
||||||
|
Object.assign(shape.style, style)
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
|
||||||
getBounds(shape) {
|
getBounds(shape) {
|
||||||
if (!this.boundsCache.has(shape)) {
|
if (!this.boundsCache.has(shape)) {
|
||||||
const bounds = {
|
const bounds = {
|
||||||
|
|
|
@ -24,8 +24,8 @@ const ellipse = registerShapeUtils<EllipseShape>({
|
||||||
parentId: "page0",
|
parentId: "page0",
|
||||||
childIndex: 0,
|
childIndex: 0,
|
||||||
point: [0, 0],
|
point: [0, 0],
|
||||||
radiusX: 20,
|
radiusX: 1,
|
||||||
radiusY: 20,
|
radiusY: 1,
|
||||||
rotation: 0,
|
rotation: 0,
|
||||||
style: {
|
style: {
|
||||||
fill: "#c6cacb",
|
fill: "#c6cacb",
|
||||||
|
@ -41,6 +41,11 @@ const ellipse = registerShapeUtils<EllipseShape>({
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
applyStyles(shape, style) {
|
||||||
|
Object.assign(shape.style, style)
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
|
||||||
getBounds(shape) {
|
getBounds(shape) {
|
||||||
if (!this.boundsCache.has(shape)) {
|
if (!this.boundsCache.has(shape)) {
|
||||||
const { radiusX, radiusY } = shape
|
const { radiusX, radiusY } = shape
|
||||||
|
|
|
@ -7,6 +7,7 @@ import {
|
||||||
Corner,
|
Corner,
|
||||||
Edge,
|
Edge,
|
||||||
ShapeByType,
|
ShapeByType,
|
||||||
|
ShapeStyles,
|
||||||
} from "types"
|
} from "types"
|
||||||
import circle from "./circle"
|
import circle from "./circle"
|
||||||
import dot from "./dot"
|
import dot from "./dot"
|
||||||
|
@ -40,6 +41,12 @@ export interface ShapeUtility<K extends Readonly<Shape>> {
|
||||||
// Create a new shape.
|
// Create a new shape.
|
||||||
create(props: Partial<K>): K
|
create(props: Partial<K>): K
|
||||||
|
|
||||||
|
applyStyles(
|
||||||
|
this: ShapeUtility<K>,
|
||||||
|
shape: K,
|
||||||
|
style: ShapeStyles
|
||||||
|
): ShapeUtility<K>
|
||||||
|
|
||||||
// Set the shape's point.
|
// Set the shape's point.
|
||||||
translateTo(this: ShapeUtility<K>, shape: K, delta: number[]): ShapeUtility<K>
|
translateTo(this: ShapeUtility<K>, shape: K, delta: number[]): ShapeUtility<K>
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,11 @@ const line = registerShapeUtils<LineShape>({
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
applyStyles(shape, style) {
|
||||||
|
Object.assign(shape.style, style)
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
|
||||||
getBounds(shape) {
|
getBounds(shape) {
|
||||||
if (!this.boundsCache.has(shape)) {
|
if (!this.boundsCache.has(shape)) {
|
||||||
const bounds = {
|
const bounds = {
|
||||||
|
|
|
@ -33,6 +33,11 @@ const polyline = registerShapeUtils<PolylineShape>({
|
||||||
return <polyline id={id} points={points.toString()} />
|
return <polyline id={id} points={points.toString()} />
|
||||||
},
|
},
|
||||||
|
|
||||||
|
applyStyles(shape, style) {
|
||||||
|
Object.assign(shape.style, style)
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
|
||||||
getBounds(shape) {
|
getBounds(shape) {
|
||||||
if (!this.boundsCache.has(shape)) {
|
if (!this.boundsCache.has(shape)) {
|
||||||
const bounds = getBoundsFromPoints(shape.points)
|
const bounds = getBoundsFromPoints(shape.points)
|
||||||
|
|
|
@ -41,6 +41,11 @@ const ray = registerShapeUtils<RayShape>({
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
applyStyles(shape, style) {
|
||||||
|
Object.assign(shape.style, style)
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
|
||||||
getRotatedBounds(shape) {
|
getRotatedBounds(shape) {
|
||||||
return this.getBounds(shape)
|
return this.getBounds(shape)
|
||||||
},
|
},
|
||||||
|
|
|
@ -22,6 +22,7 @@ const rectangle = registerShapeUtils<RectangleShape>({
|
||||||
childIndex: 0,
|
childIndex: 0,
|
||||||
point: [0, 0],
|
point: [0, 0],
|
||||||
size: [1, 1],
|
size: [1, 1],
|
||||||
|
radius: 2,
|
||||||
rotation: 0,
|
rotation: 0,
|
||||||
style: {
|
style: {
|
||||||
fill: "#c6cacb",
|
fill: "#c6cacb",
|
||||||
|
@ -31,10 +32,16 @@ const rectangle = registerShapeUtils<RectangleShape>({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
render({ id, size, parentId, childIndex }) {
|
render({ id, size, radius, childIndex }) {
|
||||||
return (
|
return (
|
||||||
<g id={id}>
|
<g id={id}>
|
||||||
<rect id={id} width={size[0]} height={size[1]} />
|
<rect
|
||||||
|
id={id}
|
||||||
|
width={size[0]}
|
||||||
|
height={size[1]}
|
||||||
|
rx={radius}
|
||||||
|
ry={radius}
|
||||||
|
/>
|
||||||
<text
|
<text
|
||||||
y={4}
|
y={4}
|
||||||
x={4}
|
x={4}
|
||||||
|
@ -50,6 +57,11 @@ const rectangle = registerShapeUtils<RectangleShape>({
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
applyStyles(shape, style) {
|
||||||
|
Object.assign(shape.style, style)
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
|
||||||
getBounds(shape) {
|
getBounds(shape) {
|
||||||
if (!this.boundsCache.has(shape)) {
|
if (!this.boundsCache.has(shape)) {
|
||||||
const [width, height] = shape.size
|
const [width, height] = shape.size
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@monaco-editor/react": "^4.1.3",
|
"@monaco-editor/react": "^4.1.3",
|
||||||
|
"@radix-ui/react-dropdown-menu": "^0.0.19",
|
||||||
"@state-designer/react": "^1.7.1",
|
"@state-designer/react": "^1.7.1",
|
||||||
"@stitches/react": "^0.1.9",
|
"@stitches/react": "^0.1.9",
|
||||||
"framer-motion": "^4.1.16",
|
"framer-motion": "^4.1.16",
|
||||||
|
@ -16,15 +17,15 @@
|
||||||
"next": "10.2.0",
|
"next": "10.2.0",
|
||||||
"perfect-freehand": "^0.4.7",
|
"perfect-freehand": "^0.4.7",
|
||||||
"prettier": "^2.3.0",
|
"prettier": "^2.3.0",
|
||||||
|
"react": "17.0.2",
|
||||||
"react-dom": "17.0.2",
|
"react-dom": "17.0.2",
|
||||||
"react-feather": "^2.0.9",
|
"react-feather": "^2.0.9",
|
||||||
"react": "17.0.2",
|
|
||||||
"uuid": "^8.3.2"
|
"uuid": "^8.3.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/next": "^9.0.0",
|
"@types/next": "^9.0.0",
|
||||||
"@types/react-dom": "^17.0.3",
|
|
||||||
"@types/react": "^17.0.5",
|
"@types/react": "^17.0.5",
|
||||||
|
"@types/react-dom": "^17.0.3",
|
||||||
"@types/uuid": "^8.3.0",
|
"@types/uuid": "^8.3.0",
|
||||||
"cypress": "^7.3.0",
|
"cypress": "^7.3.0",
|
||||||
"monaco-editor": "^0.24.0",
|
"monaco-editor": "^0.24.0",
|
||||||
|
|
|
@ -5,6 +5,7 @@ import generate from "./generate"
|
||||||
import direct from "./direct"
|
import direct from "./direct"
|
||||||
import rotate from "./rotate"
|
import rotate from "./rotate"
|
||||||
import move from "./move"
|
import move from "./move"
|
||||||
|
import style from "./style"
|
||||||
import deleteSelected from "./delete-selected"
|
import deleteSelected from "./delete-selected"
|
||||||
|
|
||||||
const commands = {
|
const commands = {
|
||||||
|
@ -15,6 +16,7 @@ const commands = {
|
||||||
direct,
|
direct,
|
||||||
rotate,
|
rotate,
|
||||||
move,
|
move,
|
||||||
|
style,
|
||||||
deleteSelected,
|
deleteSelected,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
import Command from "./command"
|
||||||
|
import history from "../history"
|
||||||
|
import { Data, ShapeStyles } from "types"
|
||||||
|
import { getPage, getSelectedShapes } from "utils/utils"
|
||||||
|
import { getShapeUtils } from "lib/shape-utils"
|
||||||
|
import { current } from "immer"
|
||||||
|
|
||||||
|
export default function styleCommand(data: Data, styles: ShapeStyles) {
|
||||||
|
const { currentPageId } = data
|
||||||
|
const initialShapes = getSelectedShapes(current(data))
|
||||||
|
|
||||||
|
history.execute(
|
||||||
|
data,
|
||||||
|
new Command({
|
||||||
|
name: "changed_style",
|
||||||
|
category: "canvas",
|
||||||
|
manualSelection: true,
|
||||||
|
do(data) {
|
||||||
|
const { shapes } = getPage(data, currentPageId)
|
||||||
|
|
||||||
|
for (const { id } of initialShapes) {
|
||||||
|
const shape = shapes[id]
|
||||||
|
getShapeUtils(shape).applyStyles(shape, styles)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
undo(data) {
|
||||||
|
const { shapes } = getPage(data, currentPageId)
|
||||||
|
|
||||||
|
for (const { id, style } of initialShapes) {
|
||||||
|
const shape = shapes[id]
|
||||||
|
getShapeUtils(shape).applyStyles(shape, style)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
|
@ -15,11 +15,6 @@ export const defaultDocument: Data["document"] = {
|
||||||
childIndex: 3,
|
childIndex: 3,
|
||||||
point: [300, 300],
|
point: [300, 300],
|
||||||
direction: [0.5, 0.5],
|
direction: [0.5, 0.5],
|
||||||
style: {
|
|
||||||
fill: "#AAA",
|
|
||||||
stroke: "#c6cacb",
|
|
||||||
strokeWidth: 1,
|
|
||||||
},
|
|
||||||
}),
|
}),
|
||||||
// shape3: shapeUtils[ShapeType.Dot].create({
|
// shape3: shapeUtils[ShapeType.Dot].create({
|
||||||
// id: "shape3",
|
// id: "shape3",
|
||||||
|
@ -38,11 +33,6 @@ export const defaultDocument: Data["document"] = {
|
||||||
childIndex: 1,
|
childIndex: 1,
|
||||||
point: [100, 600],
|
point: [100, 600],
|
||||||
radius: 50,
|
radius: 50,
|
||||||
style: {
|
|
||||||
fill: "#AAA",
|
|
||||||
stroke: "#c6cacb",
|
|
||||||
strokeWidth: 1,
|
|
||||||
},
|
|
||||||
}),
|
}),
|
||||||
shape5: shapeUtils[ShapeType.Ellipse].create({
|
shape5: shapeUtils[ShapeType.Ellipse].create({
|
||||||
id: "shape5",
|
id: "shape5",
|
||||||
|
@ -51,11 +41,6 @@ export const defaultDocument: Data["document"] = {
|
||||||
point: [400, 600],
|
point: [400, 600],
|
||||||
radiusX: 50,
|
radiusX: 50,
|
||||||
radiusY: 30,
|
radiusY: 30,
|
||||||
style: {
|
|
||||||
fill: "#AAA",
|
|
||||||
stroke: "#c6cacb",
|
|
||||||
strokeWidth: 1,
|
|
||||||
},
|
|
||||||
}),
|
}),
|
||||||
// shape7: shapeUtils[ShapeType.Ellipse].create({
|
// shape7: shapeUtils[ShapeType.Ellipse].create({
|
||||||
// id: "shape7",
|
// id: "shape7",
|
||||||
|
@ -88,18 +73,18 @@ export const defaultDocument: Data["document"] = {
|
||||||
// strokeLinejoin: "round",
|
// strokeLinejoin: "round",
|
||||||
// },
|
// },
|
||||||
// }),
|
// }),
|
||||||
shape1: shapeUtils[ShapeType.Rectangle].create({
|
// shape1: shapeUtils[ShapeType.Rectangle].create({
|
||||||
id: "shape1",
|
// id: "shape1",
|
||||||
name: "Shape 1",
|
// name: "Shape 1",
|
||||||
childIndex: 1,
|
// childIndex: 1,
|
||||||
point: [400, 600],
|
// point: [400, 600],
|
||||||
size: [200, 200],
|
// size: [200, 200],
|
||||||
style: {
|
// style: {
|
||||||
fill: "#AAA",
|
// fill: "#AAA",
|
||||||
stroke: "#c6cacb",
|
// stroke: "#c6cacb",
|
||||||
strokeWidth: 1,
|
// strokeWidth: 1,
|
||||||
},
|
// },
|
||||||
}),
|
// }),
|
||||||
// shape6: shapeUtils[ShapeType.Line].create({
|
// shape6: shapeUtils[ShapeType.Line].create({
|
||||||
// id: "shape6",
|
// id: "shape6",
|
||||||
// name: "Shape 6",
|
// name: "Shape 6",
|
||||||
|
@ -152,3 +137,24 @@ new Polyline({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const colors = {
|
||||||
|
transparent: "transparent",
|
||||||
|
white: "rgba(248, 249, 250, 1.000)",
|
||||||
|
lightGray: "rgba(224, 226, 230, 1.000)",
|
||||||
|
gray: "rgba(172, 181, 189, 1.000)",
|
||||||
|
darkGray: "rgba(52, 58, 64, 1.000)",
|
||||||
|
black: "rgba(0,0,0, 1.000)",
|
||||||
|
lime: "rgba(115, 184, 23, 1.000)",
|
||||||
|
green: "rgba(54, 178, 77, 1.000)",
|
||||||
|
teal: "rgba(9, 167, 120, 1.000)",
|
||||||
|
cyan: "rgba(14, 152, 173, 1.000)",
|
||||||
|
blue: "rgba(28, 126, 214, 1.000)",
|
||||||
|
indigo: "rgba(66, 99, 235, 1.000)",
|
||||||
|
violet: "rgba(112, 72, 232, 1.000)",
|
||||||
|
grape: "rgba(174, 62, 200, 1.000)",
|
||||||
|
pink: "rgba(214, 51, 108, 1.000)",
|
||||||
|
red: "rgba(240, 63, 63, 1.000)",
|
||||||
|
orange: "rgba(247, 103, 6, 1.000)",
|
||||||
|
yellow: "rgba(245, 159, 0, 1.000)",
|
||||||
|
}
|
||||||
|
|
172
state/state.ts
172
state/state.ts
|
@ -1,18 +1,23 @@
|
||||||
import { createSelectorHook, createState } from "@state-designer/react"
|
import { createSelectorHook, createState } from "@state-designer/react"
|
||||||
|
import * as vec from "utils/vec"
|
||||||
|
import inputs from "./inputs"
|
||||||
|
import { colors, defaultDocument } from "./data"
|
||||||
|
import { createShape, getShapeUtils } from "lib/shape-utils"
|
||||||
|
import history from "state/history"
|
||||||
|
import * as Sessions from "./sessions"
|
||||||
|
import commands from "./commands"
|
||||||
|
import { updateFromCode } from "lib/code/generate"
|
||||||
import {
|
import {
|
||||||
clamp,
|
clamp,
|
||||||
getBoundsCenter,
|
|
||||||
getChildren,
|
getChildren,
|
||||||
getCommonBounds,
|
getCommonBounds,
|
||||||
|
getCurrent,
|
||||||
getPage,
|
getPage,
|
||||||
getSelectedBounds,
|
getSelectedBounds,
|
||||||
getSelectedShapes,
|
|
||||||
getShape,
|
getShape,
|
||||||
getSiblings,
|
|
||||||
screenToWorld,
|
screenToWorld,
|
||||||
setZoomCSS,
|
setZoomCSS,
|
||||||
} from "utils/utils"
|
} from "utils/utils"
|
||||||
import * as vec from "utils/vec"
|
|
||||||
import {
|
import {
|
||||||
Data,
|
Data,
|
||||||
PointerInfo,
|
PointerInfo,
|
||||||
|
@ -22,14 +27,8 @@ import {
|
||||||
Edge,
|
Edge,
|
||||||
CodeControl,
|
CodeControl,
|
||||||
MoveType,
|
MoveType,
|
||||||
|
ShapeStyles,
|
||||||
} from "types"
|
} from "types"
|
||||||
import inputs from "./inputs"
|
|
||||||
import { defaultDocument } from "./data"
|
|
||||||
import shapeUtilityMap, { getShapeUtils } from "lib/shape-utils"
|
|
||||||
import history from "state/history"
|
|
||||||
import * as Sessions from "./sessions"
|
|
||||||
import commands from "./commands"
|
|
||||||
import { updateFromCode } from "lib/code/generate"
|
|
||||||
|
|
||||||
const initialData: Data = {
|
const initialData: Data = {
|
||||||
isReadOnly: false,
|
isReadOnly: false,
|
||||||
|
@ -37,6 +36,11 @@ const initialData: Data = {
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
isDarkMode: false,
|
isDarkMode: false,
|
||||||
isCodeOpen: false,
|
isCodeOpen: false,
|
||||||
|
isStyleOpen: false,
|
||||||
|
},
|
||||||
|
currentStyle: {
|
||||||
|
fill: colors.lightGray,
|
||||||
|
stroke: colors.darkGray,
|
||||||
},
|
},
|
||||||
camera: {
|
camera: {
|
||||||
point: [0, 0],
|
point: [0, 0],
|
||||||
|
@ -71,6 +75,8 @@ const state = createState({
|
||||||
SELECTED_POLYLINE_TOOL: { unless: "isReadOnly", to: "polyline" },
|
SELECTED_POLYLINE_TOOL: { unless: "isReadOnly", to: "polyline" },
|
||||||
SELECTED_RECTANGLE_TOOL: { unless: "isReadOnly", to: "rectangle" },
|
SELECTED_RECTANGLE_TOOL: { unless: "isReadOnly", to: "rectangle" },
|
||||||
TOGGLED_CODE_PANEL_OPEN: "toggleCodePanel",
|
TOGGLED_CODE_PANEL_OPEN: "toggleCodePanel",
|
||||||
|
TOGGLED_STYLE_PANEL_OPEN: "toggleStylePanel",
|
||||||
|
CHANGED_STYLE: ["updateStyles", "applyStylesToSelection"],
|
||||||
RESET_CAMERA: "resetCamera",
|
RESET_CAMERA: "resetCamera",
|
||||||
ZOOMED_TO_FIT: "zoomCameraToFit",
|
ZOOMED_TO_FIT: "zoomCameraToFit",
|
||||||
ZOOMED_TO_SELECTION: {
|
ZOOMED_TO_SELECTION: {
|
||||||
|
@ -442,48 +448,23 @@ const state = createState({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
results: {
|
results: {
|
||||||
// Dot
|
newDot() {
|
||||||
newDot(data, payload: PointerInfo) {
|
return ShapeType.Dot
|
||||||
return shapeUtilityMap[ShapeType.Dot].create({
|
|
||||||
point: screenToWorld(payload.point, data),
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
|
newRay() {
|
||||||
// Ray
|
return ShapeType.Ray
|
||||||
newRay(data, payload: PointerInfo) {
|
|
||||||
return shapeUtilityMap[ShapeType.Ray].create({
|
|
||||||
point: screenToWorld(payload.point, data),
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
|
newLine() {
|
||||||
// Line
|
return ShapeType.Line
|
||||||
newLine(data, payload: PointerInfo) {
|
|
||||||
return shapeUtilityMap[ShapeType.Line].create({
|
|
||||||
point: screenToWorld(payload.point, data),
|
|
||||||
direction: [0, 1],
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
|
newCircle() {
|
||||||
newCircle(data, payload: PointerInfo) {
|
return ShapeType.Circle
|
||||||
return shapeUtilityMap[ShapeType.Circle].create({
|
|
||||||
point: screenToWorld(payload.point, data),
|
|
||||||
radius: 1,
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
|
newEllipse() {
|
||||||
newEllipse(data, payload: PointerInfo) {
|
return ShapeType.Ellipse
|
||||||
return shapeUtilityMap[ShapeType.Ellipse].create({
|
|
||||||
point: screenToWorld(payload.point, data),
|
|
||||||
radiusX: 1,
|
|
||||||
radiusY: 1,
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
|
newRectangle() {
|
||||||
newRectangle(data, payload: PointerInfo) {
|
return ShapeType.Rectangle
|
||||||
return shapeUtilityMap[ShapeType.Rectangle].create({
|
|
||||||
point: screenToWorld(payload.point, data),
|
|
||||||
size: [1, 1],
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
conditions: {
|
conditions: {
|
||||||
|
@ -528,7 +509,12 @@ const state = createState({
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
/* --------------------- Shapes --------------------- */
|
/* --------------------- Shapes --------------------- */
|
||||||
createShape(data, payload, shape: Shape) {
|
createShape(data, payload, type: ShapeType) {
|
||||||
|
const shape = createShape(type, {
|
||||||
|
point: screenToWorld(payload.point, data),
|
||||||
|
style: getCurrent(data.currentStyle),
|
||||||
|
})
|
||||||
|
|
||||||
const siblings = getChildren(data, shape.parentId)
|
const siblings = getChildren(data, shape.parentId)
|
||||||
const childIndex = siblings.length
|
const childIndex = siblings.length
|
||||||
? siblings[siblings.length - 1].childIndex + 1
|
? siblings[siblings.length - 1].childIndex + 1
|
||||||
|
@ -710,41 +696,6 @@ const state = createState({
|
||||||
|
|
||||||
document.documentElement.style.setProperty("--camera-zoom", "1")
|
document.documentElement.style.setProperty("--camera-zoom", "1")
|
||||||
},
|
},
|
||||||
zoomCameraToSelection(data) {
|
|
||||||
const { camera } = data
|
|
||||||
|
|
||||||
const bounds = getSelectedBounds(data)
|
|
||||||
|
|
||||||
const zoom =
|
|
||||||
bounds.width < bounds.height
|
|
||||||
? (window.innerWidth - 128) / bounds.width
|
|
||||||
: (window.innerHeight - 128) / bounds.height
|
|
||||||
|
|
||||||
const mx = window.innerWidth - bounds.width * zoom
|
|
||||||
const my = window.innerHeight - bounds.height * zoom
|
|
||||||
|
|
||||||
camera.zoom = zoom
|
|
||||||
|
|
||||||
camera.point = vec.add(
|
|
||||||
[-bounds.minX, -bounds.minY],
|
|
||||||
[mx / 2 / zoom, my / 2 / zoom]
|
|
||||||
)
|
|
||||||
|
|
||||||
setZoomCSS(camera.zoom)
|
|
||||||
},
|
|
||||||
zoomCameraToSelectionActual(data) {
|
|
||||||
const { camera } = data
|
|
||||||
|
|
||||||
const bounds = getSelectedBounds(data)
|
|
||||||
|
|
||||||
const mx = window.innerWidth - bounds.width
|
|
||||||
const my = window.innerHeight - bounds.height
|
|
||||||
|
|
||||||
camera.zoom = 1
|
|
||||||
|
|
||||||
camera.point = vec.add([-bounds.minX, -bounds.minY], [mx / 2, my / 2])
|
|
||||||
setZoomCSS(camera.zoom)
|
|
||||||
},
|
|
||||||
zoomCameraToActual(data) {
|
zoomCameraToActual(data) {
|
||||||
const { camera } = data
|
const { camera } = data
|
||||||
|
|
||||||
|
@ -757,6 +708,37 @@ const state = createState({
|
||||||
|
|
||||||
setZoomCSS(camera.zoom)
|
setZoomCSS(camera.zoom)
|
||||||
},
|
},
|
||||||
|
zoomCameraToSelectionActual(data) {
|
||||||
|
const { camera } = data
|
||||||
|
|
||||||
|
const bounds = getSelectedBounds(data)
|
||||||
|
|
||||||
|
const mx = (window.innerWidth - bounds.width) / 2
|
||||||
|
const my = (window.innerHeight - bounds.height) / 2
|
||||||
|
|
||||||
|
camera.zoom = 1
|
||||||
|
camera.point = vec.add([-bounds.minX, -bounds.minY], [mx, my])
|
||||||
|
|
||||||
|
setZoomCSS(camera.zoom)
|
||||||
|
},
|
||||||
|
zoomCameraToSelection(data) {
|
||||||
|
const { camera } = data
|
||||||
|
|
||||||
|
const bounds = getSelectedBounds(data)
|
||||||
|
|
||||||
|
const zoom =
|
||||||
|
bounds.width > bounds.height
|
||||||
|
? (window.innerWidth - 128) / bounds.width
|
||||||
|
: (window.innerHeight - 128) / bounds.height
|
||||||
|
|
||||||
|
const mx = (window.innerWidth - bounds.width * zoom) / 2 / zoom
|
||||||
|
const my = (window.innerHeight - bounds.height * zoom) / 2 / zoom
|
||||||
|
|
||||||
|
camera.zoom = zoom
|
||||||
|
camera.point = vec.add([-bounds.minX, -bounds.minY], [mx, my])
|
||||||
|
|
||||||
|
setZoomCSS(camera.zoom)
|
||||||
|
},
|
||||||
zoomCameraToFit(data) {
|
zoomCameraToFit(data) {
|
||||||
const { camera } = data
|
const { camera } = data
|
||||||
const page = getPage(data)
|
const page = getPage(data)
|
||||||
|
@ -774,7 +756,7 @@ const state = createState({
|
||||||
)
|
)
|
||||||
|
|
||||||
const zoom =
|
const zoom =
|
||||||
bounds.width < bounds.height
|
bounds.width > bounds.height
|
||||||
? (window.innerWidth - 128) / bounds.width
|
? (window.innerWidth - 128) / bounds.width
|
||||||
: (window.innerHeight - 128) / bounds.height
|
: (window.innerHeight - 128) / bounds.height
|
||||||
|
|
||||||
|
@ -788,12 +770,10 @@ const state = createState({
|
||||||
},
|
},
|
||||||
zoomCamera(data, payload: { delta: number; point: number[] }) {
|
zoomCamera(data, payload: { delta: number; point: number[] }) {
|
||||||
const { camera } = data
|
const { camera } = data
|
||||||
|
const next = camera.zoom - (payload.delta / 100) * camera.zoom
|
||||||
|
|
||||||
const p0 = screenToWorld(payload.point, data)
|
const p0 = screenToWorld(payload.point, data)
|
||||||
camera.zoom = clamp(
|
camera.zoom = clamp(next, 0.1, 3)
|
||||||
camera.zoom - (payload.delta / 100) * camera.zoom,
|
|
||||||
0.1,
|
|
||||||
3
|
|
||||||
)
|
|
||||||
const p1 = screenToWorld(payload.point, data)
|
const p1 = screenToWorld(payload.point, data)
|
||||||
camera.point = vec.add(camera.point, vec.sub(p1, p0))
|
camera.point = vec.add(camera.point, vec.sub(p1, p0))
|
||||||
|
|
||||||
|
@ -832,6 +812,18 @@ const state = createState({
|
||||||
history.redo(data)
|
history.redo(data)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/* --------------------- Styles --------------------- */
|
||||||
|
|
||||||
|
toggleStylePanel(data) {
|
||||||
|
data.settings.isStyleOpen = !data.settings.isStyleOpen
|
||||||
|
},
|
||||||
|
updateStyles(data, payload: Partial<ShapeStyles>) {
|
||||||
|
Object.assign(data.currentStyle, payload)
|
||||||
|
},
|
||||||
|
applyStylesToSelection(data, payload: Partial<ShapeStyles>) {
|
||||||
|
commands.style(data, payload)
|
||||||
|
},
|
||||||
|
|
||||||
/* ---------------------- Code ---------------------- */
|
/* ---------------------- Code ---------------------- */
|
||||||
closeCodePanel(data) {
|
closeCodePanel(data) {
|
||||||
data.settings.isCodeOpen = false
|
data.settings.isCodeOpen = false
|
||||||
|
|
|
@ -14,6 +14,7 @@ const { styled, global, css, theme, getCssString } = createCss({
|
||||||
boundsBg: "rgba(65, 132, 244, 0.100)",
|
boundsBg: "rgba(65, 132, 244, 0.100)",
|
||||||
border: "#aaa",
|
border: "#aaa",
|
||||||
panel: "#fefefe",
|
panel: "#fefefe",
|
||||||
|
hover: "#efefef",
|
||||||
text: "#000",
|
text: "#000",
|
||||||
input: "#f3f3f3",
|
input: "#f3f3f3",
|
||||||
inputBorder: "#ddd",
|
inputBorder: "#ddd",
|
||||||
|
|
7
types.ts
7
types.ts
|
@ -12,7 +12,9 @@ export interface Data {
|
||||||
fontSize: number
|
fontSize: number
|
||||||
isDarkMode: boolean
|
isDarkMode: boolean
|
||||||
isCodeOpen: boolean
|
isCodeOpen: boolean
|
||||||
|
isStyleOpen: boolean
|
||||||
}
|
}
|
||||||
|
currentStyle: ShapeStyles
|
||||||
camera: {
|
camera: {
|
||||||
point: number[]
|
point: number[]
|
||||||
zoom: number
|
zoom: number
|
||||||
|
@ -59,6 +61,8 @@ export enum ShapeType {
|
||||||
// Cubic = "cubic",
|
// Cubic = "cubic",
|
||||||
// Conic = "conic",
|
// Conic = "conic",
|
||||||
|
|
||||||
|
export type ShapeStyles = Partial<React.SVGProps<SVGUseElement>>
|
||||||
|
|
||||||
export interface BaseShape {
|
export interface BaseShape {
|
||||||
id: string
|
id: string
|
||||||
type: ShapeType
|
type: ShapeType
|
||||||
|
@ -68,7 +72,7 @@ export interface BaseShape {
|
||||||
name: string
|
name: string
|
||||||
point: number[]
|
point: number[]
|
||||||
rotation: number
|
rotation: number
|
||||||
style: Partial<React.SVGProps<SVGUseElement>>
|
style: ShapeStyles
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DotShape extends BaseShape {
|
export interface DotShape extends BaseShape {
|
||||||
|
@ -104,6 +108,7 @@ export interface PolylineShape extends BaseShape {
|
||||||
export interface RectangleShape extends BaseShape {
|
export interface RectangleShape extends BaseShape {
|
||||||
type: ShapeType.Rectangle
|
type: ShapeType.Rectangle
|
||||||
size: number[]
|
size: number[]
|
||||||
|
radius: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export type MutableShape =
|
export type MutableShape =
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import Vector from "lib/code/vector"
|
import Vector from "lib/code/vector"
|
||||||
import React from "react"
|
import React from "react"
|
||||||
import { Data, Bounds, Edge, Corner, Shape } from "types"
|
import { Data, Bounds, Edge, Corner, Shape, ShapeStyles } from "types"
|
||||||
import * as vec from "./vec"
|
import * as vec from "./vec"
|
||||||
import _isMobile from "ismobilejs"
|
import _isMobile from "ismobilejs"
|
||||||
import { getShapeUtils } from "lib/shape-utils"
|
import { getShapeUtils } from "lib/shape-utils"
|
||||||
|
@ -1486,3 +1486,9 @@ export function forceIntegerChildIndices(shapes: Shape[]) {
|
||||||
export function setZoomCSS(zoom: number) {
|
export function setZoomCSS(zoom: number) {
|
||||||
document.documentElement.style.setProperty("--camera-zoom", zoom.toString())
|
document.documentElement.style.setProperty("--camera-zoom", zoom.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getCurrent<T extends object>(source: T): T {
|
||||||
|
return Object.fromEntries(
|
||||||
|
Object.entries(source).map(([key, value]) => [key, value])
|
||||||
|
) as T
|
||||||
|
}
|
||||||
|
|
325
yarn.lock
325
yarn.lock
|
@ -879,7 +879,7 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
regenerator-runtime "^0.13.4"
|
regenerator-runtime "^0.13.4"
|
||||||
|
|
||||||
"@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4":
|
"@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":
|
||||||
version "7.14.0"
|
version "7.14.0"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.0.tgz#46794bc20b612c5f75e62dd071e24dfd95f1cbe6"
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.0.tgz#46794bc20b612c5f75e62dd071e24dfd95f1cbe6"
|
||||||
integrity sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==
|
integrity sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==
|
||||||
|
@ -1259,6 +1259,258 @@
|
||||||
resolved "https://registry.yarnpkg.com/@opentelemetry/context-base/-/context-base-0.14.0.tgz#c67fc20a4d891447ca1a855d7d70fa79a3533001"
|
resolved "https://registry.yarnpkg.com/@opentelemetry/context-base/-/context-base-0.14.0.tgz#c67fc20a4d891447ca1a855d7d70fa79a3533001"
|
||||||
integrity sha512-sDOAZcYwynHFTbLo6n8kIbLiVF3a3BLkrmehJUyEbT9F+Smbi47kLGS2gG2g0fjBLR/Lr1InPD7kXL7FaTqEkw==
|
integrity sha512-sDOAZcYwynHFTbLo6n8kIbLiVF3a3BLkrmehJUyEbT9F+Smbi47kLGS2gG2g0fjBLR/Lr1InPD7kXL7FaTqEkw==
|
||||||
|
|
||||||
|
"@radix-ui/popper@0.0.10":
|
||||||
|
version "0.0.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/popper/-/popper-0.0.10.tgz#9f707d9cec8762423f81acaf8e650e40a554cb73"
|
||||||
|
integrity sha512-YFKuPqQPKscreQid7NuB4it3PMzSwGg03vgrud6sVliHkI43QNAOHyrHyMNo015jg6QK5GVDn+7J2W5uygqSGA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
csstype "^3.0.4"
|
||||||
|
|
||||||
|
"@radix-ui/primitive@0.0.5":
|
||||||
|
version "0.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-0.0.5.tgz#8464fb4db04401bde72d36e27e05714080668d40"
|
||||||
|
integrity sha512-VeL6A5LpKYRJhDDj5tCTnzP3zm+FnvybsAkgBHQ4LUPPBnqRdWLoyKpZhlwFze/z22QHINaTIcE9Z/fTcrUR1g==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
|
||||||
|
"@radix-ui/react-arrow@0.0.13":
|
||||||
|
version "0.0.13"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-0.0.13.tgz#06b5a17f33bbc1af1c88d2827f25f37be95daa38"
|
||||||
|
integrity sha512-BHBAULgQYmj36BrJ+1AGhC5p4QjJaE+szJgJ1a1EYOM3G6QOeIQKYvIm8TPEdKAiJhAivK+jZFccsE4Blzqc9g==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/react-polymorphic" "0.0.11"
|
||||||
|
"@radix-ui/react-primitive" "0.0.13"
|
||||||
|
|
||||||
|
"@radix-ui/react-collection@0.0.12":
|
||||||
|
version "0.0.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-0.0.12.tgz#5cd09312cdec34fdbbe1d31affaba69eb768e342"
|
||||||
|
integrity sha512-jUP99/wCHpXm7ytbmpcjhhxFHBsr2lptEzKO8DUkD2CrJBS4Q3XHMKBDOvNQQzIqJhsz0A5JP6Fo0Vgd8Ld3FQ==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/react-compose-refs" "0.0.5"
|
||||||
|
"@radix-ui/react-slot" "0.0.10"
|
||||||
|
|
||||||
|
"@radix-ui/react-compose-refs@0.0.5":
|
||||||
|
version "0.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-0.0.5.tgz#0f71f0de1dec341f30cebd420b6bc3d12a3037dd"
|
||||||
|
integrity sha512-O9mH9X/2EwuAEEoZXrU4alcrRbAhhZHGpIJ5bOH6rmRcokhaoWRBY1tOEe2lgHdb/bkKrY+viLi4Zq8Ju6/09Q==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
|
||||||
|
"@radix-ui/react-context@0.0.5":
|
||||||
|
version "0.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-0.0.5.tgz#7c15f46795d7765dabfaf6f9c53791ad28c521c2"
|
||||||
|
integrity sha512-bwrzAc0qc2EPepSTLBT4+93uCiI9wP78VSmPg2K+k71O/vpx7dPs0VqrewwCBNCHT54NIwaRr2hEsm2uqYi02A==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
|
||||||
|
"@radix-ui/react-dismissable-layer@0.0.13":
|
||||||
|
version "0.0.13"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-0.0.13.tgz#7c4be6170a14d8a66c48680a8a8c987bc29bcf05"
|
||||||
|
integrity sha512-g0zhxdZzCJhVeRumaU8ODptRFhYorSRPsLwD30sz9slYaW0yg6lHvMQicRNtgFX0WnsbmrUVY6NMrwWpSHJXbg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/react-use-body-pointer-events" "0.0.6"
|
||||||
|
"@radix-ui/react-use-callback-ref" "0.0.5"
|
||||||
|
"@radix-ui/react-use-escape-keydown" "0.0.6"
|
||||||
|
|
||||||
|
"@radix-ui/react-dropdown-menu@^0.0.19":
|
||||||
|
version "0.0.19"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-0.0.19.tgz#fbc3106bcda65d3060b280f4af3a9c45324ab474"
|
||||||
|
integrity sha512-7UhT6PIXl9fr8Ai9DkXMtxPNQFh8emrklgY5jcad9NHKWAztgfL6Fm+Ns0GEYUkd5OpJLEaIj/EUkwFM73SrGw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/primitive" "0.0.5"
|
||||||
|
"@radix-ui/react-compose-refs" "0.0.5"
|
||||||
|
"@radix-ui/react-context" "0.0.5"
|
||||||
|
"@radix-ui/react-id" "0.0.6"
|
||||||
|
"@radix-ui/react-menu" "0.0.18"
|
||||||
|
"@radix-ui/react-polymorphic" "0.0.11"
|
||||||
|
"@radix-ui/react-primitive" "0.0.13"
|
||||||
|
"@radix-ui/react-use-controllable-state" "0.0.6"
|
||||||
|
|
||||||
|
"@radix-ui/react-focus-guards@0.0.7":
|
||||||
|
version "0.0.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-0.0.7.tgz#285ed081c877587acd4ee7e6d8260bdf9044e922"
|
||||||
|
integrity sha512-enAsmrUunptHVzPLTuZqwTP/X3WFBnyJ/jP9W+0g+bRvI3o7V1kxNc+T2Rp1eRTFBW+lUNnt08qkugPytyTRog==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
|
||||||
|
"@radix-ui/react-focus-scope@0.0.13":
|
||||||
|
version "0.0.13"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-0.0.13.tgz#06dd6781d457b272601d4c087ac1240907824443"
|
||||||
|
integrity sha512-PelAuc+7HSGruBraSzuHogwaKqCvmO288ecIm3cCAkrJqPQ7hoKSd/LfLfoa/EvjqK9azmm7NQ6LSPoteQvOGQ==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/react-use-callback-ref" "0.0.5"
|
||||||
|
|
||||||
|
"@radix-ui/react-id@0.0.6":
|
||||||
|
version "0.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-0.0.6.tgz#c4b27d11861805e91ac296e7758ab47e3947b65c"
|
||||||
|
integrity sha512-PzmraF34fYggsYvTIZVJ5S68WMp3aKUN3HkSmGnz4zn9zpRjkAbbg7Xn3ueQI3FQsLWKgyUfnpsmWFDndpcqYg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
|
||||||
|
"@radix-ui/react-menu@0.0.18":
|
||||||
|
version "0.0.18"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-menu/-/react-menu-0.0.18.tgz#b36f7657eb6757c623ffc688c48a4781ffd82351"
|
||||||
|
integrity sha512-js5hFzoxNOnHV8g7RPoPl/GncUCW2aCOuNt9Qh6WznRmxmsETPUWZZe4kADJnZmYbIxG07EEl0iv3E1rmsqNMw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/primitive" "0.0.5"
|
||||||
|
"@radix-ui/react-collection" "0.0.12"
|
||||||
|
"@radix-ui/react-compose-refs" "0.0.5"
|
||||||
|
"@radix-ui/react-context" "0.0.5"
|
||||||
|
"@radix-ui/react-dismissable-layer" "0.0.13"
|
||||||
|
"@radix-ui/react-focus-guards" "0.0.7"
|
||||||
|
"@radix-ui/react-focus-scope" "0.0.13"
|
||||||
|
"@radix-ui/react-polymorphic" "0.0.11"
|
||||||
|
"@radix-ui/react-popper" "0.0.16"
|
||||||
|
"@radix-ui/react-portal" "0.0.13"
|
||||||
|
"@radix-ui/react-presence" "0.0.14"
|
||||||
|
"@radix-ui/react-primitive" "0.0.13"
|
||||||
|
"@radix-ui/react-roving-focus" "0.0.13"
|
||||||
|
"@radix-ui/react-slot" "0.0.10"
|
||||||
|
"@radix-ui/react-use-callback-ref" "0.0.5"
|
||||||
|
aria-hidden "^1.1.1"
|
||||||
|
react-remove-scroll "^2.4.0"
|
||||||
|
|
||||||
|
"@radix-ui/react-polymorphic@0.0.11":
|
||||||
|
version "0.0.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-polymorphic/-/react-polymorphic-0.0.11.tgz#23f26b14e67a0e57cd981c37618d603b952af80d"
|
||||||
|
integrity sha512-CztM4962esOx3i1ls6GuY9RBYIY2Df1Bmp5emHRTxZi8owyCZwZYPctYaDuMO0qIGikPiKD8HBion/m7VWUyEA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
|
||||||
|
"@radix-ui/react-popper@0.0.16":
|
||||||
|
version "0.0.16"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-0.0.16.tgz#62cccb7d920dc89e076bbdc3421db8c84078f428"
|
||||||
|
integrity sha512-njciQ/eIKaDF9h+27Pwi1H6NliQbzTgaHOsT0w/Lxx4vfMe8zcHtiEigYVGErNR4zAYlbW72KzLjtngtNnaorg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/popper" "0.0.10"
|
||||||
|
"@radix-ui/react-arrow" "0.0.13"
|
||||||
|
"@radix-ui/react-compose-refs" "0.0.5"
|
||||||
|
"@radix-ui/react-context" "0.0.5"
|
||||||
|
"@radix-ui/react-polymorphic" "0.0.11"
|
||||||
|
"@radix-ui/react-primitive" "0.0.13"
|
||||||
|
"@radix-ui/react-use-rect" "0.0.7"
|
||||||
|
"@radix-ui/react-use-size" "0.0.6"
|
||||||
|
"@radix-ui/rect" "0.0.5"
|
||||||
|
|
||||||
|
"@radix-ui/react-portal@0.0.13":
|
||||||
|
version "0.0.13"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-0.0.13.tgz#8e60e9ee9b1594f98ee4a8f24a9851ef7ef2ad31"
|
||||||
|
integrity sha512-Mw5hrxds2T9HTGwdDbvlKGvTUfcuKhPtqxLnizOrM685e80j+pfjAAfMSXSyfmra9KFQvk3XxmUP0d4U6+kzMg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/react-polymorphic" "0.0.11"
|
||||||
|
"@radix-ui/react-primitive" "0.0.13"
|
||||||
|
"@radix-ui/react-use-layout-effect" "0.0.5"
|
||||||
|
|
||||||
|
"@radix-ui/react-presence@0.0.14":
|
||||||
|
version "0.0.14"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-0.0.14.tgz#6a86058bbbf46234dd8840dacd620b3ac5797025"
|
||||||
|
integrity sha512-ufof9B76DHXV0sC8H7Lswh2AepdJFG8qEtF32JWrbA9N1bl2Jnf9px76KsagyC0MA8crGEZO5A96wizGuSgGWQ==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/react-compose-refs" "0.0.5"
|
||||||
|
|
||||||
|
"@radix-ui/react-primitive@0.0.13":
|
||||||
|
version "0.0.13"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-0.0.13.tgz#79c606c3e7da9c377b77a7b3f4ec879b45de47a2"
|
||||||
|
integrity sha512-6xxWzw67t7ZuN9Ikn9NNQdb/HSF7dNHPN3kPcgjiVgTEZa3tKk1xjSxGjjQztE61g9GrnTLpu7mBjmEuZDI/lA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/react-polymorphic" "0.0.11"
|
||||||
|
|
||||||
|
"@radix-ui/react-roving-focus@0.0.13":
|
||||||
|
version "0.0.13"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-0.0.13.tgz#c72f503832577979c4caa9efcfd59140730c2f80"
|
||||||
|
integrity sha512-jTx3TBMYEdj9SFzRDryO62M9ZK28pYvKKxj/mxWMpMbIjF4q6L+yJmDxtv6glHgCRkwBEyulFVGCjjDg+qxYRA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/primitive" "0.0.5"
|
||||||
|
"@radix-ui/react-collection" "0.0.12"
|
||||||
|
"@radix-ui/react-compose-refs" "0.0.5"
|
||||||
|
"@radix-ui/react-context" "0.0.5"
|
||||||
|
"@radix-ui/react-id" "0.0.6"
|
||||||
|
"@radix-ui/react-polymorphic" "0.0.11"
|
||||||
|
"@radix-ui/react-primitive" "0.0.13"
|
||||||
|
"@radix-ui/react-use-callback-ref" "0.0.5"
|
||||||
|
"@radix-ui/react-use-controllable-state" "0.0.6"
|
||||||
|
|
||||||
|
"@radix-ui/react-slot@0.0.10":
|
||||||
|
version "0.0.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-0.0.10.tgz#27a17cad7064872117aeb68113fa934bc5d34c37"
|
||||||
|
integrity sha512-p0jJj6lTz1RV2imavnclk8Gda002ZSDR4/zPJ4EQBhspGnx7Y8l6G59c8lxJrT7c7F46F2eRNjpTTjFqqir6EQ==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/primitive" "0.0.5"
|
||||||
|
"@radix-ui/react-compose-refs" "0.0.5"
|
||||||
|
|
||||||
|
"@radix-ui/react-use-body-pointer-events@0.0.6":
|
||||||
|
version "0.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-body-pointer-events/-/react-use-body-pointer-events-0.0.6.tgz#30b21301880417e7dbb345871ff5a83f2abe0d8d"
|
||||||
|
integrity sha512-ouYb7u1+K9TsiEcNs3HceNUBUgB2PV41EyD5O6y6ZPMxl1lW/QAy5dfyfJMRyaRWQ6kxwmGoKlCSb4uPTruzuQ==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/react-use-layout-effect" "0.0.5"
|
||||||
|
|
||||||
|
"@radix-ui/react-use-callback-ref@0.0.5":
|
||||||
|
version "0.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-0.0.5.tgz#fa8db050229cda573dfeeae213d74ef06f6130db"
|
||||||
|
integrity sha512-z1AI221vmq9f3vsDyrCsGLCatKagbM1YeCGdRMhMsUBzFFCaJ+Axyoe/ndVqW8wwsraGWr1zYVAhIEdlC0GvPg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
|
||||||
|
"@radix-ui/react-use-controllable-state@0.0.6":
|
||||||
|
version "0.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-0.0.6.tgz#c4b16bc911a25889333388a684a04df937e5fec7"
|
||||||
|
integrity sha512-fBk4hUSKc4N7X/NAaifWYfKKfNuOB9xvj0MBQQYS5oOTNRgg4y8/Ax3jZ0adsplXDm7ix75sxqWm0nrvUoAjcw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/react-use-callback-ref" "0.0.5"
|
||||||
|
|
||||||
|
"@radix-ui/react-use-escape-keydown@0.0.6":
|
||||||
|
version "0.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-0.0.6.tgz#1ad1c81b99961b7dbe376ef54151ebc8bef627a0"
|
||||||
|
integrity sha512-MJpVj21BYwWllmp2xbXPqpKPssJ1WWrZi+Qx7PY5hVcBhQr5Jo6yKwIX677pH5Yql95ENTTT5LW3q+LVFYIISw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/react-use-callback-ref" "0.0.5"
|
||||||
|
|
||||||
|
"@radix-ui/react-use-layout-effect@0.0.5":
|
||||||
|
version "0.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-0.0.5.tgz#cbbd059090edc765749da00d9f562a9abd43cbac"
|
||||||
|
integrity sha512-bNPW2JNOr/p2hXr0hfKKqrEy5deNSRF17sw3l9Z7qlEnvIbBtQ7iwY/wrxIz5P7XFyYGoXodIUDH5G8PEucE3A==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
|
||||||
|
"@radix-ui/react-use-rect@0.0.7":
|
||||||
|
version "0.0.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-0.0.7.tgz#e3a55fa7183ef436042198787bf38f8c9befcc14"
|
||||||
|
integrity sha512-OmaeFTgyiGNAchaxzDu+kFLz4Ly8RUcT5nwfoz4Nddd86I8Zdq93iNFnOpVLoVYqBnFEmvR6zexHXNFATrMbbQ==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/rect" "0.0.5"
|
||||||
|
|
||||||
|
"@radix-ui/react-use-size@0.0.6":
|
||||||
|
version "0.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-0.0.6.tgz#998eaf6e8871b868f81f3b7faac06c3e896c37a0"
|
||||||
|
integrity sha512-kP4RIb2I5oHQzwzXJ21Hu8htNqf+sdaRzywxQpbj+hmqeUhpvIkhoq+ShNWV9wE/3c1T7gPnka8/nKYsKaKdCg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
|
||||||
|
"@radix-ui/rect@0.0.5":
|
||||||
|
version "0.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-0.0.5.tgz#6000d8d800288114af4bbc5863e6b58755d7d978"
|
||||||
|
integrity sha512-gXw171KbjyttA7K1DRIvPguLmKsg8raitB67MIcsdZwcquy+a1O2w3xY21NIKEqGhJwqJkECPUmMJDXgMNYuAg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
|
||||||
"@rollup/plugin-babel@^5.1.0":
|
"@rollup/plugin-babel@^5.1.0":
|
||||||
version "5.3.0"
|
version "5.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-5.3.0.tgz#9cb1c5146ddd6a4968ad96f209c50c62f92f9879"
|
resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-5.3.0.tgz#9cb1c5146ddd6a4968ad96f209c50c62f92f9879"
|
||||||
|
@ -1731,6 +1983,13 @@ argparse@^1.0.7:
|
||||||
dependencies:
|
dependencies:
|
||||||
sprintf-js "~1.0.2"
|
sprintf-js "~1.0.2"
|
||||||
|
|
||||||
|
aria-hidden@^1.1.1:
|
||||||
|
version "1.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.1.3.tgz#bb48de18dc84787a3c6eee113709c473c64ec254"
|
||||||
|
integrity sha512-RhVWFtKH5BiGMycI72q2RAFMLQi8JP9bLuQXgR5a8Znp7P5KOIADSJeyfI8PCVxLEp067B2HbP5JIiI/PXIZeA==
|
||||||
|
dependencies:
|
||||||
|
tslib "^1.0.0"
|
||||||
|
|
||||||
aria-query@^4.2.2:
|
aria-query@^4.2.2:
|
||||||
version "4.2.2"
|
version "4.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b"
|
resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b"
|
||||||
|
@ -2800,7 +3059,7 @@ cssstyle@^2.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
cssom "~0.3.6"
|
cssom "~0.3.6"
|
||||||
|
|
||||||
csstype@^3.0.2:
|
csstype@^3.0.2, csstype@^3.0.4:
|
||||||
version "3.0.8"
|
version "3.0.8"
|
||||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.8.tgz#d2266a792729fb227cd216fb572f43728e1ad340"
|
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.8.tgz#d2266a792729fb227cd216fb572f43728e1ad340"
|
||||||
integrity sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==
|
integrity sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==
|
||||||
|
@ -2993,6 +3252,11 @@ detect-newline@^3.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651"
|
resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651"
|
||||||
integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==
|
integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==
|
||||||
|
|
||||||
|
detect-node-es@^1.1.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493"
|
||||||
|
integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==
|
||||||
|
|
||||||
diff-sequences@^25.2.6:
|
diff-sequences@^25.2.6:
|
||||||
version "25.2.6"
|
version "25.2.6"
|
||||||
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-25.2.6.tgz#5f467c00edd35352b7bca46d7927d60e687a76dd"
|
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-25.2.6.tgz#5f467c00edd35352b7bca46d7927d60e687a76dd"
|
||||||
|
@ -3818,6 +4082,11 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1:
|
||||||
has "^1.0.3"
|
has "^1.0.3"
|
||||||
has-symbols "^1.0.1"
|
has-symbols "^1.0.1"
|
||||||
|
|
||||||
|
get-nonce@^1.0.0:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3"
|
||||||
|
integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==
|
||||||
|
|
||||||
get-orientation@1.1.2:
|
get-orientation@1.1.2:
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/get-orientation/-/get-orientation-1.1.2.tgz#20507928951814f8a91ded0a0e67b29dfab98947"
|
resolved "https://registry.yarnpkg.com/get-orientation/-/get-orientation-1.1.2.tgz#20507928951814f8a91ded0a0e67b29dfab98947"
|
||||||
|
@ -4213,6 +4482,13 @@ interpret@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e"
|
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e"
|
||||||
integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==
|
integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==
|
||||||
|
|
||||||
|
invariant@^2.2.4:
|
||||||
|
version "2.2.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
|
||||||
|
integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==
|
||||||
|
dependencies:
|
||||||
|
loose-envify "^1.0.0"
|
||||||
|
|
||||||
ip-regex@^2.1.0:
|
ip-regex@^2.1.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9"
|
resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9"
|
||||||
|
@ -5349,7 +5625,7 @@ lolex@^5.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
"@sinonjs/commons" "^1.7.0"
|
"@sinonjs/commons" "^1.7.0"
|
||||||
|
|
||||||
loose-envify@^1.1.0, loose-envify@^1.4.0:
|
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
||||||
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
|
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
|
||||||
|
@ -6388,6 +6664,34 @@ react-refresh@0.8.3:
|
||||||
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f"
|
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f"
|
||||||
integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==
|
integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==
|
||||||
|
|
||||||
|
react-remove-scroll-bar@^2.1.0:
|
||||||
|
version "2.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.2.0.tgz#d4d545a7df024f75d67e151499a6ab5ac97c8cdd"
|
||||||
|
integrity sha512-UU9ZBP1wdMR8qoUs7owiVcpaPwsQxUDC2lypP6mmixaGlARZa7ZIBx1jcuObLdhMOvCsnZcvetOho0wzPa9PYg==
|
||||||
|
dependencies:
|
||||||
|
react-style-singleton "^2.1.0"
|
||||||
|
tslib "^1.0.0"
|
||||||
|
|
||||||
|
react-remove-scroll@^2.4.0:
|
||||||
|
version "2.4.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.4.2.tgz#5b7e3eb8c3389d3636234716d2feb618729fc4d9"
|
||||||
|
integrity sha512-mMSIZYQF3jS2uRJXeFDRaVGA+BGs/hIryV64YUKsHFtpgwZloOUcdu0oW8K6OU8uLHt/kM5d0lUZbdpIVwgXtQ==
|
||||||
|
dependencies:
|
||||||
|
react-remove-scroll-bar "^2.1.0"
|
||||||
|
react-style-singleton "^2.1.0"
|
||||||
|
tslib "^1.0.0"
|
||||||
|
use-callback-ref "^1.2.3"
|
||||||
|
use-sidecar "^1.0.1"
|
||||||
|
|
||||||
|
react-style-singleton@^2.1.0:
|
||||||
|
version "2.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.1.1.tgz#ce7f90b67618be2b6b94902a30aaea152ce52e66"
|
||||||
|
integrity sha512-jNRp07Jza6CBqdRKNgGhT3u9umWvils1xsuMOjZlghBDH2MU0PL2WZor4PGYjXpnRCa9DQSlHMs/xnABWOwYbA==
|
||||||
|
dependencies:
|
||||||
|
get-nonce "^1.0.0"
|
||||||
|
invariant "^2.2.4"
|
||||||
|
tslib "^1.0.0"
|
||||||
|
|
||||||
react@17.0.2:
|
react@17.0.2:
|
||||||
version "17.0.2"
|
version "17.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
|
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
|
||||||
|
@ -7696,7 +8000,7 @@ tslib@2.0.1:
|
||||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.1.tgz#410eb0d113e5b6356490eec749603725b021b43e"
|
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.1.tgz#410eb0d113e5b6356490eec749603725b021b43e"
|
||||||
integrity sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==
|
integrity sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==
|
||||||
|
|
||||||
tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
|
tslib@^1.0.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
|
||||||
version "1.14.1"
|
version "1.14.1"
|
||||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
|
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
|
||||||
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
||||||
|
@ -7880,6 +8184,19 @@ url@^0.11.0:
|
||||||
punycode "1.3.2"
|
punycode "1.3.2"
|
||||||
querystring "0.2.0"
|
querystring "0.2.0"
|
||||||
|
|
||||||
|
use-callback-ref@^1.2.3:
|
||||||
|
version "1.2.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.2.5.tgz#6115ed242cfbaed5915499c0a9842ca2912f38a5"
|
||||||
|
integrity sha512-gN3vgMISAgacF7sqsLPByqoePooY3n2emTH59Ur5d/M8eg4WTWu1xp8i8DHjohftIyEx0S08RiYxbffr4j8Peg==
|
||||||
|
|
||||||
|
use-sidecar@^1.0.1:
|
||||||
|
version "1.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.0.5.tgz#ffff2a17c1df42e348624b699ba6e5c220527f2b"
|
||||||
|
integrity sha512-k9jnrjYNwN6xYLj1iaGhonDghfvmeTmYjAiGvOr7clwKfPjMXJf4/HOr7oT5tJwYafgp2tG2l3eZEOfoELiMcA==
|
||||||
|
dependencies:
|
||||||
|
detect-node-es "^1.1.0"
|
||||||
|
tslib "^1.9.3"
|
||||||
|
|
||||||
use-subscription@1.5.1:
|
use-subscription@1.5.1:
|
||||||
version "1.5.1"
|
version "1.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/use-subscription/-/use-subscription-1.5.1.tgz#73501107f02fad84c6dd57965beb0b75c68c42d1"
|
resolved "https://registry.yarnpkg.com/use-subscription/-/use-subscription-1.5.1.tgz#73501107f02fad84c6dd57965beb0b75c68c42d1"
|
||||||
|
|
Ładowanie…
Reference in New Issue