@fragmentsx/runtime-react 0.2.0-dev-20260922090625 → 0.2.0-dev-20260928114300

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,8 +60,9 @@ function App() {
60
60
  не передан, клиент бьётся в `window.location.origin`, что удобно при
61
61
  same-origin проксировании `/api` на публичный API площадки.
62
62
 
63
- `Area` сама разрешает область и внутри себя обёрнута в `Suspense` — пока
64
- манифест грузится, поддерево пустое. Под капотом:
63
+ `Area` разрешает область в non-Suspense режиме; `Suspense` остаётся только
64
+ вокруг загрузки модулей конуса. На сервере область не резолвится, не требует
65
+ подключённого `$area` plugin и вместо области отдаёт `options.fallback`. Под капотом:
65
66
 
66
67
  ```
67
68
  <Area areaCode> → GET <backendEndpoint>/api/area/<code>/compiled
@@ -79,10 +80,12 @@ import { FragmentRenderer } from '@fragmentsx/runtime-react';
79
80
  <FragmentRenderer fragmentId={42} props={{ title: 'Привет' }} />
80
81
  ```
81
82
 
82
- `AreaProps` — `{ areaCode: string; options?: { timeout?, pause?, ssr? } }`.
83
+ `AreaProps` — `{ areaCode: string; options?: { timeout?, pause?, ssr? (зарезервирована), props?, fallback?, onError?, empty? } }`.
83
84
  `FragmentRendererProps` — `{ fragmentId: number; props?; globalCssUrl?;
84
85
  projectProperties?; onError? }`.
85
86
 
87
+ `options.fallback` показывает узел, пока область или модули загружаются; `options.empty` — когда контента не будет. `empty` принимает React-узел либо функцию `(reason, retry) => ReactNode`: `reason.kind` бывает `no-variant`, `misconfigured` или `failed`, а `retry` доступен только функциональной форме и намеренно не троттлится. `reason` предназначен для ветвления и диагностики, а не для готового к показу текста: `reason.error` и его код — внутренняя диагностика Fragments, решение об их отображении принимает площадка.
88
+
86
89
  ## Обработка ошибок
87
90
 
88
91
  Пакет реэкспортирует типизированные ошибки транспорта, чтобы их можно было
package/dist/index.d.ts CHANGED
@@ -1,7 +1,9 @@
1
+ import { AreaSourceTransport } from '@fragmentsx/fragments-client';
1
2
  import { ComponentType } from 'react';
2
3
  import { Context } from 'react';
3
4
  import { createFragmentsClient } from '@fragmentsx/fragments-client';
4
5
  import { CreateFragmentsClientOptions } from '@fragmentsx/fragments-client';
6
+ import { createSourceCache } from '@fragmentsx/fragments-client';
5
7
  import { FC } from 'react';
6
8
  import { FragmentsApiVersionError } from '@fragmentsx/fragments-client';
7
9
  import { FragmentsAreaError } from '@fragmentsx/fragments-client';
@@ -10,6 +12,13 @@ import { GraphState } from '@graph-state/core';
10
12
  import { ReactElement } from 'react';
11
13
  import { ReactNode } from 'react';
12
14
  import { ResolvedSlotPosition } from '@fragmentsx/fragments-client';
15
+ import { SourceCache } from '@fragmentsx/fragments-client';
16
+ import { SourceCacheEntry } from '@fragmentsx/fragments-client';
17
+ import { SourceCall } from '@fragmentsx/fragments-client';
18
+ import { SourceOrigin } from '@fragmentsx/fragments-client';
19
+ import { SourcePendingEntry } from '@fragmentsx/fragments-client';
20
+ import { SourceReadyEntry } from '@fragmentsx/fragments-client';
21
+ import { SourceRun } from '@fragmentsx/fragments-client';
13
22
 
14
23
  /**
15
24
  * Area — публичный компонент для рендеринга compiled fragment в consumer app.
@@ -21,8 +30,8 @@ export declare const Area: FC<AreaProps>;
21
30
 
22
31
  /**
23
32
  * Сентинел нерезолвленной области — возвращается вместо чтения `$area.read`,
24
- * когда на сервере `options.ssr === false`, либо когда `options.pause === true`
25
- * (suspense-режим).
33
+ * когда на сервере `options.ssr === false`, при терминальной ошибке серверного
34
+ * suspense-чтения (D-110-04), либо когда `options.pause === true`.
26
35
  *
27
36
  * Совместим с `UseAreaResult` по форме (тип возврата хука не расширяется),
28
37
  * поэтому правка остаётся minor: потребитель, передающий `rootFragmentId`
@@ -31,22 +40,38 @@ export declare const Area: FC<AreaProps>;
31
40
  */
32
41
  export declare const AREA_UNRESOLVED: UseAreaResult;
33
42
 
43
+ /** ФБ-04: static or contextual replacement content for a terminal Area outcome. */
44
+ export declare type AreaEmpty = ReactNode | ((reason: AreaEmptyReason, retry: () => void) => ReactNode);
45
+
46
+ /** D-110-01: terminal area resolution outcome exposed to the consumer fallback. */
47
+ export declare type AreaEmptyReason = {
48
+ kind: AreaEmptyReasonKind;
49
+ code?: string;
50
+ error: Error;
51
+ };
52
+
53
+ /** D-110-01/D-110-02: semantic category for a terminal area resolution outcome. */
54
+ export declare type AreaEmptyReasonKind = "no-variant" | "misconfigured" | "failed";
55
+
34
56
  /**
35
57
  * Props для Area компонента (D-09, сокращён Phase 73 B-13; расширен quick 260830-rvp):
36
58
  * - areaCode — строковый код области (Area.code в backend schema)
37
59
  * - options.pause — пропустить рендер (conditional skip per legacy contract)
38
60
  * - options.timeout — network timeout для $area.resolve fetch
39
- * - options.ssr — отключить auto-resolve в SSR environment (default `true`);
40
- * в browser auto-resolve запускается всегда. Параллель к render-react
41
- * Area options.ssr.
61
+ * - options.ssr — зарезервирована ради совместимости сигнатуры и не влияет
62
+ * на resolve: Area всегда отключает серверный resolve (ФБ-06). Рабочая
63
+ * опция сохранила бы известную SSR-мину, а тихое игнорирование стало бы
64
+ * ловушкой для площадки; удаление требует отдельного решения.
42
65
  * - options.props (INT-03) — объект мержится поверх серверных props (ключи
43
66
  * потребителя выигрывают), функция вызывается с серверными props и её
44
67
  * результат уходит в артефакт целиком. Обе формы поддержаны намеренно —
45
68
  * паритет с legacy render-react, с которого мигрирует потребитель.
46
69
  * - options.fallback (INT-04) — узел, видимый до разрешения области; default
47
- * `null` (прежнее поведение).
48
- * - options.onError (INT-04) — вызывается при броске внутри поддерева;
49
- * default — только dev-лог границы (прежнее поведение).
70
+ * `null` (прежнее поведение); в отличие от `empty`, это только загрузка.
71
+ * - options.empty (ФБ-01/ФБ-03/ФБ-04) — узел либо функция для терминального
72
+ * отсутствия контента; без него область, как и прежде, остаётся пустой.
73
+ * - options.onError (INT-04, D-110-06) — вызывается при терминальном resolve
74
+ * либо броске внутри поддерева.
50
75
  */
51
76
  export declare interface AreaProps {
52
77
  areaCode: string;
@@ -56,6 +81,7 @@ export declare interface AreaProps {
56
81
  ssr?: boolean;
57
82
  props?: Record<string, unknown> | ((serverProps: Record<string, unknown>) => Record<string, unknown>);
58
83
  fallback?: ReactNode;
84
+ empty?: AreaEmpty;
59
85
  onError?: (error: Error) => void;
60
86
  };
61
87
  }
@@ -206,6 +232,8 @@ export declare type ConsumerPropsFromSchema<S extends Record<string, SchemaField
206
232
  */
207
233
  export declare function createBrowserClient(opts: BrowserClientOptions): ReturnType<typeof createFragmentsClient>;
208
234
 
235
+ export { createSourceCache }
236
+
209
237
  /**
210
238
  * Дефолтное значение, когда Provider не установлен (потребитель вне
211
239
  * `FragmentRenderer`, например изолированный юнит-тест компонента).
@@ -315,6 +343,9 @@ export declare interface FragmentRendererProps {
315
343
  * правки (дырка рисует пустоту, как и без пропа).
316
344
  */
317
345
  slots?: Record<string, ResolvedSlotPosition>;
346
+ sources?: Record<string, AreaSourceTransport>;
347
+ /** Превью в песочнице не может и не должно ходить к источнику (D-111-22) — `offline` ставит SourceNetworkContext на всё поддерево. */
348
+ sourceNetwork?: SourceNetworkMode;
318
349
  onError?: (error: Error) => void;
319
350
  }
320
351
 
@@ -490,6 +521,22 @@ declare type ObjectFieldType<F extends SchemaFieldDescriptor, D extends number>
490
521
  fields: infer Fields;
491
522
  } ? Fields extends Record<string, SchemaFieldDescriptor> ? keyof Fields extends never ? {} : D extends 0 ? ValueOfVariableType<"Object"> : PropsShape<Fields, false, PrevDepth<D>> : {} : {};
492
523
 
524
+ declare type Operation<S extends keyof SourceMap & string, O extends keyof SourceMap[S] & string> = SourceMap[S][O] extends {
525
+ params: infer P;
526
+ response: infer R;
527
+ } ? {
528
+ params: P;
529
+ response: R;
530
+ } : never;
531
+
532
+ declare type Options<S extends keyof SourceMap & string, O extends keyof SourceMap[S] & string> = Operation<S, O>["params"] extends infer P ? ({} extends P ? {
533
+ target: O;
534
+ params?: P;
535
+ } : {
536
+ target: O;
537
+ params: P;
538
+ }) : never;
539
+
493
540
  declare type PrevDepth<D extends number> = D extends 0 ? never : DepthCountdown[D];
494
541
 
495
542
  /**
@@ -598,6 +645,25 @@ declare type Simplify<T> = {
598
645
  [K in keyof T]: T[K];
599
646
  } & {};
600
647
 
648
+ export { SourceCache }
649
+
650
+ export { SourceCacheEntry }
651
+
652
+ export { SourceCall }
653
+
654
+ export declare interface SourceMap {
655
+ }
656
+
657
+ export declare type SourceNetworkMode = "live" | "offline";
658
+
659
+ export { SourceOrigin }
660
+
661
+ export { SourcePendingEntry }
662
+
663
+ export { SourceReadyEntry }
664
+
665
+ export { SourceRun }
666
+
601
667
  /**
602
668
  * Ref-counted `<link rel="stylesheet">` injector для compiled fragment CSS delivery (Req #11).
603
669
  *
@@ -707,6 +773,7 @@ export declare interface UseAreaResult {
707
773
  * (`Area`/`FragmentRenderer`) не делает optional-проверку.
708
774
  */
709
775
  slots: Record<string, ResolvedSlotPosition>;
776
+ sources: Record<string, AreaSourceTransport>;
710
777
  }
711
778
 
712
779
  /**
@@ -772,6 +839,15 @@ export declare function useFragmentStylesheet(href: string, key: string): void;
772
839
 
773
840
  export declare function useProjectProperty<K extends keyof ProjectProperties>(name: K): ProjectProperties[K];
774
841
 
842
+ 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"]>;
843
+
844
+ export declare const useSource: UseSource;
845
+
846
+ export declare type UseSourceResult<T> = {
847
+ data: T | undefined;
848
+ loading: boolean;
849
+ };
850
+
775
851
  /** Носитель типа поля `Node` — читает `value`-проекцию третьей таблицы `NODE_TYPE_TO_TS` (D-97-03: три таблицы, три домена, слияние с `VARIABLE_TYPE_TO_TS` запрещено). */
776
852
  declare type ValueOfNodeType = (typeof NODE_TYPE_TO_TS)[typeof NODE_SCHEMA_TYPE]["value"];
777
853
 
package/dist/index.es.js CHANGED
@@ -1,45 +1,49 @@
1
- import { jsx as a, jsxs as _, Fragment as k } from "react/jsx-runtime";
2
- import { createContext as v, useContext as f, useMemo as A, useState as L, useEffect as S, useLayoutEffect as b, version as O, Component as B, Suspense as w, createElement as D } from "react";
3
- import { toScopeClassName as $, AREA_GLOBAL_CSS_KEY as U, resolveStylesHref as V, fragmentCssKey as G, createFragmentsClient as K } from "@fragmentsx/fragments-client";
4
- import { FragmentsApiVersionError as ve, FragmentsAreaError as Ee, FragmentsLoadError as ge } from "@fragmentsx/fragments-client";
5
- const E = v(
1
+ import { jsx as d, jsxs as te, Fragment as ne } from "react/jsx-runtime";
2
+ import * as ae from "react";
3
+ import { createContext as A, useContext as v, useMemo as N, useState as w, useEffect as y, useLayoutEffect as se, version as ue, Component as ce, Suspense as K, createElement as le, useCallback as _, useRef as H, useReducer as oe } from "react";
4
+ import { FragmentsAreaError as de, toScopeClassName as ie, AREA_GLOBAL_CSS_KEY as fe, resolveStylesHref as me, fragmentCssKey as he, createSourceCache as Ee, sourceCallKey as j, sourceTransportKey as ve, resolveSourceRequest as ge, runSourceFetch as ye, createFragmentsClient as Se } from "@fragmentsx/fragments-client";
5
+ import { FragmentsApiVersionError as Qe, FragmentsAreaError as We, FragmentsLoadError as Xe, createSourceCache as Ze } from "@fragmentsx/fragments-client";
6
+ const k = A(
6
7
  null
7
8
  );
8
- E.displayName = "FragmentsClientContext";
9
- function Y(r) {
10
- return /* @__PURE__ */ a(E.Provider, { value: r.value, children: r.children });
9
+ k.displayName = "FragmentsClientContext";
10
+ function Ae(r) {
11
+ return /* @__PURE__ */ d(k.Provider, { value: r.value, children: r.children });
11
12
  }
12
- const M = v(null);
13
- M.displayName = "InstanceIdContext";
14
- const g = v(
13
+ function ke() {
14
+ return v(k);
15
+ }
16
+ const z = A(null);
17
+ z.displayName = "InstanceIdContext";
18
+ const F = A(
15
19
  null
16
20
  );
17
- g.displayName = "ModulesMapContext";
18
- function H({
21
+ F.displayName = "ModulesMapContext";
22
+ function Ce({
19
23
  value: r,
20
24
  children: e
21
25
  }) {
22
- return /* @__PURE__ */ a(g.Provider, { value: r, children: e });
26
+ return /* @__PURE__ */ d(F.Provider, { value: r, children: e });
23
27
  }
24
- function ue() {
25
- const r = f(E);
26
- return A(
28
+ function Ue() {
29
+ const r = v(k);
30
+ return N(
27
31
  () => ({
28
32
  reachGoal: (e) => {
29
- var n, t;
30
- (t = (n = r == null ? void 0 : r.$metrics) == null ? void 0 : n.reachGoal) == null || t.call(n, e);
33
+ var t, n;
34
+ (n = (t = r == null ? void 0 : r.$metrics) == null ? void 0 : t.reachGoal) == null || n.call(t, e);
31
35
  }
32
36
  }),
33
37
  [r]
34
38
  );
35
39
  }
36
- function z(r) {
37
- const e = f(g);
40
+ function Pe(r) {
41
+ const e = v(F);
38
42
  if (!e)
39
43
  throw new Error("[useFragmentComponent] No ModulesMapProvider in tree");
40
44
  return e.read(r);
41
45
  }
42
- const J = typeof window < "u", x = Object.freeze({
46
+ const $ = typeof window < "u", L = Object.freeze({
43
47
  rootFragmentId: 0,
44
48
  variantId: null,
45
49
  props: {},
@@ -49,82 +53,103 @@ const J = typeof window < "u", x = Object.freeze({
49
53
  // обёртка рендера (задача 3) остаётся без атрибута class на этом сентинеле.
50
54
  fragments: [],
51
55
  // Phase 106: пустой словарь слотов — сентинел не разворачивает ни одной ссылки.
52
- slots: {}
56
+ slots: {},
57
+ sources: {}
53
58
  });
54
- function q(r, e) {
55
- const n = f(E);
56
- if (!n)
57
- throw new Error("[useArea] No FragmentsClientProvider in tree");
58
- const t = n.$area;
59
- if (!(t != null && t.read))
59
+ function R(r) {
60
+ const e = r.$area;
61
+ if (!(e != null && e.read))
60
62
  throw new Error("[useArea] $area plugin not mounted");
61
- const l = (e == null ? void 0 : e.suspense) ?? !0, u = (e == null ? void 0 : e.pause) === !0 || !J && (e == null ? void 0 : e.ssr) === !1, c = (e == null ? void 0 : e.timeout) != null ? { timeout: e.timeout } : void 0, [, m] = L(0);
62
- if (S(() => {
63
- if (l || u) return;
64
- let s = !0;
65
- return Promise.resolve(t.resolve(r, c)).catch(() => {
63
+ return e;
64
+ }
65
+ function Ne(r, e) {
66
+ const t = v(k);
67
+ if (!t)
68
+ 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 || !$ && (e == null ? void 0 : e.ssr) === !1, a = (e == null ? void 0 : e.timeout) != null ? { timeout: e.timeout } : void 0, [, i] = w(0);
70
+ if (y(() => {
71
+ if (n || s) return;
72
+ const l = R(t);
73
+ let u = !0;
74
+ return Promise.resolve(l.resolve(r, a)).catch(() => {
66
75
  }).finally(() => {
67
- s && m((o) => o + 1);
76
+ u && i((E) => E + 1);
68
77
  }), () => {
69
- s = !1;
78
+ u = !1;
70
79
  };
71
- }, [r, l, e == null ? void 0 : e.pause, e == null ? void 0 : e.timeout, e == null ? void 0 : e.ssr]), l)
72
- return u ? x : (t.has(r) || Promise.resolve(t.resolve(r, c)).catch(() => {
73
- }), t.read(r));
74
- if (u)
80
+ }, [r, n, e == null ? void 0 : e.pause, e == null ? void 0 : e.timeout, e == null ? void 0 : e.ssr]), n) {
81
+ if (s)
82
+ return L;
83
+ const l = R(t);
84
+ if (l.has(r) || Promise.resolve(l.resolve(r, a)).catch(() => {
85
+ }), !$)
86
+ try {
87
+ return l.read(r);
88
+ } catch (u) {
89
+ if (u != null && typeof u.then == "function")
90
+ throw u;
91
+ return process.env.NODE_ENV !== "production" && console.error(
92
+ `[useArea] Area ${r} remained unresolved on the server because its cache reached a terminal state`,
93
+ u
94
+ ), L;
95
+ }
96
+ return l.read(r);
97
+ }
98
+ if (s)
75
99
  return { status: "idle", data: null, error: null };
76
- if (t.has(r))
100
+ const c = R(t);
101
+ if (c.has(r))
77
102
  try {
78
- return { status: "ready", data: t.read(r), error: null };
79
- } catch (s) {
103
+ return { status: "ready", data: c.read(r), error: null };
104
+ } catch (l) {
80
105
  return {
81
106
  status: "not-found",
82
107
  data: null,
83
- error: s instanceof Error ? s : new Error(String(s))
108
+ error: l instanceof Error ? l : new Error(String(l))
84
109
  };
85
110
  }
86
- return Promise.resolve(t.resolve(r, c)).catch(() => {
111
+ return Promise.resolve(c.resolve(r, a)).catch(() => {
87
112
  }), { status: "loading", data: null, error: null };
88
113
  }
89
- const I = typeof window < "u", Q = 3e3, h = /* @__PURE__ */ new Map(), p = (r, e) => {
90
- if (!I) {
91
- const d = () => {
114
+ const G = typeof window < "u", we = 3e3, P = /* @__PURE__ */ new Map(), Y = (r, e) => {
115
+ if (!G) {
116
+ const h = () => {
92
117
  };
93
- return d.loaded = Promise.resolve(), d;
118
+ return h.loaded = Promise.resolve(), h;
94
119
  }
95
- const n = h.get(e);
96
- if (n) {
97
- n.refCount += 1;
98
- const d = () => {
99
- n.refCount -= 1, n.refCount === 0 && (n.clearReadyTimer(), n.linkEl.remove(), h.delete(e));
120
+ const t = P.get(e);
121
+ if (t) {
122
+ t.refCount += 1;
123
+ const h = () => {
124
+ t.refCount -= 1, t.refCount === 0 && (t.clearReadyTimer(), t.linkEl.remove(), P.delete(e));
100
125
  };
101
- return d.loaded = n.loaded, d;
126
+ return h.loaded = t.loaded, h;
102
127
  }
103
- const t = document.createElement("link");
104
- t.rel = "stylesheet", t.href = r, t.setAttribute("data-fragment-key", e);
105
- let l;
106
- const u = new Promise((d) => {
107
- l = d;
108
- }), c = () => {
109
- s(), l();
110
- }, m = setTimeout(c, Q), s = () => clearTimeout(m);
111
- t.addEventListener("load", c), t.addEventListener("error", c), document.head.appendChild(t);
112
- const o = { refCount: 1, linkEl: t, loaded: u, clearReadyTimer: s };
113
- h.set(e, o);
114
- const i = () => {
115
- o.refCount -= 1, o.refCount === 0 && (o.clearReadyTimer(), o.linkEl.remove(), h.delete(e));
128
+ const n = document.createElement("link");
129
+ n.rel = "stylesheet", n.href = r, n.setAttribute("data-fragment-key", e);
130
+ let s;
131
+ const a = new Promise((h) => {
132
+ s = h;
133
+ }), i = () => {
134
+ l(), s();
135
+ }, c = setTimeout(i, we), l = () => clearTimeout(c);
136
+ n.addEventListener("load", i), n.addEventListener("error", i), document.head.appendChild(n);
137
+ const u = { refCount: 1, linkEl: n, loaded: a, clearReadyTimer: l };
138
+ P.set(e, u);
139
+ const E = () => {
140
+ u.refCount -= 1, u.refCount === 0 && (u.clearReadyTimer(), u.linkEl.remove(), P.delete(e));
116
141
  };
117
- return i.loaded = u, i;
118
- }, W = I ? b : S;
119
- function X(r, e) {
120
- W(() => p(r, e), [r, e]);
142
+ return E.loaded = a, E;
143
+ }, Fe = G ? se : y;
144
+ function Te(r, e) {
145
+ Fe(() => Y(r, e), [r, e]);
121
146
  }
122
- const Z = parseInt(O.split(".")[0], 10), ee = Z >= 19;
123
- function P({
147
+ const Re = parseInt(ue.split(".")[0], 10), _e = Re >= 19;
148
+ function D({
124
149
  href: r,
125
150
  fragmentKey: e
126
151
  }) {
127
- return ee ? /* @__PURE__ */ a(
152
+ return _e ? /* @__PURE__ */ d(
128
153
  "link",
129
154
  {
130
155
  rel: "stylesheet",
@@ -132,148 +157,237 @@ function P({
132
157
  precedence: "default",
133
158
  "data-fragment-key": e
134
159
  }
135
- ) : (X(r, e), null);
160
+ ) : (Te(r, e), null);
161
+ }
162
+ function pe(r) {
163
+ }
164
+ const J = {}, x = A(null);
165
+ x.displayName = "ProjectPropertiesContext";
166
+ const q = Object.freeze({}), O = A(q);
167
+ O.displayName = "SourceTransportsContext";
168
+ const b = A("live");
169
+ b.displayName = "SourceNetworkContext";
170
+ function V(r) {
171
+ const e = r instanceof Error ? r : new Error(String(r));
172
+ if (!(e instanceof de))
173
+ return { kind: "failed", error: e };
174
+ const { code: t } = e;
175
+ 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 };
136
176
  }
137
- function se(r) {
177
+ function Q(r, e, t) {
178
+ return typeof r == "function" ? r(e, t) : r ?? null;
138
179
  }
139
- const R = {}, y = v(null);
140
- y.displayName = "ProjectPropertiesContext";
141
- class T extends B {
180
+ const xe = () => {
181
+ };
182
+ function U(r) {
183
+ return r instanceof Error ? r : new Error(String(r));
184
+ }
185
+ class W extends ce {
142
186
  constructor() {
143
- super(...arguments), this.state = { hasError: !1 };
187
+ super(...arguments), this.state = { hasError: !1, error: null };
144
188
  }
145
- static getDerivedStateFromError() {
146
- return { hasError: !0 };
189
+ static getDerivedStateFromError(e) {
190
+ return { hasError: !0, error: U(e) };
147
191
  }
148
- componentDidCatch(e, n) {
149
- var t, l;
150
- process.env.NODE_ENV !== "production" && console.error("[fragments] Area error:", e, n.componentStack), (l = (t = this.props).onError) == null || l.call(t, e);
192
+ componentDidCatch(e, t) {
193
+ var s, a;
194
+ const n = U(e);
195
+ process.env.NODE_ENV !== "production" && console.error("[fragments] Area error:", n, t.componentStack), (a = (s = this.props).onError) == null || a.call(s, n);
151
196
  }
152
197
  render() {
153
- return this.state.hasError ? null : this.props.children;
198
+ if (this.state.hasError) {
199
+ const e = { kind: "failed", error: this.state.error ?? new Error("Unknown Area error") };
200
+ try {
201
+ return Q(this.props.empty, e, this.props.retry ?? xe);
202
+ } catch {
203
+ return null;
204
+ }
205
+ }
206
+ return this.props.children;
154
207
  }
155
208
  }
156
- function j(r, e) {
209
+ function X(r, e) {
157
210
  if (!r) return {};
158
- const n = {};
159
- for (const t of Object.keys(r))
160
- n[t] = re(r[t], e);
161
- return n;
211
+ const t = {};
212
+ for (const n of Object.keys(r))
213
+ t[n] = Oe(r[n], e);
214
+ return t;
162
215
  }
163
- function re(r, e) {
164
- return Array.isArray(r) ? r.map((n, t) => n === null ? null : F(n, e, t)) : F(r, e);
216
+ function Oe(r, e) {
217
+ return Array.isArray(r) ? r.map((t, n) => t === null ? null : p(t, e, n)) : p(r, e);
165
218
  }
166
- function F(r, e, n) {
167
- let t;
219
+ function p(r, e, t) {
220
+ let n;
168
221
  try {
169
- t = e(r.fragmentId);
170
- } catch (u) {
171
- if (u != null && typeof u.then == "function")
172
- throw u;
173
- return console.warn(`[FragmentRenderer] Slot fragment ${r.fragmentId} failed to load — rendering empty hole`, u), null;
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;
174
227
  }
175
- const l = j(r.slots, e);
176
- return D(t, { key: n, ...r.props, ...l });
228
+ const s = X(r.slots, e);
229
+ return le(n, { key: t, ...r.props, ...s });
177
230
  }
178
- const N = ({
231
+ const Z = ({
179
232
  fragmentId: r,
180
233
  props: e,
181
- globalCssUrl: n = null,
182
- projectProperties: t = R,
183
- fragments: l = [r],
184
- slots: u
234
+ globalCssUrl: t = null,
235
+ projectProperties: n = J,
236
+ fragments: s = [r],
237
+ slots: a,
238
+ sources: i = q,
239
+ sourceNetwork: c = "live"
185
240
  }) => {
186
- const c = z(r), m = f(g);
187
- if (!m)
241
+ const l = Pe(r), u = v(F);
242
+ if (!u)
188
243
  throw new Error("[FragmentRendererInner] No ModulesMapProvider in tree");
189
- const s = j(u, m.read), o = { ...e ?? {}, ...s }, i = l.length > 0 ? l.map($).join(" ") : void 0;
190
- return /* @__PURE__ */ _(k, { children: [
191
- n != null && /* @__PURE__ */ a(
192
- P,
244
+ const E = X(a, u.read), h = { ...e ?? {}, ...E }, o = s.length > 0 ? s.map(ie).join(" ") : void 0;
245
+ return /* @__PURE__ */ te(ne, { children: [
246
+ t != null && /* @__PURE__ */ d(
247
+ D,
193
248
  {
194
- href: n,
195
- fragmentKey: U
249
+ href: t,
250
+ fragmentKey: fe
196
251
  }
197
252
  ),
198
- l.map((d) => {
199
- const C = V(d);
200
- return C ? /* @__PURE__ */ a(
201
- P,
253
+ s.map((m) => {
254
+ const g = me(m);
255
+ return g ? /* @__PURE__ */ d(
256
+ D,
202
257
  {
203
- href: C,
204
- fragmentKey: G(d)
258
+ href: g,
259
+ fragmentKey: he(m)
205
260
  },
206
- d
261
+ m
207
262
  ) : null;
208
263
  }),
209
- /* @__PURE__ */ a(y.Provider, { value: t, children: /* @__PURE__ */ a(M.Provider, { value: null, children: /* @__PURE__ */ a(
264
+ /* @__PURE__ */ d(b.Provider, { value: c, children: /* @__PURE__ */ d(O.Provider, { value: i, children: /* @__PURE__ */ d(x.Provider, { value: n, children: /* @__PURE__ */ d(z.Provider, { value: null, children: /* @__PURE__ */ d(
210
265
  "div",
211
266
  {
212
- className: i,
267
+ className: o,
213
268
  style: { display: "contents" },
214
- children: /* @__PURE__ */ a(c, { ...o })
269
+ children: /* @__PURE__ */ d(l, { ...h })
215
270
  }
216
- ) }) })
271
+ ) }) }) }) })
217
272
  ] });
218
- }, ce = ({ onError: r, ...e }) => /* @__PURE__ */ a(w, { fallback: null, children: /* @__PURE__ */ a(T, { onError: r, children: /* @__PURE__ */ a(N, { ...e }) }) }), te = ({ areaCode: r, options: e }) => {
219
- if ((e == null ? void 0 : e.pause) === !0)
273
+ }, Be = ({ onError: r, ...e }) => /* @__PURE__ */ d(K, { fallback: null, children: /* @__PURE__ */ d(W, { onError: r, children: /* @__PURE__ */ d(Z, { ...e }) }) }), be = ({ areaCode: r, options: e, retry: t }) => {
274
+ const n = Ne(r, {
275
+ suspense: !1,
276
+ ssr: !1,
277
+ pause: e == null ? void 0 : e.pause,
278
+ timeout: e == null ? void 0 : e.timeout
279
+ }), s = H(null);
280
+ if (y(() => {
281
+ var S;
282
+ if (n.status !== "not-found" || !n.error) return;
283
+ const m = V(n.error), g = JSON.stringify([r, m.kind, m.code, m.error.message]);
284
+ s.current !== g && (s.current = g, (S = e == null ? void 0 : e.onError) == null || S.call(e, m.error), process.env.NODE_ENV !== "production" && m.kind !== "no-variant" && console.error(
285
+ `[fragments] Area resolution ${m.kind}: areaCode=${r}, code=${m.code ?? "none"}`,
286
+ m.error
287
+ ));
288
+ }, [r, e == null ? void 0 : e.onError, n.error, n.status]), (e == null ? void 0 : e.pause) === !0)
220
289
  return null;
221
- const n = q(r, {
222
- timeout: e == null ? void 0 : e.timeout,
223
- ssr: e == null ? void 0 : e.ssr
224
- });
225
- if (n === x)
226
- return null;
227
- const { rootFragmentId: t, props: l, projectProperties: u, globalCssUrl: c, fragments: m, slots: s } = n, o = typeof (e == null ? void 0 : e.props) == "function" ? e.props(l) : e != null && e.props ? { ...l, ...e.props } : l;
228
- return /* @__PURE__ */ a(
229
- N,
290
+ if (n.status === "idle")
291
+ return (e == null ? void 0 : e.fallback) ?? null;
292
+ if (n.status === "not-found")
293
+ return Q(e == null ? void 0 : e.empty, V(n.error), t);
294
+ if (n.status === "loading" || !n.data)
295
+ return (e == null ? void 0 : e.fallback) ?? null;
296
+ const { rootFragmentId: a, props: i, projectProperties: c, globalCssUrl: l, fragments: u, slots: E, sources: h } = n.data, o = typeof (e == null ? void 0 : e.props) == "function" ? e.props(i) : e != null && e.props ? { ...i, ...e.props } : i;
297
+ return /* @__PURE__ */ d(K, { fallback: (e == null ? void 0 : e.fallback) ?? null, children: /* @__PURE__ */ d(
298
+ Z,
230
299
  {
231
- fragmentId: t,
300
+ fragmentId: a,
232
301
  props: o,
233
- globalCssUrl: c,
234
- projectProperties: u,
235
- fragments: m,
236
- slots: s
302
+ globalCssUrl: l,
303
+ projectProperties: c,
304
+ fragments: u,
305
+ slots: E,
306
+ sources: h
237
307
  }
308
+ ) });
309
+ }, Ke = ({ areaCode: r, options: e }) => {
310
+ const t = v(k), [n, s] = w(0), a = t == null ? void 0 : t.$area;
311
+ y(() => {
312
+ (e == null ? void 0 : e.ssr) !== !0 || process.env.NODE_ENV === "production" || console.error(
313
+ "[fragments] Area option `ssr` is reserved: server resolution has been removed from the runtime; existing `ssr: false` calls continue to work unchanged."
314
+ );
315
+ }, [e == null ? void 0 : e.ssr]);
316
+ const i = _(() => {
317
+ a != null && a.resolve && (a.resolve(r).catch(() => {
318
+ }), s((c) => c + 1));
319
+ }, [a, r]);
320
+ return (
321
+ // A retry remounts the boundary and AreaInner: a repeated failure is a new
322
+ // telemetry event, so AreaInner intentionally calls options.onError again.
323
+ /* @__PURE__ */ d(W, { onError: e == null ? void 0 : e.onError, empty: e == null ? void 0 : e.empty, retry: i, children: /* @__PURE__ */ d(be, { areaCode: r, options: e, retry: i }) }, n)
238
324
  );
239
- }, oe = ({ areaCode: r, options: e }) => /* @__PURE__ */ a(w, { fallback: (e == null ? void 0 : e.fallback) ?? null, children: /* @__PURE__ */ a(T, { onError: e == null ? void 0 : e.onError, children: /* @__PURE__ */ a(te, { areaCode: r, options: e }) }) });
240
- function de({ client: r, children: e }) {
241
- const n = A(
325
+ };
326
+ function He({ client: r, children: e }) {
327
+ const t = N(
242
328
  () => ({
243
- read: (t) => r.$fragments.read(t)
329
+ read: (n) => r.$fragments.read(n)
244
330
  }),
245
331
  [r]
246
332
  );
247
- return /* @__PURE__ */ a(Y, { value: r, children: /* @__PURE__ */ a(H, { value: n, children: e }) });
333
+ return /* @__PURE__ */ d(Ae, { value: r, children: /* @__PURE__ */ d(Ce, { value: t, children: e }) });
334
+ }
335
+ function ze(r) {
336
+ return (v(x) ?? J)[r];
337
+ }
338
+ function Ie(r, e) {
339
+ const [, t] = oe((a) => a + 1, 0), n = e(), s = H(n);
340
+ return s.current = n, y(() => {
341
+ const a = r(t);
342
+ return Object.is(s.current, e()) || t(), a;
343
+ }, [r, e]), n;
248
344
  }
249
- function me(r) {
250
- return (f(y) ?? R)[r];
345
+ const B = ae.useSyncExternalStore, Me = B || ((r, e) => Ie(r, e)), ee = "offline", je = () => Promise.reject(new Error(ee));
346
+ function $e(r, e) {
347
+ var M;
348
+ const t = ke(), [n] = w(Ee), s = (t == null ? void 0 : t.sourceCache) ?? n, a = (M = t == null ? void 0 : t.sourceFetchers) == null ? void 0 : M[r], i = a ? "host-fetch" : "network", c = t == null ? void 0 : t.env, l = j({ source: r, target: e.target, params: e.params }), u = N(() => ({ source: r, target: e.target, params: e.params }), [l]), E = _((T) => s.subscribe(u, T), [s, u]), h = _(() => s.get(u), [s, u]), o = Me(E, h, h), m = v(b), g = v(O), S = ve(r, e.target), f = N(
349
+ () => m === ee ? null : ge(g[S], u.params),
350
+ [m, g, S, u]
351
+ ), [C, I] = w(null);
352
+ return y(() => {
353
+ (o == null ? void 0 : o.status) === "ready" && C !== null && I(null);
354
+ }, [o, C]), y(() => {
355
+ f && !f.ok && o === void 0 && console.warn(`[useSource] ${S}: ${f.reason}`);
356
+ }, [S, f == null ? void 0 : f.ok, f && !f.ok ? f.reason : void 0, o === void 0]), y(() => {
357
+ if (f && !f.ok || (o == null ? void 0 : o.status) === "ready" || C === l) return;
358
+ I(l);
359
+ const T = f && f.ok ? () => ye({ url: f.url, init: f.init }, { fetcher: a, timeout: c == null ? void 0 : c.timeout }).then((re) => (c != null && c.debug && console.info(`[useSource] loaded ${j(u)} origin=${i}`), re)) : je;
360
+ s.load(u, T, i);
361
+ }, [s, u, l, o, C, f, a, i, c == null ? void 0 : c.timeout, c == null ? void 0 : c.debug]), (o == null ? void 0 : o.status) === "ready" ? { data: o.data ?? void 0, loading: !1 } : (o == null ? void 0 : o.status) === "pending" ? { data: void 0, loading: !0 } : f && !f.ok ? { data: void 0, loading: !1 } : { data: void 0, loading: C !== l };
251
362
  }
252
- function fe(r) {
253
- return K({ ...r, inject: p });
363
+ const Ge = $e;
364
+ function Ye(r) {
365
+ return Se({ ...r, inject: Y });
254
366
  }
255
367
  export {
256
- x as AREA_UNRESOLVED,
257
- oe as Area,
258
- ce as FragmentRenderer,
259
- P as FragmentStylesheet,
260
- ve as FragmentsApiVersionError,
261
- Ee as FragmentsAreaError,
262
- E as FragmentsClientContext,
263
- Y as FragmentsClientProvider,
264
- ge as FragmentsLoadError,
265
- de as FragmentsProvider,
266
- M as InstanceIdContext,
267
- g as ModulesMapContext,
268
- H as ModulesMapProvider,
269
- y as ProjectPropertiesContext,
270
- fe as createBrowserClient,
271
- R as defaultProjectProperties,
272
- p as injectStylesheet,
273
- q as useArea,
274
- se as useCssChunk,
275
- z as useFragmentComponent,
276
- ue as useFragmentMetrics,
277
- X as useFragmentStylesheet,
278
- me as useProjectProperty
368
+ L as AREA_UNRESOLVED,
369
+ Ke as Area,
370
+ Be as FragmentRenderer,
371
+ D as FragmentStylesheet,
372
+ Qe as FragmentsApiVersionError,
373
+ We as FragmentsAreaError,
374
+ k as FragmentsClientContext,
375
+ Ae as FragmentsClientProvider,
376
+ Xe as FragmentsLoadError,
377
+ He as FragmentsProvider,
378
+ z as InstanceIdContext,
379
+ F as ModulesMapContext,
380
+ Ce as ModulesMapProvider,
381
+ x as ProjectPropertiesContext,
382
+ Ye as createBrowserClient,
383
+ Ze as createSourceCache,
384
+ J as defaultProjectProperties,
385
+ Y as injectStylesheet,
386
+ Ne as useArea,
387
+ pe as useCssChunk,
388
+ Pe as useFragmentComponent,
389
+ Ue as useFragmentMetrics,
390
+ Te as useFragmentStylesheet,
391
+ ze as useProjectProperty,
392
+ Ge as useSource
279
393
  };
package/dist/index.umd.js CHANGED
@@ -1 +1 @@
1
- (function(l,u){typeof exports=="object"&&typeof module<"u"?u(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"],u):(l=typeof globalThis<"u"?globalThis:l||self,u(l.FragmentsRuntimeReact={},l.jsxRuntime,l.React,l.fragmentsClient))})(this,function(l,u,a,m){"use strict";const g=a.createContext(null);g.displayName="FragmentsClientContext";function j(r){return u.jsx(g.Provider,{value:r.value,children:r.children})}const P=a.createContext(null);P.displayName="InstanceIdContext";const E=a.createContext(null);E.displayName="ModulesMapContext";function w({value:r,children:e}){return u.jsx(E.Provider,{value:r,children:e})}function p(){const r=a.useContext(g);return a.useMemo(()=>({reachGoal:e=>{var n,t;(t=(n=r==null?void 0:r.$metrics)==null?void 0:n.reachGoal)==null||t.call(n,e)}}),[r])}function I(r){const e=a.useContext(E);if(!e)throw new Error("[useFragmentComponent] No ModulesMapProvider in tree");return e.read(r)}const B=typeof window<"u",F=Object.freeze({rootFragmentId:0,variantId:null,props:{},projectProperties:{},globalCssUrl:null,fragments:[],slots:{}});function T(r,e){const n=a.useContext(g);if(!n)throw new Error("[useArea] No FragmentsClientProvider in tree");const t=n.$area;if(!(t!=null&&t.read))throw new Error("[useArea] $area plugin not mounted");const s=(e==null?void 0:e.suspense)??!0,c=(e==null?void 0:e.pause)===!0||!B&&(e==null?void 0:e.ssr)===!1,d=(e==null?void 0:e.timeout)!=null?{timeout:e.timeout}:void 0,[,h]=a.useState(0);if(a.useEffect(()=>{if(s||c)return;let o=!0;return Promise.resolve(t.resolve(r,d)).catch(()=>{}).finally(()=>{o&&h(f=>f+1)}),()=>{o=!1}},[r,s,e==null?void 0:e.pause,e==null?void 0:e.timeout,e==null?void 0:e.ssr]),s)return c?F:(t.has(r)||Promise.resolve(t.resolve(r,d)).catch(()=>{}),t.read(r));if(c)return{status:"idle",data:null,error:null};if(t.has(r))try{return{status:"ready",data:t.read(r),error:null}}catch(o){return{status:"not-found",data:null,error:o instanceof Error?o:new Error(String(o))}}return Promise.resolve(t.resolve(r,d)).catch(()=>{}),{status:"loading",data:null,error:null}}const _=typeof window<"u",D=3e3,v=new Map,A=(r,e)=>{if(!_){const i=()=>{};return i.loaded=Promise.resolve(),i}const n=v.get(e);if(n){n.refCount+=1;const i=()=>{n.refCount-=1,n.refCount===0&&(n.clearReadyTimer(),n.linkEl.remove(),v.delete(e))};return i.loaded=n.loaded,i}const t=document.createElement("link");t.rel="stylesheet",t.href=r,t.setAttribute("data-fragment-key",e);let s;const c=new Promise(i=>{s=i}),d=()=>{o(),s()},h=setTimeout(d,D),o=()=>clearTimeout(h);t.addEventListener("load",d),t.addEventListener("error",d),document.head.appendChild(t);const f={refCount:1,linkEl:t,loaded:c,clearReadyTimer:o};v.set(e,f);const C=()=>{f.refCount-=1,f.refCount===0&&(f.clearReadyTimer(),f.linkEl.remove(),v.delete(e))};return C.loaded=c,C},V=_?a.useLayoutEffect:a.useEffect;function b(r,e){V(()=>A(r,e),[r,e])}const R=parseInt(a.version.split(".")[0],10)>=19;function S({href:r,fragmentKey:e}){return R?u.jsx("link",{rel:"stylesheet",href:r,precedence:"default","data-fragment-key":e}):(b(r,e),null)}function U(r){}const M={},y=a.createContext(null);y.displayName="ProjectPropertiesContext";class N extends a.Component{constructor(){super(...arguments),this.state={hasError:!1}}static getDerivedStateFromError(){return{hasError:!0}}componentDidCatch(e,n){var t,s;process.env.NODE_ENV!=="production"&&console.error("[fragments] Area error:",e,n.componentStack),(s=(t=this.props).onError)==null||s.call(t,e)}render(){return this.state.hasError?null:this.props.children}}function O(r,e){if(!r)return{};const n={};for(const t of Object.keys(r))n[t]=$(r[t],e);return n}function $(r,e){return Array.isArray(r)?r.map((n,t)=>n===null?null:L(n,e,t)):L(r,e)}function L(r,e,n){let t;try{t=e(r.fragmentId)}catch(c){if(c!=null&&typeof c.then=="function")throw c;return console.warn(`[FragmentRenderer] Slot fragment ${r.fragmentId} failed to load — rendering empty hole`,c),null}const s=O(r.slots,e);return a.createElement(t,{key:n,...r.props,...s})}const k=({fragmentId:r,props:e,globalCssUrl:n=null,projectProperties:t=M,fragments:s=[r],slots:c})=>{const d=I(r),h=a.useContext(E);if(!h)throw new Error("[FragmentRendererInner] No ModulesMapProvider in tree");const o=O(c,h.read),f={...e??{},...o},C=s.length>0?s.map(m.toScopeClassName).join(" "):void 0;return u.jsxs(u.Fragment,{children:[n!=null&&u.jsx(S,{href:n,fragmentKey:m.AREA_GLOBAL_CSS_KEY}),s.map(i=>{const x=m.resolveStylesHref(i);return x?u.jsx(S,{href:x,fragmentKey:m.fragmentCssKey(i)},i):null}),u.jsx(y.Provider,{value:t,children:u.jsx(P.Provider,{value:null,children:u.jsx("div",{className:C,style:{display:"contents"},children:u.jsx(d,{...f})})})})]})},q=({onError:r,...e})=>u.jsx(a.Suspense,{fallback:null,children:u.jsx(N,{onError:r,children:u.jsx(k,{...e})})}),G=({areaCode:r,options:e})=>{if((e==null?void 0:e.pause)===!0)return null;const n=T(r,{timeout:e==null?void 0:e.timeout,ssr:e==null?void 0:e.ssr});if(n===F)return null;const{rootFragmentId:t,props:s,projectProperties:c,globalCssUrl:d,fragments:h,slots:o}=n,f=typeof(e==null?void 0:e.props)=="function"?e.props(s):e!=null&&e.props?{...s,...e.props}:s;return u.jsx(k,{fragmentId:t,props:f,globalCssUrl:d,projectProperties:c,fragments:h,slots:o})},K=({areaCode:r,options:e})=>u.jsx(a.Suspense,{fallback:(e==null?void 0:e.fallback)??null,children:u.jsx(N,{onError:e==null?void 0:e.onError,children:u.jsx(G,{areaCode:r,options:e})})});function Y({client:r,children:e}){const n=a.useMemo(()=>({read:t=>r.$fragments.read(t)}),[r]);return u.jsx(j,{value:r,children:u.jsx(w,{value:n,children:e})})}function H(r){return(a.useContext(y)??M)[r]}function J(r){return m.createFragmentsClient({...r,inject:A})}Object.defineProperty(l,"FragmentsApiVersionError",{enumerable:!0,get:()=>m.FragmentsApiVersionError}),Object.defineProperty(l,"FragmentsAreaError",{enumerable:!0,get:()=>m.FragmentsAreaError}),Object.defineProperty(l,"FragmentsLoadError",{enumerable:!0,get:()=>m.FragmentsLoadError}),l.AREA_UNRESOLVED=F,l.Area=K,l.FragmentRenderer=q,l.FragmentStylesheet=S,l.FragmentsClientContext=g,l.FragmentsClientProvider=j,l.FragmentsProvider=Y,l.InstanceIdContext=P,l.ModulesMapContext=E,l.ModulesMapProvider=w,l.ProjectPropertiesContext=y,l.createBrowserClient=J,l.defaultProjectProperties=M,l.injectStylesheet=A,l.useArea=T,l.useCssChunk=U,l.useFragmentComponent=I,l.useFragmentMetrics=p,l.useFragmentStylesheet=b,l.useProjectProperty=H,Object.defineProperty(l,Symbol.toStringTag,{value:"Module"})});
1
+ (function(s,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):(s=typeof globalThis<"u"?globalThis:s||self,l(s.FragmentsRuntimeReact={},s.jsxRuntime,s.React,s.fragmentsClient))})(this,function(s,l,u,h){"use strict";function ee(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 re=ee(u),P=u.createContext(null);P.displayName="FragmentsClientContext";function $(r){return l.jsx(P.Provider,{value:r.value,children:r.children})}function te(){return u.useContext(P)}const N=u.createContext(null);N.displayName="InstanceIdContext";const A=u.createContext(null);A.displayName="ModulesMapContext";function D({value:r,children:e}){return l.jsx(A.Provider,{value:r,children:e})}function ne(){const r=u.useContext(P);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 L(r){const e=u.useContext(A);if(!e)throw new Error("[useFragmentComponent] No ModulesMapProvider in tree");return e.read(r)}const V=typeof window<"u",O=Object.freeze({rootFragmentId:0,variantId:null,props:{},projectProperties:{},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=u.useContext(P);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,[,m]=u.useState(0);if(u.useEffect(()=>{if(n||c)return;const f=w(t);let o=!0;return Promise.resolve(f.resolve(r,a)).catch(()=>{}).finally(()=>{o&&m(y=>y+1)}),()=>{o=!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 O;const f=w(t);if(f.has(r)||Promise.resolve(f.resolve(r,a)).catch(()=>{}),!V)try{return f.read(r)}catch(o){if(o!=null&&typeof o.then=="function")throw o;return process.env.NODE_ENV!=="production"&&console.error(`[useArea] Area ${r} remained unresolved on the server because its cache reached a terminal state`,o),O}return f.read(r)}if(c)return{status:"idle",data:null,error:null};const d=w(t);if(d.has(r))try{return{status:"ready",data:d.read(r),error:null}}catch(f){return{status:"not-found",data:null,error:f instanceof Error?f:new Error(String(f))}}return Promise.resolve(d.resolve(r,a)).catch(()=>{}),{status:"loading",data:null,error:null}}const B=typeof window<"u",ue=3e3,k=new Map,T=(r,e)=>{if(!B){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}),m=()=>{f(),c()},d=setTimeout(m,ue),f=()=>clearTimeout(d);n.addEventListener("load",m),n.addEventListener("error",m),document.head.appendChild(n);const o={refCount:1,linkEl:n,loaded:a,clearReadyTimer:f};k.set(e,o);const y=()=>{o.refCount-=1,o.refCount===0&&(o.clearReadyTimer(),o.linkEl.remove(),k.delete(e))};return y.loaded=a,y},se=B?u.useLayoutEffect:u.useEffect;function K(r,e){se(()=>T(r,e),[r,e])}const ae=parseInt(u.version.split(".")[0],10)>=19;function M({href:r,fragmentKey:e}){return ae?l.jsx("link",{rel:"stylesheet",href:r,precedence:"default","data-fragment-key":e}):(K(r,e),null)}function ce(r){}const _={},b=u.createContext(null);b.displayName="ProjectPropertiesContext";const z=Object.freeze({}),j=u.createContext(z);j.displayName="SourceTransportsContext";const I=u.createContext("live");I.displayName="SourceNetworkContext";function H(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 G(r,e,t){return typeof r=="function"?r(e,t):r??null}const oe=()=>{};function Y(r){return r instanceof Error?r:new Error(String(r))}class q extends u.Component{constructor(){super(...arguments),this.state={hasError:!1,error:null}}static getDerivedStateFromError(e){return{hasError:!0,error:Y(e)}}componentDidCatch(e,t){var c,a;const n=Y(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 G(this.props.empty,e,this.props.retry??oe)}catch{return null}}return this.props.children}}function J(r,e){if(!r)return{};const t={};for(const n of Object.keys(r))t[n]=le(r[n],e);return t}function le(r,e){return Array.isArray(r)?r.map((t,n)=>t===null?null:p(t,e,n)):p(r,e)}function p(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=J(r.slots,e);return u.createElement(n,{key:t,...r.props,...c})}const Q=({fragmentId:r,props:e,globalCssUrl:t=null,projectProperties:n=_,fragments:c=[r],slots:a,sources:m=z,sourceNetwork:d="live"})=>{const f=L(r),o=u.useContext(A);if(!o)throw new Error("[FragmentRendererInner] No ModulesMapProvider in tree");const y=J(a,o.read),v={...e??{},...y},i=c.length>0?c.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}),c.map(g=>{const S=h.resolveStylesHref(g);return S?l.jsx(M,{href:S,fragmentKey:h.fragmentCssKey(g)},g):null}),l.jsx(I.Provider,{value:d,children:l.jsx(j.Provider,{value:m,children:l.jsx(b.Provider,{value:n,children:l.jsx(N.Provider,{value:null,children:l.jsx("div",{className:i,style:{display:"contents"},children:l.jsx(f,{...v})})})})})})]})},de=({onError:r,...e})=>l.jsx(u.Suspense,{fallback:null,children:l.jsx(q,{onError:r,children:l.jsx(Q,{...e})})}),fe=({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}),c=u.useRef(null);if(u.useEffect(()=>{var C;if(n.status!=="not-found"||!n.error)return;const g=H(n.error),S=JSON.stringify([r,g.kind,g.code,g.error.message]);c.current!==S&&(c.current=S,(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 G(e==null?void 0:e.empty,H(n.error),t);if(n.status==="loading"||!n.data)return(e==null?void 0:e.fallback)??null;const{rootFragmentId:a,props:m,projectProperties:d,globalCssUrl:f,fragments:o,slots:y,sources:v}=n.data,i=typeof(e==null?void 0:e.props)=="function"?e.props(m):e!=null&&e.props?{...m,...e.props}:m;return l.jsx(u.Suspense,{fallback:(e==null?void 0:e.fallback)??null,children:l.jsx(Q,{fragmentId:a,props:i,globalCssUrl:f,projectProperties:d,fragments:o,slots:y,sources:v})})},ie=({areaCode:r,options:e})=>{const t=u.useContext(P),[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 m=u.useCallback(()=>{a!=null&&a.resolve&&(a.resolve(r).catch(()=>{}),c(d=>d+1))},[a,r]);return l.jsx(q,{onError:e==null?void 0:e.onError,empty:e==null?void 0:e.empty,retry:m,children:l.jsx(fe,{areaCode:r,options:e,retry:m})},n)};function me({client:r,children:e}){const t=u.useMemo(()=>({read:n=>r.$fragments.read(n)}),[r]);return l.jsx($,{value:r,children:l.jsx(D,{value:t,children:e})})}function Ee(r){return(u.useContext(b)??_)[r]}function he(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 W=re.useSyncExternalStore,ge=W||((r,e)=>he(r,e)),X="offline",ve=()=>Promise.reject(new Error(X));function ye(r,e){var R;const t=te(),[n]=u.useState(h.createSourceCache),c=(t==null?void 0:t.sourceCache)??n,a=(R=t==null?void 0:t.sourceFetchers)==null?void 0:R[r],m=a?"host-fetch":"network",d=t==null?void 0:t.env,f=h.sourceCallKey({source:r,target:e.target,params:e.params}),o=u.useMemo(()=>({source:r,target:e.target,params:e.params}),[f]),y=u.useCallback(x=>c.subscribe(o,x),[c,o]),v=u.useCallback(()=>c.get(o),[c,o]),i=ge(y,v,v),g=u.useContext(I),S=u.useContext(j),C=h.sourceTransportKey(r,e.target),E=u.useMemo(()=>g===X?null:h.resolveSourceRequest(S[C],o.params),[g,S,C,o]),[F,Z]=u.useState(null);return u.useEffect(()=>{(i==null?void 0:i.status)==="ready"&&F!==null&&Z(null)},[i,F]),u.useEffect(()=>{E&&!E.ok&&i===void 0&&console.warn(`[useSource] ${C}: ${E.reason}`)},[C,E==null?void 0:E.ok,E&&!E.ok?E.reason:void 0,i===void 0]),u.useEffect(()=>{if(E&&!E.ok||(i==null?void 0:i.status)==="ready"||F===f)return;Z(f);const x=E&&E.ok?()=>h.runSourceFetch({url:E.url,init:E.init},{fetcher:a,timeout:d==null?void 0:d.timeout}).then(Ce=>(d!=null&&d.debug&&console.info(`[useSource] loaded ${h.sourceCallKey(o)} origin=${m}`),Ce)):ve;c.load(o,x,m)},[c,o,f,i,F,E,a,m,d==null?void 0:d.timeout,d==null?void 0:d.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}:E&&!E.ok?{data:void 0,loading:!1}:{data:void 0,loading:F!==f}}const Se=ye;function Pe(r){return h.createFragmentsClient({...r,inject:T})}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=O,s.Area=ie,s.FragmentRenderer=de,s.FragmentStylesheet=M,s.FragmentsClientContext=P,s.FragmentsClientProvider=$,s.FragmentsProvider=me,s.InstanceIdContext=N,s.ModulesMapContext=A,s.ModulesMapProvider=D,s.ProjectPropertiesContext=b,s.createBrowserClient=Pe,s.defaultProjectProperties=_,s.injectStylesheet=T,s.useArea=U,s.useCssChunk=ce,s.useFragmentComponent=L,s.useFragmentMetrics=ne,s.useFragmentStylesheet=K,s.useProjectProperty=Ee,s.useSource=Se,Object.defineProperty(s,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-20260922090625",
4
+ "version": "0.2.0-dev-20260928114300",
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-20260922090625"
35
+ "@fragmentsx/fragments-client": "0.2.0-dev-20260928114300"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@testing-library/jest-dom": "^6.6.3",