Fix dropdown behavior.
This commit is contained in:
parent
d2061f5c1c
commit
6f175c103e
3 changed files with 68 additions and 23 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
|
|
|
|||
|
|
@ -13,10 +13,11 @@
|
|||
</svg>
|
||||
<span class="badge text-bg-secondary" data-cell-size-val>25px</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<ul class="dropdown-menu p-2">
|
||||
<li>
|
||||
<div class="small text-secondary mb-1">Cell Size</div>
|
||||
<input type="range" min="1" max="100" step="1" value="25" data-cell-size
|
||||
class="form-range toolbar-range">
|
||||
class="form-range w-100">
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
@ -30,10 +31,11 @@
|
|||
</svg>
|
||||
<span class="badge text-bg-secondary" data-fill-opacity-val>100%</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<ul class="dropdown-menu p-2">
|
||||
<li>
|
||||
<div class="small text-secondary mb-1">Fill Opacity</div>
|
||||
<input type="range" min="0" max="1" step="0.01" value="1" data-fill-opacity
|
||||
class="form-range toolbar-range">
|
||||
class="form-range w-100">
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
@ -47,10 +49,11 @@
|
|||
</svg>
|
||||
<span class="badge text-bg-secondary" data-stroke-opacity-val>100%</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<ul class="dropdown-menu p-2">
|
||||
<li>
|
||||
<div class="small text-secondary mb-1">Stroke Opacity</div>
|
||||
<input type="range" min="0" max="1" step="0.01" value="1" data-stroke-opacity
|
||||
class="form-range toolbar-range">
|
||||
class="form-range w-100">
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
@ -65,10 +68,11 @@
|
|||
</svg>
|
||||
<span class="badge text-bg-secondary" data-stroke-width-val>12%</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<ul class="dropdown-menu p-2">
|
||||
<li>
|
||||
<div class="small text-secondary mb-1">Stroke Width</div>
|
||||
<input type="range" min="0" max="1" step="0.01" value="0.12" data-stroke-width
|
||||
class="form-range toolbar-range">
|
||||
class="form-range w-100">
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue