- Run record
- loading
Loading this Run…
Loading the Revisions of this Run…
A published source file of Revision 0 of Canvely — Spring Menu 1.0.0, shown as text in the browser.
Source is browser-viewable only. There is no download or archive endpoint, and no additional license is granted beyond inspection and research.
import type { ReactNode } from "react";
import type { LayerType } from "./model";
function Svg({ children, size = 16 }: { children: ReactNode; size?: number }) {
return (
<svg
width={size}
height={size}
viewBox="0 0 16 16"
fill="none"
stroke="currentColor"
strokeWidth={1.4}
strokeLinecap="round"
strokeLinejoin="round"
aria-hidden="true"
focusable="false"
>
{children}
</svg>
);
}
export const Icon = {
move: () => (
<Svg>
<path d="M3.5 2.5 12 7.2l-3.7 1.1L6.6 12z" fill="currentColor" stroke="currentColor" strokeWidth={1.1} />
</Svg>
),
rect: () => (
<Svg>
<rect x="2.5" y="3.5" width="11" height="9" rx="1.2" />
</Svg>
),
ellipse: () => (
<Svg>
<ellipse cx="8" cy="8" rx="5.6" ry="5.1" />
</Svg>
),
text: () => (
<Svg>
<path d="M3 4V2.8h10V4M8 2.8v10.4M6 13.2h4" />
</Svg>
),
frame: () => (
<Svg>
<path d="M5 1.8v12.4M11 1.8v12.4M1.8 5h12.4M1.8 11h12.4" />
</Svg>
),
group: () => (
<Svg>
<rect x="2.5" y="2.5" width="11" height="11" rx="1.5" strokeDasharray="2.2 1.8" />
</Svg>
),
undo: () => (
<Svg>
<path d="M5.5 3 2.5 6l3 3" />
<path d="M2.8 6h6.7a3.8 3.8 0 0 1 0 7.5H6.5" />
</Svg>
),
redo: () => (
<Svg>
<path d="m10.5 3 3 3-3 3" />
<path d="M13.2 6H6.5a3.8 3.8 0 0 0 0 7.5h3" />
</Svg>
),
zoomIn: () => (
<Svg>
<path d="M8 3.5v9M3.5 8h9" />
</Svg>
),
zoomOut: () => (
<Svg>
<path d="M3.5 8h9" />
</Svg>
),
fit: () => (
<Svg>
<path d="M2.5 5.5v-3h3M10.5 2.5h3v3M13.5 10.5v3h-3M5.5 13.5h-3v-3" />
<rect x="5.5" y="5.5" width="5" height="5" rx="0.8" />
</Svg>
),
duplicate: () => (
<Svg>
<rect x="5.5" y="5.5" width="8" height="8" rx="1.3" />
<path d="M10.5 3.5v-.3a.9.9 0 0 0-.9-.9H3.4a.9.9 0 0 0-.9.9v6.2c0 .5.4.9.9.9h.3" />
</Svg>
),
trash: () => (
<Svg>
<path d="M2.8 4.3h10.4M6.3 4.3V2.8h3.4v1.5M4.2 4.3l.6 8.9h6.4l.6-8.9M6.7 6.8v4M9.3 6.8v4" />
</Svg>
),
groupAction: () => (
<Svg>
<rect x="1.8" y="1.8" width="12.4" height="12.4" rx="1.6" strokeDasharray="2 1.7" />
<rect x="4.3" y="4.3" width="4" height="4" rx="0.6" />
<circle cx="10.2" cy="10.2" r="2" />
</Svg>
),
ungroupAction: () => (
<Svg>
<rect x="2" y="2" width="5.2" height="5.2" rx="0.8" />
<circle cx="11.2" cy="11.2" r="2.6" />
<path d="M9.8 2.5h3.7v3.7M2.5 9.8v3.7h3.7" strokeDasharray="1.6 1.4" />
</Svg>
),
forward: () => (
<Svg>
<rect x="5" y="2.5" width="8.5" height="7" rx="1" fill="currentColor" fillOpacity="0.18" />
<path d="M2.5 6.5v6a1 1 0 0 0 1 1h6" />
<path d="M9.3 4.6v3M7.8 6.1l1.5-1.5 1.5 1.5" />
</Svg>
),
backward: () => (
<Svg>
<rect x="5" y="2.5" width="8.5" height="7" rx="1" />
<path d="M2.5 6.5v6a1 1 0 0 0 1 1h6" />
<path d="M9.3 4.6v3M7.8 6.1l1.5 1.5 1.5-1.5" />
</Svg>
),
eye: () => (
<Svg>
<path d="M1.6 8s2.3-4.3 6.4-4.3S14.4 8 14.4 8s-2.3 4.3-6.4 4.3S1.6 8 1.6 8z" />
<circle cx="8" cy="8" r="1.9" />
</Svg>
),
eyeOff: () => (
<Svg>
<path d="M2.5 2.5l11 11M6.3 4a6.7 6.7 0 0 1 1.7-.3c4.1 0 6.4 4.3 6.4 4.3a11 11 0 0 1-1.6 2.1M10.4 11.8a6.3 6.3 0 0 1-2.4.5C3.9 12.3 1.6 8 1.6 8a11.2 11.2 0 0 1 2.6-3" />
</Svg>
),
lock: () => (
<Svg>
<rect x="3.3" y="7" width="9.4" height="6.6" rx="1.3" />
<path d="M5.3 7V5.2a2.7 2.7 0 0 1 5.4 0V7" />
</Svg>
),
unlock: () => (
<Svg>
<rect x="3.3" y="7" width="9.4" height="6.6" rx="1.3" />
<path d="M5.3 7V5.2a2.7 2.7 0 0 1 5.2-1" />
</Svg>
),
chevron: () => (
<Svg size={12}>
<path d="m6 4 4 4-4 4" />
</Svg>
),
reset: () => (
<Svg>
<path d="M2.8 3.3v3.2H6" />
<path d="M3.1 6.4A5.3 5.3 0 1 1 3.4 10" />
</Svg>
),
layers: () => (
<Svg>
<path d="M8 2.2 14 5.4 8 8.6 2 5.4z" />
<path d="m2 8.2 6 3.2 6-3.2M2 11 8 14.2 14 11" />
</Svg>
),
rotate: () => (
<Svg size={12}>
<path d="M12.5 8a4.5 4.5 0 1 1-1.3-3.2" />
<path d="M12 2.3v2.9H9.1" />
</Svg>
),
radius: () => (
<Svg size={12}>
<path d="M3 13V8a5 5 0 0 1 5-5h5" />
</Svg>
),
opacity: () => (
<Svg size={12}>
<circle cx="8" cy="8" r="5.5" />
<path d="M8 2.5a5.5 5.5 0 0 1 0 11z" fill="currentColor" />
</Svg>
),
sliders: () => (
<Svg>
<path d="M2.5 4.5h11M2.5 11.5h11" />
<circle cx="6" cy="4.5" r="1.7" fill="var(--panel)" />
<circle cx="10.5" cy="11.5" r="1.7" fill="var(--panel)" />
</Svg>
),
};
export function TypeIcon({ type }: { type: LayerType }) {
switch (type) {
case "frame":
return <Icon.frame />;
case "group":
return <Icon.group />;
case "rect":
return <Icon.rect />;
case "ellipse":
return <Icon.ellipse />;
case "text":
return <Icon.text />;
}
}
/** The Canvely mark: a canvas tile whose corner carries a selection handle. */
export function CanvelyMark({ size = 22 }: { size?: number }) {
return (
<svg width={size} height={size} viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<rect x="1" y="1" width="22" height="22" rx="6" fill="var(--ink)" />
<path d="M16.6 8.1A6 6 0 1 0 16.6 15.9" fill="none" stroke="#fff" strokeWidth="2.6" strokeLinecap="round" />
<rect x="14.6" y="13.9" width="4.4" height="4.4" rx="0.9" fill="var(--accent-bright)" stroke="var(--ink)" strokeWidth="1.2" />
</svg>
);
}