@tapcart/mobile-components 0.13.1 → 0.14.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.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=use-infinite-scroll-params.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-infinite-scroll-params.test.d.ts","sourceRoot":"","sources":["../../../../components/hooks/__tests__/use-infinite-scroll-params.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,35 @@
1
+ import { formatSearchParamsAsNextQueryVariables, stripLayoutOnlyParams, LAYOUT_ONLY_QUERY_PARAMS, } from "../use-infinite-scroll";
2
+ // In API mode the formatted searchParams object is what forks the product cache
3
+ // key: it's hashed into the server Redis key (the by-page route does
4
+ // md5(JSON.stringify(body))) and serialized into the client IDB key. The
5
+ // layout-only `column` param must not survive into that object, or column=2 and
6
+ // column=3 read independent, independently-aged snapshots of the same
7
+ // collection (the Diamond Art Club bug).
8
+ const format = (qs) => stripLayoutOnlyParams(formatSearchParamsAsNextQueryVariables(new URLSearchParams(qs)));
9
+ describe("layout-only param stripping (column cache-key fork fix)", () => {
10
+ it("strips `column` but keeps the data-affecting params", () => {
11
+ const formatted = format("country=US&lang=EN&collectionId=463133769921&collectionHandle=diamond-painting-restocks&column=3");
12
+ expect(formatted).not.toHaveProperty("column");
13
+ expect(formatted).toEqual({
14
+ country: "US",
15
+ lang: "EN",
16
+ collectionId: "463133769921",
17
+ collectionHandle: "diamond-painting-restocks",
18
+ });
19
+ });
20
+ it("yields IDENTICAL cache-key input for column=2 vs column=3", () => {
21
+ const base = "country=US&lang=EN&collectionId=463133769921&collectionHandle=diamond-painting-restocks";
22
+ const col2 = format(`${base}&column=2`);
23
+ const col3 = format(`${base}&column=3`);
24
+ // Same serialization => one shared Redis + IDB entry across layout variants.
25
+ expect(JSON.stringify(col2)).toEqual(JSON.stringify(col3));
26
+ });
27
+ it("never strips real filter/sort params", () => {
28
+ const formatted = format("column=3&sort_by=best-selling&filter.p.tag=in-stock");
29
+ expect(formatted).toEqual({
30
+ sort_by: "best-selling",
31
+ "filter.p.tag": "in-stock",
32
+ });
33
+ expect(LAYOUT_ONLY_QUERY_PARAMS).toContain("column");
34
+ });
35
+ });
@@ -35,6 +35,8 @@ interface UseInfiniteScrollReturn {
35
35
  isValidating: boolean;
36
36
  }
37
37
  export declare const formatSearchParamsAsNextQueryVariables: (searchParams: ReadonlyURLSearchParams) => {};
38
+ export declare const LAYOUT_ONLY_QUERY_PARAMS: string[];
39
+ export declare const stripLayoutOnlyParams: (params: Record<string, unknown>) => Record<string, unknown>;
38
40
  declare const constructURL: (apiURL: string) => string;
39
41
  declare const useInfiniteScroll: ({ searchClient, initialData, queryVariables: queryVariableProps, direction, productLimit, threshold, interval, customFetcher, customGetKey, shouldSkipFetch: shouldSkipFetchProp, }: UseInfiniteScrollProps) => UseInfiniteScrollReturn;
40
42
  export { useInfiniteScroll, constructURL };
@@ -1 +1 @@
1
- {"version":3,"file":"use-infinite-scroll.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-infinite-scroll.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,uBAAuB,EAAmB,MAAM,iBAAiB,CAAA;AAE1E,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAG5D,UAAU,QAAQ;IAChB,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,GAAG,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAA;CACxC;AAED,UAAU,sBAAsB;IAE9B,YAAY,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAGxC,WAAW,CAAC,EAAE,QAAQ,CAAA;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAGpC,SAAS,CAAC,EAAE,UAAU,GAAG,YAAY,CAAA;IACrC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;IAChD,YAAY,CAAC,EAAE,CACb,SAAS,EAAE,MAAM,EACjB,gBAAgB,EAAE,GAAG,GAAG,IAAI,EAC5B,GAAG,IAAI,EAAE,GAAG,EAAE,KACX,GAAG,CAAA;IACR,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B;AAED,UAAU,uBAAuB;IAC/B,IAAI,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAA;IAC5B,KAAK,EAAE,GAAG,CAAA;IACV,oBAAoB,EAAE,OAAO,CAAA;IAC7B,aAAa,EAAE,OAAO,GAAG,SAAS,CAAA;IAClC,OAAO,EAAE,OAAO,CAAA;IAChB,aAAa,EAAE,OAAO,CAAA;IACtB,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,KAAK,IAAI,CAAA;IAChD,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,oBAAoB,EAAE,GAAG,EAAE,CAAA;IAC3B,SAAS,EAAE,OAAO,CAAA;IAClB,YAAY,EAAE,OAAO,CAAA;CACtB;AAED,eAAO,MAAM,sCAAsC,iBACnC,uBAAuB,OAsBtC,CAAA;AAED,QAAA,MAAM,YAAY,WAAY,MAAM,WAGnC,CAAA;AAED,QAAA,MAAM,iBAAiB,wLAgBpB,sBAAsB,KAAG,uBAkU3B,CAAA;AAED,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,CAAA"}
1
+ {"version":3,"file":"use-infinite-scroll.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-infinite-scroll.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,uBAAuB,EAAmB,MAAM,iBAAiB,CAAA;AAE1E,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAG5D,UAAU,QAAQ;IAChB,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,GAAG,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAA;CACxC;AAED,UAAU,sBAAsB;IAE9B,YAAY,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAGxC,WAAW,CAAC,EAAE,QAAQ,CAAA;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAGpC,SAAS,CAAC,EAAE,UAAU,GAAG,YAAY,CAAA;IACrC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;IAChD,YAAY,CAAC,EAAE,CACb,SAAS,EAAE,MAAM,EACjB,gBAAgB,EAAE,GAAG,GAAG,IAAI,EAC5B,GAAG,IAAI,EAAE,GAAG,EAAE,KACX,GAAG,CAAA;IACR,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B;AAED,UAAU,uBAAuB;IAC/B,IAAI,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAA;IAC5B,KAAK,EAAE,GAAG,CAAA;IACV,oBAAoB,EAAE,OAAO,CAAA;IAC7B,aAAa,EAAE,OAAO,GAAG,SAAS,CAAA;IAClC,OAAO,EAAE,OAAO,CAAA;IAChB,aAAa,EAAE,OAAO,CAAA;IACtB,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,KAAK,IAAI,CAAA;IAChD,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,oBAAoB,EAAE,GAAG,EAAE,CAAA;IAC3B,SAAS,EAAE,OAAO,CAAA;IAClB,YAAY,EAAE,OAAO,CAAA;CACtB;AAED,eAAO,MAAM,sCAAsC,iBACnC,uBAAuB,OAsBtC,CAAA;AAWD,eAAO,MAAM,wBAAwB,UAAa,CAAA;AAIlD,eAAO,MAAM,qBAAqB,WACxB,OAAO,MAAM,EAAE,OAAO,CAAC,KAC9B,OAAO,MAAM,EAAE,OAAO,CAMxB,CAAA;AAED,QAAA,MAAM,YAAY,WAAY,MAAM,WAGnC,CAAA;AAED,QAAA,MAAM,iBAAiB,wLAgBpB,sBAAsB,KAAG,uBAuU3B,CAAA;AAED,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,CAAA"}
@@ -38,6 +38,25 @@ export const formatSearchParamsAsNextQueryVariables = (searchParams) => {
38
38
  });
39
39
  return formattedParams;
40
40
  };
41
+ // URL params that only affect how the grid is laid out, never which products a
42
+ // collection/search returns. They MUST NOT enter the product cache key: in API
43
+ // mode this `searchParams` object is hashed into the server Redis key (the
44
+ // by-page route does `md5(JSON.stringify(body))`) and serialized into the
45
+ // client IDB cache key. Leaving `column` in meant column=2 and column=3 forked
46
+ // into two independent cache entries, each holding a snapshot of the same
47
+ // collection taken at a different time — so switching the column view could
48
+ // surface different (and independently-aged) products. Stripping them collapses
49
+ // every layout variant onto one shared cache entry.
50
+ export const LAYOUT_ONLY_QUERY_PARAMS = ["column"];
51
+ // Returns a copy of `params` with the layout-only keys removed (never mutates
52
+ // the input).
53
+ export const stripLayoutOnlyParams = (params) => {
54
+ const result = Object.assign({}, params);
55
+ for (const param of LAYOUT_ONLY_QUERY_PARAMS) {
56
+ delete result[param];
57
+ }
58
+ return result;
59
+ };
41
60
  const constructURL = (apiURL) => {
42
61
  const url = new URL(apiURL);
43
62
  return url.toString();
@@ -90,7 +109,7 @@ customFetcher, customGetKey, shouldSkipFetch: shouldSkipFetchProp, }) => {
90
109
  const queryVariables = useMemo(() => {
91
110
  if (usingSearchClient)
92
111
  return null;
93
- const formattedParams = formatSearchParamsAsNextQueryVariables(searchParams);
112
+ const formattedParams = stripLayoutOnlyParams(formatSearchParamsAsNextQueryVariables(searchParams));
94
113
  return Object.assign(Object.assign({}, queryVariableProps), { searchParams: formattedParams });
95
114
  }, [queryVariableProps, searchParams, usingSearchClient]);
96
115
  const apiGetKey = (pageIndex, previousPageData, queryVariables) => {
package/dist/styles.css CHANGED
@@ -1496,9 +1496,6 @@ video {
1496
1496
  .max-w-\[480px\] {
1497
1497
  max-width: 480px;
1498
1498
  }
1499
- .max-w-\[50\%\] {
1500
- max-width: 50%;
1501
- }
1502
1499
  .max-w-\[5rem\] {
1503
1500
  max-width: 5rem;
1504
1501
  }
@@ -1520,6 +1517,9 @@ video {
1520
1517
  .flex-1 {
1521
1518
  flex: 1 1 0%;
1522
1519
  }
1520
+ .flex-\[0_0_138px\] {
1521
+ flex: 0 0 138px;
1522
+ }
1523
1523
  .flex-\[0_0_226px\] {
1524
1524
  flex: 0 0 226px;
1525
1525
  }
@@ -1550,9 +1550,6 @@ video {
1550
1550
  .basis-\[300px\] {
1551
1551
  flex-basis: 300px;
1552
1552
  }
1553
- .basis-\[88\%\] {
1554
- flex-basis: 88%;
1555
- }
1556
1553
  .basis-full {
1557
1554
  flex-basis: 100%;
1558
1555
  }
@@ -1860,6 +1857,10 @@ video {
1860
1857
  -moz-column-gap: 0.5rem;
1861
1858
  column-gap: 0.5rem;
1862
1859
  }
1860
+ .gap-x-3 {
1861
+ -moz-column-gap: 0.75rem;
1862
+ column-gap: 0.75rem;
1863
+ }
1863
1864
  .gap-x-\[7px\] {
1864
1865
  -moz-column-gap: 7px;
1865
1866
  column-gap: 7px;
@@ -1867,6 +1868,9 @@ video {
1867
1868
  .gap-y-0 {
1868
1869
  row-gap: 0px;
1869
1870
  }
1871
+ .gap-y-1 {
1872
+ row-gap: 0.25rem;
1873
+ }
1870
1874
  .gap-y-2 {
1871
1875
  row-gap: 0.5rem;
1872
1876
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tapcart/mobile-components",
3
- "version": "0.13.1",
3
+ "version": "0.14.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "style": "dist/styles.css",