Shape Path Editor
ridiculous/shape-path-editorFreeComponent
Ridiculously typed editor for the CSS shape() function (clip-path / offset-path). The strict tier dispatches each command on its name (move/line/curve/arc/…), checking arity, direction, and every coordinate. Ships the registry's only Bézier-control-handle canvas with a live preview.
Install it
npx shadcn@latest add http://ridiculous.turtlesocks.dev/r/shape-path-editor.jsonSource
1"use client"23import { useEffect, useRef, useState } from "react"4import { Button } from "@/components/ui/button"5import {6 Popover,7 PopoverContent,8 PopoverTrigger,9} from "@/components/ui/popover"10import { cn } from "@/lib/utils"11import { CommandRow } from "./command-row"12import { ShapeCanvas } from "./shape-canvas"13import {14 defaultShape,15 formatShape,16 parseShape,17} from "./shape-path-editor.helpers"18import type {19 ShapeCommand,20 ShapeString,21 ShapeValue,22} from "./shape-path-editor.types"23import { ShapePreview } from "./shape-preview"2425// Re-export the public sub-components + their prop types so consumers (and the26// barrel) can import them from `./shape-path-editor`.27export type { CommandRowProps } from "./command-row"28export { CommandRow } from "./command-row"29export type { MiniSelectProps } from "./mini-select"30export { MiniSelect } from "./mini-select"31export type { ShapeCanvasProps } from "./shape-canvas"32export { ShapeCanvas } from "./shape-canvas"33export type { ShapePreviewMode, ShapePreviewProps } from "./shape-preview"34export { ShapePreview } from "./shape-preview"3536// ---------------------------------------------------------------------------37// Shared props38// ---------------------------------------------------------------------------3940export type ShapePathEditorMode = "clip-path" | "offset-path"4142export interface ShapePathEditorPanelProps {43 value: ShapeString | (string & {})44 onChange: (value: ShapeString) => void45 /**46 * Which CSS property the live preview targets. Both `clip-path` and47 * `offset-path` share the identical `shape()` grammar, so this does NOT48 * change validation or narrow the `onChange` output — it only drives the49 * preview render. Defaults to `"clip-path"`.50 */51 mode?: ShapePathEditorMode52 className?: string53 "aria-label"?: string54}5556export interface ShapePathEditorProps extends ShapePathEditorPanelProps {}5758// ---------------------------------------------------------------------------59// ShapePathEditor — popover-wrapped60// ---------------------------------------------------------------------------6162export function ShapePathEditor(props: ShapePathEditorProps) {63 const {64 value,65 className,66 "aria-label": ariaLabel = "Edit a shape() path",67 } = props68 const parsed = parseShape(String(value))69 const label =70 parsed.error !== null71 ? "invalid"72 : `${parsed.commands.length} cmd${parsed.commands.length === 1 ? "" : "s"}`7374 return (75 <Popover>76// … truncated
What it pulls in
Other registry items
Files it writes
More from ridiculous
All 22 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| All ridiculous componentsall | ridiculous | Components | Free | no deps | |
| Anchor Position Editoranchor-position-editor | ridiculous | Components | Free | no deps · 9 files | |
| Background Editorbackground-editor | ridiculous | Components | Free | no deps · 9 files | |
| Box Shadow Editorbox-shadow-editor | ridiculous | Components | Free | no deps · 7 files | |
| Calc Editorcalc-editor | ridiculous | Components | Free | no deps · 4 files | |
| Clip Path Editorclip-path-editor | ridiculous | Components | Free | no deps · 20 files | |
| Color Functioncolor-function | ridiculous | Components | Free | no deps · 10 files | |
| Color Pickercolor-picker | ridiculous | Components | Free | no deps · 11 files |
