diff --git a/inventory/static/css/components/draw.css b/inventory/static/css/components/draw.css index 90a32be..d40b402 100644 --- a/inventory/static/css/components/draw.css +++ b/inventory/static/css/components/draw.css @@ -25,7 +25,7 @@ } .grid-widget [data-canvas] { - z-index: 9999; + z-index: 1; pointer-events: none; inset: 0; } @@ -38,7 +38,7 @@ .grid-widget [data-dot] { transform: translate(-50%, -50%); - z-index: 10000; + z-index: 2; pointer-events: none; } @@ -46,7 +46,7 @@ display: flex; flex-wrap: nowrap; overflow-x: auto; - overflow-y: hidden; + overflow-y: visible; gap: .5rem; align-items: center; } @@ -57,6 +57,26 @@ flex: 0 0 120px; } +.grid-widget .dropdown-menu { + z-index: 2000; + min-width: 220px; + padding: .5rem .75rem; + border-radius: .5rem; +} + +.grid-widget .dropdown-menu > *:first-child { + margin-top: 0; +} + +.grid-widget .dropdown-menu > *:last-child { + margin-bottom: 0; +} + +.grid-widget .dropdown-menu .form-range { + width: 100%; + margin: 0; +} + .grid-widget [data-toolbar] .badge, .grid-widget [data-toolbar] .input-group-text { white-space: nowrap; diff --git a/inventory/static/js/components/draw.js b/inventory/static/js/components/draw.js index f3682ec..7c7bfda 100644 --- a/inventory/static/js/components/draw.js +++ b/inventory/static/js/components/draw.js @@ -14,6 +14,11 @@ document.addEventListener('keydown', (e) => { function initGridWidget(root, opts = {}) { const DEFAULT_DOC = { version: 1, cellSize: 25, shapes: [] }; const MAX_HISTORY = 100; + const SHAPE_DEFAULTS = { + strokeWidth: 0.12, + strokeOpacity: 1, + fillOpacity: 1 + }; const canvasEl = root.querySelector('[data-canvas]'); const clearEl = root.querySelector('[data-clear]'); @@ -39,7 +44,7 @@ function initGridWidget(root, opts = {}) { if (cellSizeEl && cellSizeValEl) bindRangeWithLabel(cellSizeEl, cellSizeValEl, v => `${v}px`); if (fillOpacityEl && fillValEl) bindRangeWithLabel(fillOpacityEl, fillValEl, v => `${parseInt(Number(v) * 100)}%`); if (strokeOpacityEl && strokeValEl) bindRangeWithLabel(strokeOpacityEl, strokeValEl, v => `${parseInt(Number(v) * 100)}%`); - if (strokeWidthEl && widthValEl) bindRangeWithLabel(strokeWidthEl, widthValEl, v => `${parseInt(Number(v) * 100)}%`); + if (strokeWidthEl && widthValEl) bindRangeWithLabel(strokeWidthEl, widthValEl, v => `${parseInt(Number(v) * cellSizeEl.value)}p×`); const storageKey = opts.storageKey ?? 'gridDoc'; @@ -81,6 +86,22 @@ function initGridWidget(root, opts = {}) { let activePointerId = null; + toolBarEl.querySelectorAll('[data-bs-toggle="dropdown"]').forEach((toggle) => { + bootstrap.Dropdown.getOrCreateInstance(toggle, { + popperConfig(defaultConfig) { + return { + ...defaultConfig, + strategy: 'fixed', + modifiers: [ + ...(defaultConfig.modifiers || []), + { name: 'preventOverflow', options: { boundary: 'viewport' } }, + { name: 'flip', options: { boundary: 'viewport', padding: 8 } }, + ], + }; + }, + }); + }); + const api = { handleKeyDown(e) { const key = e.key.toLowerCase(); @@ -224,8 +245,8 @@ function initGridWidget(root, opts = {}) { if (!s || typeof s !== 'object' || !allowed.has(s.type)) return []; const color = typeof s.color === 'string' ? s.color : '#000000'; - const fillOpacity = clamp01(s.fillOpacity, 1); - const strokeOpacity = clamp01(s.strokeOpacity, 1); + const fillOpacity = clamp01(s.fillOpacity, SHAPE_DEFAULTS.fillOpacity); + const strokeOpacity = clamp01(s.strokeOpacity, SHAPE_DEFAULTS.strokeOpacity); if (s.type === 'line') { if (!['x1', 'y1', 'x2', 'y2'].every(k => isFiniteNum(s[k]))) return []; @@ -233,7 +254,7 @@ function initGridWidget(root, opts = {}) { type: 'line', x1: +s.x1, y1: +s.y1, x2: +s.x2, y2: +s.y2, color, - strokeWidth: normStroke(s.strokeWidth), + strokeWidth: normStroke(s.strokeWidth, SHAPE_DEFAULTS.strokeWidth), strokeOpacity }]; } @@ -250,7 +271,7 @@ function initGridWidget(root, opts = {}) { type: 'path', points, color, - strokeWidth: normStroke(s.strokeWidth, 0.12), + strokeWidth: normStroke(s.strokeWidth, SHAPE_DEFAULTS.strokeWidth), strokeOpacity }]; } @@ -263,7 +284,7 @@ function initGridWidget(root, opts = {}) { fill: !!s.fill, fillOpacity, strokeOpacity, - strokeWidth: normStroke(s.strokeWidth) + strokeWidth: normStroke(s.strokeWidth, SHAPE_DEFAULTS.strokeWidth) }]; }); } @@ -473,7 +494,7 @@ function initGridWidget(root, opts = {}) { ctx.save(); ctx.strokeStyle = shape.color || '#000000'; - ctx.lineWidth = Math.max(1, toPx(shape.strokeWidth ?? 0.12)); + ctx.lineWidth = Math.max(1, toPx(shape.strokeWidth ?? SHAPE_DEFAULTS.strokeWidth)); if (shape.type === 'rect' || shape.type === 'ellipse') { const x = toPx(shape.x); @@ -481,7 +502,7 @@ function initGridWidget(root, opts = {}) { const w = toPx(shape.w); const h = toPx(shape.h); - ctx.globalAlpha = clamp01(shape.strokeOpacity, 1); + ctx.globalAlpha = clamp01(shape.strokeOpacity, SHAPE_DEFAULTS.strokeOpacity); if (shape.type === 'rect') { ctx.strokeRect(x, y, w, h); } else { @@ -494,7 +515,7 @@ function initGridWidget(root, opts = {}) { ctx.globalAlpha = 1; if (shape.fill) { - ctx.globalAlpha = clamp01(shape.fillOpacity, 1); + ctx.globalAlpha = clamp01(shape.fillOpacity, SHAPE_DEFAULTS.fillOpacity); ctx.fillStyle = shape.color; if (shape.type === 'rect') { ctx.fillRect(x, y, w, h); @@ -514,7 +535,7 @@ function initGridWidget(root, opts = {}) { const x2 = toPx(shape.x2); const y2 = toPx(shape.y2); - ctx.globalAlpha = clamp01(shape.strokeOpacity, 1); + ctx.globalAlpha = clamp01(shape.strokeOpacity, SHAPE_DEFAULTS.strokeOpacity); ctx.beginPath(); ctx.moveTo(x1, y1); ctx.lineTo(x2, y2); @@ -523,9 +544,9 @@ function initGridWidget(root, opts = {}) { } else if (shape.type === 'path') { const toPx = (v) => v * cellSize; - ctx.globalAlpha = clamp01(shape.strokeOpacity, 1); + ctx.globalAlpha = clamp01(shape.strokeOpacity, SHAPE_DEFAULTS.strokeOpacity); - ctx.lineWidth = Math.max(1, toPx(shape.strokeWidth ?? 0.12)); + ctx.lineWidth = Math.max(1, toPx(shape.strokeWidth ?? SHAPE_DEFAULTS.strokeWidth)); ctx.lineJoin = 'round'; ctx.lineCap = 'round'; diff --git a/inventory/templates/components/draw.html b/inventory/templates/components/draw.html index a8d0ce8..88b8cb7 100644 --- a/inventory/templates/components/draw.html +++ b/inventory/templates/components/draw.html @@ -13,10 +13,11 @@ 25px -