nodality 1.3.12 → 1.3.14
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/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 +1 -1
- package/dist/beta-desktop-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/beta-desktop-bar.esm.js +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 +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 +1 -1
- 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 +1 -1
- package/dist/image.cjs.js.LICENSE.txt +1 -1
- package/dist/image.esm.js +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 +3 -2
- package/dist/index.esm.js +1 -1
- 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 +1 -1
- package/dist/multiswitcher.cjs.js.LICENSE.txt +1 -1
- package/dist/multiswitcher.esm.js +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.LICENSE.txt +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 +4 -1
- package/layout/beta-mobile-bar.js +35 -13
- 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 +1 -1
- package/layout/grid-switcher.js +1 -1
- package/layout/grid.js +1 -1
- package/layout/horizontal-scroller.js +1 -1
- package/layout/image.js +92 -1
- package/layout/index.js +1 -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 +15 -2
- 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 +14 -9
- 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 +1 -1
- 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 +1 -1
- package/lib/element-mapper.js +71 -1
- package/lib/element-params.generated.js +4 -4
- package/lib/grid-geometry.js +1 -1
- 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 +42 -10
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* nodality v1.3.
|
|
2
|
+
* nodality v1.3.14
|
|
3
3
|
* (c) 2026 Filip Vabrousek
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -54,6 +54,9 @@ class /*Beta*/DesktopBar extends Animator { // add set method for background col
|
|
|
54
54
|
if (obj.hamburgerColour) {
|
|
55
55
|
this.hamburgerColour = obj.hamburgerColour;
|
|
56
56
|
}
|
|
57
|
+
// Last, so a page's values replace the defaults setStyles() wrote.
|
|
58
|
+
obj.color && (this.res.style.color = obj.color);
|
|
59
|
+
obj.keySet && this.keySet(obj.keySet);
|
|
57
60
|
return this;
|
|
58
61
|
}
|
|
59
62
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* nodality v1.3.
|
|
2
|
+
* nodality v1.3.14
|
|
3
3
|
* (c) 2026 Filip Vabrousek
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -39,15 +39,18 @@ let repl = this.removeQuotesFromFirstWord(JSON.stringify(this.obj));
|
|
|
39
39
|
|
|
40
40
|
// 23:38:35 Yes!!! 23/04/2025
|
|
41
41
|
// Alway construct neste in this way
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
brand
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
42
|
+
// Des renders by running this code, so an option left out of it never
|
|
43
|
+
// reaches the page — hamburgerColour was read by set() and dropped here.
|
|
44
|
+
// Every option set() reads is emitted; brand only when there is one (it
|
|
45
|
+
// threw on a bar without a brand).
|
|
46
|
+
const SERIALISED = ["background", "color", "mar", "pad", "resmar", "respad", "radius", "maxHeight", "hamburgerColour", "keySet", "menuLabel", "menuId"];
|
|
47
|
+
let codeObj = SERIALISED
|
|
48
|
+
.filter((k) => this.obj[k] !== undefined)
|
|
49
|
+
.map((k) => `${k}: ${JSON.stringify(this.obj[k])},`)
|
|
50
|
+
.join("\n");
|
|
51
|
+
if (this.obj.brand && typeof this.obj.brand.toCode === "function") {
|
|
52
|
+
codeObj += `\nbrand: ${[].concat(this.obj.brand.toCode()).join("")},`;
|
|
53
|
+
}
|
|
51
54
|
|
|
52
55
|
return `new MobileBar().set({${codeObj}}).add([
|
|
53
56
|
${items.join(",")}
|
|
@@ -92,9 +95,12 @@ radius: ${JSON.stringify(this.obj.radius)},
|
|
|
92
95
|
this.hamburgerColour = obj.hamburgerColour;
|
|
93
96
|
}
|
|
94
97
|
|
|
95
|
-
|
|
96
|
-
|
|
97
98
|
this.setStyles(obj);
|
|
99
|
+
|
|
100
|
+
// After setStyles, so a page's values replace the defaults.
|
|
101
|
+
obj.color && (this.navbar.style.color = obj.color);
|
|
102
|
+
obj.pad && this.pad(obj.pad);
|
|
103
|
+
obj.keySet && this.keySet(obj.keySet);
|
|
98
104
|
return this;
|
|
99
105
|
}
|
|
100
106
|
|
|
@@ -143,7 +149,6 @@ console.log(newTextInstance.render());*/
|
|
|
143
149
|
//}
|
|
144
150
|
|
|
145
151
|
if (obj.brand && typeof newTextInstance.render === "function") {
|
|
146
|
-
console.log("Appending brand:", newTextInstance.render());
|
|
147
152
|
this.brand.appendChild(newTextInstance.render());
|
|
148
153
|
} else {
|
|
149
154
|
}
|
|
@@ -156,9 +161,25 @@ if (obj.brand && typeof newTextInstance.render === "function") {
|
|
|
156
161
|
this.toggleButton = document.createElement('button');
|
|
157
162
|
this.toggleButton.classList.add('navbar-toggle');
|
|
158
163
|
this.toggleButton.innerHTML = '☰'; // Hamburger icon
|
|
164
|
+
// A glyph is not a name: without these a screen reader announced the
|
|
165
|
+
// button as "☰" and could not tell whether the menu was open.
|
|
166
|
+
this.toggleButton.setAttribute('type', 'button');
|
|
167
|
+
this.toggleButton.setAttribute('aria-label', obj.menuLabel ?? 'Menu');
|
|
168
|
+
this.toggleButton.setAttribute('aria-expanded', 'false');
|
|
159
169
|
|
|
160
170
|
this.navContent = document.createElement('div');
|
|
161
171
|
this.navContent.classList.add('navbar-content');
|
|
172
|
+
if (obj.menuId) {
|
|
173
|
+
this.navContent.setAttribute('id', obj.menuId);
|
|
174
|
+
this.toggleButton.setAttribute('aria-controls', obj.menuId);
|
|
175
|
+
}
|
|
176
|
+
// Following a link closes the menu. On a one-page site the links are
|
|
177
|
+
// anchors, and a menu left open covered the section it had jumped to.
|
|
178
|
+
this.navContent.addEventListener('click', (e) => {
|
|
179
|
+
if (this.isMobileNavOpen && e.target && e.target.closest && e.target.closest('a')) {
|
|
180
|
+
this.toggleMobileNav();
|
|
181
|
+
}
|
|
182
|
+
});
|
|
162
183
|
|
|
163
184
|
this.navbarHeader.appendChild(this.brand);
|
|
164
185
|
this.navbarHeader.appendChild(this.toggleButton);
|
|
@@ -213,6 +234,7 @@ if (obj.brand && typeof newTextInstance.render === "function") {
|
|
|
213
234
|
|
|
214
235
|
toggleMobileNav() {
|
|
215
236
|
this.isMobileNavOpen = !this.isMobileNavOpen;
|
|
237
|
+
this.toggleButton.setAttribute('aria-expanded', String(this.isMobileNavOpen));
|
|
216
238
|
this.navContent.style.display = this.isMobileNavOpen ? 'flex' : 'none';
|
|
217
239
|
if (this.isMobileNavOpen) {
|
|
218
240
|
this.navContent.style.flexDirection = 'column';
|
package/layout/button.js
CHANGED
package/layout/center.js
CHANGED
package/layout/checkbox.js
CHANGED
package/layout/circle.js
CHANGED
package/layout/code.js
CHANGED
package/layout/container.js
CHANGED
package/layout/dropdown-2025.js
CHANGED
package/layout/flex-card.js
CHANGED
package/layout/flex-grid.js
CHANGED
package/layout/flex-row.js
CHANGED
package/layout/free.js
CHANGED
package/layout/grid-overlay.js
CHANGED
package/layout/grid-switcher.js
CHANGED
package/layout/grid.js
CHANGED
package/layout/image.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* nodality v1.3.
|
|
2
|
+
* nodality v1.3.14
|
|
3
3
|
* (c) 2026 Filip Vabrousek
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -272,6 +272,9 @@ let obj = options;
|
|
|
272
272
|
options.clipPath && this.clipPath(options.clipPath);
|
|
273
273
|
options.clipPath && (stra += `clipPath: "${options.clipPath}", \n`);
|
|
274
274
|
|
|
275
|
+
//@ img.reveal {object}: Reveal the image through a mask as it scrolls into view: {mask: "square", size: 0.3, duration: "1.2s", easing, zoom: 1.12, offset: 0.2, delay: "0s", once: true}. It starts as a centred square `size` × its shorter side and opens to the full frame once the square rises `offset` of the viewport height above the bottom edge. Owns clip-path and scale while it runs; reduced-motion visitors, and pages with no IntersectionObserver (the prerender), get the image unmasked.
|
|
276
|
+
options.reveal && this.reveal(options.reveal);
|
|
277
|
+
|
|
275
278
|
|
|
276
279
|
// console.log("261");
|
|
277
280
|
// console.warn(obj);
|
|
@@ -674,6 +677,94 @@ if (mqa.matches){
|
|
|
674
677
|
return this;
|
|
675
678
|
}
|
|
676
679
|
|
|
680
|
+
/**
|
|
681
|
+
* Scroll reveal through a mask. The masked state is applied only where it
|
|
682
|
+
* can be undone: with no window, no IntersectionObserver (the jsdom
|
|
683
|
+
* prerender) or a reduced-motion preference the image stays unmasked,
|
|
684
|
+
* because a mask that never opens hides the content for good.
|
|
685
|
+
*
|
|
686
|
+
* The square is a true square: clip-path's inset() percentages resolve
|
|
687
|
+
* per axis, so on a portrait or wide frame a percentage inset draws a
|
|
688
|
+
* rectangle. The insets are measured in px instead and re-measured when
|
|
689
|
+
* the frame resizes; the percentage form is only the pre-layout guess.
|
|
690
|
+
*
|
|
691
|
+
* The zoom uses the `scale` property, not `transform`, so it composes with
|
|
692
|
+
* any transform the page sets instead of overwriting it.
|
|
693
|
+
*/
|
|
694
|
+
reveal(opts) {
|
|
695
|
+
const el = this.res;
|
|
696
|
+
const o = opts && typeof opts === "object" ? opts : {};
|
|
697
|
+
const mask = o.mask ?? "square";
|
|
698
|
+
if (mask !== "square") {
|
|
699
|
+
console.warn(`nodality: img.reveal mask "${mask}" is not supported — use "square".`);
|
|
700
|
+
return this;
|
|
701
|
+
}
|
|
702
|
+
if (typeof window === "undefined" || typeof window.IntersectionObserver !== "function") return this;
|
|
703
|
+
const reduced = typeof window.matchMedia === "function" &&
|
|
704
|
+
window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
705
|
+
if (reduced) return this;
|
|
706
|
+
|
|
707
|
+
const size = Math.min(1, Math.max(0, Number(o.size ?? 0.3)));
|
|
708
|
+
const duration = o.duration ?? "1.2s";
|
|
709
|
+
const easing = o.easing ?? "cubic-bezier(0.76, 0, 0.24, 1)";
|
|
710
|
+
const delay = o.delay ?? "0s";
|
|
711
|
+
const zoom = Number(o.zoom ?? 1.12);
|
|
712
|
+
const once = o.once !== false;
|
|
713
|
+
const transition = ["clip-path", "scale"].map((p) => `${p} ${duration} ${easing} ${delay}`).join(", ");
|
|
714
|
+
|
|
715
|
+
let open = false;
|
|
716
|
+
const closed = () => {
|
|
717
|
+
const w = el.clientWidth, h = el.clientHeight;
|
|
718
|
+
if (!w || !h) return `inset(${(1 - size) * 50}% ${(1 - size) * 50}%)`;
|
|
719
|
+
const s = Math.min(w, h) * size;
|
|
720
|
+
return `inset(${(h - s) / 2}px ${(w - s) / 2}px)`;
|
|
721
|
+
};
|
|
722
|
+
// Re-measuring a closed mask must not animate: the frame's first
|
|
723
|
+
// layout would otherwise play as a 1.2s morph from the guess.
|
|
724
|
+
const settle = () => {
|
|
725
|
+
el.style.transition = "none";
|
|
726
|
+
el.style.clipPath = closed();
|
|
727
|
+
void el.offsetWidth;
|
|
728
|
+
el.style.transition = transition;
|
|
729
|
+
};
|
|
730
|
+
|
|
731
|
+
el.style.clipPath = closed();
|
|
732
|
+
el.style.scale = String(zoom);
|
|
733
|
+
el.style.willChange = "clip-path, scale";
|
|
734
|
+
el.style.transition = transition;
|
|
735
|
+
|
|
736
|
+
const ro = typeof window.ResizeObserver === "function"
|
|
737
|
+
? new window.ResizeObserver(() => { if (!open) settle(); })
|
|
738
|
+
: null;
|
|
739
|
+
ro && ro.observe(el);
|
|
740
|
+
|
|
741
|
+
// Triggered by a LINE, not an area ratio: the browser clips the target
|
|
742
|
+
// by its own clip-path when it measures the intersection, so a closed
|
|
743
|
+
// square never shows more than its own share of the frame (about 8% at
|
|
744
|
+
// size 0.3) and a `threshold` of 0.35 would never be reached. Instead
|
|
745
|
+
// the square opens once it rises `offset` of the viewport above the
|
|
746
|
+
// bottom edge.
|
|
747
|
+
const offset = Math.min(0.9, Math.max(0, Number(o.offset ?? 0.2)));
|
|
748
|
+
const io = new window.IntersectionObserver((entries) => {
|
|
749
|
+
for (const entry of entries) {
|
|
750
|
+
if (entry.isIntersecting && !open) {
|
|
751
|
+
open = true;
|
|
752
|
+
el.style.clipPath = "inset(0px 0px)";
|
|
753
|
+
el.style.scale = "1";
|
|
754
|
+
if (once) { io.disconnect(); ro && ro.disconnect(); }
|
|
755
|
+
} else if (!entry.isIntersecting && open && !once) {
|
|
756
|
+
open = false;
|
|
757
|
+
el.style.clipPath = closed();
|
|
758
|
+
el.style.scale = String(zoom);
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
}, { threshold: 0, rootMargin: `0px 0px ${-offset * 100}% 0px` });
|
|
762
|
+
io.observe(el);
|
|
763
|
+
|
|
764
|
+
el.addEventListener("transitionend", () => { if (open && once) el.style.willChange = "auto"; });
|
|
765
|
+
return this;
|
|
766
|
+
}
|
|
767
|
+
|
|
677
768
|
clipPath(pathData) {
|
|
678
769
|
// Create a unique ID for the clip path
|
|
679
770
|
|
package/layout/index.js
CHANGED
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
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* nodality v1.3.
|
|
2
|
+
* nodality v1.3.14
|
|
3
3
|
* (c) 2026 Filip Vabrousek
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -117,8 +117,21 @@ str += `{ at: "${this.options.breakpoints[i].at}", view: ${this.options.breakpoi
|
|
|
117
117
|
|
|
118
118
|
applyView() {
|
|
119
119
|
|
|
120
|
+
// No matchMedia at all (a bare jsdom — the prerenderer installs its own,
|
|
121
|
+
// other hosts may not): show the widest view rather than an empty box.
|
|
122
|
+
// The browser re-runs this with real queries when it rebuilds the page.
|
|
123
|
+
if (typeof window.matchMedia !== "function") {
|
|
124
|
+
const widest = this.breakpoints.reduce((a, b) => (parseFloat(b.at) > parseFloat(a.at) ? b : a), this.breakpoints[0]);
|
|
125
|
+
if (widest && this.currentView !== widest.view.render()) {
|
|
126
|
+
this.internalDiv.innerHTML = "";
|
|
127
|
+
this.internalDiv.appendChild(widest.view.render());
|
|
128
|
+
this.currentView = widest.view.render();
|
|
129
|
+
}
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
120
133
|
// check if we are in range
|
|
121
|
-
|
|
134
|
+
|
|
122
135
|
const width = window.innerWidth;
|
|
123
136
|
|
|
124
137
|
let rstart = this.breakpoints.map(el => el.at);
|
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
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* nodality v1.3.
|
|
2
|
+
* nodality v1.3.14
|
|
3
3
|
* (c) 2026 Filip Vabrousek
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -263,14 +263,19 @@ export async function prerender({
|
|
|
263
263
|
window.matchMedia = (query) => {
|
|
264
264
|
let matches = false;
|
|
265
265
|
if (typeof query === "string" && query.includes("width")) {
|
|
266
|
-
//
|
|
267
|
-
//
|
|
268
|
-
// false
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
266
|
+
// Every min-width / max-width clause must hold, so a range —
|
|
267
|
+
// "(min-width: 0px) and (max-width: 1199px)" — resolves too. It
|
|
268
|
+
// used to fall through to false on the claim that Nodality never
|
|
269
|
+
// emits one, but the Switcher behind every `nav` does: no range
|
|
270
|
+
// matched during SSG, and every nav shipped as an empty box.
|
|
271
|
+
// Comma lists (OR) are still answered false.
|
|
272
|
+
if (!query.includes(",")) {
|
|
273
|
+
const min = query.match(/min-width:\s*([\d.]+)\s*px/i);
|
|
274
|
+
const max = query.match(/max-width:\s*([\d.]+)\s*px/i);
|
|
275
|
+
if (min || max) {
|
|
276
|
+
matches = (!min || vw >= Number(min[1])) && (!max || vw <= Number(max[1]));
|
|
277
|
+
}
|
|
278
|
+
}
|
|
274
279
|
}
|
|
275
280
|
return {
|
|
276
281
|
matches,
|
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