@fragmentsx/runtime-react 0.2.0-dev-20260928123417 → 0.2.0-dev-20260929143730

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
@@ -60,6 +60,32 @@ function App() {
60
60
  не передан, клиент бьётся в `window.location.origin`, что удобно при
61
61
  same-origin проксировании `/api` на публичный API площадки.
62
62
 
63
+ ## Свойства проекта от хоста
64
+
65
+ Сайт передаёт значение один раз на всё дерево, в том числе на несколько областей:
66
+
67
+ ```tsx
68
+ const [client] = useState(() => createBrowserClient({ apiToken }));
69
+
70
+ <FragmentsProvider client={client} properties={{ langSlug }}>
71
+ <Area areaCode="lang-card" />
72
+ <Area areaCode="lang-header" />
73
+ </FragmentsProvider>
74
+ ```
75
+
76
+ Сайт может перекрыть любое свойство проекта без специальной метки. Значение из студии остаётся запасным: оно видно в preview и на сайте, когда `properties` не передан либо содержит `null`/`undefined`. Смена `properties` реактивно обновляет области без перезагрузки и перемонтирования; инлайн-объект безопасен, потому что сравнение неглубокое.
77
+
78
+ Артефакт читает значение через `useProjectProperty('langSlug')` в корне, во вложенном фрагменте и в слоте. Props варианта, привязанные `$ref` к project-свойству, получают значение сайта также в корне и слотах. Для источника значение передаётся только явно:
79
+
80
+ ```tsx
81
+ const langSlug = useProjectProperty('langSlug');
82
+ const bonuses = useSource('Scores24', { target: 'getBonuses', params: { lang: langSlug } });
83
+ ```
84
+
85
+ Приоритет: `options.props` конкретной `<Area>` > `properties` провайдера > значение студии. Функциональная форма `options.props(serverProps)` получает уже подставленные значения хоста. Хост перекрывает только project-уровень: свойства и привязки area/campaign остаются прежними. Неизвестное свойство молча недоступно — сервер отдаёт только имена, которые используют фрагменты области, и не проверяет тип значения рантайм-переопределения.
86
+
87
+ Если вы строите собственную обёртку на `useArea` вместо `<Area>`, корневые `props` содержат студийные значения, а `projectBindings` несёт карту «ключ prop → имя project-свойства»; `<Area>` подставляет корень, `FragmentRenderer` — слоты. Вложенный `FragmentsProvider` без `properties` сбрасывает значения, поскольку его клиент обычно принадлежит другому проекту.
88
+
63
89
  `Area` разрешает область в non-Suspense режиме; `Suspense` остаётся только
64
90
  вокруг загрузки модулей конуса. На сервере область не резолвится, не требует
65
91
  подключённого `$area` plugin и вместо области отдаёт `options.fallback`. Под капотом:
package/dist/index.d.ts CHANGED
@@ -395,11 +395,13 @@ export { FragmentsLoadError }
395
395
  * useMemo критично — Context value identity stability (без него cache invalidation
396
396
  * на каждый render).
397
397
  */
398
- export declare function FragmentsProvider({ client, children }: FragmentsProviderProps): ReactElement;
398
+ export declare function FragmentsProvider({ client, children, properties }: FragmentsProviderProps): ReactElement;
399
399
 
400
400
  declare interface FragmentsProviderProps {
401
401
  client: FragmentsClient;
402
402
  children: ReactNode;
403
+ /** Значения свойств проекта от сайта: перекрывают студию; null/undefined не переданы. */
404
+ properties?: Readonly<Record<string, unknown>>;
403
405
  }
404
406
 
405
407
  export declare function FragmentStylesheet({ href, fragmentKey, }: FragmentStylesheetProps): ReactElement | null;
@@ -754,6 +756,7 @@ export declare interface UseAreaResult {
754
756
  * потребителю не нужна.
755
757
  */
756
758
  projectProperties: Record<string, unknown>;
759
+ projectBindings: Record<string, string>;
757
760
  /**
758
761
  * URL к глобальному baseline reset CSS ([data-key^="Text"], [data-key^="Fragment"]).
759
762
  * `null` — backend не отдал global reset; baseline применяться не будет.
package/dist/index.es.js CHANGED
@@ -1,33 +1,33 @@
1
- import { jsx as o, jsxs as ae, Fragment as se } from "react/jsx-runtime";
2
- import * as ue from "react";
3
- import { createContext as S, useContext as E, useMemo as w, useState as F, useEffect as g, useLayoutEffect as ce, version as le, Component as oe, Suspense as z, createElement as de, useCallback as x, useRef as G, useReducer as fe } from "react";
4
- import { FragmentsAreaError as ie, toScopeClassName as me, AREA_GLOBAL_CSS_KEY as he, resolveStylesHref as Ee, fragmentCssKey as ve, createSourceCache as ge, sourceCallKey as L, sourceTransportKey as ye, resolveSourceRequest as Se, runSourceFetch as Ae, createFragmentsClient as ke } from "@fragmentsx/fragments-client";
5
- import { FragmentsApiVersionError as Xe, FragmentsAreaError as Ze, FragmentsLoadError as er, createSourceCache as rr } from "@fragmentsx/fragments-client";
6
- const A = S(
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(
7
7
  null
8
8
  );
9
- A.displayName = "FragmentsClientContext";
10
- function Ce(r) {
11
- return /* @__PURE__ */ o(A.Provider, { value: r.value, children: r.children });
9
+ C.displayName = "FragmentsClientContext";
10
+ function we(r) {
11
+ return /* @__PURE__ */ i(C.Provider, { value: r.value, children: r.children });
12
12
  }
13
- function Pe() {
14
- return E(A);
13
+ function Te() {
14
+ return g(C);
15
15
  }
16
- const Y = S(null);
17
- Y.displayName = "InstanceIdContext";
18
- const T = S(
16
+ const J = N(null);
17
+ J.displayName = "InstanceIdContext";
18
+ const T = N(
19
19
  null
20
20
  );
21
21
  T.displayName = "ModulesMapContext";
22
- function Ne({
22
+ function be({
23
23
  value: r,
24
24
  children: e
25
25
  }) {
26
- return /* @__PURE__ */ o(T.Provider, { value: r, children: e });
26
+ return /* @__PURE__ */ i(T.Provider, { value: r, children: e });
27
27
  }
28
- function pe() {
29
- const r = E(A);
30
- return w(
28
+ function qe() {
29
+ const r = g(C);
30
+ return k(
31
31
  () => ({
32
32
  reachGoal: (e) => {
33
33
  var t, n;
@@ -37,17 +37,18 @@ function pe() {
37
37
  [r]
38
38
  );
39
39
  }
40
- function we(r) {
41
- const e = E(T);
40
+ function Fe(r) {
41
+ const e = g(T);
42
42
  if (!e)
43
43
  throw new Error("[useFragmentComponent] No ModulesMapProvider in tree");
44
44
  return e.read(r);
45
45
  }
46
- const D = typeof window < "u", U = Object.freeze({
46
+ const L = typeof window < "u", H = Object.freeze({
47
47
  rootFragmentId: 0,
48
48
  variantId: null,
49
49
  props: {},
50
50
  projectProperties: {},
51
+ projectBindings: {},
51
52
  globalCssUrl: null,
52
53
  // Phase 105 план 105-05: пустой конус — форма возврата хука не меняется,
53
54
  // обёртка рендера (задача 3) остаётся без атрибута class на этом сентинеле.
@@ -56,100 +57,100 @@ const D = typeof window < "u", U = Object.freeze({
56
57
  slots: {},
57
58
  sources: {}
58
59
  });
59
- function _(r) {
60
+ function R(r) {
60
61
  const e = r.$area;
61
62
  if (!(e != null && e.read))
62
63
  throw new Error("[useArea] $area plugin not mounted");
63
64
  return e;
64
65
  }
65
- function Fe(r, e) {
66
- const t = E(A);
66
+ function Re(r, e) {
67
+ const t = g(C);
67
68
  if (!t)
68
69
  throw new Error("[useArea] No FragmentsClientProvider in tree");
69
- const n = (e == null ? void 0 : e.suspense) ?? !0, s = (e == null ? void 0 : e.pause) === !0 || !D && (e == null ? void 0 : e.ssr) === !1, a = (e == null ? void 0 : e.timeout) != null ? { timeout: e.timeout } : void 0, [, i] = F(0);
70
- if (g(() => {
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(() => {
71
72
  if (n || s) return;
72
- const u = _(t);
73
- let l = !0;
74
- return Promise.resolve(u.resolve(r, a)).catch(() => {
73
+ const c = R(t);
74
+ let u = !0;
75
+ return Promise.resolve(c.resolve(r, a)).catch(() => {
75
76
  }).finally(() => {
76
- l && i((d) => d + 1);
77
+ u && o((f) => f + 1);
77
78
  }), () => {
78
- l = !1;
79
+ u = !1;
79
80
  };
80
81
  }, [r, n, e == null ? void 0 : e.pause, e == null ? void 0 : e.timeout, e == null ? void 0 : e.ssr]), n) {
81
82
  if (s)
82
- return U;
83
- const u = _(t);
84
- if (u.has(r) || Promise.resolve(u.resolve(r, a)).catch(() => {
85
- }), !D)
83
+ return H;
84
+ const c = R(t);
85
+ if (c.has(r) || Promise.resolve(c.resolve(r, a)).catch(() => {
86
+ }), !L)
86
87
  try {
87
- return u.read(r);
88
- } catch (l) {
89
- if (l != null && typeof l.then == "function")
90
- throw l;
88
+ return c.read(r);
89
+ } catch (u) {
90
+ if (u != null && typeof u.then == "function")
91
+ throw u;
91
92
  return process.env.NODE_ENV !== "production" && console.error(
92
93
  `[useArea] Area ${r} remained unresolved on the server because its cache reached a terminal state`,
93
- l
94
- ), U;
94
+ u
95
+ ), H;
95
96
  }
96
- return u.read(r);
97
+ return c.read(r);
97
98
  }
98
99
  if (s)
99
100
  return { status: "idle", data: null, error: null };
100
- const m = _(t);
101
- if (m.has(r))
101
+ const h = R(t);
102
+ if (h.has(r))
102
103
  try {
103
- return { status: "ready", data: m.read(r), error: null };
104
- } catch (u) {
104
+ return { status: "ready", data: h.read(r), error: null };
105
+ } catch (c) {
105
106
  return {
106
107
  status: "not-found",
107
108
  data: null,
108
- error: u instanceof Error ? u : new Error(String(u))
109
+ error: c instanceof Error ? c : new Error(String(c))
109
110
  };
110
111
  }
111
- return Promise.resolve(m.resolve(r, a)).catch(() => {
112
+ return Promise.resolve(h.resolve(r, a)).catch(() => {
112
113
  }), { status: "loading", data: null, error: null };
113
114
  }
114
- const J = typeof window < "u", Te = 3e3, N = /* @__PURE__ */ new Map(), q = (r, e) => {
115
- if (!J) {
116
- const h = () => {
115
+ const q = typeof window < "u", _e = 3e3, O = /* @__PURE__ */ new Map(), Q = (r, e) => {
116
+ if (!q) {
117
+ const E = () => {
117
118
  };
118
- return h.loaded = Promise.resolve(), h;
119
+ return E.loaded = Promise.resolve(), E;
119
120
  }
120
- const t = N.get(e);
121
+ const t = O.get(e);
121
122
  if (t) {
122
123
  t.refCount += 1;
123
- const h = () => {
124
- t.refCount -= 1, t.refCount === 0 && (t.clearReadyTimer(), t.linkEl.remove(), N.delete(e));
124
+ const E = () => {
125
+ t.refCount -= 1, t.refCount === 0 && (t.clearReadyTimer(), t.linkEl.remove(), O.delete(e));
125
126
  };
126
- return h.loaded = t.loaded, h;
127
+ return E.loaded = t.loaded, E;
127
128
  }
128
129
  const n = document.createElement("link");
129
130
  n.rel = "stylesheet", n.href = r, n.setAttribute("data-fragment-key", e);
130
131
  let s;
131
- const a = new Promise((h) => {
132
- s = h;
133
- }), i = () => {
134
- u(), s();
135
- }, m = setTimeout(i, Te), u = () => clearTimeout(m);
136
- n.addEventListener("load", i), n.addEventListener("error", i), document.head.appendChild(n);
137
- const l = { refCount: 1, linkEl: n, loaded: a, clearReadyTimer: u };
138
- N.set(e, l);
139
- const d = () => {
140
- l.refCount -= 1, l.refCount === 0 && (l.clearReadyTimer(), l.linkEl.remove(), N.delete(e));
132
+ const a = new Promise((E) => {
133
+ s = E;
134
+ }), o = () => {
135
+ c(), s();
136
+ }, h = setTimeout(o, _e), c = () => clearTimeout(h);
137
+ 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));
141
142
  };
142
- return d.loaded = a, d;
143
- }, Re = J ? ce : g;
144
- function _e(r, e) {
145
- Re(() => q(r, e), [r, e]);
143
+ return f.loaded = a, f;
144
+ }, xe = q ? ie : P;
145
+ function je(r, e) {
146
+ xe(() => Q(r, e), [r, e]);
146
147
  }
147
- const xe = parseInt(le.split(".")[0], 10), Oe = xe >= 19;
148
- function V({
148
+ const Ie = parseInt(fe.split(".")[0], 10), Me = Ie >= 19;
149
+ function U({
149
150
  href: r,
150
151
  fragmentKey: e
151
152
  }) {
152
- return Oe ? /* @__PURE__ */ o(
153
+ return Me ? /* @__PURE__ */ i(
153
154
  "link",
154
155
  {
155
156
  rel: "stylesheet",
@@ -157,48 +158,50 @@ function V({
157
158
  precedence: "default",
158
159
  "data-fragment-key": e
159
160
  }
160
- ) : (_e(r, e), null);
161
+ ) : (je(r, e), null);
161
162
  }
162
- function Ke(r) {
163
+ function Qe(r) {
163
164
  }
164
- const Q = {}, O = S(null);
165
- O.displayName = "ProjectPropertiesContext";
166
- const W = Object.freeze({}), b = S(W);
167
- b.displayName = "SourceTransportsContext";
168
- const I = S("live");
169
- I.displayName = "SourceNetworkContext";
170
- function B(r) {
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) {
171
174
  const e = r instanceof Error ? r : new Error(String(r));
172
- if (!(e instanceof ie))
175
+ if (!(e instanceof ge))
173
176
  return { kind: "failed", error: e };
174
177
  const { code: t } = e;
175
178
  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 };
176
179
  }
177
- function X(r, e, t) {
180
+ function ee(r, e, t) {
178
181
  return typeof r == "function" ? r(e, t) : r ?? null;
179
182
  }
180
- const be = () => {
183
+ const pe = () => {
181
184
  };
182
- function p(r) {
185
+ function K(r) {
183
186
  return r instanceof Error ? r : new Error(String(r));
184
187
  }
185
- class Z extends oe {
188
+ class re extends me {
186
189
  constructor() {
187
190
  super(...arguments), this.state = { hasError: !1, error: null };
188
191
  }
189
192
  static getDerivedStateFromError(e) {
190
- return { hasError: !0, error: p(e) };
193
+ return { hasError: !0, error: K(e) };
191
194
  }
192
195
  componentDidCatch(e, t) {
193
196
  var s, a;
194
- const n = p(e);
197
+ const n = K(e);
195
198
  process.env.NODE_ENV !== "production" && console.error("[fragments] Area error:", n, t.componentStack), (a = (s = this.props).onError) == null || a.call(s, n);
196
199
  }
197
200
  render() {
198
201
  if (this.state.hasError) {
199
202
  const e = { kind: "failed", error: this.state.error ?? new Error("Unknown Area error") };
200
203
  try {
201
- return X(this.props.empty, e, this.props.retry ?? be);
204
+ return ee(this.props.empty, e, this.props.retry ?? pe);
202
205
  } catch {
203
206
  return null;
204
207
  }
@@ -206,188 +209,214 @@ class Z extends oe {
206
209
  return this.props.children;
207
210
  }
208
211
  }
209
- function ee(r, e) {
210
- if (!r) return {};
211
- const t = {};
212
- for (const n of Object.keys(r))
213
- t[n] = Ie(r[n], e);
214
- return t;
212
+ function $e(r, e) {
213
+ let t;
214
+ for (const [n, s] of Object.entries(e))
215
+ s != null && (t ?? (t = { ...r }), t[n] = s);
216
+ return t ?? r;
215
217
  }
216
- function Ie(r, e) {
217
- return Array.isArray(r) ? r.map((t, n) => t === null ? null : K(t, e, n)) : K(r, e);
218
+ function Be(r, e) {
219
+ const t = Object.keys(r);
220
+ return t.length !== Object.keys(e).length ? !1 : t.every((n) => Object.prototype.hasOwnProperty.call(e, n) && Object.is(r[n], e[n]));
218
221
  }
219
- function K(r, e, t) {
222
+ const te = Object.freeze({});
223
+ function ne(r, e, t) {
220
224
  let n;
225
+ for (const [s, a] of Object.entries(e)) {
226
+ const o = t[a];
227
+ o != null && (n ?? (n = { ...r }), n[s] = o);
228
+ }
229
+ return n ?? r;
230
+ }
231
+ function se(r, e, t) {
232
+ if (!r) return {};
233
+ const n = {};
234
+ for (const s of Object.keys(r))
235
+ n[s] = De(r[s], e, t);
236
+ return n;
237
+ }
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);
240
+ }
241
+ function z(r, e, t, n) {
242
+ let s;
221
243
  try {
222
- n = e(r.fragmentId);
223
- } catch (a) {
224
- if (a != null && typeof a.then == "function")
225
- throw a;
226
- return console.warn(`[FragmentRenderer] Slot fragment ${r.fragmentId} failed to load — rendering empty hole`, a), null;
244
+ s = e(r.fragmentId);
245
+ } catch (o) {
246
+ if (o != null && typeof o.then == "function")
247
+ throw o;
248
+ return console.warn(`[FragmentRenderer] Slot fragment ${r.fragmentId} failed to load — rendering empty hole`, o), null;
227
249
  }
228
- const s = ee(r.slots, e);
229
- return de(n, { key: t, ...r.props, ...s });
250
+ const a = se(r.slots, e, t);
251
+ return he(s, { key: n, ...ne(r.props, r.projectBindings ?? te, t), ...a });
230
252
  }
231
- const re = ({
253
+ const ae = ({
232
254
  fragmentId: r,
233
255
  props: e,
234
256
  globalCssUrl: t = null,
235
- projectProperties: n = Q,
257
+ projectProperties: n = X,
236
258
  fragments: s = [r],
237
259
  slots: a,
238
- sources: i = W,
239
- sourceNetwork: m = "live"
260
+ sources: o = Z,
261
+ sourceNetwork: h = "live"
240
262
  }) => {
241
- const u = we(r), l = E(T);
242
- if (!l)
263
+ const c = Fe(r), u = g(T), f = g(b);
264
+ if (!u)
243
265
  throw new Error("[FragmentRendererInner] No ModulesMapProvider in tree");
244
- const d = ee(a, l.read), h = { ...e ?? {}, ...d }, y = s.length > 0 ? s.map(me).join(" ") : void 0;
245
- return /* @__PURE__ */ ae(se, { children: [
246
- t != null && /* @__PURE__ */ o(
247
- V,
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,
248
273
  {
249
274
  href: t,
250
- fragmentKey: he
275
+ fragmentKey: ye
251
276
  }
252
277
  ),
253
- s.map((c) => {
254
- const v = Ee(c);
255
- return v ? /* @__PURE__ */ o(
256
- V,
278
+ s.map((y) => {
279
+ const m = Se(y);
280
+ return m ? /* @__PURE__ */ i(
281
+ U,
257
282
  {
258
- href: v,
259
- fragmentKey: ve(c)
283
+ href: m,
284
+ fragmentKey: Pe(y)
260
285
  },
261
- c
286
+ y
262
287
  ) : null;
263
288
  }),
264
- /* @__PURE__ */ o(I.Provider, { value: m, children: /* @__PURE__ */ o(b.Provider, { value: i, children: /* @__PURE__ */ o(O.Provider, { value: n, children: /* @__PURE__ */ o(Y.Provider, { value: null, children: /* @__PURE__ */ o(
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(
265
290
  "div",
266
291
  {
267
- className: y,
292
+ className: v,
268
293
  style: { display: "contents" },
269
- children: /* @__PURE__ */ o(u, { ...h })
294
+ children: /* @__PURE__ */ i(c, { ...l })
270
295
  }
271
296
  ) }) }) }) })
272
297
  ] });
273
- }, He = ({ onError: r, ...e }) => /* @__PURE__ */ o(z, { fallback: null, children: /* @__PURE__ */ o(Z, { onError: r, children: /* @__PURE__ */ o(re, { ...e }) }) }), Me = ({ areaCode: r, options: e, retry: t }) => {
274
- const n = Fe(r, {
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, {
275
300
  suspense: !1,
276
301
  ssr: !1,
277
302
  pause: e == null ? void 0 : e.pause,
278
303
  timeout: e == null ? void 0 : e.timeout
279
- }), s = G(null);
280
- if (g(() => {
281
- var k;
304
+ }), s = g(b), a = x(null);
305
+ if (P(() => {
306
+ var S;
282
307
  if (n.status !== "not-found" || !n.error) return;
283
- const c = B(n.error), v = JSON.stringify([r, c.kind, c.code, c.error.message]);
284
- s.current !== v && (s.current = v, (k = e == null ? void 0 : e.onError) == null || k.call(e, c.error), process.env.NODE_ENV !== "production" && c.kind !== "no-variant" && console.error(
285
- `[fragments] Area resolution ${c.kind}: areaCode=${r}, code=${c.code ?? "none"}`,
286
- c.error
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
287
312
  ));
288
313
  }, [r, e == null ? void 0 : e.onError, n.error, n.status]), (e == null ? void 0 : e.pause) === !0)
289
314
  return null;
290
315
  if (n.status === "idle")
291
316
  return (e == null ? void 0 : e.fallback) ?? null;
292
317
  if (n.status === "not-found")
293
- return X(e == null ? void 0 : e.empty, B(n.error), t);
318
+ return ee(e == null ? void 0 : e.empty, V(n.error), t);
294
319
  if (n.status === "loading" || !n.data)
295
320
  return (e == null ? void 0 : e.fallback) ?? null;
296
- const { rootFragmentId: a, props: i, projectProperties: m, globalCssUrl: u, fragments: l, slots: d, sources: h } = n.data, y = typeof (e == null ? void 0 : e.props) == "function" ? e.props(i) : e != null && e.props ? { ...i, ...e.props } : i;
297
- return /* @__PURE__ */ o(z, { fallback: (e == null ? void 0 : e.fallback) ?? null, children: /* @__PURE__ */ o(
298
- re,
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,
299
324
  {
300
- fragmentId: a,
325
+ fragmentId: o,
301
326
  props: y,
302
327
  globalCssUrl: u,
303
- projectProperties: m,
304
- fragments: l,
305
- slots: d,
306
- sources: h
328
+ projectProperties: c,
329
+ fragments: f,
330
+ slots: E,
331
+ sources: A
307
332
  }
308
333
  ) });
309
- }, ze = ({ areaCode: r, options: e }) => {
310
- const t = E(A), [n, s] = F(0), a = t == null ? void 0 : t.$area;
311
- g(() => {
334
+ }, Xe = ({ areaCode: r, options: e }) => {
335
+ const t = g(C), [n, s] = w(0), a = t == null ? void 0 : t.$area;
336
+ P(() => {
312
337
  (e == null ? void 0 : e.ssr) !== !0 || process.env.NODE_ENV === "production" || console.error(
313
338
  "[fragments] Area option `ssr` is reserved: server resolution has been removed from the runtime; existing `ssr: false` calls continue to work unchanged."
314
339
  );
315
340
  }, [e == null ? void 0 : e.ssr]);
316
- const i = x(() => {
341
+ const o = _(() => {
317
342
  a != null && a.resolve && (a.resolve(r).catch(() => {
318
- }), s((m) => m + 1));
343
+ }), s((h) => h + 1));
319
344
  }, [a, r]);
320
345
  return (
321
346
  // A retry remounts the boundary and AreaInner: a repeated failure is a new
322
347
  // telemetry event, so AreaInner intentionally calls options.onError again.
323
- /* @__PURE__ */ o(Z, { onError: e == null ? void 0 : e.onError, empty: e == null ? void 0 : e.empty, retry: i, children: /* @__PURE__ */ o(Me, { areaCode: r, options: e, retry: i }) }, n)
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)
324
349
  );
325
350
  };
326
- function Ge({ client: r, children: e }) {
327
- const t = w(
351
+ function He(r) {
352
+ const e = r ?? W, t = x(e);
353
+ return Be(t.current, e) || (t.current = e), t.current;
354
+ }
355
+ function Ze({ client: r, children: e, properties: t }) {
356
+ const n = k(
328
357
  () => ({
329
- read: (n) => r.$fragments.read(n)
358
+ read: (a) => r.$fragments.read(a)
330
359
  }),
331
360
  [r]
332
- );
333
- return /* @__PURE__ */ o(Ce, { value: r, children: /* @__PURE__ */ o(Ne, { value: t, children: e }) });
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 }) }) });
334
363
  }
335
- function Ye(r) {
336
- return (E(O) ?? Q)[r];
364
+ function er(r) {
365
+ return (g(j) ?? X)[r];
337
366
  }
338
- function je(r, e) {
339
- const [, t] = fe((a) => a + 1, 0), n = e(), s = G(n);
340
- return s.current = n, g(() => {
367
+ function Ue(r, e) {
368
+ const [, t] = Ee((a) => a + 1, 0), n = e(), s = x(n);
369
+ return s.current = n, P(() => {
341
370
  const a = r(t);
342
371
  return Object.is(s.current, e()) || t(), a;
343
372
  }, [r, e]), n;
344
373
  }
345
- const H = ue.useSyncExternalStore, $e = H || ((r, e) => je(r, e)), te = "offline", Le = () => Promise.reject(new Error(te));
346
- function De(r, e) {
347
- var j, $;
348
- const t = Pe(), [n] = F(ge), s = (t == null ? void 0 : t.sourceCache) ?? n, a = (j = t == null ? void 0 : t.sourceFetchers) == null ? void 0 : j[r], i = ($ = t == null ? void 0 : t.sourceBaseUrls) == null ? void 0 : $[r], m = a ? "host-fetch" : "network", u = t == null ? void 0 : t.env, l = L({ source: r, target: e.target, params: e.params }), d = w(() => ({ source: r, target: e.target, params: e.params }), [l]), h = x((R) => s.subscribe(d, R), [s, d]), y = x(() => s.get(d), [s, d]), c = $e(h, y, y), v = E(I), k = E(b), P = ye(r, e.target), f = w(
349
- () => v === te ? null : Se(k[P], d.params, i),
350
- [v, k, P, d, i]
351
- ), [C, M] = F(null);
352
- return g(() => {
353
- (c == null ? void 0 : c.status) === "ready" && C !== null && M(null);
354
- }, [c, C]), g(() => {
355
- f && !f.ok && c === void 0 && console.warn(`[useSource] ${P}: ${f.reason}`);
356
- }, [P, f == null ? void 0 : f.ok, f && !f.ok ? f.reason : void 0, c === void 0]), g(() => {
357
- if (f && !f.ok || (c == null ? void 0 : c.status) === "ready" || C === l) return;
358
- M(l);
359
- const R = f && f.ok ? () => Ae({ url: f.url, init: f.init }, { fetcher: a, timeout: u == null ? void 0 : u.timeout }).then((ne) => (u != null && u.debug && console.info(`[useSource] loaded ${L(d)} origin=${m}`), ne)) : Le;
360
- s.load(d, R, m);
361
- }, [s, d, l, c, C, f, a, m, u == null ? void 0 : u.timeout, u == null ? void 0 : u.debug]), (c == null ? void 0 : c.status) === "ready" ? { data: c.data ?? void 0, loading: !1 } : (c == null ? void 0 : c.status) === "pending" ? { data: void 0, loading: !0 } : f && !f.ok ? { data: void 0, loading: !1 } : { data: void 0, loading: C !== l };
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 };
362
391
  }
363
- const Je = De;
364
- function qe(r) {
365
- return ke({ ...r, inject: q });
392
+ const rr = ze;
393
+ function tr(r) {
394
+ return Oe({ ...r, inject: Q });
366
395
  }
367
396
  export {
368
- U as AREA_UNRESOLVED,
369
- ze as Area,
370
- He as FragmentRenderer,
371
- V as FragmentStylesheet,
372
- Xe as FragmentsApiVersionError,
373
- Ze as FragmentsAreaError,
374
- A as FragmentsClientContext,
375
- Ce as FragmentsClientProvider,
376
- er as FragmentsLoadError,
377
- Ge as FragmentsProvider,
378
- Y as InstanceIdContext,
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,
379
408
  T as ModulesMapContext,
380
- Ne as ModulesMapProvider,
381
- O as ProjectPropertiesContext,
382
- qe as createBrowserClient,
383
- rr as createSourceCache,
384
- Q as defaultProjectProperties,
385
- q as injectStylesheet,
386
- Fe as useArea,
387
- Ke as useCssChunk,
388
- we as useFragmentComponent,
389
- pe as useFragmentMetrics,
390
- _e as useFragmentStylesheet,
391
- Ye as useProjectProperty,
392
- Je as useSource
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
393
422
  };
package/dist/index.umd.js CHANGED
@@ -1 +1 @@
1
- (function(s,d){typeof exports=="object"&&typeof module<"u"?d(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"],d):(s=typeof globalThis<"u"?globalThis:s||self,d(s.FragmentsRuntimeReact={},s.jsxRuntime,s.React,s.fragmentsClient))})(this,function(s,d,u,h){"use strict";function te(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 ne=te(u),S=u.createContext(null);S.displayName="FragmentsClientContext";function D(r){return d.jsx(S.Provider,{value:r.value,children:r.children})}function ue(){return u.useContext(S)}const O=u.createContext(null);O.displayName="InstanceIdContext";const C=u.createContext(null);C.displayName="ModulesMapContext";function L({value:r,children:e}){return d.jsx(C.Provider,{value:r,children:e})}function se(){const r=u.useContext(S);return u.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 U(r){const e=u.useContext(C);if(!e)throw new Error("[useFragmentComponent] No ModulesMapProvider in tree");return e.read(r)}const V=typeof window<"u",w=Object.freeze({rootFragmentId:0,variantId:null,props:{},projectProperties:{},globalCssUrl:null,fragments:[],slots:{},sources:{}});function T(r){const e=r.$area;if(!(e!=null&&e.read))throw new Error("[useArea] $area plugin not mounted");return e}function B(r,e){const t=u.useContext(S);if(!t)throw new Error("[useArea] No FragmentsClientProvider in tree");const n=(e==null?void 0:e.suspense)??!0,c=(e==null?void 0:e.pause)===!0||!V&&(e==null?void 0:e.ssr)===!1,a=(e==null?void 0:e.timeout)!=null?{timeout:e.timeout}:void 0,[,E]=u.useState(0);if(u.useEffect(()=>{if(n||c)return;const o=T(t);let f=!0;return Promise.resolve(o.resolve(r,a)).catch(()=>{}).finally(()=>{f&&E(i=>i+1)}),()=>{f=!1}},[r,n,e==null?void 0:e.pause,e==null?void 0:e.timeout,e==null?void 0:e.ssr]),n){if(c)return w;const o=T(t);if(o.has(r)||Promise.resolve(o.resolve(r,a)).catch(()=>{}),!V)try{return o.read(r)}catch(f){if(f!=null&&typeof f.then=="function")throw f;return process.env.NODE_ENV!=="production"&&console.error(`[useArea] Area ${r} remained unresolved on the server because its cache reached a terminal state`,f),w}return o.read(r)}if(c)return{status:"idle",data:null,error:null};const g=T(t);if(g.has(r))try{return{status:"ready",data:g.read(r),error:null}}catch(o){return{status:"not-found",data:null,error:o instanceof Error?o:new Error(String(o))}}return Promise.resolve(g.resolve(r,a)).catch(()=>{}),{status:"loading",data:null,error:null}}const K=typeof window<"u",ae=3e3,k=new Map,M=(r,e)=>{if(!K){const v=()=>{};return v.loaded=Promise.resolve(),v}const t=k.get(e);if(t){t.refCount+=1;const v=()=>{t.refCount-=1,t.refCount===0&&(t.clearReadyTimer(),t.linkEl.remove(),k.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 c;const a=new Promise(v=>{c=v}),E=()=>{o(),c()},g=setTimeout(E,ae),o=()=>clearTimeout(g);n.addEventListener("load",E),n.addEventListener("error",E),document.head.appendChild(n);const f={refCount:1,linkEl:n,loaded:a,clearReadyTimer:o};k.set(e,f);const i=()=>{f.refCount-=1,f.refCount===0&&(f.clearReadyTimer(),f.linkEl.remove(),k.delete(e))};return i.loaded=a,i},ce=K?u.useLayoutEffect:u.useEffect;function z(r,e){ce(()=>M(r,e),[r,e])}const oe=parseInt(u.version.split(".")[0],10)>=19;function _({href:r,fragmentKey:e}){return oe?d.jsx("link",{rel:"stylesheet",href:r,precedence:"default","data-fragment-key":e}):(z(r,e),null)}function le(r){}const j={},b=u.createContext(null);b.displayName="ProjectPropertiesContext";const H=Object.freeze({}),I=u.createContext(H);I.displayName="SourceTransportsContext";const x=u.createContext("live");x.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 Y(r,e,t){return typeof r=="function"?r(e,t):r??null}const de=()=>{};function q(r){return r instanceof Error?r:new Error(String(r))}class J extends u.Component{constructor(){super(...arguments),this.state={hasError:!1,error:null}}static getDerivedStateFromError(e){return{hasError:!0,error:q(e)}}componentDidCatch(e,t){var c,a;const n=q(e);process.env.NODE_ENV!=="production"&&console.error("[fragments] Area error:",n,t.componentStack),(a=(c=this.props).onError)==null||a.call(c,n)}render(){if(this.state.hasError){const e={kind:"failed",error:this.state.error??new Error("Unknown Area error")};try{return Y(this.props.empty,e,this.props.retry??de)}catch{return null}}return this.props.children}}function p(r,e){if(!r)return{};const t={};for(const n of Object.keys(r))t[n]=fe(r[n],e);return t}function fe(r,e){return Array.isArray(r)?r.map((t,n)=>t===null?null:Q(t,e,n)):Q(r,e)}function Q(r,e,t){let n;try{n=e(r.fragmentId)}catch(a){if(a!=null&&typeof a.then=="function")throw a;return console.warn(`[FragmentRenderer] Slot fragment ${r.fragmentId} failed to load — rendering empty hole`,a),null}const c=p(r.slots,e);return u.createElement(n,{key:t,...r.props,...c})}const W=({fragmentId:r,props:e,globalCssUrl:t=null,projectProperties:n=j,fragments:c=[r],slots:a,sources:E=H,sourceNetwork:g="live"})=>{const o=U(r),f=u.useContext(C);if(!f)throw new Error("[FragmentRendererInner] No ModulesMapProvider in tree");const i=p(a,f.read),v={...e??{},...i},P=c.length>0?c.map(h.toScopeClassName).join(" "):void 0;return d.jsxs(d.Fragment,{children:[t!=null&&d.jsx(_,{href:t,fragmentKey:h.AREA_GLOBAL_CSS_KEY}),c.map(l=>{const y=h.resolveStylesHref(l);return y?d.jsx(_,{href:y,fragmentKey:h.fragmentCssKey(l)},l):null}),d.jsx(x.Provider,{value:g,children:d.jsx(I.Provider,{value:E,children:d.jsx(b.Provider,{value:n,children:d.jsx(O.Provider,{value:null,children:d.jsx("div",{className:P,style:{display:"contents"},children:d.jsx(o,{...v})})})})})})]})},ie=({onError:r,...e})=>d.jsx(u.Suspense,{fallback:null,children:d.jsx(J,{onError:r,children:d.jsx(W,{...e})})}),me=({areaCode:r,options:e,retry:t})=>{const n=B(r,{suspense:!1,ssr:!1,pause:e==null?void 0:e.pause,timeout:e==null?void 0:e.timeout}),c=u.useRef(null);if(u.useEffect(()=>{var A;if(n.status!=="not-found"||!n.error)return;const l=G(n.error),y=JSON.stringify([r,l.kind,l.code,l.error.message]);c.current!==y&&(c.current=y,(A=e==null?void 0:e.onError)==null||A.call(e,l.error),process.env.NODE_ENV!=="production"&&l.kind!=="no-variant"&&console.error(`[fragments] Area resolution ${l.kind}: areaCode=${r}, code=${l.code??"none"}`,l.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 Y(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:a,props:E,projectProperties:g,globalCssUrl:o,fragments:f,slots:i,sources:v}=n.data,P=typeof(e==null?void 0:e.props)=="function"?e.props(E):e!=null&&e.props?{...E,...e.props}:E;return d.jsx(u.Suspense,{fallback:(e==null?void 0:e.fallback)??null,children:d.jsx(W,{fragmentId:a,props:P,globalCssUrl:o,projectProperties:g,fragments:f,slots:i,sources:v})})},Ee=({areaCode:r,options:e})=>{const t=u.useContext(S),[n,c]=u.useState(0),a=t==null?void 0:t.$area;u.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 E=u.useCallback(()=>{a!=null&&a.resolve&&(a.resolve(r).catch(()=>{}),c(g=>g+1))},[a,r]);return d.jsx(J,{onError:e==null?void 0:e.onError,empty:e==null?void 0:e.empty,retry:E,children:d.jsx(me,{areaCode:r,options:e,retry:E})},n)};function he({client:r,children:e}){const t=u.useMemo(()=>({read:n=>r.$fragments.read(n)}),[r]);return d.jsx(D,{value:r,children:d.jsx(L,{value:t,children:e})})}function ge(r){return(u.useContext(b)??j)[r]}function ve(r,e){const[,t]=u.useReducer(a=>a+1,0),n=e(),c=u.useRef(n);return c.current=n,u.useEffect(()=>{const a=r(t);return Object.is(c.current,e())||t(),a},[r,e]),n}const X=ne.useSyncExternalStore,ye=X||((r,e)=>ve(r,e)),Z="offline",Se=()=>Promise.reject(new Error(Z));function Pe(r,e){var ee,re;const t=ue(),[n]=u.useState(h.createSourceCache),c=(t==null?void 0:t.sourceCache)??n,a=(ee=t==null?void 0:t.sourceFetchers)==null?void 0:ee[r],E=(re=t==null?void 0:t.sourceBaseUrls)==null?void 0:re[r],g=a?"host-fetch":"network",o=t==null?void 0:t.env,f=h.sourceCallKey({source:r,target:e.target,params:e.params}),i=u.useMemo(()=>({source:r,target:e.target,params:e.params}),[f]),v=u.useCallback($=>c.subscribe(i,$),[c,i]),P=u.useCallback(()=>c.get(i),[c,i]),l=ye(v,P,P),y=u.useContext(x),A=u.useContext(I),N=h.sourceTransportKey(r,e.target),m=u.useMemo(()=>y===Z?null:h.resolveSourceRequest(A[N],i.params,E),[y,A,N,i,E]),[F,R]=u.useState(null);return u.useEffect(()=>{(l==null?void 0:l.status)==="ready"&&F!==null&&R(null)},[l,F]),u.useEffect(()=>{m&&!m.ok&&l===void 0&&console.warn(`[useSource] ${N}: ${m.reason}`)},[N,m==null?void 0:m.ok,m&&!m.ok?m.reason:void 0,l===void 0]),u.useEffect(()=>{if(m&&!m.ok||(l==null?void 0:l.status)==="ready"||F===f)return;R(f);const $=m&&m.ok?()=>h.runSourceFetch({url:m.url,init:m.init},{fetcher:a,timeout:o==null?void 0:o.timeout}).then(Fe=>(o!=null&&o.debug&&console.info(`[useSource] loaded ${h.sourceCallKey(i)} origin=${g}`),Fe)):Se;c.load(i,$,g)},[c,i,f,l,F,m,a,g,o==null?void 0:o.timeout,o==null?void 0:o.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}:m&&!m.ok?{data:void 0,loading:!1}:{data:void 0,loading:F!==f}}const Ce=Pe;function Ae(r){return h.createFragmentsClient({...r,inject:M})}Object.defineProperty(s,"FragmentsApiVersionError",{enumerable:!0,get:()=>h.FragmentsApiVersionError}),Object.defineProperty(s,"FragmentsAreaError",{enumerable:!0,get:()=>h.FragmentsAreaError}),Object.defineProperty(s,"FragmentsLoadError",{enumerable:!0,get:()=>h.FragmentsLoadError}),Object.defineProperty(s,"createSourceCache",{enumerable:!0,get:()=>h.createSourceCache}),s.AREA_UNRESOLVED=w,s.Area=Ee,s.FragmentRenderer=ie,s.FragmentStylesheet=_,s.FragmentsClientContext=S,s.FragmentsClientProvider=D,s.FragmentsProvider=he,s.InstanceIdContext=O,s.ModulesMapContext=C,s.ModulesMapProvider=L,s.ProjectPropertiesContext=b,s.createBrowserClient=Ae,s.defaultProjectProperties=j,s.injectStylesheet=M,s.useArea=B,s.useCssChunk=le,s.useFragmentComponent=U,s.useFragmentMetrics=se,s.useFragmentStylesheet=z,s.useProjectProperty=ge,s.useSource=Ce,Object.defineProperty(s,Symbol.toStringTag,{value:"Module"})});
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"})});
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-20260928123417",
4
+ "version": "0.2.0-dev-20260929143730",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -32,7 +32,7 @@
32
32
  },
33
33
  "dependencies": {
34
34
  "@graph-state/core": "^0.13.3",
35
- "@fragmentsx/fragments-client": "0.2.0-dev-20260928123417"
35
+ "@fragmentsx/fragments-client": "0.2.0-dev-20260929143730"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@testing-library/jest-dom": "^6.6.3",