effective-rsc 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/LLMS.md +54 -10
  2. package/README.md +3 -3
  3. package/dist/application/page.d.ts +14 -7
  4. package/dist/application/page.js +5 -3
  5. package/dist/application/page.js.map +1 -1
  6. package/dist/application/route-graph.d.ts +1 -1
  7. package/dist/application/route-graph.js.map +1 -1
  8. package/dist/application/server-fn.d.ts +10 -6
  9. package/dist/application/server-fn.js +9 -4
  10. package/dist/application/server-fn.js.map +1 -1
  11. package/dist/build/dev.d.ts +11 -11
  12. package/dist/build/dev.js +21 -5
  13. package/dist/build/dev.js.map +1 -1
  14. package/dist/cli.js +2 -0
  15. package/dist/cli.js.map +1 -1
  16. package/dist/client/application.js +12 -9
  17. package/dist/client/application.js.map +1 -1
  18. package/dist/client/browser-capabilities.d.ts +2 -9
  19. package/dist/client/browser-capabilities.js +3 -14
  20. package/dist/client/browser-capabilities.js.map +1 -1
  21. package/dist/client/browser-render-status.d.ts +25 -0
  22. package/dist/client/browser-render-status.js +20 -0
  23. package/dist/client/browser-render-status.js.map +1 -0
  24. package/dist/client/call-server.js +7 -2
  25. package/dist/client/call-server.js.map +1 -1
  26. package/dist/client/navigation-api.js +5 -4
  27. package/dist/client/navigation-api.js.map +1 -1
  28. package/dist/client/react-dom-renderer.d.ts +3 -2
  29. package/dist/client/react-dom-renderer.js +43 -2
  30. package/dist/client/react-dom-renderer.js.map +1 -1
  31. package/dist/client/route-refresh.d.ts +1 -2
  32. package/dist/client/route-refresh.js +5 -18
  33. package/dist/client/route-refresh.js.map +1 -1
  34. package/dist/dev/client.d.ts +2 -1
  35. package/dist/dev/client.js +46 -6
  36. package/dist/dev/client.js.map +1 -1
  37. package/dist/dev/panel.d.ts +12 -1
  38. package/dist/dev/panel.js +73 -5
  39. package/dist/dev/panel.js.map +1 -1
  40. package/dist/dev/runtime-failure.d.ts +1 -0
  41. package/dist/dev/runtime-failure.js +7 -1
  42. package/dist/dev/runtime-failure.js.map +1 -1
  43. package/dist/rsc/render-route-tree.d.ts +3 -3
  44. package/dist/rsc/render-route-tree.js +2 -2
  45. package/dist/rsc/render-route-tree.js.map +1 -1
  46. package/dist/server/application.js +54 -35
  47. package/dist/server/application.js.map +1 -1
  48. package/dist/server/server-fn-request.js +3 -1
  49. package/dist/server/server-fn-request.js.map +1 -1
  50. package/docs/02-guides/01-server-functions/50_greet.ts +18 -0
  51. package/docs/02-guides/01-server-functions/60_greeting-form.tsx +23 -0
  52. package/docs/02-guides/01-server-functions/index.md +7 -0
  53. package/docs/02-guides/03-routing/index.md +5 -1
  54. package/docs/03-advanced/02-client-navigation/index.md +6 -3
  55. package/docs/03-advanced/03-server-function-execution-and-refresh/index.md +3 -1
  56. package/docs/04-api-reference/02-page/index.md +8 -3
  57. package/docs/04-api-reference/06-middleware/index.md +2 -2
  58. package/docs/04-api-reference/08-server-fn/index.md +23 -0
  59. package/package.json +1 -1
@@ -1,3 +1,4 @@
1
1
  import { Effect } from 'effect';
2
+ import { BrowserRenderStatus } from '../client/browser-render-status.js';
2
3
  import { RouteRefresher } from '../client/route-refresh.js';
3
- export declare const startDevClient: Effect.Effect<void, import("effect/unstable/rpc/RpcClientError").RpcClientError, RouteRefresher | import("effect/Scope").Scope>;
4
+ export declare const startDevClient: Effect.Effect<void, import("effect/unstable/rpc/RpcClientError").RpcClientError, BrowserRenderStatus | RouteRefresher | import("effect/Scope").Scope>;
@@ -1,10 +1,12 @@
1
- import { Effect, Layer, Ref, Semaphore, Stream } from "effect";
1
+ import { Console, Effect, Layer, Ref, Semaphore, Stream } from "effect";
2
2
  import { RpcClient, RpcSerialization } from "effect/unstable/rpc";
3
+ import { navigationMode } from "../client/browser-capabilities.js";
4
+ import { BrowserRenderStatus } from "../client/browser-render-status.js";
3
5
  import { RouteRefresher } from "../client/route-refresh.js";
4
6
  import { DevChannelPath, DevRpcs } from "./channel.js";
5
7
  import { decideHotUpdate } from "./hmr-update.js";
6
8
  import { makeDevPanel } from "./panel.js";
7
- import { reportBrowserFailures } from "./runtime-failure.js";
9
+ import { fromRenderError, reportBrowserFailures } from "./runtime-failure.js";
8
10
 
9
11
  import * as __rspack_external__effect_platform_browser_BrowserSocket_31178d5b from "@effect/platform-browser/BrowserSocket";
10
12
 
@@ -23,6 +25,10 @@ import * as __rspack_external__effect_platform_browser_BrowserSocket_31178d5b fr
23
25
 
24
26
 
25
27
 
28
+
29
+
30
+
31
+
26
32
  const socketProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
27
33
  const socketUrl = `${socketProtocol}//${location.host}${DevChannelPath}`;
28
34
  const DevRpcProtocolLayer = RpcClient.layerProtocolSocket({
@@ -88,7 +94,18 @@ const settlePendingUpdate = Effect.fnUntraced(function*(pendingUpdate) {
88
94
  });
89
95
  const startDevClient = Effect.gen(function*() {
90
96
  const routeRefresher = yield* RouteRefresher;
97
+ const renderStatus = yield* BrowserRenderStatus;
91
98
  const panel = yield* makeDevPanel;
99
+ const mode = yield* navigationMode;
100
+ if (mode === 'Document') {
101
+ const missingApi = window.navigation === undefined ? 'Navigation API' : 'NavigationPrecommitController';
102
+ const message = `This browser does not support ${missingApi}. Links use full-page navigation. Client Components, Server Functions, and HMR remain enabled.`;
103
+ yield* Console.warn(`[effective-rsc] ${message}`);
104
+ yield* panel.dispatch({
105
+ _tag: 'Warning',
106
+ message
107
+ });
108
+ }
92
109
  const pendingUpdate = yield* Ref.make({
93
110
  acknowledgedClientHash: import.meta.rspackHash,
94
111
  clientHash: import.meta.rspackHash,
@@ -101,13 +118,31 @@ const startDevClient = Effect.gen(function*() {
101
118
  if (action === 'Reloading') {
102
119
  return;
103
120
  }
104
- if (action === 'Refresh') {
121
+ const status = yield* renderStatus.get;
122
+ if (action === 'Refresh' || status._tag === 'Failed') {
105
123
  yield* routeRefresher.refreshCurrentRoute('hmr-refresh');
124
+ // Starting a refresh is not evidence that the replacement rendered successfully.
125
+ return;
106
126
  }
107
127
  yield* panel.dispatch({
108
- _tag: 'Reconciled'
128
+ _tag: 'RuntimeReconciled'
109
129
  });
110
130
  });
131
+ yield* renderStatus.changes.pipe(Stream.runForEach((status)=>{
132
+ switch(status._tag){
133
+ case 'Waiting':
134
+ return Effect["void"];
135
+ case 'Rendered':
136
+ return panel.dispatch({
137
+ _tag: 'RuntimeReconciled'
138
+ });
139
+ case 'Failed':
140
+ return panel.dispatch({
141
+ _tag: 'RenderFailed',
142
+ failure: fromRenderError(status.error, status.componentStack)
143
+ });
144
+ }
145
+ }), Effect.forkScoped);
111
146
  yield* reportBrowserFailures((failure)=>panel.dispatch({
112
147
  _tag: 'RuntimeFailed',
113
148
  failure
@@ -117,8 +152,13 @@ const startDevClient = Effect.gen(function*() {
117
152
  const handleUpdate = Effect.fnUntraced(function*(phase, message) {
118
153
  if (message._tag === 'BuildFailed') {
119
154
  yield* panel.dispatch(message);
120
- } else if (phase === 'Live') {
121
- yield* handleHotUpdate(message);
155
+ } else {
156
+ yield* panel.dispatch({
157
+ _tag: 'BuildSucceeded'
158
+ });
159
+ if (phase === 'Live' || message.clientHash !== import.meta.rspackHash) {
160
+ yield* handleHotUpdate(message);
161
+ }
122
162
  }
123
163
  return 'Live';
124
164
  });
@@ -1 +1 @@
1
- {"version":3,"file":"dev/client.js","sources":["../../src/dev/client.ts"],"sourcesContent":["import * as BrowserSocket from '@effect/platform-browser/BrowserSocket';\nimport { Effect, Layer, Ref, Semaphore, Stream } from 'effect';\nimport { RpcClient, RpcSerialization } from 'effect/unstable/rpc';\n\nimport { RouteRefresher } from '../client/route-refresh';\nimport { DevChannelPath, DevRpcs, type DevUpdate } from './channel';\nimport { decideHotUpdate, type HotUpdateCheck, type PendingDevUpdate } from './hmr-update';\nimport { makeDevPanel } from './panel';\nimport { reportBrowserFailures } from './runtime-failure';\n\nconst socketProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';\nconst socketUrl = `${socketProtocol}//${location.host}${DevChannelPath}`;\n\nconst DevRpcProtocolLayer = RpcClient.layerProtocolSocket({ retryTransientErrors: true }).pipe(\n Layer.provide(BrowserSocket.layerWebSocket(socketUrl)),\n Layer.provide(RpcSerialization.layerJson),\n);\n\ntype DevHotUpdate = Exclude<DevUpdate, { readonly _tag: 'BuildFailed' }>;\ntype DevUpdatePhase = 'Snapshot' | 'Live';\n\nconst recordUpdate = (pending: PendingDevUpdate, message: DevHotUpdate): PendingDevUpdate => ({\n acknowledgedClientHash: pending.acknowledgedClientHash,\n clientHash: message.clientHash,\n rscRefresh:\n pending.rscRefresh === 'Pending' || message._tag === 'RscUpdate' ? 'Pending' : 'Current',\n});\n\nconst settlePendingUpdate = Effect.fnUntraced(function* (pendingUpdate: Ref.Ref<PendingDevUpdate>) {\n const reconcile = Effect.gen(function* () {\n const pending = yield* Ref.get(pendingUpdate);\n if (pending.acknowledgedClientHash !== pending.clientHash) {\n const previousHash = import.meta.rspackHash;\n const check = yield* Effect.tryPromise(() => import.meta.webpackHot!.check(true)).pipe(\n Effect.match({\n onFailure: (): HotUpdateCheck => ({ _tag: 'Failed' }),\n onSuccess: (updatedModules): HotUpdateCheck => ({\n _tag: 'Completed',\n currentHash: import.meta.rspackHash,\n previousHash,\n updatedModules,\n }),\n }),\n );\n const decision = decideHotUpdate(pending, check);\n if (decision._tag === 'Reload') {\n yield* Effect.sync(() => location.reload());\n return 'Reloading' as const;\n }\n\n yield* Ref.update(pendingUpdate, (current) => ({\n ...current,\n acknowledgedClientHash: decision.acknowledgedClientHash,\n }));\n return 'Retry' as const;\n }\n\n return yield* Ref.modify(pendingUpdate, (current) => {\n if (current.acknowledgedClientHash !== current.clientHash) {\n return ['Retry', current] as const;\n }\n if (current.rscRefresh === 'Current') {\n return ['Current', current] as const;\n }\n return ['Refresh', { ...current, rscRefresh: 'Current' }] as const;\n });\n });\n\n return yield* reconcile.pipe(Effect.repeat({ while: (action) => action === 'Retry' }));\n});\n\nexport const startDevClient = Effect.gen(function* () {\n const routeRefresher = yield* RouteRefresher;\n const panel = yield* makeDevPanel;\n const pendingUpdate = yield* Ref.make<PendingDevUpdate>({\n acknowledgedClientHash: import.meta.rspackHash,\n clientHash: import.meta.rspackHash,\n rscRefresh: 'Current',\n });\n const updateLock = yield* Semaphore.make(1);\n const handleHotUpdate = Effect.fnUntraced(function* (message: DevHotUpdate) {\n yield* Ref.update(pendingUpdate, (pending) => recordUpdate(pending, message));\n const action = yield* updateLock.withPermit(settlePendingUpdate(pendingUpdate));\n if (action === 'Reloading') {\n return;\n }\n if (action === 'Refresh') {\n yield* routeRefresher.refreshCurrentRoute('hmr-refresh');\n }\n yield* panel.dispatch({ _tag: 'Reconciled' });\n });\n yield* reportBrowserFailures((failure) =>\n panel.dispatch({ _tag: 'RuntimeFailed', failure }),\n ).pipe(Effect.forkScoped);\n\n const observeUpdates = Effect.gen(function* () {\n const client = yield* RpcClient.make(DevRpcs);\n const handleUpdate = Effect.fnUntraced(function* (phase: DevUpdatePhase, message: DevUpdate) {\n if (message._tag === 'BuildFailed') {\n yield* panel.dispatch(message);\n } else if (phase === 'Live') {\n yield* handleHotUpdate(message);\n }\n\n return 'Live' as const;\n });\n\n yield* client.ObserveDevUpdates().pipe(\n Stream.runFoldEffect((): DevUpdatePhase => 'Snapshot', handleUpdate),\n Effect.asVoid,\n );\n });\n\n yield* observeUpdates.pipe(Effect.provide(DevRpcProtocolLayer));\n});\n"],"names":["BrowserSocket","Effect","Layer","Ref","Semaphore","Stream","RpcClient","RpcSerialization","RouteRefresher","DevChannelPath","DevRpcs","decideHotUpdate","makeDevPanel","reportBrowserFailures","socketProtocol","location","socketUrl","DevRpcProtocolLayer","recordUpdate","pending","message","settlePendingUpdate","pendingUpdate","reconcile","previousHash","check","updatedModules","decision","current","action","startDevClient","routeRefresher","panel","updateLock","handleHotUpdate","failure","observeUpdates","client","handleUpdate","phase"],"mappings":"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"}
1
+ {"version":3,"file":"dev/client.js","sources":["../../src/dev/client.ts"],"sourcesContent":["import * as BrowserSocket from '@effect/platform-browser/BrowserSocket';\nimport { Console, Effect, Layer, Ref, Semaphore, Stream } from 'effect';\nimport { RpcClient, RpcSerialization } from 'effect/unstable/rpc';\n\nimport { navigationMode } from '../client/browser-capabilities';\nimport { BrowserRenderStatus } from '../client/browser-render-status';\nimport { RouteRefresher } from '../client/route-refresh';\nimport { DevChannelPath, DevRpcs, type DevUpdate } from './channel';\nimport { decideHotUpdate, type HotUpdateCheck, type PendingDevUpdate } from './hmr-update';\nimport { makeDevPanel } from './panel';\nimport { fromRenderError, reportBrowserFailures } from './runtime-failure';\n\nconst socketProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';\nconst socketUrl = `${socketProtocol}//${location.host}${DevChannelPath}`;\n\nconst DevRpcProtocolLayer = RpcClient.layerProtocolSocket({ retryTransientErrors: true }).pipe(\n Layer.provide(BrowserSocket.layerWebSocket(socketUrl)),\n Layer.provide(RpcSerialization.layerJson),\n);\n\ntype DevHotUpdate = Exclude<DevUpdate, { readonly _tag: 'BuildFailed' }>;\ntype DevUpdatePhase = 'Snapshot' | 'Live';\n\nconst recordUpdate = (pending: PendingDevUpdate, message: DevHotUpdate): PendingDevUpdate => ({\n acknowledgedClientHash: pending.acknowledgedClientHash,\n clientHash: message.clientHash,\n rscRefresh:\n pending.rscRefresh === 'Pending' || message._tag === 'RscUpdate' ? 'Pending' : 'Current',\n});\n\nconst settlePendingUpdate = Effect.fnUntraced(function* (pendingUpdate: Ref.Ref<PendingDevUpdate>) {\n const reconcile = Effect.gen(function* () {\n const pending = yield* Ref.get(pendingUpdate);\n if (pending.acknowledgedClientHash !== pending.clientHash) {\n const previousHash = import.meta.rspackHash;\n const check = yield* Effect.tryPromise(() => import.meta.webpackHot!.check(true)).pipe(\n Effect.match({\n onFailure: (): HotUpdateCheck => ({ _tag: 'Failed' }),\n onSuccess: (updatedModules): HotUpdateCheck => ({\n _tag: 'Completed',\n currentHash: import.meta.rspackHash,\n previousHash,\n updatedModules,\n }),\n }),\n );\n const decision = decideHotUpdate(pending, check);\n if (decision._tag === 'Reload') {\n yield* Effect.sync(() => location.reload());\n return 'Reloading' as const;\n }\n\n yield* Ref.update(pendingUpdate, (current) => ({\n ...current,\n acknowledgedClientHash: decision.acknowledgedClientHash,\n }));\n return 'Retry' as const;\n }\n\n return yield* Ref.modify(pendingUpdate, (current) => {\n if (current.acknowledgedClientHash !== current.clientHash) {\n return ['Retry', current] as const;\n }\n if (current.rscRefresh === 'Current') {\n return ['Current', current] as const;\n }\n return ['Refresh', { ...current, rscRefresh: 'Current' }] as const;\n });\n });\n\n return yield* reconcile.pipe(Effect.repeat({ while: (action) => action === 'Retry' }));\n});\n\nexport const startDevClient = Effect.gen(function* () {\n const routeRefresher = yield* RouteRefresher;\n const renderStatus = yield* BrowserRenderStatus;\n const panel = yield* makeDevPanel;\n const mode = yield* navigationMode;\n if (mode === 'Document') {\n const missingApi =\n window.navigation === undefined ? 'Navigation API' : 'NavigationPrecommitController';\n const message = `This browser does not support ${missingApi}. Links use full-page navigation. Client Components, Server Functions, and HMR remain enabled.`;\n yield* Console.warn(`[effective-rsc] ${message}`);\n yield* panel.dispatch({ _tag: 'Warning', message });\n }\n const pendingUpdate = yield* Ref.make<PendingDevUpdate>({\n acknowledgedClientHash: import.meta.rspackHash,\n clientHash: import.meta.rspackHash,\n rscRefresh: 'Current',\n });\n const updateLock = yield* Semaphore.make(1);\n const handleHotUpdate = Effect.fnUntraced(function* (message: DevHotUpdate) {\n yield* Ref.update(pendingUpdate, (pending) => recordUpdate(pending, message));\n const action = yield* updateLock.withPermit(settlePendingUpdate(pendingUpdate));\n if (action === 'Reloading') {\n return;\n }\n const status = yield* renderStatus.get;\n if (action === 'Refresh' || status._tag === 'Failed') {\n yield* routeRefresher.refreshCurrentRoute('hmr-refresh');\n // Starting a refresh is not evidence that the replacement rendered successfully.\n return;\n }\n yield* panel.dispatch({ _tag: 'RuntimeReconciled' });\n });\n yield* renderStatus.changes.pipe(\n Stream.runForEach((status) => {\n switch (status._tag) {\n case 'Waiting':\n return Effect.void;\n case 'Rendered':\n return panel.dispatch({ _tag: 'RuntimeReconciled' });\n case 'Failed':\n return panel.dispatch({\n _tag: 'RenderFailed',\n failure: fromRenderError(status.error, status.componentStack),\n });\n }\n }),\n Effect.forkScoped,\n );\n yield* reportBrowserFailures((failure) =>\n panel.dispatch({ _tag: 'RuntimeFailed', failure }),\n ).pipe(Effect.forkScoped);\n\n const observeUpdates = Effect.gen(function* () {\n const client = yield* RpcClient.make(DevRpcs);\n const handleUpdate = Effect.fnUntraced(function* (phase: DevUpdatePhase, message: DevUpdate) {\n if (message._tag === 'BuildFailed') {\n yield* panel.dispatch(message);\n } else {\n yield* panel.dispatch({ _tag: 'BuildSucceeded' });\n if (phase === 'Live' || message.clientHash !== import.meta.rspackHash) {\n yield* handleHotUpdate(message);\n }\n }\n\n return 'Live' as const;\n });\n\n yield* client.ObserveDevUpdates().pipe(\n Stream.runFoldEffect((): DevUpdatePhase => 'Snapshot', handleUpdate),\n Effect.asVoid,\n );\n });\n\n yield* observeUpdates.pipe(Effect.provide(DevRpcProtocolLayer));\n});\n"],"names":["BrowserSocket","Console","Effect","Layer","Ref","Semaphore","Stream","RpcClient","RpcSerialization","navigationMode","BrowserRenderStatus","RouteRefresher","DevChannelPath","DevRpcs","decideHotUpdate","makeDevPanel","fromRenderError","reportBrowserFailures","socketProtocol","location","socketUrl","DevRpcProtocolLayer","recordUpdate","pending","message","settlePendingUpdate","pendingUpdate","reconcile","previousHash","check","updatedModules","decision","current","action","startDevClient","routeRefresher","renderStatus","panel","mode","missingApi","window","undefined","updateLock","handleHotUpdate","status","failure","observeUpdates","client","handleUpdate","phase"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAwE;AACA;AACN;AAEF;AACM;AACb;AACW;AACuB;AACpD;AACoC;AAE3E,MAAMkB,cAAcA,GAAGC,SAAS,QAAQ,KAAK,WAAW,SAAS;AACjE,MAAMC,SAASA,GAAG,GAAGF,cAAcA,CAAC,EAAE,EAAEC,SAAS,IAAI,GAAGP,cAAcA,EAAE;AAExE,MAAMS,mBAAmBA,GAAGd,6BAA6B,CAAC;IAAE,sBAAsB;AAAK,GAAG,IAAI,CAC5FJ,aAAa,CAACH,gFAA4B,CAACoB,SAASA,IACpDjB,aAAa,CAACK,0BAA0B;AAM1C,MAAMc,YAAYA,GAAG,CAACC,SAA2BC,UAA6C;QAC5F,wBAAwBD,QAAQ,sBAAsB;QACtD,YAAYC,QAAQ,UAAU;QAC9B,YACED,QAAQ,UAAU,KAAK,aAAaC,QAAQ,IAAI,KAAK,cAAc,YAAY;IACnF;AAEA,MAAMC,mBAAmBA,GAAGvB,iBAAiB,CAAC,UAAWwB,aAAwC;IAC/F,MAAMC,YAAYzB,UAAU,CAAC;QAC3B,MAAMqB,UAAU,OAAOnB,OAAO,CAACsB;QAC/B,IAAIH,QAAQ,sBAAsB,KAAKA,QAAQ,UAAU,EAAE;YACzD,MAAMK,eAAe,YAAY,UAAU;YAC3C,MAAMC,QAAQ,OAAO3B,iBAAiB,CAAC,IAAM,YAAY,UAAU,CAAE,KAAK,CAAC,OAAO,IAAI,CACpFA,YAAY,CAAC;gBACX,WAAW,IAAuB;wBAAE,MAAM;oBAAS;gBACnD,WAAW,CAAC4B,iBAAoC;wBAC9C,MAAM;wBACN,aAAa,YAAY,UAAU;wBACnCF;wBACAE;oBACF;YACF;YAEF,MAAMC,WAAWjB,eAAeA,CAACS,SAASM;YAC1C,IAAIE,SAAS,IAAI,KAAK,UAAU;gBAC9B,OAAO7B,WAAW,CAAC,IAAMiB,SAAS,MAAM;gBACxC,OAAO;YACT;YAEA,OAAOf,UAAU,CAACsB,eAAe,CAACM,UAAa;oBAC7C,GAAGA,OAAO;oBACV,wBAAwBD,SAAS,sBAAsB;gBACzD;YACA,OAAO;QACT;QAEA,OAAO,OAAO3B,UAAU,CAACsB,eAAe,CAACM;YACvC,IAAIA,QAAQ,sBAAsB,KAAKA,QAAQ,UAAU,EAAE;gBACzD,OAAO;oBAAC;oBAASA;iBAAQ;YAC3B;YACA,IAAIA,QAAQ,UAAU,KAAK,WAAW;gBACpC,OAAO;oBAAC;oBAAWA;iBAAQ;YAC7B;YACA,OAAO;gBAAC;gBAAW;oBAAE,GAAGA,OAAO;oBAAE,YAAY;gBAAU;aAAE;QAC3D;IACF;IAEA,OAAO,OAAOL,UAAU,IAAI,CAACzB,aAAa,CAAC;QAAE,OAAO,CAAC+B,SAAWA,WAAW;IAAQ;AACrF;AAEO,MAAMC,cAAcA,GAAGhC,UAAU,CAAC;IACvC,MAAMiC,iBAAiB,OAAOxB,cAAcA;IAC5C,MAAMyB,eAAe,OAAO1B,mBAAmBA;IAC/C,MAAM2B,QAAQ,OAAOtB,YAAYA;IACjC,MAAMuB,OAAO,OAAO7B,cAAcA;IAClC,IAAI6B,SAAS,YAAY;QACvB,MAAMC,aACJC,OAAO,UAAU,KAAKC,YAAY,mBAAmB;QACvD,MAAMjB,UAAU,CAAC,8BAA8B,EAAEe,WAAW,8FAA8F,CAAC;QAC3J,OAAOtC,YAAY,CAAC,CAAC,gBAAgB,EAAEuB,SAAS;QAChD,OAAOa,MAAM,QAAQ,CAAC;YAAE,MAAM;YAAWb;QAAQ;IACnD;IACA,MAAME,gBAAgB,OAAOtB,QAAQ,CAAmB;QACtD,wBAAwB,YAAY,UAAU;QAC9C,YAAY,YAAY,UAAU;QAClC,YAAY;IACd;IACA,MAAMsC,aAAa,OAAOrC,cAAc,CAAC;IACzC,MAAMsC,kBAAkBzC,iBAAiB,CAAC,UAAWsB,OAAqB;QACxE,OAAOpB,UAAU,CAACsB,eAAe,CAACH,UAAYD,YAAYA,CAACC,SAASC;QACpE,MAAMS,SAAS,OAAOS,WAAW,UAAU,CAACjB,mBAAmBA,CAACC;QAChE,IAAIO,WAAW,aAAa;YAC1B;QACF;QACA,MAAMW,SAAS,OAAOR,aAAa,GAAG;QACtC,IAAIH,WAAW,aAAaW,OAAO,IAAI,KAAK,UAAU;YACpD,OAAOT,eAAe,mBAAmB,CAAC;YAC1C,iFAAiF;YACjF;QACF;QACA,OAAOE,MAAM,QAAQ,CAAC;YAAE,MAAM;QAAoB;IACpD;IACA,OAAOD,aAAa,OAAO,CAAC,IAAI,CAC9B9B,iBAAiB,CAAC,CAACsC;QACjB,OAAQA,OAAO,IAAI;YACjB,KAAK;gBACH,OAAO1C,cAAW;YACpB,KAAK;gBACH,OAAOmC,MAAM,QAAQ,CAAC;oBAAE,MAAM;gBAAoB;YACpD,KAAK;gBACH,OAAOA,MAAM,QAAQ,CAAC;oBACpB,MAAM;oBACN,SAASrB,eAAeA,CAAC4B,OAAO,KAAK,EAAEA,OAAO,cAAc;gBAC9D;QACJ;IACF,IACA1C,iBAAiB;IAEnB,OAAOe,qBAAqBA,CAAC,CAAC4B,UAC5BR,MAAM,QAAQ,CAAC;YAAE,MAAM;YAAiBQ;QAAQ,IAChD,IAAI,CAAC3C,iBAAiB;IAExB,MAAM4C,iBAAiB5C,UAAU,CAAC;QAChC,MAAM6C,SAAS,OAAOxC,cAAc,CAACM,OAAOA;QAC5C,MAAMmC,eAAe9C,iBAAiB,CAAC,UAAW+C,KAAqB,EAAEzB,OAAkB;YACzF,IAAIA,QAAQ,IAAI,KAAK,eAAe;gBAClC,OAAOa,MAAM,QAAQ,CAACb;YACxB,OAAO;gBACL,OAAOa,MAAM,QAAQ,CAAC;oBAAE,MAAM;gBAAiB;gBAC/C,IAAIY,UAAU,UAAUzB,QAAQ,UAAU,KAAK,YAAY,UAAU,EAAE;oBACrE,OAAOmB,gBAAgBnB;gBACzB;YACF;YAEA,OAAO;QACT;QAEA,OAAOuB,OAAO,iBAAiB,GAAG,IAAI,CACpCzC,oBAAoB,CAAC,IAAsB,YAAY0C,eACvD9C,aAAa;IAEjB;IAEA,OAAO4C,eAAe,IAAI,CAAC5C,cAAc,CAACmB,mBAAmBA;AAC/D,GAAG"}
@@ -3,6 +3,9 @@ import type { DevRuntimeFailure } from './runtime-failure.js';
3
3
  export type { DevRuntimeFailure } from './runtime-failure.js';
4
4
  export declare const DevPanelElementName = "ersc-dev-panel";
5
5
  type DevPanelContent = {
6
+ readonly _tag: 'Warning';
7
+ readonly message: string;
8
+ } | {
6
9
  readonly _tag: 'BuildFailed';
7
10
  readonly diagnostics: string;
8
11
  } | {
@@ -19,13 +22,21 @@ export type DevPanelState = {
19
22
  readonly content: DevPanelContent;
20
23
  };
21
24
  export type DevPanelEvent = {
25
+ readonly _tag: 'Warning';
26
+ readonly message: string;
27
+ } | {
22
28
  readonly _tag: 'BuildFailed';
23
29
  readonly diagnostics: string;
24
30
  } | {
25
31
  readonly _tag: 'RuntimeFailed';
26
32
  readonly failure: DevRuntimeFailure;
27
33
  } | {
28
- readonly _tag: 'Reconciled';
34
+ readonly _tag: 'RenderFailed';
35
+ readonly failure: DevRuntimeFailure;
36
+ } | {
37
+ readonly _tag: 'BuildSucceeded';
38
+ } | {
39
+ readonly _tag: 'RuntimeReconciled';
29
40
  } | {
30
41
  readonly _tag: 'Opened';
31
42
  } | {
package/dist/dev/panel.js CHANGED
@@ -9582,7 +9582,7 @@ const ScrollAreaThumb_ScrollAreaThumb = /*#__PURE__*/__rspack_external_react.for
9582
9582
  if (process.env.NODE_ENV !== "production") ScrollAreaThumb_ScrollAreaThumb.displayName = "ScrollAreaThumb";
9583
9583
 
9584
9584
 
9585
- const panelraw_namespaceObject = ":host {\n all: initial;\n color-scheme: dark;\n --ersc-canvas: #111110;\n --ersc-surface: #181817;\n --ersc-raised: #201f1e;\n --ersc-border: #343230;\n --ersc-border-subtle: #292725;\n --ersc-text: #f3f2ef;\n --ersc-text-secondary: #aaa7a1;\n --ersc-text-tertiary: #77736d;\n --ersc-danger: #ff615a;\n --ersc-danger-muted: #3a1f1d;\n --ersc-ease-out: cubic-bezier(0.23, 1, 0.32, 1);\n}\n\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\nbutton {\n font: inherit;\n}\n\n.backdrop {\n position: fixed;\n inset: 0;\n z-index: 2147483646;\n width: 100vw;\n background: rgb(9 9 8 / 76%);\n backdrop-filter: blur(2px);\n transition: opacity 160ms var(--ersc-ease-out);\n}\n\n.backdrop[data-starting-style],\n.backdrop[data-ending-style] {\n opacity: 0;\n}\n\n.viewport {\n position: fixed;\n inset: 0;\n z-index: 2147483647;\n width: 100vw;\n overflow: auto;\n padding: clamp(24px, 6vh, 72px) 20px;\n font-family:\n Inter,\n ui-sans-serif,\n -apple-system,\n BlinkMacSystemFont,\n 'Segoe UI',\n sans-serif;\n color: var(--ersc-text);\n}\n\n.popup {\n display: flex;\n width: min(920px, 100%);\n max-height: calc(100svh - clamp(48px, 12vh, 144px));\n margin: 0 auto;\n overflow: hidden;\n color: var(--ersc-text);\n background: var(--ersc-canvas);\n border: 1px solid var(--ersc-border);\n border-radius: 10px;\n box-shadow:\n 0 32px 80px rgb(0 0 0 / 48%),\n 0 2px 8px rgb(0 0 0 / 32%);\n flex-direction: column;\n transition:\n opacity 180ms var(--ersc-ease-out),\n transform 180ms var(--ersc-ease-out);\n transform-origin: center;\n}\n\n.popup[data-starting-style],\n.popup[data-ending-style] {\n opacity: 0;\n transform: translateY(8px) scale(0.985);\n}\n\nheader {\n display: flex;\n min-height: 76px;\n gap: 14px;\n align-items: center;\n padding: 14px 16px 14px 18px;\n background: var(--ersc-surface);\n border-bottom: 1px solid var(--ersc-border-subtle);\n}\n\n.error-mark {\n display: grid;\n width: 34px;\n height: 34px;\n color: var(--ersc-danger);\n background: var(--ersc-danger-muted);\n border: 1px solid rgb(255 97 90 / 24%);\n border-radius: 7px;\n flex: 0 0 auto;\n place-items: center;\n}\n\n.error-mark svg {\n width: 18px;\n height: 18px;\n}\n\n.heading {\n display: grid;\n min-width: 0;\n gap: 5px;\n flex: 1;\n}\n\n.brand {\n overflow: hidden;\n color: var(--ersc-text-secondary);\n font:\n 600 10px/1.1 ui-monospace,\n SFMono-Regular,\n Consolas,\n 'Liberation Mono',\n monospace;\n letter-spacing: 0.08em;\n text-overflow: ellipsis;\n text-transform: uppercase;\n white-space: nowrap;\n}\n\n.brand span {\n color: var(--ersc-text-tertiary);\n}\n\n.title {\n margin: 0;\n color: var(--ersc-text);\n font-size: 17px;\n font-weight: 600;\n line-height: 1.2;\n letter-spacing: -0.015em;\n}\n\n.failure-count {\n padding: 5px 8px;\n color: var(--ersc-text-secondary);\n font:\n 500 11px/1 ui-monospace,\n SFMono-Regular,\n Consolas,\n 'Liberation Mono',\n monospace;\n background: var(--ersc-raised);\n border: 1px solid var(--ersc-border);\n border-radius: 999px;\n white-space: nowrap;\n}\n\n.close {\n display: grid;\n width: 34px;\n height: 34px;\n padding: 0;\n color: var(--ersc-text-secondary);\n cursor: pointer;\n background: transparent;\n border: 1px solid transparent;\n border-radius: 7px;\n transition:\n color 140ms ease,\n background-color 140ms ease,\n border-color 140ms ease,\n transform 140ms var(--ersc-ease-out);\n place-items: center;\n}\n\n.close svg {\n width: 18px;\n height: 18px;\n}\n\n.close:focus-visible {\n color: var(--ersc-text);\n outline: 2px solid var(--ersc-danger);\n outline-offset: 2px;\n}\n\n.close:active {\n transform: scale(0.94);\n}\n\n.content {\n position: relative;\n min-height: 0;\n overflow: hidden;\n overscroll-behavior: contain;\n}\n\n.content-viewport {\n max-height: calc(100svh - clamp(124px, calc(12vh + 76px), 220px));\n overscroll-behavior: contain;\n scrollbar-width: none;\n}\n\n.scrollbar {\n position: absolute;\n top: 4px;\n right: 3px;\n bottom: 4px;\n display: flex;\n width: 8px;\n padding: 2px;\n border-radius: 999px;\n opacity: 0;\n transition: opacity 140ms ease;\n user-select: none;\n}\n\n.content[data-scrolling] .scrollbar,\n.scrollbar[data-hovering] {\n opacity: 1;\n}\n\n.scrollbar-thumb {\n width: 100%;\n background: #55514c;\n border-radius: inherit;\n}\n\narticle + article {\n border-top: 1px solid var(--ersc-border-subtle);\n}\n\n.failure {\n display: grid;\n grid-template-columns: 58px minmax(0, 1fr);\n}\n\n.failure-index {\n padding: 23px 12px;\n color: var(--ersc-text-tertiary);\n font:\n 500 11px/1 ui-monospace,\n SFMono-Regular,\n Consolas,\n 'Liberation Mono',\n monospace;\n text-align: center;\n background: var(--ersc-surface);\n border-right: 1px solid var(--ersc-border-subtle);\n}\n\n.failure-body {\n min-width: 0;\n padding: 22px 24px 24px;\n}\n\n.category,\n.component-stack-title,\n.message {\n margin: 0;\n}\n\n.category {\n display: flex;\n gap: 8px;\n align-items: center;\n color: var(--ersc-danger);\n font-size: 11px;\n font-weight: 650;\n line-height: 16px;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n}\n\n.status-dot {\n width: 6px;\n height: 6px;\n background: currentcolor;\n border-radius: 50%;\n box-shadow: 0 0 0 3px rgb(255 97 90 / 12%);\n}\n\n.component-stack-title {\n margin: 0 0 8px;\n color: var(--ersc-text-secondary);\n font-size: 10px;\n font-weight: 600;\n line-height: 16px;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n}\n\n.trace-section {\n margin-top: 18px;\n}\n\n.stack {\n margin-top: 16px;\n}\n\n.stack-trigger {\n display: flex;\n width: fit-content;\n gap: 5px;\n align-items: center;\n padding: 5px 0;\n color: var(--ersc-text-secondary);\n font:\n 600 11px/1.4 ui-monospace,\n SFMono-Regular,\n Consolas,\n 'Liberation Mono',\n monospace;\n cursor: pointer;\n background: transparent;\n border: 0;\n transition:\n color 140ms ease,\n transform 140ms var(--ersc-ease-out);\n}\n\n.stack-trigger:focus-visible {\n color: var(--ersc-text);\n outline: 2px solid var(--ersc-danger);\n outline-offset: 2px;\n}\n\n.stack-trigger:active {\n transform: scale(0.97);\n}\n\n.stack-trigger svg {\n width: 14px;\n height: 14px;\n transition: transform 160ms var(--ersc-ease-out);\n}\n\n.stack-trigger[aria-expanded='true'] svg {\n transform: rotate(90deg);\n}\n\n.stack-panel pre {\n margin-top: 6px;\n}\n\n.message {\n margin-top: 10px;\n color: var(--ersc-text);\n font:\n 500 15px/1.55 ui-monospace,\n SFMono-Regular,\n Consolas,\n 'Liberation Mono',\n monospace;\n letter-spacing: -0.015em;\n overflow-wrap: anywhere;\n}\n\n.error-name {\n color: #ff8c87;\n font-weight: 650;\n}\n\npre {\n margin: 0;\n overflow: auto;\n color: #cbc8c2;\n font:\n 12px/1.65 ui-monospace,\n SFMono-Regular,\n Consolas,\n 'Liberation Mono',\n monospace;\n tab-size: 2;\n word-break: break-word;\n white-space: pre-wrap;\n}\n\n.code-frame,\n.build-output {\n padding: 14px 16px;\n background: var(--ersc-surface);\n border: 1px solid var(--ersc-border-subtle);\n border-radius: 7px;\n}\n\n.build-failure {\n padding: 22px 24px 24px;\n}\n\n.section-heading {\n display: flex;\n gap: 16px;\n align-items: baseline;\n justify-content: space-between;\n margin-bottom: 10px;\n color: var(--ersc-text-secondary);\n font:\n 600 10px/1.4 ui-monospace,\n SFMono-Regular,\n Consolas,\n 'Liberation Mono',\n monospace;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n}\n\n.section-heading span:last-child {\n color: var(--ersc-text-tertiary);\n font-weight: 500;\n letter-spacing: 0;\n text-transform: none;\n}\n\n.build-output {\n color: var(--ersc-text);\n background: #0d0d0c;\n border-left: 2px solid var(--ersc-danger);\n}\n\n@media (hover: hover) and (pointer: fine) {\n .close:hover {\n color: var(--ersc-text);\n background: var(--ersc-raised);\n border-color: var(--ersc-border);\n }\n\n .stack-trigger:hover {\n color: var(--ersc-text);\n }\n}\n\n@media (max-width: 560px) {\n .viewport {\n padding: 12px;\n }\n\n .popup {\n max-height: calc(100svh - 24px);\n }\n\n .content-viewport {\n max-height: calc(100svh - 92px);\n }\n\n header {\n min-height: 68px;\n gap: 10px;\n padding-inline: 12px;\n }\n\n .error-mark,\n .close {\n width: 32px;\n height: 32px;\n }\n\n .failure-count {\n display: none;\n }\n\n .failure {\n grid-template-columns: 38px minmax(0, 1fr);\n }\n\n .failure-index {\n padding-inline: 8px;\n }\n\n .failure-body,\n .build-failure {\n padding: 18px 16px 20px;\n }\n\n .section-heading span:last-child {\n display: none;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .backdrop,\n .popup,\n .close,\n .stack-trigger,\n .stack-trigger svg,\n .scrollbar {\n transition-duration: 0ms;\n }\n\n .popup[data-starting-style],\n .popup[data-ending-style] {\n transform: none;\n }\n}\n\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n white-space: nowrap;\n border: 0;\n clip: rect(0, 0, 0, 0);\n}\n";
9585
+ const panelraw_namespaceObject = ":host {\n all: initial;\n color-scheme: dark;\n --ersc-canvas: #111110;\n --ersc-surface: #181817;\n --ersc-raised: #201f1e;\n --ersc-border: #343230;\n --ersc-border-subtle: #292725;\n --ersc-text: #f3f2ef;\n --ersc-text-secondary: #aaa7a1;\n --ersc-text-tertiary: #77736d;\n --ersc-danger: #ff615a;\n --ersc-danger-muted: #3a1f1d;\n --ersc-ease-out: cubic-bezier(0.23, 1, 0.32, 1);\n}\n\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\nbutton {\n font: inherit;\n}\n\n.warning-notice {\n position: fixed;\n right: 16px;\n bottom: 16px;\n z-index: 2147483645;\n display: flex;\n width: min(440px, calc(100% - 32px));\n gap: 12px;\n padding: 16px;\n color: var(--ersc-text);\n font:\n 14px/1.5 system-ui,\n sans-serif;\n background: var(--ersc-surface);\n border: 1px solid #b88a36;\n border-radius: 10px;\n box-shadow: 0 8px 32px rgb(0 0 0 / 24%);\n}\n\n.warning-notice .title {\n margin-top: 6px;\n color: #f3c56b;\n}\n\n.warning-notice p {\n margin: 8px 0 0;\n}\n\n.warning-notice .close {\n flex: 0 0 auto;\n}\n\n.backdrop {\n position: fixed;\n inset: 0;\n z-index: 2147483646;\n width: 100vw;\n background: rgb(9 9 8 / 76%);\n backdrop-filter: blur(2px);\n transition: opacity 160ms var(--ersc-ease-out);\n}\n\n.backdrop[data-starting-style],\n.backdrop[data-ending-style] {\n opacity: 0;\n}\n\n.viewport {\n position: fixed;\n inset: 0;\n z-index: 2147483647;\n width: 100vw;\n overflow: auto;\n padding: clamp(24px, 6vh, 72px) 20px;\n font-family:\n Inter,\n ui-sans-serif,\n -apple-system,\n BlinkMacSystemFont,\n 'Segoe UI',\n sans-serif;\n color: var(--ersc-text);\n}\n\n.popup {\n display: flex;\n width: min(920px, 100%);\n max-height: calc(100svh - clamp(48px, 12vh, 144px));\n margin: 0 auto;\n overflow: hidden;\n color: var(--ersc-text);\n background: var(--ersc-canvas);\n border: 1px solid var(--ersc-border);\n border-radius: 10px;\n box-shadow:\n 0 32px 80px rgb(0 0 0 / 48%),\n 0 2px 8px rgb(0 0 0 / 32%);\n flex-direction: column;\n transition:\n opacity 180ms var(--ersc-ease-out),\n transform 180ms var(--ersc-ease-out);\n transform-origin: center;\n}\n\n.popup[data-starting-style],\n.popup[data-ending-style] {\n opacity: 0;\n transform: translateY(8px) scale(0.985);\n}\n\nheader {\n display: flex;\n min-height: 76px;\n gap: 14px;\n align-items: center;\n padding: 14px 16px 14px 18px;\n background: var(--ersc-surface);\n border-bottom: 1px solid var(--ersc-border-subtle);\n}\n\n.error-mark {\n display: grid;\n width: 34px;\n height: 34px;\n color: var(--ersc-danger);\n background: var(--ersc-danger-muted);\n border: 1px solid rgb(255 97 90 / 24%);\n border-radius: 7px;\n flex: 0 0 auto;\n place-items: center;\n}\n\n.error-mark svg {\n width: 18px;\n height: 18px;\n}\n\n.heading {\n display: grid;\n min-width: 0;\n gap: 5px;\n flex: 1;\n}\n\n.brand {\n overflow: hidden;\n color: var(--ersc-text-secondary);\n font:\n 600 10px/1.1 ui-monospace,\n SFMono-Regular,\n Consolas,\n 'Liberation Mono',\n monospace;\n letter-spacing: 0.08em;\n text-overflow: ellipsis;\n text-transform: uppercase;\n white-space: nowrap;\n}\n\n.brand span {\n color: var(--ersc-text-tertiary);\n}\n\n.title {\n margin: 0;\n color: var(--ersc-text);\n font-size: 17px;\n font-weight: 600;\n line-height: 1.2;\n letter-spacing: -0.015em;\n}\n\n.failure-count {\n padding: 5px 8px;\n color: var(--ersc-text-secondary);\n font:\n 500 11px/1 ui-monospace,\n SFMono-Regular,\n Consolas,\n 'Liberation Mono',\n monospace;\n background: var(--ersc-raised);\n border: 1px solid var(--ersc-border);\n border-radius: 999px;\n white-space: nowrap;\n}\n\n.close {\n display: grid;\n width: 34px;\n height: 34px;\n padding: 0;\n color: var(--ersc-text-secondary);\n cursor: pointer;\n background: transparent;\n border: 1px solid transparent;\n border-radius: 7px;\n transition:\n color 140ms ease,\n background-color 140ms ease,\n border-color 140ms ease,\n transform 140ms var(--ersc-ease-out);\n place-items: center;\n}\n\n.close svg {\n width: 18px;\n height: 18px;\n}\n\n.close:focus-visible {\n color: var(--ersc-text);\n outline: 2px solid var(--ersc-danger);\n outline-offset: 2px;\n}\n\n.close:active {\n transform: scale(0.94);\n}\n\n.content {\n position: relative;\n min-height: 0;\n overflow: hidden;\n overscroll-behavior: contain;\n}\n\n.content-viewport {\n max-height: calc(100svh - clamp(124px, calc(12vh + 76px), 220px));\n overscroll-behavior: contain;\n scrollbar-width: none;\n}\n\n.scrollbar {\n position: absolute;\n top: 4px;\n right: 3px;\n bottom: 4px;\n display: flex;\n width: 8px;\n padding: 2px;\n border-radius: 999px;\n opacity: 0;\n transition: opacity 140ms ease;\n user-select: none;\n}\n\n.content[data-scrolling] .scrollbar,\n.scrollbar[data-hovering] {\n opacity: 1;\n}\n\n.scrollbar-thumb {\n width: 100%;\n background: #55514c;\n border-radius: inherit;\n}\n\narticle + article {\n border-top: 1px solid var(--ersc-border-subtle);\n}\n\n.failure {\n display: grid;\n grid-template-columns: 58px minmax(0, 1fr);\n}\n\n.failure-index {\n padding: 23px 12px;\n color: var(--ersc-text-tertiary);\n font:\n 500 11px/1 ui-monospace,\n SFMono-Regular,\n Consolas,\n 'Liberation Mono',\n monospace;\n text-align: center;\n background: var(--ersc-surface);\n border-right: 1px solid var(--ersc-border-subtle);\n}\n\n.failure-body {\n min-width: 0;\n padding: 22px 24px 24px;\n}\n\n.category,\n.component-stack-title,\n.message {\n margin: 0;\n}\n\n.category {\n display: flex;\n gap: 8px;\n align-items: center;\n color: var(--ersc-danger);\n font-size: 11px;\n font-weight: 650;\n line-height: 16px;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n}\n\n.status-dot {\n width: 6px;\n height: 6px;\n background: currentcolor;\n border-radius: 50%;\n box-shadow: 0 0 0 3px rgb(255 97 90 / 12%);\n}\n\n.component-stack-title {\n margin: 0 0 8px;\n color: var(--ersc-text-secondary);\n font-size: 10px;\n font-weight: 600;\n line-height: 16px;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n}\n\n.trace-section {\n margin-top: 18px;\n}\n\n.stack {\n margin-top: 16px;\n}\n\n.stack-trigger {\n display: flex;\n width: fit-content;\n gap: 5px;\n align-items: center;\n padding: 5px 0;\n color: var(--ersc-text-secondary);\n font:\n 600 11px/1.4 ui-monospace,\n SFMono-Regular,\n Consolas,\n 'Liberation Mono',\n monospace;\n cursor: pointer;\n background: transparent;\n border: 0;\n transition:\n color 140ms ease,\n transform 140ms var(--ersc-ease-out);\n}\n\n.stack-trigger:focus-visible {\n color: var(--ersc-text);\n outline: 2px solid var(--ersc-danger);\n outline-offset: 2px;\n}\n\n.stack-trigger:active {\n transform: scale(0.97);\n}\n\n.stack-trigger svg {\n width: 14px;\n height: 14px;\n transition: transform 160ms var(--ersc-ease-out);\n}\n\n.stack-trigger[aria-expanded='true'] svg {\n transform: rotate(90deg);\n}\n\n.stack-panel pre {\n margin-top: 6px;\n}\n\n.message {\n margin-top: 10px;\n color: var(--ersc-text);\n font:\n 500 15px/1.55 ui-monospace,\n SFMono-Regular,\n Consolas,\n 'Liberation Mono',\n monospace;\n letter-spacing: -0.015em;\n overflow-wrap: anywhere;\n}\n\n.error-name {\n color: #ff8c87;\n font-weight: 650;\n}\n\npre {\n margin: 0;\n overflow: auto;\n color: #cbc8c2;\n font:\n 12px/1.65 ui-monospace,\n SFMono-Regular,\n Consolas,\n 'Liberation Mono',\n monospace;\n tab-size: 2;\n word-break: break-word;\n white-space: pre-wrap;\n}\n\n.code-frame,\n.build-output {\n padding: 14px 16px;\n background: var(--ersc-surface);\n border: 1px solid var(--ersc-border-subtle);\n border-radius: 7px;\n}\n\n.build-failure {\n padding: 22px 24px 24px;\n}\n\n.section-heading {\n display: flex;\n gap: 16px;\n align-items: baseline;\n justify-content: space-between;\n margin-bottom: 10px;\n color: var(--ersc-text-secondary);\n font:\n 600 10px/1.4 ui-monospace,\n SFMono-Regular,\n Consolas,\n 'Liberation Mono',\n monospace;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n}\n\n.section-heading span:last-child {\n color: var(--ersc-text-tertiary);\n font-weight: 500;\n letter-spacing: 0;\n text-transform: none;\n}\n\n.build-output {\n color: var(--ersc-text);\n background: #0d0d0c;\n border-left: 2px solid var(--ersc-danger);\n}\n\n@media (hover: hover) and (pointer: fine) {\n .close:hover {\n color: var(--ersc-text);\n background: var(--ersc-raised);\n border-color: var(--ersc-border);\n }\n\n .stack-trigger:hover {\n color: var(--ersc-text);\n }\n}\n\n@media (max-width: 560px) {\n .viewport {\n padding: 12px;\n }\n\n .popup {\n max-height: calc(100svh - 24px);\n }\n\n .content-viewport {\n max-height: calc(100svh - 92px);\n }\n\n header {\n min-height: 68px;\n gap: 10px;\n padding-inline: 12px;\n }\n\n .error-mark,\n .close {\n width: 32px;\n height: 32px;\n }\n\n .failure-count {\n display: none;\n }\n\n .failure {\n grid-template-columns: 38px minmax(0, 1fr);\n }\n\n .failure-index {\n padding-inline: 8px;\n }\n\n .failure-body,\n .build-failure {\n padding: 18px 16px 20px;\n }\n\n .section-heading span:last-child {\n display: none;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .backdrop,\n .popup,\n .close,\n .stack-trigger,\n .stack-trigger svg,\n .scrollbar {\n transition-duration: 0ms;\n }\n\n .popup[data-starting-style],\n .popup[data-ending-style] {\n transform: none;\n }\n}\n\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n white-space: nowrap;\n border: 0;\n clip: rect(0, 0, 0, 0);\n}\n";
9586
9586
 
9587
9587
 
9588
9588
 
@@ -9607,6 +9607,24 @@ const appendRuntimeFailure = (failures, failure)=>{
9607
9607
  };
9608
9608
  const applyDevPanelEvent = (state, event)=>{
9609
9609
  switch(event._tag){
9610
+ case 'Warning':
9611
+ return state._tag === 'Inactive' ? {
9612
+ _tag: 'Visible',
9613
+ content: event
9614
+ } : state;
9615
+ case 'RenderFailed':
9616
+ if (state._tag !== 'Inactive' && state.content._tag === 'BuildFailed') {
9617
+ return state;
9618
+ }
9619
+ return {
9620
+ _tag: 'Visible',
9621
+ content: {
9622
+ _tag: 'RuntimeFailed',
9623
+ failures: [
9624
+ event.failure
9625
+ ]
9626
+ }
9627
+ };
9610
9628
  case 'BuildFailed':
9611
9629
  return {
9612
9630
  _tag: 'Visible',
@@ -9644,11 +9662,23 @@ const applyDevPanelEvent = (state, event)=>{
9644
9662
  failures: appendRuntimeFailure(state.content.failures, event.failure)
9645
9663
  }
9646
9664
  };
9665
+ case 'Warning':
9666
+ return {
9667
+ _tag: 'Visible',
9668
+ content: {
9669
+ _tag: 'RuntimeFailed',
9670
+ failures: [
9671
+ event.failure
9672
+ ]
9673
+ }
9674
+ };
9647
9675
  }
9648
9676
  }
9649
9677
  }
9650
- case 'Reconciled':
9651
- return InitialDevPanelState;
9678
+ case 'BuildSucceeded':
9679
+ return state._tag !== 'Inactive' && state.content._tag === 'BuildFailed' ? InitialDevPanelState : state;
9680
+ case 'RuntimeReconciled':
9681
+ return state._tag !== 'Inactive' && state.content._tag === 'RuntimeFailed' ? InitialDevPanelState : state;
9652
9682
  case 'Opened':
9653
9683
  return state._tag === 'Dismissed' ? {
9654
9684
  _tag: 'Visible',
@@ -9772,7 +9802,7 @@ function RuntimeFailure({ failure, index }) {
9772
9802
  });
9773
9803
  }
9774
9804
  function DevPanelContent({ state }) {
9775
- if (state._tag === 'Inactive') {
9805
+ if (state._tag === 'Inactive' || state.content._tag === 'Warning') {
9776
9806
  return null;
9777
9807
  }
9778
9808
  const isBuildFailure = state.content._tag === 'BuildFailed';
@@ -9838,7 +9868,7 @@ function DevPanelContent({ state }) {
9838
9868
  className: "section-heading",
9839
9869
  children: [
9840
9870
  /*#__PURE__*/ jsx("span", {
9841
- children: "Compiler output"
9871
+ children: "Build diagnostics"
9842
9872
  }),
9843
9873
  /*#__PURE__*/ jsx("span", {
9844
9874
  children: "Fix the error and save to retry"
@@ -9868,6 +9898,44 @@ function DevPanelContent({ state }) {
9868
9898
  });
9869
9899
  }
9870
9900
  function DevPanel({ onOpenChange, portalContainer, state }) {
9901
+ if (state._tag !== 'Inactive' && state.content._tag === 'Warning') {
9902
+ return state._tag === 'Dismissed' ? null : /*#__PURE__*/ jsxs(Fragment, {
9903
+ children: [
9904
+ /*#__PURE__*/ jsx("style", {
9905
+ children: panelraw_namespaceObject
9906
+ }),
9907
+ /*#__PURE__*/ jsxs("aside", {
9908
+ "aria-label": "Development warning",
9909
+ "aria-live": "polite",
9910
+ className: "warning-notice",
9911
+ children: [
9912
+ /*#__PURE__*/ jsxs("div", {
9913
+ children: [
9914
+ /*#__PURE__*/ jsx("span", {
9915
+ className: "brand",
9916
+ children: "effective-rsc / development"
9917
+ }),
9918
+ /*#__PURE__*/ jsx("h2", {
9919
+ className: "title",
9920
+ children: "Client navigation unavailable"
9921
+ }),
9922
+ /*#__PURE__*/ jsx("p", {
9923
+ children: state.content.message
9924
+ })
9925
+ ]
9926
+ }),
9927
+ /*#__PURE__*/ jsx("button", {
9928
+ "aria-label": "Dismiss development warning",
9929
+ className: "close",
9930
+ onClick: ()=>onOpenChange(false),
9931
+ type: "button",
9932
+ children: "\xd7"
9933
+ })
9934
+ ]
9935
+ })
9936
+ ]
9937
+ });
9938
+ }
9871
9939
  return /*#__PURE__*/ jsx(DialogRoot_DialogRoot, {
9872
9940
  onOpenChange: onOpenChange,
9873
9941
  open: state._tag === 'Visible',