/
diz
/
lens
Обзор
Документация
Войти
/
diz
/
lens
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/shared.css
184 строки
16 KB
Diman
feat: загрузка PDF перетаскиванием файла в окно (drag & drop) с оверлеем-индикатором; подсказка на стартовой карточке
03 авг 2026, 10:32
03 авг 2026, 10:32
305233a
Код
Авторство
О чём код?
* { margin:0; padding:0; box-sizing:border-box; } html,body { height:100%; overflow:hidden; } body { font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif; background:#f0f2f5; color:#1a1a2e; } #app { display:flex; flex-direction:column; height:100vh; } .toolbar { display:flex; flex-direction:column; gap:4px; align-items:center; background:#fff; padding:6px 14px; border-bottom:1px solid #e0e0e0; flex-shrink:0; } .toolbar-row { display:flex; flex-wrap:wrap; gap:6px; align-items:center; justify-content:center; } .toolbar-sep { width:1px; height:24px; background:#ddd; margin:0 4px; flex-shrink:0; } .file-label { display:inline-flex; align-items:center; height:28px; padding:0 12px; background:#e8ecf1; border-radius:5px; font-size:12px; cursor:pointer; white-space:nowrap; } .file-label:hover { background:#d0d7de; } .file-label.start-pulse { animation:labelPulse 2s infinite; box-shadow:0 0 0 0 #0d6efd; } @keyframes labelPulse { 50%{box-shadow:0 0 0 3px rgba(13,110,253,.45)} } .file-label input { display:none; } button { padding:0 12px; height:28px; border:1px solid #000; box-sizing:border-box; border-radius:5px; font-size:12px; cursor:pointer; background:#e8ecf1; color:#1a1a2e; white-space:nowrap; display:inline-flex; align-items:center; justify-content:center; gap:5px; } button:hover { background:#d0d7de; } button:disabled { opacity:.5; cursor:default; } button.danger { background:#dc3545; color:#fff; } button.danger:hover { background:#bb2d3b; } button.success { background:#198754; color:#fff; } button.success:hover { background:#157347; } button.primary { background:#0d6efd; color:#fff; } button.primary:hover { background:#0b5ed7; } button.primary:disabled { background:#89b5f7; cursor:default; } button.active { background:#0d6efd; color:#fff; } .smode { font-size:11px; padding:0 8px; height:24px; } .smode.active { background:#0d6efd; color:#fff; } .mode-tab { font-weight:600; font-size:13px; padding:0 16px; border-radius:5px 5px 0 0; height:28px; } .mode-tab.active { background:#1a1a2e; color:#fff; } .mode-tab.active:hover { background:#333; } .page-ind { min-width:54px; height:28px; display:inline-flex; align-items:center; justify-content:center; background:#e8ecf1; border-radius:5px; font-size:13px; font-weight:600; } .cgroup { display:flex; align-items:center; gap:6px; font-size:12px; color:#555; } .color-btn { width:18px; height:18px; border-radius:50%; border:2px solid #ddd; cursor:pointer; padding:0; flex-shrink:0; } .color-btn.active { border-color:#1a1a2e; box-shadow:0 0 0 2px #fff,0 0 0 3px #1a1a2e; } input[type=color] { width:26px; height:24px; border:1px solid #ccc; border-radius:4px; padding:0; cursor:pointer; background:#fff; } input[type=color]:disabled { opacity:.5; cursor:default; } .slider-group { display:flex; align-items:center; gap:6px; font-size:12px; } .slider-group input[type=range] { width:100px; height:4px; cursor:pointer; -webkit-appearance:none; appearance:none; background:#d0d7de; border-radius:4px; outline:none; } .slider-group input[type=range]::-webkit-slider-thumb { -webkit-appearance:none; width:16px; height:16px; border-radius:50%; background:#0d6efd; cursor:pointer; border:2px solid #fff; box-shadow:0 1px 3px rgba(0,0,0,.25); } .slider-value { font-weight:400; min-width:36px; text-align:center; font-size:12px; color:#000; } .bg-toggle { font-size:12px; color:#555; display:inline-flex; align-items:center; gap:4px; cursor:pointer; user-select:none; } .bg-toggle input { margin:0; cursor:pointer; } .mode-controls { display:none; align-items:center; gap:6px; } .mode-controls.active { display:flex; } .main-area { position:relative; flex:1; min-height:0; } .side-panel { position:absolute; left:0; top:0; bottom:0; width:280px; display:none; flex-direction:column; gap:8px; padding:10px; background:#fff; border-right:1px solid #e0e0e0; z-index:30; } .side-panel.visible { display:flex; } .side-panel label { font-size:12px; font-weight:600; color:#444; } .side-panel textarea { flex:1; font-family:'Consolas','Courier New',monospace; font-size:13px; padding:8px; border:1px solid #ccc; border-radius:6px; resize:none; outline:none; background:#fafbfc; } .side-panel textarea:focus { border-color:#0d6efd; box-shadow:0 0 0 2px rgba(13,110,253,.15); } .side-panel .btn-group { display:flex; flex-wrap:wrap; gap:6px; } .side-panel .btn-group button { flex:1; } .canvas-wrap { position:relative; overflow:hidden; background:#e8ecf1; width:100%; height:100%; cursor:grab; user-select:none; } .canvas-wrap.grabbing { cursor:grabbing; } .canvas-wrap.drawmode, .canvas-wrap.selectmode, .canvas-wrap.selecting { cursor:crosshair; } .tg { position:absolute; top:0; left:0; transform-origin:0 0; } canvas { display:block; } #labelCanvas { position:absolute; top:0; left:0; pointer-events:none; z-index:20; } .overlay { position:absolute; top:0; left:0; pointer-events:none; } .cbox { position:absolute; border:1.5px solid rgba(220,53,69,.9); background:rgba(220,53,69,.10); pointer-events:auto; cursor:pointer; box-sizing:border-box; } .cbox:hover { background:rgba(220,53,69,.22); } .cbox.sel { border-color:#0d6efd; background:rgba(13,110,253,.18); border-width:2px; } .cbox.del { border-style:dashed; border-color:#888; background:rgba(120,120,120,.18); } .cbox.hidden { border-style:dashed; border-color:#999; background:rgba(150,150,150,.12); opacity:0.4; pointer-events:auto; cursor:pointer; } .cbox.hidden:hover { opacity:0.7; } .white-rect { position:absolute; background:#fff; border:1px solid #ddd; pointer-events:auto; z-index:auto; } .white-rect-preview { position:absolute; background:rgba(255,255,255,0.55); border:1.5px dashed #555; pointer-events:none; z-index:4; } .selection-overlay { position:absolute; border:2px solid #0d6efd; background:rgba(13,110,253,0.08); pointer-events:none; z-index:10; display:none; } .start-instruction { position:absolute; inset:0; display:flex; align-items:center; justify-content:center; z-index:20; background:#f0f2f5; } .start-card { background:#fff; border-radius:14px; padding:36px 44px; max-width:480px; text-align:center; box-shadow:0 6px 24px rgba(0,0,0,.08); } .start-card h1 { font-size:28px; font-weight:700; margin-bottom:6px; color:#1a1a2e; } .start-sub { font-size:15px; color:#555; margin-bottom:18px; } .start-list { list-style:none; padding:0; text-align:left; margin-bottom:22px; } .start-list li { padding:8px 0 8px 24px; font-size:14px; color:#333; line-height:1.5; position:relative; } .start-list li::before { content:'•'; position:absolute; left:6px; color:#0d6efd; font-weight:700; font-size:18px; } .start-list li strong { color:#1a1a2e; } .version { font-size:12px; color:#888; margin-top:-4px; margin-bottom:10px; } .start-highlight { font-size:15px; font-weight:700; color:#0d6efd; background:#eef3fe; padding:10px 20px; border-radius:8px; display:inline-block; animation:pulse 2s infinite; } @keyframes pulse { 0%,100%{transform:scale(1)} 50%{transform:scale(1.04)} } .zoom-ind { position:absolute; bottom:10px; right:12px; background:rgba(0,0,0,.55); color:#fff; padding:2px 8px; border-radius:4px; font-size:11px; pointer-events:none; } .status-bar { display:flex; align-items:center; justify-content:center; gap:8px; padding:5px 14px; background:#fff; border-top:1px solid #e0e0e0; flex-shrink:0; } .status { font-size:12px; color:#555; text-align:center; cursor:default; } .copy-btn { font-size:11px; padding:0 8px; height:22px; border:1px solid #ccc; border-radius:4px; background:#f5f5f5; cursor:pointer; white-space:nowrap; display:none; } .copy-btn:hover { background:#e8e8e8; } .copy-btn.visible { display:inline-flex; align-items:center; } .dl-site-btn { font-size:13px; padding:0; width:22px; height:22px; border:1px solid #ccc; border-radius:4px; background:#f5f5f5; cursor:pointer; display:inline-flex; align-items:center; justify-content:center; margin-left:auto; flex-shrink:0; } .dl-site-btn:hover { background:#e8e8e8; } .toast { position:fixed; bottom:30px; left:50%; transform:translateX(-50%); background:#1a1a2e; color:#fff; padding:8px 22px; border-radius:8px; font-size:13px; opacity:0; transition:opacity .25s; pointer-events:none; z-index:999; } .toast.show { opacity:1; } /* Оверлей перетаскивания PDF: рамка + карточка «Отпустите файл» */ .drop-overlay { position:fixed; inset:0; display:none; align-items:center; justify-content:center; background:rgba(13,110,253,.08); z-index:950; pointer-events:none; } .drop-overlay.show { display:flex; } .drop-overlay-card { display:flex; flex-direction:column; align-items:center; gap:6px; padding:28px 48px; background:#fff; border-radius:14px; box-shadow:0 8px 32px rgba(0,0,0,.18); border:2px dashed #0d6efd; color:#333; font-size:14px; } .drop-overlay-card strong { font-size:17px; color:#0d6efd; } .drop-overlay-card span { font-size:13px; color:#666; } .loading-overlay { position:fixed; inset:0; background:rgba(0,0,0,.45); display:none; flex-direction:column; align-items:center; justify-content:center; gap:14px; z-index:1000; color:#fff; font-size:15px; } .loading-spinner { width:32px; height:32px; border:3px solid rgba(255,255,255,.3); border-top-color:#fff; border-radius:50%; animation:spin .7s linear infinite; } @keyframes spin { to { transform:rotate(360deg); } } /* Индикатор перерисовки слоёв при relevel-зуме: спиннер на тёмной подложке по центру, не блокирует события (pointer-events:none) */ .render-waiting { position:fixed; inset:0; display:none; align-items:center; justify-content:center; z-index:900; pointer-events:none; } .render-waiting.show { display:flex; } .render-waiting-card { display:flex; align-items:center; justify-content:center; padding:16px 26px; background:rgba(20,24,36,.78); border-radius:10px; box-shadow:0 4px 20px rgba(0,0,0,.25); } .side-panel.right { left:auto; right:0; border-right:none; border-left:1px solid #e0e0e0; } .layers-header { font-weight:600; padding:8px 10px; border-bottom:1px solid #e0e0e0; font-size:13px; color:#333; flex-shrink:0; } #layersList { overflow-y:auto; flex:1; padding:4px 0; } .layer-item { display:flex; align-items:center; gap:6px; padding:3px 10px; cursor:pointer; font-size:13px; color:#333; user-select:none; } .layer-item:hover { background:#f0f4f8; } .layer-item input { margin:0; cursor:pointer; } /* ── Overlay image canvas (between PDF and labels) ── */ #overlayImageCanvas { position:absolute; top:0; left:0; pointer-events:none; z-index:10; } /* ── Image overlay dialog ── */ .overlay-dialog { position:fixed; inset:0; background:rgba(0,0,0,.45); display:flex; align-items:center; justify-content:center; z-index:500; } .overlay-dialog-content { background:#fff; border-radius:12px; width:680px; max-width:90vw; max-height:90vh; display:flex; flex-direction:column; box-shadow:0 8px 32px rgba(0,0,0,.2); } .overlay-dialog-header { display:flex; align-items:center; justify-content:space-between; padding:14px 18px; border-bottom:1px solid #e0e0e0; } .overlay-dialog-header h3 { font-size:15px; font-weight:700; margin:0; } .overlay-close-btn { width:28px; height:28px; border:none; background:none; font-size:20px; cursor:pointer; border-radius:4px; display:flex; align-items:center; justify-content:center; } .overlay-close-btn:hover { background:#f0f0f0; } .overlay-dialog-body { padding:14px 18px; flex:1; overflow-y:auto; display:flex; flex-direction:column; gap:12px; } .overlay-dialog-hint { font-size:12px; color:#555; line-height:1.5; margin:0; } .overlay-img-section { margin:0; } .overlay-file-label { display:inline-flex; align-items:center; height:30px; padding:0 14px; background:#e8ecf1; border-radius:5px; font-size:12px; cursor:pointer; white-space:nowrap; } .overlay-file-label:hover { background:#d0d7de; } .overlay-file-label input { display:none; } .overlay-canvas-wrap { position:relative; width:100%; height:380px; background:#f0f2f5; border:1px solid #ddd; border-radius:6px; overflow:hidden; cursor:crosshair; } .overlay-canvas-wrap canvas { display:block; width:100%; height:100%; } .overlay-status { font-size:12px; color:#666; margin:0; min-height:18px; } .overlay-dialog-footer { display:flex; justify-content:flex-end; gap:8px; padding:12px 18px; border-top:1px solid #e0e0e0; } .overlay-step-indicator { font-size:13px; font-weight:600; color:#333; text-align:center; min-height:22px; } .overlay-step-indicator .step-dots { display:inline-flex; gap:6px; margin-left:8px; vertical-align:middle; } .overlay-step-indicator .step-dot { display:inline-flex; align-items:center; justify-content:center; width:22px; height:22px; border-radius:50%; font-size:11px; font-weight:700; background:#e0e0e0; color:#888; } .overlay-step-indicator .step-dot.done { background:#0d6efd; color:#fff; } .overlay-step-indicator .step-dot.current { background:#ffc107; color:#333; box-shadow:0 0 0 2px rgba(255,193,7,.4); } /* ── Prepare Image Modal (перспективное выравнивание) ── */ .prepare-modal { position:fixed; inset:0; background:rgba(0,0,0,.5); display:flex; align-items:center; justify-content:center; z-index:600; } .prepare-modal-content { background:#2c2c2c; border-radius:10px; width:95vw; max-width:1400px; height:92vh; display:flex; flex-direction:column; box-shadow:0 8px 40px rgba(0,0,0,.4); color:#e0e0e0; } .prepare-modal-header { display:flex; align-items:center; justify-content:space-between; padding:10px 16px; border-bottom:1px solid #444; flex-shrink:0; } .prepare-modal-header h3 { font-size:15px; font-weight:600; margin:0; } .prepare-modal-body { flex:1; display:flex; flex-direction:column; padding:10px; gap:8px; min-height:0; } .prepare-modal-footer { display:flex; justify-content:flex-end; gap:8px; padding:10px 16px; border-top:1px solid #444; flex-shrink:0; } .prepare-toolbar { display:flex; flex-wrap:wrap; gap:6px; align-items:center; flex-shrink:0; } .prepare-toolbar button { height:28px; padding:0 10px; display:inline-flex; align-items:center; } .prepare-toolbar .file-label { background:#3a3a3a; color:#e0e0e0; height:28px; font-size:12px; } .prepare-toolbar .file-label:hover { background:#4a4a4a; } /* Акцентная кнопка «Выбрать изображение» — первое действие в модалке */ .prepare-toolbar .file-label.modal-file-cta { background:#0d6efd; color:#fff; font-weight:600; box-shadow:0 0 0 3px rgba(13,110,253,.25), 0 2px 8px rgba(0,0,0,.35); transition:background .15s, box-shadow .15s; } .prepare-toolbar .file-label.modal-file-cta:hover { background:#0b5ed7; box-shadow:0 0 0 3px rgba(13,110,253,.4), 0 4px 12px rgba(0,0,0,.4); } .prepare-panels { flex:1; display:flex; gap:8px; min-height:0; } .prepare-panel { flex:1; background:#1e1e1e; border-radius:6px; display:flex; flex-direction:column; overflow:hidden; min-width:0; } .prepare-panel .panel-header { padding:6px 10px; font-size:12px; font-weight:600; background:#2a2a2a; border-bottom:1px solid #444; flex-shrink:0; } .prepare-panel .panel-hint { font-weight:400; color:#888; font-size:11px; } .prepare-panel .panel-body { flex:1; position:relative; overflow:hidden; background:#333; } .prepare-panel .panel-body canvas { position:absolute; top:0; left:0; width:100%; height:100%; } .prepare-panel .zoom-ind { position:absolute; bottom:6px; right:8px; background:rgba(0,0,0,.6); color:#fff; padding:1px 6px; border-radius:3px; font-size:10px; pointer-events:none; z-index:5; } .prepare-status { font-size:12px; color:#888; margin:0; text-align:center; flex-shrink:0; padding:2px 0; } .prepare-modal-footer button { padding:0 14px; height:28px; box-sizing:border-box; border:1px solid #000; border-radius:5px; font-size:12px; cursor:pointer; background:#3a3a3a; color:#e0e0e0; } .prepare-modal-footer button:hover { background:#4a4a4a; } .prepare-modal-footer button.primary { background:#0d6efd; color:#fff; } .prepare-modal-footer button.primary:hover { background:#0b5ed7; } .prepare-modal-footer button.primary:disabled { background:#3a6a9f; cursor:default; } .prepare-pdf-hint { font-size:11px; color:#888; margin-right:auto; align-self:center; } .btn-wrapper { display:flex; align-items:center; } .btn-wrapper[title] { cursor:help; }