nodality 1.3.8 → 1.3.10
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.LICENSE.txt +1 -1
- package/dist/animator.esm.js.LICENSE.txt +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.LICENSE.txt +1 -1
- package/dist/base.esm.js.LICENSE.txt +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.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.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.LICENSE.txt +1 -1
- package/dist/center.esm.js.LICENSE.txt +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.LICENSE.txt +1 -1
- package/dist/code.esm.js.LICENSE.txt +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.LICENSE.txt +1 -1
- package/dist/flex-card.esm.js.LICENSE.txt +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.LICENSE.txt +1 -1
- package/dist/flex-row.esm.js.LICENSE.txt +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.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.LICENSE.txt +1 -1
- package/dist/image-picker.esm.js.LICENSE.txt +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.LICENSE.txt +1 -1
- package/dist/link-getter.esm.js.LICENSE.txt +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.LICENSE.txt +1 -1
- package/dist/meta-adder.esm.js.LICENSE.txt +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.LICENSE.txt +1 -1
- package/dist/multiswitcher.esm.js.LICENSE.txt +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.LICENSE.txt +1 -1
- package/dist/picker.esm.js.LICENSE.txt +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.LICENSE.txt +1 -1
- package/dist/side-bar.esm.js.LICENSE.txt +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.LICENSE.txt +1 -1
- package/dist/simple-bar.esm.js.LICENSE.txt +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.LICENSE.txt +1 -1
- package/dist/spacer.esm.js.LICENSE.txt +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.LICENSE.txt +1 -1
- package/dist/table.esm.js.LICENSE.txt +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.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.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.LICENSE.txt +1 -1
- package/dist/wrap.esm.js.LICENSE.txt +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 +206 -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 +1 -1
- 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 +165 -6
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* nodality v1.3.10
|
|
3
|
+
* (c) 2026 Filip Vabrousek
|
|
4
|
+
* License: MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Animator } from "./animator.js";
|
|
8
|
+
import { toObjectSource } from "../lib/codegen.js";
|
|
9
|
+
import { gridGeometry, resolveGridOptions, readoutPosition } from "../lib/grid-geometry.js";
|
|
10
|
+
|
|
11
|
+
// GridOverlay — a blueprint grid drawn over the page: lines, registration
|
|
12
|
+
// marks at the intersections, and small uppercase readouts beside chosen
|
|
13
|
+
// intersections.
|
|
14
|
+
//
|
|
15
|
+
// new GridOverlay().set({
|
|
16
|
+
// columns: 4, rows: 2, inset: 16, color: "#fff",
|
|
17
|
+
// readouts: [{ id: "angle", col: 1, row: 1, text: "horná časť · 412 mm" }],
|
|
18
|
+
// mobile: { columns: 1, rows: 4 },
|
|
19
|
+
// }).render("#mount");
|
|
20
|
+
//
|
|
21
|
+
// It is decoration by contract: `aria-hidden`, `pointer-events: none`, and
|
|
22
|
+
// nothing in it is focusable. Anything a readout says must also exist as
|
|
23
|
+
// real text on the page.
|
|
24
|
+
//
|
|
25
|
+
// Lines use `currentColor`, so `color` recolours the whole grid, and Theme
|
|
26
|
+
// defaults apply when no colour is given.
|
|
27
|
+
//
|
|
28
|
+
// `position: "fixed"` (default) pins the grid to the viewport so it stays
|
|
29
|
+
// while content scrolls under it. `position: "absolute"` fills the nearest
|
|
30
|
+
// positioned ancestor instead — give that ancestor `position: relative`.
|
|
31
|
+
//
|
|
32
|
+
// Geometry comes from lib/grid-geometry.js, which layout components that
|
|
33
|
+
// place content on the same grid should share.
|
|
34
|
+
|
|
35
|
+
const SVG_NS = "http://www.w3.org/2000/svg";
|
|
36
|
+
|
|
37
|
+
const DEFAULTS = {
|
|
38
|
+
columns: 4,
|
|
39
|
+
rows: 2,
|
|
40
|
+
inset: 16,
|
|
41
|
+
lineWidth: 1,
|
|
42
|
+
lineOpacity: 0.35,
|
|
43
|
+
marks: "square", // "square" | "cross" | "none"
|
|
44
|
+
markSize: 8,
|
|
45
|
+
position: "fixed", // "fixed" | "absolute"
|
|
46
|
+
zIndex: 2,
|
|
47
|
+
font: "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace",
|
|
48
|
+
fontSize: 11,
|
|
49
|
+
letterSpacing: "0.04em",
|
|
50
|
+
uppercase: true,
|
|
51
|
+
breakpoint: 768,
|
|
52
|
+
readouts: [],
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
class GridOverlay extends Animator {
|
|
56
|
+
constructor() {
|
|
57
|
+
super();
|
|
58
|
+
this.options = {};
|
|
59
|
+
this.config = null;
|
|
60
|
+
this._readoutEls = new Map();
|
|
61
|
+
this._readoutText = new Map();
|
|
62
|
+
this.setup();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
setup() {
|
|
66
|
+
const host = document.createElement("div");
|
|
67
|
+
host.setAttribute("aria-hidden", "true");
|
|
68
|
+
host.setAttribute("data-nodality", "grid-overlay");
|
|
69
|
+
host.style.pointerEvents = "none";
|
|
70
|
+
host.style.top = "0";
|
|
71
|
+
host.style.right = "0";
|
|
72
|
+
host.style.bottom = "0";
|
|
73
|
+
host.style.left = "0";
|
|
74
|
+
host.style.overflow = "hidden";
|
|
75
|
+
|
|
76
|
+
const svg = document.createElementNS(SVG_NS, "svg");
|
|
77
|
+
svg.setAttribute("width", "100%");
|
|
78
|
+
svg.setAttribute("height", "100%");
|
|
79
|
+
svg.setAttribute("focusable", "false");
|
|
80
|
+
svg.style.display = "block";
|
|
81
|
+
host.appendChild(svg);
|
|
82
|
+
|
|
83
|
+
this.res = host;
|
|
84
|
+
this.svg = svg;
|
|
85
|
+
return this;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
set(obj = {}) {
|
|
89
|
+
this.options = obj;
|
|
90
|
+
|
|
91
|
+
// Every option is read as a literal `obj.name`: the schema generator
|
|
92
|
+
// discovers a type's parameters from exactly these reads, so a spread
|
|
93
|
+
// or a destructure here would hide them from `get_schema` and make the
|
|
94
|
+
// validator reject valid specs.
|
|
95
|
+
this.config = {
|
|
96
|
+
//@ gridOverlay.columns: 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.
|
|
97
|
+
columns: obj.columns ?? DEFAULTS.columns,
|
|
98
|
+
//@ gridOverlay.rows: Rows across the overlay's height, counted as cells. 0 draws no horizontal lines. Default 2.
|
|
99
|
+
rows: obj.rows ?? DEFAULTS.rows,
|
|
100
|
+
//@ gridOverlay.inset: Distance of the outermost lines from the edge in px. A number, or {x, y}. Default 16.
|
|
101
|
+
inset: obj.inset ?? DEFAULTS.inset,
|
|
102
|
+
//@ gridOverlay.color: Colour of lines, marks and readouts (drawn with currentColor). Falls back to the Theme text colour.
|
|
103
|
+
color: obj.color,
|
|
104
|
+
//@ gridOverlay.lineWidth: Stroke width of the grid lines in px. Default 1.
|
|
105
|
+
lineWidth: obj.lineWidth ?? DEFAULTS.lineWidth,
|
|
106
|
+
//@ gridOverlay.lineOpacity: Opacity of the lines only; marks and readouts stay opaque. 0–1, default 0.35.
|
|
107
|
+
lineOpacity: obj.lineOpacity ?? DEFAULTS.lineOpacity,
|
|
108
|
+
//@ gridOverlay.marks: Registration mark at each intersection: "square" (default), "cross" or "none".
|
|
109
|
+
marks: obj.marks ?? DEFAULTS.marks,
|
|
110
|
+
//@ gridOverlay.markSize: Size of each registration mark in px. Default 8.
|
|
111
|
+
markSize: obj.markSize ?? DEFAULTS.markSize,
|
|
112
|
+
//@ gridOverlay.position: "fixed" (default) pins the grid to the viewport; "absolute" fills the nearest positioned ancestor.
|
|
113
|
+
position: obj.position ?? DEFAULTS.position,
|
|
114
|
+
//@ gridOverlay.zIndex: Stacking order of the overlay. Default 2 — keep navigation above it.
|
|
115
|
+
zIndex: obj.zIndex ?? DEFAULTS.zIndex,
|
|
116
|
+
//@ gridOverlay.font: Font family of the readouts. Default a monospace stack.
|
|
117
|
+
font: obj.font ?? DEFAULTS.font,
|
|
118
|
+
//@ gridOverlay.fontSize: Readout font size in px. Default 11.
|
|
119
|
+
fontSize: obj.fontSize ?? DEFAULTS.fontSize,
|
|
120
|
+
//@ gridOverlay.letterSpacing: Readout letter spacing, any CSS length. Default "0.04em".
|
|
121
|
+
letterSpacing: obj.letterSpacing ?? DEFAULTS.letterSpacing,
|
|
122
|
+
//@ gridOverlay.uppercase: Uppercase the readout text. Default true.
|
|
123
|
+
uppercase: obj.uppercase ?? DEFAULTS.uppercase,
|
|
124
|
+
//@ gridOverlay.breakpoint: Viewport width in px below which `mobile` applies. Default 768.
|
|
125
|
+
breakpoint: obj.breakpoint ?? DEFAULTS.breakpoint,
|
|
126
|
+
//@ gridOverlay.mobile: Options that replace their desktop values below `breakpoint`, e.g. {columns: 1, rows: 4}.
|
|
127
|
+
mobile: obj.mobile,
|
|
128
|
+
//@ gridOverlay.readouts: 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.
|
|
129
|
+
readouts: obj.readouts ?? DEFAULTS.readouts,
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const c = this.config;
|
|
133
|
+
this.res.style.position = c.position === "absolute" ? "absolute" : "fixed";
|
|
134
|
+
this.res.style.zIndex = String(c.zIndex);
|
|
135
|
+
obj.color && (this.res.style.color = obj.color);
|
|
136
|
+
obj.id && this.res.setAttribute("id", obj.id);
|
|
137
|
+
|
|
138
|
+
this._watchSize();
|
|
139
|
+
this.draw();
|
|
140
|
+
|
|
141
|
+
//@ gridOverlay.raster: Raster op nodes for the overlay, e.g. an offset driven by hover to bend the lines near the cursor.
|
|
142
|
+
obj.raster && this.rasterize(obj.raster);
|
|
143
|
+
return this;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Change one readout's text without rebuilding the grid — the path for
|
|
147
|
+
// live values such as a rotation angle.
|
|
148
|
+
readout(id, text) {
|
|
149
|
+
this._readoutText.set(id, text);
|
|
150
|
+
const el = this._readoutEls.get(id);
|
|
151
|
+
if (el) el.textContent = this._format(text);
|
|
152
|
+
return this;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// The geometry currently drawn, for callers that align content to it.
|
|
156
|
+
geometry() {
|
|
157
|
+
return this._geometry || null;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
draw() {
|
|
161
|
+
if (!this.config) return this;
|
|
162
|
+
const { width, height } = this._measure();
|
|
163
|
+
const c = resolveGridOptions(this.config, this._viewportWidth());
|
|
164
|
+
const g = gridGeometry({
|
|
165
|
+
width, height,
|
|
166
|
+
columns: c.columns, rows: c.rows,
|
|
167
|
+
inset: c.inset, lineWidth: c.lineWidth,
|
|
168
|
+
});
|
|
169
|
+
this._geometry = g;
|
|
170
|
+
|
|
171
|
+
const svg = this.svg;
|
|
172
|
+
while (svg.firstChild) svg.removeChild(svg.firstChild);
|
|
173
|
+
this._readoutEls.clear();
|
|
174
|
+
if (!width || !height) return this;
|
|
175
|
+
|
|
176
|
+
svg.setAttribute("viewBox", `0 0 ${width} ${height}`);
|
|
177
|
+
|
|
178
|
+
// Lines run edge to edge; the inset only decides where they sit.
|
|
179
|
+
const lines = this._node("g", {
|
|
180
|
+
stroke: "currentColor",
|
|
181
|
+
"stroke-width": c.lineWidth,
|
|
182
|
+
"stroke-opacity": c.lineOpacity,
|
|
183
|
+
"shape-rendering": "crispEdges",
|
|
184
|
+
});
|
|
185
|
+
for (const x of g.x) lines.appendChild(this._node("line", { x1: x, y1: 0, x2: x, y2: height }));
|
|
186
|
+
for (const y of g.y) lines.appendChild(this._node("line", { x1: 0, y1: y, x2: width, y2: y }));
|
|
187
|
+
svg.appendChild(lines);
|
|
188
|
+
|
|
189
|
+
const s = Number(c.markSize) || 0;
|
|
190
|
+
if (s > 0 && c.marks === "square") {
|
|
191
|
+
const marks = this._node("g", { fill: "currentColor", "shape-rendering": "crispEdges" });
|
|
192
|
+
for (const p of g.intersections) {
|
|
193
|
+
marks.appendChild(this._node("rect", { x: p.x - s / 2, y: p.y - s / 2, width: s, height: s }));
|
|
194
|
+
}
|
|
195
|
+
svg.appendChild(marks);
|
|
196
|
+
} else if (s > 0 && c.marks === "cross") {
|
|
197
|
+
const d = g.intersections
|
|
198
|
+
.map((p) => `M${p.x - s / 2} ${p.y}H${p.x + s / 2}M${p.x} ${p.y - s / 2}V${p.y + s / 2}`)
|
|
199
|
+
.join("");
|
|
200
|
+
if (d) {
|
|
201
|
+
svg.appendChild(this._node("path", {
|
|
202
|
+
d, fill: "none", stroke: "currentColor",
|
|
203
|
+
"stroke-width": c.lineWidth, "shape-rendering": "crispEdges",
|
|
204
|
+
}));
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const readouts = Array.isArray(c.readouts) ? c.readouts : [];
|
|
209
|
+
if (readouts.length) {
|
|
210
|
+
const group = this._node("g", {
|
|
211
|
+
fill: "currentColor",
|
|
212
|
+
"font-family": c.font,
|
|
213
|
+
"font-size": c.fontSize,
|
|
214
|
+
"letter-spacing": c.letterSpacing,
|
|
215
|
+
});
|
|
216
|
+
const gap = s / 2 + 6;
|
|
217
|
+
readouts.forEach((r, i) => {
|
|
218
|
+
if (!r) return;
|
|
219
|
+
const point = g.intersections.find((p) => p.col === r.col && p.row === r.row);
|
|
220
|
+
if (!point) return;
|
|
221
|
+
const pos = readoutPosition(point, r.anchor, gap, { width, height });
|
|
222
|
+
const id = r.id != null ? String(r.id) : `readout-${i}`;
|
|
223
|
+
const text = this._node("text", {
|
|
224
|
+
x: pos.x, y: pos.y,
|
|
225
|
+
"text-anchor": pos.textAnchor,
|
|
226
|
+
"dominant-baseline": pos.baseline,
|
|
227
|
+
"data-readout": id,
|
|
228
|
+
});
|
|
229
|
+
text.textContent = this._format(this._readoutText.has(id) ? this._readoutText.get(id) : r.text);
|
|
230
|
+
group.appendChild(text);
|
|
231
|
+
this._readoutEls.set(id, text);
|
|
232
|
+
});
|
|
233
|
+
svg.appendChild(group);
|
|
234
|
+
}
|
|
235
|
+
return this;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
_format(text) {
|
|
239
|
+
const s = text == null ? "" : String(text);
|
|
240
|
+
return this.config && this.config.uppercase === false ? s : s.toUpperCase();
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
_node(tag, attrs) {
|
|
244
|
+
const el = document.createElementNS(SVG_NS, tag);
|
|
245
|
+
for (const k in attrs) el.setAttribute(k, String(attrs[k]));
|
|
246
|
+
return el;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
_viewportWidth() {
|
|
250
|
+
return typeof window !== "undefined" && window.innerWidth ? window.innerWidth : Infinity;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// The host's own box once laid out; the viewport before that. Before
|
|
254
|
+
// render() the element has no box, and under jsdom it never does.
|
|
255
|
+
_measure() {
|
|
256
|
+
const hasWindow = typeof window !== "undefined";
|
|
257
|
+
const width = this.res.clientWidth || (hasWindow ? window.innerWidth : 0) || 0;
|
|
258
|
+
const height = this.res.clientHeight || (hasWindow ? window.innerHeight : 0) || 0;
|
|
259
|
+
return { width, height };
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
_watchSize() {
|
|
263
|
+
if (this._watching || typeof window === "undefined") return;
|
|
264
|
+
this._watching = true;
|
|
265
|
+
if (typeof window.ResizeObserver === "function") {
|
|
266
|
+
const ro = new window.ResizeObserver(() => this.draw());
|
|
267
|
+
ro.observe(this.res);
|
|
268
|
+
this._track(() => ro.disconnect());
|
|
269
|
+
} else {
|
|
270
|
+
this._on(window, "resize", () => this.draw());
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
toCode() {
|
|
275
|
+
if (this.excludeFromCodeTrue) return [""];
|
|
276
|
+
const cleaned = Object.fromEntries(
|
|
277
|
+
Object.entries(this.options || {}).filter(([, v]) => v != null)
|
|
278
|
+
);
|
|
279
|
+
return [`new GridOverlay().set(${toObjectSource(cleaned, 4)})`];
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
excludeFromCode() { this.excludeFromCodeTrue = true; return this; }
|
|
283
|
+
|
|
284
|
+
render(selector) {
|
|
285
|
+
if (selector) {
|
|
286
|
+
const parent = document.querySelector(selector);
|
|
287
|
+
if (parent) {
|
|
288
|
+
parent.appendChild(this.res);
|
|
289
|
+
this.draw();
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return this.res;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
export { GridOverlay };
|
package/layout/grid-switcher.js
CHANGED
package/layout/grid.js
CHANGED
package/layout/image.js
CHANGED
package/layout/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* nodality v1.3.
|
|
2
|
+
* nodality v1.3.10
|
|
3
3
|
* (c) 2026 Filip Vabrousek
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -69,6 +69,7 @@ import { Theme } from "../lib/theme.js";
|
|
|
69
69
|
import { AreaSwitcher } from "../layout/grid-switcher.js";
|
|
70
70
|
import { Polygon } from "../layout/polygon.js";
|
|
71
71
|
import { Circle } from "../layout/circle.js";
|
|
72
|
+
import { GridOverlay } from "../layout/grid-overlay.js";
|
|
72
73
|
|
|
73
74
|
// SEO + data helpers — also surface via package.json subpath exports
|
|
74
75
|
// (`nodality/seo`, `nodality/data`) for Node-side tree-shaking, but we
|
|
@@ -140,6 +141,7 @@ if (typeof window !== 'undefined') {
|
|
|
140
141
|
window.Slider = Slider;
|
|
141
142
|
window.Polygon = Polygon;
|
|
142
143
|
window.Circle = Circle;
|
|
144
|
+
window.GridOverlay = GridOverlay;
|
|
143
145
|
window.FloatingInput = FloatingInput;
|
|
144
146
|
window.Form = Form;
|
|
145
147
|
}
|
|
@@ -200,6 +202,7 @@ if (typeof global !== 'undefined') {
|
|
|
200
202
|
global.Slider = Slider;
|
|
201
203
|
global.Polygon = Polygon;
|
|
202
204
|
global.Circle = Circle;
|
|
205
|
+
global.GridOverlay = GridOverlay;
|
|
203
206
|
global.FloatingInput = FloatingInput;
|
|
204
207
|
global.Form = Form;
|
|
205
208
|
}
|
|
@@ -260,6 +263,7 @@ export {
|
|
|
260
263
|
Slider,
|
|
261
264
|
Polygon,
|
|
262
265
|
Circle,
|
|
266
|
+
GridOverlay,
|
|
263
267
|
FloatingInput,
|
|
264
268
|
Form,
|
|
265
269
|
// SEO + data helpers — see explanation above the imports block.
|
package/layout/link.js
CHANGED
package/layout/list.js
CHANGED
package/layout/meta-adder.js
CHANGED
package/layout/modal-2025.js
CHANGED
package/layout/morph.js
CHANGED
package/layout/multiswitcher.js
CHANGED
package/layout/nav-bar.js
CHANGED
package/layout/new-nav-bar.js
CHANGED
package/layout/polygon.js
CHANGED
package/layout/prerender-site.js
CHANGED
package/layout/prerender.js
CHANGED
package/layout/progress.js
CHANGED
package/layout/row.js
CHANGED
package/layout/scroll-video.js
CHANGED
package/layout/side-bar.js
CHANGED
package/layout/side-nav-bar.js
CHANGED
package/layout/simple-bar.js
CHANGED
package/layout/slider-2025.js
CHANGED
package/layout/spacer.js
CHANGED
package/layout/stack.js
CHANGED
package/layout/svg.js
CHANGED
package/layout/switcher.js
CHANGED
package/layout/table.js
CHANGED
package/layout/text-field.js
CHANGED
package/layout/text.js
CHANGED
package/layout/ulist.js
CHANGED