@tiledev/sdk-apptile-live-selling 0.13.0 → 0.15.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.
Files changed (131) hide show
  1. package/README.md +116 -12
  2. package/dist/clipsPage.d.ts +29 -0
  3. package/dist/clipsPage.d.ts.map +1 -0
  4. package/dist/clipsPage.js +49 -0
  5. package/dist/clipsPage.js.map +1 -0
  6. package/dist/giveawayPrizeLines.d.ts +10 -0
  7. package/dist/giveawayPrizeLines.d.ts.map +1 -1
  8. package/dist/giveawayPrizeLines.js +11 -1
  9. package/dist/giveawayPrizeLines.js.map +1 -1
  10. package/dist/hiddenShows.d.ts +10 -0
  11. package/dist/hiddenShows.d.ts.map +1 -1
  12. package/dist/hiddenShows.js +11 -0
  13. package/dist/hiddenShows.js.map +1 -1
  14. package/dist/index.d.ts +10 -3
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +53 -2
  17. package/dist/index.js.map +1 -1
  18. package/dist/linkLots.d.ts +64 -0
  19. package/dist/linkLots.d.ts.map +1 -0
  20. package/dist/linkLots.js +84 -0
  21. package/dist/linkLots.js.map +1 -0
  22. package/dist/livePages.d.ts +166 -0
  23. package/dist/livePages.d.ts.map +1 -0
  24. package/dist/livePages.js +187 -0
  25. package/dist/livePages.js.map +1 -0
  26. package/dist/liveRoom.d.ts +21 -0
  27. package/dist/liveRoom.d.ts.map +1 -0
  28. package/dist/liveRoom.js +28 -0
  29. package/dist/liveRoom.js.map +1 -0
  30. package/dist/pageOptions.d.ts +118 -0
  31. package/dist/pageOptions.d.ts.map +1 -0
  32. package/dist/pageOptions.js +99 -0
  33. package/dist/pageOptions.js.map +1 -0
  34. package/dist/pageTypes.d.ts +185 -0
  35. package/dist/pageTypes.d.ts.map +1 -0
  36. package/dist/pageTypes.js +3 -0
  37. package/dist/pageTypes.js.map +1 -0
  38. package/dist/react/LiveSellingProvider.d.ts +31 -1
  39. package/dist/react/LiveSellingProvider.d.ts.map +1 -1
  40. package/dist/react/LiveSellingProvider.js +44 -2
  41. package/dist/react/LiveSellingProvider.js.map +1 -1
  42. package/dist/react/index.d.ts +12 -0
  43. package/dist/react/index.d.ts.map +1 -1
  44. package/dist/react/index.js +34 -1
  45. package/dist/react/index.js.map +1 -1
  46. package/dist/react/index.web.d.ts +13 -32
  47. package/dist/react/index.web.d.ts.map +1 -1
  48. package/dist/react/index.web.js +52 -139
  49. package/dist/react/index.web.js.map +1 -1
  50. package/dist/react/navigation.d.ts +13 -0
  51. package/dist/react/navigation.d.ts.map +1 -0
  52. package/dist/react/navigation.js +7 -0
  53. package/dist/react/navigation.js.map +1 -0
  54. package/dist/react/platformSession.d.ts +16 -0
  55. package/dist/react/platformSession.d.ts.map +1 -0
  56. package/dist/react/platformSession.js +28 -0
  57. package/dist/react/platformSession.js.map +1 -0
  58. package/dist/react/platformSession.web.d.ts +35 -0
  59. package/dist/react/platformSession.web.d.ts.map +1 -0
  60. package/dist/react/platformSession.web.js +148 -0
  61. package/dist/react/platformSession.web.js.map +1 -0
  62. package/dist/react/replayPlayer.d.ts +74 -0
  63. package/dist/react/replayPlayer.d.ts.map +1 -0
  64. package/dist/react/replayPlayer.js +279 -0
  65. package/dist/react/replayPlayer.js.map +1 -0
  66. package/dist/react/shopifyProviders.d.ts +69 -0
  67. package/dist/react/shopifyProviders.d.ts.map +1 -0
  68. package/dist/react/shopifyProviders.js +100 -0
  69. package/dist/react/shopifyProviders.js.map +1 -0
  70. package/dist/react/useAccountName.d.ts +8 -0
  71. package/dist/react/useAccountName.d.ts.map +1 -0
  72. package/dist/react/useAccountName.js +49 -0
  73. package/dist/react/useAccountName.js.map +1 -0
  74. package/dist/react/useClipsPage.d.ts +47 -0
  75. package/dist/react/useClipsPage.d.ts.map +1 -0
  76. package/dist/react/useClipsPage.js +130 -0
  77. package/dist/react/useClipsPage.js.map +1 -0
  78. package/dist/react/useKeepScreenAwake.d.ts +2 -0
  79. package/dist/react/useKeepScreenAwake.d.ts.map +1 -0
  80. package/dist/react/useKeepScreenAwake.js +34 -0
  81. package/dist/react/useKeepScreenAwake.js.map +1 -0
  82. package/dist/react/useLiveAuction.d.ts +106 -0
  83. package/dist/react/useLiveAuction.d.ts.map +1 -0
  84. package/dist/react/useLiveAuction.js +249 -0
  85. package/dist/react/useLiveAuction.js.map +1 -0
  86. package/dist/react/useLiveChat.d.ts +110 -0
  87. package/dist/react/useLiveChat.d.ts.map +1 -0
  88. package/dist/react/useLiveChat.js +209 -0
  89. package/dist/react/useLiveChat.js.map +1 -0
  90. package/dist/react/useLiveGiveawaysAndPolls.d.ts +95 -0
  91. package/dist/react/useLiveGiveawaysAndPolls.d.ts.map +1 -0
  92. package/dist/react/useLiveGiveawaysAndPolls.js +225 -0
  93. package/dist/react/useLiveGiveawaysAndPolls.js.map +1 -0
  94. package/dist/react/useLivePage.d.ts +134 -0
  95. package/dist/react/useLivePage.d.ts.map +1 -0
  96. package/dist/react/useLivePage.js +304 -0
  97. package/dist/react/useLivePage.js.map +1 -0
  98. package/dist/react/useLiveShop.d.ts +103 -0
  99. package/dist/react/useLiveShop.d.ts.map +1 -0
  100. package/dist/react/useLiveShop.js +211 -0
  101. package/dist/react/useLiveShop.js.map +1 -0
  102. package/dist/react/useReplayPage.d.ts +133 -0
  103. package/dist/react/useReplayPage.d.ts.map +1 -0
  104. package/dist/react/useReplayPage.js +565 -0
  105. package/dist/react/useReplayPage.js.map +1 -0
  106. package/dist/showCredit.d.ts +87 -0
  107. package/dist/showCredit.d.ts.map +1 -0
  108. package/dist/showCredit.js +120 -0
  109. package/dist/showCredit.js.map +1 -0
  110. package/dist/showNames.d.ts +11 -0
  111. package/dist/showNames.d.ts.map +1 -1
  112. package/dist/showNames.js +23 -1
  113. package/dist/showNames.js.map +1 -1
  114. package/dist/ui/BubbleFrame.d.ts +38 -0
  115. package/dist/ui/BubbleFrame.d.ts.map +1 -0
  116. package/dist/ui/BubbleFrame.js +181 -0
  117. package/dist/ui/BubbleFrame.js.map +1 -0
  118. package/dist/ui/LiveBubble.d.ts +37 -0
  119. package/dist/ui/LiveBubble.d.ts.map +1 -0
  120. package/dist/ui/LiveBubble.js +101 -0
  121. package/dist/ui/LiveBubble.js.map +1 -0
  122. package/dist/ui/ReplayBubble.d.ts +23 -0
  123. package/dist/ui/ReplayBubble.d.ts.map +1 -0
  124. package/dist/ui/ReplayBubble.js +65 -0
  125. package/dist/ui/ReplayBubble.js.map +1 -0
  126. package/dist/ui.d.ts +27 -0
  127. package/dist/ui.d.ts.map +1 -0
  128. package/dist/ui.js +34 -0
  129. package/dist/ui.js.map +1 -0
  130. package/package.json +36 -5
  131. package/ui/package.json +6 -0
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ShopifyLiveSellingProvider = ShopifyLiveSellingProvider;
7
+ exports.ShopifyLiveSessionProvider = ShopifyLiveSessionProvider;
8
+ /**
9
+ * The live-selling providers for an app on `@tiledev/sdk-shopify` (0.14.0, moved from amore-v2's
10
+ * `AppLiveSellingProvider` and `AppLiveSessionProvider`, `src/core/providers/liveSelling.tsx` and
11
+ * `liveSession.tsx`): `LiveSellingProvider` and `LiveSessionProvider` filled in from the app's own
12
+ * sdk-shopify client (`shopify`) and customer (`useCustomer`), so the app passes only its config.
13
+ *
14
+ * `createElement` rather than JSX, like the rest of the package, so this stays a plain `.ts`.
15
+ */
16
+ const async_storage_1 = __importDefault(require("@react-native-async-storage/async-storage"));
17
+ const sdk_shopify_1 = require("@tiledev/sdk-shopify");
18
+ const react_1 = require("react");
19
+ const shopifyCommerce_1 = require("../shopifyCommerce");
20
+ const shopifyIdentity_1 = require("../shopifyIdentity");
21
+ const showNames_1 = require("../showNames");
22
+ const LiveSellingProvider_1 = require("./LiveSellingProvider");
23
+ const platformSession_1 = require("./platformSession");
24
+ /**
25
+ * `LiveSellingProvider` on the app's sdk-shopify client and customer (the README's §4 "On Shopify"):
26
+ * products from Shopify at the card photo size; the wins checkout, a cart of its own (a won lot stamped
27
+ * `_winningBid`, a prize `prizeWriteKey`) with `source_name`, `source_type: "auction"` and `auction_id`
28
+ * for the order webhook; and the bidder, the customer's numeric id, only for a Shopify sign-in (the
29
+ * winner's record is on the Customer Account API). The phone's storage keeps the poll votes, a
30
+ * signed-out shopper's name and the accepted terms across relaunches. Hidden shows (`hiddenShows`) are
31
+ * hidden from every shopper whose email isn't the team's: the signed-in customer's email is the
32
+ * provider's `viewerEmail`, so a sign-in reaches every screen at once.
33
+ *
34
+ * Mount it inside sdk-shopify's `ShopifyProvider`, above the navigator. `routes`, `track`, `onWarning`
35
+ * and `shopName` pass through to `LiveSellingProvider`.
36
+ */
37
+ function ShopifyLiveSellingProvider({ children, config, cartSourceName, prizeWriteKey, imageTransform = sdk_shopify_1.CARD_IMAGE, ...pageProps }) {
38
+ var _a, _b;
39
+ const customer = (0, sdk_shopify_1.useCustomer)();
40
+ const latestCustomer = (0, react_1.useRef)(customer);
41
+ latestCustomer.current = customer;
42
+ const liveConfig = (0, react_1.useMemo)(() => {
43
+ var _a;
44
+ const signedIn = (0, shopifyIdentity_1.createShopifyLiveIdentity)(() => latestCustomer.current);
45
+ return {
46
+ ...config,
47
+ storage: (_a = config.storage) !== null && _a !== void 0 ? _a : async_storage_1.default,
48
+ identity: signedIn.identity,
49
+ customerAccountRequest: signedIn.customerAccountRequest,
50
+ commerce: (0, shopifyCommerce_1.createShopifyLiveCommerce)({
51
+ shopify: sdk_shopify_1.shopify,
52
+ cartSourceName,
53
+ prizeWriteKey,
54
+ buyer: signedIn.buyer,
55
+ imageTransform,
56
+ }),
57
+ };
58
+ }, [config, cartSourceName, prizeWriteKey, imageTransform]);
59
+ return (0, react_1.createElement)(LiveSellingProvider_1.LiveSellingProvider, {
60
+ ...pageProps,
61
+ config: liveConfig,
62
+ viewerEmail: (_b = (_a = customer.customer) === null || _a === void 0 ? void 0 : _a.email) !== null && _b !== void 0 ? _b : null,
63
+ children,
64
+ });
65
+ }
66
+ /**
67
+ * The app's one live session (`LiveSessionProvider`; decided 2026-10-05 by amore-v2's Head of
68
+ * Engineering: joined app-wide, as Freckled Poppy). Mount it above the navigator, inside
69
+ * `ShopifyLiveSellingProvider`, because Zego's engine holds exactly one room and several places show
70
+ * the same show: the Live tab's card, the Live screen and the bubble. Each binds to the picture with
71
+ * `LiveVideoTarget`; none owns the room.
72
+ *
73
+ * - **`viewerName`** is the signed-in shopper's (`viewerNameFor`: first and last name, else whichever
74
+ * the account has; never an email nor its part before the @), so a name edited on Account reaches the
75
+ * room without a restart. Null with no name on the account, or signed out, so a name the shopper typed
76
+ * on this phone stays in charge (the comment box asks for one: `useLivePage`'s chat).
77
+ * - **`blockedNames`**: the names nobody watching may go by. `LiveSellingProvider`'s (0.15.0: the list
78
+ * the name asks check too, so the session and the sheets agree), unless one is passed here; Host and
79
+ * Moderator unless the app says otherwise.
80
+ * - **`onPipRestore`**: the phone's picture-in-picture window, opened from the Live screen and then
81
+ * expanded (or, on iOS, left up when the shopper came back by the app's icon), comes back to the Live
82
+ * screen (`routes.openLive`). A window opened from the bubble goes back to the bubble instead, which
83
+ * the session does itself without calling this. An `onPipRestore` of the app's own replaces it.
84
+ */
85
+ function ShopifyLiveSessionProvider({ children, onPipRestore, blockedNames, ...props }) {
86
+ const { customer } = (0, sdk_shopify_1.useCustomer)();
87
+ const { routes, blockedNames: providerBlockedNames } = (0, LiveSellingProvider_1.useLivePageOptions)();
88
+ const backToTheLiveShow = (0, react_1.useMemo)(() => onPipRestore !== null && onPipRestore !== void 0 ? onPipRestore : ((streamId) => {
89
+ if (streamId)
90
+ routes.openLive(streamId);
91
+ }), [onPipRestore, routes]);
92
+ return (0, react_1.createElement)(platformSession_1.LiveSessionProvider, {
93
+ ...props,
94
+ viewerName: (0, showNames_1.viewerNameFor)(customer),
95
+ blockedNames: blockedNames !== null && blockedNames !== void 0 ? blockedNames : providerBlockedNames,
96
+ onPipRestore: backToTheLiveShow,
97
+ children,
98
+ });
99
+ }
100
+ //# sourceMappingURL=shopifyProviders.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shopifyProviders.js","sourceRoot":"","sources":["../../src/react/shopifyProviders.ts"],"names":[],"mappings":";;;;;AA8DA,gEAmCC;AAyBD,gEAkBC;AA5ID;;;;;;;GAOG;AACH,8FAAqE;AACrE,sDAAwE;AACxE,iCAAuD;AAGvD,wDAA2F;AAC3F,wDAA+D;AAC/D,4CAA6C;AAE7C,+DAA+G;AAC/G,uDAAwD;AA+BxD;;;;;;;;;;;;GAYG;AACH,SAAgB,0BAA0B,CAAC,EACzC,QAAQ,EACR,MAAM,EACN,cAAc,EACd,aAAa,EACb,cAAc,GAAG,wBAAU,EAC3B,GAAG,SAAS,EACoB;;IAChC,MAAM,QAAQ,GAAG,IAAA,yBAAW,GAAE,CAAC;IAC/B,MAAM,cAAc,GAAG,IAAA,cAAM,EAAC,QAAQ,CAAC,CAAC;IACxC,cAAc,CAAC,OAAO,GAAG,QAAQ,CAAC;IAElC,MAAM,UAAU,GAAG,IAAA,eAAO,EAAoB,GAAG,EAAE;;QACjD,MAAM,QAAQ,GAAG,IAAA,2CAAyB,EAAC,GAAG,EAAE,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QACzE,OAAO;YACL,GAAG,MAAM;YACT,OAAO,EAAE,MAAA,MAAM,CAAC,OAAO,mCAAI,uBAAY;YACvC,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,sBAAsB,EAAE,QAAQ,CAAC,sBAAsB;YACvD,QAAQ,EAAE,IAAA,2CAAyB,EAAC;gBAClC,OAAO,EAAP,qBAAO;gBACP,cAAc;gBACd,aAAa;gBACb,KAAK,EAAE,QAAQ,CAAC,KAAK;gBACrB,cAAc;aACf,CAAC;SACH,CAAC;IACJ,CAAC,EAAE,CAAC,MAAM,EAAE,cAAc,EAAE,aAAa,EAAE,cAAc,CAAC,CAAC,CAAC;IAE5D,OAAO,IAAA,qBAAa,EAAC,yCAAmB,EAAE;QACxC,GAAG,SAAS;QACZ,MAAM,EAAE,UAAU;QAClB,WAAW,EAAE,MAAA,MAAA,QAAQ,CAAC,QAAQ,0CAAE,KAAK,mCAAI,IAAI;QAC7C,QAAQ;KACT,CAAC,CAAC;AACL,CAAC;AAMD;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAgB,0BAA0B,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,GAAG,KAAK,EAAmC;IAC5H,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAA,yBAAW,GAAE,CAAC;IACnC,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,oBAAoB,EAAE,GAAG,IAAA,wCAAkB,GAAE,CAAC;IAC5E,MAAM,iBAAiB,GAAG,IAAA,eAAO,EAC/B,GAAG,EAAE,CACH,YAAY,aAAZ,YAAY,cAAZ,YAAY,GACZ,CAAC,CAAC,QAA4B,EAAE,EAAE;QAChC,IAAI,QAAQ;YAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC1C,CAAC,CAAC,EACJ,CAAC,YAAY,EAAE,MAAM,CAAC,CACvB,CAAC;IACF,OAAO,IAAA,qBAAa,EAAC,qCAAmB,EAAE;QACxC,GAAG,KAAK;QACR,UAAU,EAAE,IAAA,yBAAa,EAAC,QAAQ,CAAC;QACnC,YAAY,EAAE,YAAY,aAAZ,YAAY,cAAZ,YAAY,GAAI,oBAAoB;QAClD,YAAY,EAAE,iBAAiB;QAC/B,QAAQ;KACT,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { NameOnAccount } from '../pageTypes';
2
+ export interface AccountName {
3
+ accountLoading: boolean;
4
+ nameToComplete: NameOnAccount | null;
5
+ saveNameToAccount: (firstName: string, lastName: string) => Promise<string | null>;
6
+ }
7
+ export declare function useAccountName(): AccountName;
8
+ //# sourceMappingURL=useAccountName.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAccountName.d.ts","sourceRoot":"","sources":["../../src/react/useAccountName.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAGlD,MAAM,WAAW,WAAW;IAC1B,cAAc,EAAE,OAAO,CAAC;IACxB,cAAc,EAAE,aAAa,GAAG,IAAI,CAAC;IACrC,iBAAiB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACpF;AAED,wBAAgB,cAAc,IAAI,WAAW,CAyB5C"}
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useAccountName = useAccountName;
4
+ /**
5
+ * `useAccountName()` — the signed-in shopper's name on their Shopify account, for the Live screen's name
6
+ * asks (0.15.0, moved from amore-v2's `src/core/hooks/useAccountName.ts`): the comment box's "Commenting
7
+ * As:" (`useLiveChat`) and the giveaway's "Entering As:" (`useLiveGiveawaysAndPolls`).
8
+ *
9
+ * amore-v2's ENG-686, decided 2026-10-19 by its Head of Engineering (old Amore's and old K-Marie's way,
10
+ * for giveaways too the same day): a Shopify sign-in by emailed code leaves the account's name blank, and
11
+ * since 0.13.0 the room names nobody by their email. Such a shopper is asked once, by whichever comes
12
+ * first, a comment or a giveaway entry, for a first and a last name (the last optional), which go on the
13
+ * account (sdk-shopify's `updateProfile`, which says "Profile updated" as Edit Profile does). The account
14
+ * then names them in the room, on Account and on their orders, and neither ask comes again.
15
+ *
16
+ * - **`accountLoading`:** signed in, the account not read yet (`accountLoadingOf`). Send and Enter wait.
17
+ * - **`nameToComplete`:** the account has been read and has no first name, or a name the show's team
18
+ * goes by (`LiveSellingProvider`'s `blockedNames`): what it has, for the ask to start from
19
+ * (`accountNameToComplete`). Null when it has a first name, while it loads, and when signed out.
20
+ * - **`saveNameToAccount(firstName, lastName)`:** the name as it went on the account ("Jane Doe", or
21
+ * "Jane"), or null when it didn't: no first name, a team name (`tidyAccountName`), or Shopify refused
22
+ * it or couldn't be reached.
23
+ */
24
+ const sdk_shopify_1 = require("@tiledev/sdk-shopify");
25
+ const react_1 = require("react");
26
+ const livePages_1 = require("../livePages");
27
+ const LiveSellingProvider_1 = require("./LiveSellingProvider");
28
+ function useAccountName() {
29
+ var _a, _b;
30
+ const { loggedIn, restoring, customer, updateProfile } = (0, sdk_shopify_1.useCustomer)();
31
+ const { blockedNames } = (0, LiveSellingProvider_1.useLivePageOptions)();
32
+ const account = { loggedIn: !!loggedIn, restoring: !!restoring, customer };
33
+ const accountLoading = (0, livePages_1.accountLoadingOf)(account);
34
+ const needed = (0, livePages_1.accountNameToComplete)(account, blockedNames);
35
+ const firstName = (_a = needed === null || needed === void 0 ? void 0 : needed.firstName) !== null && _a !== void 0 ? _a : null;
36
+ const lastName = (_b = needed === null || needed === void 0 ? void 0 : needed.lastName) !== null && _b !== void 0 ? _b : null;
37
+ // One object while the name it needs stays the same, so a tile's sheet doesn't start over each draw.
38
+ const nameToComplete = (0, react_1.useMemo)(() => (firstName !== null ? { firstName, lastName } : null), [firstName, lastName]);
39
+ const saveNameToAccount = (0, react_1.useCallback)(async (typedFirstName, typedLastName) => {
40
+ const name = (0, livePages_1.tidyAccountName)(typedFirstName, typedLastName, blockedNames);
41
+ if (!name)
42
+ return null;
43
+ if (!(await updateProfile({ firstName: name.firstName, lastName: name.lastName })))
44
+ return null;
45
+ return name.fullName;
46
+ }, [blockedNames, updateProfile]);
47
+ return { accountLoading, nameToComplete, saveNameToAccount };
48
+ }
49
+ //# sourceMappingURL=useAccountName.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAccountName.js","sourceRoot":"","sources":["../../src/react/useAccountName.ts"],"names":[],"mappings":";;AAiCA,wCAyBC;AA1DD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,sDAAmD;AACnD,iCAA6C;AAE7C,4CAAwF;AAExF,+DAA2D;AAQ3D,SAAgB,cAAc;;IAC5B,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,GAAG,IAAA,yBAAW,GAAE,CAAC;IACvE,MAAM,EAAE,YAAY,EAAE,GAAG,IAAA,wCAAkB,GAAE,CAAC;IAC9C,MAAM,OAAO,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,QAAQ,EAAE,CAAC;IAC3E,MAAM,cAAc,GAAG,IAAA,4BAAgB,EAAC,OAAO,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,IAAA,iCAAqB,EAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IAC5D,MAAM,SAAS,GAAG,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,SAAS,mCAAI,IAAI,CAAC;IAC5C,MAAM,QAAQ,GAAG,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,QAAQ,mCAAI,IAAI,CAAC;IAC1C,qGAAqG;IACrG,MAAM,cAAc,GAAG,IAAA,eAAO,EAC5B,GAAG,EAAE,CAAC,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAC3D,CAAC,SAAS,EAAE,QAAQ,CAAC,CACtB,CAAC;IAEF,MAAM,iBAAiB,GAAG,IAAA,mBAAW,EACnC,KAAK,EAAE,cAAsB,EAAE,aAAqB,EAA0B,EAAE;QAC9E,MAAM,IAAI,GAAG,IAAA,2BAAe,EAAC,cAAc,EAAE,aAAa,EAAE,YAAY,CAAC,CAAC;QAC1E,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QACvB,IAAI,CAAC,CAAC,MAAM,aAAa,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QAChG,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC,EACD,CAAC,YAAY,EAAE,aAAa,CAAC,CAC9B,CAAC;IAEF,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,iBAAiB,EAAE,CAAC;AAC/D,CAAC"}
@@ -0,0 +1,47 @@
1
+ import type { ClipReelItem } from '../pageTypes';
2
+ /**
3
+ * Everything the Clips page wires, so the screen stays plain tiles: the reel (`reel`, the reel tile's
4
+ * props) and the bar over it (`header`). Call it from the screen and from each of its tiles' wiring.
5
+ *
6
+ * - **The reel** is the live-selling gateway's video collection (`useClips`): which clips, in what
7
+ * order, the video each plays and its poster. The merchant curates it in the dashboard.
8
+ * - **Each clip's product** comes from Shopify, in one read for the whole reel (`shopify.products.byIds`,
9
+ * at sdk-shopify's `CARD_IMAGE`, the grids' card size, which the product store keeps as the product's
10
+ * card image). A clip whose product the store no longer has is left out (`clipReelItems`): there is
11
+ * nothing to buy from it. Products are kept across reads, so a refreshed reel only waits for products
12
+ * it hasn't seen.
13
+ * - **Loading** until the clips' first read has started (`useClips` reads only once the SDK is ready,
14
+ * and says `loading` only from then: until it has read once, an empty reel is still loading, not "No
15
+ * clips yet.") and while products it shows are on their way. A failed read of either is `error`;
16
+ * Retry reads both again.
17
+ * - **Playback:** only while the page is on screen (`paused` otherwise); one mute setting for the reel,
18
+ * starting muted.
19
+ * - **Buy** opens the variant page (`routes.openVariantPage`): the product page's tiles in a sheet over
20
+ * the reel. **Share** sends the product's link (`productShareUrl`). **Close** goes back to where the
21
+ * shopper came from; the bar's cart opens the Cart (`routes.openCart`).
22
+ */
23
+ export declare function useClipsPage(): {
24
+ /** The reel has a clip to show. */
25
+ hasReel: boolean;
26
+ /** The page is on show: light status bar glyphs over the video. */
27
+ isFocused: boolean;
28
+ reel: {
29
+ clips: ClipReelItem[];
30
+ loading: boolean;
31
+ error: boolean;
32
+ paused: boolean;
33
+ muted: boolean;
34
+ onToggleMute: () => void;
35
+ onShare: (clip: ClipReelItem) => void;
36
+ onBuy: (clip: ClipReelItem) => void;
37
+ onRetry: () => void;
38
+ };
39
+ header: {
40
+ cartCount: number;
41
+ onClose: () => void;
42
+ onCart: () => void;
43
+ };
44
+ };
45
+ /** What `useClipsPage` hands the Clips page and its tiles. */
46
+ export type ClipsPage = ReturnType<typeof useClipsPage>;
47
+ //# sourceMappingURL=useClipsPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useClipsPage.d.ts","sourceRoot":"","sources":["../../src/react/useClipsPage.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAMjD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,YAAY;IA+DxB,mCAAmC;;IAEnC,mEAAmE;;;;;;;;;wBASjD,YAAY;sBAId,YAAY;;;;;;;;EAe/B;AAED,8DAA8D;AAC9D,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC"}
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useClipsPage = useClipsPage;
4
+ /**
5
+ * The Clips page's page model (0.15.0, moved from amore-v2's `src/core/hooks/useClipsPage.ts`, ported
6
+ * there from the earlier app's Clips tab, 2026-10-18): the reel a rail of clips opens, on the clip tapped.
7
+ * The routes are the app's (`LiveSellingProvider`'s `routes`); the clip to open on is the app's route
8
+ * param, which its screen hands the reel tile (amore-v2: `clipId`, as `firstClipId`).
9
+ */
10
+ const sdk_shopify_1 = require("@tiledev/sdk-shopify");
11
+ const react_1 = require("react");
12
+ const clipsPage_1 = require("../clipsPage");
13
+ const LiveSellingProvider_1 = require("./LiveSellingProvider");
14
+ const useClips_1 = require("./useClips");
15
+ const useLiveShop_1 = require("./useLiveShop");
16
+ const navigation_1 = require("./navigation");
17
+ /**
18
+ * Everything the Clips page wires, so the screen stays plain tiles: the reel (`reel`, the reel tile's
19
+ * props) and the bar over it (`header`). Call it from the screen and from each of its tiles' wiring.
20
+ *
21
+ * - **The reel** is the live-selling gateway's video collection (`useClips`): which clips, in what
22
+ * order, the video each plays and its poster. The merchant curates it in the dashboard.
23
+ * - **Each clip's product** comes from Shopify, in one read for the whole reel (`shopify.products.byIds`,
24
+ * at sdk-shopify's `CARD_IMAGE`, the grids' card size, which the product store keeps as the product's
25
+ * card image). A clip whose product the store no longer has is left out (`clipReelItems`): there is
26
+ * nothing to buy from it. Products are kept across reads, so a refreshed reel only waits for products
27
+ * it hasn't seen.
28
+ * - **Loading** until the clips' first read has started (`useClips` reads only once the SDK is ready,
29
+ * and says `loading` only from then: until it has read once, an empty reel is still loading, not "No
30
+ * clips yet.") and while products it shows are on their way. A failed read of either is `error`;
31
+ * Retry reads both again.
32
+ * - **Playback:** only while the page is on screen (`paused` otherwise); one mute setting for the reel,
33
+ * starting muted.
34
+ * - **Buy** opens the variant page (`routes.openVariantPage`): the product page's tiles in a sheet over
35
+ * the reel. **Share** sends the product's link (`productShareUrl`). **Close** goes back to where the
36
+ * shopper came from; the bar's cart opens the Cart (`routes.openCart`).
37
+ */
38
+ function useClipsPage() {
39
+ const nav = (0, navigation_1.useNavigation)();
40
+ const isFocused = (0, navigation_1.useIsFocused)();
41
+ const { ready: liveSellingReady } = (0, LiveSellingProvider_1.useLiveSelling)();
42
+ const { routes } = (0, LiveSellingProvider_1.useLivePageOptions)();
43
+ const { ready: shopifyReady } = (0, sdk_shopify_1.useShopify)();
44
+ const { clips, loading: loadingClips, error: clipsError, refresh: refreshClips } = (0, useClips_1.useClips)();
45
+ const { itemCount } = (0, sdk_shopify_1.useCart)();
46
+ // `useClips` starts reading only once the live-selling SDK is ready, and says `loading` only from
47
+ // then: until it has read once, an empty reel is still loading, not "No clips yet.".
48
+ const [clipsReadStarted, setClipsReadStarted] = (0, react_1.useState)(false);
49
+ (0, react_1.useEffect)(() => {
50
+ if (loadingClips)
51
+ setClipsReadStarted(true);
52
+ }, [loadingClips]);
53
+ // The clips' products by id: `null` for one the store no longer has. Kept across reads.
54
+ const [productsById, setProductsById] = (0, react_1.useState)(new Map());
55
+ const [productsFailed, setProductsFailed] = (0, react_1.useState)(false);
56
+ const [productReadCount, setProductReadCount] = (0, react_1.useState)(0);
57
+ const productIds = (0, react_1.useMemo)(() => [...new Set(clips.map(clipsPage_1.clipProductId).filter((id) => !!id))], [clips]);
58
+ const missingIds = productIds.filter((id) => !productsById.has(id));
59
+ const missingKey = missingIds.join(',');
60
+ (0, react_1.useEffect)(() => {
61
+ if (!shopifyReady || !missingKey)
62
+ return;
63
+ const ids = missingKey.split(',');
64
+ let stillMounted = true;
65
+ setProductsFailed(false);
66
+ sdk_shopify_1.shopify.products
67
+ .byIds(ids, { imageTransform: sdk_shopify_1.CARD_IMAGE, keepMissing: true })
68
+ .then((found) => {
69
+ if (!stillMounted)
70
+ return;
71
+ setProductsById((known) => {
72
+ const next = new Map(known);
73
+ ids.forEach((id, index) => { var _a; return next.set(id, (_a = found[index]) !== null && _a !== void 0 ? _a : null); });
74
+ return next;
75
+ });
76
+ })
77
+ .catch(() => {
78
+ if (stillMounted)
79
+ setProductsFailed(true);
80
+ });
81
+ return () => {
82
+ stillMounted = false;
83
+ };
84
+ }, [shopifyReady, missingKey, productReadCount]);
85
+ const reel = (0, react_1.useMemo)(() => (0, clipsPage_1.clipReelItems)(clips, productsById), [clips, productsById]);
86
+ const productOfClip = (0, react_1.useCallback)((clipId) => {
87
+ var _a;
88
+ const clip = clips.find((candidate) => candidate.id === clipId);
89
+ const productId = clip ? (0, clipsPage_1.clipProductId)(clip) : null;
90
+ return productId ? ((_a = productsById.get(productId)) !== null && _a !== void 0 ? _a : null) : null;
91
+ }, [clips, productsById]);
92
+ const [muted, setMuted] = (0, react_1.useState)(true);
93
+ const waitingForProducts = missingIds.length > 0 && !productsFailed;
94
+ const hasReel = reel.length > 0;
95
+ return {
96
+ /** The reel has a clip to show. */
97
+ hasReel,
98
+ /** The page is on show: light status bar glyphs over the video. */
99
+ isFocused,
100
+ reel: {
101
+ clips: reel,
102
+ loading: !liveSellingReady || !clipsReadStarted || loadingClips || waitingForProducts,
103
+ error: !!clipsError || productsFailed,
104
+ paused: !isFocused,
105
+ muted,
106
+ onToggleMute: () => setMuted((wasMuted) => !wasMuted),
107
+ onShare: (clip) => {
108
+ const product = productOfClip(clip.id);
109
+ if (product)
110
+ void (0, useLiveShop_1.shareAddress)((0, sdk_shopify_1.productShareUrl)(product));
111
+ },
112
+ onBuy: (clip) => {
113
+ const product = productOfClip(clip.id);
114
+ if (product)
115
+ routes.openVariantPage({ handle: product.handle }, nav);
116
+ },
117
+ onRetry: () => {
118
+ if (productsFailed)
119
+ setProductReadCount((count) => count + 1);
120
+ void refreshClips();
121
+ },
122
+ },
123
+ header: {
124
+ cartCount: itemCount,
125
+ onClose: () => nav.goBack(),
126
+ onCart: () => routes.openCart({ itemsYouWon: false }, nav),
127
+ },
128
+ };
129
+ }
130
+ //# sourceMappingURL=useClipsPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useClipsPage.js","sourceRoot":"","sources":["../../src/react/useClipsPage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function useKeepScreenAwake(active: boolean, tag: string): void;
2
+ //# sourceMappingURL=useKeepScreenAwake.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useKeepScreenAwake.d.ts","sourceRoot":"","sources":["../../src/react/useKeepScreenAwake.ts"],"names":[],"mappings":"AAmBA,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAWrE"}
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useKeepScreenAwake = useKeepScreenAwake;
4
+ /**
5
+ * `useKeepScreenAwake(active, tag)` (0.14.0, moved from amore-v2's `src/core/hooks/useKeepScreenAwake.ts`,
6
+ * Freckled Poppy's before it): keeps the phone's screen on while `active` is true. A live show runs for
7
+ * an hour and is watched without a touch, so the phone's idle timer would put it to sleep mid-show.
8
+ *
9
+ * - **Driven by a condition, not by the screen being mounted** (expo-keep-awake's own `useKeepAwake`):
10
+ * the Live screen stays mounted under the Cart and the variant page, where it has no claim on the
11
+ * screen.
12
+ * - **One `tag` per caller.** expo-keep-awake releases by tag, so the Live screen and the live bubble
13
+ * holding the same tag would release each other's hold as the show moves between them.
14
+ * - The release waits for the hold to have been taken: both cross to native, and a condition that turns
15
+ * off as soon as it turned on would otherwise release a hold not yet made, leaving it on for good.
16
+ * - A hold or release that fails goes to `LiveSellingProvider`'s `onWarning`.
17
+ */
18
+ const expo_keep_awake_1 = require("expo-keep-awake");
19
+ const react_1 = require("react");
20
+ const pageOptions_1 = require("../pageOptions");
21
+ function useKeepScreenAwake(active, tag) {
22
+ (0, react_1.useEffect)(() => {
23
+ if (!active)
24
+ return;
25
+ const holding = (0, expo_keep_awake_1.activateKeepAwakeAsync)(tag);
26
+ holding.catch((error) => (0, pageOptions_1.reportLiveWarning)(error, { at: 'useKeepScreenAwake.activate', tag }));
27
+ return () => {
28
+ holding
29
+ .then(() => (0, expo_keep_awake_1.deactivateKeepAwake)(tag))
30
+ .catch((error) => (0, pageOptions_1.reportLiveWarning)(error, { at: 'useKeepScreenAwake.deactivate', tag }));
31
+ };
32
+ }, [active, tag]);
33
+ }
34
+ //# sourceMappingURL=useKeepScreenAwake.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useKeepScreenAwake.js","sourceRoot":"","sources":["../../src/react/useKeepScreenAwake.ts"],"names":[],"mappings":";;AAmBA,gDAWC;AA9BD;;;;;;;;;;;;;GAaG;AACH,qDAA8E;AAC9E,iCAAkC;AAElC,gDAAmD;AAEnD,SAAgB,kBAAkB,CAAC,MAAe,EAAE,GAAW;IAC7D,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,MAAM,OAAO,GAAG,IAAA,wCAAsB,EAAC,GAAG,CAAC,CAAC;QAC5C,OAAO,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE,CAAC,IAAA,+BAAiB,EAAC,KAAK,EAAE,EAAE,EAAE,EAAE,6BAA6B,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;QACxG,OAAO,GAAG,EAAE;YACV,OAAO;iBACJ,IAAI,CAAC,GAAG,EAAE,CAAC,IAAA,qCAAmB,EAAC,GAAG,CAAC,CAAC;iBACpC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE,CAAC,IAAA,+BAAiB,EAAC,KAAK,EAAE,EAAE,EAAE,EAAE,+BAA+B,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;QACvG,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;AACpB,CAAC"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * The Live screen's auction (0.14.0, moved from amore-v2's `src/core/hooks/useLiveAuction.ts`: phase 4
3
+ * of its "Live player plan", bidding). The routes and the store's name are the app's
4
+ * (`LiveSellingProvider`'s `routes` and `shopName`); the route's `streamId` param is read here.
5
+ */
6
+ import { type Product } from '@tiledev/sdk-shopify';
7
+ import type { LiveAuctionLot, LiveAuctionRound, LiveAuctionWinner, LiveBidRefusal, LiveBidStep, LiveShopLink } from '../pageTypes';
8
+ /** What the Live screen hands the auction. */
9
+ export interface LiveAuctionScreen {
10
+ /**
11
+ * Opens Items You Won over the show, as the header's cart does on an auction show (`useLivePage`'s
12
+ * `header.onCart`, which shrinks a show on air into the bubble first): the unpaid-wins sheet's
13
+ * "Checkout now".
14
+ */
15
+ openItemsYouWon: () => void;
16
+ }
17
+ /**
18
+ * The Live screen's auction, so the screen stays plain tiles. The session never ticks: it gives when
19
+ * the round closes (`auction.closesAt`, on the phone's clock), and the bid bar and the final countdown
20
+ * count down to it themselves (`useAuctionCountdown`), so the screen is never drawn on the round's
21
+ * clock.
22
+ *
23
+ * - **The session does the auction:** the round, the leader, the clock, the hammer and whether it is the
24
+ * shopper's (`session.auction`, `lastWin.isYou`), the bid itself (`actions.placeBid`), and everything
25
+ * in front of a bid (`useAuctionBidGate`: signed in, nothing unpaid from another show, the rules
26
+ * accepted once per phone, a variant chosen once a round). Nothing here repeats them.
27
+ * - **The bid gate's sheets are the bid bar's** (decided, amore-v2's Head of Engineering): `step` tells
28
+ * the bid bar which one to show. Signing in is sdk-shopify's `useSignIn` (Shopify's sheet, or the
29
+ * app's Sign In page: `routes.openSignIn`), as bidding needs a Shopify sign-in (the win is written to
30
+ * the customer).
31
+ * - **Back to the bid after signing in** (the gate's `startSignIn`): the bid waits; once the shopper is
32
+ * a bidder, and if bidding on that lot is still open, it goes through the gate again (unpaid wins,
33
+ * read fresh first, then the rules, the variant). Dropped when bidding on the lot closes, when the
34
+ * shopper asks for another bid, or when this screen is back on show still signed out (the Sign In
35
+ * page closed). Shopify's own sign-in sheet doesn't leave the screen: closed without signing in, the
36
+ * bid waits until bidding on its lot closes. Signed in with the customer still loading, no sign-in
37
+ * opens: the bid waits for them (`signInLoading`).
38
+ * - **A bid goes out at the amount the shopper saw** (the gate's `atAmountShown`): the slide's "Bid
39
+ * $25.00", or the amount typed. The last look before it goes: the round still open with time on the
40
+ * clock, at most the host's ceiling, at least the next bid. If the room moved past it (a sheet was
41
+ * open meanwhile), it isn't sent and the bar says so (`refusal`), rather than going out at a price
42
+ * nobody showed. After a bid goes the bar takes no other for 1.2 s (`bidOnItsWay`). The session sends
43
+ * nothing when it knows no moderator for the round (L3), and a send can fail: `placeBid` says so
44
+ * (`{ sent: false }`), and the bar says the bid didn't go through in the place of the outbid line,
45
+ * and takes a bid again at once (decided 2026-10-06: "Bid didn't go through"). The bar's line goes
46
+ * with the next bid or the round.
47
+ * - **The winner is told** (`win`): everyone sees who won; the shopper sees "You" when they held the
48
+ * highest bid as the round closed and the winning bid is theirs (`lastWin.isYou`). The room sends only
49
+ * the winner's name, not who they are. No name is handed out as an email. The win itself reaches the
50
+ * cart's Items You Won from the server; that page reads it each time it opens.
51
+ * - **The lots** for the Shop button's sheet and the card (`lotStateFor`): open (the round is on it),
52
+ * closed (won: on the show's record, or seen here), else upcoming. A link the host added (0.15.0,
53
+ * `showLinkOf`) sits among them with its price and no state, and a featured link has no round on the
54
+ * card: it is opened, never bid on (`useLiveShop` opens it).
55
+ * - **The store's name** in the bidding rules is `shopName` (old Amore's took the host's, which can be
56
+ * a person's).
57
+ * - **Nothing shows** until the session holds this show's record (`useLiveShow`; never a hidden show the
58
+ * shopper can't see), or on a show that isn't an auction. The web's session is always "ended":
59
+ * nothing draws there.
60
+ */
61
+ export declare function useLiveAuction({ openItemsYouWon }: LiveAuctionScreen): {
62
+ bidBar: {
63
+ visible: boolean;
64
+ currencyCode: string;
65
+ highestBid: number;
66
+ nextBid: number;
67
+ closesAt: number | null;
68
+ extended: boolean;
69
+ extendedSeconds: number;
70
+ isLeading: boolean;
71
+ bidCap: number | null;
72
+ busy: boolean;
73
+ step: LiveBidStep | null;
74
+ shopName: string | undefined;
75
+ lotProduct: Product | null;
76
+ refusal: LiveBidRefusal | null;
77
+ onBid: (amount: number) => void;
78
+ onAcceptTerms: () => void;
79
+ onChooseVariant: (variantId: string) => void;
80
+ onCloseStep: () => void;
81
+ onSeeWins: () => void;
82
+ };
83
+ finalCountdown: {
84
+ visible: boolean;
85
+ closesAt: number | null;
86
+ };
87
+ biddingWar: {
88
+ active: boolean;
89
+ onDone: () => void;
90
+ };
91
+ win: {
92
+ winner: LiveAuctionWinner | null;
93
+ onDone: () => void;
94
+ };
95
+ /** The auction part of the featured card; `useLiveShop` gives the rest. */
96
+ productCard: {
97
+ auctionRound: LiveAuctionRound | null;
98
+ };
99
+ /** The auction part of the Shop button: its sheet lists the lots. */
100
+ shopButton: {
101
+ lots: (LiveShopLink | LiveAuctionLot)[] | null;
102
+ };
103
+ };
104
+ /** What `useLiveAuction` hands the Live screen's auction tiles. */
105
+ export type LiveAuction = ReturnType<typeof useLiveAuction>;
106
+ //# sourceMappingURL=useLiveAuction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLiveAuction.d.ts","sourceRoot":"","sources":["../../src/react/useLiveAuction.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAuC,KAAK,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAKzF,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,cAAc,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAiBnI,8CAA8C;AAC9C,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,eAAe,EAAE,MAAM,IAAI,CAAC;CAC7B;AAcD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAgB,cAAc,CAAC,EAAE,eAAe,EAAE,EAAE,iBAAiB;;;;;;;;;;;;;;;;wBAqFxD,MAAM;;;;;;;;;;;;;;;;;;IAsGf,2EAA2E;;;;IAE3E,qEAAqE;;;;EAGxE;AAED,mEAAmE;AACnE,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC"}