Final fixes to CSS.
This commit is contained in:
parent
c51ef38d99
commit
6d711474df
4 changed files with 234 additions and 246 deletions
|
|
@ -1,258 +1,224 @@
|
||||||
:root {
|
:root { --tb-h: 34px; }
|
||||||
--tb-h: 34px;
|
|
||||||
|
/* =========================================================
|
||||||
|
GRID WIDGET (editor uses container queries, viewer does not)
|
||||||
|
========================================================= */
|
||||||
|
|
||||||
|
/* -------------------------
|
||||||
|
Shared basics (both modes)
|
||||||
|
------------------------- */
|
||||||
|
|
||||||
|
.grid-widget { /* no container-type here */ }
|
||||||
|
|
||||||
|
/* drawing stack */
|
||||||
|
.grid-widget [data-grid] {
|
||||||
|
position: relative;
|
||||||
|
margin-inline: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-widget {
|
/* Overlay elements */
|
||||||
container-type: inline-size;
|
.grid-widget [data-canvas],
|
||||||
|
.grid-widget [data-dot],
|
||||||
|
.grid-widget [data-coords] { position: absolute; }
|
||||||
|
|
||||||
|
.grid-widget [data-canvas]{
|
||||||
|
inset: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: block;
|
||||||
|
z-index: 1;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-widget [data-dot]{
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
z-index: 2;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-widget [data-coords]{
|
||||||
|
bottom: 10px;
|
||||||
|
left: 10px;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------
|
||||||
|
Toolbar styling
|
||||||
|
------------------------- */
|
||||||
|
|
||||||
|
.grid-widget [data-toolbar].toolbar{
|
||||||
|
display: grid !important;
|
||||||
|
grid-template-rows: auto auto;
|
||||||
|
align-content: start;
|
||||||
|
gap: 0.5rem;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-widget [data-toolbar] .toolbar-row{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
min-width: 0;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-widget [data-toolbar] .toolbar-row--primary,
|
||||||
|
.grid-widget [data-toolbar] .toolbar-row--secondary{
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-widget [data-toolbar] .toolbar-row--secondary{ opacity: 0.95; }
|
||||||
|
|
||||||
|
/* container query only matters in editor (set below) */
|
||||||
|
@container (min-width: 750px){
|
||||||
|
.grid-widget [data-toolbar].toolbar{
|
||||||
|
display: flex !important;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-widget [data-toolbar] .toolbar-row{ display: contents; }
|
||||||
|
|
||||||
|
.grid-widget [data-toolbar] .toolbar-row--primary,
|
||||||
|
.grid-widget [data-toolbar] .toolbar-row--secondary{ overflow: visible; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-widget [data-toolbar]::-webkit-scrollbar{ height: 8px; }
|
||||||
|
|
||||||
|
.grid-widget .toolbar-group{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.25rem;
|
||||||
|
padding: 0.25rem;
|
||||||
|
border: 1px solid rgba(0,0,0,0.08);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
background: rgba(0,0,0,0.02);
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-widget .btn,
|
||||||
|
.grid-widget .form-control,
|
||||||
|
.grid-widget .badge{ height: var(--tb-h); }
|
||||||
|
|
||||||
|
.grid-widget [data-toolbar] .badge,
|
||||||
|
.grid-widget [data-toolbar] .input-group-text{ white-space: nowrap; }
|
||||||
|
|
||||||
|
.grid-widget .toolbar .btn{
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-widget .toolbar .form-control-color{ width: var(--tb-h); padding: 0; }
|
||||||
|
|
||||||
|
.grid-widget .tb-btn{ flex-direction: column; gap: 2px; line-height: 1; }
|
||||||
|
.grid-widget .tb-btn small{ font-size: 11px; opacity: 0.75; }
|
||||||
|
|
||||||
|
.grid-widget .dropdown-toggle::after{ display: none; }
|
||||||
|
|
||||||
|
.grid-widget .toolbar .btn-group .btn{ border-radius: 0; }
|
||||||
|
.grid-widget .toolbar .btn-group .btn:first-child{
|
||||||
|
border-top-left-radius: 0.5rem;
|
||||||
|
border-bottom-left-radius: 0.5rem;
|
||||||
|
}
|
||||||
|
.grid-widget .toolbar .btn-group .btn:last-child{
|
||||||
|
border-top-right-radius: 0.5rem;
|
||||||
|
border-bottom-right-radius: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-widget .btn-check:checked + .btn{
|
||||||
|
background: rgba(0,0,0,0.08);
|
||||||
|
border-color: rgba(0,0,0,0.18);
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-widget .dropdown-menu{
|
||||||
|
min-width: 200px;
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
box-shadow: 0 10px 30px rgba(0,0,0,0.12);
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1000;
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-widget .dropdown-menu .form-range{ width: 100%; margin: 0; }
|
||||||
|
|
||||||
|
/* =========================================================
|
||||||
|
EDITOR MODE (needs container queries)
|
||||||
|
========================================================= */
|
||||||
|
|
||||||
|
.grid-widget[data-mode="editor"]{
|
||||||
|
container-type: inline-size; /* ONLY here */
|
||||||
min-width: 375px;
|
min-width: 375px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-widget .grid-wrap {
|
.grid-widget[data-mode="editor"] [data-grid-wrap]{
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
min-height: 375px;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
min-height: 375px;
|
|
||||||
z-index: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-widget [data-toolbar].toolbar {
|
.grid-widget[data-mode="editor"] [data-grid]{
|
||||||
display: grid !important;
|
|
||||||
grid-template-rows: auto auto;
|
|
||||||
align-content: start;
|
|
||||||
gap: .5rem;
|
|
||||||
overflow: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-widget [data-toolbar] .toolbar-row {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: .5rem;
|
|
||||||
min-width: 0;
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-widget [data-toolbar] .toolbar-row--primary,
|
|
||||||
.grid-widget [data-toolbar] .toolbar-row--secondary {
|
|
||||||
overflow-x: auto;
|
|
||||||
overflow-y: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-widget [data-toolbar] .toolbar-row--secondary {
|
|
||||||
opacity: .95;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-widget[data-mode="viewer"] {
|
|
||||||
display: inline-block;
|
|
||||||
height: auto;
|
|
||||||
min-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-widget[data-mode="viewer"] .grid-wrap {
|
|
||||||
flex: 0 0 auto;
|
|
||||||
min-height: 0;
|
|
||||||
width: fit-content;
|
|
||||||
overflow: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-widget[data-mode="viewer"] [data-grid]{
|
|
||||||
position: relative;
|
|
||||||
width: auto;
|
|
||||||
height: auto;
|
|
||||||
inset: auto;
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* WIDE: 1 row */
|
|
||||||
@container (min-width: 750px) {
|
|
||||||
.grid-widget [data-toolbar].toolbar {
|
|
||||||
display: flex !important;
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
align-items: center;
|
|
||||||
gap: .5rem;
|
|
||||||
overflow-x: auto;
|
|
||||||
overflow-y: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-widget [data-toolbar] .toolbar-row {
|
|
||||||
display: contents;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-widget [data-toolbar] .toolbar-row--primary,
|
|
||||||
.grid-widget [data-toolbar] .toolbar-row--secondary {
|
|
||||||
overflow: visible;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-widget [data-grid] {
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
cursor: crosshair;
|
inset: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
cursor: crosshair;
|
||||||
touch-action: none;
|
touch-action: none;
|
||||||
margin: 0 auto;
|
|
||||||
max-width: 100%;
|
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
inset: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-widget [data-canvas],
|
/* Editor: toolbar should match snapped grid width */
|
||||||
.grid-widget [data-coords],
|
.grid-widget[data-mode="editor"] [data-toolbar]{
|
||||||
.grid-widget [data-dot] {
|
width: var(--grid-maxw, 100%);
|
||||||
position: absolute;
|
margin-inline: auto; /* center it to match the centered grid */
|
||||||
|
max-width: 100%;
|
||||||
|
align-self: center; /* don't stretch full parent width */
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-widget [data-toolbar]::-webkit-scrollbar {
|
/* =========================================================
|
||||||
height: 8px;
|
VIEWER MODE (must shrink-wrap like an <img>)
|
||||||
z-index: 10;
|
========================================================= */
|
||||||
}
|
|
||||||
|
|
||||||
.grid-widget [data-grid-wrap] {
|
.grid-widget[data-mode="viewer"]{
|
||||||
|
/* explicitly undo any containment */
|
||||||
|
container-type: normal; /* <-- the money line */
|
||||||
|
contain: none;
|
||||||
|
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
flex: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-widget [data-coords] {
|
/* wrap is the sized box (JS sets px) */
|
||||||
bottom: 10px;
|
.grid-widget[data-mode="viewer"] [data-grid-wrap]{
|
||||||
pointer-events: none;
|
display: inline-block;
|
||||||
left: 10px;
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
line-height: 0; /* remove inline baseline gap */
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-widget [data-canvas] {
|
/* grid must be in-flow and fill wrap */
|
||||||
z-index: 1;
|
.grid-widget[data-mode="viewer"] [data-grid]{
|
||||||
pointer-events: none;
|
|
||||||
inset: 0;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
display: block;
|
display: block;
|
||||||
}
|
|
||||||
|
|
||||||
.grid-widget [data-dot] {
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
z-index: 2;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-widget .toolbar-range {
|
|
||||||
width: 120px;
|
|
||||||
margin: 0;
|
|
||||||
flex: 0 0 120px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-widget .dropdown-menu {
|
|
||||||
min-width: 200px;
|
|
||||||
padding: .5rem .75rem;
|
|
||||||
border-radius: .75rem;
|
|
||||||
box-shadow: 0 10px 30px rgba(0, 0, 0, .12);
|
|
||||||
position: absolute;
|
|
||||||
z-index: 1000 !important;
|
|
||||||
pointer-events: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.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%;
|
width: 100%;
|
||||||
margin: 0;
|
height: 100%;
|
||||||
|
cursor: default;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-widget [data-toolbar] .badge,
|
/* viewer hides editor-only overlays */
|
||||||
.grid-widget [data-toolbar] .input-group-text {
|
.grid-widget[data-mode="viewer"] [data-coords],
|
||||||
white-space: nowrap;
|
.grid-widget[data-mode="viewer"] [data-dot]{ display: none !important; }
|
||||||
}
|
|
||||||
|
|
||||||
.grid-widget [data-toolbar]>* {
|
|
||||||
align-self: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-widget [data-toolbar] .vr {
|
|
||||||
align-self: stretch;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-widget [data-toolbar] .btn-group,
|
|
||||||
.grid-widget [data-toolbar] .dropdown,
|
|
||||||
.grid-widget [data-toolbar] .vr {
|
|
||||||
flex: 0 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-widget .toolbar-group {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: .25rem;
|
|
||||||
padding: .25rem;
|
|
||||||
border: 1px solid rgba(0, 0, 0, .08);
|
|
||||||
border-radius: .5rem;
|
|
||||||
background: rgba(0, 0, 0, .02);
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-widget .btn,
|
|
||||||
.grid-widget .form-control,
|
|
||||||
.grid-widget .badge {
|
|
||||||
height: var(--tb-h);
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-widget .toolbar .btn {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
padding: 0 .5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-widget .toolbar .form-control-color {
|
|
||||||
width: var(--tb-h);
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-widget .tb-btn {
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 2px;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-widget .tb-btn small {
|
|
||||||
font-size: 11px;
|
|
||||||
opacity: .75;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-widget .dropdown-toggle::after {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-widget .toolbar .btn-group .btn {
|
|
||||||
border-radius: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-widget .toolbar .btn-group .btn:first-child {
|
|
||||||
border-top-left-radius: .5rem;
|
|
||||||
border-bottom-left-radius: .5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-widget .toolbar .btn-group .btn:last-child {
|
|
||||||
border-top-right-radius: .5rem;
|
|
||||||
border-bottom-right-radius: .5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-widget .btn-check:checked+.btn {
|
|
||||||
background: rgba(0, 0, 0, .08);
|
|
||||||
border-color: rgba(0, 0, 0, .18);
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-widget [data-toolbar],
|
|
||||||
.grid-widget [data-grid] {
|
|
||||||
margin-inline: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-widget [data-toolbar] {
|
|
||||||
max-width: var(--grid-maxw, 100%);
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,25 @@
|
||||||
(function bindGridGlobalKeydownOnce() {
|
(function bindGridGlobalOnce() {
|
||||||
if (window.__gridKeydownBound) return;
|
if (window.__gridGlobalBound) return;
|
||||||
window.__gridKeydownBound = true;
|
window.__gridGlobalBound = true;
|
||||||
|
|
||||||
window.activeGridWidget = null;
|
window.activeGridWidget = null;
|
||||||
|
|
||||||
|
// Keydown (undo/redo, escape)
|
||||||
document.addEventListener('keydown', (e) => {
|
document.addEventListener('keydown', (e) => {
|
||||||
const w = window.activeGridWidget;
|
const w = window.activeGridWidget;
|
||||||
if (!w) return;
|
if (!w || typeof w.handleKeyDown !== 'function') return;
|
||||||
w.handleKeyDown(e);
|
w.handleKeyDown(e);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Pointer finalize (for drawing finishing outside the element)
|
||||||
|
const forwardPointer = (e) => {
|
||||||
|
const w = window.activeGridWidget;
|
||||||
|
if (!w || typeof w.handleGlobalPointerUp !== 'function') return;
|
||||||
|
w.handleGlobalPointerUp(e);
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('pointerup', forwardPointer, { capture: true });
|
||||||
|
window.addEventListener('pointercancel', forwardPointer, { capture: true });
|
||||||
})();
|
})();
|
||||||
|
|
||||||
function initGridWidget(root, opts = {}) {
|
function initGridWidget(root, opts = {}) {
|
||||||
|
|
@ -190,6 +201,12 @@ function initGridWidget(root, opts = {}) {
|
||||||
ctx = canvasEl.getContext('2d');
|
ctx = canvasEl.getContext('2d');
|
||||||
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
||||||
|
|
||||||
|
ctx.save();
|
||||||
|
ctx.globalAlpha = 1;
|
||||||
|
ctx.fillStyle = "red";
|
||||||
|
ctx.fillRect(0, 0, 10, 10);
|
||||||
|
ctx.restore();
|
||||||
|
|
||||||
redrawAll();
|
redrawAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -280,6 +297,7 @@ function initGridWidget(root, opts = {}) {
|
||||||
if (!ctx || !shapes) return;
|
if (!ctx || !shapes) return;
|
||||||
|
|
||||||
clearCanvas();
|
clearCanvas();
|
||||||
|
|
||||||
ctx.save();
|
ctx.save();
|
||||||
if (mode !== 'editor') {
|
if (mode !== 'editor') {
|
||||||
ctx.translate(viewerOffset.x, viewerOffset.y);
|
ctx.translate(viewerOffset.x, viewerOffset.y);
|
||||||
|
|
@ -308,15 +326,15 @@ function initGridWidget(root, opts = {}) {
|
||||||
const hCells = b ? (b.maxY - b.minY + padCells * 2) : 10;
|
const hCells = b ? (b.maxY - b.minY + padCells * 2) : 10;
|
||||||
|
|
||||||
const wPx = Math.max(1, Math.ceil(wCells * cellSize));
|
const wPx = Math.max(1, Math.ceil(wCells * cellSize));
|
||||||
const wPy = Math.max(1, Math.ceil(hCells * cellSize));
|
const hPx = Math.max(1, Math.ceil(hCells * cellSize));
|
||||||
|
|
||||||
gridEl.style.width = `${wPx}px`;
|
gridEl.style.width = `${wPx}px`;
|
||||||
gridEl.style.height = `${wPy}px`;
|
gridEl.style.height = `${hPx}px`;
|
||||||
|
|
||||||
gridWrapEl.style.width = `${wPx}px`;
|
gridWrapEl.style.width = `${wPx}px`;
|
||||||
gridWrapEl.style.height = `${wPy}px`;
|
gridWrapEl.style.height = `${hPx}px`;
|
||||||
|
|
||||||
if(b) {
|
if (b) {
|
||||||
viewerOffset.x = (-b.minX + padCells) * cellSize;
|
viewerOffset.x = (-b.minX + padCells) * cellSize;
|
||||||
viewerOffset.y = (-b.minY + padCells) * cellSize;
|
viewerOffset.y = (-b.minY + padCells) * cellSize;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -465,6 +483,11 @@ function initGridWidget(root, opts = {}) {
|
||||||
currentShape = null;
|
currentShape = null;
|
||||||
redrawAll();
|
redrawAll();
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleGlobalPointerUp(e) {
|
||||||
|
// Only finalize if this widget is the active one (it should be)
|
||||||
|
finishPointer(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -565,6 +588,7 @@ function initGridWidget(root, opts = {}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function finishPointer(e) {
|
function finishPointer(e) {
|
||||||
|
if (window.activeGridWidget !== api) return;
|
||||||
if (!currentShape) return;
|
if (!currentShape) return;
|
||||||
if (activePointerId !== null && e.pointerId !== activePointerId) return;
|
if (activePointerId !== null && e.pointerId !== activePointerId) return;
|
||||||
|
|
||||||
|
|
@ -1004,8 +1028,6 @@ function initGridWidget(root, opts = {}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
gridEl.addEventListener('pointerup', finishPointer);
|
gridEl.addEventListener('pointerup', finishPointer);
|
||||||
window.addEventListener('pointerup', finishPointer);
|
|
||||||
window.addEventListener('pointercancel', finishPointer);
|
|
||||||
|
|
||||||
root.querySelectorAll('input[data-tool]').forEach((input) => {
|
root.querySelectorAll('input[data-tool]').forEach((input) => {
|
||||||
input.addEventListener('change', () => {
|
input.addEventListener('change', () => {
|
||||||
|
|
@ -1289,7 +1311,12 @@ function initGridWidget(root, opts = {}) {
|
||||||
if (mode !== 'editor') {
|
if (mode !== 'editor') {
|
||||||
const script = root.querySelector('[data-grid-doc]');
|
const script = root.querySelector('[data-grid-doc]');
|
||||||
if (script?.textContent?.trim()) {
|
if (script?.textContent?.trim()) {
|
||||||
try { api.setDoc(JSON.parse(script.textContent)); } catch { }
|
try {
|
||||||
|
const parsed = JSON.parse(script.textContent);
|
||||||
|
api.setDoc(parsed);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("viewer JSON.parse failed:", err, script.textContent);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -244,22 +244,23 @@
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
{% macro viewWidget(uid, json) %}
|
{% macro viewWidget(uid, json) %}
|
||||||
<div class="grid-widget" data-grid-widget data-mode="viewer" data-storage-key="gridDoc:{{ uid }}">
|
<span class="grid-widget" data-grid-widget data-mode="viewer" data-storage-key="gridDoc:{{ uid }}">
|
||||||
<div class="grid-wrap" data-grid-wrap>
|
<span class="grid-wrap" data-grid-wrap>
|
||||||
<span class="position-absolute p-0 m-0 d-none dot" data-dot>
|
<span class="position-absolute p-0 m-0 d-none dot" data-dot>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32" data-dot-svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32" data-dot-svg>
|
||||||
<circle cx="16" cy="16" r="4" fill="black" />
|
<circle cx="16" cy="16" r="4" fill="black" />
|
||||||
</svg>
|
</svg>
|
||||||
</span>
|
</span>
|
||||||
<div class="position-relative overflow-hidden grid" data-grid>
|
<span class="position-relative overflow-hidden grid" data-grid>
|
||||||
<div class="border border-black position-absolute d-none bg-warning-subtle px-1 py-0 user-select-none coords"
|
<span
|
||||||
data-coords></div>
|
class="border border-black position-absolute d-none bg-warning-subtle px-1 py-0 user-select-none coords"
|
||||||
<canvas class="position-absolute w-100 h-100" data-canvas></canvas>
|
data-coords></span>
|
||||||
</div>
|
<canvas class="position-absolute" data-canvas></canvas>
|
||||||
</div>
|
</span>
|
||||||
|
</span>
|
||||||
|
|
||||||
<script type="application/json" data-grid-doc>
|
<script type="application/json" data-grid-doc>
|
||||||
{{ json | safe }}
|
{{ json | safe }}
|
||||||
</script>
|
</script>
|
||||||
</div>
|
</span>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
@ -143,16 +143,10 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
{% endset %}
|
{% endset %}
|
||||||
<div class="row">
|
{{ draw.drawWidget('test1') }}
|
||||||
{#
|
I am testing a thing.
|
||||||
<div class="col" style="min-height: 80vh">
|
|
||||||
{{ draw.drawWidget('test1') }}
|
|
||||||
</div>
|
|
||||||
#}
|
|
||||||
<div class="col" style="min-height: 80vh">
|
|
||||||
{{ draw.viewWidget('test2', jsonImage) }}
|
{{ draw.viewWidget('test2', jsonImage) }}
|
||||||
</div>
|
The thing has been tested.
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block scriptincludes %}
|
{% block scriptincludes %}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue