@fragmentsx/runtime-react 0.2.0-dev-20261011155313 → 0.2.0-dev-20261022125555

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 CHANGED
@@ -9,14 +9,15 @@ React.
9
9
 
10
10
  Скомпилированный сервером фрагмент — это ESM-артефакт, который нужно
11
11
  загрузить, смонтировать в дерево React, подключить его стили и дать доступ
12
- к метрикам и переменным области. `runtime-react` закрывает весь этот путь:
12
+ к данным области и переменным площадки. `runtime-react` закрывает весь этот путь:
13
13
 
14
14
  - `FragmentsProvider` — контекст клиента на дерево приложения;
15
15
  - `Area` / `FragmentRenderer` — резолвинг области и рендер фрагмента;
16
16
  - `useFragmentComponent`, `useFragmentStylesheet`, `FragmentStylesheet` —
17
17
  подгрузка компонента и его CSS;
18
- - `useFragmentMetrics`, `useArea`, `useProjectProperty` — доступ к метрикам,
19
- данным области и project-переменным площадки внутри фрагмента.
18
+ - `useArea`, `useProjectProperty` — доступ к данным области и
19
+ project-переменным площадки внутри фрагмента;
20
+ - `useGoal` — измерение целей: единственный путь, прежний хук метрик снят.
20
21
 
21
22
  ## Установка
22
23
 
package/dist/index.d.ts CHANGED
@@ -1,9 +1,11 @@
1
+ import { AreaExperiment } from '@fragmentsx/fragments-client';
1
2
  import { AreaSourceTransport } from '@fragmentsx/fragments-client';
2
3
  import { ComponentType } from 'react';
3
4
  import { Context } from 'react';
4
5
  import { createFragmentsClient } from '@fragmentsx/fragments-client';
5
6
  import { CreateFragmentsClientOptions } from '@fragmentsx/fragments-client';
6
7
  import { createSourceCache } from '@fragmentsx/fragments-client';
8
+ import { ExperimentEvent } from '@fragmentsx/fragments-client';
7
9
  import { FC } from 'react';
8
10
  import { FragmentsApiVersionError } from '@fragmentsx/fragments-client';
9
11
  import { FragmentsAreaError } from '@fragmentsx/fragments-client';
@@ -53,6 +55,16 @@ export declare type AreaEmptyReason = {
53
55
  /** D-110-01/D-110-02: semantic category for a terminal area resolution outcome. */
54
56
  export declare type AreaEmptyReasonKind = "no-variant" | "misconfigured" | "failed";
55
57
 
58
+ export declare const AreaExposureContext: Context<AreaExposureValue | null>;
59
+
60
+ export declare interface AreaExposureValue {
61
+ experiment: AreaExperiment;
62
+ viewId: string;
63
+ emit: (event: ExperimentEvent) => void;
64
+ reachedGoals: Set<string>;
65
+ ensureImpression: () => void;
66
+ }
67
+
56
68
  /**
57
69
  * Props для Area компонента (D-09, сокращён Phase 73 B-13; расширен quick 260830-rvp):
58
70
  * - areaCode — строковый код области (Area.code в backend schema)
@@ -303,10 +315,6 @@ declare type FieldRequired<F extends SchemaFieldDescriptor, ConsiderDefault exte
303
315
  */
304
316
  declare type FieldValueType<F extends SchemaFieldDescriptor, D extends number> = F["type"] extends "Enum" ? EnumFieldType<F> : F["type"] extends "Object" ? ObjectFieldType<F, D> : F["type"] extends "Array" ? ArrayFieldType<F, D> : F["type"] extends typeof NODE_SCHEMA_TYPE ? ValueOfNodeType : ValueOfVariableType<Extract<F["type"], VariableType>>;
305
317
 
306
- export declare interface FragmentMetrics {
307
- reachGoal: (info: ReachGoalInfo) => void;
308
- }
309
-
310
318
  /**
311
319
  * Публичный компонент — тело композиции за собственными Suspense + границей
312
320
  * ошибок. `Area` тело не использует напрямую (у неё Suspense/граница уже
@@ -364,9 +372,8 @@ export declare type FragmentsClient = GraphState;
364
372
  /**
365
373
  * Single source of truth для FragmentsClient в compiled output.
366
374
  *
367
- * Значение `null` означает «client ещё не установлен» — defensive в
368
- * `useFragmentMetrics` чтобы reachGoal был no-op (preview / SSG-первая загрузка
369
- * до hydration).
375
+ * Значение `null` означает «client ещё не установлен» (preview / SSG-первая
376
+ * загрузка до hydration) — потребители обязаны это терпеть.
370
377
  */
371
378
  export declare const FragmentsClientContext: Context<FragmentsClient | null>;
372
379
 
@@ -389,7 +396,7 @@ export { FragmentsLoadError }
389
396
  * Unified Provider для compiled fragments.
390
397
  *
391
398
  * Одновременно устанавливает:
392
- * - FragmentsClientContext: client — для useArea cache lookup + $metrics.reachGoal
399
+ * - FragmentsClientContext: client — для useArea cache lookup (цели — через useGoal)
393
400
  * - ModulesMapContext: {read} cache-reader — для useFragmentComponent delegation
394
401
  *
395
402
  * useMemo критично — Context value identity stability (без него cache invalidation
@@ -411,6 +418,14 @@ declare interface FragmentStylesheetProps {
411
418
  fragmentKey: string;
412
419
  }
413
420
 
421
+ /**
422
+ * Пустая карта целей: её дописывает аугментация гейта из реестра проекта. Без
423
+ * аугментации `keyof GoalMap` — `never`, и любой вызов `useGoal` — ошибка
424
+ * компиляции (fail-closed, как `ProjectProperties`).
425
+ */
426
+ export declare interface GoalMap {
427
+ }
428
+
414
429
  /** Присутствие КЛЮЧА `defaultValue`, а не истинность его значения (Phase 97, план 97-02): `defaultValue: 0`/`''`/`false`/`null` — присутствующие значения, `keyof F` включает ключ ровно тогда, когда он был указан в литерале поля. */
415
430
  declare type HasDefaultValueKey<F> = "defaultValue" extends keyof F ? true : false;
416
431
 
@@ -602,19 +617,6 @@ declare type PropsShape<S extends Record<string, SchemaFieldDescriptor>, Conside
602
617
  [K in keyof S as FieldRequired<S[K], ConsiderDefault> extends true ? never : K]?: FieldValueType<S[K], D>;
603
618
  }>;
604
619
 
605
- /**
606
- * Payload для `reachGoal`. Phase 3 НЕ автоинъектит scope-поля
607
- * (variantId / areaId / campaignId) — caller передаёт явно, типизация
608
- * сообщает о доступных полях. Совпадает по shape с
609
- * `client-core.metricsPlugin GoalInfo` (см. metrics/index.ts).
610
- */
611
- export declare interface ReachGoalInfo {
612
- goalId: number;
613
- variantId?: number;
614
- areaId?: number;
615
- campaignId?: number;
616
- }
617
-
618
620
  /**
619
621
  * Дескриптор ОДНОГО поля литерала `schema` артефакта (Phase 97, план 97-02,
620
622
  * TYPES-03/04) — форма, которую `PropsFromSchema` видит в TSX-исходнике
@@ -741,6 +743,12 @@ export declare interface UseAreaResult {
741
743
  * поле обязательное и nullable, а не опциональное.
742
744
  */
743
745
  variantId: number | null;
746
+ /**
747
+ * Phase 128 (D-11, EVT-01): блок эксперимента для трассера аналитики.
748
+ * Обязательное и nullable — по образцу variantId. null — старый манифест,
749
+ * кампания не активна, превью или сентинел AREA_UNRESOLVED.
750
+ */
751
+ experiment: AreaExperiment | null;
744
752
  /**
745
753
  * Phase 73, B-02/B-06: значения props корневого артефакта, разрешённые сервером
746
754
  * (`resolveVariantProps`) — привязки `$ref` сюда не доезжают, только готовые значения.
@@ -830,16 +838,10 @@ export declare function useCssChunk(_chunkId: number): void;
830
838
 
831
839
  export declare function useFragmentComponent(fragmentId: number): ComponentType<any>;
832
840
 
833
- /**
834
- * Возвращает обёртку над client.$metrics.reachGoal.
835
- *
836
- * - Без `<FragmentsClientProvider>` — reachGoal no-op (не бросает).
837
- * - С provider — делегирует на `client.$metrics.reachGoal(info)`.
838
- */
839
- export declare function useFragmentMetrics(): FragmentMetrics;
840
-
841
841
  export declare function useFragmentStylesheet(href: string, key: string): void;
842
842
 
843
+ export declare function useGoal<K extends keyof GoalMap & string>(key: K): () => void;
844
+
843
845
  export declare function useProjectProperty<K extends keyof ProjectProperties>(name: K): ProjectProperties[K];
844
846
 
845
847
  export declare type UseSource = <S extends keyof SourceMap & string, O extends keyof SourceMap[S] & string>(source: S, options: Options<S, O>) => UseSourceResult<Operation<S, O>["response"]>;
package/dist/index.es.js CHANGED
@@ -1,51 +1,40 @@
1
- import { jsx as i, jsxs as oe, Fragment as le } from "react/jsx-runtime";
2
- import * as de from "react";
3
- import { createContext as N, useContext as g, useMemo as k, useState as w, useEffect as P, useLayoutEffect as ie, version as fe, Component as me, Suspense as G, createElement as he, useCallback as _, useRef as x, useReducer as Ee } from "react";
4
- import { FragmentsAreaError as ge, toScopeClassName as ve, AREA_GLOBAL_CSS_KEY as ye, resolveStylesHref as Se, fragmentCssKey as Pe, createSourceCache as Ne, sourceCallKey as D, sourceTransportKey as Ae, resolveSourceRequest as Ce, runSourceFetch as ke, createFragmentsClient as Oe } from "@fragmentsx/fragments-client";
5
- import { FragmentsApiVersionError as ar, FragmentsAreaError as cr, FragmentsLoadError as ur, createSourceCache as or } from "@fragmentsx/fragments-client";
6
- const C = N(
1
+ import { jsx as l, jsxs as Ie, Fragment as Ne } from "react/jsx-runtime";
2
+ import * as ke from "react";
3
+ import { createContext as I, useContext as w, useState as L, useEffect as R, useLayoutEffect as _e, version as Fe, Component as Me, Suspense as de, useMemo as j, createElement as Le, useRef as A, useCallback as B, useReducer as je } from "react";
4
+ import { FragmentsAreaError as Be, toScopeClassName as He, AREA_GLOBAL_CSS_KEY as Ue, resolveStylesHref as $e, fragmentCssKey as De, createSourceCache as Ve, sourceCallKey as re, sourceTransportKey as ze, resolveSourceRequest as Ke, runSourceFetch as Ge, createFragmentsClient as Ye } from "@fragmentsx/fragments-client";
5
+ import { FragmentsApiVersionError as kr, FragmentsAreaError as _r, FragmentsLoadError as Fr, createSourceCache as Mr } from "@fragmentsx/fragments-client";
6
+ const F = I(
7
7
  null
8
8
  );
9
- C.displayName = "FragmentsClientContext";
10
- function we(r) {
11
- return /* @__PURE__ */ i(C.Provider, { value: r.value, children: r.children });
9
+ F.displayName = "FragmentsClientContext";
10
+ function Je(r) {
11
+ return /* @__PURE__ */ l(F.Provider, { value: r.value, children: r.children });
12
12
  }
13
- function Te() {
14
- return g(C);
13
+ function We() {
14
+ return w(F);
15
15
  }
16
- const J = N(null);
17
- J.displayName = "InstanceIdContext";
18
- const T = N(
16
+ const fe = I(null);
17
+ fe.displayName = "InstanceIdContext";
18
+ const V = I(
19
19
  null
20
20
  );
21
- T.displayName = "ModulesMapContext";
22
- function be({
21
+ V.displayName = "ModulesMapContext";
22
+ function Xe({
23
23
  value: r,
24
24
  children: e
25
25
  }) {
26
- return /* @__PURE__ */ i(T.Provider, { value: r, children: e });
26
+ return /* @__PURE__ */ l(V.Provider, { value: r, children: e });
27
27
  }
28
- function qe() {
29
- const r = g(C);
30
- return k(
31
- () => ({
32
- reachGoal: (e) => {
33
- var t, n;
34
- (n = (t = r == null ? void 0 : r.$metrics) == null ? void 0 : t.reachGoal) == null || n.call(t, e);
35
- }
36
- }),
37
- [r]
38
- );
39
- }
40
- function Fe(r) {
41
- const e = g(T);
28
+ function qe(r) {
29
+ const e = w(V);
42
30
  if (!e)
43
31
  throw new Error("[useFragmentComponent] No ModulesMapProvider in tree");
44
32
  return e.read(r);
45
33
  }
46
- const L = typeof window < "u", H = Object.freeze({
34
+ const te = typeof window < "u", ne = Object.freeze({
47
35
  rootFragmentId: 0,
48
36
  variantId: null,
37
+ experiment: null,
49
38
  props: {},
50
39
  projectProperties: {},
51
40
  projectBindings: {},
@@ -57,100 +46,100 @@ const L = typeof window < "u", H = Object.freeze({
57
46
  slots: {},
58
47
  sources: {}
59
48
  });
60
- function R(r) {
49
+ function G(r) {
61
50
  const e = r.$area;
62
51
  if (!(e != null && e.read))
63
52
  throw new Error("[useArea] $area plugin not mounted");
64
53
  return e;
65
54
  }
66
- function Re(r, e) {
67
- const t = g(C);
55
+ function Qe(r, e) {
56
+ const t = w(F);
68
57
  if (!t)
69
58
  throw new Error("[useArea] No FragmentsClientProvider in tree");
70
- const n = (e == null ? void 0 : e.suspense) ?? !0, s = (e == null ? void 0 : e.pause) === !0 || !L && (e == null ? void 0 : e.ssr) === !1, a = (e == null ? void 0 : e.timeout) != null ? { timeout: e.timeout } : void 0, [, o] = w(0);
71
- if (P(() => {
59
+ const n = (e == null ? void 0 : e.suspense) ?? !0, s = (e == null ? void 0 : e.pause) === !0 || !te && (e == null ? void 0 : e.ssr) === !1, c = (e == null ? void 0 : e.timeout) != null ? { timeout: e.timeout } : void 0, [, o] = L(0);
60
+ if (R(() => {
72
61
  if (n || s) return;
73
- const c = R(t);
74
- let u = !0;
75
- return Promise.resolve(c.resolve(r, a)).catch(() => {
62
+ const u = G(t);
63
+ let a = !0;
64
+ return Promise.resolve(u.resolve(r, c)).catch(() => {
76
65
  }).finally(() => {
77
- u && o((f) => f + 1);
66
+ a && o((d) => d + 1);
78
67
  }), () => {
79
- u = !1;
68
+ a = !1;
80
69
  };
81
70
  }, [r, n, e == null ? void 0 : e.pause, e == null ? void 0 : e.timeout, e == null ? void 0 : e.ssr]), n) {
82
71
  if (s)
83
- return H;
84
- const c = R(t);
85
- if (c.has(r) || Promise.resolve(c.resolve(r, a)).catch(() => {
86
- }), !L)
72
+ return ne;
73
+ const u = G(t);
74
+ if (u.has(r) || Promise.resolve(u.resolve(r, c)).catch(() => {
75
+ }), !te)
87
76
  try {
88
- return c.read(r);
89
- } catch (u) {
90
- if (u != null && typeof u.then == "function")
91
- throw u;
77
+ return u.read(r);
78
+ } catch (a) {
79
+ if (a != null && typeof a.then == "function")
80
+ throw a;
92
81
  return process.env.NODE_ENV !== "production" && console.error(
93
82
  `[useArea] Area ${r} remained unresolved on the server because its cache reached a terminal state`,
94
- u
95
- ), H;
83
+ a
84
+ ), ne;
96
85
  }
97
- return c.read(r);
86
+ return u.read(r);
98
87
  }
99
88
  if (s)
100
89
  return { status: "idle", data: null, error: null };
101
- const h = R(t);
102
- if (h.has(r))
90
+ const m = G(t);
91
+ if (m.has(r))
103
92
  try {
104
- return { status: "ready", data: h.read(r), error: null };
105
- } catch (c) {
93
+ return { status: "ready", data: m.read(r), error: null };
94
+ } catch (u) {
106
95
  return {
107
96
  status: "not-found",
108
97
  data: null,
109
- error: c instanceof Error ? c : new Error(String(c))
98
+ error: u instanceof Error ? u : new Error(String(u))
110
99
  };
111
100
  }
112
- return Promise.resolve(h.resolve(r, a)).catch(() => {
101
+ return Promise.resolve(m.resolve(r, c)).catch(() => {
113
102
  }), { status: "loading", data: null, error: null };
114
103
  }
115
- const q = typeof window < "u", _e = 3e3, O = /* @__PURE__ */ new Map(), Q = (r, e) => {
116
- if (!q) {
117
- const E = () => {
104
+ const me = typeof window < "u", Ze = 3e3, D = /* @__PURE__ */ new Map(), he = (r, e) => {
105
+ if (!me) {
106
+ const h = () => {
118
107
  };
119
- return E.loaded = Promise.resolve(), E;
108
+ return h.loaded = Promise.resolve(), h;
120
109
  }
121
- const t = O.get(e);
110
+ const t = D.get(e);
122
111
  if (t) {
123
112
  t.refCount += 1;
124
- const E = () => {
125
- t.refCount -= 1, t.refCount === 0 && (t.clearReadyTimer(), t.linkEl.remove(), O.delete(e));
113
+ const h = () => {
114
+ t.refCount -= 1, t.refCount === 0 && (t.clearReadyTimer(), t.linkEl.remove(), D.delete(e));
126
115
  };
127
- return E.loaded = t.loaded, E;
116
+ return h.loaded = t.loaded, h;
128
117
  }
129
118
  const n = document.createElement("link");
130
119
  n.rel = "stylesheet", n.href = r, n.setAttribute("data-fragment-key", e);
131
120
  let s;
132
- const a = new Promise((E) => {
133
- s = E;
121
+ const c = new Promise((h) => {
122
+ s = h;
134
123
  }), o = () => {
135
- c(), s();
136
- }, h = setTimeout(o, _e), c = () => clearTimeout(h);
124
+ u(), s();
125
+ }, m = setTimeout(o, Ze), u = () => clearTimeout(m);
137
126
  n.addEventListener("load", o), n.addEventListener("error", o), document.head.appendChild(n);
138
- const u = { refCount: 1, linkEl: n, loaded: a, clearReadyTimer: c };
139
- O.set(e, u);
140
- const f = () => {
141
- u.refCount -= 1, u.refCount === 0 && (u.clearReadyTimer(), u.linkEl.remove(), O.delete(e));
127
+ const a = { refCount: 1, linkEl: n, loaded: c, clearReadyTimer: u };
128
+ D.set(e, a);
129
+ const d = () => {
130
+ a.refCount -= 1, a.refCount === 0 && (a.clearReadyTimer(), a.linkEl.remove(), D.delete(e));
142
131
  };
143
- return f.loaded = a, f;
144
- }, xe = q ? ie : P;
145
- function je(r, e) {
146
- xe(() => Q(r, e), [r, e]);
132
+ return d.loaded = c, d;
133
+ }, er = me ? _e : R;
134
+ function rr(r, e) {
135
+ er(() => he(r, e), [r, e]);
147
136
  }
148
- const Ie = parseInt(fe.split(".")[0], 10), Me = Ie >= 19;
149
- function U({
137
+ const tr = parseInt(Fe.split(".")[0], 10), nr = tr >= 19;
138
+ function oe({
150
139
  href: r,
151
140
  fragmentKey: e
152
141
  }) {
153
- return Me ? /* @__PURE__ */ i(
142
+ return nr ? /* @__PURE__ */ l(
154
143
  "link",
155
144
  {
156
145
  rel: "stylesheet",
@@ -158,50 +147,50 @@ function U({
158
147
  precedence: "default",
159
148
  "data-fragment-key": e
160
149
  }
161
- ) : (je(r, e), null);
150
+ ) : (rr(r, e), null);
162
151
  }
163
- function Qe(r) {
152
+ function Sr(r) {
164
153
  }
165
- const W = Object.freeze({}), b = N(W);
166
- b.displayName = "HostPropertiesContext";
167
- const X = {}, j = N(null);
168
- j.displayName = "ProjectPropertiesContext";
169
- const Z = Object.freeze({}), I = N(Z);
170
- I.displayName = "SourceTransportsContext";
171
- const M = N("live");
172
- M.displayName = "SourceNetworkContext";
173
- function V(r) {
154
+ const ve = Object.freeze({}), z = I(ve);
155
+ z.displayName = "HostPropertiesContext";
156
+ const ge = {}, Y = I(null);
157
+ Y.displayName = "ProjectPropertiesContext";
158
+ const Ee = Object.freeze({}), J = I(Ee);
159
+ J.displayName = "SourceTransportsContext";
160
+ const W = I("live");
161
+ W.displayName = "SourceNetworkContext";
162
+ function se(r) {
174
163
  const e = r instanceof Error ? r : new Error(String(r));
175
- if (!(e instanceof ge))
164
+ if (!(e instanceof Be))
176
165
  return { kind: "failed", error: e };
177
166
  const { code: t } = e;
178
167
  return t === "NO_ACTIVE_VARIANT" ? { kind: "no-variant", code: t, error: e } : t === "AREA_NOT_FOUND" || t === "NO_PUBLISHED_SNAPSHOT" || t === "NESTED_SNAPSHOT_MISSING" ? { kind: "misconfigured", code: t, error: e } : { kind: "failed", code: t, error: e };
179
168
  }
180
- function ee(r, e, t) {
169
+ function ye(r, e, t) {
181
170
  return typeof r == "function" ? r(e, t) : r ?? null;
182
171
  }
183
- const pe = () => {
172
+ const or = () => {
184
173
  };
185
- function K(r) {
174
+ function ce(r) {
186
175
  return r instanceof Error ? r : new Error(String(r));
187
176
  }
188
- class re extends me {
177
+ class pe extends Me {
189
178
  constructor() {
190
179
  super(...arguments), this.state = { hasError: !1, error: null };
191
180
  }
192
181
  static getDerivedStateFromError(e) {
193
- return { hasError: !0, error: K(e) };
182
+ return { hasError: !0, error: ce(e) };
194
183
  }
195
184
  componentDidCatch(e, t) {
196
- var s, a;
197
- const n = K(e);
198
- process.env.NODE_ENV !== "production" && console.error("[fragments] Area error:", n, t.componentStack), (a = (s = this.props).onError) == null || a.call(s, n);
185
+ var s, c;
186
+ const n = ce(e);
187
+ process.env.NODE_ENV !== "production" && console.error("[fragments] Area error:", n, t.componentStack), (c = (s = this.props).onError) == null || c.call(s, n);
199
188
  }
200
189
  render() {
201
190
  if (this.state.hasError) {
202
191
  const e = { kind: "failed", error: this.state.error ?? new Error("Unknown Area error") };
203
192
  try {
204
- return ee(this.props.empty, e, this.props.retry ?? pe);
193
+ return ye(this.props.empty, e, this.props.retry ?? or);
205
194
  } catch {
206
195
  return null;
207
196
  }
@@ -209,36 +198,36 @@ class re extends me {
209
198
  return this.props.children;
210
199
  }
211
200
  }
212
- function $e(r, e) {
201
+ function sr(r, e) {
213
202
  let t;
214
203
  for (const [n, s] of Object.entries(e))
215
204
  s != null && (t ?? (t = { ...r }), t[n] = s);
216
205
  return t ?? r;
217
206
  }
218
- function Be(r, e) {
207
+ function cr(r, e) {
219
208
  const t = Object.keys(r);
220
209
  return t.length !== Object.keys(e).length ? !1 : t.every((n) => Object.prototype.hasOwnProperty.call(e, n) && Object.is(r[n], e[n]));
221
210
  }
222
- const te = Object.freeze({});
223
- function ne(r, e, t) {
211
+ const xe = Object.freeze({});
212
+ function we(r, e, t) {
224
213
  let n;
225
- for (const [s, a] of Object.entries(e)) {
226
- const o = t[a];
214
+ for (const [s, c] of Object.entries(e)) {
215
+ const o = t[c];
227
216
  o != null && (n ?? (n = { ...r }), n[s] = o);
228
217
  }
229
218
  return n ?? r;
230
219
  }
231
- function se(r, e, t) {
220
+ function Se(r, e, t) {
232
221
  if (!r) return {};
233
222
  const n = {};
234
223
  for (const s of Object.keys(r))
235
- n[s] = De(r[s], e, t);
224
+ n[s] = ur(r[s], e, t);
236
225
  return n;
237
226
  }
238
- function De(r, e, t) {
239
- return Array.isArray(r) ? r.map((n, s) => n === null ? null : z(n, e, t, s)) : z(r, e, t);
227
+ function ur(r, e, t) {
228
+ return Array.isArray(r) ? r.map((n, s) => n === null ? null : ue(n, e, t, s)) : ue(r, e, t);
240
229
  }
241
- function z(r, e, t, n) {
230
+ function ue(r, e, t, n) {
242
231
  let s;
243
232
  try {
244
233
  s = e(r.fragmentId);
@@ -247,176 +236,371 @@ function z(r, e, t, n) {
247
236
  throw o;
248
237
  return console.warn(`[FragmentRenderer] Slot fragment ${r.fragmentId} failed to load — rendering empty hole`, o), null;
249
238
  }
250
- const a = se(r.slots, e, t);
251
- return he(s, { key: n, ...ne(r.props, r.projectBindings ?? te, t), ...a });
239
+ const c = Se(r.slots, e, t);
240
+ return Le(s, { key: n, ...we(r.props, r.projectBindings ?? xe, t), ...c });
252
241
  }
253
- const ae = ({
242
+ const be = ({
254
243
  fragmentId: r,
255
244
  props: e,
256
245
  globalCssUrl: t = null,
257
- projectProperties: n = X,
246
+ projectProperties: n = ge,
258
247
  fragments: s = [r],
259
- slots: a,
260
- sources: o = Z,
261
- sourceNetwork: h = "live"
248
+ slots: c,
249
+ sources: o = Ee,
250
+ sourceNetwork: m = "live"
262
251
  }) => {
263
- const c = Fe(r), u = g(T), f = g(b);
264
- if (!u)
252
+ const u = qe(r), a = w(V), d = w(z);
253
+ if (!a)
265
254
  throw new Error("[FragmentRendererInner] No ModulesMapProvider in tree");
266
- const E = se(a, u.read, f), A = k(
267
- () => $e(n, f),
268
- [n, f]
269
- ), l = { ...e ?? {}, ...E }, v = s.length > 0 ? s.map(ve).join(" ") : void 0;
270
- return /* @__PURE__ */ oe(le, { children: [
271
- t != null && /* @__PURE__ */ i(
272
- U,
255
+ const h = Se(c, a.read, d), S = j(
256
+ () => sr(n, d),
257
+ [n, d]
258
+ ), f = { ...e ?? {}, ...h }, T = s.length > 0 ? s.map(He).join(" ") : void 0;
259
+ return /* @__PURE__ */ Ie(Ne, { children: [
260
+ t != null && /* @__PURE__ */ l(
261
+ oe,
273
262
  {
274
263
  href: t,
275
- fragmentKey: ye
264
+ fragmentKey: Ue
276
265
  }
277
266
  ),
278
- s.map((y) => {
279
- const m = Se(y);
280
- return m ? /* @__PURE__ */ i(
281
- U,
267
+ s.map((v) => {
268
+ const p = $e(v);
269
+ return p ? /* @__PURE__ */ l(
270
+ oe,
282
271
  {
283
- href: m,
284
- fragmentKey: Pe(y)
272
+ href: p,
273
+ fragmentKey: De(v)
285
274
  },
286
- y
275
+ v
287
276
  ) : null;
288
277
  }),
289
- /* @__PURE__ */ i(M.Provider, { value: h, children: /* @__PURE__ */ i(I.Provider, { value: o, children: /* @__PURE__ */ i(j.Provider, { value: A, children: /* @__PURE__ */ i(J.Provider, { value: null, children: /* @__PURE__ */ i(
278
+ /* @__PURE__ */ l(W.Provider, { value: m, children: /* @__PURE__ */ l(J.Provider, { value: o, children: /* @__PURE__ */ l(Y.Provider, { value: S, children: /* @__PURE__ */ l(fe.Provider, { value: null, children: /* @__PURE__ */ l(
290
279
  "div",
291
280
  {
292
- className: v,
281
+ className: T,
293
282
  style: { display: "contents" },
294
- children: /* @__PURE__ */ i(c, { ...l })
283
+ children: /* @__PURE__ */ l(u, { ...f })
295
284
  }
296
285
  ) }) }) }) })
297
286
  ] });
298
- }, We = ({ onError: r, ...e }) => /* @__PURE__ */ i(G, { fallback: null, children: /* @__PURE__ */ i(re, { onError: r, children: /* @__PURE__ */ i(ae, { ...e }) }) }), Le = ({ areaCode: r, options: e, retry: t }) => {
299
- const n = Re(r, {
287
+ }, br = ({ onError: r, ...e }) => /* @__PURE__ */ l(de, { fallback: null, children: /* @__PURE__ */ l(pe, { onError: r, children: /* @__PURE__ */ l(be, { ...e }) }) }), X = I(null);
288
+ X.displayName = "AreaExposureContext";
289
+ const ar = 1e3, ir = Array.from({ length: 101 }, (r, e) => e / 100);
290
+ function lr({
291
+ visibleArea: r,
292
+ totalArea: e,
293
+ visibleHeight: t,
294
+ viewportHeight: n
295
+ }) {
296
+ if (r <= 0)
297
+ return !1;
298
+ const s = e > 0 && r >= 0.5 * e, c = n > 0 && t >= 0.5 * n;
299
+ return s || c;
300
+ }
301
+ function ae() {
302
+ return typeof crypto < "u" && typeof crypto.randomUUID == "function" ? crypto.randomUUID() : "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (r) => {
303
+ const e = Math.random() * 16 | 0;
304
+ return (r === "x" ? e : e & 3 | 8).toString(16);
305
+ });
306
+ }
307
+ function ie(r) {
308
+ const e = r.getBoundingClientRect();
309
+ return e.width > 0 && e.height > 0;
310
+ }
311
+ function dr(r) {
312
+ const e = [];
313
+ function t(n, s) {
314
+ var c;
315
+ for (const o of Array.from(n.children)) {
316
+ let m = "";
317
+ try {
318
+ m = window.getComputedStyle(o).display;
319
+ } catch {
320
+ m = ((c = o.style) == null ? void 0 : c.display) || "";
321
+ }
322
+ if (m === "contents")
323
+ t(o, s);
324
+ else if (m === "none" || ie(o))
325
+ s.push(o);
326
+ else {
327
+ const u = [];
328
+ t(o, u), u.some(ie) ? s.push(...u) : s.push(o);
329
+ }
330
+ }
331
+ }
332
+ return t(r, e), e;
333
+ }
334
+ const fr = ({
335
+ experiment: r,
336
+ emit: e,
337
+ children: t
338
+ }) => {
339
+ const [n, s] = L(ae), c = A(!1), o = A(null), m = A(/* @__PURE__ */ new Set()), u = A(null), a = A(r);
340
+ a.current = r;
341
+ const d = A(e);
342
+ d.current = e;
343
+ const h = A(n);
344
+ h.current = n;
345
+ const S = B(() => {
346
+ c.current || (c.current = !0, o.current && (clearTimeout(o.current), o.current = null), d.current({
347
+ type: "impression",
348
+ experiment: a.current,
349
+ viewId: h.current
350
+ }));
351
+ }, []), f = j(
352
+ () => ({
353
+ experiment: r,
354
+ viewId: n,
355
+ emit: e,
356
+ reachedGoals: m.current,
357
+ ensureImpression: S
358
+ }),
359
+ [r, n, e, S]
360
+ );
361
+ return R(() => {
362
+ if (typeof window > "u" || typeof IntersectionObserver > "u")
363
+ return;
364
+ const T = u.current;
365
+ if (!T) return;
366
+ let v = [];
367
+ const p = /* @__PURE__ */ new Map(), i = () => !(typeof document > "u" || "visibilityState" in document && document.visibilityState === "hidden" || "prerendering" in document && document.prerendering), y = () => {
368
+ if (c.current || v.length === 0) return;
369
+ let P = 0, E = 0, M = !1, k = 1 / 0, _ = -1 / 0;
370
+ for (const K of v) {
371
+ const x = p.get(K);
372
+ x && (P += x.interArea, E += x.boundArea, x.interArea > 0 && x.interBottom > x.interTop && (M = !0, x.interTop < k && (k = x.interTop), x.interBottom > _ && (_ = x.interBottom)));
373
+ }
374
+ const U = M ? Math.max(0, _ - k) : 0, $ = typeof window < "u" ? window.innerHeight : 0;
375
+ i() && lr({
376
+ visibleArea: P,
377
+ totalArea: E,
378
+ visibleHeight: U,
379
+ viewportHeight: $
380
+ }) ? o.current || (o.current = setTimeout(() => {
381
+ o.current = null, S();
382
+ }, ar)) : o.current && (clearTimeout(o.current), o.current = null);
383
+ }, g = new IntersectionObserver(
384
+ (P) => {
385
+ var E, M, k, _, U, $;
386
+ for (const O of P) {
387
+ const K = ((E = O.boundingClientRect) == null ? void 0 : E.width) ?? 0, x = ((M = O.boundingClientRect) == null ? void 0 : M.height) ?? 0, Ae = ((k = O.intersectionRect) == null ? void 0 : k.width) ?? 0, Te = ((_ = O.intersectionRect) == null ? void 0 : _.height) ?? 0, ee = K * x, Re = Ae * Te, Ce = ((U = O.intersectionRect) == null ? void 0 : U.top) ?? 0, Oe = (($ = O.intersectionRect) == null ? void 0 : $.bottom) ?? 0;
388
+ p.set(O.target, {
389
+ interArea: ee > 0 ? Re : 0,
390
+ boundArea: ee,
391
+ interTop: Ce,
392
+ interBottom: Oe
393
+ });
394
+ }
395
+ c.current || y();
396
+ },
397
+ { threshold: ir }
398
+ ), C = () => {
399
+ if (c.current || !u.current) return;
400
+ const P = dr(u.current);
401
+ for (const E of v)
402
+ P.includes(E) || (g.unobserve(E), p.delete(E));
403
+ for (const E of P)
404
+ v.includes(E) || g.observe(E);
405
+ v = P;
406
+ };
407
+ C();
408
+ let b = null;
409
+ typeof MutationObserver < "u" && (b = new MutationObserver(() => {
410
+ c.current || C();
411
+ }), b.observe(T, { childList: !0, subtree: !0 }));
412
+ const N = () => {
413
+ typeof document < "u" && document.visibilityState === "hidden" ? o.current && (clearTimeout(o.current), o.current = null) : y();
414
+ }, H = () => {
415
+ y();
416
+ }, q = () => {
417
+ o.current && (clearTimeout(o.current), o.current = null);
418
+ }, Q = () => {
419
+ y();
420
+ }, Z = (P) => {
421
+ if (P.persisted) {
422
+ o.current && (clearTimeout(o.current), o.current = null), c.current = !1;
423
+ const E = ae();
424
+ h.current = E, s(E), y();
425
+ }
426
+ };
427
+ return typeof document < "u" && (document.addEventListener("visibilitychange", N), document.addEventListener("prerenderingchange", H)), typeof window < "u" && (window.addEventListener("pagehide", q), window.addEventListener("resize", Q), window.addEventListener("pageshow", Z)), () => {
428
+ o.current && (clearTimeout(o.current), o.current = null), g.disconnect(), b && b.disconnect(), typeof document < "u" && (document.removeEventListener("visibilitychange", N), document.removeEventListener("prerenderingchange", H)), typeof window < "u" && (window.removeEventListener("pagehide", q), window.removeEventListener("resize", Q), window.removeEventListener("pageshow", Z));
429
+ };
430
+ }, [r, e]), /* @__PURE__ */ l(X.Provider, { value: f, children: /* @__PURE__ */ l("div", { ref: u, style: { display: "contents" }, children: t }) });
431
+ }, mr = ({ areaCode: r, options: e, retry: t }) => {
432
+ const n = Qe(r, {
300
433
  suspense: !1,
301
434
  ssr: !1,
302
435
  pause: e == null ? void 0 : e.pause,
303
436
  timeout: e == null ? void 0 : e.timeout
304
- }), s = g(b), a = x(null);
305
- if (P(() => {
306
- var S;
437
+ }), s = w(z), c = w(F), o = A(null);
438
+ if (R(() => {
439
+ var b;
307
440
  if (n.status !== "not-found" || !n.error) return;
308
- const m = V(n.error), d = JSON.stringify([r, m.kind, m.code, m.error.message]);
309
- a.current !== d && (a.current = d, (S = e == null ? void 0 : e.onError) == null || S.call(e, m.error), process.env.NODE_ENV !== "production" && m.kind !== "no-variant" && console.error(
310
- `[fragments] Area resolution ${m.kind}: areaCode=${r}, code=${m.code ?? "none"}`,
311
- m.error
441
+ const g = se(n.error), C = JSON.stringify([
442
+ r,
443
+ g.kind,
444
+ g.code,
445
+ g.error.message
446
+ ]);
447
+ o.current !== C && (o.current = C, (b = e == null ? void 0 : e.onError) == null || b.call(e, g.error), process.env.NODE_ENV !== "production" && g.kind !== "no-variant" && console.error(
448
+ `[fragments] Area resolution ${g.kind}: areaCode=${r}, code=${g.code ?? "none"}`,
449
+ g.error
312
450
  ));
313
451
  }, [r, e == null ? void 0 : e.onError, n.error, n.status]), (e == null ? void 0 : e.pause) === !0)
314
452
  return null;
315
453
  if (n.status === "idle")
316
454
  return (e == null ? void 0 : e.fallback) ?? null;
317
455
  if (n.status === "not-found")
318
- return ee(e == null ? void 0 : e.empty, V(n.error), t);
456
+ return ye(
457
+ e == null ? void 0 : e.empty,
458
+ se(n.error),
459
+ t
460
+ );
319
461
  if (n.status === "loading" || !n.data)
320
462
  return (e == null ? void 0 : e.fallback) ?? null;
321
- const { rootFragmentId: o, props: h, projectProperties: c, globalCssUrl: u, fragments: f, slots: E, sources: A, projectBindings: l } = n.data, v = ne(h, l ?? te, s), y = typeof (e == null ? void 0 : e.props) == "function" ? e.props(v) : e != null && e.props ? { ...v, ...e.props } : v;
322
- return /* @__PURE__ */ i(G, { fallback: (e == null ? void 0 : e.fallback) ?? null, children: /* @__PURE__ */ i(
323
- ae,
463
+ const {
464
+ rootFragmentId: m,
465
+ props: u,
466
+ projectProperties: a,
467
+ globalCssUrl: d,
468
+ fragments: h,
469
+ slots: S,
470
+ sources: f,
471
+ projectBindings: T
472
+ } = n.data, v = we(
473
+ u,
474
+ T ?? xe,
475
+ s
476
+ ), p = typeof (e == null ? void 0 : e.props) == "function" ? e.props(v) : e != null && e.props ? { ...v, ...e.props } : v, i = n.data.experiment, y = /* @__PURE__ */ l(
477
+ be,
324
478
  {
325
- fragmentId: o,
326
- props: y,
327
- globalCssUrl: u,
328
- projectProperties: c,
329
- fragments: f,
330
- slots: E,
331
- sources: A
479
+ fragmentId: m,
480
+ props: p,
481
+ globalCssUrl: d,
482
+ projectProperties: a,
483
+ fragments: h,
484
+ slots: S,
485
+ sources: f
332
486
  }
333
- ) });
334
- }, Xe = ({ areaCode: r, options: e }) => {
335
- const t = g(C), [n, s] = w(0), a = t == null ? void 0 : t.$area;
336
- P(() => {
487
+ );
488
+ return /* @__PURE__ */ l(de, { fallback: (e == null ? void 0 : e.fallback) ?? null, children: i && (c != null && c.$events) ? /* @__PURE__ */ l(
489
+ fr,
490
+ {
491
+ experiment: i,
492
+ emit: c.$events.emit,
493
+ children: y
494
+ },
495
+ `${i.label}:${i.variantId}`
496
+ ) : y });
497
+ }, Pr = ({ areaCode: r, options: e }) => {
498
+ const t = w(F), [n, s] = L(0), c = t == null ? void 0 : t.$area;
499
+ R(() => {
337
500
  (e == null ? void 0 : e.ssr) !== !0 || process.env.NODE_ENV === "production" || console.error(
338
501
  "[fragments] Area option `ssr` is reserved: server resolution has been removed from the runtime; existing `ssr: false` calls continue to work unchanged."
339
502
  );
340
503
  }, [e == null ? void 0 : e.ssr]);
341
- const o = _(() => {
342
- a != null && a.resolve && (a.resolve(r).catch(() => {
343
- }), s((h) => h + 1));
344
- }, [a, r]);
504
+ const o = B(() => {
505
+ c != null && c.resolve && (c.resolve(r).catch(() => {
506
+ }), s((m) => m + 1));
507
+ }, [c, r]);
345
508
  return (
346
509
  // A retry remounts the boundary and AreaInner: a repeated failure is a new
347
510
  // telemetry event, so AreaInner intentionally calls options.onError again.
348
- /* @__PURE__ */ i(re, { onError: e == null ? void 0 : e.onError, empty: e == null ? void 0 : e.empty, retry: o, children: /* @__PURE__ */ i(Le, { areaCode: r, options: e, retry: o }) }, n)
511
+ /* @__PURE__ */ l(
512
+ pe,
513
+ {
514
+ onError: e == null ? void 0 : e.onError,
515
+ empty: e == null ? void 0 : e.empty,
516
+ retry: o,
517
+ children: /* @__PURE__ */ l(mr, { areaCode: r, options: e, retry: o })
518
+ },
519
+ n
520
+ )
349
521
  );
350
522
  };
351
- function He(r) {
352
- const e = r ?? W, t = x(e);
353
- return Be(t.current, e) || (t.current = e), t.current;
523
+ function hr(r) {
524
+ const e = r ?? ve, t = A(e);
525
+ return cr(t.current, e) || (t.current = e), t.current;
354
526
  }
355
- function Ze({ client: r, children: e, properties: t }) {
356
- const n = k(
527
+ function Ar({ client: r, children: e, properties: t }) {
528
+ const n = j(
357
529
  () => ({
358
- read: (a) => r.$fragments.read(a)
530
+ read: (c) => r.$fragments.read(c)
359
531
  }),
360
532
  [r]
361
- ), s = He(t);
362
- return /* @__PURE__ */ i(we, { value: r, children: /* @__PURE__ */ i(be, { value: n, children: /* @__PURE__ */ i(b.Provider, { value: s, children: e }) }) });
533
+ ), s = hr(t);
534
+ return /* @__PURE__ */ l(Je, { value: r, children: /* @__PURE__ */ l(Xe, { value: n, children: /* @__PURE__ */ l(z.Provider, { value: s, children: e }) }) });
535
+ }
536
+ function Tr(r) {
537
+ return (w(Y) ?? ge)[r];
363
538
  }
364
- function er(r) {
365
- return (g(j) ?? X)[r];
539
+ function Rr(r) {
540
+ const e = w(X);
541
+ return B(() => {
542
+ e && (e.reachedGoals.has(r) || (e.reachedGoals.add(r), e.ensureImpression(), e.emit({
543
+ type: "goal",
544
+ experiment: e.experiment,
545
+ viewId: e.viewId,
546
+ goalKey: r
547
+ })));
548
+ }, [e, r]);
366
549
  }
367
- function Ue(r, e) {
368
- const [, t] = Ee((a) => a + 1, 0), n = e(), s = x(n);
369
- return s.current = n, P(() => {
370
- const a = r(t);
371
- return Object.is(s.current, e()) || t(), a;
550
+ function vr(r, e) {
551
+ const [, t] = je((c) => c + 1, 0), n = e(), s = A(n);
552
+ return s.current = n, R(() => {
553
+ const c = r(t);
554
+ return Object.is(s.current, e()) || t(), c;
372
555
  }, [r, e]), n;
373
556
  }
374
- const Y = de.useSyncExternalStore, Ve = Y || ((r, e) => Ue(r, e)), ce = "offline", Ke = () => Promise.reject(new Error(ce));
375
- function ze(r, e) {
376
- var $, B;
377
- const t = Te(), [n] = w(Ne), s = (t == null ? void 0 : t.sourceCache) ?? n, a = ($ = t == null ? void 0 : t.sourceFetchers) == null ? void 0 : $[r], o = (B = t == null ? void 0 : t.sourceBaseUrls) == null ? void 0 : B[r], h = a ? "host-fetch" : "network", c = t == null ? void 0 : t.env, u = D({ source: r, target: e.target, params: e.params }), f = k(() => ({ source: r, target: e.target, params: e.params }), [u]), E = _((F) => s.subscribe(f, F), [s, f]), A = _(() => s.get(f), [s, f]), l = Ve(E, A, A), v = g(M), y = g(I), m = Ae(r, e.target), d = k(
378
- () => v === ce ? null : Ce(y[m], f.params, o),
379
- [v, y, m, f, o]
380
- ), [S, p] = w(null);
381
- return P(() => {
382
- (l == null ? void 0 : l.status) === "ready" && S !== null && p(null);
383
- }, [l, S]), P(() => {
384
- d && !d.ok && l === void 0 && console.warn(`[useSource] ${m}: ${d.reason}`);
385
- }, [m, d == null ? void 0 : d.ok, d && !d.ok ? d.reason : void 0, l === void 0]), P(() => {
386
- if (d && !d.ok || (l == null ? void 0 : l.status) === "ready" || S === u) return;
387
- p(u);
388
- const F = d && d.ok ? () => ke({ url: d.url, init: d.init }, { fetcher: a, timeout: c == null ? void 0 : c.timeout }).then((ue) => (c != null && c.debug && console.info(`[useSource] loaded ${D(f)} origin=${h}`), ue)) : Ke;
389
- s.load(f, F, h);
390
- }, [s, f, u, l, S, d, a, h, c == null ? void 0 : c.timeout, c == null ? void 0 : c.debug]), (l == null ? void 0 : l.status) === "ready" ? { data: l.data ?? void 0, loading: !1 } : (l == null ? void 0 : l.status) === "pending" ? { data: void 0, loading: !0 } : d && !d.ok ? { data: void 0, loading: !1 } : { data: void 0, loading: S !== u };
557
+ const le = ke.useSyncExternalStore, gr = le || ((r, e) => vr(r, e)), Pe = "offline", Er = () => Promise.reject(new Error(Pe));
558
+ function yr(r, e) {
559
+ var C, b;
560
+ const t = We(), [n] = L(Ve), s = (t == null ? void 0 : t.sourceCache) ?? n, c = (C = t == null ? void 0 : t.sourceFetchers) == null ? void 0 : C[r], o = (b = t == null ? void 0 : t.sourceBaseUrls) == null ? void 0 : b[r], m = c ? "host-fetch" : "network", u = t == null ? void 0 : t.env, a = re({ source: r, target: e.target, params: e.params }), d = j(() => ({ source: r, target: e.target, params: e.params }), [a]), h = B((N) => s.subscribe(d, N), [s, d]), S = B(() => s.get(d), [s, d]), f = gr(h, S, S), T = w(W), v = w(J), p = ze(r, e.target), i = j(
561
+ () => T === Pe ? null : Ke(v[p], d.params, o),
562
+ [T, v, p, d, o]
563
+ ), [y, g] = L(null);
564
+ return R(() => {
565
+ (f == null ? void 0 : f.status) === "ready" && y !== null && g(null);
566
+ }, [f, y]), R(() => {
567
+ i && !i.ok && f === void 0 && console.warn(`[useSource] ${p}: ${i.reason}`);
568
+ }, [p, i == null ? void 0 : i.ok, i && !i.ok ? i.reason : void 0, f === void 0]), R(() => {
569
+ if (i && !i.ok || (f == null ? void 0 : f.status) === "ready" || y === a) return;
570
+ g(a);
571
+ const N = i && i.ok ? () => Ge({ url: i.url, init: i.init }, { fetcher: c, timeout: u == null ? void 0 : u.timeout }).then((H) => (u != null && u.debug && console.info(`[useSource] loaded ${re(d)} origin=${m}`), H)) : Er;
572
+ s.load(d, N, m);
573
+ }, [s, d, a, f, y, i, c, m, u == null ? void 0 : u.timeout, u == null ? void 0 : u.debug]), (f == null ? void 0 : f.status) === "ready" ? { data: f.data ?? void 0, loading: !1 } : (f == null ? void 0 : f.status) === "pending" ? { data: void 0, loading: !0 } : i && !i.ok ? { data: void 0, loading: !1 } : { data: void 0, loading: y !== a };
391
574
  }
392
- const rr = ze;
393
- function tr(r) {
394
- return Oe({ ...r, inject: Q });
575
+ const Cr = yr;
576
+ function Or(r) {
577
+ return Ye({ ...r, inject: he });
395
578
  }
396
579
  export {
397
- H as AREA_UNRESOLVED,
398
- Xe as Area,
399
- We as FragmentRenderer,
400
- U as FragmentStylesheet,
401
- ar as FragmentsApiVersionError,
402
- cr as FragmentsAreaError,
403
- C as FragmentsClientContext,
404
- we as FragmentsClientProvider,
405
- ur as FragmentsLoadError,
406
- Ze as FragmentsProvider,
407
- J as InstanceIdContext,
408
- T as ModulesMapContext,
409
- be as ModulesMapProvider,
410
- j as ProjectPropertiesContext,
411
- tr as createBrowserClient,
412
- or as createSourceCache,
413
- X as defaultProjectProperties,
414
- Q as injectStylesheet,
415
- Re as useArea,
416
- Qe as useCssChunk,
417
- Fe as useFragmentComponent,
418
- qe as useFragmentMetrics,
419
- je as useFragmentStylesheet,
420
- er as useProjectProperty,
421
- rr as useSource
580
+ ne as AREA_UNRESOLVED,
581
+ Pr as Area,
582
+ X as AreaExposureContext,
583
+ br as FragmentRenderer,
584
+ oe as FragmentStylesheet,
585
+ kr as FragmentsApiVersionError,
586
+ _r as FragmentsAreaError,
587
+ F as FragmentsClientContext,
588
+ Je as FragmentsClientProvider,
589
+ Fr as FragmentsLoadError,
590
+ Ar as FragmentsProvider,
591
+ fe as InstanceIdContext,
592
+ V as ModulesMapContext,
593
+ Xe as ModulesMapProvider,
594
+ Y as ProjectPropertiesContext,
595
+ Or as createBrowserClient,
596
+ Mr as createSourceCache,
597
+ ge as defaultProjectProperties,
598
+ he as injectStylesheet,
599
+ Qe as useArea,
600
+ Sr as useCssChunk,
601
+ qe as useFragmentComponent,
602
+ rr as useFragmentStylesheet,
603
+ Rr as useGoal,
604
+ Tr as useProjectProperty,
605
+ Cr as useSource
422
606
  };
package/dist/index.umd.js CHANGED
@@ -1 +1 @@
1
- (function(a,l){typeof exports=="object"&&typeof module<"u"?l(exports,require("react/jsx-runtime"),require("react"),require("@fragmentsx/fragments-client")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react","@fragmentsx/fragments-client"],l):(a=typeof globalThis<"u"?globalThis:a||self,l(a.FragmentsRuntimeReact={},a.jsxRuntime,a.React,a.fragmentsClient))})(this,function(a,l,s,h){"use strict";function oe(r){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(r){for(const t in r)if(t!=="default"){const n=Object.getOwnPropertyDescriptor(r,t);Object.defineProperty(e,t,n.get?n:{enumerable:!0,get:()=>r[t]})}}return e.default=r,Object.freeze(e)}const ae=oe(s),O=s.createContext(null);O.displayName="FragmentsClientContext";function D(r){return l.jsx(O.Provider,{value:r.value,children:r.children})}function ce(){return s.useContext(O)}const j=s.createContext(null);j.displayName="InstanceIdContext";const A=s.createContext(null);A.displayName="ModulesMapContext";function $({value:r,children:e}){return l.jsx(A.Provider,{value:r,children:e})}function le(){const r=s.useContext(O);return s.useMemo(()=>({reachGoal:e=>{var t,n;(n=(t=r==null?void 0:r.$metrics)==null?void 0:t.reachGoal)==null||n.call(t,e)}}),[r])}function L(r){const e=s.useContext(A);if(!e)throw new Error("[useFragmentComponent] No ModulesMapProvider in tree");return e.read(r)}const H=typeof window<"u",T=Object.freeze({rootFragmentId:0,variantId:null,props:{},projectProperties:{},projectBindings:{},globalCssUrl:null,fragments:[],slots:{},sources:{}});function w(r){const e=r.$area;if(!(e!=null&&e.read))throw new Error("[useArea] $area plugin not mounted");return e}function U(r,e){const t=s.useContext(O);if(!t)throw new Error("[useArea] No FragmentsClientProvider in tree");const n=(e==null?void 0:e.suspense)??!0,u=(e==null?void 0:e.pause)===!0||!H&&(e==null?void 0:e.ssr)===!1,o=(e==null?void 0:e.timeout)!=null?{timeout:e.timeout}:void 0,[,f]=s.useState(0);if(s.useEffect(()=>{if(n||u)return;const c=w(t);let d=!0;return Promise.resolve(c.resolve(r,o)).catch(()=>{}).finally(()=>{d&&f(E=>E+1)}),()=>{d=!1}},[r,n,e==null?void 0:e.pause,e==null?void 0:e.timeout,e==null?void 0:e.ssr]),n){if(u)return T;const c=w(t);if(c.has(r)||Promise.resolve(c.resolve(r,o)).catch(()=>{}),!H)try{return c.read(r)}catch(d){if(d!=null&&typeof d.then=="function")throw d;return process.env.NODE_ENV!=="production"&&console.error(`[useArea] Area ${r} remained unresolved on the server because its cache reached a terminal state`,d),T}return c.read(r)}if(u)return{status:"idle",data:null,error:null};const v=w(t);if(v.has(r))try{return{status:"ready",data:v.read(r),error:null}}catch(c){return{status:"not-found",data:null,error:c instanceof Error?c:new Error(String(c))}}return Promise.resolve(v.resolve(r,o)).catch(()=>{}),{status:"loading",data:null,error:null}}const V=typeof window<"u",de=3e3,F=new Map,_=(r,e)=>{if(!V){const y=()=>{};return y.loaded=Promise.resolve(),y}const t=F.get(e);if(t){t.refCount+=1;const y=()=>{t.refCount-=1,t.refCount===0&&(t.clearReadyTimer(),t.linkEl.remove(),F.delete(e))};return y.loaded=t.loaded,y}const n=document.createElement("link");n.rel="stylesheet",n.href=r,n.setAttribute("data-fragment-key",e);let u;const o=new Promise(y=>{u=y}),f=()=>{c(),u()},v=setTimeout(f,de),c=()=>clearTimeout(v);n.addEventListener("load",f),n.addEventListener("error",f),document.head.appendChild(n);const d={refCount:1,linkEl:n,loaded:o,clearReadyTimer:c};F.set(e,d);const E=()=>{d.refCount-=1,d.refCount===0&&(d.clearReadyTimer(),d.linkEl.remove(),F.delete(e))};return E.loaded=o,E},fe=V?s.useLayoutEffect:s.useEffect;function K(r,e){fe(()=>_(r,e),[r,e])}const ie=parseInt(s.version.split(".")[0],10)>=19;function M({href:r,fragmentKey:e}){return ie?l.jsx("link",{rel:"stylesheet",href:r,precedence:"default","data-fragment-key":e}):(K(r,e),null)}function me(r){}const z=Object.freeze({}),N=s.createContext(z);N.displayName="HostPropertiesContext";const I={},k=s.createContext(null);k.displayName="ProjectPropertiesContext";const Y=Object.freeze({}),x=s.createContext(Y);x.displayName="SourceTransportsContext";const p=s.createContext("live");p.displayName="SourceNetworkContext";function G(r){const e=r instanceof Error?r:new Error(String(r));if(!(e instanceof h.FragmentsAreaError))return{kind:"failed",error:e};const{code:t}=e;return t==="NO_ACTIVE_VARIANT"?{kind:"no-variant",code:t,error:e}:t==="AREA_NOT_FOUND"||t==="NO_PUBLISHED_SNAPSHOT"||t==="NESTED_SNAPSHOT_MISSING"?{kind:"misconfigured",code:t,error:e}:{kind:"failed",code:t,error:e}}function q(r,e,t){return typeof r=="function"?r(e,t):r??null}const Ee=()=>{};function J(r){return r instanceof Error?r:new Error(String(r))}class Q extends s.Component{constructor(){super(...arguments),this.state={hasError:!1,error:null}}static getDerivedStateFromError(e){return{hasError:!0,error:J(e)}}componentDidCatch(e,t){var u,o;const n=J(e);process.env.NODE_ENV!=="production"&&console.error("[fragments] Area error:",n,t.componentStack),(o=(u=this.props).onError)==null||o.call(u,n)}render(){if(this.state.hasError){const e={kind:"failed",error:this.state.error??new Error("Unknown Area error")};try{return q(this.props.empty,e,this.props.retry??Ee)}catch{return null}}return this.props.children}}function he(r,e){let t;for(const[n,u]of Object.entries(e))u!=null&&(t??(t={...r}),t[n]=u);return t??r}function ge(r,e){const t=Object.keys(r);return t.length!==Object.keys(e).length?!1:t.every(n=>Object.prototype.hasOwnProperty.call(e,n)&&Object.is(r[n],e[n]))}const W=Object.freeze({});function X(r,e,t){let n;for(const[u,o]of Object.entries(e)){const f=t[o];f!=null&&(n??(n={...r}),n[u]=f)}return n??r}function Z(r,e,t){if(!r)return{};const n={};for(const u of Object.keys(r))n[u]=ve(r[u],e,t);return n}function ve(r,e,t){return Array.isArray(r)?r.map((n,u)=>n===null?null:R(n,e,t,u)):R(r,e,t)}function R(r,e,t,n){let u;try{u=e(r.fragmentId)}catch(f){if(f!=null&&typeof f.then=="function")throw f;return console.warn(`[FragmentRenderer] Slot fragment ${r.fragmentId} failed to load — rendering empty hole`,f),null}const o=Z(r.slots,e,t);return s.createElement(u,{key:n,...X(r.props,r.projectBindings??W,t),...o})}const ee=({fragmentId:r,props:e,globalCssUrl:t=null,projectProperties:n=I,fragments:u=[r],slots:o,sources:f=Y,sourceNetwork:v="live"})=>{const c=L(r),d=s.useContext(A),E=s.useContext(N);if(!d)throw new Error("[FragmentRendererInner] No ModulesMapProvider in tree");const y=Z(o,d.read,E),b=s.useMemo(()=>he(n,E),[n,E]),i={...e??{},...y},S=u.length>0?u.map(h.toScopeClassName).join(" "):void 0;return l.jsxs(l.Fragment,{children:[t!=null&&l.jsx(M,{href:t,fragmentKey:h.AREA_GLOBAL_CSS_KEY}),u.map(P=>{const g=h.resolveStylesHref(P);return g?l.jsx(M,{href:g,fragmentKey:h.fragmentCssKey(P)},P):null}),l.jsx(p.Provider,{value:v,children:l.jsx(x.Provider,{value:f,children:l.jsx(k.Provider,{value:b,children:l.jsx(j.Provider,{value:null,children:l.jsx("div",{className:S,style:{display:"contents"},children:l.jsx(c,{...i})})})})})})]})},ye=({onError:r,...e})=>l.jsx(s.Suspense,{fallback:null,children:l.jsx(Q,{onError:r,children:l.jsx(ee,{...e})})}),Se=({areaCode:r,options:e,retry:t})=>{const n=U(r,{suspense:!1,ssr:!1,pause:e==null?void 0:e.pause,timeout:e==null?void 0:e.timeout}),u=s.useContext(N),o=s.useRef(null);if(s.useEffect(()=>{var C;if(n.status!=="not-found"||!n.error)return;const g=G(n.error),m=JSON.stringify([r,g.kind,g.code,g.error.message]);o.current!==m&&(o.current=m,(C=e==null?void 0:e.onError)==null||C.call(e,g.error),process.env.NODE_ENV!=="production"&&g.kind!=="no-variant"&&console.error(`[fragments] Area resolution ${g.kind}: areaCode=${r}, code=${g.code??"none"}`,g.error))},[r,e==null?void 0:e.onError,n.error,n.status]),(e==null?void 0:e.pause)===!0)return null;if(n.status==="idle")return(e==null?void 0:e.fallback)??null;if(n.status==="not-found")return q(e==null?void 0:e.empty,G(n.error),t);if(n.status==="loading"||!n.data)return(e==null?void 0:e.fallback)??null;const{rootFragmentId:f,props:v,projectProperties:c,globalCssUrl:d,fragments:E,slots:y,sources:b,projectBindings:i}=n.data,S=X(v,i??W,u),P=typeof(e==null?void 0:e.props)=="function"?e.props(S):e!=null&&e.props?{...S,...e.props}:S;return l.jsx(s.Suspense,{fallback:(e==null?void 0:e.fallback)??null,children:l.jsx(ee,{fragmentId:f,props:P,globalCssUrl:d,projectProperties:c,fragments:E,slots:y,sources:b})})},Pe=({areaCode:r,options:e})=>{const t=s.useContext(O),[n,u]=s.useState(0),o=t==null?void 0:t.$area;s.useEffect(()=>{(e==null?void 0:e.ssr)!==!0||process.env.NODE_ENV==="production"||console.error("[fragments] Area option `ssr` is reserved: server resolution has been removed from the runtime; existing `ssr: false` calls continue to work unchanged.")},[e==null?void 0:e.ssr]);const f=s.useCallback(()=>{o!=null&&o.resolve&&(o.resolve(r).catch(()=>{}),u(v=>v+1))},[o,r]);return l.jsx(Q,{onError:e==null?void 0:e.onError,empty:e==null?void 0:e.empty,retry:f,children:l.jsx(Se,{areaCode:r,options:e,retry:f})},n)};function Ce(r){const e=r??z,t=s.useRef(e);return ge(t.current,e)||(t.current=e),t.current}function Oe({client:r,children:e,properties:t}){const n=s.useMemo(()=>({read:o=>r.$fragments.read(o)}),[r]),u=Ce(t);return l.jsx(D,{value:r,children:l.jsx($,{value:n,children:l.jsx(N.Provider,{value:u,children:e})})})}function be(r){return(s.useContext(k)??I)[r]}function Ae(r,e){const[,t]=s.useReducer(o=>o+1,0),n=e(),u=s.useRef(n);return u.current=n,s.useEffect(()=>{const o=r(t);return Object.is(u.current,e())||t(),o},[r,e]),n}const re=ae.useSyncExternalStore,Fe=re||((r,e)=>Ae(r,e)),te="offline",Ne=()=>Promise.reject(new Error(te));function ke(r,e){var se,ue;const t=ce(),[n]=s.useState(h.createSourceCache),u=(t==null?void 0:t.sourceCache)??n,o=(se=t==null?void 0:t.sourceFetchers)==null?void 0:se[r],f=(ue=t==null?void 0:t.sourceBaseUrls)==null?void 0:ue[r],v=o?"host-fetch":"network",c=t==null?void 0:t.env,d=h.sourceCallKey({source:r,target:e.target,params:e.params}),E=s.useMemo(()=>({source:r,target:e.target,params:e.params}),[d]),y=s.useCallback(B=>u.subscribe(E,B),[u,E]),b=s.useCallback(()=>u.get(E),[u,E]),i=Fe(y,b,b),S=s.useContext(p),P=s.useContext(x),g=h.sourceTransportKey(r,e.target),m=s.useMemo(()=>S===te?null:h.resolveSourceRequest(P[g],E.params,f),[S,P,g,E,f]),[C,ne]=s.useState(null);return s.useEffect(()=>{(i==null?void 0:i.status)==="ready"&&C!==null&&ne(null)},[i,C]),s.useEffect(()=>{m&&!m.ok&&i===void 0&&console.warn(`[useSource] ${g}: ${m.reason}`)},[g,m==null?void 0:m.ok,m&&!m.ok?m.reason:void 0,i===void 0]),s.useEffect(()=>{if(m&&!m.ok||(i==null?void 0:i.status)==="ready"||C===d)return;ne(d);const B=m&&m.ok?()=>h.runSourceFetch({url:m.url,init:m.init},{fetcher:o,timeout:c==null?void 0:c.timeout}).then(we=>(c!=null&&c.debug&&console.info(`[useSource] loaded ${h.sourceCallKey(E)} origin=${v}`),we)):Ne;u.load(E,B,v)},[u,E,d,i,C,m,o,v,c==null?void 0:c.timeout,c==null?void 0:c.debug]),(i==null?void 0:i.status)==="ready"?{data:i.data??void 0,loading:!1}:(i==null?void 0:i.status)==="pending"?{data:void 0,loading:!0}:m&&!m.ok?{data:void 0,loading:!1}:{data:void 0,loading:C!==d}}const je=ke;function Te(r){return h.createFragmentsClient({...r,inject:_})}Object.defineProperty(a,"FragmentsApiVersionError",{enumerable:!0,get:()=>h.FragmentsApiVersionError}),Object.defineProperty(a,"FragmentsAreaError",{enumerable:!0,get:()=>h.FragmentsAreaError}),Object.defineProperty(a,"FragmentsLoadError",{enumerable:!0,get:()=>h.FragmentsLoadError}),Object.defineProperty(a,"createSourceCache",{enumerable:!0,get:()=>h.createSourceCache}),a.AREA_UNRESOLVED=T,a.Area=Pe,a.FragmentRenderer=ye,a.FragmentStylesheet=M,a.FragmentsClientContext=O,a.FragmentsClientProvider=D,a.FragmentsProvider=Oe,a.InstanceIdContext=j,a.ModulesMapContext=A,a.ModulesMapProvider=$,a.ProjectPropertiesContext=k,a.createBrowserClient=Te,a.defaultProjectProperties=I,a.injectStylesheet=_,a.useArea=U,a.useCssChunk=me,a.useFragmentComponent=L,a.useFragmentMetrics=le,a.useFragmentStylesheet=K,a.useProjectProperty=be,a.useSource=je,Object.defineProperty(a,Symbol.toStringTag,{value:"Module"})});
1
+ (function(i,l){typeof exports=="object"&&typeof module<"u"?l(exports,require("react/jsx-runtime"),require("react"),require("@fragmentsx/fragments-client")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react","@fragmentsx/fragments-client"],l):(i=typeof globalThis<"u"?globalThis:i||self,l(i.FragmentsRuntimeReact={},i.jsxRuntime,i.React,i.fragmentsClient))})(this,function(i,l,o,E){"use strict";function Pe(r){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(r){for(const t in r)if(t!=="default"){const n=Object.getOwnPropertyDescriptor(r,t);Object.defineProperty(e,t,n.get?n:{enumerable:!0,get:()=>r[t]})}}return e.default=r,Object.freeze(e)}const Ce=Pe(o),N=o.createContext(null);N.displayName="FragmentsClientContext";function Z(r){return l.jsx(N.Provider,{value:r.value,children:r.children})}function Ae(){return o.useContext(N)}const z=o.createContext(null);z.displayName="InstanceIdContext";const M=o.createContext(null);M.displayName="ModulesMapContext";function R({value:r,children:e}){return l.jsx(M.Provider,{value:r,children:e})}function ee(r){const e=o.useContext(M);if(!e)throw new Error("[useFragmentComponent] No ModulesMapProvider in tree");return e.read(r)}const re=typeof window<"u",K=Object.freeze({rootFragmentId:0,variantId:null,experiment:null,props:{},projectProperties:{},projectBindings:{},globalCssUrl:null,fragments:[],slots:{},sources:{}});function G(r){const e=r.$area;if(!(e!=null&&e.read))throw new Error("[useArea] $area plugin not mounted");return e}function te(r,e){const t=o.useContext(N);if(!t)throw new Error("[useArea] No FragmentsClientProvider in tree");const n=(e==null?void 0:e.suspense)??!0,u=(e==null?void 0:e.pause)===!0||!re&&(e==null?void 0:e.ssr)===!1,c=(e==null?void 0:e.timeout)!=null?{timeout:e.timeout}:void 0,[,s]=o.useState(0);if(o.useEffect(()=>{if(n||u)return;const a=G(t);let d=!0;return Promise.resolve(a.resolve(r,c)).catch(()=>{}).finally(()=>{d&&s(m=>m+1)}),()=>{d=!1}},[r,n,e==null?void 0:e.pause,e==null?void 0:e.timeout,e==null?void 0:e.ssr]),n){if(u)return K;const a=G(t);if(a.has(r)||Promise.resolve(a.resolve(r,c)).catch(()=>{}),!re)try{return a.read(r)}catch(d){if(d!=null&&typeof d.then=="function")throw d;return process.env.NODE_ENV!=="production"&&console.error(`[useArea] Area ${r} remained unresolved on the server because its cache reached a terminal state`,d),K}return a.read(r)}if(u)return{status:"idle",data:null,error:null};const g=G(t);if(g.has(r))try{return{status:"ready",data:g.read(r),error:null}}catch(a){return{status:"not-found",data:null,error:a instanceof Error?a:new Error(String(a))}}return Promise.resolve(g.resolve(r,c)).catch(()=>{}),{status:"loading",data:null,error:null}}const ne=typeof window<"u",Oe=3e3,L=new Map,Y=(r,e)=>{if(!ne){const v=()=>{};return v.loaded=Promise.resolve(),v}const t=L.get(e);if(t){t.refCount+=1;const v=()=>{t.refCount-=1,t.refCount===0&&(t.clearReadyTimer(),t.linkEl.remove(),L.delete(e))};return v.loaded=t.loaded,v}const n=document.createElement("link");n.rel="stylesheet",n.href=r,n.setAttribute("data-fragment-key",e);let u;const c=new Promise(v=>{u=v}),s=()=>{a(),u()},g=setTimeout(s,Oe),a=()=>clearTimeout(g);n.addEventListener("load",s),n.addEventListener("error",s),document.head.appendChild(n);const d={refCount:1,linkEl:n,loaded:c,clearReadyTimer:a};L.set(e,d);const m=()=>{d.refCount-=1,d.refCount===0&&(d.clearReadyTimer(),d.linkEl.remove(),L.delete(e))};return m.loaded=c,m},Te=ne?o.useLayoutEffect:o.useEffect;function oe(r,e){Te(()=>Y(r,e),[r,e])}const Ie=parseInt(o.version.split(".")[0],10)>=19;function q({href:r,fragmentKey:e}){return Ie?l.jsx("link",{rel:"stylesheet",href:r,precedence:"default","data-fragment-key":e}):(oe(r,e),null)}function Ne(r){}const se=Object.freeze({}),B=o.createContext(se);B.displayName="HostPropertiesContext";const J={},D=o.createContext(null);D.displayName="ProjectPropertiesContext";const ue=Object.freeze({}),W=o.createContext(ue);W.displayName="SourceTransportsContext";const X=o.createContext("live");X.displayName="SourceNetworkContext";function ce(r){const e=r instanceof Error?r:new Error(String(r));if(!(e instanceof E.FragmentsAreaError))return{kind:"failed",error:e};const{code:t}=e;return t==="NO_ACTIVE_VARIANT"?{kind:"no-variant",code:t,error:e}:t==="AREA_NOT_FOUND"||t==="NO_PUBLISHED_SNAPSHOT"||t==="NESTED_SNAPSHOT_MISSING"?{kind:"misconfigured",code:t,error:e}:{kind:"failed",code:t,error:e}}function ae(r,e,t){return typeof r=="function"?r(e,t):r??null}const ke=()=>{};function ie(r){return r instanceof Error?r:new Error(String(r))}class le extends o.Component{constructor(){super(...arguments),this.state={hasError:!1,error:null}}static getDerivedStateFromError(e){return{hasError:!0,error:ie(e)}}componentDidCatch(e,t){var u,c;const n=ie(e);process.env.NODE_ENV!=="production"&&console.error("[fragments] Area error:",n,t.componentStack),(c=(u=this.props).onError)==null||c.call(u,n)}render(){if(this.state.hasError){const e={kind:"failed",error:this.state.error??new Error("Unknown Area error")};try{return ae(this.props.empty,e,this.props.retry??ke)}catch{return null}}return this.props.children}}function Fe(r,e){let t;for(const[n,u]of Object.entries(e))u!=null&&(t??(t={...r}),t[n]=u);return t??r}function je(r,e){const t=Object.keys(r);return t.length!==Object.keys(e).length?!1:t.every(n=>Object.prototype.hasOwnProperty.call(e,n)&&Object.is(r[n],e[n]))}const de=Object.freeze({});function fe(r,e,t){let n;for(const[u,c]of Object.entries(e)){const s=t[c];s!=null&&(n??(n={...r}),n[u]=s)}return n??r}function me(r,e,t){if(!r)return{};const n={};for(const u of Object.keys(r))n[u]=Me(r[u],e,t);return n}function Me(r,e,t){return Array.isArray(r)?r.map((n,u)=>n===null?null:he(n,e,t,u)):he(r,e,t)}function he(r,e,t,n){let u;try{u=e(r.fragmentId)}catch(s){if(s!=null&&typeof s.then=="function")throw s;return console.warn(`[FragmentRenderer] Slot fragment ${r.fragmentId} failed to load — rendering empty hole`,s),null}const c=me(r.slots,e,t);return o.createElement(u,{key:n,...fe(r.props,r.projectBindings??de,t),...c})}const ge=({fragmentId:r,props:e,globalCssUrl:t=null,projectProperties:n=J,fragments:u=[r],slots:c,sources:s=ue,sourceNetwork:g="live"})=>{const a=ee(r),d=o.useContext(M),m=o.useContext(B);if(!d)throw new Error("[FragmentRendererInner] No ModulesMapProvider in tree");const v=me(c,d.read,m),P=o.useMemo(()=>Fe(n,m),[n,m]),h={...e??{},...v},O=u.length>0?u.map(E.toScopeClassName).join(" "):void 0;return l.jsxs(l.Fragment,{children:[t!=null&&l.jsx(q,{href:t,fragmentKey:E.AREA_GLOBAL_CSS_KEY}),u.map(y=>{const w=E.resolveStylesHref(y);return w?l.jsx(q,{href:w,fragmentKey:E.fragmentCssKey(y)},y):null}),l.jsx(X.Provider,{value:g,children:l.jsx(W.Provider,{value:s,children:l.jsx(D.Provider,{value:P,children:l.jsx(z.Provider,{value:null,children:l.jsx("div",{className:O,style:{display:"contents"},children:l.jsx(a,{...h})})})})})})]})},_e=({onError:r,...e})=>l.jsx(o.Suspense,{fallback:null,children:l.jsx(le,{onError:r,children:l.jsx(ge,{...e})})}),H=o.createContext(null);H.displayName="AreaExposureContext";const Le=1e3,Be=Array.from({length:101},(r,e)=>e/100);function De({visibleArea:r,totalArea:e,visibleHeight:t,viewportHeight:n}){if(r<=0)return!1;const u=e>0&&r>=.5*e,c=n>0&&t>=.5*n;return u||c}function ve(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,r=>{const e=Math.random()*16|0;return(r==="x"?e:e&3|8).toString(16)})}function Ee(r){const e=r.getBoundingClientRect();return e.width>0&&e.height>0}function He(r){const e=[];function t(n,u){var c;for(const s of Array.from(n.children)){let g="";try{g=window.getComputedStyle(s).display}catch{g=((c=s.style)==null?void 0:c.display)||""}if(g==="contents")t(s,u);else if(g==="none"||Ee(s))u.push(s);else{const a=[];t(s,a),a.some(Ee)?u.push(...a):u.push(s)}}}return t(r,e),e}const Ue=({experiment:r,emit:e,children:t})=>{const[n,u]=o.useState(ve),c=o.useRef(!1),s=o.useRef(null),g=o.useRef(new Set),a=o.useRef(null),d=o.useRef(r);d.current=r;const m=o.useRef(e);m.current=e;const v=o.useRef(n);v.current=n;const P=o.useCallback(()=>{c.current||(c.current=!0,s.current&&(clearTimeout(s.current),s.current=null),m.current({type:"impression",experiment:d.current,viewId:v.current}))},[]),h=o.useMemo(()=>({experiment:r,viewId:n,emit:e,reachedGoals:g.current,ensureImpression:P}),[r,n,e,P]);return o.useEffect(()=>{if(typeof window>"u"||typeof IntersectionObserver>"u")return;const O=a.current;if(!O)return;let y=[];const w=new Map,f=()=>!(typeof document>"u"||"visibilityState"in document&&document.visibilityState==="hidden"||"prerendering"in document&&document.prerendering),x=()=>{if(c.current||y.length===0)return;let A=0,p=0,_=!1,F=1/0,j=-1/0;for(const Q of y){const b=w.get(Q);b&&(A+=b.interArea,p+=b.boundArea,b.interArea>0&&b.interBottom>b.interTop&&(_=!0,b.interTop<F&&(F=b.interTop),b.interBottom>j&&(j=b.interBottom)))}const $=_?Math.max(0,j-F):0,V=typeof window<"u"?window.innerHeight:0;f()&&De({visibleArea:A,totalArea:p,visibleHeight:$,viewportHeight:V})?s.current||(s.current=setTimeout(()=>{s.current=null,P()},Le)):s.current&&(clearTimeout(s.current),s.current=null)},S=new IntersectionObserver(A=>{var p,_,F,j,$,V;for(const I of A){const Q=((p=I.boundingClientRect)==null?void 0:p.width)??0,b=((_=I.boundingClientRect)==null?void 0:_.height)??0,Re=((F=I.intersectionRect)==null?void 0:F.width)??0,er=((j=I.intersectionRect)==null?void 0:j.height)??0,be=Q*b,rr=Re*er,tr=(($=I.intersectionRect)==null?void 0:$.top)??0,nr=((V=I.intersectionRect)==null?void 0:V.bottom)??0;w.set(I.target,{interArea:be>0?rr:0,boundArea:be,interTop:tr,interBottom:nr})}c.current||x()},{threshold:Be}),T=()=>{if(c.current||!a.current)return;const A=He(a.current);for(const p of y)A.includes(p)||(S.unobserve(p),w.delete(p));for(const p of A)y.includes(p)||S.observe(p);y=A};T();let C=null;typeof MutationObserver<"u"&&(C=new MutationObserver(()=>{c.current||T()}),C.observe(O,{childList:!0,subtree:!0}));const k=()=>{typeof document<"u"&&document.visibilityState==="hidden"?s.current&&(clearTimeout(s.current),s.current=null):x()},U=()=>{x()},pe=()=>{s.current&&(clearTimeout(s.current),s.current=null)},xe=()=>{x()},we=A=>{if(A.persisted){s.current&&(clearTimeout(s.current),s.current=null),c.current=!1;const p=ve();v.current=p,u(p),x()}};return typeof document<"u"&&(document.addEventListener("visibilitychange",k),document.addEventListener("prerenderingchange",U)),typeof window<"u"&&(window.addEventListener("pagehide",pe),window.addEventListener("resize",xe),window.addEventListener("pageshow",we)),()=>{s.current&&(clearTimeout(s.current),s.current=null),S.disconnect(),C&&C.disconnect(),typeof document<"u"&&(document.removeEventListener("visibilitychange",k),document.removeEventListener("prerenderingchange",U)),typeof window<"u"&&(window.removeEventListener("pagehide",pe),window.removeEventListener("resize",xe),window.removeEventListener("pageshow",we))}},[r,e]),l.jsx(H.Provider,{value:h,children:l.jsx("div",{ref:a,style:{display:"contents"},children:t})})},$e=({areaCode:r,options:e,retry:t})=>{const n=te(r,{suspense:!1,ssr:!1,pause:e==null?void 0:e.pause,timeout:e==null?void 0:e.timeout}),u=o.useContext(B),c=o.useContext(N),s=o.useRef(null);if(o.useEffect(()=>{var C;if(n.status!=="not-found"||!n.error)return;const S=ce(n.error),T=JSON.stringify([r,S.kind,S.code,S.error.message]);s.current!==T&&(s.current=T,(C=e==null?void 0:e.onError)==null||C.call(e,S.error),process.env.NODE_ENV!=="production"&&S.kind!=="no-variant"&&console.error(`[fragments] Area resolution ${S.kind}: areaCode=${r}, code=${S.code??"none"}`,S.error))},[r,e==null?void 0:e.onError,n.error,n.status]),(e==null?void 0:e.pause)===!0)return null;if(n.status==="idle")return(e==null?void 0:e.fallback)??null;if(n.status==="not-found")return ae(e==null?void 0:e.empty,ce(n.error),t);if(n.status==="loading"||!n.data)return(e==null?void 0:e.fallback)??null;const{rootFragmentId:g,props:a,projectProperties:d,globalCssUrl:m,fragments:v,slots:P,sources:h,projectBindings:O}=n.data,y=fe(a,O??de,u),w=typeof(e==null?void 0:e.props)=="function"?e.props(y):e!=null&&e.props?{...y,...e.props}:y,f=n.data.experiment,x=l.jsx(ge,{fragmentId:g,props:w,globalCssUrl:m,projectProperties:d,fragments:v,slots:P,sources:h});return l.jsx(o.Suspense,{fallback:(e==null?void 0:e.fallback)??null,children:f&&(c!=null&&c.$events)?l.jsx(Ue,{experiment:f,emit:c.$events.emit,children:x},`${f.label}:${f.variantId}`):x})},Ve=({areaCode:r,options:e})=>{const t=o.useContext(N),[n,u]=o.useState(0),c=t==null?void 0:t.$area;o.useEffect(()=>{(e==null?void 0:e.ssr)!==!0||process.env.NODE_ENV==="production"||console.error("[fragments] Area option `ssr` is reserved: server resolution has been removed from the runtime; existing `ssr: false` calls continue to work unchanged.")},[e==null?void 0:e.ssr]);const s=o.useCallback(()=>{c!=null&&c.resolve&&(c.resolve(r).catch(()=>{}),u(g=>g+1))},[c,r]);return l.jsx(le,{onError:e==null?void 0:e.onError,empty:e==null?void 0:e.empty,retry:s,children:l.jsx($e,{areaCode:r,options:e,retry:s})},n)};function ze(r){const e=r??se,t=o.useRef(e);return je(t.current,e)||(t.current=e),t.current}function Ke({client:r,children:e,properties:t}){const n=o.useMemo(()=>({read:c=>r.$fragments.read(c)}),[r]),u=ze(t);return l.jsx(Z,{value:r,children:l.jsx(R,{value:n,children:l.jsx(B.Provider,{value:u,children:e})})})}function Ge(r){return(o.useContext(D)??J)[r]}function Ye(r){const e=o.useContext(H);return o.useCallback(()=>{e&&(e.reachedGoals.has(r)||(e.reachedGoals.add(r),e.ensureImpression(),e.emit({type:"goal",experiment:e.experiment,viewId:e.viewId,goalKey:r})))},[e,r])}function qe(r,e){const[,t]=o.useReducer(c=>c+1,0),n=e(),u=o.useRef(n);return u.current=n,o.useEffect(()=>{const c=r(t);return Object.is(u.current,e())||t(),c},[r,e]),n}const ye=Ce.useSyncExternalStore,Je=ye||((r,e)=>qe(r,e)),Se="offline",We=()=>Promise.reject(new Error(Se));function Xe(r,e){var T,C;const t=Ae(),[n]=o.useState(E.createSourceCache),u=(t==null?void 0:t.sourceCache)??n,c=(T=t==null?void 0:t.sourceFetchers)==null?void 0:T[r],s=(C=t==null?void 0:t.sourceBaseUrls)==null?void 0:C[r],g=c?"host-fetch":"network",a=t==null?void 0:t.env,d=E.sourceCallKey({source:r,target:e.target,params:e.params}),m=o.useMemo(()=>({source:r,target:e.target,params:e.params}),[d]),v=o.useCallback(k=>u.subscribe(m,k),[u,m]),P=o.useCallback(()=>u.get(m),[u,m]),h=Je(v,P,P),O=o.useContext(X),y=o.useContext(W),w=E.sourceTransportKey(r,e.target),f=o.useMemo(()=>O===Se?null:E.resolveSourceRequest(y[w],m.params,s),[O,y,w,m,s]),[x,S]=o.useState(null);return o.useEffect(()=>{(h==null?void 0:h.status)==="ready"&&x!==null&&S(null)},[h,x]),o.useEffect(()=>{f&&!f.ok&&h===void 0&&console.warn(`[useSource] ${w}: ${f.reason}`)},[w,f==null?void 0:f.ok,f&&!f.ok?f.reason:void 0,h===void 0]),o.useEffect(()=>{if(f&&!f.ok||(h==null?void 0:h.status)==="ready"||x===d)return;S(d);const k=f&&f.ok?()=>E.runSourceFetch({url:f.url,init:f.init},{fetcher:c,timeout:a==null?void 0:a.timeout}).then(U=>(a!=null&&a.debug&&console.info(`[useSource] loaded ${E.sourceCallKey(m)} origin=${g}`),U)):We;u.load(m,k,g)},[u,m,d,h,x,f,c,g,a==null?void 0:a.timeout,a==null?void 0:a.debug]),(h==null?void 0:h.status)==="ready"?{data:h.data??void 0,loading:!1}:(h==null?void 0:h.status)==="pending"?{data:void 0,loading:!0}:f&&!f.ok?{data:void 0,loading:!1}:{data:void 0,loading:x!==d}}const Qe=Xe;function Ze(r){return E.createFragmentsClient({...r,inject:Y})}Object.defineProperty(i,"FragmentsApiVersionError",{enumerable:!0,get:()=>E.FragmentsApiVersionError}),Object.defineProperty(i,"FragmentsAreaError",{enumerable:!0,get:()=>E.FragmentsAreaError}),Object.defineProperty(i,"FragmentsLoadError",{enumerable:!0,get:()=>E.FragmentsLoadError}),Object.defineProperty(i,"createSourceCache",{enumerable:!0,get:()=>E.createSourceCache}),i.AREA_UNRESOLVED=K,i.Area=Ve,i.AreaExposureContext=H,i.FragmentRenderer=_e,i.FragmentStylesheet=q,i.FragmentsClientContext=N,i.FragmentsClientProvider=Z,i.FragmentsProvider=Ke,i.InstanceIdContext=z,i.ModulesMapContext=M,i.ModulesMapProvider=R,i.ProjectPropertiesContext=D,i.createBrowserClient=Ze,i.defaultProjectProperties=J,i.injectStylesheet=Y,i.useArea=te,i.useCssChunk=Ne,i.useFragmentComponent=ee,i.useFragmentStylesheet=oe,i.useGoal=Ye,i.useProjectProperty=Ge,i.useSource=Qe,Object.defineProperty(i,Symbol.toStringTag,{value:"Module"})});
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@fragmentsx/runtime-react",
3
3
  "private": false,
4
- "version": "0.2.0-dev-20261011155313",
4
+ "version": "0.2.0-dev-20261022125555",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -32,20 +32,23 @@
32
32
  },
33
33
  "dependencies": {
34
34
  "@graph-state/core": "^0.13.3",
35
- "@fragmentsx/fragments-client": "0.2.0-dev-20261011155313"
35
+ "@fragmentsx/fragments-client": "0.2.0-dev-20261022125555"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@testing-library/jest-dom": "^6.6.3",
39
39
  "@testing-library/react": "^16.0.1",
40
40
  "@types/react": "^19.0.0",
41
41
  "@vitejs/plugin-react": "^4.3.4",
42
+ "@vitest/browser": "4.0.18",
43
+ "@vitest/browser-playwright": "4.0.18",
42
44
  "jsdom": "^27.4.0",
45
+ "playwright": "1.58.2",
43
46
  "react": "^19.0.0",
44
47
  "react-dom": "^19.2.3",
45
48
  "typescript": "^5.5.4",
46
49
  "vite": "^6.1.0",
47
50
  "vite-plugin-dts": "^4.5.0",
48
- "vitest": "^3.1.1",
51
+ "vitest": "4.0.18",
49
52
  "@fragmentsx/definition": "0.2.3"
50
53
  },
51
54
  "scripts": {
@@ -53,6 +56,7 @@
53
56
  "build": "vite build",
54
57
  "dev": "vite build -w",
55
58
  "test": "NODE_OPTIONS=--max-old-space-size=2048 vitest run --config ./vitest.config.ts",
59
+ "test:browser": "NODE_OPTIONS=--max-old-space-size=2048 vitest run --config ./vitest.config.browser.ts",
56
60
  "test:watch": "vitest --config ./vitest.config.ts",
57
61
  "lint": "eslint . --ext .ts,.tsx --fix"
58
62
  }