@brytdesigns/web-component-accordion 1.1.8 → 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 +1 @@
1
- {"version":3,"sources":["../../../src/hooks/useAccordion.ts"],"names":["state"],"mappings":"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","file":"useAccordion.js","sourcesContent":["import {\n type ICustomElement,\n createContext,\n provide,\n consume,\n} from \"component-register\";\nimport {\n createEffect,\n mergeProps,\n on,\n batch,\n splitProps,\n createSelector,\n untrack,\n} from \"solid-js\";\nimport { createStore } from \"solid-js/store\";\nimport {\n toHyphenated,\n getContextFromProvider,\n createWithElementContext,\n} from \"@brytdesigns/web-component-core/utils\";\n\ntype StoreContext = {\n animationQueue: Promise<unknown>[];\n};\n\ntype CreateContextOptions = {\n root: HTMLElement & ICustomElement;\n isAnimating: boolean;\n activeIndex: number;\n};\n\ntype WalkableNode = Parameters<typeof provide>[2];\n\ntype AccordionContext = ReturnType<typeof initializeAccordionContext>;\n\nfunction initializeAccordionContext(props: CreateContextOptions) {\n const [element, stateProps] = splitProps(props, [\"root\"]);\n const [store, setStore] = createStore<StoreContext>({ animationQueue: [] });\n\n createEffect(\n on(\n () => store.animationQueue,\n (animationQueue) => {\n if (!animationQueue.length) return;\n const animations = Promise.allSettled(store.animationQueue);\n setElementState(\"isAnimating\", true);\n animations.finally(() => {\n batch(() => {\n setElementState(\"isAnimating\", false);\n setStore(\"animationQueue\", []);\n });\n });\n },\n ),\n );\n\n function setElementState(\n key: keyof Omit<CreateContextOptions, \"root\">,\n value: boolean | number | ((v: boolean | number) => boolean | number),\n ) {\n const currentValue = untrack(() => props[key]);\n if (typeof value === \"function\") {\n let result: boolean | number = false;\n if (typeof currentValue === \"number\") {\n result = value(currentValue || 0);\n } else if (typeof currentValue === \"boolean\") {\n result = value(currentValue || false);\n }\n if (`${currentValue}` === `${value}`) return;\n element.root.setAttribute(toHyphenated(key), `${result}`);\n return;\n }\n if (`${currentValue}` === `${value}`) return;\n return element.root.setAttribute(toHyphenated(key), `${value}`);\n }\n\n return [\n mergeProps(store, stateProps),\n { setElementState, setStore },\n ] as const;\n}\n\nconst AccordionContextState = createContext(initializeAccordionContext);\n\nexport const provideAccordionContext = (\n initialState: Omit<CreateContextOptions, \"root\">,\n element: WalkableNode,\n): AccordionContext => {\n const props = mergeProps(initialState, { root: element });\n return provide(AccordionContextState, props, element);\n};\n\nexport const useAccordionContext = (context: AccordionContext) => {\n const [state, { setElementState, setStore: setState }] = context;\n\n function updateAnimationQueue(animation: Promise<unknown>) {\n setState(\"animationQueue\", (state) => [...state, animation]);\n }\n\n function updateActiveIndex(index: number) {\n setElementState(\"activeIndex\", index);\n }\n\n const isActive = createSelector(() => state.activeIndex);\n\n return [\n state,\n { updateAnimationQueue, item: { update: updateActiveIndex, isActive } },\n ] as const;\n};\n\nexport const useAccordion = (element: HTMLElement & ICustomElement) => {\n const context: AccordionContext = consume(AccordionContextState, element);\n\n if (!context) {\n throw console.error(\n \"AccordionContext not found! Please ensure to wrap your custom element with accordion-context element.\",\n );\n }\n\n return useAccordionContext(context);\n};\n\nexport const withAccordionElementContext = createWithElementContext<\n typeof AccordionContextState,\n AccordionContext\n>(AccordionContextState);\n\nexport const getAccordionContext = (element: Element) => {\n const context = getContextFromProvider<AccordionContext>(\n AccordionContextState,\n element,\n );\n return useAccordionContext(context);\n};\n"]}
1
+ {"version":3,"file":"useAccordion.js","names":[],"sources":["../../../src/hooks/useAccordion.ts"],"sourcesContent":["import {\n\tcreateGuardedEffect,\n\tcreateRemoteContext,\n\tgetContextFromProvider,\n\ttoHyphenated,\n} from \"@brytdesigns/web-component-core/utils\";\nimport {\n\tconsume,\n\tcreateContext,\n\ttype ICustomElement,\n\tprovide,\n} from \"component-register\";\nimport { createSignal, createStore, merge, omit, untrack } from \"solid-js\";\n\ntype StoreContext = {\n\t/**\n\t * Incremented once per find-in-page reveal, and never reset.\n\t *\n\t * A reveal has to open the matched item — and, without `allow-multiple`,\n\t * close the one open in its place — *without* animating, so the layout is\n\t * settled by the time the browser scrolls to the match. Solid 1 could\n\t * express that as a boolean held across the write, because a write outside\n\t * `batch()` flushed its effects synchronously: the content's effect ran\n\t * inside `reveal()` and saw the flag still set. Solid 2 stages writes and\n\t * flushes them together, so by the time the effect runs the flag would\n\t * already be back to `false`.\n\t *\n\t * A counter does not depend on when the flush happens. Each content\n\t * remembers the value it last ran at; a run whose value has moved was\n\t * caused by a reveal, whenever it is flushed.\n\t */\n\trevealCount: number;\n};\n\ntype CreateContextOptions = {\n\troot: HTMLElement & ICustomElement;\n\tisAnimating: boolean;\n\tactiveIndex: number;\n\tallowMultiple: boolean;\n};\n\ntype WalkableNode = Parameters<typeof provide>[2];\n\ntype AccordionContext = ReturnType<typeof initializeAccordionContext>;\n\nfunction initializeAccordionContext(props: CreateContextOptions) {\n\t// `omit` returns only the rest, so `root` is read straight off `props`.\n\tconst stateProps = omit(props, \"root\");\n\tconst [store, setStore] = createStore<StoreContext>({ revealCount: 0 });\n\n\t/**\n\t * The animation queue is a SIGNAL, not part of the store above.\n\t *\n\t * A store deep-proxies what you put in it, and what goes in here is a list\n\t * of live promises. Proxied, every `.then` on them is a reactive read from\n\t * a non-tracking scope — Solid reports it (STRICT_READ_UNTRACKED), and it\n\t * is a proxy hop on every access of an object that is not state at all.\n\t *\n\t * Nothing here needs per-property reactivity: the queue is replaced\n\t * wholesale and read wholesale. `revealCount` stays in the store, because\n\t * that genuinely is state.\n\t */\n\tconst [animationQueue, setAnimationQueue] = createSignal<Promise<unknown>[]>(\n\t\t[],\n\t);\n\n\tcreateGuardedEffect(animationQueue, (queue) => {\n\t\tif (!queue.length) return;\n\t\tconst animations = Promise.allSettled(queue);\n\t\tsetElementState(\"isAnimating\", true);\n\t\tanimations.finally(() => {\n\t\t\t// No `batch` in v2 — writes stage and flush together by default.\n\t\t\tsetElementState(\"isAnimating\", false);\n\t\t\tsetAnimationQueue([]);\n\t\t});\n\t});\n\n\tfunction setElementState(\n\t\tkey: keyof Omit<CreateContextOptions, \"root\">,\n\t\tvalue: boolean | number | ((v: boolean | number) => boolean | number),\n\t) {\n\t\tconst currentValue = untrack(() => props[key]);\n\t\tif (typeof value === \"function\") {\n\t\t\tlet result: boolean | number = false;\n\t\t\tif (typeof currentValue === \"number\") {\n\t\t\t\tresult = value(currentValue || 0);\n\t\t\t} else if (typeof currentValue === \"boolean\") {\n\t\t\t\tresult = value(currentValue || false);\n\t\t\t}\n\t\t\t// Compare against the computed result, not `value` — `value` is the\n\t\t\t// updater function here, and its source text never equals a state\n\t\t\t// value, so this guard never fired on the updater path. Latent\n\t\t\t// rather than active today: every updater in the repo is a\n\t\t\t// negation, so the result always differs anyway.\n\t\t\tif (`${currentValue}` === `${result}`) return;\n\t\t\tprops.root.setAttribute(toHyphenated(key), `${result}`);\n\t\t\treturn;\n\t\t}\n\t\tif (`${currentValue}` === `${value}`) return;\n\t\treturn props.root.setAttribute(toHyphenated(key), `${value}`);\n\t}\n\n\treturn [\n\t\tmerge(store, stateProps, {\n\t\t\tget animationQueue() {\n\t\t\t\treturn animationQueue();\n\t\t\t},\n\t\t}),\n\t\t{ setElementState, setStore, setAnimationQueue },\n\t] as const;\n}\n\nconst AccordionContextState = createContext(initializeAccordionContext);\n\nexport const provideAccordionContext = (\n\tinitialState: Omit<CreateContextOptions, \"root\">,\n\telement: WalkableNode,\n): AccordionContext => {\n\tconst props = merge(initialState, { root: element });\n\treturn provide(AccordionContextState, props, element);\n};\n\nexport const useAccordionContext = (context: AccordionContext) => {\n\tconst [state, { setElementState, setStore: setState, setAnimationQueue }] =\n\t\tcontext;\n\n\tfunction updateAnimationQueue(animation: Promise<unknown>) {\n\t\t// Replaced rather than pushed into. The effect in\n\t\t// `initializeAccordionContext` tracks the queue signal, and an in-place\n\t\t// `push` leaves it holding the same array — so the effect never re-ran\n\t\t// and `is-animating` was never published on `accordion-context` at all.\n\t\t// The Solid 1 code this replaced built a new array for the same reason;\n\t\t// translating it to `push` dropped that, and no test covered it.\n\t\tsetAnimationQueue((queue) => [...queue, animation]);\n\t}\n\n\tfunction updateActiveIndex(index: number) {\n\t\tsetElementState(\"activeIndex\", index);\n\t}\n\n\t/**\n\t * Runs `open` with content snapping to its new state instead of animating.\n\t * Used when find-in-page reveals closed content: the item it opens, and the\n\t * item that closes in its place, settle before the browser scrolls to the\n\t * match, so the match does not move out of view.\n\t */\n\tfunction reveal(open: () => void) {\n\t\tsetState((draft) => {\n\t\t\tdraft.revealCount += 1;\n\t\t});\n\t\topen();\n\t}\n\n\t// `createSelector` is gone. It was an invalidation optimisation for large\n\t// keyed sets; with a handful of accordion items a plain equality read is\n\t// identical in behaviour and clearer than reshaping this into\n\t// `createProjection`, which is store-shaped rather than predicate-shaped.\n\tconst isActive = (index: number) => state.activeIndex === index;\n\n\treturn [\n\t\tstate,\n\t\t{\n\t\t\tupdateAnimationQueue,\n\t\t\treveal,\n\t\t\titem: { update: updateActiveIndex, isActive },\n\t\t},\n\t] as const;\n};\n\nexport const useAccordion = (element: HTMLElement & ICustomElement) => {\n\tconst context: AccordionContext = consume(AccordionContextState, element);\n\n\tif (!context) {\n\t\tthrow new Error(\n\t\t\t\"AccordionContext not found! Please ensure to wrap your custom element with accordion-context element.\",\n\t\t);\n\t}\n\n\treturn useAccordionContext(context);\n};\n\nexport const useAccordionAt = createRemoteContext<AccordionContext>(\n\tAccordionContextState,\n);\n\nexport const getAccordionContext = (element: Element) => {\n\tconst context = getContextFromProvider<AccordionContext>(\n\t\tAccordionContextState,\n\t\telement,\n\t);\n\treturn useAccordionContext(context);\n};\n"],"mappings":";;;;AA6CA,SAAS,2BAA2B,OAA6B;CAEhE,MAAM,aAAa,KAAK,OAAO,MAAM;CACrC,MAAM,CAAC,OAAO,YAAY,YAA0B,EAAE,aAAa,EAAE,CAAC;;;;;;;;;;;;;CActE,MAAM,CAAC,gBAAgB,qBAAqB,aAC3C,CAAC,CACF;CAEA,oBAAoB,iBAAiB,UAAU;EAC9C,IAAI,CAAC,MAAM,QAAQ;EACnB,MAAM,aAAa,QAAQ,WAAW,KAAK;EAC3C,gBAAgB,eAAe,IAAI;EACnC,WAAW,cAAc;GAExB,gBAAgB,eAAe,KAAK;GACpC,kBAAkB,CAAC,CAAC;EACrB,CAAC;CACF,CAAC;CAED,SAAS,gBACR,KACA,OACC;EACD,MAAM,eAAe,cAAc,MAAM,IAAI;EAC7C,IAAI,OAAO,UAAU,YAAY;GAChC,IAAI,SAA2B;GAC/B,IAAI,OAAO,iBAAiB,UAC3B,SAAS,MAAM,gBAAgB,CAAC;QAC1B,IAAI,OAAO,iBAAiB,WAClC,SAAS,MAAM,gBAAgB,KAAK;GAOrC,IAAI,GAAG,mBAAmB,GAAG,UAAU;GACvC,MAAM,KAAK,aAAa,aAAa,GAAG,GAAG,GAAG,QAAQ;GACtD;EACD;EACA,IAAI,GAAG,mBAAmB,GAAG,SAAS;EACtC,OAAO,MAAM,KAAK,aAAa,aAAa,GAAG,GAAG,GAAG,OAAO;CAC7D;CAEA,OAAO,CACN,MAAM,OAAO,YAAY,EACxB,IAAI,iBAAiB;EACpB,OAAO,eAAe;CACvB,EACD,CAAC,GACD;EAAE;EAAiB;EAAU;CAAkB,CAChD;AACD;AAEA,IAAM,wBAAwB,cAAc,0BAA0B;AAEtE,IAAa,2BACZ,cACA,YACsB;CACtB,MAAM,QAAQ,MAAM,cAAc,EAAE,MAAM,QAAQ,CAAC;CACnD,OAAO,QAAQ,uBAAuB,OAAO,OAAO;AACrD;AAEA,IAAa,uBAAuB,YAA8B;CACjE,MAAM,CAAC,OAAO,EAAE,iBAAiB,UAAU,UAAU,uBACpD;CAED,SAAS,qBAAqB,WAA6B;EAO1D,mBAAmB,UAAU,CAAC,GAAG,OAAO,SAAS,CAAC;CACnD;CAEA,SAAS,kBAAkB,OAAe;EACzC,gBAAgB,eAAe,KAAK;CACrC;;;;;;;CAQA,SAAS,OAAO,MAAkB;EACjC,UAAU,UAAU;GACnB,MAAM,eAAe;EACtB,CAAC;EACD,KAAK;CACN;CAMA,MAAM,YAAY,UAAkB,MAAM,gBAAgB;CAE1D,OAAO,CACN,OACA;EACC;EACA;EACA,MAAM;GAAE,QAAQ;GAAmB;EAAS;CAC7C,CACD;AACD;AAEA,IAAa,gBAAgB,YAA0C;CACtE,MAAM,UAA4B,QAAQ,uBAAuB,OAAO;CAExE,IAAI,CAAC,SACJ,MAAM,IAAI,MACT,uGACD;CAGD,OAAO,oBAAoB,OAAO;AACnC;AAEA,IAAa,iBAAiB,oBAC7B,qBACD;AAEA,IAAa,uBAAuB,YAAqB;CAKxD,OAAO,oBAJS,uBACf,uBACA,OAE0B,CAAO;AACnC"}
@@ -1,107 +1,85 @@
1
- import { createContext, provide, consume } from 'component-register';
2
- import { splitProps, createEffect, batch, untrack, mergeProps } from 'solid-js';
3
- import { createWithElementContext, toHyphenated, getContextFromProvider } from '@brytdesigns/web-component-core/utils';
4
- import { useAccordion } from './useAccordion.js';
5
-
1
+ import { useAccordion } from "./useAccordion.js";
2
+ import { createGuardedEffect, createRemoteContext, getContextFromProvider, toHyphenated } from "@brytdesigns/web-component-core/utils";
3
+ import { merge, omit, untrack } from "solid-js";
4
+ import { consume, createContext, provide } from "component-register";
5
+ //#region src/hooks/useAccordionItem.ts
6
6
  function initializeAccordionItemContext(props) {
7
- const [element, _, stateProps] = splitProps(
8
- props,
9
- ["root"],
10
- ["ariaExpanded"]
11
- );
12
- const [context, methods] = useAccordion(element.root);
13
- function setElementState(key, value) {
14
- const currentValue = untrack(() => props[key]);
15
- if (typeof value === "function") {
16
- let result = false;
17
- if (typeof currentValue === "number") {
18
- result = value(currentValue || 0);
19
- } else if (typeof currentValue === "boolean") {
20
- result = value(currentValue || false);
21
- }
22
- if (`${currentValue}` === `${value}`) return;
23
- element.root.setAttribute(toHyphenated(key), `${result}`);
24
- return;
25
- }
26
- if (`${currentValue}` === `${value}`) return;
27
- return element.root.setAttribute(toHyphenated(key), `${value}`);
28
- }
29
- createEffect(() => {
30
- const isActive = methods.item.isActive(props.index);
31
- batch(() => {
32
- setElementState("isExpanded", isActive);
33
- setElementState("ariaExpanded", isActive);
34
- });
35
- });
36
- createEffect(() => {
37
- const index = untrack(() => stateProps.index);
38
- const isExpanded = stateProps.isExpanded;
39
- if (isExpanded) methods.item.update(index);
40
- });
41
- function setActive(index) {
42
- methods.item.update(index);
43
- }
44
- return [
45
- mergeProps(stateProps, {
46
- get isAnimating() {
47
- return context.isAnimating;
48
- }
49
- }),
50
- { setElementState, setActive }
51
- ];
7
+ const stateProps = omit(props, "root");
8
+ const [context, methods] = useAccordion(props.root);
9
+ const allowMultiple = untrack(() => context.allowMultiple);
10
+ function setElementState(key, value) {
11
+ const currentValue = untrack(() => props[key]);
12
+ if (typeof value === "function") {
13
+ let result = false;
14
+ if (typeof currentValue === "number") result = value(currentValue || 0);
15
+ else if (typeof currentValue === "boolean") result = value(currentValue || false);
16
+ if (`${currentValue}` === `${result}`) return;
17
+ props.root.setAttribute(toHyphenated(key), `${result}`);
18
+ return;
19
+ }
20
+ if (`${currentValue}` === `${value}`) return;
21
+ return props.root.setAttribute(toHyphenated(key), `${value}`);
22
+ }
23
+ if (!allowMultiple) {
24
+ createGuardedEffect(() => methods.item.isActive(props.index), (isActive, previous) => {
25
+ if (previous === void 0 && untrack(() => props.isExpanded)) return;
26
+ setElementState("isExpanded", isActive);
27
+ });
28
+ createGuardedEffect(() => stateProps.isExpanded, (isExpanded) => {
29
+ if (isExpanded) methods.item.update(untrack(() => stateProps.index));
30
+ });
31
+ }
32
+ function setActive(index) {
33
+ if (!allowMultiple) methods.item.update(index);
34
+ }
35
+ return [merge(stateProps, { get isAnimating() {
36
+ return context.isAnimating;
37
+ } }), {
38
+ setElementState,
39
+ setActive
40
+ }];
52
41
  }
53
- const AccordionItemContextState = createContext(initializeAccordionItemContext);
54
- const provideAccordionItemContext = (initialState, element) => {
55
- const props = mergeProps(initialState, { root: element });
56
- return provide(AccordionItemContextState, props, element);
42
+ var AccordionItemContextState = createContext(initializeAccordionItemContext);
43
+ var provideAccordionItemContext = (initialState, element) => {
44
+ const props = merge(initialState, { root: element });
45
+ return provide(AccordionItemContextState, props, element);
57
46
  };
58
- const useAccordionItemContext = (context) => {
59
- const [state, { setElementState, setActive }] = context;
60
- function expand() {
61
- const index = untrack(() => state.index);
62
- batch(() => {
63
- setActive(index);
64
- setElementState("isExpanded", true);
65
- });
66
- }
67
- function collapse() {
68
- batch(() => {
69
- setActive(-1);
70
- setElementState("isExpanded", false);
71
- });
72
- }
73
- function toggle() {
74
- setElementState("isExpanded", (v) => {
75
- const index = untrack(() => state.index);
76
- const newValue = !v;
77
- if (newValue) setActive(index);
78
- else setActive(-1);
79
- return newValue;
80
- });
81
- }
82
- return [state, { expand, collapse, toggle }];
47
+ var useAccordionItemContext = (context) => {
48
+ const [state, { setElementState, setActive }] = context;
49
+ function expand() {
50
+ const index = untrack(() => state.index);
51
+ setActive(index);
52
+ setElementState("isExpanded", true);
53
+ }
54
+ function collapse() {
55
+ setActive(-1);
56
+ setElementState("isExpanded", false);
57
+ }
58
+ function toggle() {
59
+ setElementState("isExpanded", (v) => {
60
+ const index = untrack(() => state.index);
61
+ const newValue = !v;
62
+ if (newValue) setActive(index);
63
+ else setActive(-1);
64
+ return newValue;
65
+ });
66
+ }
67
+ return [state, {
68
+ expand,
69
+ collapse,
70
+ toggle
71
+ }];
83
72
  };
84
- const useAccordionItem = (element) => {
85
- const context = consume(
86
- AccordionItemContextState,
87
- element
88
- );
89
- if (!context) {
90
- throw console.error(
91
- "AccordionItemContext not found! Please ensure to wrap your custom element with accordion-item element."
92
- );
93
- }
94
- return useAccordionItemContext(context);
73
+ var useAccordionItem = (element) => {
74
+ const context = consume(AccordionItemContextState, element);
75
+ if (!context) throw new Error("AccordionItemContext not found! Please ensure to wrap your custom element with accordion-item element.");
76
+ return useAccordionItemContext(context);
95
77
  };
96
- const withAccordionItemElementContext = createWithElementContext(AccordionItemContextState);
97
- const getAccordionItemContext = (element) => {
98
- const context = getContextFromProvider(
99
- AccordionItemContextState,
100
- element
101
- );
102
- return useAccordionItemContext(context);
78
+ var useAccordionItemAt = createRemoteContext(AccordionItemContextState);
79
+ var getAccordionItemContext = (element) => {
80
+ return useAccordionItemContext(getContextFromProvider(AccordionItemContextState, element));
103
81
  };
82
+ //#endregion
83
+ export { getAccordionItemContext, provideAccordionItemContext, useAccordionItem, useAccordionItemAt, useAccordionItemContext };
104
84
 
105
- export { getAccordionItemContext, provideAccordionItemContext, useAccordionItem, useAccordionItemContext, withAccordionItemElementContext };
106
- //# sourceMappingURL=useAccordionItem.js.map
107
85
  //# sourceMappingURL=useAccordionItem.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/hooks/useAccordionItem.ts"],"names":[],"mappings":"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","file":"useAccordionItem.js","sourcesContent":["import {\n type ICustomElement,\n createContext,\n provide,\n consume,\n} from \"component-register\";\nimport { batch, createEffect, mergeProps, splitProps, untrack } from \"solid-js\";\nimport {\n toHyphenated,\n getContextFromProvider,\n createWithElementContext,\n} from \"@brytdesigns/web-component-core/utils\";\nimport { useAccordion } from \"./useAccordion.js\";\n\ntype CreateContextOptions = {\n root: HTMLElement & ICustomElement;\n isExpanded: boolean;\n index: number;\n ariaExpanded: boolean;\n};\n\ntype WalkableNode = Parameters<typeof provide>[2];\n\ntype AccordionItemContext = ReturnType<typeof initializeAccordionItemContext>;\n\nfunction initializeAccordionItemContext(props: CreateContextOptions) {\n const [element, _, stateProps] = splitProps(\n props,\n [\"root\"],\n [\"ariaExpanded\"],\n );\n const [context, methods] = useAccordion(element.root);\n\n function setElementState(\n key: keyof Omit<CreateContextOptions, \"root\">,\n value: boolean | number | ((v: boolean | number) => boolean | number),\n ) {\n const currentValue = untrack(() => props[key]);\n if (typeof value === \"function\") {\n let result: boolean | number = false;\n if (typeof currentValue === \"number\") {\n result = value(currentValue || 0);\n } else if (typeof currentValue === \"boolean\") {\n result = value(currentValue || false);\n }\n if (`${currentValue}` === `${value}`) return;\n element.root.setAttribute(toHyphenated(key), `${result}`);\n return;\n }\n if (`${currentValue}` === `${value}`) return;\n return element.root.setAttribute(toHyphenated(key), `${value}`);\n }\n\n createEffect(() => {\n const isActive = methods.item.isActive(props.index);\n batch(() => {\n setElementState(\"isExpanded\", isActive);\n setElementState(\"ariaExpanded\", isActive);\n });\n });\n\n createEffect(() => {\n const index = untrack(() => stateProps.index);\n const isExpanded = stateProps.isExpanded;\n if (isExpanded) methods.item.update(index);\n });\n\n function setActive(index: number) {\n methods.item.update(index);\n }\n\n return [\n mergeProps(stateProps, {\n get isAnimating() {\n return context.isAnimating;\n },\n }),\n { setElementState, setActive },\n ] as const;\n}\n\nconst AccordionItemContextState = createContext(initializeAccordionItemContext);\n\nexport const provideAccordionItemContext = (\n initialState: Omit<CreateContextOptions, \"root\">,\n element: WalkableNode,\n): AccordionItemContext => {\n const props = mergeProps(initialState, { root: element });\n return provide(AccordionItemContextState, props, element);\n};\n\nexport const useAccordionItemContext = (context: AccordionItemContext) => {\n const [state, { setElementState, setActive }] = context;\n\n function expand() {\n const index = untrack(() => state.index);\n batch(() => {\n setActive(index);\n setElementState(\"isExpanded\", true);\n });\n }\n\n function collapse() {\n batch(() => {\n setActive(-1);\n setElementState(\"isExpanded\", false);\n });\n }\n\n function toggle() {\n setElementState(\"isExpanded\", (v) => {\n const index = untrack(() => state.index);\n const newValue = !v;\n if (newValue) setActive(index);\n else setActive(-1);\n return newValue;\n });\n }\n\n return [state, { expand, collapse, toggle }] as const;\n};\n\nexport const useAccordionItem = (element: HTMLElement & ICustomElement) => {\n const context: AccordionItemContext = consume(\n AccordionItemContextState,\n element,\n );\n\n if (!context) {\n throw console.error(\n \"AccordionItemContext not found! Please ensure to wrap your custom element with accordion-item element.\",\n );\n }\n\n return useAccordionItemContext(context);\n};\n\nexport const withAccordionItemElementContext = createWithElementContext<\n typeof AccordionItemContextState,\n AccordionItemContext\n>(AccordionItemContextState);\n\nexport const getAccordionItemContext = (element: Element) => {\n const context = getContextFromProvider<AccordionItemContext>(\n AccordionItemContextState,\n element,\n );\n return useAccordionItemContext(context);\n};\n"]}
1
+ {"version":3,"file":"useAccordionItem.js","names":[],"sources":["../../../src/hooks/useAccordionItem.ts"],"sourcesContent":["import {\n\tcreateGuardedEffect,\n\tcreateRemoteContext,\n\tgetContextFromProvider,\n\ttoHyphenated,\n} from \"@brytdesigns/web-component-core/utils\";\nimport {\n\tconsume,\n\tcreateContext,\n\ttype ICustomElement,\n\tprovide,\n} from \"component-register\";\nimport { merge, omit, untrack } from \"solid-js\";\nimport { useAccordion } from \"./useAccordion.js\";\n\ntype CreateContextOptions = {\n\troot: HTMLElement & ICustomElement;\n\tisExpanded: boolean;\n\tindex: number;\n};\n\ntype WalkableNode = Parameters<typeof provide>[2];\n\ntype AccordionItemContext = ReturnType<typeof initializeAccordionItemContext>;\n\nfunction initializeAccordionItemContext(props: CreateContextOptions) {\n\t// `omit` returns only the rest; picked keys are read straight off `props`.\n\tconst stateProps = omit(props, \"root\");\n\tconst [context, methods] = useAccordion(props.root);\n\t// With allow-multiple, the item owns its open state instead of following\n\t// the context's active-index. Read once, like the context does.\n\tconst allowMultiple = untrack(() => context.allowMultiple);\n\n\tfunction setElementState(\n\t\tkey: keyof Omit<CreateContextOptions, \"root\">,\n\t\tvalue: boolean | number | ((v: boolean | number) => boolean | number),\n\t) {\n\t\tconst currentValue = untrack(() => props[key]);\n\t\tif (typeof value === \"function\") {\n\t\t\tlet result: boolean | number = false;\n\t\t\tif (typeof currentValue === \"number\") {\n\t\t\t\tresult = value(currentValue || 0);\n\t\t\t} else if (typeof currentValue === \"boolean\") {\n\t\t\t\tresult = value(currentValue || false);\n\t\t\t}\n\t\t\t// Compare against the computed result, not `value` — `value` is the\n\t\t\t// updater function here, and its source text never equals a state\n\t\t\t// value, so this guard never fired on the updater path. Latent\n\t\t\t// rather than active today: every updater in the repo is a\n\t\t\t// negation, so the result always differs anyway.\n\t\t\tif (`${currentValue}` === `${result}`) return;\n\t\t\tprops.root.setAttribute(toHyphenated(key), `${result}`);\n\t\t\treturn;\n\t\t}\n\t\tif (`${currentValue}` === `${value}`) return;\n\t\treturn props.root.setAttribute(toHyphenated(key), `${value}`);\n\t}\n\n\t// Without `allow-multiple`, `active-index` is the single source of truth and\n\t// these two effects keep the item in step with it. With it, each item owns\n\t// `is-expanded` outright, so neither runs and nothing closes an item that\n\t// the visitor did not close.\n\tif (!allowMultiple) {\n\t\tcreateGuardedEffect(\n\t\t\t() => methods.item.isActive(props.index),\n\t\t\t(isActive, previous) => {\n\t\t\t\t// On the mount run the markup wins. `accordion-context` seeds\n\t\t\t\t// `active-index` from the items' `is-expanded` a microtask later —\n\t\t\t\t// it cannot write its own prop from a component body under Solid 2\n\t\t\t\t// — so `active-index` is still -1 here and `isActive` is false even\n\t\t\t\t// for the item the markup opened. Writing that false would close\n\t\t\t\t// the item and then re-open it a tick later, which animates the\n\t\t\t\t// content shut and back open on load.\n\t\t\t\tif (previous === undefined && untrack(() => props.isExpanded)) return;\n\t\t\t\tsetElementState(\"isExpanded\", isActive);\n\t\t\t},\n\t\t);\n\n\t\tcreateGuardedEffect(\n\t\t\t() => stateProps.isExpanded,\n\t\t\t(isExpanded) => {\n\t\t\t\t// apply is untracked, so the read of `index` is a snapshot. It is\n\t\t\t\t// still written with `untrack`, because a bare read is reported\n\t\t\t\t// (STRICT_READ_UNTRACKED) and an unreviewed report is the only\n\t\t\t\t// kind worth having.\n\t\t\t\tif (isExpanded) methods.item.update(untrack(() => stateProps.index));\n\t\t\t},\n\t\t);\n\t}\n\n\tfunction setActive(index: number) {\n\t\tif (!allowMultiple) methods.item.update(index);\n\t}\n\n\treturn [\n\t\tmerge(stateProps, {\n\t\t\tget isAnimating() {\n\t\t\t\treturn context.isAnimating;\n\t\t\t},\n\t\t}),\n\t\t{ setElementState, setActive },\n\t] as const;\n}\n\nconst AccordionItemContextState = createContext(initializeAccordionItemContext);\n\nexport const provideAccordionItemContext = (\n\tinitialState: Omit<CreateContextOptions, \"root\">,\n\telement: WalkableNode,\n): AccordionItemContext => {\n\tconst props = merge(initialState, { root: element });\n\treturn provide(AccordionItemContextState, props, element);\n};\n\nexport const useAccordionItemContext = (context: AccordionItemContext) => {\n\tconst [state, { setElementState, setActive }] = context;\n\n\tfunction expand() {\n\t\tconst index = untrack(() => state.index);\n\t\tsetActive(index);\n\t\tsetElementState(\"isExpanded\", true);\n\t}\n\n\tfunction collapse() {\n\t\tsetActive(-1);\n\t\tsetElementState(\"isExpanded\", false);\n\t}\n\n\tfunction toggle() {\n\t\tsetElementState(\"isExpanded\", (v) => {\n\t\t\tconst index = untrack(() => state.index);\n\t\t\tconst newValue = !v;\n\t\t\tif (newValue) setActive(index);\n\t\t\telse setActive(-1);\n\t\t\treturn newValue;\n\t\t});\n\t}\n\n\treturn [state, { expand, collapse, toggle }] as const;\n};\n\nexport const useAccordionItem = (element: HTMLElement & ICustomElement) => {\n\tconst context: AccordionItemContext = consume(\n\t\tAccordionItemContextState,\n\t\telement,\n\t);\n\n\tif (!context) {\n\t\tthrow new Error(\n\t\t\t\"AccordionItemContext not found! Please ensure to wrap your custom element with accordion-item element.\",\n\t\t);\n\t}\n\n\treturn useAccordionItemContext(context);\n};\n\nexport const useAccordionItemAt = createRemoteContext<AccordionItemContext>(\n\tAccordionItemContextState,\n);\n\nexport const getAccordionItemContext = (element: Element) => {\n\tconst context = getContextFromProvider<AccordionItemContext>(\n\t\tAccordionItemContextState,\n\t\telement,\n\t);\n\treturn useAccordionItemContext(context);\n};\n"],"mappings":";;;;;AAyBA,SAAS,+BAA+B,OAA6B;CAEpE,MAAM,aAAa,KAAK,OAAO,MAAM;CACrC,MAAM,CAAC,SAAS,WAAW,aAAa,MAAM,IAAI;CAGlD,MAAM,gBAAgB,cAAc,QAAQ,aAAa;CAEzD,SAAS,gBACR,KACA,OACC;EACD,MAAM,eAAe,cAAc,MAAM,IAAI;EAC7C,IAAI,OAAO,UAAU,YAAY;GAChC,IAAI,SAA2B;GAC/B,IAAI,OAAO,iBAAiB,UAC3B,SAAS,MAAM,gBAAgB,CAAC;QAC1B,IAAI,OAAO,iBAAiB,WAClC,SAAS,MAAM,gBAAgB,KAAK;GAOrC,IAAI,GAAG,mBAAmB,GAAG,UAAU;GACvC,MAAM,KAAK,aAAa,aAAa,GAAG,GAAG,GAAG,QAAQ;GACtD;EACD;EACA,IAAI,GAAG,mBAAmB,GAAG,SAAS;EACtC,OAAO,MAAM,KAAK,aAAa,aAAa,GAAG,GAAG,GAAG,OAAO;CAC7D;CAMA,IAAI,CAAC,eAAe;EACnB,0BACO,QAAQ,KAAK,SAAS,MAAM,KAAK,IACtC,UAAU,aAAa;GAQvB,IAAI,aAAa,KAAA,KAAa,cAAc,MAAM,UAAU,GAAG;GAC/D,gBAAgB,cAAc,QAAQ;EACvC,CACD;EAEA,0BACO,WAAW,aAChB,eAAe;GAKf,IAAI,YAAY,QAAQ,KAAK,OAAO,cAAc,WAAW,KAAK,CAAC;EACpE,CACD;CACD;CAEA,SAAS,UAAU,OAAe;EACjC,IAAI,CAAC,eAAe,QAAQ,KAAK,OAAO,KAAK;CAC9C;CAEA,OAAO,CACN,MAAM,YAAY,EACjB,IAAI,cAAc;EACjB,OAAO,QAAQ;CAChB,EACD,CAAC,GACD;EAAE;EAAiB;CAAU,CAC9B;AACD;AAEA,IAAM,4BAA4B,cAAc,8BAA8B;AAE9E,IAAa,+BACZ,cACA,YAC0B;CAC1B,MAAM,QAAQ,MAAM,cAAc,EAAE,MAAM,QAAQ,CAAC;CACnD,OAAO,QAAQ,2BAA2B,OAAO,OAAO;AACzD;AAEA,IAAa,2BAA2B,YAAkC;CACzE,MAAM,CAAC,OAAO,EAAE,iBAAiB,eAAe;CAEhD,SAAS,SAAS;EACjB,MAAM,QAAQ,cAAc,MAAM,KAAK;EACvC,UAAU,KAAK;EACf,gBAAgB,cAAc,IAAI;CACnC;CAEA,SAAS,WAAW;EACnB,UAAU,EAAE;EACZ,gBAAgB,cAAc,KAAK;CACpC;CAEA,SAAS,SAAS;EACjB,gBAAgB,eAAe,MAAM;GACpC,MAAM,QAAQ,cAAc,MAAM,KAAK;GACvC,MAAM,WAAW,CAAC;GAClB,IAAI,UAAU,UAAU,KAAK;QACxB,UAAU,EAAE;GACjB,OAAO;EACR,CAAC;CACF;CAEA,OAAO,CAAC,OAAO;EAAE;EAAQ;EAAU;CAAO,CAAC;AAC5C;AAEA,IAAa,oBAAoB,YAA0C;CAC1E,MAAM,UAAgC,QACrC,2BACA,OACD;CAEA,IAAI,CAAC,SACJ,MAAM,IAAI,MACT,wGACD;CAGD,OAAO,wBAAwB,OAAO;AACvC;AAEA,IAAa,qBAAqB,oBACjC,yBACD;AAEA,IAAa,2BAA2B,YAAqB;CAK5D,OAAO,wBAJS,uBACf,2BACA,OAE8B,CAAO;AACvC"}
@@ -2,6 +2,11 @@
2
2
 
3
3
  import { ICustomElement, provide } from 'component-register';
4
4
 
5
+ /**
6
+ * `component-register` types `options.element` as a bare `ICustomElement`, but
7
+ * at runtime it is always also an `HTMLElement`. Every component in this repo
8
+ * needs the DOM half.
9
+ */
5
10
  export type CorrectComponentOptions = {
6
11
  element: HTMLElement & ICustomElement;
7
12
  };
@@ -14,7 +19,6 @@ declare const Component: CorrectComponentType<Props>;
14
19
  type Props$1 = {
15
20
  index: number;
16
21
  isExpanded: boolean;
17
- ariaExpanded: boolean;
18
22
  };
19
23
  declare const Name$1 = "accordion-item";
20
24
  declare const Component$1: CorrectComponentType<Props$1>;
@@ -24,77 +28,109 @@ type Props$2 = {
24
28
  declare const Name$2 = "accordion-trigger";
25
29
  declare const Component$2: CorrectComponentType<Props$2>;
26
30
  export type StoreContext = {
27
- animationQueue: Promise<unknown>[];
31
+ /**
32
+ * Incremented once per find-in-page reveal, and never reset.
33
+ *
34
+ * A reveal has to open the matched item — and, without `allow-multiple`,
35
+ * close the one open in its place — *without* animating, so the layout is
36
+ * settled by the time the browser scrolls to the match. Solid 1 could
37
+ * express that as a boolean held across the write, because a write outside
38
+ * `batch()` flushed its effects synchronously: the content's effect ran
39
+ * inside `reveal()` and saw the flag still set. Solid 2 stages writes and
40
+ * flushes them together, so by the time the effect runs the flag would
41
+ * already be back to `false`.
42
+ *
43
+ * A counter does not depend on when the flush happens. Each content
44
+ * remembers the value it last ran at; a run whose value has moved was
45
+ * caused by a reveal, whenever it is flushed.
46
+ */
47
+ revealCount: number;
28
48
  };
29
49
  export type CreateContextOptions = {
30
50
  root: HTMLElement & ICustomElement;
31
51
  isAnimating: boolean;
32
52
  activeIndex: number;
53
+ allowMultiple: boolean;
33
54
  };
34
55
  export type WalkableNode = Parameters<typeof provide>[2];
35
56
  export type AccordionContext = ReturnType<typeof initializeAccordionContext>;
36
57
  declare function initializeAccordionContext(props: CreateContextOptions): readonly [
37
58
  {
38
- animationQueue: Promise<unknown>[];
59
+ revealCount: number;
39
60
  isAnimating: boolean;
40
61
  activeIndex: number;
62
+ allowMultiple: boolean;
63
+ readonly animationQueue: Promise<unknown>[];
41
64
  },
42
65
  {
43
66
  readonly setElementState: (key: keyof Omit<CreateContextOptions, "root">, value: boolean | number | ((v: boolean | number) => boolean | number)) => void;
44
- readonly setStore: import("solid-js/store").SetStoreFunction<StoreContext>;
67
+ readonly setStore: import("solid-js").StoreSetter<StoreContext>;
68
+ readonly setAnimationQueue: import("solid-js").Setter<Promise<unknown>[]>;
45
69
  }
46
70
  ];
47
71
  export declare const provideAccordionContext: (initialState: Omit<CreateContextOptions, "root">, element: WalkableNode) => AccordionContext;
48
72
  export declare const useAccordionContext: (context: AccordionContext) => readonly [
49
73
  {
50
- animationQueue: Promise<unknown>[];
74
+ revealCount: number;
51
75
  isAnimating: boolean;
52
76
  activeIndex: number;
77
+ allowMultiple: boolean;
78
+ readonly animationQueue: Promise<unknown>[];
53
79
  },
54
80
  {
55
81
  readonly updateAnimationQueue: (animation: Promise<unknown>) => void;
82
+ readonly reveal: (open: () => void) => void;
56
83
  readonly item: {
57
84
  readonly update: (index: number) => void;
58
- readonly isActive: (key: number) => boolean;
85
+ readonly isActive: (index: number) => boolean;
59
86
  };
60
87
  }
61
88
  ];
62
89
  export declare const useAccordion: (element: HTMLElement & ICustomElement) => readonly [
63
90
  {
64
- animationQueue: Promise<unknown>[];
91
+ revealCount: number;
65
92
  isAnimating: boolean;
66
93
  activeIndex: number;
94
+ allowMultiple: boolean;
95
+ readonly animationQueue: Promise<unknown>[];
67
96
  },
68
97
  {
69
98
  readonly updateAnimationQueue: (animation: Promise<unknown>) => void;
99
+ readonly reveal: (open: () => void) => void;
70
100
  readonly item: {
71
101
  readonly update: (index: number) => void;
72
- readonly isActive: (key: number) => boolean;
102
+ readonly isActive: (index: number) => boolean;
73
103
  };
74
104
  }
75
105
  ];
76
- export declare const withAccordionElementContext: <D extends unknown>(target: string | import("solid-js").Accessor<string> | import("solid-js").Accessor<() => Element>, dependencies: import("solid-js").Accessor<D> | undefined, cb: (context: readonly [
106
+ export declare const useAccordionAt: (target: () => string | undefined, host: HTMLElement) => import("solid-js").SourceAccessor<readonly [
77
107
  {
78
- animationQueue: Promise<unknown>[];
108
+ revealCount: number;
79
109
  isAnimating: boolean;
80
110
  activeIndex: number;
111
+ allowMultiple: boolean;
112
+ readonly animationQueue: Promise<unknown>[];
81
113
  },
82
114
  {
83
115
  readonly setElementState: (key: keyof Omit<CreateContextOptions, "root">, value: boolean | number | ((v: boolean | number) => boolean | number)) => void;
84
- readonly setStore: import("solid-js/store").SetStoreFunction<StoreContext>;
116
+ readonly setStore: import("solid-js").StoreSetter<StoreContext>;
117
+ readonly setAnimationQueue: import("solid-js").Setter<Promise<unknown>[]>;
85
118
  }
86
- ], dependencies: D) => void | (() => void)) => void;
119
+ ]>;
87
120
  export declare const getAccordionContext: (element: Element) => readonly [
88
121
  {
89
- animationQueue: Promise<unknown>[];
122
+ revealCount: number;
90
123
  isAnimating: boolean;
91
124
  activeIndex: number;
125
+ allowMultiple: boolean;
126
+ readonly animationQueue: Promise<unknown>[];
92
127
  },
93
128
  {
94
129
  readonly updateAnimationQueue: (animation: Promise<unknown>) => void;
130
+ readonly reveal: (open: () => void) => void;
95
131
  readonly item: {
96
132
  readonly update: (index: number) => void;
97
- readonly isActive: (key: number) => boolean;
133
+ readonly isActive: (index: number) => boolean;
98
134
  };
99
135
  }
100
136
  ];
@@ -102,7 +138,6 @@ type CreateContextOptions$1 = {
102
138
  root: HTMLElement & ICustomElement;
103
139
  isExpanded: boolean;
104
140
  index: number;
105
- ariaExpanded: boolean;
106
141
  };
107
142
  type WalkableNode$1 = Parameters<typeof provide>[2];
108
143
  export type AccordionItemContext = ReturnType<typeof initializeAccordionItemContext>;
@@ -142,7 +177,7 @@ export declare const useAccordionItem: (element: HTMLElement & ICustomElement) =
142
177
  readonly toggle: () => void;
143
178
  }
144
179
  ];
145
- export declare const withAccordionItemElementContext: <D extends unknown>(target: string | import("solid-js").Accessor<string> | import("solid-js").Accessor<() => Element>, dependencies: import("solid-js").Accessor<D> | undefined, cb: (context: readonly [
180
+ export declare const useAccordionItemAt: (target: () => string | undefined, host: HTMLElement) => import("solid-js").SourceAccessor<readonly [
146
181
  {
147
182
  isExpanded: boolean;
148
183
  index: number;
@@ -152,7 +187,7 @@ export declare const withAccordionItemElementContext: <D extends unknown>(target
152
187
  readonly setElementState: (key: keyof Omit<CreateContextOptions$1, "root">, value: boolean | number | ((v: boolean | number) => boolean | number)) => void;
153
188
  readonly setActive: (index: number) => void;
154
189
  }
155
- ], dependencies: D) => void | (() => void)) => void;
190
+ ]>;
156
191
  export declare const getAccordionItemContext: (element: Element) => readonly [
157
192
  {
158
193
  isExpanded: boolean;
@@ -1,26 +1,25 @@
1
- import { customShadowlessElement, correctElementType } from '@brytdesigns/web-component-core/utils';
2
- import { AccordionContext, AccordionItem, AccordionTrigger, AccordionContent } from './components/index.js';
3
- export * from './hooks/index.js';
1
+ import { getAccordionContext, provideAccordionContext, useAccordion, useAccordionAt, useAccordionContext } from "./hooks/useAccordion.js";
2
+ import { getAccordionItemContext, provideAccordionItemContext, useAccordionItem, useAccordionItemAt, useAccordionItemContext } from "./hooks/useAccordionItem.js";
3
+ import "./hooks/index.js";
4
+ import { Component, Name } from "./components/accordion-content.js";
5
+ import { Component as Component$1, Name as Name$1 } from "./components/accordion-context.js";
6
+ import { Component as Component$2, Name as Name$2 } from "./components/accordion-item.js";
7
+ import { Component as Component$3, Name as Name$3 } from "./components/accordion-trigger.js";
8
+ import "./components/index.js";
9
+ import { customShadowlessElement } from "@brytdesigns/web-component-core/utils";
10
+ //#region src/index.ts
11
+ customShadowlessElement(Name$1, {
12
+ activeIndex: -1,
13
+ isAnimating: false,
14
+ allowMultiple: false
15
+ }, Component$1);
16
+ customShadowlessElement(Name$2, {
17
+ index: 0,
18
+ isExpanded: false
19
+ }, Component$2);
20
+ customShadowlessElement(Name$3, { preventDefault: true }, Component$3);
21
+ customShadowlessElement(Name, { shouldScrollIntoView: false }, Component);
22
+ //#endregion
23
+ export { getAccordionContext, getAccordionItemContext, provideAccordionContext, provideAccordionItemContext, useAccordion, useAccordionAt, useAccordionContext, useAccordionItem, useAccordionItemAt, useAccordionItemContext };
4
24
 
5
- customShadowlessElement(
6
- AccordionContext.Name,
7
- { activeIndex: -1, isAnimating: false },
8
- correctElementType(AccordionContext.Component)
9
- );
10
- customShadowlessElement(
11
- AccordionItem.Name,
12
- { index: 0, isExpanded: false, ariaExpanded: false },
13
- correctElementType(AccordionItem.Component)
14
- );
15
- customShadowlessElement(
16
- AccordionTrigger.Name,
17
- { preventDefault: true },
18
- correctElementType(AccordionTrigger.Component)
19
- );
20
- customShadowlessElement(
21
- AccordionContent.Name,
22
- { shouldScrollIntoView: false },
23
- correctElementType(AccordionContent.Component)
24
- );
25
- //# sourceMappingURL=index.js.map
26
25
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.ts"],"names":[],"mappings":";;;;AAiBA,uBAAA;AAAA,EACE,gBAAiB,CAAA,IAAA;AAAA,EACjB,EAAE,WAAA,EAAa,EAAI,EAAA,WAAA,EAAa,KAAM,EAAA;AAAA,EACtC,kBAAA,CAAmB,iBAAiB,SAAS;AAC/C,CAAA;AAEA,uBAAA;AAAA,EACE,aAAc,CAAA,IAAA;AAAA,EACd,EAAE,KAAO,EAAA,CAAA,EAAG,UAAY,EAAA,KAAA,EAAO,cAAc,KAAM,EAAA;AAAA,EACnD,kBAAA,CAAmB,cAAc,SAAS;AAC5C,CAAA;AAEA,uBAAA;AAAA,EACE,gBAAiB,CAAA,IAAA;AAAA,EACjB,EAAE,gBAAgB,IAAK,EAAA;AAAA,EACvB,kBAAA,CAAmB,iBAAiB,SAAS;AAC/C,CAAA;AAEA,uBAAA;AAAA,EACE,gBAAiB,CAAA,IAAA;AAAA,EACjB,EAAE,sBAAsB,KAAM,EAAA;AAAA,EAC9B,kBAAA,CAAmB,iBAAiB,SAAS;AAC/C,CAAA","file":"index.js","sourcesContent":["import {\n customShadowlessElement,\n correctElementType,\n} from \"@brytdesigns/web-component-core/utils\";\n\nimport {\n AccordionContext,\n AccordionItem,\n AccordionContent,\n AccordionTrigger,\n} from \"./components/index.js\";\n\nexport type AccordionContextProps = AccordionContent.Props;\nexport type AccordionItemProps = AccordionItem.Props;\nexport type AccordionTriggerProps = AccordionTrigger.Props;\nexport type AccordionContentProps = AccordionContent.Props;\n\ncustomShadowlessElement(\n AccordionContext.Name,\n { activeIndex: -1, isAnimating: false },\n correctElementType(AccordionContext.Component),\n);\n\ncustomShadowlessElement(\n AccordionItem.Name,\n { index: 0, isExpanded: false, ariaExpanded: false },\n correctElementType(AccordionItem.Component),\n);\n\ncustomShadowlessElement(\n AccordionTrigger.Name,\n { preventDefault: true },\n correctElementType(AccordionTrigger.Component),\n);\n\ncustomShadowlessElement(\n AccordionContent.Name,\n { shouldScrollIntoView: false },\n correctElementType(AccordionContent.Component),\n);\n\nexport * from \"./hooks/index.js\";\n"]}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/index.ts"],"sourcesContent":["import { customShadowlessElement } from \"@brytdesigns/web-component-core/utils\";\n\nimport {\n\tAccordionContent,\n\tAccordionContext,\n\tAccordionItem,\n\tAccordionTrigger,\n} from \"./components/index.js\";\n\nexport type AccordionContextProps = AccordionContent.Props;\nexport type AccordionItemProps = AccordionItem.Props;\nexport type AccordionTriggerProps = AccordionTrigger.Props;\nexport type AccordionContentProps = AccordionContent.Props;\n\ncustomShadowlessElement(\n\tAccordionContext.Name,\n\t{ activeIndex: -1, isAnimating: false, allowMultiple: false },\n\tAccordionContext.Component,\n);\n\ncustomShadowlessElement(\n\tAccordionItem.Name,\n\t{ index: 0, isExpanded: false },\n\tAccordionItem.Component,\n);\n\ncustomShadowlessElement(\n\tAccordionTrigger.Name,\n\t{ preventDefault: true },\n\tAccordionTrigger.Component,\n);\n\ncustomShadowlessElement(\n\tAccordionContent.Name,\n\t{ shouldScrollIntoView: false },\n\tAccordionContent.Component,\n);\n\nexport * from \"./hooks/index.js\";\n"],"mappings":";;;;;;;;;;AAcA,wBACC,QACA;CAAE,aAAa;CAAI,aAAa;CAAO,eAAe;AAAM,GAC5D,WACD;AAEA,wBACC,QACA;CAAE,OAAO;CAAG,YAAY;AAAM,GAC9B,WACD;AAEA,wBACC,QACA,EAAE,gBAAgB,KAAK,GACvB,WACD;AAEA,wBACC,MACA,EAAE,sBAAsB,MAAM,GAC9B,SACD"}
@@ -0,0 +1,35 @@
1
+ /*
2
+ * accordion-content is a flow-root once the component starts, open or closed.
3
+ * Making it one from the first paint stops open content shifting (its padding
4
+ * and margins taking effect) when the script loads. Theme rules override this.
5
+ *
6
+ * flow-root rather than block: it establishes a block formatting context, so
7
+ * the panel contains its children's margins. The component applies the same,
8
+ * and the two must agree or the content shifts on load — which is the whole
9
+ * point of this rule.
10
+ */
11
+ accordion-content {
12
+ display: flow-root;
13
+ }
14
+
15
+ /*
16
+ * Closed accordion content before the component starts.
17
+ *
18
+ * Render closed content with hidden="until-found" and load this stylesheet
19
+ * before the markup, so it does not flash open while the script loads.
20
+ *
21
+ * - display: flow-root lets hidden="until-found" hide the content (it works
22
+ * through content-visibility, which does not apply to an inline box, and
23
+ * custom elements are inline by default). Where it is supported, the text
24
+ * stays reachable by find-in-page.
25
+ * - The rest keeps the content collapsed where hidden="until-found" is not
26
+ * supported, or where theme CSS overrides the browser's [hidden] style.
27
+ *
28
+ * Once the component starts it manages the closed state itself.
29
+ */
30
+ accordion-content[hidden] {
31
+ display: flow-root;
32
+ overflow: hidden;
33
+ max-height: 0;
34
+ padding-block: 0;
35
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brytdesigns/web-component-accordion",
3
- "version": "1.1.8",
3
+ "version": "3.0.0",
4
4
  "description": "Headless accordion web component",
5
5
  "main": "./dist/main/index.js",
6
6
  "module": "./dist/main/index.js",
@@ -9,8 +9,9 @@
9
9
  "exports": {
10
10
  ".": {
11
11
  "types": "./dist/main/index.d.ts",
12
- "module": "./dist/main/index.js"
13
- }
12
+ "default": "./dist/main/index.js"
13
+ },
14
+ "./styles.css": "./dist/styles.css"
14
15
  },
15
16
  "files": [
16
17
  "dist"
@@ -19,18 +20,17 @@
19
20
  "author": "Bryt Designs",
20
21
  "license": "ISC",
21
22
  "dependencies": {
23
+ "@brytdesigns/web-component-core": "3.0.0",
22
24
  "component-register": "0.8.7",
23
- "motion": "^12.40.0",
24
- "solid-element": "^1.9.1",
25
- "solid-js": "^1.9.9",
26
- "@brytdesigns/web-component-core": "1.1.7"
25
+ "motion": "^12.43.0",
26
+ "solid-js": "2.0.0-rc.14"
27
27
  },
28
28
  "devDependencies": {
29
- "dts-bundle-generator": "^9.5.1",
30
- "tsup": "^8.4.0"
29
+ "@repo/vite-config": "0.0.0",
30
+ "vite": "^8.2.2"
31
31
  },
32
32
  "scripts": {
33
- "build": "tsup --clean",
33
+ "build": "vite build",
34
34
  "typecheck": "tsc --noEmit"
35
35
  }
36
36
  }