@datlv-trustshop/shopify-inapp-components 0.3.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"GrowApps.d.ts","sourceRoot":"","sources":["../../src/components/GrowApps.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAC;AAejF,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAG7C,OAAO,EAAU,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEhE,MAAM,WAAW,aAAc,SAAQ,aAAa;IAClD,yBAAyB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,wBAAwB;IACxB,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IAEpC,gCAAgC;IAChC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAQD,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CA8iB5C,CAAC"}
1
+ {"version":3,"file":"GrowApps.d.ts","sourceRoot":"","sources":["../../src/components/GrowApps.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAC;AAejF,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAG7C,OAAO,EAAU,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEhE,MAAM,WAAW,aAAc,SAAQ,aAAa;IAClD,yBAAyB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,wBAAwB;IACxB,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IAEpC,gCAAgC;IAChC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAQD,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAqiB5C,CAAC"}
@@ -86,26 +86,23 @@ shopInfo, locale, translations, config, }) => {
86
86
  if (!slidesContainerRef.current) {
87
87
  return;
88
88
  }
89
- const slideWrap = slidesContainerRef.current.querySelector(".slides-wrapper");
90
- if (!slideWrap)
91
- return;
92
89
  const containerWidth = slidesContainerRef.current.offsetWidth;
93
- const totalWidth = slideWrap.scrollWidth;
94
- const slideWidth = CARD_WIDTH;
95
- const gap = GAP_SIZE;
96
- const slideStep = slideWidth + gap;
97
- const maxSlides = Math.max(0, Math.ceil((totalWidth - containerWidth) / slideStep));
90
+ const slideStep = CARD_WIDTH + GAP_SIZE;
91
+ // Calculate how many items can fit in the container
92
+ const itemsPerView = Math.floor((containerWidth + GAP_SIZE) / slideStep);
93
+ // Maximum index is total items minus items per view
94
+ const maxSlides = Math.max(0, growApps.length - itemsPerView);
98
95
  const newIndex = Math.max(0, Math.min(currentIndex + direction, maxSlides));
99
96
  if ((direction < 0 && currentIndex === 0) ||
100
97
  (direction > 0 && currentIndex >= maxSlides)) {
101
98
  return;
102
99
  }
103
100
  const newPosition = -newIndex * slideStep;
104
- // Remove direct DOM manipulation - let React handle it
101
+ // Update all states
105
102
  setCurrentPosition(newPosition);
106
103
  setCurrentIndex(newIndex);
107
104
  setMaxIndex(maxSlides);
108
- }, [currentIndex]);
105
+ }, [currentIndex, growApps.length]);
109
106
  const handleTouchStart = useCallback((e) => {
110
107
  touchStartX.current = e.touches[0].clientX;
111
108
  touchEndX.current = e.touches[0].clientX; // Initialize end position
@@ -152,15 +149,18 @@ shopInfo, locale, translations, config, }) => {
152
149
  const calculateMaxIndex = () => {
153
150
  if (!slidesContainerRef.current)
154
151
  return;
155
- const slideWrap = slidesContainerRef.current.querySelector(".slides-wrapper");
156
- if (!slideWrap)
157
- return;
158
152
  const containerWidth = slidesContainerRef.current.offsetWidth;
159
- const totalWidth = slideWrap.scrollWidth;
160
153
  const slideStep = CARD_WIDTH + GAP_SIZE;
161
- const maxSlides = Math.max(0, Math.ceil((totalWidth - containerWidth) / slideStep));
154
+ // Calculate how many items can fit in the container
155
+ const itemsPerView = Math.floor((containerWidth + GAP_SIZE) / slideStep);
156
+ // Maximum index is total items minus items per view
157
+ const maxSlides = Math.max(0, growApps.length - itemsPerView);
162
158
  setMaxIndex(maxSlides);
163
159
  };
160
+ // Wait for DOM to be ready and content to be loaded
161
+ if (!isContentReady) {
162
+ return;
163
+ }
164
164
  // Use requestAnimationFrame instead of setTimeout for better performance
165
165
  const rafId = requestAnimationFrame(calculateMaxIndex);
166
166
  const handleResize = () => {
@@ -171,7 +171,7 @@ shopInfo, locale, translations, config, }) => {
171
171
  cancelAnimationFrame(rafId);
172
172
  window.removeEventListener("resize", handleResize);
173
173
  };
174
- }, [growApps.length]);
174
+ }, [growApps.length, isContentReady]);
175
175
  // Memoize navigation button styles to prevent recalculation
176
176
  // Must be defined before any returns to follow React hooks rules
177
177
  const navButtonStyle = useMemo(() => ({
@@ -1 +1 @@
1
- {"version":3,"file":"GrowApps.js","sourceRoot":"","sources":["../../src/components/GrowApps.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useState, useRef, useCallback, useEffect, useMemo } from \"react\";\nimport {\n Card,\n Text,\n BlockStack,\n Box,\n InlineStack,\n Button,\n Popover,\n ActionList,\n SkeletonBodyText,\n SkeletonThumbnail,\n} from \"@shopify/polaris\";\nimport { ExternalIcon, MenuHorizontalIcon } from \"@shopify/polaris-icons\";\nimport { useDashboard } from \"../hooks/useDashboard\";\nimport { GrowApp } from \"../types/dashboard\";\nimport { useTranslation } from \"../hooks/useTranslations\";\nimport { COMPONENT_DEFAULTS } from \"../config/component-defaults\";\nimport { useSDK, type UseSDKOptions } from \"../core/SDKManager\";\n\nexport interface GrowAppsProps extends UseSDKOptions {\n /** Optional CSS class */\n className?: string;\n \n /** Handle app clicks */\n onAppClick?: (app: GrowApp) => void;\n \n /** Optional dismiss callback */\n onDismiss?: () => void;\n}\n\n// Fixed dimensions to prevent layout shifts\nconst CARD_WIDTH = 282;\nconst CARD_MIN_HEIGHT = 140; // Reduced from 180 to avoid excessive white space\nconst ICON_SIZE = 60;\nconst GAP_SIZE = 20;\n\nexport const GrowApps: React.FC<GrowAppsProps> = ({\n className = \"\",\n onAppClick,\n onDismiss,\n // SDK options (optional)\n shopInfo,\n locale,\n translations,\n config,\n}) => {\n // Connect to SDK Manager (auto-initializes)\n // @ts-ignore - Will be used in future refactoring\n const _sdk = useSDK({ shopInfo, locale, translations, config });\n \n // Use internal defaults\n const {\n dismissKey,\n dismissDuration,\n showDismiss,\n showNavigation,\n maxItems,\n } = COMPONENT_DEFAULTS.growApps;\n const slidesContainerRef = useRef<HTMLDivElement>(null);\n const [currentPosition, setCurrentPosition] = useState(0);\n const { data, loading } = useDashboard();\n const growAppsTranslations = useTranslation(\"growApps\");\n\n const allGrowApps = data?.grow_apps || [];\n const displayLimit = data?.grow_apps_display_limit || maxItems;\n const growApps = allGrowApps.slice(0, displayLimit);\n\n const [currentIndex, setCurrentIndex] = useState(0);\n const [maxIndex, setMaxIndex] = useState(0);\n const [popoverActive, setPopoverActive] = useState(false);\n const [isVisible, setIsVisible] = useState(true);\n const [isContentReady, setIsContentReady] = useState(false);\n const [touchDelta, setTouchDelta] = useState(0);\n const [isSwiping, setIsSwiping] = useState(false);\n\n const touchStartX = useRef<number | null>(null);\n const touchEndX = useRef<number | null>(null);\n const swiping = useRef(false);\n const lastDelta = useRef(0);\n\n const togglePopoverActive = () => setPopoverActive((active) => !active);\n\n const handleDismiss = () => {\n setIsVisible(false);\n setPopoverActive(false);\n\n const dismissData = {\n timestamp: Date.now(),\n dismissed: true,\n };\n localStorage.setItem(dismissKey, JSON.stringify(dismissData));\n onDismiss?.();\n };\n\n useEffect(() => {\n const dismissedData = localStorage.getItem(dismissKey);\n if (dismissedData) {\n try {\n const { timestamp } = JSON.parse(dismissedData);\n const now = Date.now();\n\n if (now - timestamp < dismissDuration) {\n setIsVisible(false);\n } else {\n localStorage.removeItem(dismissKey);\n }\n } catch (error) {\n localStorage.removeItem(dismissKey);\n }\n }\n }, [dismissKey, dismissDuration]);\n\n // Mark content as ready when data loads\n useEffect(() => {\n if (!loading && growApps.length >= 0) {\n // Small delay to ensure DOM is ready\n requestAnimationFrame(() => {\n setIsContentReady(true);\n });\n }\n }, [loading, growApps.length]);\n\n const handleGetAppClick = (app: GrowApp) => {\n const url = app.button_install_link || app.app_url || app.get_app || \"#\";\n\n if (url && url !== \"#\") {\n window.open(url, \"_blank\");\n }\n onAppClick?.(app);\n };\n\n const handleSlide = useCallback(\n (direction: number) => {\n if (!slidesContainerRef.current) {\n return;\n }\n\n const slideWrap =\n slidesContainerRef.current.querySelector<HTMLElement>(\n \".slides-wrapper\",\n );\n if (!slideWrap) return;\n\n const containerWidth = slidesContainerRef.current.offsetWidth;\n const totalWidth = slideWrap.scrollWidth;\n const slideWidth = CARD_WIDTH;\n const gap = GAP_SIZE;\n const slideStep = slideWidth + gap;\n\n const maxSlides = Math.max(\n 0,\n Math.ceil((totalWidth - containerWidth) / slideStep),\n );\n const newIndex = Math.max(\n 0,\n Math.min(currentIndex + direction, maxSlides),\n );\n\n if (\n (direction < 0 && currentIndex === 0) ||\n (direction > 0 && currentIndex >= maxSlides)\n ) {\n return;\n }\n\n const newPosition = -newIndex * slideStep;\n\n // Remove direct DOM manipulation - let React handle it\n setCurrentPosition(newPosition);\n setCurrentIndex(newIndex);\n setMaxIndex(maxSlides);\n },\n [currentIndex],\n );\n\n const handleTouchStart = useCallback((e: React.TouchEvent) => {\n touchStartX.current = e.touches[0].clientX;\n touchEndX.current = e.touches[0].clientX; // Initialize end position\n swiping.current = true;\n setIsSwiping(true);\n setTouchDelta(0);\n }, []);\n\n const handleTouchMove = useCallback((e: React.TouchEvent) => {\n if (!swiping.current || touchStartX.current === null) return;\n \n touchEndX.current = e.touches[0].clientX;\n const delta = touchEndX.current - touchStartX.current;\n \n // Only update if delta changed significantly (reduce jitter)\n if (Math.abs(delta - lastDelta.current) > 1) {\n lastDelta.current = delta;\n setTouchDelta(delta);\n }\n }, []);\n\n const handleTouchEnd = useCallback(() => {\n if (!swiping.current) return;\n\n const swipeThreshold = 50;\n const diff = (touchStartX.current || 0) - (touchEndX.current || 0);\n\n if (Math.abs(diff) > swipeThreshold) {\n if (diff > 0) {\n handleSlide(1);\n } else {\n handleSlide(-1);\n }\n } else {\n // Snap back if swipe wasn't far enough\n setTouchDelta(0);\n }\n\n swiping.current = false;\n touchStartX.current = null;\n touchEndX.current = null;\n lastDelta.current = 0;\n setIsSwiping(false);\n setTouchDelta(0);\n }, [handleSlide]);\n\n useEffect(() => {\n const calculateMaxIndex = () => {\n if (!slidesContainerRef.current) return;\n\n const slideWrap =\n slidesContainerRef.current.querySelector<HTMLElement>(\n \".slides-wrapper\",\n );\n if (!slideWrap) return;\n\n const containerWidth = slidesContainerRef.current.offsetWidth;\n const totalWidth = slideWrap.scrollWidth;\n const slideStep = CARD_WIDTH + GAP_SIZE;\n\n const maxSlides = Math.max(\n 0,\n Math.ceil((totalWidth - containerWidth) / slideStep),\n );\n setMaxIndex(maxSlides);\n };\n\n // Use requestAnimationFrame instead of setTimeout for better performance\n const rafId = requestAnimationFrame(calculateMaxIndex);\n\n const handleResize = () => {\n requestAnimationFrame(calculateMaxIndex);\n };\n window.addEventListener(\"resize\", handleResize);\n\n return () => {\n cancelAnimationFrame(rafId);\n window.removeEventListener(\"resize\", handleResize);\n };\n }, [growApps.length]);\n\n // Memoize navigation button styles to prevent recalculation\n // Must be defined before any returns to follow React hooks rules\n const navButtonStyle = useMemo(() => ({\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"24px\",\n height: \"24px\",\n padding: 0,\n border: \"none\",\n borderRadius: \"4px\",\n backgroundColor: \"transparent\",\n transition: \"opacity 0.2s ease\", // Only animate opacity\n }), []);\n\n // Don't render at all if dismissed to prevent CLS\n if (!isVisible) {\n return null;\n }\n\n // Show skeleton while loading to reserve space\n if (loading || !isContentReady) {\n return (\n <div className={className} style={{ width: \"100%\" }}>\n <Card>\n <Box>\n <BlockStack gap=\"200\">\n {/* Header skeleton */}\n <BlockStack gap=\"100\">\n <SkeletonBodyText lines={1} />\n <SkeletonBodyText lines={1} />\n </BlockStack>\n {/* Cards skeleton */}\n <div style={{ display: \"flex\", gap: `${GAP_SIZE}px`, overflow: \"hidden\" }}>\n {[1, 2, 3].map((idx) => (\n <div\n key={idx}\n style={{\n flexShrink: 0,\n width: `${CARD_WIDTH}px`,\n minHeight: `${CARD_MIN_HEIGHT}px`,\n }}\n >\n <Card>\n <Box>\n <BlockStack gap=\"300\">\n <SkeletonThumbnail size=\"large\" />\n <BlockStack gap=\"200\">\n <SkeletonBodyText lines={1} />\n <SkeletonBodyText lines={2} />\n </BlockStack>\n </BlockStack>\n </Box>\n </Card>\n </div>\n ))}\n </div>\n </BlockStack>\n </Box>\n </Card>\n </div>\n );\n }\n\n // Handle empty state with reserved space\n if (growApps.length === 0) {\n return (\n <div className={className} style={{ width: \"100%\" }}>\n <Card>\n <Box>\n <Text variant=\"bodyMd\" tone=\"subdued\" as=\"p\">\n {growAppsTranslations?.noData || \"No apps available\"}\n </Text>\n </Box>\n </Card>\n </div>\n );\n }\n\n const activator = (\n <Button\n icon={MenuHorizontalIcon}\n variant=\"tertiary\"\n onClick={togglePopoverActive}\n ariaExpanded={popoverActive}\n />\n );\n\n return (\n <div className={className} style={{ width: \"100%\" }}>\n <Card>\n <Box>\n <BlockStack gap=\"200\">\n <InlineStack\n align=\"space-between\"\n blockAlign=\"center\"\n wrap={false}\n gap=\"300\"\n >\n <BlockStack gap=\"100\">\n <Text variant=\"headingMd\" as=\"h3\">\n {growAppsTranslations?.title || \"Grow faster with apps\"}\n </Text>\n <Text variant=\"bodyMd\" tone=\"subdued\" as=\"p\">\n {growAppsTranslations?.subtitle ||\n \"Discover powerful apps to enhance your store, streamline workflows, and boost sales.\"}\n </Text>\n </BlockStack>\n <InlineStack gap=\"100\" wrap={false}>\n {showDismiss && (\n <Box padding=\"150\">\n <Popover\n active={popoverActive}\n activator={activator}\n onClose={togglePopoverActive}\n ariaHaspopup={false}\n >\n <ActionList\n actionRole=\"menuitem\"\n items={[\n {\n content: growAppsTranslations?.dismiss || \"Dismiss\",\n onAction: handleDismiss,\n },\n ]}\n />\n </Popover>\n </Box>\n )}\n {showNavigation && growApps.length > 3 && (\n <div\n style={{\n position: \"relative\",\n width: \"fit-content\",\n boxSizing: \"content-box\",\n padding: \"4px 6px\",\n display: \"flex\",\n flexDirection: \"row\",\n flexWrap: \"nowrap\",\n gap: \"4px\",\n borderRadius: \"8px\",\n backgroundColor: \"#e3e3e3\",\n }}\n >\n <button\n onClick={() => handleSlide(-1)}\n disabled={currentIndex === 0}\n style={{\n ...navButtonStyle,\n cursor: currentIndex === 0 ? \"not-allowed\" : \"pointer\",\n opacity: currentIndex === 0 ? 0.5 : 1,\n }}\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"currentColor\"\n >\n <path\n d=\"M10.5 13L5.5 8l5-5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n fill=\"none\"\n />\n </svg>\n </button>\n <button\n onClick={() => handleSlide(1)}\n disabled={currentIndex >= maxIndex}\n style={{\n ...navButtonStyle,\n cursor: currentIndex >= maxIndex ? \"not-allowed\" : \"pointer\",\n opacity: currentIndex >= maxIndex ? 0.5 : 1,\n }}\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"currentColor\"\n >\n <path\n d=\"M5.5 13l5-5-5-5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n fill=\"none\"\n />\n </svg>\n </button>\n </div>\n )}\n </InlineStack>\n </InlineStack>\n\n <div\n className=\"slides-container\"\n style={{\n overflow: \"hidden\",\n width: \"100%\",\n touchAction: \"pan-y pinch-zoom\", // Allow vertical scroll and pinch, handle horizontal\n WebkitOverflowScrolling: \"touch\", // iOS momentum scrolling\n userSelect: \"none\", // Prevent text selection during swipe\n WebkitUserSelect: \"none\"\n // Removed minHeight to avoid excessive white space\n }}\n ref={slidesContainerRef}\n onTouchStart={handleTouchStart}\n onTouchMove={handleTouchMove}\n onTouchEnd={handleTouchEnd}\n >\n <div\n className=\"slides-wrapper\"\n style={{\n display: \"flex\",\n gap: `${GAP_SIZE}px`,\n transition: isSwiping ? \"none\" : \"transform 0.3s cubic-bezier(0.4, 0, 0.2, 1)\", // Better easing\n transform: `translate3d(${currentPosition + touchDelta}px, 0, 0)`, // Use translate3d for GPU\n willChange: isSwiping ? \"transform\" : \"auto\", // Only during interaction\n backfaceVisibility: \"hidden\", // Force GPU acceleration\n perspective: 1000, // Create 3D rendering context\n }}\n >\n {growApps.map((app: GrowApp, index: number) => {\n const iconUrl = app.icon_url || app.imageUrl || \"\";\n const buttonText =\n app.button_install_text ||\n app.button_text ||\n app.button_get_app ||\n growAppsTranslations?.install ||\n \"Get app\";\n\n return (\n <div\n key={app.id || index}\n data-index={index}\n style={{\n flexShrink: 0,\n width: `${CARD_WIDTH}px`,\n // Remove per-card transition that causes CLS\n }}\n >\n <Card>\n <Box minWidth={`${CARD_WIDTH - 32}px`}>\n <BlockStack gap=\"300\">\n <InlineStack gap=\"400\" blockAlign=\"start\">\n {iconUrl ? (\n <img\n src={iconUrl}\n alt={app.title}\n width={ICON_SIZE}\n height={ICON_SIZE}\n style={{\n borderRadius: \"8px\",\n flexShrink: 0,\n objectFit: \"cover\",\n }}\n loading=\"eager\"\n decoding=\"async\"\n />\n ) : (\n <div\n style={{\n width: `${ICON_SIZE}px`,\n height: `${ICON_SIZE}px`,\n borderRadius: \"8px\",\n backgroundColor: \"#f0f0f0\",\n flexShrink: 0,\n }}\n />\n )}\n </InlineStack>\n\n <BlockStack gap=\"200\">\n <div\n style={{\n display: \"-webkit-box\",\n fontSize: \"13px\",\n fontWeight: 650,\n color: \"#303030\",\n WebkitLineClamp: 1,\n WebkitBoxOrient: \"vertical\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n minHeight: \"20px\", // Reserve space\n }}\n >\n {app.title}\n </div>\n\n <div\n style={{\n display: \"-webkit-box\",\n WebkitLineClamp: 2,\n WebkitBoxOrient: \"vertical\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n fontSize: \"13px\",\n color: \"#616161\",\n lineHeight: 1.4,\n minHeight: \"36px\", // Reserve space for 2 lines\n }}\n >\n {app.content}\n </div>\n <div\n style={{\n alignSelf: \"flex-start\",\n minHeight: \"36px\", // Reserve space for button\n }}\n >\n <Button\n icon={ExternalIcon}\n variant=\"secondary\"\n size=\"medium\"\n onClick={() => handleGetAppClick(app)}\n >\n {buttonText}\n </Button>\n </div>\n </BlockStack>\n </BlockStack>\n </Box>\n </Card>\n </div>\n );\n })}\n </div>\n </div>\n </BlockStack>\n </Box>\n </Card>\n </div>\n );\n};\n"]}
1
+ {"version":3,"file":"GrowApps.js","sourceRoot":"","sources":["../../src/components/GrowApps.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useState, useRef, useCallback, useEffect, useMemo } from \"react\";\nimport {\n Card,\n Text,\n BlockStack,\n Box,\n InlineStack,\n Button,\n Popover,\n ActionList,\n SkeletonBodyText,\n SkeletonThumbnail,\n} from \"@shopify/polaris\";\nimport { ExternalIcon, MenuHorizontalIcon } from \"@shopify/polaris-icons\";\nimport { useDashboard } from \"../hooks/useDashboard\";\nimport { GrowApp } from \"../types/dashboard\";\nimport { useTranslation } from \"../hooks/useTranslations\";\nimport { COMPONENT_DEFAULTS } from \"../config/component-defaults\";\nimport { useSDK, type UseSDKOptions } from \"../core/SDKManager\";\n\nexport interface GrowAppsProps extends UseSDKOptions {\n /** Optional CSS class */\n className?: string;\n \n /** Handle app clicks */\n onAppClick?: (app: GrowApp) => void;\n \n /** Optional dismiss callback */\n onDismiss?: () => void;\n}\n\n// Fixed dimensions to prevent layout shifts\nconst CARD_WIDTH = 282;\nconst CARD_MIN_HEIGHT = 140; // Reduced from 180 to avoid excessive white space\nconst ICON_SIZE = 60;\nconst GAP_SIZE = 20;\n\nexport const GrowApps: React.FC<GrowAppsProps> = ({\n className = \"\",\n onAppClick,\n onDismiss,\n // SDK options (optional)\n shopInfo,\n locale,\n translations,\n config,\n}) => {\n // Connect to SDK Manager (auto-initializes)\n // @ts-ignore - Will be used in future refactoring\n const _sdk = useSDK({ shopInfo, locale, translations, config });\n \n // Use internal defaults\n const {\n dismissKey,\n dismissDuration,\n showDismiss,\n showNavigation,\n maxItems,\n } = COMPONENT_DEFAULTS.growApps;\n const slidesContainerRef = useRef<HTMLDivElement>(null);\n const [currentPosition, setCurrentPosition] = useState(0);\n const { data, loading } = useDashboard();\n const growAppsTranslations = useTranslation(\"growApps\");\n\n const allGrowApps = data?.grow_apps || [];\n const displayLimit = data?.grow_apps_display_limit || maxItems;\n const growApps = allGrowApps.slice(0, displayLimit);\n\n const [currentIndex, setCurrentIndex] = useState(0);\n const [maxIndex, setMaxIndex] = useState(0);\n const [popoverActive, setPopoverActive] = useState(false);\n const [isVisible, setIsVisible] = useState(true);\n const [isContentReady, setIsContentReady] = useState(false);\n const [touchDelta, setTouchDelta] = useState(0);\n const [isSwiping, setIsSwiping] = useState(false);\n\n const touchStartX = useRef<number | null>(null);\n const touchEndX = useRef<number | null>(null);\n const swiping = useRef(false);\n const lastDelta = useRef(0);\n\n const togglePopoverActive = () => setPopoverActive((active) => !active);\n\n const handleDismiss = () => {\n setIsVisible(false);\n setPopoverActive(false);\n\n const dismissData = {\n timestamp: Date.now(),\n dismissed: true,\n };\n localStorage.setItem(dismissKey, JSON.stringify(dismissData));\n onDismiss?.();\n };\n\n useEffect(() => {\n const dismissedData = localStorage.getItem(dismissKey);\n if (dismissedData) {\n try {\n const { timestamp } = JSON.parse(dismissedData);\n const now = Date.now();\n\n if (now - timestamp < dismissDuration) {\n setIsVisible(false);\n } else {\n localStorage.removeItem(dismissKey);\n }\n } catch (error) {\n localStorage.removeItem(dismissKey);\n }\n }\n }, [dismissKey, dismissDuration]);\n\n // Mark content as ready when data loads\n useEffect(() => {\n if (!loading && growApps.length >= 0) {\n // Small delay to ensure DOM is ready\n requestAnimationFrame(() => {\n setIsContentReady(true);\n });\n }\n }, [loading, growApps.length]);\n\n const handleGetAppClick = (app: GrowApp) => {\n const url = app.button_install_link || app.app_url || app.get_app || \"#\";\n\n if (url && url !== \"#\") {\n window.open(url, \"_blank\");\n }\n onAppClick?.(app);\n };\n\n const handleSlide = useCallback(\n (direction: number) => {\n if (!slidesContainerRef.current) {\n return;\n }\n\n const containerWidth = slidesContainerRef.current.offsetWidth;\n const slideStep = CARD_WIDTH + GAP_SIZE;\n \n // Calculate how many items can fit in the container\n const itemsPerView = Math.floor((containerWidth + GAP_SIZE) / slideStep);\n // Maximum index is total items minus items per view\n const maxSlides = Math.max(0, growApps.length - itemsPerView);\n \n const newIndex = Math.max(\n 0,\n Math.min(currentIndex + direction, maxSlides),\n );\n\n if (\n (direction < 0 && currentIndex === 0) ||\n (direction > 0 && currentIndex >= maxSlides)\n ) {\n return;\n }\n\n const newPosition = -newIndex * slideStep;\n\n // Update all states\n setCurrentPosition(newPosition);\n setCurrentIndex(newIndex);\n setMaxIndex(maxSlides);\n },\n [currentIndex, growApps.length],\n );\n\n const handleTouchStart = useCallback((e: React.TouchEvent) => {\n touchStartX.current = e.touches[0].clientX;\n touchEndX.current = e.touches[0].clientX; // Initialize end position\n swiping.current = true;\n setIsSwiping(true);\n setTouchDelta(0);\n }, []);\n\n const handleTouchMove = useCallback((e: React.TouchEvent) => {\n if (!swiping.current || touchStartX.current === null) return;\n \n touchEndX.current = e.touches[0].clientX;\n const delta = touchEndX.current - touchStartX.current;\n \n // Only update if delta changed significantly (reduce jitter)\n if (Math.abs(delta - lastDelta.current) > 1) {\n lastDelta.current = delta;\n setTouchDelta(delta);\n }\n }, []);\n\n const handleTouchEnd = useCallback(() => {\n if (!swiping.current) return;\n\n const swipeThreshold = 50;\n const diff = (touchStartX.current || 0) - (touchEndX.current || 0);\n\n if (Math.abs(diff) > swipeThreshold) {\n if (diff > 0) {\n handleSlide(1);\n } else {\n handleSlide(-1);\n }\n } else {\n // Snap back if swipe wasn't far enough\n setTouchDelta(0);\n }\n\n swiping.current = false;\n touchStartX.current = null;\n touchEndX.current = null;\n lastDelta.current = 0;\n setIsSwiping(false);\n setTouchDelta(0);\n }, [handleSlide]);\n\n useEffect(() => {\n const calculateMaxIndex = () => {\n if (!slidesContainerRef.current) return;\n\n const containerWidth = slidesContainerRef.current.offsetWidth;\n const slideStep = CARD_WIDTH + GAP_SIZE;\n \n // Calculate how many items can fit in the container\n const itemsPerView = Math.floor((containerWidth + GAP_SIZE) / slideStep);\n // Maximum index is total items minus items per view\n const maxSlides = Math.max(0, growApps.length - itemsPerView);\n \n setMaxIndex(maxSlides);\n };\n\n // Wait for DOM to be ready and content to be loaded\n if (!isContentReady) {\n return;\n }\n \n // Use requestAnimationFrame instead of setTimeout for better performance\n const rafId = requestAnimationFrame(calculateMaxIndex);\n\n const handleResize = () => {\n requestAnimationFrame(calculateMaxIndex);\n };\n window.addEventListener(\"resize\", handleResize);\n\n return () => {\n cancelAnimationFrame(rafId);\n window.removeEventListener(\"resize\", handleResize);\n };\n }, [growApps.length, isContentReady]);\n\n // Memoize navigation button styles to prevent recalculation\n // Must be defined before any returns to follow React hooks rules\n const navButtonStyle = useMemo(() => ({\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"24px\",\n height: \"24px\",\n padding: 0,\n border: \"none\",\n borderRadius: \"4px\",\n backgroundColor: \"transparent\",\n transition: \"opacity 0.2s ease\", // Only animate opacity\n }), []);\n\n // Don't render at all if dismissed to prevent CLS\n if (!isVisible) {\n return null;\n }\n\n // Show skeleton while loading to reserve space\n if (loading || !isContentReady) {\n return (\n <div className={className} style={{ width: \"100%\" }}>\n <Card>\n <Box>\n <BlockStack gap=\"200\">\n {/* Header skeleton */}\n <BlockStack gap=\"100\">\n <SkeletonBodyText lines={1} />\n <SkeletonBodyText lines={1} />\n </BlockStack>\n {/* Cards skeleton */}\n <div style={{ display: \"flex\", gap: `${GAP_SIZE}px`, overflow: \"hidden\" }}>\n {[1, 2, 3].map((idx) => (\n <div\n key={idx}\n style={{\n flexShrink: 0,\n width: `${CARD_WIDTH}px`,\n minHeight: `${CARD_MIN_HEIGHT}px`,\n }}\n >\n <Card>\n <Box>\n <BlockStack gap=\"300\">\n <SkeletonThumbnail size=\"large\" />\n <BlockStack gap=\"200\">\n <SkeletonBodyText lines={1} />\n <SkeletonBodyText lines={2} />\n </BlockStack>\n </BlockStack>\n </Box>\n </Card>\n </div>\n ))}\n </div>\n </BlockStack>\n </Box>\n </Card>\n </div>\n );\n }\n\n // Handle empty state with reserved space\n if (growApps.length === 0) {\n return (\n <div className={className} style={{ width: \"100%\" }}>\n <Card>\n <Box>\n <Text variant=\"bodyMd\" tone=\"subdued\" as=\"p\">\n {growAppsTranslations?.noData || \"No apps available\"}\n </Text>\n </Box>\n </Card>\n </div>\n );\n }\n\n const activator = (\n <Button\n icon={MenuHorizontalIcon}\n variant=\"tertiary\"\n onClick={togglePopoverActive}\n ariaExpanded={popoverActive}\n />\n );\n\n return (\n <div className={className} style={{ width: \"100%\" }}>\n <Card>\n <Box>\n <BlockStack gap=\"200\">\n <InlineStack\n align=\"space-between\"\n blockAlign=\"center\"\n wrap={false}\n gap=\"300\"\n >\n <BlockStack gap=\"100\">\n <Text variant=\"headingMd\" as=\"h3\">\n {growAppsTranslations?.title || \"Grow faster with apps\"}\n </Text>\n <Text variant=\"bodyMd\" tone=\"subdued\" as=\"p\">\n {growAppsTranslations?.subtitle ||\n \"Discover powerful apps to enhance your store, streamline workflows, and boost sales.\"}\n </Text>\n </BlockStack>\n <InlineStack gap=\"100\" wrap={false}>\n {showDismiss && (\n <Box padding=\"150\">\n <Popover\n active={popoverActive}\n activator={activator}\n onClose={togglePopoverActive}\n ariaHaspopup={false}\n >\n <ActionList\n actionRole=\"menuitem\"\n items={[\n {\n content: growAppsTranslations?.dismiss || \"Dismiss\",\n onAction: handleDismiss,\n },\n ]}\n />\n </Popover>\n </Box>\n )}\n {showNavigation && growApps.length > 3 && (\n <div\n style={{\n position: \"relative\",\n width: \"fit-content\",\n boxSizing: \"content-box\",\n padding: \"4px 6px\",\n display: \"flex\",\n flexDirection: \"row\",\n flexWrap: \"nowrap\",\n gap: \"4px\",\n borderRadius: \"8px\",\n backgroundColor: \"#e3e3e3\",\n }}\n >\n <button\n onClick={() => handleSlide(-1)}\n disabled={currentIndex === 0}\n style={{\n ...navButtonStyle,\n cursor: currentIndex === 0 ? \"not-allowed\" : \"pointer\",\n opacity: currentIndex === 0 ? 0.5 : 1,\n }}\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"currentColor\"\n >\n <path\n d=\"M10.5 13L5.5 8l5-5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n fill=\"none\"\n />\n </svg>\n </button>\n <button\n onClick={() => handleSlide(1)}\n disabled={currentIndex >= maxIndex}\n style={{\n ...navButtonStyle,\n cursor: currentIndex >= maxIndex ? \"not-allowed\" : \"pointer\",\n opacity: currentIndex >= maxIndex ? 0.5 : 1,\n }}\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"currentColor\"\n >\n <path\n d=\"M5.5 13l5-5-5-5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n fill=\"none\"\n />\n </svg>\n </button>\n </div>\n )}\n </InlineStack>\n </InlineStack>\n\n <div\n className=\"slides-container\"\n style={{\n overflow: \"hidden\",\n width: \"100%\",\n touchAction: \"pan-y pinch-zoom\", // Allow vertical scroll and pinch, handle horizontal\n WebkitOverflowScrolling: \"touch\", // iOS momentum scrolling\n userSelect: \"none\", // Prevent text selection during swipe\n WebkitUserSelect: \"none\"\n // Removed minHeight to avoid excessive white space\n }}\n ref={slidesContainerRef}\n onTouchStart={handleTouchStart}\n onTouchMove={handleTouchMove}\n onTouchEnd={handleTouchEnd}\n >\n <div\n className=\"slides-wrapper\"\n style={{\n display: \"flex\",\n gap: `${GAP_SIZE}px`,\n transition: isSwiping ? \"none\" : \"transform 0.3s cubic-bezier(0.4, 0, 0.2, 1)\", // Better easing\n transform: `translate3d(${currentPosition + touchDelta}px, 0, 0)`, // Use translate3d for GPU\n willChange: isSwiping ? \"transform\" : \"auto\", // Only during interaction\n backfaceVisibility: \"hidden\", // Force GPU acceleration\n perspective: 1000, // Create 3D rendering context\n }}\n >\n {growApps.map((app: GrowApp, index: number) => {\n const iconUrl = app.icon_url || app.imageUrl || \"\";\n const buttonText =\n app.button_install_text ||\n app.button_text ||\n app.button_get_app ||\n growAppsTranslations?.install ||\n \"Get app\";\n\n return (\n <div\n key={app.id || index}\n data-index={index}\n style={{\n flexShrink: 0,\n width: `${CARD_WIDTH}px`,\n // Remove per-card transition that causes CLS\n }}\n >\n <Card>\n <Box minWidth={`${CARD_WIDTH - 32}px`}>\n <BlockStack gap=\"300\">\n <InlineStack gap=\"400\" blockAlign=\"start\">\n {iconUrl ? (\n <img\n src={iconUrl}\n alt={app.title}\n width={ICON_SIZE}\n height={ICON_SIZE}\n style={{\n borderRadius: \"8px\",\n flexShrink: 0,\n objectFit: \"cover\",\n }}\n loading=\"eager\"\n decoding=\"async\"\n />\n ) : (\n <div\n style={{\n width: `${ICON_SIZE}px`,\n height: `${ICON_SIZE}px`,\n borderRadius: \"8px\",\n backgroundColor: \"#f0f0f0\",\n flexShrink: 0,\n }}\n />\n )}\n </InlineStack>\n\n <BlockStack gap=\"200\">\n <div\n style={{\n display: \"-webkit-box\",\n fontSize: \"13px\",\n fontWeight: 650,\n color: \"#303030\",\n WebkitLineClamp: 1,\n WebkitBoxOrient: \"vertical\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n minHeight: \"20px\", // Reserve space\n }}\n >\n {app.title}\n </div>\n\n <div\n style={{\n display: \"-webkit-box\",\n WebkitLineClamp: 2,\n WebkitBoxOrient: \"vertical\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n fontSize: \"13px\",\n color: \"#616161\",\n lineHeight: 1.4,\n minHeight: \"36px\", // Reserve space for 2 lines\n }}\n >\n {app.content}\n </div>\n <div\n style={{\n alignSelf: \"flex-start\",\n minHeight: \"36px\", // Reserve space for button\n }}\n >\n <Button\n icon={ExternalIcon}\n variant=\"secondary\"\n size=\"medium\"\n onClick={() => handleGetAppClick(app)}\n >\n {buttonText}\n </Button>\n </div>\n </BlockStack>\n </BlockStack>\n </Box>\n </Card>\n </div>\n );\n })}\n </div>\n </div>\n </BlockStack>\n </Box>\n </Card>\n </div>\n );\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datlv-trustshop/shopify-inapp-components",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "private": false,
5
5
  "description": "React TypeScript components for Shopify in-app dashboard content",
6
6
  "main": "dist/index.js",