@brytdesigns/web-component-gnav-header 3.3.3 → 3.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/package.json +2 -2
- package/dist/esm/index.js +0 -246
- package/dist/esm/index.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brytdesigns/web-component-gnav-header",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0",
|
|
4
4
|
"description": "Web component wrapper for the gnav-header navigation element",
|
|
5
5
|
"main": "./dist/main/index.js",
|
|
6
6
|
"module": "./dist/main/index.js",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"author": "Bryt Designs",
|
|
21
21
|
"license": "ISC",
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@brytdesigns/web-component-core": "3.
|
|
23
|
+
"@brytdesigns/web-component-core": "3.4.0",
|
|
24
24
|
"@solid-primitives/scheduled": "^2.0.0-next.2",
|
|
25
25
|
"component-register": "0.8.7",
|
|
26
26
|
"motion": "^12.43.0",
|
package/dist/esm/index.js
DELETED
|
@@ -1,246 +0,0 @@
|
|
|
1
|
-
import { customShadowlessElement, correctElementType } from '@brytdesigns/web-component-core/utils';
|
|
2
|
-
import { awaitAllAnimations, getTransitionConfig } from '@brytdesigns/web-component-core/animation';
|
|
3
|
-
import { debounce } from '@solid-primitives/scheduled';
|
|
4
|
-
import { createSignal, onCleanup, createEffect, on } from 'solid-js';
|
|
5
|
-
import { animate } from 'motion';
|
|
6
|
-
|
|
7
|
-
var __defProp = Object.defineProperty;
|
|
8
|
-
var __export = (target, all) => {
|
|
9
|
-
for (var name in all)
|
|
10
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
// src/components/gnav-header.ts
|
|
14
|
-
var gnav_header_exports = {};
|
|
15
|
-
__export(gnav_header_exports, {
|
|
16
|
-
Component: () => Component,
|
|
17
|
-
Name: () => Name
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
// src/utils.ts
|
|
21
|
-
var groupBy = (list, getKey) => list.reduce(
|
|
22
|
-
(previous, currentItem, index) => {
|
|
23
|
-
const group = getKey(currentItem, index);
|
|
24
|
-
if (!previous[group]) previous[group] = [];
|
|
25
|
-
previous[group].push(currentItem);
|
|
26
|
-
return previous;
|
|
27
|
-
},
|
|
28
|
-
{}
|
|
29
|
-
);
|
|
30
|
-
var CSSVars = {
|
|
31
|
-
headerHeight: "--header-height",
|
|
32
|
-
collapsedHeaderHeight: "--collapsed-header-height",
|
|
33
|
-
stickyHeaderHeight: "--sticky-header-height",
|
|
34
|
-
stickyHeaderTop: "--sticky-header-top"
|
|
35
|
-
};
|
|
36
|
-
function updateCssVar(varName, amount) {
|
|
37
|
-
document.documentElement.style.setProperty(CSSVars[varName], `${amount}px`);
|
|
38
|
-
}
|
|
39
|
-
function getCssVarValue(varName) {
|
|
40
|
-
const raw = getComputedStyle(document.documentElement).getPropertyValue(
|
|
41
|
-
CSSVars[varName]
|
|
42
|
-
);
|
|
43
|
-
return parseFloat(raw) || 0;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// src/components/gnav-header.ts
|
|
47
|
-
var Name = `gnav-header`;
|
|
48
|
-
var SECTION_TAG = "gnav-header-section";
|
|
49
|
-
function awaitInFlightSectionAnimations(sections) {
|
|
50
|
-
return Promise.allSettled(
|
|
51
|
-
sections.flatMap(
|
|
52
|
-
(section) => section.getAnimations().map((animation) => animation.finished)
|
|
53
|
-
)
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
|
-
function nodesContainSection(nodes) {
|
|
57
|
-
return Array.from(nodes).some(
|
|
58
|
-
(node) => node instanceof Element && (node.tagName.toLowerCase() === SECTION_TAG || node.querySelector(SECTION_TAG) !== null)
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
function getTransition(host) {
|
|
62
|
-
const fromCss = getTransitionConfig(getComputedStyle(host));
|
|
63
|
-
const cleaned = Object.fromEntries(
|
|
64
|
-
Object.entries(fromCss).filter(([, v]) => v !== void 0)
|
|
65
|
-
);
|
|
66
|
-
return { duration: 0.3, ease: "easeOut", ...cleaned };
|
|
67
|
-
}
|
|
68
|
-
var Component = (props, { element }) => {
|
|
69
|
-
const [sections, setSections] = createSignal([]);
|
|
70
|
-
let runId = 0;
|
|
71
|
-
function setupSection(section, position) {
|
|
72
|
-
section.setAttribute("position", String(position));
|
|
73
|
-
if (!section.style.position) section.style.position = "relative";
|
|
74
|
-
if (section.hasAttribute("hide-on-trigger")) section.style.zIndex = "99";
|
|
75
|
-
else section.style.zIndex = "100";
|
|
76
|
-
}
|
|
77
|
-
function refreshSections() {
|
|
78
|
-
const found = Array.from(
|
|
79
|
-
document.querySelectorAll(SECTION_TAG)
|
|
80
|
-
);
|
|
81
|
-
found.forEach((section, i) => setupSection(section, i + 1));
|
|
82
|
-
setSections(found);
|
|
83
|
-
}
|
|
84
|
-
refreshSections();
|
|
85
|
-
if (!sections().length) {
|
|
86
|
-
console.warn("No gnav-header-section found!");
|
|
87
|
-
}
|
|
88
|
-
updateCssVar("headerHeight", element.offsetHeight);
|
|
89
|
-
updateCssVar("collapsedHeaderHeight", getCollapsedHeaderHeight());
|
|
90
|
-
const observer = new MutationObserver((mutations) => {
|
|
91
|
-
const relevant = mutations.some(
|
|
92
|
-
(m) => nodesContainSection(m.addedNodes) || nodesContainSection(m.removedNodes)
|
|
93
|
-
);
|
|
94
|
-
if (relevant) refreshSections();
|
|
95
|
-
});
|
|
96
|
-
observer.observe(document.body, { childList: true, subtree: true });
|
|
97
|
-
onCleanup(() => observer.disconnect());
|
|
98
|
-
createEffect(
|
|
99
|
-
on(
|
|
100
|
-
() => props.scrollThreshold,
|
|
101
|
-
(scrollThreshold) => {
|
|
102
|
-
const controller = new AbortController();
|
|
103
|
-
let previousScroll = window.scrollY;
|
|
104
|
-
function handleScroll() {
|
|
105
|
-
const delta = window.scrollY - previousScroll;
|
|
106
|
-
if (Math.abs(delta) < scrollThreshold) return;
|
|
107
|
-
element.setAttribute("collapsed", String(delta > 0));
|
|
108
|
-
previousScroll = Math.max(0, window.scrollY);
|
|
109
|
-
}
|
|
110
|
-
const handleResize = debounce(function() {
|
|
111
|
-
updateCssVar("headerHeight", element.offsetHeight);
|
|
112
|
-
updateCssVar("collapsedHeaderHeight", getCollapsedHeaderHeight());
|
|
113
|
-
if (props.collapsed) handleScrollDownAnimation();
|
|
114
|
-
else handleScrollUpAnimation();
|
|
115
|
-
}, 200);
|
|
116
|
-
window.addEventListener("scroll", handleScroll, {
|
|
117
|
-
capture: true,
|
|
118
|
-
signal: controller.signal
|
|
119
|
-
});
|
|
120
|
-
window.addEventListener("resize", handleResize, {
|
|
121
|
-
capture: true,
|
|
122
|
-
signal: controller.signal
|
|
123
|
-
});
|
|
124
|
-
onCleanup(() => {
|
|
125
|
-
controller.abort();
|
|
126
|
-
handleResize.clear();
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
)
|
|
130
|
-
);
|
|
131
|
-
createEffect(
|
|
132
|
-
on(
|
|
133
|
-
() => props.collapsed,
|
|
134
|
-
(collapsed) => {
|
|
135
|
-
if (collapsed) {
|
|
136
|
-
return handleScrollDownAnimation();
|
|
137
|
-
}
|
|
138
|
-
return handleScrollUpAnimation();
|
|
139
|
-
}
|
|
140
|
-
)
|
|
141
|
-
);
|
|
142
|
-
function shouldHideSectionOnTrigger(section) {
|
|
143
|
-
return section.hasAttribute("hide-on-trigger");
|
|
144
|
-
}
|
|
145
|
-
function getCollapsedHeaderHeight() {
|
|
146
|
-
return sections().reduce((total, section) => {
|
|
147
|
-
if (shouldHideSectionOnTrigger(section)) return total;
|
|
148
|
-
return total + section.getBoundingClientRect().height;
|
|
149
|
-
}, 0);
|
|
150
|
-
}
|
|
151
|
-
function getGroupedSections() {
|
|
152
|
-
return groupBy(
|
|
153
|
-
sections(),
|
|
154
|
-
(section) => shouldHideSectionOnTrigger(section) ? "hidden" : "visible"
|
|
155
|
-
);
|
|
156
|
-
}
|
|
157
|
-
async function handleScrollDownAnimation() {
|
|
158
|
-
const id = ++runId;
|
|
159
|
-
const currentSections = sections();
|
|
160
|
-
if (!currentSections.length) return;
|
|
161
|
-
await awaitInFlightSectionAnimations(currentSections);
|
|
162
|
-
if (id !== runId) return;
|
|
163
|
-
const transition = getTransition(element);
|
|
164
|
-
const animations = [];
|
|
165
|
-
const groupedSections = getGroupedSections();
|
|
166
|
-
if (!groupedSections.hidden) groupedSections.hidden = [];
|
|
167
|
-
if (!groupedSections.visible) groupedSections.visible = [];
|
|
168
|
-
let offset = groupedSections.hidden.reduce((total, el) => {
|
|
169
|
-
return total + el.getBoundingClientRect().height;
|
|
170
|
-
}, 0);
|
|
171
|
-
groupedSections.hidden.forEach((section) => {
|
|
172
|
-
const bounding = section.getBoundingClientRect();
|
|
173
|
-
const animation = animate(
|
|
174
|
-
section,
|
|
175
|
-
{ y: `${(section.offsetTop + offset) * -1}px` },
|
|
176
|
-
transition
|
|
177
|
-
);
|
|
178
|
-
offset -= bounding.height;
|
|
179
|
-
animations.push(animation);
|
|
180
|
-
});
|
|
181
|
-
offset = 0;
|
|
182
|
-
groupedSections.visible.forEach((section) => {
|
|
183
|
-
const bounding = section.getBoundingClientRect();
|
|
184
|
-
const animation = animate(
|
|
185
|
-
section,
|
|
186
|
-
{ y: `${offset - section.offsetTop}px` },
|
|
187
|
-
transition
|
|
188
|
-
);
|
|
189
|
-
offset += bounding.height;
|
|
190
|
-
animations.push(animation);
|
|
191
|
-
});
|
|
192
|
-
updateCssVar("stickyHeaderHeight", offset);
|
|
193
|
-
updateCssVar("collapsedHeaderHeight", offset);
|
|
194
|
-
animations.push(animateStickyHeaderTop());
|
|
195
|
-
return awaitAllAnimations(animations);
|
|
196
|
-
}
|
|
197
|
-
async function handleScrollUpAnimation() {
|
|
198
|
-
const id = ++runId;
|
|
199
|
-
const currentSections = sections();
|
|
200
|
-
if (!currentSections.length) return;
|
|
201
|
-
await awaitInFlightSectionAnimations(currentSections);
|
|
202
|
-
if (id !== runId) return;
|
|
203
|
-
updateCssVar("stickyHeaderHeight", element.getBoundingClientRect().height);
|
|
204
|
-
return awaitAllAnimations([
|
|
205
|
-
animate(currentSections, { y: "0px" }, getTransition(element)),
|
|
206
|
-
animateStickyHeaderTop(false)
|
|
207
|
-
]);
|
|
208
|
-
}
|
|
209
|
-
function animateStickyHeaderTop(isScrollingDown = true) {
|
|
210
|
-
let from = getCssVarValue("stickyHeaderTop");
|
|
211
|
-
if (!from)
|
|
212
|
-
from = isScrollingDown ? element.offsetHeight : getCollapsedHeaderHeight();
|
|
213
|
-
const to = isScrollingDown ? getCollapsedHeaderHeight() : element.getBoundingClientRect().height;
|
|
214
|
-
return animate(from, to, {
|
|
215
|
-
...getTransition(element),
|
|
216
|
-
onUpdate: (latest) => updateCssVar("stickyHeaderTop", latest)
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
// src/components/gnav-header-section.ts
|
|
222
|
-
var gnav_header_section_exports = {};
|
|
223
|
-
__export(gnav_header_section_exports, {
|
|
224
|
-
Component: () => Component2,
|
|
225
|
-
Name: () => Name2
|
|
226
|
-
});
|
|
227
|
-
var Name2 = "gnav-header-section";
|
|
228
|
-
var Component2 = () => {
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
// src/index.ts
|
|
232
|
-
customShadowlessElement(
|
|
233
|
-
gnav_header_exports.Name,
|
|
234
|
-
{
|
|
235
|
-
scrollThreshold: 20,
|
|
236
|
-
collapsed: false
|
|
237
|
-
},
|
|
238
|
-
correctElementType(gnav_header_exports.Component)
|
|
239
|
-
);
|
|
240
|
-
customShadowlessElement(gnav_header_section_exports.Name, {
|
|
241
|
-
hideOnTrigger: false,
|
|
242
|
-
position: 0,
|
|
243
|
-
shouldTrigger: false
|
|
244
|
-
}, correctElementType(gnav_header_section_exports.Component));
|
|
245
|
-
//# sourceMappingURL=index.js.map
|
|
246
|
-
//# sourceMappingURL=index.js.map
|
package/dist/esm/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/gnav-header.ts","../../src/utils.ts","../../src/components/gnav-header-section.ts","../../src/index.ts"],"names":["Component","Name"],"mappings":"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","file":"index.js","sourcesContent":["import { type CorrectComponentType } from \"@brytdesigns/web-component-core/utils\";\nimport {\n awaitAllAnimations,\n getTransitionConfig,\n} from \"@brytdesigns/web-component-core/animation\";\nimport { debounce } from \"@solid-primitives/scheduled\";\nimport { onCleanup, createEffect, createSignal, on } from \"solid-js\";\nimport { animate } from \"motion\";\n\nimport { groupBy, updateCssVar, getCssVarValue } from \"../utils.js\";\n\nexport type Props = {\n scrollThreshold: number;\n collapsed: boolean;\n};\n\nexport const Name = `gnav-header`;\n\nconst SECTION_TAG = \"gnav-header-section\";\n\nfunction awaitInFlightSectionAnimations(sections: HTMLElement[]) {\n return Promise.allSettled(\n sections.flatMap((section) =>\n section.getAnimations().map((animation) => animation.finished),\n ),\n );\n}\n\nfunction nodesContainSection(nodes: NodeList): boolean {\n return Array.from(nodes).some(\n (node) =>\n node instanceof Element &&\n (node.tagName.toLowerCase() === SECTION_TAG ||\n node.querySelector(SECTION_TAG) !== null),\n );\n}\n\nfunction getTransition(host: HTMLElement) {\n const fromCss = getTransitionConfig(getComputedStyle(host));\n const cleaned = Object.fromEntries(\n Object.entries(fromCss).filter(([, v]) => v !== undefined),\n );\n return { duration: 0.3, ease: \"easeOut\" as const, ...cleaned };\n}\n\nexport const Component: CorrectComponentType<Props> = (props, { element }) => {\n const [sections, setSections] = createSignal<HTMLElement[]>([]);\n let runId = 0;\n\n function setupSection(section: HTMLElement, position: number) {\n section.setAttribute(\"position\", String(position));\n if (!section.style.position) section.style.position = \"relative\";\n if (section.hasAttribute(\"hide-on-trigger\")) section.style.zIndex = \"99\";\n else section.style.zIndex = \"100\";\n }\n\n function refreshSections() {\n const found = Array.from(\n document.querySelectorAll<HTMLElement>(SECTION_TAG),\n );\n found.forEach((section, i) => setupSection(section, i + 1));\n setSections(found);\n }\n\n refreshSections();\n\n if (!sections().length) {\n console.warn(\"No gnav-header-section found!\");\n }\n\n updateCssVar(\"headerHeight\", element.offsetHeight);\n updateCssVar(\"collapsedHeaderHeight\", getCollapsedHeaderHeight());\n\n const observer = new MutationObserver((mutations) => {\n const relevant = mutations.some(\n (m) =>\n nodesContainSection(m.addedNodes) ||\n nodesContainSection(m.removedNodes),\n );\n if (relevant) refreshSections();\n });\n observer.observe(document.body, { childList: true, subtree: true });\n onCleanup(() => observer.disconnect());\n\n createEffect(\n on(\n () => props.scrollThreshold,\n (scrollThreshold) => {\n const controller = new AbortController();\n let previousScroll = window.scrollY;\n\n function handleScroll() {\n const delta = window.scrollY - previousScroll;\n if (Math.abs(delta) < scrollThreshold) return;\n element.setAttribute(\"collapsed\", String(delta > 0));\n previousScroll = Math.max(0, window.scrollY);\n }\n\n const handleResize = debounce(function () {\n updateCssVar(\"headerHeight\", element.offsetHeight);\n updateCssVar(\"collapsedHeaderHeight\", getCollapsedHeaderHeight());\n if (props.collapsed) handleScrollDownAnimation();\n else handleScrollUpAnimation();\n }, 200);\n\n window.addEventListener(\"scroll\", handleScroll, {\n capture: true,\n signal: controller.signal,\n });\n window.addEventListener(\"resize\", handleResize, {\n capture: true,\n signal: controller.signal,\n });\n\n onCleanup(() => {\n controller.abort();\n handleResize.clear();\n });\n },\n ),\n );\n\n createEffect(\n on(\n () => props.collapsed,\n (collapsed) => {\n if (collapsed) {\n return handleScrollDownAnimation();\n }\n return handleScrollUpAnimation();\n },\n ),\n );\n\n function shouldHideSectionOnTrigger(section: HTMLElement) {\n return section.hasAttribute(\"hide-on-trigger\");\n }\n\n function getCollapsedHeaderHeight() {\n return sections().reduce((total, section) => {\n if (shouldHideSectionOnTrigger(section)) return total;\n return total + section.getBoundingClientRect().height;\n }, 0);\n }\n\n function getGroupedSections() {\n return groupBy(sections(), (section) =>\n shouldHideSectionOnTrigger(section) ? \"hidden\" : \"visible\",\n );\n }\n\n async function handleScrollDownAnimation() {\n const id = ++runId;\n const currentSections = sections();\n if (!currentSections.length) return;\n\n await awaitInFlightSectionAnimations(currentSections);\n if (id !== runId) return;\n\n const transition = getTransition(element);\n const animations = [];\n const groupedSections = getGroupedSections();\n\n if (!groupedSections.hidden) groupedSections.hidden = [];\n if (!groupedSections.visible) groupedSections.visible = [];\n\n let offset = groupedSections.hidden.reduce((total, el) => {\n return total + el.getBoundingClientRect().height;\n }, 0);\n\n groupedSections.hidden.forEach((section) => {\n const bounding = section.getBoundingClientRect();\n const animation = animate(\n section,\n { y: `${(section.offsetTop + offset) * -1}px` },\n transition,\n );\n offset -= bounding.height;\n animations.push(animation);\n });\n\n offset = 0;\n\n groupedSections.visible.forEach((section) => {\n const bounding = section.getBoundingClientRect();\n const animation = animate(\n section,\n { y: `${offset - section.offsetTop}px` },\n transition,\n );\n offset += bounding.height;\n animations.push(animation);\n });\n\n updateCssVar(\"stickyHeaderHeight\", offset);\n updateCssVar(\"collapsedHeaderHeight\", offset);\n\n animations.push(animateStickyHeaderTop());\n\n return awaitAllAnimations(animations);\n }\n\n async function handleScrollUpAnimation() {\n const id = ++runId;\n const currentSections = sections();\n if (!currentSections.length) return;\n\n await awaitInFlightSectionAnimations(currentSections);\n if (id !== runId) return;\n\n updateCssVar(\"stickyHeaderHeight\", element.getBoundingClientRect().height);\n return awaitAllAnimations([\n animate(currentSections, { y: \"0px\" }, getTransition(element)),\n animateStickyHeaderTop(false),\n ]);\n }\n\n function animateStickyHeaderTop(isScrollingDown = true) {\n let from = getCssVarValue(\"stickyHeaderTop\");\n\n if (!from)\n from = isScrollingDown ? element.offsetHeight : getCollapsedHeaderHeight();\n\n const to = isScrollingDown\n ? getCollapsedHeaderHeight()\n : element.getBoundingClientRect().height;\n\n return animate(from, to, {\n ...getTransition(element),\n onUpdate: (latest) => updateCssVar(\"stickyHeaderTop\", latest),\n });\n }\n};\n","export const groupBy = <T, K extends PropertyKey>(\n list: T[],\n getKey: (item: T, index: number) => K\n) =>\n list.reduce(\n (previous, currentItem, index) => {\n const group = getKey(currentItem, index);\n if (!previous[group]) previous[group] = [];\n previous[group].push(currentItem);\n return previous;\n },\n {} as Record<K, T[]>\n );\n\nexport const CSSVars = {\n headerHeight: \"--header-height\",\n collapsedHeaderHeight: \"--collapsed-header-height\",\n stickyHeaderHeight: \"--sticky-header-height\",\n stickyHeaderTop: \"--sticky-header-top\",\n} as const;\n\nexport function updateCssVar(\n varName: keyof typeof CSSVars,\n amount: number\n) {\n document.documentElement.style.setProperty(CSSVars[varName], `${amount}px`);\n}\n\nexport function getCssVarValue(varName: keyof typeof CSSVars): number {\n const raw = getComputedStyle(document.documentElement).getPropertyValue(\n CSSVars[varName]\n );\n return parseFloat(raw) || 0;\n}\n","import type { CorrectComponentType } from \"@brytdesigns/web-component-core/utils\";\n\nexport type Props = {\n shouldTrigger: boolean;\n position: number;\n hideOnTrigger: boolean;\n};\n\nexport const Name = \"gnav-header-section\";\n\nexport const Component: CorrectComponentType<Props> = () => {};\n","import {\n\tcorrectElementType,\n\tcustomShadowlessElement,\n} from \"@brytdesigns/web-component-core/utils\";\n\nimport { GnavHeader, GnavHeaderSection } from \"./components/index.js\";\n\nexport type GnavHeaderProps = GnavHeader.Props;\nexport type GnavHeaderSectionProps = GnavHeaderSection.Props;\n\ncustomShadowlessElement(\n\tGnavHeader.Name,\n\t{\n\t\tscrollThreshold: 20,\n\t\tcollapsed: false\n\t},\n\tcorrectElementType(GnavHeader.Component),\n);\n\ncustomShadowlessElement(GnavHeaderSection.Name, {\n\thideOnTrigger: false,\n\tposition: 0,\n\tshouldTrigger: false\n}, correctElementType(GnavHeaderSection.Component))"]}
|