Spaces:
Running
Running
| class AppSidebar extends HTMLElement { | |
| connectedCallback() { | |
| this.attachShadow({ mode: 'open' }); | |
| this.shadowRoot.innerHTML = ` | |
| <style> | |
| :host { | |
| width: var(--sidebar-width, 320px); | |
| background-color: white; | |
| border-right: 1px solid #e2e8f0; | |
| display: flex; | |
| flex-direction: column; | |
| height: 100%; | |
| overflow-y: auto; | |
| transition: transform 0.3s ease; | |
| flex-shrink: 0; | |
| z-index: 40; | |
| } | |
| .section { | |
| padding: 1.5rem 1rem; | |
| border-bottom: 1px solid #f1f5f9; | |
| } | |
| .section h3 { | |
| font-size: 0.875rem; | |
| font-weight: 700; | |
| text-transform: uppercase; | |
| color: #64748b; | |
| margin-bottom: 1rem; | |
| display: flex; | |
| align-items: center; | |
| gap: 0.5rem; | |
| } | |
| label.file-label { | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 0.5rem; | |
| width: 100%; | |
| padding: 0.75rem; | |
| background: #eff6ff; | |
| color: #2563eb; | |
| border: 1px dashed #bfdbfe; | |
| border-radius: 0.5rem; | |
| font-size: 0.875rem; | |
| font-weight: 500; | |
| cursor: pointer; | |
| transition: all 0.2s; | |
| text-align: center; | |
| } | |
| label.file-label:hover { | |
| background: #dbeafe; | |
| border-color: #3b82f6; | |
| } | |
| .file-upload-wrapper { | |
| position: relative; | |
| overflow: hidden; | |
| display: inline-block; | |
| width: 100%; | |
| } | |
| .file-upload-wrapper input[type=file] { | |
| position: absolute; | |
| left: 0; | |
| top: 0; | |
| opacity: 0; | |
| width: 100%; | |
| height: 100%; | |
| cursor: pointer; | |
| } | |
| .file-name { | |
| font-size: 0.75rem; | |
| color: #94a3b8; | |
| margin-top: 0.25rem; | |
| white-space: nowrap; | |
| overflow: hidden; | |
| text-overflow: ellipsis; | |
| } | |
| button.action-btn { | |
| width: 100%; | |
| padding: 0.75rem; | |
| border-radius: 0.5rem; | |
| border: none; | |
| font-weight: 600; | |
| cursor: pointer; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 0.5rem; | |
| transition: all 0.2s; | |
| margin-bottom: 0.5rem; | |
| } | |
| .btn-primary { | |
| background: linear-gradient(135deg, #2563eb, #4f46e5); | |
| color: white; | |
| } | |
| .btn-primary:hover { | |
| box-shadow: 0 4px 12px rgba(37, 99, 235, 0.3); | |
| transform: translateY(-1px); | |
| } | |
| .btn-secondary { | |
| background: #f1f5f9; | |
| color: #475569; | |
| } | |
| .btn-secondary:hover { | |
| background: #e2e8f0; | |
| } | |
| .btn-indigo { | |
| background: #4f46e5; | |
| color: white; | |
| } | |
| .form-group { | |
| margin-bottom: 1rem; | |
| } | |
| select.form-control { | |
| width: 100%; | |
| padding: 0.5rem; | |
| border: 1px solid #cbd5e1; | |
| border-radius: 0.375rem; | |
| background: white; | |
| } | |
| /* Dark Mode Support via Host selector */ | |
| :host-context([data-theme="dark"]) { | |
| background-color: #1e293b; | |
| border-color: #334155; | |
| } | |
| :host-context([data-theme="dark"]) .section h3 { | |
| color: #94a3b8; | |
| } | |
| :host-context([data-theme="dark"]) label.file-label { | |
| background: #172554; | |
| color: #60a5fa; | |
| border-color: #1e3a8a; | |
| } | |
| :host-context([data-theme="dark"]) .file-name { | |
| color: #64748b; | |
| } | |
| :host-context([data-theme="dark"]) .btn-secondary { | |
| background: #334155; | |
| color: #e2e8f0; | |
| } | |
| :host-context([data-theme="dark"]) select.form-control { | |
| background: #0f172a; | |
| color: white; | |
| border-color: #475569; | |
| } | |
| </style> | |
| <!-- Standard Sidebar Content --> | |
| <div id="sidebar-standard"> | |
| <div class="section"> | |
| <h3><i data-feather="image"></i> Backgrounds</h3> | |
| <div class="form-group"> | |
| <div class="file-upload-wrapper"> | |
| <input type="file" id="bg1-file" accept="image/*,.pdf"> | |
| <label for="bg1-file" class="file-label"> | |
| <i data-feather="upload"></i> Page 1 Image | |
| </label> | |
| </div> | |
| <div id="bg1-name" class="file-name">No file selected</div> | |
| </div> | |
| <div class="form-group"> | |
| <div class="file-upload-wrapper"> | |
| <input type="file" id="bg2-file" accept="image/*,.pdf"> | |
| <label for="bg2-file" class="file-label"> | |
| <i data-feather="upload"></i> Page 2 Image | |
| </label> | |
| </div> | |
| <div id="bg2-name" class="file-name">No file selected</div> | |
| </div> | |
| <button id="btn-apply-bg" class="action-btn btn-primary"> | |
| <i data-feather="check"></i> Apply Backgrounds | |
| </button> | |
| </div> | |
| <div class="section"> | |
| <h3><i data-feather="database"></i> Data Source</h3> | |
| <div class="form-group"> | |
| <div class="file-upload-wrapper"> | |
| <input type="file" id="json-file" accept=".json"> | |
| <label for="json-file" class="file-label"> | |
| <i data-feather="file-text"></i> Import JSON | |
| </label> | |
| </div> | |
| <div id="json-name" class="file-name">No file selected</div> | |
| </div> | |
| <div class="form-group"> | |
| <label class="text-xs font-bold text-slate-500 uppercase mb-1 block">Select Record</label> | |
| <select id="data-select" class="form-control" disabled> | |
| <option value="">-- No Data --</option> | |
| </select> | |
| </div> | |
| <button id="btn-load-sample" class="action-btn btn-indigo"> | |
| <i data-feather="box"></i> Load Sample | |
| </button> | |
| </div> | |
| <div class="section"> | |
| <h3><i data-feather="book-open"></i> PDF Tools</h3> | |
| <div class="form-group"> | |
| <div class="file-upload-wrapper"> | |
| <input type="file" id="pdf-upload" accept="application/pdf"> | |
| <label for="pdf-upload" class="file-label"> | |
| <i data-feather="upload"></i> Import PDF | |
| </label> | |
| </div> | |
| <div id="pdf-name" class="file-name">No file selected</div> | |
| </div> | |
| </div> | |
| <div class="section"> | |
| <h3><i data-feather="download"></i> Export</h3> | |
| <button id="btn-download-pdf" class="action-btn btn-primary"> | |
| <i data-feather="download"></i> Download PDF | |
| </button> | |
| <button id="btn-download-all" class="action-btn btn-secondary"> | |
| <i data-feather="download-cloud"></i> Download All | |
| </button> | |
| <button id="btn-qr-modal" class="action-btn btn-indigo"> | |
| <i data-feather="grid"></i> Add QR & Download | |
| </button> | |
| </div> | |
| <div class="section"> | |
| <h3><i data-feather="layout"></i> Layout Management</h3> | |
| <div class="form-group"> | |
| <input type="text" id="layout-name-input" placeholder="Layout name" class="form-control mb-2"> | |
| </div> | |
| <div class="form-group"> | |
| <div class="file-upload-wrapper"> | |
| <input type="file" id="layout-import" accept=".json"> | |
| <label for="layout-import" class="file-label"> | |
| <i data-feather="upload"></i> Import Layout | |
| </label> | |
| </div> | |
| <div id="layout-import-name" class="file-name">No file selected</div> | |
| </div> | |
| <button id="btn-export-layout" class="action-btn btn-secondary"> | |
| <i data-feather="save"></i> Export Layout | |
| </button> | |
| <button id="btn-save-layout" class="action-btn btn-primary"> | |
| <i data-feather="database"></i> Save to History | |
| </button> | |
| <button id="btn-new-layout" class="action-btn btn-secondary"> | |
| <i data-feather="file-plus"></i> New Layout | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Design Mode Sidebar Content --> | |
| <div id="sidebar-design" style="display: none;"> | |
| <div class="section"> | |
| <h3><i data-feather="sliders"></i> Field Properties</h3> | |
| <div id="no-field-selected" class="text-center py-4 text-slate-500"> | |
| <i data-feather="mouse-pointer" class="w-8 h-8 mx-auto mb-2"></i> | |
| <p>Select a field to edit</p> | |
| </div> | |
| <div id="field-controls" style="display: none;"> | |
| <div class="form-group"> | |
| <label>Field ID</label> | |
| <div id="prop-id" class="font-mono text-sm p-2 bg-slate-100 dark:bg-slate-700 rounded"></div> | |
| </div> | |
| <div class="grid grid-cols-2 gap-2"> | |
| <div class="form-group"> | |
| <label for="prop-x">X Position</label> | |
| <input type="number" id="prop-x" class="form-control" step="1"> | |
| </div> | |
| <div class="form-group"> | |
| <label for="prop-y">Y Position</label> | |
| <input type="number" id="prop-y" class="form-control" step="1"> | |
| </div> | |
| </div> | |
| <div class="form-group"> | |
| <label for="prop-size">Font Size</label> | |
| <input type="number" id="prop-size" class="form-control" min="8" max="72"> | |
| </div> | |
| <div class="form-group"> | |
| <label for="prop-weight">Font Weight</label> | |
| <select id="prop-weight" class="form-control"> | |
| <option value="normal">Normal</option> | |
| <option value="bold">Bold</option> | |
| <option value="lighter">Light</option> | |
| </select> | |
| </div> | |
| <div class="form-group"> | |
| <label for="prop-color">Text Color</label> | |
| <input type="color" id="prop-color" class="form-control h-10"> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="section"> | |
| <h3><i data-feather="layout"></i> Layout Actions</h3> | |
| <div class="form-group"> | |
| <input type="text" id="design-layout-name" placeholder="Layout name" class="form-control mb-2"> | |
| </div> | |
| <button id="btn-export-design" class="action-btn btn-secondary"> | |
| <i data-feather="save"></i> Export Layout | |
| </button> | |
| <button id="btn-save-design" class="action-btn btn-primary"> | |
| <i data-feather="database"></i> Save to History | |
| </button> | |
| <button id="btn-new-design" class="action-btn btn-secondary"> | |
| <i data-feather="file-plus"></i> New Layout | |
| </button> | |
| </div> | |
| </div> | |
| `; | |
| // Icons | |
| feather.replace(); | |
| } | |
| } | |
| customElements.define('app-sidebar', AppSidebar); | |