From fc551cb2e2216a4081a6de8ef4a8e6b875507aac Mon Sep 17 00:00:00 2001 From: SLP-DEV1 Date: Thu, 27 Aug 2026 01:17:32 +0200 Subject: [PATCH 1/8] demo: add original sample project assets --- public/examples/sample-design-leaf.png | Bin 0 -> 4531 bytes public/examples/sample-design-sun.png | Bin 0 -> 4587 bytes public/examples/sample-poster-mockup.png | Bin 0 -> 782 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 public/examples/sample-design-leaf.png create mode 100644 public/examples/sample-design-sun.png create mode 100644 public/examples/sample-poster-mockup.png diff --git a/public/examples/sample-design-leaf.png b/public/examples/sample-design-leaf.png new file mode 100644 index 0000000000000000000000000000000000000000..005042325585cf72a708aadc1c0f03b316b2c3e3 GIT binary patch literal 4531 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 literal 0 HcmV?d00001 diff --git a/public/examples/sample-poster-mockup.png b/public/examples/sample-poster-mockup.png new file mode 100644 index 0000000000000000000000000000000000000000..059c3c7236486b118b304d4db2b5f5c03a99327e GIT binary patch literal 782 zcmb`F-%FEG7{{OY^<5q^wzD;9%4p}cnTn>%A9D3o2H4$=3Uvxd2}a5UKnWtZO`H>xRjW*JaFaN`!vO38A5{&C)xmgPh{~poj=sG0 z<1xU>Lfrm#_M;Rfb3SmQrwM2^VR*DBYdewO%>r+hn{c5d{TQG0js96wz?oy!+~dt3 zbh(MZ-LCKv;00JgSK=!S5QvD^x`8NBt(s$eE@A-Mgxcn}p~24#ib0EbOPjI`YDGkp zfA@tbfuu%8VqhmKey$s&ZZ^FYA%>ZK_5D`{m6kc(>u3#e6v$|ffp3#Q0+3;vpl;WK zibI^&^{3D|@89+i&zG$4P`H&&)bkA6muyE{lBcHT^$!Lf$#uGdld==mAR(xpoyHFX z{`KV;uBTn1B7ZDNbF&vz5`6T#L(s~`G=60sYBtWg2vTg*8`qb3X{rk;McM#btK}&a zKHTwTOwsnQNiBC3tyN3yqN`;7AIrA@X6D?VZ5f}z@I=F{d%MI-6D7h^eqqlri}oip zxN+d!&HGM+2x59raHe&ppJL`yYTxAa%y3Nyzlj%Dv=31V(j7pK%mJxDLB0W~m;)$C m-U^YYAkAd5Q`k;e5&i1y($r~7 Date: Thu, 27 Aug 2026 01:18:30 +0200 Subject: [PATCH 2/8] docs: license bundled sample assets --- public/examples/README.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 public/examples/README.md diff --git a/public/examples/README.md b/public/examples/README.md new file mode 100644 index 0000000..1e92c2f --- /dev/null +++ b/public/examples/README.md @@ -0,0 +1,7 @@ +# OpenMockup Studio sample assets + +The files in this directory are original demo artwork created specifically for OpenMockup Studio. + +They are distributed under the same MIT license as this repository and may be used, modified, and redistributed for testing, documentation, screenshots, demos, and derivative work. + +They intentionally avoid third-party logos, trademarks, stock photography, and external copyrighted artwork. From 707394c600be46e446e17b3afcb1e90295928e3c Mon Sep 17 00:00:00 2001 From: SLP-DEV1 Date: Thu, 27 Aug 2026 01:18:45 +0200 Subject: [PATCH 3/8] demo: add sample project loader --- src/lib/app/sampleProject.ts | 51 ++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/lib/app/sampleProject.ts diff --git a/src/lib/app/sampleProject.ts b/src/lib/app/sampleProject.ts new file mode 100644 index 0000000..c4c646e --- /dev/null +++ b/src/lib/app/sampleProject.ts @@ -0,0 +1,51 @@ +export const SAMPLE_PROJECT_EVENT = "openmockup:sample-files"; + +export type SampleFileRole = "mockups" | "designs"; + +export interface SampleFilesDetail { + role: SampleFileRole; + files: File[]; +} + +export const sampleProjectAssets = { + mockups: [ + { path: "examples/sample-poster-mockup.png", name: "sample-poster-mockup.png" }, + ], + designs: [ + { path: "examples/sample-design-sun.png", name: "sample-design-sun.png" }, + { path: "examples/sample-design-leaf.png", name: "sample-design-leaf.png" }, + ], +} as const; + +export function buildSampleAssetUrl(baseUrl: string, path: string): string { + const normalizedBase = baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`; + return `${normalizedBase}${path.replace(/^\/+/, "")}`; +} + +async function loadSampleFile( + baseUrl: string, + asset: { path: string; name: string }, + fetcher: typeof fetch, +): Promise { + const response = await fetcher(buildSampleAssetUrl(baseUrl, asset.path)); + if (!response.ok) throw new Error(`Could not load sample asset: ${asset.name}`); + const blob = await response.blob(); + return new File([blob], asset.name, { type: blob.type || "image/png" }); +} + +export async function loadSampleProjectFiles( + baseUrl: string, + fetcher: typeof fetch = fetch, +): Promise<{ mockups: File[]; designs: File[] }> { + const [mockups, designs] = await Promise.all([ + Promise.all(sampleProjectAssets.mockups.map((asset) => loadSampleFile(baseUrl, asset, fetcher))), + Promise.all(sampleProjectAssets.designs.map((asset) => loadSampleFile(baseUrl, asset, fetcher))), + ]); + return { mockups, designs }; +} + +export function dispatchSampleFiles(role: SampleFileRole, files: File[]): void { + window.dispatchEvent(new CustomEvent(SAMPLE_PROJECT_EVENT, { + detail: { role, files }, + })); +} From 78e821e42402e937e0f889b0c060dd00309c2cb6 Mon Sep 17 00:00:00 2001 From: SLP-DEV1 Date: Thu, 27 Aug 2026 01:18:51 +0200 Subject: [PATCH 4/8] test: preserve Pages subpath for sample assets --- src/lib/app/sampleProject.test.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/lib/app/sampleProject.test.ts diff --git a/src/lib/app/sampleProject.test.ts b/src/lib/app/sampleProject.test.ts new file mode 100644 index 0000000..b724c1e --- /dev/null +++ b/src/lib/app/sampleProject.test.ts @@ -0,0 +1,14 @@ +import { describe, expect, it } from "vitest"; +import { buildSampleAssetUrl, sampleProjectAssets } from "./sampleProject"; + +describe("sample project assets", () => { + it("keeps the GitHub Pages repository subpath", () => { + expect(buildSampleAssetUrl("/OpenMockup-Studio/", sampleProjectAssets.mockups[0].path)) + .toBe("/OpenMockup-Studio/examples/sample-poster-mockup.png"); + }); + + it("normalizes a base URL without a trailing slash", () => { + expect(buildSampleAssetUrl("/OpenMockup-Studio", sampleProjectAssets.designs[0].path)) + .toBe("/OpenMockup-Studio/examples/sample-design-sun.png"); + }); +}); From 0f4c03ad0f5dfdbcb71ae4bbaba5f18a95852702 Mon Sep 17 00:00:00 2001 From: SLP-DEV1 Date: Thu, 27 Aug 2026 01:19:04 +0200 Subject: [PATCH 5/8] demo: route sample files through normal pickers --- src/components/FileDrop.tsx | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/components/FileDrop.tsx b/src/components/FileDrop.tsx index f6096fc..8a6733f 100644 --- a/src/components/FileDrop.tsx +++ b/src/components/FileDrop.tsx @@ -1,4 +1,5 @@ -import type { ChangeEvent } from "react"; +import { useEffect, type ChangeEvent } from "react"; +import { SAMPLE_PROJECT_EVENT, type SampleFilesDetail } from "../lib/app/sampleProject"; interface FileDropProps { title: string; @@ -12,6 +13,7 @@ interface FileDropProps { export function FileDrop({ title, hint, accept, multiple, onFiles, selectedLabel }: FileDropProps) { const isStaticDemo = import.meta.env.MODE === "demo"; const isMockupPicker = accept.toLowerCase().includes(".psd"); + const sampleRole = isMockupPicker ? "mockups" : "designs"; const effectiveAccept = isStaticDemo && isMockupPicker ? accept .split(",") @@ -23,6 +25,19 @@ export function FileDrop({ title, hint, accept, multiple, onFiles, selectedLabel ? "Choose PNG, JPG or WebP mockups ยท PSD requires the local app" : hint; + useEffect(() => { + if (!isStaticDemo) return; + + const handleSampleFiles = (event: Event): void => { + const detail = (event as CustomEvent).detail; + if (!detail || detail.role !== sampleRole) return; + onFiles(detail.files); + }; + + window.addEventListener(SAMPLE_PROJECT_EVENT, handleSampleFiles); + return () => window.removeEventListener(SAMPLE_PROJECT_EVENT, handleSampleFiles); + }, [isStaticDemo, onFiles, sampleRole]); + function handleChange(event: ChangeEvent): void { const files = Array.from(event.target.files ?? []); const acceptedFiles = isStaticDemo && isMockupPicker From af7ed5919851a3d558dfc97220d8da1549db7639 Mon Sep 17 00:00:00 2001 From: SLP-DEV1 Date: Thu, 27 Aug 2026 01:19:19 +0200 Subject: [PATCH 6/8] demo: add one-click sample controls --- src/components/DemoBanner.tsx | 76 +++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 src/components/DemoBanner.tsx diff --git a/src/components/DemoBanner.tsx b/src/components/DemoBanner.tsx new file mode 100644 index 0000000..1972589 --- /dev/null +++ b/src/components/DemoBanner.tsx @@ -0,0 +1,76 @@ +import { useState } from "react"; +import { dispatchSampleFiles, loadSampleProjectFiles } from "../lib/app/sampleProject"; + +export function DemoBanner() { + const [isLoading, setLoading] = useState(false); + const [isSampleLoaded, setSampleLoaded] = useState(false); + const [error, setError] = useState(""); + + async function loadSample(): Promise { + if (isLoading) return; + setLoading(true); + setError(""); + try { + const sample = await loadSampleProjectFiles(import.meta.env.BASE_URL); + dispatchSampleFiles("mockups", sample.mockups); + dispatchSampleFiles("designs", sample.designs); + setSampleLoaded(true); + } catch (sampleError) { + setError(sampleError instanceof Error ? sampleError.message : "Sample project could not be loaded."); + } finally { + setLoading(false); + } + } + + function clearSample(): void { + dispatchSampleFiles("mockups", []); + dispatchSampleFiles("designs", []); + setSampleLoaded(false); + setError(""); + } + + return ( +
+ Browser demo: PNG, JPG and WebP mockups run locally in this tab. + + + PSD / full version + + {error ? {error} : null} +
+ ); +} From 17c21acb0c5ab69c0a5ffc69cf63b7f9af7583dc Mon Sep 17 00:00:00 2001 From: SLP-DEV1 Date: Thu, 27 Aug 2026 01:19:26 +0200 Subject: [PATCH 7/8] demo: show one-click sample banner --- src/main.tsx | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/src/main.tsx b/src/main.tsx index 7a845d0..9202ab3 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,5 +1,6 @@ import ReactDOM from "react-dom/client"; import App from "./App"; +import { DemoBanner } from "./components/DemoBanner"; import "./styles.css"; import "./coverClip.css"; @@ -11,28 +12,7 @@ if (isStaticDemo) { ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( <> - {isStaticDemo ? ( -
- Browser demo: PNG, JPG and WebP mockups run locally in this tab. PSD Smart Objects require the local app.{" "} - - Run the full version - -
- ) : null} + {isStaticDemo ? : null} , ); From f3c24be3f4d272c1e7d32c6ba530ad00b5682e27 Mon Sep 17 00:00:00 2001 From: SLP-DEV1 Date: Thu, 27 Aug 2026 01:22:32 +0200 Subject: [PATCH 8/8] demo: align sample artwork with bundled mockup --- public/examples/sample-design-leaf.png | Bin 4531 -> 3301 bytes public/examples/sample-design-sun.png | Bin 4587 -> 2944 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/public/examples/sample-design-leaf.png b/public/examples/sample-design-leaf.png index 005042325585cf72a708aadc1c0f03b316b2c3e3..f058302b005c631a1716dbe34ba2b80784ee1ee7 100644 GIT binary patch literal 3301 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 XO}3V4sRtSh^)>?hzF^6jeDU7_6{^D3 literal 4531 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 a!_QrK>Nn55W3tj2J!OC|mm_8KbN&s3YbwJ4 literal 4587 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