@aranova/tracking-react 1.17.0 → 1.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -0
- package/dist/{bookings-2ZKfenQ7.d.ts → bookings-BDLyF70h.d.ts} +61 -5
- package/dist/{bookings-DOh1WMhH.d.mts → bookings-v3HA8gsC.d.mts} +61 -5
- package/dist/client.d.mts +122 -5
- package/dist/client.d.ts +122 -5
- package/dist/client.js +1917 -193
- package/dist/client.js.map +1 -1
- package/dist/client.mjs +1919 -193
- package/dist/client.mjs.map +1 -1
- package/dist/index.d.mts +17 -41
- package/dist/index.d.ts +17 -41
- package/dist/index.js +220 -39
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +218 -39
- package/dist/index.mjs.map +1 -1
- package/dist/{ingest-typed-D7I4aQ7p.d.ts → ingest-typed-BEFQd3WM.d.mts} +290 -2
- package/dist/{ingest-typed-BO6Arbw-.d.mts → ingest-typed-DChvvgwd.d.ts} +290 -2
- package/dist/{phone-utils-CYr6AmEP.d.mts → phone-utils-BlWj8oxq.d.mts} +1 -0
- package/dist/{phone-utils-CYr6AmEP.d.ts → phone-utils-BlWj8oxq.d.ts} +1 -0
- package/dist/phone.d.mts +1 -1
- package/dist/phone.d.ts +1 -1
- package/dist/{sales-B1u_IHLZ.d.mts → sales-Cu8M8I8k.d.ts} +1 -1
- package/dist/{sales-I2jXSS-l.d.ts → sales-DriCnCbM.d.mts} +1 -1
- package/dist/sales.d.mts +3 -3
- package/dist/sales.d.ts +3 -3
- package/dist/sales.js +150 -38
- package/dist/sales.js.map +1 -1
- package/dist/sales.mjs +150 -38
- package/dist/sales.mjs.map +1 -1
- package/package.json +1 -1
package/dist/client.js
CHANGED
|
@@ -34,10 +34,15 @@ __export(client_exports, {
|
|
|
34
34
|
AdPlatformTracking: () => AdPlatformTracking,
|
|
35
35
|
BookingHandoffLink: () => BookingHandoffLink,
|
|
36
36
|
ConsentBanner: () => ConsentBanner,
|
|
37
|
+
DEFAULT_VIDEO_CHECKPOINTS: () => DEFAULT_VIDEO_CHECKPOINTS,
|
|
37
38
|
GoogleAdsTracking: () => GoogleAdsTracking,
|
|
38
39
|
PhoneField: () => PhoneField,
|
|
40
|
+
TrackedVideo: () => TrackedVideo,
|
|
41
|
+
TrackedVideoStage: () => TrackedVideoStage,
|
|
39
42
|
createLeadFormSubmit: () => createLeadFormSubmit,
|
|
40
43
|
createTracking: () => createTracking,
|
|
44
|
+
streamManifestUrl: () => streamManifestUrl,
|
|
45
|
+
streamPosterUrl: () => streamPosterUrl,
|
|
41
46
|
useBookingHandoffUrl: () => useBookingHandoffUrl,
|
|
42
47
|
useBookingIntegration: () => useBookingIntegration,
|
|
43
48
|
useBookingSlots: () => useBookingSlots,
|
|
@@ -48,6 +53,7 @@ __export(client_exports, {
|
|
|
48
53
|
useGclid: () => useGclid,
|
|
49
54
|
usePhoneConfig: () => usePhoneConfig,
|
|
50
55
|
usePhoneField: () => usePhoneField,
|
|
56
|
+
useTrackedVideoConfig: () => useTrackedVideoConfig,
|
|
51
57
|
useTrackingParams: () => useTrackingParams
|
|
52
58
|
});
|
|
53
59
|
module.exports = __toCommonJS(client_exports);
|
|
@@ -307,7 +313,8 @@ var TRACKING_CAPABILITIES = [
|
|
|
307
313
|
"form_capture",
|
|
308
314
|
"phone_click_capture",
|
|
309
315
|
"phone_fields",
|
|
310
|
-
"typed_form_submit"
|
|
316
|
+
"typed_form_submit",
|
|
317
|
+
"video_tracking"
|
|
311
318
|
];
|
|
312
319
|
var CAPABILITY_DOM_ATTRIBUTE = "data-aranova-capability";
|
|
313
320
|
var registered = /* @__PURE__ */ new Set();
|
|
@@ -1088,8 +1095,48 @@ function parseTrigger(value) {
|
|
|
1088
1095
|
if (typeof t.threshold_seconds === "number") spec.threshold_seconds = t.threshold_seconds;
|
|
1089
1096
|
if (typeof t.page_threshold === "number") spec.page_threshold = t.page_threshold;
|
|
1090
1097
|
if (typeof t.page_name === "string") spec.page_name = t.page_name;
|
|
1098
|
+
if (t.metric === "percent" || t.metric === "seconds") spec.metric = t.metric;
|
|
1099
|
+
if (typeof t.threshold === "number") spec.threshold = t.threshold;
|
|
1100
|
+
if (typeof t.video_id === "string" || t.video_id === null) spec.video_id = t.video_id;
|
|
1091
1101
|
return spec;
|
|
1092
1102
|
}
|
|
1103
|
+
function parseVideoEntry(fallbackKey2, entry) {
|
|
1104
|
+
const key = typeof entry.key === "string" && entry.key ? entry.key : fallbackKey2;
|
|
1105
|
+
if (!key) return null;
|
|
1106
|
+
const host = typeof entry.host === "string" ? entry.host : "";
|
|
1107
|
+
const title = typeof entry.title === "string" && entry.title ? entry.title : key;
|
|
1108
|
+
const sourcesRaw = isRecord(entry.sources) ? entry.sources : null;
|
|
1109
|
+
const desktop = sourcesRaw && typeof sourcesRaw.desktop === "string" ? sourcesRaw.desktop : typeof entry.desktop_uid === "string" ? entry.desktop_uid : "";
|
|
1110
|
+
if (!host || !desktop) return null;
|
|
1111
|
+
const mobile = sourcesRaw && typeof sourcesRaw.mobile === "string" ? sourcesRaw.mobile : typeof entry.mobile_uid === "string" ? entry.mobile_uid : null;
|
|
1112
|
+
const posterTime = typeof entry.poster_time === "number" ? entry.poster_time : typeof entry.poster_time_s === "number" ? entry.poster_time_s : 4;
|
|
1113
|
+
return {
|
|
1114
|
+
key,
|
|
1115
|
+
title,
|
|
1116
|
+
host,
|
|
1117
|
+
sources: { desktop, mobile },
|
|
1118
|
+
poster_time: posterTime,
|
|
1119
|
+
duration_s: typeof entry.duration_s === "number" ? entry.duration_s : null
|
|
1120
|
+
};
|
|
1121
|
+
}
|
|
1122
|
+
function parseVideos(value) {
|
|
1123
|
+
const out = {};
|
|
1124
|
+
if (Array.isArray(value)) {
|
|
1125
|
+
for (const item of value) {
|
|
1126
|
+
if (!isRecord(item)) continue;
|
|
1127
|
+
const parsed = parseVideoEntry("", item);
|
|
1128
|
+
if (parsed) out[parsed.key] = parsed;
|
|
1129
|
+
}
|
|
1130
|
+
return out;
|
|
1131
|
+
}
|
|
1132
|
+
if (!isRecord(value)) return out;
|
|
1133
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
1134
|
+
if (!isRecord(entry)) continue;
|
|
1135
|
+
const parsed = parseVideoEntry(key, entry);
|
|
1136
|
+
if (parsed) out[parsed.key] = parsed;
|
|
1137
|
+
}
|
|
1138
|
+
return out;
|
|
1139
|
+
}
|
|
1093
1140
|
function parseConversionConfig(raw) {
|
|
1094
1141
|
if (!raw || typeof raw !== "object") return null;
|
|
1095
1142
|
const obj = raw;
|
|
@@ -1140,7 +1187,8 @@ function parseConversionConfig(raw) {
|
|
|
1140
1187
|
goals,
|
|
1141
1188
|
linked_hostnames: Array.isArray(obj.linked_hostnames) ? obj.linked_hostnames.filter((h) => typeof h === "string" && h.length > 0) : [],
|
|
1142
1189
|
integrations: parseIntegrations(obj.integrations),
|
|
1143
|
-
lead_forms: parseLeadForms(obj.lead_forms)
|
|
1190
|
+
lead_forms: parseLeadForms(obj.lead_forms),
|
|
1191
|
+
videos: parseVideos(obj.videos)
|
|
1144
1192
|
};
|
|
1145
1193
|
}
|
|
1146
1194
|
function parseLeadForms(value) {
|
|
@@ -1386,6 +1434,21 @@ function automaticThresholdMet(goal, eventType, metadata) {
|
|
|
1386
1434
|
case "form_start":
|
|
1387
1435
|
case "phone_click":
|
|
1388
1436
|
return true;
|
|
1437
|
+
case "video_play":
|
|
1438
|
+
return trigger.video_id == null || hasStringField(metadata, "video_id") && metadata.video_id === trigger.video_id;
|
|
1439
|
+
case "video_progress": {
|
|
1440
|
+
if (trigger.video_id != null && (!hasStringField(metadata, "video_id") || metadata.video_id !== trigger.video_id)) {
|
|
1441
|
+
return false;
|
|
1442
|
+
}
|
|
1443
|
+
if (typeof trigger.threshold !== "number") return false;
|
|
1444
|
+
if (trigger.metric === "seconds") {
|
|
1445
|
+
return hasNumberField(metadata, "watched_s") && metadata.watched_s >= trigger.threshold;
|
|
1446
|
+
}
|
|
1447
|
+
if (trigger.metric === "percent") {
|
|
1448
|
+
return hasNumberField(metadata, "max_percent") && metadata.max_percent >= trigger.threshold || hasNumberField(metadata, "watched_percent") && metadata.watched_percent >= trigger.threshold;
|
|
1449
|
+
}
|
|
1450
|
+
return false;
|
|
1451
|
+
}
|
|
1389
1452
|
default:
|
|
1390
1453
|
return false;
|
|
1391
1454
|
}
|
|
@@ -1422,6 +1485,9 @@ var RETRY_BASE_MS = 5e3;
|
|
|
1422
1485
|
var RETRY_MAX_MS = 5 * 6e4;
|
|
1423
1486
|
var runtimes = /* @__PURE__ */ new Map();
|
|
1424
1487
|
var configuredIds = /* @__PURE__ */ new Set();
|
|
1488
|
+
var EMPTY_GOALS = [];
|
|
1489
|
+
var EMPTY_STRINGS = [];
|
|
1490
|
+
var EMPTY_VIDEOS = {};
|
|
1425
1491
|
var scriptLoad = null;
|
|
1426
1492
|
var jsInitialized = false;
|
|
1427
1493
|
function cacheKey2(url) {
|
|
@@ -1612,11 +1678,11 @@ var TrackingConfigRuntime = class {
|
|
|
1612
1678
|
void this.flush();
|
|
1613
1679
|
}
|
|
1614
1680
|
listGoals() {
|
|
1615
|
-
return this.current?.goals ??
|
|
1681
|
+
return this.current?.goals ?? EMPTY_GOALS;
|
|
1616
1682
|
}
|
|
1617
1683
|
/** Sibling hostnames for the linker — read from the cached object even while unconfirmed. */
|
|
1618
1684
|
linkedHostnames() {
|
|
1619
|
-
return this.current?.linked_hostnames ??
|
|
1685
|
+
return this.current?.linked_hostnames ?? EMPTY_STRINGS;
|
|
1620
1686
|
}
|
|
1621
1687
|
/**
|
|
1622
1688
|
* Integration blocks, from the cached object even while unconfirmed: the booking fallback
|
|
@@ -1629,6 +1695,14 @@ var TrackingConfigRuntime = class {
|
|
|
1629
1695
|
leadForms() {
|
|
1630
1696
|
return this.current?.lead_forms ?? null;
|
|
1631
1697
|
}
|
|
1698
|
+
/** Configured Cloudflare Stream tracked videos for this site. */
|
|
1699
|
+
videos() {
|
|
1700
|
+
return this.current?.videos ?? EMPTY_VIDEOS;
|
|
1701
|
+
}
|
|
1702
|
+
/** Look up one configured Cloudflare Stream tracked video by key. */
|
|
1703
|
+
getVideo(key) {
|
|
1704
|
+
return this.current?.videos?.[key] ?? null;
|
|
1705
|
+
}
|
|
1632
1706
|
async revalidateNow() {
|
|
1633
1707
|
try {
|
|
1634
1708
|
const headers = {};
|
|
@@ -1785,6 +1859,16 @@ var TrackingConfigRuntime = class {
|
|
|
1785
1859
|
this.scheduleRetry();
|
|
1786
1860
|
return;
|
|
1787
1861
|
}
|
|
1862
|
+
if (outcome === "fired" && typeof window !== "undefined" && typeof window.fbq === "function") {
|
|
1863
|
+
try {
|
|
1864
|
+
window.fbq("trackCustom", item.key, {
|
|
1865
|
+
...value != null ? { value } : {},
|
|
1866
|
+
...currency ? { currency } : {},
|
|
1867
|
+
...item.transactionId ? { transaction_id: item.transactionId } : {}
|
|
1868
|
+
});
|
|
1869
|
+
} catch {
|
|
1870
|
+
}
|
|
1871
|
+
}
|
|
1788
1872
|
this.conversionQueue.shift();
|
|
1789
1873
|
}
|
|
1790
1874
|
}
|
|
@@ -1928,12 +2012,24 @@ function createConversionAutoFire(store) {
|
|
|
1928
2012
|
const firing = goal.firing;
|
|
1929
2013
|
const cents = firing.value_cents ?? null;
|
|
1930
2014
|
const currency = firing.currency ?? null;
|
|
1931
|
-
|
|
2015
|
+
const value = cents != null && currency ? fromMinor(cents, currency) : null;
|
|
2016
|
+
const outcome = fireConversionWithConsent({
|
|
1932
2017
|
sendTo: firing.send_to,
|
|
1933
|
-
value
|
|
2018
|
+
value,
|
|
1934
2019
|
currency,
|
|
1935
2020
|
transactionId
|
|
1936
2021
|
});
|
|
2022
|
+
if (outcome === "fired" && typeof window !== "undefined" && typeof window.fbq === "function") {
|
|
2023
|
+
try {
|
|
2024
|
+
window.fbq("trackCustom", goal.key, {
|
|
2025
|
+
event_type: eventType,
|
|
2026
|
+
...value != null ? { value } : {},
|
|
2027
|
+
...currency ? { currency } : {},
|
|
2028
|
+
transaction_id: transactionId
|
|
2029
|
+
});
|
|
2030
|
+
} catch {
|
|
2031
|
+
}
|
|
2032
|
+
}
|
|
1937
2033
|
}
|
|
1938
2034
|
}
|
|
1939
2035
|
return {
|
|
@@ -2030,6 +2126,13 @@ var EVENT_SEMANTICS = {
|
|
|
2030
2126
|
outcomeRole: "engagement",
|
|
2031
2127
|
clientVisibility: "detailed"
|
|
2032
2128
|
},
|
|
2129
|
+
// Adds to the submit it names; counting it as a lead would double every lead.
|
|
2130
|
+
form_details: {
|
|
2131
|
+
label: "Form details added",
|
|
2132
|
+
category: "lead",
|
|
2133
|
+
outcomeRole: "engagement",
|
|
2134
|
+
clientVisibility: "detailed"
|
|
2135
|
+
},
|
|
2033
2136
|
form_submit: {
|
|
2034
2137
|
label: "Form submitted",
|
|
2035
2138
|
category: "lead",
|
|
@@ -2059,6 +2162,18 @@ var EVENT_SEMANTICS = {
|
|
|
2059
2162
|
category: "page",
|
|
2060
2163
|
outcomeRole: "navigation",
|
|
2061
2164
|
clientVisibility: "simple"
|
|
2165
|
+
},
|
|
2166
|
+
video_play: {
|
|
2167
|
+
label: "Video played",
|
|
2168
|
+
category: "engagement",
|
|
2169
|
+
outcomeRole: "engagement",
|
|
2170
|
+
clientVisibility: "simple"
|
|
2171
|
+
},
|
|
2172
|
+
video_progress: {
|
|
2173
|
+
label: "Video watched",
|
|
2174
|
+
category: "engagement",
|
|
2175
|
+
outcomeRole: "engagement",
|
|
2176
|
+
clientVisibility: "detailed"
|
|
2062
2177
|
}
|
|
2063
2178
|
};
|
|
2064
2179
|
function getEventSemantics(eventName) {
|
|
@@ -2646,14 +2761,31 @@ function createTrackingClient(config) {
|
|
|
2646
2761
|
metadata: input.metadata ?? null,
|
|
2647
2762
|
occurred_at: occurredAt
|
|
2648
2763
|
});
|
|
2649
|
-
|
|
2764
|
+
const triggerReason = input.metadata?.trigger;
|
|
2765
|
+
const isUrgentVideoEvent = input.eventType === "video_play" || input.eventType === "video_progress" && (triggerReason === "ended" || triggerReason === "goal" || triggerReason === "checkpoint");
|
|
2766
|
+
if (queue.length >= maxQueueSize || input.eventType === "form_details" || getEventSemantics(input.eventType)?.outcomeRole === "lead" || isUrgentVideoEvent) {
|
|
2650
2767
|
void flush();
|
|
2651
2768
|
} else {
|
|
2652
2769
|
scheduleFlush();
|
|
2653
2770
|
}
|
|
2654
2771
|
}
|
|
2772
|
+
const beforeUnloadListeners = /* @__PURE__ */ new Set();
|
|
2773
|
+
let runningBeforeUnload = false;
|
|
2655
2774
|
function flushOnUnload() {
|
|
2656
2775
|
if (destroyed) return;
|
|
2776
|
+
if (!runningBeforeUnload && beforeUnloadListeners.size > 0) {
|
|
2777
|
+
runningBeforeUnload = true;
|
|
2778
|
+
try {
|
|
2779
|
+
for (const listener of beforeUnloadListeners) {
|
|
2780
|
+
try {
|
|
2781
|
+
listener();
|
|
2782
|
+
} catch {
|
|
2783
|
+
}
|
|
2784
|
+
}
|
|
2785
|
+
} finally {
|
|
2786
|
+
runningBeforeUnload = false;
|
|
2787
|
+
}
|
|
2788
|
+
}
|
|
2657
2789
|
bufferQueued();
|
|
2658
2790
|
clearScheduledFlush();
|
|
2659
2791
|
if (pending.length === 0) return;
|
|
@@ -2674,6 +2806,12 @@ function createTrackingClient(config) {
|
|
|
2674
2806
|
trackEvent,
|
|
2675
2807
|
flush,
|
|
2676
2808
|
flushBeacon: flushOnUnload,
|
|
2809
|
+
onBeforeUnload: (listener) => {
|
|
2810
|
+
beforeUnloadListeners.add(listener);
|
|
2811
|
+
return () => {
|
|
2812
|
+
beforeUnloadListeners.delete(listener);
|
|
2813
|
+
};
|
|
2814
|
+
},
|
|
2677
2815
|
getSessionId: () => sessionId,
|
|
2678
2816
|
getVisitorId: () => visitorId,
|
|
2679
2817
|
destroy: () => {
|
|
@@ -2684,6 +2822,7 @@ function createTrackingClient(config) {
|
|
|
2684
2822
|
destroyed = true;
|
|
2685
2823
|
clearScheduledFlush();
|
|
2686
2824
|
queue = [];
|
|
2825
|
+
beforeUnloadListeners.clear();
|
|
2687
2826
|
if (typeof window !== "undefined") {
|
|
2688
2827
|
window.removeEventListener("pagehide", flushOnUnload);
|
|
2689
2828
|
window.removeEventListener("visibilitychange", onVisibilityChange);
|
|
@@ -2750,110 +2889,133 @@ var formStartConfigSchema = z5.strictObject({
|
|
|
2750
2889
|
selector: z5.optional(z5.string())
|
|
2751
2890
|
});
|
|
2752
2891
|
|
|
2753
|
-
// ../tracking-core/src/events/form-
|
|
2892
|
+
// ../tracking-core/src/events/form-details.ts
|
|
2893
|
+
var z7 = __toESM(require("zod/mini"));
|
|
2894
|
+
|
|
2895
|
+
// ../tracking-core/src/events/form-submit.ts
|
|
2754
2896
|
var z6 = __toESM(require("zod/mini"));
|
|
2755
|
-
var
|
|
2897
|
+
var jsonValueSchema = z6.lazy(
|
|
2898
|
+
() => z6.union([
|
|
2899
|
+
z6.string(),
|
|
2900
|
+
z6.number(),
|
|
2901
|
+
z6.boolean(),
|
|
2902
|
+
z6.null(),
|
|
2903
|
+
z6.array(jsonValueSchema),
|
|
2904
|
+
z6.record(z6.string(), jsonValueSchema)
|
|
2905
|
+
])
|
|
2906
|
+
).register(z6.globalRegistry, { id: "JsonSerializableValue" });
|
|
2907
|
+
var contractNameSchema = z6.string().check(z6.regex(/^[a-z][a-z0-9_]{0,47}(:[a-z0-9_-]{1,48})?$/));
|
|
2908
|
+
var violationRole = z6.string().check(
|
|
2909
|
+
z6.maxLength(200),
|
|
2910
|
+
z6.regex(
|
|
2911
|
+
/^[a-z][a-z0-9_]{0,47}(:[a-z0-9_-]{1,48})?(\|[a-z][a-z0-9_]{0,47}(:[a-z0-9_-]{1,48})?)*$/
|
|
2912
|
+
)
|
|
2913
|
+
);
|
|
2914
|
+
var MAX_CONTRACT_VIOLATIONS = 50;
|
|
2915
|
+
var contractViolationSchema = z6.strictObject({
|
|
2916
|
+
role: z6.nullable(violationRole),
|
|
2917
|
+
rule: z6.string().check(z6.regex(/^[a-z][a-z_]{0,47}$/))
|
|
2918
|
+
});
|
|
2919
|
+
var formFieldSchema = z6.strictObject({
|
|
2920
|
+
name: z6.string(),
|
|
2921
|
+
type: z6.string(),
|
|
2922
|
+
label: z6.nullable(z6.string()),
|
|
2923
|
+
value: jsonValueSchema,
|
|
2924
|
+
role: z6.optional(z6.nullable(contractNameSchema))
|
|
2925
|
+
});
|
|
2926
|
+
var formExtraSchema = z6.optional(
|
|
2927
|
+
z6.nullable(
|
|
2928
|
+
z6.array(
|
|
2929
|
+
z6.strictObject({
|
|
2930
|
+
key: z6.string().check(z6.maxLength(64)),
|
|
2931
|
+
label: z6.string().check(z6.maxLength(200)),
|
|
2932
|
+
value: jsonValueSchema
|
|
2933
|
+
})
|
|
2934
|
+
).check(z6.maxLength(20))
|
|
2935
|
+
)
|
|
2936
|
+
);
|
|
2937
|
+
var contractVersionSchema = z6.optional(z6.nullable(z6.int().check(z6.gte(1))));
|
|
2938
|
+
var contractHashSchema = z6.optional(z6.nullable(z6.string().check(z6.maxLength(64))));
|
|
2939
|
+
var formContractViolationsSchema = z6.optional(
|
|
2940
|
+
z6.nullable(z6.array(contractViolationSchema).check(z6.maxLength(MAX_CONTRACT_VIOLATIONS)))
|
|
2941
|
+
);
|
|
2942
|
+
var formSubmitMetadataSchema = z6.strictObject({
|
|
2756
2943
|
form: z6.strictObject({
|
|
2757
2944
|
id: z6.string(),
|
|
2758
|
-
action: z6.nullable(z6.string())
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2945
|
+
action: z6.nullable(z6.string()),
|
|
2946
|
+
fields: z6.optional(z6.array(formFieldSchema)),
|
|
2947
|
+
kind: z6.optional(z6.nullable(contractNameSchema)),
|
|
2948
|
+
contract_version: contractVersionSchema,
|
|
2949
|
+
contract_hash: contractHashSchema,
|
|
2950
|
+
extra: formExtraSchema,
|
|
2951
|
+
contract_violations: formContractViolationsSchema,
|
|
2952
|
+
// Minted per submit; a later `form_details` names it to add answers to this lead.
|
|
2953
|
+
submission_id: z6.optional(z6.nullable(z6.uuidv4()))
|
|
2766
2954
|
}),
|
|
2767
|
-
direction: z6.enum(["forward", "back"]),
|
|
2768
2955
|
page: z6.strictObject({
|
|
2769
2956
|
path: z6.string()
|
|
2770
2957
|
})
|
|
2771
2958
|
});
|
|
2772
|
-
var
|
|
2959
|
+
var formSubmitConfigSchema = z6.strictObject({});
|
|
2773
2960
|
|
|
2774
|
-
// ../tracking-core/src/events/form-
|
|
2775
|
-
var
|
|
2776
|
-
var jsonValueSchema = z7.lazy(
|
|
2777
|
-
() => z7.union([
|
|
2778
|
-
z7.string(),
|
|
2779
|
-
z7.number(),
|
|
2780
|
-
z7.boolean(),
|
|
2781
|
-
z7.null(),
|
|
2782
|
-
z7.array(jsonValueSchema),
|
|
2783
|
-
z7.record(z7.string(), jsonValueSchema)
|
|
2784
|
-
])
|
|
2785
|
-
).register(z7.globalRegistry, { id: "JsonSerializableValue" });
|
|
2786
|
-
var contractNameSchema = z7.string().check(z7.regex(/^[a-z][a-z0-9_]{0,47}(:[a-z0-9_-]{1,48})?$/));
|
|
2787
|
-
var contractName = contractNameSchema;
|
|
2788
|
-
var violationRole = z7.string().check(
|
|
2789
|
-
z7.maxLength(200),
|
|
2790
|
-
z7.regex(
|
|
2791
|
-
/^[a-z][a-z0-9_]{0,47}(:[a-z0-9_-]{1,48})?(\|[a-z][a-z0-9_]{0,47}(:[a-z0-9_-]{1,48})?)*$/
|
|
2792
|
-
)
|
|
2793
|
-
);
|
|
2794
|
-
var MAX_CONTRACT_VIOLATIONS = 50;
|
|
2795
|
-
var contractViolationSchema = z7.strictObject({
|
|
2796
|
-
role: z7.nullable(violationRole),
|
|
2797
|
-
rule: z7.string().check(z7.regex(/^[a-z][a-z_]{0,47}$/))
|
|
2798
|
-
});
|
|
2799
|
-
var formSubmitMetadataSchema = z7.strictObject({
|
|
2961
|
+
// ../tracking-core/src/events/form-details.ts
|
|
2962
|
+
var formDetailsMetadataSchema = z7.strictObject({
|
|
2800
2963
|
form: z7.strictObject({
|
|
2801
2964
|
id: z7.string(),
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
value: jsonValueSchema,
|
|
2810
|
-
role: z7.optional(z7.nullable(contractName))
|
|
2811
|
-
})
|
|
2812
|
-
)
|
|
2813
|
-
),
|
|
2814
|
-
kind: z7.optional(z7.nullable(contractName)),
|
|
2815
|
-
contract_version: z7.optional(z7.nullable(z7.int().check(z7.gte(1)))),
|
|
2816
|
-
contract_hash: z7.optional(z7.nullable(z7.string().check(z7.maxLength(64)))),
|
|
2817
|
-
extra: z7.optional(
|
|
2818
|
-
z7.nullable(
|
|
2819
|
-
z7.array(
|
|
2820
|
-
z7.strictObject({
|
|
2821
|
-
key: z7.string().check(z7.maxLength(64)),
|
|
2822
|
-
label: z7.string().check(z7.maxLength(200)),
|
|
2823
|
-
value: jsonValueSchema
|
|
2824
|
-
})
|
|
2825
|
-
).check(z7.maxLength(20))
|
|
2826
|
-
)
|
|
2827
|
-
),
|
|
2828
|
-
contract_violations: z7.optional(
|
|
2829
|
-
z7.nullable(z7.array(contractViolationSchema).check(z7.maxLength(MAX_CONTRACT_VIOLATIONS)))
|
|
2830
|
-
)
|
|
2965
|
+
submission_id: z7.uuidv4(),
|
|
2966
|
+
kind: z7.optional(z7.nullable(contractNameSchema)),
|
|
2967
|
+
fields: z7.array(formFieldSchema),
|
|
2968
|
+
contract_version: contractVersionSchema,
|
|
2969
|
+
contract_hash: contractHashSchema,
|
|
2970
|
+
extra: formExtraSchema,
|
|
2971
|
+
contract_violations: formContractViolationsSchema
|
|
2831
2972
|
}),
|
|
2832
2973
|
page: z7.strictObject({
|
|
2833
2974
|
path: z7.string()
|
|
2834
2975
|
})
|
|
2835
2976
|
});
|
|
2836
|
-
var
|
|
2977
|
+
var formDetailsConfigSchema = z7.strictObject({});
|
|
2837
2978
|
|
|
2838
|
-
// ../tracking-core/src/events/
|
|
2979
|
+
// ../tracking-core/src/events/form-step.ts
|
|
2839
2980
|
var z8 = __toESM(require("zod/mini"));
|
|
2840
|
-
var
|
|
2841
|
-
|
|
2981
|
+
var formStepMetadataSchema = z8.strictObject({
|
|
2982
|
+
form: z8.strictObject({
|
|
2983
|
+
id: z8.string(),
|
|
2984
|
+
action: z8.nullable(z8.string())
|
|
2985
|
+
}),
|
|
2986
|
+
step: z8.strictObject({
|
|
2987
|
+
id: z8.string().check(z8.minLength(1), z8.maxLength(64), z8.regex(/^[A-Za-z0-9_-]+$/)),
|
|
2988
|
+
// 1-based position in the flow the visitor is on right now.
|
|
2989
|
+
index: z8.int().check(z8.gte(1), z8.lte(50)),
|
|
2990
|
+
// Null when the number of steps depends on earlier answers.
|
|
2991
|
+
total: z8.nullable(z8.int().check(z8.gte(1), z8.lte(50)))
|
|
2992
|
+
}),
|
|
2993
|
+
direction: z8.enum(["forward", "back"]),
|
|
2842
2994
|
page: z8.strictObject({
|
|
2843
2995
|
path: z8.string()
|
|
2844
2996
|
})
|
|
2845
2997
|
});
|
|
2846
|
-
var
|
|
2847
|
-
|
|
2998
|
+
var formStepConfigSchema = z8.strictObject({});
|
|
2999
|
+
|
|
3000
|
+
// ../tracking-core/src/events/multi-page-session.ts
|
|
3001
|
+
var z9 = __toESM(require("zod/mini"));
|
|
3002
|
+
var multiPageSessionMetadataSchema = z9.strictObject({
|
|
3003
|
+
page_count: z9.int().check(z9.gte(2)),
|
|
3004
|
+
page: z9.strictObject({
|
|
3005
|
+
path: z9.string()
|
|
3006
|
+
})
|
|
3007
|
+
});
|
|
3008
|
+
var multiPageSessionConfigSchema = z9.strictObject({
|
|
3009
|
+
pageThreshold: z9.int().check(z9.gte(2))
|
|
2848
3010
|
});
|
|
2849
3011
|
|
|
2850
3012
|
// ../tracking-core/src/events/page-exit.ts
|
|
2851
|
-
var
|
|
2852
|
-
var pageExitMetadataSchema =
|
|
2853
|
-
dwell_ms:
|
|
3013
|
+
var z10 = __toESM(require("zod/mini"));
|
|
3014
|
+
var pageExitMetadataSchema = z10.strictObject({
|
|
3015
|
+
dwell_ms: z10.int().check(z10.gte(0)),
|
|
2854
3016
|
// null = left without any scroll signal; floor is 0 so a valid 0% is never
|
|
2855
3017
|
// rejected (a single bad field 422s the whole keepalive beacon batch).
|
|
2856
|
-
max_scroll_percent:
|
|
3018
|
+
max_scroll_percent: z10.nullable(z10.int().check(z10.gte(0), z10.lte(100))),
|
|
2857
3019
|
// The gating baseline: the fraction of the page visible at load with
|
|
2858
3020
|
// zero scrolling — or, for pages that grew after the post-paint snapshot
|
|
2859
3021
|
// (skeleton/streaming renders), the first-scroll position that
|
|
@@ -2861,106 +3023,186 @@ var pageExitMetadataSchema = z9.strictObject({
|
|
|
2861
3023
|
// ended before the snapshot. Optionality is load-bearing: SDK builds
|
|
2862
3024
|
// predating this field keep POSTing page_exit without the key —
|
|
2863
3025
|
// requiring it would 422 whole keepalive beacon batches.
|
|
2864
|
-
scroll_baseline_percent:
|
|
2865
|
-
page:
|
|
2866
|
-
path:
|
|
3026
|
+
scroll_baseline_percent: z10.optional(z10.nullable(z10.int().check(z10.gte(0), z10.lte(100)))),
|
|
3027
|
+
page: z10.strictObject({
|
|
3028
|
+
path: z10.string()
|
|
2867
3029
|
})
|
|
2868
3030
|
});
|
|
2869
|
-
var pageExitConfigSchema =
|
|
3031
|
+
var pageExitConfigSchema = z10.strictObject({});
|
|
2870
3032
|
|
|
2871
3033
|
// ../tracking-core/src/events/phone-click.ts
|
|
2872
|
-
var
|
|
2873
|
-
var phoneClickMetadataSchema =
|
|
2874
|
-
phone_number:
|
|
2875
|
-
page:
|
|
2876
|
-
path:
|
|
3034
|
+
var z11 = __toESM(require("zod/mini"));
|
|
3035
|
+
var phoneClickMetadataSchema = z11.strictObject({
|
|
3036
|
+
phone_number: z11.string(),
|
|
3037
|
+
page: z11.strictObject({
|
|
3038
|
+
path: z11.string()
|
|
2877
3039
|
}),
|
|
2878
|
-
section:
|
|
3040
|
+
section: z11.optional(z11.nullable(z11.string()))
|
|
2879
3041
|
});
|
|
2880
|
-
var phoneClickConfigSchema =
|
|
2881
|
-
autoCapture:
|
|
2882
|
-
|
|
2883
|
-
selector:
|
|
3042
|
+
var phoneClickConfigSchema = z11.strictObject({
|
|
3043
|
+
autoCapture: z11.optional(
|
|
3044
|
+
z11.strictObject({
|
|
3045
|
+
selector: z11.optional(z11.string())
|
|
2884
3046
|
})
|
|
2885
3047
|
)
|
|
2886
3048
|
});
|
|
2887
3049
|
|
|
2888
3050
|
// ../tracking-core/src/events/scroll-depth.ts
|
|
2889
|
-
var
|
|
2890
|
-
var scrollDepthMetadataSchema =
|
|
2891
|
-
depth_percent:
|
|
2892
|
-
page:
|
|
2893
|
-
path:
|
|
3051
|
+
var z12 = __toESM(require("zod/mini"));
|
|
3052
|
+
var scrollDepthMetadataSchema = z12.strictObject({
|
|
3053
|
+
depth_percent: z12.int().check(z12.gte(1), z12.lte(100)),
|
|
3054
|
+
page: z12.strictObject({
|
|
3055
|
+
path: z12.string()
|
|
2894
3056
|
})
|
|
2895
3057
|
});
|
|
2896
|
-
var scrollDepthConfigSchema =
|
|
2897
|
-
thresholds:
|
|
3058
|
+
var scrollDepthConfigSchema = z12.strictObject({
|
|
3059
|
+
thresholds: z12.array(z12.int().check(z12.gte(1), z12.lte(100))).check(z12.minLength(1))
|
|
2898
3060
|
});
|
|
2899
3061
|
|
|
2900
3062
|
// ../tracking-core/src/events/specific-page-visit.ts
|
|
2901
|
-
var
|
|
3063
|
+
var z13 = __toESM(require("zod/mini"));
|
|
2902
3064
|
var PAGE_IDENTITY_MAX_LENGTH = 64;
|
|
2903
3065
|
var PAGE_IDENTITY_PATTERN = /^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$/;
|
|
2904
|
-
var pageIdentitySchema =
|
|
2905
|
-
|
|
2906
|
-
|
|
3066
|
+
var pageIdentitySchema = z13.string().check(
|
|
3067
|
+
z13.maxLength(PAGE_IDENTITY_MAX_LENGTH),
|
|
3068
|
+
z13.regex(PAGE_IDENTITY_PATTERN, {
|
|
2907
3069
|
message: "page identity must be lowercase snake_case, start with a letter, and contain at most 64 characters"
|
|
2908
3070
|
})
|
|
2909
3071
|
);
|
|
2910
3072
|
var specificPageNameSchema = pageIdentitySchema;
|
|
2911
|
-
var specificPageVisitMetadataSchema =
|
|
3073
|
+
var specificPageVisitMetadataSchema = z13.strictObject({
|
|
2912
3074
|
page_name: specificPageNameSchema,
|
|
2913
|
-
page:
|
|
2914
|
-
path:
|
|
3075
|
+
page: z13.strictObject({
|
|
3076
|
+
path: z13.string()
|
|
2915
3077
|
})
|
|
2916
3078
|
});
|
|
2917
|
-
var specificPageVisitConfigSchema =
|
|
2918
|
-
pages:
|
|
2919
|
-
|
|
3079
|
+
var specificPageVisitConfigSchema = z13.strictObject({
|
|
3080
|
+
pages: z13.array(
|
|
3081
|
+
z13.strictObject({
|
|
2920
3082
|
name: specificPageNameSchema,
|
|
2921
|
-
pathPattern:
|
|
3083
|
+
pathPattern: z13.custom((value) => value instanceof RegExp, {
|
|
2922
3084
|
message: "pathPattern must be a RegExp"
|
|
2923
3085
|
})
|
|
2924
3086
|
})
|
|
2925
|
-
).check(
|
|
3087
|
+
).check(z13.minLength(1))
|
|
2926
3088
|
});
|
|
2927
3089
|
|
|
2928
3090
|
// ../tracking-core/src/events/site-link.ts
|
|
2929
|
-
var
|
|
2930
|
-
var siteLinkClickMetadataSchema =
|
|
2931
|
-
destination_host:
|
|
2932
|
-
destination_url:
|
|
2933
|
-
page:
|
|
2934
|
-
path:
|
|
3091
|
+
var z14 = __toESM(require("zod/mini"));
|
|
3092
|
+
var siteLinkClickMetadataSchema = z14.strictObject({
|
|
3093
|
+
destination_host: z14.string(),
|
|
3094
|
+
destination_url: z14.string(),
|
|
3095
|
+
page: z14.strictObject({
|
|
3096
|
+
path: z14.string()
|
|
2935
3097
|
})
|
|
2936
3098
|
});
|
|
2937
|
-
var siteLinkClickConfigSchema =
|
|
2938
|
-
var siteLinkArrivalMetadataSchema =
|
|
2939
|
-
outcome:
|
|
2940
|
-
origin_session_id:
|
|
2941
|
-
origin_visitor_id:
|
|
3099
|
+
var siteLinkClickConfigSchema = z14.strictObject({});
|
|
3100
|
+
var siteLinkArrivalMetadataSchema = z14.strictObject({
|
|
3101
|
+
outcome: z14.enum(["linked", "stale", "invalid"]),
|
|
3102
|
+
origin_session_id: z14.optional(z14.nullable(z14.string())),
|
|
3103
|
+
origin_visitor_id: z14.optional(z14.nullable(z14.string())),
|
|
2942
3104
|
// Milliseconds between the origin click and this page load.
|
|
2943
|
-
transit_ms:
|
|
3105
|
+
transit_ms: z14.optional(z14.nullable(z14.number())),
|
|
2944
3106
|
// True when this browser had no visitor id and took the origin's.
|
|
2945
|
-
adopted_visitor:
|
|
2946
|
-
page:
|
|
2947
|
-
path:
|
|
3107
|
+
adopted_visitor: z14.boolean(),
|
|
3108
|
+
page: z14.strictObject({
|
|
3109
|
+
path: z14.string()
|
|
2948
3110
|
})
|
|
2949
3111
|
});
|
|
2950
|
-
var siteLinkArrivalConfigSchema =
|
|
3112
|
+
var siteLinkArrivalConfigSchema = z14.strictObject({});
|
|
2951
3113
|
|
|
2952
3114
|
// ../tracking-core/src/events/time-on-site.ts
|
|
2953
|
-
var
|
|
2954
|
-
var timeOnSiteMetadataSchema =
|
|
2955
|
-
duration_ms:
|
|
2956
|
-
page:
|
|
2957
|
-
path:
|
|
3115
|
+
var z15 = __toESM(require("zod/mini"));
|
|
3116
|
+
var timeOnSiteMetadataSchema = z15.strictObject({
|
|
3117
|
+
duration_ms: z15.int().check(z15.nonnegative()),
|
|
3118
|
+
page: z15.strictObject({
|
|
3119
|
+
path: z15.string()
|
|
2958
3120
|
})
|
|
2959
3121
|
});
|
|
2960
|
-
var timeOnSiteConfigSchema =
|
|
2961
|
-
thresholdSeconds:
|
|
3122
|
+
var timeOnSiteConfigSchema = z15.strictObject({
|
|
3123
|
+
thresholdSeconds: z15.int().check(z15.positive())
|
|
2962
3124
|
});
|
|
2963
3125
|
|
|
3126
|
+
// ../tracking-core/src/events/video.ts
|
|
3127
|
+
var z16 = __toESM(require("zod/mini"));
|
|
3128
|
+
|
|
3129
|
+
// ../tracking-core/src/video-ranges.ts
|
|
3130
|
+
var VIDEO_ID_MAX_LENGTH = 64;
|
|
3131
|
+
var VIDEO_ID_PATTERN = /^[A-Za-z0-9_-]+$/;
|
|
3132
|
+
function roundVideoSeconds(value) {
|
|
3133
|
+
if (!Number.isFinite(value) || value < 0) return 0;
|
|
3134
|
+
return Math.round(value * 100) / 100;
|
|
3135
|
+
}
|
|
3136
|
+
function mergeVideoRanges(ranges, epsilonSeconds = 0.25) {
|
|
3137
|
+
const valid2 = ranges.filter((r) => Number.isFinite(r.start_s) && Number.isFinite(r.end_s) && r.end_s > r.start_s).map((r) => ({
|
|
3138
|
+
start_s: roundVideoSeconds(r.start_s),
|
|
3139
|
+
end_s: roundVideoSeconds(r.end_s)
|
|
3140
|
+
})).filter((r) => r.end_s - r.start_s >= 0.05).sort((a, b) => a.start_s - b.start_s || a.end_s - b.end_s);
|
|
3141
|
+
if (valid2.length === 0) return [];
|
|
3142
|
+
const merged = [{ ...valid2[0] }];
|
|
3143
|
+
for (let i = 1; i < valid2.length; i += 1) {
|
|
3144
|
+
const cur = valid2[i];
|
|
3145
|
+
const last = merged[merged.length - 1];
|
|
3146
|
+
if (cur.start_s <= last.end_s + epsilonSeconds) {
|
|
3147
|
+
last.end_s = roundVideoSeconds(Math.max(last.end_s, cur.end_s));
|
|
3148
|
+
} else {
|
|
3149
|
+
merged.push({ ...cur });
|
|
3150
|
+
}
|
|
3151
|
+
}
|
|
3152
|
+
return merged;
|
|
3153
|
+
}
|
|
3154
|
+
function sumVideoRangesSeconds(ranges, durationSeconds = 0) {
|
|
3155
|
+
const merged = mergeVideoRanges(ranges);
|
|
3156
|
+
const raw = merged.reduce((acc, r) => acc + Math.max(0, r.end_s - r.start_s), 0);
|
|
3157
|
+
const clamped = durationSeconds > 0 ? Math.min(raw, durationSeconds) : raw;
|
|
3158
|
+
return roundVideoSeconds(clamped);
|
|
3159
|
+
}
|
|
3160
|
+
|
|
3161
|
+
// ../tracking-core/src/events/video.ts
|
|
3162
|
+
var videoIdSchema = z16.string().check(z16.minLength(1), z16.maxLength(VIDEO_ID_MAX_LENGTH), z16.regex(VIDEO_ID_PATTERN));
|
|
3163
|
+
var videoVariantSchema = z16.enum(["16x9", "9x16"]);
|
|
3164
|
+
var videoProgressTriggerReasonSchema = z16.enum([
|
|
3165
|
+
"checkpoint",
|
|
3166
|
+
"goal",
|
|
3167
|
+
"pause",
|
|
3168
|
+
"seek",
|
|
3169
|
+
"ended",
|
|
3170
|
+
"page_exit"
|
|
3171
|
+
]);
|
|
3172
|
+
var videoRangeSchema = z16.strictObject({
|
|
3173
|
+
start_s: z16.number().check(z16.gte(0)),
|
|
3174
|
+
end_s: z16.number().check(z16.gte(0))
|
|
3175
|
+
});
|
|
3176
|
+
var videoPlayMetadataSchema = z16.strictObject({
|
|
3177
|
+
video_id: videoIdSchema,
|
|
3178
|
+
variant: videoVariantSchema,
|
|
3179
|
+
current_s: z16.number().check(z16.gte(0)),
|
|
3180
|
+
duration_s: z16.number().check(z16.gte(0)),
|
|
3181
|
+
play_sequence: z16.int().check(z16.gte(1)),
|
|
3182
|
+
page: z16.strictObject({
|
|
3183
|
+
path: z16.string()
|
|
3184
|
+
})
|
|
3185
|
+
});
|
|
3186
|
+
var videoPlayConfigSchema = z16.strictObject({});
|
|
3187
|
+
var videoProgressMetadataSchema = z16.strictObject({
|
|
3188
|
+
video_id: videoIdSchema,
|
|
3189
|
+
variant: videoVariantSchema,
|
|
3190
|
+
trigger: videoProgressTriggerReasonSchema,
|
|
3191
|
+
current_s: z16.number().check(z16.gte(0)),
|
|
3192
|
+
furthest_s: z16.number().check(z16.gte(0)),
|
|
3193
|
+
watched_s: z16.number().check(z16.gte(0)),
|
|
3194
|
+
duration_s: z16.number().check(z16.gte(0)),
|
|
3195
|
+
max_percent: z16.int().check(z16.gte(0), z16.lte(100)),
|
|
3196
|
+
watched_percent: z16.int().check(z16.gte(0), z16.lte(100)),
|
|
3197
|
+
play_count: z16.int().check(z16.gte(1)),
|
|
3198
|
+
seek_count: z16.int().check(z16.gte(0)),
|
|
3199
|
+
ranges: z16.array(videoRangeSchema),
|
|
3200
|
+
page: z16.strictObject({
|
|
3201
|
+
path: z16.string()
|
|
3202
|
+
})
|
|
3203
|
+
});
|
|
3204
|
+
var videoProgressConfigSchema = z16.strictObject({});
|
|
3205
|
+
|
|
2964
3206
|
// ../tracking-core/src/events/registry.ts
|
|
2965
3207
|
var EVENT_REGISTRY = {
|
|
2966
3208
|
// --- automatic triggers ---
|
|
@@ -3027,6 +3269,18 @@ var EVENT_REGISTRY = {
|
|
|
3027
3269
|
metadataSchema: siteLinkArrivalMetadataSchema,
|
|
3028
3270
|
configSchema: siteLinkArrivalConfigSchema
|
|
3029
3271
|
},
|
|
3272
|
+
video_play: {
|
|
3273
|
+
kind: "automatic",
|
|
3274
|
+
semantics: EVENT_SEMANTICS.video_play,
|
|
3275
|
+
metadataSchema: videoPlayMetadataSchema,
|
|
3276
|
+
configSchema: videoPlayConfigSchema
|
|
3277
|
+
},
|
|
3278
|
+
video_progress: {
|
|
3279
|
+
kind: "automatic",
|
|
3280
|
+
semantics: EVENT_SEMANTICS.video_progress,
|
|
3281
|
+
metadataSchema: videoProgressMetadataSchema,
|
|
3282
|
+
configSchema: videoProgressConfigSchema
|
|
3283
|
+
},
|
|
3030
3284
|
// --- manual triggers ---
|
|
3031
3285
|
form_submit: {
|
|
3032
3286
|
kind: "manual",
|
|
@@ -3040,6 +3294,12 @@ var EVENT_REGISTRY = {
|
|
|
3040
3294
|
metadataSchema: formStepMetadataSchema,
|
|
3041
3295
|
configSchema: formStepConfigSchema
|
|
3042
3296
|
},
|
|
3297
|
+
form_details: {
|
|
3298
|
+
kind: "manual",
|
|
3299
|
+
semantics: EVENT_SEMANTICS.form_details,
|
|
3300
|
+
metadataSchema: formDetailsMetadataSchema,
|
|
3301
|
+
configSchema: formDetailsConfigSchema
|
|
3302
|
+
},
|
|
3043
3303
|
phone_click: {
|
|
3044
3304
|
kind: "manual",
|
|
3045
3305
|
semantics: EVENT_SEMANTICS.phone_click,
|
|
@@ -3078,6 +3338,7 @@ function salvageFormSubmit(metadata) {
|
|
|
3078
3338
|
...valid("contract_version", form.contract_version),
|
|
3079
3339
|
...valid("contract_hash", form.contract_hash),
|
|
3080
3340
|
...valid("extra", form.extra),
|
|
3341
|
+
...valid("submission_id", form.submission_id),
|
|
3081
3342
|
contract_violations: [...reported, INVALID_SHAPE].slice(-MAX_CONTRACT_VIOLATIONS)
|
|
3082
3343
|
},
|
|
3083
3344
|
page: { path: typeof page.path === "string" ? page.path : currentPath2() }
|
|
@@ -3120,6 +3381,17 @@ function currentPath2() {
|
|
|
3120
3381
|
|
|
3121
3382
|
// ../tracking-core/src/ingest-typed.ts
|
|
3122
3383
|
var clientSettings = /* @__PURE__ */ new WeakMap();
|
|
3384
|
+
var latestTrackingConfig;
|
|
3385
|
+
var latestRawClient = null;
|
|
3386
|
+
function setDefaultTrackingConfig(ref) {
|
|
3387
|
+
if (ref) latestTrackingConfig = ref;
|
|
3388
|
+
}
|
|
3389
|
+
function getActiveTrackingEnv() {
|
|
3390
|
+
return {
|
|
3391
|
+
rawClient: latestRawClient,
|
|
3392
|
+
trackingConfig: latestTrackingConfig
|
|
3393
|
+
};
|
|
3394
|
+
}
|
|
3123
3395
|
function typedClientSettings(client) {
|
|
3124
3396
|
return clientSettings.get(client) ?? {};
|
|
3125
3397
|
}
|
|
@@ -3150,7 +3422,9 @@ function createTypedClient(raw, registry, options = {}) {
|
|
|
3150
3422
|
getSessionId: raw.getSessionId.bind(raw),
|
|
3151
3423
|
getVisitorId: raw.getVisitorId.bind(raw)
|
|
3152
3424
|
};
|
|
3153
|
-
|
|
3425
|
+
latestRawClient = raw;
|
|
3426
|
+
if (options.trackingConfig) latestTrackingConfig = options.trackingConfig;
|
|
3427
|
+
clientSettings.set(client, { ...options, rawClient: raw });
|
|
3154
3428
|
return client;
|
|
3155
3429
|
}
|
|
3156
3430
|
|
|
@@ -3358,7 +3632,7 @@ function attachScrollDepth(client, config) {
|
|
|
3358
3632
|
}
|
|
3359
3633
|
const thresholds = new Set(config.thresholds);
|
|
3360
3634
|
let firedForPath = /* @__PURE__ */ new Set();
|
|
3361
|
-
let
|
|
3635
|
+
let currentPath4 = window.location.pathname;
|
|
3362
3636
|
let rafId = null;
|
|
3363
3637
|
const gate = createBaselineGate();
|
|
3364
3638
|
function checkThresholds() {
|
|
@@ -3374,7 +3648,7 @@ function attachScrollDepth(client, config) {
|
|
|
3374
3648
|
eventType: "scroll_depth",
|
|
3375
3649
|
metadata: {
|
|
3376
3650
|
depth_percent: threshold,
|
|
3377
|
-
page: { path:
|
|
3651
|
+
page: { path: currentPath4 }
|
|
3378
3652
|
},
|
|
3379
3653
|
pageUrl: window.location.href,
|
|
3380
3654
|
occurredAt: null
|
|
@@ -3391,8 +3665,8 @@ function attachScrollDepth(client, config) {
|
|
|
3391
3665
|
}
|
|
3392
3666
|
function resetIfPathChanged() {
|
|
3393
3667
|
const newPath = window.location.pathname;
|
|
3394
|
-
if (newPath ===
|
|
3395
|
-
|
|
3668
|
+
if (newPath === currentPath4) return;
|
|
3669
|
+
currentPath4 = newPath;
|
|
3396
3670
|
firedForPath = /* @__PURE__ */ new Set();
|
|
3397
3671
|
gate.rebaseline();
|
|
3398
3672
|
}
|
|
@@ -3455,13 +3729,13 @@ function attachMultiPageSession(client, config) {
|
|
|
3455
3729
|
return storage.getItem(FIRED_KEY) === "1";
|
|
3456
3730
|
}
|
|
3457
3731
|
function check2() {
|
|
3458
|
-
const
|
|
3459
|
-
if (
|
|
3460
|
-
lastCheckedPath =
|
|
3732
|
+
const currentPath4 = window.location.pathname;
|
|
3733
|
+
if (currentPath4 === lastCheckedPath) return;
|
|
3734
|
+
lastCheckedPath = currentPath4;
|
|
3461
3735
|
resetIfSessionChanged();
|
|
3462
3736
|
if (hasFired()) return;
|
|
3463
3737
|
const paths = getDistinctPaths();
|
|
3464
|
-
paths.add(
|
|
3738
|
+
paths.add(currentPath4);
|
|
3465
3739
|
saveDistinctPaths(paths);
|
|
3466
3740
|
if (paths.size >= pageThreshold) {
|
|
3467
3741
|
storage.setItem(FIRED_KEY, "1");
|
|
@@ -3506,7 +3780,7 @@ function attachFormStart(client, config) {
|
|
|
3506
3780
|
}
|
|
3507
3781
|
const selector = config.selector ?? "form";
|
|
3508
3782
|
let firedForms = /* @__PURE__ */ new Set();
|
|
3509
|
-
let
|
|
3783
|
+
let currentPath4 = window.location.pathname;
|
|
3510
3784
|
let pendingTap = null;
|
|
3511
3785
|
function getFormKey(form) {
|
|
3512
3786
|
if (form.id) return `id:${form.id}`;
|
|
@@ -3557,8 +3831,8 @@ function attachFormStart(client, config) {
|
|
|
3557
3831
|
}
|
|
3558
3832
|
function resetIfPathChanged() {
|
|
3559
3833
|
const newPath = window.location.pathname;
|
|
3560
|
-
if (newPath ===
|
|
3561
|
-
|
|
3834
|
+
if (newPath === currentPath4) return;
|
|
3835
|
+
currentPath4 = newPath;
|
|
3562
3836
|
firedForms = /* @__PURE__ */ new Set();
|
|
3563
3837
|
}
|
|
3564
3838
|
const originalPushState = history.pushState.bind(history);
|
|
@@ -3599,7 +3873,7 @@ function attachPageExit(client) {
|
|
|
3599
3873
|
return () => {
|
|
3600
3874
|
};
|
|
3601
3875
|
}
|
|
3602
|
-
let
|
|
3876
|
+
let currentPath4 = window.location.pathname;
|
|
3603
3877
|
let activeSince = document.visibilityState === "visible" ? Date.now() : null;
|
|
3604
3878
|
let accumulatedMs = 0;
|
|
3605
3879
|
let maxScrollPercent = null;
|
|
@@ -3649,9 +3923,9 @@ function attachPageExit(client) {
|
|
|
3649
3923
|
}
|
|
3650
3924
|
function onNavigate() {
|
|
3651
3925
|
const newPath = window.location.pathname;
|
|
3652
|
-
if (newPath ===
|
|
3653
|
-
emitSegment(
|
|
3654
|
-
|
|
3926
|
+
if (newPath === currentPath4) return;
|
|
3927
|
+
emitSegment(currentPath4, false);
|
|
3928
|
+
currentPath4 = newPath;
|
|
3655
3929
|
maxScrollPercent = null;
|
|
3656
3930
|
gate.rebaseline();
|
|
3657
3931
|
accumulatedMs = 0;
|
|
@@ -3659,15 +3933,18 @@ function attachPageExit(client) {
|
|
|
3659
3933
|
}
|
|
3660
3934
|
function onVisibilityChange() {
|
|
3661
3935
|
if (document.visibilityState === "hidden") {
|
|
3662
|
-
emitSegment(
|
|
3936
|
+
emitSegment(currentPath4, true);
|
|
3663
3937
|
} else {
|
|
3664
3938
|
activeSince = Date.now();
|
|
3665
3939
|
}
|
|
3666
3940
|
}
|
|
3667
3941
|
function onPageHide() {
|
|
3668
|
-
emitSegment(
|
|
3942
|
+
emitSegment(currentPath4, true);
|
|
3669
3943
|
}
|
|
3670
3944
|
const unsubscribeNav = onHistoryChange(onNavigate);
|
|
3945
|
+
const unsubscribeBeforeUnload = client.onBeforeUnload?.(() => {
|
|
3946
|
+
emitSegment(currentPath4, false);
|
|
3947
|
+
});
|
|
3671
3948
|
window.addEventListener("scroll", onScroll, { passive: true });
|
|
3672
3949
|
document.addEventListener("visibilitychange", onVisibilityChange);
|
|
3673
3950
|
window.addEventListener("pagehide", onPageHide);
|
|
@@ -3676,6 +3953,7 @@ function attachPageExit(client) {
|
|
|
3676
3953
|
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
3677
3954
|
gate.cancel();
|
|
3678
3955
|
unsubscribeNav();
|
|
3956
|
+
unsubscribeBeforeUnload?.();
|
|
3679
3957
|
window.removeEventListener("scroll", onScroll);
|
|
3680
3958
|
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
3681
3959
|
window.removeEventListener("pagehide", onPageHide);
|
|
@@ -3845,7 +4123,7 @@ function attachPhoneClickCapture(client, config) {
|
|
|
3845
4123
|
}
|
|
3846
4124
|
|
|
3847
4125
|
// ../tracking-core/src/lead-forms/lead-forms.gen.ts
|
|
3848
|
-
var
|
|
4126
|
+
var z17 = __toESM(require("zod/mini"));
|
|
3849
4127
|
var LEAD_FORM_REGISTRY_VERSION = 2;
|
|
3850
4128
|
var LEAD_FORM_ROLES = [
|
|
3851
4129
|
"given_name",
|
|
@@ -3871,28 +4149,28 @@ var LEAD_FORM_ROLES = [
|
|
|
3871
4149
|
"attribution"
|
|
3872
4150
|
];
|
|
3873
4151
|
var leadFormPrimitiveSchemas = /* @__PURE__ */ (() => ({
|
|
3874
|
-
string:
|
|
3875
|
-
text:
|
|
3876
|
-
enum:
|
|
3877
|
-
multi_enum:
|
|
3878
|
-
bool:
|
|
3879
|
-
date:
|
|
3880
|
-
time_window:
|
|
3881
|
-
start:
|
|
3882
|
-
end:
|
|
3883
|
-
label:
|
|
4152
|
+
string: z17.string().check(z17.maxLength(120)),
|
|
4153
|
+
text: z17.string().check(z17.maxLength(2e3)),
|
|
4154
|
+
enum: z17.string().check(z17.regex(/^[a-z0-9-]{1,48}$/)),
|
|
4155
|
+
multi_enum: z17.array(z17.string().check(z17.regex(/^[a-z0-9-]{1,48}$/))).check(z17.maxLength(10)),
|
|
4156
|
+
bool: z17.boolean(),
|
|
4157
|
+
date: z17.string().check(z17.regex(/^\d{4}-\d{2}-\d{2}$/)),
|
|
4158
|
+
time_window: z17.strictObject({
|
|
4159
|
+
start: z17.string().check(z17.regex(/^([01]\d|2[0-3]):[0-5]\d$/)),
|
|
4160
|
+
end: z17.nullable(z17.string().check(z17.regex(/^([01]\d|2[0-3]):[0-5]\d$/))),
|
|
4161
|
+
label: z17.optional(z17.string().check(z17.maxLength(60)))
|
|
3884
4162
|
}),
|
|
3885
|
-
phone:
|
|
3886
|
-
email:
|
|
3887
|
-
address:
|
|
3888
|
-
line1:
|
|
3889
|
-
line2:
|
|
3890
|
-
city:
|
|
3891
|
-
region:
|
|
3892
|
-
postal_code:
|
|
3893
|
-
country:
|
|
4163
|
+
phone: z17.string().check(z17.regex(/^\+[1-9]\d{6,14}$/)),
|
|
4164
|
+
email: z17.string().check(z17.maxLength(320), z17.regex(/^[^\s@]+@[^\s@]+$/)),
|
|
4165
|
+
address: z17.strictObject({
|
|
4166
|
+
line1: z17.string().check(z17.maxLength(120)),
|
|
4167
|
+
line2: z17.optional(z17.string().check(z17.maxLength(120))),
|
|
4168
|
+
city: z17.optional(z17.string().check(z17.maxLength(120))),
|
|
4169
|
+
region: z17.optional(z17.string().check(z17.maxLength(120))),
|
|
4170
|
+
postal_code: z17.optional(z17.string().check(z17.maxLength(120))),
|
|
4171
|
+
country: z17.optional(z17.string().check(z17.maxLength(120)))
|
|
3894
4172
|
}),
|
|
3895
|
-
number:
|
|
4173
|
+
number: z17.number()
|
|
3896
4174
|
}))();
|
|
3897
4175
|
var LEAD_FORM_ROLE_SPECS = {
|
|
3898
4176
|
given_name: { primitive: "string", smsLabel: "", contactIdentity: true },
|
|
@@ -3974,34 +4252,70 @@ function createLeadFormSubmit(tracking, contracts, options = {}) {
|
|
|
3974
4252
|
contracts,
|
|
3975
4253
|
settings
|
|
3976
4254
|
);
|
|
4255
|
+
const submission = { submissionId: uuidV4(), formId: input.formId, kind: input.kind };
|
|
3977
4256
|
const metadata = {
|
|
3978
4257
|
form: {
|
|
3979
4258
|
id: input.formId,
|
|
3980
4259
|
action: input.action ?? null,
|
|
3981
|
-
fields: fields.map(
|
|
3982
|
-
name: role,
|
|
3983
|
-
type: INPUT_TYPES[primitiveOf(role) ?? "string"],
|
|
3984
|
-
label: labelOf(role),
|
|
3985
|
-
value,
|
|
3986
|
-
role
|
|
3987
|
-
})),
|
|
4260
|
+
fields: fields.map(fieldEntry),
|
|
3988
4261
|
kind: input.kind,
|
|
3989
4262
|
contract_version: LEAD_FORM_REGISTRY_VERSION,
|
|
3990
4263
|
...hash ? { contract_hash: hash } : {},
|
|
3991
4264
|
...input.extra?.length ? { extra: input.extra } : {},
|
|
3992
|
-
...violations.length > 0 ? { contract_violations: violations.slice(0, MAX_CONTRACT_VIOLATIONS) } : {}
|
|
4265
|
+
...violations.length > 0 ? { contract_violations: violations.slice(0, MAX_CONTRACT_VIOLATIONS) } : {},
|
|
4266
|
+
submission_id: submission.submissionId
|
|
3993
4267
|
},
|
|
3994
|
-
page: { path:
|
|
4268
|
+
page: { path: currentPath3() }
|
|
3995
4269
|
};
|
|
3996
4270
|
tracking.trackEvent("form_submit", metadata);
|
|
3997
|
-
return metadata;
|
|
4271
|
+
return { ...metadata, submission };
|
|
4272
|
+
},
|
|
4273
|
+
addDetails(submission, input) {
|
|
4274
|
+
const fields = presentFields(input.fields);
|
|
4275
|
+
const extra = (input.extra ?? []).filter((item) => !isBlank(item.value));
|
|
4276
|
+
if (fields.length === 0 && extra.length === 0) return { sent: false, reason: "no_fields" };
|
|
4277
|
+
const { violations, hash } = judgeLeadForm(
|
|
4278
|
+
submission.kind,
|
|
4279
|
+
submission.formId,
|
|
4280
|
+
fields,
|
|
4281
|
+
contracts,
|
|
4282
|
+
settings,
|
|
4283
|
+
{ partial: true }
|
|
4284
|
+
);
|
|
4285
|
+
const metadata = {
|
|
4286
|
+
form: {
|
|
4287
|
+
id: submission.formId,
|
|
4288
|
+
submission_id: submission.submissionId,
|
|
4289
|
+
kind: submission.kind,
|
|
4290
|
+
fields: fields.map(fieldEntry),
|
|
4291
|
+
contract_version: LEAD_FORM_REGISTRY_VERSION,
|
|
4292
|
+
...hash ? { contract_hash: hash } : {},
|
|
4293
|
+
...extra.length > 0 ? { extra } : {},
|
|
4294
|
+
...violations.length > 0 ? { contract_violations: violations.slice(0, MAX_CONTRACT_VIOLATIONS) } : {}
|
|
4295
|
+
},
|
|
4296
|
+
page: { path: currentPath3() }
|
|
4297
|
+
};
|
|
4298
|
+
tracking.trackEvent("form_details", metadata);
|
|
4299
|
+
return { sent: true };
|
|
3998
4300
|
}
|
|
3999
4301
|
};
|
|
4000
4302
|
}
|
|
4001
|
-
function
|
|
4303
|
+
function fieldEntry([role, value]) {
|
|
4304
|
+
return {
|
|
4305
|
+
name: role,
|
|
4306
|
+
type: INPUT_TYPES[primitiveOf(role) ?? "string"],
|
|
4307
|
+
label: labelOf(role),
|
|
4308
|
+
value,
|
|
4309
|
+
role
|
|
4310
|
+
};
|
|
4311
|
+
}
|
|
4312
|
+
function currentPath3() {
|
|
4313
|
+
return typeof window === "undefined" ? "/" : window.location.pathname;
|
|
4314
|
+
}
|
|
4315
|
+
function judgeLeadForm(kind, formId, fields, contracts, settings, { partial = false } = {}) {
|
|
4002
4316
|
const generated = contracts?.contracts[kind];
|
|
4003
4317
|
const live = liveContract(settings.trackingConfig, kind);
|
|
4004
|
-
const violations = check(live === void 0 ? generated : fromLive(live), fields);
|
|
4318
|
+
const violations = check(live === void 0 ? generated : fromLive(live), fields, partial);
|
|
4005
4319
|
const liveHash = live === void 0 ? void 0 : live?.contract_hash ?? null;
|
|
4006
4320
|
if (contracts && (liveHash !== void 0 && (generated?.hash ?? null) !== liveHash || contracts.registryVersion !== LEAD_FORM_REGISTRY_VERSION)) {
|
|
4007
4321
|
violations.push({ role: null, rule: "contract_behind" });
|
|
@@ -4047,7 +4361,7 @@ function normalize(role, value) {
|
|
|
4047
4361
|
function isBlank(value) {
|
|
4048
4362
|
return value === void 0 || value === null || typeof value === "string" && value.trim() === "" || Array.isArray(value) && value.length === 0;
|
|
4049
4363
|
}
|
|
4050
|
-
function check(contract, fields) {
|
|
4364
|
+
function check(contract, fields, partial) {
|
|
4051
4365
|
const answered = new Map(fields);
|
|
4052
4366
|
const violations = [];
|
|
4053
4367
|
for (const [role, value] of fields) {
|
|
@@ -4065,6 +4379,7 @@ function check(contract, fields) {
|
|
|
4065
4379
|
violations.push({ role, rule: "unknown_option" });
|
|
4066
4380
|
}
|
|
4067
4381
|
}
|
|
4382
|
+
if (partial) return violations;
|
|
4068
4383
|
for (const { role, requiredWhen } of contract?.requires ?? []) {
|
|
4069
4384
|
const owing = requiredWhen === null || optionKeys(answered.get(requiredWhen.role)).some((key) => requiredWhen.anyOf.includes(key));
|
|
4070
4385
|
if (owing && !answered.has(role)) violations.push({ role, rule: "missing_required" });
|
|
@@ -4427,7 +4742,7 @@ function GoogleAdsTracking(props) {
|
|
|
4427
4742
|
var import_react6 = require("react");
|
|
4428
4743
|
|
|
4429
4744
|
// package.json
|
|
4430
|
-
var version = "1.
|
|
4745
|
+
var version = "1.19.0";
|
|
4431
4746
|
|
|
4432
4747
|
// ../tracking-core/src/phone-react.tsx
|
|
4433
4748
|
var import_react5 = require("react");
|
|
@@ -4538,6 +4853,7 @@ function createTracking(options) {
|
|
|
4538
4853
|
trackingConfig
|
|
4539
4854
|
} = options;
|
|
4540
4855
|
registerCapability("base_tracking");
|
|
4856
|
+
setDefaultTrackingConfig(trackingConfig);
|
|
4541
4857
|
if (trackingConfig) registerCapability("conversion_goals_auto");
|
|
4542
4858
|
if (!apiKey || !endpoint) {
|
|
4543
4859
|
if (apiKey || endpoint) {
|
|
@@ -4805,15 +5121,1422 @@ function useBookingSubmit(bookings, options = {}) {
|
|
|
4805
5121
|
const status = submitting ? "submitting" : outcome?.status ?? "idle";
|
|
4806
5122
|
return { status, outcome, booked, submit, updateBooking, reset };
|
|
4807
5123
|
}
|
|
5124
|
+
|
|
5125
|
+
// ../tracking-core/src/video-react.tsx
|
|
5126
|
+
var import_react8 = require("react");
|
|
5127
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
5128
|
+
var DEFAULT_VIDEO_CHECKPOINTS = [25, 50, 75, 90, 100];
|
|
5129
|
+
var streamManifestUrl = (host, uid) => `https://${host}/${uid}/manifest/video.m3u8`;
|
|
5130
|
+
var streamPosterUrl = (host, uid, time = 4) => `https://${host}/${uid}/thumbnails/thumbnail.jpg?time=${time}s`;
|
|
5131
|
+
var TV_SKIN_STYLE_ATTR = "data-aranova-tv-skin";
|
|
5132
|
+
var TV_SKIN_CSS = `
|
|
5133
|
+
.tv-skin {
|
|
5134
|
+
container-type: inline-size;
|
|
5135
|
+
position: relative;
|
|
5136
|
+
overflow: hidden;
|
|
5137
|
+
border-radius: 18px;
|
|
5138
|
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
|
5139
|
+
background: #0a0e1a;
|
|
5140
|
+
box-shadow: 0 18px 48px rgba(0, 0, 0, 0.32);
|
|
5141
|
+
}
|
|
5142
|
+
.tv-skin-desktop {
|
|
5143
|
+
display: none;
|
|
5144
|
+
aspect-ratio: 16 / 9;
|
|
5145
|
+
width: 100%;
|
|
5146
|
+
}
|
|
5147
|
+
.tv-skin-mobile {
|
|
5148
|
+
display: block;
|
|
5149
|
+
margin-left: auto;
|
|
5150
|
+
margin-right: auto;
|
|
5151
|
+
aspect-ratio: 9 / 16;
|
|
5152
|
+
width: 100%;
|
|
5153
|
+
max-width: 420px;
|
|
5154
|
+
}
|
|
5155
|
+
@media (min-width: 768px) {
|
|
5156
|
+
.tv-skin-desktop {
|
|
5157
|
+
display: block;
|
|
5158
|
+
}
|
|
5159
|
+
.tv-skin-mobile {
|
|
5160
|
+
display: none;
|
|
5161
|
+
}
|
|
5162
|
+
}
|
|
5163
|
+
.tv-skin media-controller {
|
|
5164
|
+
display: block;
|
|
5165
|
+
width: 100%;
|
|
5166
|
+
height: 100%;
|
|
5167
|
+
background: #000;
|
|
5168
|
+
--media-primary-color: #ffffff;
|
|
5169
|
+
--media-text-color: rgba(255, 255, 255, 0.82);
|
|
5170
|
+
--media-icon-color: #ffffff;
|
|
5171
|
+
--media-secondary-color: transparent;
|
|
5172
|
+
--media-control-background: transparent;
|
|
5173
|
+
--media-control-hover-background: transparent;
|
|
5174
|
+
--media-control-padding: 0;
|
|
5175
|
+
--media-control-height: 40px;
|
|
5176
|
+
--media-tooltip-display: none;
|
|
5177
|
+
--media-font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
|
|
5178
|
+
--media-font-size: 11.5px;
|
|
5179
|
+
--media-focus-box-shadow: 0 0 0 2px #74a0ff;
|
|
5180
|
+
--media-button-icon-width: 20px;
|
|
5181
|
+
--media-button-icon-height: 20px;
|
|
5182
|
+
--media-range-padding: 0;
|
|
5183
|
+
--media-range-bar-color: #ffffff;
|
|
5184
|
+
--media-range-track-background: rgba(255, 255, 255, 0.25);
|
|
5185
|
+
--media-range-track-border-radius: 3px;
|
|
5186
|
+
--media-time-range-buffered-color: transparent;
|
|
5187
|
+
--media-time-range-hover-display: none;
|
|
5188
|
+
--media-preview-time-background: transparent;
|
|
5189
|
+
--media-range-thumb-background: #ffffff;
|
|
5190
|
+
--media-range-thumb-width: 12px;
|
|
5191
|
+
--media-range-thumb-height: 12px;
|
|
5192
|
+
--media-range-thumb-opacity: 0;
|
|
5193
|
+
}
|
|
5194
|
+
.tv-skin media-controller::part(vertical-layer),
|
|
5195
|
+
.tv-skin media-controller::part(centered-layer) {
|
|
5196
|
+
background: transparent;
|
|
5197
|
+
}
|
|
5198
|
+
.tv-chrome {
|
|
5199
|
+
position: absolute;
|
|
5200
|
+
inset: auto 0 0 0;
|
|
5201
|
+
padding-top: 56px;
|
|
5202
|
+
background: linear-gradient(to top, rgba(0, 0, 0, 0.62), rgba(0, 0, 0, 0));
|
|
5203
|
+
transition: opacity 0.25s ease;
|
|
5204
|
+
}
|
|
5205
|
+
.tv-skin media-controller[userinactive]:not([mediapaused]) .tv-chrome {
|
|
5206
|
+
opacity: 0;
|
|
5207
|
+
pointer-events: none;
|
|
5208
|
+
}
|
|
5209
|
+
.tv-row {
|
|
5210
|
+
display: flex;
|
|
5211
|
+
align-items: center;
|
|
5212
|
+
gap: 2px;
|
|
5213
|
+
padding: 0 4px;
|
|
5214
|
+
}
|
|
5215
|
+
.tv-spacer {
|
|
5216
|
+
flex: 1 1 auto;
|
|
5217
|
+
}
|
|
5218
|
+
.tv-ctl,
|
|
5219
|
+
.tv-btn {
|
|
5220
|
+
display: inline-flex;
|
|
5221
|
+
align-items: center;
|
|
5222
|
+
justify-content: center;
|
|
5223
|
+
width: 40px;
|
|
5224
|
+
height: 40px;
|
|
5225
|
+
padding: 0;
|
|
5226
|
+
border: 0;
|
|
5227
|
+
border-radius: 0;
|
|
5228
|
+
background: transparent;
|
|
5229
|
+
box-shadow: none;
|
|
5230
|
+
color: rgba(255, 255, 255, 0.92);
|
|
5231
|
+
cursor: pointer;
|
|
5232
|
+
transition: color 0.15s;
|
|
5233
|
+
}
|
|
5234
|
+
.tv-ctl:hover,
|
|
5235
|
+
.tv-btn:hover {
|
|
5236
|
+
background: transparent;
|
|
5237
|
+
color: #ffffff;
|
|
5238
|
+
}
|
|
5239
|
+
.tv-ctl:focus-visible,
|
|
5240
|
+
.tv-btn:focus-visible,
|
|
5241
|
+
.tv-menu-item:focus-visible {
|
|
5242
|
+
outline: 2px solid #74a0ff;
|
|
5243
|
+
outline-offset: -4px;
|
|
5244
|
+
box-shadow: none;
|
|
5245
|
+
}
|
|
5246
|
+
.tv-time {
|
|
5247
|
+
width: auto;
|
|
5248
|
+
padding: 0 4px 0 6px;
|
|
5249
|
+
background: transparent;
|
|
5250
|
+
letter-spacing: 0.02em;
|
|
5251
|
+
white-space: nowrap;
|
|
5252
|
+
--media-control-background: transparent;
|
|
5253
|
+
}
|
|
5254
|
+
.tv-time-cur {
|
|
5255
|
+
display: none;
|
|
5256
|
+
}
|
|
5257
|
+
.tv-seek {
|
|
5258
|
+
display: block;
|
|
5259
|
+
width: 100%;
|
|
5260
|
+
height: 16px;
|
|
5261
|
+
margin: 0;
|
|
5262
|
+
padding: 0;
|
|
5263
|
+
background: transparent;
|
|
5264
|
+
box-shadow: none;
|
|
5265
|
+
border: 0;
|
|
5266
|
+
--media-range-track-height: 3px;
|
|
5267
|
+
--media-control-background: transparent;
|
|
5268
|
+
--media-control-hover-background: transparent;
|
|
5269
|
+
}
|
|
5270
|
+
.tv-seek:hover,
|
|
5271
|
+
.tv-seek:focus-visible {
|
|
5272
|
+
--media-range-track-height: 6px;
|
|
5273
|
+
--media-range-thumb-opacity: 1;
|
|
5274
|
+
}
|
|
5275
|
+
.tv-vol {
|
|
5276
|
+
display: flex;
|
|
5277
|
+
align-items: center;
|
|
5278
|
+
}
|
|
5279
|
+
.tv-volrange {
|
|
5280
|
+
width: 64px;
|
|
5281
|
+
height: 40px;
|
|
5282
|
+
margin-right: 4px;
|
|
5283
|
+
padding: 0;
|
|
5284
|
+
opacity: 0;
|
|
5285
|
+
pointer-events: none;
|
|
5286
|
+
transform: scaleX(0.75);
|
|
5287
|
+
transform-origin: right center;
|
|
5288
|
+
background: transparent;
|
|
5289
|
+
transition: transform 0.2s ease, opacity 0.2s ease;
|
|
5290
|
+
--media-control-background: transparent;
|
|
5291
|
+
--media-range-track-height: 3px;
|
|
5292
|
+
}
|
|
5293
|
+
.tv-vol:hover .tv-volrange,
|
|
5294
|
+
.tv-vol:focus-within .tv-volrange {
|
|
5295
|
+
opacity: 1;
|
|
5296
|
+
pointer-events: auto;
|
|
5297
|
+
transform: scaleX(1);
|
|
5298
|
+
}
|
|
5299
|
+
@media (hover: none) {
|
|
5300
|
+
.tv-volrange {
|
|
5301
|
+
display: none;
|
|
5302
|
+
}
|
|
5303
|
+
}
|
|
5304
|
+
@container (max-width: 479px) {
|
|
5305
|
+
.tv-vol,
|
|
5306
|
+
.tv-time-full {
|
|
5307
|
+
display: none;
|
|
5308
|
+
}
|
|
5309
|
+
.tv-time-cur {
|
|
5310
|
+
display: inline-flex;
|
|
5311
|
+
}
|
|
5312
|
+
}
|
|
5313
|
+
@container (max-width: 767px) {
|
|
5314
|
+
.tv-theater {
|
|
5315
|
+
display: none;
|
|
5316
|
+
}
|
|
5317
|
+
}
|
|
5318
|
+
.tv-menu-wrap {
|
|
5319
|
+
position: relative;
|
|
5320
|
+
display: flex;
|
|
5321
|
+
align-items: center;
|
|
5322
|
+
}
|
|
5323
|
+
.tv-menu {
|
|
5324
|
+
position: absolute;
|
|
5325
|
+
right: 0;
|
|
5326
|
+
bottom: calc(100% + 8px);
|
|
5327
|
+
z-index: 5;
|
|
5328
|
+
width: 136px;
|
|
5329
|
+
max-height: 232px;
|
|
5330
|
+
margin: 0;
|
|
5331
|
+
padding: 4px 0;
|
|
5332
|
+
overflow-y: auto;
|
|
5333
|
+
list-style: none;
|
|
5334
|
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
5335
|
+
border-radius: 10px;
|
|
5336
|
+
background: linear-gradient(rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0.12)), rgba(10, 14, 26, 0.55);
|
|
5337
|
+
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12), 0 12px 32px rgba(0, 0, 0, 0.35);
|
|
5338
|
+
}
|
|
5339
|
+
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
|
|
5340
|
+
.tv-menu {
|
|
5341
|
+
-webkit-backdrop-filter: blur(16px) saturate(140%);
|
|
5342
|
+
backdrop-filter: blur(16px) saturate(140%);
|
|
5343
|
+
}
|
|
5344
|
+
}
|
|
5345
|
+
.tv-menu-item {
|
|
5346
|
+
position: relative;
|
|
5347
|
+
display: flex;
|
|
5348
|
+
width: 100%;
|
|
5349
|
+
height: 32px;
|
|
5350
|
+
align-items: center;
|
|
5351
|
+
padding: 0 12px 0 24px;
|
|
5352
|
+
border: 0;
|
|
5353
|
+
background: transparent;
|
|
5354
|
+
color: rgba(255, 255, 255, 0.75);
|
|
5355
|
+
font-family: var(--font-sans, system-ui, -apple-system, sans-serif);
|
|
5356
|
+
font-size: 13px;
|
|
5357
|
+
font-weight: 500;
|
|
5358
|
+
text-align: left;
|
|
5359
|
+
cursor: pointer;
|
|
5360
|
+
}
|
|
5361
|
+
.tv-menu-item:hover,
|
|
5362
|
+
.tv-menu-item:focus-visible {
|
|
5363
|
+
background: rgba(255, 255, 255, 0.1);
|
|
5364
|
+
color: #ffffff;
|
|
5365
|
+
outline: none;
|
|
5366
|
+
}
|
|
5367
|
+
.tv-menu-item[aria-checked='true'] {
|
|
5368
|
+
color: #ffffff;
|
|
5369
|
+
font-weight: 600;
|
|
5370
|
+
}
|
|
5371
|
+
.tv-menu-item[aria-checked='true']::before {
|
|
5372
|
+
content: '';
|
|
5373
|
+
position: absolute;
|
|
5374
|
+
left: 12px;
|
|
5375
|
+
width: 5px;
|
|
5376
|
+
height: 5px;
|
|
5377
|
+
border-radius: 50%;
|
|
5378
|
+
background: #ffffff;
|
|
5379
|
+
}
|
|
5380
|
+
.tv-menu-sub {
|
|
5381
|
+
margin-left: 4px;
|
|
5382
|
+
font-size: 11.5px;
|
|
5383
|
+
font-weight: 400;
|
|
5384
|
+
color: rgba(255, 255, 255, 0.55);
|
|
5385
|
+
}
|
|
5386
|
+
.tv-menu-note {
|
|
5387
|
+
height: 20px;
|
|
5388
|
+
padding: 0 12px 0 24px;
|
|
5389
|
+
color: rgba(255, 255, 255, 0.55);
|
|
5390
|
+
font-family: var(--font-sans, system-ui, -apple-system, sans-serif);
|
|
5391
|
+
font-size: 11.5px;
|
|
5392
|
+
line-height: 20px;
|
|
5393
|
+
}
|
|
5394
|
+
.tv-poster-overlay {
|
|
5395
|
+
position: absolute;
|
|
5396
|
+
inset: 0;
|
|
5397
|
+
}
|
|
5398
|
+
.tv-poster-img {
|
|
5399
|
+
width: 100%;
|
|
5400
|
+
height: 100%;
|
|
5401
|
+
object-fit: cover;
|
|
5402
|
+
display: block;
|
|
5403
|
+
}
|
|
5404
|
+
.tv-play-trigger {
|
|
5405
|
+
position: absolute;
|
|
5406
|
+
inset: 0;
|
|
5407
|
+
width: 100%;
|
|
5408
|
+
height: 100%;
|
|
5409
|
+
border: 0;
|
|
5410
|
+
padding: 0;
|
|
5411
|
+
background: transparent;
|
|
5412
|
+
cursor: pointer;
|
|
5413
|
+
display: flex;
|
|
5414
|
+
align-items: center;
|
|
5415
|
+
justify-content: center;
|
|
5416
|
+
transition: filter 0.2s ease;
|
|
5417
|
+
}
|
|
5418
|
+
.tv-play-trigger:hover {
|
|
5419
|
+
filter: brightness(1.1);
|
|
5420
|
+
}
|
|
5421
|
+
.tv-play-trigger:focus-visible {
|
|
5422
|
+
outline: 2px solid #74a0ff;
|
|
5423
|
+
outline-offset: -4px;
|
|
5424
|
+
}
|
|
5425
|
+
.tv-play-pill {
|
|
5426
|
+
display: flex;
|
|
5427
|
+
width: 64px;
|
|
5428
|
+
height: 64px;
|
|
5429
|
+
align-items: center;
|
|
5430
|
+
justify-content: center;
|
|
5431
|
+
border-radius: 9999px;
|
|
5432
|
+
border: 2px solid rgba(255, 255, 255, 0.72);
|
|
5433
|
+
background: rgba(255, 255, 255, 0.15);
|
|
5434
|
+
color: #ffffff;
|
|
5435
|
+
backdrop-filter: blur(2px);
|
|
5436
|
+
-webkit-backdrop-filter: blur(2px);
|
|
5437
|
+
transition: transform 0.3s ease;
|
|
5438
|
+
}
|
|
5439
|
+
.tv-play-trigger:hover .tv-play-pill {
|
|
5440
|
+
transform: scale(1.05);
|
|
5441
|
+
}
|
|
5442
|
+
`;
|
|
5443
|
+
function ensureTvSkinStyles() {
|
|
5444
|
+
if (typeof document === "undefined") return;
|
|
5445
|
+
if (document.querySelector(`style[${TV_SKIN_STYLE_ATTR}]`)) return;
|
|
5446
|
+
const style = document.createElement("style");
|
|
5447
|
+
style.setAttribute(TV_SKIN_STYLE_ATTR, "1");
|
|
5448
|
+
style.textContent = TV_SKIN_CSS;
|
|
5449
|
+
document.head.append(style);
|
|
5450
|
+
}
|
|
5451
|
+
function IconPlay({
|
|
5452
|
+
slot,
|
|
5453
|
+
size = 20,
|
|
5454
|
+
filled = false
|
|
5455
|
+
}) {
|
|
5456
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
5457
|
+
"svg",
|
|
5458
|
+
{
|
|
5459
|
+
slot,
|
|
5460
|
+
width: size,
|
|
5461
|
+
height: size,
|
|
5462
|
+
viewBox: "0 0 24 24",
|
|
5463
|
+
fill: filled ? "currentColor" : "none",
|
|
5464
|
+
stroke: "currentColor",
|
|
5465
|
+
strokeWidth: filled ? 0 : 1.75,
|
|
5466
|
+
strokeLinecap: "round",
|
|
5467
|
+
strokeLinejoin: "round",
|
|
5468
|
+
"aria-hidden": "true",
|
|
5469
|
+
style: filled ? { marginLeft: 3 } : void 0,
|
|
5470
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("polygon", { points: "6 3 20 12 6 21 6 3" })
|
|
5471
|
+
}
|
|
5472
|
+
);
|
|
5473
|
+
}
|
|
5474
|
+
function IconPause({ slot }) {
|
|
5475
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
5476
|
+
"svg",
|
|
5477
|
+
{
|
|
5478
|
+
slot,
|
|
5479
|
+
width: 20,
|
|
5480
|
+
height: 20,
|
|
5481
|
+
viewBox: "0 0 24 24",
|
|
5482
|
+
fill: "none",
|
|
5483
|
+
stroke: "currentColor",
|
|
5484
|
+
strokeWidth: 1.75,
|
|
5485
|
+
strokeLinecap: "round",
|
|
5486
|
+
strokeLinejoin: "round",
|
|
5487
|
+
"aria-hidden": "true",
|
|
5488
|
+
children: [
|
|
5489
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("rect", { x: "14", y: "4", width: "4", height: "16", rx: "1" }),
|
|
5490
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("rect", { x: "6", y: "4", width: "4", height: "16", rx: "1" })
|
|
5491
|
+
]
|
|
5492
|
+
}
|
|
5493
|
+
);
|
|
5494
|
+
}
|
|
5495
|
+
function IconVolumeHigh({ slot }) {
|
|
5496
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
5497
|
+
"svg",
|
|
5498
|
+
{
|
|
5499
|
+
slot,
|
|
5500
|
+
width: 20,
|
|
5501
|
+
height: 20,
|
|
5502
|
+
viewBox: "0 0 24 24",
|
|
5503
|
+
fill: "none",
|
|
5504
|
+
stroke: "currentColor",
|
|
5505
|
+
strokeWidth: 1.75,
|
|
5506
|
+
strokeLinecap: "round",
|
|
5507
|
+
strokeLinejoin: "round",
|
|
5508
|
+
"aria-hidden": "true",
|
|
5509
|
+
children: [
|
|
5510
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("polygon", { points: "11 5 6 9 2 9 2 15 6 15 11 19 11 5" }),
|
|
5511
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M15.54 8.46a5 5 0 0 1 0 7.07" }),
|
|
5512
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M19.07 4.93a10 10 0 0 1 0 14.14" })
|
|
5513
|
+
]
|
|
5514
|
+
}
|
|
5515
|
+
);
|
|
5516
|
+
}
|
|
5517
|
+
function IconVolumeLow({ slot }) {
|
|
5518
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
5519
|
+
"svg",
|
|
5520
|
+
{
|
|
5521
|
+
slot,
|
|
5522
|
+
width: 20,
|
|
5523
|
+
height: 20,
|
|
5524
|
+
viewBox: "0 0 24 24",
|
|
5525
|
+
fill: "none",
|
|
5526
|
+
stroke: "currentColor",
|
|
5527
|
+
strokeWidth: 1.75,
|
|
5528
|
+
strokeLinecap: "round",
|
|
5529
|
+
strokeLinejoin: "round",
|
|
5530
|
+
"aria-hidden": "true",
|
|
5531
|
+
children: [
|
|
5532
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("polygon", { points: "11 5 6 9 2 9 2 15 6 15 11 19 11 5" }),
|
|
5533
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M15.54 8.46a5 5 0 0 1 0 7.07" })
|
|
5534
|
+
]
|
|
5535
|
+
}
|
|
5536
|
+
);
|
|
5537
|
+
}
|
|
5538
|
+
function IconVolumeOff({ slot }) {
|
|
5539
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
5540
|
+
"svg",
|
|
5541
|
+
{
|
|
5542
|
+
slot,
|
|
5543
|
+
width: 20,
|
|
5544
|
+
height: 20,
|
|
5545
|
+
viewBox: "0 0 24 24",
|
|
5546
|
+
fill: "none",
|
|
5547
|
+
stroke: "currentColor",
|
|
5548
|
+
strokeWidth: 1.75,
|
|
5549
|
+
strokeLinecap: "round",
|
|
5550
|
+
strokeLinejoin: "round",
|
|
5551
|
+
"aria-hidden": "true",
|
|
5552
|
+
children: [
|
|
5553
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("polygon", { points: "11 5 6 9 2 9 2 15 6 15 11 19 11 5" }),
|
|
5554
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "22", y1: "9", x2: "16", y2: "15" }),
|
|
5555
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "16", y1: "9", x2: "22", y2: "15" })
|
|
5556
|
+
]
|
|
5557
|
+
}
|
|
5558
|
+
);
|
|
5559
|
+
}
|
|
5560
|
+
function IconSettings() {
|
|
5561
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
5562
|
+
"svg",
|
|
5563
|
+
{
|
|
5564
|
+
width: 20,
|
|
5565
|
+
height: 20,
|
|
5566
|
+
viewBox: "0 0 24 24",
|
|
5567
|
+
fill: "none",
|
|
5568
|
+
stroke: "currentColor",
|
|
5569
|
+
strokeWidth: 1.75,
|
|
5570
|
+
strokeLinecap: "round",
|
|
5571
|
+
strokeLinejoin: "round",
|
|
5572
|
+
"aria-hidden": "true",
|
|
5573
|
+
children: [
|
|
5574
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z" }),
|
|
5575
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { cx: "12", cy: "12", r: "3" })
|
|
5576
|
+
]
|
|
5577
|
+
}
|
|
5578
|
+
);
|
|
5579
|
+
}
|
|
5580
|
+
function IconTheaterExpand() {
|
|
5581
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
5582
|
+
"svg",
|
|
5583
|
+
{
|
|
5584
|
+
width: 20,
|
|
5585
|
+
height: 20,
|
|
5586
|
+
viewBox: "0 0 24 24",
|
|
5587
|
+
fill: "none",
|
|
5588
|
+
stroke: "currentColor",
|
|
5589
|
+
strokeWidth: 1.75,
|
|
5590
|
+
strokeLinecap: "round",
|
|
5591
|
+
strokeLinejoin: "round",
|
|
5592
|
+
"aria-hidden": "true",
|
|
5593
|
+
children: [
|
|
5594
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("polyline", { points: "15 3 21 3 21 9" }),
|
|
5595
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("polyline", { points: "9 21 3 21 3 15" }),
|
|
5596
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "21", y1: "3", x2: "14", y2: "10" }),
|
|
5597
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "3", y1: "21", x2: "10", y2: "14" })
|
|
5598
|
+
]
|
|
5599
|
+
}
|
|
5600
|
+
);
|
|
5601
|
+
}
|
|
5602
|
+
function IconTheaterShrink() {
|
|
5603
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
5604
|
+
"svg",
|
|
5605
|
+
{
|
|
5606
|
+
width: 20,
|
|
5607
|
+
height: 20,
|
|
5608
|
+
viewBox: "0 0 24 24",
|
|
5609
|
+
fill: "none",
|
|
5610
|
+
stroke: "currentColor",
|
|
5611
|
+
strokeWidth: 1.75,
|
|
5612
|
+
strokeLinecap: "round",
|
|
5613
|
+
strokeLinejoin: "round",
|
|
5614
|
+
"aria-hidden": "true",
|
|
5615
|
+
children: [
|
|
5616
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("polyline", { points: "4 14 10 14 10 20" }),
|
|
5617
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("polyline", { points: "20 10 14 10 14 4" }),
|
|
5618
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "14", y1: "10", x2: "21", y2: "3" }),
|
|
5619
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "3", y1: "21", x2: "10", y2: "14" })
|
|
5620
|
+
]
|
|
5621
|
+
}
|
|
5622
|
+
);
|
|
5623
|
+
}
|
|
5624
|
+
function IconFullscreenEnter({ slot }) {
|
|
5625
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
5626
|
+
"svg",
|
|
5627
|
+
{
|
|
5628
|
+
slot,
|
|
5629
|
+
width: 20,
|
|
5630
|
+
height: 20,
|
|
5631
|
+
viewBox: "0 0 24 24",
|
|
5632
|
+
fill: "none",
|
|
5633
|
+
stroke: "currentColor",
|
|
5634
|
+
strokeWidth: 1.75,
|
|
5635
|
+
strokeLinecap: "round",
|
|
5636
|
+
strokeLinejoin: "round",
|
|
5637
|
+
"aria-hidden": "true",
|
|
5638
|
+
children: [
|
|
5639
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M8 3H5a2 2 0 0 0-2 2v3" }),
|
|
5640
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M21 8V5a2 2 0 0 0-2-2h-3" }),
|
|
5641
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M3 16v3a2 2 0 0 0 2 2h3" }),
|
|
5642
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M16 21h3a2 2 0 0 0 2-2v-3" })
|
|
5643
|
+
]
|
|
5644
|
+
}
|
|
5645
|
+
);
|
|
5646
|
+
}
|
|
5647
|
+
function IconFullscreenExit({ slot }) {
|
|
5648
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
5649
|
+
"svg",
|
|
5650
|
+
{
|
|
5651
|
+
slot,
|
|
5652
|
+
width: 20,
|
|
5653
|
+
height: 20,
|
|
5654
|
+
viewBox: "0 0 24 24",
|
|
5655
|
+
fill: "none",
|
|
5656
|
+
stroke: "currentColor",
|
|
5657
|
+
strokeWidth: 1.75,
|
|
5658
|
+
strokeLinecap: "round",
|
|
5659
|
+
strokeLinejoin: "round",
|
|
5660
|
+
"aria-hidden": "true",
|
|
5661
|
+
children: [
|
|
5662
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M8 3v3a2 2 0 0 1-2 2H3" }),
|
|
5663
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M21 8h-3a2 2 0 0 1-2-2V3" }),
|
|
5664
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M3 16h3a2 2 0 0 1 2 2v3" }),
|
|
5665
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M16 21v-3a2 2 0 0 1 2-2h3" })
|
|
5666
|
+
]
|
|
5667
|
+
}
|
|
5668
|
+
);
|
|
5669
|
+
}
|
|
5670
|
+
var EMPTY_GOALS2 = [];
|
|
5671
|
+
function serverVideoSnapshot() {
|
|
5672
|
+
return null;
|
|
5673
|
+
}
|
|
5674
|
+
function serverGoalsSnapshot() {
|
|
5675
|
+
return EMPTY_GOALS2;
|
|
5676
|
+
}
|
|
5677
|
+
function useTrackedVideoConfig(videoKey, trackingConfig, fallbackConfig) {
|
|
5678
|
+
registerCapability("video_tracking");
|
|
5679
|
+
const effectiveRef = trackingConfig ?? getActiveTrackingEnv().trackingConfig;
|
|
5680
|
+
const subscribe = (0, import_react8.useCallback)(
|
|
5681
|
+
(listener) => effectiveRef ? getTrackingConfigRuntime(effectiveRef).subscribe(listener) : () => {
|
|
5682
|
+
},
|
|
5683
|
+
[effectiveRef]
|
|
5684
|
+
);
|
|
5685
|
+
const live = (0, import_react8.useSyncExternalStore)(
|
|
5686
|
+
subscribe,
|
|
5687
|
+
() => effectiveRef && videoKey ? getTrackingConfigRuntime(effectiveRef).getVideo(videoKey) : null,
|
|
5688
|
+
serverVideoSnapshot
|
|
5689
|
+
);
|
|
5690
|
+
return live ?? fallbackConfig ?? null;
|
|
5691
|
+
}
|
|
5692
|
+
function useActiveVideoGoals(videoId, trackingConfig) {
|
|
5693
|
+
const effectiveRef = trackingConfig ?? getActiveTrackingEnv().trackingConfig;
|
|
5694
|
+
const subscribe = (0, import_react8.useCallback)(
|
|
5695
|
+
(listener) => effectiveRef ? getTrackingConfigRuntime(effectiveRef).subscribe(listener) : () => {
|
|
5696
|
+
},
|
|
5697
|
+
[effectiveRef]
|
|
5698
|
+
);
|
|
5699
|
+
const goals = (0, import_react8.useSyncExternalStore)(
|
|
5700
|
+
subscribe,
|
|
5701
|
+
() => effectiveRef ? getTrackingConfigRuntime(effectiveRef).listGoals() : EMPTY_GOALS2,
|
|
5702
|
+
serverGoalsSnapshot
|
|
5703
|
+
);
|
|
5704
|
+
return (0, import_react8.useMemo)(() => {
|
|
5705
|
+
const out = [];
|
|
5706
|
+
for (const goal of goals) {
|
|
5707
|
+
if (goal.kind !== "event" || !goal.trigger) continue;
|
|
5708
|
+
if (goal.trigger.event_type !== "video_progress") continue;
|
|
5709
|
+
if (goal.trigger.video_id && goal.trigger.video_id !== videoId) continue;
|
|
5710
|
+
const metric = goal.trigger.metric;
|
|
5711
|
+
const threshold = goal.trigger.threshold;
|
|
5712
|
+
if ((metric === "percent" || metric === "seconds") && typeof threshold === "number") {
|
|
5713
|
+
out.push({ key: goal.key, metric, threshold });
|
|
5714
|
+
}
|
|
5715
|
+
}
|
|
5716
|
+
return out;
|
|
5717
|
+
}, [goals, videoId]);
|
|
5718
|
+
}
|
|
5719
|
+
function renditionsOf(h) {
|
|
5720
|
+
const best = /* @__PURE__ */ new Map();
|
|
5721
|
+
h.levels.forEach((l, index) => {
|
|
5722
|
+
const px = Math.min(l.width || Infinity, l.height || Infinity);
|
|
5723
|
+
if (!Number.isFinite(px)) return;
|
|
5724
|
+
const cur = best.get(px);
|
|
5725
|
+
if (!cur || l.bitrate > cur.bitrate) best.set(px, { height: px, index, bitrate: l.bitrate });
|
|
5726
|
+
});
|
|
5727
|
+
return [...best.values()].sort((a, b) => b.height - a.height).map(({ height, index }) => ({ height, index }));
|
|
5728
|
+
}
|
|
5729
|
+
var MEDIA_CHROME_CDN_URL = "https://cdn.jsdelivr.net/npm/media-chrome@4/+esm";
|
|
5730
|
+
var HLS_JS_CDN_URL = "https://cdn.jsdelivr.net/npm/hls.js@1/dist/hls.min.js";
|
|
5731
|
+
var defaultLibsPromise = null;
|
|
5732
|
+
function loadScriptOnce(src, attr, isModule = false) {
|
|
5733
|
+
if (typeof document === "undefined") return Promise.resolve();
|
|
5734
|
+
const existing = document.querySelector(`script[${attr}]`);
|
|
5735
|
+
if (existing) return Promise.resolve();
|
|
5736
|
+
return new Promise((resolve) => {
|
|
5737
|
+
const s = document.createElement("script");
|
|
5738
|
+
if (isModule) s.type = "module";
|
|
5739
|
+
s.async = true;
|
|
5740
|
+
s.src = src;
|
|
5741
|
+
s.setAttribute(attr, "1");
|
|
5742
|
+
s.addEventListener("load", () => resolve(), { once: true });
|
|
5743
|
+
s.addEventListener("error", () => resolve(), { once: true });
|
|
5744
|
+
document.head.append(s);
|
|
5745
|
+
if (typeof navigator !== "undefined" && /jsdom/i.test(navigator.userAgent)) {
|
|
5746
|
+
setTimeout(resolve, 0);
|
|
5747
|
+
}
|
|
5748
|
+
});
|
|
5749
|
+
}
|
|
5750
|
+
function loadDefaultPlayerLibs() {
|
|
5751
|
+
if (typeof window === "undefined") return Promise.resolve({});
|
|
5752
|
+
if (defaultLibsPromise) return defaultLibsPromise;
|
|
5753
|
+
defaultLibsPromise = Promise.all([
|
|
5754
|
+
typeof customElements !== "undefined" && customElements.get("media-controller") ? Promise.resolve() : loadScriptOnce(MEDIA_CHROME_CDN_URL, "data-aranova-media-chrome", true),
|
|
5755
|
+
window.Hls ? Promise.resolve() : loadScriptOnce(HLS_JS_CDN_URL, "data-aranova-hls-js", false)
|
|
5756
|
+
]).then(() => ({
|
|
5757
|
+
hls: window.Hls
|
|
5758
|
+
}));
|
|
5759
|
+
return defaultLibsPromise;
|
|
5760
|
+
}
|
|
5761
|
+
function Cut({
|
|
5762
|
+
id,
|
|
5763
|
+
variant,
|
|
5764
|
+
uid,
|
|
5765
|
+
host,
|
|
5766
|
+
title,
|
|
5767
|
+
posterTime,
|
|
5768
|
+
posterUrl,
|
|
5769
|
+
renderPoster,
|
|
5770
|
+
theater,
|
|
5771
|
+
onTheaterChange,
|
|
5772
|
+
autoExpandOnPlay,
|
|
5773
|
+
checkpoints,
|
|
5774
|
+
videoGoals,
|
|
5775
|
+
client,
|
|
5776
|
+
loadPlayerLibs,
|
|
5777
|
+
className,
|
|
5778
|
+
...cb
|
|
5779
|
+
}) {
|
|
5780
|
+
const root = (0, import_react8.useRef)(null);
|
|
5781
|
+
const video = (0, import_react8.useRef)(null);
|
|
5782
|
+
const hls = (0, import_react8.useRef)(null);
|
|
5783
|
+
const lastTime = (0, import_react8.useRef)(0);
|
|
5784
|
+
const seekFrom = (0, import_react8.useRef)(0);
|
|
5785
|
+
const cbRef = (0, import_react8.useRef)(cb);
|
|
5786
|
+
cbRef.current = cb;
|
|
5787
|
+
const clientRef = (0, import_react8.useRef)(client);
|
|
5788
|
+
clientRef.current = client;
|
|
5789
|
+
const goalsRef = (0, import_react8.useRef)(videoGoals);
|
|
5790
|
+
goalsRef.current = videoGoals;
|
|
5791
|
+
const rangesRef = (0, import_react8.useRef)([]);
|
|
5792
|
+
const activeSegmentStartRef = (0, import_react8.useRef)(null);
|
|
5793
|
+
const furthestSecondsRef = (0, import_react8.useRef)(0);
|
|
5794
|
+
const maxPercentRef = (0, import_react8.useRef)(0);
|
|
5795
|
+
const durationRef = (0, import_react8.useRef)(0);
|
|
5796
|
+
const playCountRef = (0, import_react8.useRef)(0);
|
|
5797
|
+
const seekCountRef = (0, import_react8.useRef)(0);
|
|
5798
|
+
const firedCheckpointsRef = (0, import_react8.useRef)(/* @__PURE__ */ new Set());
|
|
5799
|
+
const firedGoalsRef = (0, import_react8.useRef)(/* @__PURE__ */ new Set());
|
|
5800
|
+
const dirtySinceLastEmitRef = (0, import_react8.useRef)(false);
|
|
5801
|
+
const [started, setStarted] = (0, import_react8.useState)(false);
|
|
5802
|
+
const [ready, setReady] = (0, import_react8.useState)(false);
|
|
5803
|
+
const [playing, setPlaying] = (0, import_react8.useState)(false);
|
|
5804
|
+
const [renditions, setRenditions] = (0, import_react8.useState)([]);
|
|
5805
|
+
const [selected, setSelected] = (0, import_react8.useState)("auto");
|
|
5806
|
+
const [live, setLive] = (0, import_react8.useState)(null);
|
|
5807
|
+
const [menu, setMenu] = (0, import_react8.useState)(false);
|
|
5808
|
+
const [pending, setPending] = (0, import_react8.useState)(null);
|
|
5809
|
+
const pendingRef = (0, import_react8.useRef)(null);
|
|
5810
|
+
const wrap = (0, import_react8.useRef)(null);
|
|
5811
|
+
const gear = (0, import_react8.useRef)(null);
|
|
5812
|
+
const selectedRef = (0, import_react8.useRef)("auto");
|
|
5813
|
+
const pendingTimer = (0, import_react8.useRef)(null);
|
|
5814
|
+
const liveRef = (0, import_react8.useRef)(null);
|
|
5815
|
+
const videoId = `${id}-${variant}`;
|
|
5816
|
+
const getCurrentRanges = (0, import_react8.useCallback)(() => {
|
|
5817
|
+
const v = video.current;
|
|
5818
|
+
const cur = v ? v.currentTime : lastTime.current;
|
|
5819
|
+
const list = [...rangesRef.current];
|
|
5820
|
+
if (activeSegmentStartRef.current !== null && cur > activeSegmentStartRef.current) {
|
|
5821
|
+
list.push({
|
|
5822
|
+
start_s: activeSegmentStartRef.current,
|
|
5823
|
+
end_s: cur
|
|
5824
|
+
});
|
|
5825
|
+
}
|
|
5826
|
+
return mergeVideoRanges(list);
|
|
5827
|
+
}, []);
|
|
5828
|
+
const commitActiveSegment = (0, import_react8.useCallback)((endTime) => {
|
|
5829
|
+
const end = endTime ?? video.current?.currentTime ?? lastTime.current;
|
|
5830
|
+
if (activeSegmentStartRef.current !== null && end > activeSegmentStartRef.current) {
|
|
5831
|
+
rangesRef.current = mergeVideoRanges([
|
|
5832
|
+
...rangesRef.current,
|
|
5833
|
+
{ start_s: activeSegmentStartRef.current, end_s: end }
|
|
5834
|
+
]);
|
|
5835
|
+
}
|
|
5836
|
+
activeSegmentStartRef.current = null;
|
|
5837
|
+
}, []);
|
|
5838
|
+
const snap = (0, import_react8.useCallback)(() => {
|
|
5839
|
+
const v = video.current;
|
|
5840
|
+
const currentTime = roundVideoSeconds(v?.currentTime ?? lastTime.current);
|
|
5841
|
+
const rawDuration = v?.duration;
|
|
5842
|
+
const duration = typeof rawDuration === "number" && Number.isFinite(rawDuration) && rawDuration > 0 ? roundVideoSeconds(rawDuration) : durationRef.current;
|
|
5843
|
+
if (duration > 0) durationRef.current = duration;
|
|
5844
|
+
if (currentTime > furthestSecondsRef.current) {
|
|
5845
|
+
furthestSecondsRef.current = currentTime;
|
|
5846
|
+
}
|
|
5847
|
+
const ranges = getCurrentRanges();
|
|
5848
|
+
const watchedSeconds = sumVideoRangesSeconds(ranges, duration);
|
|
5849
|
+
const watchedPercent = duration > 0 ? Math.min(100, Math.round(watchedSeconds / duration * 100)) : 0;
|
|
5850
|
+
const curPercent = duration > 0 ? Math.min(100, Math.round(furthestSecondsRef.current / duration * 100)) : 0;
|
|
5851
|
+
if (curPercent > maxPercentRef.current) {
|
|
5852
|
+
maxPercentRef.current = curPercent;
|
|
5853
|
+
}
|
|
5854
|
+
return {
|
|
5855
|
+
id,
|
|
5856
|
+
videoId,
|
|
5857
|
+
variant,
|
|
5858
|
+
currentTime,
|
|
5859
|
+
duration,
|
|
5860
|
+
watchedSeconds,
|
|
5861
|
+
watchedPercent,
|
|
5862
|
+
maxPercent: maxPercentRef.current,
|
|
5863
|
+
ranges
|
|
5864
|
+
};
|
|
5865
|
+
}, [getCurrentRanges, id, variant, videoId]);
|
|
5866
|
+
const emitProgress = (0, import_react8.useCallback)(
|
|
5867
|
+
(trigger, snapshotOverride) => {
|
|
5868
|
+
const activeClient = clientRef.current ?? getActiveTrackingEnv().rawClient;
|
|
5869
|
+
if (!activeClient || playCountRef.current <= 0) return;
|
|
5870
|
+
const s = snapshotOverride ?? snap();
|
|
5871
|
+
if (s.ranges.length === 0 && s.currentTime <= 0 && trigger !== "ended") return;
|
|
5872
|
+
dirtySinceLastEmitRef.current = false;
|
|
5873
|
+
const path = typeof window === "undefined" ? "/" : window.location.pathname;
|
|
5874
|
+
activeClient.trackEvent({
|
|
5875
|
+
eventType: "video_progress",
|
|
5876
|
+
metadata: {
|
|
5877
|
+
video_id: id,
|
|
5878
|
+
variant,
|
|
5879
|
+
trigger,
|
|
5880
|
+
current_s: s.currentTime,
|
|
5881
|
+
furthest_s: roundVideoSeconds(furthestSecondsRef.current),
|
|
5882
|
+
watched_s: s.watchedSeconds,
|
|
5883
|
+
duration_s: s.duration,
|
|
5884
|
+
max_percent: s.maxPercent,
|
|
5885
|
+
watched_percent: s.watchedPercent,
|
|
5886
|
+
play_count: playCountRef.current,
|
|
5887
|
+
seek_count: seekCountRef.current,
|
|
5888
|
+
ranges: s.ranges,
|
|
5889
|
+
page: { path }
|
|
5890
|
+
}
|
|
5891
|
+
});
|
|
5892
|
+
},
|
|
5893
|
+
[id, snap, variant]
|
|
5894
|
+
);
|
|
5895
|
+
const clearPending = () => {
|
|
5896
|
+
if (pendingTimer.current) clearTimeout(pendingTimer.current);
|
|
5897
|
+
pendingTimer.current = null;
|
|
5898
|
+
pendingRef.current = null;
|
|
5899
|
+
setPending(null);
|
|
5900
|
+
};
|
|
5901
|
+
(0, import_react8.useEffect)(() => {
|
|
5902
|
+
ensureTvSkinStyles();
|
|
5903
|
+
registerCapability("video_tracking");
|
|
5904
|
+
return () => {
|
|
5905
|
+
if (pendingTimer.current) clearTimeout(pendingTimer.current);
|
|
5906
|
+
hls.current?.destroy();
|
|
5907
|
+
hls.current = null;
|
|
5908
|
+
};
|
|
5909
|
+
}, []);
|
|
5910
|
+
(0, import_react8.useEffect)(() => {
|
|
5911
|
+
if (!started || typeof window === "undefined") return;
|
|
5912
|
+
const flushExitProgress = (useBeacon) => {
|
|
5913
|
+
if (playCountRef.current <= 0 || !dirtySinceLastEmitRef.current) return;
|
|
5914
|
+
commitActiveSegment();
|
|
5915
|
+
emitProgress("page_exit");
|
|
5916
|
+
if (useBeacon) {
|
|
5917
|
+
const activeClient2 = clientRef.current ?? getActiveTrackingEnv().rawClient;
|
|
5918
|
+
activeClient2?.flushBeacon();
|
|
5919
|
+
}
|
|
5920
|
+
};
|
|
5921
|
+
const activeClient = clientRef.current ?? getActiveTrackingEnv().rawClient;
|
|
5922
|
+
const unsubscribeBeforeUnload = activeClient?.onBeforeUnload?.(() => {
|
|
5923
|
+
flushExitProgress(false);
|
|
5924
|
+
});
|
|
5925
|
+
const onVisibilityChange = () => {
|
|
5926
|
+
if (document.visibilityState === "hidden") {
|
|
5927
|
+
flushExitProgress(true);
|
|
5928
|
+
}
|
|
5929
|
+
};
|
|
5930
|
+
const onPageHide = () => {
|
|
5931
|
+
flushExitProgress(true);
|
|
5932
|
+
};
|
|
5933
|
+
document.addEventListener("visibilitychange", onVisibilityChange);
|
|
5934
|
+
window.addEventListener("pagehide", onPageHide);
|
|
5935
|
+
return () => {
|
|
5936
|
+
unsubscribeBeforeUnload?.();
|
|
5937
|
+
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
5938
|
+
window.removeEventListener("pagehide", onPageHide);
|
|
5939
|
+
};
|
|
5940
|
+
}, [started, commitActiveSegment, emitProgress]);
|
|
5941
|
+
(0, import_react8.useEffect)(() => {
|
|
5942
|
+
if (!started) return;
|
|
5943
|
+
let was = false;
|
|
5944
|
+
const report = (fullscreen) => {
|
|
5945
|
+
if (fullscreen === was) return;
|
|
5946
|
+
was = fullscreen;
|
|
5947
|
+
cbRef.current.onFullscreenChange?.({ ...snap(), fullscreen });
|
|
5948
|
+
};
|
|
5949
|
+
const onDoc = () => {
|
|
5950
|
+
const el = root.current;
|
|
5951
|
+
const fe = document.fullscreenElement ?? document.webkitFullscreenElement;
|
|
5952
|
+
report(Boolean(el && fe && el.contains(fe)));
|
|
5953
|
+
};
|
|
5954
|
+
const v = video.current;
|
|
5955
|
+
const begin = () => report(true);
|
|
5956
|
+
const end = () => report(false);
|
|
5957
|
+
document.addEventListener("fullscreenchange", onDoc);
|
|
5958
|
+
document.addEventListener("webkitfullscreenchange", onDoc);
|
|
5959
|
+
v?.addEventListener("webkitbeginfullscreen", begin);
|
|
5960
|
+
v?.addEventListener("webkitendfullscreen", end);
|
|
5961
|
+
return () => {
|
|
5962
|
+
document.removeEventListener("fullscreenchange", onDoc);
|
|
5963
|
+
document.removeEventListener("webkitfullscreenchange", onDoc);
|
|
5964
|
+
v?.removeEventListener("webkitbeginfullscreen", begin);
|
|
5965
|
+
v?.removeEventListener("webkitendfullscreen", end);
|
|
5966
|
+
};
|
|
5967
|
+
}, [started, snap]);
|
|
5968
|
+
(0, import_react8.useEffect)(() => {
|
|
5969
|
+
if (!menu) return;
|
|
5970
|
+
const outside = (e) => {
|
|
5971
|
+
if (wrap.current && !wrap.current.contains(e.target)) setMenu(false);
|
|
5972
|
+
};
|
|
5973
|
+
document.addEventListener("pointerdown", outside);
|
|
5974
|
+
return () => document.removeEventListener("pointerdown", outside);
|
|
5975
|
+
}, [menu]);
|
|
5976
|
+
const closeMenu = (refocus) => {
|
|
5977
|
+
setMenu(false);
|
|
5978
|
+
if (refocus) gear.current?.focus();
|
|
5979
|
+
};
|
|
5980
|
+
const onMenuKey = (e) => {
|
|
5981
|
+
if (e.key === "Escape") {
|
|
5982
|
+
e.preventDefault();
|
|
5983
|
+
e.stopPropagation();
|
|
5984
|
+
closeMenu(true);
|
|
5985
|
+
} else if (e.key === "ArrowDown" || e.key === "ArrowUp") {
|
|
5986
|
+
e.preventDefault();
|
|
5987
|
+
const items = [
|
|
5988
|
+
...wrap.current?.querySelectorAll('[role="menuitemradio"]') ?? []
|
|
5989
|
+
];
|
|
5990
|
+
const i = items.indexOf(document.activeElement);
|
|
5991
|
+
items[(i + (e.key === "ArrowDown" ? 1 : items.length - 1)) % items.length]?.focus();
|
|
5992
|
+
}
|
|
5993
|
+
};
|
|
5994
|
+
const emitQuality = (from, to, source) => cbRef.current.onQualityChange?.({ ...snap(), from, to, source });
|
|
5995
|
+
const start = async () => {
|
|
5996
|
+
const v = video.current;
|
|
5997
|
+
if (!v || started) return;
|
|
5998
|
+
setStarted(true);
|
|
5999
|
+
if (variant === "16x9" && autoExpandOnPlay) {
|
|
6000
|
+
onTheaterChange?.(true);
|
|
6001
|
+
}
|
|
6002
|
+
const src = streamManifestUrl(host, uid);
|
|
6003
|
+
try {
|
|
6004
|
+
const loaded = await (loadPlayerLibs ? loadPlayerLibs() : loadDefaultPlayerLibs());
|
|
6005
|
+
setReady(true);
|
|
6006
|
+
const rawHls = (loaded && typeof loaded === "object" && "hls" in loaded ? loaded.hls : null) ?? (typeof window !== "undefined" ? window.Hls : void 0);
|
|
6007
|
+
const HlsLib = rawHls && typeof rawHls === "object" && "default" in rawHls ? rawHls.default : rawHls;
|
|
6008
|
+
if (!HlsLib || !HlsLib.isSupported()) {
|
|
6009
|
+
v.src = src;
|
|
6010
|
+
} else {
|
|
6011
|
+
const h = new HlsLib({ capLevelToPlayerSize: true });
|
|
6012
|
+
hls.current = h;
|
|
6013
|
+
h.on(HlsLib.Events.MANIFEST_PARSED, () => setRenditions(renditionsOf(h)));
|
|
6014
|
+
h.on(HlsLib.Events.LEVEL_SWITCHED, (_e, data) => {
|
|
6015
|
+
const lv = h.levels[data.level];
|
|
6016
|
+
const height = lv ? Math.min(lv.width || Infinity, lv.height || Infinity) : null;
|
|
6017
|
+
const from = liveRef.current;
|
|
6018
|
+
liveRef.current = height;
|
|
6019
|
+
setLive(height);
|
|
6020
|
+
const want = pendingRef.current;
|
|
6021
|
+
if (want !== null && want === height) clearPending();
|
|
6022
|
+
if (selectedRef.current === "auto" && height && from && from !== height) {
|
|
6023
|
+
emitQuality(from, height, "auto");
|
|
6024
|
+
}
|
|
6025
|
+
});
|
|
6026
|
+
h.on(HlsLib.Events.ERROR, () => clearPending());
|
|
6027
|
+
h.loadSource(src);
|
|
6028
|
+
h.attachMedia(v);
|
|
6029
|
+
}
|
|
6030
|
+
} catch {
|
|
6031
|
+
setReady(true);
|
|
6032
|
+
v.src = src;
|
|
6033
|
+
}
|
|
6034
|
+
try {
|
|
6035
|
+
await v.play();
|
|
6036
|
+
} catch {
|
|
6037
|
+
}
|
|
6038
|
+
};
|
|
6039
|
+
const pick = (q) => {
|
|
6040
|
+
const h = hls.current;
|
|
6041
|
+
const from = selectedRef.current;
|
|
6042
|
+
setMenu(false);
|
|
6043
|
+
if (!h || q === from) return;
|
|
6044
|
+
if (q === "auto") h.nextLevel = -1;
|
|
6045
|
+
else {
|
|
6046
|
+
const r = renditions.find((x) => x.height === q);
|
|
6047
|
+
if (r) h.nextLevel = r.index;
|
|
6048
|
+
}
|
|
6049
|
+
selectedRef.current = q;
|
|
6050
|
+
setSelected(q);
|
|
6051
|
+
clearPending();
|
|
6052
|
+
if (typeof q === "number" && q !== liveRef.current) {
|
|
6053
|
+
pendingRef.current = q;
|
|
6054
|
+
setPending(q);
|
|
6055
|
+
pendingTimer.current = setTimeout(clearPending, 4e3);
|
|
6056
|
+
}
|
|
6057
|
+
emitQuality(from, q, "manual");
|
|
6058
|
+
};
|
|
6059
|
+
const qualityLabel = selected === "auto" ? live ? `Auto (${live}p)` : "Auto" : `${selected}p`;
|
|
6060
|
+
const resolvedPosterUrl = posterUrl ?? streamPosterUrl(host, uid, posterTime);
|
|
6061
|
+
const posterWidth = variant === "16x9" ? 1280 : 720;
|
|
6062
|
+
const posterHeight = variant === "16x9" ? 720 : 1280;
|
|
6063
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
6064
|
+
"div",
|
|
6065
|
+
{
|
|
6066
|
+
ref: root,
|
|
6067
|
+
className: `tv-skin ${variant === "16x9" ? "tv-skin-desktop" : "tv-skin-mobile"} ${className ?? ""}`,
|
|
6068
|
+
"data-video-id": videoId,
|
|
6069
|
+
children: [
|
|
6070
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("media-controller", { class: "absolute inset-0 block", autohide: menu ? "-1" : "2", children: [
|
|
6071
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
6072
|
+
"video",
|
|
6073
|
+
{
|
|
6074
|
+
ref: video,
|
|
6075
|
+
slot: "media",
|
|
6076
|
+
style: { width: "100%", height: "100%", backgroundColor: "#000", objectFit: "contain" },
|
|
6077
|
+
preload: "none",
|
|
6078
|
+
playsInline: true,
|
|
6079
|
+
title,
|
|
6080
|
+
"aria-label": title,
|
|
6081
|
+
"data-video-id": videoId,
|
|
6082
|
+
onPlay: () => {
|
|
6083
|
+
const v = video.current;
|
|
6084
|
+
const cur = roundVideoSeconds(v?.currentTime ?? 0);
|
|
6085
|
+
activeSegmentStartRef.current = cur;
|
|
6086
|
+
playCountRef.current += 1;
|
|
6087
|
+
dirtySinceLastEmitRef.current = true;
|
|
6088
|
+
const s = snap();
|
|
6089
|
+
const activeClient = clientRef.current ?? getActiveTrackingEnv().rawClient;
|
|
6090
|
+
if (activeClient) {
|
|
6091
|
+
const path = typeof window === "undefined" ? "/" : window.location.pathname;
|
|
6092
|
+
activeClient.trackEvent({
|
|
6093
|
+
eventType: "video_play",
|
|
6094
|
+
metadata: {
|
|
6095
|
+
video_id: id,
|
|
6096
|
+
variant,
|
|
6097
|
+
current_s: s.currentTime,
|
|
6098
|
+
duration_s: s.duration,
|
|
6099
|
+
play_sequence: playCountRef.current,
|
|
6100
|
+
page: { path }
|
|
6101
|
+
}
|
|
6102
|
+
});
|
|
6103
|
+
}
|
|
6104
|
+
cbRef.current.onPlay?.(s);
|
|
6105
|
+
},
|
|
6106
|
+
onPlaying: () => setPlaying(true),
|
|
6107
|
+
onPause: () => {
|
|
6108
|
+
const v = video.current;
|
|
6109
|
+
if (v?.ended) return;
|
|
6110
|
+
commitActiveSegment(v?.currentTime);
|
|
6111
|
+
const s = snap();
|
|
6112
|
+
emitProgress("pause", s);
|
|
6113
|
+
cbRef.current.onPause?.(s);
|
|
6114
|
+
},
|
|
6115
|
+
onEnded: () => {
|
|
6116
|
+
const v = video.current;
|
|
6117
|
+
const dur = typeof v?.duration === "number" && Number.isFinite(v.duration) ? v.duration : durationRef.current;
|
|
6118
|
+
commitActiveSegment(dur > 0 ? dur : v?.currentTime);
|
|
6119
|
+
maxPercentRef.current = 100;
|
|
6120
|
+
const s = snap();
|
|
6121
|
+
if (!firedCheckpointsRef.current.has(100) && checkpoints.includes(100)) {
|
|
6122
|
+
firedCheckpointsRef.current.add(100);
|
|
6123
|
+
cbRef.current.onCheckpoint?.({ ...s, checkpoint: 100 });
|
|
6124
|
+
}
|
|
6125
|
+
emitProgress("ended", s);
|
|
6126
|
+
cbRef.current.onEnded?.(s);
|
|
6127
|
+
},
|
|
6128
|
+
onWaiting: () => cbRef.current.onWaiting?.(snap()),
|
|
6129
|
+
onTimeUpdate: () => {
|
|
6130
|
+
const v = video.current;
|
|
6131
|
+
if (v && !v.seeking) {
|
|
6132
|
+
if (activeSegmentStartRef.current === null && !v.paused) {
|
|
6133
|
+
activeSegmentStartRef.current = lastTime.current;
|
|
6134
|
+
}
|
|
6135
|
+
lastTime.current = v.currentTime;
|
|
6136
|
+
dirtySinceLastEmitRef.current = true;
|
|
6137
|
+
}
|
|
6138
|
+
const s = snap();
|
|
6139
|
+
let hitCheckpoint = false;
|
|
6140
|
+
let hitGoal = false;
|
|
6141
|
+
for (const goal of goalsRef.current) {
|
|
6142
|
+
if (firedGoalsRef.current.has(goal.key)) continue;
|
|
6143
|
+
const met = goal.metric === "seconds" ? s.watchedSeconds >= goal.threshold : s.watchedPercent >= goal.threshold;
|
|
6144
|
+
if (met) {
|
|
6145
|
+
firedGoalsRef.current.add(goal.key);
|
|
6146
|
+
hitGoal = true;
|
|
6147
|
+
}
|
|
6148
|
+
}
|
|
6149
|
+
const newlyFiredCheckpoints = [];
|
|
6150
|
+
for (const cp of checkpoints) {
|
|
6151
|
+
if (firedCheckpointsRef.current.has(cp)) continue;
|
|
6152
|
+
if (s.watchedPercent >= cp || s.maxPercent >= cp) {
|
|
6153
|
+
firedCheckpointsRef.current.add(cp);
|
|
6154
|
+
newlyFiredCheckpoints.push(cp);
|
|
6155
|
+
hitCheckpoint = true;
|
|
6156
|
+
}
|
|
6157
|
+
}
|
|
6158
|
+
if (hitCheckpoint || hitGoal) {
|
|
6159
|
+
commitActiveSegment(v?.currentTime);
|
|
6160
|
+
if (v && !v.paused) activeSegmentStartRef.current = v.currentTime;
|
|
6161
|
+
const emittedSnap = snap();
|
|
6162
|
+
emitProgress(hitCheckpoint ? "checkpoint" : "goal", emittedSnap);
|
|
6163
|
+
for (const cp of newlyFiredCheckpoints) {
|
|
6164
|
+
cbRef.current.onCheckpoint?.({ ...emittedSnap, checkpoint: cp });
|
|
6165
|
+
}
|
|
6166
|
+
}
|
|
6167
|
+
cbRef.current.onTimeUpdate?.(s);
|
|
6168
|
+
},
|
|
6169
|
+
onSeeking: () => {
|
|
6170
|
+
seekFrom.current = lastTime.current;
|
|
6171
|
+
commitActiveSegment(seekFrom.current);
|
|
6172
|
+
},
|
|
6173
|
+
onSeeked: () => {
|
|
6174
|
+
const v = video.current;
|
|
6175
|
+
const to = roundVideoSeconds(v?.currentTime ?? 0);
|
|
6176
|
+
const from = roundVideoSeconds(seekFrom.current);
|
|
6177
|
+
lastTime.current = to;
|
|
6178
|
+
if (v && !v.paused) {
|
|
6179
|
+
activeSegmentStartRef.current = to;
|
|
6180
|
+
}
|
|
6181
|
+
if (Math.abs(to - from) >= 1) {
|
|
6182
|
+
seekCountRef.current += 1;
|
|
6183
|
+
const s = snap();
|
|
6184
|
+
emitProgress("seek", s);
|
|
6185
|
+
cbRef.current.onSeek?.({ ...s, from, to });
|
|
6186
|
+
}
|
|
6187
|
+
},
|
|
6188
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("track", { kind: "captions" })
|
|
6189
|
+
}
|
|
6190
|
+
),
|
|
6191
|
+
ready && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
6192
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("media-loading-indicator", { slot: "centered-chrome" }),
|
|
6193
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "tv-chrome", children: [
|
|
6194
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "tv-row", children: [
|
|
6195
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("media-play-button", { class: "tv-ctl", children: [
|
|
6196
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(IconPlay, { slot: "play" }),
|
|
6197
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(IconPause, { slot: "pause" })
|
|
6198
|
+
] }),
|
|
6199
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("media-time-display", { class: "tv-time tv-time-full", showduration: true }),
|
|
6200
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("media-time-display", { class: "tv-time tv-time-cur" }),
|
|
6201
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "tv-spacer" }),
|
|
6202
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "tv-vol", children: [
|
|
6203
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("media-mute-button", { class: "tv-ctl", children: [
|
|
6204
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(IconVolumeHigh, { slot: "high" }),
|
|
6205
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(IconVolumeLow, { slot: "medium" }),
|
|
6206
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(IconVolumeLow, { slot: "low" }),
|
|
6207
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(IconVolumeOff, { slot: "off" })
|
|
6208
|
+
] }),
|
|
6209
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("media-volume-range", { class: "tv-volrange" })
|
|
6210
|
+
] }),
|
|
6211
|
+
renditions.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "tv-menu-wrap", ref: wrap, children: [
|
|
6212
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
6213
|
+
"button",
|
|
6214
|
+
{
|
|
6215
|
+
ref: gear,
|
|
6216
|
+
type: "button",
|
|
6217
|
+
className: "tv-btn",
|
|
6218
|
+
"aria-haspopup": "menu",
|
|
6219
|
+
"aria-expanded": menu,
|
|
6220
|
+
"aria-label": `Settings, quality ${qualityLabel}`,
|
|
6221
|
+
title: "Settings",
|
|
6222
|
+
onClick: () => setMenu((m) => !m),
|
|
6223
|
+
onKeyDown: onMenuKey,
|
|
6224
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(IconSettings, {})
|
|
6225
|
+
}
|
|
6226
|
+
),
|
|
6227
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { role: "status", className: "sr-only", children: pending !== null ? `Switching to ${pending}p` : "" }),
|
|
6228
|
+
menu && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
6229
|
+
"ul",
|
|
6230
|
+
{
|
|
6231
|
+
role: "menu",
|
|
6232
|
+
"aria-label": "Quality",
|
|
6233
|
+
className: "tv-menu",
|
|
6234
|
+
onKeyDown: onMenuKey,
|
|
6235
|
+
children: [
|
|
6236
|
+
["auto", ...renditions.map((r) => r.height)].map(
|
|
6237
|
+
(q) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("li", { role: "none", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
6238
|
+
"button",
|
|
6239
|
+
{
|
|
6240
|
+
type: "button",
|
|
6241
|
+
role: "menuitemradio",
|
|
6242
|
+
"aria-checked": selected === q,
|
|
6243
|
+
className: "tv-menu-item",
|
|
6244
|
+
onClick: () => pick(q),
|
|
6245
|
+
children: q === "auto" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
6246
|
+
"Auto",
|
|
6247
|
+
live ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "tv-menu-sub", children: [
|
|
6248
|
+
" ",
|
|
6249
|
+
live,
|
|
6250
|
+
"p"
|
|
6251
|
+
] }) : null
|
|
6252
|
+
] }) : `${q}p`
|
|
6253
|
+
}
|
|
6254
|
+
) }, String(q))
|
|
6255
|
+
),
|
|
6256
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("li", { "aria-hidden": "true", className: "tv-menu-note", children: pending !== null ? `Switching to ${pending}p\u2026` : "" })
|
|
6257
|
+
]
|
|
6258
|
+
}
|
|
6259
|
+
)
|
|
6260
|
+
] }),
|
|
6261
|
+
variant === "16x9" && onTheaterChange && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
6262
|
+
"button",
|
|
6263
|
+
{
|
|
6264
|
+
type: "button",
|
|
6265
|
+
className: "tv-btn tv-theater",
|
|
6266
|
+
"aria-pressed": theater,
|
|
6267
|
+
"aria-label": theater ? "Shrink the player" : "Expand the player",
|
|
6268
|
+
title: theater ? "Shrink" : "Expand",
|
|
6269
|
+
onClick: () => onTheaterChange(!theater),
|
|
6270
|
+
children: theater ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(IconTheaterShrink, {}) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(IconTheaterExpand, {})
|
|
6271
|
+
}
|
|
6272
|
+
),
|
|
6273
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("media-fullscreen-button", { class: "tv-ctl", children: [
|
|
6274
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(IconFullscreenEnter, { slot: "enter" }),
|
|
6275
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(IconFullscreenExit, { slot: "exit" })
|
|
6276
|
+
] })
|
|
6277
|
+
] }),
|
|
6278
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("media-time-range", { class: "tv-seek" })
|
|
6279
|
+
] })
|
|
6280
|
+
] })
|
|
6281
|
+
] }),
|
|
6282
|
+
!playing && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "tv-poster-overlay", children: [
|
|
6283
|
+
renderPoster ? renderPoster({
|
|
6284
|
+
src: resolvedPosterUrl,
|
|
6285
|
+
variant,
|
|
6286
|
+
title,
|
|
6287
|
+
width: posterWidth,
|
|
6288
|
+
height: posterHeight
|
|
6289
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
6290
|
+
"img",
|
|
6291
|
+
{
|
|
6292
|
+
src: resolvedPosterUrl,
|
|
6293
|
+
alt: "",
|
|
6294
|
+
width: posterWidth,
|
|
6295
|
+
height: posterHeight,
|
|
6296
|
+
loading: "lazy",
|
|
6297
|
+
decoding: "async",
|
|
6298
|
+
className: "tv-poster-img"
|
|
6299
|
+
}
|
|
6300
|
+
),
|
|
6301
|
+
!started && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
6302
|
+
"button",
|
|
6303
|
+
{
|
|
6304
|
+
type: "button",
|
|
6305
|
+
onClick: start,
|
|
6306
|
+
"aria-label": `Play video: ${title}`,
|
|
6307
|
+
className: "tv-play-trigger",
|
|
6308
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "tv-play-pill", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(IconPlay, { size: 26, filled: true }) })
|
|
6309
|
+
}
|
|
6310
|
+
)
|
|
6311
|
+
] })
|
|
6312
|
+
]
|
|
6313
|
+
}
|
|
6314
|
+
);
|
|
6315
|
+
}
|
|
6316
|
+
function TrackedVideo(props) {
|
|
6317
|
+
const {
|
|
6318
|
+
id,
|
|
6319
|
+
video,
|
|
6320
|
+
host,
|
|
6321
|
+
sources,
|
|
6322
|
+
title,
|
|
6323
|
+
posterTime,
|
|
6324
|
+
posterUrl,
|
|
6325
|
+
renderPoster,
|
|
6326
|
+
theater: controlledTheater,
|
|
6327
|
+
defaultTheater = false,
|
|
6328
|
+
onTheaterChange,
|
|
6329
|
+
expandMode = "inline",
|
|
6330
|
+
autoExpandOnPlay = true,
|
|
6331
|
+
expandedMaxWidth = 1100,
|
|
6332
|
+
checkpoints = DEFAULT_VIDEO_CHECKPOINTS,
|
|
6333
|
+
trackingConfig,
|
|
6334
|
+
fallbackConfig,
|
|
6335
|
+
client = null,
|
|
6336
|
+
loadPlayerLibs,
|
|
6337
|
+
className = "",
|
|
6338
|
+
style,
|
|
6339
|
+
...callbacks
|
|
6340
|
+
} = props;
|
|
6341
|
+
const videoKey = id ?? video ?? fallbackConfig?.key ?? "";
|
|
6342
|
+
const r2Video = useTrackedVideoConfig(videoKey || void 0, trackingConfig, fallbackConfig);
|
|
6343
|
+
const videoGoals = useActiveVideoGoals(videoKey, trackingConfig);
|
|
6344
|
+
const [internalTheater, setInternalTheater] = (0, import_react8.useState)(defaultTheater);
|
|
6345
|
+
const isTheaterControlled = controlledTheater !== void 0;
|
|
6346
|
+
const activeTheater = isTheaterControlled ? controlledTheater : internalTheater;
|
|
6347
|
+
const handleTheaterChange = (0, import_react8.useCallback)(
|
|
6348
|
+
(next) => {
|
|
6349
|
+
if (!isTheaterControlled) {
|
|
6350
|
+
setInternalTheater(next);
|
|
6351
|
+
}
|
|
6352
|
+
onTheaterChange?.(next);
|
|
6353
|
+
},
|
|
6354
|
+
[isTheaterControlled, onTheaterChange]
|
|
6355
|
+
);
|
|
6356
|
+
const resolvedHost = host ?? r2Video?.host ?? "";
|
|
6357
|
+
const desktopUid = sources?.desktop ?? r2Video?.sources.desktop ?? "";
|
|
6358
|
+
const mobileUid = sources?.mobile ?? r2Video?.sources.mobile ?? desktopUid;
|
|
6359
|
+
const resolvedTitle = title ?? r2Video?.title ?? videoKey;
|
|
6360
|
+
const resolvedPosterTime = posterTime ?? r2Video?.poster_time ?? r2Video?.poster_time_s ?? 4;
|
|
6361
|
+
if (!videoKey || !resolvedHost || !desktopUid) {
|
|
6362
|
+
return null;
|
|
6363
|
+
}
|
|
6364
|
+
const showTheaterControl = expandMode !== "none" && (expandMode === "theater" || Boolean(onTheaterChange));
|
|
6365
|
+
const wrapperStyle = !isTheaterControlled && expandMode === "theater" && activeTheater ? {
|
|
6366
|
+
maxWidth: typeof expandedMaxWidth === "number" ? `${expandedMaxWidth}px` : expandedMaxWidth,
|
|
6367
|
+
marginLeft: "auto",
|
|
6368
|
+
marginRight: "auto",
|
|
6369
|
+
width: "100%",
|
|
6370
|
+
transition: "max-width 360ms cubic-bezier(0.2, 0.7, 0.2, 1)",
|
|
6371
|
+
...style
|
|
6372
|
+
} : style;
|
|
6373
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className, style: wrapperStyle, "data-tracked-video": videoKey, children: [
|
|
6374
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
6375
|
+
Cut,
|
|
6376
|
+
{
|
|
6377
|
+
...callbacks,
|
|
6378
|
+
id: videoKey,
|
|
6379
|
+
variant: "16x9",
|
|
6380
|
+
uid: desktopUid,
|
|
6381
|
+
host: resolvedHost,
|
|
6382
|
+
title: resolvedTitle,
|
|
6383
|
+
posterTime: resolvedPosterTime,
|
|
6384
|
+
posterUrl,
|
|
6385
|
+
renderPoster,
|
|
6386
|
+
theater: activeTheater,
|
|
6387
|
+
onTheaterChange: showTheaterControl ? handleTheaterChange : void 0,
|
|
6388
|
+
autoExpandOnPlay,
|
|
6389
|
+
checkpoints,
|
|
6390
|
+
videoGoals,
|
|
6391
|
+
client,
|
|
6392
|
+
loadPlayerLibs
|
|
6393
|
+
}
|
|
6394
|
+
),
|
|
6395
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
6396
|
+
Cut,
|
|
6397
|
+
{
|
|
6398
|
+
...callbacks,
|
|
6399
|
+
id: videoKey,
|
|
6400
|
+
variant: "9x16",
|
|
6401
|
+
uid: mobileUid || desktopUid,
|
|
6402
|
+
host: resolvedHost,
|
|
6403
|
+
title: resolvedTitle,
|
|
6404
|
+
posterTime: resolvedPosterTime,
|
|
6405
|
+
posterUrl,
|
|
6406
|
+
renderPoster,
|
|
6407
|
+
theater: false,
|
|
6408
|
+
onTheaterChange: void 0,
|
|
6409
|
+
autoExpandOnPlay: false,
|
|
6410
|
+
checkpoints,
|
|
6411
|
+
videoGoals,
|
|
6412
|
+
client,
|
|
6413
|
+
loadPlayerLibs
|
|
6414
|
+
}
|
|
6415
|
+
)
|
|
6416
|
+
] });
|
|
6417
|
+
}
|
|
6418
|
+
var STAGE_DURATION_MS = 360;
|
|
6419
|
+
var STAGE_EASE = "cubic-bezier(0.2, 0.7, 0.2, 1)";
|
|
6420
|
+
function TrackedVideoStage({
|
|
6421
|
+
video,
|
|
6422
|
+
children,
|
|
6423
|
+
expandedMaxWidth = 1100,
|
|
6424
|
+
collapsedTextMaxWidth = 760,
|
|
6425
|
+
className = ""
|
|
6426
|
+
}) {
|
|
6427
|
+
const [theater, setTheater] = (0, import_react8.useState)(video.defaultTheater ?? false);
|
|
6428
|
+
const videoBox = (0, import_react8.useRef)(null);
|
|
6429
|
+
const textBox = (0, import_react8.useRef)(null);
|
|
6430
|
+
const first = (0, import_react8.useRef)(null);
|
|
6431
|
+
const activeTheater = video.theater !== void 0 ? video.theater : theater;
|
|
6432
|
+
const change = (0, import_react8.useCallback)(
|
|
6433
|
+
(next) => {
|
|
6434
|
+
if (next === activeTheater) return;
|
|
6435
|
+
if (next && typeof window !== "undefined" && !window.matchMedia("(min-width: 768px)").matches) {
|
|
6436
|
+
return;
|
|
6437
|
+
}
|
|
6438
|
+
if (videoBox.current && textBox.current) {
|
|
6439
|
+
first.current = {
|
|
6440
|
+
v: videoBox.current.getBoundingClientRect(),
|
|
6441
|
+
t: textBox.current.getBoundingClientRect()
|
|
6442
|
+
};
|
|
6443
|
+
}
|
|
6444
|
+
if (video.theater === void 0) {
|
|
6445
|
+
setTheater(next);
|
|
6446
|
+
}
|
|
6447
|
+
video.onTheaterChange?.(next);
|
|
6448
|
+
},
|
|
6449
|
+
[activeTheater, video]
|
|
6450
|
+
);
|
|
6451
|
+
(0, import_react8.useLayoutEffect)(() => {
|
|
6452
|
+
if (typeof window === "undefined") return;
|
|
6453
|
+
const f = first.current;
|
|
6454
|
+
const vb = videoBox.current;
|
|
6455
|
+
const tb = textBox.current;
|
|
6456
|
+
first.current = null;
|
|
6457
|
+
if (!f || !vb || !tb) return;
|
|
6458
|
+
const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
6459
|
+
const lv = vb.getBoundingClientRect();
|
|
6460
|
+
const lt = tb.getBoundingClientRect();
|
|
6461
|
+
if (!reduce && typeof vb.animate === "function" && lv.width > 0) {
|
|
6462
|
+
const s = f.v.width / lv.width;
|
|
6463
|
+
vb.animate(
|
|
6464
|
+
[
|
|
6465
|
+
{
|
|
6466
|
+
transformOrigin: "top left",
|
|
6467
|
+
transform: `translate(${f.v.left - lv.left}px, ${f.v.top - lv.top}px) scale(${s})`
|
|
6468
|
+
},
|
|
6469
|
+
{ transformOrigin: "top left", transform: "none" }
|
|
6470
|
+
],
|
|
6471
|
+
{ duration: STAGE_DURATION_MS, easing: STAGE_EASE }
|
|
6472
|
+
);
|
|
6473
|
+
tb.animate(
|
|
6474
|
+
[
|
|
6475
|
+
{
|
|
6476
|
+
transform: `translate(${f.t.left - lt.left}px, ${f.t.top - lt.top}px)`,
|
|
6477
|
+
opacity: 0.4
|
|
6478
|
+
},
|
|
6479
|
+
{ transform: "none", opacity: 1 }
|
|
6480
|
+
],
|
|
6481
|
+
{ duration: STAGE_DURATION_MS, easing: STAGE_EASE }
|
|
6482
|
+
);
|
|
6483
|
+
}
|
|
6484
|
+
if (lv.top < 80 || lv.bottom > window.innerHeight - 24) {
|
|
6485
|
+
const top = window.scrollY + lv.top - Math.max(96, (window.innerHeight - lv.height) / 2);
|
|
6486
|
+
window.scrollTo({ top, behavior: reduce ? "auto" : "smooth" });
|
|
6487
|
+
}
|
|
6488
|
+
}, [activeTheater]);
|
|
6489
|
+
const maxVideoWidthCss = typeof expandedMaxWidth === "number" ? `${expandedMaxWidth}px` : expandedMaxWidth;
|
|
6490
|
+
const maxTextWidthCss = typeof collapsedTextMaxWidth === "number" ? `${collapsedTextMaxWidth}px` : collapsedTextMaxWidth;
|
|
6491
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
6492
|
+
"div",
|
|
6493
|
+
{
|
|
6494
|
+
className: activeTheater ? `grid gap-10 md:gap-12 ${className}` : `grid items-start gap-10 lg:grid-cols-[1fr_1fr] lg:gap-16 ${className}`,
|
|
6495
|
+
children: [
|
|
6496
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
6497
|
+
"div",
|
|
6498
|
+
{
|
|
6499
|
+
ref: textBox,
|
|
6500
|
+
className: activeTheater ? "md:order-2" : "",
|
|
6501
|
+
style: activeTheater ? { maxWidth: maxTextWidthCss } : void 0,
|
|
6502
|
+
children
|
|
6503
|
+
}
|
|
6504
|
+
),
|
|
6505
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
6506
|
+
"div",
|
|
6507
|
+
{
|
|
6508
|
+
ref: videoBox,
|
|
6509
|
+
className: activeTheater ? "md:order-1 md:mx-auto md:w-full" : "",
|
|
6510
|
+
style: activeTheater ? { maxWidth: maxVideoWidthCss, width: "100%" } : void 0,
|
|
6511
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
6512
|
+
TrackedVideo,
|
|
6513
|
+
{
|
|
6514
|
+
...video,
|
|
6515
|
+
theater: activeTheater,
|
|
6516
|
+
onTheaterChange: change,
|
|
6517
|
+
className: video.className ?? "w-full"
|
|
6518
|
+
}
|
|
6519
|
+
)
|
|
6520
|
+
}
|
|
6521
|
+
)
|
|
6522
|
+
]
|
|
6523
|
+
}
|
|
6524
|
+
);
|
|
6525
|
+
}
|
|
4808
6526
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4809
6527
|
0 && (module.exports = {
|
|
4810
6528
|
AdPlatformTracking,
|
|
4811
6529
|
BookingHandoffLink,
|
|
4812
6530
|
ConsentBanner,
|
|
6531
|
+
DEFAULT_VIDEO_CHECKPOINTS,
|
|
4813
6532
|
GoogleAdsTracking,
|
|
4814
6533
|
PhoneField,
|
|
6534
|
+
TrackedVideo,
|
|
6535
|
+
TrackedVideoStage,
|
|
4815
6536
|
createLeadFormSubmit,
|
|
4816
6537
|
createTracking,
|
|
6538
|
+
streamManifestUrl,
|
|
6539
|
+
streamPosterUrl,
|
|
4817
6540
|
useBookingHandoffUrl,
|
|
4818
6541
|
useBookingIntegration,
|
|
4819
6542
|
useBookingSlots,
|
|
@@ -4824,6 +6547,7 @@ function useBookingSubmit(bookings, options = {}) {
|
|
|
4824
6547
|
useGclid,
|
|
4825
6548
|
usePhoneConfig,
|
|
4826
6549
|
usePhoneField,
|
|
6550
|
+
useTrackedVideoConfig,
|
|
4827
6551
|
useTrackingParams
|
|
4828
6552
|
});
|
|
4829
6553
|
//# sourceMappingURL=client.js.map
|