@brytdesigns/web-component-accordion 1.1.7 → 3.0.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.
@@ -1,114 +1,58 @@
1
- import { animate } from 'motion';
2
- import { createEffect, on, onCleanup } from 'solid-js';
3
- import { controlsToPromise } from '@brytdesigns/web-component-core/animation';
4
- import { useAccordionItem, useAccordion } from '../hooks/index.js';
5
-
6
- const hideElement = (element) => {
7
- element.style.cssText = `
8
- display: none;
9
- opacity: 0;
10
- visibility: hidden;
11
- max-height: 0px;
12
- `;
13
- element.style.overflow = null;
14
- };
15
- const showElement = (element) => {
16
- element.style.cssText = `
17
- display: block;
18
- opacity: 1;
19
- visibility: visible;
20
- `;
21
- };
22
- const getHeight = (el) => {
23
- el.style.maxHeight = "max-content";
24
- const height = el.getBoundingClientRect().height;
25
- el.style.maxHeight = `${0}`;
26
- return height;
27
- };
28
- const getPaddingTop = (element) => {
29
- const paddingY = parseInt(getComputedStyle(element).paddingTop);
30
- return paddingY;
1
+ import { useAccordion } from "../hooks/useAccordion.js";
2
+ import { useAccordionItem } from "../hooks/useAccordionItem.js";
3
+ import "../hooks/index.js";
4
+ import { createGuardedEffect } from "@brytdesigns/web-component-core/utils";
5
+ import { collapseContent, controlsToPromise, expandContent, hideContent, onContentRevealed, shouldReduceMotion, showContent } from "@brytdesigns/web-component-core/animation";
6
+ import { onCleanup, untrack } from "solid-js";
7
+ //#region src/components/accordion-content.ts
8
+ var Name = `accordion-content`;
9
+ var Component = (props, { element }) => {
10
+ const [state, itemMethods] = useAccordionItem(element);
11
+ const [accordionState, accordionMethods] = useAccordion(element);
12
+ let isFirstRender = true;
13
+ let seenRevealCount = untrack(() => accordionState.revealCount);
14
+ onCleanup(onContentRevealed(element, () => accordionMethods.reveal(itemMethods.expand)));
15
+ const expand = (element, isStale) => {
16
+ const animation = expandContent(element, isStale);
17
+ animation.then(() => {
18
+ if (isStale()) return;
19
+ if (props.shouldScrollIntoView) element.scrollIntoView({
20
+ behavior: shouldReduceMotion() ? "instant" : "smooth",
21
+ block: "start",
22
+ inline: "nearest"
23
+ });
24
+ });
25
+ return animation;
26
+ };
27
+ createGuardedEffect(() => state.isExpanded, (isExpanded) => {
28
+ const revealCount = untrack(() => accordionState.revealCount);
29
+ const isRevealing = revealCount !== seenRevealCount;
30
+ seenRevealCount = revealCount;
31
+ if (isFirstRender || isRevealing) {
32
+ isFirstRender = false;
33
+ if (isExpanded) showContent(element);
34
+ else hideContent(element);
35
+ return;
36
+ }
37
+ let stale = false;
38
+ const isStale = () => stale;
39
+ if (!isExpanded) {
40
+ const animation = collapseContent(element, isStale);
41
+ accordionMethods.updateAnimationQueue(controlsToPromise(animation));
42
+ return () => {
43
+ stale = true;
44
+ animation.complete();
45
+ };
46
+ }
47
+ const animation = expand(element, isStale);
48
+ accordionMethods.updateAnimationQueue(controlsToPromise(animation));
49
+ return () => {
50
+ stale = true;
51
+ animation.complete();
52
+ };
53
+ });
31
54
  };
32
- const getPaddingBottom = (element) => {
33
- const paddingY = parseInt(getComputedStyle(element).paddingBottom);
34
- return paddingY;
35
- };
36
- const Name = `accordion-content`;
37
- const Component = (props, { element }) => {
38
- const [state] = useAccordionItem(element);
39
- const [_, accordionMethods] = useAccordion(element);
40
- let isFirstRender = true;
41
- const expand = (element2) => {
42
- showElement(element2);
43
- const height = getHeight(element2), pt = getPaddingTop(element2), pb = getPaddingBottom(element2);
44
- Array.from(element2.children).forEach(
45
- (child) => child.style.opacity = "1"
46
- );
47
- const animation = animate(
48
- element2,
49
- {
50
- maxHeight: ["0px", `${height}px`],
51
- paddingTop: ["0px", `${pt}px`],
52
- paddingBottom: ["0px", `${pb}px`]
53
- },
54
- {
55
- duration: 0.35
56
- }
57
- );
58
- animation.then(() => {
59
- element2.style.maxHeight = "max-content";
60
- element2.style.overflow = null;
61
- if (props.shouldScrollIntoView)
62
- element2.scrollIntoView({
63
- behavior: "smooth",
64
- block: "start",
65
- inline: "nearest"
66
- });
67
- return;
68
- });
69
- return animation;
70
- };
71
- const collapse = (element2) => {
72
- const height = getHeight(element2), pt = getPaddingTop(element2), pb = getPaddingBottom(element2);
73
- element2.style.overflow = "hidden";
74
- Array.from(element2.children).forEach(
75
- (child) => child.style.opacity = "0"
76
- );
77
- const animation = animate(
78
- element2,
79
- {
80
- maxHeight: [`${height}px`, "0px"],
81
- paddingTop: [`${pt}px`, "0px"],
82
- paddingBottom: [`${pb}px`, "0px"]
83
- },
84
- {
85
- duration: 0.35
86
- }
87
- );
88
- animation.then(() => hideElement(element2));
89
- return animation;
90
- };
91
- createEffect(
92
- on(
93
- () => state.isExpanded,
94
- (isExpanded) => {
95
- if (!isExpanded) {
96
- const animation2 = collapse(element);
97
- accordionMethods.updateAnimationQueue(controlsToPromise(animation2));
98
- return onCleanup(() => animation2.complete());
99
- }
100
- if (isFirstRender) {
101
- isFirstRender = false;
102
- showElement(element);
103
- }
104
- const animation = expand(element);
105
- accordionMethods.updateAnimationQueue(controlsToPromise(animation));
106
- return onCleanup(() => animation.complete());
107
- }
108
- )
109
- );
110
- };
111
-
55
+ //#endregion
112
56
  export { Component, Name };
113
- //# sourceMappingURL=accordion-content.js.map
57
+
114
58
  //# sourceMappingURL=accordion-content.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/accordion-content.ts"],"names":["element","animation"],"mappings":"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","file":"accordion-content.js","sourcesContent":["import type { CorrectComponentType } from \"@brytdesigns/web-component-core/utils\";\nimport type { ICustomElement } from \"component-register\";\nimport { animate } from \"motion\";\nimport { createEffect, on, onCleanup } from \"solid-js\";\n\nimport { controlsToPromise } from \"@brytdesigns/web-component-core/animation\";\n\nimport { useAccordion, useAccordionItem } from \"../hooks/index.js\";\n\nexport type Props = {\n shouldScrollIntoView: boolean;\n};\n\nconst hideElement = (element: ICustomElement) => {\n element.style.cssText = `\n display: none;\n opacity: 0;\n visibility: hidden;\n max-height: 0px;\n `;\n element.style.overflow = null;\n};\n\nconst showElement = (element: ICustomElement) => {\n element.style.cssText = `\n display: block;\n opacity: 1;\n visibility: visible;\n `;\n};\n\nconst getHeight = (el: ICustomElement & HTMLElement) => {\n el.style.maxHeight = \"max-content\";\n const height = el.getBoundingClientRect().height;\n el.style.maxHeight = `${0}`;\n return height;\n};\n\nconst getPaddingTop = (element: ICustomElement & HTMLElement) => {\n const paddingY = parseInt(getComputedStyle(element).paddingTop);\n return paddingY;\n};\n\nconst getPaddingBottom = (element: ICustomElement & HTMLElement) => {\n const paddingY = parseInt(getComputedStyle(element).paddingBottom);\n return paddingY;\n};\n\nexport const Name = `accordion-content`;\n\nexport const Component: CorrectComponentType<Props> = (props, { element }) => {\n const [state] = useAccordionItem(element);\n const [_, accordionMethods] = useAccordion(element);\n\n let isFirstRender = true;\n\n const expand = (element: ICustomElement & HTMLElement) => {\n showElement(element);\n\n const height = getHeight(element),\n pt = getPaddingTop(element),\n pb = getPaddingBottom(element);\n\n (Array.from(element.children) as HTMLElement[]).forEach(\n (child) => (child.style.opacity = \"1\"),\n );\n\n const animation = animate(\n element,\n {\n maxHeight: [\"0px\", `${height}px`],\n paddingTop: [\"0px\", `${pt}px`],\n paddingBottom: [\"0px\", `${pb}px`],\n },\n {\n duration: 0.35,\n },\n );\n\n animation.then(() => {\n element.style.maxHeight = \"max-content\";\n //@ts-ignore\n element.style.overflow = null;\n if (props.shouldScrollIntoView)\n element.scrollIntoView({\n behavior: \"smooth\",\n block: \"start\",\n inline: \"nearest\",\n });\n return;\n });\n\n return animation;\n };\n\n const collapse = (element: ICustomElement & HTMLElement) => {\n const height = getHeight(element),\n pt = getPaddingTop(element),\n pb = getPaddingBottom(element);\n\n element.style.overflow = \"hidden\";\n\n (Array.from(element.children) as HTMLElement[]).forEach(\n (child) => (child.style.opacity = \"0\"),\n );\n\n const animation = animate(\n element,\n {\n maxHeight: [`${height}px`, \"0px\"],\n paddingTop: [`${pt}px`, \"0px\"],\n paddingBottom: [`${pb}px`, \"0px\"],\n },\n {\n duration: 0.35,\n },\n );\n\n animation.then(() => hideElement(element));\n\n return animation;\n };\n\n createEffect(\n on(\n () => state.isExpanded,\n (isExpanded) => {\n if (!isExpanded) {\n const animation = collapse(element);\n accordionMethods.updateAnimationQueue(controlsToPromise(animation));\n return onCleanup(() => animation.complete());\n }\n\n if (isFirstRender) {\n isFirstRender = false;\n showElement(element);\n }\n\n const animation = expand(element);\n accordionMethods.updateAnimationQueue(controlsToPromise(animation));\n return onCleanup(() => animation.complete());\n },\n ),\n );\n};\n"]}
1
+ {"version":3,"file":"accordion-content.js","names":[],"sources":["../../../src/components/accordion-content.ts"],"sourcesContent":["import {\n\tcollapseContent,\n\tcontrolsToPromise,\n\texpandContent,\n\thideContent,\n\tonContentRevealed,\n\tshouldReduceMotion,\n\tshowContent,\n} from \"@brytdesigns/web-component-core/animation\";\nimport type { CorrectComponentType } from \"@brytdesigns/web-component-core/utils\";\nimport { createGuardedEffect } from \"@brytdesigns/web-component-core/utils\";\nimport { onCleanup, untrack } from \"solid-js\";\n\nimport { useAccordion, useAccordionItem } from \"../hooks/index.js\";\n\nexport type Props = {\n\tshouldScrollIntoView: boolean;\n};\n\nexport const Name = `accordion-content`;\n\nexport const Component: CorrectComponentType<Props> = (props, { element }) => {\n\tconst [state, itemMethods] = useAccordionItem(element);\n\tconst [accordionState, accordionMethods] = useAccordion(element);\n\n\tlet isFirstRender = true;\n\t// The reveal counter as it stood when this content last applied a state.\n\t// See `revealCount` in useAccordion for why this is a counter rather than a\n\t// flag held across the write.\n\tlet seenRevealCount = untrack(() => accordionState.revealCount);\n\n\t// Component-level `onCleanup` does register and fire; inside an effect's\n\t// apply phase it would not, because the apply phase is not a computation.\n\tonCleanup(\n\t\tonContentRevealed(element, () =>\n\t\t\taccordionMethods.reveal(itemMethods.expand),\n\t\t),\n\t);\n\n\tconst expand = (element: HTMLElement, isStale: () => boolean) => {\n\t\tconst animation = expandContent(element, isStale);\n\n\t\tanimation.then(() => {\n\t\t\tif (isStale()) return;\n\t\t\tif (props.shouldScrollIntoView)\n\t\t\t\telement.scrollIntoView({\n\t\t\t\t\tbehavior: shouldReduceMotion() ? \"instant\" : \"smooth\",\n\t\t\t\t\tblock: \"start\",\n\t\t\t\t\tinline: \"nearest\",\n\t\t\t\t});\n\t\t});\n\n\t\treturn animation;\n\t};\n\n\tcreateGuardedEffect(\n\t\t() => state.isExpanded,\n\t\t(isExpanded) => {\n\t\t\t// The apply phase is untracked, so this reads the counter as it\n\t\t\t// stands at flush time without subscribing to it. Spelled with\n\t\t\t// `untrack` rather than left implicit: Solid reports a bare read\n\t\t\t// here (STRICT_READ_UNTRACKED) because it cannot tell a deliberate\n\t\t\t// snapshot from a dependency someone forgot, and the whole value of\n\t\t\t// that diagnostic is that every remaining one is unreviewed.\n\t\t\tconst revealCount = untrack(() => accordionState.revealCount);\n\t\t\tconst isRevealing = revealCount !== seenRevealCount;\n\t\t\tseenRevealCount = revealCount;\n\n\t\t\t// The first render applies the starting state without animating, as\n\t\t\t// does a find-in-page reveal: the match is scrolled to straight after,\n\t\t\t// so the layout has to be settled by then.\n\t\t\tif (isFirstRender || isRevealing) {\n\t\t\t\tisFirstRender = false;\n\t\t\t\tif (isExpanded) showContent(element);\n\t\t\t\telse hideContent(element);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Flipped by this run's cleanup, so a completed-but-still-pending\n\t\t\t// animation cannot write styles for a direction we have left.\n\t\t\tlet stale = false;\n\t\t\tconst isStale = () => stale;\n\n\t\t\tif (!isExpanded) {\n\t\t\t\tconst animation = collapseContent(element, isStale);\n\t\t\t\taccordionMethods.updateAnimationQueue(controlsToPromise(animation));\n\t\t\t\t// v2 treats the apply phase's return value as the cleanup, so the\n\t\t\t\t// function is returned directly rather than via `onCleanup`.\n\t\t\t\treturn () => {\n\t\t\t\t\tstale = true;\n\t\t\t\t\tanimation.complete();\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst animation = expand(element, isStale);\n\t\t\taccordionMethods.updateAnimationQueue(controlsToPromise(animation));\n\t\t\treturn () => {\n\t\t\t\tstale = true;\n\t\t\t\tanimation.complete();\n\t\t\t};\n\t\t},\n\t);\n};\n"],"mappings":";;;;;;;AAmBA,IAAa,OAAO;AAEpB,IAAa,aAA0C,OAAO,EAAE,cAAc;CAC7E,MAAM,CAAC,OAAO,eAAe,iBAAiB,OAAO;CACrD,MAAM,CAAC,gBAAgB,oBAAoB,aAAa,OAAO;CAE/D,IAAI,gBAAgB;CAIpB,IAAI,kBAAkB,cAAc,eAAe,WAAW;CAI9D,UACC,kBAAkB,eACjB,iBAAiB,OAAO,YAAY,MAAM,CAC3C,CACD;CAEA,MAAM,UAAU,SAAsB,YAA2B;EAChE,MAAM,YAAY,cAAc,SAAS,OAAO;EAEhD,UAAU,WAAW;GACpB,IAAI,QAAQ,GAAG;GACf,IAAI,MAAM,sBACT,QAAQ,eAAe;IACtB,UAAU,mBAAmB,IAAI,YAAY;IAC7C,OAAO;IACP,QAAQ;GACT,CAAC;EACH,CAAC;EAED,OAAO;CACR;CAEA,0BACO,MAAM,aACX,eAAe;EAOf,MAAM,cAAc,cAAc,eAAe,WAAW;EAC5D,MAAM,cAAc,gBAAgB;EACpC,kBAAkB;EAKlB,IAAI,iBAAiB,aAAa;GACjC,gBAAgB;GAChB,IAAI,YAAY,YAAY,OAAO;QAC9B,YAAY,OAAO;GACxB;EACD;EAIA,IAAI,QAAQ;EACZ,MAAM,gBAAgB;EAEtB,IAAI,CAAC,YAAY;GAChB,MAAM,YAAY,gBAAgB,SAAS,OAAO;GAClD,iBAAiB,qBAAqB,kBAAkB,SAAS,CAAC;GAGlE,aAAa;IACZ,QAAQ;IACR,UAAU,SAAS;GACpB;EACD;EAEA,MAAM,YAAY,OAAO,SAAS,OAAO;EACzC,iBAAiB,qBAAqB,kBAAkB,SAAS,CAAC;EAClE,aAAa;GACZ,QAAQ;GACR,UAAU,SAAS;EACpB;CACD,CACD;AACD"}
@@ -1,22 +1,30 @@
1
- import { toHyphenated } from '@brytdesigns/web-component-core/utils';
2
- import { provideAccordionContext, useAccordionContext } from '../hooks/index.js';
3
-
4
- const Name = `accordion-context`;
5
- const Component = (props, { element }) => {
6
- const context = provideAccordionContext(props, element);
7
- const [_, methods] = useAccordionContext(context);
8
- const children = Array.from(element.children);
9
- const accordionItems = children.filter(
10
- (child) => child.tagName === "ACCORDION-ITEM"
11
- );
12
- accordionItems.forEach((accordionItem, index) => {
13
- accordionItem.setAttribute("index", `${index + 1}`);
14
- if (accordionItem.getAttribute(toHyphenated("isExpanded")) !== "true")
15
- return;
16
- methods.item.update(index + 1);
17
- });
1
+ import { provideAccordionContext, useAccordionContext } from "../hooks/useAccordion.js";
2
+ import "../hooks/index.js";
3
+ import { toHyphenated } from "@brytdesigns/web-component-core/utils";
4
+ import { untrack } from "solid-js";
5
+ //#region src/components/accordion-context.ts
6
+ var Name = `accordion-context`;
7
+ var Component = (props, { element }) => {
8
+ const context = provideAccordionContext(props, element);
9
+ const [_, methods] = useAccordionContext(context);
10
+ const accordionItems = Array.from(element.children).filter((child) => child.tagName === "ACCORDION-ITEM");
11
+ const allowMultiple = untrack(() => props.allowMultiple);
12
+ const startIndex = untrack(() => props.activeIndex);
13
+ accordionItems.forEach((accordionItem, index) => {
14
+ accordionItem.setAttribute("index", `${index + 1}`);
15
+ if (index + 1 === startIndex) accordionItem.setAttribute(toHyphenated("isExpanded"), "true");
16
+ });
17
+ queueMicrotask(() => {
18
+ if (allowMultiple) {
19
+ methods.item.update(-1);
20
+ return;
21
+ }
22
+ const expanded = accordionItems.findIndex((item) => item.getAttribute(toHyphenated("isExpanded")) === "true");
23
+ if (expanded === -1) return;
24
+ methods.item.update(expanded + 1);
25
+ });
18
26
  };
19
-
27
+ //#endregion
20
28
  export { Component, Name };
21
- //# sourceMappingURL=accordion-context.js.map
29
+
22
30
  //# sourceMappingURL=accordion-context.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/accordion-context.ts"],"names":[],"mappings":";;;AAeO,MAAM,IAAO,GAAA,CAAA,iBAAA;AAEb,MAAM,SAAyC,GAAA,CAAC,KAAO,EAAA,EAAE,SAAc,KAAA;AAC5E,EAAM,MAAA,OAAA,GAAU,uBAAwB,CAAA,KAAA,EAAO,OAAO,CAAA;AACtD,EAAA,MAAM,CAAC,CAAA,EAAG,OAAO,CAAA,GAAI,oBAAoB,OAAO,CAAA;AAChD,EAAA,MAAM,QAAW,GAAA,KAAA,CAAM,IAAK,CAAA,OAAA,CAAQ,QAAQ,CAAA;AAC5C,EAAA,MAAM,iBAAiB,QAAS,CAAA,MAAA;AAAA,IAC9B,CAAC,KAAU,KAAA,KAAA,CAAM,OAAY,KAAA;AAAA,GAC/B;AACA,EAAe,cAAA,CAAA,OAAA,CAAQ,CAAC,aAAA,EAAe,KAAU,KAAA;AAC/C,IAAA,aAAA,CAAc,YAAa,CAAA,OAAA,EAAS,CAAG,EAAA,KAAA,GAAQ,CAAC,CAAE,CAAA,CAAA;AAClD,IAAA,IAAI,aAAc,CAAA,YAAA,CAAa,YAAa,CAAA,YAAY,CAAC,CAAM,KAAA,MAAA;AAC7D,MAAA;AACF,IAAQ,OAAA,CAAA,IAAA,CAAK,MAAO,CAAA,KAAA,GAAQ,CAAC,CAAA;AAAA,GAC9B,CAAA;AACH","file":"accordion-context.js","sourcesContent":["import {\n toHyphenated,\n type CorrectComponentType,\n} from \"@brytdesigns/web-component-core/utils\";\n\nimport {\n provideAccordionContext,\n useAccordionContext,\n} from \"../hooks/index.js\";\n\nexport type Props = {\n activeIndex: number;\n isAnimating: boolean;\n};\n\nexport const Name = `accordion-context`;\n\nexport const Component: CorrectComponentType<Props> = (props, { element }) => {\n const context = provideAccordionContext(props, element);\n const [_, methods] = useAccordionContext(context);\n const children = Array.from(element.children) as HTMLElement[];\n const accordionItems = children.filter(\n (child) => child.tagName === \"ACCORDION-ITEM\",\n );\n accordionItems.forEach((accordionItem, index) => {\n accordionItem.setAttribute(\"index\", `${index + 1}`);\n if (accordionItem.getAttribute(toHyphenated(\"isExpanded\")) !== \"true\")\n return;\n methods.item.update(index + 1);\n });\n};\n"]}
1
+ {"version":3,"file":"accordion-context.js","names":[],"sources":["../../../src/components/accordion-context.ts"],"sourcesContent":["import {\n\ttype CorrectComponentType,\n\ttoHyphenated,\n} from \"@brytdesigns/web-component-core/utils\";\nimport { untrack } from \"solid-js\";\n\nimport {\n\tprovideAccordionContext,\n\tuseAccordionContext,\n} from \"../hooks/index.js\";\n\nexport type Props = {\n\tactiveIndex: number;\n\tisAnimating: boolean;\n\tallowMultiple: boolean;\n};\n\nexport const Name = `accordion-context`;\n\nexport const Component: CorrectComponentType<Props> = (props, { element }) => {\n\tconst context = provideAccordionContext(props, element);\n\tconst [_, methods] = useAccordionContext(context);\n\tconst children = Array.from(element.children) as HTMLElement[];\n\tconst accordionItems = children.filter(\n\t\t(child) => child.tagName === \"ACCORDION-ITEM\",\n\t);\n\t// Both read once: changing allow-multiple after startup has no effect, and\n\t// active-index only picks the item that starts open.\n\tconst allowMultiple = untrack(() => props.allowMultiple);\n\tconst startIndex = untrack(() => props.activeIndex);\n\n\taccordionItems.forEach((accordionItem, index) => {\n\t\taccordionItem.setAttribute(\"index\", `${index + 1}`);\n\n\t\t// `active-index` is turned into the item's own `is-expanded` here, before\n\t\t// the items initialise, rather than left for the item to follow once its\n\t\t// effects run. By then its content has already applied a closed starting\n\t\t// state, so following it would animate the content open on load. Writing\n\t\t// a child's attribute from a component body is fine; writing *our own*\n\t\t// prop is what Solid 2 forbids, which is why the rest is deferred below.\n\t\tif (index + 1 === startIndex)\n\t\t\taccordionItem.setAttribute(toHyphenated(\"isExpanded\"), \"true\");\n\t});\n\n\t// Seeding `activeIndex` from markup is deferred by a microtask. Writing it\n\t// here would be a write inside a component body: `setElementState` calls\n\t// `setAttribute`, component-register turns that straight back into a signal\n\t// write, and Solid 2 forbids that from an owned scope — with no opt-out,\n\t// since the signal belongs to @solidjs/element's prop bridge rather than to\n\t// us. A microtask is the smallest move out of the owner; initialisation\n\t// lands one tick later than it used to.\n\tqueueMicrotask(() => {\n\t\t// With several items open, no single index describes the state, so\n\t\t// `active-index` is reset and then ignored for the rest of the session.\n\t\tif (allowMultiple) {\n\t\t\tmethods.item.update(-1);\n\t\t\treturn;\n\t\t}\n\n\t\tconst expanded = accordionItems.findIndex(\n\t\t\t(item) => item.getAttribute(toHyphenated(\"isExpanded\")) === \"true\",\n\t\t);\n\t\tif (expanded === -1) return;\n\t\tmethods.item.update(expanded + 1);\n\t});\n};\n"],"mappings":";;;;;AAiBA,IAAa,OAAO;AAEpB,IAAa,aAA0C,OAAO,EAAE,cAAc;CAC7E,MAAM,UAAU,wBAAwB,OAAO,OAAO;CACtD,MAAM,CAAC,GAAG,WAAW,oBAAoB,OAAO;CAEhD,MAAM,iBADW,MAAM,KAAK,QAAQ,QACb,CAAA,CAAS,QAC9B,UAAU,MAAM,YAAY,gBAC9B;CAGA,MAAM,gBAAgB,cAAc,MAAM,aAAa;CACvD,MAAM,aAAa,cAAc,MAAM,WAAW;CAElD,eAAe,SAAS,eAAe,UAAU;EAChD,cAAc,aAAa,SAAS,GAAG,QAAQ,GAAG;EAQlD,IAAI,QAAQ,MAAM,YACjB,cAAc,aAAa,aAAa,YAAY,GAAG,MAAM;CAC/D,CAAC;CASD,qBAAqB;EAGpB,IAAI,eAAe;GAClB,QAAQ,KAAK,OAAO,EAAE;GACtB;EACD;EAEA,MAAM,WAAW,eAAe,WAC9B,SAAS,KAAK,aAAa,aAAa,YAAY,CAAC,MAAM,MAC7D;EACA,IAAI,aAAa,IAAI;EACrB,QAAQ,KAAK,OAAO,WAAW,CAAC;CACjC,CAAC;AACF"}
@@ -1,16 +1,12 @@
1
- import '@brytdesigns/web-component-core/utils';
2
- import { provideAccordionItemContext } from '../hooks/index.js';
3
-
4
- const Name = `accordion-item`;
5
- const Component = (props, { element }) => {
6
- if (element.parentElement?.tagName !== "ACCORDION-CONTEXT")
7
- return console.warn(
8
- `${Name}: must be an immediate child of accordion-context`,
9
- element
10
- );
11
- provideAccordionItemContext(props, element);
1
+ import { provideAccordionItemContext } from "../hooks/useAccordionItem.js";
2
+ import "../hooks/index.js";
3
+ //#region src/components/accordion-item.ts
4
+ var Name = `accordion-item`;
5
+ var Component = (props, { element }) => {
6
+ if (element.parentElement?.tagName !== "ACCORDION-CONTEXT") return console.warn(`${Name}: must be an immediate child of accordion-context`, element);
7
+ provideAccordionItemContext(props, element);
12
8
  };
13
-
9
+ //#endregion
14
10
  export { Component, Name };
15
- //# sourceMappingURL=accordion-item.js.map
11
+
16
12
  //# sourceMappingURL=accordion-item.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/accordion-item.ts"],"names":[],"mappings":";;;AAUO,MAAM,IAAO,GAAA,CAAA,cAAA;AAEb,MAAM,SAAyC,GAAA,CAAC,KAAO,EAAA,EAAE,SAAc,KAAA;AAC5E,EAAI,IAAA,OAAA,CAAQ,eAAe,OAAY,KAAA,mBAAA;AACrC,IAAA,OAAO,OAAQ,CAAA,IAAA;AAAA,MACb,GAAG,IAAI,CAAA,iDAAA,CAAA;AAAA,MACP;AAAA,KACF;AAEF,EAAA,2BAAA,CAA4B,OAAO,OAAO,CAAA;AAC5C","file":"accordion-item.js","sourcesContent":["import { type CorrectComponentType } from \"@brytdesigns/web-component-core/utils\";\n\nimport { provideAccordionItemContext } from \"../hooks/index.js\";\n\nexport type Props = {\n index: number;\n isExpanded: boolean;\n ariaExpanded: boolean;\n};\n\nexport const Name = `accordion-item`;\n\nexport const Component: CorrectComponentType<Props> = (props, { element }) => {\n if (element.parentElement?.tagName !== \"ACCORDION-CONTEXT\")\n return console.warn(\n `${Name}: must be an immediate child of accordion-context`,\n element,\n );\n\n provideAccordionItemContext(props, element);\n};\n"]}
1
+ {"version":3,"file":"accordion-item.js","names":[],"sources":["../../../src/components/accordion-item.ts"],"sourcesContent":["import type { CorrectComponentType } from \"@brytdesigns/web-component-core/utils\";\n\nimport { provideAccordionItemContext } from \"../hooks/index.js\";\n\nexport type Props = {\n\tindex: number;\n\tisExpanded: boolean;\n};\n\nexport const Name = `accordion-item`;\n\nexport const Component: CorrectComponentType<Props> = (props, { element }) => {\n\tif (element.parentElement?.tagName !== \"ACCORDION-CONTEXT\")\n\t\treturn console.warn(\n\t\t\t`${Name}: must be an immediate child of accordion-context`,\n\t\t\telement,\n\t\t);\n\n\tprovideAccordionItemContext(props, element);\n};\n"],"mappings":";;;AASA,IAAa,OAAO;AAEpB,IAAa,aAA0C,OAAO,EAAE,cAAc;CAC7E,IAAI,QAAQ,eAAe,YAAY,qBACtC,OAAO,QAAQ,KACd,GAAG,KAAK,oDACR,OACD;CAED,4BAA4B,OAAO,OAAO;AAC3C"}
@@ -1,28 +1,35 @@
1
- import '@brytdesigns/web-component-core/utils';
2
- import { createEffect, onCleanup } from 'solid-js';
3
- import { useAccordionItem } from '../hooks/index.js';
4
-
5
- const Name = `accordion-trigger`;
6
- const Component = (props, { element }) => {
7
- const [state, methods] = useAccordionItem(element);
8
- createEffect(() => {
9
- const isAnimating = state.isAnimating;
10
- if (isAnimating) return;
11
- const controller = new AbortController(), preventDefault = props.preventDefault;
12
- element.addEventListener(
13
- "click",
14
- (event) => {
15
- if (preventDefault) event.preventDefault();
16
- methods.toggle();
17
- },
18
- { signal: controller.signal }
19
- );
20
- return onCleanup(() => {
21
- controller.abort();
22
- });
23
- });
1
+ import { useAccordionItem } from "../hooks/useAccordionItem.js";
2
+ import "../hooks/index.js";
3
+ import { createGuardedEffect, findDisclosureContent, findDisclosureControl, linkDisclosureControl } from "@brytdesigns/web-component-core/utils";
4
+ //#region src/components/accordion-trigger.ts
5
+ var Name = `accordion-trigger`;
6
+ var Component = (props, { element }) => {
7
+ const [state, methods] = useAccordionItem(element);
8
+ const control = findDisclosureControl(element);
9
+ if (!control) console.warn(`${Name}: put a <button> inside the trigger so assistive tech can operate it`, element);
10
+ else {
11
+ let isLinked = false;
12
+ createGuardedEffect(() => state.isExpanded, (isExpanded) => {
13
+ control.setAttribute("aria-expanded", isExpanded ? "true" : "false");
14
+ if (!isLinked) isLinked = linkDisclosureControl(control, findDisclosureContent(element, "accordion-item", "accordion-content"), "accordion-content");
15
+ });
16
+ }
17
+ createGuardedEffect(() => ({
18
+ isAnimating: state.isAnimating,
19
+ preventDefault: props.preventDefault
20
+ }), ({ isAnimating, preventDefault }) => {
21
+ if (isAnimating) return;
22
+ const controller = new AbortController();
23
+ element.addEventListener("click", (event) => {
24
+ if (preventDefault) event.preventDefault();
25
+ methods.toggle();
26
+ }, { signal: controller.signal });
27
+ return () => {
28
+ controller.abort();
29
+ };
30
+ });
24
31
  };
25
-
32
+ //#endregion
26
33
  export { Component, Name };
27
- //# sourceMappingURL=accordion-trigger.js.map
34
+
28
35
  //# sourceMappingURL=accordion-trigger.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/accordion-trigger.ts"],"names":[],"mappings":";;;;AAUO,MAAM,IAAO,GAAA,CAAA,iBAAA;AAEb,MAAM,SAAyC,GAAA,CAAC,KAAO,EAAA,EAAE,SAAc,KAAA;AAC5E,EAAA,MAAM,CAAC,KAAA,EAAO,OAAO,CAAA,GAAI,iBAAiB,OAAO,CAAA;AAEjD,EAAA,YAAA,CAAa,MAAM;AACjB,IAAA,MAAM,cAAc,KAAM,CAAA,WAAA;AAC1B,IAAA,IAAI,WAAa,EAAA;AAEjB,IAAA,MAAM,UAAa,GAAA,IAAI,eAAgB,EAAA,EACrC,iBAAiB,KAAM,CAAA,cAAA;AAEzB,IAAQ,OAAA,CAAA,gBAAA;AAAA,MACN,OAAA;AAAA,MACA,CAAC,KAAU,KAAA;AACT,QAAI,IAAA,cAAA,QAAsB,cAAe,EAAA;AACzC,QAAA,OAAA,CAAQ,MAAO,EAAA;AAAA,OACjB;AAAA,MACA,EAAE,MAAQ,EAAA,UAAA,CAAW,MAAO;AAAA,KAC9B;AAEA,IAAA,OAAO,UAAU,MAAM;AACrB,MAAA,UAAA,CAAW,KAAM,EAAA;AAAA,KAClB,CAAA;AAAA,GACF,CAAA;AACH","file":"accordion-trigger.js","sourcesContent":["import { type CorrectComponentType } from \"@brytdesigns/web-component-core/utils\";\n\nimport { createEffect, onCleanup } from \"solid-js\";\n\nimport { useAccordionItem } from \"../hooks/index.js\";\n\nexport type Props = {\n preventDefault: boolean;\n};\n\nexport const Name = `accordion-trigger`;\n\nexport const Component: CorrectComponentType<Props> = (props, { element }) => {\n const [state, methods] = useAccordionItem(element);\n\n createEffect(() => {\n const isAnimating = state.isAnimating;\n if (isAnimating) return;\n\n const controller = new AbortController(),\n preventDefault = props.preventDefault;\n\n element.addEventListener(\n \"click\",\n (event) => {\n if (preventDefault) event.preventDefault();\n methods.toggle();\n },\n { signal: controller.signal },\n );\n\n return onCleanup(() => {\n controller.abort();\n });\n });\n};\n"]}
1
+ {"version":3,"file":"accordion-trigger.js","names":[],"sources":["../../../src/components/accordion-trigger.ts"],"sourcesContent":["import {\n\ttype CorrectComponentType,\n\tcreateGuardedEffect,\n\tfindDisclosureContent,\n\tfindDisclosureControl,\n\tlinkDisclosureControl,\n} from \"@brytdesigns/web-component-core/utils\";\n\nimport { useAccordionItem } from \"../hooks/index.js\";\n\nexport type Props = {\n\tpreventDefault: boolean;\n};\n\nexport const Name = `accordion-trigger`;\n\nexport const Component: CorrectComponentType<Props> = (props, { element }) => {\n\tconst [state, methods] = useAccordionItem(element);\n\n\t// `aria-expanded` belongs on the element with the button role, not on\n\t// `accordion-trigger`, which has no role at all — assistive tech ignored it\n\t// there.\n\tconst control = findDisclosureControl(element);\n\tif (!control) {\n\t\tconsole.warn(\n\t\t\t`${Name}: put a <button> inside the trigger so assistive tech can operate it`,\n\t\t\telement,\n\t\t);\n\t} else {\n\t\tlet isLinked = false;\n\t\tcreateGuardedEffect(\n\t\t\t() => state.isExpanded,\n\t\t\t(isExpanded) => {\n\t\t\t\tcontrol.setAttribute(\"aria-expanded\", isExpanded ? \"true\" : \"false\");\n\t\t\t\t// The content may not be parsed yet when the trigger first renders.\n\t\t\t\tif (!isLinked)\n\t\t\t\t\tisLinked = linkDisclosureControl(\n\t\t\t\t\t\tcontrol,\n\t\t\t\t\t\tfindDisclosureContent(\n\t\t\t\t\t\t\telement,\n\t\t\t\t\t\t\t\"accordion-item\",\n\t\t\t\t\t\t\t\"accordion-content\",\n\t\t\t\t\t\t),\n\t\t\t\t\t\t\"accordion-content\",\n\t\t\t\t\t);\n\t\t\t},\n\t\t);\n\t}\n\n\tcreateGuardedEffect(\n\t\t// `preventDefault` belongs in the compute: read in apply it is untracked,\n\t\t// so changing the attribute would not rewire the listener.\n\t\t() => ({\n\t\t\tisAnimating: state.isAnimating,\n\t\t\tpreventDefault: props.preventDefault,\n\t\t}),\n\t\t({ isAnimating, preventDefault }) => {\n\t\t\tif (isAnimating) return;\n\n\t\t\tconst controller = new AbortController();\n\n\t\t\telement.addEventListener(\n\t\t\t\t\"click\",\n\t\t\t\t(event) => {\n\t\t\t\t\tif (preventDefault) event.preventDefault();\n\t\t\t\t\tmethods.toggle();\n\t\t\t\t},\n\t\t\t\t{ signal: controller.signal },\n\t\t\t);\n\n\t\t\treturn () => {\n\t\t\t\tcontroller.abort();\n\t\t\t};\n\t\t},\n\t);\n};\n"],"mappings":";;;;AAcA,IAAa,OAAO;AAEpB,IAAa,aAA0C,OAAO,EAAE,cAAc;CAC7E,MAAM,CAAC,OAAO,WAAW,iBAAiB,OAAO;CAKjD,MAAM,UAAU,sBAAsB,OAAO;CAC7C,IAAI,CAAC,SACJ,QAAQ,KACP,GAAG,KAAK,uEACR,OACD;MACM;EACN,IAAI,WAAW;EACf,0BACO,MAAM,aACX,eAAe;GACf,QAAQ,aAAa,iBAAiB,aAAa,SAAS,OAAO;GAEnE,IAAI,CAAC,UACJ,WAAW,sBACV,SACA,sBACC,SACA,kBACA,mBACD,GACA,mBACD;EACF,CACD;CACD;CAEA,2BAGQ;EACN,aAAa,MAAM;EACnB,gBAAgB,MAAM;CACvB,KACC,EAAE,aAAa,qBAAqB;EACpC,IAAI,aAAa;EAEjB,MAAM,aAAa,IAAI,gBAAgB;EAEvC,QAAQ,iBACP,UACC,UAAU;GACV,IAAI,gBAAgB,MAAM,eAAe;GACzC,QAAQ,OAAO;EAChB,GACA,EAAE,QAAQ,WAAW,OAAO,CAC7B;EAEA,aAAa;GACZ,WAAW,MAAM;EAClB;CACD,CACD;AACD"}
@@ -1,10 +1,4 @@
1
- import * as accordionContent_js from './accordion-content.js';
2
- export { accordionContent_js as AccordionContent };
3
- import * as accordionItem_js from './accordion-item.js';
4
- export { accordionItem_js as AccordionItem };
5
- import * as accordionTrigger_js from './accordion-trigger.js';
6
- export { accordionTrigger_js as AccordionTrigger };
7
- import * as accordionContext_js from './accordion-context.js';
8
- export { accordionContext_js as AccordionContext };
9
- //# sourceMappingURL=index.js.map
10
- //# sourceMappingURL=index.js.map
1
+ import "./accordion-content.js";
2
+ import "./accordion-context.js";
3
+ import "./accordion-item.js";
4
+ import "./accordion-trigger.js";
@@ -1,4 +1,3 @@
1
- export * from './useAccordion.js';
2
- export * from './useAccordionItem.js';
3
- //# sourceMappingURL=index.js.map
4
- //# sourceMappingURL=index.js.map
1
+ import { getAccordionContext, provideAccordionContext, useAccordion, useAccordionAt, useAccordionContext } from "./useAccordion.js";
2
+ import { getAccordionItemContext, provideAccordionItemContext, useAccordionItem, useAccordionItemAt, useAccordionItemContext } from "./useAccordionItem.js";
3
+ export { getAccordionContext, getAccordionItemContext, provideAccordionContext, provideAccordionItemContext, useAccordion, useAccordionAt, useAccordionContext, useAccordionItem, useAccordionItemAt, useAccordionItemContext };
@@ -1,85 +1,98 @@
1
- import { createContext, provide, consume } from 'component-register';
2
- import { splitProps, createEffect, on, batch, untrack, mergeProps, createSelector } from 'solid-js';
3
- import { createStore } from 'solid-js/store';
4
- import { createWithElementContext, toHyphenated, getContextFromProvider } from '@brytdesigns/web-component-core/utils';
5
-
1
+ import { createGuardedEffect, createRemoteContext, getContextFromProvider, toHyphenated } from "@brytdesigns/web-component-core/utils";
2
+ import { createSignal, createStore, merge, omit, untrack } from "solid-js";
3
+ import { consume, createContext, provide } from "component-register";
4
+ //#region src/hooks/useAccordion.ts
6
5
  function initializeAccordionContext(props) {
7
- const [element, stateProps] = splitProps(props, ["root"]);
8
- const [store, setStore] = createStore({ animationQueue: [] });
9
- createEffect(
10
- on(
11
- () => store.animationQueue,
12
- (animationQueue) => {
13
- if (!animationQueue.length) return;
14
- const animations = Promise.allSettled(store.animationQueue);
15
- setElementState("isAnimating", true);
16
- animations.finally(() => {
17
- batch(() => {
18
- setElementState("isAnimating", false);
19
- setStore("animationQueue", []);
20
- });
21
- });
22
- }
23
- )
24
- );
25
- function setElementState(key, value) {
26
- const currentValue = untrack(() => props[key]);
27
- if (typeof value === "function") {
28
- let result = false;
29
- if (typeof currentValue === "number") {
30
- result = value(currentValue || 0);
31
- } else if (typeof currentValue === "boolean") {
32
- result = value(currentValue || false);
33
- }
34
- if (`${currentValue}` === `${value}`) return;
35
- element.root.setAttribute(toHyphenated(key), `${result}`);
36
- return;
37
- }
38
- if (`${currentValue}` === `${value}`) return;
39
- return element.root.setAttribute(toHyphenated(key), `${value}`);
40
- }
41
- return [
42
- mergeProps(store, stateProps),
43
- { setElementState, setStore }
44
- ];
6
+ const stateProps = omit(props, "root");
7
+ const [store, setStore] = createStore({ revealCount: 0 });
8
+ /**
9
+ * The animation queue is a SIGNAL, not part of the store above.
10
+ *
11
+ * A store deep-proxies what you put in it, and what goes in here is a list
12
+ * of live promises. Proxied, every `.then` on them is a reactive read from
13
+ * a non-tracking scope — Solid reports it (STRICT_READ_UNTRACKED), and it
14
+ * is a proxy hop on every access of an object that is not state at all.
15
+ *
16
+ * Nothing here needs per-property reactivity: the queue is replaced
17
+ * wholesale and read wholesale. `revealCount` stays in the store, because
18
+ * that genuinely is state.
19
+ */
20
+ const [animationQueue, setAnimationQueue] = createSignal([]);
21
+ createGuardedEffect(animationQueue, (queue) => {
22
+ if (!queue.length) return;
23
+ const animations = Promise.allSettled(queue);
24
+ setElementState("isAnimating", true);
25
+ animations.finally(() => {
26
+ setElementState("isAnimating", false);
27
+ setAnimationQueue([]);
28
+ });
29
+ });
30
+ function setElementState(key, value) {
31
+ const currentValue = untrack(() => props[key]);
32
+ if (typeof value === "function") {
33
+ let result = false;
34
+ if (typeof currentValue === "number") result = value(currentValue || 0);
35
+ else if (typeof currentValue === "boolean") result = value(currentValue || false);
36
+ if (`${currentValue}` === `${result}`) return;
37
+ props.root.setAttribute(toHyphenated(key), `${result}`);
38
+ return;
39
+ }
40
+ if (`${currentValue}` === `${value}`) return;
41
+ return props.root.setAttribute(toHyphenated(key), `${value}`);
42
+ }
43
+ return [merge(store, stateProps, { get animationQueue() {
44
+ return animationQueue();
45
+ } }), {
46
+ setElementState,
47
+ setStore,
48
+ setAnimationQueue
49
+ }];
45
50
  }
46
- const AccordionContextState = createContext(initializeAccordionContext);
47
- const provideAccordionContext = (initialState, element) => {
48
- const props = mergeProps(initialState, { root: element });
49
- return provide(AccordionContextState, props, element);
51
+ var AccordionContextState = createContext(initializeAccordionContext);
52
+ var provideAccordionContext = (initialState, element) => {
53
+ const props = merge(initialState, { root: element });
54
+ return provide(AccordionContextState, props, element);
50
55
  };
51
- const useAccordionContext = (context) => {
52
- const [state, { setElementState, setStore: setState }] = context;
53
- function updateAnimationQueue(animation) {
54
- setState("animationQueue", (state2) => [...state2, animation]);
55
- }
56
- function updateActiveIndex(index) {
57
- setElementState("activeIndex", index);
58
- }
59
- const isActive = createSelector(() => state.activeIndex);
60
- return [
61
- state,
62
- { updateAnimationQueue, item: { update: updateActiveIndex, isActive } }
63
- ];
56
+ var useAccordionContext = (context) => {
57
+ const [state, { setElementState, setStore: setState, setAnimationQueue }] = context;
58
+ function updateAnimationQueue(animation) {
59
+ setAnimationQueue((queue) => [...queue, animation]);
60
+ }
61
+ function updateActiveIndex(index) {
62
+ setElementState("activeIndex", index);
63
+ }
64
+ /**
65
+ * Runs `open` with content snapping to its new state instead of animating.
66
+ * Used when find-in-page reveals closed content: the item it opens, and the
67
+ * item that closes in its place, settle before the browser scrolls to the
68
+ * match, so the match does not move out of view.
69
+ */
70
+ function reveal(open) {
71
+ setState((draft) => {
72
+ draft.revealCount += 1;
73
+ });
74
+ open();
75
+ }
76
+ const isActive = (index) => state.activeIndex === index;
77
+ return [state, {
78
+ updateAnimationQueue,
79
+ reveal,
80
+ item: {
81
+ update: updateActiveIndex,
82
+ isActive
83
+ }
84
+ }];
64
85
  };
65
- const useAccordion = (element) => {
66
- const context = consume(AccordionContextState, element);
67
- if (!context) {
68
- throw console.error(
69
- "AccordionContext not found! Please ensure to wrap your custom element with accordion-context element."
70
- );
71
- }
72
- return useAccordionContext(context);
86
+ var useAccordion = (element) => {
87
+ const context = consume(AccordionContextState, element);
88
+ if (!context) throw new Error("AccordionContext not found! Please ensure to wrap your custom element with accordion-context element.");
89
+ return useAccordionContext(context);
73
90
  };
74
- const withAccordionElementContext = createWithElementContext(AccordionContextState);
75
- const getAccordionContext = (element) => {
76
- const context = getContextFromProvider(
77
- AccordionContextState,
78
- element
79
- );
80
- return useAccordionContext(context);
91
+ var useAccordionAt = createRemoteContext(AccordionContextState);
92
+ var getAccordionContext = (element) => {
93
+ return useAccordionContext(getContextFromProvider(AccordionContextState, element));
81
94
  };
95
+ //#endregion
96
+ export { getAccordionContext, provideAccordionContext, useAccordion, useAccordionAt, useAccordionContext };
82
97
 
83
- export { getAccordionContext, provideAccordionContext, useAccordion, useAccordionContext, withAccordionElementContext };
84
- //# sourceMappingURL=useAccordion.js.map
85
98
  //# sourceMappingURL=useAccordion.js.map