@daydreamui/grid-editor 0.0.0-stage → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1493 -0
- package/icon.svg +5 -0
- package/manifest.json +14 -0
- package/package.json +15 -4
- package/README.md +0 -3
package/dist/index.js
ADDED
|
@@ -0,0 +1,1493 @@
|
|
|
1
|
+
import { className, createComponent, delegateEvents, effect, insert, ref, setAttribute, setStyleProperty, template } from "@solidjs/web";
|
|
2
|
+
import { For, Show, createEffect, createMemo, createSignal, onSettled, untrack } from "solid-js";
|
|
3
|
+
var leading = (band, reversed) => reversed ? band.end : band.start;
|
|
4
|
+
var trailing = (band, reversed) => reversed ? band.start : band.end;
|
|
5
|
+
function trackEdges(axis) {
|
|
6
|
+
const edges = [];
|
|
7
|
+
for (const band of axis.bands) edges.push(band.start, band.end);
|
|
8
|
+
edges.sort((a, b) => a - b);
|
|
9
|
+
return edges.filter((edge, i) => i === 0 || edge - edges[i - 1] > 1e-6);
|
|
10
|
+
}
|
|
11
|
+
function lineAnchors(axis) {
|
|
12
|
+
const { bands, reversed } = axis;
|
|
13
|
+
const anchors = [];
|
|
14
|
+
for (const [i, band] of bands.entries()) {
|
|
15
|
+
const prev = bands[i - 1];
|
|
16
|
+
anchors.push(prev === void 0 ? leading(band, reversed) : (trailing(prev, reversed) + leading(band, reversed)) / 2);
|
|
17
|
+
}
|
|
18
|
+
const last = bands[bands.length - 1];
|
|
19
|
+
if (last !== void 0) anchors.push(trailing(last, reversed));
|
|
20
|
+
return anchors;
|
|
21
|
+
}
|
|
22
|
+
function gapsOf(axis) {
|
|
23
|
+
const sorted = [...axis.bands].sort((a, b) => a.start - b.start);
|
|
24
|
+
const gaps = [];
|
|
25
|
+
for (const [i, band] of sorted.entries()) {
|
|
26
|
+
const prev = sorted[i - 1];
|
|
27
|
+
if (prev !== void 0 && band.start - prev.end > 1e-6) gaps.push({
|
|
28
|
+
start: prev.end,
|
|
29
|
+
end: band.start
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
return gaps;
|
|
33
|
+
}
|
|
34
|
+
function trackSpan(axis) {
|
|
35
|
+
if (axis.bands.length === 0) return null;
|
|
36
|
+
return {
|
|
37
|
+
start: Math.min(...axis.bands.map((band) => band.start)),
|
|
38
|
+
end: Math.max(...axis.bands.map((band) => band.end))
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function parseTrackSizes(value) {
|
|
42
|
+
if (value === "none" || value === "") return [];
|
|
43
|
+
const sizes = [];
|
|
44
|
+
for (const token of value.replace(/\[[^\]]*\]/g, " ").trim().split(/\s+/)) {
|
|
45
|
+
if (token === "") continue;
|
|
46
|
+
const px = token.endsWith("px") ? Number.parseFloat(token) : NaN;
|
|
47
|
+
if (Number.isNaN(px)) return null;
|
|
48
|
+
sizes.push(px);
|
|
49
|
+
}
|
|
50
|
+
return sizes;
|
|
51
|
+
}
|
|
52
|
+
function parsePx(value) {
|
|
53
|
+
if (value === "normal") return 0;
|
|
54
|
+
if (!value.endsWith("px")) return null;
|
|
55
|
+
const px = Number.parseFloat(value);
|
|
56
|
+
return Number.isNaN(px) ? null : px;
|
|
57
|
+
}
|
|
58
|
+
function parseGap(value, contentSize) {
|
|
59
|
+
if (value.endsWith("%")) {
|
|
60
|
+
const pct = Number.parseFloat(value);
|
|
61
|
+
return Number.isNaN(pct) ? null : pct / 100 * contentSize;
|
|
62
|
+
}
|
|
63
|
+
return parsePx(value);
|
|
64
|
+
}
|
|
65
|
+
function distribute(keyword, free, count, options = {}) {
|
|
66
|
+
const none = {
|
|
67
|
+
offset: 0,
|
|
68
|
+
between: 0
|
|
69
|
+
};
|
|
70
|
+
if (count === 0) return none;
|
|
71
|
+
const safe = /^safe\s/.test(keyword);
|
|
72
|
+
let word = keyword.replace(/^(safe|unsafe)\s+/, "");
|
|
73
|
+
if (word === "left") word = options.rtl === true ? "end" : "start";
|
|
74
|
+
else if (word === "right") word = options.rtl === true ? "start" : "end";
|
|
75
|
+
const held = (offset) => ({
|
|
76
|
+
offset: safe ? Math.max(0, offset) : offset,
|
|
77
|
+
between: 0
|
|
78
|
+
});
|
|
79
|
+
switch (word) {
|
|
80
|
+
case "center": return held(free / 2);
|
|
81
|
+
case "end":
|
|
82
|
+
case "flex-end": return held(free);
|
|
83
|
+
case "space-between": return free > 0 && count > 1 ? {
|
|
84
|
+
offset: 0,
|
|
85
|
+
between: free / (count - 1)
|
|
86
|
+
} : none;
|
|
87
|
+
case "space-around": return free > 0 ? {
|
|
88
|
+
offset: free / count / 2,
|
|
89
|
+
between: free / count
|
|
90
|
+
} : none;
|
|
91
|
+
case "space-evenly": return free > 0 ? {
|
|
92
|
+
offset: free / (count + 1),
|
|
93
|
+
between: free / (count + 1)
|
|
94
|
+
} : none;
|
|
95
|
+
default: return none;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function layOutBands(sizes, gap, origin, zoom, placement = {
|
|
99
|
+
offset: 0,
|
|
100
|
+
between: 0
|
|
101
|
+
}, reversed = false, extent = 0) {
|
|
102
|
+
const bands = [];
|
|
103
|
+
let pos = placement.offset;
|
|
104
|
+
for (const size of sizes) {
|
|
105
|
+
if (bands.length > 0) pos += gap + placement.between;
|
|
106
|
+
const start = pos;
|
|
107
|
+
const end = pos + size;
|
|
108
|
+
bands.push(reversed ? {
|
|
109
|
+
start: origin + (extent - end) * zoom,
|
|
110
|
+
end: origin + (extent - start) * zoom
|
|
111
|
+
} : {
|
|
112
|
+
start: origin + start * zoom,
|
|
113
|
+
end: origin + end * zoom
|
|
114
|
+
});
|
|
115
|
+
pos = end;
|
|
116
|
+
}
|
|
117
|
+
return bands;
|
|
118
|
+
}
|
|
119
|
+
function readGridGeometry(dd, elementId) {
|
|
120
|
+
const rect = dd.geometry.rect(elementId);
|
|
121
|
+
const node = dd.geometry.node(elementId);
|
|
122
|
+
if (rect === null || node === void 0) return null;
|
|
123
|
+
const style = getComputedStyle(node);
|
|
124
|
+
if (style.display !== "grid" && style.display !== "inline-grid") return null;
|
|
125
|
+
if (style.writingMode !== "horizontal-tb") return null;
|
|
126
|
+
const { zoom } = dd.geometry.camera();
|
|
127
|
+
const colSizes = parseTrackSizes(style.gridTemplateColumns);
|
|
128
|
+
const rowSizes = parseTrackSizes(style.gridTemplateRows);
|
|
129
|
+
const edges = [
|
|
130
|
+
style.borderLeftWidth,
|
|
131
|
+
style.borderTopWidth,
|
|
132
|
+
style.paddingLeft,
|
|
133
|
+
style.paddingTop,
|
|
134
|
+
style.borderRightWidth,
|
|
135
|
+
style.borderBottomWidth,
|
|
136
|
+
style.paddingRight,
|
|
137
|
+
style.paddingBottom
|
|
138
|
+
].map(parsePx);
|
|
139
|
+
if (colSizes === null || rowSizes === null || edges.some((e) => e === null)) return null;
|
|
140
|
+
const [bl, bt, pl, pt, br, bb, pr, pb] = edges;
|
|
141
|
+
const contentWidth = rect.width / zoom - (bl + br + pl + pr);
|
|
142
|
+
const contentHeight = rect.height / zoom - (bt + bb + pt + pb);
|
|
143
|
+
const colGap = parseGap(style.columnGap, contentWidth);
|
|
144
|
+
const rowGap = parseGap(style.rowGap, contentHeight);
|
|
145
|
+
if (colGap === null || rowGap === null) return null;
|
|
146
|
+
const contentX = rect.x + (bl + pl - node.scrollLeft) * zoom;
|
|
147
|
+
const contentY = rect.y + (bt + pt - node.scrollTop) * zoom;
|
|
148
|
+
const used = (sizes, gap) => sizes.reduce((a, v) => a + v, 0) + gap * Math.max(0, sizes.length - 1);
|
|
149
|
+
const cols = distribute(style.justifyContent, contentWidth - used(colSizes, colGap), colSizes.length, { rtl: style.direction === "rtl" });
|
|
150
|
+
const rows = distribute(style.alignContent, contentHeight - used(rowSizes, rowGap), rowSizes.length, {});
|
|
151
|
+
const rtl = style.direction === "rtl";
|
|
152
|
+
return {
|
|
153
|
+
cols: {
|
|
154
|
+
sizes: colSizes,
|
|
155
|
+
gap: colGap,
|
|
156
|
+
bands: layOutBands(colSizes, colGap, contentX, zoom, cols, rtl, contentWidth),
|
|
157
|
+
reversed: rtl
|
|
158
|
+
},
|
|
159
|
+
rows: {
|
|
160
|
+
sizes: rowSizes,
|
|
161
|
+
gap: rowGap,
|
|
162
|
+
bands: layOutBands(rowSizes, rowGap, contentY, zoom, rows),
|
|
163
|
+
reversed: false
|
|
164
|
+
},
|
|
165
|
+
rect,
|
|
166
|
+
zoom
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
function lineNumber(value, explicit) {
|
|
170
|
+
const match = /^(-?\d+)$/.exec(value.trim());
|
|
171
|
+
if (match === null) return null;
|
|
172
|
+
const n = Number(match[1]);
|
|
173
|
+
return n < 0 ? explicit + 2 + n : n;
|
|
174
|
+
}
|
|
175
|
+
function gridItems(node) {
|
|
176
|
+
const items = [];
|
|
177
|
+
for (const child of node.children) {
|
|
178
|
+
const style = getComputedStyle(child);
|
|
179
|
+
if (style.display === "none") continue;
|
|
180
|
+
if (style.display === "contents") items.push(...gridItems(child));
|
|
181
|
+
else if (style.position !== "absolute" && style.position !== "fixed") items.push(child);
|
|
182
|
+
}
|
|
183
|
+
return items;
|
|
184
|
+
}
|
|
185
|
+
function startsBeforeFirst(node, axis, explicit) {
|
|
186
|
+
const [startProperty, endProperty] = axis === "cols" ? ["grid-column-start", "grid-column-end"] : ["grid-row-start", "grid-row-end"];
|
|
187
|
+
for (const child of gridItems(node)) {
|
|
188
|
+
const style = getComputedStyle(child);
|
|
189
|
+
const startText = style.getPropertyValue(startProperty).trim();
|
|
190
|
+
const endText = style.getPropertyValue(endProperty).trim();
|
|
191
|
+
const start = lineNumber(startText, explicit);
|
|
192
|
+
const end = lineNumber(endText, explicit);
|
|
193
|
+
const span = /^span\s+(\d+)$/.exec(startText);
|
|
194
|
+
let first = null;
|
|
195
|
+
if (start !== null) first = end === null ? start : Math.min(start, end);
|
|
196
|
+
else if (end !== null) first = end - (span === null ? 1 : Number(span[1]));
|
|
197
|
+
if (first !== null && first < 1) return true;
|
|
198
|
+
}
|
|
199
|
+
return false;
|
|
200
|
+
}
|
|
201
|
+
function selectedGrid(dd, selectedId) {
|
|
202
|
+
const version = dd.geometry.version();
|
|
203
|
+
const cached = reads.get(dd);
|
|
204
|
+
if (cached?.version === version && cached.selectedId === selectedId) return cached.grid;
|
|
205
|
+
const grid = read(dd, selectedId);
|
|
206
|
+
reads.set(dd, {
|
|
207
|
+
version,
|
|
208
|
+
selectedId,
|
|
209
|
+
grid
|
|
210
|
+
});
|
|
211
|
+
return grid;
|
|
212
|
+
}
|
|
213
|
+
var reads = new WeakMap();
|
|
214
|
+
function read(dd, selectedId) {
|
|
215
|
+
const found = (gridId) => {
|
|
216
|
+
const geometry = readGridGeometry(dd, gridId);
|
|
217
|
+
return geometry === null ? null : {
|
|
218
|
+
gridId,
|
|
219
|
+
geometry
|
|
220
|
+
};
|
|
221
|
+
};
|
|
222
|
+
const own = found(selectedId);
|
|
223
|
+
if (own !== null) return own;
|
|
224
|
+
const parent = dd.pageElement(selectedId)?.parentId ?? null;
|
|
225
|
+
return parent === null ? null : found(parent);
|
|
226
|
+
}
|
|
227
|
+
var classPrefix = (pluginId) => pluginId.replace(/[^A-Za-z0-9_-]/g, "-");
|
|
228
|
+
var guidesCss = (p) => `
|
|
229
|
+
.${p}-guides {
|
|
230
|
+
position: absolute;
|
|
231
|
+
inset: 0;
|
|
232
|
+
width: 100%;
|
|
233
|
+
height: 100%;
|
|
234
|
+
overflow: visible;
|
|
235
|
+
pointer-events: none;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.${p}-line {
|
|
239
|
+
stroke: color-mix(in srgb, var(--dream-app-accent, #4c9aff) 55%, transparent);
|
|
240
|
+
stroke-width: 1;
|
|
241
|
+
stroke-dasharray: 4 3;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.${p}-gap-band {
|
|
245
|
+
fill: url(#${p}-gap-hatch);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.${p}-hatch-line {
|
|
249
|
+
stroke: color-mix(in srgb, var(--dream-app-accent, #4c9aff) 28%, transparent);
|
|
250
|
+
stroke-width: 1;
|
|
251
|
+
fill: none;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
.${p}-badge {
|
|
255
|
+
fill: color-mix(in srgb, var(--dream-app-raised, #172233) 85%, transparent);
|
|
256
|
+
stroke: color-mix(in srgb, var(--dream-app-accent, #4c9aff) 45%, transparent);
|
|
257
|
+
stroke-width: 1;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.${p}-badge-text {
|
|
261
|
+
fill: var(--dream-app-accent, #a8ccff);
|
|
262
|
+
font-family: var(--dream-app-mono, monospace);
|
|
263
|
+
font-size: 9px;
|
|
264
|
+
text-anchor: middle;
|
|
265
|
+
dominant-baseline: central;
|
|
266
|
+
}
|
|
267
|
+
`;
|
|
268
|
+
var handlesCss = (p) => `
|
|
269
|
+
.${p}-layer {
|
|
270
|
+
position: absolute;
|
|
271
|
+
left: 0;
|
|
272
|
+
top: 0;
|
|
273
|
+
width: 0;
|
|
274
|
+
height: 0;
|
|
275
|
+
overflow: visible;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
.${p}-handle {
|
|
279
|
+
position: absolute;
|
|
280
|
+
box-sizing: border-box;
|
|
281
|
+
background: color-mix(in srgb, var(--dream-app-accent, #4c9aff) 8%, transparent);
|
|
282
|
+
transition: background 120ms ease, opacity 120ms ease;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
.${p}-handle:hover,
|
|
286
|
+
.${p}-layer[data-dragging] .${p}-handle[data-hot] {
|
|
287
|
+
background: color-mix(in srgb, var(--dream-app-accent, #4c9aff) 24%, transparent);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
.${p}-layer[data-dragging] .${p}-handle:not([data-hot]) {
|
|
291
|
+
background: transparent;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
.${p}-layer[data-dragging] .${p}-handle:not([data-active]):not([data-hot]) {
|
|
295
|
+
pointer-events: none;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.${p}-handle[data-edge] {
|
|
299
|
+
opacity: 0;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.${p}-handle[data-edge]:hover,
|
|
303
|
+
.${p}-layer[data-dragging] .${p}-handle[data-edge][data-hot] {
|
|
304
|
+
opacity: 1;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
.${p}-handle-cols {
|
|
308
|
+
cursor: col-resize;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
.${p}-handle-rows {
|
|
312
|
+
cursor: row-resize;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
.${p}-note {
|
|
316
|
+
position: absolute;
|
|
317
|
+
padding: 2px 6px;
|
|
318
|
+
font-family: var(--dream-app-mono, monospace);
|
|
319
|
+
font-size: 10px;
|
|
320
|
+
line-height: 14px;
|
|
321
|
+
white-space: nowrap;
|
|
322
|
+
color: var(--dream-app-accent, #a8ccff);
|
|
323
|
+
background: color-mix(in srgb, var(--dream-app-raised, #172233) 92%, transparent);
|
|
324
|
+
border: 1px solid color-mix(in srgb, var(--dream-app-accent, #4c9aff) 45%, transparent);
|
|
325
|
+
border-radius: 4px;
|
|
326
|
+
pointer-events: none;
|
|
327
|
+
}
|
|
328
|
+
`;
|
|
329
|
+
var _tmpl$$1 = template(`<svg><g><rect height=14 rx=7></rect><text></svg>`, 2);
|
|
330
|
+
var _tmpl$2$1 = template(`<svg aria-hidden=true>`);
|
|
331
|
+
var _tmpl$3 = template(`<svg><g><defs><pattern patternUnits=userSpaceOnUse width=6 height=6><path d="M 0 6 L 6 0"></path><path d="M -1.5 1.5 L 1.5 -1.5"></path><path d="M 4.5 7.5 L 7.5 4.5"></path></pattern></defs><!><!><!><!><!><!></svg>`, 2);
|
|
332
|
+
var _tmpl$4 = template(`<svg><rect></svg>`, 2);
|
|
333
|
+
var _tmpl$5 = template(`<svg><line></svg>`, 2);
|
|
334
|
+
var LINE_EXTENSION = 12;
|
|
335
|
+
var BADGE_OFFSET = 14;
|
|
336
|
+
function Badge(props) {
|
|
337
|
+
const label = () => String(props.line);
|
|
338
|
+
const width = () => 8 + label().length * 6;
|
|
339
|
+
var _el$ = _tmpl$$1();
|
|
340
|
+
var _el$2 = _el$.firstChild;
|
|
341
|
+
var _el$3 = _el$2.nextSibling;
|
|
342
|
+
insert(_el$3, label);
|
|
343
|
+
effect(() => {
|
|
344
|
+
return {
|
|
345
|
+
e: `${props.prefix}-badge`,
|
|
346
|
+
t: props.x - width() / 2,
|
|
347
|
+
a: props.y - 7,
|
|
348
|
+
o: width(),
|
|
349
|
+
i: `${props.prefix}-badge-text`,
|
|
350
|
+
n: props.x,
|
|
351
|
+
s: props.y
|
|
352
|
+
};
|
|
353
|
+
}, ({ e, t, a, o, i, n, s }, _p$) => {
|
|
354
|
+
className(_el$2, e, _p$?.e);
|
|
355
|
+
t !== _p$?.t && setAttribute(_el$2, "x", t);
|
|
356
|
+
a !== _p$?.a && setAttribute(_el$2, "y", a);
|
|
357
|
+
o !== _p$?.o && setAttribute(_el$2, "width", o);
|
|
358
|
+
className(_el$3, i, _p$?.i);
|
|
359
|
+
n !== _p$?.n && setAttribute(_el$3, "x", n);
|
|
360
|
+
s !== _p$?.s && setAttribute(_el$3, "y", s);
|
|
361
|
+
});
|
|
362
|
+
return _el$;
|
|
363
|
+
}
|
|
364
|
+
function createGridOverlay(dd) {
|
|
365
|
+
const p = classPrefix(dd.plugin.id);
|
|
366
|
+
const [geometry, setGeometry] = createSignal(null);
|
|
367
|
+
createEffect(() => {
|
|
368
|
+
dd.geometry.version();
|
|
369
|
+
return dd.selection();
|
|
370
|
+
}, (selectedId) => {
|
|
371
|
+
setGeometry(selectedId === null ? null : untrack(() => selectedGrid(dd, selectedId)?.geometry ?? null));
|
|
372
|
+
});
|
|
373
|
+
var _el$4 = _tmpl$2$1();
|
|
374
|
+
insert(_el$4, createComponent(Show, {
|
|
375
|
+
get when() {
|
|
376
|
+
return geometry();
|
|
377
|
+
},
|
|
378
|
+
children: (g) => {
|
|
379
|
+
const rect = () => g().rect;
|
|
380
|
+
const rowSpan = () => trackSpan(g().rows);
|
|
381
|
+
const colSpan = () => trackSpan(g().cols);
|
|
382
|
+
var _el$5 = _tmpl$3();
|
|
383
|
+
var _el$6 = _el$5.firstChild;
|
|
384
|
+
var _el$7 = _el$6.firstChild;
|
|
385
|
+
var _el$8 = _el$7.firstChild;
|
|
386
|
+
var _el$9 = _el$8.nextSibling;
|
|
387
|
+
var _el$10 = _el$9.nextSibling;
|
|
388
|
+
var _el$11 = _el$6.nextSibling;
|
|
389
|
+
var _el$12 = _el$11.nextSibling;
|
|
390
|
+
var _el$13 = _el$12.nextSibling;
|
|
391
|
+
var _el$14 = _el$13.nextSibling;
|
|
392
|
+
var _el$15 = _el$14.nextSibling;
|
|
393
|
+
var _el$16 = _el$15.nextSibling;
|
|
394
|
+
setAttribute(_el$7, "id", `${p}-gap-hatch`);
|
|
395
|
+
insert(_el$5, createComponent(Show, {
|
|
396
|
+
get when() {
|
|
397
|
+
return rowSpan();
|
|
398
|
+
},
|
|
399
|
+
children: (span) => createComponent(For, {
|
|
400
|
+
get each() {
|
|
401
|
+
return gapsOf(g().cols);
|
|
402
|
+
},
|
|
403
|
+
children: (gap) => (() => {
|
|
404
|
+
var _el$17 = _tmpl$4();
|
|
405
|
+
effect(() => {
|
|
406
|
+
return {
|
|
407
|
+
e: `${p}-gap-band`,
|
|
408
|
+
t: gap.start,
|
|
409
|
+
a: span().start,
|
|
410
|
+
o: gap.end - gap.start,
|
|
411
|
+
i: span().end - span().start
|
|
412
|
+
};
|
|
413
|
+
}, ({ e, t, a, o, i }, _p$) => {
|
|
414
|
+
className(_el$17, e, _p$?.e);
|
|
415
|
+
t !== _p$?.t && setAttribute(_el$17, "x", t);
|
|
416
|
+
a !== _p$?.a && setAttribute(_el$17, "y", a);
|
|
417
|
+
o !== _p$?.o && setAttribute(_el$17, "width", o);
|
|
418
|
+
i !== _p$?.i && setAttribute(_el$17, "height", i);
|
|
419
|
+
});
|
|
420
|
+
return _el$17;
|
|
421
|
+
})()
|
|
422
|
+
})
|
|
423
|
+
}), _el$11);
|
|
424
|
+
insert(_el$5, createComponent(Show, {
|
|
425
|
+
get when() {
|
|
426
|
+
return colSpan();
|
|
427
|
+
},
|
|
428
|
+
children: (span) => createComponent(For, {
|
|
429
|
+
get each() {
|
|
430
|
+
return gapsOf(g().rows);
|
|
431
|
+
},
|
|
432
|
+
children: (gap) => (() => {
|
|
433
|
+
var _el$18 = _tmpl$4();
|
|
434
|
+
effect(() => {
|
|
435
|
+
return {
|
|
436
|
+
e: `${p}-gap-band`,
|
|
437
|
+
t: span().start,
|
|
438
|
+
a: gap.start,
|
|
439
|
+
o: span().end - span().start,
|
|
440
|
+
i: gap.end - gap.start
|
|
441
|
+
};
|
|
442
|
+
}, ({ e, t, a, o, i }, _p$) => {
|
|
443
|
+
className(_el$18, e, _p$?.e);
|
|
444
|
+
t !== _p$?.t && setAttribute(_el$18, "x", t);
|
|
445
|
+
a !== _p$?.a && setAttribute(_el$18, "y", a);
|
|
446
|
+
o !== _p$?.o && setAttribute(_el$18, "width", o);
|
|
447
|
+
i !== _p$?.i && setAttribute(_el$18, "height", i);
|
|
448
|
+
});
|
|
449
|
+
return _el$18;
|
|
450
|
+
})()
|
|
451
|
+
})
|
|
452
|
+
}), _el$12);
|
|
453
|
+
insert(_el$5, createComponent(For, {
|
|
454
|
+
get each() {
|
|
455
|
+
return trackEdges(g().cols);
|
|
456
|
+
},
|
|
457
|
+
children: (x) => (() => {
|
|
458
|
+
var _el$19 = _tmpl$5();
|
|
459
|
+
setAttribute(_el$19, "x1", x);
|
|
460
|
+
setAttribute(_el$19, "x2", x);
|
|
461
|
+
effect(() => {
|
|
462
|
+
return {
|
|
463
|
+
e: `${p}-line`,
|
|
464
|
+
t: rect().y - LINE_EXTENSION,
|
|
465
|
+
a: rect().y + rect().height + LINE_EXTENSION
|
|
466
|
+
};
|
|
467
|
+
}, ({ e, t, a }, _p$) => {
|
|
468
|
+
className(_el$19, e, _p$?.e);
|
|
469
|
+
t !== _p$?.t && setAttribute(_el$19, "y1", t);
|
|
470
|
+
a !== _p$?.a && setAttribute(_el$19, "y2", a);
|
|
471
|
+
});
|
|
472
|
+
return _el$19;
|
|
473
|
+
})()
|
|
474
|
+
}), _el$13);
|
|
475
|
+
insert(_el$5, createComponent(For, {
|
|
476
|
+
get each() {
|
|
477
|
+
return trackEdges(g().rows);
|
|
478
|
+
},
|
|
479
|
+
children: (y) => (() => {
|
|
480
|
+
var _el$20 = _tmpl$5();
|
|
481
|
+
setAttribute(_el$20, "y1", y);
|
|
482
|
+
setAttribute(_el$20, "y2", y);
|
|
483
|
+
effect(() => {
|
|
484
|
+
return {
|
|
485
|
+
e: `${p}-line`,
|
|
486
|
+
t: rect().x - LINE_EXTENSION,
|
|
487
|
+
a: rect().x + rect().width + LINE_EXTENSION
|
|
488
|
+
};
|
|
489
|
+
}, ({ e, t, a }, _p$) => {
|
|
490
|
+
className(_el$20, e, _p$?.e);
|
|
491
|
+
t !== _p$?.t && setAttribute(_el$20, "x1", t);
|
|
492
|
+
a !== _p$?.a && setAttribute(_el$20, "x2", a);
|
|
493
|
+
});
|
|
494
|
+
return _el$20;
|
|
495
|
+
})()
|
|
496
|
+
}), _el$14);
|
|
497
|
+
insert(_el$5, createComponent(For, {
|
|
498
|
+
get each() {
|
|
499
|
+
return lineAnchors(g().cols);
|
|
500
|
+
},
|
|
501
|
+
children: (x, i) => createComponent(Badge, {
|
|
502
|
+
prefix: p,
|
|
503
|
+
x,
|
|
504
|
+
get y() {
|
|
505
|
+
return rect().y - BADGE_OFFSET;
|
|
506
|
+
},
|
|
507
|
+
get line() {
|
|
508
|
+
return i() + 1;
|
|
509
|
+
}
|
|
510
|
+
})
|
|
511
|
+
}), _el$15);
|
|
512
|
+
insert(_el$5, createComponent(For, {
|
|
513
|
+
get each() {
|
|
514
|
+
return lineAnchors(g().rows);
|
|
515
|
+
},
|
|
516
|
+
children: (y, i) => createComponent(Badge, {
|
|
517
|
+
prefix: p,
|
|
518
|
+
get x() {
|
|
519
|
+
return rect().x - BADGE_OFFSET;
|
|
520
|
+
},
|
|
521
|
+
y,
|
|
522
|
+
get line() {
|
|
523
|
+
return i() + 1;
|
|
524
|
+
}
|
|
525
|
+
})
|
|
526
|
+
}), _el$16);
|
|
527
|
+
effect(() => {
|
|
528
|
+
return {
|
|
529
|
+
e: `${p}-hatch-line`,
|
|
530
|
+
t: `${p}-hatch-line`,
|
|
531
|
+
a: `${p}-hatch-line`
|
|
532
|
+
};
|
|
533
|
+
}, ({ e, t, a }, _p$) => {
|
|
534
|
+
className(_el$8, e, _p$?.e);
|
|
535
|
+
className(_el$9, t, _p$?.t);
|
|
536
|
+
className(_el$10, a, _p$?.a);
|
|
537
|
+
});
|
|
538
|
+
return _el$5;
|
|
539
|
+
}
|
|
540
|
+
}));
|
|
541
|
+
effect(() => `${p}-guides`, (_v$, _$p) => {
|
|
542
|
+
className(_el$4, _v$, _$p);
|
|
543
|
+
});
|
|
544
|
+
return _el$4;
|
|
545
|
+
}
|
|
546
|
+
function winningIn(dd, declarations, properties) {
|
|
547
|
+
let last = null;
|
|
548
|
+
let important = null;
|
|
549
|
+
for (const declaration of dd.core.cssDeclarations(declarations)) {
|
|
550
|
+
if (!properties.includes(declaration.property)) continue;
|
|
551
|
+
if (declaration.important === true) important = declaration;
|
|
552
|
+
else last = declaration;
|
|
553
|
+
}
|
|
554
|
+
return important ?? last;
|
|
555
|
+
}
|
|
556
|
+
function findTarget(dd, elementId, properties, shorthands = []) {
|
|
557
|
+
const stack = dd.pageStack(elementId);
|
|
558
|
+
if (stack === null) return null;
|
|
559
|
+
const { viewportId } = stack;
|
|
560
|
+
const winner = dd.pageWinner(elementId, properties);
|
|
561
|
+
if (winner !== null) {
|
|
562
|
+
if (winner.rule === null) return {
|
|
563
|
+
kind: "blocked",
|
|
564
|
+
why: "inline"
|
|
565
|
+
};
|
|
566
|
+
if (!winner.rule.editable) return {
|
|
567
|
+
kind: "blocked",
|
|
568
|
+
why: "readonly"
|
|
569
|
+
};
|
|
570
|
+
if (shorthands.includes(winner.declaration.property)) return {
|
|
571
|
+
kind: "blocked",
|
|
572
|
+
why: "shorthand"
|
|
573
|
+
};
|
|
574
|
+
return {
|
|
575
|
+
kind: "rule",
|
|
576
|
+
viewportId,
|
|
577
|
+
rule: winner.rule,
|
|
578
|
+
declaration: winner.declaration
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
const editable = stack.rules.filter((rule) => rule.active && rule.pseudo === void 0 && rule.editable);
|
|
582
|
+
const rule = editable.find((rule) => {
|
|
583
|
+
const display = winningIn(dd, rule.declarations, ["display"]);
|
|
584
|
+
return display !== null && /grid/i.test(display.value);
|
|
585
|
+
}) ?? editable[0] ?? null;
|
|
586
|
+
if (rule !== null) return {
|
|
587
|
+
kind: "rule",
|
|
588
|
+
viewportId,
|
|
589
|
+
rule,
|
|
590
|
+
declaration: null
|
|
591
|
+
};
|
|
592
|
+
const sheet = stack.sheets.find((each) => each.editable)?.source ?? null;
|
|
593
|
+
const selector = dd.pageElement(elementId)?.selector ?? null;
|
|
594
|
+
if (sheet === null || selector === null) return null;
|
|
595
|
+
return {
|
|
596
|
+
kind: "add",
|
|
597
|
+
viewportId,
|
|
598
|
+
sheet,
|
|
599
|
+
selector
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
function withDeclaration(dd, declarations, property, value) {
|
|
603
|
+
const winner = winningIn(dd, declarations, [property]);
|
|
604
|
+
const text = `${property}: ${value}${winner?.important === true ? " !important" : ""};`;
|
|
605
|
+
if (winner === null) {
|
|
606
|
+
const kept = declarations.replace(/\s+$/, "");
|
|
607
|
+
if (kept === "") return text;
|
|
608
|
+
return `${kept}${kept.endsWith(";") ? "" : ";"}\n${text}`;
|
|
609
|
+
}
|
|
610
|
+
return declarations.slice(0, winner.range[0]) + text + declarations.slice(winner.range[1]);
|
|
611
|
+
}
|
|
612
|
+
function createWriter(dd, target) {
|
|
613
|
+
const { viewportId } = target;
|
|
614
|
+
const session = dd.beginItemTransaction();
|
|
615
|
+
let key = target.kind === "rule" ? target.rule.key : null;
|
|
616
|
+
let expected = target.kind === "rule" ? target.rule.declarations : "";
|
|
617
|
+
const original = expected;
|
|
618
|
+
return {
|
|
619
|
+
write(property, value) {
|
|
620
|
+
if (key === null) {
|
|
621
|
+
if (target.kind !== "add") return "nowhere to write";
|
|
622
|
+
const answer = session.write({
|
|
623
|
+
kind: "add",
|
|
624
|
+
viewportId,
|
|
625
|
+
sheet: target.sheet,
|
|
626
|
+
selector: target.selector,
|
|
627
|
+
declarations: `${property}: ${value};`
|
|
628
|
+
});
|
|
629
|
+
if (typeof answer === "string") return answer;
|
|
630
|
+
key = answer.key;
|
|
631
|
+
expected = answer.declarations;
|
|
632
|
+
return null;
|
|
633
|
+
}
|
|
634
|
+
const declarations = withDeclaration(dd, expected, property, value);
|
|
635
|
+
if (declarations === expected) return null;
|
|
636
|
+
const answer = session.write({
|
|
637
|
+
kind: "rule",
|
|
638
|
+
viewportId,
|
|
639
|
+
key,
|
|
640
|
+
expected,
|
|
641
|
+
declarations
|
|
642
|
+
});
|
|
643
|
+
if (typeof answer === "string") return answer;
|
|
644
|
+
key = answer.key;
|
|
645
|
+
expected = answer.declarations;
|
|
646
|
+
return null;
|
|
647
|
+
},
|
|
648
|
+
reset() {
|
|
649
|
+
if (key === null || expected === original) return;
|
|
650
|
+
const answer = session.write({
|
|
651
|
+
kind: "rule",
|
|
652
|
+
viewportId,
|
|
653
|
+
key,
|
|
654
|
+
expected,
|
|
655
|
+
declarations: original
|
|
656
|
+
});
|
|
657
|
+
if (typeof answer !== "string") {
|
|
658
|
+
key = answer.key;
|
|
659
|
+
expected = answer.declarations;
|
|
660
|
+
}
|
|
661
|
+
},
|
|
662
|
+
commit: () => session.commit(),
|
|
663
|
+
cancel: () => session.cancel()
|
|
664
|
+
};
|
|
665
|
+
}
|
|
666
|
+
var LENGTH = /^(\d*\.?\d+)([a-z%]+)$/i;
|
|
667
|
+
function classify(text) {
|
|
668
|
+
const match = LENGTH.exec(text);
|
|
669
|
+
if (match !== null) return {
|
|
670
|
+
text,
|
|
671
|
+
length: {
|
|
672
|
+
value: Number(match[1]),
|
|
673
|
+
unit: match[2].toLowerCase()
|
|
674
|
+
}
|
|
675
|
+
};
|
|
676
|
+
if (text === "0") return {
|
|
677
|
+
text,
|
|
678
|
+
length: {
|
|
679
|
+
value: 0,
|
|
680
|
+
unit: "px"
|
|
681
|
+
}
|
|
682
|
+
};
|
|
683
|
+
return {
|
|
684
|
+
text,
|
|
685
|
+
length: null
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
function splitTopLevel(text) {
|
|
689
|
+
const out = [];
|
|
690
|
+
let depth = 0;
|
|
691
|
+
let start = -1;
|
|
692
|
+
let names = false;
|
|
693
|
+
for (let i = 0; i < text.length; i++) {
|
|
694
|
+
const ch = text[i];
|
|
695
|
+
if (names) {
|
|
696
|
+
if (ch === "]") {
|
|
697
|
+
out.push(text.slice(start, i + 1));
|
|
698
|
+
start = -1;
|
|
699
|
+
names = false;
|
|
700
|
+
}
|
|
701
|
+
continue;
|
|
702
|
+
}
|
|
703
|
+
if (ch === "[" && depth === 0) {
|
|
704
|
+
if (start !== -1) out.push(text.slice(start, i));
|
|
705
|
+
start = i;
|
|
706
|
+
names = true;
|
|
707
|
+
continue;
|
|
708
|
+
}
|
|
709
|
+
if (ch === "(" || ch === "[") depth++;
|
|
710
|
+
else if (ch === ")" || ch === "]") depth = Math.max(0, depth - 1);
|
|
711
|
+
if (depth === 0 && /\s/.test(ch)) {
|
|
712
|
+
if (start !== -1) out.push(text.slice(start, i));
|
|
713
|
+
start = -1;
|
|
714
|
+
} else if (start === -1) start = i;
|
|
715
|
+
}
|
|
716
|
+
if (start !== -1) out.push(text.slice(start));
|
|
717
|
+
return out;
|
|
718
|
+
}
|
|
719
|
+
function item(text) {
|
|
720
|
+
return {
|
|
721
|
+
text,
|
|
722
|
+
track: text.startsWith("[") && text.endsWith("]") ? null : classify(text)
|
|
723
|
+
};
|
|
724
|
+
}
|
|
725
|
+
function parseTrackList(value) {
|
|
726
|
+
const text = value.trim();
|
|
727
|
+
if (text === "" || /^(none|inherit|initial|unset|revert|revert-layer)$/i.test(text) || /^(subgrid|masonry)\b/i.test(text)) return null;
|
|
728
|
+
if (/var\(/i.test(text)) return null;
|
|
729
|
+
const segments = [];
|
|
730
|
+
const tracks = [];
|
|
731
|
+
for (const token of splitTopLevel(text)) {
|
|
732
|
+
if (/^repeat\(/i.test(token) && token.endsWith(")")) {
|
|
733
|
+
const inside = token.slice(7, -1);
|
|
734
|
+
const comma = inside.indexOf(",");
|
|
735
|
+
if (comma === -1) return null;
|
|
736
|
+
const count = inside.slice(0, comma).trim();
|
|
737
|
+
if (!/^\d+$/.test(count) || Number(count) < 1) return null;
|
|
738
|
+
const rest = inside.slice(comma + 1).trim();
|
|
739
|
+
if (/repeat\(/i.test(rest)) return null;
|
|
740
|
+
const inner = splitTopLevel(rest).map(item);
|
|
741
|
+
const times = Number(count);
|
|
742
|
+
segments.push({
|
|
743
|
+
kind: "repeat",
|
|
744
|
+
text: token,
|
|
745
|
+
count: times,
|
|
746
|
+
inner
|
|
747
|
+
});
|
|
748
|
+
for (let copy = 0; copy < times; copy++) for (const each of inner) if (each.track !== null) tracks.push(each.track);
|
|
749
|
+
continue;
|
|
750
|
+
}
|
|
751
|
+
const each = item(token);
|
|
752
|
+
segments.push({
|
|
753
|
+
kind: "item",
|
|
754
|
+
item: each
|
|
755
|
+
});
|
|
756
|
+
if (each.track !== null) tracks.push(each.track);
|
|
757
|
+
}
|
|
758
|
+
return {
|
|
759
|
+
segments,
|
|
760
|
+
tracks
|
|
761
|
+
};
|
|
762
|
+
}
|
|
763
|
+
function perCopy(segment) {
|
|
764
|
+
return segment.inner.filter((each) => each.track !== null).length;
|
|
765
|
+
}
|
|
766
|
+
function changed(list, edits, index) {
|
|
767
|
+
const edit = edits.get(index);
|
|
768
|
+
return edit !== void 0 && edit !== list.tracks[index]?.text;
|
|
769
|
+
}
|
|
770
|
+
function writeTrackList(list, edits, insert, remove) {
|
|
771
|
+
const out = [];
|
|
772
|
+
let index = 0;
|
|
773
|
+
let inserted = insert === void 0;
|
|
774
|
+
const place = () => {
|
|
775
|
+
if (!inserted && insert !== void 0 && insert.index === index) {
|
|
776
|
+
out.push(insert.text);
|
|
777
|
+
inserted = true;
|
|
778
|
+
}
|
|
779
|
+
};
|
|
780
|
+
const emit = (each) => {
|
|
781
|
+
if (each.track === null) {
|
|
782
|
+
if (insert?.after === false) place();
|
|
783
|
+
out.push(each.text);
|
|
784
|
+
return;
|
|
785
|
+
}
|
|
786
|
+
place();
|
|
787
|
+
if (index !== remove) out.push(edits.get(index) ?? each.text);
|
|
788
|
+
index++;
|
|
789
|
+
};
|
|
790
|
+
for (const segment of list.segments) {
|
|
791
|
+
if (segment.kind === "item") {
|
|
792
|
+
emit(segment.item);
|
|
793
|
+
continue;
|
|
794
|
+
}
|
|
795
|
+
const last = index + segment.count * perCopy(segment);
|
|
796
|
+
let touched = remove !== void 0 && remove >= index && remove < last;
|
|
797
|
+
if (insert !== void 0 && insert.index > index && insert.index < last) touched = true;
|
|
798
|
+
for (let i = index; !touched && i < last; i++) if (changed(list, edits, i)) touched = true;
|
|
799
|
+
if (!touched) {
|
|
800
|
+
place();
|
|
801
|
+
out.push(segment.text);
|
|
802
|
+
index = last;
|
|
803
|
+
continue;
|
|
804
|
+
}
|
|
805
|
+
for (let copy = 0; copy < segment.count; copy++) for (const each of segment.inner) emit(each);
|
|
806
|
+
}
|
|
807
|
+
if (!inserted && insert !== void 0) out.push(insert.text);
|
|
808
|
+
return joinList(out);
|
|
809
|
+
}
|
|
810
|
+
function joinList(parts) {
|
|
811
|
+
return parts.join(" ").replace(/\]\s+\[/g, " ");
|
|
812
|
+
}
|
|
813
|
+
function formatLength(value, unit) {
|
|
814
|
+
const precision = unit === "px" ? 1 : 2;
|
|
815
|
+
return `${String(Number(value.toFixed(precision)))}${unit}`;
|
|
816
|
+
}
|
|
817
|
+
function scaleLength(text, px, nextPx) {
|
|
818
|
+
const { length } = classify(text);
|
|
819
|
+
if (length === null || px <= 0) return formatLength(nextPx, "px");
|
|
820
|
+
return formatLength(length.value * nextPx / px, length.unit);
|
|
821
|
+
}
|
|
822
|
+
var isShare = (track) => track.length !== null && track.length.unit === "fr";
|
|
823
|
+
var functionOf = (track) => /^([a-z-]+)\(/i.exec(track.text)?.[1] ?? null;
|
|
824
|
+
function precedence(track, px) {
|
|
825
|
+
if (track.length === null || px <= 0) return 0;
|
|
826
|
+
return track.length.unit === "fr" ? 1 : 2;
|
|
827
|
+
}
|
|
828
|
+
function tradeAcross(list, sizes, boundary, delta) {
|
|
829
|
+
const a = list.tracks[boundary];
|
|
830
|
+
const b = list.tracks[boundary + 1];
|
|
831
|
+
const pa = sizes[boundary];
|
|
832
|
+
const pb = sizes[boundary + 1];
|
|
833
|
+
if (a === void 0 || b === void 0 || pa === void 0 || pb === void 0) return null;
|
|
834
|
+
const d = Math.max(-pa, Math.min(pb, delta));
|
|
835
|
+
const na = pa + d;
|
|
836
|
+
const nb = pb - d;
|
|
837
|
+
const shares = list.tracks.filter(isShare).length;
|
|
838
|
+
const lone = (share, other) => isShare(share) && other.length === null && shares === 1;
|
|
839
|
+
let first;
|
|
840
|
+
let second;
|
|
841
|
+
if ((isShare(a) || isShare(b)) && pa + pb <= 0) return null;
|
|
842
|
+
if (isShare(a) && isShare(b)) {
|
|
843
|
+
const total = a.length.value + b.length.value;
|
|
844
|
+
const k = total / (pa + pb);
|
|
845
|
+
const fa = Number((na * k).toFixed(2));
|
|
846
|
+
first = formatLength(fa, "fr");
|
|
847
|
+
second = formatLength(Math.max(0, total - fa), "fr");
|
|
848
|
+
} else if (lone(a, b) || lone(b, a)) {
|
|
849
|
+
const fn = functionOf(isShare(a) ? b : a);
|
|
850
|
+
if (fn !== null) return { refused: fn };
|
|
851
|
+
first = isShare(a) ? a.text : formatLength(na, "px");
|
|
852
|
+
second = isShare(b) ? b.text : formatLength(nb, "px");
|
|
853
|
+
} else {
|
|
854
|
+
const top = Math.max(precedence(a, pa), precedence(b, pb));
|
|
855
|
+
if (top === 0) {
|
|
856
|
+
const fn = functionOf(a) ?? functionOf(b);
|
|
857
|
+
if (fn !== null) return { refused: fn };
|
|
858
|
+
first = formatLength(na, "px");
|
|
859
|
+
second = formatLength(nb, "px");
|
|
860
|
+
} else if (top === 2 && shares >= 2 && (isShare(a) || isShare(b))) {
|
|
861
|
+
const share = isShare(a) ? a : b;
|
|
862
|
+
const sharePx = isShare(a) ? pa : pb;
|
|
863
|
+
const shareNext = isShare(a) ? na : nb;
|
|
864
|
+
if (sharePx > 0 && shareNext > 0) {
|
|
865
|
+
const scaled = scaleLength(share.text, sharePx, shareNext);
|
|
866
|
+
const fixed = isShare(a) ? scaleLength(b.text, pb, nb) : scaleLength(a.text, pa, na);
|
|
867
|
+
first = isShare(a) ? scaled : fixed;
|
|
868
|
+
second = isShare(a) ? fixed : scaled;
|
|
869
|
+
} else {
|
|
870
|
+
first = precedence(a, pa) === top ? scaleLength(a.text, pa, na) : a.text;
|
|
871
|
+
second = precedence(b, pb) === top ? scaleLength(b.text, pb, nb) : b.text;
|
|
872
|
+
}
|
|
873
|
+
} else {
|
|
874
|
+
first = precedence(a, pa) === top ? scaleLength(a.text, pa, na) : a.text;
|
|
875
|
+
second = precedence(b, pb) === top ? scaleLength(b.text, pb, nb) : b.text;
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
const edits = new Map([[boundary, first], [boundary + 1, second]]);
|
|
879
|
+
const collapsed = na <= 0 ? boundary : nb <= 0 ? boundary + 1 : null;
|
|
880
|
+
return {
|
|
881
|
+
list: writeTrackList(list, edits),
|
|
882
|
+
first,
|
|
883
|
+
second,
|
|
884
|
+
collapsed
|
|
885
|
+
};
|
|
886
|
+
}
|
|
887
|
+
function insertAt(list, sizes, line, delta) {
|
|
888
|
+
if (Math.abs(delta) < .5) return { refused: "still" };
|
|
889
|
+
const donorIndex = delta > 0 ? line : line - 1;
|
|
890
|
+
const px = sizes[donorIndex];
|
|
891
|
+
if (donorIndex < 0 || px === void 0) return { refused: "outward" };
|
|
892
|
+
const donor = list.tracks[donorIndex];
|
|
893
|
+
if (donor === void 0) return { refused: "implicit" };
|
|
894
|
+
const size = Math.min(Math.abs(delta), px);
|
|
895
|
+
if (size < .5) return { refused: "still" };
|
|
896
|
+
const scalable = donor.length !== null && donor.length.value > 0 && px > 0;
|
|
897
|
+
const born = scalable ? scaleLength(donor.text, px, size) : formatLength(size, "px");
|
|
898
|
+
const rest = scalable ? scaleLength(donor.text, px, px - size) : donor.text;
|
|
899
|
+
return {
|
|
900
|
+
list: writeTrackList(list, new Map([[donorIndex, rest]]), {
|
|
901
|
+
index: line,
|
|
902
|
+
text: born,
|
|
903
|
+
after: delta > 0
|
|
904
|
+
}),
|
|
905
|
+
born,
|
|
906
|
+
donor: rest,
|
|
907
|
+
line: delta > 0 ? line + 1 : line
|
|
908
|
+
};
|
|
909
|
+
}
|
|
910
|
+
function bumpRepeat(list, track, line, by) {
|
|
911
|
+
const out = [];
|
|
912
|
+
let index = 0;
|
|
913
|
+
let hit = false;
|
|
914
|
+
for (const segment of list.segments) {
|
|
915
|
+
if (segment.kind === "item") {
|
|
916
|
+
out.push(segment.item.text);
|
|
917
|
+
if (segment.item.track !== null) index++;
|
|
918
|
+
continue;
|
|
919
|
+
}
|
|
920
|
+
const last = index + segment.count * perCopy(segment);
|
|
921
|
+
const inside = track >= index && track < last && line >= index;
|
|
922
|
+
if (!hit && perCopy(segment) === 1 && inside && line <= last) {
|
|
923
|
+
hit = true;
|
|
924
|
+
const count = segment.count + by;
|
|
925
|
+
const inner = segment.inner.map((each) => each.text).join(" ");
|
|
926
|
+
if (count >= 2) out.push(`repeat(${count}, ${inner})`);
|
|
927
|
+
else if (count === 1) out.push(inner);
|
|
928
|
+
} else out.push(segment.text);
|
|
929
|
+
index = last;
|
|
930
|
+
}
|
|
931
|
+
return hit ? joinList(out) : null;
|
|
932
|
+
}
|
|
933
|
+
function insertEqual(list, line) {
|
|
934
|
+
const copy = list.tracks[Math.max(0, line - 1)];
|
|
935
|
+
if (copy === void 0 || line > list.tracks.length) return null;
|
|
936
|
+
const bumped = bumpRepeat(list, Math.max(0, line - 1), line, 1);
|
|
937
|
+
if (bumped !== null) return {
|
|
938
|
+
list: bumped,
|
|
939
|
+
text: copy.text
|
|
940
|
+
};
|
|
941
|
+
const insert = {
|
|
942
|
+
index: line,
|
|
943
|
+
text: copy.text,
|
|
944
|
+
after: line === 0
|
|
945
|
+
};
|
|
946
|
+
return {
|
|
947
|
+
list: writeTrackList(list, new Map(), insert),
|
|
948
|
+
text: copy.text
|
|
949
|
+
};
|
|
950
|
+
}
|
|
951
|
+
function removeTrack(list, index) {
|
|
952
|
+
if (index < 0 || index >= list.tracks.length) return null;
|
|
953
|
+
const written = bumpRepeat(list, index, index, -1) ?? writeTrackList(list, new Map(), void 0, index);
|
|
954
|
+
const left = parseTrackList(written);
|
|
955
|
+
return left === null || left.tracks.length === 0 ? "none" : written;
|
|
956
|
+
}
|
|
957
|
+
function parseGapShorthand(value) {
|
|
958
|
+
const tokens = splitTopLevel(value.trim());
|
|
959
|
+
const row = tokens[0];
|
|
960
|
+
if (row === void 0 || tokens.length > 2) return null;
|
|
961
|
+
return {
|
|
962
|
+
row,
|
|
963
|
+
column: tokens[1] ?? row
|
|
964
|
+
};
|
|
965
|
+
}
|
|
966
|
+
function gapShorthand(row, column) {
|
|
967
|
+
return row === column ? row : `${row} ${column}`;
|
|
968
|
+
}
|
|
969
|
+
var TRACK_PROPERTY = {
|
|
970
|
+
cols: "grid-template-columns",
|
|
971
|
+
rows: "grid-template-rows"
|
|
972
|
+
};
|
|
973
|
+
var TRACK_SHORTHANDS = ["grid-template", "grid"];
|
|
974
|
+
var GAP_LONGHAND = {
|
|
975
|
+
cols: "column-gap",
|
|
976
|
+
rows: "row-gap"
|
|
977
|
+
};
|
|
978
|
+
var GAP_PROPERTIES = {
|
|
979
|
+
cols: [
|
|
980
|
+
"column-gap",
|
|
981
|
+
"grid-column-gap",
|
|
982
|
+
"gap",
|
|
983
|
+
"grid-gap"
|
|
984
|
+
],
|
|
985
|
+
rows: [
|
|
986
|
+
"row-gap",
|
|
987
|
+
"grid-row-gap",
|
|
988
|
+
"gap",
|
|
989
|
+
"grid-gap"
|
|
990
|
+
]
|
|
991
|
+
};
|
|
992
|
+
var NOUN = {
|
|
993
|
+
cols: "columns",
|
|
994
|
+
rows: "rows"
|
|
995
|
+
};
|
|
996
|
+
var ONE = {
|
|
997
|
+
cols: "column",
|
|
998
|
+
rows: "row"
|
|
999
|
+
};
|
|
1000
|
+
var inert = (note, line) => ({
|
|
1001
|
+
peek: () => ({
|
|
1002
|
+
note,
|
|
1003
|
+
line
|
|
1004
|
+
}),
|
|
1005
|
+
step: () => ({
|
|
1006
|
+
note,
|
|
1007
|
+
line
|
|
1008
|
+
}),
|
|
1009
|
+
commit: () => {},
|
|
1010
|
+
restore: () => {}
|
|
1011
|
+
});
|
|
1012
|
+
var blockedNote = (axis, why) => ({
|
|
1013
|
+
inline: `${NOUN[axis]} are set inline — the CSS panel edits that`,
|
|
1014
|
+
readonly: `${NOUN[axis]} are set by a rule this page can't edit`,
|
|
1015
|
+
shorthand: `${NOUN[axis]} come from a grid-template shorthand — the CSS panel edits that`
|
|
1016
|
+
})[why];
|
|
1017
|
+
function openTracks(dd, gridId, geometry, axis, implicitHint) {
|
|
1018
|
+
const property = TRACK_PROPERTY[axis];
|
|
1019
|
+
const target = findTarget(dd, gridId, [property, ...TRACK_SHORTHANDS], TRACK_SHORTHANDS);
|
|
1020
|
+
if (target === null) return `${NOUN[axis]} can't be written here`;
|
|
1021
|
+
if (target.kind === "blocked") return blockedNote(axis, target.why);
|
|
1022
|
+
const declaration = target.kind === "rule" ? target.declaration : null;
|
|
1023
|
+
if (declaration === null) return `${NOUN[axis]} are implicit — ${implicitHint}`;
|
|
1024
|
+
const list = parseTrackList(declaration.value);
|
|
1025
|
+
if (list === null) return `${NOUN[axis]} use a value only the CSS panel can edit`;
|
|
1026
|
+
if (list.tracks.length > geometry[axis].sizes.length) return `${NOUN[axis]} come from a rule that is not in force here`;
|
|
1027
|
+
const node = dd.geometry.node(gridId);
|
|
1028
|
+
if (node !== void 0 && startsBeforeFirst(node, axis, list.tracks.length)) return `${NOUN[axis]} start before the first — the CSS panel edits that`;
|
|
1029
|
+
return {
|
|
1030
|
+
target,
|
|
1031
|
+
list,
|
|
1032
|
+
property
|
|
1033
|
+
};
|
|
1034
|
+
}
|
|
1035
|
+
function beginTrade(dd, gridId, geometry, axis, line) {
|
|
1036
|
+
const sizes = geometry[axis].sizes;
|
|
1037
|
+
if (line === 0 || line >= sizes.length) return inert(`pull inward to open a ${ONE[axis]}`, line);
|
|
1038
|
+
const opened = openTracks(dd, gridId, geometry, axis, "⌘-drag adjusts the gap");
|
|
1039
|
+
if (typeof opened === "string") return inert(opened, line);
|
|
1040
|
+
const { target, list, property } = opened;
|
|
1041
|
+
const a = list.tracks[line - 1];
|
|
1042
|
+
const b = list.tracks[line];
|
|
1043
|
+
if (a === void 0 || b === void 0) return inert(`implicit track — ⌘-drag adjusts the gap`, line);
|
|
1044
|
+
const writer = createWriter(dd, target);
|
|
1045
|
+
return {
|
|
1046
|
+
peek: () => ({
|
|
1047
|
+
note: `${a.text} · ${b.text}`,
|
|
1048
|
+
line
|
|
1049
|
+
}),
|
|
1050
|
+
step(delta) {
|
|
1051
|
+
const trade = tradeAcross(list, sizes, line - 1, delta);
|
|
1052
|
+
if (trade === null) return {
|
|
1053
|
+
note: `${NOUN[axis]} can't be written here`,
|
|
1054
|
+
line
|
|
1055
|
+
};
|
|
1056
|
+
if ("refused" in trade) return {
|
|
1057
|
+
note: `${NOUN[axis]} use ${trade.refused}() — the CSS panel edits that`,
|
|
1058
|
+
line
|
|
1059
|
+
};
|
|
1060
|
+
const problem = writer.write(property, trade.list);
|
|
1061
|
+
if (problem !== null) return {
|
|
1062
|
+
note: problem,
|
|
1063
|
+
line
|
|
1064
|
+
};
|
|
1065
|
+
const hint = trade.collapsed === null ? "" : " — ⇧-double-click to remove";
|
|
1066
|
+
return {
|
|
1067
|
+
note: `${trade.first} · ${trade.second}${hint}`,
|
|
1068
|
+
line
|
|
1069
|
+
};
|
|
1070
|
+
},
|
|
1071
|
+
commit: () => writer.commit(),
|
|
1072
|
+
restore: () => writer.cancel()
|
|
1073
|
+
};
|
|
1074
|
+
}
|
|
1075
|
+
function beginInsert(dd, gridId, geometry, axis, line) {
|
|
1076
|
+
const sizes = geometry[axis].sizes;
|
|
1077
|
+
const opened = openTracks(dd, gridId, geometry, axis, `a ${ONE[axis]} is born from content`);
|
|
1078
|
+
if (typeof opened === "string") return inert(opened, line);
|
|
1079
|
+
const { target, list, property } = opened;
|
|
1080
|
+
const refused = {
|
|
1081
|
+
still: `pull to open a ${ONE[axis]}`,
|
|
1082
|
+
outward: `pull inward to open a ${ONE[axis]}`,
|
|
1083
|
+
implicit: "implicit track — nothing to carve from"
|
|
1084
|
+
};
|
|
1085
|
+
const writer = createWriter(dd, target);
|
|
1086
|
+
return {
|
|
1087
|
+
peek: () => ({
|
|
1088
|
+
note: refused.still,
|
|
1089
|
+
line
|
|
1090
|
+
}),
|
|
1091
|
+
step(delta) {
|
|
1092
|
+
const insertion = insertAt(list, sizes, line, delta);
|
|
1093
|
+
if ("refused" in insertion) {
|
|
1094
|
+
writer.reset();
|
|
1095
|
+
return {
|
|
1096
|
+
note: refused[insertion.refused],
|
|
1097
|
+
line
|
|
1098
|
+
};
|
|
1099
|
+
}
|
|
1100
|
+
const problem = writer.write(property, insertion.list);
|
|
1101
|
+
if (problem !== null) return {
|
|
1102
|
+
note: problem,
|
|
1103
|
+
line
|
|
1104
|
+
};
|
|
1105
|
+
return {
|
|
1106
|
+
note: delta > 0 ? `new ${insertion.born} · ${insertion.donor}` : `${insertion.donor} · new ${insertion.born}`,
|
|
1107
|
+
line: insertion.line
|
|
1108
|
+
};
|
|
1109
|
+
},
|
|
1110
|
+
commit: () => writer.commit(),
|
|
1111
|
+
restore: () => writer.cancel()
|
|
1112
|
+
};
|
|
1113
|
+
}
|
|
1114
|
+
function insertEqualAt(dd, gridId, geometry, axis, line) {
|
|
1115
|
+
const opened = openTracks(dd, gridId, geometry, axis, `a ${ONE[axis]} is born from content`);
|
|
1116
|
+
if (typeof opened === "string") return opened;
|
|
1117
|
+
const equal = insertEqual(opened.list, line);
|
|
1118
|
+
if (equal === null) return "implicit track — nothing to copy";
|
|
1119
|
+
const writer = createWriter(dd, opened.target);
|
|
1120
|
+
const problem = writer.write(opened.property, equal.list);
|
|
1121
|
+
writer.commit();
|
|
1122
|
+
return problem ?? `+${equal.text}`;
|
|
1123
|
+
}
|
|
1124
|
+
function removeBefore(dd, gridId, geometry, axis, line) {
|
|
1125
|
+
const opened = openTracks(dd, gridId, geometry, axis, "nothing to remove");
|
|
1126
|
+
if (typeof opened === "string") return opened;
|
|
1127
|
+
const index = Math.max(0, line - 1);
|
|
1128
|
+
const without = removeTrack(opened.list, index);
|
|
1129
|
+
if (without === null) return "implicit track — nothing to remove";
|
|
1130
|
+
const writer = createWriter(dd, opened.target);
|
|
1131
|
+
const problem = writer.write(opened.property, without);
|
|
1132
|
+
writer.commit();
|
|
1133
|
+
return problem ?? `${ONE[axis]} ${index + 1} removed`;
|
|
1134
|
+
}
|
|
1135
|
+
var isFunction = (value) => /\(/.test(value);
|
|
1136
|
+
function planGap(declaration, axis) {
|
|
1137
|
+
if (declaration === null) return {
|
|
1138
|
+
property: GAP_LONGHAND[axis],
|
|
1139
|
+
current: null,
|
|
1140
|
+
spell: (s) => s
|
|
1141
|
+
};
|
|
1142
|
+
const { property, value } = declaration;
|
|
1143
|
+
if (property === "gap" || property === "grid-gap") {
|
|
1144
|
+
const parts = parseGapShorthand(value);
|
|
1145
|
+
if (parts === null) return null;
|
|
1146
|
+
const current = axis === "cols" ? parts.column : parts.row;
|
|
1147
|
+
if (isFunction(current)) return null;
|
|
1148
|
+
return {
|
|
1149
|
+
property,
|
|
1150
|
+
current,
|
|
1151
|
+
spell: (s) => axis === "cols" ? gapShorthand(parts.row, s) : gapShorthand(s, parts.column)
|
|
1152
|
+
};
|
|
1153
|
+
}
|
|
1154
|
+
if (isFunction(value)) return null;
|
|
1155
|
+
return {
|
|
1156
|
+
property,
|
|
1157
|
+
current: value,
|
|
1158
|
+
spell: (s) => s
|
|
1159
|
+
};
|
|
1160
|
+
}
|
|
1161
|
+
function beginGap(dd, gridId, geometry, axis, line) {
|
|
1162
|
+
const target = findTarget(dd, gridId, GAP_PROPERTIES[axis]);
|
|
1163
|
+
if (target === null) return inert("the gap can't be written here", line);
|
|
1164
|
+
if (target.kind === "blocked") return inert(target.why === "inline" ? "the gap is set inline — the CSS panel edits that" : "the gap is set by a rule this page can't edit", line);
|
|
1165
|
+
const plan = planGap(target.kind === "rule" ? target.declaration : null, axis);
|
|
1166
|
+
if (plan === null) return inert("the gap uses a value only the CSS panel can edit", line);
|
|
1167
|
+
const px = geometry[axis].gap;
|
|
1168
|
+
const label = axis === "cols" ? "column gap" : "row gap";
|
|
1169
|
+
const current = plan.current ?? formatLength(px, "px");
|
|
1170
|
+
const writer = createWriter(dd, target);
|
|
1171
|
+
return {
|
|
1172
|
+
peek: () => ({
|
|
1173
|
+
note: `${label} ${current}`,
|
|
1174
|
+
line
|
|
1175
|
+
}),
|
|
1176
|
+
step(delta) {
|
|
1177
|
+
const next = Math.max(0, px + delta);
|
|
1178
|
+
const scaled = scaleLength(current, px, next);
|
|
1179
|
+
const problem = writer.write(plan.property, plan.spell(scaled));
|
|
1180
|
+
if (problem !== null) return {
|
|
1181
|
+
note: problem,
|
|
1182
|
+
line
|
|
1183
|
+
};
|
|
1184
|
+
return {
|
|
1185
|
+
note: `${label} ${scaled}`,
|
|
1186
|
+
line
|
|
1187
|
+
};
|
|
1188
|
+
},
|
|
1189
|
+
commit: () => writer.commit(),
|
|
1190
|
+
restore: () => writer.cancel()
|
|
1191
|
+
};
|
|
1192
|
+
}
|
|
1193
|
+
function beginSession(dd, gridId, geometry, axis, line, mode) {
|
|
1194
|
+
switch (mode) {
|
|
1195
|
+
case "gap": return beginGap(dd, gridId, geometry, axis, line);
|
|
1196
|
+
case "insert": return beginInsert(dd, gridId, geometry, axis, line);
|
|
1197
|
+
default: return beginTrade(dd, gridId, geometry, axis, line);
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
var _tmpl$ = template(`<div>`);
|
|
1201
|
+
var _tmpl$2 = template(`<div><!><!><!>`);
|
|
1202
|
+
var MIN_HIT = 10;
|
|
1203
|
+
var NOTE_OFFSET = {
|
|
1204
|
+
x: 14,
|
|
1205
|
+
y: 18
|
|
1206
|
+
};
|
|
1207
|
+
var FLASH_MS = 900;
|
|
1208
|
+
var DOUBLE_CLICK_MS = 600;
|
|
1209
|
+
function clipTo(box, clip) {
|
|
1210
|
+
if (clip === null) return box;
|
|
1211
|
+
const x0 = Math.max(box.x, clip.x);
|
|
1212
|
+
const y0 = Math.max(box.y, clip.y);
|
|
1213
|
+
const x1 = Math.min(box.x + box.width, clip.x + clip.width);
|
|
1214
|
+
const y1 = Math.min(box.y + box.height, clip.y + clip.height);
|
|
1215
|
+
return {
|
|
1216
|
+
...box,
|
|
1217
|
+
x: x0,
|
|
1218
|
+
y: y0,
|
|
1219
|
+
width: Math.max(0, x1 - x0),
|
|
1220
|
+
height: Math.max(0, y1 - y0)
|
|
1221
|
+
};
|
|
1222
|
+
}
|
|
1223
|
+
function handlesFor(axis, g, clip) {
|
|
1224
|
+
const along = axis === "cols" ? g.cols.bands : g.rows.bands;
|
|
1225
|
+
const across = axis === "cols" ? g.rows.bands : g.cols.bands;
|
|
1226
|
+
const reversed = axis === "cols" ? g.cols.reversed : g.rows.reversed;
|
|
1227
|
+
const first = along[0];
|
|
1228
|
+
const last = along[along.length - 1];
|
|
1229
|
+
if (first === void 0 || last === void 0) return [];
|
|
1230
|
+
const spanStart = across.length === 0 ? axis === "cols" ? g.rect.y : g.rect.x : Math.min(...across.map((band) => band.start));
|
|
1231
|
+
const spanEnd = across.length === 0 ? axis === "cols" ? g.rect.y + g.rect.height : g.rect.x + g.rect.width : Math.max(...across.map((band) => band.end));
|
|
1232
|
+
const box = (line, center, size, edge) => clipTo(axis === "cols" ? {
|
|
1233
|
+
x: center - size / 2,
|
|
1234
|
+
y: spanStart,
|
|
1235
|
+
width: size,
|
|
1236
|
+
height: spanEnd - spanStart,
|
|
1237
|
+
line,
|
|
1238
|
+
edge
|
|
1239
|
+
} : {
|
|
1240
|
+
x: spanStart,
|
|
1241
|
+
y: center - size / 2,
|
|
1242
|
+
width: spanEnd - spanStart,
|
|
1243
|
+
height: size,
|
|
1244
|
+
line,
|
|
1245
|
+
edge
|
|
1246
|
+
}, clip);
|
|
1247
|
+
const out = [box(0, reversed ? first.end : first.start, MIN_HIT, true)];
|
|
1248
|
+
for (let i = 0; i + 1 < along.length; i++) {
|
|
1249
|
+
const a = Math.min(along[i].end, along[i + 1].end);
|
|
1250
|
+
const b = Math.max(along[i].start, along[i + 1].start);
|
|
1251
|
+
out.push(box(i + 1, (a + b) / 2, Math.max(b - a, MIN_HIT), false));
|
|
1252
|
+
}
|
|
1253
|
+
out.push(box(along.length, reversed ? last.start : last.end, MIN_HIT, true));
|
|
1254
|
+
return out;
|
|
1255
|
+
}
|
|
1256
|
+
function createGridHandles(dd) {
|
|
1257
|
+
const p = classPrefix(dd.plugin.id);
|
|
1258
|
+
const [visual, setVisual] = createSignal(null);
|
|
1259
|
+
const [note, setNote] = createSignal(null);
|
|
1260
|
+
const [dragging, setDragging] = createSignal(null);
|
|
1261
|
+
let flashTimer;
|
|
1262
|
+
onSettled(() => () => window.clearTimeout(flashTimer));
|
|
1263
|
+
const readVisual = (selectedId) => {
|
|
1264
|
+
const grid = selectedGrid(dd, selectedId);
|
|
1265
|
+
if (grid === null) return null;
|
|
1266
|
+
const viewportId = dd.pageElement(grid.gridId)?.viewportId ?? null;
|
|
1267
|
+
const clip = viewportId === null ? null : dd.geometry.itemRect(viewportId);
|
|
1268
|
+
return {
|
|
1269
|
+
...grid,
|
|
1270
|
+
clip
|
|
1271
|
+
};
|
|
1272
|
+
};
|
|
1273
|
+
createEffect(() => {
|
|
1274
|
+
dd.geometry.version();
|
|
1275
|
+
return dd.selection();
|
|
1276
|
+
}, (selectedId) => {
|
|
1277
|
+
setVisual(selectedId === null ? null : untrack(() => readVisual(selectedId)));
|
|
1278
|
+
});
|
|
1279
|
+
const cols = createMemo(() => {
|
|
1280
|
+
const v = visual();
|
|
1281
|
+
return v === null ? [] : handlesFor("cols", v.geometry, v.clip);
|
|
1282
|
+
});
|
|
1283
|
+
const rows = createMemo(() => {
|
|
1284
|
+
const v = visual();
|
|
1285
|
+
return v === null ? [] : handlesFor("rows", v.geometry, v.clip);
|
|
1286
|
+
});
|
|
1287
|
+
const overlayPoint = (clientX, clientY) => {
|
|
1288
|
+
const world = dd.canvas.screenToWorld(clientX, clientY);
|
|
1289
|
+
const camera = dd.geometry.camera();
|
|
1290
|
+
return {
|
|
1291
|
+
x: camera.panX + world.x * camera.zoom,
|
|
1292
|
+
y: camera.panY + world.y * camera.zoom
|
|
1293
|
+
};
|
|
1294
|
+
};
|
|
1295
|
+
const showNote = (clientX, clientY, text) => {
|
|
1296
|
+
const at = overlayPoint(clientX, clientY);
|
|
1297
|
+
setNote({
|
|
1298
|
+
x: at.x + NOTE_OFFSET.x,
|
|
1299
|
+
y: at.y + NOTE_OFFSET.y,
|
|
1300
|
+
text
|
|
1301
|
+
});
|
|
1302
|
+
};
|
|
1303
|
+
const handlers = (axis, box, onMoved) => {
|
|
1304
|
+
let mode = "trade";
|
|
1305
|
+
let session = null;
|
|
1306
|
+
let zoom = 1;
|
|
1307
|
+
let sign = 1;
|
|
1308
|
+
let wrote = false;
|
|
1309
|
+
const delta = (screen) => sign * (axis === "cols" ? screen.x : screen.y) / zoom;
|
|
1310
|
+
return {
|
|
1311
|
+
shouldStart: (event) => {
|
|
1312
|
+
mode = event.metaKey || event.ctrlKey ? "gap" : event.shiftKey || untrack(box).edge ? "insert" : "trade";
|
|
1313
|
+
return true;
|
|
1314
|
+
},
|
|
1315
|
+
movementAxes: () => axis === "cols" ? {
|
|
1316
|
+
x: true,
|
|
1317
|
+
y: false
|
|
1318
|
+
} : {
|
|
1319
|
+
x: false,
|
|
1320
|
+
y: true
|
|
1321
|
+
},
|
|
1322
|
+
onStart: (context) => {
|
|
1323
|
+
const v = untrack(visual);
|
|
1324
|
+
if (v === null) return;
|
|
1325
|
+
const line = untrack(box).line;
|
|
1326
|
+
zoom = v.geometry.zoom;
|
|
1327
|
+
sign = v.geometry[axis].reversed ? -1 : 1;
|
|
1328
|
+
wrote = false;
|
|
1329
|
+
window.clearTimeout(flashTimer);
|
|
1330
|
+
session = untrack(() => beginSession(dd, v.gridId, v.geometry, axis, line, mode));
|
|
1331
|
+
const step = session.peek();
|
|
1332
|
+
setDragging({
|
|
1333
|
+
axis,
|
|
1334
|
+
line,
|
|
1335
|
+
hot: step.line
|
|
1336
|
+
});
|
|
1337
|
+
showNote(context.startScreen.x, context.startScreen.y, step.note);
|
|
1338
|
+
},
|
|
1339
|
+
onMove: (context) => {
|
|
1340
|
+
if (session === null || !context.moved) return;
|
|
1341
|
+
wrote = true;
|
|
1342
|
+
const step = session.step(delta(context.deltaScreen));
|
|
1343
|
+
setDragging((d) => d === null ? null : {
|
|
1344
|
+
...d,
|
|
1345
|
+
hot: step.line
|
|
1346
|
+
});
|
|
1347
|
+
showNote(context.currentScreen.x, context.currentScreen.y, step.note);
|
|
1348
|
+
},
|
|
1349
|
+
onEnd: (context) => {
|
|
1350
|
+
if (context.moved || wrote) onMoved();
|
|
1351
|
+
if (session !== null) {
|
|
1352
|
+
if (context.canceled) session.restore();
|
|
1353
|
+
else {
|
|
1354
|
+
if (context.moved || wrote) session.step(delta(context.deltaScreen));
|
|
1355
|
+
session.commit();
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
session = null;
|
|
1359
|
+
setDragging(null);
|
|
1360
|
+
setNote(null);
|
|
1361
|
+
}
|
|
1362
|
+
};
|
|
1363
|
+
};
|
|
1364
|
+
const doubleClick = (axis, box, event) => {
|
|
1365
|
+
if (event.button !== 0 || event.metaKey || event.ctrlKey) return;
|
|
1366
|
+
const v = untrack(visual);
|
|
1367
|
+
if (v === null) return;
|
|
1368
|
+
const line = untrack(box).line;
|
|
1369
|
+
const text = untrack(() => event.shiftKey ? removeBefore(dd, v.gridId, v.geometry, axis, line) : insertEqualAt(dd, v.gridId, v.geometry, axis, line));
|
|
1370
|
+
showNote(event.clientX, event.clientY, text);
|
|
1371
|
+
window.clearTimeout(flashTimer);
|
|
1372
|
+
flashTimer = window.setTimeout(() => setNote(null), FLASH_MS);
|
|
1373
|
+
};
|
|
1374
|
+
const Handle = (props) => {
|
|
1375
|
+
let binding;
|
|
1376
|
+
let movedAt = Number.NEGATIVE_INFINITY;
|
|
1377
|
+
onSettled(() => () => binding?.dispose());
|
|
1378
|
+
const mine = (which) => {
|
|
1379
|
+
const d = dragging();
|
|
1380
|
+
return d !== null && d.axis === props.axis && d[which] === props.box().line;
|
|
1381
|
+
};
|
|
1382
|
+
var _el$ = _tmpl$();
|
|
1383
|
+
ref(() => {
|
|
1384
|
+
return (node) => {
|
|
1385
|
+
binding = dd.canvas.bindDrag(node, handlers(props.axis, props.box, () => {
|
|
1386
|
+
movedAt = performance.now();
|
|
1387
|
+
}));
|
|
1388
|
+
};
|
|
1389
|
+
}, _el$);
|
|
1390
|
+
_el$._$$dblclick = (event) => {
|
|
1391
|
+
if (performance.now() - movedAt < DOUBLE_CLICK_MS) return;
|
|
1392
|
+
doubleClick(props.axis, props.box, event);
|
|
1393
|
+
};
|
|
1394
|
+
effect(() => {
|
|
1395
|
+
return {
|
|
1396
|
+
e: `${p}-handle ${p}-handle-${props.axis}`,
|
|
1397
|
+
t: props.box().line,
|
|
1398
|
+
a: props.box().edge ? "" : void 0,
|
|
1399
|
+
o: mine("line") ? "" : void 0,
|
|
1400
|
+
i: mine("hot") ? "" : void 0,
|
|
1401
|
+
n: `${props.box().x}px`,
|
|
1402
|
+
s: `${props.box().y}px`,
|
|
1403
|
+
h: `${props.box().width}px`,
|
|
1404
|
+
r: `${props.box().height}px`
|
|
1405
|
+
};
|
|
1406
|
+
}, ({ e, t, a, o, i, n, s, h, r }, _p$) => {
|
|
1407
|
+
className(_el$, e, _p$?.e);
|
|
1408
|
+
t !== _p$?.t && setAttribute(_el$, "data-line", t);
|
|
1409
|
+
a !== _p$?.a && setAttribute(_el$, "data-edge", a);
|
|
1410
|
+
o !== _p$?.o && setAttribute(_el$, "data-active", o);
|
|
1411
|
+
i !== _p$?.i && setAttribute(_el$, "data-hot", i);
|
|
1412
|
+
n !== _p$?.n && setStyleProperty(_el$, "left", n);
|
|
1413
|
+
s !== _p$?.s && setStyleProperty(_el$, "top", s);
|
|
1414
|
+
h !== _p$?.h && setStyleProperty(_el$, "width", h);
|
|
1415
|
+
r !== _p$?.r && setStyleProperty(_el$, "height", r);
|
|
1416
|
+
});
|
|
1417
|
+
return _el$;
|
|
1418
|
+
};
|
|
1419
|
+
var _el$2 = _tmpl$2();
|
|
1420
|
+
var _el$3 = _el$2.firstChild;
|
|
1421
|
+
var _el$4 = _el$3.nextSibling;
|
|
1422
|
+
var _el$5 = _el$4.nextSibling;
|
|
1423
|
+
insert(_el$2, createComponent(For, {
|
|
1424
|
+
get each() {
|
|
1425
|
+
return cols();
|
|
1426
|
+
},
|
|
1427
|
+
keyed: false,
|
|
1428
|
+
children: (box) => createComponent(Handle, {
|
|
1429
|
+
axis: "cols",
|
|
1430
|
+
box
|
|
1431
|
+
})
|
|
1432
|
+
}), _el$3);
|
|
1433
|
+
insert(_el$2, createComponent(For, {
|
|
1434
|
+
get each() {
|
|
1435
|
+
return rows();
|
|
1436
|
+
},
|
|
1437
|
+
keyed: false,
|
|
1438
|
+
children: (box) => createComponent(Handle, {
|
|
1439
|
+
axis: "rows",
|
|
1440
|
+
box
|
|
1441
|
+
})
|
|
1442
|
+
}), _el$4);
|
|
1443
|
+
insert(_el$2, createComponent(Show, {
|
|
1444
|
+
get when() {
|
|
1445
|
+
return note();
|
|
1446
|
+
},
|
|
1447
|
+
children: (n) => (() => {
|
|
1448
|
+
var _el$6 = _tmpl$();
|
|
1449
|
+
insert(_el$6, () => {
|
|
1450
|
+
return n().text;
|
|
1451
|
+
});
|
|
1452
|
+
effect(() => {
|
|
1453
|
+
return {
|
|
1454
|
+
e: `${p}-note`,
|
|
1455
|
+
t: `${n().x}px`,
|
|
1456
|
+
a: `${n().y}px`
|
|
1457
|
+
};
|
|
1458
|
+
}, ({ e, t, a }, _p$) => {
|
|
1459
|
+
className(_el$6, e, _p$?.e);
|
|
1460
|
+
t !== _p$?.t && setStyleProperty(_el$6, "left", t);
|
|
1461
|
+
a !== _p$?.a && setStyleProperty(_el$6, "top", a);
|
|
1462
|
+
});
|
|
1463
|
+
return _el$6;
|
|
1464
|
+
})()
|
|
1465
|
+
}), _el$5);
|
|
1466
|
+
effect(() => {
|
|
1467
|
+
return {
|
|
1468
|
+
e: `${p}-layer`,
|
|
1469
|
+
t: dragging() === null ? void 0 : ""
|
|
1470
|
+
};
|
|
1471
|
+
}, ({ e, t }, _p$) => {
|
|
1472
|
+
className(_el$2, e, _p$?.e);
|
|
1473
|
+
t !== _p$?.t && setAttribute(_el$2, "data-dragging", t);
|
|
1474
|
+
});
|
|
1475
|
+
return _el$2;
|
|
1476
|
+
}
|
|
1477
|
+
delegateEvents(["dblclick"]);
|
|
1478
|
+
function activate(dd) {
|
|
1479
|
+
const p = classPrefix(dd.plugin.id);
|
|
1480
|
+
dd.registerOverlay({
|
|
1481
|
+
id: "grid",
|
|
1482
|
+
slot: "overlay.screen",
|
|
1483
|
+
styles: guidesCss(p),
|
|
1484
|
+
render: () => createGridOverlay(dd)
|
|
1485
|
+
});
|
|
1486
|
+
dd.registerOverlay({
|
|
1487
|
+
id: "grid-handles",
|
|
1488
|
+
slot: "overlay.interactive",
|
|
1489
|
+
styles: handlesCss(p),
|
|
1490
|
+
render: () => createGridHandles(dd)
|
|
1491
|
+
});
|
|
1492
|
+
}
|
|
1493
|
+
export { activate as default };
|