nodality 1.3.7 → 1.3.9
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/bin/nodality.mjs +1 -1
- package/dist/animator.cjs.js +1 -1
- package/dist/animator.cjs.js.LICENSE.txt +1 -1
- package/dist/animator.esm.js.LICENSE.txt +1 -1
- package/dist/audionew.cjs.js +1 -1
- package/dist/audionew.cjs.js.LICENSE.txt +1 -1
- package/dist/audionew.esm.js.LICENSE.txt +1 -1
- package/dist/base.cjs.js +1 -1
- package/dist/base.cjs.js.LICENSE.txt +1 -1
- package/dist/base.esm.js.LICENSE.txt +1 -1
- package/dist/beta-desktop-bar.cjs.js +1 -1
- package/dist/beta-desktop-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/beta-desktop-bar.esm.js.LICENSE.txt +1 -1
- package/dist/beta-mobile-bar.cjs.js +1 -1
- package/dist/beta-mobile-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/beta-mobile-bar.esm.js.LICENSE.txt +1 -1
- package/dist/bundle.umd.js +1 -1
- package/dist/bundle.umd.js.LICENSE.txt +1 -1
- package/dist/button.cjs.js +1 -1
- package/dist/button.cjs.js.LICENSE.txt +1 -1
- package/dist/button.esm.js.LICENSE.txt +1 -1
- package/dist/card-getter.cjs.js.LICENSE.txt +1 -1
- package/dist/card-getter.esm.js.LICENSE.txt +1 -1
- package/dist/center.cjs.js +1 -1
- package/dist/center.cjs.js.LICENSE.txt +1 -1
- package/dist/center.esm.js.LICENSE.txt +1 -1
- package/dist/checkbox.cjs.js +1 -1
- package/dist/checkbox.cjs.js.LICENSE.txt +1 -1
- package/dist/checkbox.esm.js.LICENSE.txt +1 -1
- package/dist/code.cjs.js +1 -1
- package/dist/code.cjs.js.LICENSE.txt +1 -1
- package/dist/code.esm.js.LICENSE.txt +1 -1
- package/dist/container.cjs.js +1 -1
- package/dist/container.cjs.js.LICENSE.txt +1 -1
- package/dist/container.esm.js.LICENSE.txt +1 -1
- package/dist/data-list.cjs.js.LICENSE.txt +1 -1
- package/dist/data-list.esm.js.LICENSE.txt +1 -1
- package/dist/designer.cjs.js +1 -1
- package/dist/designer.cjs.js.LICENSE.txt +1 -1
- package/dist/designer.esm.js +1 -1
- package/dist/designer.esm.js.LICENSE.txt +1 -1
- package/dist/element-mapper.cjs.js +1 -1
- package/dist/element-mapper.cjs.js.LICENSE.txt +1 -1
- package/dist/element-mapper.esm.js +1 -1
- package/dist/element-mapper.esm.js.LICENSE.txt +1 -1
- package/dist/finalresult.esm.js +2 -2
- package/dist/finalresult.esm.js.LICENSE.txt +1 -1
- package/dist/flex-card.cjs.js +1 -1
- package/dist/flex-card.cjs.js.LICENSE.txt +1 -1
- package/dist/flex-card.esm.js.LICENSE.txt +1 -1
- package/dist/flex-grid.cjs.js +1 -1
- package/dist/flex-grid.cjs.js.LICENSE.txt +1 -1
- package/dist/flex-grid.esm.js.LICENSE.txt +1 -1
- package/dist/flex-row.cjs.js +1 -1
- package/dist/flex-row.cjs.js.LICENSE.txt +1 -1
- package/dist/flex-row.esm.js.LICENSE.txt +1 -1
- package/dist/floating-input.cjs.js +1 -1
- package/dist/floating-input.cjs.js.LICENSE.txt +1 -1
- package/dist/floating-input.esm.js.LICENSE.txt +1 -1
- package/dist/free.cjs.js +1 -1
- package/dist/free.cjs.js.LICENSE.txt +1 -1
- package/dist/free.esm.js.LICENSE.txt +1 -1
- package/dist/horizontal-scroller.cjs.js.LICENSE.txt +1 -1
- package/dist/horizontal-scroller.esm.js.LICENSE.txt +1 -1
- package/dist/image-picker.cjs.js +1 -1
- package/dist/image-picker.cjs.js.LICENSE.txt +1 -1
- package/dist/image-picker.esm.js.LICENSE.txt +1 -1
- package/dist/image.cjs.js +1 -1
- package/dist/image.cjs.js.LICENSE.txt +1 -1
- package/dist/image.esm.js.LICENSE.txt +1 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.LICENSE.txt +1 -1
- package/dist/index.d.ts +17 -2
- package/dist/index.esm.js +2 -2
- package/dist/index.esm.js.LICENSE.txt +1 -1
- package/dist/keyframe-animation.cjs.js.LICENSE.txt +1 -1
- package/dist/keyframe-animation.esm.js.LICENSE.txt +1 -1
- package/dist/link-getter.cjs.js +1 -1
- package/dist/link-getter.cjs.js.LICENSE.txt +1 -1
- package/dist/link-getter.esm.js.LICENSE.txt +1 -1
- package/dist/link.cjs.js +1 -1
- package/dist/link.cjs.js.LICENSE.txt +1 -1
- package/dist/link.esm.js.LICENSE.txt +1 -1
- package/dist/meta-adder.cjs.js +1 -1
- package/dist/meta-adder.cjs.js.LICENSE.txt +1 -1
- package/dist/meta-adder.esm.js.LICENSE.txt +1 -1
- package/dist/modal-2025.cjs.js +1 -1
- package/dist/modal-2025.cjs.js.LICENSE.txt +1 -1
- package/dist/modal-2025.esm.js.LICENSE.txt +1 -1
- package/dist/multiswitcher.cjs.js +1 -1
- package/dist/multiswitcher.cjs.js.LICENSE.txt +1 -1
- package/dist/multiswitcher.esm.js.LICENSE.txt +1 -1
- package/dist/new-nav-bar.cjs.js +1 -1
- package/dist/new-nav-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/new-nav-bar.esm.js.LICENSE.txt +1 -1
- package/dist/picker.cjs.js +1 -1
- package/dist/picker.cjs.js.LICENSE.txt +1 -1
- package/dist/picker.esm.js.LICENSE.txt +1 -1
- package/dist/progress.cjs.js +1 -1
- package/dist/progress.cjs.js.LICENSE.txt +1 -1
- package/dist/progress.esm.js.LICENSE.txt +1 -1
- package/dist/radio.cjs.js.LICENSE.txt +1 -1
- package/dist/radio.esm.js.LICENSE.txt +1 -1
- package/dist/range.cjs.js.LICENSE.txt +1 -1
- package/dist/range.esm.js.LICENSE.txt +1 -1
- package/dist/scroll-video.cjs.js.LICENSE.txt +1 -1
- package/dist/scroll-video.esm.js.LICENSE.txt +1 -1
- package/dist/side-bar.cjs.js +1 -1
- package/dist/side-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/side-bar.esm.js.LICENSE.txt +1 -1
- package/dist/side-nav-bar.cjs.js +1 -1
- package/dist/side-nav-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/side-nav-bar.esm.js.LICENSE.txt +1 -1
- package/dist/simple-bar.cjs.js +1 -1
- package/dist/simple-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/simple-bar.esm.js.LICENSE.txt +1 -1
- package/dist/slider-2025.cjs.js +1 -1
- package/dist/slider-2025.cjs.js.LICENSE.txt +1 -1
- package/dist/slider-2025.esm.js.LICENSE.txt +1 -1
- package/dist/spacer.cjs.js +1 -1
- package/dist/spacer.cjs.js.LICENSE.txt +1 -1
- package/dist/spacer.esm.js.LICENSE.txt +1 -1
- package/dist/stack.cjs.js +1 -1
- package/dist/stack.cjs.js.LICENSE.txt +1 -1
- package/dist/stack.esm.js.LICENSE.txt +1 -1
- package/dist/stacker.cjs.js.LICENSE.txt +1 -1
- package/dist/stacker.esm.js.LICENSE.txt +1 -1
- package/dist/table.cjs.js +1 -1
- package/dist/table.cjs.js.LICENSE.txt +1 -1
- package/dist/table.esm.js.LICENSE.txt +1 -1
- package/dist/text-field.cjs.js +1 -1
- package/dist/text-field.cjs.js.LICENSE.txt +1 -1
- package/dist/text-field.esm.js.LICENSE.txt +1 -1
- package/dist/text.cjs.js +1 -1
- package/dist/text.cjs.js.LICENSE.txt +1 -1
- package/dist/text.esm.js.LICENSE.txt +1 -1
- package/dist/theme.cjs.js.LICENSE.txt +1 -1
- package/dist/theme.esm.js.LICENSE.txt +1 -1
- package/dist/transform-anim.cjs.js.LICENSE.txt +1 -1
- package/dist/transform-anim.esm.js.LICENSE.txt +1 -1
- package/dist/ulist.cjs.js +1 -1
- package/dist/ulist.cjs.js.LICENSE.txt +1 -1
- package/dist/ulist.esm.js.LICENSE.txt +1 -1
- package/dist/video.cjs.js +1 -1
- package/dist/video.cjs.js.LICENSE.txt +1 -1
- package/dist/video.esm.js +1 -1
- package/dist/video.esm.js.LICENSE.txt +1 -1
- package/dist/wrap.cjs.js +1 -1
- package/dist/wrap.cjs.js.LICENSE.txt +1 -1
- package/dist/wrap.esm.js.LICENSE.txt +1 -1
- package/dist/zoom-card.cjs.js +1 -1
- package/dist/zoom-card.cjs.js.LICENSE.txt +1 -1
- package/dist/zoom-card.esm.js.LICENSE.txt +1 -1
- package/layout/animator.js +1 -1
- package/layout/audio.js +1 -1
- package/layout/audionew.js +1 -1
- package/layout/base.js +1 -1
- package/layout/beta-desktop-bar.js +1 -1
- package/layout/beta-mobile-bar.js +1 -1
- package/layout/button.js +1 -1
- package/layout/center.js +1 -1
- package/layout/checkbox.js +1 -1
- package/layout/circle.js +1 -1
- package/layout/code.js +1 -1
- package/layout/container.js +1 -1
- package/layout/dropdown-2025.js +1 -1
- package/layout/flex-card.js +1 -1
- package/layout/flex-grid.js +1 -1
- package/layout/flex-row.js +1 -1
- package/layout/form-components/custom.js +1 -1
- package/layout/form-components/data-list.js +1 -1
- package/layout/form-components/floating-input.js +1 -1
- package/layout/form-components/form-all.js +1 -1
- package/layout/form-components/form.js +1 -1
- package/layout/form-components/image-picker.js +1 -1
- package/layout/form-components/picker.js +1 -1
- package/layout/form-components/radio.js +1 -1
- package/layout/form-components/radiogroup.js +1 -1
- package/layout/form-components/range.js +1 -1
- package/layout/free.js +1 -1
- package/layout/grid-overlay.js +296 -0
- package/layout/grid-switcher.js +1 -1
- package/layout/grid.js +1 -1
- package/layout/horizontal-scroller.js +1 -1
- package/layout/image.js +1 -1
- package/layout/index.js +5 -1
- package/layout/link.js +1 -1
- package/layout/list.js +1 -1
- package/layout/meta-adder.js +1 -1
- package/layout/modal-2025.js +1 -1
- package/layout/morph.js +1 -1
- package/layout/multiswitcher.js +1 -1
- package/layout/nav-bar.js +1 -1
- package/layout/nav-factor/custom-div.js +1 -1
- package/layout/new-nav-bar.js +1 -1
- package/layout/polygon.js +1 -1
- package/layout/prerender-site.js +1 -1
- package/layout/prerender.js +1 -1
- package/layout/progress.js +1 -1
- package/layout/row.js +1 -1
- package/layout/scroll-video.js +1 -1
- package/layout/side-bar.js +1 -1
- package/layout/side-nav-bar.js +1 -1
- package/layout/simple-bar.js +1 -1
- package/layout/slider-2025.js +1 -1
- package/layout/spacer.js +1 -1
- package/layout/stack.js +1 -1
- package/layout/svg.js +1 -1
- package/layout/switcher.js +1 -1
- package/layout/table.js +1 -1
- package/layout/text-field.js +1 -1
- package/layout/text.js +1 -1
- package/layout/ulist.js +1 -1
- package/layout/video.js +203 -38
- package/layout/wrap.js +1 -1
- package/layout/zoom-card.js +1 -1
- package/lib/agent-surface.js +1 -1
- package/lib/card-getter.js +1 -1
- package/lib/check-page.js +1 -1
- package/lib/codegen.js +1 -1
- package/lib/data.js +1 -1
- package/lib/designer.js +4 -2
- package/lib/element-mapper.js +36 -3
- package/lib/element-params.generated.js +2 -2
- package/lib/grid-geometry.js +137 -0
- package/lib/keyframe-animation.js +1 -1
- package/lib/link-getter.js +1 -1
- package/lib/morph-node.js +1 -1
- package/lib/normalize-spec.js +1 -1
- package/lib/parse-html.js +1 -1
- package/lib/raster-inspect.js +1 -1
- package/lib/raster-ops.js +42 -3
- package/lib/raster-presets.js +1 -1
- package/lib/resolve-refs.js +1 -1
- package/lib/scroll-video.js +1 -1
- package/lib/seo.js +1 -1
- package/lib/stacker.js +1 -1
- package/lib/suggest.js +1 -1
- package/lib/theme.js +1 -1
- package/lib/transform-anim.js +1 -1
- package/lib/transition.js +1 -1
- package/lib/validate-nodes.js +1 -1
- package/lib/webmcp-adapter.js +1 -1
- package/package.json +1 -1
- package/schema.json +164 -5
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* nodality v1.3.9
|
|
3
|
+
* (c) 2026 Filip Vabrousek
|
|
4
|
+
* License: MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// grid-geometry.js — the arithmetic behind GridOverlay.
|
|
8
|
+
//
|
|
9
|
+
// One pure function turns a box size and a grid description into the pixel
|
|
10
|
+
// position of every line and every intersection. It lives apart from the
|
|
11
|
+
// component for two reasons:
|
|
12
|
+
//
|
|
13
|
+
// • It is testable in bare Node. No DOM, no window, nothing at import.
|
|
14
|
+
// • Anything that must land ON the grid needs the same numbers. The
|
|
15
|
+
// overlay draws the lines; a layout component that places content in
|
|
16
|
+
// the cells has to agree with it to the pixel, and two copies of this
|
|
17
|
+
// maths would drift.
|
|
18
|
+
//
|
|
19
|
+
// Conventions
|
|
20
|
+
// columns / rows count CELLS, not lines. N cells → N+1 lines. 0 → no
|
|
21
|
+
// on that axis (and therefore no intersections).
|
|
22
|
+
// inset distance of the outermost lines from the box edge, in px.
|
|
23
|
+
// A number applies to both axes; { x, y } sets them apart.
|
|
24
|
+
// lineWidth used only to snap positions so 1px lines land on a pixel
|
|
25
|
+
// boundary and stay sharp instead of smearing over two.
|
|
26
|
+
|
|
27
|
+
const clampCount = (n) => {
|
|
28
|
+
const v = Math.floor(Number(n));
|
|
29
|
+
return Number.isFinite(v) && v > 0 ? v : 0;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const toInset = (inset) => {
|
|
33
|
+
if (inset && typeof inset === "object") {
|
|
34
|
+
return { x: Math.max(0, Number(inset.x) || 0), y: Math.max(0, Number(inset.y) || 0) };
|
|
35
|
+
}
|
|
36
|
+
const v = Math.max(0, Number(inset) || 0);
|
|
37
|
+
return { x: v, y: v };
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// Odd stroke widths centre on a half pixel; even ones on a whole pixel.
|
|
41
|
+
const snap = (v, lineWidth) => {
|
|
42
|
+
const w = Math.max(1, Math.round(Number(lineWidth) || 1));
|
|
43
|
+
return w % 2 === 1 ? Math.round(v - 0.5) + 0.5 : Math.round(v);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Positions of `count + 1` lines spread evenly from `start` to `end`.
|
|
47
|
+
const linePositions = (count, start, end, lineWidth) => {
|
|
48
|
+
if (count === 0 || end <= start) return [];
|
|
49
|
+
const step = (end - start) / count;
|
|
50
|
+
const out = [];
|
|
51
|
+
for (let i = 0; i <= count; i++) out.push(snap(start + step * i, lineWidth));
|
|
52
|
+
return out;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
function gridGeometry({ width = 0, height = 0, columns = 4, rows = 2, inset = 0, lineWidth = 1 } = {}) {
|
|
56
|
+
const w = Math.max(0, Number(width) || 0);
|
|
57
|
+
const h = Math.max(0, Number(height) || 0);
|
|
58
|
+
const c = clampCount(columns);
|
|
59
|
+
const r = clampCount(rows);
|
|
60
|
+
const pad = toInset(inset);
|
|
61
|
+
|
|
62
|
+
// An inset larger than half the box leaves no room for a grid.
|
|
63
|
+
const left = Math.min(pad.x, w / 2);
|
|
64
|
+
const top = Math.min(pad.y, h / 2);
|
|
65
|
+
|
|
66
|
+
const x = linePositions(c, left, w - left, lineWidth);
|
|
67
|
+
const y = linePositions(r, top, h - top, lineWidth);
|
|
68
|
+
|
|
69
|
+
const intersections = [];
|
|
70
|
+
for (let row = 0; row < y.length; row++) {
|
|
71
|
+
for (let col = 0; col < x.length; col++) {
|
|
72
|
+
intersections.push({ col, row, x: x[col], y: y[row] });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
width: w,
|
|
78
|
+
height: h,
|
|
79
|
+
columns: c,
|
|
80
|
+
rows: r,
|
|
81
|
+
inset: { x: left, y: top },
|
|
82
|
+
cell: {
|
|
83
|
+
width: c ? (w - 2 * left) / c : 0,
|
|
84
|
+
height: r ? (h - 2 * top) / r : 0,
|
|
85
|
+
},
|
|
86
|
+
x,
|
|
87
|
+
y,
|
|
88
|
+
intersections,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Options for the current viewport. Below `breakpoint` the keys in `mobile`
|
|
93
|
+
// replace their desktop counterparts; everything else carries over.
|
|
94
|
+
function resolveGridOptions(options = {}, viewportWidth = Infinity) {
|
|
95
|
+
const { mobile, ...base } = options || {};
|
|
96
|
+
const breakpoint = Number(base.breakpoint) || 768;
|
|
97
|
+
if (mobile && typeof mobile === "object" && viewportWidth < breakpoint) {
|
|
98
|
+
return { ...base, ...mobile };
|
|
99
|
+
}
|
|
100
|
+
return base;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Where a label sits relative to an intersection. `anchor` names the
|
|
104
|
+
// quadrant: "br" below-right (default), "bl", "tr", "tl".
|
|
105
|
+
//
|
|
106
|
+
// Pass `box` and the anchor becomes a preference rather than an order: a
|
|
107
|
+
// label that would land outside the box flips to the opposite side. Without
|
|
108
|
+
// it, any readout on the last column or bottom row is clipped by the host's
|
|
109
|
+
// overflow — which is what the outermost intersections are FOR, so the
|
|
110
|
+
// default must not punish using them.
|
|
111
|
+
function readoutPosition(point, anchor = "br", gap = 8, box = null) {
|
|
112
|
+
const a = ["tl", "tr", "bl", "br"].includes(anchor) ? anchor : "br";
|
|
113
|
+
let right = a[1] === "r";
|
|
114
|
+
let below = a[0] === "b";
|
|
115
|
+
|
|
116
|
+
if (box) {
|
|
117
|
+
const w = Number(box.width) || 0;
|
|
118
|
+
const h = Number(box.height) || 0;
|
|
119
|
+
// Room for a short label on the side the anchor asks for. The exact
|
|
120
|
+
// text width is a render-time measurement; this only has to catch the
|
|
121
|
+
// case where the intersection sits ON the edge.
|
|
122
|
+
const room = gap + 24;
|
|
123
|
+
if (right && point.x + room > w) right = false;
|
|
124
|
+
else if (!right && point.x - room < 0) right = true;
|
|
125
|
+
if (below && point.y + room > h) below = false;
|
|
126
|
+
else if (!below && point.y - room < 0) below = true;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
x: point.x + (right ? gap : -gap),
|
|
131
|
+
y: point.y + (below ? gap : -gap),
|
|
132
|
+
textAnchor: right ? "start" : "end",
|
|
133
|
+
baseline: below ? "hanging" : "alphabetic",
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export { gridGeometry, resolveGridOptions, readoutPosition };
|
package/lib/link-getter.js
CHANGED
package/lib/morph-node.js
CHANGED
package/lib/normalize-spec.js
CHANGED
package/lib/parse-html.js
CHANGED
package/lib/raster-inspect.js
CHANGED
package/lib/raster-ops.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* nodality v1.3.
|
|
2
|
+
* nodality v1.3.9
|
|
3
3
|
* (c) 2026 Filip Vabrousek
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -2936,8 +2936,24 @@ function snapshotToImage(el, w, h, dpr) {
|
|
|
2936
2936
|
return embeddedFontCss(el).catch(() => "").then((fontCss) => new Promise((resolve, reject) => {
|
|
2937
2937
|
const serialized = new XMLSerializer()
|
|
2938
2938
|
.serializeToString(freezeStyles(el, el.cloneNode(true)));
|
|
2939
|
+
// The SVG carries NO scaling at all — it is emitted at CSS size, 1:1.
|
|
2940
|
+
//
|
|
2941
|
+
// Engines do not agree about scaling foreignObject content: mobile Chrome and
|
|
2942
|
+
// Safari apply neither a viewBox ratio nor an ancestor transform to the HTML
|
|
2943
|
+
// subtree, so content laid out at `w x h` stayed `w x h` in the top-left of a
|
|
2944
|
+
// `w*dpr` canvas. Reading the uploaded texture back off the GPU on a dpr-3
|
|
2945
|
+
// phone showed exactly that: a 1101x369 texture with its ink confined to the
|
|
2946
|
+
// first 367x123. The same SVG looked correct in an <img> sized to 367 CSS px,
|
|
2947
|
+
// because there the unscaled content happened to fill the box — which is what
|
|
2948
|
+
// made this look like a compositing bug for so long.
|
|
2949
|
+
//
|
|
2950
|
+
// So the SVG is rasterised at the size its contents are laid out for, and the
|
|
2951
|
+
// dpr upscale is done by drawImage below, where the destination rectangle is
|
|
2952
|
+
// stated outright and no engine has an opinion. High-dpr output is a touch
|
|
2953
|
+
// softer than a native-resolution rasterisation would be; correct everywhere
|
|
2954
|
+
// beats crisp on the machines that happened to agree with us.
|
|
2939
2955
|
const svg =
|
|
2940
|
-
`<svg xmlns="http://www.w3.org/2000/svg" width="${w
|
|
2956
|
+
`<svg xmlns="http://www.w3.org/2000/svg" width="${w}" height="${h}" viewBox="0 0 ${w} ${h}">` +
|
|
2941
2957
|
`<foreignObject width="100%" height="100%">` +
|
|
2942
2958
|
`<div xmlns="http://www.w3.org/1999/xhtml">` +
|
|
2943
2959
|
(fontCss ? `<style>${fontCss}</style>` : "") +
|
|
@@ -2948,7 +2964,30 @@ function snapshotToImage(el, w, h, dpr) {
|
|
|
2948
2964
|
// globalThis. Where they do, the DOM constructor is gone and this
|
|
2949
2965
|
// promise never settles: the snapshot backend hangs with no error.
|
|
2950
2966
|
const img = document.createElement("img");
|
|
2951
|
-
img.onload = () =>
|
|
2967
|
+
img.onload = () => {
|
|
2968
|
+
// Rasterise into a canvas of exactly the size we asked for, and hand
|
|
2969
|
+
// THAT to the caller.
|
|
2970
|
+
//
|
|
2971
|
+
// texImage2D takes an image's INTRINSIC size, and engines disagree about
|
|
2972
|
+
// what that is for an SVG: desktop Chrome honours the width/height
|
|
2973
|
+
// attributes (w*dpr), while mobile Chrome and Safari take it from the
|
|
2974
|
+
// viewBox (w). On a phone the texture therefore arrived at 1/dpr scale
|
|
2975
|
+
// and the effect painted its content into the top-left corner of its own
|
|
2976
|
+
// canvas — the headline came out about a third of its size, while every
|
|
2977
|
+
// measurement of the box, the SVG and the CSS looked perfectly correct.
|
|
2978
|
+
//
|
|
2979
|
+
// Drawing with an explicit destination rectangle makes the size ours
|
|
2980
|
+
// instead of theirs, so the texture matches the backing store on every
|
|
2981
|
+
// engine. This mirrors what fitImageToBox already does for the
|
|
2982
|
+
// sole-image fast path.
|
|
2983
|
+
const c = document.createElement("canvas");
|
|
2984
|
+
c.width = Math.max(1, Math.round(w * dpr));
|
|
2985
|
+
c.height = Math.max(1, Math.round(h * dpr));
|
|
2986
|
+
const ctx = c.getContext("2d");
|
|
2987
|
+
if (!ctx) { resolve(img); return; }
|
|
2988
|
+
ctx.drawImage(img, 0, 0, c.width, c.height);
|
|
2989
|
+
resolve(c);
|
|
2990
|
+
};
|
|
2952
2991
|
img.onerror = reject;
|
|
2953
2992
|
img.src = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(svg);
|
|
2954
2993
|
}));
|
package/lib/raster-presets.js
CHANGED
package/lib/resolve-refs.js
CHANGED
package/lib/scroll-video.js
CHANGED
package/lib/seo.js
CHANGED
package/lib/stacker.js
CHANGED
package/lib/suggest.js
CHANGED
package/lib/theme.js
CHANGED
package/lib/transform-anim.js
CHANGED
package/lib/transition.js
CHANGED
package/lib/validate-nodes.js
CHANGED
package/lib/webmcp-adapter.js
CHANGED
package/package.json
CHANGED
package/schema.json
CHANGED
|
@@ -4593,16 +4593,85 @@
|
|
|
4593
4593
|
"Set"
|
|
4594
4594
|
],
|
|
4595
4595
|
"params": [
|
|
4596
|
+
{
|
|
4597
|
+
"name": "aspectRatio",
|
|
4598
|
+
"description": "Box proportion held before the video loads, e.g. \"16 / 9\". Prevents the page shifting when the first frame arrives."
|
|
4599
|
+
},
|
|
4600
|
+
{
|
|
4601
|
+
"name": "autoplay",
|
|
4602
|
+
"description": "Start on its own. Implies muted and playsinline, pauses off screen and in a hidden tab, and is cancelled by prefers-reduced-motion (the poster stays)."
|
|
4603
|
+
},
|
|
4604
|
+
{
|
|
4605
|
+
"name": "background",
|
|
4606
|
+
"description": "CSS background behind the frame — visible while the poster loads."
|
|
4607
|
+
},
|
|
4608
|
+
{
|
|
4609
|
+
"name": "controls",
|
|
4610
|
+
"description": "Show the browser's playback controls. Default true — pass false for an ambient loop."
|
|
4611
|
+
},
|
|
4612
|
+
{
|
|
4613
|
+
"name": "decorative",
|
|
4614
|
+
"description": "Hide from assistive technology. For an ambient loop that repeats what the page already says in text."
|
|
4615
|
+
},
|
|
4616
|
+
{
|
|
4617
|
+
"name": "height",
|
|
4618
|
+
"description": "CSS height of the element."
|
|
4619
|
+
},
|
|
4596
4620
|
{
|
|
4597
4621
|
"name": "id",
|
|
4598
4622
|
"description": "This element's DOM id. Also what a design node's `target` names, and what `parse` recovers an element by."
|
|
4599
4623
|
},
|
|
4600
4624
|
{
|
|
4601
|
-
"name": "
|
|
4625
|
+
"name": "label",
|
|
4626
|
+
"description": "Accessible name, for a clip that carries meaning."
|
|
4627
|
+
},
|
|
4628
|
+
{
|
|
4629
|
+
"name": "lazy",
|
|
4630
|
+
"description": "Only play while on screen. On by default whenever `autoplay` is set; pass false to keep an autoplaying clip running off screen."
|
|
4631
|
+
},
|
|
4632
|
+
{
|
|
4633
|
+
"name": "loop",
|
|
4634
|
+
"description": "Restart when the clip ends."
|
|
4635
|
+
},
|
|
4636
|
+
{
|
|
4637
|
+
"name": "maxWidth",
|
|
4638
|
+
"description": "CSS max-width of the element."
|
|
4639
|
+
},
|
|
4640
|
+
{
|
|
4641
|
+
"name": "muted",
|
|
4642
|
+
"description": "Mute the audio track. Forced on by `autoplay`, because browsers block an unmuted autoplay; pass false only if you mean to accept that."
|
|
4643
|
+
},
|
|
4644
|
+
{
|
|
4645
|
+
"name": "objectFit",
|
|
4646
|
+
"description": "How the frame fills the element box: \"cover\", \"contain\", \"fill\", \"none\"."
|
|
4647
|
+
},
|
|
4648
|
+
{
|
|
4649
|
+
"name": "opacity",
|
|
4650
|
+
"description": "0–1."
|
|
4651
|
+
},
|
|
4652
|
+
{
|
|
4653
|
+
"name": "playsinline",
|
|
4654
|
+
"description": "Play in place on iPhone instead of taking over the screen. Implied by `autoplay`; there is no reason to refuse it on a background loop."
|
|
4655
|
+
},
|
|
4656
|
+
{
|
|
4657
|
+
"name": "poster",
|
|
4658
|
+
"description": "Image shown before the first frame decodes. Give one on any autoplaying clip: it is what holds the layout still and what reduced-motion visitors see instead of the video."
|
|
4659
|
+
},
|
|
4660
|
+
{
|
|
4661
|
+
"name": "preload",
|
|
4662
|
+
"description": "\"none\", \"metadata\" (a good default for a loop) or \"auto\"."
|
|
4602
4663
|
},
|
|
4603
4664
|
{
|
|
4604
4665
|
"name": "radius",
|
|
4605
|
-
"description": "Corner radius
|
|
4666
|
+
"description": "Corner radius. A CSS length; a bare number is read as pixels."
|
|
4667
|
+
},
|
|
4668
|
+
{
|
|
4669
|
+
"name": "raster",
|
|
4670
|
+
"description": "Raster op nodes to run over this element."
|
|
4671
|
+
},
|
|
4672
|
+
{
|
|
4673
|
+
"name": "sources",
|
|
4674
|
+
"description": "Several encodings of the same clip: [{url, type}] or plain url strings. The browser picks the first it can play, so order best-first (AV1, then HEVC, then H.264). `type` is inferred from the extension when omitted."
|
|
4606
4675
|
},
|
|
4607
4676
|
{
|
|
4608
4677
|
"name": "type",
|
|
@@ -4612,7 +4681,8 @@
|
|
|
4612
4681
|
"name": "url"
|
|
4613
4682
|
},
|
|
4614
4683
|
{
|
|
4615
|
-
"name": "width"
|
|
4684
|
+
"name": "width",
|
|
4685
|
+
"description": "CSS width of the element."
|
|
4616
4686
|
}
|
|
4617
4687
|
]
|
|
4618
4688
|
},
|
|
@@ -6285,11 +6355,100 @@
|
|
|
6285
6355
|
"name": "width"
|
|
6286
6356
|
}
|
|
6287
6357
|
]
|
|
6358
|
+
},
|
|
6359
|
+
"gridOverlay": {
|
|
6360
|
+
"resolved": true,
|
|
6361
|
+
"mapper": "mapGridOverlay",
|
|
6362
|
+
"components": [
|
|
6363
|
+
"GridOverlay"
|
|
6364
|
+
],
|
|
6365
|
+
"params": [
|
|
6366
|
+
{
|
|
6367
|
+
"name": "breakpoint",
|
|
6368
|
+
"description": "Viewport width in px below which `mobile` applies. Default 768."
|
|
6369
|
+
},
|
|
6370
|
+
{
|
|
6371
|
+
"name": "color",
|
|
6372
|
+
"description": "Colour of lines, marks and readouts (drawn with currentColor). Falls back to the Theme text colour."
|
|
6373
|
+
},
|
|
6374
|
+
{
|
|
6375
|
+
"name": "columns",
|
|
6376
|
+
"description": "Columns, counted as cells (N cells draw N+1 lines). 0 draws no vertical lines. Default 4. Named `columns`, not `cols`: the library's shared `cols` means grid-template-columns verbatim."
|
|
6377
|
+
},
|
|
6378
|
+
{
|
|
6379
|
+
"name": "font",
|
|
6380
|
+
"description": "Font family of the readouts. Default a monospace stack."
|
|
6381
|
+
},
|
|
6382
|
+
{
|
|
6383
|
+
"name": "fontSize",
|
|
6384
|
+
"description": "Readout font size in px. Default 11."
|
|
6385
|
+
},
|
|
6386
|
+
{
|
|
6387
|
+
"name": "id",
|
|
6388
|
+
"description": "This element's DOM id. Also what a design node's `target` names, and what `parse` recovers an element by."
|
|
6389
|
+
},
|
|
6390
|
+
{
|
|
6391
|
+
"name": "inset",
|
|
6392
|
+
"description": "Distance of the outermost lines from the edge in px. A number, or {x, y}. Default 16."
|
|
6393
|
+
},
|
|
6394
|
+
{
|
|
6395
|
+
"name": "letterSpacing",
|
|
6396
|
+
"description": "Readout letter spacing, any CSS length. Default \"0.04em\"."
|
|
6397
|
+
},
|
|
6398
|
+
{
|
|
6399
|
+
"name": "lineOpacity",
|
|
6400
|
+
"description": "Opacity of the lines only; marks and readouts stay opaque. 0–1, default 0.35."
|
|
6401
|
+
},
|
|
6402
|
+
{
|
|
6403
|
+
"name": "lineWidth",
|
|
6404
|
+
"description": "Stroke width of the grid lines in px. Default 1."
|
|
6405
|
+
},
|
|
6406
|
+
{
|
|
6407
|
+
"name": "markSize",
|
|
6408
|
+
"description": "Size of each registration mark in px. Default 8."
|
|
6409
|
+
},
|
|
6410
|
+
{
|
|
6411
|
+
"name": "marks",
|
|
6412
|
+
"description": "Registration mark at each intersection: \"square\" (default), \"cross\" or \"none\"."
|
|
6413
|
+
},
|
|
6414
|
+
{
|
|
6415
|
+
"name": "mobile",
|
|
6416
|
+
"description": "Options that replace their desktop values below `breakpoint`, e.g. {columns: 1, rows: 4}."
|
|
6417
|
+
},
|
|
6418
|
+
{
|
|
6419
|
+
"name": "position",
|
|
6420
|
+
"description": "\"fixed\" (default) pins the grid to the viewport; \"absolute\" fills the nearest positioned ancestor."
|
|
6421
|
+
},
|
|
6422
|
+
{
|
|
6423
|
+
"name": "raster",
|
|
6424
|
+
"description": "Raster op nodes for the overlay, e.g. an offset driven by hover to bend the lines near the cursor."
|
|
6425
|
+
},
|
|
6426
|
+
{
|
|
6427
|
+
"name": "readouts",
|
|
6428
|
+
"description": "Labels beside intersections: [{id, col, row, text, anchor}]. col/row index lines from 0; anchor \"br\" (default), \"bl\", \"tr\" or \"tl\", flipped automatically when the label would fall outside. Decorative — say the same thing in real page text."
|
|
6429
|
+
},
|
|
6430
|
+
{
|
|
6431
|
+
"name": "rows",
|
|
6432
|
+
"description": "Rows across the overlay's height, counted as cells. 0 draws no horizontal lines. Default 2."
|
|
6433
|
+
},
|
|
6434
|
+
{
|
|
6435
|
+
"name": "type",
|
|
6436
|
+
"description": "The element type, which selects the mapper that builds it -- \"h1\", \"cards\", \"form\", and so on."
|
|
6437
|
+
},
|
|
6438
|
+
{
|
|
6439
|
+
"name": "uppercase",
|
|
6440
|
+
"description": "Uppercase the readout text. Default true."
|
|
6441
|
+
},
|
|
6442
|
+
{
|
|
6443
|
+
"name": "zIndex",
|
|
6444
|
+
"description": "Stacking order of the overlay. Default 2 — keep navigation above it."
|
|
6445
|
+
}
|
|
6446
|
+
]
|
|
6288
6447
|
}
|
|
6289
6448
|
},
|
|
6290
6449
|
"summary": {
|
|
6291
|
-
"types":
|
|
6292
|
-
"resolved":
|
|
6450
|
+
"types": 36,
|
|
6451
|
+
"resolved": 36,
|
|
6293
6452
|
"unresolved": 0
|
|
6294
6453
|
}
|
|
6295
6454
|
}
|