@brytdesigns/shopify-product-info-components 1.1.10 → 3.1.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,12 +1,5 @@
1
- import * as productInfo_js from './product-info.js';
2
- export { productInfo_js as ProductInfo };
3
- import * as productVariantRender_js from './product-variant-render.js';
4
- export { productVariantRender_js as ProductVariantRender };
5
- import * as productOptions_js from './product-options.js';
6
- export { productOptions_js as ProductOptions };
7
- import * as productOptionGroup_js from './product-option-group.js';
8
- export { productOptionGroup_js as ProductOptionGroup };
9
- import * as productVariantInput_js from './product-variant-input.js';
10
- export { productVariantInput_js as ProductVariantInput };
11
- //# sourceMappingURL=index.js.map
12
- //# sourceMappingURL=index.js.map
1
+ import "./product-info.js";
2
+ import "./product-option-group.js";
3
+ import "./product-options.js";
4
+ import "./product-variant-input.js";
5
+ import "./product-variant-render.js";
@@ -1,39 +1,58 @@
1
- import { createMemo, createEffect, observable } from 'solid-js';
2
- import { provideProductContext } from '../hooks/index.js';
3
-
4
- const Name = `product-info`;
5
- const Component = (props, { element }) => {
6
- if (!props.product)
7
- return console.warn(`${Name}: product attribute is required`);
8
- if (!props.product.variants)
9
- return console.warn(`${Name}: product attribute needs variants array`);
10
- if (!props.product.selected_or_first_available_variant)
11
- return console.warn(
12
- `${Name}: product attribute needs selected or first available variant object`
13
- );
14
- provideProductContext(props, element);
15
- const url = createMemo(() => {
16
- const url2 = new URL(window.location.href);
17
- const variant = props?.product?.selected_or_first_available_variant;
18
- if (props.product && variant && variant?.id) {
19
- url2.searchParams.set("variant", variant.id.toString());
20
- } else {
21
- url2.searchParams.delete("variant");
22
- }
23
- return url2;
24
- });
25
- function subscribe(cb) {
26
- return observable(() => props.product).subscribe(cb).unsubscribe;
27
- }
28
- Object.assign(element, {
29
- subscribe
30
- });
31
- createEffect(() => {
32
- if (!props.isProductPage) return;
33
- window.history.replaceState(null, "", url());
34
- });
1
+ import { provideProductContext } from "../hooks/useProduct.js";
2
+ import "../hooks/index.js";
3
+ import { announce, createGuardedEffect } from "@brytdesigns/web-component-core/utils";
4
+ import { createMemo, createRoot, untrack } from "solid-js";
5
+ //#region src/components/product-info.ts
6
+ var Name = `product-info`;
7
+ var Component = (props, { element }) => {
8
+ const product = untrack(() => props.product);
9
+ if (!product) return console.warn(`${Name}: product attribute is required`);
10
+ if (!product.variants) return console.warn(`${Name}: product attribute needs variants array`);
11
+ if (!product.selected_or_first_available_variant) return console.warn(`${Name}: product attribute needs selected or first available variant object`);
12
+ provideProductContext(props, element);
13
+ const url = createMemo(() => {
14
+ const url = new URL(window.location.href);
15
+ const variant = props?.product?.selected_or_first_available_variant;
16
+ if (props.product && variant && variant?.id) url.searchParams.set("variant", variant.id.toString());
17
+ else url.searchParams.delete("variant");
18
+ return url;
19
+ });
20
+ function subscribe(cb) {
21
+ return createRoot((dispose) => {
22
+ createGuardedEffect(() => props.product, (product) => cb(product));
23
+ return dispose;
24
+ });
25
+ }
26
+ Object.assign(element, { subscribe });
27
+ /**
28
+ * Choosing a variant rewrites price, availability and whatever else the
29
+ * theme renders from it — silently, as far as assistive tech is concerned.
30
+ *
31
+ * The radio or select announces its own new value, because it is a native
32
+ * control doing its job. Nothing announces what that selection *did*, which
33
+ * is the part a shopper actually needs: an option that turned out to be
34
+ * sold out reads identically to one that did not.
35
+ */
36
+ createGuardedEffect(() => props.product?.selected_or_first_available_variant, (variant, previous) => {
37
+ if (previous === void 0 || !variant) return;
38
+ if (previous && previous.id === variant.id) return;
39
+ const described = variant.title ?? variant.options.join(", ");
40
+ const { availableLabel, unavailableLabel } = untrack(() => ({
41
+ availableLabel: props.availableLabel,
42
+ unavailableLabel: props.unavailableLabel
43
+ }));
44
+ const availability = typeof variant.available === "boolean" ? variant.available ? availableLabel : unavailableLabel : "";
45
+ announce([described, availability].filter(Boolean).join(". "));
46
+ });
47
+ createGuardedEffect(() => ({
48
+ isProductPage: props.isProductPage,
49
+ url: url()
50
+ }), ({ isProductPage, url }) => {
51
+ if (!isProductPage) return;
52
+ window.history.replaceState(null, "", url);
53
+ });
35
54
  };
36
-
55
+ //#endregion
37
56
  export { Component, Name };
38
- //# sourceMappingURL=product-info.js.map
57
+
39
58
  //# sourceMappingURL=product-info.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/product-info.ts"],"names":["url"],"mappings":";;;AAaO,MAAM,IAAO,GAAA,CAAA,YAAA;AAEb,MAAM,SAAyC,GAAA,CAAC,KAAO,EAAA,EAAE,SAAc,KAAA;AAC5E,EAAA,IAAI,CAAC,KAAM,CAAA,OAAA;AACT,IAAA,OAAO,OAAQ,CAAA,IAAA,CAAK,CAAG,EAAA,IAAI,CAAiC,+BAAA,CAAA,CAAA;AAC9D,EAAI,IAAA,CAAC,MAAM,OAAQ,CAAA,QAAA;AACjB,IAAA,OAAO,OAAQ,CAAA,IAAA,CAAK,CAAG,EAAA,IAAI,CAA0C,wCAAA,CAAA,CAAA;AACvE,EAAI,IAAA,CAAC,MAAM,OAAQ,CAAA,mCAAA;AACjB,IAAA,OAAO,OAAQ,CAAA,IAAA;AAAA,MACb,GAAG,IAAI,CAAA,oEAAA;AAAA,KACT;AACF,EAAA,qBAAA,CAAsB,OAAc,OAAO,CAAA;AAE3C,EAAM,MAAA,GAAA,GAAM,WAAW,MAAM;AAC3B,IAAA,MAAMA,IAAM,GAAA,IAAI,GAAI,CAAA,MAAA,CAAO,SAAS,IAAI,CAAA;AACxC,IAAM,MAAA,OAAA,GAAU,OAAO,OAAS,EAAA,mCAAA;AAChC,IAAA,IAAI,KAAM,CAAA,OAAA,IAAW,OAAW,IAAA,OAAA,EAAS,EAAI,EAAA;AAC3C,MAAAA,KAAI,YAAa,CAAA,GAAA,CAAI,WAAW,OAAQ,CAAA,EAAA,CAAG,UAAU,CAAA;AAAA,KAChD,MAAA;AACL,MAAAA,IAAAA,CAAI,YAAa,CAAA,MAAA,CAAO,SAAS,CAAA;AAAA;AAEnC,IAAOA,OAAAA,IAAAA;AAAA,GACR,CAAA;AAED,EAAA,SAAS,UAAU,EAA4C,EAAA;AAC7D,IAAA,OAAO,WAAW,MAAM,KAAA,CAAM,OAAO,CAAE,CAAA,SAAA,CAAU,EAAE,CAAE,CAAA,WAAA;AAAA;AAGvD,EAAA,MAAA,CAAO,OAAO,OAAS,EAAA;AAAA,IACrB;AAAA,GACD,CAAA;AAED,EAAA,YAAA,CAAa,MAAM;AACjB,IAAI,IAAA,CAAC,MAAM,aAAe,EAAA;AAC1B,IAAA,MAAA,CAAO,OAAQ,CAAA,YAAA,CAAa,IAAM,EAAA,EAAA,EAAI,KAAK,CAAA;AAAA,GAC5C,CAAA;AACH","file":"product-info.js","sourcesContent":["import type { CorrectComponentType } from \"@brytdesigns/web-component-core/utils\";\n\nimport { createEffect, createMemo, observable } from \"solid-js\";\n\nimport { provideProductContext } from \"../hooks/index.js\";\n\nimport type { Product } from \"../types.js\";\n\nexport type Props = {\n product?: Product;\n isProductPage?: boolean;\n};\n\nexport const Name = `product-info`;\n\nexport const Component: CorrectComponentType<Props> = (props, { element }) => {\n if (!props.product)\n return console.warn(`${Name}: product attribute is required`);\n if (!props.product.variants)\n return console.warn(`${Name}: product attribute needs variants array`);\n if (!props.product.selected_or_first_available_variant)\n return console.warn(\n `${Name}: product attribute needs selected or first available variant object`,\n );\n provideProductContext(props as any, element);\n\n const url = createMemo(() => {\n const url = new URL(window.location.href);\n const variant = props?.product?.selected_or_first_available_variant;\n if (props.product && variant && variant?.id) {\n url.searchParams.set(\"variant\", variant.id.toString());\n } else {\n url.searchParams.delete(\"variant\");\n }\n return url;\n });\n\n function subscribe(cb: (product: Product | undefined) => void) {\n return observable(() => props.product).subscribe(cb).unsubscribe;\n }\n\n Object.assign(element, {\n subscribe,\n });\n\n createEffect(() => {\n if (!props.isProductPage) return;\n window.history.replaceState(null, \"\", url());\n });\n};\n"]}
1
+ {"version":3,"file":"product-info.js","names":[],"sources":["../../../src/components/product-info.ts"],"sourcesContent":["import {\n\tannounce,\n\ttype CorrectComponentType,\n\tcreateGuardedEffect,\n} from \"@brytdesigns/web-component-core/utils\";\n\nimport { createMemo, createRoot, untrack } from \"solid-js\";\n\nimport { provideProductContext } from \"../hooks/index.js\";\n\nimport type { Product } from \"../types.js\";\n\nexport type Props = {\n\tproduct?: Product;\n\tisProductPage?: boolean;\n\t/** Appended to the announcement when the chosen variant is in stock. */\n\tavailableLabel: string;\n\t/** Appended when it is not. */\n\tunavailableLabel: string;\n};\n\nexport const Name = `product-info`;\n\nexport const Component: CorrectComponentType<Props> = (props, { element }) => {\n\t// One-time validation of the mounting attributes. Read into a local so the\n\t// snapshot is explicit and TypeScript can narrow it — an `untrack` closure\n\t// around each check would defeat narrowing.\n\tconst product = untrack(() => props.product);\n\tif (!product) return console.warn(`${Name}: product attribute is required`);\n\tif (!product.variants)\n\t\treturn console.warn(`${Name}: product attribute needs variants array`);\n\tif (!product.selected_or_first_available_variant)\n\t\treturn console.warn(\n\t\t\t`${Name}: product attribute needs selected or first available variant object`,\n\t\t);\n\tprovideProductContext(props as any, element);\n\n\tconst url = createMemo(() => {\n\t\tconst url = new URL(window.location.href);\n\t\tconst variant = props?.product?.selected_or_first_available_variant;\n\t\tif (props.product && variant && variant?.id) {\n\t\t\turl.searchParams.set(\"variant\", variant.id.toString());\n\t\t} else {\n\t\t\turl.searchParams.delete(\"variant\");\n\t\t}\n\t\treturn url;\n\t});\n\n\tfunction subscribe(cb: (product: Product | undefined) => void) {\n\t\t// `observable` is gone in v2; pushing a signal out to an external\n\t\t// subscriber is an effect in its own root, with the disposer as the\n\t\t// unsubscribe. The public signature is unchanged.\n\t\treturn createRoot((dispose) => {\n\t\t\tcreateGuardedEffect(\n\t\t\t\t() => props.product,\n\t\t\t\t(product) => cb(product),\n\t\t\t);\n\t\t\treturn dispose;\n\t\t});\n\t}\n\n\tObject.assign(element, {\n\t\tsubscribe,\n\t});\n\n\t/**\n\t * Choosing a variant rewrites price, availability and whatever else the\n\t * theme renders from it — silently, as far as assistive tech is concerned.\n\t *\n\t * The radio or select announces its own new value, because it is a native\n\t * control doing its job. Nothing announces what that selection *did*, which\n\t * is the part a shopper actually needs: an option that turned out to be\n\t * sold out reads identically to one that did not.\n\t */\n\tcreateGuardedEffect(\n\t\t() => props.product?.selected_or_first_available_variant,\n\t\t(variant, previous) => {\n\t\t\t// Silent on the first run. The page has only just loaded and the\n\t\t\t// reader is about to encounter all of this in order anyway.\n\t\t\tif (previous === undefined || !variant) return;\n\t\t\tif (previous && previous.id === variant.id) return;\n\n\t\t\tconst described = variant.title ?? variant.options.join(\", \");\n\t\t\t// Read when the announcement is made, deliberately: the labels are\n\t\t\t// copy, and the current wording is the right wording. `untrack`\n\t\t\t// states that — the apply phase is not a tracking scope, so a bare\n\t\t\t// read here is one Solid reports and nobody has reviewed.\n\t\t\tconst { availableLabel, unavailableLabel } = untrack(() => ({\n\t\t\t\tavailableLabel: props.availableLabel,\n\t\t\t\tunavailableLabel: props.unavailableLabel,\n\t\t\t}));\n\t\t\tconst availability =\n\t\t\t\ttypeof variant.available === \"boolean\"\n\t\t\t\t\t? variant.available\n\t\t\t\t\t\t? availableLabel\n\t\t\t\t\t\t: unavailableLabel\n\t\t\t\t\t: \"\";\n\t\t\tannounce([described, availability].filter(Boolean).join(\". \"));\n\t\t},\n\t);\n\n\tcreateGuardedEffect(\n\t\t() => ({ isProductPage: props.isProductPage, url: url() }),\n\t\t({ isProductPage, url }) => {\n\t\t\tif (!isProductPage) return;\n\t\t\twindow.history.replaceState(null, \"\", url);\n\t\t},\n\t);\n};\n"],"mappings":";;;;;AAqBA,IAAa,OAAO;AAEpB,IAAa,aAA0C,OAAO,EAAE,cAAc;CAI7E,MAAM,UAAU,cAAc,MAAM,OAAO;CAC3C,IAAI,CAAC,SAAS,OAAO,QAAQ,KAAK,GAAG,KAAK,gCAAgC;CAC1E,IAAI,CAAC,QAAQ,UACZ,OAAO,QAAQ,KAAK,GAAG,KAAK,yCAAyC;CACtE,IAAI,CAAC,QAAQ,qCACZ,OAAO,QAAQ,KACd,GAAG,KAAK,qEACT;CACD,sBAAsB,OAAc,OAAO;CAE3C,MAAM,MAAM,iBAAiB;EAC5B,MAAM,MAAM,IAAI,IAAI,OAAO,SAAS,IAAI;EACxC,MAAM,UAAU,OAAO,SAAS;EAChC,IAAI,MAAM,WAAW,WAAW,SAAS,IACxC,IAAI,aAAa,IAAI,WAAW,QAAQ,GAAG,SAAS,CAAC;OAErD,IAAI,aAAa,OAAO,SAAS;EAElC,OAAO;CACR,CAAC;CAED,SAAS,UAAU,IAA4C;EAI9D,OAAO,YAAY,YAAY;GAC9B,0BACO,MAAM,UACX,YAAY,GAAG,OAAO,CACxB;GACA,OAAO;EACR,CAAC;CACF;CAEA,OAAO,OAAO,SAAS,EACtB,UACD,CAAC;;;;;;;;;;CAWD,0BACO,MAAM,SAAS,sCACpB,SAAS,aAAa;EAGtB,IAAI,aAAa,KAAA,KAAa,CAAC,SAAS;EACxC,IAAI,YAAY,SAAS,OAAO,QAAQ,IAAI;EAE5C,MAAM,YAAY,QAAQ,SAAS,QAAQ,QAAQ,KAAK,IAAI;EAK5D,MAAM,EAAE,gBAAgB,qBAAqB,eAAe;GAC3D,gBAAgB,MAAM;GACtB,kBAAkB,MAAM;EACzB,EAAE;EACF,MAAM,eACL,OAAO,QAAQ,cAAc,YAC1B,QAAQ,YACP,iBACA,mBACD;EACJ,SAAS,CAAC,WAAW,YAAY,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,IAAI,CAAC;CAC9D,CACD;CAEA,2BACQ;EAAE,eAAe,MAAM;EAAe,KAAK,IAAI;CAAE,KACvD,EAAE,eAAe,UAAU;EAC3B,IAAI,CAAC,eAAe;EACpB,OAAO,QAAQ,aAAa,MAAM,IAAI,GAAG;CAC1C,CACD;AACD"}
@@ -1,69 +1,56 @@
1
- import { createEffect, on, onCleanup } from 'solid-js';
2
- import { useProductOptions } from '../hooks/index.js';
3
-
4
- const Name = `product-option-group`;
5
- const Component = (props, { element }) => {
6
- const [context, methods] = useProductOptions(element);
7
- createEffect(
8
- on(
9
- () => ({
10
- selectedOption: context.selectedOptions[props.position - 1],
11
- position: props.position,
12
- name: props.name,
13
- inputType: props.inputType
14
- }),
15
- ({ selectedOption, position, name, inputType }) => {
16
- if (inputType !== "radio" && inputType !== "select") return;
17
- const optionName = `${name}-${position}`;
18
- if (inputType === "radio") {
19
- const inputs = element.querySelectorAll(
20
- `input[name="${optionName}"]`
21
- );
22
- inputs.forEach((input) => {
23
- const prevValue = input.checked;
24
- if (input.value === selectedOption) input.checked = true;
25
- else input.checked = false;
26
- if (prevValue !== input.checked) {
27
- input.dispatchEvent(new Event("change", { bubbles: true }));
28
- }
29
- });
30
- return;
31
- }
32
- const select = element.querySelector(
33
- `select[name="${optionName}"]`
34
- );
35
- if (!select || !selectedOption) return;
36
- select.value = selectedOption;
37
- select.dispatchEvent(new Event("change", { bubbles: true }));
38
- }
39
- )
40
- );
41
- createEffect(() => {
42
- const position = props.position;
43
- function handleChange(event) {
44
- const target = event.target;
45
- if (!target) return;
46
- const selectedOption = target.value;
47
- if (context.selectedOptions[position - 1] === selectedOption) return;
48
- element.dispatchEvent(
49
- new CustomEvent("option-updated", {
50
- detail: {
51
- group: props.name,
52
- position,
53
- selectedOption
54
- },
55
- bubbles: true
56
- })
57
- );
58
- methods.options.updateOption(selectedOption, position - 1);
59
- }
60
- element.addEventListener("change", handleChange);
61
- return onCleanup(() => {
62
- element.removeEventListener("change", handleChange);
63
- });
64
- });
1
+ import { useProductOptions } from "../hooks/useProductOptions.js";
2
+ import "../hooks/index.js";
3
+ import { createGuardedEffect } from "@brytdesigns/web-component-core/utils";
4
+ //#region src/components/product-option-group.ts
5
+ var Name = `product-option-group`;
6
+ var Component = (props, { element }) => {
7
+ const [context, methods] = useProductOptions(element);
8
+ createGuardedEffect(() => ({
9
+ selectedOption: context.selectedOptions[props.position - 1],
10
+ position: props.position,
11
+ name: props.name,
12
+ inputType: props.inputType
13
+ }), ({ selectedOption, position, name, inputType }) => {
14
+ if (inputType !== "radio" && inputType !== "select") return;
15
+ const optionName = `${name}-${position}`;
16
+ if (inputType === "radio") {
17
+ element.querySelectorAll(`input[name="${optionName}"]`).forEach((input) => {
18
+ const prevValue = input.checked;
19
+ if (input.value === selectedOption) input.checked = true;
20
+ else input.checked = false;
21
+ if (prevValue !== input.checked && input.checked) input.dispatchEvent(new Event("change", { bubbles: true }));
22
+ });
23
+ return;
24
+ }
25
+ const select = element.querySelector(`select[name="${optionName}"]`);
26
+ if (!select || !selectedOption) return;
27
+ select.value = selectedOption;
28
+ select.dispatchEvent(new Event("change", { bubbles: true }));
29
+ });
30
+ createGuardedEffect(() => props.position, (position) => {
31
+ function handleChange(event) {
32
+ const target = event.target;
33
+ if (!target) return;
34
+ if (target.type === "radio" && !target.checked) return;
35
+ const selectedOption = target.value;
36
+ if (context.selectedOptions[position - 1] === selectedOption) return;
37
+ element.dispatchEvent(new CustomEvent("option-updated", {
38
+ detail: {
39
+ group: props.name,
40
+ position,
41
+ selectedOption
42
+ },
43
+ bubbles: true
44
+ }));
45
+ methods.options.updateOption(selectedOption, position - 1);
46
+ }
47
+ element.addEventListener("change", handleChange);
48
+ return () => {
49
+ element.removeEventListener("change", handleChange);
50
+ };
51
+ });
65
52
  };
66
-
53
+ //#endregion
67
54
  export { Component, Name };
68
- //# sourceMappingURL=product-option-group.js.map
55
+
69
56
  //# sourceMappingURL=product-option-group.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/product-option-group.ts"],"names":[],"mappings":";;;AAYO,MAAM,IAAO,GAAA,CAAA,oBAAA;AAEb,MAAM,SAAyC,GAAA,CAAC,KAAO,EAAA,EAAE,SAAc,KAAA;AAC5E,EAAA,MAAM,CAAC,OAAA,EAAS,OAAO,CAAA,GAAI,kBAAkB,OAAO,CAAA;AAEpD,EAAA,YAAA;AAAA,IACE,EAAA;AAAA,MACE,OAAO;AAAA,QACL,cAAgB,EAAA,OAAA,CAAQ,eAAgB,CAAA,KAAA,CAAM,WAAW,CAAC,CAAA;AAAA,QAC1D,UAAU,KAAM,CAAA,QAAA;AAAA,QAChB,MAAM,KAAM,CAAA,IAAA;AAAA,QACZ,WAAW,KAAM,CAAA;AAAA,OACnB,CAAA;AAAA,MACA,CAAC,EAAE,cAAA,EAAgB,QAAU,EAAA,IAAA,EAAM,WAAgB,KAAA;AACjD,QAAI,IAAA,SAAA,KAAc,OAAW,IAAA,SAAA,KAAc,QAAU,EAAA;AAErD,QAAA,MAAM,UAAa,GAAA,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAA;AAEtC,QAAA,IAAI,cAAc,OAAS,EAAA;AACzB,UAAA,MAAM,SAAS,OAAQ,CAAA,gBAAA;AAAA,YACrB,eAAe,UAAU,CAAA,EAAA;AAAA,WAC3B;AACA,UAAO,MAAA,CAAA,OAAA,CAAQ,CAAC,KAAU,KAAA;AACxB,YAAA,MAAM,YAAY,KAAM,CAAA,OAAA;AACxB,YAAA,IAAI,KAAM,CAAA,KAAA,KAAU,cAAgB,EAAA,KAAA,CAAM,OAAU,GAAA,IAAA;AAAA,uBACzC,OAAU,GAAA,KAAA;AACrB,YAAI,IAAA,SAAA,KAAc,MAAM,OAAS,EAAA;AAC/B,cAAM,KAAA,CAAA,aAAA,CAAc,IAAI,KAAM,CAAA,QAAA,EAAU,EAAE,OAAS,EAAA,IAAA,EAAM,CAAC,CAAA;AAAA;AAC5D,WACD,CAAA;AACD,UAAA;AAAA;AAGF,QAAA,MAAM,SAAS,OAAQ,CAAA,aAAA;AAAA,UACrB,gBAAgB,UAAU,CAAA,EAAA;AAAA,SAC5B;AACA,QAAI,IAAA,CAAC,MAAU,IAAA,CAAC,cAAgB,EAAA;AAChC,QAAA,MAAA,CAAO,KAAQ,GAAA,cAAA;AACf,QAAO,MAAA,CAAA,aAAA,CAAc,IAAI,KAAM,CAAA,QAAA,EAAU,EAAE,OAAS,EAAA,IAAA,EAAM,CAAC,CAAA;AAAA;AAC7D;AACF,GACF;AAEA,EAAA,YAAA,CAAa,MAAM;AACjB,IAAA,MAAM,WAAW,KAAM,CAAA,QAAA;AAEvB,IAAA,SAAS,aAAa,KAAc,EAAA;AAClC,MAAA,MAAM,SAAS,KAAM,CAAA,MAAA;AACrB,MAAA,IAAI,CAAC,MAAQ,EAAA;AACb,MAAA,MAAM,iBAAiB,MAAO,CAAA,KAAA;AAC9B,MAAA,IAAI,OAAQ,CAAA,eAAA,CAAgB,QAAW,GAAA,CAAC,MAAM,cAAgB,EAAA;AAE9D,MAAQ,OAAA,CAAA,aAAA;AAAA,QACN,IAAI,YAAY,gBAAkB,EAAA;AAAA,UAChC,MAAQ,EAAA;AAAA,YACN,OAAO,KAAM,CAAA,IAAA;AAAA,YACb,QAAA;AAAA,YACA;AAAA,WACF;AAAA,UACA,OAAS,EAAA;AAAA,SACV;AAAA,OACH;AAEA,MAAA,OAAA,CAAQ,OAAQ,CAAA,YAAA,CAAa,cAAgB,EAAA,QAAA,GAAW,CAAC,CAAA;AAAA;AAG3D,IAAQ,OAAA,CAAA,gBAAA,CAAiB,UAAU,YAAY,CAAA;AAE/C,IAAA,OAAO,UAAU,MAAM;AACrB,MAAQ,OAAA,CAAA,mBAAA,CAAoB,UAAU,YAAY,CAAA;AAAA,KACnD,CAAA;AAAA,GACF,CAAA;AACH","file":"product-option-group.js","sourcesContent":["import type { CorrectComponentType } from \"@brytdesigns/web-component-core/utils\";\n\nimport { createEffect, on, onCleanup } from \"solid-js\";\n\nimport { useProductOptions } from \"../hooks/index.js\";\n\nexport type Props = {\n position: number;\n name: string;\n inputType: \"radio\" | \"select\";\n};\n\nexport const Name = `product-option-group`;\n\nexport const Component: CorrectComponentType<Props> = (props, { element }) => {\n const [context, methods] = useProductOptions(element);\n\n createEffect(\n on(\n () => ({\n selectedOption: context.selectedOptions[props.position - 1],\n position: props.position,\n name: props.name,\n inputType: props.inputType,\n }),\n ({ selectedOption, position, name, inputType }) => {\n if (inputType !== \"radio\" && inputType !== \"select\") return;\n\n const optionName = `${name}-${position}`;\n\n if (inputType === \"radio\") {\n const inputs = element.querySelectorAll<HTMLInputElement>(\n `input[name=\"${optionName}\"]`,\n );\n inputs.forEach((input) => {\n const prevValue = input.checked;\n if (input.value === selectedOption) input.checked = true;\n else input.checked = false;\n if (prevValue !== input.checked) {\n input.dispatchEvent(new Event(\"change\", { bubbles: true }));\n }\n });\n return;\n }\n\n const select = element.querySelector<HTMLSelectElement>(\n `select[name=\"${optionName}\"]`,\n );\n if (!select || !selectedOption) return;\n select.value = selectedOption;\n select.dispatchEvent(new Event(\"change\", { bubbles: true }));\n },\n ),\n );\n\n createEffect(() => {\n const position = props.position;\n\n function handleChange(event: Event) {\n const target = event.target as HTMLInputElement;\n if (!target) return;\n const selectedOption = target.value;\n if (context.selectedOptions[position - 1] === selectedOption) return;\n\n element.dispatchEvent(\n new CustomEvent(\"option-updated\", {\n detail: {\n group: props.name,\n position: position,\n selectedOption,\n },\n bubbles: true,\n }),\n );\n\n methods.options.updateOption(selectedOption, position - 1);\n }\n\n element.addEventListener(\"change\", handleChange);\n\n return onCleanup(() => {\n element.removeEventListener(\"change\", handleChange);\n });\n });\n};\n"]}
1
+ {"version":3,"file":"product-option-group.js","names":[],"sources":["../../../src/components/product-option-group.ts"],"sourcesContent":["import type { CorrectComponentType } from \"@brytdesigns/web-component-core/utils\";\nimport { createGuardedEffect } from \"@brytdesigns/web-component-core/utils\";\n\nimport { useProductOptions } from \"../hooks/index.js\";\n\nexport type Props = {\n\tposition: number;\n\tname: string;\n\tinputType: \"radio\" | \"select\";\n};\n\nexport const Name = `product-option-group`;\n\nexport const Component: CorrectComponentType<Props> = (props, { element }) => {\n\tconst [context, methods] = useProductOptions(element);\n\n\tcreateGuardedEffect(\n\t\t() => ({\n\t\t\tselectedOption: context.selectedOptions[props.position - 1],\n\t\t\tposition: props.position,\n\t\t\tname: props.name,\n\t\t\tinputType: props.inputType,\n\t\t}),\n\t\t({ selectedOption, position, name, inputType }) => {\n\t\t\tif (inputType !== \"radio\" && inputType !== \"select\") return;\n\n\t\t\tconst optionName = `${name}-${position}`;\n\n\t\t\tif (inputType === \"radio\") {\n\t\t\t\tconst inputs = element.querySelectorAll<HTMLInputElement>(\n\t\t\t\t\t`input[name=\"${optionName}\"]`,\n\t\t\t\t);\n\t\t\t\tinputs.forEach((input) => {\n\t\t\t\t\tconst prevValue = input.checked;\n\t\t\t\t\tif (input.value === selectedOption) input.checked = true;\n\t\t\t\t\telse input.checked = false;\n\t\t\t\t\t// Only the input that became CHECKED announces itself.\n\t\t\t\t\t//\n\t\t\t\t\t// This used to fire on any input whose state flipped, which\n\t\t\t\t\t// meant the radio being *de*selected dispatched `change` too.\n\t\t\t\t\t// The browser never does that - clicking B fires `change` on B\n\t\t\t\t\t// alone - and `handleChange` below reads `target.value` off\n\t\t\t\t\t// whatever fired, so the deselected option's value was fed\n\t\t\t\t\t// straight back into `updateOption` and the group could\n\t\t\t\t\t// oscillate between two options.\n\t\t\t\t\tif (prevValue !== input.checked && input.checked) {\n\t\t\t\t\t\tinput.dispatchEvent(new Event(\"change\", { bubbles: true }));\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst select = element.querySelector<HTMLSelectElement>(\n\t\t\t\t`select[name=\"${optionName}\"]`,\n\t\t\t);\n\t\t\tif (!select || !selectedOption) return;\n\t\t\tselect.value = selectedOption;\n\t\t\tselect.dispatchEvent(new Event(\"change\", { bubbles: true }));\n\t\t},\n\t);\n\n\tcreateGuardedEffect(\n\t\t() => props.position,\n\t\t(position) => {\n\t\t\tfunction handleChange(event: Event) {\n\t\t\t\tconst target = event.target as HTMLInputElement;\n\t\t\t\tif (!target) return;\n\t\t\t\t// A radio that is not checked is not a selection. Reading `value`\n\t\t\t\t// off one treats the option the shopper just moved *away* from as\n\t\t\t\t// the new choice - the other half of the oscillation guarded\n\t\t\t\t// against above, and the half that also covers a `change` this\n\t\t\t\t// component did not dispatch.\n\t\t\t\tif (target.type === \"radio\" && !target.checked) return;\n\t\t\t\tconst selectedOption = target.value;\n\t\t\t\tif (context.selectedOptions[position - 1] === selectedOption) return;\n\n\t\t\t\telement.dispatchEvent(\n\t\t\t\t\tnew CustomEvent(\"option-updated\", {\n\t\t\t\t\t\tdetail: {\n\t\t\t\t\t\t\tgroup: props.name,\n\t\t\t\t\t\t\tposition: position,\n\t\t\t\t\t\t\tselectedOption,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbubbles: true,\n\t\t\t\t\t}),\n\t\t\t\t);\n\n\t\t\t\tmethods.options.updateOption(selectedOption, position - 1);\n\t\t\t}\n\n\t\t\telement.addEventListener(\"change\", handleChange);\n\n\t\t\treturn () => {\n\t\t\t\telement.removeEventListener(\"change\", handleChange);\n\t\t\t};\n\t\t},\n\t);\n};\n"],"mappings":";;;;AAWA,IAAa,OAAO;AAEpB,IAAa,aAA0C,OAAO,EAAE,cAAc;CAC7E,MAAM,CAAC,SAAS,WAAW,kBAAkB,OAAO;CAEpD,2BACQ;EACN,gBAAgB,QAAQ,gBAAgB,MAAM,WAAW;EACzD,UAAU,MAAM;EAChB,MAAM,MAAM;EACZ,WAAW,MAAM;CAClB,KACC,EAAE,gBAAgB,UAAU,MAAM,gBAAgB;EAClD,IAAI,cAAc,WAAW,cAAc,UAAU;EAErD,MAAM,aAAa,GAAG,KAAK,GAAG;EAE9B,IAAI,cAAc,SAAS;GAI1B,QAHuB,iBACtB,eAAe,WAAW,GAE3B,CAAA,CAAO,SAAS,UAAU;IACzB,MAAM,YAAY,MAAM;IACxB,IAAI,MAAM,UAAU,gBAAgB,MAAM,UAAU;SAC/C,MAAM,UAAU;IAUrB,IAAI,cAAc,MAAM,WAAW,MAAM,SACxC,MAAM,cAAc,IAAI,MAAM,UAAU,EAAE,SAAS,KAAK,CAAC,CAAC;GAE5D,CAAC;GACD;EACD;EAEA,MAAM,SAAS,QAAQ,cACtB,gBAAgB,WAAW,GAC5B;EACA,IAAI,CAAC,UAAU,CAAC,gBAAgB;EAChC,OAAO,QAAQ;EACf,OAAO,cAAc,IAAI,MAAM,UAAU,EAAE,SAAS,KAAK,CAAC,CAAC;CAC5D,CACD;CAEA,0BACO,MAAM,WACX,aAAa;EACb,SAAS,aAAa,OAAc;GACnC,MAAM,SAAS,MAAM;GACrB,IAAI,CAAC,QAAQ;GAMb,IAAI,OAAO,SAAS,WAAW,CAAC,OAAO,SAAS;GAChD,MAAM,iBAAiB,OAAO;GAC9B,IAAI,QAAQ,gBAAgB,WAAW,OAAO,gBAAgB;GAE9D,QAAQ,cACP,IAAI,YAAY,kBAAkB;IACjC,QAAQ;KACP,OAAO,MAAM;KACH;KACV;IACD;IACA,SAAS;GACV,CAAC,CACF;GAEA,QAAQ,QAAQ,aAAa,gBAAgB,WAAW,CAAC;EAC1D;EAEA,QAAQ,iBAAiB,UAAU,YAAY;EAE/C,aAAa;GACZ,QAAQ,oBAAoB,UAAU,YAAY;EACnD;CACD,CACD;AACD"}
@@ -1,12 +1,13 @@
1
- import { provideProductOptionsContext } from '../hooks/index.js';
2
-
3
- const Name = `product-options`;
4
- const Component = (props, { element }) => {
5
- if (!props.selectedOptions)
6
- return console.warn(`${Name}: selected-options attribute is required`);
7
- provideProductOptionsContext(props, element);
1
+ import { provideProductOptionsContext } from "../hooks/useProductOptions.js";
2
+ import "../hooks/index.js";
3
+ import { untrack } from "solid-js";
4
+ //#region src/components/product-options.ts
5
+ var Name = `product-options`;
6
+ var Component = (props, { element }) => {
7
+ if (untrack(() => !props.selectedOptions)) return console.warn(`${Name}: selected-options attribute is required`);
8
+ provideProductOptionsContext(props, element);
8
9
  };
9
-
10
+ //#endregion
10
11
  export { Component, Name };
11
- //# sourceMappingURL=product-options.js.map
12
+
12
13
  //# sourceMappingURL=product-options.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/product-options.ts"],"names":[],"mappings":";;AAOO,MAAM,IAAO,GAAA,CAAA,eAAA;AAEb,MAAM,SAAyC,GAAA,CAAC,KAAO,EAAA,EAAE,SAAc,KAAA;AAC5E,EAAA,IAAI,CAAC,KAAM,CAAA,eAAA;AACT,IAAA,OAAO,OAAQ,CAAA,IAAA,CAAK,CAAG,EAAA,IAAI,CAA0C,wCAAA,CAAA,CAAA;AACvE,EAAA,4BAAA,CAA6B,OAAO,OAAO,CAAA;AAC7C","file":"product-options.js","sourcesContent":["import type { CorrectComponentType } from \"@brytdesigns/web-component-core/utils\";\nimport { provideProductOptionsContext } from \"../hooks/index.js\";\n\nexport type Props = {\n selectedOptions: string[];\n};\n\nexport const Name = `product-options`;\n\nexport const Component: CorrectComponentType<Props> = (props, { element }) => {\n if (!props.selectedOptions)\n return console.warn(`${Name}: selected-options attribute is required`);\n provideProductOptionsContext(props, element);\n};\n"]}
1
+ {"version":3,"file":"product-options.js","names":[],"sources":["../../../src/components/product-options.ts"],"sourcesContent":["import type { CorrectComponentType } from \"@brytdesigns/web-component-core/utils\";\nimport { untrack } from \"solid-js\";\nimport { provideProductOptionsContext } from \"../hooks/index.js\";\n\nexport type Props = {\n\tselectedOptions: string[];\n};\n\nexport const Name = `product-options`;\n\nexport const Component: CorrectComponentType<Props> = (props, { element }) => {\n\tif (untrack(() => !props.selectedOptions))\n\t\treturn console.warn(`${Name}: selected-options attribute is required`);\n\tprovideProductOptionsContext(props, element);\n};\n"],"mappings":";;;;AAQA,IAAa,OAAO;AAEpB,IAAa,aAA0C,OAAO,EAAE,cAAc;CAC7E,IAAI,cAAc,CAAC,MAAM,eAAe,GACvC,OAAO,QAAQ,KAAK,GAAG,KAAK,yCAAyC;CACtE,6BAA6B,OAAO,OAAO;AAC5C"}
@@ -1,49 +1,52 @@
1
- import { createEffect, onCleanup } from 'solid-js';
2
- import { useProduct, useProductOptions } from '../hooks/index.js';
3
-
4
- const Name = `product-variant-input`;
5
- const Component = (props, { element }) => {
6
- const [productContext, productContextMethods] = useProduct(element);
7
- const [_, optionsMethods] = useProductOptions(element);
8
- createEffect(() => {
9
- let target = null;
10
- if (props.target) target = element.querySelector(props.target);
11
- if (!target) target = element;
12
- const preventDefault = props.preventDefault;
13
- function handleChange(event) {
14
- if (preventDefault) event.preventDefault();
15
- const target2 = event.target;
16
- if (!target2) return;
17
- const value = target2.value;
18
- if (value === productContext?.product?.selected_or_first_available_variant?.id)
19
- return;
20
- const variant = productContext?.product?.variants.find(
21
- (variant2) => variant2.id.toString() === value.toString()
22
- );
23
- if (!variant) return;
24
- if (optionsMethods) optionsMethods.options.update(variant.options);
25
- else productContextMethods.variant.update(variant.id);
26
- }
27
- target.addEventListener("change", handleChange);
28
- return onCleanup(() => {
29
- target.removeEventListener("change", handleChange);
30
- });
31
- });
32
- createEffect(() => {
33
- let target = null;
34
- if (props.target)
35
- target = element.querySelector(props.target);
36
- if (!target)
37
- target = element.querySelector("input[name='id']");
38
- if (!target) return console.warn(`${Name}: target input not found`);
39
- const variantId = productContext?.product?.selected_or_first_available_variant?.id;
40
- if (!variantId) return;
41
- if (target.value === variantId.toString()) return;
42
- target.value = variantId.toString();
43
- target.dispatchEvent(new Event("change", { bubbles: true }));
44
- });
1
+ import { useProduct } from "../hooks/useProduct.js";
2
+ import { useProductOptions } from "../hooks/useProductOptions.js";
3
+ import "../hooks/index.js";
4
+ import { createGuardedEffect } from "@brytdesigns/web-component-core/utils";
5
+ import { untrack } from "solid-js";
6
+ //#region src/components/product-variant-input.ts
7
+ var Name = `product-variant-input`;
8
+ var Component = (props, { element }) => {
9
+ const [productContext, productContextMethods] = useProduct(element);
10
+ const [_, optionsMethods] = useProductOptions(element);
11
+ createGuardedEffect(() => ({
12
+ target: props.target,
13
+ preventDefault: props.preventDefault
14
+ }), ({ target: selector, preventDefault }) => {
15
+ let target = null;
16
+ if (selector) target = element.querySelector(selector);
17
+ if (!target) target = element;
18
+ function handleChange(event) {
19
+ if (preventDefault) event.preventDefault();
20
+ const target = event.target;
21
+ if (!target) return;
22
+ const value = target.value;
23
+ const product = untrack(() => productContext?.product);
24
+ if (value === String(product?.selected_or_first_available_variant?.id ?? "")) return;
25
+ const variant = product?.variants.find((variant) => variant.id.toString() === value.toString());
26
+ if (!variant) return;
27
+ if (optionsMethods) optionsMethods.options.update(variant.options);
28
+ else productContextMethods.variant.update(variant.id);
29
+ }
30
+ target.addEventListener("change", handleChange);
31
+ return () => {
32
+ target.removeEventListener("change", handleChange);
33
+ };
34
+ });
35
+ createGuardedEffect(() => ({
36
+ target: props.target,
37
+ variantId: productContext?.product?.selected_or_first_available_variant?.id
38
+ }), ({ target: selector, variantId }) => {
39
+ let target = null;
40
+ if (selector) target = element.querySelector(selector);
41
+ if (!target) target = element.querySelector("input[name='id']");
42
+ if (!target) return console.warn(`${Name}: target input not found`);
43
+ if (!variantId) return;
44
+ if (target.value === variantId.toString()) return;
45
+ target.value = variantId.toString();
46
+ target.dispatchEvent(new Event("change", { bubbles: true }));
47
+ });
45
48
  };
46
-
49
+ //#endregion
47
50
  export { Component, Name };
48
- //# sourceMappingURL=product-variant-input.js.map
51
+
49
52
  //# sourceMappingURL=product-variant-input.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/product-variant-input.ts"],"names":["target","variant"],"mappings":";;;AAWO,MAAM,IAAO,GAAA,CAAA,qBAAA;AAEb,MAAM,SAAyC,GAAA,CAAC,KAAO,EAAA,EAAE,SAAc,KAAA;AAC5E,EAAA,MAAM,CAAC,cAAA,EAAgB,qBAAqB,CAAA,GAAI,WAAW,OAAO,CAAA;AAClE,EAAA,MAAM,CAAC,CAAA,EAAG,cAAc,CAAA,GAAI,kBAAkB,OAAO,CAAA;AAErD,EAAA,YAAA,CAAa,MAAM;AACjB,IAAA,IAAI,MAAS,GAAA,IAAA;AACb,IAAA,IAAI,MAAM,MAAQ,EAAA,MAAA,GAAS,OAAQ,CAAA,aAAA,CAAc,MAAM,MAAM,CAAA;AAC7D,IAAI,IAAA,CAAC,QAAiB,MAAA,GAAA,OAAA;AAEtB,IAAA,MAAM,iBAAiB,KAAM,CAAA,cAAA;AAE7B,IAAA,SAAS,aAAa,KAAc,EAAA;AAClC,MAAI,IAAA,cAAA,QAAsB,cAAe,EAAA;AACzC,MAAA,MAAMA,UAAS,KAAM,CAAA,MAAA;AACrB,MAAA,IAAI,CAACA,OAAQ,EAAA;AACb,MAAA,MAAM,QAAQA,OAAO,CAAA,KAAA;AACrB,MACE,IAAA,KAAA,KACA,cAAgB,EAAA,OAAA,EAAS,mCAAqC,EAAA,EAAA;AAE9D,QAAA;AACF,MAAM,MAAA,OAAA,GAAU,cAAgB,EAAA,OAAA,EAAS,QAAS,CAAA,IAAA;AAAA,QAChD,CAACC,QAAYA,KAAAA,QAAAA,CAAQ,GAAG,QAAS,EAAA,KAAM,MAAM,QAAS;AAAA,OACxD;AACA,MAAA,IAAI,CAAC,OAAS,EAAA;AACd,MAAA,IAAI,cAAgB,EAAA,cAAA,CAAe,OAAQ,CAAA,MAAA,CAAO,QAAQ,OAAO,CAAA;AAAA,WACtC,qBAAA,CAAA,OAAA,CAAQ,MAAO,CAAA,OAAA,CAAQ,EAAE,CAAA;AAAA;AAGtD,IAAO,MAAA,CAAA,gBAAA,CAAiB,UAAU,YAAY,CAAA;AAE9C,IAAA,OAAO,UAAU,MAAM;AACrB,MAAO,MAAA,CAAA,mBAAA,CAAoB,UAAU,YAAY,CAAA;AAAA,KAClD,CAAA;AAAA,GACF,CAAA;AAED,EAAA,YAAA,CAAa,MAAM;AACjB,IAAA,IAAI,MAAS,GAAA,IAAA;AACb,IAAA,IAAI,KAAM,CAAA,MAAA;AACR,MAAS,MAAA,GAAA,OAAA,CAAQ,aAAgC,CAAA,KAAA,CAAM,MAAM,CAAA;AAC/D,IAAA,IAAI,CAAC,MAAA;AACH,MAAS,MAAA,GAAA,OAAA,CAAQ,cAAgC,kBAAkB,CAAA;AACrE,IAAA,IAAI,CAAC,MAAQ,EAAA,OAAO,QAAQ,IAAK,CAAA,CAAA,EAAG,IAAI,CAA0B,wBAAA,CAAA,CAAA;AAElE,IAAM,MAAA,SAAA,GACJ,cAAgB,EAAA,OAAA,EAAS,mCAAqC,EAAA,EAAA;AAChE,IAAA,IAAI,CAAC,SAAW,EAAA;AAChB,IAAA,IAAI,MAAO,CAAA,KAAA,KAAU,SAAU,CAAA,QAAA,EAAY,EAAA;AAC3C,IAAO,MAAA,CAAA,KAAA,GAAQ,UAAU,QAAS,EAAA;AAClC,IAAO,MAAA,CAAA,aAAA,CAAc,IAAI,KAAM,CAAA,QAAA,EAAU,EAAE,OAAS,EAAA,IAAA,EAAM,CAAC,CAAA;AAAA,GAC5D,CAAA;AACH","file":"product-variant-input.js","sourcesContent":["import type { CorrectComponentType } from \"@brytdesigns/web-component-core/utils\";\n\nimport { createEffect, onCleanup } from \"solid-js\";\n\nimport { useProduct, useProductOptions } from \"../hooks/index.js\";\n\nexport type Props = {\n target: string | null;\n preventDefault?: boolean;\n};\n\nexport const Name = `product-variant-input`;\n\nexport const Component: CorrectComponentType<Props> = (props, { element }) => {\n const [productContext, productContextMethods] = useProduct(element);\n const [_, optionsMethods] = useProductOptions(element);\n\n createEffect(() => {\n let target = null;\n if (props.target) target = element.querySelector(props.target);\n if (!target) target = element;\n\n const preventDefault = props.preventDefault;\n\n function handleChange(event: Event) {\n if (preventDefault) event.preventDefault();\n const target = event.target as HTMLInputElement;\n if (!target) return;\n const value = target.value;\n if (\n value ===\n productContext?.product?.selected_or_first_available_variant?.id\n )\n return;\n const variant = productContext?.product?.variants.find(\n (variant) => variant.id.toString() === value.toString(),\n );\n if (!variant) return;\n if (optionsMethods) optionsMethods.options.update(variant.options);\n else productContextMethods.variant.update(variant.id);\n }\n\n target.addEventListener(\"change\", handleChange);\n\n return onCleanup(() => {\n target.removeEventListener(\"change\", handleChange);\n });\n });\n\n createEffect(() => {\n let target = null;\n if (props.target)\n target = element.querySelector<HTMLInputElement>(props.target);\n if (!target)\n target = element.querySelector<HTMLInputElement>(\"input[name='id']\");\n if (!target) return console.warn(`${Name}: target input not found`);\n\n const variantId =\n productContext?.product?.selected_or_first_available_variant?.id;\n if (!variantId) return;\n if (target.value === variantId.toString()) return;\n target.value = variantId.toString();\n target.dispatchEvent(new Event(\"change\", { bubbles: true }));\n });\n};\n"]}
1
+ {"version":3,"file":"product-variant-input.js","names":[],"sources":["../../../src/components/product-variant-input.ts"],"sourcesContent":["import type { CorrectComponentType } from \"@brytdesigns/web-component-core/utils\";\nimport { createGuardedEffect } from \"@brytdesigns/web-component-core/utils\";\nimport { untrack } from \"solid-js\";\n\nimport { useProduct, useProductOptions } from \"../hooks/index.js\";\n\nexport type Props = {\n\ttarget: string | null;\n\tpreventDefault?: boolean;\n};\n\nexport const Name = `product-variant-input`;\n\nexport const Component: CorrectComponentType<Props> = (props, { element }) => {\n\tconst [productContext, productContextMethods] = useProduct(element);\n\tconst [_, optionsMethods] = useProductOptions(element);\n\n\tcreateGuardedEffect(\n\t\t() => ({\n\t\t\ttarget: props.target,\n\t\t\tpreventDefault: props.preventDefault,\n\t\t}),\n\t\t({ target: selector, preventDefault }) => {\n\t\t\tlet target: Element | null = null;\n\t\t\tif (selector) target = element.querySelector(selector);\n\t\t\tif (!target) target = element;\n\n\t\t\tfunction handleChange(event: Event) {\n\t\t\t\tif (preventDefault) event.preventDefault();\n\t\t\t\tconst target = event.target as HTMLInputElement;\n\t\t\t\tif (!target) return;\n\t\t\t\tconst value = target.value;\n\t\t\t\t// An event handler is not a tracking scope, and the product has\n\t\t\t\t// to be read as it stands when the shopper picks — not as it\n\t\t\t\t// stood when the listener was attached. Declared with `untrack`\n\t\t\t\t// so the read is reviewed rather than reported.\n\t\t\t\tconst product = untrack(() => productContext?.product);\n\t\t\t\t// Compared as strings. `value` is always a string and the id is a\n\t\t\t\t// number, so `===` was never true and this early return never\n\t\t\t\t// fired - every change ran the lookup and the update below, even\n\t\t\t\t// when nothing had actually changed.\n\t\t\t\tif (\n\t\t\t\t\tvalue ===\n\t\t\t\t\tString(product?.selected_or_first_available_variant?.id ?? \"\")\n\t\t\t\t)\n\t\t\t\t\treturn;\n\t\t\t\tconst variant = product?.variants.find(\n\t\t\t\t\t(variant) => variant.id.toString() === value.toString(),\n\t\t\t\t);\n\t\t\t\tif (!variant) return;\n\t\t\t\tif (optionsMethods) optionsMethods.options.update(variant.options);\n\t\t\t\telse productContextMethods.variant.update(variant.id);\n\t\t\t}\n\n\t\t\ttarget.addEventListener(\"change\", handleChange);\n\n\t\t\treturn () => {\n\t\t\t\ttarget.removeEventListener(\"change\", handleChange);\n\t\t\t};\n\t\t},\n\t);\n\n\tcreateGuardedEffect(\n\t\t// `variantId` is read HERE, in the compute phase, because only the\n\t\t// compute phase tracks. It used to be read in the apply phase below,\n\t\t// which meant this effect depended on `props.target` alone: the hidden\n\t\t// `input[name=\"id\"]` was written once at mount and never again, so\n\t\t// choosing a swatch left the form posting the *first* variant and the\n\t\t// shopper received the wrong one. A single-function Solid 1 effect\n\t\t// tracked its whole body; a split Solid 2 effect does not.\n\t\t() => ({\n\t\t\ttarget: props.target,\n\t\t\tvariantId:\n\t\t\t\tproductContext?.product?.selected_or_first_available_variant?.id,\n\t\t}),\n\t\t({ target: selector, variantId }) => {\n\t\t\tlet target: HTMLInputElement | null = null;\n\t\t\tif (selector) target = element.querySelector<HTMLInputElement>(selector);\n\t\t\tif (!target)\n\t\t\t\ttarget = element.querySelector<HTMLInputElement>(\"input[name='id']\");\n\t\t\tif (!target) return console.warn(`${Name}: target input not found`);\n\n\t\t\tif (!variantId) return;\n\t\t\tif (target.value === variantId.toString()) return;\n\t\t\ttarget.value = variantId.toString();\n\t\t\ttarget.dispatchEvent(new Event(\"change\", { bubbles: true }));\n\t\t},\n\t);\n};\n"],"mappings":";;;;;;AAWA,IAAa,OAAO;AAEpB,IAAa,aAA0C,OAAO,EAAE,cAAc;CAC7E,MAAM,CAAC,gBAAgB,yBAAyB,WAAW,OAAO;CAClE,MAAM,CAAC,GAAG,kBAAkB,kBAAkB,OAAO;CAErD,2BACQ;EACN,QAAQ,MAAM;EACd,gBAAgB,MAAM;CACvB,KACC,EAAE,QAAQ,UAAU,qBAAqB;EACzC,IAAI,SAAyB;EAC7B,IAAI,UAAU,SAAS,QAAQ,cAAc,QAAQ;EACrD,IAAI,CAAC,QAAQ,SAAS;EAEtB,SAAS,aAAa,OAAc;GACnC,IAAI,gBAAgB,MAAM,eAAe;GACzC,MAAM,SAAS,MAAM;GACrB,IAAI,CAAC,QAAQ;GACb,MAAM,QAAQ,OAAO;GAKrB,MAAM,UAAU,cAAc,gBAAgB,OAAO;GAKrD,IACC,UACA,OAAO,SAAS,qCAAqC,MAAM,EAAE,GAE7D;GACD,MAAM,UAAU,SAAS,SAAS,MAChC,YAAY,QAAQ,GAAG,SAAS,MAAM,MAAM,SAAS,CACvD;GACA,IAAI,CAAC,SAAS;GACd,IAAI,gBAAgB,eAAe,QAAQ,OAAO,QAAQ,OAAO;QAC5D,sBAAsB,QAAQ,OAAO,QAAQ,EAAE;EACrD;EAEA,OAAO,iBAAiB,UAAU,YAAY;EAE9C,aAAa;GACZ,OAAO,oBAAoB,UAAU,YAAY;EAClD;CACD,CACD;CAEA,2BAQQ;EACN,QAAQ,MAAM;EACd,WACC,gBAAgB,SAAS,qCAAqC;CAChE,KACC,EAAE,QAAQ,UAAU,gBAAgB;EACpC,IAAI,SAAkC;EACtC,IAAI,UAAU,SAAS,QAAQ,cAAgC,QAAQ;EACvE,IAAI,CAAC,QACJ,SAAS,QAAQ,cAAgC,kBAAkB;EACpE,IAAI,CAAC,QAAQ,OAAO,QAAQ,KAAK,GAAG,KAAK,yBAAyB;EAElE,IAAI,CAAC,WAAW;EAChB,IAAI,OAAO,UAAU,UAAU,SAAS,GAAG;EAC3C,OAAO,QAAQ,UAAU,SAAS;EAClC,OAAO,cAAc,IAAI,MAAM,UAAU,EAAE,SAAS,KAAK,CAAC,CAAC;CAC5D,CACD;AACD"}
@@ -1,37 +1,31 @@
1
- import { createMemo, Show } from 'solid-js';
2
- import html from 'solid-js/html';
3
- import { useProduct } from '../hooks/index.js';
4
-
5
- const Name = `product-variant-render`;
6
- const Component = (_, { element }) => {
7
- const templates = Array.from(
8
- element.querySelectorAll("template[variant-id]")
9
- );
10
- if (!templates.length)
11
- return console.warn(`${Name}: No variant templates found`);
12
- const [state] = useProduct(element);
13
- const fallbackChildren = Array.from(element.children);
14
- const activeVariantTemplate = createMemo(() => {
15
- const variantId = state.product?.selected_or_first_available_variant?.id;
16
- if (!variantId) return null;
17
- const template = templates.find(
18
- (t) => t.getAttribute("variant-id") === `${variantId}`
19
- );
20
- return template || null;
21
- });
22
- element.replaceChildren(...[]);
23
- return html`
24
- <${Show}
25
- when=${() => !!activeVariantTemplate()}
26
- fallback=${fallbackChildren}
27
- >
28
- ${() => Array.from(
29
- activeVariantTemplate()?.content.cloneNode(true).childNodes || []
30
- )}
31
- <//>
32
- `;
1
+ import { useProduct } from "../hooks/useProduct.js";
2
+ import "../hooks/index.js";
3
+ import { createMemo } from "solid-js";
4
+ import { Show, createComponent } from "@solidjs/web";
5
+ //#region src/components/product-variant-render.tsx
6
+ var Name = `product-variant-render`;
7
+ var Component = (_, { element }) => {
8
+ const templates = Array.from(element.querySelectorAll("template[variant-id]"));
9
+ if (!templates.length) return console.warn(`${Name}: No variant templates found`);
10
+ const [state] = useProduct(element);
11
+ const fallbackChildren = Array.from(element.children);
12
+ const activeVariantTemplate = createMemo(() => {
13
+ const variantId = state.product?.selected_or_first_available_variant?.id;
14
+ if (!variantId) return null;
15
+ return templates.find((t) => t.getAttribute("variant-id") === `${variantId}`) || null;
16
+ });
17
+ element.replaceChildren(...[]);
18
+ return createComponent(Show, {
19
+ get when() {
20
+ return !!activeVariantTemplate();
21
+ },
22
+ fallback: fallbackChildren,
23
+ get children() {
24
+ return Array.from(activeVariantTemplate()?.content.cloneNode(true).childNodes || []);
25
+ }
26
+ });
33
27
  };
34
-
28
+ //#endregion
35
29
  export { Component, Name };
36
- //# sourceMappingURL=product-variant-render.js.map
30
+
37
31
  //# sourceMappingURL=product-variant-render.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/product-variant-render.ts"],"names":[],"mappings":";;;;AASO,MAAM,IAAO,GAAA,CAAA,sBAAA;AAEb,MAAM,SAAyC,GAAA,CAAC,CAAG,EAAA,EAAE,SAAc,KAAA;AACxE,EAAA,MAAM,YAAY,KAAM,CAAA,IAAA;AAAA,IACtB,OAAA,CAAQ,iBAAsC,sBAAsB;AAAA,GACtE;AACA,EAAA,IAAI,CAAC,SAAU,CAAA,MAAA;AACb,IAAA,OAAO,OAAQ,CAAA,IAAA,CAAK,CAAG,EAAA,IAAI,CAA8B,4BAAA,CAAA,CAAA;AAC3D,EAAA,MAAM,CAAC,KAAK,CAAI,GAAA,UAAA,CAAW,OAAO,CAAA;AAElC,EAAA,MAAM,gBAAmB,GAAA,KAAA,CAAM,IAAK,CAAA,OAAA,CAAQ,QAAQ,CAAA;AAEpD,EAAM,MAAA,qBAAA,GAAwB,WAAW,MAAM;AAC7C,IAAM,MAAA,SAAA,GAAY,KAAM,CAAA,OAAA,EAAS,mCAAqC,EAAA,EAAA;AACtE,IAAI,IAAA,CAAC,WAAkB,OAAA,IAAA;AACvB,IAAA,MAAM,WAAW,SAAU,CAAA,IAAA;AAAA,MACzB,CAAC,CAAM,KAAA,CAAA,CAAE,aAAa,YAAY,CAAA,KAAM,GAAG,SAAS,CAAA;AAAA,KACtD;AACA,IAAA,OAAO,QAAY,IAAA,IAAA;AAAA,GACpB,CAAA;AAED,EAAQ,OAAA,CAAA,eAAA,CAAgB,GAAG,EAAE,CAAA;AAE7B,EAAO,OAAA,IAAA;AAAA,KAAA,EACF,IAAI;AAAA,WAAA,EACE,MAAM,CAAC,CAAC,qBAAA,EAAuB;AAAA,eAAA,EAC3B,gBAAgB;AAAA;AAAA,MAAA,EAEzB,MACF,KAAM,CAAA,IAAA;AAAA,IACJ,uBAAyB,EAAA,OAAA,CAAQ,UAAU,IAAI,CAAA,CAAE,cAAc;AAAC,GACjE;AAAA;AAAA,EAAA,CAAA;AAGP","file":"product-variant-render.js","sourcesContent":["import type { CorrectComponentType } from \"@brytdesigns/web-component-core/utils\";\n\nimport { createMemo, Show } from \"solid-js\";\nimport html from \"solid-js/html\";\n\nimport { useProduct } from \"../hooks/index.js\";\n\nexport type Props = {};\n\nexport const Name = `product-variant-render`;\n\nexport const Component: CorrectComponentType<Props> = (_, { element }) => {\n const templates = Array.from(\n element.querySelectorAll<HTMLTemplateElement>(\"template[variant-id]\"),\n );\n if (!templates.length)\n return console.warn(`${Name}: No variant templates found`);\n const [state] = useProduct(element);\n\n const fallbackChildren = Array.from(element.children);\n\n const activeVariantTemplate = createMemo(() => {\n const variantId = state.product?.selected_or_first_available_variant?.id;\n if (!variantId) return null;\n const template = templates.find(\n (t) => t.getAttribute(\"variant-id\") === `${variantId}`,\n );\n return template || null;\n });\n\n element.replaceChildren(...[]);\n\n return html`\n <${Show}\n when=${() => !!activeVariantTemplate()}\n fallback=${fallbackChildren}\n >\n ${() =>\n Array.from(\n activeVariantTemplate()?.content.cloneNode(true).childNodes || [],\n )}\n <//>\n `;\n};\n"]}
1
+ {"version":3,"file":"product-variant-render.js","names":["<Show when={!!activeVariantTemplate()} fallback={fallbackChildren}>\n\t\t\t{Array.from(\n\t\t\t\tactiveVariantTemplate()?.content.cloneNode(true).childNodes || [],\n\t\t\t)}\n\t\t</Show>","fallback={fallbackChildren}"],"sources":["../../../src/components/product-variant-render.tsx"],"sourcesContent":["import type { CorrectComponentType } from \"@brytdesigns/web-component-core/utils\";\n\nimport { Show } from \"@solidjs/web\";\nimport { createMemo } from \"solid-js\";\n\nimport { useProduct } from \"../hooks/index.js\";\n\nexport type Props = {};\n\nexport const Name = `product-variant-render`;\n\nexport const Component: CorrectComponentType<Props> = (_, { element }) => {\n\tconst templates = Array.from(\n\t\telement.querySelectorAll<HTMLTemplateElement>(\"template[variant-id]\"),\n\t);\n\tif (!templates.length)\n\t\treturn console.warn(`${Name}: No variant templates found`);\n\tconst [state] = useProduct(element);\n\n\tconst fallbackChildren = Array.from(element.children);\n\n\tconst activeVariantTemplate = createMemo(() => {\n\t\tconst variantId = state.product?.selected_or_first_available_variant?.id;\n\t\tif (!variantId) return null;\n\t\tconst template = templates.find(\n\t\t\t(t) => t.getAttribute(\"variant-id\") === `${variantId}`,\n\t\t);\n\t\treturn template || null;\n\t});\n\n\telement.replaceChildren(...[]);\n\n\treturn (\n\t\t<Show when={!!activeVariantTemplate()} fallback={fallbackChildren}>\n\t\t\t{Array.from(\n\t\t\t\tactiveVariantTemplate()?.content.cloneNode(true).childNodes || [],\n\t\t\t)}\n\t\t</Show>\n\t);\n};\n"],"mappings":";;;;;AASA,IAAa,OAAO;AAEpB,IAAa,aAA0C,GAAG,EAAE,cAAc;CACzE,MAAM,YAAY,MAAM,KACvB,QAAQ,iBAAsC,sBAAsB,CACrE;CACA,IAAI,CAAC,UAAU,QACd,OAAO,QAAQ,KAAK,GAAG,KAAK,6BAA6B;CAC1D,MAAM,CAAC,SAAS,WAAW,OAAO;CAElC,MAAM,mBAAmB,MAAM,KAAK,QAAQ,QAAQ;CAEpD,MAAM,wBAAwB,iBAAiB;EAC9C,MAAM,YAAY,MAAM,SAAS,qCAAqC;EACtE,IAAI,CAAC,WAAW,OAAO;EAIvB,OAHiB,UAAU,MACzB,MAAM,EAAE,aAAa,YAAY,MAAM,GAAG,WAErC,KAAY;CACpB,CAAC;CAED,QAAQ,gBAAgB,GAAG,CAAC,CAAC;CAE7B,OACCA,gBAAAA,MAAAA;EAAM,IAAA,OAAA;GAAM,OAAA,CAAC,CAAC,sBAAsB;EAAC;EAAEC,UAAU;EAAjD,IAAA,WAAA;GACE,OAAA,MAAM,KACN,sBAAsB,CAAC,EAAE,QAAQ,UAAU,IAAI,CAAC,CAAC,cAAc,CAAC,CACjE;EACK;;AAER"}
@@ -1,4 +1,3 @@
1
- export * from './useProduct.js';
2
- export * from './useProductOptions.js';
3
- //# sourceMappingURL=index.js.map
4
- //# sourceMappingURL=index.js.map
1
+ import { getProductContext, provideProductContext, useProduct, useProductAt, useProductContext } from "./useProduct.js";
2
+ import { getProductOptionsContext, provideProductOptionsContext, useProductOptions, useProductOptionsAt, useProductOptionsContext } from "./useProductOptions.js";
3
+ export { getProductContext, getProductOptionsContext, provideProductContext, provideProductOptionsContext, useProduct, useProductAt, useProductContext, useProductOptions, useProductOptionsAt, useProductOptionsContext };