@tapcart/mobile-components 0.7.6 → 0.7.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,128 @@
1
+ "use client";
2
+ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
3
+ import React, { useState, useEffect, useCallback, useRef, } from "react";
4
+ // Shared manager for all instances of the hook
5
+ const tapManager = (() => {
6
+ const elements = new Map();
7
+ let isListening = false;
8
+ const startListening = () => {
9
+ if (isListening)
10
+ return;
11
+ const handleTouchStart = (e) => {
12
+ const touch = e.touches[0];
13
+ elements.forEach((data, el) => {
14
+ if (el.contains(touch.target)) {
15
+ data.touchStarted = true;
16
+ data.touchMoved = false;
17
+ data.startPosition = { x: touch.clientX, y: touch.clientY };
18
+ // Don't set isPressed here, wait to determine if it's a tap or drag
19
+ }
20
+ });
21
+ };
22
+ const handleTouchMove = (e) => {
23
+ const touch = e.touches[0];
24
+ elements.forEach((data, el) => {
25
+ if (data.touchStarted) {
26
+ const deltaX = Math.abs(touch.clientX - data.startPosition.x);
27
+ const deltaY = Math.abs(touch.clientY - data.startPosition.y);
28
+ if (deltaX > data.tapThreshold || deltaY > data.tapThreshold) {
29
+ data.touchMoved = true;
30
+ data.setIsPressed(false);
31
+ }
32
+ }
33
+ });
34
+ };
35
+ const handleTouchEnd = () => {
36
+ elements.forEach((data) => {
37
+ if (data.touchStarted) {
38
+ data.touchStarted = false;
39
+ if (!data.touchMoved) {
40
+ // It's a tap, set isPressed briefly
41
+ data.setIsPressed(true);
42
+ setTimeout(() => data.setIsPressed(false), 100);
43
+ }
44
+ }
45
+ });
46
+ };
47
+ document.addEventListener("touchstart", (e) => handleTouchStart(e), { passive: true });
48
+ document.addEventListener("touchmove", (e) => handleTouchMove(e), { passive: true });
49
+ document.addEventListener("touchend", () => handleTouchEnd(), {
50
+ passive: true,
51
+ });
52
+ isListening = true;
53
+ };
54
+ return {
55
+ register: (el, data) => {
56
+ elements.set(el, data);
57
+ startListening();
58
+ },
59
+ unregister: (el) => {
60
+ elements.delete(el);
61
+ },
62
+ elements,
63
+ };
64
+ })();
65
+ const useTap = (tapThreshold = 10) => {
66
+ const [isPressed, setIsPressed] = useState(false);
67
+ const elementRef = useRef(null);
68
+ useEffect(() => {
69
+ const element = elementRef.current;
70
+ if (!element)
71
+ return;
72
+ const data = {
73
+ touchStarted: false,
74
+ touchMoved: false,
75
+ startPosition: { x: 0, y: 0 },
76
+ setIsPressed,
77
+ tapThreshold,
78
+ };
79
+ tapManager.register(element, data);
80
+ return () => {
81
+ tapManager.unregister(element);
82
+ };
83
+ }, [tapThreshold]);
84
+ const onTap = useCallback((handler) => {
85
+ return (event) => {
86
+ const data = tapManager.elements.get(elementRef.current);
87
+ if (!data)
88
+ return;
89
+ if (event.type === "touchend" && !data.touchMoved) {
90
+ handler(event);
91
+ }
92
+ else if (event.type === "click" && !data.touchStarted) {
93
+ handler(event);
94
+ setIsPressed(true);
95
+ setTimeout(() => setIsPressed(false), 100);
96
+ }
97
+ };
98
+ }, []);
99
+ return { onTap, isPressed, ref: elementRef };
100
+ };
101
+ const Tap = ({ children }) => {
102
+ const { onTap, isPressed, ref } = useTap();
103
+ const child = React.Children.only(children);
104
+ const cloneElement = (element, props) => {
105
+ return React.cloneElement(element, Object.assign(Object.assign({}, props), { onClick: undefined, onTouchEnd: (event) => {
106
+ onTap(() => {
107
+ if (element.props.onTouchEnd) {
108
+ element.props.onTouchEnd(event);
109
+ return;
110
+ }
111
+ if (element.props.onClick) {
112
+ element.props.onClick(event);
113
+ return;
114
+ }
115
+ })(event);
116
+ }, style: Object.assign(Object.assign({}, element.props.style), { cursor: "pointer", opacity: isPressed ? 0.7 : 1 }) }));
117
+ };
118
+ const cloneChildren = (children) => {
119
+ return React.Children.map(children, (child) => {
120
+ if (React.isValidElement(child)) {
121
+ return cloneElement(child, { ref });
122
+ }
123
+ return child;
124
+ });
125
+ };
126
+ return _jsx(_Fragment, { children: cloneChildren(child) });
127
+ };
128
+ export { Tap, useTap };
@@ -0,0 +1,18 @@
1
+ import * as React from "react";
2
+ type VideoAttributes = {
3
+ enabled: boolean;
4
+ aspectRatio: string;
5
+ videoFit: "fill" | "fit";
6
+ overlayOpacity: number;
7
+ autoplay: boolean;
8
+ videoSound: boolean;
9
+ };
10
+ interface VideoProps extends React.VideoHTMLAttributes<HTMLVideoElement> {
11
+ src: string;
12
+ videoAttributes: VideoAttributes;
13
+ naturalAspectRatio?: string;
14
+ className?: string;
15
+ }
16
+ declare const Video: React.ForwardRefExoticComponent<VideoProps & React.RefAttributes<HTMLVideoElement>>;
17
+ export { Video as VideoEnhanced };
18
+ //# sourceMappingURL=video-enhanced.d.ts.map
@@ -0,0 +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;AAW9B,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,UAAW,SAAQ,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC;IACtE,GAAG,EAAE,MAAM,CAAA;IACX,eAAe,EAAE,eAAe,CAAA;IAChC,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,QAAA,MAAM,KAAK,qFAkOV,CAAA;AAID,OAAO,EAAE,KAAK,IAAI,aAAa,EAAE,CAAA"}
@@ -0,0 +1,197 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ var __rest = (this && this.__rest) || function (s, e) {
11
+ var t = {};
12
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
13
+ t[p] = s[p];
14
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
15
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
16
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
17
+ t[p[i]] = s[p[i]];
18
+ }
19
+ return t;
20
+ };
21
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
22
+ import * as React from "react";
23
+ import { cn } from "../../lib/utils";
24
+ const videoVariants = {
25
+ base: "w-full",
26
+ fit: {
27
+ cover: "object-cover",
28
+ contain: "object-contain",
29
+ },
30
+ };
31
+ const Video = React.forwardRef((_a, ref) => {
32
+ var _b;
33
+ var { src, videoAttributes, naturalAspectRatio = "1/1", className } = _a, props = __rest(_a, ["src", "videoAttributes", "naturalAspectRatio", "className"]);
34
+ const internalRef = React.useRef(null);
35
+ const videoRef = ref || internalRef;
36
+ const playAttemptRef = React.useRef(false);
37
+ const observerRef = React.useRef(null);
38
+ const lastPositionRef = React.useRef(0);
39
+ const [isLoaded, setIsLoaded] = React.useState(false);
40
+ const [isVisible, setIsVisible] = React.useState(false);
41
+ const [isPlaying, setIsPlaying] = React.useState(false);
42
+ const setupVideo = React.useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
43
+ const video = videoRef.current;
44
+ if (!video)
45
+ return;
46
+ try {
47
+ video.currentTime = lastPositionRef.current;
48
+ if (!videoAttributes.videoSound) {
49
+ video.muted = true;
50
+ }
51
+ yield video.play();
52
+ setIsPlaying(true);
53
+ playAttemptRef.current = true;
54
+ // If sound is enabled and autoplay was successful, unmute
55
+ if (videoAttributes.videoSound && videoAttributes.autoplay) {
56
+ video.muted = false;
57
+ }
58
+ }
59
+ catch (error) {
60
+ console.error("Error playing video:", error);
61
+ setIsPlaying(false);
62
+ }
63
+ }), [videoAttributes.autoplay, videoAttributes.videoSound, videoRef]);
64
+ const handlePlayPause = () => __awaiter(void 0, void 0, void 0, function* () {
65
+ const video = videoRef.current;
66
+ if (!video)
67
+ return;
68
+ if (video.paused) {
69
+ try {
70
+ yield setupVideo();
71
+ }
72
+ catch (error) {
73
+ console.error("Error playing video:", error);
74
+ }
75
+ }
76
+ else {
77
+ video.pause();
78
+ setIsPlaying(false);
79
+ }
80
+ });
81
+ React.useEffect(() => {
82
+ const video = videoRef.current;
83
+ if (!video)
84
+ return;
85
+ // Create intersection observer
86
+ observerRef.current = new IntersectionObserver((entries) => {
87
+ const [entry] = entries;
88
+ setIsVisible(entry.isIntersecting);
89
+ // Handle visibility change
90
+ if (!entry.isIntersecting && !video.paused) {
91
+ lastPositionRef.current = video.currentTime;
92
+ video.pause();
93
+ setIsPlaying(false);
94
+ }
95
+ else if (entry.isIntersecting &&
96
+ videoAttributes.autoplay &&
97
+ video.paused) {
98
+ video.currentTime = lastPositionRef.current;
99
+ setupVideo();
100
+ }
101
+ }, {
102
+ threshold: 0.1, // 10% of the video needs to be visible
103
+ });
104
+ // Start observing
105
+ observerRef.current.observe(video);
106
+ // Track play state
107
+ const handlePlay = () => setIsPlaying(true);
108
+ const handlePause = () => setIsPlaying(false);
109
+ video.addEventListener("play", handlePlay);
110
+ video.addEventListener("pause", handlePause);
111
+ return () => {
112
+ if (video && !video.paused) {
113
+ lastPositionRef.current = video.currentTime;
114
+ }
115
+ if (observerRef.current) {
116
+ observerRef.current.disconnect();
117
+ }
118
+ video.removeEventListener("play", handlePlay);
119
+ video.removeEventListener("pause", handlePause);
120
+ playAttemptRef.current = false;
121
+ };
122
+ }, [setupVideo, videoAttributes.autoplay, videoRef]);
123
+ // Handle attribute changes
124
+ React.useEffect(() => {
125
+ const video = videoRef.current;
126
+ if (!video)
127
+ return;
128
+ if (isVisible && videoAttributes.autoplay) {
129
+ setupVideo();
130
+ }
131
+ else if (!isVisible && !video.paused) {
132
+ lastPositionRef.current = video.currentTime;
133
+ video.pause();
134
+ setIsPlaying(false);
135
+ }
136
+ return () => {
137
+ if (video && !video.paused) {
138
+ lastPositionRef.current = video.currentTime;
139
+ }
140
+ };
141
+ }, [
142
+ videoAttributes.autoplay,
143
+ videoAttributes.videoSound,
144
+ isVisible,
145
+ videoRef,
146
+ setupVideo,
147
+ ]);
148
+ React.useEffect(() => {
149
+ const video = videoRef.current;
150
+ if (!video)
151
+ return;
152
+ const handleTimeUpdate = () => {
153
+ lastPositionRef.current = video.currentTime;
154
+ };
155
+ video.addEventListener("timeupdate", handleTimeUpdate);
156
+ return () => {
157
+ video.removeEventListener("timeupdate", handleTimeUpdate);
158
+ };
159
+ }, [videoRef]);
160
+ // Initial load and metadata setup - only needs to run when src changes
161
+ React.useEffect(() => {
162
+ const video = videoRef.current;
163
+ if (!video)
164
+ return;
165
+ const handleLoadedMetadata = () => {
166
+ setIsLoaded(true);
167
+ if (videoAttributes.autoplay && isVisible) {
168
+ const currentTime = lastPositionRef.current;
169
+ video.currentTime = currentTime;
170
+ video.play().catch((error) => {
171
+ console.error("Error playing video:", error);
172
+ });
173
+ }
174
+ };
175
+ video.addEventListener("loadedmetadata", handleLoadedMetadata);
176
+ video.load();
177
+ return () => {
178
+ video.removeEventListener("loadedmetadata", handleLoadedMetadata);
179
+ };
180
+ }, [src]);
181
+ React.useEffect(() => {
182
+ lastPositionRef.current = 0;
183
+ setIsLoaded(false);
184
+ }, [src]);
185
+ const videoStyle = {
186
+ aspectRatio: videoAttributes.enabled && videoAttributes.aspectRatio !== "auto"
187
+ ? videoAttributes.aspectRatio.replace(":", "/")
188
+ : naturalAspectRatio.replace(":", "/"),
189
+ };
190
+ return (_jsxs("div", Object.assign({ className: "relative w-full" }, { children: [_jsx("video", Object.assign({ ref: videoRef, className: cn(videoVariants.base, videoAttributes.videoFit === "fill"
191
+ ? videoVariants.fit.cover
192
+ : videoVariants.fit.contain, className), style: videoStyle, preload: "metadata", playsInline: true, loop: videoAttributes.enabled, controls: false, src: src }, props)), ((isLoaded && !isPlaying) ||
193
+ (videoAttributes.videoSound && ((_b = videoRef.current) === null || _b === void 0 ? void 0 : _b.muted))) &&
194
+ videoAttributes.enabled && (_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 hover:bg-black/90 \n flex items-center justify-center transition-all duration-300\n hover:scale-110 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]" }) })))] })));
195
+ });
196
+ Video.displayName = "Video";
197
+ export { Video as VideoEnhanced };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { cn, cva, getColor, getBackgroundAndPaddingStyle, getBorderSidesStyle, getTextStyle, getVerticalAlignmentStyle, getBackgroundAndSpacingStyle, getIdFromGid, productGidFromId, variantGidFromId, getPaddingStyle, getVerticalAlignment, mapFlexToAlignment, formatRelativeTime, stringRatioToInt, getOverlayStyle, getDestinationHandler, createCollectionImageMap, } from "./lib/utils";
1
+ export { cn, cva, getColor, getBackgroundAndPaddingStyle, getBorderSidesStyle, getTextStyle, getVerticalAlignmentStyle, getBackgroundAndSpacingStyle, getIdFromGid, productGidFromId, variantGidFromId, getPaddingStyle, getVerticalAlignment, mapFlexToAlignment, formatRelativeTime, stringRatioToInt, getOverlayStyle, throttleFunction, getDestinationHandler, getProductGidsFromIds, createCollectionImageMap, } from "./lib/utils";
2
2
  export * from "./components/hooks/use-collection";
3
3
  export * from "./components/hooks/use-infinite-scroll";
4
4
  export * from "./components/hooks/use-recommendations";
@@ -7,7 +7,6 @@ export * from "./components/hooks/use-scroll-direction";
7
7
  export * from "./components/hooks/use-sort-filter";
8
8
  export * from "./components/hooks/use-product-options";
9
9
  export * from "./components/hooks/use-shop";
10
- export * from "./components/hooks/use-tap";
11
10
  export * from "./components/ui/accordion";
12
11
  export * from "./components/ui/aspect-ratio";
13
12
  export * from "./components/ui/badge";
@@ -48,11 +47,16 @@ export * from "./components/ui/toggle-group";
48
47
  export * from "./components/ui/toggle";
49
48
  export * from "./components/ui/use-toast";
50
49
  export * from "./components/ui/video";
50
+ export * from "./components/ui/video-enhanced";
51
51
  export * from "./components/ui/wishlist";
52
52
  export * from "./components/ui/wishlist-select";
53
53
  export * from "./components/hooks/use-shop";
54
54
  export * from "./components/libs/sort-filter/search-integration";
55
55
  export * from "./components/hooks/use-reviews";
56
56
  export * from "./components/ui/subcollection-tabs";
57
+ export * from "./components/ui/ProductCard/utils";
58
+ export * from "./lib/price";
59
+ export * from "./components/hooks/use-nosto-recommendation";
57
60
  export * from "./components/libs/sort-filter/search-integration";
61
+ export * from "./components/ui/tap";
58
62
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,EAAE,EACF,GAAG,EACH,QAAQ,EACR,4BAA4B,EAC5B,mBAAmB,EACnB,YAAY,EACZ,yBAAyB,EACzB,4BAA4B,EAC5B,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,aAAa,CAAA;AACpB,cAAc,mCAAmC,CAAA;AACjD,cAAc,wCAAwC,CAAA;AACtD,cAAc,wCAAwC,CAAA;AACtD,cAAc,iCAAiC,CAAA;AAC/C,cAAc,yCAAyC,CAAA;AACvD,cAAc,oCAAoC,CAAA;AAClD,cAAc,wCAAwC,CAAA;AACtD,cAAc,6BAA6B,CAAA;AAC3C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,2BAA2B,CAAA;AACzC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,uBAAuB,CAAA;AACrC,cAAc,wBAAwB,CAAA;AACtC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AACxC,cAAc,sBAAsB,CAAA;AACpC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,2BAA2B,CAAA;AACzC,cAAc,wBAAwB,CAAA;AACtC,cAAc,0BAA0B,CAAA;AACxC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,0BAA0B,CAAA;AACxC,cAAc,sBAAsB,CAAA;AACpC,cAAc,sBAAsB,CAAA;AACpC,cAAc,uBAAuB,CAAA;AACrC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,uBAAuB,CAAA;AACrC,cAAc,sCAAsC,CAAA;AACpD,cAAc,uBAAuB,CAAA;AACrC,cAAc,uBAAuB,CAAA;AACrC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,iCAAiC,CAAA;AAC/C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,2BAA2B,CAAA;AACzC,cAAc,2BAA2B,CAAA;AACzC,cAAc,0BAA0B,CAAA;AACxC,cAAc,wBAAwB,CAAA;AACtC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,wBAAwB,CAAA;AACtC,cAAc,sBAAsB,CAAA;AACpC,cAAc,sBAAsB,CAAA;AACpC,cAAc,0BAA0B,CAAA;AACxC,cAAc,uBAAuB,CAAA;AACrC,cAAc,yBAAyB,CAAA;AACvC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,wBAAwB,CAAA;AACtC,cAAc,2BAA2B,CAAA;AACzC,cAAc,uBAAuB,CAAA;AACrC,cAAc,0BAA0B,CAAA;AACxC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,kDAAkD,CAAA;AAChE,cAAc,gCAAgC,CAAA;AAC9C,cAAc,oCAAoC,CAAA;AAClD,cAAc,kDAAkD,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,EAAE,EACF,GAAG,EACH,QAAQ,EACR,4BAA4B,EAC5B,mBAAmB,EACnB,YAAY,EACZ,yBAAyB,EACzB,4BAA4B,EAC5B,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,qBAAqB,EACrB,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,aAAa,CAAA;AACpB,cAAc,mCAAmC,CAAA;AACjD,cAAc,wCAAwC,CAAA;AACtD,cAAc,wCAAwC,CAAA;AACtD,cAAc,iCAAiC,CAAA;AAC/C,cAAc,yCAAyC,CAAA;AACvD,cAAc,oCAAoC,CAAA;AAClD,cAAc,wCAAwC,CAAA;AACtD,cAAc,6BAA6B,CAAA;AAC3C,cAAc,2BAA2B,CAAA;AACzC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,uBAAuB,CAAA;AACrC,cAAc,wBAAwB,CAAA;AACtC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AACxC,cAAc,sBAAsB,CAAA;AACpC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,2BAA2B,CAAA;AACzC,cAAc,wBAAwB,CAAA;AACtC,cAAc,0BAA0B,CAAA;AACxC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,0BAA0B,CAAA;AACxC,cAAc,sBAAsB,CAAA;AACpC,cAAc,sBAAsB,CAAA;AACpC,cAAc,uBAAuB,CAAA;AACrC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,uBAAuB,CAAA;AACrC,cAAc,sCAAsC,CAAA;AACpD,cAAc,uBAAuB,CAAA;AACrC,cAAc,uBAAuB,CAAA;AACrC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,iCAAiC,CAAA;AAC/C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,2BAA2B,CAAA;AACzC,cAAc,2BAA2B,CAAA;AACzC,cAAc,0BAA0B,CAAA;AACxC,cAAc,wBAAwB,CAAA;AACtC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,wBAAwB,CAAA;AACtC,cAAc,sBAAsB,CAAA;AACpC,cAAc,sBAAsB,CAAA;AACpC,cAAc,0BAA0B,CAAA;AACxC,cAAc,uBAAuB,CAAA;AACrC,cAAc,yBAAyB,CAAA;AACvC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,wBAAwB,CAAA;AACtC,cAAc,2BAA2B,CAAA;AACzC,cAAc,uBAAuB,CAAA;AACrC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,0BAA0B,CAAA;AACxC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,kDAAkD,CAAA;AAChE,cAAc,gCAAgC,CAAA;AAC9C,cAAc,oCAAoC,CAAA;AAClD,cAAc,mCAAmC,CAAA;AACjD,cAAc,aAAa,CAAA;AAC3B,cAAc,6CAA6C,CAAA;AAC3D,cAAc,kDAAkD,CAAA;AAChE,cAAc,qBAAqB,CAAA"}
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // component exports
2
- export { cn, cva, getColor, getBackgroundAndPaddingStyle, getBorderSidesStyle, getTextStyle, getVerticalAlignmentStyle, getBackgroundAndSpacingStyle, getIdFromGid, productGidFromId, variantGidFromId, getPaddingStyle, getVerticalAlignment, mapFlexToAlignment, formatRelativeTime, stringRatioToInt, getOverlayStyle, getDestinationHandler, createCollectionImageMap, } from "./lib/utils";
2
+ export { cn, cva, getColor, getBackgroundAndPaddingStyle, getBorderSidesStyle, getTextStyle, getVerticalAlignmentStyle, getBackgroundAndSpacingStyle, getIdFromGid, productGidFromId, variantGidFromId, getPaddingStyle, getVerticalAlignment, mapFlexToAlignment, formatRelativeTime, stringRatioToInt, getOverlayStyle, throttleFunction, getDestinationHandler, getProductGidsFromIds, createCollectionImageMap, } from "./lib/utils";
3
3
  export * from "./components/hooks/use-collection";
4
4
  export * from "./components/hooks/use-infinite-scroll";
5
5
  export * from "./components/hooks/use-recommendations";
@@ -8,7 +8,6 @@ export * from "./components/hooks/use-scroll-direction";
8
8
  export * from "./components/hooks/use-sort-filter";
9
9
  export * from "./components/hooks/use-product-options";
10
10
  export * from "./components/hooks/use-shop";
11
- export * from "./components/hooks/use-tap";
12
11
  export * from "./components/ui/accordion";
13
12
  export * from "./components/ui/aspect-ratio";
14
13
  export * from "./components/ui/badge";
@@ -49,10 +48,15 @@ export * from "./components/ui/toggle-group";
49
48
  export * from "./components/ui/toggle";
50
49
  export * from "./components/ui/use-toast";
51
50
  export * from "./components/ui/video";
51
+ export * from "./components/ui/video-enhanced";
52
52
  export * from "./components/ui/wishlist";
53
53
  export * from "./components/ui/wishlist-select";
54
54
  export * from "./components/hooks/use-shop";
55
55
  export * from "./components/libs/sort-filter/search-integration";
56
56
  export * from "./components/hooks/use-reviews";
57
57
  export * from "./components/ui/subcollection-tabs";
58
+ export * from "./components/ui/ProductCard/utils";
59
+ export * from "./lib/price";
60
+ export * from "./components/hooks/use-nosto-recommendation";
58
61
  export * from "./components/libs/sort-filter/search-integration";
62
+ export * from "./components/ui/tap";
@@ -0,0 +1,29 @@
1
+ import { ProductVariant, Product } from "app-studio-types";
2
+ type Badge = {
3
+ verticalPosition: "below" | "bottom" | "top";
4
+ priority: number;
5
+ tags: string[];
6
+ excludeTags: string[];
7
+ text?: string;
8
+ color?: string;
9
+ backgroundColor?: string;
10
+ };
11
+ type BadgeConfig = {
12
+ [key in "below" | "bottom" | "top"]?: Badge[];
13
+ };
14
+ export declare const getCheapestProductFromVariantsFn: (productVariants: ProductVariant[]) => ProductVariant;
15
+ export declare const getBadgeForProductFn: (badgeConfig?: BadgeConfig, productTags?: string[]) => Badge | undefined;
16
+ export declare function getPriceRangesFn(product: Product): {
17
+ price: number;
18
+ isSale: boolean;
19
+ priceHigh?: number | undefined;
20
+ compareAtPrice?: number | undefined;
21
+ compareAtPriceHigh?: number | undefined;
22
+ };
23
+ export declare function getPriceFn(product: Product): {
24
+ price: number;
25
+ compareAtPrice: number;
26
+ isSale: boolean;
27
+ };
28
+ export {};
29
+ //# sourceMappingURL=price.d.ts.map
@@ -0,0 +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;AAG1D,KAAK,KAAK,GAAG;IACX,gBAAgB,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAA;IAC5C,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,WAAW,EAAE,MAAM,EAAE,CAAA;IAErB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB,CAAA;AAGD,KAAK,WAAW,GAAG;KAChB,GAAG,IAAI,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE;CAC9C,CAAA;AAGD,eAAO,MAAM,gCAAgC,oBAC1B,cAAc,EAAE,mBAelC,CAAA;AAED,eAAO,MAAM,oBAAoB,iBAClB,WAAW,gBACX,MAAM,EAAE,KACpB,KAAK,GAAG,SAqBV,CAAA;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO;WAsBtC,MAAM;YACL,OAAO;;;;EAclB;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO;;;;EAQ1C"}
@@ -0,0 +1,66 @@
1
+ // Return the cheapest available variant for pricing details
2
+ export const getCheapestProductFromVariantsFn = (productVariants) => {
3
+ const availableVariants = productVariants.filter((variant) => variant.availableForSale);
4
+ // Use pricing from in-stock variants only. If all are out of stock use all variants.
5
+ const activeVariants = availableVariants.length
6
+ ? availableVariants
7
+ : productVariants;
8
+ return activeVariants.reduce((lowest, current) => {
9
+ return parseFloat(current.price.amount) < parseFloat(lowest.price.amount)
10
+ ? current
11
+ : lowest;
12
+ });
13
+ };
14
+ export const getBadgeForProductFn = (badgeConfig = {}, productTags = []) => {
15
+ const badgePositions = ["below", "bottom", "top"];
16
+ const badgesCombined = [];
17
+ const addBadgesToCombined = (badgePosition) => {
18
+ var _a;
19
+ return (_a = badgeConfig[badgePosition]) === null || _a === void 0 ? void 0 : _a.forEach((badge) => badgesCombined.push(Object.assign(Object.assign({}, badge), { verticalPosition: badgePosition })));
20
+ };
21
+ badgePositions.forEach(addBadgesToCombined);
22
+ badgesCombined.sort((a, b) => a.priority - b.priority);
23
+ let productBadge = badgesCombined.find((badge) => {
24
+ if (productTags.includes(badge.tags[0])) {
25
+ if (productTags.includes(badge.excludeTags[0]))
26
+ return false;
27
+ return true;
28
+ }
29
+ return false;
30
+ });
31
+ return productBadge;
32
+ };
33
+ export function getPriceRangesFn(product) {
34
+ const { minVariantPrice: minPrice, maxVariantPrice: maxPrice } = product.priceRange;
35
+ const { minVariantPrice: minCompareAt, maxVariantPrice: maxCompareAt } = product.compareAtPriceRange;
36
+ const floatMinPrice = parseFloat(minPrice.amount);
37
+ const floatMaxPrice = minPrice.amount !== maxPrice.amount && parseFloat(maxPrice.amount);
38
+ const floatMinCompareAt = minCompareAt && parseFloat(minCompareAt.amount);
39
+ const floatMaxCompareAt = minCompareAt.amount !== maxCompareAt.amount &&
40
+ parseFloat(maxCompareAt.amount);
41
+ const isSale = product.variants.some((variant) => {
42
+ return (variant.compareAtPrice &&
43
+ parseFloat(variant.price.amount) <
44
+ parseFloat(variant.compareAtPrice.amount));
45
+ });
46
+ const formattedPrice = {
47
+ price: floatMinPrice,
48
+ isSale,
49
+ };
50
+ if (floatMaxPrice)
51
+ formattedPrice.priceHigh = floatMaxPrice;
52
+ if (floatMinCompareAt)
53
+ formattedPrice.compareAtPrice = floatMinCompareAt;
54
+ if (floatMaxCompareAt)
55
+ formattedPrice.compareAtPriceHigh = floatMaxCompareAt;
56
+ return formattedPrice;
57
+ }
58
+ export function getPriceFn(product) {
59
+ var _a, _b, _c, _d, _e, _f, _g, _h;
60
+ return {
61
+ price: parseFloat((_b = (_a = product.variants[0]) === null || _a === void 0 ? void 0 : _a.price) === null || _b === void 0 ? void 0 : _b.amount),
62
+ compareAtPrice: parseFloat((_d = (_c = product.variants[0]) === null || _c === void 0 ? void 0 : _c.compareAtPrice) === null || _d === void 0 ? void 0 : _d.amount),
63
+ isSale: parseFloat((_f = (_e = product.variants[0]) === null || _e === void 0 ? void 0 : _e.price) === null || _f === void 0 ? void 0 : _f.amount) <
64
+ parseFloat((_h = (_g = product.variants[0]) === null || _g === void 0 ? void 0 : _g.compareAtPrice) === null || _h === void 0 ? void 0 : _h.amount),
65
+ };
66
+ }
@@ -146,6 +146,7 @@ export declare const mapFlexToAlignment: (flexClass: string) => string;
146
146
  export declare function getIdFromGid(gid: string | undefined): string;
147
147
  export declare function productGidFromId(id: string | null | undefined): string | null;
148
148
  export declare function variantGidFromId(id: string | null | undefined): string | null;
149
+ export declare function throttleFunction(fn: Function, wait: number): ((...args: any[]) => void)[];
149
150
  export declare function formatRelativeTime(inputDate: Date | string): string;
150
151
  export declare const stringRatioToInt: (string: string) => number;
151
152
  export declare const getOverlayStyle: (opacity: number) => {
@@ -171,6 +172,7 @@ type DestinationActions = {
171
172
  }) => void;
172
173
  };
173
174
  export declare const getDestinationHandler: (type: "app-screen" | "url" | "product" | "collection" | "none") => ((location: string, actions: DestinationActions) => void) | ((location: string, actions: DestinationActions) => void) | ((location: string, actions: DestinationActions) => void) | ((location: string, actions: DestinationActions) => void) | (() => void);
175
+ export declare function getProductGidsFromIds(ids: string[]): string[];
174
176
  export declare const createCollectionImageMap: (collections: {
175
177
  id: string;
176
178
  customImage: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../lib/utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../lib/utils.ts"],"names":[],"mappings":"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"}
package/dist/lib/utils.js CHANGED
@@ -37,13 +37,13 @@ export const getColor = (colorOption) => {
37
37
  : undefined;
38
38
  };
39
39
  export const getBorderSidesStyle = (borderSides) => {
40
- const style = borderSides.includes("all")
40
+ const style = (borderSides === null || borderSides === void 0 ? void 0 : borderSides.includes("all"))
41
41
  ? { borderWidth: "1px" }
42
42
  : {
43
- borderTopWidth: borderSides.includes("top") ? "1px" : 0,
44
- borderBottomWidth: borderSides.includes("bottom") ? "1px" : 0,
45
- borderLeftWidth: borderSides.includes("left") ? "1px" : 0,
46
- borderRightWidth: borderSides.includes("right") ? "1px" : 0,
43
+ borderTopWidth: (borderSides === null || borderSides === void 0 ? void 0 : borderSides.includes("top")) ? "1px" : 0,
44
+ borderBottomWidth: (borderSides === null || borderSides === void 0 ? void 0 : borderSides.includes("bottom")) ? "1px" : 0,
45
+ borderLeftWidth: (borderSides === null || borderSides === void 0 ? void 0 : borderSides.includes("left")) ? "1px" : 0,
46
+ borderRightWidth: (borderSides === null || borderSides === void 0 ? void 0 : borderSides.includes("right")) ? "1px" : 0,
47
47
  };
48
48
  return style;
49
49
  };
@@ -149,6 +149,24 @@ export function variantGidFromId(id) {
149
149
  return id;
150
150
  return `gid://shopify/ProductVariant/${id}`;
151
151
  }
152
+ // Use to prevent multiple clicks in quick succession
153
+ export function throttleFunction(fn, wait) {
154
+ let throttle = false;
155
+ return [
156
+ function () {
157
+ return throttle;
158
+ },
159
+ function (...args) {
160
+ if (!throttle) {
161
+ fn(...args);
162
+ throttle = true;
163
+ setInterval(() => {
164
+ throttle = false;
165
+ }, wait);
166
+ }
167
+ },
168
+ ];
169
+ }
152
170
  export function formatRelativeTime(inputDate) {
153
171
  dayjs.extend(relativeTime);
154
172
  return dayjs(inputDate).fromNow();
@@ -184,6 +202,14 @@ const DESTINATION_HANDLERS = {
184
202
  export const getDestinationHandler = (type) => {
185
203
  return DESTINATION_HANDLERS[type];
186
204
  };
205
+ export function getProductGidsFromIds(ids) {
206
+ return ids.map((id) => {
207
+ if (id.startsWith("gid://shopify/Product/")) {
208
+ return id;
209
+ }
210
+ return `gid://shopify/Product/${id}`;
211
+ });
212
+ }
187
213
  export const createCollectionImageMap = (collections) => {
188
214
  return collections.reduce((imageMap, collection) => {
189
215
  if (collection.customImage && collection.image) {