@tapcart/mobile-components 0.18.1 → 0.19.1

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.
Files changed (37) hide show
  1. package/dist/components/core/text.d.ts +1 -1
  2. package/dist/components/core/text.d.ts.map +1 -1
  3. package/dist/components/core/text.js +5 -1
  4. package/dist/components/hooks/use-create-question.d.ts +33 -0
  5. package/dist/components/hooks/use-create-question.d.ts.map +1 -0
  6. package/dist/components/hooks/use-create-question.js +98 -0
  7. package/dist/components/hooks/use-questions.d.ts +35 -0
  8. package/dist/components/hooks/use-questions.d.ts.map +1 -0
  9. package/dist/components/hooks/use-questions.js +198 -0
  10. package/dist/components/hooks/use-recommendations.d.ts.map +1 -1
  11. package/dist/components/hooks/use-recommendations.js +4 -3
  12. package/dist/components/ui/__tests__/drawer-glass-inset.test.d.ts +2 -0
  13. package/dist/components/ui/__tests__/drawer-glass-inset.test.d.ts.map +1 -0
  14. package/dist/components/ui/__tests__/drawer-glass-inset.test.js +84 -0
  15. package/dist/components/ui/__tests__/text-self-translates.test.d.ts +2 -0
  16. package/dist/components/ui/__tests__/text-self-translates.test.d.ts.map +1 -0
  17. package/dist/components/ui/__tests__/text-self-translates.test.js +19 -0
  18. package/dist/components/ui/drawer.d.ts.map +1 -1
  19. package/dist/components/ui/drawer.js +6 -1
  20. package/dist/components/ui/money.d.ts +1 -1
  21. package/dist/components/ui/money.d.ts.map +1 -1
  22. package/dist/components/ui/price.d.ts.map +1 -1
  23. package/dist/components/ui/price.js +1 -1
  24. package/dist/components/ui/video-enhanced.d.ts +1 -0
  25. package/dist/components/ui/video-enhanced.d.ts.map +1 -1
  26. package/dist/components/ui/video-enhanced.js +8 -2
  27. package/dist/core/index.d.ts +1 -0
  28. package/dist/core/index.d.ts.map +1 -1
  29. package/dist/core/index.js +1 -0
  30. package/dist/index.d.ts +2 -0
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +2 -0
  33. package/dist/lib/price.d.ts +1 -1
  34. package/dist/lib/price.d.ts.map +1 -1
  35. package/dist/lib/price.js +3 -0
  36. package/dist/styles.css +91 -13
  37. package/package.json +1 -1
@@ -8,7 +8,7 @@ type Injections = Record<string, {
8
8
  };
9
9
  }>;
10
10
  declare const textVariants: (props?: ({
11
- kind?: "title" | "caption" | "body" | "header" | "headline" | "subtitle" | null | undefined;
11
+ kind?: "title" | "caption" | "body" | "header" | "label" | "headline" | "subtitle" | null | undefined;
12
12
  } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
13
13
  export type TextKind = NonNullable<VariantProps<typeof textVariants>["kind"]>;
14
14
  export interface TextProps extends React.HTMLAttributes<HTMLParagraphElement> {
@@ -1 +1 @@
1
- {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../../components/core/text.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAQjE,KAAK,UAAU,GAAG,MAAM,CACtB,MAAM,EACN;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAC7E,CAAA;AAgDD,QAAA,MAAM,YAAY;;mFAchB,CAAA;AAEF,MAAM,MAAM,QAAQ,GAAG,WAAW,CAAC,YAAY,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;AAE7E,MAAM,WAAW,SAAU,SAAQ,KAAK,CAAC,cAAc,CAAC,oBAAoB,CAAC;IAC3E,IAAI,CAAC,EAAE,QAAQ,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAC3B;AAED,iBAAS,IAAI,CAAC,EACZ,SAAS,EACT,IAAI,EACJ,SAAS,EACT,UAAU,EACV,UAAU,EACV,QAAQ,EACR,aAAa,EACb,UAAU,EACV,QAAQ,EACR,KAAK,EACL,GAAG,KAAK,EACT,EAAE,SAAS,2CAyCX;kBArDQ,IAAI;;;AAyDb,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,CAAA"}
1
+ {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../../components/core/text.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAQjE,KAAK,UAAU,GAAG,MAAM,CACtB,MAAM,EACN;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAC7E,CAAA;AAmDD,QAAA,MAAM,YAAY;;mFAehB,CAAA;AAEF,MAAM,MAAM,QAAQ,GAAG,WAAW,CAAC,YAAY,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;AAE7E,MAAM,WAAW,SAAU,SAAQ,KAAK,CAAC,cAAc,CAAC,oBAAoB,CAAC;IAC3E,IAAI,CAAC,EAAE,QAAQ,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAC3B;AAED,iBAAS,IAAI,CAAC,EACZ,SAAS,EACT,IAAI,EACJ,SAAS,EACT,UAAU,EACV,UAAU,EACV,QAAQ,EACR,aAAa,EACb,UAAU,EACV,QAAQ,EACR,KAAK,EACL,GAAG,KAAK,EACT,EAAE,SAAS,2CAyCX;kBArDQ,IAAI;;;AAyDb,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,CAAA"}
@@ -44,7 +44,10 @@ function injectString(template, injections) {
44
44
  }
45
45
  return parts.length ? parts : undefined;
46
46
  }
47
- // V2 kind tokens only — no legacy h1/h2/h3/body-primary/body-secondary/label.
47
+ // V2 kind tokens only — no legacy h1/h2/h3/body-primary/body-secondary.
48
+ // `label` is a first-class V2 scale (brand-label lives in TYPOGRAPHY_DEFAULTS /
49
+ // TYPOGRAPHY_CLASS_MAP / ElementTypographyClasses with full overrides), so it
50
+ // belongs here alongside the other kinds.
48
51
  const textVariants = cva("", {
49
52
  variants: {
50
53
  kind: {
@@ -53,6 +56,7 @@ const textVariants = cva("", {
53
56
  subtitle: "brand-subtitle",
54
57
  body: "brand-body",
55
58
  caption: "brand-caption",
59
+ label: "brand-label",
56
60
  header: "brand-header",
57
61
  },
58
62
  },
@@ -0,0 +1,33 @@
1
+ type CreateQuestionInput = {
2
+ provider: string;
3
+ productId: string;
4
+ productHandle?: string;
5
+ productTitle?: string;
6
+ productUrl?: string;
7
+ displayName: string;
8
+ email: string;
9
+ questionContent: string;
10
+ };
11
+ type UseCreateQuestionProps = {
12
+ baseURL: string;
13
+ };
14
+ type CreateQuestionOutcome = {
15
+ ok: boolean;
16
+ };
17
+ type UseCreateQuestionReturn = {
18
+ createQuestion: (input: CreateQuestionInput) => Promise<CreateQuestionOutcome>;
19
+ isSubmitting: boolean;
20
+ isSuccess: boolean;
21
+ error: string | null;
22
+ reset: () => void;
23
+ };
24
+ /**
25
+ * Mutation counterpart to `useQuestions`. Submits a new question through the
26
+ * app-scoped API route (`POST {baseURL}/questions/create`), which proxies to
27
+ * the Q&A provider (currently Yotpo only). Yotpo emails the asker a
28
+ * confirmation link; the question appears after email confirmation and
29
+ * merchant moderation.
30
+ */
31
+ export declare function useCreateQuestion({ baseURL, }: UseCreateQuestionProps): UseCreateQuestionReturn;
32
+ export {};
33
+ //# sourceMappingURL=use-create-question.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-create-question.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-create-question.ts"],"names":[],"mappings":"AAGA,KAAK,mBAAmB,GAAG;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IAGjB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,eAAe,EAAE,MAAM,CAAA;CACxB,CAAA;AAED,KAAK,sBAAsB,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,KAAK,qBAAqB,GAAG;IAC3B,EAAE,EAAE,OAAO,CAAA;CACZ,CAAA;AAED,KAAK,uBAAuB,GAAG;IAC7B,cAAc,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,OAAO,CAAC,qBAAqB,CAAC,CAAA;IAC9E,YAAY,EAAE,OAAO,CAAA;IACrB,SAAS,EAAE,OAAO,CAAA;IAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,KAAK,EAAE,MAAM,IAAI,CAAA;CAClB,CAAA;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,OAAO,GACR,EAAE,sBAAsB,GAAG,uBAAuB,CAkFlD"}
@@ -0,0 +1,98 @@
1
+ "use client";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ import { useCallback, useEffect, useRef, useState } from "react";
12
+ /**
13
+ * Mutation counterpart to `useQuestions`. Submits a new question through the
14
+ * app-scoped API route (`POST {baseURL}/questions/create`), which proxies to
15
+ * the Q&A provider (currently Yotpo only). Yotpo emails the asker a
16
+ * confirmation link; the question appears after email confirmation and
17
+ * merchant moderation.
18
+ */
19
+ export function useCreateQuestion({ baseURL, }) {
20
+ const [isSubmitting, setIsSubmitting] = useState(false);
21
+ const [isSuccess, setIsSuccess] = useState(false);
22
+ const [error, setError] = useState(null);
23
+ // Track the in-flight request so a closing/reset drawer can abort it; a
24
+ // late resolution must not write success/error state onto a form the user
25
+ // left.
26
+ const createAbortRef = useRef(null);
27
+ const createQuestion = useCallback((input) => __awaiter(this, void 0, void 0, function* () {
28
+ setIsSubmitting(true);
29
+ setError(null);
30
+ const controller = new AbortController();
31
+ createAbortRef.current = controller;
32
+ try {
33
+ const response = yield fetch(`${baseURL}/questions/create`, {
34
+ method: "POST",
35
+ headers: { "Content-Type": "application/json" },
36
+ body: JSON.stringify(input),
37
+ signal: controller.signal,
38
+ });
39
+ if (!response.ok) {
40
+ let message = "Something went wrong. Please try again.";
41
+ // Only surface the server's message for client errors (validation
42
+ // strings meant for the user). 5xx bodies can carry internal error
43
+ // detail and get the generic copy instead.
44
+ if (response.status >= 400 && response.status < 500) {
45
+ try {
46
+ const body = yield response.json();
47
+ if (typeof (body === null || body === void 0 ? void 0 : body.error) === "string") {
48
+ message = body.error;
49
+ }
50
+ }
51
+ catch (_a) {
52
+ // non-JSON error body; keep the generic message
53
+ }
54
+ }
55
+ setError(message);
56
+ return { ok: false };
57
+ }
58
+ setIsSuccess(true);
59
+ return { ok: true };
60
+ }
61
+ catch (error) {
62
+ // Aborted because the drawer closed — leave state untouched so a
63
+ // reopened drawer isn't painted with this abandoned submission.
64
+ if (controller.signal.aborted)
65
+ return { ok: false };
66
+ console.error("Error creating question:", error);
67
+ setError("Something went wrong. Please try again.");
68
+ return { ok: false };
69
+ }
70
+ finally {
71
+ setIsSubmitting(false);
72
+ }
73
+ }), [baseURL]);
74
+ const reset = useCallback(() => {
75
+ var _a;
76
+ // Cancel any in-flight request so it can't resolve into stale UI state.
77
+ (_a = createAbortRef.current) === null || _a === void 0 ? void 0 : _a.abort();
78
+ setIsSubmitting(false);
79
+ setIsSuccess(false);
80
+ setError(null);
81
+ }, []);
82
+ // The drawer only wires reset() to its own close; if the whole subtree
83
+ // unmounts mid-submit (accordion collapse, navigation), abort here too so
84
+ // the request is actually cancelled.
85
+ useEffect(() => {
86
+ return () => {
87
+ var _a;
88
+ (_a = createAbortRef.current) === null || _a === void 0 ? void 0 : _a.abort();
89
+ };
90
+ }, []);
91
+ return {
92
+ createQuestion,
93
+ isSubmitting,
94
+ isSuccess,
95
+ error,
96
+ reset,
97
+ };
98
+ }
@@ -0,0 +1,35 @@
1
+ import { QnaSummaryData, QnaSearchData } from "app-studio-types";
2
+ type UseQuestionsProps = {
3
+ baseURL: string;
4
+ productId: string;
5
+ provider: string;
6
+ fetcher?: (url: string) => Promise<any>;
7
+ dataType: "summary" | "search" | null;
8
+ perPage?: number;
9
+ page?: number;
10
+ };
11
+ type UseQuestionsReturn = {
12
+ data: QnaSummaryData | QnaSearchData | null;
13
+ error: any;
14
+ isLoading: boolean;
15
+ questionsMockData?: any;
16
+ mockQnaSummaryData?: QnaSummaryData;
17
+ };
18
+ /**
19
+ * Read counterpart to `useReviews` for Q&A. Fetches the question summary
20
+ * (total questions/answers) or a page of questions through the app-scoped
21
+ * API route (`GET {baseURL}/questions/by-id`), which proxies to the Q&A
22
+ * provider (currently Yotpo only) with the merchant key held server-side.
23
+ */
24
+ export declare function useQuestions(props: UseQuestionsProps | null): UseQuestionsReturn;
25
+ type UseQuestionsInfiniteReturn = UseQuestionsReturn & {
26
+ ref: (node?: Element | null) => void;
27
+ retry: () => void;
28
+ };
29
+ /**
30
+ * Infinite-scroll variant for the question list, mirroring
31
+ * `useReviewsInfinite` (page-number pagination against pagination.total).
32
+ */
33
+ export declare function useQuestionsInfinite(props: UseQuestionsProps | null): UseQuestionsInfiniteReturn;
34
+ export {};
35
+ //# sourceMappingURL=use-questions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-questions.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-questions.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAGhE,KAAK,iBAAiB,GAAG;IACvB,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;IAGvC,QAAQ,EAAE,SAAS,GAAG,QAAQ,GAAG,IAAI,CAAA;IACrC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,KAAK,kBAAkB,GAAG;IACxB,IAAI,EAAE,cAAc,GAAG,aAAa,GAAG,IAAI,CAAA;IAC3C,KAAK,EAAE,GAAG,CAAA;IACV,SAAS,EAAE,OAAO,CAAA;IAClB,iBAAiB,CAAC,EAAE,GAAG,CAAA;IACvB,kBAAkB,CAAC,EAAE,cAAc,CAAA;CACpC,CAAA;AAsFD;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,iBAAiB,GAAG,IAAI,GAC9B,kBAAkB,CAsCpB;AAED,KAAK,0BAA0B,GAAG,kBAAkB,GAAG;IACrD,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,KAAK,IAAI,CAAA;IACpC,KAAK,EAAE,MAAM,IAAI,CAAA;CAClB,CAAA;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,iBAAiB,GAAG,IAAI,GAC9B,0BAA0B,CAsG5B"}
@@ -0,0 +1,198 @@
1
+ "use client";
2
+ import { useCallback, useEffect, useRef } from "react";
3
+ import useSWR from "swr";
4
+ import useSWRInfinite from "swr/infinite";
5
+ import { useInView } from "react-intersection-observer";
6
+ const YOTPO = "yotpo";
7
+ const SUPPORTED_PROVIDERS = [YOTPO];
8
+ // Placeholder Q&A rendered in the dashboard preview (where there's no live
9
+ // product), mirroring reviewsMockData in use-reviews.
10
+ const questionsMockData = [
11
+ {
12
+ id: 1,
13
+ content: "Does this run true to size?",
14
+ date: "2024-10-10T00:00:00.000Z",
15
+ asker: {
16
+ displayName: "Name",
17
+ },
18
+ answers: [
19
+ {
20
+ id: 11,
21
+ content: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua...",
22
+ date: "2024-10-11T00:00:00.000Z",
23
+ storeOwner: true,
24
+ answerer: {
25
+ displayName: "Store Owner",
26
+ },
27
+ },
28
+ ],
29
+ },
30
+ {
31
+ id: 2,
32
+ content: "Is this machine washable?",
33
+ date: "2024-08-10T00:00:00.000Z",
34
+ asker: {
35
+ displayName: "Name",
36
+ },
37
+ answers: [
38
+ {
39
+ id: 21,
40
+ content: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
41
+ date: "2024-08-11T00:00:00.000Z",
42
+ storeOwner: false,
43
+ answerer: {
44
+ displayName: "Name",
45
+ },
46
+ },
47
+ ],
48
+ },
49
+ ];
50
+ const mockQnaSummaryData = {
51
+ totalQuestions: questionsMockData.length,
52
+ totalAnswers: questionsMockData.reduce((sum, question) => sum + question.answers.length, 0),
53
+ };
54
+ // Shared by both hooks. The route 404s when the yotpo-qa flag is off or the
55
+ // merchant's Yotpo plan lacks Q&A; surface that as an error (not data) so
56
+ // the block hides the Q&A row.
57
+ const defaultFetcher = (url) => fetch(url).then((res) => {
58
+ if (!res.ok)
59
+ throw new Error(`questions request failed: ${res.status}`);
60
+ return res.json();
61
+ });
62
+ function buildQueryParams(props) {
63
+ var _a, _b;
64
+ const queryParams = new URLSearchParams();
65
+ if (((_a = props.productId) === null || _a === void 0 ? void 0 : _a.length) > 0) {
66
+ queryParams.set("id", props.productId);
67
+ }
68
+ if (((_b = props.provider) === null || _b === void 0 ? void 0 : _b.length) > 0) {
69
+ queryParams.set("provider", props.provider);
70
+ }
71
+ queryParams.set("dataType", props.dataType);
72
+ if (props.perPage) {
73
+ queryParams.set("perPage", String(props.perPage));
74
+ }
75
+ return queryParams;
76
+ }
77
+ /**
78
+ * Read counterpart to `useReviews` for Q&A. Fetches the question summary
79
+ * (total questions/answers) or a page of questions through the app-scoped
80
+ * API route (`GET {baseURL}/questions/by-id`), which proxies to the Q&A
81
+ * provider (currently Yotpo only) with the merchant key held server-side.
82
+ */
83
+ export function useQuestions(props) {
84
+ let url = null;
85
+ if (props) {
86
+ const queryParams = buildQueryParams(props);
87
+ if (props.page) {
88
+ queryParams.set("page", String(props.page));
89
+ }
90
+ if (props.dataType === null ||
91
+ !props.productId ||
92
+ !SUPPORTED_PROVIDERS.includes(props.provider)) {
93
+ url = null;
94
+ }
95
+ else {
96
+ url = `${props.baseURL}/questions/by-id?${queryParams.toString()}`;
97
+ }
98
+ }
99
+ const fetcher = (props === null || props === void 0 ? void 0 : props.fetcher) || defaultFetcher;
100
+ const { data, error } = useSWR(url, fetcher, {
101
+ revalidateOnFocus: false,
102
+ revalidateOnReconnect: false,
103
+ revalidateIfStale: false,
104
+ dedupingInterval: 60000,
105
+ // The 404 from a disabled flag/plan is an expected state, not a
106
+ // transient failure — don't let SWR retry-loop the probe.
107
+ shouldRetryOnError: false,
108
+ });
109
+ return {
110
+ data: data || null,
111
+ error,
112
+ isLoading: Boolean(url) && !data && !error,
113
+ questionsMockData,
114
+ mockQnaSummaryData,
115
+ };
116
+ }
117
+ /**
118
+ * Infinite-scroll variant for the question list, mirroring
119
+ * `useReviewsInfinite` (page-number pagination against pagination.total).
120
+ */
121
+ export function useQuestionsInfinite(props) {
122
+ var _a, _b;
123
+ const { ref, inView } = useInView({ rootMargin: "800px" });
124
+ const isEndReached = useRef(false);
125
+ const getKey = (pageIndex, previousPageData) => {
126
+ if (!props ||
127
+ props.dataType == null ||
128
+ !props.productId ||
129
+ !SUPPORTED_PROVIDERS.includes(props.provider)) {
130
+ return null;
131
+ }
132
+ if (previousPageData && previousPageData.pagination) {
133
+ const { perPage, total } = previousPageData.pagination;
134
+ isEndReached.current = (pageIndex + 1) * perPage >= total;
135
+ }
136
+ const queryParams = buildQueryParams(props);
137
+ return `${props.baseURL}/questions/by-id?${queryParams.toString()}&page=${pageIndex + 1}`;
138
+ };
139
+ const fetcher = (props === null || props === void 0 ? void 0 : props.fetcher) || defaultFetcher;
140
+ const { data: dataInfinite, error: errorInfinite, size, setSize, isLoading, isValidating, mutate, } = useSWRInfinite(getKey, fetcher, {
141
+ revalidateOnFocus: false,
142
+ revalidateOnReconnect: false,
143
+ revalidateIfStale: false,
144
+ dedupingInterval: 60000,
145
+ // Failures surface in the block's error state with a manual retry;
146
+ // don't also auto-retry on backoff.
147
+ shouldRetryOnError: false,
148
+ });
149
+ const mergedQuestions = dataInfinite
150
+ ? dataInfinite
151
+ .filter((page) => page && page.questions)
152
+ .flatMap((page) => page.questions)
153
+ : [];
154
+ const searchResponse = {
155
+ pagination: (dataInfinite === null || dataInfinite === void 0 ? void 0 : dataInfinite.length) ? dataInfinite[0].pagination : null,
156
+ questions: mergedQuestions,
157
+ };
158
+ // Recomputed from the loaded pages: once page 1 has landed, we've reached
159
+ // the end when everything the pagination promised is loaded — including
160
+ // total === 0 (e.g. all questions pending moderation), which must not
161
+ // keep loadMore incrementing size forever.
162
+ isEndReached.current = (dataInfinite === null || dataInfinite === void 0 ? void 0 : dataInfinite.length)
163
+ ? mergedQuestions.length >= ((_b = (_a = searchResponse.pagination) === null || _a === void 0 ? void 0 : _a.total) !== null && _b !== void 0 ? _b : 0)
164
+ : false;
165
+ const loadMore = useCallback(() => {
166
+ if (!isLoading && !isValidating && !isEndReached.current) {
167
+ setSize(size + 1);
168
+ }
169
+ }, [isLoading, isValidating, setSize, size]);
170
+ useEffect(() => {
171
+ if (inView) {
172
+ loadMore();
173
+ }
174
+ }, [inView, loadMore]);
175
+ // Reset on the real fetch inputs, not the props object (the block passes a
176
+ // fresh literal every render, which would make an object-keyed effect fire
177
+ // on every commit).
178
+ const productId = props === null || props === void 0 ? void 0 : props.productId;
179
+ const dataType = props === null || props === void 0 ? void 0 : props.dataType;
180
+ const provider = props === null || props === void 0 ? void 0 : props.provider;
181
+ useEffect(() => {
182
+ isEndReached.current = false;
183
+ }, [productId, dataType, provider]);
184
+ // Revalidates every loaded page — the block's error state wires this to a
185
+ // "Try Again" button.
186
+ const retry = useCallback(() => {
187
+ mutate();
188
+ }, [mutate]);
189
+ return {
190
+ data: searchResponse,
191
+ error: errorInfinite,
192
+ isLoading: isValidating,
193
+ ref,
194
+ retry,
195
+ questionsMockData,
196
+ mockQnaSummaryData,
197
+ };
198
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"use-recommendations.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-recommendations.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAOxE,UAAU,sBAAsB;IAE9B,YAAY,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IACxC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAGxC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACnC,MAAM,EAAE,MAAM,CAAA;IAEd;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAUD,UAAU,uBAAuB;IAC/B,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,WAAW,EAAE,UAAU,EAAE,CAAA;IACzB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,MAAM,EAAE,GAAG,EAAE,CAAA;IACb,SAAS,EAAE,OAAO,CAAA;IAClB,KAAK,EAAE,GAAG,CAAA;CACX;AAmBD,QAAA,MAAM,kBAAkB,kFAWrB,sBAAsB,KAAG,uBA8H3B,CAAA;AAED,OAAO,EAAE,kBAAkB,EAAE,CAAA"}
1
+ {"version":3,"file":"use-recommendations.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-recommendations.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAOxE,UAAU,sBAAsB;IAE9B,YAAY,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IACxC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAGxC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACnC,MAAM,EAAE,MAAM,CAAA;IAEd;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAUD,UAAU,uBAAuB;IAC/B,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,WAAW,EAAE,UAAU,EAAE,CAAA;IACzB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,MAAM,EAAE,GAAG,EAAE,CAAA;IACb,SAAS,EAAE,OAAO,CAAA;IAClB,KAAK,EAAE,GAAG,CAAA;CACX;AAqBD,QAAA,MAAM,kBAAkB,kFAWrB,sBAAsB,KAAG,uBA8H3B,CAAA;AAED,OAAO,EAAE,kBAAkB,EAAE,CAAA"}
@@ -17,9 +17,10 @@ const constructURL = (apiURL) => {
17
17
  return url.toString();
18
18
  };
19
19
  const getCollections = (collections) => {
20
- return collections
21
- ? collections === null || collections === void 0 ? void 0 : collections.filter((obj) => obj.handle !== "empty-collection")
22
- : [];
20
+ if (!Array.isArray(collections)) {
21
+ return [];
22
+ }
23
+ return collections.filter((obj) => obj.handle !== "empty-collection");
23
24
  };
24
25
  const recommendationsLocalStorage = new RecommendationsLocalStorage();
25
26
  const MIN_QUERY_LENGTH = 3;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=drawer-glass-inset.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drawer-glass-inset.test.d.ts","sourceRoot":"","sources":["../../../../components/ui/__tests__/drawer-glass-inset.test.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,84 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import * as fs from "fs";
3
+ import * as path from "path";
4
+ import { render, screen } from "@testing-library/react";
5
+ import { Drawer, DrawerContentBase } from "../drawer";
6
+ // A bottom sheet portals to <body> and pins itself with `position: fixed;
7
+ // bottom: 0`, so it lives OUTSIDE #tc-vgsl and never receives the frame
8
+ // clearance that element carries. Its bottom cushion is therefore the only
9
+ // thing keeping content off an overlay bottom bar (iOS Liquid Glass).
10
+ //
11
+ // `pb-safe` alone is just env(safe-area-inset-bottom) - the home indicator,
12
+ // not the bar. `tc-pb-frame` is the glass-gated rule in styles/globals.css
13
+ // that raises the cushion to max(env(safe-area-inset-bottom),
14
+ // --tc-frame-bottom). jsdom does not evaluate the cascade, so this asserts the
15
+ // contract the stylesheet keys off; the geometry itself is proven in the
16
+ // browser A/B (qa-evidence/glass-sheet-insets).
17
+ describe("DrawerContentBase bottom-overlay clearance", () => {
18
+ it("carries both the legacy safe cushion and the glass frame cushion", () => {
19
+ render(_jsx(Drawer, Object.assign({ open: true }, { children: _jsx(DrawerContentBase, { children: "content" }) })));
20
+ const sheet = screen.getByTestId("drawer-content");
21
+ expect(sheet.className).toContain("pb-safe");
22
+ expect(sheet.className).toContain("tc-pb-frame");
23
+ });
24
+ it("keeps the cushion when a caller passes its own className", () => {
25
+ render(_jsx(Drawer, Object.assign({ open: true }, { children: _jsx(DrawerContentBase, Object.assign({ className: "bg-red-500" }, { children: "content" })) })));
26
+ const sheet = screen.getByTestId("drawer-content");
27
+ expect(sheet.className).toContain("tc-pb-frame");
28
+ expect(sheet.className).toContain("bg-red-500");
29
+ });
30
+ // FORWARD GUARD, not proof of the glass fix: this assertion is already green
31
+ // on the pre-fix component, because `bottom-0` predates it. It exists to go
32
+ // red if someone later moves the clearance out of padding and into `bottom`.
33
+ it("stays anchored to the bottom edge instead of floating above the bar", () => {
34
+ // The clearance must live in padding, not in `bottom`: the sheet surface
35
+ // keeps bleeding to the physical bottom edge the way a native sheet does,
36
+ // and only its CONTENT is lifted. A `bottom` offset would leave a strip of
37
+ // backdrop under the sheet.
38
+ render(_jsx(Drawer, Object.assign({ open: true }, { children: _jsx(DrawerContentBase, { children: "content" }) })));
39
+ const sheet = screen.getByTestId("drawer-content");
40
+ expect(sheet.className).toContain("bottom-0");
41
+ expect(sheet.style.bottom).toBe("");
42
+ });
43
+ // The two assertions above only pin the class NAME. jest has no CSS
44
+ // transform and the component imports no stylesheet, so deleting or renaming
45
+ // the rule in styles/globals.css would leave them green while the clearance
46
+ // silently stopped existing. This closes that drift: it reads the AUTHORED
47
+ // stylesheet (styles/globals.css) and checks a rule really is keyed to the
48
+ // class the component emits, with the right variable in it.
49
+ //
50
+ // Source, not dist/: dist/styles.css is gitignored and only exists after a
51
+ // build, so asserting against it would make this test pass or fail on build
52
+ // state rather than on the committed CSS. The build step for this file is
53
+ // postcss with no selector rewriting, so source and shipped agree - but the
54
+ // guard is on the input, and a transform that ever changed that would slip
55
+ // past it.
56
+ it("has a stylesheet rule keyed to the class the component emits", () => {
57
+ render(_jsx(Drawer, Object.assign({ open: true }, { children: _jsx(DrawerContentBase, { children: "content" }) })));
58
+ const emitted = screen
59
+ .getByTestId("drawer-content")
60
+ .className.split(/\s+/)
61
+ .find((c) => c === "tc-pb-frame");
62
+ expect(emitted).toBe("tc-pb-frame");
63
+ const css = fs
64
+ .readFileSync(path.join(__dirname, "../../../styles/globals.css"), "utf8")
65
+ // Comments in this file quote CSS ("pin themselves with position: fixed;
66
+ // bottom: 0"), which would otherwise be read as declarations below.
67
+ .replace(/\/\*[\s\S]*?\*\//g, "");
68
+ // Whole selector token: a substring match would still find the class
69
+ // inside a renamed `.tc-pb-frame-something`, which is exactly the drift
70
+ // this test exists to catch.
71
+ const selector = new RegExp(`\\.${emitted}(?![\\w-])`);
72
+ const rule = css
73
+ .split("}")
74
+ .map((block) => block + "}")
75
+ .find((block) => selector.test(block) && block.includes("padding-bottom"));
76
+ expect(rule).toBeDefined();
77
+ // Glass-gated, and reading the frame inset rather than a hardcoded value.
78
+ expect(rule).toContain("tc-glass");
79
+ expect(rule).toContain("--tc-frame-bottom");
80
+ // Clearance lives in padding, never in `bottom`. Anchored to a declaration
81
+ // start so it does not also match the `bottom` inside `padding-bottom`.
82
+ expect(rule).not.toMatch(/[;{]\s*bottom:/);
83
+ });
84
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=text-self-translates.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-self-translates.test.d.ts","sourceRoot":"","sources":["../../../../components/ui/__tests__/text-self-translates.test.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { render, screen } from "@testing-library/react";
3
+ import { Text } from "../text";
4
+ import { TranslationProvider } from "../../contexts/translation-context";
5
+ // Block code relies on this: <Text> translates its own children via
6
+ // TranslationContext, so callers must NOT pre-translate text that only
7
+ // ever reaches the DOM through <Text> (see ShareButton/ReferralCode).
8
+ describe("Text self-translation via TranslationContext", () => {
9
+ it("translates plain children with no explicit lookup at the call site", () => {
10
+ render(_jsx(TranslationProvider, Object.assign({ translations: {
11
+ "share with your friends": "Compartir con tus amigos",
12
+ } }, { children: _jsx(Text, { children: "Share with your friends" }) })));
13
+ expect(screen.getByText("Compartir con tus amigos")).not.toBeNull();
14
+ });
15
+ it("falls back to the raw children when no provider is mounted", () => {
16
+ render(_jsx(Text, { children: "Share with your friends" }));
17
+ expect(screen.getByText("Share with your friends")).not.toBeNull();
18
+ });
19
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"drawer.d.ts","sourceRoot":"","sources":["../../../components/ui/drawer.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,MAAM,CAAA;AAKhD,KAAK,kBAAkB,GAAG,KAAK,CAAC,wBAAwB,CAAC,QAAQ,CAAC,GAAG;IACnE,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,KAAK,iBAAiB,GAAG;IACvB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,YAAY,CAAC,EAAE,WAAW,CAAA;CAC3B,CAAA;AAED,KAAK,gBAAgB,GAAG,KAAK,CAAC,wBAAwB,CAAC,QAAQ,CAAC,GAAG;IACjE,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,QAAA,MAAM,aAAa,8BAA0D,CAAA;AAG7E,QAAA,MAAM,YAAY;iCAAgC,iBAAiB;;CAgBlE,CAAA;AAGD,QAAA,MAAM,WAAW,4BAAsD,CAAA;AAGvE,KAAK,WAAW,GAAG,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,IAAI,CAAC,GAAG;IACrE,YAAY,CAAC,EAAE,WAAW,CAAA;CAC3B,CAAA;AAED,QAAA,MAAM,MAAM;0CAAyC,WAAW;;CAS/D,CAAA;AAOD,QAAA,MAAM,aAAa;;wCAYlB,CAAA;AAWD,QAAA,MAAM,iBAAiB;;;;;;wCA2CtB,CAAA;AAWD,QAAA,MAAM,WAAW,qLAYf,CAAA;AAGF,QAAA,MAAM,YAAY;8BAGf,MAAM,cAAc,CAAC,cAAc,CAAC;;CAQtC,CAAA;AAGD,QAAA,MAAM,iBAAiB,+LASrB,CAAA;AAGF,KAAK,iBAAiB,GAAG;IACvB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,KAAK,EAAE,MAAM,CAAA;IACb,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAA;CACjD,CAAA;AAED,QAAA,MAAM,YAAY,0DAKf,iBAAiB,4CA8BnB,CAAA;AAED,QAAA,MAAM,aAAa,sCAIhB,MAAM,cAAc,CAAC,cAAc,CAAC,4CAMtC,CAAA;AAED,OAAO,EACL,MAAM,EACN,YAAY,EACZ,aAAa,EACb,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,aAAa,EACb,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,YAAY,GACb,CAAA"}
1
+ {"version":3,"file":"drawer.d.ts","sourceRoot":"","sources":["../../../components/ui/drawer.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,MAAM,CAAA;AAKhD,KAAK,kBAAkB,GAAG,KAAK,CAAC,wBAAwB,CAAC,QAAQ,CAAC,GAAG;IACnE,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,KAAK,iBAAiB,GAAG;IACvB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,YAAY,CAAC,EAAE,WAAW,CAAA;CAC3B,CAAA;AAED,KAAK,gBAAgB,GAAG,KAAK,CAAC,wBAAwB,CAAC,QAAQ,CAAC,GAAG;IACjE,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,QAAA,MAAM,aAAa,8BAA0D,CAAA;AAG7E,QAAA,MAAM,YAAY;iCAAgC,iBAAiB;;CAgBlE,CAAA;AAGD,QAAA,MAAM,WAAW,4BAAsD,CAAA;AAGvE,KAAK,WAAW,GAAG,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,IAAI,CAAC,GAAG;IACrE,YAAY,CAAC,EAAE,WAAW,CAAA;CAC3B,CAAA;AAED,QAAA,MAAM,MAAM;0CAAyC,WAAW;;CAS/D,CAAA;AAOD,QAAA,MAAM,aAAa;;wCAYlB,CAAA;AAWD,QAAA,MAAM,iBAAiB;;;;;;wCA+CtB,CAAA;AAWD,QAAA,MAAM,WAAW,qLAYf,CAAA;AAGF,QAAA,MAAM,YAAY;8BAGf,MAAM,cAAc,CAAC,cAAc,CAAC;;CAQtC,CAAA;AAGD,QAAA,MAAM,iBAAiB,+LASrB,CAAA;AAGF,KAAK,iBAAiB,GAAG;IACvB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,KAAK,EAAE,MAAM,CAAA;IACb,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAA;CACjD,CAAA;AAED,QAAA,MAAM,YAAY,0DAKf,iBAAiB,4CA8BnB,CAAA;AAED,QAAA,MAAM,aAAa,sCAIhB,MAAM,cAAc,CAAC,cAAc,CAAC,4CAMtC,CAAA;AAED,OAAO,EACL,MAAM,EACN,YAAY,EACZ,aAAa,EACb,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,aAAa,EACb,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,YAAY,GACb,CAAA"}
@@ -51,7 +51,12 @@ const DrawerContentBase = React.forwardRef((_a, ref) => {
51
51
  const baseStyles = isSheet
52
52
  ? { height: "calc(100dvh - 112px)" }
53
53
  : { maxHeight: maxHeight || "calc(100dvh - 112px)" };
54
- return (_jsxs(DrawerPortal, Object.assign({ containerRef: containerRef }, { children: [hideBackdrop ? null : (_jsx(DrawerOverlay, { backdropHexColor: backdropHexColor })), _jsxs(DrawerPrimitive.Content, Object.assign({ ref: ref, style: Object.assign(Object.assign({}, baseStyles), style), className: cn("fixed inset-x-0 bottom-0 z-50 flex h-auto flex-col rounded-t-2xl bg-coreColors-modalBackground pb-safe", className) }, props, { "data-testid": "drawer-content" }, { children: [_jsx("div", { className: "mx-auto mb-2 mt-2 h-[4px] w-[40px] rounded-full bg-coreColors-dividingLines" }), children] }))] })));
54
+ return (_jsxs(DrawerPortal, Object.assign({ containerRef: containerRef }, { children: [hideBackdrop ? null : (_jsx(DrawerOverlay, { backdropHexColor: backdropHexColor })), _jsxs(DrawerPrimitive.Content, Object.assign({ ref: ref, style: Object.assign(Object.assign({}, baseStyles), style), className: cn(
55
+ // tc-pb-frame: bottom-overlay (iOS Liquid Glass) clearance. The
56
+ // sheet is viewport-anchored, so it never inherits #tc-vgsl's
57
+ // --tc-frame-bottom padding; see styles/globals.css. Inert off
58
+ // glass, where pb-safe alone stays authoritative.
59
+ "fixed inset-x-0 bottom-0 z-50 flex h-auto flex-col rounded-t-2xl bg-coreColors-modalBackground pb-safe tc-pb-frame", className) }, props, { "data-testid": "drawer-content" }, { children: [_jsx("div", { className: "mx-auto mb-2 mt-2 h-[4px] w-[40px] rounded-full bg-coreColors-dividingLines" }), children] }))] })));
55
60
  });
56
61
  DrawerContentBase.displayName = "DrawerContentBase";
57
62
  const DrawerHeaderBase = (_a) => {
@@ -6,7 +6,7 @@ interface MoneyType {
6
6
  price: number;
7
7
  }
8
8
  declare const moneyVariants: (props?: ({} & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
9
- export interface MoneyProps extends MoneyType, VariantProps<typeof moneyVariants> {
9
+ export interface MoneyProps extends MoneyType, VariantProps<typeof moneyVariants>, React.HTMLAttributes<HTMLSpanElement> {
10
10
  hideZeroCents?: boolean;
11
11
  styles?: React.CSSProperties;
12
12
  }
@@ -1 +1 @@
1
- {"version":3,"file":"money.d.ts","sourceRoot":"","sources":["../../../components/ui/money.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAGjE,UAAU,SAAS;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;CACd;AAED,QAAA,MAAM,aAAa,gGAMjB,CAAA;AAEF,MAAM,WAAW,UACf,SAAQ,SAAS,EACf,YAAY,CAAC,OAAO,aAAa,CAAC;IACpC,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,MAAM,CAAC,EAAE,KAAK,CAAC,aAAa,CAAA;CAC7B;AAED,iBAAS,KAAK,CAAC,EACb,KAAK,EACL,MAAM,EACN,QAAQ,EACR,aAAqB,EACrB,MAAM,EACN,GAAG,KAAK,EACT,EAAE,UAAU,2CAiFZ;AAED,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,CAAA"}
1
+ {"version":3,"file":"money.d.ts","sourceRoot":"","sources":["../../../components/ui/money.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAGjE,UAAU,SAAS;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;CACd;AAED,QAAA,MAAM,aAAa,gGAMjB,CAAA;AAEF,MAAM,WAAW,UACf,SAAQ,SAAS,EACf,YAAY,CAAC,OAAO,aAAa,CAAC,EAClC,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC;IACvC,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,MAAM,CAAC,EAAE,KAAK,CAAC,aAAa,CAAA;CAC7B;AAED,iBAAS,KAAK,CAAC,EACb,KAAK,EACL,MAAM,EACN,QAAQ,EACR,aAAqB,EACrB,MAAM,EACN,GAAG,KAAK,EACT,EAAE,UAAU,2CAiFZ;AAED,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"price.d.ts","sourceRoot":"","sources":["../../../components/ui/price.tsx"],"names":[],"mappings":";AAIA,UAAU,UAAU;IAClB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACnC,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,EAAE,CAAA;IAChD,cAAc,CAAC,EAAE,KAAK,CAAC,aAAa,CAAA;IACpC,UAAU,CAAC,EAAE,KAAK,CAAC,aAAa,CAAA;IAChC,mBAAmB,CAAC,EAAE,KAAK,CAAC,aAAa,CAAA;CAC1C;AAED,iBAAS,KAAK,CAAC,EACb,KAAK,EACL,SAAS,EACT,WAAmB,EACnB,MAAc,EACd,cAAc,EACd,kBAAkB,EAClB,QAAgB,EAChB,MAAgB,EAChB,QAAa,EACb,aAAkB,EAClB,cAAc,EACd,UAAU,EACV,mBAAmB,EACnB,aAAa,GACd,EAAE,UAAU,2CA6EZ;AAED,OAAO,EAAE,KAAK,EAAE,CAAA"}
1
+ {"version":3,"file":"price.d.ts","sourceRoot":"","sources":["../../../components/ui/price.tsx"],"names":[],"mappings":";AAIA,UAAU,UAAU;IAClB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACnC,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,EAAE,CAAA;IAChD,cAAc,CAAC,EAAE,KAAK,CAAC,aAAa,CAAA;IACpC,UAAU,CAAC,EAAE,KAAK,CAAC,aAAa,CAAA;IAChC,mBAAmB,CAAC,EAAE,KAAK,CAAC,aAAa,CAAA;CAC1C;AAED,iBAAS,KAAK,CAAC,EACb,KAAK,EACL,SAAS,EACT,WAAmB,EACnB,MAAc,EACd,cAAc,EACd,kBAAkB,EAClB,QAAgB,EAChB,MAAgB,EAChB,QAAa,EACb,aAAkB,EAClB,cAAc,EACd,UAAU,EACV,mBAAmB,EACnB,aAAa,GACd,EAAE,UAAU,2CAiFZ;AAED,OAAO,EAAE,KAAK,EAAE,CAAA"}
@@ -9,7 +9,7 @@ function Price({ price, priceHigh, priceRanges = false, isSale = false, compareA
9
9
  const colorClass = isSale
10
10
  ? "text-textColors-salePriceText"
11
11
  : "text-textColors-priceText";
12
- return (_jsx(Text, Object.assign({ className: `${colorClass} flex-shrink-0 max-w-full`, style: { fontSize: `${fontSize}px` } }, { children: _jsxs("span", Object.assign({ className: "flex-grow min-w-[fit-content] break-all" }, { children: [_jsx(Money, { price: price, currency: currency, locale: locale, styles: priceStyles, hideZeroCents: hideZeroCents }), priceRanges && priceHigh !== undefined && _jsx(Spacer, {}), priceRanges && priceHigh !== undefined && (_jsx(Money, { price: priceHigh, currency: currency, locale: locale, styles: priceStyles, hideZeroCents: hideZeroCents }))] })) })));
12
+ return (_jsx(Text, Object.assign({ className: `${colorClass} flex-shrink-0 max-w-full`, style: { fontSize: `${fontSize}px` } }, { children: _jsxs("span", Object.assign({ className: "flex-grow" }, { children: [_jsx(Money, { className: "whitespace-nowrap", price: price, currency: currency, locale: locale, styles: priceStyles, hideZeroCents: hideZeroCents }), priceRanges && priceHigh !== undefined && _jsx(Spacer, {}), priceRanges && priceHigh !== undefined && (_jsx(Money, { className: "whitespace-nowrap", price: priceHigh, currency: currency, locale: locale, styles: priceStyles, hideZeroCents: hideZeroCents }))] })) })));
13
13
  };
14
14
  const StrikeThroughPrice = () => {
15
15
  if (!isSale || !compareAtPrice)
@@ -6,6 +6,7 @@ type VideoAttributes = {
6
6
  overlayOpacity: number;
7
7
  autoplay: boolean;
8
8
  videoSound: boolean;
9
+ loop?: boolean;
9
10
  };
10
11
  interface VideoProps extends Omit<React.VideoHTMLAttributes<HTMLVideoElement>, "onLoadedData"> {
11
12
  src: string;
@@ -1 +1 @@
1
- {"version":3,"file":"video-enhanced.d.ts","sourceRoot":"","sources":["../../../components/ui/video-enhanced.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAkB9B,KAAK,eAAe,GAAG;IACrB,OAAO,EAAE,OAAO,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,GAAG,KAAK,CAAA;IACxB,cAAc,EAAE,MAAM,CAAA;IACtB,QAAQ,EAAE,OAAO,CAAA;IACjB,UAAU,EAAE,OAAO,CAAA;CACpB,CAAA;AAED,UAAU,UACR,SAAQ,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,cAAc,CAAC;IACzE,GAAG,EAAE,MAAM,CAAA;IACX,eAAe,EAAE,eAAe,CAAA;IAChC,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAA;IAKlB,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,GAAG,KAAK,KAAK,IAAI,CAAA;CAC1D;AAED,QAAA,MAAM,KAAK,qFAkQV,CAAA;AAID,OAAO,EAAE,KAAK,IAAI,aAAa,EAAE,CAAA"}
1
+ {"version":3,"file":"video-enhanced.d.ts","sourceRoot":"","sources":["../../../components/ui/video-enhanced.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAkB9B,KAAK,eAAe,GAAG;IACrB,OAAO,EAAE,OAAO,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,GAAG,KAAK,CAAA;IACxB,cAAc,EAAE,MAAM,CAAA;IACtB,QAAQ,EAAE,OAAO,CAAA;IACjB,UAAU,EAAE,OAAO,CAAA;IAEnB,IAAI,CAAC,EAAE,OAAO,CAAA;CACf,CAAA;AAED,UAAU,UACR,SAAQ,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,cAAc,CAAC;IACzE,GAAG,EAAE,MAAM,CAAA;IACX,eAAe,EAAE,eAAe,CAAA;IAChC,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAA;IAKlB,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,GAAG,KAAK,KAAK,IAAI,CAAA;CAC1D;AAED,QAAA,MAAM,KAAK,qFAuQV,CAAA;AAID,OAAO,EAAE,KAAK,IAAI,aAAa,EAAE,CAAA"}
@@ -35,7 +35,13 @@ const videoVariants = {
35
35
  // first frame well within this window, so they still reveal via `loadeddata`.
36
36
  const LOADED_DATA_FALLBACK_MS = 1000;
37
37
  const Video = React.forwardRef((_a, ref) => {
38
- var { src, videoAttributes, naturalAspectRatio = "1/1", className, onLoadedData } = _a, props = __rest(_a, ["src", "videoAttributes", "naturalAspectRatio", "className", "onLoadedData"]);
38
+ var _b;
39
+ var { src, videoAttributes, naturalAspectRatio = "1/1", className, onLoadedData,
40
+ // Pull `loop` out of the spread: it's a native <video> attribute, so
41
+ // leaving it in `...props` (which is applied AFTER our computed value)
42
+ // would let a passed-in prop silently override the attribute-driven
43
+ // loop logic below. An explicit prop still wins, but explicitly.
44
+ loop: loopProp } = _a, props = __rest(_a, ["src", "videoAttributes", "naturalAspectRatio", "className", "onLoadedData", "loop"]);
39
45
  const autoPlayEnabled = videoAttributes.autoplay && !videoAttributes.videoSound;
40
46
  const internalRef = React.useRef(null);
41
47
  const videoRef = ref || internalRef;
@@ -226,7 +232,7 @@ const Video = React.forwardRef((_a, ref) => {
226
232
  };
227
233
  return (_jsxs("div", Object.assign({ className: "relative w-full" }, { children: [_jsx("video", Object.assign({ ref: videoRef, className: cn(videoVariants.base, videoAttributes.videoFit === "fill"
228
234
  ? videoVariants.fit.cover
229
- : videoVariants.fit.contain, className), style: videoStyle, preload: "metadata", playsInline: true, loop: videoAttributes.enabled, controls: false }, props)), isLoaded && !isPlaying && (_jsx("button", Object.assign({ onClick: handlePlayPause, className: "absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 z-50\n w-16 h-16 rounded-full bg-black/75 \n flex items-center justify-center transition-all duration-300\n focus:outline-none focus:ring-2 focus:ring-white", "aria-label": "Play video" }, { children: _jsx("div", { className: "w-0 h-0 border-y-8 border-y-transparent \n border-l-[16px] border-l-white \n translate-x-[2px]" }) })))] })));
235
+ : videoVariants.fit.contain, className), style: videoStyle, preload: "metadata", playsInline: true, loop: (_b = loopProp !== null && loopProp !== void 0 ? loopProp : videoAttributes.loop) !== null && _b !== void 0 ? _b : videoAttributes.enabled, controls: false }, props)), isLoaded && !isPlaying && (_jsx("button", Object.assign({ onClick: handlePlayPause, className: "absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 z-50\n w-16 h-16 rounded-full bg-black/75 \n flex items-center justify-center transition-all duration-300\n focus:outline-none focus:ring-2 focus:ring-white", "aria-label": "Play video" }, { children: _jsx("div", { className: "w-0 h-0 border-y-8 border-y-transparent \n border-l-[16px] border-l-white \n translate-x-[2px]" }) })))] })));
230
236
  });
231
237
  Video.displayName = "Video";
232
238
  export { Video as VideoEnhanced };
@@ -84,6 +84,7 @@ export * from "../components/core/html";
84
84
  export * from "../components/hooks/use-shop";
85
85
  export * from "../components/libs/sort-filter/search-integration";
86
86
  export * from "../components/hooks/use-reviews";
87
+ export * from "../components/hooks/use-questions";
87
88
  export * from "../components/hooks/use-style-parent";
88
89
  export * from "../components/ui/subcollection-tabs";
89
90
  export * from "../components/ui/ProductCard/utils";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../core/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../core/index.ts"],"names":[],"mappings":"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"}
@@ -84,6 +84,7 @@ export * from "../components/core/html";
84
84
  export * from "../components/hooks/use-shop";
85
85
  export * from "../components/libs/sort-filter/search-integration";
86
86
  export * from "../components/hooks/use-reviews";
87
+ export * from "../components/hooks/use-questions";
87
88
  export * from "../components/hooks/use-style-parent";
88
89
  export * from "../components/ui/subcollection-tabs";
89
90
  export * from "../components/ui/ProductCard/utils";
package/dist/index.d.ts CHANGED
@@ -86,6 +86,8 @@ export * from "./components/hooks/use-shop";
86
86
  export * from "./components/libs/sort-filter/search-integration";
87
87
  export * from "./components/hooks/use-reviews";
88
88
  export * from "./components/hooks/use-create-review";
89
+ export * from "./components/hooks/use-questions";
90
+ export * from "./components/hooks/use-create-question";
89
91
  export * from "./components/hooks/use-style-parent";
90
92
  export * from "./components/ui/subcollection-tabs";
91
93
  export * from "./components/ui/ProductCard/utils";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -86,6 +86,8 @@ export * from "./components/hooks/use-shop";
86
86
  export * from "./components/libs/sort-filter/search-integration";
87
87
  export * from "./components/hooks/use-reviews";
88
88
  export * from "./components/hooks/use-create-review";
89
+ export * from "./components/hooks/use-questions";
90
+ export * from "./components/hooks/use-create-question";
89
91
  export * from "./components/hooks/use-style-parent";
90
92
  export * from "./components/ui/subcollection-tabs";
91
93
  export * from "./components/ui/ProductCard/utils";
@@ -1,5 +1,5 @@
1
1
  import { ProductVariant, Product } from "app-studio-types";
2
- export declare const getCheapestProductFromVariantsFn: (productVariants: ProductVariant[]) => ProductVariant;
2
+ export declare const getCheapestProductFromVariantsFn: (productVariants: ProductVariant[]) => ProductVariant | undefined;
3
3
  export declare function getPriceRangesFn(product: Product): {
4
4
  price: number;
5
5
  isSale: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"price.d.ts","sourceRoot":"","sources":["../../lib/price.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AA0B1D,eAAO,MAAM,gCAAgC,oBAC1B,cAAc,EAAE,mBAelC,CAAA;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO;WAsBtC,MAAM;YACL,OAAO;;;;EAclB;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO;;;;EAQ1C"}
1
+ {"version":3,"file":"price.d.ts","sourceRoot":"","sources":["../../lib/price.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AA0B1D,eAAO,MAAM,gCAAgC,oBAC1B,cAAc,EAAE,+BAmBlC,CAAA;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO;WAsBtC,MAAM;YACL,OAAO;;;;EAclB;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO;;;;EAQ1C"}
package/dist/lib/price.js CHANGED
@@ -1,5 +1,8 @@
1
1
  // Return the cheapest available variant for pricing details
2
2
  export const getCheapestProductFromVariantsFn = (productVariants) => {
3
+ if (!Array.isArray(productVariants) || productVariants.length === 0) {
4
+ return undefined;
5
+ }
3
6
  const availableVariants = productVariants.filter((variant) => variant.availableForSale);
4
7
  // Use pricing from in-stock variants only. If all are out of stock use all variants.
5
8
  const activeVariants = availableVariants.length
package/dist/styles.css CHANGED
@@ -612,11 +612,16 @@ video {
612
612
  --productBadging-fill: #000000;
613
613
  --productBadging-text: #fefefe;
614
614
 
615
+ /* Legacy v1 tokens — kept for backwards compat with existing blocks. */
615
616
  --productImage-aspectRatio: "2:3";
616
617
  --productImage-scaling: cover;
617
618
  --productImage-isCustom: "false";
618
619
 
619
- --standard-shadow: 0px 5px 25px 0px rgba (0,  0,  0,  0.10);
620
+ /* V2 brand-kit tokens (fall back to legacy values). */
621
+ --brand-image-ratio: 2/3;
622
+ --brand-image-scaling: var(--productImage-scaling);
623
+
624
+ --standard-shadow: 0px 5px 25px 0px rgba (0, 0, 0, 0.10);
620
625
  }
621
626
  .textarea-component::-webkit-scrollbar {
622
627
  width: 4px;
@@ -1134,7 +1139,7 @@ video {
1134
1139
  aspect-ratio: 327/316;
1135
1140
  }
1136
1141
  .aspect-productImages {
1137
- aspect-ratio: var(--productImage-aspectRatio);
1142
+ aspect-ratio: var(--brand-image-ratio);
1138
1143
  }
1139
1144
  .aspect-square {
1140
1145
  aspect-ratio: 1 / 1;
@@ -1511,6 +1516,9 @@ video {
1511
1516
  .min-w-8 {
1512
1517
  min-width: 2rem;
1513
1518
  }
1519
+ .min-w-\[104px\] {
1520
+ min-width: 104px;
1521
+ }
1514
1522
  .min-w-\[150px\] {
1515
1523
  min-width: 150px;
1516
1524
  }
@@ -1520,10 +1528,6 @@ video {
1520
1528
  .min-w-\[8rem\] {
1521
1529
  min-width: 8rem;
1522
1530
  }
1523
- .min-w-\[fit-content\] {
1524
- min-width: -moz-fit-content;
1525
- min-width: fit-content;
1526
- }
1527
1531
  .max-w-\[140px\] {
1528
1532
  max-width: 140px;
1529
1533
  }
@@ -1902,6 +1906,9 @@ video {
1902
1906
  .gap-5 {
1903
1907
  gap: 1.25rem;
1904
1908
  }
1909
+ .gap-6 {
1910
+ gap: 1.5rem;
1911
+ }
1905
1912
  .gap-\[7px\] {
1906
1913
  gap: 7px;
1907
1914
  }
@@ -2018,6 +2025,9 @@ video {
2018
2025
  .text-ellipsis {
2019
2026
  text-overflow: ellipsis;
2020
2027
  }
2028
+ .text-clip {
2029
+ text-overflow: clip;
2030
+ }
2021
2031
  .whitespace-normal {
2022
2032
  white-space: normal;
2023
2033
  }
@@ -2133,6 +2143,9 @@ video {
2133
2143
  .border-l {
2134
2144
  border-left-width: 1px;
2135
2145
  }
2146
+ .border-l-2 {
2147
+ border-left-width: 2px;
2148
+ }
2136
2149
  .border-l-\[16px\] {
2137
2150
  border-left-width: 16px;
2138
2151
  }
@@ -2193,6 +2206,10 @@ video {
2193
2206
  .border-coreColors-dividingLines {
2194
2207
  border-color: var(--coreColors-dividingLines);
2195
2208
  }
2209
+ .border-gray-100 {
2210
+ --tw-border-opacity: 1;
2211
+ border-color: rgb(243 244 246 / var(--tw-border-opacity, 1));
2212
+ }
2196
2213
  .border-gray-300 {
2197
2214
  --tw-border-opacity: 1;
2198
2215
  border-color: rgb(209 213 219 / var(--tw-border-opacity, 1));
@@ -2319,6 +2336,10 @@ video {
2319
2336
  --tw-bg-opacity: 1;
2320
2337
  background-color: rgb(254 226 226 / var(--tw-bg-opacity, 1));
2321
2338
  }
2339
+ .bg-red-500 {
2340
+ --tw-bg-opacity: 1;
2341
+ background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
2342
+ }
2322
2343
  .bg-stateColors-disabled {
2323
2344
  background-color: var(--stateColors-disabled);
2324
2345
  }
@@ -2555,6 +2576,9 @@ video {
2555
2576
  .pl-2 {
2556
2577
  padding-left: 0.5rem;
2557
2578
  }
2579
+ .pl-3 {
2580
+ padding-left: 0.75rem;
2581
+ }
2558
2582
  .pl-4 {
2559
2583
  padding-left: 1rem;
2560
2584
  }
@@ -2630,6 +2654,9 @@ video {
2630
2654
  .font-fontRegular {
2631
2655
  font-family: var(--fontRegular);
2632
2656
  }
2657
+ .font-mono {
2658
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
2659
+ }
2633
2660
  .text-5xl {
2634
2661
  font-size: 3rem;
2635
2662
  line-height: 1;
@@ -2764,6 +2791,9 @@ video {
2764
2791
  .tracking-tight {
2765
2792
  letter-spacing: -0.025em;
2766
2793
  }
2794
+ .tracking-wider {
2795
+ letter-spacing: 0.05em;
2796
+ }
2767
2797
  .text-\[\#666666\] {
2768
2798
  --tw-text-opacity: 1;
2769
2799
  color: rgb(102 102 102 / var(--tw-text-opacity, 1));
@@ -2882,6 +2912,10 @@ video {
2882
2912
  .text-foreground\/50 {
2883
2913
  color: hsl(var(--foreground) / 0.5);
2884
2914
  }
2915
+ .text-gray-400 {
2916
+ --tw-text-opacity: 1;
2917
+ color: rgb(156 163 175 / var(--tw-text-opacity, 1));
2918
+ }
2885
2919
  .text-gray-500 {
2886
2920
  --tw-text-opacity: 1;
2887
2921
  color: rgb(107 114 128 / var(--tw-text-opacity, 1));
@@ -3267,11 +3301,11 @@ video {
3267
3301
  .paused {
3268
3302
  animation-play-state: paused;
3269
3303
  }
3270
- .\!container {
3304
+ .\!container {
3271
3305
  padding-right: 16px !important;
3272
3306
  padding-left: 16px !important;
3273
3307
  }
3274
- .container {
3308
+ .container {
3275
3309
  padding-right: 16px;
3276
3310
  padding-left: 16px;
3277
3311
  }
@@ -3365,10 +3399,17 @@ body::-webkit-scrollbar {
3365
3399
  * home indicator) dedupe instead of double-counting.
3366
3400
  */
3367
3401
 
3368
- /* SLIM SCOPE — bottom-overlay iOS adapter only. Top-edge, cutout, generalized
3369
- --tc-content-* / drawer vars and their Tailwind utilities are deferred to
3370
- Insets V2 (they had zero consumers). Everything here is inert unless the
3371
- shell reports an overlay bottom bar (.tc-glass; see the gated block below). */
3402
+ /* SLIM SCOPE — bottom-overlay iOS adapter only. Top-edge, cutout and the
3403
+ generalized --tc-content-* var API are deferred to Insets V2. Everything here
3404
+ is inert unless the shell reports an overlay bottom bar (.tc-glass; see the
3405
+ gated block below).
3406
+
3407
+ Drawer clearance is NO LONGER part of that deferral. #3407 deferred "drawer
3408
+ APIs" on the rationale that they had zero consumers; that rationale expired
3409
+ once bottom sheets were found painting behind the bar on 22 block templates
3410
+ plus the quickadd and wishlist modals. What landed is one narrow utility
3411
+ class (.tc-pb-frame, at the end of this file) consumed by DrawerContentBase —
3412
+ NOT the generalized drawer var API, which stays deferred. */
3372
3413
 
3373
3414
  /* --tc-bar-bottom is @property-registered so the hide-on-scroll bar collapse
3374
3415
  animates smoothly (300ms native bar). */
@@ -3427,6 +3468,38 @@ body::-webkit-scrollbar {
3427
3468
  var(--tc-bar-bottom, 0px)
3428
3469
  );
3429
3470
  }
3471
+
3472
+ /* Bottom cushion for VIEWPORT-ANCHORED overlays (bottom sheets / drawers).
3473
+ These portal to <body> and pin themselves with `position: fixed; bottom: 0`,
3474
+ so they sit outside #tc-vgsl and never receive the frame clearance it carries
3475
+ (--tc-frame-bottom-gated on the native path, --tc-frame-bottom in web mode;
3476
+ see apps/tapcart-ssr-app/app/layout.tsx). Under an overlay bottom bar their
3477
+ last row of content therefore paints behind the bar.
3478
+
3479
+ This rule reads the NON-gated --tc-frame-bottom on purpose. #tc-vgsl needs
3480
+ the gated variant so it goes IACVT-invalid and collapses to 0 on a shell that
3481
+ never wrote --tc-safe-bottom, leaving the legacy RN bridge authoritative over
3482
+ the same element. Nothing competes for this padding, and the injection script
3483
+ writes --tc-safe-bottom and --tc-bar-bottom-glass together, so under .tc-glass
3484
+ the two variants are equal anyway; the non-gated one additionally keeps the
3485
+ env()/--rn-* fallback chain alive.
3486
+
3487
+ The sheet's own surface should keep bleeding to the physical bottom edge
3488
+ (native sheets do), so the clearance goes into padding and lifts the CONTENT
3489
+ instead of floating the whole sheet. max() against the pre-PR env() cushion
3490
+ keeps the two from double-counting when the bar hides on scroll and
3491
+ --tc-frame-bottom collapses to the safe area.
3492
+
3493
+ Gated on .tc-glass: on every non-glass shell this rule never matches and the
3494
+ element's existing `pb-safe` stays byte-for-byte authoritative.
3495
+
3496
+ Specificity note: this is (0,4,0), well above a Tailwind pb-* utility, and
3497
+ tailwind-merge does not treat `tc-pb-frame` as a padding-bottom conflict. A
3498
+ caller passing `pb-0`/`p-0` to DrawerContentBase would therefore keep the
3499
+ cushion under glass and lose it everywhere else. No caller does today. */
3500
+ :root.tc-platform-ios.tc-glass .tc-pb-frame {
3501
+ padding-bottom: max(env(safe-area-inset-bottom), var(--tc-frame-bottom, 0px));
3502
+ }
3430
3503
  .file\:border-0::file-selector-button {
3431
3504
  border-width: 0px;
3432
3505
  }
@@ -3904,6 +3977,12 @@ body::-webkit-scrollbar {
3904
3977
  .\[\&_\*\]\:placeholder\:text-stateColors-error *::placeholder {
3905
3978
  color: var(--stateColors-error);
3906
3979
  }
3980
+ .\[\&_a\]\:text-inherit a {
3981
+ color: inherit;
3982
+ }
3983
+ .\[\&_a\]\:underline a {
3984
+ text-decoration-line: underline;
3985
+ }
3907
3986
  .\[\&_label\]\:focus-within\:\!text-stateColors-error:focus-within label {
3908
3987
  color: var(--stateColors-error) !important;
3909
3988
  }
@@ -3913,4 +3992,3 @@ body::-webkit-scrollbar {
3913
3992
  .\[\&_p\]\:text-stateColors-disabled p {
3914
3993
  color: var(--stateColors-disabled);
3915
3994
  }
3916
-
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tapcart/mobile-components",
3
- "version": "0.18.1",
3
+ "version": "0.19.1",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "style": "dist/styles.css",