@brytdesigns/web-component-gnav-header 1.0.0 → 1.0.2

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/esm/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { customShadowlessElement, correctElementType } from '@brytdesigns/web-component-core/utils';
2
- import { awaitAllAnimations } from '@brytdesigns/web-component-core/animation';
2
+ import { awaitAllAnimations, getTransitionConfig } from '@brytdesigns/web-component-core/animation';
3
3
  import { debounce } from '@solid-primitives/scheduled';
4
4
  import { createSignal, onCleanup, createEffect, on } from 'solid-js';
5
5
  import { animate } from 'motion';
@@ -33,11 +33,13 @@ var CSSVars = {
33
33
  stickyHeaderHeight: "--sticky-header-height",
34
34
  stickyHeaderTop: "--sticky-header-top"
35
35
  };
36
- function updateCssVar(host, varName, amount) {
37
- host.style.setProperty(CSSVars[varName], `${amount}px`);
36
+ function updateCssVar(varName, amount) {
37
+ document.documentElement.style.setProperty(CSSVars[varName], `${amount}px`);
38
38
  }
39
- function getCssVarValue(host, varName) {
40
- const raw = getComputedStyle(host).getPropertyValue(CSSVars[varName]);
39
+ function getCssVarValue(varName) {
40
+ const raw = getComputedStyle(document.documentElement).getPropertyValue(
41
+ CSSVars[varName]
42
+ );
41
43
  return parseFloat(raw) || 0;
42
44
  }
43
45
 
@@ -56,6 +58,13 @@ function nodesContainSection(nodes) {
56
58
  (node) => node instanceof Element && (node.tagName.toLowerCase() === SECTION_TAG || node.querySelector(SECTION_TAG) !== null)
57
59
  );
58
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
+ }
59
68
  var Component = (props, { element }) => {
60
69
  const [sections, setSections] = createSignal([]);
61
70
  let runId = 0;
@@ -76,8 +85,8 @@ var Component = (props, { element }) => {
76
85
  if (!sections().length) {
77
86
  console.warn("No gnav-header-section found!");
78
87
  }
79
- updateCssVar(element, "headerHeight", element.offsetHeight);
80
- updateCssVar(element, "collapsedHeaderHeight", getCollapsedHeaderHeight());
88
+ updateCssVar("headerHeight", element.offsetHeight);
89
+ updateCssVar("collapsedHeaderHeight", getCollapsedHeaderHeight());
81
90
  const observer = new MutationObserver((mutations) => {
82
91
  const relevant = mutations.some(
83
92
  (m) => nodesContainSection(m.addedNodes) || nodesContainSection(m.removedNodes)
@@ -99,12 +108,8 @@ var Component = (props, { element }) => {
99
108
  previousScroll = Math.max(0, window.scrollY);
100
109
  }
101
110
  const handleResize = debounce(function() {
102
- updateCssVar(element, "headerHeight", element.offsetHeight);
103
- updateCssVar(
104
- element,
105
- "collapsedHeaderHeight",
106
- getCollapsedHeaderHeight()
107
- );
111
+ updateCssVar("headerHeight", element.offsetHeight);
112
+ updateCssVar("collapsedHeaderHeight", getCollapsedHeaderHeight());
108
113
  if (props.collapsed) handleScrollDownAnimation();
109
114
  else handleScrollUpAnimation();
110
115
  }, 200);
@@ -155,6 +160,7 @@ var Component = (props, { element }) => {
155
160
  if (!currentSections.length) return;
156
161
  await awaitInFlightSectionAnimations(currentSections);
157
162
  if (id !== runId) return;
163
+ const transition = getTransition(element);
158
164
  const animations = [];
159
165
  const groupedSections = getGroupedSections();
160
166
  if (!groupedSections.hidden) groupedSections.hidden = [];
@@ -164,23 +170,27 @@ var Component = (props, { element }) => {
164
170
  }, 0);
165
171
  groupedSections.hidden.forEach((section) => {
166
172
  const bounding = section.getBoundingClientRect();
167
- const animation = animate(section, {
168
- y: `${(section.offsetTop + offset) * -1}px`
169
- });
173
+ const animation = animate(
174
+ section,
175
+ { y: `${(section.offsetTop + offset) * -1}px` },
176
+ transition
177
+ );
170
178
  offset -= bounding.height;
171
179
  animations.push(animation);
172
180
  });
173
181
  offset = 0;
174
182
  groupedSections.visible.forEach((section) => {
175
183
  const bounding = section.getBoundingClientRect();
176
- const animation = animate(section, {
177
- y: `${offset - section.offsetTop}px`
178
- });
184
+ const animation = animate(
185
+ section,
186
+ { y: `${offset - section.offsetTop}px` },
187
+ transition
188
+ );
179
189
  offset += bounding.height;
180
190
  animations.push(animation);
181
191
  });
182
- updateCssVar(element, "stickyHeaderHeight", offset);
183
- updateCssVar(element, "collapsedHeaderHeight", offset);
192
+ updateCssVar("stickyHeaderHeight", offset);
193
+ updateCssVar("collapsedHeaderHeight", offset);
184
194
  animations.push(animateStickyHeaderTop());
185
195
  return awaitAllAnimations(animations);
186
196
  }
@@ -190,25 +200,20 @@ var Component = (props, { element }) => {
190
200
  if (!currentSections.length) return;
191
201
  await awaitInFlightSectionAnimations(currentSections);
192
202
  if (id !== runId) return;
193
- updateCssVar(
194
- element,
195
- "stickyHeaderHeight",
196
- element.getBoundingClientRect().height
197
- );
203
+ updateCssVar("stickyHeaderHeight", element.getBoundingClientRect().height);
198
204
  return awaitAllAnimations([
199
- animate(currentSections, {
200
- y: "0px"
201
- }),
205
+ animate(currentSections, { y: "0px" }, getTransition(element)),
202
206
  animateStickyHeaderTop(false)
203
207
  ]);
204
208
  }
205
209
  function animateStickyHeaderTop(isScrollingDown = true) {
206
- let from = getCssVarValue(element, "stickyHeaderTop");
210
+ let from = getCssVarValue("stickyHeaderTop");
207
211
  if (!from)
208
212
  from = isScrollingDown ? element.offsetHeight : getCollapsedHeaderHeight();
209
213
  const to = isScrollingDown ? getCollapsedHeaderHeight() : element.getBoundingClientRect().height;
210
214
  return animate(from, to, {
211
- onUpdate: (latest) => updateCssVar(element, "stickyHeaderTop", latest)
215
+ ...getTransition(element),
216
+ onUpdate: (latest) => updateCssVar("stickyHeaderTop", latest)
212
217
  });
213
218
  }
214
219
  };
@@ -1 +1 @@
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 { awaitAllAnimations } 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\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(element, \"headerHeight\", element.offsetHeight);\n updateCssVar(element, \"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(element, \"headerHeight\", element.offsetHeight);\n updateCssVar(\n element,\n \"collapsedHeaderHeight\",\n getCollapsedHeaderHeight(),\n );\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 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(section, {\n y: `${(section.offsetTop + offset) * -1}px`,\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(section, {\n y: `${offset - section.offsetTop}px`,\n });\n offset += bounding.height;\n animations.push(animation);\n });\n\n updateCssVar(element, \"stickyHeaderHeight\", offset);\n updateCssVar(element, \"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(\n element,\n \"stickyHeaderHeight\",\n element.getBoundingClientRect().height,\n );\n return awaitAllAnimations([\n animate(currentSections, {\n y: \"0px\",\n }),\n animateStickyHeaderTop(false),\n ]);\n }\n\n function animateStickyHeaderTop(isScrollingDown = true) {\n let from = getCssVarValue(element, \"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 onUpdate: (latest) => updateCssVar(element, \"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 host: HTMLElement,\n varName: keyof typeof CSSVars,\n amount: number\n) {\n host.style.setProperty(CSSVars[varName], `${amount}px`);\n}\n\nexport function getCssVarValue(\n host: HTMLElement,\n varName: keyof typeof CSSVars\n): number {\n const raw = getComputedStyle(host).getPropertyValue(CSSVars[varName]);\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))"]}
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))"]}
@@ -1,5 +1,5 @@
1
1
  import '@brytdesigns/web-component-core/utils';
2
- import { awaitAllAnimations } from '@brytdesigns/web-component-core/animation';
2
+ import { awaitAllAnimations, getTransitionConfig } from '@brytdesigns/web-component-core/animation';
3
3
  import { debounce } from '@solid-primitives/scheduled';
4
4
  import { createSignal, onCleanup, createEffect, on } from 'solid-js';
5
5
  import { animate } from 'motion';
@@ -19,6 +19,13 @@ function nodesContainSection(nodes) {
19
19
  (node) => node instanceof Element && (node.tagName.toLowerCase() === SECTION_TAG || node.querySelector(SECTION_TAG) !== null)
20
20
  );
21
21
  }
22
+ function getTransition(host) {
23
+ const fromCss = getTransitionConfig(getComputedStyle(host));
24
+ const cleaned = Object.fromEntries(
25
+ Object.entries(fromCss).filter(([, v]) => v !== void 0)
26
+ );
27
+ return { duration: 0.3, ease: "easeOut", ...cleaned };
28
+ }
22
29
  const Component = (props, { element }) => {
23
30
  const [sections, setSections] = createSignal([]);
24
31
  let runId = 0;
@@ -39,8 +46,8 @@ const Component = (props, { element }) => {
39
46
  if (!sections().length) {
40
47
  console.warn("No gnav-header-section found!");
41
48
  }
42
- updateCssVar(element, "headerHeight", element.offsetHeight);
43
- updateCssVar(element, "collapsedHeaderHeight", getCollapsedHeaderHeight());
49
+ updateCssVar("headerHeight", element.offsetHeight);
50
+ updateCssVar("collapsedHeaderHeight", getCollapsedHeaderHeight());
44
51
  const observer = new MutationObserver((mutations) => {
45
52
  const relevant = mutations.some(
46
53
  (m) => nodesContainSection(m.addedNodes) || nodesContainSection(m.removedNodes)
@@ -62,12 +69,8 @@ const Component = (props, { element }) => {
62
69
  previousScroll = Math.max(0, window.scrollY);
63
70
  }
64
71
  const handleResize = debounce(function() {
65
- updateCssVar(element, "headerHeight", element.offsetHeight);
66
- updateCssVar(
67
- element,
68
- "collapsedHeaderHeight",
69
- getCollapsedHeaderHeight()
70
- );
72
+ updateCssVar("headerHeight", element.offsetHeight);
73
+ updateCssVar("collapsedHeaderHeight", getCollapsedHeaderHeight());
71
74
  if (props.collapsed) handleScrollDownAnimation();
72
75
  else handleScrollUpAnimation();
73
76
  }, 200);
@@ -118,6 +121,7 @@ const Component = (props, { element }) => {
118
121
  if (!currentSections.length) return;
119
122
  await awaitInFlightSectionAnimations(currentSections);
120
123
  if (id !== runId) return;
124
+ const transition = getTransition(element);
121
125
  const animations = [];
122
126
  const groupedSections = getGroupedSections();
123
127
  if (!groupedSections.hidden) groupedSections.hidden = [];
@@ -127,23 +131,27 @@ const Component = (props, { element }) => {
127
131
  }, 0);
128
132
  groupedSections.hidden.forEach((section) => {
129
133
  const bounding = section.getBoundingClientRect();
130
- const animation = animate(section, {
131
- y: `${(section.offsetTop + offset) * -1}px`
132
- });
134
+ const animation = animate(
135
+ section,
136
+ { y: `${(section.offsetTop + offset) * -1}px` },
137
+ transition
138
+ );
133
139
  offset -= bounding.height;
134
140
  animations.push(animation);
135
141
  });
136
142
  offset = 0;
137
143
  groupedSections.visible.forEach((section) => {
138
144
  const bounding = section.getBoundingClientRect();
139
- const animation = animate(section, {
140
- y: `${offset - section.offsetTop}px`
141
- });
145
+ const animation = animate(
146
+ section,
147
+ { y: `${offset - section.offsetTop}px` },
148
+ transition
149
+ );
142
150
  offset += bounding.height;
143
151
  animations.push(animation);
144
152
  });
145
- updateCssVar(element, "stickyHeaderHeight", offset);
146
- updateCssVar(element, "collapsedHeaderHeight", offset);
153
+ updateCssVar("stickyHeaderHeight", offset);
154
+ updateCssVar("collapsedHeaderHeight", offset);
147
155
  animations.push(animateStickyHeaderTop());
148
156
  return awaitAllAnimations(animations);
149
157
  }
@@ -153,25 +161,20 @@ const Component = (props, { element }) => {
153
161
  if (!currentSections.length) return;
154
162
  await awaitInFlightSectionAnimations(currentSections);
155
163
  if (id !== runId) return;
156
- updateCssVar(
157
- element,
158
- "stickyHeaderHeight",
159
- element.getBoundingClientRect().height
160
- );
164
+ updateCssVar("stickyHeaderHeight", element.getBoundingClientRect().height);
161
165
  return awaitAllAnimations([
162
- animate(currentSections, {
163
- y: "0px"
164
- }),
166
+ animate(currentSections, { y: "0px" }, getTransition(element)),
165
167
  animateStickyHeaderTop(false)
166
168
  ]);
167
169
  }
168
170
  function animateStickyHeaderTop(isScrollingDown = true) {
169
- let from = getCssVarValue(element, "stickyHeaderTop");
171
+ let from = getCssVarValue("stickyHeaderTop");
170
172
  if (!from)
171
173
  from = isScrollingDown ? element.offsetHeight : getCollapsedHeaderHeight();
172
174
  const to = isScrollingDown ? getCollapsedHeaderHeight() : element.getBoundingClientRect().height;
173
175
  return animate(from, to, {
174
- onUpdate: (latest) => updateCssVar(element, "stickyHeaderTop", latest)
176
+ ...getTransition(element),
177
+ onUpdate: (latest) => updateCssVar("stickyHeaderTop", latest)
175
178
  });
176
179
  }
177
180
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/gnav-header.ts"],"names":[],"mappings":"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","file":"gnav-header.js","sourcesContent":["import { type CorrectComponentType } from \"@brytdesigns/web-component-core/utils\";\nimport { awaitAllAnimations } 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\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(element, \"headerHeight\", element.offsetHeight);\n updateCssVar(element, \"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(element, \"headerHeight\", element.offsetHeight);\n updateCssVar(\n element,\n \"collapsedHeaderHeight\",\n getCollapsedHeaderHeight(),\n );\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 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(section, {\n y: `${(section.offsetTop + offset) * -1}px`,\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(section, {\n y: `${offset - section.offsetTop}px`,\n });\n offset += bounding.height;\n animations.push(animation);\n });\n\n updateCssVar(element, \"stickyHeaderHeight\", offset);\n updateCssVar(element, \"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(\n element,\n \"stickyHeaderHeight\",\n element.getBoundingClientRect().height,\n );\n return awaitAllAnimations([\n animate(currentSections, {\n y: \"0px\",\n }),\n animateStickyHeaderTop(false),\n ]);\n }\n\n function animateStickyHeaderTop(isScrollingDown = true) {\n let from = getCssVarValue(element, \"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 onUpdate: (latest) => updateCssVar(element, \"stickyHeaderTop\", latest),\n });\n }\n};\n"]}
1
+ {"version":3,"sources":["../../../src/components/gnav-header.ts"],"names":[],"mappings":"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","file":"gnav-header.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"]}
@@ -13,11 +13,13 @@ const CSSVars = {
13
13
  stickyHeaderHeight: "--sticky-header-height",
14
14
  stickyHeaderTop: "--sticky-header-top"
15
15
  };
16
- function updateCssVar(host, varName, amount) {
17
- host.style.setProperty(CSSVars[varName], `${amount}px`);
16
+ function updateCssVar(varName, amount) {
17
+ document.documentElement.style.setProperty(CSSVars[varName], `${amount}px`);
18
18
  }
19
- function getCssVarValue(host, varName) {
20
- const raw = getComputedStyle(host).getPropertyValue(CSSVars[varName]);
19
+ function getCssVarValue(varName) {
20
+ const raw = getComputedStyle(document.documentElement).getPropertyValue(
21
+ CSSVars[varName]
22
+ );
21
23
  return parseFloat(raw) || 0;
22
24
  }
23
25
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils.ts"],"names":[],"mappings":"AAAO,MAAM,OAAU,GAAA,CACrB,IACA,EAAA,MAAA,KAEA,IAAK,CAAA,MAAA;AAAA,EACH,CAAC,QAAU,EAAA,WAAA,EAAa,KAAU,KAAA;AAChC,IAAM,MAAA,KAAA,GAAQ,MAAO,CAAA,WAAA,EAAa,KAAK,CAAA;AACvC,IAAA,IAAI,CAAC,QAAS,CAAA,KAAK,GAAY,QAAA,CAAA,KAAK,IAAI,EAAC;AACzC,IAAS,QAAA,CAAA,KAAK,CAAE,CAAA,IAAA,CAAK,WAAW,CAAA;AAChC,IAAO,OAAA,QAAA;AAAA,GACT;AAAA,EACA;AACF;AAEK,MAAM,OAAU,GAAA;AAAA,EACrB,YAAc,EAAA,iBAAA;AAAA,EACd,qBAAuB,EAAA,2BAAA;AAAA,EACvB,kBAAoB,EAAA,wBAAA;AAAA,EACpB,eAAiB,EAAA;AACnB;AAEO,SAAS,YAAA,CACd,IACA,EAAA,OAAA,EACA,MACA,EAAA;AACA,EAAA,IAAA,CAAK,MAAM,WAAY,CAAA,OAAA,CAAQ,OAAO,CAAG,EAAA,CAAA,EAAG,MAAM,CAAI,EAAA,CAAA,CAAA;AACxD;AAEO,SAAS,cAAA,CACd,MACA,OACQ,EAAA;AACR,EAAA,MAAM,MAAM,gBAAiB,CAAA,IAAI,EAAE,gBAAiB,CAAA,OAAA,CAAQ,OAAO,CAAC,CAAA;AACpE,EAAO,OAAA,UAAA,CAAW,GAAG,CAAK,IAAA,CAAA;AAC5B","file":"utils.js","sourcesContent":["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 host: HTMLElement,\n varName: keyof typeof CSSVars,\n amount: number\n) {\n host.style.setProperty(CSSVars[varName], `${amount}px`);\n}\n\nexport function getCssVarValue(\n host: HTMLElement,\n varName: keyof typeof CSSVars\n): number {\n const raw = getComputedStyle(host).getPropertyValue(CSSVars[varName]);\n return parseFloat(raw) || 0;\n}\n"]}
1
+ {"version":3,"sources":["../../src/utils.ts"],"names":[],"mappings":"AAAO,MAAM,OAAU,GAAA,CACrB,IACA,EAAA,MAAA,KAEA,IAAK,CAAA,MAAA;AAAA,EACH,CAAC,QAAU,EAAA,WAAA,EAAa,KAAU,KAAA;AAChC,IAAM,MAAA,KAAA,GAAQ,MAAO,CAAA,WAAA,EAAa,KAAK,CAAA;AACvC,IAAA,IAAI,CAAC,QAAS,CAAA,KAAK,GAAY,QAAA,CAAA,KAAK,IAAI,EAAC;AACzC,IAAS,QAAA,CAAA,KAAK,CAAE,CAAA,IAAA,CAAK,WAAW,CAAA;AAChC,IAAO,OAAA,QAAA;AAAA,GACT;AAAA,EACA;AACF;AAEK,MAAM,OAAU,GAAA;AAAA,EACrB,YAAc,EAAA,iBAAA;AAAA,EACd,qBAAuB,EAAA,2BAAA;AAAA,EACvB,kBAAoB,EAAA,wBAAA;AAAA,EACpB,eAAiB,EAAA;AACnB;AAEO,SAAS,YAAA,CACd,SACA,MACA,EAAA;AACA,EAAS,QAAA,CAAA,eAAA,CAAgB,MAAM,WAAY,CAAA,OAAA,CAAQ,OAAO,CAAG,EAAA,CAAA,EAAG,MAAM,CAAI,EAAA,CAAA,CAAA;AAC5E;AAEO,SAAS,eAAe,OAAuC,EAAA;AACpE,EAAA,MAAM,GAAM,GAAA,gBAAA,CAAiB,QAAS,CAAA,eAAe,CAAE,CAAA,gBAAA;AAAA,IACrD,QAAQ,OAAO;AAAA,GACjB;AACA,EAAO,OAAA,UAAA,CAAW,GAAG,CAAK,IAAA,CAAA;AAC5B","file":"utils.js","sourcesContent":["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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brytdesigns/web-component-gnav-header",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
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",