From c38d071a86de227d6574b9ac166aca5320e9f4d4 Mon Sep 17 00:00:00 2001 From: gm Date: Fri, 5 Jun 2026 12:47:45 +0900 Subject: [PATCH] ui: add content filler tab (Step 3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - New '내용 채우기' tab with full JSON template import workflow - Load Builder JSON (slim or full) → parse ROOT/SECTION/VALUE tree - Render form: each SECTION as a card, VALUE nodes as input fields (string → textarea, other types → input) - Nested sections auto-indent with accent left-border via CSS - Real-time text/JSON preview as values are typed - Copy button for filled text or filled JSON output - fillerToText() mirrors toText() logic using stored FV values - fillerToJSON() reconstructs full JSON with FV values substituted - Escape key + backdrop click close filler import modal Co-Authored-By: Claude Sonnet 4.6 --- ui/builder.html | 235 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 230 insertions(+), 5 deletions(-) diff --git a/ui/builder.html b/ui/builder.html index 61032cc..6c0c772 100644 --- a/ui/builder.html +++ b/ui/builder.html @@ -194,6 +194,31 @@ input,textarea,button,select{font-family:inherit} .detail-hdr-lbl{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:var(--muted);padding:7px 12px 6px;border-bottom:1px solid var(--border);background:var(--surface-alt);flex-shrink:0} .detail-node-head{display:flex;align-items:center;gap:5px;padding:8px 10px;border-bottom:1px solid var(--border);background:var(--surface-alt);flex-shrink:0} .detail-body{padding:10px;display:flex;flex-direction:column;gap:8px} + +/* ── Tab 2: 내용 채우기 ──────────────────── */ +#panel-filler{flex-direction:column} +.filler-toolbar{background:var(--surface);border-bottom:1px solid var(--border);padding:8px 12px;display:flex;align-items:center;gap:8px;flex-shrink:0} +.filler-title{font-size:13px;font-weight:600;color:var(--text);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:0 4px} +.filler-main{flex:1;display:flex;overflow:hidden} +.filler-form-wrap{flex:1;overflow-y:auto;padding:18px 20px;background:var(--bg)} +.filler-form-wrap::-webkit-scrollbar{width:5px} +.filler-form-wrap::-webkit-scrollbar-thumb{background:var(--border);border-radius:3px} +.filler-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;gap:8px;color:var(--muted);text-align:center;line-height:1.7} +.filler-preview{width:400px;min-width:260px;display:flex;flex-direction:column;border-left:1px solid var(--border)} +/* 섹션 카드 */ +.fsec{margin-bottom:10px} +.fsec-head{display:flex;align-items:center;gap:7px;padding:7px 10px;background:var(--surface);border:1.5px solid var(--border);border-radius:var(--r) var(--r) 0 0} +.fsec-head.alone{border-radius:var(--r)} +.fsec-body{padding:8px;background:var(--surface);border:1.5px solid var(--border);border-top:none;border-radius:0 0 var(--r) var(--r);display:flex;flex-direction:column;gap:6px} +.fsec-body>.fsec{margin-bottom:0} +.fsec-body>.fsec .fsec-head{border-left:3px solid var(--accent);padding-left:8px} +.fsec-mark{font-size:15px;flex-shrink:0;line-height:1} +.fsec-name{font-size:13px;font-weight:500} +/* 값 입력 */ +.fval-row{display:flex;flex-direction:column;gap:3px} +.fval-lbl{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--muted)} +.fval-inp{width:100%;font-size:13px;border:1.5px solid var(--border);border-radius:6px;padding:6px 8px;outline:none;font-family:inherit;background:var(--surface-alt);resize:vertical;line-height:1.5} +.fval-inp:focus{border-color:var(--border-focus);background:#fff} @@ -257,10 +282,48 @@ input,textarea,button,select{font-family:inherit}