@askrjs/askr 0.0.50 → 0.0.51

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 (227) hide show
  1. package/dist/bench/components/benchmark-table.js.map +1 -1
  2. package/dist/benchmark.js +5 -4
  3. package/dist/benchmark.js.map +1 -1
  4. package/dist/bin/askr-ssg.d.ts.map +1 -1
  5. package/dist/bin/askr-ssg.js.map +1 -1
  6. package/dist/boot/hydration.js.map +1 -1
  7. package/dist/boot/index.js +2 -1
  8. package/dist/boot/index.js.map +1 -1
  9. package/dist/boot/root-lifecycle.d.ts.map +1 -1
  10. package/dist/boot/root-lifecycle.js +4 -4
  11. package/dist/boot/root-lifecycle.js.map +1 -1
  12. package/dist/boot/route-startup.js.map +1 -1
  13. package/dist/common/error-boundary.d.ts +16 -0
  14. package/dist/common/error-boundary.d.ts.map +1 -0
  15. package/dist/common/invariant.js +17 -0
  16. package/dist/common/invariant.js.map +1 -0
  17. package/dist/{dev → common}/logger.js +5 -6
  18. package/dist/common/logger.js.map +1 -0
  19. package/dist/common/vnode.js.map +1 -1
  20. package/dist/components/error-boundary.d.ts +2 -15
  21. package/dist/components/error-boundary.d.ts.map +1 -1
  22. package/dist/components/error-boundary.js +2 -74
  23. package/dist/components/error-boundary.js.map +1 -1
  24. package/dist/components/index.d.ts +2 -1
  25. package/dist/components/link.js +2 -0
  26. package/dist/components/link.js.map +1 -1
  27. package/dist/control/case.d.ts.map +1 -1
  28. package/dist/control/case.js +1 -0
  29. package/dist/control/case.js.map +1 -1
  30. package/dist/control/for.d.ts +3 -3
  31. package/dist/control/for.d.ts.map +1 -1
  32. package/dist/control/for.js +2 -2
  33. package/dist/control/for.js.map +1 -1
  34. package/dist/control/show.js +1 -0
  35. package/dist/control/show.js.map +1 -1
  36. package/dist/data/data-runtime.js.map +1 -1
  37. package/dist/data/invalidation.js +2 -2
  38. package/dist/data/invalidation.js.map +1 -1
  39. package/dist/data/mutation-cell.d.ts.map +1 -1
  40. package/dist/data/mutation-cell.js +1 -1
  41. package/dist/data/mutation-cell.js.map +1 -1
  42. package/dist/data/query-cell.js +2 -2
  43. package/dist/data/query-cell.js.map +1 -1
  44. package/dist/data/shared.js +1 -0
  45. package/dist/data/shared.js.map +1 -1
  46. package/dist/data/testing.js +2 -0
  47. package/dist/foundations/index.d.ts +1 -1
  48. package/dist/foundations/index.js +1 -1
  49. package/dist/foundations/state/controllable.d.ts +0 -1
  50. package/dist/foundations/state/controllable.d.ts.map +1 -1
  51. package/dist/foundations/state/controllable.js +1 -0
  52. package/dist/foundations/state/controllable.js.map +1 -1
  53. package/dist/foundations/structures/index.d.ts +1 -1
  54. package/dist/foundations/structures/index.js +2 -1
  55. package/dist/foundations/structures/portal.d.ts +2 -24
  56. package/dist/foundations/structures/portal.js +3 -187
  57. package/dist/fx/fx.js +2 -2
  58. package/dist/fx/fx.js.map +1 -1
  59. package/dist/fx/index.js +1 -0
  60. package/dist/index.d.ts +3 -3
  61. package/dist/index.js +4 -4
  62. package/dist/index.js.map +1 -1
  63. package/dist/jsx/types.d.ts.map +1 -1
  64. package/dist/jsx-dev-runtime.js +1 -0
  65. package/dist/jsx-dev-runtime.js.map +1 -1
  66. package/dist/jsx-runtime.js +1 -0
  67. package/dist/jsx-runtime.js.map +1 -1
  68. package/dist/renderer/attributes.js +1 -0
  69. package/dist/renderer/attributes.js.map +1 -1
  70. package/dist/renderer/boundaries.js +5 -5
  71. package/dist/renderer/boundaries.js.map +1 -1
  72. package/dist/renderer/child-shape.js +2 -2
  73. package/dist/renderer/child-shape.js.map +1 -1
  74. package/dist/renderer/children-fastpath.js +149 -0
  75. package/dist/renderer/children-fastpath.js.map +1 -0
  76. package/dist/renderer/children.js +3 -138
  77. package/dist/renderer/children.js.map +1 -1
  78. package/dist/renderer/cleanup.js +2 -2
  79. package/dist/renderer/cleanup.js.map +1 -1
  80. package/dist/renderer/component-host-cleanup.js +1 -1
  81. package/dist/renderer/component-host-cleanup.js.map +1 -1
  82. package/dist/renderer/component-host-instances.js +1 -1
  83. package/dist/renderer/component-host-instances.js.map +1 -1
  84. package/dist/renderer/component-host.js +1 -1
  85. package/dist/renderer/component-host.js.map +1 -1
  86. package/dist/renderer/dom-host.js.map +1 -1
  87. package/dist/renderer/dom-internal.js +5 -4
  88. package/dist/renderer/dom-internal.js.map +1 -1
  89. package/dist/renderer/dom.js +2 -1
  90. package/dist/renderer/element-children.js.map +1 -1
  91. package/dist/renderer/error-boundary-dom.js +51 -2
  92. package/dist/renderer/error-boundary-dom.js.map +1 -1
  93. package/dist/renderer/evaluate-reconcile.js +6 -5
  94. package/dist/renderer/evaluate-reconcile.js.map +1 -1
  95. package/dist/renderer/evaluate.js.map +1 -1
  96. package/dist/renderer/fastpath.js +3 -2
  97. package/dist/renderer/fastpath.js.map +1 -1
  98. package/dist/renderer/for-commit-dom-map.js.map +1 -1
  99. package/dist/renderer/for-commit-removal.js +2 -2
  100. package/dist/renderer/for-commit-removal.js.map +1 -1
  101. package/dist/renderer/for-commit-reorder.js +2 -2
  102. package/dist/renderer/for-commit-reorder.js.map +1 -1
  103. package/dist/renderer/for-commit.js +3 -3
  104. package/dist/renderer/for-commit.js.map +1 -1
  105. package/dist/renderer/index.js +3 -1
  106. package/dist/renderer/index.js.map +1 -1
  107. package/dist/renderer/prop-bindings.js +4 -4
  108. package/dist/renderer/prop-bindings.js.map +1 -1
  109. package/dist/renderer/reactive-child-dom.js.map +1 -1
  110. package/dist/renderer/reactive-children.js +4 -4
  111. package/dist/renderer/reactive-children.js.map +1 -1
  112. package/dist/renderer/reconcile-fastpaths.js +2 -1
  113. package/dist/renderer/reconcile-fastpaths.js.map +1 -1
  114. package/dist/renderer/reconcile-resolution.js +3 -3
  115. package/dist/renderer/reconcile-resolution.js.map +1 -1
  116. package/dist/renderer/retained-element-rollback.js +2 -1
  117. package/dist/renderer/retained-element-rollback.js.map +1 -1
  118. package/dist/renderer/stable-patch.js +2 -3
  119. package/dist/renderer/stable-patch.js.map +1 -1
  120. package/dist/renderer/utils.js +2 -1
  121. package/dist/renderer/utils.js.map +1 -1
  122. package/dist/resources/index.js +1 -2
  123. package/dist/router/activity.d.ts.map +1 -1
  124. package/dist/router/activity.js +20 -22
  125. package/dist/router/activity.js.map +1 -1
  126. package/dist/router/authoring.js +1 -1
  127. package/dist/router/authoring.js.map +1 -1
  128. package/dist/router/index.d.ts +1 -1
  129. package/dist/router/navigate.js +1 -1
  130. package/dist/router/navigate.js.map +1 -1
  131. package/dist/router/navigation-registry.js +1 -1
  132. package/dist/router/navigation-registry.js.map +1 -1
  133. package/dist/router/navigation-targets.d.ts.map +1 -1
  134. package/dist/router/navigation-targets.js +7 -5
  135. package/dist/router/navigation-targets.js.map +1 -1
  136. package/dist/router/rendering.js +1 -0
  137. package/dist/router/rendering.js.map +1 -1
  138. package/dist/router/resolution.d.ts +1 -14
  139. package/dist/router/resolution.d.ts.map +1 -1
  140. package/dist/router/resolution.js +6 -173
  141. package/dist/router/resolution.js.map +1 -1
  142. package/dist/router/route-matching.d.ts +20 -0
  143. package/dist/router/route-matching.d.ts.map +1 -0
  144. package/dist/router/route-matching.js +175 -0
  145. package/dist/router/route-matching.js.map +1 -0
  146. package/dist/router/route.js +4 -2
  147. package/dist/router/testing.js +4 -0
  148. package/dist/runtime/access.d.ts +20 -0
  149. package/dist/runtime/access.d.ts.map +1 -0
  150. package/dist/runtime/component-cleanup.js +1 -1
  151. package/dist/runtime/component-cleanup.js.map +1 -1
  152. package/dist/runtime/component-commit.js +1 -1
  153. package/dist/runtime/component-commit.js.map +1 -1
  154. package/dist/runtime/component-internal.d.ts +1 -1
  155. package/dist/runtime/component-internal.js +1 -1
  156. package/dist/runtime/component-internal.js.map +1 -1
  157. package/dist/runtime/component-lifecycle.d.ts +1 -1
  158. package/dist/runtime/component-lifecycle.js +1 -1
  159. package/dist/runtime/component-lifecycle.js.map +1 -1
  160. package/dist/runtime/component-scope.d.ts +1 -1
  161. package/dist/runtime/dev-namespace.d.ts +31 -0
  162. package/dist/runtime/dev-namespace.d.ts.map +1 -0
  163. package/dist/runtime/error-boundary.d.ts +5 -0
  164. package/dist/runtime/error-boundary.d.ts.map +1 -0
  165. package/dist/runtime/error-boundary.js +31 -0
  166. package/dist/runtime/error-boundary.js.map +1 -0
  167. package/dist/runtime/events.d.ts +58 -0
  168. package/dist/runtime/events.d.ts.map +1 -0
  169. package/dist/runtime/events.js +1 -1
  170. package/dist/runtime/events.js.map +1 -1
  171. package/dist/runtime/execution-model.d.ts +7 -0
  172. package/dist/runtime/execution-model.d.ts.map +1 -0
  173. package/dist/runtime/fastlane.d.ts +34 -0
  174. package/dist/runtime/fastlane.d.ts.map +1 -0
  175. package/dist/runtime/for-internal.d.ts +5 -5
  176. package/dist/runtime/for-internal.d.ts.map +1 -1
  177. package/dist/runtime/for-internal.js.map +1 -1
  178. package/dist/runtime/for-signals.d.ts +1 -1
  179. package/dist/runtime/for-signals.d.ts.map +1 -1
  180. package/dist/runtime/for-signals.js +1 -1
  181. package/dist/runtime/for-signals.js.map +1 -1
  182. package/dist/runtime/for-types.d.ts +9 -0
  183. package/dist/runtime/for-types.d.ts.map +1 -0
  184. package/dist/runtime/index.d.ts +24 -0
  185. package/dist/runtime/index.js +31 -0
  186. package/dist/runtime/perf-metrics.d.ts +26 -0
  187. package/dist/runtime/perf-metrics.d.ts.map +1 -0
  188. package/dist/runtime/portal.d.ts +22 -0
  189. package/dist/runtime/portal.d.ts.map +1 -0
  190. package/dist/runtime/portal.js +213 -0
  191. package/dist/runtime/portal.js.map +1 -0
  192. package/dist/runtime/resource-cell.js +1 -1
  193. package/dist/runtime/resource-cell.js.map +1 -1
  194. package/dist/runtime/resource-operation.js +1 -1
  195. package/dist/runtime/runtime.d.ts +1 -1
  196. package/dist/runtime/scheduler.js +2 -2
  197. package/dist/runtime/scheduler.js.map +1 -1
  198. package/dist/runtime/selector-store.js +24 -0
  199. package/dist/runtime/selector-store.js.map +1 -0
  200. package/dist/runtime/selector.d.ts.map +1 -1
  201. package/dist/runtime/selector.js +3 -18
  202. package/dist/runtime/selector.js.map +1 -1
  203. package/dist/ssg/create-static-gen.js +1 -0
  204. package/dist/ssg/create-static-gen.js.map +1 -1
  205. package/dist/ssg/static-routes.js +1 -0
  206. package/dist/ssg/static-routes.js.map +1 -1
  207. package/dist/ssr/boundaries.js +2 -2
  208. package/dist/ssr/boundaries.js.map +1 -1
  209. package/dist/ssr/component-runtime.js +3 -3
  210. package/dist/ssr/component-runtime.js.map +1 -1
  211. package/dist/ssr/render-resolved.js +1 -1
  212. package/dist/ssr/render-sync.js +1 -1
  213. package/dist/ssr/render-sync.js.map +1 -1
  214. package/dist/ssr/route-policy-resolution.js +2 -1
  215. package/dist/ssr/route-policy-resolution.js.map +1 -1
  216. package/dist/ssr/route-render.js +2 -1
  217. package/dist/ssr/route-render.js.map +1 -1
  218. package/dist/testing/index.d.ts.map +1 -1
  219. package/dist/testing/index.js +3 -2
  220. package/dist/testing/index.js.map +1 -1
  221. package/package.json +4 -4
  222. package/dist/dev/invariant.js +0 -29
  223. package/dist/dev/invariant.js.map +0 -1
  224. package/dist/dev/logger.js.map +0 -1
  225. package/dist/foundations/structures/portal.d.ts.map +0 -1
  226. package/dist/foundations/structures/portal.js.map +0 -1
  227. package/dist/runtime/component-contracts.js +0 -5
@@ -1 +1 @@
1
- {"version":3,"file":"error-boundary.js","names":[],"sources":["../../src/components/error-boundary.tsx"],"sourcesContent":["import type { Props } from '../common/props';\nimport { ELEMENT_TYPE, type JSXElement } from '../common/jsx';\nimport type { VNode } from '../common/vnode';\nimport { __ERROR_BOUNDARY__ } from '../common/vnode';\nimport {\n getCurrentComponentInstance,\n type ComponentInstance,\n} from '../runtime/component';\nimport { logger } from '../dev/logger';\nimport { isDevelopmentEnvironment } from '../common/env';\n\ntype ErrorBoundaryContent = VNode | readonly VNode[];\ntype ErrorBoundaryFallbackValue = ErrorBoundaryContent | Node;\n\nexport type ErrorBoundaryFallbackRender = (\n error: unknown,\n reset: () => void\n) => ErrorBoundaryFallbackValue;\n\nexport interface ErrorBoundaryProps extends Props {\n children?: ErrorBoundaryContent;\n fallback?: ErrorBoundaryFallbackValue | ErrorBoundaryFallbackRender;\n onError?: (error: unknown) => void;\n resetKey?: unknown;\n}\n\ntype ErrorBoundaryState = NonNullable<ComponentInstance['errorBoundaryState']>;\n\ntype ErrorBoundaryVNode = JSXElement & {\n __instance?: ComponentInstance;\n};\n\nfunction getBoundaryMessage(error: unknown): string {\n if (error instanceof Error) {\n return error.message || error.name || 'Unknown error';\n }\n\n if (typeof error === 'string') {\n return error;\n }\n\n try {\n return JSON.stringify(error);\n } catch {\n return String(error);\n }\n}\n\nfunction ensureBoundaryState(\n instance: ComponentInstance,\n resetKey: unknown\n): ErrorBoundaryState {\n const boundaryState =\n instance.errorBoundaryState ??\n (instance.errorBoundaryState = {\n error: null,\n resetKey,\n notified: false,\n });\n\n if (!Object.is(boundaryState.resetKey, resetKey)) {\n boundaryState.error = null;\n boundaryState.resetKey = resetKey;\n boundaryState.notified = false;\n }\n\n return boundaryState;\n}\n\nfunction createBoundaryVNode(\n instance: ComponentInstance,\n props: ErrorBoundaryProps\n): ErrorBoundaryVNode {\n const key =\n typeof props.key === 'symbol'\n ? null\n : ((props.key ?? null) as string | number | null);\n\n return {\n $$typeof: ELEMENT_TYPE,\n type: __ERROR_BOUNDARY__,\n props: {\n children: props.children,\n fallback: props.fallback,\n onError: props.onError,\n resetKey: props.resetKey,\n },\n key,\n __instance: instance,\n };\n}\n\nexport function ErrorBoundary(props: ErrorBoundaryProps): JSXElement {\n const instance = getCurrentComponentInstance();\n if (!instance) {\n throw new Error(\n '[Askr] ErrorBoundary() can only be used during component render execution.'\n );\n }\n\n ensureBoundaryState(instance, props.resetKey);\n return createBoundaryVNode(instance, props);\n}\n\nexport function isErrorBoundaryVNode(\n value: unknown\n): value is ErrorBoundaryVNode {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as ErrorBoundaryVNode).type === __ERROR_BOUNDARY__\n );\n}\n\nexport function resolveErrorBoundaryState(\n vnode: ErrorBoundaryVNode\n): ErrorBoundaryState | null {\n return vnode.__instance?.errorBoundaryState ?? null;\n}\n\nexport function resolveErrorBoundaryFallback(\n fallback: ErrorBoundaryProps['fallback'],\n error: unknown,\n reset: () => void\n): ErrorBoundaryFallbackValue {\n if (typeof fallback === 'function') {\n return fallback(error, reset);\n }\n\n if (fallback !== undefined) {\n return fallback;\n }\n\n const message = getBoundaryMessage(error);\n const wrapper = document.createElement('div');\n wrapper.setAttribute('role', 'alert');\n wrapper.setAttribute('data-askr-error-boundary', 'true');\n wrapper.style.boxSizing = 'border-box';\n wrapper.style.padding = '1rem';\n wrapper.style.border = '1px solid currentColor';\n wrapper.style.borderRadius = '0.75rem';\n wrapper.style.display = 'grid';\n wrapper.style.gap = '0.75rem';\n wrapper.style.maxWidth = '100%';\n\n const title = document.createElement('strong');\n title.textContent = 'Something went wrong while rendering this view.';\n\n const summary = document.createElement('p');\n summary.textContent =\n 'The app recovered into a visible fallback so the error is not hidden in the console.';\n summary.style.margin = '0';\n\n const details = document.createElement('details');\n details.open = isDevelopmentEnvironment();\n\n const detailsSummary = document.createElement('summary');\n detailsSummary.textContent = 'Error details';\n\n const pre = document.createElement('pre');\n pre.textContent = message;\n pre.style.margin = '0';\n pre.style.whiteSpace = 'pre-wrap';\n pre.style.wordBreak = 'break-word';\n\n const button = document.createElement('button');\n button.type = 'button';\n button.textContent = 'Try again';\n button.addEventListener('click', () => reset());\n\n details.append(detailsSummary, pre);\n wrapper.append(title, summary, details, button);\n return wrapper;\n}\n\nexport function createBoundaryReset(instance: ComponentInstance): () => void {\n return () => {\n const boundaryState = instance.errorBoundaryState;\n if (!boundaryState) {\n return;\n }\n boundaryState.error = null;\n boundaryState.notified = false;\n queueMicrotask(() => {\n instance._enqueueRun?.();\n });\n };\n}\n\nexport function reportBoundaryError(\n instance: ComponentInstance,\n error: unknown,\n onError?: (error: unknown) => void\n): void {\n const boundaryState = instance.errorBoundaryState;\n if (\n boundaryState &&\n Object.is(boundaryState.error, error) &&\n boundaryState.notified\n ) {\n return;\n }\n\n if (boundaryState) {\n boundaryState.error = error;\n boundaryState.notified = true;\n }\n\n try {\n onError?.(error);\n } catch (hookError) {\n logger.error('[Askr] ErrorBoundary onError handler threw:', hookError);\n }\n\n logger.error('[Askr] ErrorBoundary caught render error:', error);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"error-boundary.js","names":[],"sources":["../../src/components/error-boundary.tsx"],"sourcesContent":["import type {\n ErrorBoundaryFallbackRender,\n ErrorBoundaryProps,\n} from '../common/error-boundary';\nimport { ELEMENT_TYPE, type JSXElement } from '../common/jsx';\nimport { __ERROR_BOUNDARY__ } from '../common/vnode';\nimport {\n getCurrentComponentInstance,\n type ComponentInstance,\n} from '../runtime';\n\nexport type { ErrorBoundaryFallbackRender, ErrorBoundaryProps };\n\ntype ErrorBoundaryState = NonNullable<ComponentInstance['errorBoundaryState']>;\n\ntype ErrorBoundaryVNode = JSXElement & {\n __instance?: ComponentInstance;\n};\n\nfunction ensureBoundaryState(\n instance: ComponentInstance,\n resetKey: unknown\n): ErrorBoundaryState {\n const boundaryState =\n instance.errorBoundaryState ??\n (instance.errorBoundaryState = {\n error: null,\n resetKey,\n notified: false,\n });\n\n if (!Object.is(boundaryState.resetKey, resetKey)) {\n boundaryState.error = null;\n boundaryState.resetKey = resetKey;\n boundaryState.notified = false;\n }\n\n return boundaryState;\n}\n\nfunction createBoundaryVNode(\n instance: ComponentInstance,\n props: ErrorBoundaryProps\n): ErrorBoundaryVNode {\n const key =\n typeof props.key === 'symbol'\n ? null\n : ((props.key ?? null) as string | number | null);\n\n return {\n $$typeof: ELEMENT_TYPE,\n type: __ERROR_BOUNDARY__,\n props: {\n children: props.children,\n fallback: props.fallback,\n onError: props.onError,\n resetKey: props.resetKey,\n },\n key,\n __instance: instance,\n };\n}\n\nexport function ErrorBoundary(props: ErrorBoundaryProps): JSXElement {\n const instance = getCurrentComponentInstance();\n if (!instance) {\n throw new Error(\n '[Askr] ErrorBoundary() can only be used during component render execution.'\n );\n }\n\n ensureBoundaryState(instance, props.resetKey);\n return createBoundaryVNode(instance, props);\n}\n\nexport function isErrorBoundaryVNode(\n value: unknown\n): value is ErrorBoundaryVNode {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as ErrorBoundaryVNode).type === __ERROR_BOUNDARY__\n );\n}\n\nexport function resolveErrorBoundaryState(\n vnode: ErrorBoundaryVNode\n): ErrorBoundaryState | null {\n return vnode.__instance?.errorBoundaryState ?? null;\n}\n"],"mappings":";;;;;AAmBA,SAAS,oBACP,UACA,UACoB;CACpB,MAAM,gBACJ,SAAS,uBACR,SAAS,qBAAqB;EAC7B,OAAO;EACP;EACA,UAAU;CACZ;CAEF,IAAI,CAAC,OAAO,GAAG,cAAc,UAAU,QAAQ,GAAG;EAChD,cAAc,QAAQ;EACtB,cAAc,WAAW;EACzB,cAAc,WAAW;CAC3B;CAEA,OAAO;AACT;AAEA,SAAS,oBACP,UACA,OACoB;CACpB,MAAM,MACJ,OAAO,MAAM,QAAQ,WACjB,OACE,MAAM,OAAO;CAErB,OAAO;EACL,UAAU;EACV,MAAM;EACN,OAAO;GACL,UAAU,MAAM;GAChB,UAAU,MAAM;GAChB,SAAS,MAAM;GACf,UAAU,MAAM;EAClB;EACA;EACA,YAAY;CACd;AACF;AAEA,SAAgB,cAAc,OAAuC;CACnE,MAAM,WAAW,4BAA4B;CAC7C,IAAI,CAAC,UACH,MAAM,IAAI,MACR,4EACF;CAGF,oBAAoB,UAAU,MAAM,QAAQ;CAC5C,OAAO,oBAAoB,UAAU,KAAK;AAC5C"}
@@ -1,2 +1,3 @@
1
- import { ErrorBoundary, ErrorBoundaryFallbackRender, ErrorBoundaryProps } from "./error-boundary.js";
1
+ import { ErrorBoundaryFallbackRender, ErrorBoundaryProps } from "../common/error-boundary.js";
2
+ import { ErrorBoundary } from "./error-boundary.js";
2
3
  export { ErrorBoundary, type ErrorBoundaryFallbackRender, type ErrorBoundaryProps };
@@ -3,7 +3,9 @@ import { jsx } from "../jsx-runtime.js";
3
3
  import "../jsx-runtime2.js";
4
4
  import { navigate } from "../router/navigate.js";
5
5
  import { mergeProps } from "../foundations/utilities/merge-props.js";
6
+ import "../foundations/utilities/index.js";
6
7
  import { applyInteractionPolicy } from "../foundations/interactions/interaction-policy.js";
8
+ import "../foundations/interactions/index.js";
7
9
  //#region src/components/link.tsx
8
10
  /**
9
11
  * Link component for client-side navigation
@@ -1 +1 @@
1
- {"version":3,"file":"link.js","names":[],"sources":["../../src/components/link.tsx"],"sourcesContent":["/**\n * Link component for client-side navigation\n */\n\nimport '../jsx/types';\nimport type { JSXElement } from '../common/jsx';\nimport type { AnchorIntrinsicProps, Props } from '../common/props';\nimport type { RenderableChild } from '../common/vnode';\nimport { navigate } from '../router/navigate';\nimport { applyInteractionPolicy } from '../foundations/interactions/interaction-policy';\nimport { mergeProps } from '../foundations/utilities/merge-props';\n\nexport type LinkProps = Omit<\n Props,\n | 'children'\n | 'href'\n | 'class'\n | 'rel'\n | 'target'\n | 'aria-current'\n | 'aria-label'\n> & {\n href: string;\n class?: string;\n children?: RenderableChild;\n /**\n * Optional rel attribute for link relationships.\n * Common values: \"noopener\", \"noreferrer\", \"nofollow\"\n */\n rel?: string;\n /**\n * Optional target attribute.\n * Use \"_blank\" for new tab/window.\n */\n target?: string;\n /**\n * Optional aria-current attribute for indicating current page/location.\n * Use \"page\" for the current page in navigation.\n */\n 'aria-current'?:\n | 'page'\n | 'step'\n | 'location'\n | 'date'\n | 'time'\n | 'true'\n | 'false';\n /**\n * Optional aria-label for accessibility when link text isn't descriptive enough.\n */\n 'aria-label'?: string;\n};\n\nfunction isSameOriginNavigableHref(href: string): boolean {\n if (typeof window === 'undefined') {\n return true;\n }\n\n try {\n const target = new URL(href, window.location.href);\n return (\n target.origin === window.location.origin &&\n (target.protocol === 'http:' || target.protocol === 'https:')\n );\n } catch {\n return false;\n }\n}\n\n/**\n * Link component that prevents default navigation and uses navigate()\n * Provides declarative way to navigate between routes\n *\n * Accessibility features:\n * - Proper semantic <a> element (not a button)\n * - Supports aria-current for indicating active page\n * - Supports aria-label for descriptive labels\n * - Keyboard accessible (Enter key handled by native <a> element)\n *\n * Respects native browser behaviors:\n * - Middle-click (opens in new tab)\n * - Ctrl/Cmd+click (opens in new tab)\n * - Shift+click (opens in new window)\n * - Alt+click (downloads link)\n * - Right-click context menu\n *\n * Best practices:\n * - Use target=\"_blank\" with rel=\"noopener noreferrer\" for external links\n * - Use aria-current=\"page\" for the current page in navigation\n * - Provide descriptive link text or aria-label\n *\n * Uses applyInteractionPolicy to enforce pit-of-success principles:\n * - Interaction behavior centralized in foundations\n * - Keyboard handling automatic\n * - Composable via mergeProps\n */\nexport function Link({\n href,\n class: className,\n children,\n rel,\n target,\n 'aria-current': ariaCurrent,\n 'aria-label': ariaLabel,\n ...rest\n}: LinkProps): JSXElement {\n const interaction = applyInteractionPolicy({\n isNative: true,\n disabled: false,\n onPress: (e: Event) => {\n const event = e as MouseEvent;\n\n // Only intercept left-click without modifiers\n // Default button to 0 if undefined (for mock events in tests)\n const button = event.button ?? 0;\n if (\n button !== 0 || // not left-click\n event.ctrlKey || // Ctrl/Cmd+click\n event.metaKey || // Cmd on Mac\n event.shiftKey || // Shift+click\n event.altKey // Alt+click\n ) {\n return; // Let browser handle it (new tab, etc.)\n }\n\n // Don't intercept external links or explicit target.\n if (target || !isSameOriginNavigableHref(href)) {\n return; // Let browser handle it\n }\n\n event.preventDefault();\n navigate(href);\n },\n });\n\n const props = mergeProps(rest, {\n ...interaction,\n href,\n class: className,\n rel,\n target,\n 'aria-current': ariaCurrent,\n 'aria-label': ariaLabel,\n });\n\n return <a {...(props as AnchorIntrinsicProps)}>{children}</a>;\n}\n"],"mappings":";;;;;;;;;;AAqDA,SAAS,0BAA0B,MAAuB;CACxD,IAAI,OAAO,WAAW,aACpB,OAAO;CAGT,IAAI;EACF,MAAM,SAAS,IAAI,IAAI,MAAM,OAAO,SAAS,IAAI;EACjD,OACE,OAAO,WAAW,OAAO,SAAS,WACjC,OAAO,aAAa,WAAW,OAAO,aAAa;CAExD,QAAQ;EACN,OAAO;CACT;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,SAAgB,KAAK,EACnB,MACA,OAAO,WACP,UACA,KACA,QACA,gBAAgB,aAChB,cAAc,WACd,GAAG,QACqB;CAwCxB,OAAO,oBAAC,KAAD;EAAG,GAVI,WAAW,MAAM;GAC7B,GA9BkB,uBAAuB;IACzC,UAAU;IACV,UAAU;IACV,UAAU,MAAa;KACrB,MAAM,QAAQ;KAKd,KADe,MAAM,UAAU,OAElB,KACX,MAAM,WACN,MAAM,WACN,MAAM,YACN,MAAM,QAEN;KAIF,IAAI,UAAU,CAAC,0BAA0B,IAAI,GAC3C;KAGF,MAAM,eAAe;KACrB,SAAS,IAAI;IACf;GACF,CAGK;GACH;GACA,OAAO;GACP;GACA;GACA,gBAAgB;GAChB,cAAc;EAChB,CAEe;EAAiC;CAAY,CAAA;AAC9D"}
1
+ {"version":3,"file":"link.js","names":[],"sources":["../../src/components/link.tsx"],"sourcesContent":["/**\n * Link component for client-side navigation\n */\n\nimport '../jsx/types';\nimport type { JSXElement } from '../common/jsx';\nimport type { AnchorIntrinsicProps, Props } from '../common/props';\nimport type { RenderableChild } from '../common/vnode';\nimport { navigate } from '../router/navigate';\nimport { applyInteractionPolicy } from '../foundations/interactions';\nimport { mergeProps } from '../foundations/utilities';\n\nexport type LinkProps = Omit<\n Props,\n | 'children'\n | 'href'\n | 'class'\n | 'rel'\n | 'target'\n | 'aria-current'\n | 'aria-label'\n> & {\n href: string;\n class?: string;\n children?: RenderableChild;\n /**\n * Optional rel attribute for link relationships.\n * Common values: \"noopener\", \"noreferrer\", \"nofollow\"\n */\n rel?: string;\n /**\n * Optional target attribute.\n * Use \"_blank\" for new tab/window.\n */\n target?: string;\n /**\n * Optional aria-current attribute for indicating current page/location.\n * Use \"page\" for the current page in navigation.\n */\n 'aria-current'?:\n | 'page'\n | 'step'\n | 'location'\n | 'date'\n | 'time'\n | 'true'\n | 'false';\n /**\n * Optional aria-label for accessibility when link text isn't descriptive enough.\n */\n 'aria-label'?: string;\n};\n\nfunction isSameOriginNavigableHref(href: string): boolean {\n if (typeof window === 'undefined') {\n return true;\n }\n\n try {\n const target = new URL(href, window.location.href);\n return (\n target.origin === window.location.origin &&\n (target.protocol === 'http:' || target.protocol === 'https:')\n );\n } catch {\n return false;\n }\n}\n\n/**\n * Link component that prevents default navigation and uses navigate()\n * Provides declarative way to navigate between routes\n *\n * Accessibility features:\n * - Proper semantic <a> element (not a button)\n * - Supports aria-current for indicating active page\n * - Supports aria-label for descriptive labels\n * - Keyboard accessible (Enter key handled by native <a> element)\n *\n * Respects native browser behaviors:\n * - Middle-click (opens in new tab)\n * - Ctrl/Cmd+click (opens in new tab)\n * - Shift+click (opens in new window)\n * - Alt+click (downloads link)\n * - Right-click context menu\n *\n * Best practices:\n * - Use target=\"_blank\" with rel=\"noopener noreferrer\" for external links\n * - Use aria-current=\"page\" for the current page in navigation\n * - Provide descriptive link text or aria-label\n *\n * Uses applyInteractionPolicy to enforce pit-of-success principles:\n * - Interaction behavior centralized in foundations\n * - Keyboard handling automatic\n * - Composable via mergeProps\n */\nexport function Link({\n href,\n class: className,\n children,\n rel,\n target,\n 'aria-current': ariaCurrent,\n 'aria-label': ariaLabel,\n ...rest\n}: LinkProps): JSXElement {\n const interaction = applyInteractionPolicy({\n isNative: true,\n disabled: false,\n onPress: (e: Event) => {\n const event = e as MouseEvent;\n\n // Only intercept left-click without modifiers\n // Default button to 0 if undefined (for mock events in tests)\n const button = event.button ?? 0;\n if (\n button !== 0 || // not left-click\n event.ctrlKey || // Ctrl/Cmd+click\n event.metaKey || // Cmd on Mac\n event.shiftKey || // Shift+click\n event.altKey // Alt+click\n ) {\n return; // Let browser handle it (new tab, etc.)\n }\n\n // Don't intercept external links or explicit target.\n if (target || !isSameOriginNavigableHref(href)) {\n return; // Let browser handle it\n }\n\n event.preventDefault();\n navigate(href);\n },\n });\n\n const props = mergeProps(rest, {\n ...interaction,\n href,\n class: className,\n rel,\n target,\n 'aria-current': ariaCurrent,\n 'aria-label': ariaLabel,\n });\n\n return <a {...(props as AnchorIntrinsicProps)}>{children}</a>;\n}\n"],"mappings":";;;;;;;;;;;;AAqDA,SAAS,0BAA0B,MAAuB;CACxD,IAAI,OAAO,WAAW,aACpB,OAAO;CAGT,IAAI;EACF,MAAM,SAAS,IAAI,IAAI,MAAM,OAAO,SAAS,IAAI;EACjD,OACE,OAAO,WAAW,OAAO,SAAS,WACjC,OAAO,aAAa,WAAW,OAAO,aAAa;CAExD,QAAQ;EACN,OAAO;CACT;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,SAAgB,KAAK,EACnB,MACA,OAAO,WACP,UACA,KACA,QACA,gBAAgB,aAChB,cAAc,WACd,GAAG,QACqB;CAwCxB,OAAO,oBAAC,KAAD;EAAG,GAVI,WAAW,MAAM;GAC7B,GA9BkB,uBAAuB;IACzC,UAAU;IACV,UAAU;IACV,UAAU,MAAa;KACrB,MAAM,QAAQ;KAKd,KADe,MAAM,UAAU,OAElB,KACX,MAAM,WACN,MAAM,WACN,MAAM,YACN,MAAM,QAEN;KAIF,IAAI,UAAU,CAAC,0BAA0B,IAAI,GAC3C;KAGF,MAAM,eAAe;KACrB,SAAS,IAAI;IACf;GACF,CAGK;GACH;GACA,OAAO;GACP;GACA;GACA,gBAAgB;GAChB,cAAc;EAChB,CAEe;EAAiC;CAAY,CAAA;AAC9D"}
@@ -1 +1 @@
1
- {"version":3,"file":"case.d.ts","names":[],"sources":["../../src/control/case.ts"],"mappings":";;;;KAeK,UAAA,GAAa,aAAA,UAAuB,aAAa;AAAA,KAE1C,UAAA;EACV,GAAA;EACA,IAAA;EACA,QAAA,EAAU,UAAU;AAAA;AAAA,KAGV,SAAA;EACV,QAAA,GAAW,aAAa;EACxB,QAAA;AAAA;AAAA,iBAmBc,KAAA,CAAM,MAAkB,EAAV,UAAU;AAAA,cAyF3B,IAAA,GAEP,KAAA,EAAO,SAAA,KAAc,UAAU"}
1
+ {"version":3,"file":"case.d.ts","names":[],"sources":["../../src/control/case.ts"],"mappings":";;;;KAWK,UAAA,GAAa,aAAA,UAAuB,aAAa;AAAA,KAE1C,UAAA;EACV,GAAA;EACA,IAAA;EACA,QAAA,EAAU,UAAU;AAAA;AAAA,KAGV,SAAA;EACV,QAAA,GAAW,aAAa;EACxB,QAAA;AAAA;AAAA,iBAmBc,KAAA,CAAM,MAAkB,EAAV,UAAU;AAAA,cAyF3B,IAAA,GAEP,KAAA,EAAO,SAAA,KAAc,UAAU"}
@@ -2,6 +2,7 @@ import { __CONTROL_BOUNDARY__, markEagerControlPrimitive } from "../common/contr
2
2
  import { isDevelopmentEnvironment } from "../common/env.js";
3
3
  import { createCaseState } from "../runtime/control.js";
4
4
  import { state } from "../runtime/state.js";
5
+ import "../runtime/index.js";
5
6
  import { normalizeBoundaryChild } from "./shared.js";
6
7
  //#region src/control/case.ts
7
8
  function flattenChildren(children) {
@@ -1 +1 @@
1
- {"version":3,"file":"case.js","names":[],"sources":["../../src/control/case.ts"],"sourcesContent":["import {\n __CONTROL_BOUNDARY__,\n markEagerControlPrimitive,\n} from '../common/control';\nimport type { JSXElement } from '../common/jsx';\nimport type { VNode } from '../common/vnode';\nimport { isDevelopmentEnvironment } from '../common/env';\nimport {\n createCaseState,\n type CaseState,\n type MatchBranch,\n} from '../runtime/control';\nimport { state } from '../runtime/state';\nimport { type BoundaryChild, normalizeBoundaryChild } from './shared';\n\ntype MatchChild = BoundaryChild | (() => BoundaryChild);\n\nexport type MatchProps = {\n key?: string | number | null;\n when: unknown;\n children: MatchChild;\n};\n\nexport type CaseProps = {\n fallback?: BoundaryChild;\n children?: unknown;\n};\n\nfunction flattenChildren(children: unknown): unknown[] {\n if (!Array.isArray(children)) {\n return children == null || children === false ? [] : [children];\n }\n\n const result: unknown[] = [];\n for (const child of children) {\n if (Array.isArray(child)) {\n result.push(...flattenChildren(child));\n continue;\n }\n result.push(child);\n }\n return result;\n}\n\nexport function Match(_props: MatchProps): null {\n if (isDevelopmentEnvironment()) {\n throw new Error(\n '[askr] <Match> may only be used as a direct child of <Case>.'\n );\n }\n return null;\n}\n\nfunction createCaseFallbackRenderer(\n fallback: BoundaryChild | undefined\n): (() => VNode) | null {\n const normalizedFallback = normalizeBoundaryChild(fallback);\n if (normalizedFallback == null || normalizedFallback === false) {\n return null;\n }\n return () => normalizedFallback;\n}\n\nfunction createMatchBranchKey(\n key: string | number | null | undefined,\n index: number\n): string | number {\n if (key == null) {\n return index;\n }\n return `match:${index}:${typeof key}:${String(key)}`;\n}\n\nfunction readMatchBranches(children: unknown): MatchBranch[] {\n const branches: MatchBranch[] = [];\n const flatChildren = flattenChildren(children);\n\n for (let index = 0; index < flatChildren.length; index += 1) {\n const child = flatChildren[index];\n if (child == null || child === false) {\n continue;\n }\n\n if (\n typeof child === 'object' &&\n child !== null &&\n 'type' in child &&\n (child as JSXElement).type === Match\n ) {\n const element = child as JSXElement;\n const props = (element.props ?? {}) as MatchProps;\n const key = createMatchBranchKey(element.key, index);\n const render =\n typeof props.children === 'function'\n ? () =>\n normalizeBoundaryChild(\n (props.children as () => BoundaryChild)()\n ) as VNode\n : () => normalizeBoundaryChild(props.children) as VNode;\n branches.push({\n key,\n render,\n when: props.when,\n });\n continue;\n }\n\n if (isDevelopmentEnvironment()) {\n throw new Error('[askr] <Case> only accepts <Match> children.');\n }\n }\n\n return branches;\n}\n\nfunction CasePrimitive(props: CaseProps): JSXElement {\n const matches = readMatchBranches(props.children);\n const fallback = createCaseFallbackRenderer(props.fallback);\n\n const caseStateContainer = state<CaseState>(\n createCaseState(matches, fallback)\n );\n const caseState = caseStateContainer();\n\n caseState.matches = matches;\n caseState.fallback = fallback;\n\n return {\n type: __CONTROL_BOUNDARY__,\n _controlState: caseState,\n } as unknown as JSXElement;\n}\n\nexport const Case = markEagerControlPrimitive(\n CasePrimitive as (props: CaseProps) => JSXElement\n) as (props: CaseProps) => JSXElement;\n"],"mappings":";;;;;;AA4BA,SAAS,gBAAgB,UAA8B;CACrD,IAAI,CAAC,MAAM,QAAQ,QAAQ,GACzB,OAAO,YAAY,QAAQ,aAAa,QAAQ,CAAC,IAAI,CAAC,QAAQ;CAGhE,MAAM,SAAoB,CAAC;CAC3B,KAAK,MAAM,SAAS,UAAU;EAC5B,IAAI,MAAM,QAAQ,KAAK,GAAG;GACxB,OAAO,KAAK,GAAG,gBAAgB,KAAK,CAAC;GACrC;EACF;EACA,OAAO,KAAK,KAAK;CACnB;CACA,OAAO;AACT;AAEA,SAAgB,MAAM,QAA0B;CAC9C,IAAI,yBAAyB,GAC3B,MAAM,IAAI,MACR,8DACF;CAEF,OAAO;AACT;AAEA,SAAS,2BACP,UACsB;CACtB,MAAM,qBAAqB,uBAAuB,QAAQ;CAC1D,IAAI,sBAAsB,QAAQ,uBAAuB,OACvD,OAAO;CAET,aAAa;AACf;AAEA,SAAS,qBACP,KACA,OACiB;CACjB,IAAI,OAAO,MACT,OAAO;CAET,OAAO,SAAS,MAAM,GAAG,OAAO,IAAI,GAAG,OAAO,GAAG;AACnD;AAEA,SAAS,kBAAkB,UAAkC;CAC3D,MAAM,WAA0B,CAAC;CACjC,MAAM,eAAe,gBAAgB,QAAQ;CAE7C,KAAK,IAAI,QAAQ,GAAG,QAAQ,aAAa,QAAQ,SAAS,GAAG;EAC3D,MAAM,QAAQ,aAAa;EAC3B,IAAI,SAAS,QAAQ,UAAU,OAC7B;EAGF,IACE,OAAO,UAAU,YACjB,UAAU,QACV,UAAU,SACT,MAAqB,SAAS,OAC/B;GACA,MAAM,UAAU;GAChB,MAAM,QAAS,QAAQ,SAAS,CAAC;GACjC,MAAM,MAAM,qBAAqB,QAAQ,KAAK,KAAK;GACnD,MAAM,SACJ,OAAO,MAAM,aAAa,mBAEpB,uBACG,MAAM,SAAiC,CAC1C,UACI,uBAAuB,MAAM,QAAQ;GACjD,SAAS,KAAK;IACZ;IACA;IACA,MAAM,MAAM;GACd,CAAC;GACD;EACF;EAEA,IAAI,yBAAyB,GAC3B,MAAM,IAAI,MAAM,8CAA8C;CAElE;CAEA,OAAO;AACT;AAEA,SAAS,cAAc,OAA8B;CACnD,MAAM,UAAU,kBAAkB,MAAM,QAAQ;CAChD,MAAM,WAAW,2BAA2B,MAAM,QAAQ;CAK1D,MAAM,YAHqB,MACzB,gBAAgB,SAAS,QAAQ,CAEjB,CAAA,CAAmB;CAErC,UAAU,UAAU;CACpB,UAAU,WAAW;CAErB,OAAO;EACL,MAAM;EACN,eAAe;CACjB;AACF;AAEA,MAAa,OAAO,0BAClB,aACF"}
1
+ {"version":3,"file":"case.js","names":[],"sources":["../../src/control/case.ts"],"sourcesContent":["import {\n __CONTROL_BOUNDARY__,\n markEagerControlPrimitive,\n} from '../common/control';\nimport type { JSXElement } from '../common/jsx';\nimport type { VNode } from '../common/vnode';\nimport { isDevelopmentEnvironment } from '../common/env';\nimport { createCaseState, type CaseState, type MatchBranch } from '../runtime';\nimport { state } from '../runtime';\nimport { type BoundaryChild, normalizeBoundaryChild } from './shared';\n\ntype MatchChild = BoundaryChild | (() => BoundaryChild);\n\nexport type MatchProps = {\n key?: string | number | null;\n when: unknown;\n children: MatchChild;\n};\n\nexport type CaseProps = {\n fallback?: BoundaryChild;\n children?: unknown;\n};\n\nfunction flattenChildren(children: unknown): unknown[] {\n if (!Array.isArray(children)) {\n return children == null || children === false ? [] : [children];\n }\n\n const result: unknown[] = [];\n for (const child of children) {\n if (Array.isArray(child)) {\n result.push(...flattenChildren(child));\n continue;\n }\n result.push(child);\n }\n return result;\n}\n\nexport function Match(_props: MatchProps): null {\n if (isDevelopmentEnvironment()) {\n throw new Error(\n '[askr] <Match> may only be used as a direct child of <Case>.'\n );\n }\n return null;\n}\n\nfunction createCaseFallbackRenderer(\n fallback: BoundaryChild | undefined\n): (() => VNode) | null {\n const normalizedFallback = normalizeBoundaryChild(fallback);\n if (normalizedFallback == null || normalizedFallback === false) {\n return null;\n }\n return () => normalizedFallback;\n}\n\nfunction createMatchBranchKey(\n key: string | number | null | undefined,\n index: number\n): string | number {\n if (key == null) {\n return index;\n }\n return `match:${index}:${typeof key}:${String(key)}`;\n}\n\nfunction readMatchBranches(children: unknown): MatchBranch[] {\n const branches: MatchBranch[] = [];\n const flatChildren = flattenChildren(children);\n\n for (let index = 0; index < flatChildren.length; index += 1) {\n const child = flatChildren[index];\n if (child == null || child === false) {\n continue;\n }\n\n if (\n typeof child === 'object' &&\n child !== null &&\n 'type' in child &&\n (child as JSXElement).type === Match\n ) {\n const element = child as JSXElement;\n const props = (element.props ?? {}) as MatchProps;\n const key = createMatchBranchKey(element.key, index);\n const render =\n typeof props.children === 'function'\n ? () =>\n normalizeBoundaryChild(\n (props.children as () => BoundaryChild)()\n ) as VNode\n : () => normalizeBoundaryChild(props.children) as VNode;\n branches.push({\n key,\n render,\n when: props.when,\n });\n continue;\n }\n\n if (isDevelopmentEnvironment()) {\n throw new Error('[askr] <Case> only accepts <Match> children.');\n }\n }\n\n return branches;\n}\n\nfunction CasePrimitive(props: CaseProps): JSXElement {\n const matches = readMatchBranches(props.children);\n const fallback = createCaseFallbackRenderer(props.fallback);\n\n const caseStateContainer = state<CaseState>(\n createCaseState(matches, fallback)\n );\n const caseState = caseStateContainer();\n\n caseState.matches = matches;\n caseState.fallback = fallback;\n\n return {\n type: __CONTROL_BOUNDARY__,\n _controlState: caseState,\n } as unknown as JSXElement;\n}\n\nexport const Case = markEagerControlPrimitive(\n CasePrimitive as (props: CaseProps) => JSXElement\n) as (props: CaseProps) => JSXElement;\n"],"mappings":";;;;;;;AAwBA,SAAS,gBAAgB,UAA8B;CACrD,IAAI,CAAC,MAAM,QAAQ,QAAQ,GACzB,OAAO,YAAY,QAAQ,aAAa,QAAQ,CAAC,IAAI,CAAC,QAAQ;CAGhE,MAAM,SAAoB,CAAC;CAC3B,KAAK,MAAM,SAAS,UAAU;EAC5B,IAAI,MAAM,QAAQ,KAAK,GAAG;GACxB,OAAO,KAAK,GAAG,gBAAgB,KAAK,CAAC;GACrC;EACF;EACA,OAAO,KAAK,KAAK;CACnB;CACA,OAAO;AACT;AAEA,SAAgB,MAAM,QAA0B;CAC9C,IAAI,yBAAyB,GAC3B,MAAM,IAAI,MACR,8DACF;CAEF,OAAO;AACT;AAEA,SAAS,2BACP,UACsB;CACtB,MAAM,qBAAqB,uBAAuB,QAAQ;CAC1D,IAAI,sBAAsB,QAAQ,uBAAuB,OACvD,OAAO;CAET,aAAa;AACf;AAEA,SAAS,qBACP,KACA,OACiB;CACjB,IAAI,OAAO,MACT,OAAO;CAET,OAAO,SAAS,MAAM,GAAG,OAAO,IAAI,GAAG,OAAO,GAAG;AACnD;AAEA,SAAS,kBAAkB,UAAkC;CAC3D,MAAM,WAA0B,CAAC;CACjC,MAAM,eAAe,gBAAgB,QAAQ;CAE7C,KAAK,IAAI,QAAQ,GAAG,QAAQ,aAAa,QAAQ,SAAS,GAAG;EAC3D,MAAM,QAAQ,aAAa;EAC3B,IAAI,SAAS,QAAQ,UAAU,OAC7B;EAGF,IACE,OAAO,UAAU,YACjB,UAAU,QACV,UAAU,SACT,MAAqB,SAAS,OAC/B;GACA,MAAM,UAAU;GAChB,MAAM,QAAS,QAAQ,SAAS,CAAC;GACjC,MAAM,MAAM,qBAAqB,QAAQ,KAAK,KAAK;GACnD,MAAM,SACJ,OAAO,MAAM,aAAa,mBAEpB,uBACG,MAAM,SAAiC,CAC1C,UACI,uBAAuB,MAAM,QAAQ;GACjD,SAAS,KAAK;IACZ;IACA;IACA,MAAM,MAAM;GACd,CAAC;GACD;EACF;EAEA,IAAI,yBAAyB,GAC3B,MAAM,IAAI,MAAM,8CAA8C;CAElE;CAEA,OAAO;AACT;AAEA,SAAS,cAAc,OAA8B;CACnD,MAAM,UAAU,kBAAkB,MAAM,QAAQ;CAChD,MAAM,WAAW,2BAA2B,MAAM,QAAQ;CAK1D,MAAM,YAHqB,MACzB,gBAAgB,SAAS,QAAQ,CAEjB,CAAA,CAAmB;CAErC,UAAU,UAAU;CACpB,UAAU,WAAW;CAErB,OAAO;EACL,MAAM;EACN,eAAe;CACjB;AACF;AAEA,MAAa,OAAO,0BAClB,aACF"}
@@ -1,9 +1,9 @@
1
1
  import { JSXElement } from "../common/jsx.js";
2
- import { BoundaryChild } from "./shared.js";
2
+ import { ForEachSource } from "../runtime/for-types.js";
3
3
  import { VNode } from "../common/vnode.js";
4
+ import { BoundaryChild } from "./shared.js";
4
5
 
5
6
  //#region src/control/for.d.ts
6
- type ForEachSource<T> = T[] | (() => T[]);
7
7
  type ForBaseProps<T> = {
8
8
  each: ForEachSource<T>;
9
9
  fallback?: BoundaryChild;
@@ -20,5 +20,5 @@ type IndexedForProps<T> = ForBaseProps<T> & {
20
20
  type ForProps<T, K extends string | number = string | number> = KeyedForProps<T, K> | IndexedForProps<T>;
21
21
  declare const For: <T, K extends string | number = string | number>(props: ForProps<T, K>) => JSXElement;
22
22
  //#endregion
23
- export { For, ForEachSource, ForProps };
23
+ export { For, ForProps };
24
24
  //# sourceMappingURL=for.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"for.d.ts","names":[],"sources":["../../src/control/for.ts"],"mappings":";;;;;KAgBY,aAAA,MAAmB,CAAA,YAAa,CAAC;AAAA,KAExC,YAAA;EACH,IAAA,EAAM,aAAA,CAAc,CAAA;EACpB,QAAA,GAAW,aAAA;EACX,QAAA,GAAW,IAAA,EAAM,CAAA,EAAG,KAAA,mBAAwB,KAAA;AAAA;AAAA,KAGzC,aAAA,iCAA8C,YAAA,CAAa,CAAA;EAC9D,EAAA,GAAK,IAAA,EAAM,CAAA,EAAG,KAAA,aAAkB,CAAA;EAChC,OAAA;AAAA;AAAA,KAGG,eAAA,MAAqB,YAAY,CAAC,CAAA;EACrC,EAAA;EACA,OAAA;AAAA;AAAA,KAGU,QAAA,mDACR,aAAA,CAAc,CAAA,EAAG,CAAA,IACjB,eAAA,CAAgB,CAAA;AAAA,cA0EP,GAAA,mDAKX,KAAA,EAAO,QAAA,CAAS,CAAA,EAAG,CAAA,MAChB,UAAA"}
1
+ {"version":3,"file":"for.d.ts","names":[],"sources":["../../src/control/for.ts"],"mappings":";;;;;;KAoBK,YAAA;EACH,IAAA,EAAM,aAAA,CAAc,CAAA;EACpB,QAAA,GAAW,aAAA;EACX,QAAA,GAAW,IAAA,EAAM,CAAA,EAAG,KAAA,mBAAwB,KAAA;AAAA;AAAA,KAGzC,aAAA,iCAA8C,YAAA,CAAa,CAAA;EAC9D,EAAA,GAAK,IAAA,EAAM,CAAA,EAAG,KAAA,aAAkB,CAAA;EAChC,OAAA;AAAA;AAAA,KAGG,eAAA,MAAqB,YAAY,CAAC,CAAA;EACrC,EAAA;EACA,OAAA;AAAA;AAAA,KAGU,QAAA,mDACR,aAAA,CAAc,CAAA,EAAG,CAAA,IACjB,eAAA,CAAgB,CAAA;AAAA,cA0EP,GAAA,mDAKX,KAAA,EAAO,QAAA,CAAS,CAAA,EAAG,CAAA,MAChB,UAAA"}
@@ -1,7 +1,7 @@
1
1
  import { __CONTROL_BOUNDARY__, markEagerControlPrimitive } from "../common/control.js";
2
- import { useForState } from "../runtime/for-internal.js";
3
- import "../runtime/for.js";
4
2
  import { createFineGrainedEffect } from "../runtime/effect.js";
3
+ import { useForState } from "../runtime/for-internal.js";
4
+ import "../runtime/index.js";
5
5
  import { normalizeBoundaryChild } from "./shared.js";
6
6
  //#region src/control/for.ts
7
7
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"for.js","names":[],"sources":["../../src/control/for.ts"],"sourcesContent":["/**\n * For JSX primitive\n *\n * Creates a keyed child-scope boundary for efficient list rendering.\n */\n\nimport {\n __CONTROL_BOUNDARY__,\n markEagerControlPrimitive,\n} from '../common/control';\nimport type { JSXElement } from '../common/jsx';\nimport type { DOMElement, VNode } from '../common/vnode';\nimport { createFineGrainedEffect } from '../runtime/effect';\nimport { type ForState, useForState } from '../runtime/for';\nimport { type BoundaryChild, normalizeBoundaryChild } from './shared';\n\nexport type ForEachSource<T> = T[] | (() => T[]);\n\ntype ForBaseProps<T> = {\n each: ForEachSource<T>;\n fallback?: BoundaryChild;\n children: (item: T, index: () => number) => VNode;\n};\n\ntype KeyedForProps<T, K extends string | number> = ForBaseProps<T> & {\n by: (item: T, index: number) => K;\n byIndex?: never;\n};\n\ntype IndexedForProps<T> = ForBaseProps<T> & {\n by?: never;\n byIndex: true;\n};\n\nexport type ForProps<T, K extends string | number = string | number> =\n | KeyedForProps<T, K>\n | IndexedForProps<T>;\n\nfunction resolveEach<T>(each: ForEachSource<T>): T[] {\n const resolved = typeof each === 'function' ? each() : each;\n if (!Array.isArray(resolved)) {\n throw new Error('For each must resolve to an array.');\n }\n return resolved;\n}\n\nfunction resolveKeyFn<T>(\n props: ForProps<T>\n): (item: T, index: number) => string | number {\n if ('by' in props && typeof props.by === 'function') {\n return props.by;\n }\n if ('byIndex' in props && props.byIndex === true) {\n return (_item, index) => index;\n }\n throw new Error(\n '[askr] <For> requires a stable `by` key function. Use `byIndex` only as an explicit positional escape hatch.'\n );\n}\n\nfunction createForBoundary<T>(props: ForProps<T>): DOMElement {\n if ('by' in props && typeof props.by === 'function' && 'byIndex' in props) {\n throw new Error('[askr] <For> accepts either `by` or `byIndex`, not both.');\n }\n\n const byFn = resolveKeyFn(props);\n const fallback = normalizeBoundaryChild(props.fallback);\n const forState = useForState(props.each, byFn, props.children, fallback);\n\n const computeItems = () => resolveEach(forState.eachSource);\n if (!forState._sourceEffect) {\n forState._suspendSourceCommit = true;\n forState._sourceEffect = createFineGrainedEffect({\n lane: 'reactive',\n compute: computeItems,\n commit: (items) => {\n forState.currentItems = items;\n\n if (forState._suspendSourceCommit) {\n return;\n }\n\n forState._needsSourceReconcile = true;\n\n if (forState._enqueueBoundaryCommit) {\n forState._enqueueBoundaryCommit();\n return;\n }\n\n forState.parentInstance?._enqueueRun?.();\n },\n });\n forState._suspendSourceCommit = false;\n } else {\n forState._suspendSourceCommit = true;\n forState._sourceEffect.updateCompute(computeItems);\n forState._suspendSourceCommit = false;\n }\n\n return {\n type: __CONTROL_BOUNDARY__,\n _controlState: forState as unknown as ForState<unknown>,\n _forState: forState as unknown as ForState<unknown>,\n };\n}\n\nfunction ForPrimitive<T>(props: ForProps<T>): JSXElement {\n return createForBoundary(props) as unknown as JSXElement;\n}\n\nexport const For = markEagerControlPrimitive(\n ForPrimitive as <T, K extends string | number = string | number>(\n props: ForProps<T, K>\n ) => JSXElement\n) as <T, K extends string | number = string | number>(\n props: ForProps<T, K>\n) => JSXElement;\n"],"mappings":";;;;;;;;;;;AAsCA,SAAS,YAAe,MAA6B;CACnD,MAAM,WAAW,OAAO,SAAS,aAAa,KAAK,IAAI;CACvD,IAAI,CAAC,MAAM,QAAQ,QAAQ,GACzB,MAAM,IAAI,MAAM,oCAAoC;CAEtD,OAAO;AACT;AAEA,SAAS,aACP,OAC6C;CAC7C,IAAI,QAAQ,SAAS,OAAO,MAAM,OAAO,YACvC,OAAO,MAAM;CAEf,IAAI,aAAa,SAAS,MAAM,YAAY,MAC1C,QAAQ,OAAO,UAAU;CAE3B,MAAM,IAAI,MACR,8GACF;AACF;AAEA,SAAS,kBAAqB,OAAgC;CAC5D,IAAI,QAAQ,SAAS,OAAO,MAAM,OAAO,cAAc,aAAa,OAClE,MAAM,IAAI,MAAM,0DAA0D;CAG5E,MAAM,OAAO,aAAa,KAAK;CAC/B,MAAM,WAAW,uBAAuB,MAAM,QAAQ;CACtD,MAAM,WAAW,YAAY,MAAM,MAAM,MAAM,MAAM,UAAU,QAAQ;CAEvE,MAAM,qBAAqB,YAAY,SAAS,UAAU;CAC1D,IAAI,CAAC,SAAS,eAAe;EAC3B,SAAS,uBAAuB;EAChC,SAAS,gBAAgB,wBAAwB;GAC/C,MAAM;GACN,SAAS;GACT,SAAS,UAAU;IACjB,SAAS,eAAe;IAExB,IAAI,SAAS,sBACX;IAGF,SAAS,wBAAwB;IAEjC,IAAI,SAAS,wBAAwB;KACnC,SAAS,uBAAuB;KAChC;IACF;IAEA,SAAS,gBAAgB,cAAc;GACzC;EACF,CAAC;EACD,SAAS,uBAAuB;CAClC,OAAO;EACL,SAAS,uBAAuB;EAChC,SAAS,cAAc,cAAc,YAAY;EACjD,SAAS,uBAAuB;CAClC;CAEA,OAAO;EACL,MAAM;EACN,eAAe;EACf,WAAW;CACb;AACF;AAEA,SAAS,aAAgB,OAAgC;CACvD,OAAO,kBAAkB,KAAK;AAChC;AAEA,MAAa,MAAM,0BACjB,YAGF"}
1
+ {"version":3,"file":"for.js","names":[],"sources":["../../src/control/for.ts"],"sourcesContent":["/**\n * For JSX primitive\n *\n * Creates a keyed child-scope boundary for efficient list rendering.\n */\n\nimport {\n __CONTROL_BOUNDARY__,\n markEagerControlPrimitive,\n} from '../common/control';\nimport type { JSXElement } from '../common/jsx';\nimport type { DOMElement, VNode } from '../common/vnode';\nimport {\n createFineGrainedEffect,\n type ForEachSource,\n type ForState,\n useForState,\n} from '../runtime';\nimport { type BoundaryChild, normalizeBoundaryChild } from './shared';\n\ntype ForBaseProps<T> = {\n each: ForEachSource<T>;\n fallback?: BoundaryChild;\n children: (item: T, index: () => number) => VNode;\n};\n\ntype KeyedForProps<T, K extends string | number> = ForBaseProps<T> & {\n by: (item: T, index: number) => K;\n byIndex?: never;\n};\n\ntype IndexedForProps<T> = ForBaseProps<T> & {\n by?: never;\n byIndex: true;\n};\n\nexport type ForProps<T, K extends string | number = string | number> =\n | KeyedForProps<T, K>\n | IndexedForProps<T>;\n\nfunction resolveEach<T>(each: ForEachSource<T>): T[] {\n const resolved = typeof each === 'function' ? each() : each;\n if (!Array.isArray(resolved)) {\n throw new Error('For each must resolve to an array.');\n }\n return resolved;\n}\n\nfunction resolveKeyFn<T>(\n props: ForProps<T>\n): (item: T, index: number) => string | number {\n if ('by' in props && typeof props.by === 'function') {\n return props.by;\n }\n if ('byIndex' in props && props.byIndex === true) {\n return (_item, index) => index;\n }\n throw new Error(\n '[askr] <For> requires a stable `by` key function. Use `byIndex` only as an explicit positional escape hatch.'\n );\n}\n\nfunction createForBoundary<T>(props: ForProps<T>): DOMElement {\n if ('by' in props && typeof props.by === 'function' && 'byIndex' in props) {\n throw new Error('[askr] <For> accepts either `by` or `byIndex`, not both.');\n }\n\n const byFn = resolveKeyFn(props);\n const fallback = normalizeBoundaryChild(props.fallback);\n const forState = useForState(props.each, byFn, props.children, fallback);\n\n const computeItems = () => resolveEach(forState.eachSource);\n if (!forState._sourceEffect) {\n forState._suspendSourceCommit = true;\n forState._sourceEffect = createFineGrainedEffect({\n lane: 'reactive',\n compute: computeItems,\n commit: (items) => {\n forState.currentItems = items;\n\n if (forState._suspendSourceCommit) {\n return;\n }\n\n forState._needsSourceReconcile = true;\n\n if (forState._enqueueBoundaryCommit) {\n forState._enqueueBoundaryCommit();\n return;\n }\n\n forState.parentInstance?._enqueueRun?.();\n },\n });\n forState._suspendSourceCommit = false;\n } else {\n forState._suspendSourceCommit = true;\n forState._sourceEffect.updateCompute(computeItems);\n forState._suspendSourceCommit = false;\n }\n\n return {\n type: __CONTROL_BOUNDARY__,\n _controlState: forState as unknown as ForState<unknown>,\n _forState: forState as unknown as ForState<unknown>,\n };\n}\n\nfunction ForPrimitive<T>(props: ForProps<T>): JSXElement {\n return createForBoundary(props) as unknown as JSXElement;\n}\n\nexport const For = markEagerControlPrimitive(\n ForPrimitive as <T, K extends string | number = string | number>(\n props: ForProps<T, K>\n ) => JSXElement\n) as <T, K extends string | number = string | number>(\n props: ForProps<T, K>\n) => JSXElement;\n"],"mappings":";;;;;;;;;;;AAwCA,SAAS,YAAe,MAA6B;CACnD,MAAM,WAAW,OAAO,SAAS,aAAa,KAAK,IAAI;CACvD,IAAI,CAAC,MAAM,QAAQ,QAAQ,GACzB,MAAM,IAAI,MAAM,oCAAoC;CAEtD,OAAO;AACT;AAEA,SAAS,aACP,OAC6C;CAC7C,IAAI,QAAQ,SAAS,OAAO,MAAM,OAAO,YACvC,OAAO,MAAM;CAEf,IAAI,aAAa,SAAS,MAAM,YAAY,MAC1C,QAAQ,OAAO,UAAU;CAE3B,MAAM,IAAI,MACR,8GACF;AACF;AAEA,SAAS,kBAAqB,OAAgC;CAC5D,IAAI,QAAQ,SAAS,OAAO,MAAM,OAAO,cAAc,aAAa,OAClE,MAAM,IAAI,MAAM,0DAA0D;CAG5E,MAAM,OAAO,aAAa,KAAK;CAC/B,MAAM,WAAW,uBAAuB,MAAM,QAAQ;CACtD,MAAM,WAAW,YAAY,MAAM,MAAM,MAAM,MAAM,UAAU,QAAQ;CAEvE,MAAM,qBAAqB,YAAY,SAAS,UAAU;CAC1D,IAAI,CAAC,SAAS,eAAe;EAC3B,SAAS,uBAAuB;EAChC,SAAS,gBAAgB,wBAAwB;GAC/C,MAAM;GACN,SAAS;GACT,SAAS,UAAU;IACjB,SAAS,eAAe;IAExB,IAAI,SAAS,sBACX;IAGF,SAAS,wBAAwB;IAEjC,IAAI,SAAS,wBAAwB;KACnC,SAAS,uBAAuB;KAChC;IACF;IAEA,SAAS,gBAAgB,cAAc;GACzC;EACF,CAAC;EACD,SAAS,uBAAuB;CAClC,OAAO;EACL,SAAS,uBAAuB;EAChC,SAAS,cAAc,cAAc,YAAY;EACjD,SAAS,uBAAuB;CAClC;CAEA,OAAO;EACL,MAAM;EACN,eAAe;EACf,WAAW;CACb;AACF;AAEA,SAAS,aAAgB,OAAgC;CACvD,OAAO,kBAAkB,KAAK;AAChC;AAEA,MAAa,MAAM,0BACjB,YAGF"}
@@ -1,6 +1,7 @@
1
1
  import { __CONTROL_BOUNDARY__, markEagerControlPrimitive } from "../common/control.js";
2
2
  import { createShowState } from "../runtime/control.js";
3
3
  import { state } from "../runtime/state.js";
4
+ import "../runtime/index.js";
4
5
  import { normalizeBoundaryChild, resolveMaybeAccessor } from "./shared.js";
5
6
  //#region src/control/show.ts
6
7
  function createTruthyRenderer(props) {
@@ -1 +1 @@
1
- {"version":3,"file":"show.js","names":[],"sources":["../../src/control/show.ts"],"sourcesContent":["import {\n __CONTROL_BOUNDARY__,\n markEagerControlPrimitive,\n} from '../common/control';\nimport type { JSXElement } from '../common/jsx';\nimport type { VNode } from '../common/vnode';\nimport { createShowState, type ShowState } from '../runtime/control';\nimport { state } from '../runtime/state';\nimport {\n type BoundaryChild,\n normalizeBoundaryChild,\n resolveMaybeAccessor,\n} from './shared';\n\ntype ShowSource<T> = T | (() => T);\ntype Truthy<T> = T extends false | '' | 0 | 0n | null | undefined ? never : T;\n\nexport type ShowProps<T> = {\n when: ShowSource<T>;\n fallback?: BoundaryChild;\n children: BoundaryChild | ((value: Truthy<T>) => BoundaryChild);\n};\n\nfunction createTruthyRenderer<T>(\n props: ShowProps<T>\n): ShowState['renderTruthy'] {\n if (typeof props.children === 'function') {\n return (value: unknown) =>\n normalizeBoundaryChild(\n (props.children as (resolved: Truthy<T>) => VNode)(value as Truthy<T>)\n ) as VNode;\n }\n\n const staticChild = normalizeBoundaryChild(props.children);\n return () => staticChild as VNode;\n}\n\nfunction createFallbackRenderer(\n fallback: BoundaryChild | undefined\n): (() => VNode) | null {\n const normalizedFallback = normalizeBoundaryChild(fallback);\n if (normalizedFallback == null || normalizedFallback === false) {\n return null;\n }\n return () => normalizedFallback;\n}\n\nfunction ShowPrimitive<T>(props: ShowProps<T>): JSXElement {\n const selectedValue = resolveMaybeAccessor(props.when);\n const renderTruthy = createTruthyRenderer(props);\n const renderFallback = createFallbackRenderer(props.fallback);\n\n const showStateContainer = state<ShowState>(\n createShowState(selectedValue, renderTruthy, renderFallback)\n );\n const showState = showStateContainer();\n\n showState.selectedValue = selectedValue;\n showState.renderTruthy = renderTruthy;\n showState.renderFallback = renderFallback;\n\n return {\n type: __CONTROL_BOUNDARY__,\n _controlState: showState,\n } as unknown as JSXElement;\n}\n\nexport const Show = markEagerControlPrimitive(\n ShowPrimitive as <T>(props: ShowProps<T>) => JSXElement\n) as <T>(props: ShowProps<T>) => JSXElement;\n"],"mappings":";;;;;AAuBA,SAAS,qBACP,OAC2B;CAC3B,IAAI,OAAO,MAAM,aAAa,YAC5B,QAAQ,UACN,uBACG,MAAM,SAA4C,KAAkB,CACvE;CAGJ,MAAM,cAAc,uBAAuB,MAAM,QAAQ;CACzD,aAAa;AACf;AAEA,SAAS,uBACP,UACsB;CACtB,MAAM,qBAAqB,uBAAuB,QAAQ;CAC1D,IAAI,sBAAsB,QAAQ,uBAAuB,OACvD,OAAO;CAET,aAAa;AACf;AAEA,SAAS,cAAiB,OAAiC;CACzD,MAAM,gBAAgB,qBAAqB,MAAM,IAAI;CACrD,MAAM,eAAe,qBAAqB,KAAK;CAC/C,MAAM,iBAAiB,uBAAuB,MAAM,QAAQ;CAK5D,MAAM,YAHqB,MACzB,gBAAgB,eAAe,cAAc,cAAc,CAE3C,CAAA,CAAmB;CAErC,UAAU,gBAAgB;CAC1B,UAAU,eAAe;CACzB,UAAU,iBAAiB;CAE3B,OAAO;EACL,MAAM;EACN,eAAe;CACjB;AACF;AAEA,MAAa,OAAO,0BAClB,aACF"}
1
+ {"version":3,"file":"show.js","names":[],"sources":["../../src/control/show.ts"],"sourcesContent":["import {\n __CONTROL_BOUNDARY__,\n markEagerControlPrimitive,\n} from '../common/control';\nimport type { JSXElement } from '../common/jsx';\nimport type { VNode } from '../common/vnode';\nimport { createShowState, type ShowState } from '../runtime';\nimport { state } from '../runtime';\nimport {\n type BoundaryChild,\n normalizeBoundaryChild,\n resolveMaybeAccessor,\n} from './shared';\n\ntype ShowSource<T> = T | (() => T);\ntype Truthy<T> = T extends false | '' | 0 | 0n | null | undefined ? never : T;\n\nexport type ShowProps<T> = {\n when: ShowSource<T>;\n fallback?: BoundaryChild;\n children: BoundaryChild | ((value: Truthy<T>) => BoundaryChild);\n};\n\nfunction createTruthyRenderer<T>(\n props: ShowProps<T>\n): ShowState['renderTruthy'] {\n if (typeof props.children === 'function') {\n return (value: unknown) =>\n normalizeBoundaryChild(\n (props.children as (resolved: Truthy<T>) => VNode)(value as Truthy<T>)\n ) as VNode;\n }\n\n const staticChild = normalizeBoundaryChild(props.children);\n return () => staticChild as VNode;\n}\n\nfunction createFallbackRenderer(\n fallback: BoundaryChild | undefined\n): (() => VNode) | null {\n const normalizedFallback = normalizeBoundaryChild(fallback);\n if (normalizedFallback == null || normalizedFallback === false) {\n return null;\n }\n return () => normalizedFallback;\n}\n\nfunction ShowPrimitive<T>(props: ShowProps<T>): JSXElement {\n const selectedValue = resolveMaybeAccessor(props.when);\n const renderTruthy = createTruthyRenderer(props);\n const renderFallback = createFallbackRenderer(props.fallback);\n\n const showStateContainer = state<ShowState>(\n createShowState(selectedValue, renderTruthy, renderFallback)\n );\n const showState = showStateContainer();\n\n showState.selectedValue = selectedValue;\n showState.renderTruthy = renderTruthy;\n showState.renderFallback = renderFallback;\n\n return {\n type: __CONTROL_BOUNDARY__,\n _controlState: showState,\n } as unknown as JSXElement;\n}\n\nexport const Show = markEagerControlPrimitive(\n ShowPrimitive as <T>(props: ShowProps<T>) => JSXElement\n) as <T>(props: ShowProps<T>) => JSXElement;\n"],"mappings":";;;;;;AAuBA,SAAS,qBACP,OAC2B;CAC3B,IAAI,OAAO,MAAM,aAAa,YAC5B,QAAQ,UACN,uBACG,MAAM,SAA4C,KAAkB,CACvE;CAGJ,MAAM,cAAc,uBAAuB,MAAM,QAAQ;CACzD,aAAa;AACf;AAEA,SAAS,uBACP,UACsB;CACtB,MAAM,qBAAqB,uBAAuB,QAAQ;CAC1D,IAAI,sBAAsB,QAAQ,uBAAuB,OACvD,OAAO;CAET,aAAa;AACf;AAEA,SAAS,cAAiB,OAAiC;CACzD,MAAM,gBAAgB,qBAAqB,MAAM,IAAI;CACrD,MAAM,eAAe,qBAAqB,KAAK;CAC/C,MAAM,iBAAiB,uBAAuB,MAAM,QAAQ;CAK5D,MAAM,YAHqB,MACzB,gBAAgB,eAAe,cAAc,cAAc,CAE3C,CAAA,CAAmB;CAErC,UAAU,gBAAgB;CAC1B,UAAU,eAAe;CACzB,UAAU,iBAAiB;CAE3B,OAAO;EACL,MAAM;EACN,eAAe;CACjB;AACF;AAEA,MAAa,OAAO,0BAClB,aACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"data-runtime.js","names":[],"sources":["../../src/data/data-runtime.ts"],"sourcesContent":["import { getActiveRenderContext } from '../common/render-context';\nimport type { ComponentInstance } from '../runtime/component';\nimport { emitInvalidation } from './invalidation-listeners';\nimport type { MutationCell } from './mutation-cell';\nimport type { QueryCell } from './query-cell';\nimport type { DataRuntime, DataRuntimeOptions } from './types';\n\nexport type QuerySlot = {\n key: string;\n cell: QueryCell<unknown>;\n};\n\nexport type DataRuntimeState = {\n queryCache: Map<string, QueryCell<unknown>>;\n querySlotsByInstance: WeakMap<ComponentInstance, Map<number, QuerySlot>>;\n mutationSlotsByInstance: WeakMap<\n ComponentInstance,\n Map<number, MutationCell<unknown, unknown>>\n >;\n queryCleanupRegistered: WeakSet<ComponentInstance>;\n mutationCleanupRegistered: WeakSet<ComponentInstance>;\n};\n\nconst dataRuntimeStates = new WeakMap<DataRuntime, DataRuntimeState>();\nconst dataRuntimeByQueryCache = new WeakMap<\n Map<string, unknown>,\n DataRuntime\n>();\n\nfunction createDataRuntimeState(\n queryCache: Map<string, unknown>\n): DataRuntimeState {\n return {\n queryCache: queryCache as Map<string, QueryCell<unknown>>,\n querySlotsByInstance: new WeakMap(),\n mutationSlotsByInstance: new WeakMap(),\n queryCleanupRegistered: new WeakSet(),\n mutationCleanupRegistered: new WeakSet(),\n };\n}\n\nexport function createDataRuntime(\n options: DataRuntimeOptions = {}\n): DataRuntime {\n const runtime: DataRuntime = Object.freeze({\n queryCache: options.queryCache ?? new Map<string, unknown>(),\n });\n dataRuntimeStates.set(runtime, createDataRuntimeState(runtime.queryCache));\n dataRuntimeByQueryCache.set(runtime.queryCache, runtime);\n return runtime;\n}\n\nconst defaultDataRuntime = createDataRuntime();\n\nexport function getDefaultDataRuntime(): DataRuntime {\n return defaultDataRuntime;\n}\n\nfunction getDataRuntimeState(runtime: DataRuntime): DataRuntimeState {\n const state = dataRuntimeStates.get(runtime);\n if (!state) {\n throw new Error(\n '[Askr] data runtime was not created by createDataRuntime().'\n );\n }\n return state;\n}\n\nfunction isDataRuntime(value: unknown): value is DataRuntime {\n return (\n typeof value === 'object' &&\n value !== null &&\n dataRuntimeStates.has(value as DataRuntime)\n );\n}\n\nfunction getDataRuntimeForQueryCache(\n queryCache: Map<string, unknown>\n): DataRuntime {\n let runtime = dataRuntimeByQueryCache.get(queryCache);\n if (!runtime) {\n runtime = createDataRuntime({ queryCache });\n dataRuntimeByQueryCache.set(queryCache, runtime);\n }\n return runtime;\n}\n\nfunction getActiveDataRuntime(): DataRuntime {\n const ctx = getActiveRenderContext();\n if (isDataRuntime(ctx?.dataRuntime)) {\n return ctx.dataRuntime;\n }\n\n if (ctx?.queryCache) {\n return getDataRuntimeForQueryCache(ctx.queryCache);\n }\n\n return defaultDataRuntime;\n}\n\nfunction getActiveDataRuntimeState(): DataRuntimeState {\n return getDataRuntimeState(getActiveDataRuntime());\n}\n\nexport function resolveDataRuntimeState(\n runtime?: DataRuntime\n): DataRuntimeState {\n return runtime ? getDataRuntimeState(runtime) : getActiveDataRuntimeState();\n}\n\nexport function getQuerySlotStore(\n runtimeState: DataRuntimeState,\n instance: ComponentInstance\n): Map<number, QuerySlot> {\n let store = runtimeState.querySlotsByInstance.get(instance);\n if (!store) {\n store = new Map();\n runtimeState.querySlotsByInstance.set(instance, store);\n }\n return store;\n}\n\nexport function getMutationSlotStore(\n runtimeState: DataRuntimeState,\n instance: ComponentInstance\n): Map<number, MutationCell<unknown, unknown>> {\n let store = runtimeState.mutationSlotsByInstance.get(instance);\n if (!store) {\n store = new Map();\n runtimeState.mutationSlotsByInstance.set(instance, store);\n }\n return store;\n}\n\nexport function ensureQueryCleanup(\n runtimeState: DataRuntimeState,\n instance: ComponentInstance\n): void {\n if (runtimeState.queryCleanupRegistered.has(instance)) {\n return;\n }\n\n runtimeState.queryCleanupRegistered.add(instance);\n instance.cleanupFns.push(() => {\n const slots = runtimeState.querySlotsByInstance.get(instance);\n if (!slots) {\n runtimeState.queryCleanupRegistered.delete(instance);\n return;\n }\n\n for (const [hookIndex, slot] of slots) {\n slot.cell.detach(instance, hookIndex);\n }\n\n slots.clear();\n runtimeState.querySlotsByInstance.delete(instance);\n runtimeState.queryCleanupRegistered.delete(instance);\n });\n}\n\nexport function ensureMutationCleanup(\n runtimeState: DataRuntimeState,\n instance: ComponentInstance\n): void {\n if (runtimeState.mutationCleanupRegistered.has(instance)) {\n return;\n }\n\n runtimeState.mutationCleanupRegistered.add(instance);\n instance.cleanupFns.push(() => {\n const slots = runtimeState.mutationSlotsByInstance.get(instance);\n if (!slots) {\n runtimeState.mutationCleanupRegistered.delete(instance);\n return;\n }\n\n for (const cell of slots.values()) {\n cell.abort();\n }\n\n slots.clear();\n runtimeState.mutationSlotsByInstance.delete(instance);\n runtimeState.mutationCleanupRegistered.delete(instance);\n });\n}\n\nexport function invalidateQueriesForRuntime(\n runtimeState: DataRuntimeState,\n prefix: string,\n markPendingWrite: boolean\n): void {\n emitInvalidation({ prefix, markPendingWrite });\n\n const cache = runtimeState.queryCache;\n\n for (const [key, query] of cache) {\n if (!key.startsWith(prefix)) {\n continue;\n }\n\n if (markPendingWrite) {\n query.markPendingWrite();\n }\n\n void query.refresh();\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"data-runtime.js","names":[],"sources":["../../src/data/data-runtime.ts"],"sourcesContent":["import { getActiveRenderContext } from '../common/render-context';\nimport type { ComponentInstance } from '../runtime';\nimport { emitInvalidation } from './invalidation-listeners';\nimport type { MutationCell } from './mutation-cell';\nimport type { QueryCell } from './query-cell';\nimport type { DataRuntime, DataRuntimeOptions } from './types';\n\nexport type QuerySlot = {\n key: string;\n cell: QueryCell<unknown>;\n};\n\nexport type DataRuntimeState = {\n queryCache: Map<string, QueryCell<unknown>>;\n querySlotsByInstance: WeakMap<ComponentInstance, Map<number, QuerySlot>>;\n mutationSlotsByInstance: WeakMap<\n ComponentInstance,\n Map<number, MutationCell<unknown, unknown>>\n >;\n queryCleanupRegistered: WeakSet<ComponentInstance>;\n mutationCleanupRegistered: WeakSet<ComponentInstance>;\n};\n\nconst dataRuntimeStates = new WeakMap<DataRuntime, DataRuntimeState>();\nconst dataRuntimeByQueryCache = new WeakMap<\n Map<string, unknown>,\n DataRuntime\n>();\n\nfunction createDataRuntimeState(\n queryCache: Map<string, unknown>\n): DataRuntimeState {\n return {\n queryCache: queryCache as Map<string, QueryCell<unknown>>,\n querySlotsByInstance: new WeakMap(),\n mutationSlotsByInstance: new WeakMap(),\n queryCleanupRegistered: new WeakSet(),\n mutationCleanupRegistered: new WeakSet(),\n };\n}\n\nexport function createDataRuntime(\n options: DataRuntimeOptions = {}\n): DataRuntime {\n const runtime: DataRuntime = Object.freeze({\n queryCache: options.queryCache ?? new Map<string, unknown>(),\n });\n dataRuntimeStates.set(runtime, createDataRuntimeState(runtime.queryCache));\n dataRuntimeByQueryCache.set(runtime.queryCache, runtime);\n return runtime;\n}\n\nconst defaultDataRuntime = createDataRuntime();\n\nexport function getDefaultDataRuntime(): DataRuntime {\n return defaultDataRuntime;\n}\n\nfunction getDataRuntimeState(runtime: DataRuntime): DataRuntimeState {\n const state = dataRuntimeStates.get(runtime);\n if (!state) {\n throw new Error(\n '[Askr] data runtime was not created by createDataRuntime().'\n );\n }\n return state;\n}\n\nfunction isDataRuntime(value: unknown): value is DataRuntime {\n return (\n typeof value === 'object' &&\n value !== null &&\n dataRuntimeStates.has(value as DataRuntime)\n );\n}\n\nfunction getDataRuntimeForQueryCache(\n queryCache: Map<string, unknown>\n): DataRuntime {\n let runtime = dataRuntimeByQueryCache.get(queryCache);\n if (!runtime) {\n runtime = createDataRuntime({ queryCache });\n dataRuntimeByQueryCache.set(queryCache, runtime);\n }\n return runtime;\n}\n\nfunction getActiveDataRuntime(): DataRuntime {\n const ctx = getActiveRenderContext();\n if (isDataRuntime(ctx?.dataRuntime)) {\n return ctx.dataRuntime;\n }\n\n if (ctx?.queryCache) {\n return getDataRuntimeForQueryCache(ctx.queryCache);\n }\n\n return defaultDataRuntime;\n}\n\nfunction getActiveDataRuntimeState(): DataRuntimeState {\n return getDataRuntimeState(getActiveDataRuntime());\n}\n\nexport function resolveDataRuntimeState(\n runtime?: DataRuntime\n): DataRuntimeState {\n return runtime ? getDataRuntimeState(runtime) : getActiveDataRuntimeState();\n}\n\nexport function getQuerySlotStore(\n runtimeState: DataRuntimeState,\n instance: ComponentInstance\n): Map<number, QuerySlot> {\n let store = runtimeState.querySlotsByInstance.get(instance);\n if (!store) {\n store = new Map();\n runtimeState.querySlotsByInstance.set(instance, store);\n }\n return store;\n}\n\nexport function getMutationSlotStore(\n runtimeState: DataRuntimeState,\n instance: ComponentInstance\n): Map<number, MutationCell<unknown, unknown>> {\n let store = runtimeState.mutationSlotsByInstance.get(instance);\n if (!store) {\n store = new Map();\n runtimeState.mutationSlotsByInstance.set(instance, store);\n }\n return store;\n}\n\nexport function ensureQueryCleanup(\n runtimeState: DataRuntimeState,\n instance: ComponentInstance\n): void {\n if (runtimeState.queryCleanupRegistered.has(instance)) {\n return;\n }\n\n runtimeState.queryCleanupRegistered.add(instance);\n instance.cleanupFns.push(() => {\n const slots = runtimeState.querySlotsByInstance.get(instance);\n if (!slots) {\n runtimeState.queryCleanupRegistered.delete(instance);\n return;\n }\n\n for (const [hookIndex, slot] of slots) {\n slot.cell.detach(instance, hookIndex);\n }\n\n slots.clear();\n runtimeState.querySlotsByInstance.delete(instance);\n runtimeState.queryCleanupRegistered.delete(instance);\n });\n}\n\nexport function ensureMutationCleanup(\n runtimeState: DataRuntimeState,\n instance: ComponentInstance\n): void {\n if (runtimeState.mutationCleanupRegistered.has(instance)) {\n return;\n }\n\n runtimeState.mutationCleanupRegistered.add(instance);\n instance.cleanupFns.push(() => {\n const slots = runtimeState.mutationSlotsByInstance.get(instance);\n if (!slots) {\n runtimeState.mutationCleanupRegistered.delete(instance);\n return;\n }\n\n for (const cell of slots.values()) {\n cell.abort();\n }\n\n slots.clear();\n runtimeState.mutationSlotsByInstance.delete(instance);\n runtimeState.mutationCleanupRegistered.delete(instance);\n });\n}\n\nexport function invalidateQueriesForRuntime(\n runtimeState: DataRuntimeState,\n prefix: string,\n markPendingWrite: boolean\n): void {\n emitInvalidation({ prefix, markPendingWrite });\n\n const cache = runtimeState.queryCache;\n\n for (const [key, query] of cache) {\n if (!key.startsWith(prefix)) {\n continue;\n }\n\n if (markPendingWrite) {\n query.markPendingWrite();\n }\n\n void query.refresh();\n }\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { invalidateQueriesForRuntime, resolveDataRuntimeState } from "./data-runtime.js";
2
1
  import { documentVisible, routeActive, timer, windowFocused } from "../runtime/lifecycle-operations.js";
3
- import "../runtime/operations.js";
2
+ import "../runtime/index.js";
3
+ import { invalidateQueriesForRuntime, resolveDataRuntimeState } from "./data-runtime.js";
4
4
  import { createQueryScope } from "./query-key.js";
5
5
  //#region src/data/invalidation.ts
6
6
  function invalidate(prefix, options) {
@@ -1 +1 @@
1
- {"version":3,"file":"invalidation.js","names":[],"sources":["../../src/data/invalidation.ts"],"sourcesContent":["import {\n documentVisible,\n routeActive,\n timer,\n windowFocused,\n type ActivityPredicate,\n} from '../runtime/operations';\nimport {\n invalidateQueriesForRuntime,\n resolveDataRuntimeState,\n} from './data-runtime';\nimport { createQueryScope } from './query-key';\nimport type {\n InvalidateOnIntervalOptions,\n InvalidateOptions,\n QueryScope,\n} from './types';\n\nexport function invalidate(prefix: string, options?: InvalidateOptions): void {\n invalidateQueriesForRuntime(\n resolveDataRuntimeState(options?.runtime),\n prefix,\n options?.markPendingWrite ?? false\n );\n}\n\nexport function queryScope(namespace: string): QueryScope {\n return createQueryScope(namespace, invalidate);\n}\n\nconst INVALIDATE_ON_INTERVAL_OPTIONS_ERROR =\n '[Askr] invalidateOnInterval() requires an options object with a finite numeric intervalMs.';\n\nexport function invalidateOnInterval(\n prefix: string,\n options: InvalidateOnIntervalOptions\n): void {\n if (\n !options ||\n typeof options !== 'object' ||\n typeof options.intervalMs !== 'number' ||\n !Number.isFinite(options.intervalMs)\n ) {\n throw new Error(INVALIDATE_ON_INTERVAL_OPTIONS_ERROR);\n }\n\n const runtimeState = resolveDataRuntimeState(options.runtime);\n const when: ActivityPredicate[] = [];\n\n if (options.activeOn) {\n when.push(routeActive(options.activeOn));\n }\n\n if (options.visibleOnly) {\n when.push(documentVisible());\n }\n\n if (options.focusedOnly) {\n when.push(windowFocused());\n }\n\n timer(\n options.intervalMs,\n () => {\n invalidateQueriesForRuntime(\n runtimeState,\n prefix,\n options.markPendingWrite ?? false\n );\n },\n when.length > 0 ? { when } : undefined\n );\n}\n"],"mappings":";;;;;AAkBA,SAAgB,WAAW,QAAgB,SAAmC;CAC5E,4BACE,wBAAwB,SAAS,OAAO,GACxC,QACA,SAAS,oBAAoB,KAC/B;AACF;AAEA,SAAgB,WAAW,WAA+B;CACxD,OAAO,iBAAiB,WAAW,UAAU;AAC/C;AAEA,MAAM,uCACJ;AAEF,SAAgB,qBACd,QACA,SACM;CACN,IACE,CAAC,WACD,OAAO,YAAY,YACnB,OAAO,QAAQ,eAAe,YAC9B,CAAC,OAAO,SAAS,QAAQ,UAAU,GAEnC,MAAM,IAAI,MAAM,oCAAoC;CAGtD,MAAM,eAAe,wBAAwB,QAAQ,OAAO;CAC5D,MAAM,OAA4B,CAAC;CAEnC,IAAI,QAAQ,UACV,KAAK,KAAK,YAAY,QAAQ,QAAQ,CAAC;CAGzC,IAAI,QAAQ,aACV,KAAK,KAAK,gBAAgB,CAAC;CAG7B,IAAI,QAAQ,aACV,KAAK,KAAK,cAAc,CAAC;CAG3B,MACE,QAAQ,kBACF;EACJ,4BACE,cACA,QACA,QAAQ,oBAAoB,KAC9B;CACF,GACA,KAAK,SAAS,IAAI,EAAE,KAAK,IAAI,MAC/B;AACF"}
1
+ {"version":3,"file":"invalidation.js","names":[],"sources":["../../src/data/invalidation.ts"],"sourcesContent":["import {\n documentVisible,\n routeActive,\n timer,\n windowFocused,\n type ActivityPredicate,\n} from '../runtime';\nimport {\n invalidateQueriesForRuntime,\n resolveDataRuntimeState,\n} from './data-runtime';\nimport { createQueryScope } from './query-key';\nimport type {\n InvalidateOnIntervalOptions,\n InvalidateOptions,\n QueryScope,\n} from './types';\n\nexport function invalidate(prefix: string, options?: InvalidateOptions): void {\n invalidateQueriesForRuntime(\n resolveDataRuntimeState(options?.runtime),\n prefix,\n options?.markPendingWrite ?? false\n );\n}\n\nexport function queryScope(namespace: string): QueryScope {\n return createQueryScope(namespace, invalidate);\n}\n\nconst INVALIDATE_ON_INTERVAL_OPTIONS_ERROR =\n '[Askr] invalidateOnInterval() requires an options object with a finite numeric intervalMs.';\n\nexport function invalidateOnInterval(\n prefix: string,\n options: InvalidateOnIntervalOptions\n): void {\n if (\n !options ||\n typeof options !== 'object' ||\n typeof options.intervalMs !== 'number' ||\n !Number.isFinite(options.intervalMs)\n ) {\n throw new Error(INVALIDATE_ON_INTERVAL_OPTIONS_ERROR);\n }\n\n const runtimeState = resolveDataRuntimeState(options.runtime);\n const when: ActivityPredicate[] = [];\n\n if (options.activeOn) {\n when.push(routeActive(options.activeOn));\n }\n\n if (options.visibleOnly) {\n when.push(documentVisible());\n }\n\n if (options.focusedOnly) {\n when.push(windowFocused());\n }\n\n timer(\n options.intervalMs,\n () => {\n invalidateQueriesForRuntime(\n runtimeState,\n prefix,\n options.markPendingWrite ?? false\n );\n },\n when.length > 0 ? { when } : undefined\n );\n}\n"],"mappings":";;;;;AAkBA,SAAgB,WAAW,QAAgB,SAAmC;CAC5E,4BACE,wBAAwB,SAAS,OAAO,GACxC,QACA,SAAS,oBAAoB,KAC/B;AACF;AAEA,SAAgB,WAAW,WAA+B;CACxD,OAAO,iBAAiB,WAAW,UAAU;AAC/C;AAEA,MAAM,uCACJ;AAEF,SAAgB,qBACd,QACA,SACM;CACN,IACE,CAAC,WACD,OAAO,YAAY,YACnB,OAAO,QAAQ,eAAe,YAC9B,CAAC,OAAO,SAAS,QAAQ,UAAU,GAEnC,MAAM,IAAI,MAAM,oCAAoC;CAGtD,MAAM,eAAe,wBAAwB,QAAQ,OAAO;CAC5D,MAAM,OAA4B,CAAC;CAEnC,IAAI,QAAQ,UACV,KAAK,KAAK,YAAY,QAAQ,QAAQ,CAAC;CAGzC,IAAI,QAAQ,aACV,KAAK,KAAK,gBAAgB,CAAC;CAG7B,IAAI,QAAQ,aACV,KAAK,KAAK,cAAc,CAAC;CAG3B,MACE,QAAQ,kBACF;EACJ,4BACE,cACA,QACA,QAAQ,oBAAoB,KAC9B;CACF,GACA,KAAK,SAAS,IAAI,EAAE,KAAK,IAAI,MAC/B;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"mutation-cell.d.ts","names":[],"sources":["../../src/data/mutation-cell.ts"],"mappings":";;;;cAoBa,YAAA;EAAA,iBACM,MAAA;EAAA,iBACA,YAAA;EAAA,QACT,MAAA;EAAA,QACA,OAAA;EAAA,QACA,YAAA;EAAA,QACA,UAAA;EAAA,QACA,UAAA;EAAA,QAEA,KAAA;cAON,OAAA,EAAS,eAAA,CAAgB,MAAA,EAAQ,OAAA,GACjC,YAAA,EAAc,gBAAA;EAQhB,UAAA,CAAW,OAAA,EAAS,eAAA,CAAgB,MAAA,EAAQ,OAAA;EAAA,IAMxC,MAAA;EAAA,IAKA,OAAA;EAAA,IAKA,KAAA;EAAA,IAKA,MAAA,IAAU,OAAA;EAAA,QAKN,QAAA;EAQF,OAAA,CAAQ,KAAA,EAAO,MAAA,GAAS,OAAA,CAAQ,OAAA;EA8CtC,KAAA;EAWA,KAAA;AAAA;AAAA,iBAQc,cAAA,kBACd,OAAA,EAAS,eAAA,CAAgB,MAAA,EAAQ,OAAA,IAChC,QAAA,CAAS,MAAA,EAAQ,OAAA"}
1
+ {"version":3,"file":"mutation-cell.d.ts","names":[],"sources":["../../src/data/mutation-cell.ts"],"mappings":";;;;cAiBa,YAAA;EAAA,iBACM,MAAA;EAAA,iBACA,YAAA;EAAA,QACT,MAAA;EAAA,QACA,OAAA;EAAA,QACA,YAAA;EAAA,QACA,UAAA;EAAA,QACA,UAAA;EAAA,QAEA,KAAA;cAON,OAAA,EAAS,eAAA,CAAgB,MAAA,EAAQ,OAAA,GACjC,YAAA,EAAc,gBAAA;EAQhB,UAAA,CAAW,OAAA,EAAS,eAAA,CAAgB,MAAA,EAAQ,OAAA;EAAA,IAMxC,MAAA;EAAA,IAKA,OAAA;EAAA,IAKA,KAAA;EAAA,IAKA,MAAA,IAAU,OAAA;EAAA,QAKN,QAAA;EAQF,OAAA,CAAQ,KAAA,EAAO,MAAA,GAAS,OAAA,CAAQ,OAAA;EA8CtC,KAAA;EAWA,KAAA;AAAA;AAAA,iBAQc,cAAA,kBACd,OAAA,EAAS,eAAA,CAAgB,MAAA,EAAQ,OAAA,IAChC,QAAA,CAAS,MAAA,EAAQ,OAAA"}
@@ -1,6 +1,6 @@
1
1
  import { recordReadableRead } from "../runtime/readable.js";
2
2
  import { claimHookIndex, getCurrentComponentInstance } from "../runtime/component-scope.js";
3
- import "../runtime/component.js";
3
+ import "../runtime/index.js";
4
4
  import { ensureMutationCleanup, getMutationSlotStore, invalidateQueriesForRuntime, resolveDataRuntimeState } from "./data-runtime.js";
5
5
  import { createReadableSource, isAbortError, normalizeAsyncDataError, notifySource } from "./shared.js";
6
6
  //#region src/data/mutation-cell.ts
@@ -1 +1 @@
1
- {"version":3,"file":"mutation-cell.js","names":[],"sources":["../../src/data/mutation-cell.ts"],"sourcesContent":["import {\n claimHookIndex,\n getCurrentComponentInstance,\n} from '../runtime/component';\nimport { recordReadableRead } from '../runtime/readable';\nimport {\n ensureMutationCleanup,\n getMutationSlotStore,\n invalidateQueriesForRuntime,\n resolveDataRuntimeState,\n type DataRuntimeState,\n} from './data-runtime';\nimport {\n createReadableSource,\n isAbortError,\n normalizeAsyncDataError,\n notifySource,\n} from './shared';\nimport type { Mutation, MutationOptions, MutationRecord } from './types';\n\nexport class MutationCell<TInput, TResult> {\n private readonly source = createReadableSource();\n private readonly runtimeState: DataRuntimeState;\n private action: MutationOptions<TInput, TResult>['action'];\n private affects?: MutationOptions<TInput, TResult>['affects'];\n private afterSuccess?: MutationOptions<TInput, TResult>['afterSuccess'];\n private controller: AbortController | null = null;\n private generation = 0;\n\n private state: MutationRecord<TResult> = {\n status: 'idle',\n error: null,\n result: null,\n };\n\n constructor(\n options: MutationOptions<TInput, TResult>,\n runtimeState: DataRuntimeState\n ) {\n this.runtimeState = runtimeState;\n this.action = options.action;\n this.affects = options.affects;\n this.afterSuccess = options.afterSuccess;\n }\n\n setOptions(options: MutationOptions<TInput, TResult>): void {\n this.action = options.action;\n this.affects = options.affects;\n this.afterSuccess = options.afterSuccess;\n }\n\n get status(): 'idle' | 'pending' | 'success' | 'error' {\n recordReadableRead(this.source);\n return this.state.status;\n }\n\n get pending(): boolean {\n recordReadableRead(this.source);\n return this.state.status === 'pending';\n }\n\n get error(): {} | null {\n recordReadableRead(this.source);\n return this.state.error;\n }\n\n get result(): TResult | null {\n recordReadableRead(this.source);\n return this.state.result;\n }\n\n private setState(next: Partial<MutationRecord<TResult>>): void {\n this.state = {\n ...this.state,\n ...next,\n };\n notifySource(this.source);\n }\n\n async execute(input: TInput): Promise<TResult> {\n this.generation += 1;\n const generation = this.generation;\n\n this.controller?.abort();\n const controller = new AbortController();\n this.controller = controller;\n\n this.setState({ status: 'pending', error: null, result: null });\n\n let result: TResult;\n try {\n result = await this.action(input, { signal: controller.signal });\n } catch (error) {\n if (this.generation !== generation || this.controller !== controller) {\n throw error;\n }\n\n if (isAbortError(error, controller.signal)) {\n this.setState({ status: 'idle', error: null });\n throw error;\n }\n\n this.setState({\n status: 'error',\n error: normalizeAsyncDataError(error, 'Unknown mutation error'),\n });\n throw error;\n }\n\n if (this.generation !== generation || this.controller !== controller) {\n return result;\n }\n\n this.setState({ status: 'success', error: null, result });\n\n if (this.afterSuccess === 'invalidate') {\n const prefixes = this.affects?.(input, result) ?? [];\n for (const prefix of new Set(prefixes)) {\n invalidateQueriesForRuntime(this.runtimeState, prefix, true);\n }\n }\n\n return result;\n }\n\n abort(): void {\n if (this.state.status !== 'pending') {\n return;\n }\n\n this.generation += 1;\n this.controller?.abort();\n this.controller = null;\n this.setState({ status: 'idle', error: null, result: null });\n }\n\n reset(): void {\n this.generation += 1;\n this.controller?.abort();\n this.controller = null;\n this.setState({ status: 'idle', error: null, result: null });\n }\n}\n\nexport function createMutation<TInput, TResult>(\n options: MutationOptions<TInput, TResult>\n): Mutation<TInput, TResult> {\n const instance = getCurrentComponentInstance();\n const runtimeState = resolveDataRuntimeState(options.runtime);\n\n if (!instance) {\n return new MutationCell(options, runtimeState) as unknown as Mutation<\n TInput,\n TResult\n >;\n }\n\n const hookIndex = claimHookIndex(instance, 'mutation');\n ensureMutationCleanup(runtimeState, instance);\n\n const slotStore = getMutationSlotStore(runtimeState, instance);\n const existing = slotStore.get(hookIndex) as\n | MutationCell<TInput, TResult>\n | undefined;\n if (existing) {\n existing.setOptions(options);\n return existing as unknown as Mutation<TInput, TResult>;\n }\n\n const created = new MutationCell(options, runtimeState);\n slotStore.set(hookIndex, created as MutationCell<unknown, unknown>);\n return created as unknown as Mutation<TInput, TResult>;\n}\n"],"mappings":";;;;;;AAoBA,IAAa,eAAb,MAA2C;CAezC,YACE,SACA,cACA;gBAjBwB,qBAAqB;oBAKF;oBACxB;eAEoB;GACvC,QAAQ;GACR,OAAO;GACP,QAAQ;EACV;EAME,KAAK,eAAe;EACpB,KAAK,SAAS,QAAQ;EACtB,KAAK,UAAU,QAAQ;EACvB,KAAK,eAAe,QAAQ;CAC9B;CAEA,WAAW,SAAiD;EAC1D,KAAK,SAAS,QAAQ;EACtB,KAAK,UAAU,QAAQ;EACvB,KAAK,eAAe,QAAQ;CAC9B;CAEA,IAAI,SAAmD;EACrD,mBAAmB,KAAK,MAAM;EAC9B,OAAO,KAAK,MAAM;CACpB;CAEA,IAAI,UAAmB;EACrB,mBAAmB,KAAK,MAAM;EAC9B,OAAO,KAAK,MAAM,WAAW;CAC/B;CAEA,IAAI,QAAmB;EACrB,mBAAmB,KAAK,MAAM;EAC9B,OAAO,KAAK,MAAM;CACpB;CAEA,IAAI,SAAyB;EAC3B,mBAAmB,KAAK,MAAM;EAC9B,OAAO,KAAK,MAAM;CACpB;CAEA,SAAiB,MAA8C;EAC7D,KAAK,QAAQ;GACX,GAAG,KAAK;GACR,GAAG;EACL;EACA,aAAa,KAAK,MAAM;CAC1B;CAEA,MAAM,QAAQ,OAAiC;EAC7C,KAAK,cAAc;EACnB,MAAM,aAAa,KAAK;EAExB,KAAK,YAAY,MAAM;EACvB,MAAM,aAAa,IAAI,gBAAgB;EACvC,KAAK,aAAa;EAElB,KAAK,SAAS;GAAE,QAAQ;GAAW,OAAO;GAAM,QAAQ;EAAK,CAAC;EAE9D,IAAI;EACJ,IAAI;GACF,SAAS,MAAM,KAAK,OAAO,OAAO,EAAE,QAAQ,WAAW,OAAO,CAAC;EACjE,SAAS,OAAO;GACd,IAAI,KAAK,eAAe,cAAc,KAAK,eAAe,YACxD,MAAM;GAGR,IAAI,aAAa,OAAO,WAAW,MAAM,GAAG;IAC1C,KAAK,SAAS;KAAE,QAAQ;KAAQ,OAAO;IAAK,CAAC;IAC7C,MAAM;GACR;GAEA,KAAK,SAAS;IACZ,QAAQ;IACR,OAAO,wBAAwB,OAAO,wBAAwB;GAChE,CAAC;GACD,MAAM;EACR;EAEA,IAAI,KAAK,eAAe,cAAc,KAAK,eAAe,YACxD,OAAO;EAGT,KAAK,SAAS;GAAE,QAAQ;GAAW,OAAO;GAAM;EAAO,CAAC;EAExD,IAAI,KAAK,iBAAiB,cAAc;GACtC,MAAM,WAAW,KAAK,UAAU,OAAO,MAAM,KAAK,CAAC;GACnD,KAAK,MAAM,UAAU,IAAI,IAAI,QAAQ,GACnC,4BAA4B,KAAK,cAAc,QAAQ,IAAI;EAE/D;EAEA,OAAO;CACT;CAEA,QAAc;EACZ,IAAI,KAAK,MAAM,WAAW,WACxB;EAGF,KAAK,cAAc;EACnB,KAAK,YAAY,MAAM;EACvB,KAAK,aAAa;EAClB,KAAK,SAAS;GAAE,QAAQ;GAAQ,OAAO;GAAM,QAAQ;EAAK,CAAC;CAC7D;CAEA,QAAc;EACZ,KAAK,cAAc;EACnB,KAAK,YAAY,MAAM;EACvB,KAAK,aAAa;EAClB,KAAK,SAAS;GAAE,QAAQ;GAAQ,OAAO;GAAM,QAAQ;EAAK,CAAC;CAC7D;AACF;AAEA,SAAgB,eACd,SAC2B;CAC3B,MAAM,WAAW,4BAA4B;CAC7C,MAAM,eAAe,wBAAwB,QAAQ,OAAO;CAE5D,IAAI,CAAC,UACH,OAAO,IAAI,aAAa,SAAS,YAAY;CAM/C,MAAM,YAAY,eAAe,UAAU,UAAU;CACrD,sBAAsB,cAAc,QAAQ;CAE5C,MAAM,YAAY,qBAAqB,cAAc,QAAQ;CAC7D,MAAM,WAAW,UAAU,IAAI,SAAS;CAGxC,IAAI,UAAU;EACZ,SAAS,WAAW,OAAO;EAC3B,OAAO;CACT;CAEA,MAAM,UAAU,IAAI,aAAa,SAAS,YAAY;CACtD,UAAU,IAAI,WAAW,OAAyC;CAClE,OAAO;AACT"}
1
+ {"version":3,"file":"mutation-cell.js","names":[],"sources":["../../src/data/mutation-cell.ts"],"sourcesContent":["import { claimHookIndex, getCurrentComponentInstance } from '../runtime';\nimport { recordReadableRead } from '../runtime';\nimport {\n ensureMutationCleanup,\n getMutationSlotStore,\n invalidateQueriesForRuntime,\n resolveDataRuntimeState,\n type DataRuntimeState,\n} from './data-runtime';\nimport {\n createReadableSource,\n isAbortError,\n normalizeAsyncDataError,\n notifySource,\n} from './shared';\nimport type { Mutation, MutationOptions, MutationRecord } from './types';\n\nexport class MutationCell<TInput, TResult> {\n private readonly source = createReadableSource();\n private readonly runtimeState: DataRuntimeState;\n private action: MutationOptions<TInput, TResult>['action'];\n private affects?: MutationOptions<TInput, TResult>['affects'];\n private afterSuccess?: MutationOptions<TInput, TResult>['afterSuccess'];\n private controller: AbortController | null = null;\n private generation = 0;\n\n private state: MutationRecord<TResult> = {\n status: 'idle',\n error: null,\n result: null,\n };\n\n constructor(\n options: MutationOptions<TInput, TResult>,\n runtimeState: DataRuntimeState\n ) {\n this.runtimeState = runtimeState;\n this.action = options.action;\n this.affects = options.affects;\n this.afterSuccess = options.afterSuccess;\n }\n\n setOptions(options: MutationOptions<TInput, TResult>): void {\n this.action = options.action;\n this.affects = options.affects;\n this.afterSuccess = options.afterSuccess;\n }\n\n get status(): 'idle' | 'pending' | 'success' | 'error' {\n recordReadableRead(this.source);\n return this.state.status;\n }\n\n get pending(): boolean {\n recordReadableRead(this.source);\n return this.state.status === 'pending';\n }\n\n get error(): {} | null {\n recordReadableRead(this.source);\n return this.state.error;\n }\n\n get result(): TResult | null {\n recordReadableRead(this.source);\n return this.state.result;\n }\n\n private setState(next: Partial<MutationRecord<TResult>>): void {\n this.state = {\n ...this.state,\n ...next,\n };\n notifySource(this.source);\n }\n\n async execute(input: TInput): Promise<TResult> {\n this.generation += 1;\n const generation = this.generation;\n\n this.controller?.abort();\n const controller = new AbortController();\n this.controller = controller;\n\n this.setState({ status: 'pending', error: null, result: null });\n\n let result: TResult;\n try {\n result = await this.action(input, { signal: controller.signal });\n } catch (error) {\n if (this.generation !== generation || this.controller !== controller) {\n throw error;\n }\n\n if (isAbortError(error, controller.signal)) {\n this.setState({ status: 'idle', error: null });\n throw error;\n }\n\n this.setState({\n status: 'error',\n error: normalizeAsyncDataError(error, 'Unknown mutation error'),\n });\n throw error;\n }\n\n if (this.generation !== generation || this.controller !== controller) {\n return result;\n }\n\n this.setState({ status: 'success', error: null, result });\n\n if (this.afterSuccess === 'invalidate') {\n const prefixes = this.affects?.(input, result) ?? [];\n for (const prefix of new Set(prefixes)) {\n invalidateQueriesForRuntime(this.runtimeState, prefix, true);\n }\n }\n\n return result;\n }\n\n abort(): void {\n if (this.state.status !== 'pending') {\n return;\n }\n\n this.generation += 1;\n this.controller?.abort();\n this.controller = null;\n this.setState({ status: 'idle', error: null, result: null });\n }\n\n reset(): void {\n this.generation += 1;\n this.controller?.abort();\n this.controller = null;\n this.setState({ status: 'idle', error: null, result: null });\n }\n}\n\nexport function createMutation<TInput, TResult>(\n options: MutationOptions<TInput, TResult>\n): Mutation<TInput, TResult> {\n const instance = getCurrentComponentInstance();\n const runtimeState = resolveDataRuntimeState(options.runtime);\n\n if (!instance) {\n return new MutationCell(options, runtimeState) as unknown as Mutation<\n TInput,\n TResult\n >;\n }\n\n const hookIndex = claimHookIndex(instance, 'mutation');\n ensureMutationCleanup(runtimeState, instance);\n\n const slotStore = getMutationSlotStore(runtimeState, instance);\n const existing = slotStore.get(hookIndex) as\n | MutationCell<TInput, TResult>\n | undefined;\n if (existing) {\n existing.setOptions(options);\n return existing as unknown as Mutation<TInput, TResult>;\n }\n\n const created = new MutationCell(options, runtimeState);\n slotStore.set(hookIndex, created as MutationCell<unknown, unknown>);\n return created as unknown as Mutation<TInput, TResult>;\n}\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
- import { logger } from "../dev/logger.js";
1
+ import { logger } from "../common/logger.js";
2
2
  import { enqueueRuntimeTask } from "../runtime/access.js";
3
3
  import { recordReadableRead } from "../runtime/readable.js";
4
4
  import { claimHookIndex, getCurrentComponentInstance } from "../runtime/component-scope.js";
5
- import "../runtime/component.js";
5
+ import "../runtime/index.js";
6
6
  import { ensureQueryCleanup, getQuerySlotStore, resolveDataRuntimeState } from "./data-runtime.js";
7
7
  import { createReadableSource, isAbortError, normalizeAsyncDataError, notifySource } from "./shared.js";
8
8
  //#region src/data/query-cell.ts
@@ -1 +1 @@
1
- {"version":3,"file":"query-cell.js","names":[],"sources":["../../src/data/query-cell.ts"],"sourcesContent":["import { logger } from '../dev/logger';\nimport { enqueueRuntimeTask } from '../runtime/access';\nimport {\n claimHookIndex,\n getCurrentComponentInstance,\n type ComponentInstance,\n} from '../runtime/component';\nimport { recordReadableRead } from '../runtime/readable';\nimport {\n ensureQueryCleanup,\n getQuerySlotStore,\n resolveDataRuntimeState,\n} from './data-runtime';\nimport {\n createReadableSource,\n isAbortError,\n normalizeAsyncDataError,\n notifySource,\n} from './shared';\nimport type {\n Query,\n QueryDefinitionField,\n QueryOptions,\n QueryState,\n} from './types';\n\nconst RECONCILE_MAX_ATTEMPTS = 3;\nconst RECONCILE_RETRY_DELAY_MS = 25;\n\nexport class QueryCell<T> {\n private readonly source = createReadableSource();\n private readonly key: string;\n private readonly cache: Map<string, QueryCell<unknown>>;\n private options: QueryOptions<T>;\n private controller: AbortController | null = null;\n private generation = 0;\n private startQueued = false;\n private pendingRefresh: Promise<void> | null = null;\n private pendingRefreshResolve: (() => void) | null = null;\n private reconcileAttemptCount = 0;\n private destroyed = false;\n private ownerCount = 0;\n private readonly owners = new Map<ComponentInstance, Set<number>>();\n private readonly warnedDefinitionConflictKeys = new Set<string>();\n\n private state: QueryState<T> = {\n data: null,\n error: null,\n loading: true,\n refreshing: false,\n stale: false,\n consistency: 'fresh',\n staleReason: null,\n };\n\n constructor(\n options: QueryOptions<T>,\n key: string,\n cache: Map<string, QueryCell<unknown>>\n ) {\n this.options = options;\n this.key = key;\n this.cache = cache;\n }\n\n attach(instance: ComponentInstance, hookIndex: number): void {\n let hooks = this.owners.get(instance);\n if (!hooks) {\n hooks = new Set();\n this.owners.set(instance, hooks);\n }\n\n if (hooks.has(hookIndex)) {\n return;\n }\n\n hooks.add(hookIndex);\n this.ownerCount += 1;\n }\n\n detach(instance: ComponentInstance, hookIndex: number): void {\n const hooks = this.owners.get(instance);\n if (!hooks || !hooks.delete(hookIndex)) {\n return;\n }\n\n this.ownerCount -= 1;\n if (hooks.size === 0) {\n this.owners.delete(instance);\n }\n\n if (this.ownerCount <= 0) {\n this.destroy();\n }\n }\n\n warnOnConflictingDefinition(options: QueryOptions<T>): void {\n const conflicts = this.getDefinitionConflicts(options);\n if (conflicts.length === 0) {\n return;\n }\n\n const conflictKey = conflicts.join(',');\n if (this.warnedDefinitionConflictKeys.has(conflictKey)) {\n return;\n }\n\n this.warnedDefinitionConflictKeys.add(conflictKey);\n\n const callbackLabel =\n conflicts.length === 1\n ? `callback \\`${conflicts[0]}\\``\n : `callbacks ${conflicts.map((field) => `\\`${field}\\``).join(', ')}`;\n\n logger.warn(\n `[askr] Conflicting shared query definition for key \"${this.key}\". ` +\n `Shared queries are canonical by key, so reuse the same ${callbackLabel} ` +\n 'for every reader of that key.'\n );\n }\n\n private destroy(): void {\n if (this.destroyed) {\n return;\n }\n\n this.destroyed = true;\n this.controller?.abort();\n this.controller = null;\n this.startQueued = false;\n this.reconcileAttemptCount = 0;\n this.ownerCount = 0;\n this.owners.clear();\n this.cache.delete(this.key);\n this.finishPendingRefresh();\n }\n\n private getDefinitionConflicts(\n options: QueryOptions<T>\n ): QueryDefinitionField[] {\n const conflicts: QueryDefinitionField[] = [];\n\n if (this.options.fetch !== options.fetch) {\n conflicts.push('fetch');\n }\n\n if (this.options.isConsistent !== options.isConsistent) {\n conflicts.push('isConsistent');\n }\n\n if (this.options.reconcile !== options.reconcile) {\n conflicts.push('reconcile');\n }\n\n return conflicts;\n }\n\n get data(): T | null {\n recordReadableRead(this.source);\n return this.state.data;\n }\n\n get error(): {} | null {\n recordReadableRead(this.source);\n return this.state.error;\n }\n\n get loading(): boolean {\n recordReadableRead(this.source);\n return this.state.loading;\n }\n\n get refreshing(): boolean {\n recordReadableRead(this.source);\n return this.state.refreshing;\n }\n\n get stale(): boolean {\n recordReadableRead(this.source);\n return this.state.stale;\n }\n\n get consistency(): QueryState<T>['consistency'] {\n recordReadableRead(this.source);\n return this.state.consistency;\n }\n\n get staleReason(): QueryState<T>['staleReason'] {\n recordReadableRead(this.source);\n return this.state.staleReason;\n }\n\n ensureStarted(): void {\n if (\n this.destroyed ||\n this.state.data !== null ||\n this.pendingRefresh ||\n this.startQueued\n ) {\n return;\n }\n\n this.queueStart('initial');\n }\n\n refresh(): Promise<void> {\n if (this.destroyed) {\n return Promise.resolve();\n }\n\n if (this.pendingRefresh) {\n return this.pendingRefresh;\n }\n\n this.queueStart('manual');\n return this.pendingRefresh ?? Promise.resolve();\n }\n\n markPendingWrite(): void {\n if (this.destroyed) {\n return;\n }\n\n if (this.state.data === null) {\n return;\n }\n\n this.setState({\n loading: false,\n error: null,\n refreshing: true,\n stale: true,\n consistency: 'pending-write',\n staleReason: null,\n });\n }\n\n private queueStart(\n reason: 'initial' | 'manual' | 'invalidate' | 'pending-write'\n ): void {\n if (this.destroyed) {\n return;\n }\n\n this.startQueued = true;\n this.pendingRefresh = new Promise<void>((resolve) => {\n this.pendingRefreshResolve = resolve;\n enqueueRuntimeTask(() => {\n this.startQueued = false;\n if (this.destroyed) {\n this.finishPendingRefresh();\n return;\n }\n void this.start(reason).finally(() => {\n this.finishPendingRefresh();\n });\n });\n });\n }\n\n private finishPendingRefresh(): void {\n const resolve = this.pendingRefreshResolve;\n this.pendingRefresh = null;\n this.pendingRefreshResolve = null;\n resolve?.();\n }\n\n private setState(next: Partial<QueryState<T>>): void {\n if (this.destroyed) {\n return;\n }\n\n this.state = {\n ...this.state,\n ...next,\n };\n notifySource(this.source);\n }\n\n private async start(\n reason: 'initial' | 'manual' | 'invalidate' | 'pending-write'\n ): Promise<void> {\n if (this.destroyed) {\n return;\n }\n\n this.generation += 1;\n const generation = this.generation;\n\n this.controller?.abort();\n const controller = new AbortController();\n this.controller = controller;\n\n const hasData = this.state.data !== null;\n this.setState({\n loading: !hasData,\n refreshing: hasData,\n stale: hasData,\n consistency:\n reason === 'pending-write'\n ? 'pending-write'\n : hasData\n ? 'refreshing'\n : 'fresh',\n error: null,\n staleReason: null,\n });\n\n let nextData: T;\n try {\n nextData = await this.options.fetch({ signal: controller.signal });\n } catch (error) {\n if (\n this.destroyed ||\n this.generation !== generation ||\n this.controller !== controller\n ) {\n return;\n }\n\n if (isAbortError(error, controller.signal)) {\n this.setState(\n hasData\n ? {\n loading: false,\n refreshing: false,\n stale: true,\n consistency: 'stale',\n error: null,\n staleReason: 'aborted',\n }\n : {\n loading: true,\n refreshing: false,\n stale: false,\n consistency: 'fresh',\n error: null,\n staleReason: null,\n }\n );\n return;\n }\n\n this.setState({\n loading: false,\n refreshing: false,\n stale: true,\n consistency: 'stale',\n error: normalizeAsyncDataError(error, 'Unknown query error'),\n staleReason: 'error',\n });\n return;\n }\n\n if (\n this.destroyed ||\n this.generation !== generation ||\n this.controller !== controller\n ) {\n return;\n }\n\n const isConsistent = this.options.isConsistent?.(nextData) ?? true;\n if (!isConsistent) {\n this.setState({\n data: nextData,\n loading: false,\n refreshing: false,\n stale: true,\n consistency: 'stale',\n staleReason: 'inconsistent',\n });\n await this.reconcile(nextData);\n return;\n }\n\n this.reconcileAttemptCount = 0;\n this.setState({\n data: nextData,\n loading: false,\n refreshing: false,\n stale: false,\n consistency: 'fresh',\n error: null,\n staleReason: null,\n });\n }\n\n private async reconcile(data: T): Promise<void> {\n const shouldRetry =\n this.options.reconcile?.(data, { key: this.options.key }) ?? false;\n\n if (!shouldRetry || this.destroyed) {\n return;\n }\n\n this.reconcileAttemptCount += 1;\n if (this.reconcileAttemptCount > RECONCILE_MAX_ATTEMPTS) {\n this.setState({\n consistency: 'stale',\n refreshing: false,\n staleReason: 'inconsistent',\n });\n return;\n }\n\n await new Promise<void>((resolve) =>\n setTimeout(resolve, RECONCILE_RETRY_DELAY_MS)\n );\n if (this.destroyed || this.state.consistency === 'fresh') {\n return;\n }\n\n await this.refresh();\n }\n}\n\nexport function createQuery<T extends {}>(options: QueryOptions<T>): Query<T> {\n const instance = getCurrentComponentInstance();\n const runtimeState = resolveDataRuntimeState(options.runtime);\n const cache = runtimeState.queryCache;\n if (!instance) {\n let cell = cache.get(options.key) as QueryCell<T> | undefined;\n if (!cell) {\n cell = new QueryCell(options, options.key, cache);\n cache.set(options.key, cell as QueryCell<unknown>);\n cell.ensureStarted();\n } else {\n cell.warnOnConflictingDefinition(options);\n }\n return cell as unknown as Query<T>;\n }\n\n const hookIndex = claimHookIndex(instance, 'query');\n ensureQueryCleanup(runtimeState, instance);\n\n const slotStore = getQuerySlotStore(runtimeState, instance);\n const existingSlot = slotStore.get(hookIndex);\n if (existingSlot && existingSlot.key === options.key) {\n (existingSlot.cell as QueryCell<T>).warnOnConflictingDefinition(options);\n return existingSlot.cell as unknown as Query<T>;\n }\n\n if (existingSlot) {\n existingSlot.cell.detach(instance, hookIndex);\n }\n\n let cell = cache.get(options.key) as QueryCell<T> | undefined;\n if (!cell) {\n cell = new QueryCell(options, options.key, cache);\n cache.set(options.key, cell as QueryCell<unknown>);\n cell.ensureStarted();\n } else {\n cell.warnOnConflictingDefinition(options);\n }\n\n slotStore.set(hookIndex, {\n key: options.key,\n cell: cell as QueryCell<unknown>,\n });\n cell.attach(instance, hookIndex);\n return cell as unknown as Query<T>;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"query-cell.js","names":[],"sources":["../../src/data/query-cell.ts"],"sourcesContent":["import { logger } from '../common/logger';\nimport { enqueueRuntimeTask } from '../runtime';\nimport {\n claimHookIndex,\n getCurrentComponentInstance,\n type ComponentInstance,\n} from '../runtime';\nimport { recordReadableRead } from '../runtime';\nimport {\n ensureQueryCleanup,\n getQuerySlotStore,\n resolveDataRuntimeState,\n} from './data-runtime';\nimport {\n createReadableSource,\n isAbortError,\n normalizeAsyncDataError,\n notifySource,\n} from './shared';\nimport type {\n Query,\n QueryDefinitionField,\n QueryOptions,\n QueryState,\n} from './types';\n\nconst RECONCILE_MAX_ATTEMPTS = 3;\nconst RECONCILE_RETRY_DELAY_MS = 25;\n\nexport class QueryCell<T> {\n private readonly source = createReadableSource();\n private readonly key: string;\n private readonly cache: Map<string, QueryCell<unknown>>;\n private options: QueryOptions<T>;\n private controller: AbortController | null = null;\n private generation = 0;\n private startQueued = false;\n private pendingRefresh: Promise<void> | null = null;\n private pendingRefreshResolve: (() => void) | null = null;\n private reconcileAttemptCount = 0;\n private destroyed = false;\n private ownerCount = 0;\n private readonly owners = new Map<ComponentInstance, Set<number>>();\n private readonly warnedDefinitionConflictKeys = new Set<string>();\n\n private state: QueryState<T> = {\n data: null,\n error: null,\n loading: true,\n refreshing: false,\n stale: false,\n consistency: 'fresh',\n staleReason: null,\n };\n\n constructor(\n options: QueryOptions<T>,\n key: string,\n cache: Map<string, QueryCell<unknown>>\n ) {\n this.options = options;\n this.key = key;\n this.cache = cache;\n }\n\n attach(instance: ComponentInstance, hookIndex: number): void {\n let hooks = this.owners.get(instance);\n if (!hooks) {\n hooks = new Set();\n this.owners.set(instance, hooks);\n }\n\n if (hooks.has(hookIndex)) {\n return;\n }\n\n hooks.add(hookIndex);\n this.ownerCount += 1;\n }\n\n detach(instance: ComponentInstance, hookIndex: number): void {\n const hooks = this.owners.get(instance);\n if (!hooks || !hooks.delete(hookIndex)) {\n return;\n }\n\n this.ownerCount -= 1;\n if (hooks.size === 0) {\n this.owners.delete(instance);\n }\n\n if (this.ownerCount <= 0) {\n this.destroy();\n }\n }\n\n warnOnConflictingDefinition(options: QueryOptions<T>): void {\n const conflicts = this.getDefinitionConflicts(options);\n if (conflicts.length === 0) {\n return;\n }\n\n const conflictKey = conflicts.join(',');\n if (this.warnedDefinitionConflictKeys.has(conflictKey)) {\n return;\n }\n\n this.warnedDefinitionConflictKeys.add(conflictKey);\n\n const callbackLabel =\n conflicts.length === 1\n ? `callback \\`${conflicts[0]}\\``\n : `callbacks ${conflicts.map((field) => `\\`${field}\\``).join(', ')}`;\n\n logger.warn(\n `[askr] Conflicting shared query definition for key \"${this.key}\". ` +\n `Shared queries are canonical by key, so reuse the same ${callbackLabel} ` +\n 'for every reader of that key.'\n );\n }\n\n private destroy(): void {\n if (this.destroyed) {\n return;\n }\n\n this.destroyed = true;\n this.controller?.abort();\n this.controller = null;\n this.startQueued = false;\n this.reconcileAttemptCount = 0;\n this.ownerCount = 0;\n this.owners.clear();\n this.cache.delete(this.key);\n this.finishPendingRefresh();\n }\n\n private getDefinitionConflicts(\n options: QueryOptions<T>\n ): QueryDefinitionField[] {\n const conflicts: QueryDefinitionField[] = [];\n\n if (this.options.fetch !== options.fetch) {\n conflicts.push('fetch');\n }\n\n if (this.options.isConsistent !== options.isConsistent) {\n conflicts.push('isConsistent');\n }\n\n if (this.options.reconcile !== options.reconcile) {\n conflicts.push('reconcile');\n }\n\n return conflicts;\n }\n\n get data(): T | null {\n recordReadableRead(this.source);\n return this.state.data;\n }\n\n get error(): {} | null {\n recordReadableRead(this.source);\n return this.state.error;\n }\n\n get loading(): boolean {\n recordReadableRead(this.source);\n return this.state.loading;\n }\n\n get refreshing(): boolean {\n recordReadableRead(this.source);\n return this.state.refreshing;\n }\n\n get stale(): boolean {\n recordReadableRead(this.source);\n return this.state.stale;\n }\n\n get consistency(): QueryState<T>['consistency'] {\n recordReadableRead(this.source);\n return this.state.consistency;\n }\n\n get staleReason(): QueryState<T>['staleReason'] {\n recordReadableRead(this.source);\n return this.state.staleReason;\n }\n\n ensureStarted(): void {\n if (\n this.destroyed ||\n this.state.data !== null ||\n this.pendingRefresh ||\n this.startQueued\n ) {\n return;\n }\n\n this.queueStart('initial');\n }\n\n refresh(): Promise<void> {\n if (this.destroyed) {\n return Promise.resolve();\n }\n\n if (this.pendingRefresh) {\n return this.pendingRefresh;\n }\n\n this.queueStart('manual');\n return this.pendingRefresh ?? Promise.resolve();\n }\n\n markPendingWrite(): void {\n if (this.destroyed) {\n return;\n }\n\n if (this.state.data === null) {\n return;\n }\n\n this.setState({\n loading: false,\n error: null,\n refreshing: true,\n stale: true,\n consistency: 'pending-write',\n staleReason: null,\n });\n }\n\n private queueStart(\n reason: 'initial' | 'manual' | 'invalidate' | 'pending-write'\n ): void {\n if (this.destroyed) {\n return;\n }\n\n this.startQueued = true;\n this.pendingRefresh = new Promise<void>((resolve) => {\n this.pendingRefreshResolve = resolve;\n enqueueRuntimeTask(() => {\n this.startQueued = false;\n if (this.destroyed) {\n this.finishPendingRefresh();\n return;\n }\n void this.start(reason).finally(() => {\n this.finishPendingRefresh();\n });\n });\n });\n }\n\n private finishPendingRefresh(): void {\n const resolve = this.pendingRefreshResolve;\n this.pendingRefresh = null;\n this.pendingRefreshResolve = null;\n resolve?.();\n }\n\n private setState(next: Partial<QueryState<T>>): void {\n if (this.destroyed) {\n return;\n }\n\n this.state = {\n ...this.state,\n ...next,\n };\n notifySource(this.source);\n }\n\n private async start(\n reason: 'initial' | 'manual' | 'invalidate' | 'pending-write'\n ): Promise<void> {\n if (this.destroyed) {\n return;\n }\n\n this.generation += 1;\n const generation = this.generation;\n\n this.controller?.abort();\n const controller = new AbortController();\n this.controller = controller;\n\n const hasData = this.state.data !== null;\n this.setState({\n loading: !hasData,\n refreshing: hasData,\n stale: hasData,\n consistency:\n reason === 'pending-write'\n ? 'pending-write'\n : hasData\n ? 'refreshing'\n : 'fresh',\n error: null,\n staleReason: null,\n });\n\n let nextData: T;\n try {\n nextData = await this.options.fetch({ signal: controller.signal });\n } catch (error) {\n if (\n this.destroyed ||\n this.generation !== generation ||\n this.controller !== controller\n ) {\n return;\n }\n\n if (isAbortError(error, controller.signal)) {\n this.setState(\n hasData\n ? {\n loading: false,\n refreshing: false,\n stale: true,\n consistency: 'stale',\n error: null,\n staleReason: 'aborted',\n }\n : {\n loading: true,\n refreshing: false,\n stale: false,\n consistency: 'fresh',\n error: null,\n staleReason: null,\n }\n );\n return;\n }\n\n this.setState({\n loading: false,\n refreshing: false,\n stale: true,\n consistency: 'stale',\n error: normalizeAsyncDataError(error, 'Unknown query error'),\n staleReason: 'error',\n });\n return;\n }\n\n if (\n this.destroyed ||\n this.generation !== generation ||\n this.controller !== controller\n ) {\n return;\n }\n\n const isConsistent = this.options.isConsistent?.(nextData) ?? true;\n if (!isConsistent) {\n this.setState({\n data: nextData,\n loading: false,\n refreshing: false,\n stale: true,\n consistency: 'stale',\n staleReason: 'inconsistent',\n });\n await this.reconcile(nextData);\n return;\n }\n\n this.reconcileAttemptCount = 0;\n this.setState({\n data: nextData,\n loading: false,\n refreshing: false,\n stale: false,\n consistency: 'fresh',\n error: null,\n staleReason: null,\n });\n }\n\n private async reconcile(data: T): Promise<void> {\n const shouldRetry =\n this.options.reconcile?.(data, { key: this.options.key }) ?? false;\n\n if (!shouldRetry || this.destroyed) {\n return;\n }\n\n this.reconcileAttemptCount += 1;\n if (this.reconcileAttemptCount > RECONCILE_MAX_ATTEMPTS) {\n this.setState({\n consistency: 'stale',\n refreshing: false,\n staleReason: 'inconsistent',\n });\n return;\n }\n\n await new Promise<void>((resolve) =>\n setTimeout(resolve, RECONCILE_RETRY_DELAY_MS)\n );\n if (this.destroyed || this.state.consistency === 'fresh') {\n return;\n }\n\n await this.refresh();\n }\n}\n\nexport function createQuery<T extends {}>(options: QueryOptions<T>): Query<T> {\n const instance = getCurrentComponentInstance();\n const runtimeState = resolveDataRuntimeState(options.runtime);\n const cache = runtimeState.queryCache;\n if (!instance) {\n let cell = cache.get(options.key) as QueryCell<T> | undefined;\n if (!cell) {\n cell = new QueryCell(options, options.key, cache);\n cache.set(options.key, cell as QueryCell<unknown>);\n cell.ensureStarted();\n } else {\n cell.warnOnConflictingDefinition(options);\n }\n return cell as unknown as Query<T>;\n }\n\n const hookIndex = claimHookIndex(instance, 'query');\n ensureQueryCleanup(runtimeState, instance);\n\n const slotStore = getQuerySlotStore(runtimeState, instance);\n const existingSlot = slotStore.get(hookIndex);\n if (existingSlot && existingSlot.key === options.key) {\n (existingSlot.cell as QueryCell<T>).warnOnConflictingDefinition(options);\n return existingSlot.cell as unknown as Query<T>;\n }\n\n if (existingSlot) {\n existingSlot.cell.detach(instance, hookIndex);\n }\n\n let cell = cache.get(options.key) as QueryCell<T> | undefined;\n if (!cell) {\n cell = new QueryCell(options, options.key, cache);\n cache.set(options.key, cell as QueryCell<unknown>);\n cell.ensureStarted();\n } else {\n cell.warnOnConflictingDefinition(options);\n }\n\n slotStore.set(hookIndex, {\n key: options.key,\n cell: cell as QueryCell<unknown>,\n });\n cell.attach(instance, hookIndex);\n return cell as unknown as Query<T>;\n}\n"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { markReactivePropsDirtySource, markReadableDerivedSubscribersDirty, notifyReadableReaders } from "../runtime/readable.js";
2
+ import "../runtime/index.js";
2
3
  //#region src/data/shared.ts
3
4
  function createReadableSource() {
4
5
  return (() => void 0);
@@ -1 +1 @@
1
- {"version":3,"file":"shared.js","names":[],"sources":["../../src/data/shared.ts"],"sourcesContent":["import {\n markReadableDerivedSubscribersDirty,\n markReactivePropsDirtySource,\n notifyReadableReaders,\n type ReadableSource,\n} from '../runtime/readable';\n\nexport function createReadableSource(): ReadableSource<unknown> {\n return (() => undefined) as ReadableSource<unknown>;\n}\n\nexport function notifySource(source: ReadableSource<unknown>): void {\n markReadableDerivedSubscribersDirty(source);\n markReactivePropsDirtySource(source);\n notifyReadableReaders(source);\n}\n\nexport function isAbortError(error: unknown, signal: AbortSignal): boolean {\n return (\n signal.aborted ||\n (error instanceof Error && error.name === 'AbortError') ||\n (typeof DOMException !== 'undefined' &&\n error instanceof DOMException &&\n error.name === 'AbortError')\n );\n}\n\nexport function normalizeAsyncDataError(\n error: unknown,\n fallbackMessage: string\n): {} {\n return error ?? new Error(fallbackMessage);\n}\n"],"mappings":";;AAOA,SAAgB,uBAAgD;CAC9D,cAAc;AAChB;AAEA,SAAgB,aAAa,QAAuC;CAClE,oCAAoC,MAAM;CAC1C,6BAA6B,MAAM;CACnC,sBAAsB,MAAM;AAC9B;AAEA,SAAgB,aAAa,OAAgB,QAA8B;CACzE,OACE,OAAO,WACN,iBAAiB,SAAS,MAAM,SAAS,gBACzC,OAAO,iBAAiB,eACvB,iBAAiB,gBACjB,MAAM,SAAS;AAErB;AAEA,SAAgB,wBACd,OACA,iBACI;CACJ,OAAO,SAAS,IAAI,MAAM,eAAe;AAC3C"}
1
+ {"version":3,"file":"shared.js","names":[],"sources":["../../src/data/shared.ts"],"sourcesContent":["import {\n markReadableDerivedSubscribersDirty,\n markReactivePropsDirtySource,\n notifyReadableReaders,\n type ReadableSource,\n} from '../runtime';\n\nexport function createReadableSource(): ReadableSource<unknown> {\n return (() => undefined) as ReadableSource<unknown>;\n}\n\nexport function notifySource(source: ReadableSource<unknown>): void {\n markReadableDerivedSubscribersDirty(source);\n markReactivePropsDirtySource(source);\n notifyReadableReaders(source);\n}\n\nexport function isAbortError(error: unknown, signal: AbortSignal): boolean {\n return (\n signal.aborted ||\n (error instanceof Error && error.name === 'AbortError') ||\n (typeof DOMException !== 'undefined' &&\n error instanceof DOMException &&\n error.name === 'AbortError')\n );\n}\n\nexport function normalizeAsyncDataError(\n error: unknown,\n fallbackMessage: string\n): {} {\n return error ?? new Error(fallbackMessage);\n}\n"],"mappings":";;;AAOA,SAAgB,uBAAgD;CAC9D,cAAc;AAChB;AAEA,SAAgB,aAAa,QAAuC;CAClE,oCAAoC,MAAM;CAC1C,6BAA6B,MAAM;CACnC,sBAAsB,MAAM;AAC9B;AAEA,SAAgB,aAAa,OAAgB,QAA8B;CACzE,OACE,OAAO,WACN,iBAAiB,SAAS,MAAM,SAAS,gBACzC,OAAO,iBAAiB,eACvB,iBAAiB,gBACjB,MAAM,SAAS;AAErB;AAEA,SAAgB,wBACd,OACA,iBACI;CACJ,OAAO,SAAS,IAAI,MAAM,eAAe;AAC3C"}
@@ -0,0 +1,2 @@
1
+ import { addInvalidationListener } from "./invalidation-listeners.js";
2
+ export { addInvalidationListener };
@@ -1,6 +1,6 @@
1
1
  import { JSXElement } from "../common/jsx.js";
2
+ import { DefaultPortal, Portal, PortalProps, definePortal } from "../runtime/portal.js";
2
3
  import { LayoutComponent, layout } from "./structures/layout.js";
3
4
  import { Slot, SlotProps } from "./structures/slot.js";
4
5
  import { Presence, PresenceProps } from "./structures/presence.js";
5
- import { DefaultPortal, Portal, PortalProps, definePortal } from "./structures/portal.js";
6
6
  export { DefaultPortal, type JSXElement, type LayoutComponent, Portal, type PortalProps, Presence, type PresenceProps, Slot, type SlotProps, definePortal, layout };
@@ -1,4 +1,4 @@
1
- import { DefaultPortal, Portal, definePortal } from "./structures/portal.js";
1
+ import { DefaultPortal, Portal, definePortal } from "../runtime/portal.js";
2
2
  import { layout } from "./structures/layout.js";
3
3
  import { Slot } from "./structures/slot.js";
4
4
  import { Presence } from "./structures/presence.js";
@@ -1,5 +1,4 @@
1
1
  import { State } from "../../runtime/state.js";
2
-
3
2
  //#region src/foundations/state/controllable.d.ts
4
3
  declare function isControlled<T>(value: T | undefined): value is T;
5
4
  declare function resolveControllable<T>(value: T | undefined, defaultValue: T): {
@@ -1 +1 @@
1
- {"version":3,"file":"controllable.d.ts","names":[],"sources":["../../../src/foundations/state/controllable.ts"],"mappings":";;;iBA0BgB,YAAA,IAAgB,KAAA,EAAO,CAAA,eAAgB,KAAA,IAAS,CAAC;AAAA,iBAIjD,mBAAA,IACd,KAAA,EAAO,CAAA,cACP,YAAA,EAAc,CAAA;EACX,KAAA,EAAO,CAAA;EAAG,YAAA;AAAA;AAAA,iBAQC,gBAAA,IAAoB,OAAA;EAClC,KAAA,EAAO,CAAA;EACP,YAAA,EAAc,CAAA;EACd,QAAA,IAAY,IAAA,EAAM,CAAA;EAClB,WAAA,IAAe,IAAA,EAAM,CAAA;AAAA;cAKF,CAAA;;;KAYT,iBAAA,MAAuB,KAAK,CAAC,CAAA;EAAO,YAAA;AAAA;;;;;;;iBAQhC,iBAAA,IAAqB,OAAA;EACnC,KAAA,EAAO,CAAA;EACP,YAAA,EAAc,CAAA;EACd,QAAA,IAAY,IAAA,EAAM,CAAA;AAAA,IAChB,iBAAA,CAAkB,CAAA"}
1
+ {"version":3,"file":"controllable.d.ts","names":[],"sources":["../../../src/foundations/state/controllable.ts"],"mappings":";;iBA0BgB,YAAA,IAAgB,KAAA,EAAO,CAAA,eAAgB,KAAA,IAAS,CAAC;AAAA,iBAIjD,mBAAA,IACd,KAAA,EAAO,CAAA,cACP,YAAA,EAAc,CAAA;EACX,KAAA,EAAO,CAAA;EAAG,YAAA;AAAA;AAAA,iBAQC,gBAAA,IAAoB,OAAA;EAClC,KAAA,EAAO,CAAA;EACP,YAAA,EAAc,CAAA;EACd,QAAA,IAAY,IAAA,EAAM,CAAA;EAClB,WAAA,IAAe,IAAA,EAAM,CAAA;AAAA;cAKF,CAAA;;;KAYT,iBAAA,MAAuB,KAAK,CAAC,CAAA;EAAO,YAAA;AAAA;;;;;;;iBAQhC,iBAAA,IAAqB,OAAA;EACnC,KAAA,EAAO,CAAA;EACP,YAAA,EAAc,CAAA;EACd,QAAA,IAAY,IAAA,EAAM,CAAA;AAAA,IAChB,iBAAA,CAAkB,CAAA"}
@@ -1,4 +1,5 @@
1
1
  import { state } from "../../runtime/state.js";
2
+ import "../../runtime/index.js";
2
3
  //#region src/foundations/state/controllable.ts
3
4
  /**
4
5
  * controllable
@@ -1 +1 @@
1
- {"version":3,"file":"controllable.js","names":[],"sources":["../../../src/foundations/state/controllable.ts"],"sourcesContent":["/**\n * controllable\n *\n * Small utilities for controlled vs uncontrolled components. These helpers are\n * intentionally minimal and do not manage state themselves; they help component\n * implementations make correct decisions about when to call `onChange` vs\n * update internal state.\n *\n * POLICY DECISIONS (LOCKED):\n *\n * 1. Controlled Detection\n * A value is \"controlled\" if it is not `undefined`.\n * This matches React conventions and is SSR-safe.\n *\n * 2. onChange Timing\n * - Controlled mode: onChange called immediately, no internal update\n * - Uncontrolled mode: internal state updated first, then onChange called\n * This ensures onChange sees the new value in both modes.\n *\n * 3. Value Equality\n * controllableState uses Object.is() to prevent unnecessary onChange calls.\n * This is intentional — strict equality, no deep comparison.\n */\n\nimport { state, type State } from '../../runtime/state';\n\nexport function isControlled<T>(value: T | undefined): value is T {\n return value !== undefined;\n}\n\nexport function resolveControllable<T>(\n value: T | undefined,\n defaultValue: T\n): { value: T; isControlled: boolean } {\n const controlled = isControlled(value);\n return {\n value: controlled ? (value as T) : defaultValue,\n isControlled: controlled,\n };\n}\n\nexport function makeControllable<T>(options: {\n value: T | undefined;\n defaultValue: T;\n onChange?: (next: T) => void;\n setInternal?: (next: T) => void;\n}) {\n const { value, defaultValue, onChange, setInternal } = options;\n const { isControlled } = resolveControllable(value, defaultValue);\n\n function set(next: T) {\n if (isControlled) {\n onChange?.(next);\n } else {\n setInternal?.(next);\n onChange?.(next);\n }\n }\n\n return { set, isControlled };\n}\n\nexport type ControllableState<T> = State<T> & { isControlled: boolean };\n\n/**\n * controllableState\n *\n * Hook-like primitive that mirrors `state()` semantics while supporting\n * controlled/uncontrolled behavior.\n */\nexport function controllableState<T>(options: {\n value: T | undefined;\n defaultValue: T;\n onChange?: (next: T) => void;\n}): ControllableState<T> {\n const isControlled = options.value !== undefined;\n const internal = isControlled ? null : state<T>(options.defaultValue);\n\n function read(): T {\n if (isControlled) {\n return options.value as T;\n }\n\n return internal!();\n }\n\n read.set = (nextOrUpdater: T | ((prev: T) => T)) => {\n const prev = read();\n const next =\n typeof nextOrUpdater === 'function'\n ? (nextOrUpdater as (p: T) => T)(prev)\n : (nextOrUpdater as T);\n\n if (Object.is(prev, next)) return;\n\n if (isControlled) {\n options.onChange?.(next);\n return;\n }\n\n internal!.set(nextOrUpdater as never);\n options.onChange?.(next);\n };\n\n (read as ControllableState<T>).isControlled = isControlled;\n return read as ControllableState<T>;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,SAAgB,aAAgB,OAAkC;CAChE,OAAO,UAAU;AACnB;AAEA,SAAgB,oBACd,OACA,cACqC;CACrC,MAAM,aAAa,aAAa,KAAK;CACrC,OAAO;EACL,OAAO,aAAc,QAAc;EACnC,cAAc;CAChB;AACF;AAEA,SAAgB,iBAAoB,SAKjC;CACD,MAAM,EAAE,OAAO,cAAc,UAAU,gBAAgB;CACvD,MAAM,EAAE,iBAAiB,oBAAoB,OAAO,YAAY;CAEhE,SAAS,IAAI,MAAS;EACpB,IAAI,cACF,WAAW,IAAI;OACV;GACL,cAAc,IAAI;GAClB,WAAW,IAAI;EACjB;CACF;CAEA,OAAO;EAAE;EAAK;CAAa;AAC7B;;;;;;;AAUA,SAAgB,kBAAqB,SAIZ;CACvB,MAAM,eAAe,QAAQ,UAAU;CACvC,MAAM,WAAW,eAAe,OAAO,MAAS,QAAQ,YAAY;CAEpE,SAAS,OAAU;EACjB,IAAI,cACF,OAAO,QAAQ;EAGjB,OAAO,SAAU;CACnB;CAEA,KAAK,OAAO,kBAAwC;EAClD,MAAM,OAAO,KAAK;EAClB,MAAM,OACJ,OAAO,kBAAkB,aACpB,cAA8B,IAAI,IAClC;EAEP,IAAI,OAAO,GAAG,MAAM,IAAI,GAAG;EAE3B,IAAI,cAAc;GAChB,QAAQ,WAAW,IAAI;GACvB;EACF;EAEA,SAAU,IAAI,aAAsB;EACpC,QAAQ,WAAW,IAAI;CACzB;CAEA,KAA+B,eAAe;CAC9C,OAAO;AACT"}
1
+ {"version":3,"file":"controllable.js","names":[],"sources":["../../../src/foundations/state/controllable.ts"],"sourcesContent":["/**\n * controllable\n *\n * Small utilities for controlled vs uncontrolled components. These helpers are\n * intentionally minimal and do not manage state themselves; they help component\n * implementations make correct decisions about when to call `onChange` vs\n * update internal state.\n *\n * POLICY DECISIONS (LOCKED):\n *\n * 1. Controlled Detection\n * A value is \"controlled\" if it is not `undefined`.\n * This matches React conventions and is SSR-safe.\n *\n * 2. onChange Timing\n * - Controlled mode: onChange called immediately, no internal update\n * - Uncontrolled mode: internal state updated first, then onChange called\n * This ensures onChange sees the new value in both modes.\n *\n * 3. Value Equality\n * controllableState uses Object.is() to prevent unnecessary onChange calls.\n * This is intentional — strict equality, no deep comparison.\n */\n\nimport { state, type State } from '../../runtime';\n\nexport function isControlled<T>(value: T | undefined): value is T {\n return value !== undefined;\n}\n\nexport function resolveControllable<T>(\n value: T | undefined,\n defaultValue: T\n): { value: T; isControlled: boolean } {\n const controlled = isControlled(value);\n return {\n value: controlled ? (value as T) : defaultValue,\n isControlled: controlled,\n };\n}\n\nexport function makeControllable<T>(options: {\n value: T | undefined;\n defaultValue: T;\n onChange?: (next: T) => void;\n setInternal?: (next: T) => void;\n}) {\n const { value, defaultValue, onChange, setInternal } = options;\n const { isControlled } = resolveControllable(value, defaultValue);\n\n function set(next: T) {\n if (isControlled) {\n onChange?.(next);\n } else {\n setInternal?.(next);\n onChange?.(next);\n }\n }\n\n return { set, isControlled };\n}\n\nexport type ControllableState<T> = State<T> & { isControlled: boolean };\n\n/**\n * controllableState\n *\n * Hook-like primitive that mirrors `state()` semantics while supporting\n * controlled/uncontrolled behavior.\n */\nexport function controllableState<T>(options: {\n value: T | undefined;\n defaultValue: T;\n onChange?: (next: T) => void;\n}): ControllableState<T> {\n const isControlled = options.value !== undefined;\n const internal = isControlled ? null : state<T>(options.defaultValue);\n\n function read(): T {\n if (isControlled) {\n return options.value as T;\n }\n\n return internal!();\n }\n\n read.set = (nextOrUpdater: T | ((prev: T) => T)) => {\n const prev = read();\n const next =\n typeof nextOrUpdater === 'function'\n ? (nextOrUpdater as (p: T) => T)(prev)\n : (nextOrUpdater as T);\n\n if (Object.is(prev, next)) return;\n\n if (isControlled) {\n options.onChange?.(next);\n return;\n }\n\n internal!.set(nextOrUpdater as never);\n options.onChange?.(next);\n };\n\n (read as ControllableState<T>).isControlled = isControlled;\n return read as ControllableState<T>;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,SAAgB,aAAgB,OAAkC;CAChE,OAAO,UAAU;AACnB;AAEA,SAAgB,oBACd,OACA,cACqC;CACrC,MAAM,aAAa,aAAa,KAAK;CACrC,OAAO;EACL,OAAO,aAAc,QAAc;EACnC,cAAc;CAChB;AACF;AAEA,SAAgB,iBAAoB,SAKjC;CACD,MAAM,EAAE,OAAO,cAAc,UAAU,gBAAgB;CACvD,MAAM,EAAE,iBAAiB,oBAAoB,OAAO,YAAY;CAEhE,SAAS,IAAI,MAAS;EACpB,IAAI,cACF,WAAW,IAAI;OACV;GACL,cAAc,IAAI;GAClB,WAAW,IAAI;EACjB;CACF;CAEA,OAAO;EAAE;EAAK;CAAa;AAC7B;;;;;;;AAUA,SAAgB,kBAAqB,SAIZ;CACvB,MAAM,eAAe,QAAQ,UAAU;CACvC,MAAM,WAAW,eAAe,OAAO,MAAS,QAAQ,YAAY;CAEpE,SAAS,OAAU;EACjB,IAAI,cACF,OAAO,QAAQ;EAGjB,OAAO,SAAU;CACnB;CAEA,KAAK,OAAO,kBAAwC;EAClD,MAAM,OAAO,KAAK;EAClB,MAAM,OACJ,OAAO,kBAAkB,aACpB,cAA8B,IAAI,IAClC;EAEP,IAAI,OAAO,GAAG,MAAM,IAAI,GAAG;EAE3B,IAAI,cAAc;GAChB,QAAQ,WAAW,IAAI;GACvB;EACF;EAEA,SAAU,IAAI,aAAsB;EACpC,QAAQ,WAAW,IAAI;CACzB;CAEA,KAA+B,eAAe;CAC9C,OAAO;AACT"}
@@ -1,8 +1,8 @@
1
1
  import { JSXElement } from "../../common/jsx.js";
2
+ import { DefaultPortal, Portal, PortalProps, definePortal } from "../../runtime/portal.js";
2
3
  import { LayoutComponent, layout } from "./layout.js";
3
4
  import { Slot, SlotProps } from "./slot.js";
4
5
  import { Presence, PresenceProps } from "./presence.js";
5
- import { DefaultPortal, Portal, PortalProps, definePortal } from "./portal.js";
6
6
  import { Collection, CollectionItem, createCollection } from "./collection.js";
7
7
  import { Layer, LayerManager, LayerOptions, createLayer } from "./layer.js";
8
8
  export { type Collection, type CollectionItem, DefaultPortal, type JSXElement, type Layer, type LayerManager, type LayerOptions, type LayoutComponent, Portal, type PortalProps, Presence, type PresenceProps, Slot, type SlotProps, createCollection, createLayer, definePortal, layout };
@@ -1,7 +1,8 @@
1
- import { DefaultPortal, Portal, definePortal } from "./portal.js";
1
+ import { DefaultPortal, Portal, definePortal } from "../../runtime/portal.js";
2
2
  import { layout } from "./layout.js";
3
3
  import { Slot } from "./slot.js";
4
4
  import { Presence } from "./presence.js";
5
+ import "./portal.js";
5
6
  import { createCollection } from "./collection.js";
6
7
  import { createLayer } from "./layer.js";
7
8
  export { DefaultPortal, Portal, Presence, Slot, createCollection, createLayer, definePortal, layout };
@@ -1,24 +1,2 @@
1
- import { ComponentInstance } from "../../runtime/component-internal.js";
2
- import { RenderableChild } from "../../common/vnode.js";
3
-
4
- //#region src/foundations/structures/portal.d.ts
5
- interface Portal<T extends RenderableChild = RenderableChild> {
6
- /** Mount point — rendered exactly once */
7
- (): unknown;
8
- /** Render content into the portal */
9
- render(props: {
10
- children?: T;
11
- }): unknown;
12
- }
13
- interface PortalProps {
14
- children?: RenderableChild;
15
- }
16
- declare function definePortal<T extends RenderableChild = RenderableChild>(): Portal<T>;
17
- declare function _resetDefaultPortal(): void;
18
- declare function disposeDefaultPortalScope(scope: object | null): void;
19
- declare function clearDefaultPortalForInstance(instance: ComponentInstance): void;
20
- declare const DefaultPortal: Portal<RenderableChild>;
21
- declare function Portal(props: PortalProps): null;
22
- //#endregion
23
- export { DefaultPortal, Portal, PortalProps, definePortal };
24
- //# sourceMappingURL=portal.d.ts.map
1
+ import { DefaultPortal, Portal, PortalProps, definePortal } from "../../runtime/portal.js";
2
+ export { DefaultPortal, Portal, type PortalProps, definePortal };