mirror of
https://github.com/PR0M3TH3AN/Artstr-Studio.git
synced 2026-11-02 11:40:39 +00:00
861e17e3f98d86e230d5fccc01367cf1d7195dd7
Vector shapes feature (per docs/VECTOR_SHAPES_FEATURE.md): Phase A - Shape primitive layers (rect, rounded-rect, circle, ellipse, triangle, polygon, star, line) with a 0-100 viewBox coord system that renders on all six surfaces (editor canvas + five preview renderers) plus Canvas2D export. Solid fill, kind-specific controls (corner radius, sides, star points, inner ratio, line stroke width). Layer data is purely additive in JSON; old clients skip unknown shape kinds. Phase B - Linear + radial gradient fills with two-stop pickers. SVG emits via <defs><linearGradient>/<radialGradient>; canvas via createLinearGradient/createRadialGradient. Angles follow CSS linear-gradient convention. Switching fill types preserves the most relevant color. Phase C - Solid strokes on all non-line shapes. Color, width (in shape-local viewBox units), dash style (solid / dashed / dotted) with auto-scaled dash patterns. SVG emits stroke attributes; canvas uses strokeStyle + setLineDash. Phase D - Custom SVG / full-SVG layer via file upload: - File picker (.svg, image/svg+xml) replaces a paste textarea. - Detects single <path d=…> vs full <svg>…</svg>; single paths land as kind:'path' with editable fill/stroke, multi-element SVGs land as kind:'svg' with fills baked in. - Sanitizer strips <script>, <foreignObject>, <iframe>, <embed>, <animate>, <image>, <a>, all on* event handlers, external hrefs/xlink:hrefs, and javascript:/external-url style entries. - Canvas export serializes the sanitized inner into a blob URL, loads via Image, drawImage. - Per-element editor: a list inside the shape panel exposes every paintable child (path / rect / circle / ellipse / polygon / polyline / line) with fill + stroke color pickers and a stroke-width input. Auto-applies a viewBox-relative default stroke width when stroke is first set so strokes are visible at any zoom. Layer-level fill / stroke panels are hidden for SVG imports (per-element is the canonical control). Phase E - Clip / mask on any layer type: - New optional `clip` field with two flavors: inline-shape (clip to a primitive defined inline) and layer-ref (clip to another shape layer's geometry in the same target). - Clip source dropdown in the selected-layer panel offers rect / rounded-rect / circle / ellipse / triangle / polygon / star / custom path / From another layer. Kind-specific param inputs show on demand. - DOM rendering uses a shared hidden SVG defs container with <clipPath clipPathUnits="objectBoundingBox"> entries, referenced via clip-path: url(#clip-<layerId>) on each layer wrapper. - Canvas export builds a Path2D with a DOMMatrix transform mapping 0-100 coords to the layer's pixel bounds, then ctx.clip() before drawing the layer contents. - Cycle detection: if A clips to B and B clips back to A, both fall back to unclipped instead of looping. - Single-path-SVG clips reuse the upload modal in an edit-clip flow that rejects multi-element SVGs with an inline error. Phase A bonus polish: - Shapes spawn 1:1 (min(bounds.w, bounds.h) * 0.4). - Session-wide aspect-ratio lock (default on) with a 🔒/🔓 toggle between the W/H inputs in the selected-layer panel. Typing in one dimension updates the other proportionally on every layer type. Per-mode metadata isolation: - state.savedMetaByMode parks Template-mode and Disc-Designer-mode metadata separately. swapMetaForAppMode runs before any appMode flip so loading a template in disc designer doesn't overwrite the designer's title / category / identifiers. omdbApiKey stays sticky across modes as a per-user preference. Strict per-sub-mode layout isolation: - isLayerForCurrentMode no longer treats target='page' as a universal wildcard. Each layer belongs to exactly one sub-mode by its target. - Removed the "Whole page" entry from the layer-target dropdown. - migrateLegacyLayerTargets retargets legacy page/empty layers to the current sub-mode's primary target on load. Wired into all four mode-specific load paths and the legacy full-project path. - Fixes the bug where case-cover artwork was rendering misaligned in the disc-sheet preview. Layer clipboard: - Session-only clipboard supports cross-sub-mode and cross-tool paste with retargeting. Copy / Cut on selected layer + Copy all / Paste in the panel header. Paste retargets to the current sub-mode's primary target and clamps positions so a layer copied from a wide cover doesn't land off-canvas in a 4.6" disc. UI polish: - Hide unused artwork-mode sidebar controls: cover full-wrap mode hides the separate Back / Spine / Front controls and vice versa, via the existing body.mode-combined / mode-separate classes. - Category-aware identifier visibility: only show IMDb / UPC / TheTVDB / MusicBrainz fields that fit the chosen category. Custom art hides all four. - Added "Custom art" to the canonical mediaCategories list and populated both the template and designer category selects from it (the template select was previously hardcoded). - Selected-layer panel hides entirely when nothing is selected. - Jewel spine-text details block hides until at least one jewel insert has artwork. - Close project / disc-designer reset / clear images all use a shared blankMeta() helper that covers UPC / TheTVDB / MusicBrainz (the previous reset path was missing them). Close project also resets state.customArt to its defaults so the background color doesn't carry over. - Disc Designer mode now has a proper add-layer panel (Add image with URL + Copy / Add text / Add color block / Add shape menu) in addition to the layer list. - Project file loads route through loadProjectFromText regardless of which "Load from file" button was used; an info toast announces a mode switch when one is needed. Publish flow: - New publish-confirm modal renders a live design preview, a metadata table (Type / Title / Category / Language / IMDb / UPC / TheTVDB / MusicBrainz / Author), and an edit-mode tradeoff banner. Replaces the bare confirm(). Errors render inline. - Removed the legacy "Copy Nostr event" button — only "Copy event ID" remains, and it stays hidden until something has been published. Toast system: - All 41 native alert() calls swapped for in-app toasts (toastError with a red border for failures, toastSuccess with the accent color for publish/copy confirmations). Auto-dismiss after a few seconds; manual close button on each. NIP-57 zap tab: - _feedPagination grew a Zapped entry so the new tab can render without crashing the rerender pipeline. - fetchZapsForEvents now runs chunks in parallel and streams a debounced rerender on every ingested receipt, so totals appear within a second or two instead of taking up to ~28 s. - invalidateFeedCache clears the zap cache too so Refresh re-queries receipts. Co-Authored-By: Claude Opus 4.7 <[email protected]>
CaseWrap Studio
CaseWrap Studio is a static print-layout editor for physical media packaging. It supports DVD/Blu-ray case wraps, Avery 8960/8944 disc-label sheets, Avery 8693/8943 CD jewel-case insert sheets, and reusable single-disc designs.
What it supports
- Separate front, spine, and back case artwork (or one combined wrap image)
- Disc-label sheet mode (two print positions on one Avery 8960/8944 sheet)
- CD jewel insert mode (front + tray inserts on one Avery 8693/8943 sheet)
- Disc Designer mode for creating a reusable single-disc design
- Additional image and text layers
- Drag positioning, z-order changes, rotation, sizing, and opacity
- PDF export through the browser print dialog
- Nostr community browsing/sharing for templates and disc designs
- Publishing, replies, reactions, follows, and reposts from inside the app
Important workflow
All image sources are remote URLs.
That means:
- Case art, disc art, jewel insert art, and extra image layers should use
httporhttpsURLs - Saved project JSON remains portable across machines
- Exported/copied Nostr events can reconstruct layouts from event content
- Community feed data comes from relays listed in the Community panel
- Publishing/social actions require a NIP-07 browser extension (for example Alby or nos2x)
If a URL stops working later, the image will no longer render. For long-term reliability, use stable hosted URLs.
Main file
src/index.htmlis the complete app entrypoint. Open it directly in a browser or serve it from any static host.
Export and print
- Use
Print / Save PDFfor print-ready output - Keep browser scale at
100% - Disable browser headers and footers
Save, restore, and sharing
Save projectwrites project JSONLoad projectrestores project JSONCopy Nostr eventcopies a signed event payloadImport from Nostrrestores a template/design from a copied event- The Community modal lets you browse New/Popular/Search/Mine, preview templates, and import them
- Disc designs can be published and reused independently, then imported into Disc 1 or Disc 2 positions on a disc sheet
Nostr data model
- Template/design payloads are published as kind
30078app-data events withcasewraptags - Typical social events use standard kinds (
1,7,6,3,0) - Template modes include
cover,disc,jewel, anddisc-design - Current schema version is
5; minimum supported schema version is4
Notes
- The app is fully static and does not require a backend
- Local browser autosave is still available
- Older saved projects with embedded data URLs may still load, but new work should use remote URLs
Description
A static site DVD and Blu-Ray Case and disk label designer
Readme
5.7 MiB
0 Stars
1 Watchers
0 Forks
Languages
JavaScript
99.7%
HTML
0.3%