From 59e9d490937db44fd482b2f7e072420a4de68763 Mon Sep 17 00:00:00 2001 From: casper Date: Tue, 30 Jun 2026 03:21:59 +0000 Subject: [PATCH] Upload files to "/" --- .env | 1 + Dockerfile | 12 ++++++++++++ docker-compose.yml | 19 +++++++++++++++++++ package.json | 15 +++++++++++++++ styles.css | 4 ++++ 5 files changed, 51 insertions(+) create mode 100644 .env create mode 100644 Dockerfile create mode 100644 docker-compose.yml create mode 100644 package.json create mode 100644 styles.css diff --git a/.env b/.env new file mode 100644 index 0000000..b1f410d --- /dev/null +++ b/.env @@ -0,0 +1 @@ +DOMAIN=draw.ui.backend-3.com diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a272686 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +FROM node:20-bookworm AS build +WORKDIR /app + +COPY package*.json ./ +RUN npm install + +COPY . . +RUN npm run build + +FROM nginx:alpine AS runner +COPY --from=build /app/dist /usr/share/nginx/html +EXPOSE 80 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..379a839 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,19 @@ +services: + perfect-freehand-demo: + build: + context: /srv/sites/draw/perfect-freehand-demo + dockerfile: Dockerfile + image: perfect-freehand-demo:latest + container_name: perfect-freehand-demo + restart: unless-stopped + expose: + - "80" + networks: + - web + labels: + caddy: draw.ui.backend-3.com + caddy.reverse_proxy: "{{upstreams 80}}" + +networks: + web: + external: true diff --git a/package.json b/package.json new file mode 100644 index 0000000..2cf9332 --- /dev/null +++ b/package.json @@ -0,0 +1,15 @@ +{ + "name": "perfect-freehand-demo", + "private": true, + "version": "1.0.0", + "type": "module", + "scripts": { + "build": "vite build" + }, + "dependencies": { + "perfect-freehand": "^1.2.2" + }, + "devDependencies": { + "vite": "^5.4.0" + } +} diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..4b8cbf0 --- /dev/null +++ b/styles.css @@ -0,0 +1,4 @@ +:root{color-scheme:light dark;--bg:rgba(255,255,255,.72);--bg-strong:rgba(255,255,255,.82);--border:rgba(0,0,0,0);--border-strong:rgba(0,0,0,.05);--text:#0f0f10;--text-dim:rgba(15,15,16,.65);--shadow:0 12px 36px rgba(0,0,0,.14);--blur:blur(20px);--radius:3px;--track:rgba(0,0,0,.12);--thumb:rgba(15,15,16,.9);--thumb-border:rgba(15,15,16,.22);--input-bg:rgba(0,0,0,0);--panel-txt-shadow:none;--icon:#0f0f10;--icon-hover-bg:rgba(0,0,0,.06);--glass-bg:rgba(255,255,255,.58);--glass-border:rgba(0,0,0,.06);--glass-inset-hi:rgba(255,255,255,.55);--glass-inset-lo:rgba(0,0,0,.01);--glass-shadow:0 16px 44px rgba(0,0,0,.16);--ctrl-bg:rgba(255,255,255,.05);--ctrl-inset-hi:rgba(255,255,255,.15);--ctrl-inset-lo:rgba(0,0,0,.08)} +body[data-theme=dark]{--bg:rgba(10,10,10,.26);--bg-strong:rgba(10,10,10,.34);--border:rgba(255,255,255,.07);--border-strong:rgba(255,255,255,.11);--text:#fff;--text-dim:rgba(255,255,255,.68);--shadow:0 12px 36px rgba(0,0,0,.28);--track:rgba(255,255,255,.14);--thumb:rgba(255,255,255,.94);--thumb-border:rgba(255,255,255,.24);--input-bg:rgba(0,0,0,0);--panel-txt-shadow:0 1px 0 rgba(0,0,0,.15);--icon:#fff;--icon-hover-bg:rgba(255,255,255,.06);--glass-bg:rgba(18,18,20,.38);--glass-border:rgba(255,255,255,.14);--glass-inset-hi:rgba(255,255,255,.1);--glass-inset-lo:rgba(0,0,0,.42);--glass-shadow:0 18px 50px rgba(0,0,0,.38);--ctrl-bg:rgba(0,0,0,.14);--ctrl-inset-hi:rgba(255,255,255,.12);--ctrl-inset-lo:rgba(0,0,0,.42)} +body[data-theme=light]{--bg:rgba(255,255,255,.72);--bg-strong:rgba(255,255,255,.82);--border:rgba(0,0,0,.12);--border-strong:rgba(0,0,0,.2);--text:#0f0f10;--text-dim:rgba(15,15,16,.65);--shadow:0 12px 36px rgba(0,0,0,.14);--track:rgba(0,0,0,.12);--thumb:rgba(15,15,16,.9);--thumb-border:rgba(15,15,16,.22);--input-bg:rgba(0,0,0,0);--panel-txt-shadow:none;--icon:#0f0f10;--icon-hover-bg:rgba(0,0,0,.06);--glass-bg:rgba(255,255,255,.58);--glass-border:rgba(0,0,0,.12);--glass-inset-hi:rgba(255,255,255,.55);--glass-inset-lo:rgba(0,0,0,.08);--glass-shadow:0 16px 44px rgba(0,0,0,.16);--ctrl-bg:rgba(255,255,255,.05);--ctrl-inset-hi:rgba(255,255,255,.45);--ctrl-inset-lo:rgba(0,0,0,.08)} +*{box-sizing:border-box}html,body{margin:0;width:100%;height:100%;overflow:hidden;background:#fff;color:var(--text);font-family:Inter,"SF Pro Text","SF Pro Display",Helvetica,system-ui,sans-serif;text-transform:lowercase;font-size:13px;line-height:1.35;font-weight:400;letter-spacing:.01em;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-rendering:optimizeLegibility}body{background:#fff;color:var(--text)}button,input,select{font:inherit;text-transform:inherit;color:var(--text)}button{font-weight:500;border-radius:3px}#app,.wrap{width:100%;height:100%}#canvas{position:absolute;inset:0;width:100vw;height:100vh;display:block;touch-action:none;background:inherit}.hud{position:fixed;left:16px;top:16px;z-index:10;pointer-events:none;transition:transform 180ms ease,opacity 180ms ease,box-shadow 180ms ease,background-color 180ms ease,border-color 180ms ease;transform-origin:top left;will-change:transform,opacity}.hud.compact{opacity:.95;transform:scale(.985);width:88px;min-width:0;max-width:88px}.hud-inner{max-height:auto;width:336px;pointer-events:auto;border:1px solid var(--glass-border);background:var(--glass-bg);color:var(--text);backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);box-shadow:inset 0 1px 0 var(--glass-inset-hi),inset 0 -1px 0 var(--glass-inset-lo),var(--glass-shadow);border-radius:var(--radius);overflow:hidden}.hud.compact .hud-inner{width:88px}.hud-top,.hud-footer,.hud-body,.hint{padding:10px 12px;background:transparent}.hud-top{position:relative;display:inline-flex;min-width:100%;align-items:center;justify-content:flex-start;gap:0;border-bottom:1px solid var(--border);cursor:grab;user-select:none;pointer-events:auto;z-index:2}.hud.dragging .hud-top{cursor:grabbing}#hudDragHandle{position:absolute;inset:0;z-index:1;pointer-events:auto}.hud-top>*:not(#hudDragHandle){position:relative;z-index:2}.hud-footer{display:flex;gap:5px;align-items:center;justify-content:center;border-top:1px solid var(--border)}.hud-body{display:grid;gap:3px;overflow:hidden;max-height:1200px;opacity:1;transform:translateY(0);transition:max-height 220ms ease,opacity 160ms ease,transform 160ms ease,padding 160ms ease}.hud.compact .hud-body{max-height:0;opacity:0;transform:translateY(-6px);pointer-events:none;padding-top:0;padding-bottom:0}.row{display:grid;grid-template-columns:82px 1fr;gap:10px;align-items:center}.row label,.mini,.hint{color:var(--text-dim);font-size:11px;font-weight:500;letter-spacing:.02em;text-shadow:var(--panel-txt-shadow)}.value{display:grid;grid-template-columns:1fr 72px;gap:8px;align-items:center}button,input[type=number],select,.glass-checkbox,input[type=color]{min-height:28px;border:1px solid var(--glass-border);background:var(--ctrl-bg);color:var(--text);border-radius:6px;backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);box-shadow:inset 0 1px 0 var(--ctrl-inset-hi),inset 0 -1px 0 var(--ctrl-inset-lo)}button{padding:6px 10px;cursor:pointer;font-size:12px}button:hover,input[type=number]:hover,select:hover,.glass-checkbox:hover,input[type=color]:hover{border-color:var(--border-strong)}button:active{transform:translateY(1px)}input[type=number],select{width:100%;padding:5px 6px;outline:none;font-size:12px}input[type=color]{width:100%;padding:3px 4px;cursor:pointer}input[type=range]{--pct:50%;width:100%;height:16px;appearance:none;background:transparent;outline:none;cursor:pointer;margin:0}input[type=range]::-webkit-slider-runnable-track{height:4px;border-radius:999px;background:linear-gradient(to right,var(--thumb) 0 var(--pct),var(--track) var(--pct) 100%);border:1px solid var(--border);box-shadow:inset 0 1px 1px rgba(0,0,0,.12),0 0 0 1px rgba(255,255,255,.03)}input[type=range]::-webkit-slider-thumb{appearance:none;width:14px;height:14px;margin-top:-6px;border-radius:999px;background:var(--thumb);border:1px solid var(--thumb-border);box-shadow:0 3px 10px rgba(0,0,0,.14),inset 0 1px 0 rgba(255,255,255,.25)}input[type=range]::-moz-range-track{height:4px;border-radius:999px;background:var(--track);border:1px solid var(--border);box-shadow:inset 0 1px 1px rgba(0,0,0,.12),0 0 0 1px rgba(255,255,255,.03)}input[type=range]::-moz-range-progress{height:4px;border-radius:999px;background:var(--thumb)}input[type=range]::-moz-range-thumb{width:14px;height:14px;border-radius:999px;background:var(--thumb);border:1px solid var(--thumb-border);box-shadow:0 3px 10px rgba(0,0,0,.14),inset 0 1px 0 rgba(255,255,255,.25)}input[type=number]::-webkit-outer-spin-button,input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}input[type=number]{-moz-appearance:textfield}.glass-checkbox{display:inline-flex;align-items:center;gap:6px;padding:5px 8px;cursor:pointer;user-select:none;font-size:11px}.glass-checkbox input{margin:0;accent-color:currentColor}.checkbox-row{align-items:center}.hidden{display:none}.hint{border-top:1px solid var(--border);padding-top:8px;text-align:center}.hud.compact .hud-footer,.hud.compact .hint{display:none}.hud.compact .hud-top{justify-content:flex-start}#hudHoverGap{flex:1 1 auto;min-width:18px;height:32px;margin:0;border-radius:10px;background:transparent;cursor:default;touch-action:none;-webkit-tap-highlight-color:transparent;pointer-events:auto}#hudHoverGap:hover{background:rgba(0,0,0,.03)}body[data-theme=dark] #hudHoverGap:hover{background:rgba(255,255,255,.01)}.hud.compact #hudHoverGap{flex:0 0 auto;min-width:0;width:0;padding:0;margin:0}@media (pointer:coarse){#hudHoverGap{min-width:25px;height:40px}}.icon-btn{position:relative;z-index:3;display:inline-flex;align-items:center;justify-content:center;gap:0;padding:.5rem;min-width:2.25rem;min-height:2.25rem;margin:0;border:1px solid transparent;border-radius:.5rem;background:transparent;color:var(--icon);cursor:pointer;line-height:0;-webkit-tap-highlight-color:transparent;opacity:.6;transition:opacity .15s ease,background-color .15s ease,border-color .15s ease}.icon-btn:hover,.icon-btn:focus-visible{opacity:1}.icon-btn:hover{background:var(--icon-hover-bg)}.icon-btn:focus-visible{outline:2px solid currentColor;outline-offset:2px}.icon-btn:disabled{opacity:.35;cursor:not-allowed}.icon-btn .icon{width:1.33rem;height:1.33rem;display:block;flex:0 0 auto;color:var(--icon)}.hud:focus-within{pointer-events:auto}.hud:focus-within .hud-top,.hud:focus-within .hud-inner{cursor:default}@media (prefers-reduced-motion:reduce){.icon-btn,.hud-body{transition:none}}body[data-cursor=dot] #canvas{cursor:none}body[data-cursor=crosshair] #canvas{cursor:crosshair}body[data-cursor=default] #canvas{cursor:default}.cursor-ic{display:none}.cursor-ic.active{display:block}#cursorDot{position:fixed;left:0;top:0;width:var(--cursor-dot-size,10px);height:var(--cursor-dot-size,10px);margin:calc(var(--cursor-dot-size,10px)/-2) 0 0 calc(var(--cursor-dot-size,10px)/-2);border-radius:999px;pointer-events:none;z-index:9999;opacity:0;transform:translate3d(-9999px,-9999px,0);will-change:transform,opacity;transition:opacity .12s ease;background:var(--cursor-dot-color,rgba(0,0,0,.35));mix-blend-mode:normal;box-shadow:0 0 0 1px rgba(0,0,0,.14),0 10px 28px rgba(0,0,0,.14)}body[data-theme=dark] #cursorDot{box-shadow:0 0 0 1px rgba(255,255,255,.18),0 12px 30px rgba(0,0,0,.28)}#cycleCursor .cursor-ic{display:none!important}#cycleCursor .cursor-ic.active{display:block!important}#refLayer{position:absolute;inset:0;z-index:5;pointer-events:none}.ref-item{position:absolute;pointer-events:auto;user-select:none;touch-action:none;overflow:hidden;background:rgba(0,0,0,.08);border:2px solid transparent;outline-offset:2px;box-shadow:none;transition:border-color 180ms ease,box-shadow 180ms ease,opacity 180ms ease}.ref-item img{display:block;width:100%;height:100%;object-fit:contain;pointer-events:none}.ref-item.ref-selected{border-color:rgba(255,255,255,.11);box-shadow:0 0 0 1px rgba(190,250,255,.22)}.ref-item.ref-fade{border-color:transparent;box-shadow:none}.ref-item.active-dragging{cursor:grabbing}.ref-handle{position:absolute;right:-6px;bottom:-6px;width:14px;height:14px;border-radius:999px;background:rgba(255,255,255,.09);border:1px solid rgba(0,0,0,.1);cursor:nwse-resize;pointer-events:auto}.ref-menu{position:fixed;z-index:10000;display:none;min-width:180px;padding:8px;border-radius:7px;background:rgba(20,20,20,.94);color:#fff;box-shadow:0 10px 30px rgba(0,0,0,.35)}.ref-menu button,.ref-menu input[type=range]{width:100%;margin:4px 0}.collapsible-panel{overflow:hidden;max-height:0;opacity:0;transform:translateY(-4px);pointer-events:none;transition:max-height 220ms ease,opacity 180ms ease,transform 180ms ease}.collapsible-panel.open{max-height:520px;opacity:1;transform:translateY(0);pointer-events:auto}#gradientToggle,#guidesToggle{width:100%;min-height:28px}#gradientPanel,#guidesPanel{display:grid;gap:5px;padding-top:2px;margin-top:2px;border-top:1px solid var(--border)}.brush-preview{width:100%;height:8px;border-radius:999px;background:#000;border:1px solid var(--border);box-shadow:inset 0 1px 1px rgba(255,255,255,.12)}