@shopify/shop-minis-react 0.9.0 → 0.11.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.
- package/dist/components/atoms/safe-area.js +37 -0
- package/dist/components/atoms/safe-area.js.map +1 -0
- package/dist/hooks/util/useSafeArea.js +8 -0
- package/dist/hooks/util/useSafeArea.js.map +1 -0
- package/dist/index.js +239 -235
- package/dist/index.js.map +1 -1
- package/dist/shop-minis-react/node_modules/.pnpm/simple-swizzle@0.2.2/node_modules/simple-swizzle/index.js +1 -1
- package/dist/shop-minis-react/node_modules/.pnpm/use-sync-external-store@1.5.0_react@19.1.0/node_modules/use-sync-external-store/shim/index.js +1 -1
- package/eslint/rules/validate-manifest.cjs +1 -98
- package/generated-hook-maps/component-scopes-map.json +1 -18
- package/package.json +1 -1
- package/src/components/atoms/safe-area.tsx +92 -0
- package/src/components/index.ts +1 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/util/useSafeArea.ts +24 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { jsx as f } from "react/jsx-runtime";
|
|
2
|
+
import { useSafeArea as g } from "../../hooks/util/useSafeArea.js";
|
|
3
|
+
const m = ["top", "right", "bottom", "left"], d = {
|
|
4
|
+
top: "var(--safe-area-inset-top, 0px)",
|
|
5
|
+
right: "var(--safe-area-inset-right, 0px)",
|
|
6
|
+
bottom: "var(--safe-area-inset-bottom, 0px)",
|
|
7
|
+
left: "var(--safe-area-inset-left, 0px)"
|
|
8
|
+
}, c = {
|
|
9
|
+
padding: {
|
|
10
|
+
top: "paddingTop",
|
|
11
|
+
right: "paddingRight",
|
|
12
|
+
bottom: "paddingBottom",
|
|
13
|
+
left: "paddingLeft"
|
|
14
|
+
},
|
|
15
|
+
margin: {
|
|
16
|
+
top: "marginTop",
|
|
17
|
+
right: "marginRight",
|
|
18
|
+
bottom: "marginBottom",
|
|
19
|
+
left: "marginLeft"
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
function x({
|
|
23
|
+
edges: e = m,
|
|
24
|
+
mode: a = "padding",
|
|
25
|
+
className: i,
|
|
26
|
+
style: r,
|
|
27
|
+
children: n
|
|
28
|
+
}) {
|
|
29
|
+
const o = { ...r }, s = c[a], p = g();
|
|
30
|
+
for (const t of e)
|
|
31
|
+
p?.[t] > 0 && (o[s[t]] = d[t]);
|
|
32
|
+
return /* @__PURE__ */ f("div", { className: i, style: o, children: n });
|
|
33
|
+
}
|
|
34
|
+
export {
|
|
35
|
+
x as SafeArea
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=safe-area.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safe-area.js","sources":["../../../src/components/atoms/safe-area.tsx"],"sourcesContent":["import {useSafeArea} from '../../hooks/util/useSafeArea'\n\ntype Edge = 'top' | 'right' | 'bottom' | 'left'\n\nexport interface SafeAreaDocProps {\n /** Which edges to apply safe area insets to. Defaults to all edges. */\n edges?: Edge[]\n /** Whether to apply insets as padding or margin. Defaults to 'padding'. */\n mode?: 'padding' | 'margin'\n /** Additional CSS classes */\n className?: string\n /** Additional inline styles */\n style?: React.CSSProperties\n /** Content to render inside the safe area */\n children?: React.ReactNode\n}\n\nconst ALL_EDGES: Edge[] = ['top', 'right', 'bottom', 'left']\n\nconst CSS_VAR_MAP: {[key in Edge]: string} = {\n top: 'var(--safe-area-inset-top, 0px)',\n right: 'var(--safe-area-inset-right, 0px)',\n bottom: 'var(--safe-area-inset-bottom, 0px)',\n left: 'var(--safe-area-inset-left, 0px)',\n}\n\nconst STYLE_KEY_MAP: {[key in 'padding' | 'margin']: {[edge in Edge]: string}} =\n {\n padding: {\n top: 'paddingTop',\n right: 'paddingRight',\n bottom: 'paddingBottom',\n left: 'paddingLeft',\n },\n margin: {\n top: 'marginTop',\n right: 'marginRight',\n bottom: 'marginBottom',\n left: 'marginLeft',\n },\n }\n\n/**\n * A container that applies safe area insets as padding or margin.\n *\n * Ensures content isn't hidden behind system UI (home indicator,\n * navigation bar, etc).\n *\n * Uses CSS custom properties (`--safe-area-inset-*`) injected by the\n * Shop app, which work reliably on both iOS and Android.\n *\n * Only applies inline padding/margin for edges where the safe area\n * inset is non-zero, so your Tailwind classes and styles are preserved\n * on edges that don't need safe area handling.\n *\n * @example\n * ```tsx\n * <SafeArea edges={['bottom']}>\n * <footer>Sticky footer content</footer>\n * </SafeArea>\n * ```\n *\n * @example\n * ```tsx\n * <SafeArea className=\"pt-12 px-4\">\n * <div>Custom top/side padding, safe area bottom</div>\n * </SafeArea>\n * ```\n */\nexport function SafeArea({\n edges = ALL_EDGES,\n mode = 'padding',\n className,\n style: styleProp,\n children,\n}: SafeAreaDocProps) {\n const style: React.CSSProperties = {...styleProp}\n const keys = STYLE_KEY_MAP[mode]\n const insets = useSafeArea()\n\n for (const edge of edges) {\n if (insets?.[edge] > 0) {\n ;(style as any)[keys[edge]] = CSS_VAR_MAP[edge]\n }\n }\n\n return (\n <div className={className} style={style}>\n {children}\n </div>\n )\n}\n"],"names":["ALL_EDGES","CSS_VAR_MAP","STYLE_KEY_MAP","SafeArea","edges","mode","className","styleProp","children","style","keys","insets","useSafeArea","edge","jsx"],"mappings":";;AAiBA,MAAMA,IAAoB,CAAC,OAAO,SAAS,UAAU,MAAM,GAErDC,IAAuC;AAAA,EAC3C,KAAK;AAAA,EACL,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,MAAM;AACR,GAEMC,IACJ;AAAA,EACE,SAAS;AAAA,IACP,KAAK;AAAA,IACL,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,MAAM;AAAA,EACR;AAAA,EACA,QAAQ;AAAA,IACN,KAAK;AAAA,IACL,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,MAAM;AAAA,EAAA;AAEV;AA6BK,SAASC,EAAS;AAAA,EACvB,OAAAC,IAAQJ;AAAA,EACR,MAAAK,IAAO;AAAA,EACP,WAAAC;AAAA,EACA,OAAOC;AAAA,EACP,UAAAC;AACF,GAAqB;AACb,QAAAC,IAA6B,EAAC,GAAGF,EAAS,GAC1CG,IAAOR,EAAcG,CAAI,GACzBM,IAASC,EAAY;AAE3B,aAAWC,KAAQT;AACb,IAAAO,IAASE,CAAI,IAAI,MACjBJ,EAAcC,EAAKG,CAAI,CAAC,IAAIZ,EAAYY,CAAI;AAIlD,SACG,gBAAAC,EAAA,OAAA,EAAI,WAAAR,GAAsB,OAAAG,GACxB,UAAAD,EACH,CAAA;AAEJ;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSafeArea.js","sources":["../../../src/hooks/util/useSafeArea.ts"],"sourcesContent":["import type {SafeAreaInsets} from '@shopify/shop-minis-platform'\n\nconst DEFAULT_INSETS: SafeAreaInsets = {top: 0, right: 0, bottom: 0, left: 0}\n\n/**\n * Returns the safe area insets for the current device.\n *\n * These values represent the areas of the screen that are obscured by\n * system UI (home indicator, navigation bar, etc). Use them to ensure\n * content isn't hidden behind system chrome.\n *\n * The values are also available as CSS custom properties:\n * `--safe-area-inset-top`, `--safe-area-inset-right`,\n * `--safe-area-inset-bottom`, `--safe-area-inset-left`\n *\n * @example\n * ```tsx\n * const {bottom} = useSafeArea()\n * return <div style={{paddingBottom: bottom}}>Content</div>\n * ```\n */\nexport function useSafeArea(): SafeAreaInsets {\n return window.minisParams?.safeAreaInsets ?? DEFAULT_INSETS\n}\n"],"names":["DEFAULT_INSETS","useSafeArea"],"mappings":"AAEA,MAAMA,IAAiC,EAAC,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,EAAC;AAmBrE,SAASC,IAA8B;AACrC,SAAA,OAAO,aAAa,kBAAkBD;AAC/C;"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DATA_NAVIGATION_TYPE_ATTRIBUTE as o, NAVIGATION_TYPES as t } from "./types/index.js";
|
|
2
|
-
import { MinisContainer as
|
|
2
|
+
import { MinisContainer as p } from "./components/MinisContainer.js";
|
|
3
3
|
import { AddToCartButton as m } from "./components/commerce/add-to-cart.js";
|
|
4
4
|
import { BuyNowButton as s } from "./components/commerce/buy-now.js";
|
|
5
5
|
import { ProductCard as u, ProductCardBadge as f, ProductCardContainer as x, ProductCardFavoriteButton as c, ProductCardImage as d, ProductCardImageContainer as C, ProductCardInfo as g, ProductCardPrice as S, ProductCardReviewStars as A, ProductCardTitle as D } from "./components/commerce/product-card.js";
|
|
@@ -18,159 +18,161 @@ import { IconButton as X } from "./components/atoms/icon-button.js";
|
|
|
18
18
|
import { Image as rr } from "./components/atoms/image.js";
|
|
19
19
|
import { Touchable as or } from "./components/atoms/touchable.js";
|
|
20
20
|
import { LongPressDetector as ar } from "./components/atoms/long-press-detector.js";
|
|
21
|
-
import { AlertDialogAtom as
|
|
21
|
+
import { AlertDialogAtom as ir } from "./components/atoms/alert-dialog.js";
|
|
22
22
|
import { List as nr } from "./components/atoms/list.js";
|
|
23
23
|
import { VideoPlayer as lr } from "./components/atoms/video-player.js";
|
|
24
24
|
import { TextInput as fr } from "./components/atoms/text-input.js";
|
|
25
25
|
import { ContentWrapper as cr } from "./components/atoms/content-wrapper.js";
|
|
26
26
|
import { ProductVariantPrice as Cr } from "./components/atoms/product-variant-price.js";
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
38
|
-
import {
|
|
39
|
-
import {
|
|
40
|
-
import {
|
|
41
|
-
import {
|
|
42
|
-
import {
|
|
43
|
-
import {
|
|
44
|
-
import {
|
|
45
|
-
import {
|
|
46
|
-
import {
|
|
47
|
-
import {
|
|
48
|
-
import {
|
|
49
|
-
import {
|
|
50
|
-
import {
|
|
51
|
-
import {
|
|
52
|
-
import {
|
|
53
|
-
import {
|
|
54
|
-
import {
|
|
55
|
-
import {
|
|
56
|
-
import {
|
|
57
|
-
import {
|
|
58
|
-
import {
|
|
59
|
-
import {
|
|
60
|
-
import {
|
|
61
|
-
import {
|
|
62
|
-
import {
|
|
63
|
-
import {
|
|
64
|
-
import {
|
|
65
|
-
import {
|
|
66
|
-
import {
|
|
67
|
-
import {
|
|
68
|
-
import {
|
|
69
|
-
import {
|
|
70
|
-
import {
|
|
71
|
-
import {
|
|
72
|
-
import {
|
|
73
|
-
import {
|
|
74
|
-
import {
|
|
75
|
-
import {
|
|
76
|
-
import {
|
|
77
|
-
import {
|
|
78
|
-
import {
|
|
79
|
-
import {
|
|
80
|
-
import {
|
|
81
|
-
import {
|
|
82
|
-
import {
|
|
83
|
-
import {
|
|
84
|
-
import {
|
|
85
|
-
import {
|
|
86
|
-
import {
|
|
87
|
-
import {
|
|
88
|
-
import {
|
|
89
|
-
import {
|
|
90
|
-
import {
|
|
91
|
-
import {
|
|
92
|
-
import {
|
|
93
|
-
import {
|
|
94
|
-
import {
|
|
95
|
-
import {
|
|
96
|
-
import {
|
|
97
|
-
import {
|
|
98
|
-
import {
|
|
99
|
-
import {
|
|
100
|
-
import {
|
|
101
|
-
import {
|
|
102
|
-
import {
|
|
27
|
+
import { SafeArea as Sr } from "./components/atoms/safe-area.js";
|
|
28
|
+
import { StaticArea as Dr } from "./components/atoms/static-area.js";
|
|
29
|
+
import { Accordion as Tr, AccordionContent as hr, AccordionItem as Ir, AccordionTrigger as Rr } from "./components/ui/accordion.js";
|
|
30
|
+
import { Alert as wr, AlertDescription as Br, AlertTitle as Er } from "./components/ui/alert.js";
|
|
31
|
+
import { AlertDialog as Fr, AlertDialogAction as Ur, AlertDialogCancel as br, AlertDialogContent as Lr, AlertDialogDescription as kr, AlertDialogFooter as Nr, AlertDialogHeader as Or, AlertDialogOverlay as _r, AlertDialogPortal as yr, AlertDialogTitle as Gr, AlertDialogTrigger as Hr } from "./components/ui/alert-dialog.js";
|
|
32
|
+
import { Avatar as zr, AvatarFallback as Wr, AvatarImage as Yr } from "./components/ui/avatar.js";
|
|
33
|
+
import { Badge as Kr, badgeVariants as Qr } from "./components/ui/badge.js";
|
|
34
|
+
import { Card as jr, CardAction as Jr, CardContent as Xr, CardDescription as $r, CardFooter as re, CardHeader as ee, CardTitle as oe } from "./components/ui/card.js";
|
|
35
|
+
import { Carousel as ae, CarouselContent as pe, CarouselItem as ie, CarouselNext as me, CarouselPrevious as ne } from "./components/ui/carousel.js";
|
|
36
|
+
import { Checkbox as le } from "./components/ui/checkbox.js";
|
|
37
|
+
import { Dialog as fe, DialogClose as xe, DialogContent as ce, DialogDescription as de, DialogFooter as Ce, DialogHeader as ge, DialogOverlay as Se, DialogPortal as Ae, DialogTitle as De, DialogTrigger as Pe } from "./components/ui/dialog.js";
|
|
38
|
+
import { Drawer as he, DrawerClose as Ie, DrawerContent as Re, DrawerDescription as ve, DrawerFooter as we, DrawerHeader as Be, DrawerOverlay as Ee, DrawerPortal as Me, DrawerTitle as Fe, DrawerTrigger as Ue } from "./components/ui/drawer.js";
|
|
39
|
+
import { Input as Le } from "./components/ui/input.js";
|
|
40
|
+
import { Label as Ne } from "./components/ui/label.js";
|
|
41
|
+
import { Progress as _e } from "./components/ui/progress.js";
|
|
42
|
+
import { RadioGroup as Ge, RadioGroupItem as He } from "./components/ui/radio-group.js";
|
|
43
|
+
import { ResizableHandle as ze, ResizablePanel as We, ResizablePanelGroup as Ye } from "./components/ui/resizable.js";
|
|
44
|
+
import { ScrollArea as Ke, ScrollBar as Qe } from "./components/ui/scroll-area.js";
|
|
45
|
+
import { Select as je, SelectContent as Je, SelectGroup as Xe, SelectItem as $e, SelectLabel as ro, SelectScrollDownButton as eo, SelectScrollUpButton as oo, SelectSeparator as to, SelectTrigger as ao, SelectValue as po } from "./components/ui/select.js";
|
|
46
|
+
import { Separator as mo } from "./components/ui/separator.js";
|
|
47
|
+
import { Sheet as so, SheetClose as lo, SheetContent as uo, SheetDescription as fo, SheetFooter as xo, SheetHeader as co, SheetTitle as Co, SheetTrigger as go } from "./components/ui/sheet.js";
|
|
48
|
+
import { Toaster as Ao } from "./components/ui/sonner.js";
|
|
49
|
+
import { toast as Po } from "./shop-minis-react/node_modules/.pnpm/sonner@2.0.5_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/sonner/dist/index.js";
|
|
50
|
+
import { Skeleton as ho } from "./components/ui/skeleton.js";
|
|
51
|
+
import { useRecentProducts as Ro } from "./hooks/user/useRecentProducts.js";
|
|
52
|
+
import { useRecentShops as wo } from "./hooks/user/useRecentShops.js";
|
|
53
|
+
import { useSavedProducts as Eo } from "./hooks/user/useSavedProducts.js";
|
|
54
|
+
import { useSavedProductsActions as Fo } from "./hooks/user/useSavedProductsActions.js";
|
|
55
|
+
import { useFollowedShops as bo } from "./hooks/user/useFollowedShops.js";
|
|
56
|
+
import { useFollowedShopsActions as ko } from "./hooks/user/useFollowedShopsActions.js";
|
|
57
|
+
import { useCurrentUser as Oo } from "./hooks/user/useCurrentUser.js";
|
|
58
|
+
import { useOrders as yo } from "./hooks/user/useOrders.js";
|
|
59
|
+
import { useBuyerAttributes as Ho } from "./hooks/user/useBuyerAttributes.js";
|
|
60
|
+
import { useGenerateUserToken as zo } from "./hooks/user/useGenerateUserToken.js";
|
|
61
|
+
import { useProductListActions as Yo } from "./hooks/product/useProductListActions.js";
|
|
62
|
+
import { useProductLists as Ko } from "./hooks/product/useProductLists.js";
|
|
63
|
+
import { useProductList as Zo } from "./hooks/product/useProductList.js";
|
|
64
|
+
import { useProduct as Jo } from "./hooks/product/useProduct.js";
|
|
65
|
+
import { useProducts as $o } from "./hooks/product/useProducts.js";
|
|
66
|
+
import { useProductVariants as et } from "./hooks/product/useProductVariants.js";
|
|
67
|
+
import { useProductMedia as tt } from "./hooks/product/useProductMedia.js";
|
|
68
|
+
import { useProductReviews as pt } from "./hooks/product/useProductReviews.js";
|
|
69
|
+
import { useProductSearch as mt } from "./hooks/product/useProductSearch.js";
|
|
70
|
+
import { useRecommendedProducts as st } from "./hooks/product/useRecommendedProducts.js";
|
|
71
|
+
import { usePopularProducts as ut } from "./hooks/product/usePopularProducts.js";
|
|
72
|
+
import { useARPreview as xt } from "./hooks/product/useARPreview.js";
|
|
73
|
+
import { useAsyncStorage as dt } from "./hooks/storage/useAsyncStorage.js";
|
|
74
|
+
import { useSecureStorage as gt } from "./hooks/storage/useSecureStorage.js";
|
|
75
|
+
import { useImageUpload as At } from "./hooks/storage/useImageUpload.js";
|
|
76
|
+
import { useShopNavigation as Pt } from "./hooks/navigation/useShopNavigation.js";
|
|
77
|
+
import { useCloseMini as ht } from "./hooks/navigation/useCloseMini.js";
|
|
78
|
+
import { useDeeplink as Rt } from "./hooks/navigation/useDeeplink.js";
|
|
79
|
+
import { useNavigateWithTransition as wt } from "./hooks/navigation/useNavigateWithTransition.js";
|
|
80
|
+
import { useShop as Et } from "./hooks/shop/useShop.js";
|
|
81
|
+
import { useRecommendedShops as Ft } from "./hooks/shop/useRecommendedShops.js";
|
|
82
|
+
import { useCreateImageContent as bt } from "./hooks/content/useCreateImageContent.js";
|
|
83
|
+
import { useErrorToast as kt } from "./hooks/util/useErrorToast.js";
|
|
84
|
+
import { useErrorScreen as Ot } from "./hooks/util/useErrorScreen.js";
|
|
85
|
+
import { useSafeArea as yt } from "./hooks/util/useSafeArea.js";
|
|
86
|
+
import { useShare as Ht } from "./hooks/util/useShare.js";
|
|
87
|
+
import { useImagePicker as zt } from "./hooks/util/useImagePicker.js";
|
|
88
|
+
import { useKeyboardAvoidingView as Yt } from "./hooks/util/useKeyboardAvoidingView.js";
|
|
89
|
+
import { useRequestPermissions as Kt } from "./hooks/util/useRequestPermissions.js";
|
|
90
|
+
import { useOnMiniFocus as Zt } from "./hooks/events/useOnMiniFocus.js";
|
|
91
|
+
import { useOnMiniBlur as Jt } from "./hooks/events/useOnMiniBlur.js";
|
|
92
|
+
import { useOnMiniClose as $t } from "./hooks/events/useOnMiniClose.js";
|
|
93
|
+
import { useOnAppStateChange as ea } from "./hooks/events/useOnAppStateChange.js";
|
|
94
|
+
import { useOnNavigateBack as ta } from "./hooks/events/useOnNavigateBack.js";
|
|
95
|
+
import { buildDeeplinkUrl as pa } from "./utils/buildDeeplinkUrl.js";
|
|
96
|
+
import { MiniEntityNotFoundError as ma, MiniError as na, MiniNetworkError as sa, formatError as la } from "./utils/errors.js";
|
|
97
|
+
import { extractBrandTheme as fa, formatReviewCount as xa, getFeaturedImages as ca, normalizeRating as da } from "./utils/merchant-card.js";
|
|
98
|
+
import { parseUrl as ga } from "./utils/parseUrl.js";
|
|
99
|
+
import { dataURLToBlob as Aa, fileToDataUri as Da, getResizedImageUrl as Pa, getThumbhashBlobURL as Ta, getThumbhashDataURL as ha } from "./utils/image.js";
|
|
100
|
+
import { formatMoney as Ra } from "./utils/formatMoney.js";
|
|
101
|
+
import { UserState as wa, UserTokenGenerateUserErrorCode as Ba } from "./shop-minis-platform/src/types/user.js";
|
|
102
|
+
import { ContentCreateUserErrorCode as Ma, MinisContentStatus as Fa } from "./shop-minis-platform/src/types/content.js";
|
|
103
|
+
import { Social as ba } from "./shop-minis-platform/src/types/share.js";
|
|
104
|
+
import { DATA_FETCHING_DEFAULT_FETCH_POLICY as ka, DATA_FETCHING_DEFAULT_PAGE_SIZE as Na } from "./shop-minis-platform/src/constants.js";
|
|
103
105
|
export {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
106
|
+
Tr as Accordion,
|
|
107
|
+
hr as AccordionContent,
|
|
108
|
+
Ir as AccordionItem,
|
|
109
|
+
Rr as AccordionTrigger,
|
|
108
110
|
m as AddToCartButton,
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
111
|
+
wr as Alert,
|
|
112
|
+
Br as AlertDescription,
|
|
113
|
+
Fr as AlertDialog,
|
|
114
|
+
Ur as AlertDialogAction,
|
|
115
|
+
ir as AlertDialogAtom,
|
|
116
|
+
br as AlertDialogCancel,
|
|
117
|
+
Lr as AlertDialogContent,
|
|
118
|
+
kr as AlertDialogDescription,
|
|
119
|
+
Nr as AlertDialogFooter,
|
|
120
|
+
Or as AlertDialogHeader,
|
|
121
|
+
_r as AlertDialogOverlay,
|
|
122
|
+
yr as AlertDialogPortal,
|
|
123
|
+
Gr as AlertDialogTitle,
|
|
124
|
+
Hr as AlertDialogTrigger,
|
|
125
|
+
Er as AlertTitle,
|
|
126
|
+
zr as Avatar,
|
|
127
|
+
Wr as AvatarFallback,
|
|
128
|
+
Yr as AvatarImage,
|
|
129
|
+
Kr as Badge,
|
|
128
130
|
j as Button,
|
|
129
131
|
s as BuyNowButton,
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
132
|
+
jr as Card,
|
|
133
|
+
Jr as CardAction,
|
|
134
|
+
Xr as CardContent,
|
|
135
|
+
$r as CardDescription,
|
|
136
|
+
re as CardFooter,
|
|
137
|
+
ee as CardHeader,
|
|
138
|
+
oe as CardTitle,
|
|
139
|
+
ae as Carousel,
|
|
140
|
+
pe as CarouselContent,
|
|
141
|
+
ie as CarouselItem,
|
|
142
|
+
me as CarouselNext,
|
|
143
|
+
ne as CarouselPrevious,
|
|
144
|
+
le as Checkbox,
|
|
145
|
+
Ma as ContentCreateUserErrorCode,
|
|
144
146
|
cr as ContentWrapper,
|
|
145
|
-
|
|
146
|
-
|
|
147
|
+
ka as DATA_FETCHING_DEFAULT_FETCH_POLICY,
|
|
148
|
+
Na as DATA_FETCHING_DEFAULT_PAGE_SIZE,
|
|
147
149
|
o as DATA_NAVIGATION_TYPE_ATTRIBUTE,
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
150
|
+
fe as Dialog,
|
|
151
|
+
xe as DialogClose,
|
|
152
|
+
ce as DialogContent,
|
|
153
|
+
de as DialogDescription,
|
|
154
|
+
Ce as DialogFooter,
|
|
155
|
+
ge as DialogHeader,
|
|
156
|
+
Se as DialogOverlay,
|
|
157
|
+
Ae as DialogPortal,
|
|
158
|
+
De as DialogTitle,
|
|
159
|
+
Pe as DialogTrigger,
|
|
160
|
+
he as Drawer,
|
|
161
|
+
Ie as DrawerClose,
|
|
162
|
+
Re as DrawerContent,
|
|
163
|
+
ve as DrawerDescription,
|
|
164
|
+
we as DrawerFooter,
|
|
165
|
+
Be as DrawerHeader,
|
|
166
|
+
Ee as DrawerOverlay,
|
|
167
|
+
Me as DrawerPortal,
|
|
168
|
+
Fe as DrawerTitle,
|
|
169
|
+
Ue as DrawerTrigger,
|
|
168
170
|
V as FavoriteButton,
|
|
169
171
|
X as IconButton,
|
|
170
172
|
rr as Image,
|
|
171
173
|
W as ImageContentWrapper,
|
|
172
|
-
|
|
173
|
-
|
|
174
|
+
Le as Input,
|
|
175
|
+
Ne as Label,
|
|
174
176
|
nr as List,
|
|
175
177
|
ar as LongPressDetector,
|
|
176
178
|
I as MerchantCard,
|
|
@@ -180,11 +182,11 @@ export {
|
|
|
180
182
|
B as MerchantCardName,
|
|
181
183
|
E as MerchantCardRating,
|
|
182
184
|
b as MerchantCardSkeleton,
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
185
|
+
ma as MiniEntityNotFoundError,
|
|
186
|
+
na as MiniError,
|
|
187
|
+
sa as MiniNetworkError,
|
|
188
|
+
p as MinisContainer,
|
|
189
|
+
Fa as MinisContentStatus,
|
|
188
190
|
q as MinisRouter,
|
|
189
191
|
t as NAVIGATION_TYPES,
|
|
190
192
|
u as ProductCard,
|
|
@@ -200,105 +202,107 @@ export {
|
|
|
200
202
|
D as ProductCardTitle,
|
|
201
203
|
T as ProductLink,
|
|
202
204
|
Cr as ProductVariantPrice,
|
|
203
|
-
|
|
205
|
+
_e as Progress,
|
|
204
206
|
k as QuantitySelector,
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
207
|
+
Ge as RadioGroup,
|
|
208
|
+
He as RadioGroupItem,
|
|
209
|
+
ze as ResizableHandle,
|
|
210
|
+
We as ResizablePanel,
|
|
211
|
+
Ye as ResizablePanelGroup,
|
|
212
|
+
Sr as SafeArea,
|
|
213
|
+
Ke as ScrollArea,
|
|
214
|
+
Qe as ScrollBar,
|
|
212
215
|
O as Search,
|
|
213
216
|
_ as SearchInput,
|
|
214
217
|
y as SearchProvider,
|
|
215
218
|
G as SearchResultsList,
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
219
|
+
je as Select,
|
|
220
|
+
Je as SelectContent,
|
|
221
|
+
Xe as SelectGroup,
|
|
222
|
+
$e as SelectItem,
|
|
223
|
+
ro as SelectLabel,
|
|
224
|
+
eo as SelectScrollDownButton,
|
|
225
|
+
oo as SelectScrollUpButton,
|
|
226
|
+
to as SelectSeparator,
|
|
227
|
+
ao as SelectTrigger,
|
|
228
|
+
po as SelectValue,
|
|
229
|
+
mo as Separator,
|
|
230
|
+
so as Sheet,
|
|
231
|
+
lo as SheetClose,
|
|
232
|
+
uo as SheetContent,
|
|
233
|
+
fo as SheetDescription,
|
|
234
|
+
xo as SheetFooter,
|
|
235
|
+
co as SheetHeader,
|
|
236
|
+
Co as SheetTitle,
|
|
237
|
+
go as SheetTrigger,
|
|
238
|
+
ho as Skeleton,
|
|
239
|
+
ba as Social,
|
|
240
|
+
Dr as StaticArea,
|
|
238
241
|
fr as TextInput,
|
|
239
|
-
|
|
242
|
+
Ao as Toaster,
|
|
240
243
|
or as Touchable,
|
|
241
244
|
Q as TransitionLink,
|
|
242
|
-
|
|
243
|
-
|
|
245
|
+
wa as UserState,
|
|
246
|
+
Ba as UserTokenGenerateUserErrorCode,
|
|
244
247
|
lr as VideoPlayer,
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
Eo as
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
248
|
+
Qr as badgeVariants,
|
|
249
|
+
pa as buildDeeplinkUrl,
|
|
250
|
+
Aa as dataURLToBlob,
|
|
251
|
+
fa as extractBrandTheme,
|
|
252
|
+
Da as fileToDataUri,
|
|
253
|
+
la as formatError,
|
|
254
|
+
Ra as formatMoney,
|
|
255
|
+
xa as formatReviewCount,
|
|
256
|
+
ca as getFeaturedImages,
|
|
257
|
+
Pa as getResizedImageUrl,
|
|
258
|
+
Ta as getThumbhashBlobURL,
|
|
259
|
+
ha as getThumbhashDataURL,
|
|
260
|
+
da as normalizeRating,
|
|
261
|
+
ga as parseUrl,
|
|
262
|
+
Po as toast,
|
|
263
|
+
xt as useARPreview,
|
|
264
|
+
dt as useAsyncStorage,
|
|
265
|
+
Ho as useBuyerAttributes,
|
|
266
|
+
ht as useCloseMini,
|
|
267
|
+
bt as useCreateImageContent,
|
|
268
|
+
Oo as useCurrentUser,
|
|
269
|
+
Rt as useDeeplink,
|
|
270
|
+
Ot as useErrorScreen,
|
|
271
|
+
kt as useErrorToast,
|
|
272
|
+
bo as useFollowedShops,
|
|
273
|
+
ko as useFollowedShopsActions,
|
|
274
|
+
zo as useGenerateUserToken,
|
|
275
|
+
zt as useImagePicker,
|
|
276
|
+
At as useImageUpload,
|
|
277
|
+
Yt as useKeyboardAvoidingView,
|
|
278
|
+
wt as useNavigateWithTransition,
|
|
279
|
+
ea as useOnAppStateChange,
|
|
280
|
+
Jt as useOnMiniBlur,
|
|
281
|
+
$t as useOnMiniClose,
|
|
282
|
+
Zt as useOnMiniFocus,
|
|
283
|
+
ta as useOnNavigateBack,
|
|
284
|
+
yo as useOrders,
|
|
285
|
+
ut as usePopularProducts,
|
|
286
|
+
Jo as useProduct,
|
|
287
|
+
Zo as useProductList,
|
|
288
|
+
Yo as useProductListActions,
|
|
289
|
+
Ko as useProductLists,
|
|
290
|
+
tt as useProductMedia,
|
|
291
|
+
pt as useProductReviews,
|
|
292
|
+
mt as useProductSearch,
|
|
293
|
+
et as useProductVariants,
|
|
294
|
+
$o as useProducts,
|
|
295
|
+
Ro as useRecentProducts,
|
|
296
|
+
wo as useRecentShops,
|
|
297
|
+
st as useRecommendedProducts,
|
|
298
|
+
Ft as useRecommendedShops,
|
|
299
|
+
Kt as useRequestPermissions,
|
|
300
|
+
yt as useSafeArea,
|
|
301
|
+
Eo as useSavedProducts,
|
|
302
|
+
Fo as useSavedProductsActions,
|
|
303
|
+
gt as useSecureStorage,
|
|
304
|
+
Ht as useShare,
|
|
305
|
+
Et as useShop,
|
|
306
|
+
Pt as useShopNavigation
|
|
303
307
|
};
|
|
304
308
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { __module as r } from "../../../../../../../_virtual/
|
|
1
|
+
import { __module as r } from "../../../../../../../_virtual/index11.js";
|
|
2
2
|
import { __require as o } from "../cjs/use-sync-external-store-shim.production.js";
|
|
3
3
|
import { __require as i } from "../cjs/use-sync-external-store-shim.development.js";
|
|
4
4
|
var e;
|
|
@@ -122,10 +122,6 @@ module.exports = {
|
|
|
122
122
|
messages: {
|
|
123
123
|
missingScope:
|
|
124
124
|
'{{source}} requires scope "{{scope}}" in src/manifest.json. Add "{{scope}}" to the "scopes" array.',
|
|
125
|
-
missingScopeProductCard:
|
|
126
|
-
'Component "ProductCard" requires scope "{{scope}}" in src/manifest.json. Add "{{scope}}" to the "scopes" array or set favoriteButtonDisabled to true on all ProductCard instances.',
|
|
127
|
-
missingScopeProductLink:
|
|
128
|
-
'Component "ProductLink" requires scope "{{scope}}" in src/manifest.json. Add "{{scope}}" to the "scopes" array or set hideFavoriteAction to true (or provide a customAction) on all ProductLink instances.',
|
|
129
125
|
missingPermission:
|
|
130
126
|
'{{reason}} requires permission "{{permission}}" in src/manifest.json. Add "{{permission}}" to the "permissions" array.',
|
|
131
127
|
missingTrustedDomain:
|
|
@@ -149,9 +145,6 @@ module.exports = {
|
|
|
149
145
|
const requiredPermissions = new Set()
|
|
150
146
|
const requiredDomains = new Set()
|
|
151
147
|
const fixedIssues = new Set()
|
|
152
|
-
// Track how components are actually used (e.g., with specific props)
|
|
153
|
-
const componentUsagePatterns = new Map()
|
|
154
|
-
|
|
155
148
|
// Check module-level cache first to avoid repeated file I/O
|
|
156
149
|
if (manifestPathCache && fs.existsSync(manifestPathCache)) {
|
|
157
150
|
// Check if manifest.json has been modified (for IDE integration)
|
|
@@ -465,78 +458,6 @@ module.exports = {
|
|
|
465
458
|
}
|
|
466
459
|
},
|
|
467
460
|
|
|
468
|
-
// Track ProductCard and ProductLink usage with disabled favorite functionality
|
|
469
|
-
JSXElement(node) {
|
|
470
|
-
const elementName = node.openingElement.name.name
|
|
471
|
-
|
|
472
|
-
// Handle ProductCard with favoriteButtonDisabled prop
|
|
473
|
-
if (elementName === 'ProductCard') {
|
|
474
|
-
// Check if favoriteButtonDisabled prop is present and true
|
|
475
|
-
const favoriteDisabledProp = node.openingElement.attributes.find(
|
|
476
|
-
attr =>
|
|
477
|
-
attr.type === 'JSXAttribute' &&
|
|
478
|
-
attr.name?.name === 'favoriteButtonDisabled'
|
|
479
|
-
)
|
|
480
|
-
|
|
481
|
-
const isDisabled =
|
|
482
|
-
favoriteDisabledProp &&
|
|
483
|
-
// Shorthand syntax: <ProductCard favoriteButtonDisabled />
|
|
484
|
-
(favoriteDisabledProp.value === null ||
|
|
485
|
-
// Explicit true: <ProductCard favoriteButtonDisabled={true} />
|
|
486
|
-
(favoriteDisabledProp.value?.type === 'JSXExpressionContainer' &&
|
|
487
|
-
favoriteDisabledProp.value?.expression?.type === 'Literal' &&
|
|
488
|
-
favoriteDisabledProp.value?.expression?.value === true))
|
|
489
|
-
|
|
490
|
-
// Track usage pattern
|
|
491
|
-
const componentPath = 'commerce/product-card'
|
|
492
|
-
if (!componentUsagePatterns.has(componentPath)) {
|
|
493
|
-
componentUsagePatterns.set(componentPath, {
|
|
494
|
-
allDisabled: true,
|
|
495
|
-
hasUsage: true,
|
|
496
|
-
})
|
|
497
|
-
}
|
|
498
|
-
const pattern = componentUsagePatterns.get(componentPath)
|
|
499
|
-
pattern.allDisabled = pattern.allDisabled && isDisabled
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
// Handle ProductLink with hideFavoriteAction or customAction props
|
|
503
|
-
if (elementName === 'ProductLink') {
|
|
504
|
-
// Check if hideFavoriteAction prop is present and true
|
|
505
|
-
const hideFavoriteProp = node.openingElement.attributes.find(
|
|
506
|
-
attr =>
|
|
507
|
-
attr.type === 'JSXAttribute' &&
|
|
508
|
-
attr.name?.name === 'hideFavoriteAction'
|
|
509
|
-
)
|
|
510
|
-
|
|
511
|
-
// Check if customAction prop is present (replaces favorite action)
|
|
512
|
-
const customActionProp = node.openingElement.attributes.find(
|
|
513
|
-
attr =>
|
|
514
|
-
attr.type === 'JSXAttribute' && attr.name?.name === 'customAction'
|
|
515
|
-
)
|
|
516
|
-
|
|
517
|
-
const isFavoriteDisabled =
|
|
518
|
-
// hideFavoriteAction={true} or shorthand
|
|
519
|
-
(hideFavoriteProp &&
|
|
520
|
-
(hideFavoriteProp.value === null || // shorthand
|
|
521
|
-
(hideFavoriteProp.value?.type === 'JSXExpressionContainer' &&
|
|
522
|
-
hideFavoriteProp.value?.expression?.type === 'Literal' &&
|
|
523
|
-
hideFavoriteProp.value?.expression?.value === true))) ||
|
|
524
|
-
// customAction is provided (any truthy value replaces favorites)
|
|
525
|
-
customActionProp !== undefined
|
|
526
|
-
|
|
527
|
-
// Track usage pattern
|
|
528
|
-
const componentPath = 'commerce/product-link'
|
|
529
|
-
if (!componentUsagePatterns.has(componentPath)) {
|
|
530
|
-
componentUsagePatterns.set(componentPath, {
|
|
531
|
-
allDisabled: true,
|
|
532
|
-
hasUsage: true,
|
|
533
|
-
})
|
|
534
|
-
}
|
|
535
|
-
const pattern = componentUsagePatterns.get(componentPath)
|
|
536
|
-
pattern.allDisabled = pattern.allDisabled && isFavoriteDisabled
|
|
537
|
-
}
|
|
538
|
-
},
|
|
539
|
-
|
|
540
461
|
// Check JSX attributes for external URLs
|
|
541
462
|
JSXAttribute(node) {
|
|
542
463
|
if (!node.value || node.value.type !== 'Literal') {
|
|
@@ -669,18 +590,6 @@ module.exports = {
|
|
|
669
590
|
// Check scopes for components
|
|
670
591
|
usedComponents.forEach(
|
|
671
592
|
({path: componentPath, name: componentName, node}) => {
|
|
672
|
-
// Special handling for components with conditional favorite functionality
|
|
673
|
-
if (
|
|
674
|
-
componentPath === 'commerce/product-card' ||
|
|
675
|
-
componentPath === 'commerce/product-link'
|
|
676
|
-
) {
|
|
677
|
-
const usagePattern = componentUsagePatterns.get(componentPath)
|
|
678
|
-
// Skip scope requirement if all usages have favorites disabled
|
|
679
|
-
if (usagePattern?.hasUsage && usagePattern?.allDisabled) {
|
|
680
|
-
return // No scope required when favorite functionality is disabled
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
|
|
684
593
|
const componentData = componentScopesMap[componentPath]
|
|
685
594
|
if (
|
|
686
595
|
!componentData ||
|
|
@@ -789,13 +698,7 @@ module.exports = {
|
|
|
789
698
|
const sourceName = issue.hookName || issue.componentName
|
|
790
699
|
const sourceType = issue.hookName ? 'Hook' : 'Component'
|
|
791
700
|
|
|
792
|
-
|
|
793
|
-
let messageId = 'missingScope'
|
|
794
|
-
if (issue.componentName === 'ProductCard') {
|
|
795
|
-
messageId = 'missingScopeProductCard'
|
|
796
|
-
} else if (issue.componentName === 'ProductLink') {
|
|
797
|
-
messageId = 'missingScopeProductLink'
|
|
798
|
-
}
|
|
701
|
+
const messageId = 'missingScope'
|
|
799
702
|
|
|
800
703
|
context.report({
|
|
801
704
|
loc: {line: 1, column: 0},
|
|
@@ -1,18 +1 @@
|
|
|
1
|
-
{
|
|
2
|
-
"commerce/product-card": {
|
|
3
|
-
"scopes": [
|
|
4
|
-
"product_list:write"
|
|
5
|
-
],
|
|
6
|
-
"hooks": [
|
|
7
|
-
"useSavedProductsActions"
|
|
8
|
-
]
|
|
9
|
-
},
|
|
10
|
-
"commerce/product-link": {
|
|
11
|
-
"scopes": [
|
|
12
|
-
"product_list:write"
|
|
13
|
-
],
|
|
14
|
-
"hooks": [
|
|
15
|
-
"useSavedProductsActions"
|
|
16
|
-
]
|
|
17
|
-
}
|
|
18
|
-
}
|
|
1
|
+
{}
|
package/package.json
CHANGED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import {useSafeArea} from '../../hooks/util/useSafeArea'
|
|
2
|
+
|
|
3
|
+
type Edge = 'top' | 'right' | 'bottom' | 'left'
|
|
4
|
+
|
|
5
|
+
export interface SafeAreaDocProps {
|
|
6
|
+
/** Which edges to apply safe area insets to. Defaults to all edges. */
|
|
7
|
+
edges?: Edge[]
|
|
8
|
+
/** Whether to apply insets as padding or margin. Defaults to 'padding'. */
|
|
9
|
+
mode?: 'padding' | 'margin'
|
|
10
|
+
/** Additional CSS classes */
|
|
11
|
+
className?: string
|
|
12
|
+
/** Additional inline styles */
|
|
13
|
+
style?: React.CSSProperties
|
|
14
|
+
/** Content to render inside the safe area */
|
|
15
|
+
children?: React.ReactNode
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const ALL_EDGES: Edge[] = ['top', 'right', 'bottom', 'left']
|
|
19
|
+
|
|
20
|
+
const CSS_VAR_MAP: {[key in Edge]: string} = {
|
|
21
|
+
top: 'var(--safe-area-inset-top, 0px)',
|
|
22
|
+
right: 'var(--safe-area-inset-right, 0px)',
|
|
23
|
+
bottom: 'var(--safe-area-inset-bottom, 0px)',
|
|
24
|
+
left: 'var(--safe-area-inset-left, 0px)',
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const STYLE_KEY_MAP: {[key in 'padding' | 'margin']: {[edge in Edge]: string}} =
|
|
28
|
+
{
|
|
29
|
+
padding: {
|
|
30
|
+
top: 'paddingTop',
|
|
31
|
+
right: 'paddingRight',
|
|
32
|
+
bottom: 'paddingBottom',
|
|
33
|
+
left: 'paddingLeft',
|
|
34
|
+
},
|
|
35
|
+
margin: {
|
|
36
|
+
top: 'marginTop',
|
|
37
|
+
right: 'marginRight',
|
|
38
|
+
bottom: 'marginBottom',
|
|
39
|
+
left: 'marginLeft',
|
|
40
|
+
},
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* A container that applies safe area insets as padding or margin.
|
|
45
|
+
*
|
|
46
|
+
* Ensures content isn't hidden behind system UI (home indicator,
|
|
47
|
+
* navigation bar, etc).
|
|
48
|
+
*
|
|
49
|
+
* Uses CSS custom properties (`--safe-area-inset-*`) injected by the
|
|
50
|
+
* Shop app, which work reliably on both iOS and Android.
|
|
51
|
+
*
|
|
52
|
+
* Only applies inline padding/margin for edges where the safe area
|
|
53
|
+
* inset is non-zero, so your Tailwind classes and styles are preserved
|
|
54
|
+
* on edges that don't need safe area handling.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```tsx
|
|
58
|
+
* <SafeArea edges={['bottom']}>
|
|
59
|
+
* <footer>Sticky footer content</footer>
|
|
60
|
+
* </SafeArea>
|
|
61
|
+
* ```
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```tsx
|
|
65
|
+
* <SafeArea className="pt-12 px-4">
|
|
66
|
+
* <div>Custom top/side padding, safe area bottom</div>
|
|
67
|
+
* </SafeArea>
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export function SafeArea({
|
|
71
|
+
edges = ALL_EDGES,
|
|
72
|
+
mode = 'padding',
|
|
73
|
+
className,
|
|
74
|
+
style: styleProp,
|
|
75
|
+
children,
|
|
76
|
+
}: SafeAreaDocProps) {
|
|
77
|
+
const style: React.CSSProperties = {...styleProp}
|
|
78
|
+
const keys = STYLE_KEY_MAP[mode]
|
|
79
|
+
const insets = useSafeArea()
|
|
80
|
+
|
|
81
|
+
for (const edge of edges) {
|
|
82
|
+
if (insets?.[edge] > 0) {
|
|
83
|
+
;(style as any)[keys[edge]] = CSS_VAR_MAP[edge]
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<div className={className} style={style}>
|
|
89
|
+
{children}
|
|
90
|
+
</div>
|
|
91
|
+
)
|
|
92
|
+
}
|
package/src/components/index.ts
CHANGED
|
@@ -27,6 +27,7 @@ export * from './atoms/video-player'
|
|
|
27
27
|
export * from './atoms/text-input'
|
|
28
28
|
export * from './atoms/content-wrapper'
|
|
29
29
|
export * from './atoms/product-variant-price'
|
|
30
|
+
export * from './atoms/safe-area'
|
|
30
31
|
export * from './atoms/static-area'
|
|
31
32
|
|
|
32
33
|
export * from './ui/accordion'
|
package/src/hooks/index.ts
CHANGED
|
@@ -45,6 +45,7 @@ export * from './content/useCreateImageContent'
|
|
|
45
45
|
// - Utility Hooks
|
|
46
46
|
export * from './util/useErrorToast'
|
|
47
47
|
export * from './util/useErrorScreen'
|
|
48
|
+
export * from './util/useSafeArea'
|
|
48
49
|
export * from './util/useShare'
|
|
49
50
|
export * from './util/useImagePicker'
|
|
50
51
|
export * from './util/useKeyboardAvoidingView'
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type {SafeAreaInsets} from '@shopify/shop-minis-platform'
|
|
2
|
+
|
|
3
|
+
const DEFAULT_INSETS: SafeAreaInsets = {top: 0, right: 0, bottom: 0, left: 0}
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Returns the safe area insets for the current device.
|
|
7
|
+
*
|
|
8
|
+
* These values represent the areas of the screen that are obscured by
|
|
9
|
+
* system UI (home indicator, navigation bar, etc). Use them to ensure
|
|
10
|
+
* content isn't hidden behind system chrome.
|
|
11
|
+
*
|
|
12
|
+
* The values are also available as CSS custom properties:
|
|
13
|
+
* `--safe-area-inset-top`, `--safe-area-inset-right`,
|
|
14
|
+
* `--safe-area-inset-bottom`, `--safe-area-inset-left`
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* const {bottom} = useSafeArea()
|
|
19
|
+
* return <div style={{paddingBottom: bottom}}>Content</div>
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export function useSafeArea(): SafeAreaInsets {
|
|
23
|
+
return window.minisParams?.safeAreaInsets ?? DEFAULT_INSETS
|
|
24
|
+
}
|