@spearwolf/shadow-objects 0.33.0 → 0.35.0

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 (312) hide show
  1. package/CHANGELOG.md +350 -61
  2. package/README.md +66 -13
  3. package/bundle.js +6 -53
  4. package/package.json +15 -3
  5. package/src/ChangeTrailRefusedError.d.ts +27 -0
  6. package/src/ChangeTrailRefusedError.d.ts.map +1 -0
  7. package/src/ChangeTrailRefusedError.js +12 -0
  8. package/src/ChangeTrailRefusedError.js.map +7 -0
  9. package/src/EntityUuidInUseError.d.ts +19 -0
  10. package/src/EntityUuidInUseError.d.ts.map +1 -0
  11. package/src/EntityUuidInUseError.js +11 -0
  12. package/src/EntityUuidInUseError.js.map +7 -0
  13. package/src/WorkerTimeoutError.d.ts +26 -0
  14. package/src/WorkerTimeoutError.d.ts.map +1 -0
  15. package/src/WorkerTimeoutError.js +12 -0
  16. package/src/WorkerTimeoutError.js.map +7 -0
  17. package/src/bundle.d.ts +1 -1
  18. package/src/bundle.d.ts.map +1 -1
  19. package/src/bundle.js +1 -1
  20. package/src/bundle.js.map +2 -2
  21. package/src/constants.d.ts +13 -2
  22. package/src/constants.d.ts.map +1 -1
  23. package/src/constants.js +7 -1
  24. package/src/constants.js.map +2 -2
  25. package/src/create-worker.bundle.d.ts +1 -1
  26. package/src/create-worker.bundle.d.ts.map +1 -1
  27. package/src/create-worker.bundle.js.map +1 -1
  28. package/src/create-worker.d.ts +1 -1
  29. package/src/create-worker.d.ts.map +1 -1
  30. package/src/create-worker.js.map +1 -1
  31. package/src/elements/ShaeElement.d.ts +70 -2
  32. package/src/elements/ShaeElement.d.ts.map +1 -1
  33. package/src/elements/ShaeElement.js +129 -25
  34. package/src/elements/ShaeElement.js.map +3 -3
  35. package/src/elements/ShaeEntElement.d.ts +39 -1
  36. package/src/elements/ShaeEntElement.d.ts.map +1 -1
  37. package/src/elements/ShaeEntElement.js +397 -167
  38. package/src/elements/ShaeEntElement.js.map +2 -2
  39. package/src/elements/ShaeLifecycleElement.d.ts +71 -0
  40. package/src/elements/ShaeLifecycleElement.d.ts.map +1 -0
  41. package/src/elements/ShaeLifecycleElement.js +83 -0
  42. package/src/elements/ShaeLifecycleElement.js.map +7 -0
  43. package/src/elements/ShaePropElement.d.ts +61 -2
  44. package/src/elements/ShaePropElement.d.ts.map +1 -1
  45. package/src/elements/ShaePropElement.js +264 -219
  46. package/src/elements/ShaePropElement.js.map +2 -2
  47. package/src/elements/ShaeWorkerElement.d.ts +59 -5
  48. package/src/elements/ShaeWorkerElement.d.ts.map +1 -1
  49. package/src/elements/ShaeWorkerElement.js +271 -73
  50. package/src/elements/ShaeWorkerElement.js.map +2 -2
  51. package/src/elements/constants.d.ts +9 -0
  52. package/src/elements/constants.d.ts.map +1 -1
  53. package/src/elements/constants.js +18 -0
  54. package/src/elements/constants.js.map +2 -2
  55. package/src/elements/deferredTeardown.d.ts +24 -0
  56. package/src/elements/deferredTeardown.d.ts.map +1 -0
  57. package/src/elements/deferredTeardown.js +30 -0
  58. package/src/elements/deferredTeardown.js.map +7 -0
  59. package/src/elements/displayContentsRule.d.ts +25 -0
  60. package/src/elements/displayContentsRule.d.ts.map +1 -0
  61. package/src/elements/displayContentsRule.js +37 -0
  62. package/src/elements/displayContentsRule.js.map +7 -0
  63. package/src/elements/events.d.ts +10 -7
  64. package/src/elements/events.d.ts.map +1 -1
  65. package/src/elements/forwardCustomEvents.d.ts +19 -0
  66. package/src/elements/forwardCustomEvents.d.ts.map +1 -0
  67. package/src/elements/forwardCustomEvents.js +47 -0
  68. package/src/elements/forwardCustomEvents.js.map +7 -0
  69. package/src/elements/hostedSlots.d.ts +36 -0
  70. package/src/elements/hostedSlots.d.ts.map +1 -0
  71. package/src/elements/hostedSlots.js +118 -0
  72. package/src/elements/hostedSlots.js.map +7 -0
  73. package/src/elements/parentRemoval.d.ts +18 -0
  74. package/src/elements/parentRemoval.d.ts.map +1 -0
  75. package/src/elements/parentRemoval.js +60 -0
  76. package/src/elements/parentRemoval.js.map +7 -0
  77. package/src/elements/propValueConverters.d.ts +3 -0
  78. package/src/elements/propValueConverters.d.ts.map +1 -0
  79. package/src/elements/propValueConverters.js +54 -0
  80. package/src/elements/propValueConverters.js.map +7 -0
  81. package/src/elements/requestEntAncestor.d.ts +32 -0
  82. package/src/elements/requestEntAncestor.d.ts.map +1 -0
  83. package/src/elements/requestEntAncestor.js +16 -0
  84. package/src/elements/requestEntAncestor.js.map +7 -0
  85. package/src/elements.js.map +1 -1
  86. package/src/in-the-dark/Entity.d.ts +143 -3
  87. package/src/in-the-dark/Entity.d.ts.map +1 -1
  88. package/src/in-the-dark/Entity.js +330 -63
  89. package/src/in-the-dark/Entity.js.map +3 -3
  90. package/src/in-the-dark/Kernel.d.ts +98 -16
  91. package/src/in-the-dark/Kernel.d.ts.map +1 -1
  92. package/src/in-the-dark/Kernel.js +466 -379
  93. package/src/in-the-dark/Kernel.js.map +3 -3
  94. package/src/in-the-dark/Registry.d.ts +7 -1
  95. package/src/in-the-dark/Registry.d.ts.map +1 -1
  96. package/src/in-the-dark/Registry.js +112 -14
  97. package/src/in-the-dark/Registry.js.map +2 -2
  98. package/src/in-the-dark/ShadowObject.d.ts.map +1 -1
  99. package/src/in-the-dark/ShadowObject.js +1 -0
  100. package/src/in-the-dark/ShadowObject.js.map +2 -2
  101. package/src/in-the-dark/ShadowObjectCreationScope.d.ts +133 -0
  102. package/src/in-the-dark/ShadowObjectCreationScope.d.ts.map +1 -0
  103. package/src/in-the-dark/ShadowObjectCreationScope.js +603 -0
  104. package/src/in-the-dark/ShadowObjectCreationScope.js.map +7 -0
  105. package/src/in-the-dark/SignalsPath.d.ts +2 -0
  106. package/src/in-the-dark/SignalsPath.d.ts.map +1 -1
  107. package/src/in-the-dark/SignalsPath.js +6 -2
  108. package/src/in-the-dark/SignalsPath.js.map +2 -2
  109. package/src/in-the-dark/displayName.d.ts +4 -0
  110. package/src/in-the-dark/displayName.d.ts.map +1 -0
  111. package/src/in-the-dark/displayName.js +5 -0
  112. package/src/in-the-dark/displayName.js.map +7 -0
  113. package/src/in-the-dark/events.js.map +1 -1
  114. package/src/in-the-dark/importModule.d.ts +7 -0
  115. package/src/in-the-dark/importModule.d.ts.map +1 -1
  116. package/src/in-the-dark/importModule.js +5 -2
  117. package/src/in-the-dark/importModule.js.map +2 -2
  118. package/src/index.d.ts +9 -1
  119. package/src/index.d.ts.map +1 -1
  120. package/src/index.js +9 -1
  121. package/src/index.js.map +2 -2
  122. package/src/inspect/createKernelSnapshot.d.ts +17 -0
  123. package/src/inspect/createKernelSnapshot.d.ts.map +1 -0
  124. package/src/inspect/createKernelSnapshot.js +247 -0
  125. package/src/inspect/createKernelSnapshot.js.map +7 -0
  126. package/src/inspect/createViewSnapshot.d.ts +10 -0
  127. package/src/inspect/createViewSnapshot.d.ts.map +1 -0
  128. package/src/inspect/createViewSnapshot.js +143 -0
  129. package/src/inspect/createViewSnapshot.js.map +7 -0
  130. package/src/inspect/normalizeInspectRequest.d.ts +32 -0
  131. package/src/inspect/normalizeInspectRequest.d.ts.map +1 -0
  132. package/src/inspect/normalizeInspectRequest.js +55 -0
  133. package/src/inspect/normalizeInspectRequest.js.map +7 -0
  134. package/src/inspect/serializeValue.d.ts +13 -0
  135. package/src/inspect/serializeValue.d.ts.map +1 -0
  136. package/src/inspect/serializeValue.js +149 -0
  137. package/src/inspect/serializeValue.js.map +7 -0
  138. package/src/inspect/types.d.ts +260 -0
  139. package/src/inspect/types.d.ts.map +1 -0
  140. package/src/inspect/types.js +1 -0
  141. package/src/inspect/types.js.map +7 -0
  142. package/src/model-context/ModelContextLike.d.ts +59 -0
  143. package/src/model-context/ModelContextLike.d.ts.map +1 -0
  144. package/src/model-context/ModelContextLike.js +15 -0
  145. package/src/model-context/ModelContextLike.js.map +7 -0
  146. package/src/model-context/exposeShadowEnvsToModelContext.d.ts +48 -0
  147. package/src/model-context/exposeShadowEnvsToModelContext.d.ts.map +1 -0
  148. package/src/model-context/exposeShadowEnvsToModelContext.js +39 -0
  149. package/src/model-context/exposeShadowEnvsToModelContext.js.map +7 -0
  150. package/src/model-context/redactProps.d.ts +14 -0
  151. package/src/model-context/redactProps.d.ts.map +1 -0
  152. package/src/model-context/redactProps.js +22 -0
  153. package/src/model-context/redactProps.js.map +7 -0
  154. package/src/model-context/sharedExposure.d.ts +32 -0
  155. package/src/model-context/sharedExposure.d.ts.map +1 -0
  156. package/src/model-context/sharedExposure.js +108 -0
  157. package/src/model-context/sharedExposure.js.map +7 -0
  158. package/src/model-context/toolSupport.d.ts +72 -0
  159. package/src/model-context/toolSupport.d.ts.map +1 -0
  160. package/src/model-context/toolSupport.js +145 -0
  161. package/src/model-context/toolSupport.js.map +7 -0
  162. package/src/model-context/tools/findEntities.d.ts +15 -0
  163. package/src/model-context/tools/findEntities.d.ts.map +1 -0
  164. package/src/model-context/tools/findEntities.js +71 -0
  165. package/src/model-context/tools/findEntities.js.map +7 -0
  166. package/src/model-context/tools/getEntity.d.ts +16 -0
  167. package/src/model-context/tools/getEntity.d.ts.map +1 -0
  168. package/src/model-context/tools/getEntity.js +65 -0
  169. package/src/model-context/tools/getEntity.js.map +7 -0
  170. package/src/model-context/tools/getEntityTree.d.ts +4 -0
  171. package/src/model-context/tools/getEntityTree.d.ts.map +1 -0
  172. package/src/model-context/tools/getEntityTree.js +58 -0
  173. package/src/model-context/tools/getEntityTree.js.map +7 -0
  174. package/src/model-context/tools/getRegistry.d.ts +14 -0
  175. package/src/model-context/tools/getRegistry.d.ts.map +1 -0
  176. package/src/model-context/tools/getRegistry.js +39 -0
  177. package/src/model-context/tools/getRegistry.js.map +7 -0
  178. package/src/model-context/tools/index.d.ts +9 -0
  179. package/src/model-context/tools/index.d.ts.map +1 -0
  180. package/src/model-context/tools/index.js +16 -0
  181. package/src/model-context/tools/index.js.map +7 -0
  182. package/src/model-context/tools/listEnvs.d.ts +33 -0
  183. package/src/model-context/tools/listEnvs.d.ts.map +1 -0
  184. package/src/model-context/tools/listEnvs.js +37 -0
  185. package/src/model-context/tools/listEnvs.js.map +7 -0
  186. package/src/model-context.d.ts +13 -0
  187. package/src/model-context.d.ts.map +1 -0
  188. package/src/model-context.js +15 -0
  189. package/src/model-context.js.map +7 -0
  190. package/src/shadow-objects.d.ts +4 -0
  191. package/src/shadow-objects.d.ts.map +1 -1
  192. package/src/shadow-objects.js +6 -0
  193. package/src/shadow-objects.js.map +2 -2
  194. package/src/shadow-objects.worker.js +0 -1
  195. package/src/shadow-objects.worker.js.map +2 -2
  196. package/src/shae-ent.js.map +1 -1
  197. package/src/shae-prop.js +2 -2
  198. package/src/shae-prop.js.map +2 -2
  199. package/src/shae-worker.js.map +1 -1
  200. package/src/testing/TestEntity.d.ts +79 -0
  201. package/src/testing/TestEntity.d.ts.map +1 -0
  202. package/src/testing/TestEntity.js +135 -0
  203. package/src/testing/TestEntity.js.map +7 -0
  204. package/src/testing/createTestKernel.d.ts +11 -0
  205. package/src/testing/createTestKernel.d.ts.map +1 -0
  206. package/src/testing/createTestKernel.js +132 -0
  207. package/src/testing/createTestKernel.js.map +7 -0
  208. package/src/testing/mountShadowObject.d.ts +21 -0
  209. package/src/testing/mountShadowObject.d.ts.map +1 -0
  210. package/src/testing/mountShadowObject.js +72 -0
  211. package/src/testing/mountShadowObject.js.map +7 -0
  212. package/src/testing/recordKernelErrors.d.ts +21 -0
  213. package/src/testing/recordKernelErrors.d.ts.map +1 -0
  214. package/src/testing/recordKernelErrors.js +39 -0
  215. package/src/testing/recordKernelErrors.js.map +7 -0
  216. package/src/testing/settle.d.ts +15 -0
  217. package/src/testing/settle.d.ts.map +1 -0
  218. package/src/testing/settle.js +19 -0
  219. package/src/testing/settle.js.map +7 -0
  220. package/src/testing/types.d.ts +119 -0
  221. package/src/testing/types.d.ts.map +1 -0
  222. package/src/testing/types.js +1 -0
  223. package/src/testing/types.js.map +7 -0
  224. package/src/testing.d.ts +14 -0
  225. package/src/testing.d.ts.map +1 -0
  226. package/src/testing.js +11 -0
  227. package/src/testing.js.map +7 -0
  228. package/src/types.d.ts +185 -14
  229. package/src/types.d.ts.map +1 -1
  230. package/src/utils/ConsoleLogger.d.ts +45 -10
  231. package/src/utils/ConsoleLogger.d.ts.map +1 -1
  232. package/src/utils/ConsoleLogger.js +51 -26
  233. package/src/utils/ConsoleLogger.js.map +2 -2
  234. package/src/utils/FrameLoop.d.ts +42 -3
  235. package/src/utils/FrameLoop.d.ts.map +1 -1
  236. package/src/utils/FrameLoop.js +71 -10
  237. package/src/utils/FrameLoop.js.map +2 -2
  238. package/src/utils/MicrotaskCollector.d.ts +45 -0
  239. package/src/utils/MicrotaskCollector.d.ts.map +1 -0
  240. package/src/utils/MicrotaskCollector.js +33 -0
  241. package/src/utils/MicrotaskCollector.js.map +7 -0
  242. package/src/utils/MicrotaskGate.d.ts +17 -0
  243. package/src/utils/MicrotaskGate.d.ts.map +1 -0
  244. package/src/utils/MicrotaskGate.js +20 -0
  245. package/src/utils/MicrotaskGate.js.map +7 -0
  246. package/src/utils/array-utils.js.map +1 -1
  247. package/src/utils/attr-utils.d.ts +11 -0
  248. package/src/utils/attr-utils.d.ts.map +1 -1
  249. package/src/utils/attr-utils.js +5 -1
  250. package/src/utils/attr-utils.js.map +2 -2
  251. package/src/utils/constants.js.map +1 -1
  252. package/src/utils/generateUUID.d.ts +11 -0
  253. package/src/utils/generateUUID.d.ts.map +1 -1
  254. package/src/utils/generateUUID.js +31 -266
  255. package/src/utils/generateUUID.js.map +2 -2
  256. package/src/utils/props-utils.d.ts +3 -2
  257. package/src/utils/props-utils.d.ts.map +1 -1
  258. package/src/utils/props-utils.js +13 -24
  259. package/src/utils/props-utils.js.map +2 -2
  260. package/src/utils/runGuarded.d.ts +27 -0
  261. package/src/utils/runGuarded.d.ts.map +1 -0
  262. package/src/utils/runGuarded.js +11 -0
  263. package/src/utils/runGuarded.js.map +7 -0
  264. package/src/utils/toMaybe.d.ts.map +1 -1
  265. package/src/utils/toMaybe.js.map +1 -1
  266. package/src/utils/toNamespace.d.ts.map +1 -1
  267. package/src/utils/toNamespace.js.map +1 -1
  268. package/src/utils/toUrlString.d.ts +12 -0
  269. package/src/utils/toUrlString.d.ts.map +1 -1
  270. package/src/utils/toUrlString.js.map +2 -2
  271. package/src/utils/waitForMessageOfType.d.ts +12 -1
  272. package/src/utils/waitForMessageOfType.d.ts.map +1 -1
  273. package/src/utils/waitForMessageOfType.js +16 -1
  274. package/src/utils/waitForMessageOfType.js.map +2 -2
  275. package/src/view/ComponentChanges.d.ts +88 -1
  276. package/src/view/ComponentChanges.d.ts.map +1 -1
  277. package/src/view/ComponentChanges.js +243 -73
  278. package/src/view/ComponentChanges.js.map +2 -2
  279. package/src/view/ComponentContext.d.ts +206 -16
  280. package/src/view/ComponentContext.d.ts.map +1 -1
  281. package/src/view/ComponentContext.js +548 -91
  282. package/src/view/ComponentContext.js.map +2 -2
  283. package/src/view/ComponentMemory.d.ts +3 -3
  284. package/src/view/ComponentMemory.d.ts.map +1 -1
  285. package/src/view/ComponentMemory.js.map +1 -1
  286. package/src/view/IShadowObjectEnvProxy.d.ts +38 -3
  287. package/src/view/IShadowObjectEnvProxy.d.ts.map +1 -1
  288. package/src/view/LocalShadowObjectEnv.d.ts +8 -1
  289. package/src/view/LocalShadowObjectEnv.d.ts.map +1 -1
  290. package/src/view/LocalShadowObjectEnv.js +23 -7
  291. package/src/view/LocalShadowObjectEnv.js.map +2 -2
  292. package/src/view/RemoteWorkerEnv.d.ts +108 -5
  293. package/src/view/RemoteWorkerEnv.d.ts.map +1 -1
  294. package/src/view/RemoteWorkerEnv.js +244 -77
  295. package/src/view/RemoteWorkerEnv.js.map +2 -2
  296. package/src/view/ShadowEnv.d.ts +79 -2
  297. package/src/view/ShadowEnv.d.ts.map +1 -1
  298. package/src/view/ShadowEnv.js +323 -59
  299. package/src/view/ShadowEnv.js.map +3 -3
  300. package/src/view/ViewComponent.d.ts +78 -14
  301. package/src/view/ViewComponent.d.ts.map +1 -1
  302. package/src/view/ViewComponent.js +90 -14
  303. package/src/view/ViewComponent.js.map +2 -2
  304. package/src/view/cloneChangeTrail.js.map +2 -2
  305. package/src/worker/MessageRouter.d.ts +14 -0
  306. package/src/worker/MessageRouter.d.ts.map +1 -1
  307. package/src/worker/MessageRouter.js +98 -15
  308. package/src/worker/MessageRouter.js.map +2 -2
  309. package/src/worker/WorkerRuntime.d.ts +22 -1
  310. package/src/worker/WorkerRuntime.d.ts.map +1 -1
  311. package/src/worker/WorkerRuntime.js +60 -8
  312. package/src/worker/WorkerRuntime.js.map +2 -2
@@ -1,33 +1,51 @@
1
1
  const RequestEntParentEventName = "shaeRequestEntParent";
2
2
  const ReRequestEntParentEventName = "shaeReRequestEntParent";
3
+ const ReRequestEntHostEventName = "shaeReRequestEntHost";
3
4
  const SHAE_WORKER = "shae-worker";
4
5
  const SHAE_ENT = "shae-ent";
5
6
  const SHAE_PROP = "shae-prop";
6
7
  const ATTR_TOKEN = "token";
7
8
  const ATTR_FORWARD_CUSTOM_EVENTS = "forward-custom-events";
9
+ const ATTR_AUTO_DESTRUCT = "auto-destruct";
8
10
  const ATTR_NS = "ns";
9
11
  const ATTR_LOCAL = "local";
10
12
  const ATTR_NO_AUTOSTART = "no-autostart";
11
13
  const ATTR_NO_STRUCTURED_CLONE = "no-structured-clone";
12
14
  const ATTR_AUTO_SYNC = "auto-sync";
13
15
  const ATTR_SRC = "src";
16
+ const ATTR_LOAD_TIMEOUT = "load-timeout";
17
+ const ATTR_CONFIGURE_TIMEOUT = "configure-timeout";
18
+ const ATTR_CHANGE_TRAIL_TIMEOUT = "change-trail-timeout";
19
+ const ATTR_INSPECT_TIMEOUT = "inspect-timeout";
20
+ const ATTR_DESTROY_TIMEOUT = "destroy-timeout";
21
+ const ATTR_EXPOSE_TO_MODEL_CONTEXT = "expose-to-model-context";
22
+ const ATTR_REDACT_PROPS = "redact-props";
14
23
  const ATTR_NAME = "name";
15
24
  const ATTR_VALUE = "value";
16
25
  const ATTR_TYPE = "type";
17
26
  const ATTR_NO_TRIM = "no-trim";
18
27
  export {
28
+ ATTR_AUTO_DESTRUCT,
19
29
  ATTR_AUTO_SYNC,
30
+ ATTR_CHANGE_TRAIL_TIMEOUT,
31
+ ATTR_CONFIGURE_TIMEOUT,
32
+ ATTR_DESTROY_TIMEOUT,
33
+ ATTR_EXPOSE_TO_MODEL_CONTEXT,
20
34
  ATTR_FORWARD_CUSTOM_EVENTS,
35
+ ATTR_INSPECT_TIMEOUT,
36
+ ATTR_LOAD_TIMEOUT,
21
37
  ATTR_LOCAL,
22
38
  ATTR_NAME,
23
39
  ATTR_NO_AUTOSTART,
24
40
  ATTR_NO_STRUCTURED_CLONE,
25
41
  ATTR_NO_TRIM,
26
42
  ATTR_NS,
43
+ ATTR_REDACT_PROPS,
27
44
  ATTR_SRC,
28
45
  ATTR_TOKEN,
29
46
  ATTR_TYPE,
30
47
  ATTR_VALUE,
48
+ ReRequestEntHostEventName,
31
49
  ReRequestEntParentEventName,
32
50
  RequestEntParentEventName,
33
51
  SHAE_ENT,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/elements/constants.ts"],
4
- "sourcesContent": ["export const RequestEntParentEventName = 'shaeRequestEntParent';\nexport const ReRequestEntParentEventName = 'shaeReRequestEntParent';\n\nexport const SHAE_WORKER = 'shae-worker';\nexport const SHAE_ENT = 'shae-ent';\nexport const SHAE_PROP = 'shae-prop';\n\n// <shae-ent> attributes\nexport const ATTR_TOKEN = 'token';\nexport const ATTR_FORWARD_CUSTOM_EVENTS = 'forward-custom-events';\n\n// <shae-ent> + <shae-worker> attributes\nexport const ATTR_NS = 'ns';\n\n// <shae-worker> attributes\nexport const ATTR_LOCAL = 'local';\nexport const ATTR_NO_AUTOSTART = 'no-autostart';\nexport const ATTR_NO_STRUCTURED_CLONE = 'no-structured-clone';\nexport const ATTR_AUTO_SYNC = 'auto-sync';\nexport const ATTR_SRC = 'src';\n\n// <shae-prop> attributes\nexport const ATTR_NAME = 'name';\nexport const ATTR_VALUE = 'value';\nexport const ATTR_TYPE = 'type';\nexport const ATTR_NO_TRIM = 'no-trim';"],
5
- "mappings": "AAAO,MAAM,4BAA4B;AAClC,MAAM,8BAA8B;AAEpC,MAAM,cAAc;AACpB,MAAM,WAAW;AACjB,MAAM,YAAY;AAGlB,MAAM,aAAa;AACnB,MAAM,6BAA6B;AAGnC,MAAM,UAAU;AAGhB,MAAM,aAAa;AACnB,MAAM,oBAAoB;AAC1B,MAAM,2BAA2B;AACjC,MAAM,iBAAiB;AACvB,MAAM,WAAW;AAGjB,MAAM,YAAY;AAClB,MAAM,aAAa;AACnB,MAAM,YAAY;AAClB,MAAM,eAAe;",
4
+ "sourcesContent": ["export const RequestEntParentEventName = 'shaeRequestEntParent';\nexport const ReRequestEntParentEventName = 'shaeReRequestEntParent';\nexport const ReRequestEntHostEventName = 'shaeReRequestEntHost';\n\nexport const SHAE_WORKER = 'shae-worker';\nexport const SHAE_ENT = 'shae-ent';\nexport const SHAE_PROP = 'shae-prop';\n\n// <shae-ent> attributes\nexport const ATTR_TOKEN = 'token';\nexport const ATTR_FORWARD_CUSTOM_EVENTS = 'forward-custom-events';\nexport const ATTR_AUTO_DESTRUCT = 'auto-destruct';\n\n// <shae-ent> + <shae-worker> attributes\nexport const ATTR_NS = 'ns';\n\n// <shae-worker> attributes\nexport const ATTR_LOCAL = 'local';\nexport const ATTR_NO_AUTOSTART = 'no-autostart';\nexport const ATTR_NO_STRUCTURED_CLONE = 'no-structured-clone';\nexport const ATTR_AUTO_SYNC = 'auto-sync';\nexport const ATTR_SRC = 'src';\nexport const ATTR_LOAD_TIMEOUT = 'load-timeout';\nexport const ATTR_CONFIGURE_TIMEOUT = 'configure-timeout';\nexport const ATTR_CHANGE_TRAIL_TIMEOUT = 'change-trail-timeout';\nexport const ATTR_INSPECT_TIMEOUT = 'inspect-timeout';\nexport const ATTR_DESTROY_TIMEOUT = 'destroy-timeout';\nexport const ATTR_EXPOSE_TO_MODEL_CONTEXT = 'expose-to-model-context';\nexport const ATTR_REDACT_PROPS = 'redact-props';\n\n// <shae-prop> attributes\nexport const ATTR_NAME = 'name';\nexport const ATTR_VALUE = 'value';\nexport const ATTR_TYPE = 'type';\nexport const ATTR_NO_TRIM = 'no-trim';\n"],
5
+ "mappings": "AAAO,MAAM,4BAA4B;AAClC,MAAM,8BAA8B;AACpC,MAAM,4BAA4B;AAElC,MAAM,cAAc;AACpB,MAAM,WAAW;AACjB,MAAM,YAAY;AAGlB,MAAM,aAAa;AACnB,MAAM,6BAA6B;AACnC,MAAM,qBAAqB;AAG3B,MAAM,UAAU;AAGhB,MAAM,aAAa;AACnB,MAAM,oBAAoB;AAC1B,MAAM,2BAA2B;AACjC,MAAM,iBAAiB;AACvB,MAAM,WAAW;AACjB,MAAM,oBAAoB;AAC1B,MAAM,yBAAyB;AAC/B,MAAM,4BAA4B;AAClC,MAAM,uBAAuB;AAC7B,MAAM,uBAAuB;AAC7B,MAAM,+BAA+B;AACrC,MAAM,oBAAoB;AAG1B,MAAM,YAAY;AAClB,MAAM,aAAa;AACnB,MAAM,YAAY;AAClB,MAAM,eAAe;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * A teardown that waits for the next microtask before it commits.
3
+ *
4
+ * Leaving the tree is not the same as ending. A re-render takes an element out and puts it back
5
+ * inside one task, and everything hanging on it — an environment, its proxy, every entity in it —
6
+ * has to come through that move untouched. So the teardown is booked instead of run, and the
7
+ * microtask that follows asks where the element stands by then: whoever moved it in the meantime
8
+ * has left the answer here, and being back in the tree calls the teardown off. However often the
9
+ * element is moved inside that one window, only the first booking queues a microtask, so the
10
+ * question is asked once. An element that is still out when the microtask runs is torn down.
11
+ *
12
+ * A cancelled booking leaves its microtask standing — it wakes up, finds nothing booked and
13
+ * returns. Running twice is not guarded against here: that guard belongs to the teardown itself,
14
+ * which is callable by hand as well and has to carry it in either case.
15
+ */
16
+ export declare class DeferredTeardown {
17
+ #private;
18
+ constructor(run: () => void);
19
+ /** Book the teardown, and make sure someone comes asking. */
20
+ schedule(): void;
21
+ /** Take the booking back. */
22
+ cancel(): void;
23
+ }
24
+ //# sourceMappingURL=deferredTeardown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deferredTeardown.d.ts","sourceRoot":"","sources":["../../../src/elements/deferredTeardown.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,qBAAa,gBAAgB;;IAS3B,YAAY,GAAG,EAAE,MAAM,IAAI,EAE1B;IAED,6DAA6D;IAC7D,QAAQ,IAAI,IAAI,CAgBf;IAED,6BAA6B;IAC7B,MAAM,IAAI,IAAI,CAEb;CACF"}
@@ -0,0 +1,30 @@
1
+ class DeferredTeardown {
2
+ #run;
3
+ /** Whether a teardown is booked right now. */
4
+ #isBooked = false;
5
+ /** Whether a microtask is already on its way to ask. */
6
+ #isAsking = false;
7
+ constructor(run) {
8
+ this.#run = run;
9
+ }
10
+ /** Book the teardown, and make sure someone comes asking. */
11
+ schedule() {
12
+ this.#isBooked = true;
13
+ if (this.#isAsking) return;
14
+ this.#isAsking = true;
15
+ queueMicrotask(() => {
16
+ this.#isAsking = false;
17
+ if (!this.#isBooked) return;
18
+ this.#isBooked = false;
19
+ this.#run();
20
+ });
21
+ }
22
+ /** Take the booking back. */
23
+ cancel() {
24
+ this.#isBooked = false;
25
+ }
26
+ }
27
+ export {
28
+ DeferredTeardown
29
+ };
30
+ //# sourceMappingURL=deferredTeardown.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/elements/deferredTeardown.ts"],
4
+ "sourcesContent": ["/**\n * A teardown that waits for the next microtask before it commits.\n *\n * Leaving the tree is not the same as ending. A re-render takes an element out and puts it back\n * inside one task, and everything hanging on it \u2014 an environment, its proxy, every entity in it \u2014\n * has to come through that move untouched. So the teardown is booked instead of run, and the\n * microtask that follows asks where the element stands by then: whoever moved it in the meantime\n * has left the answer here, and being back in the tree calls the teardown off. However often the\n * element is moved inside that one window, only the first booking queues a microtask, so the\n * question is asked once. An element that is still out when the microtask runs is torn down.\n *\n * A cancelled booking leaves its microtask standing \u2014 it wakes up, finds nothing booked and\n * returns. Running twice is not guarded against here: that guard belongs to the teardown itself,\n * which is callable by hand as well and has to carry it in either case.\n */\nexport class DeferredTeardown {\n readonly #run: () => void;\n\n /** Whether a teardown is booked right now. */\n #isBooked = false;\n\n /** Whether a microtask is already on its way to ask. */\n #isAsking = false;\n\n constructor(run: () => void) {\n this.#run = run;\n }\n\n /** Book the teardown, and make sure someone comes asking. */\n schedule(): void {\n this.#isBooked = true;\n\n if (this.#isAsking) return;\n this.#isAsking = true;\n\n queueMicrotask(() => {\n this.#isAsking = false;\n if (!this.#isBooked) return;\n // the booking is cleared in front of the run, not behind it: the field says whether a\n // teardown is waiting, and one that is being carried out is not waiting. It also decides what\n // a `schedule()` from inside the teardown means \u2014 a fresh round, rather than a booking that\n // the line behind the call would wipe out\n this.#isBooked = false;\n this.#run();\n });\n }\n\n /** Take the booking back. */\n cancel(): void {\n this.#isBooked = false;\n }\n}\n"],
5
+ "mappings": "AAeO,MAAM,iBAAiB;AAAA,EACnB;AAAA;AAAA,EAGT,YAAY;AAAA;AAAA,EAGZ,YAAY;AAAA,EAEZ,YAAY,KAAiB;AAC3B,SAAK,OAAO;AAAA,EACd;AAAA;AAAA,EAGA,WAAiB;AACf,SAAK,YAAY;AAEjB,QAAI,KAAK,UAAW;AACpB,SAAK,YAAY;AAEjB,mBAAe,MAAM;AACnB,WAAK,YAAY;AACjB,UAAI,CAAC,KAAK,UAAW;AAKrB,WAAK,YAAY;AACjB,WAAK,KAAK;AAAA,IACZ,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,SAAe;AACb,SAAK,YAAY;AAAA,EACnB;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Makes sure `root` carries a `display: contents` rule for `tagName`, and does so once per root.
3
+ *
4
+ * The elements of this library carry no box of their own: they wire DOM structure into entities
5
+ * and must leave the layout of whatever sits inside them untouched. That is a styling statement,
6
+ * and a stylesheet rule is where it belongs — an element constructor cannot make it, because the
7
+ * Custom Elements specification forbids a constructor from giving its element attributes, and an
8
+ * inline style is written as the `style` attribute. A constructor that writes one makes the
9
+ * browser abort the upgrade and hand back an `HTMLUnknownElement`.
10
+ *
11
+ * The rule is keyed by the tag name the element actually connects under, not by a fixed list:
12
+ * a subclass registered under a tag of its own — the extension point the guides describe — lays
13
+ * out no box either, and is covered the moment one of its instances connects. A tag that joins
14
+ * later widens the selector of the rule already there instead of adding a second one, so the
15
+ * position of the rule in the cascade never moves.
16
+ *
17
+ * The rule goes to the root the element stands in, not to `document`: style rules do not cross a
18
+ * shadow boundary, so an element inside a shadow root needs the rule inside that root.
19
+ *
20
+ * It is prepended rather than appended. Its specificity is 0-0-1, so a rule of the consumer's with
21
+ * the same specificity decides by order — coming later, it wins, and nobody needs `!important` to
22
+ * override the default.
23
+ */
24
+ export declare const ensureDisplayContentsRule: (root: Node, tagName: string) => void;
25
+ //# sourceMappingURL=displayContentsRule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"displayContentsRule.d.ts","sourceRoot":"","sources":["../../../src/elements/displayContentsRule.ts"],"names":[],"mappings":"AAyBA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,yBAAyB,SAAU,IAAI,WAAW,MAAM,KAAG,IAyCvE,CAAC"}
@@ -0,0 +1,37 @@
1
+ const RuleStatePerRoot = /* @__PURE__ */ new WeakMap();
2
+ const buildRule = (tags) => `${Array.from(tags, (tag) => CSS.escape(tag)).join(",")}{display:contents}`;
3
+ const isDocument = (node) => node.nodeType === 9;
4
+ const isShadowRoot = (node) => node.nodeType === 11 && node.host != null;
5
+ const ensureDisplayContentsRule = (root, tagName) => {
6
+ let mountPoint;
7
+ let doc;
8
+ let key;
9
+ if (isDocument(root)) {
10
+ mountPoint = root.head ?? root.documentElement ?? root;
11
+ doc = root;
12
+ key = root;
13
+ } else if (isShadowRoot(root)) {
14
+ mountPoint = root;
15
+ doc = root.ownerDocument;
16
+ key = root;
17
+ } else {
18
+ return;
19
+ }
20
+ const state = RuleStatePerRoot.get(key);
21
+ if (state?.style.isConnected) {
22
+ if (state.tags.has(tagName)) return;
23
+ state.tags.add(tagName);
24
+ state.style.textContent = buildRule(state.tags);
25
+ return;
26
+ }
27
+ const tags = state?.tags ?? /* @__PURE__ */ new Set();
28
+ tags.add(tagName);
29
+ const style = doc.createElement("style");
30
+ style.textContent = buildRule(tags);
31
+ mountPoint.prepend(style);
32
+ RuleStatePerRoot.set(key, { tags, style });
33
+ };
34
+ export {
35
+ ensureDisplayContentsRule
36
+ };
37
+ //# sourceMappingURL=displayContentsRule.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/elements/displayContentsRule.ts"],
4
+ "sourcesContent": ["/** What a root already carries: the tag names covered, and the element holding the rule. */\ninterface DisplayRuleState {\n tags: Set<string>;\n style: HTMLStyleElement;\n}\n\nconst RuleStatePerRoot = new WeakMap<Document | ShadowRoot, DisplayRuleState>();\n\n// `CSS.escape` guards a tag name that carries a character the selector grammar would otherwise\n// read as a combinator \u2014 a dot is legal in a custom element name and would parse as a class\n// selector instead of naming the tag it belongs to\nconst buildRule = (tags: Set<string>): string => `${Array.from(tags, (tag) => CSS.escape(tag)).join(',')}{display:contents}`;\n\n/**\n * Whether `node` is a document \u2014 across realms.\n *\n * `instanceof Document` reads the constructor of the realm this module was loaded in, so an\n * element adopted into a document from another realm \u2014 an iframe, most of all \u2014 would fall\n * through it and quietly get no rule at all. The node type is the same number everywhere.\n */\nconst isDocument = (node: Node): node is Document => node.nodeType === 9;\n\n/** Whether `node` is a shadow root, by the same reasoning \u2014 a document fragment carrying a host. */\nconst isShadowRoot = (node: Node): node is ShadowRoot => node.nodeType === 11 && (node as ShadowRoot).host != null;\n\n/**\n * Makes sure `root` carries a `display: contents` rule for `tagName`, and does so once per root.\n *\n * The elements of this library carry no box of their own: they wire DOM structure into entities\n * and must leave the layout of whatever sits inside them untouched. That is a styling statement,\n * and a stylesheet rule is where it belongs \u2014 an element constructor cannot make it, because the\n * Custom Elements specification forbids a constructor from giving its element attributes, and an\n * inline style is written as the `style` attribute. A constructor that writes one makes the\n * browser abort the upgrade and hand back an `HTMLUnknownElement`.\n *\n * The rule is keyed by the tag name the element actually connects under, not by a fixed list:\n * a subclass registered under a tag of its own \u2014 the extension point the guides describe \u2014 lays\n * out no box either, and is covered the moment one of its instances connects. A tag that joins\n * later widens the selector of the rule already there instead of adding a second one, so the\n * position of the rule in the cascade never moves.\n *\n * The rule goes to the root the element stands in, not to `document`: style rules do not cross a\n * shadow boundary, so an element inside a shadow root needs the rule inside that root.\n *\n * It is prepended rather than appended. Its specificity is 0-0-1, so a rule of the consumer's with\n * the same specificity decides by order \u2014 coming later, it wins, and nobody needs `!important` to\n * override the default.\n */\nexport const ensureDisplayContentsRule = (root: Node, tagName: string): void => {\n let mountPoint: ParentNode;\n let doc: Document;\n let key: Document | ShadowRoot;\n\n if (isDocument(root)) {\n // `head` is typed non-null but a document can be built without one \u2014 an XML document, or a\n // `createDocument()` \u2014 so the rule falls back to whatever parent the document offers\n mountPoint = root.head ?? root.documentElement ?? root;\n doc = root;\n key = root;\n } else if (isShadowRoot(root)) {\n mountPoint = root;\n doc = root.ownerDocument;\n key = root;\n } else {\n // an element that has entered neither a document nor a shadow root is its own root: nothing\n // to style yet, and the next connect asks again\n return;\n }\n\n const state = RuleStatePerRoot.get(key);\n\n // a root that gets its content replaced wholesale \u2014 a shadow root re-filled through `innerHTML`,\n // most of all \u2014 takes the `<style>` the rule lives in down with the rest of the markup, so the\n // root can look known while the element carrying its rule is no longer in it. Rebuilding the\n // `<style>` here covers both a root seen for the first time and one whose rule element fell out.\n if (state?.style.isConnected) {\n if (state.tags.has(tagName)) return;\n state.tags.add(tagName);\n state.style.textContent = buildRule(state.tags);\n return;\n }\n\n const tags = state?.tags ?? new Set();\n tags.add(tagName);\n const style = doc.createElement('style');\n style.textContent = buildRule(tags);\n mountPoint.prepend(style);\n\n RuleStatePerRoot.set(key, {tags, style});\n};\n"],
5
+ "mappings": "AAMA,MAAM,mBAAmB,oBAAI,QAAiD;AAK9E,MAAM,YAAY,CAAC,SAA8B,GAAG,MAAM,KAAK,MAAM,CAAC,QAAQ,IAAI,OAAO,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC;AASxG,MAAM,aAAa,CAAC,SAAiC,KAAK,aAAa;AAGvE,MAAM,eAAe,CAAC,SAAmC,KAAK,aAAa,MAAO,KAAoB,QAAQ;AAyBvG,MAAM,4BAA4B,CAAC,MAAY,YAA0B;AAC9E,MAAI;AACJ,MAAI;AACJ,MAAI;AAEJ,MAAI,WAAW,IAAI,GAAG;AAGpB,iBAAa,KAAK,QAAQ,KAAK,mBAAmB;AAClD,UAAM;AACN,UAAM;AAAA,EACR,WAAW,aAAa,IAAI,GAAG;AAC7B,iBAAa;AACb,UAAM,KAAK;AACX,UAAM;AAAA,EACR,OAAO;AAGL;AAAA,EACF;AAEA,QAAM,QAAQ,iBAAiB,IAAI,GAAG;AAMtC,MAAI,OAAO,MAAM,aAAa;AAC5B,QAAI,MAAM,KAAK,IAAI,OAAO,EAAG;AAC7B,UAAM,KAAK,IAAI,OAAO;AACtB,UAAM,MAAM,cAAc,UAAU,MAAM,IAAI;AAC9C;AAAA,EACF;AAEA,QAAM,OAAO,OAAO,QAAQ,oBAAI,IAAI;AACpC,OAAK,IAAI,OAAO;AAChB,QAAM,QAAQ,IAAI,cAAc,OAAO;AACvC,QAAM,cAAc,UAAU,IAAI;AAClC,aAAW,QAAQ,KAAK;AAExB,mBAAiB,IAAI,KAAK,EAAC,MAAM,MAAK,CAAC;AACzC;",
6
+ "names": []
7
+ }
@@ -1,24 +1,27 @@
1
- import type { RequestEntParentEventName, ReRequestEntParentEventName } from './constants.js';
1
+ import type { RequestEntParentEventName, ReRequestEntHostEventName, ReRequestEntParentEventName } from './constants.js';
2
+ import type { EntAncestorRequest } from './requestEntAncestor.js';
2
3
  import type { ShaeEntElement } from './ShaeEntElement.js';
3
4
  export interface RequestEntParentEvent extends CustomEvent {
5
+ detail: EntAncestorRequest;
6
+ }
7
+ export interface ReRequestEntParentEvent extends CustomEvent {
4
8
  detail: {
5
9
  requester: ShaeEntElement;
10
+ shadowRootHost: HTMLElement;
6
11
  };
7
12
  }
8
- export interface ReRequestEntParentEvent extends CustomEvent {
13
+ export interface ReRequestEntHostEvent extends CustomEvent {
9
14
  detail: {
10
15
  requester: ShaeEntElement;
11
- shadowRootHost: HTMLElement;
12
16
  };
13
17
  }
14
- export interface ShadowEntsEventMap {
18
+ export interface ShadowObjectsEventMap {
15
19
  [RequestEntParentEventName]: RequestEntParentEvent;
16
20
  [ReRequestEntParentEventName]: ReRequestEntParentEvent;
21
+ [ReRequestEntHostEventName]: ReRequestEntHostEvent;
17
22
  }
18
23
  declare global {
19
- interface HTMLElementEventMap extends ShadowEntsEventMap {
20
- addEventListener<K extends keyof ShadowEntsEventMap>(type: K, listener: (this: Document, ev: ShadowEntsEventMap[K]) => void): void;
21
- dispatchEvent<K extends keyof ShadowEntsEventMap>(ev: ShadowEntsEventMap[K]): void;
24
+ interface HTMLElementEventMap extends ShadowObjectsEventMap {
22
25
  }
23
26
  }
24
27
  //# sourceMappingURL=events.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../../src/elements/events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,yBAAyB,EAAE,2BAA2B,EAAC,MAAM,gBAAgB,CAAC;AAC3F,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,qBAAqB,CAAC;AAExD,MAAM,WAAW,qBAAsB,SAAQ,WAAW;IACxD,MAAM,EAAE;QACN,SAAS,EAAE,cAAc,CAAC;KAC3B,CAAC;CACH;AAED,MAAM,WAAW,uBAAwB,SAAQ,WAAW;IAC1D,MAAM,EAAE;QACN,SAAS,EAAE,cAAc,CAAC;QAC1B,cAAc,EAAE,WAAW,CAAC;KAC7B,CAAC;CACH;AAED,MAAM,WAAW,kBAAkB;IACjC,CAAC,yBAAyB,CAAC,EAAE,qBAAqB,CAAC;IACnD,CAAC,2BAA2B,CAAC,EAAE,uBAAuB,CAAC;CACxD;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,mBAAoB,SAAQ,kBAAkB;QACtD,gBAAgB,CAAC,CAAC,SAAS,MAAM,kBAAkB,EACjD,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,kBAAkB,CAAC,CAAC,CAAC,KAAK,IAAI,GAC5D,IAAI,CAAC;QACR,aAAa,CAAC,CAAC,SAAS,MAAM,kBAAkB,EAAE,EAAE,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;KACpF;CACF"}
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../../src/elements/events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,yBAAyB,EAAE,yBAAyB,EAAE,2BAA2B,EAAC,MAAM,gBAAgB,CAAC;AACtH,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,qBAAqB,CAAC;AAExD,MAAM,WAAW,qBAAsB,SAAQ,WAAW;IACxD,MAAM,EAAE,kBAAkB,CAAC;CAC5B;AAED,MAAM,WAAW,uBAAwB,SAAQ,WAAW;IAC1D,MAAM,EAAE;QACN,SAAS,EAAE,cAAc,CAAC;QAC1B,cAAc,EAAE,WAAW,CAAC;KAC7B,CAAC;CACH;AAED,MAAM,WAAW,qBAAsB,SAAQ,WAAW;IACxD,MAAM,EAAE;QACN,SAAS,EAAE,cAAc,CAAC;KAC3B,CAAC;CACH;AAED,MAAM,WAAW,qBAAqB;IACpC,CAAC,yBAAyB,CAAC,EAAE,qBAAqB,CAAC;IACnD,CAAC,2BAA2B,CAAC,EAAE,uBAAuB,CAAC;IACvD,CAAC,yBAAyB,CAAC,EAAE,qBAAqB,CAAC;CACpD;AAED,OAAO,CAAC,MAAM,CAAC;IAGb,UAAU,mBAAoB,SAAQ,qBAAqB;KAAG;CAC/D"}
@@ -0,0 +1,19 @@
1
+ import type { ViewComponent } from '../view/ViewComponent.js';
2
+ /** An allow-list without entries forwards nothing — the same thing `false` says. */
3
+ export declare const isEmptyFilter: (val: Set<string> | boolean) => boolean;
4
+ /**
5
+ * Whether two filter values are the same value — a `Set` by its entries rather than by identity.
6
+ *
7
+ * This is not the question {@link isEmptyFilter} answers. An empty `Set` and `false` forward the
8
+ * same nothing, and they are still two different values: only a write that replaces the one with
9
+ * the other reaches the subscribers of the signal, and the read-back on connect depends on it.
10
+ */
11
+ export declare const isSameFilter: (a: Set<string> | boolean, b: Set<string> | boolean) => boolean;
12
+ /**
13
+ * Carry the events a component dispatches out to `target` as DOM events, as far as `filter` allows.
14
+ *
15
+ * Answers with the call that takes the forwarding back, or with `undefined` where `filter` forwards
16
+ * nothing and no patch was set.
17
+ */
18
+ export declare const forwardCustomEventsFrom: (vc: ViewComponent, target: EventTarget, filter: Set<string> | boolean) => (() => void) | undefined;
19
+ //# sourceMappingURL=forwardCustomEvents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forwardCustomEvents.d.ts","sourceRoot":"","sources":["../../../src/elements/forwardCustomEvents.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,0BAA0B,CAAC;AAE5D,oFAAoF;AACpF,eAAO,MAAM,aAAa,QAAS,GAAG,CAAC,MAAM,CAAC,GAAG,OAAO,KAAG,OAA+C,CAAC;AAE3G;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,MAAO,GAAG,CAAC,MAAM,CAAC,GAAG,OAAO,KAAK,GAAG,CAAC,MAAM,CAAC,GAAG,OAAO,KAAG,OAUjF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,OAC9B,aAAa,UACT,WAAW,UACX,GAAG,CAAC,MAAM,CAAC,GAAG,OAAO,KAC5B,CAAC,MAAM,IAAI,CAAC,GAAG,SA+CjB,CAAC"}
@@ -0,0 +1,47 @@
1
+ import { ComponentContext } from "../view/ComponentContext.js";
2
+ const isEmptyFilter = (val) => val instanceof Set && val.size === 0;
3
+ const isSameFilter = (a, b) => {
4
+ if (a === b) return true;
5
+ if (a instanceof Set && b instanceof Set) {
6
+ if (a.size !== b.size) return false;
7
+ for (const type of a) {
8
+ if (!b.has(type)) return false;
9
+ }
10
+ return true;
11
+ }
12
+ return false;
13
+ };
14
+ const forwardCustomEventsFrom = (vc, target, filter) => {
15
+ if (!filter || isEmptyFilter(filter)) return;
16
+ const originalDispatchEvent = Object.hasOwn(vc, "dispatchEvent") ? Object.getPrototypeOf(vc).dispatchEvent : vc.dispatchEvent;
17
+ const allowedTypes = filter instanceof Set ? filter : void 0;
18
+ const newDispatch = (type, data, traverseChildren) => {
19
+ originalDispatchEvent.call(vc, type, data, traverseChildren);
20
+ if (type === ComponentContext.ReRequestParentRoots || type === ComponentContext.ReRequestParent || type === ComponentContext.ReRequestEntHost)
21
+ return;
22
+ if (allowedTypes && !allowedTypes.has(type)) return;
23
+ target.dispatchEvent(
24
+ new CustomEvent(type, {
25
+ bubbles: true,
26
+ composed: true,
27
+ detail: data
28
+ })
29
+ );
30
+ };
31
+ Object.defineProperty(vc, "dispatchEvent", {
32
+ value: newDispatch,
33
+ writable: true,
34
+ configurable: true
35
+ });
36
+ return () => {
37
+ if (Object.hasOwn(vc, "dispatchEvent") && vc.dispatchEvent === newDispatch) {
38
+ delete vc.dispatchEvent;
39
+ }
40
+ };
41
+ };
42
+ export {
43
+ forwardCustomEventsFrom,
44
+ isEmptyFilter,
45
+ isSameFilter
46
+ };
47
+ //# sourceMappingURL=forwardCustomEvents.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/elements/forwardCustomEvents.ts"],
4
+ "sourcesContent": ["import {ComponentContext} from '../view/ComponentContext.js';\nimport type {ViewComponent} from '../view/ViewComponent.js';\n\n/** An allow-list without entries forwards nothing \u2014 the same thing `false` says. */\nexport const isEmptyFilter = (val: Set<string> | boolean): boolean => val instanceof Set && val.size === 0;\n\n/**\n * Whether two filter values are the same value \u2014 a `Set` by its entries rather than by identity.\n *\n * This is not the question {@link isEmptyFilter} answers. An empty `Set` and `false` forward the\n * same nothing, and they are still two different values: only a write that replaces the one with\n * the other reaches the subscribers of the signal, and the read-back on connect depends on it.\n */\nexport const isSameFilter = (a: Set<string> | boolean, b: Set<string> | boolean): boolean => {\n if (a === b) return true;\n if (a instanceof Set && b instanceof Set) {\n if (a.size !== b.size) return false;\n for (const type of a) {\n if (!b.has(type)) return false;\n }\n return true;\n }\n return false;\n};\n\n/**\n * Carry the events a component dispatches out to `target` as DOM events, as far as `filter` allows.\n *\n * Answers with the call that takes the forwarding back, or with `undefined` where `filter` forwards\n * nothing and no patch was set.\n */\nexport const forwardCustomEventsFrom = (\n vc: ViewComponent,\n target: EventTarget,\n filter: Set<string> | boolean,\n): (() => void) | undefined => {\n if (!filter || isEmptyFilter(filter)) return;\n\n // the patch goes on the instance, so a component that already carries one shadows the very\n // method the new patch has to call through to: that original sits on the prototype\n const originalDispatchEvent = Object.hasOwn(vc, 'dispatchEvent') ? Object.getPrototypeOf(vc).dispatchEvent : vc.dispatchEvent;\n\n const allowedTypes = filter instanceof Set ? filter : undefined;\n\n const newDispatch = (type: string, data: unknown, traverseChildren: boolean) => {\n originalDispatchEvent.call(vc, type, data, traverseChildren);\n\n // the internal signals of the parent resolution never leave the view side as a DOM event,\n // not even under `forward-custom-events` without a filter list\n if (\n type === ComponentContext.ReRequestParentRoots ||\n type === ComponentContext.ReRequestParent ||\n type === ComponentContext.ReRequestEntHost\n )\n return;\n\n if (allowedTypes && !allowedTypes.has(type)) return;\n\n target.dispatchEvent(\n new CustomEvent(type, {\n bubbles: true,\n composed: true,\n detail: data,\n }),\n );\n };\n\n // We use defineProperty to ensure it is writable and configurable\n Object.defineProperty(vc, 'dispatchEvent', {\n value: newDispatch,\n writable: true,\n configurable: true,\n });\n\n return () => {\n if (Object.hasOwn(vc, 'dispatchEvent') && vc.dispatchEvent === newDispatch) {\n // the property lives on the instance (defineProperty above), the method it shadows lives\n // on the prototype: deleting the own property restores the original, it does not remove\n // the method\n delete (vc as {dispatchEvent?: ViewComponent['dispatchEvent']}).dispatchEvent;\n }\n };\n};\n"],
5
+ "mappings": "AAAA,SAAQ,wBAAuB;AAIxB,MAAM,gBAAgB,CAAC,QAAwC,eAAe,OAAO,IAAI,SAAS;AASlG,MAAM,eAAe,CAAC,GAA0B,MAAsC;AAC3F,MAAI,MAAM,EAAG,QAAO;AACpB,MAAI,aAAa,OAAO,aAAa,KAAK;AACxC,QAAI,EAAE,SAAS,EAAE,KAAM,QAAO;AAC9B,eAAW,QAAQ,GAAG;AACpB,UAAI,CAAC,EAAE,IAAI,IAAI,EAAG,QAAO;AAAA,IAC3B;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAQO,MAAM,0BAA0B,CACrC,IACA,QACA,WAC6B;AAC7B,MAAI,CAAC,UAAU,cAAc,MAAM,EAAG;AAItC,QAAM,wBAAwB,OAAO,OAAO,IAAI,eAAe,IAAI,OAAO,eAAe,EAAE,EAAE,gBAAgB,GAAG;AAEhH,QAAM,eAAe,kBAAkB,MAAM,SAAS;AAEtD,QAAM,cAAc,CAAC,MAAc,MAAe,qBAA8B;AAC9E,0BAAsB,KAAK,IAAI,MAAM,MAAM,gBAAgB;AAI3D,QACE,SAAS,iBAAiB,wBAC1B,SAAS,iBAAiB,mBAC1B,SAAS,iBAAiB;AAE1B;AAEF,QAAI,gBAAgB,CAAC,aAAa,IAAI,IAAI,EAAG;AAE7C,WAAO;AAAA,MACL,IAAI,YAAY,MAAM;AAAA,QACpB,SAAS;AAAA,QACT,UAAU;AAAA,QACV,QAAQ;AAAA,MACV,CAAC;AAAA,IACH;AAAA,EACF;AAGA,SAAO,eAAe,IAAI,iBAAiB;AAAA,IACzC,OAAO;AAAA,IACP,UAAU;AAAA,IACV,cAAc;AAAA,EAChB,CAAC;AAED,SAAO,MAAM;AACX,QAAI,OAAO,OAAO,IAAI,eAAe,KAAK,GAAG,kBAAkB,aAAa;AAI1E,aAAQ,GAAwD;AAAA,IAClE;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,36 @@
1
+ import type { ShaeEntElement } from './ShaeEntElement.js';
2
+ /**
3
+ * The `<slot>`s one entity element answers for.
4
+ *
5
+ * The owner asks it to take up what it finds — {@link HostedSlots.collect} on the way into the
6
+ * tree, {@link HostedSlots.takeUp} for a slot that reports — and to let go of everything at
7
+ * once with {@link HostedSlots.releaseAll}. Everything beyond that it decides for itself.
8
+ */
9
+ export declare class HostedSlots {
10
+ #private;
11
+ constructor(owner: ShaeEntElement);
12
+ /**
13
+ * Take up the `<slot>`s below this element that project something.
14
+ *
15
+ * A slot is answered for from the moment it reports an assignment, and an entity leaving the
16
+ * tree lets go of every slot it holds. Entering the tree is the counterpart: the entity takes
17
+ * up the slots below it, because the assignment inside a shadow root does not change while
18
+ * its host is out of the document — nothing reports on the way back in, so the entity has to
19
+ * look for itself.
20
+ *
21
+ * Only inside a shadow root, and that test is exact rather than an optimization: a `<slot>`
22
+ * in a node tree that is not a shadow tree has no assignment and never reports one, so there
23
+ * is nothing below such an element to take up.
24
+ */
25
+ collect(): void;
26
+ /**
27
+ * Take up the slot a `slotchange` names, if this element is the closest entity above it.
28
+ *
29
+ * `event.target` is the slot that reports, which is what the bubbling channel at the element
30
+ * carries — a different reading from the one {@link HostedSlots} makes of a `slotchange` on a
31
+ * slot it listens to itself, where the slot in question is the one the listener hangs on.
32
+ */
33
+ takeUp(event: Event): void;
34
+ releaseAll(): void;
35
+ }
36
+ //# sourceMappingURL=hostedSlots.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hostedSlots.d.ts","sourceRoot":"","sources":["../../../src/elements/hostedSlots.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,qBAAqB,CAAC;AAiDxD;;;;;;GAMG;AACH,qBAAa,WAAW;;IAUtB,YAAY,KAAK,EAAE,cAAc,EAEhC;IAoDD;;;;;;;;;;;;OAYG;IACH,OAAO,SASN;IAED;;;;;;OAMG;IACH,MAAM,CAAC,KAAK,EAAE,KAAK,QAgBlB;IAED,UAAU,SAKT;CACF"}
@@ -0,0 +1,118 @@
1
+ import { ComponentContext } from "../view/ComponentContext.js";
2
+ const entHostOfSlot = /* @__PURE__ */ new WeakMap();
3
+ const reRequestedForSlotChange = /* @__PURE__ */ new WeakSet();
4
+ const askEveryoneToReRequest = (event) => {
5
+ if (reRequestedForSlotChange.has(event)) return;
6
+ reRequestedForSlotChange.add(event);
7
+ for (const context of ComponentContext.getContextsMap().values()) {
8
+ context.broadcastEvent(ComponentContext.ReRequestParent);
9
+ context.broadcastEvent(ComponentContext.ReRequestEntHost);
10
+ }
11
+ };
12
+ class HostedSlots {
13
+ #owner;
14
+ // The `<slot>`s this element currently answers for. A listener on the slot itself is the only
15
+ // thing that tells the side losing a slot about the loss: `slotchange` fires at the slot,
16
+ // wherever it has landed, and the ascent from there is the one reading of "is this still mine"
17
+ // that survives the move. `WeakRef` for the same reason as in the register — a slot that is gone
18
+ // is held by nobody here.
19
+ #slots = /* @__PURE__ */ new Set();
20
+ constructor(owner) {
21
+ this.#owner = owner;
22
+ }
23
+ // Whether this element is the closest entity above `slot`. The ascent goes over `parentElement`
24
+ // and nothing else, and both callers stand on the same ground for it: `slotchange` bubbles along
25
+ // the node tree of one shadow root, so the slot and every entity that can hear it sit in the same
26
+ // tree, and a slot found by `querySelectorAll` never leaves the node tree it was searched in
27
+ // either. The flattened parent is not the question here. Without the test every entity of the
28
+ // chain would write the register and the outermost one would win — the answer a projected node
29
+ // gets comes from the closest.
30
+ #isClosestEntAbove(slot) {
31
+ for (let current = slot.parentElement; current != null; current = current.parentElement) {
32
+ if (current === this.#owner) return true;
33
+ if (current.isShaeEntElement) return false;
34
+ }
35
+ return false;
36
+ }
37
+ #watch(slot) {
38
+ for (const ref of this.#slots) {
39
+ const el = ref.deref();
40
+ if (el === void 0) this.#slots.delete(ref);
41
+ else if (el === slot) return;
42
+ }
43
+ this.#slots.add(new WeakRef(slot));
44
+ slot.addEventListener("slotchange", this.#onSlotChange, { capture: false, passive: false });
45
+ }
46
+ #release(slot) {
47
+ slot.removeEventListener("slotchange", this.#onSlotChange, { capture: false });
48
+ for (const ref of this.#slots) {
49
+ const el = ref.deref();
50
+ if (el === void 0 || el === slot) this.#slots.delete(ref);
51
+ }
52
+ }
53
+ // `currentTarget` rather than `target`: a `<slot>` can stand in the fallback content of another
54
+ // slot, and what reports then is the inner one while the slot this listener hangs on is the one
55
+ // in question. The early return on "still mine" hands the whole job — register and round alike —
56
+ // to the bubbling listener, which would otherwise do it a second time. And the `null` entry: a
57
+ // slot that comes back to this entity has changed hands twice, and the round has to run for the
58
+ // second change as well.
59
+ #onSlotChange = (event) => {
60
+ const slot = event.currentTarget;
61
+ if (this.#isClosestEntAbove(slot)) return;
62
+ this.#release(slot);
63
+ if (entHostOfSlot.get(slot)?.deref() === this.#owner) {
64
+ entHostOfSlot.set(slot, null);
65
+ }
66
+ askEveryoneToReRequest(event);
67
+ };
68
+ /**
69
+ * Take up the `<slot>`s below this element that project something.
70
+ *
71
+ * A slot is answered for from the moment it reports an assignment, and an entity leaving the
72
+ * tree lets go of every slot it holds. Entering the tree is the counterpart: the entity takes
73
+ * up the slots below it, because the assignment inside a shadow root does not change while
74
+ * its host is out of the document — nothing reports on the way back in, so the entity has to
75
+ * look for itself.
76
+ *
77
+ * Only inside a shadow root, and that test is exact rather than an optimization: a `<slot>`
78
+ * in a node tree that is not a shadow tree has no assignment and never reports one, so there
79
+ * is nothing below such an element to take up.
80
+ */
81
+ collect() {
82
+ if (this.#owner.findShadowRootHost() == null) return;
83
+ for (const slot of this.#owner.querySelectorAll("slot")) {
84
+ if (slot.assignedNodes().length === 0) continue;
85
+ if (!this.#isClosestEntAbove(slot)) continue;
86
+ entHostOfSlot.set(slot, new WeakRef(this.#owner));
87
+ this.#watch(slot);
88
+ }
89
+ }
90
+ /**
91
+ * Take up the slot a `slotchange` names, if this element is the closest entity above it.
92
+ *
93
+ * `event.target` is the slot that reports, which is what the bubbling channel at the element
94
+ * carries — a different reading from the one {@link HostedSlots} makes of a `slotchange` on a
95
+ * slot it listens to itself, where the slot in question is the one the listener hangs on.
96
+ */
97
+ takeUp(event) {
98
+ const slot = event.target;
99
+ if (this.#isClosestEntAbove(slot)) {
100
+ const previous = entHostOfSlot.get(slot);
101
+ entHostOfSlot.set(slot, new WeakRef(this.#owner));
102
+ this.#watch(slot);
103
+ if (previous !== void 0 && previous?.deref() !== this.#owner) {
104
+ askEveryoneToReRequest(event);
105
+ }
106
+ }
107
+ }
108
+ releaseAll() {
109
+ for (const ref of this.#slots) {
110
+ ref.deref()?.removeEventListener("slotchange", this.#onSlotChange, { capture: false });
111
+ }
112
+ this.#slots.clear();
113
+ }
114
+ }
115
+ export {
116
+ HostedSlots
117
+ };
118
+ //# sourceMappingURL=hostedSlots.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/elements/hostedSlots.ts"],
4
+ "sourcesContent": ["import {ComponentContext} from '../view/ComponentContext.js';\nimport type {ShaeEntElement} from './ShaeEntElement.js';\n\n/**\n * The entity that answers for a `<slot>`, written on either of the two occasions an entity comes\n * to answer for one: the slot reports an assignment and the closest entity above it takes it up,\n * or an entity enters the tree and takes up the slots below it. The reporting writer takes the\n * slot as it finds it: `slotchange` announces every change of an assignment, one that has just\n * become empty included, so an entry can name a slot that projects nothing at this moment. What\n * no entry ever names is a slot that has not reported at all \u2014 and the entering writer holds that\n * line by skipping a slot with an empty assignment, because a name put on such a slot would let\n * its first report, under whatever entity it sits below by then, read as a change of hands.\n *\n * `slotchange` fires after the move and therefore at the new location; the place the slot came\n * from cannot be read from there any more \u2014 this register is the only place where it still has a\n * name. A `WeakMap` so a slot that is gone holds nothing, and a `WeakRef` as its value so a slot\n * that stays does not hold the entity it left: a slot can outlive its entity, and an entry read\n * back as empty is one more way of saying \"not the entity asking now\", which is the only thing\n * the register is ever asked.\n *\n * An entry of `null` names no entity and is still an entry: it says that the entity which answered\n * for this slot has let go of it. That is a different statement from `undefined`, which is a slot\n * nobody has ever reported.\n */\nconst entHostOfSlot = new WeakMap<Element, WeakRef<ShaeEntElement> | null>();\n\n/** The `slotchange` events whose re-request round has already run. */\nconst reRequestedForSlotChange = new WeakSet<Event>();\n\n/**\n * Everything the slot projects hangs on the entity above the slot, and the slot just took a\n * different one. There is no named counterpart to inform: the projected nodes can sit in any\n * namespace, below any entity, and the entities involved are not reachable from here. So the\n * request goes to every candidate there is, in every namespace: a property binds to the closest\n * entity above it whatever namespace that entity carries, and an entity from another namespace can\n * be projected through the same slot.\n *\n * Both sides of a move see the same event \u2014 the entity losing the slot as a listener on the slot\n * itself, the one gaining it while the event bubbles \u2014 and the round either of them would start is\n * the same round over the whole document. Whoever gets here first runs it.\n */\nconst askEveryoneToReRequest = (event: Event): void => {\n if (reRequestedForSlotChange.has(event)) return;\n reRequestedForSlotChange.add(event);\n for (const context of ComponentContext.getContextsMap().values()) {\n context.broadcastEvent(ComponentContext.ReRequestParent);\n context.broadcastEvent(ComponentContext.ReRequestEntHost);\n }\n};\n\n/**\n * The `<slot>`s one entity element answers for.\n *\n * The owner asks it to take up what it finds \u2014 {@link HostedSlots.collect} on the way into the\n * tree, {@link HostedSlots.takeUp} for a slot that reports \u2014 and to let go of everything at\n * once with {@link HostedSlots.releaseAll}. Everything beyond that it decides for itself.\n */\nexport class HostedSlots {\n readonly #owner: ShaeEntElement;\n\n // The `<slot>`s this element currently answers for. A listener on the slot itself is the only\n // thing that tells the side losing a slot about the loss: `slotchange` fires at the slot,\n // wherever it has landed, and the ascent from there is the one reading of \"is this still mine\"\n // that survives the move. `WeakRef` for the same reason as in the register \u2014 a slot that is gone\n // is held by nobody here.\n readonly #slots = new Set<WeakRef<Element>>();\n\n constructor(owner: ShaeEntElement) {\n this.#owner = owner;\n }\n\n // Whether this element is the closest entity above `slot`. The ascent goes over `parentElement`\n // and nothing else, and both callers stand on the same ground for it: `slotchange` bubbles along\n // the node tree of one shadow root, so the slot and every entity that can hear it sit in the same\n // tree, and a slot found by `querySelectorAll` never leaves the node tree it was searched in\n // either. The flattened parent is not the question here. Without the test every entity of the\n // chain would write the register and the outermost one would win \u2014 the answer a projected node\n // gets comes from the closest.\n #isClosestEntAbove(slot: Element): boolean {\n for (let current = slot.parentElement; current != null; current = current.parentElement) {\n if (current === this.#owner) return true;\n if ((current as ShaeEntElement).isShaeEntElement) return false;\n }\n return false;\n }\n\n #watch(slot: Element) {\n for (const ref of this.#slots) {\n const el = ref.deref();\n if (el === undefined) this.#slots.delete(ref);\n else if (el === slot) return;\n }\n this.#slots.add(new WeakRef(slot));\n slot.addEventListener('slotchange', this.#onSlotChange, {capture: false, passive: false});\n }\n\n #release(slot: Element) {\n slot.removeEventListener('slotchange', this.#onSlotChange, {capture: false});\n for (const ref of this.#slots) {\n const el = ref.deref();\n if (el === undefined || el === slot) this.#slots.delete(ref);\n }\n }\n\n // `currentTarget` rather than `target`: a `<slot>` can stand in the fallback content of another\n // slot, and what reports then is the inner one while the slot this listener hangs on is the one\n // in question. The early return on \"still mine\" hands the whole job \u2014 register and round alike \u2014\n // to the bubbling listener, which would otherwise do it a second time. And the `null` entry: a\n // slot that comes back to this entity has changed hands twice, and the round has to run for the\n // second change as well.\n #onSlotChange = (event: Event) => {\n const slot = event.currentTarget as Element;\n if (this.#isClosestEntAbove(slot)) return;\n\n this.#release(slot);\n if (entHostOfSlot.get(slot)?.deref() === this.#owner) {\n entHostOfSlot.set(slot, null);\n }\n askEveryoneToReRequest(event);\n };\n\n /**\n * Take up the `<slot>`s below this element that project something.\n *\n * A slot is answered for from the moment it reports an assignment, and an entity leaving the\n * tree lets go of every slot it holds. Entering the tree is the counterpart: the entity takes\n * up the slots below it, because the assignment inside a shadow root does not change while\n * its host is out of the document \u2014 nothing reports on the way back in, so the entity has to\n * look for itself.\n *\n * Only inside a shadow root, and that test is exact rather than an optimization: a `<slot>`\n * in a node tree that is not a shadow tree has no assignment and never reports one, so there\n * is nothing below such an element to take up.\n */\n collect() {\n if (this.#owner.findShadowRootHost() == null) return;\n\n for (const slot of this.#owner.querySelectorAll('slot')) {\n if (slot.assignedNodes().length === 0) continue;\n if (!this.#isClosestEntAbove(slot)) continue;\n entHostOfSlot.set(slot, new WeakRef(this.#owner));\n this.#watch(slot);\n }\n }\n\n /**\n * Take up the slot a `slotchange` names, if this element is the closest entity above it.\n *\n * `event.target` is the slot that reports, which is what the bubbling channel at the element\n * carries \u2014 a different reading from the one {@link HostedSlots} makes of a `slotchange` on a\n * slot it listens to itself, where the slot in question is the one the listener hangs on.\n */\n takeUp(event: Event) {\n const slot = event.target as Element;\n if (this.#isClosestEntAbove(slot)) {\n const previous = entHostOfSlot.get(slot);\n entHostOfSlot.set(slot, new WeakRef(this.#owner));\n this.#watch(slot);\n // the gate in front of the round, and it is closed twice. What a slot reporting for the\n // first time projects is reached by the two calls that frame this block, so the first\n // registration writes the register and pays nothing beyond it. Afterwards a slot whose\n // entity above it is the same one as last time reports changed content, and content moves\n // no binding. What is left is the slot that arrived here from somewhere else \u2014 and an entry\n // naming nobody is such an arrival too: that slot stood under no entity in between\n if (previous !== undefined && previous?.deref() !== this.#owner) {\n askEveryoneToReRequest(event);\n }\n }\n }\n\n releaseAll() {\n for (const ref of this.#slots) {\n ref.deref()?.removeEventListener('slotchange', this.#onSlotChange, {capture: false});\n }\n this.#slots.clear();\n }\n}\n"],
5
+ "mappings": "AAAA,SAAQ,wBAAuB;AAwB/B,MAAM,gBAAgB,oBAAI,QAAiD;AAG3E,MAAM,2BAA2B,oBAAI,QAAe;AAcpD,MAAM,yBAAyB,CAAC,UAAuB;AACrD,MAAI,yBAAyB,IAAI,KAAK,EAAG;AACzC,2BAAyB,IAAI,KAAK;AAClC,aAAW,WAAW,iBAAiB,eAAe,EAAE,OAAO,GAAG;AAChE,YAAQ,eAAe,iBAAiB,eAAe;AACvD,YAAQ,eAAe,iBAAiB,gBAAgB;AAAA,EAC1D;AACF;AASO,MAAM,YAAY;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,SAAS,oBAAI,IAAsB;AAAA,EAE5C,YAAY,OAAuB;AACjC,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,mBAAmB,MAAwB;AACzC,aAAS,UAAU,KAAK,eAAe,WAAW,MAAM,UAAU,QAAQ,eAAe;AACvF,UAAI,YAAY,KAAK,OAAQ,QAAO;AACpC,UAAK,QAA2B,iBAAkB,QAAO;AAAA,IAC3D;AACA,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,MAAe;AACpB,eAAW,OAAO,KAAK,QAAQ;AAC7B,YAAM,KAAK,IAAI,MAAM;AACrB,UAAI,OAAO,OAAW,MAAK,OAAO,OAAO,GAAG;AAAA,eACnC,OAAO,KAAM;AAAA,IACxB;AACA,SAAK,OAAO,IAAI,IAAI,QAAQ,IAAI,CAAC;AACjC,SAAK,iBAAiB,cAAc,KAAK,eAAe,EAAC,SAAS,OAAO,SAAS,MAAK,CAAC;AAAA,EAC1F;AAAA,EAEA,SAAS,MAAe;AACtB,SAAK,oBAAoB,cAAc,KAAK,eAAe,EAAC,SAAS,MAAK,CAAC;AAC3E,eAAW,OAAO,KAAK,QAAQ;AAC7B,YAAM,KAAK,IAAI,MAAM;AACrB,UAAI,OAAO,UAAa,OAAO,KAAM,MAAK,OAAO,OAAO,GAAG;AAAA,IAC7D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,gBAAgB,CAAC,UAAiB;AAChC,UAAM,OAAO,MAAM;AACnB,QAAI,KAAK,mBAAmB,IAAI,EAAG;AAEnC,SAAK,SAAS,IAAI;AAClB,QAAI,cAAc,IAAI,IAAI,GAAG,MAAM,MAAM,KAAK,QAAQ;AACpD,oBAAc,IAAI,MAAM,IAAI;AAAA,IAC9B;AACA,2BAAuB,KAAK;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,UAAU;AACR,QAAI,KAAK,OAAO,mBAAmB,KAAK,KAAM;AAE9C,eAAW,QAAQ,KAAK,OAAO,iBAAiB,MAAM,GAAG;AACvD,UAAI,KAAK,cAAc,EAAE,WAAW,EAAG;AACvC,UAAI,CAAC,KAAK,mBAAmB,IAAI,EAAG;AACpC,oBAAc,IAAI,MAAM,IAAI,QAAQ,KAAK,MAAM,CAAC;AAChD,WAAK,OAAO,IAAI;AAAA,IAClB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAO,OAAc;AACnB,UAAM,OAAO,MAAM;AACnB,QAAI,KAAK,mBAAmB,IAAI,GAAG;AACjC,YAAM,WAAW,cAAc,IAAI,IAAI;AACvC,oBAAc,IAAI,MAAM,IAAI,QAAQ,KAAK,MAAM,CAAC;AAChD,WAAK,OAAO,IAAI;AAOhB,UAAI,aAAa,UAAa,UAAU,MAAM,MAAM,KAAK,QAAQ;AAC/D,+BAAuB,KAAK;AAAA,MAC9B;AAAA,IACF;AAAA,EACF;AAAA,EAEA,aAAa;AACX,eAAW,OAAO,KAAK,QAAQ;AAC7B,UAAI,MAAM,GAAG,oBAAoB,cAAc,KAAK,eAAe,EAAC,SAAS,MAAK,CAAC;AAAA,IACrF;AACA,SAAK,OAAO,MAAM;AAAA,EACpB;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Run `onRemoved` once `node` is taken out of `parent`'s child list.
3
+ *
4
+ * A second call for the same pair replaces the callback. The watch ends the moment it fires
5
+ * — whoever wants to go on watching says so from inside the callback.
6
+ *
7
+ * A shared observer can already be sitting on a `childList` record from earlier in the same task
8
+ * — a sibling taken out a moment ago, still waiting for the microtask that delivers observer
9
+ * callbacks. Registering `node` now must not let that stale record apply to it once delivery
10
+ * catches up, so pending records are taken out and dispatched first, against the watchers this
11
+ * call still finds. `node` itself is not among them yet, so it cannot be the one a stale record
12
+ * matches — the only nodes a `takeRecords()` batch can name here are ones some earlier call
13
+ * already put in `parent`'s child list and that have since left it again.
14
+ */
15
+ export declare const watchForRemovalFrom: (parent: Node, node: Node, onRemoved: () => void) => void;
16
+ /** Stop watching `node` under `parent`. A pair nobody watches is left alone. */
17
+ export declare const stopWatchingForRemovalFrom: (parent: Node, node: Node) => void;
18
+ //# sourceMappingURL=parentRemoval.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parentRemoval.d.ts","sourceRoot":"","sources":["../../../src/elements/parentRemoval.ts"],"names":[],"mappings":"AA8EA;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,mBAAmB,WAAY,IAAI,QAAQ,IAAI,aAAa,MAAM,IAAI,KAAG,IAerF,CAAC;AAEF,gFAAgF;AAChF,eAAO,MAAM,0BAA0B,WAAY,IAAI,QAAQ,IAAI,KAAG,IAQrE,CAAC"}
@@ -0,0 +1,60 @@
1
+ const parentWatches = /* @__PURE__ */ new WeakMap();
2
+ const dispatchRemovals = (watch, mutations) => {
3
+ const removed = [];
4
+ for (const { removedNodes } of mutations) {
5
+ for (const node of removedNodes) {
6
+ const onRemoved = watch.watchers.get(node);
7
+ if (onRemoved == null) continue;
8
+ watch.watchers.delete(node);
9
+ removed.push(onRemoved);
10
+ }
11
+ }
12
+ for (const onRemoved of removed) {
13
+ try {
14
+ onRemoved();
15
+ } catch (error) {
16
+ console.error("a removal watcher failed:", error);
17
+ }
18
+ }
19
+ };
20
+ const createParentWatch = (parent) => {
21
+ const watchers = /* @__PURE__ */ new Map();
22
+ const watch = {
23
+ observer: new MutationObserver((mutations, activeObserver) => {
24
+ dispatchRemovals(watch, mutations);
25
+ if (watchers.size === 0) {
26
+ activeObserver.disconnect();
27
+ if (parentWatches.get(parent) === watch) parentWatches.delete(parent);
28
+ }
29
+ }),
30
+ watchers
31
+ };
32
+ watch.observer.observe(parent, { childList: true, subtree: false, attributes: false });
33
+ return watch;
34
+ };
35
+ const watchForRemovalFrom = (parent, node, onRemoved) => {
36
+ let watch = parentWatches.get(parent);
37
+ if (watch != null) {
38
+ dispatchRemovals(watch, watch.observer.takeRecords());
39
+ watch = parentWatches.get(parent);
40
+ }
41
+ if (watch == null) {
42
+ watch = createParentWatch(parent);
43
+ parentWatches.set(parent, watch);
44
+ }
45
+ watch.watchers.set(node, onRemoved);
46
+ };
47
+ const stopWatchingForRemovalFrom = (parent, node) => {
48
+ const watch = parentWatches.get(parent);
49
+ if (watch == null) return;
50
+ if (!watch.watchers.delete(node)) return;
51
+ if (watch.watchers.size === 0) {
52
+ watch.observer.disconnect();
53
+ parentWatches.delete(parent);
54
+ }
55
+ };
56
+ export {
57
+ stopWatchingForRemovalFrom,
58
+ watchForRemovalFrom
59
+ };
60
+ //# sourceMappingURL=parentRemoval.js.map