@redotech/redo-hydrogen 1.4.5 → 1.4.7

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,42 @@
1
+ import { useEffect } from "react";
2
+ import {
3
+ updatePurpleDotButtons,
4
+ cleanupPurpleDotButtons,
5
+ } from "../utils/purple-dot";
6
+
7
+ /**
8
+ * React hook to disable add-to-cart buttons when a Purple Dot preorder element is present.
9
+ * Watches for DOM changes and automatically disables/enables buttons based on the presence
10
+ * of the <purple-dot-learn-more> element.
11
+ *
12
+ * @param disablePreorderButtons - When true, enables the preorder button disabling logic.
13
+ * When false, the hook does nothing.
14
+ *
15
+ * Usage:
16
+ * ```tsx
17
+ * function ProductPage() {
18
+ * const isShopOnSiteActive = true; // your condition here
19
+ * useDisablePurpleDotPreorder(isShopOnSiteActive);
20
+ * return <div>...</div>;
21
+ * }
22
+ * ```
23
+ */
24
+ export function useDisablePurpleDotPreorder(disablePreorderButtons: boolean): void {
25
+ useEffect(() => {
26
+ if (!disablePreorderButtons) {
27
+ return;
28
+ }
29
+
30
+ // Initial check
31
+ updatePurpleDotButtons();
32
+
33
+ // Watch for DOM changes (variant selection, page navigation, etc.)
34
+ const observer = new MutationObserver(updatePurpleDotButtons);
35
+ observer.observe(document.body, { childList: true, subtree: true });
36
+
37
+ return () => {
38
+ observer.disconnect();
39
+ cleanupPurpleDotButtons();
40
+ };
41
+ }, [disablePreorderButtons]);
42
+ }
package/src/index.ts CHANGED
@@ -4,6 +4,7 @@ import { REDO_REQUIRED_HOSTNAMES } from "./utils/security";
4
4
  import { CartProductVariantFragment, CartAttributeKey, CartInfoToEnable, RedoContextValue, RedoCoverageClient, RedoError, RedoErrorType } from "./types";
5
5
  import { LoadState, Loader, useLoad } from './utils/react-utils'
6
6
  import { RedoInfoCard } from "./components/redo-info-modal";
7
+ import { useDisablePurpleDotPreorder } from "./hooks/use-purple-dot-preorder";
7
8
 
8
9
  export {
9
10
  RedoCheckoutButtons,
@@ -12,7 +13,8 @@ export {
12
13
  useLoad,
13
14
  REDO_REQUIRED_HOSTNAMES,
14
15
  RedoErrorType,
15
- RedoInfoCard
16
+ RedoInfoCard,
17
+ useDisablePurpleDotPreorder
16
18
  };
17
19
 
18
20
  export type {
@@ -0,0 +1,92 @@
1
+ const DISABLED_ATTR = "data-redo-preorder-disabled";
2
+ const ORIGINAL_DISABLED_ATTR = "data-redo-original-disabled";
3
+
4
+ /**
5
+ * Finds add-to-cart buttons on the page
6
+ */
7
+ function findAddToCartButtons(): HTMLButtonElement[] {
8
+ const buttons = document.querySelectorAll<HTMLButtonElement>(
9
+ 'button[name="add"], button[type="submit"], .product-form__submit'
10
+ );
11
+
12
+ return Array.from(buttons).filter((button) => {
13
+ const text = button.textContent?.toLowerCase().trim() ?? "";
14
+ return text.includes("add to cart") || text.includes("add to bag");
15
+ });
16
+ }
17
+
18
+ /**
19
+ * Checks for Purple Dot preorder element and updates button states accordingly.
20
+ * Disables add-to-cart buttons when purple-dot-learn-more element is present.
21
+ * Re-enables them when the element is removed.
22
+ */
23
+ export function updatePurpleDotButtons(): void {
24
+ const hasPurpleDot = document.querySelector("purple-dot-learn-more") !== null;
25
+ const addToCartButtons = findAddToCartButtons();
26
+
27
+ for (const button of addToCartButtons) {
28
+ if (hasPurpleDot) {
29
+ // Disable the button
30
+ if (!button.hasAttribute(DISABLED_ATTR)) {
31
+ // Preserve original disabled state
32
+ if (!button.hasAttribute(ORIGINAL_DISABLED_ATTR)) {
33
+ button.setAttribute(ORIGINAL_DISABLED_ATTR, String(button.disabled));
34
+ }
35
+
36
+ button.setAttribute(DISABLED_ATTR, "true");
37
+ button.disabled = true;
38
+ button.style.opacity = "0.5";
39
+ button.style.cursor = "not-allowed";
40
+ button.style.pointerEvents = "none";
41
+
42
+ // Add message if not already present
43
+ if (!button.parentElement?.querySelector(".redo-preorder-msg")) {
44
+ const msg = document.createElement("div");
45
+ msg.className = "redo-preorder-msg";
46
+ msg.textContent = "Preorder items cannot be added during exchanges";
47
+ msg.style.cssText =
48
+ "color: #d63031; font-size: 12px; margin-top: 8px; font-weight: 500;";
49
+ button.parentElement?.insertBefore(msg, button.nextSibling);
50
+ }
51
+ }
52
+ } else {
53
+ // Re-enable the button if we disabled it
54
+ if (button.hasAttribute(DISABLED_ATTR)) {
55
+ const wasDisabled =
56
+ button.getAttribute(ORIGINAL_DISABLED_ATTR) === "true";
57
+ button.removeAttribute(DISABLED_ATTR);
58
+ button.removeAttribute(ORIGINAL_DISABLED_ATTR);
59
+ button.disabled = wasDisabled;
60
+ button.style.opacity = "";
61
+ button.style.cursor = "";
62
+ button.style.pointerEvents = "";
63
+ button.parentElement?.querySelector(".redo-preorder-msg")?.remove();
64
+ }
65
+ }
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Cleans up all disabled buttons (used on unmount).
71
+ * Restores original disabled state.
72
+ */
73
+ export function cleanupPurpleDotButtons(): void {
74
+ const disabledButtons = Array.from(
75
+ document.querySelectorAll<HTMLButtonElement>(`button[${DISABLED_ATTR}]`)
76
+ );
77
+
78
+ for (const button of disabledButtons) {
79
+ const wasDisabled = button.getAttribute(ORIGINAL_DISABLED_ATTR) === "true";
80
+ button.removeAttribute(DISABLED_ATTR);
81
+ button.removeAttribute(ORIGINAL_DISABLED_ATTR);
82
+ button.disabled = wasDisabled;
83
+ button.style.opacity = "";
84
+ button.style.cursor = "";
85
+ button.style.pointerEvents = "";
86
+ }
87
+
88
+ // Remove all messages
89
+ document
90
+ .querySelectorAll(".redo-preorder-msg")
91
+ .forEach((msg) => msg.remove());
92
+ }