@gyral/core 0.2.0 → 0.3.1

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 (517) hide show
  1. package/CHANGELOG.md +129 -0
  2. package/NOTICE +19 -0
  3. package/README.md +35 -8
  4. package/dist/call.d.ts +32 -0
  5. package/dist/call.js +63 -0
  6. package/dist/call.js.map +1 -0
  7. package/dist/children.d.ts +30 -5
  8. package/dist/children.js +26 -4
  9. package/dist/children.js.map +1 -1
  10. package/dist/cli/gyral-types.d.ts +2 -0
  11. package/dist/cli/gyral-types.js +23 -0
  12. package/dist/cli/gyral-types.js.map +1 -0
  13. package/dist/command.d.ts +54 -12
  14. package/dist/command.js +31 -11
  15. package/dist/command.js.map +1 -1
  16. package/dist/compiler/ast.d.ts +23 -0
  17. package/dist/compiler/ast.js +149 -0
  18. package/dist/compiler/ast.js.map +1 -0
  19. package/dist/compiler/compile.d.ts +41 -0
  20. package/dist/compiler/compile.js +148 -0
  21. package/dist/compiler/compile.js.map +1 -0
  22. package/dist/compiler/component-entries.d.ts +7 -0
  23. package/dist/compiler/component-entries.js +42 -0
  24. package/dist/compiler/component-entries.js.map +1 -0
  25. package/dist/compiler/components.d.ts +4 -0
  26. package/dist/compiler/components.js +182 -0
  27. package/dist/compiler/components.js.map +1 -0
  28. package/dist/compiler/facts.d.ts +31 -0
  29. package/dist/compiler/facts.js +285 -0
  30. package/dist/compiler/facts.js.map +1 -0
  31. package/dist/compiler/features.d.ts +34 -0
  32. package/dist/compiler/features.js +158 -0
  33. package/dist/compiler/features.js.map +1 -0
  34. package/dist/compiler/hooks.d.ts +22 -0
  35. package/dist/compiler/hooks.js +241 -0
  36. package/dist/compiler/hooks.js.map +1 -0
  37. package/dist/compiler/loader-source.d.ts +14 -0
  38. package/dist/compiler/loader-source.js +86 -0
  39. package/dist/compiler/loader-source.js.map +1 -0
  40. package/dist/compiler/locate.d.ts +14 -0
  41. package/dist/compiler/locate.js +78 -0
  42. package/dist/compiler/locate.js.map +1 -0
  43. package/dist/compiler/parse5-check.d.ts +21 -0
  44. package/dist/compiler/parse5-check.js +60 -0
  45. package/dist/compiler/parse5-check.js.map +1 -0
  46. package/dist/compiler/prop-schemas.d.ts +4 -0
  47. package/dist/compiler/prop-schemas.js +108 -0
  48. package/dist/compiler/prop-schemas.js.map +1 -0
  49. package/dist/compiler/scan.d.ts +41 -0
  50. package/dist/compiler/scan.js +160 -0
  51. package/dist/compiler/scan.js.map +1 -0
  52. package/dist/compiler/scope.d.ts +8 -0
  53. package/dist/compiler/scope.js +116 -0
  54. package/dist/compiler/scope.js.map +1 -0
  55. package/dist/compiler/source.d.ts +34 -0
  56. package/dist/compiler/source.js +114 -0
  57. package/dist/compiler/source.js.map +1 -0
  58. package/dist/compiler/tag-map.d.ts +41 -0
  59. package/dist/compiler/tag-map.js +126 -0
  60. package/dist/compiler/tag-map.js.map +1 -0
  61. package/dist/components-ready.d.ts +7 -0
  62. package/dist/components-ready.js +19 -0
  63. package/dist/components-ready.js.map +1 -0
  64. package/dist/define.d.ts +13 -4
  65. package/dist/define.js +35 -331
  66. package/dist/define.js.map +1 -1
  67. package/dist/devtools-events.d.ts +13 -0
  68. package/dist/devtools-events.js.map +1 -1
  69. package/dist/devtools-off.d.ts +2 -0
  70. package/dist/devtools-off.js +2 -0
  71. package/dist/devtools-off.js.map +1 -1
  72. package/dist/devtools.d.ts +4 -0
  73. package/dist/devtools.js +17 -2
  74. package/dist/devtools.js.map +1 -1
  75. package/dist/drivers-scope.d.ts +1 -1
  76. package/dist/drivers-scope.js +1 -8
  77. package/dist/drivers-scope.js.map +1 -1
  78. package/dist/element-internals.d.ts +1 -0
  79. package/dist/element-internals.js +11 -0
  80. package/dist/element-internals.js.map +1 -0
  81. package/dist/element-types.d.ts +11 -5
  82. package/dist/element-types.js.map +1 -1
  83. package/dist/element.d.ts +3 -0
  84. package/dist/element.js +322 -0
  85. package/dist/element.js.map +1 -0
  86. package/dist/error-view.d.ts +10 -0
  87. package/dist/error-view.js +30 -0
  88. package/dist/error-view.js.map +1 -0
  89. package/dist/errors.d.ts +21 -0
  90. package/dist/errors.js +47 -0
  91. package/dist/errors.js.map +1 -0
  92. package/dist/errors.json +289 -0
  93. package/dist/eslint/imports.d.ts +26 -0
  94. package/dist/eslint/imports.js +78 -0
  95. package/dist/eslint/imports.js.map +1 -0
  96. package/dist/eslint/index.d.ts +16 -0
  97. package/dist/eslint/index.js +23 -0
  98. package/dist/eslint/index.js.map +1 -0
  99. package/dist/eslint/locate.d.ts +33 -0
  100. package/dist/eslint/locate.js +132 -0
  101. package/dist/eslint/locate.js.map +1 -0
  102. package/dist/eslint/row-purity-rule.d.ts +2 -0
  103. package/dist/eslint/row-purity-rule.js +103 -0
  104. package/dist/eslint/row-purity-rule.js.map +1 -0
  105. package/dist/eslint/template-rule.d.ts +6 -0
  106. package/dist/eslint/template-rule.js +76 -0
  107. package/dist/eslint/template-rule.js.map +1 -0
  108. package/dist/eslint/unused-intent-rule.d.ts +2 -0
  109. package/dist/eslint/unused-intent-rule.js +186 -0
  110. package/dist/eslint/unused-intent-rule.js.map +1 -0
  111. package/dist/features.d.ts +39 -0
  112. package/dist/features.js +2 -0
  113. package/dist/features.js.map +1 -0
  114. package/dist/focus.d.ts +13 -12
  115. package/dist/focus.js +44 -11
  116. package/dist/focus.js.map +1 -1
  117. package/dist/form-associated.d.ts +46 -0
  118. package/dist/form-associated.js +77 -0
  119. package/dist/form-associated.js.map +1 -0
  120. package/dist/forms.d.ts +42 -30
  121. package/dist/forms.js +85 -41
  122. package/dist/forms.js.map +1 -1
  123. package/dist/frame-lane.d.ts +11 -0
  124. package/dist/frame-lane.js +28 -0
  125. package/dist/frame-lane.js.map +1 -0
  126. package/dist/head.d.ts +61 -0
  127. package/dist/head.js +85 -0
  128. package/dist/head.js.map +1 -0
  129. package/dist/hooks/invalid.d.ts +14 -0
  130. package/dist/hooks/invalid.js +72 -0
  131. package/dist/hooks/invalid.js.map +1 -0
  132. package/dist/host-model.d.ts +77 -0
  133. package/dist/host-model.js +278 -0
  134. package/dist/host-model.js.map +1 -0
  135. package/dist/hydration-client.d.ts +9 -0
  136. package/dist/hydration-client.js +35 -0
  137. package/dist/hydration-client.js.map +1 -0
  138. package/dist/hydration-loader.d.ts +13 -0
  139. package/dist/hydration-loader.js +58 -0
  140. package/dist/hydration-loader.js.map +1 -0
  141. package/dist/hydration-off.d.ts +8 -0
  142. package/dist/hydration-off.js +25 -0
  143. package/dist/hydration-off.js.map +1 -0
  144. package/dist/hydration.d.ts +3 -21
  145. package/dist/hydration.js +14 -63
  146. package/dist/hydration.js.map +1 -1
  147. package/dist/index.d.ts +24 -36
  148. package/dist/index.js +14 -32
  149. package/dist/index.js.map +1 -1
  150. package/dist/indexeddb-types.d.ts +97 -0
  151. package/dist/indexeddb-types.js +2 -0
  152. package/dist/indexeddb-types.js.map +1 -0
  153. package/dist/indexeddb.d.ts +5 -0
  154. package/dist/indexeddb.js +118 -0
  155. package/dist/indexeddb.js.map +1 -0
  156. package/dist/intent.d.ts +62 -17
  157. package/dist/intent.js +193 -100
  158. package/dist/intent.js.map +1 -1
  159. package/dist/internal/indexeddb-open.d.ts +8 -0
  160. package/dist/internal/indexeddb-open.js +96 -0
  161. package/dist/internal/indexeddb-open.js.map +1 -0
  162. package/dist/internal/indexeddb-transaction.d.ts +4 -0
  163. package/dist/internal/indexeddb-transaction.js +134 -0
  164. package/dist/internal/indexeddb-transaction.js.map +1 -0
  165. package/dist/internal/interpreter.d.ts +15 -1
  166. package/dist/internal/interpreter.js +42 -47
  167. package/dist/internal/interpreter.js.map +1 -1
  168. package/dist/internal/token.d.ts +1 -0
  169. package/dist/internal/token.js +7 -0
  170. package/dist/internal/token.js.map +1 -0
  171. package/dist/internal.d.ts +20 -0
  172. package/dist/internal.js +22 -0
  173. package/dist/internal.js.map +1 -0
  174. package/dist/invoker-fallback-used.d.ts +4 -0
  175. package/dist/invoker-fallback-used.js +10 -0
  176. package/dist/invoker-fallback-used.js.map +1 -0
  177. package/dist/invoker-fallback.d.ts +4 -0
  178. package/dist/invoker-fallback.js +15 -0
  179. package/dist/invoker-fallback.js.map +1 -0
  180. package/dist/invokers-shim.d.ts +6 -0
  181. package/dist/invokers-shim.js +32 -0
  182. package/dist/invokers-shim.js.map +1 -0
  183. package/dist/invokers.d.ts +3 -5
  184. package/dist/invokers.js +11 -51
  185. package/dist/invokers.js.map +1 -1
  186. package/dist/islands.d.ts +0 -2
  187. package/dist/islands.js +4 -11
  188. package/dist/islands.js.map +1 -1
  189. package/dist/light-dom.d.ts +4 -53
  190. package/dist/light-dom.js +5 -100
  191. package/dist/light-dom.js.map +1 -1
  192. package/dist/prop.d.ts +89 -0
  193. package/dist/prop.js +41 -0
  194. package/dist/prop.js.map +1 -0
  195. package/dist/props.d.ts +57 -21
  196. package/dist/props.js +157 -34
  197. package/dist/props.js.map +1 -1
  198. package/dist/retry.d.ts +15 -0
  199. package/dist/retry.js +48 -0
  200. package/dist/retry.js.map +1 -0
  201. package/dist/scheduler.d.ts +43 -0
  202. package/dist/scheduler.js +212 -0
  203. package/dist/scheduler.js.map +1 -0
  204. package/dist/script-json.d.ts +2 -0
  205. package/dist/script-json.js +13 -0
  206. package/dist/script-json.js.map +1 -0
  207. package/dist/server-component.d.ts +10 -0
  208. package/dist/server-component.js +133 -0
  209. package/dist/server-component.js.map +1 -0
  210. package/dist/server-specs.d.ts +6 -0
  211. package/dist/server-specs.js +13 -0
  212. package/dist/server-specs.js.map +1 -0
  213. package/dist/server.d.ts +34 -0
  214. package/dist/server.js +59 -0
  215. package/dist/server.js.map +1 -0
  216. package/dist/settled.d.ts +11 -0
  217. package/dist/settled.js +62 -0
  218. package/dist/settled.js.map +1 -0
  219. package/dist/spec-features-used.d.ts +21 -0
  220. package/dist/spec-features-used.js +50 -0
  221. package/dist/spec-features-used.js.map +1 -0
  222. package/dist/spec-features.d.ts +28 -0
  223. package/dist/spec-features.js +42 -0
  224. package/dist/spec-features.js.map +1 -0
  225. package/dist/states.d.ts +3 -5
  226. package/dist/states.js +22 -11
  227. package/dist/states.js.map +1 -1
  228. package/dist/storage.d.ts +69 -0
  229. package/dist/storage.js +158 -0
  230. package/dist/storage.js.map +1 -0
  231. package/dist/store-binding.d.ts +6 -3
  232. package/dist/store-binding.js +7 -8
  233. package/dist/store-binding.js.map +1 -1
  234. package/dist/store-scope.d.ts +8 -11
  235. package/dist/store-scope.js +15 -40
  236. package/dist/store-scope.js.map +1 -1
  237. package/dist/store.d.ts +3 -0
  238. package/dist/store.js +45 -10
  239. package/dist/store.js.map +1 -1
  240. package/dist/stores-provider.d.ts +2 -6
  241. package/dist/stores-provider.js +21 -55
  242. package/dist/stores-provider.js.map +1 -1
  243. package/dist/subscription.d.ts +35 -0
  244. package/dist/subscription.js +74 -0
  245. package/dist/subscription.js.map +1 -0
  246. package/dist/subscriptions.d.ts +26 -0
  247. package/dist/subscriptions.js +98 -0
  248. package/dist/subscriptions.js.map +1 -0
  249. package/dist/transitions.d.ts +5 -7
  250. package/dist/transitions.js +17 -20
  251. package/dist/transitions.js.map +1 -1
  252. package/dist/types.d.ts +142 -49
  253. package/dist/types.js.map +1 -1
  254. package/dist/use-dialogs.d.ts +2 -0
  255. package/dist/use-dialogs.js +9 -0
  256. package/dist/use-dialogs.js.map +1 -0
  257. package/dist/use-disposal.d.ts +2 -0
  258. package/dist/use-disposal.js +9 -0
  259. package/dist/use-disposal.js.map +1 -0
  260. package/dist/use-error-view.d.ts +2 -0
  261. package/dist/use-error-view.js +9 -0
  262. package/dist/use-error-view.js.map +1 -0
  263. package/dist/use-errored.d.ts +2 -0
  264. package/dist/use-errored.js +9 -0
  265. package/dist/use-errored.js.map +1 -0
  266. package/dist/use-form-associated.d.ts +2 -0
  267. package/dist/use-form-associated.js +7 -0
  268. package/dist/use-form-associated.js.map +1 -0
  269. package/dist/use-frame-lane.d.ts +2 -0
  270. package/dist/use-frame-lane.js +10 -0
  271. package/dist/use-frame-lane.js.map +1 -0
  272. package/dist/use-invokers.d.ts +2 -0
  273. package/dist/use-invokers.js +10 -0
  274. package/dist/use-invokers.js.map +1 -0
  275. package/dist/use-states.d.ts +2 -0
  276. package/dist/use-states.js +10 -0
  277. package/dist/use-states.js.map +1 -0
  278. package/dist/use-subscriptions.d.ts +2 -0
  279. package/dist/use-subscriptions.js +10 -0
  280. package/dist/use-subscriptions.js.map +1 -0
  281. package/dist/use-transitions.d.ts +2 -0
  282. package/dist/use-transitions.js +10 -0
  283. package/dist/use-transitions.js.map +1 -0
  284. package/dist/view/attributes.d.ts +11 -0
  285. package/dist/view/attributes.js +15 -0
  286. package/dist/view/attributes.js.map +1 -0
  287. package/dist/view/compiled.d.ts +1 -0
  288. package/dist/view/compiled.js +6 -0
  289. package/dist/view/compiled.js.map +1 -0
  290. package/dist/view/dev-off.d.ts +1 -0
  291. package/dist/view/dev-off.js +4 -0
  292. package/dist/view/dev-off.js.map +1 -0
  293. package/dist/view/dev.d.ts +1 -0
  294. package/dist/view/dev.js +5 -0
  295. package/dist/view/dev.js.map +1 -0
  296. package/dist/view/flags.d.ts +1 -0
  297. package/dist/view/flags.js +4 -0
  298. package/dist/view/flags.js.map +1 -0
  299. package/dist/view/index.d.ts +26 -0
  300. package/dist/view/index.js +27 -0
  301. package/dist/view/index.js.map +1 -0
  302. package/dist/view/loc.d.ts +9 -0
  303. package/dist/view/loc.js +50 -0
  304. package/dist/view/loc.js.map +1 -0
  305. package/dist/view/message.d.ts +17 -0
  306. package/dist/view/message.js +40 -0
  307. package/dist/view/message.js.map +1 -0
  308. package/dist/view/messages.d.ts +43 -0
  309. package/dist/view/messages.js +84 -0
  310. package/dist/view/messages.js.map +1 -0
  311. package/dist/view/normalize/check.d.ts +23 -0
  312. package/dist/view/normalize/check.js +81 -0
  313. package/dist/view/normalize/check.js.map +1 -0
  314. package/dist/view/normalize/emit.d.ts +15 -0
  315. package/dist/view/normalize/emit.js +165 -0
  316. package/dist/view/normalize/emit.js.map +1 -0
  317. package/dist/view/normalize/entities.d.ts +4 -0
  318. package/dist/view/normalize/entities.js +38 -0
  319. package/dist/view/normalize/entities.js.map +1 -0
  320. package/dist/view/normalize/errors.d.ts +9 -0
  321. package/dist/view/normalize/errors.js +19 -0
  322. package/dist/view/normalize/errors.js.map +1 -0
  323. package/dist/view/normalize/id.d.ts +10 -0
  324. package/dist/view/normalize/id.js +55 -0
  325. package/dist/view/normalize/id.js.map +1 -0
  326. package/dist/view/normalize/normalize.d.ts +18 -0
  327. package/dist/view/normalize/normalize.js +42 -0
  328. package/dist/view/normalize/normalize.js.map +1 -0
  329. package/dist/view/normalize/repairs.d.ts +24 -0
  330. package/dist/view/normalize/repairs.js +166 -0
  331. package/dist/view/normalize/repairs.js.map +1 -0
  332. package/dist/view/normalize/rules.d.ts +39 -0
  333. package/dist/view/normalize/rules.js +120 -0
  334. package/dist/view/normalize/rules.js.map +1 -0
  335. package/dist/view/normalize/shape.d.ts +5 -0
  336. package/dist/view/normalize/shape.js +38 -0
  337. package/dist/view/normalize/shape.js.map +1 -0
  338. package/dist/view/normalize/source.d.ts +13 -0
  339. package/dist/view/normalize/source.js +34 -0
  340. package/dist/view/normalize/source.js.map +1 -0
  341. package/dist/view/normalize/svg.d.ts +14 -0
  342. package/dist/view/normalize/svg.js +40 -0
  343. package/dist/view/normalize/svg.js.map +1 -0
  344. package/dist/view/normalize/tag-states.d.ts +23 -0
  345. package/dist/view/normalize/tag-states.js +192 -0
  346. package/dist/view/normalize/tag-states.js.map +1 -0
  347. package/dist/view/normalize/tokenizer.d.ts +5 -0
  348. package/dist/view/normalize/tokenizer.js +233 -0
  349. package/dist/view/normalize/tokenizer.js.map +1 -0
  350. package/dist/view/normalize/tokens.d.ts +55 -0
  351. package/dist/view/normalize/tokens.js +24 -0
  352. package/dist/view/normalize/tokens.js.map +1 -0
  353. package/dist/view/normalize/tree.d.ts +65 -0
  354. package/dist/view/normalize/tree.js +235 -0
  355. package/dist/view/normalize/tree.js.map +1 -0
  356. package/dist/view/normalize/types.d.ts +146 -0
  357. package/dist/view/normalize/types.js +29 -0
  358. package/dist/view/normalize/types.js.map +1 -0
  359. package/dist/view/normalize/whitespace.d.ts +2 -0
  360. package/dist/{template-whitespace.js → view/normalize/whitespace.js} +27 -36
  361. package/dist/view/normalize/whitespace.js.map +1 -0
  362. package/dist/view/prepare-stub.d.ts +3 -0
  363. package/dist/view/prepare-stub.js +7 -0
  364. package/dist/view/prepare-stub.js.map +1 -0
  365. package/dist/view/prepare.d.ts +11 -0
  366. package/dist/view/prepare.js +63 -0
  367. package/dist/view/prepare.js.map +1 -0
  368. package/dist/view/registry.d.ts +78 -0
  369. package/dist/view/registry.js +27 -0
  370. package/dist/view/registry.js.map +1 -0
  371. package/dist/view/render/adopt-attr.d.ts +14 -0
  372. package/dist/view/render/adopt-attr.js +83 -0
  373. package/dist/view/render/adopt-attr.js.map +1 -0
  374. package/dist/view/render/adopt-plan.d.ts +10 -0
  375. package/dist/view/render/adopt-plan.js +26 -0
  376. package/dist/view/render/adopt-plan.js.map +1 -0
  377. package/dist/view/render/adopt.d.ts +3 -0
  378. package/dist/view/render/adopt.js +286 -0
  379. package/dist/view/render/adopt.js.map +1 -0
  380. package/dist/view/render/attr-parts.d.ts +72 -0
  381. package/dist/view/render/attr-parts.js +262 -0
  382. package/dist/view/render/attr-parts.js.map +1 -0
  383. package/dist/view/render/child-part.d.ts +51 -0
  384. package/dist/view/render/child-part.js +173 -0
  385. package/dist/view/render/child-part.js.map +1 -0
  386. package/dist/view/render/dev-check.d.ts +12 -0
  387. package/dist/view/render/dev-check.js +122 -0
  388. package/dist/view/render/dev-check.js.map +1 -0
  389. package/dist/view/render/dispose.d.ts +3 -0
  390. package/dist/view/render/dispose.js +76 -0
  391. package/dist/view/render/dispose.js.map +1 -0
  392. package/dist/view/render/hook-part.d.ts +5 -0
  393. package/dist/view/render/hook-part.js +36 -0
  394. package/dist/view/render/hook-part.js.map +1 -0
  395. package/dist/view/render/hook-run.d.ts +2 -0
  396. package/dist/view/render/hook-run.js +72 -0
  397. package/dist/view/render/hook-run.js.map +1 -0
  398. package/dist/view/render/hooks.d.ts +108 -0
  399. package/dist/view/render/hooks.js +108 -0
  400. package/dist/view/render/hooks.js.map +1 -0
  401. package/dist/view/render/hydrate.d.ts +10 -0
  402. package/dist/view/render/hydrate.js +33 -0
  403. package/dist/view/render/hydrate.js.map +1 -0
  404. package/dist/view/render/instance.d.ts +33 -0
  405. package/dist/view/render/instance.js +107 -0
  406. package/dist/view/render/instance.js.map +1 -0
  407. package/dist/view/render/keyed.d.ts +6 -0
  408. package/dist/view/render/keyed.js +15 -0
  409. package/dist/view/render/keyed.js.map +1 -0
  410. package/dist/view/render/list.d.ts +20 -0
  411. package/dist/view/render/list.js +156 -0
  412. package/dist/view/render/list.js.map +1 -0
  413. package/dist/view/render/mismatch.d.ts +10 -0
  414. package/dist/view/render/mismatch.js +55 -0
  415. package/dist/view/render/mismatch.js.map +1 -0
  416. package/dist/view/render/modal.d.ts +3 -0
  417. package/dist/view/render/modal.js +39 -0
  418. package/dist/view/render/modal.js.map +1 -0
  419. package/dist/view/render/nodes.d.ts +10 -0
  420. package/dist/view/render/nodes.js +37 -0
  421. package/dist/view/render/nodes.js.map +1 -0
  422. package/dist/view/render/place.d.ts +18 -0
  423. package/dist/view/render/place.js +69 -0
  424. package/dist/view/render/place.js.map +1 -0
  425. package/dist/view/render/plan.d.ts +26 -0
  426. package/dist/view/render/plan.js +124 -0
  427. package/dist/view/render/plan.js.map +1 -0
  428. package/dist/view/render/raw.d.ts +21 -0
  429. package/dist/view/render/raw.js +72 -0
  430. package/dist/view/render/raw.js.map +1 -0
  431. package/dist/view/render/render.d.ts +15 -0
  432. package/dist/view/render/render.js +65 -0
  433. package/dist/view/render/render.js.map +1 -0
  434. package/dist/view/render/reorder.d.ts +4 -0
  435. package/dist/view/render/reorder.js +101 -0
  436. package/dist/view/render/reorder.js.map +1 -0
  437. package/dist/view/render/rows.d.ts +23 -0
  438. package/dist/view/render/rows.js +95 -0
  439. package/dist/view/render/rows.js.map +1 -0
  440. package/dist/view/render/seen.d.ts +11 -0
  441. package/dist/view/render/seen.js +17 -0
  442. package/dist/view/render/seen.js.map +1 -0
  443. package/dist/view/render/toggles.d.ts +6 -0
  444. package/dist/view/render/toggles.js +6 -0
  445. package/dist/view/render/toggles.js.map +1 -0
  446. package/dist/view/render/values.d.ts +29 -0
  447. package/dist/view/render/values.js +13 -0
  448. package/dist/view/render/values.js.map +1 -0
  449. package/dist/view/render/warn.d.ts +28 -0
  450. package/dist/view/render/warn.js +114 -0
  451. package/dist/view/render/warn.js.map +1 -0
  452. package/dist/view/server/component.d.ts +12 -0
  453. package/dist/view/server/component.js +64 -0
  454. package/dist/view/server/component.js.map +1 -0
  455. package/dist/view/server/escape.d.ts +10 -0
  456. package/dist/view/server/escape.js +34 -0
  457. package/dist/view/server/escape.js.map +1 -0
  458. package/dist/view/server/index.d.ts +48 -0
  459. package/dist/view/server/index.js +80 -0
  460. package/dist/view/server/index.js.map +1 -0
  461. package/dist/view/server/sha256.d.ts +2 -0
  462. package/dist/view/server/sha256.js +75 -0
  463. package/dist/view/server/sha256.js.map +1 -0
  464. package/dist/view/server/tags.d.ts +68 -0
  465. package/dist/view/server/tags.js +132 -0
  466. package/dist/view/server/tags.js.map +1 -0
  467. package/dist/view/server/values.d.ts +18 -0
  468. package/dist/view/server/values.js +94 -0
  469. package/dist/view/server/values.js.map +1 -0
  470. package/dist/view/server/writer.d.ts +21 -0
  471. package/dist/view/server/writer.js +170 -0
  472. package/dist/view/server/writer.js.map +1 -0
  473. package/dist/view/styles.d.ts +25 -0
  474. package/dist/view/styles.js +58 -0
  475. package/dist/view/styles.js.map +1 -0
  476. package/dist/view/template-element.d.ts +10 -0
  477. package/dist/view/template-element.js +45 -0
  478. package/dist/view/template-element.js.map +1 -0
  479. package/dist/view/template.d.ts +29 -0
  480. package/dist/view/template.js +84 -0
  481. package/dist/view/template.js.map +1 -0
  482. package/dist/view/trusted-html.d.ts +6 -0
  483. package/dist/view/trusted-html.js +34 -0
  484. package/dist/view/trusted-html.js.map +1 -0
  485. package/dist/vite.d.ts +57 -11
  486. package/dist/vite.js +319 -27
  487. package/dist/vite.js.map +1 -1
  488. package/package.json +70 -4
  489. package/dist/accessible-name.d.ts +0 -19
  490. package/dist/accessible-name.js +0 -56
  491. package/dist/accessible-name.js.map +0 -1
  492. package/dist/element-directive.d.ts +0 -20
  493. package/dist/element-directive.js +0 -31
  494. package/dist/element-directive.js.map +0 -1
  495. package/dist/invalid.d.ts +0 -21
  496. package/dist/invalid.js +0 -70
  497. package/dist/invalid.js.map +0 -1
  498. package/dist/lit-html-check.d.ts +0 -6
  499. package/dist/lit-html-check.js +0 -48
  500. package/dist/lit-html-check.js.map +0 -1
  501. package/dist/live-boolean.d.ts +0 -22
  502. package/dist/live-boolean.js +0 -34
  503. package/dist/live-boolean.js.map +0 -1
  504. package/dist/random.d.ts +0 -13
  505. package/dist/random.js +0 -19
  506. package/dist/random.js.map +0 -1
  507. package/dist/styles.d.ts +0 -12
  508. package/dist/styles.js +0 -11
  509. package/dist/styles.js.map +0 -1
  510. package/dist/template-whitespace.d.ts +0 -7
  511. package/dist/template-whitespace.js.map +0 -1
  512. package/dist/templates.d.ts +0 -5
  513. package/dist/templates.js +0 -15
  514. package/dist/templates.js.map +0 -1
  515. package/dist/textarea.d.ts +0 -26
  516. package/dist/textarea.js +0 -85
  517. package/dist/textarea.js.map +0 -1
package/dist/invokers.js CHANGED
@@ -5,60 +5,20 @@
5
5
  //
6
6
  // Browsers with invoker commands dispatch a `CommandEvent` on the target. Elsewhere (invokers
7
7
  // are Baseline newly available, not widely) Gyral dispatches an equivalent `command` event when
8
- // a custom-command (`--…`) invoker inside a component is clicked, so the same markup works.
9
- // Built-in commands (`show-modal`, `toggle-popover`, …) are left to the browser.
8
+ // a custom-command (`--…`) invoker inside a component is clicked, so the same markup works:
9
+ // invokers-shim.ts, an ADR 0003 tier-3 fallback loaded with import() only there, and only by
10
+ // components listening for `command`. Built-in commands (`show-modal`, …) are left to the
11
+ // browser.
10
12
  /** Native invoker commands available? */
11
13
  export const invokersSupported = () => 'CommandEvent' in globalThis;
12
- /** The command carried by a native `CommandEvent` or by Gyral's fallback event. */
13
- export function commandOf(event) {
14
- if (event.type !== 'command')
15
- return undefined;
16
- if (event instanceof CustomEvent) {
17
- const detail = event.detail;
18
- return typeof detail?.command === 'string'
19
- ? { command: detail.command, source: detail.source }
20
- : undefined;
21
- }
22
- const native = event;
23
- return typeof native.command === 'string'
24
- ? {
25
- command: native.command,
26
- source: native.source instanceof Element ? native.source : undefined,
27
- }
28
- : undefined;
29
- }
30
- /** The custom-command invoker an event passed through, if any. */
31
- function invokerIn(event) {
32
- for (const node of event.composedPath()) {
33
- if (node instanceof Element &&
34
- node.getAttribute('command')?.startsWith('--') === true &&
35
- node.hasAttribute('commandfor')) {
36
- return node;
37
- }
38
- }
39
- return undefined;
40
- }
41
14
  /**
42
- * Fallback for browsers without invoker commands: a click on a `command="--…"` invoker inside
43
- * `root` dispatches a `command` CustomEvent on its `commandfor` target (same tree scope).
15
+ * The command carried by a `CommandEvent`, or by Gyral's fallback event, which has the same
16
+ * `command` and `source` properties.
44
17
  */
45
- export function shimInvokers(root) {
46
- root.addEventListener('click', (event) => {
47
- if (invokersSupported())
48
- return;
49
- const invoker = invokerIn(event);
50
- const id = invoker?.getAttribute('commandfor');
51
- const command = invoker?.getAttribute('command');
52
- if (invoker === undefined || id == null || command == null)
53
- return;
54
- const scope = invoker.getRootNode();
55
- const target = scope.getElementById(id);
56
- if (target === null)
57
- return;
58
- target.dispatchEvent(new CustomEvent('command', {
59
- detail: { command, source: invoker },
60
- cancelable: true,
61
- }));
62
- });
18
+ export function commandOf(event) {
19
+ const { type, command, source } = event;
20
+ return type === 'command' && typeof command === 'string'
21
+ ? { command, source: source instanceof Element ? source : undefined }
22
+ : undefined;
63
23
  }
64
24
  //# sourceMappingURL=invokers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"invokers.js","sourceRoot":"","sources":["../src/invokers.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,EAAE;AACF,6EAA6E;AAC7E,mFAAmF;AACnF,EAAE;AACF,8FAA8F;AAC9F,gGAAgG;AAChG,4FAA4F;AAC5F,iFAAiF;AASjF,yCAAyC;AACzC,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAY,EAAE,CAAC,cAAc,IAAI,UAAU,CAAC;AAE7E,mFAAmF;AACnF,MAAM,UAAU,SAAS,CAAC,KAAY;IACpC,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC/C,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAqC,CAAC;QAC3D,OAAO,OAAO,MAAM,EAAE,OAAO,KAAK,QAAQ;YACxC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;YACpD,CAAC,CAAC,SAAS,CAAC;IAChB,CAAC;IACD,MAAM,MAAM,GAAG,KAAwD,CAAC;IACxE,OAAO,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ;QACvC,CAAC,CAAC;YACE,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,MAAM,EAAE,MAAM,CAAC,MAAM,YAAY,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;SACrE;QACH,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC;AAED,kEAAkE;AAClE,SAAS,SAAS,CAAC,KAAY;IAC7B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,YAAY,EAAE,EAAE,CAAC;QACxC,IACE,IAAI,YAAY,OAAO;YACvB,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,EAAE,UAAU,CAAC,IAAI,CAAC,KAAK,IAAI;YACvD,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,EAC/B,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,IAAU;IACrC,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;QACvC,IAAI,iBAAiB,EAAE;YAAE,OAAO;QAChC,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;QACjC,MAAM,EAAE,GAAG,OAAO,EAAE,YAAY,CAAC,YAAY,CAAC,CAAC;QAC/C,MAAM,OAAO,GAAG,OAAO,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC;QACjD,IAAI,OAAO,KAAK,SAAS,IAAI,EAAE,IAAI,IAAI,IAAI,OAAO,IAAI,IAAI;YAAE,OAAO;QACnE,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,EAA2B,CAAC;QAC7D,MAAM,MAAM,GAAG,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;QACxC,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO;QAC5B,MAAM,CAAC,aAAa,CAClB,IAAI,WAAW,CAAc,SAAS,EAAE;YACtC,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE;YACpC,UAAU,EAAE,IAAI;SACjB,CAAC,CACH,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["// Invoker commands as an intent source (gyral-czi.6, ADR 0001 addendum, ADR 0003).\n//\n// <button type=\"button\" commandfor=\"cart\" command=\"--clear\">Clear</button>\n// <section id=\"cart\" data-intent=${i.Clear} data-intent-on=\"command\">…</section>\n//\n// Browsers with invoker commands dispatch a `CommandEvent` on the target. Elsewhere (invokers\n// are Baseline newly available, not widely) Gyral dispatches an equivalent `command` event when\n// a custom-command (`--…`) invoker inside a component is clicked, so the same markup works.\n// Built-in commands (`show-modal`, `toggle-popover`, …) are left to the browser.\n\nexport interface CommandInfo {\n /** The command, e.g. `--clear`. */\n readonly command: string;\n /** The invoker (the button) that sent it. */\n readonly source: Element | undefined;\n}\n\n/** Native invoker commands available? */\nexport const invokersSupported = (): boolean => 'CommandEvent' in globalThis;\n\n/** The command carried by a native `CommandEvent` or by Gyral's fallback event. */\nexport function commandOf(event: Event): CommandInfo | undefined {\n if (event.type !== 'command') return undefined;\n if (event instanceof CustomEvent) {\n const detail = event.detail as Partial<CommandInfo> | null;\n return typeof detail?.command === 'string'\n ? { command: detail.command, source: detail.source }\n : undefined;\n }\n const native = event as Event & { command?: unknown; source?: unknown };\n return typeof native.command === 'string'\n ? {\n command: native.command,\n source: native.source instanceof Element ? native.source : undefined,\n }\n : undefined;\n}\n\n/** The custom-command invoker an event passed through, if any. */\nfunction invokerIn(event: Event): Element | undefined {\n for (const node of event.composedPath()) {\n if (\n node instanceof Element &&\n node.getAttribute('command')?.startsWith('--') === true &&\n node.hasAttribute('commandfor')\n ) {\n return node;\n }\n }\n return undefined;\n}\n\n/**\n * Fallback for browsers without invoker commands: a click on a `command=\"--…\"` invoker inside\n * `root` dispatches a `command` CustomEvent on its `commandfor` target (same tree scope).\n */\nexport function shimInvokers(root: Node): void {\n root.addEventListener('click', (event) => {\n if (invokersSupported()) return;\n const invoker = invokerIn(event);\n const id = invoker?.getAttribute('commandfor');\n const command = invoker?.getAttribute('command');\n if (invoker === undefined || id == null || command == null) return;\n const scope = invoker.getRootNode() as Document | ShadowRoot;\n const target = scope.getElementById(id);\n if (target === null) return;\n target.dispatchEvent(\n new CustomEvent<CommandInfo>('command', {\n detail: { command, source: invoker },\n cancelable: true,\n }),\n );\n });\n}\n"]}
1
+ {"version":3,"file":"invokers.js","sourceRoot":"","sources":["../src/invokers.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,EAAE;AACF,6EAA6E;AAC7E,mFAAmF;AACnF,EAAE;AACF,8FAA8F;AAC9F,gGAAgG;AAChG,4FAA4F;AAC5F,6FAA6F;AAC7F,0FAA0F;AAC1F,WAAW;AASX,yCAAyC;AACzC,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAY,EAAE,CAAC,cAAc,IAAI,UAAU,CAAC;AAE7E;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,KAAY;IACpC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,KAAwD,CAAC;IAC3F,OAAO,IAAI,KAAK,SAAS,IAAI,OAAO,OAAO,KAAK,QAAQ;QACtD,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EAAE;QACrE,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC","sourcesContent":["// Invoker commands as an intent source (gyral-czi.6, ADR 0001 addendum, ADR 0003).\n//\n// <button type=\"button\" commandfor=\"cart\" command=\"--clear\">Clear</button>\n// <section id=\"cart\" data-intent=${i.Clear} data-intent-on=\"command\">…</section>\n//\n// Browsers with invoker commands dispatch a `CommandEvent` on the target. Elsewhere (invokers\n// are Baseline newly available, not widely) Gyral dispatches an equivalent `command` event when\n// a custom-command (`--…`) invoker inside a component is clicked, so the same markup works:\n// invokers-shim.ts, an ADR 0003 tier-3 fallback loaded with import() only there, and only by\n// components listening for `command`. Built-in commands (`show-modal`, …) are left to the\n// browser.\n\nexport interface CommandInfo {\n /** The command, e.g. `--clear`. */\n readonly command: string;\n /** The invoker (the button) that sent it. */\n readonly source: Element | undefined;\n}\n\n/** Native invoker commands available? */\nexport const invokersSupported = (): boolean => 'CommandEvent' in globalThis;\n\n/**\n * The command carried by a `CommandEvent`, or by Gyral's fallback event, which has the same\n * `command` and `source` properties.\n */\nexport function commandOf(event: Event): CommandInfo | undefined {\n const { type, command, source } = event as Event & { command?: unknown; source?: unknown };\n return type === 'command' && typeof command === 'string'\n ? { command, source: source instanceof Element ? source : undefined }\n : undefined;\n}\n"]}
package/dist/islands.d.ts CHANGED
@@ -2,8 +2,6 @@
2
2
  export type HydrateStrategy = 'load' | 'idle' | 'visible' | 'interaction';
3
3
  /** Server-written strategy for a deferred island; removed when the island is released. */
4
4
  export declare const ISLAND_ATTRIBUTE = "data-gyral-hydrate";
5
- /** Server side: marks the host as an island unless it hydrates on load. */
6
- export declare function markIsland(host: Element, strategy: HydrateStrategy | undefined): void;
7
5
  /**
8
6
  * Client side: if `host` is a deferred island, releases it when its strategy fires. Called on
9
7
  * connect; scheduling happens once per element.
package/dist/islands.js CHANGED
@@ -1,20 +1,13 @@
1
1
  // Lazy hydration islands (gyral-4k7.4, ADR 0012 addendum). A server-rendered component may
2
2
  // hydrate later than page load: when the browser is idle, when it scrolls into view, or when
3
- // the user first reaches for it. The server marks it with Lit's `defer-hydration` plus the
4
- // strategy; the client removes `defer-hydration` when the strategy fires, and Lit's hydrate
5
- // support hydrates it in place (define() finishes connecting from attributeChangedCallback).
3
+ // the user first reaches for it. The server marks it with `defer-hydration` plus the strategy
4
+ // (view/06-server.md); the client removes `defer-hydration` when the strategy fires, and
5
+ // define() finishes connecting from attributeChangedCallback (view/07-hydration.md "Islands").
6
6
  /** Server-written strategy for a deferred island; removed when the island is released. */
7
7
  export const ISLAND_ATTRIBUTE = 'data-gyral-hydrate';
8
8
  const DEFER = 'defer-hydration';
9
9
  /** Events that mean the user is about to interact: they arrive before the click itself. */
10
10
  const INTERACTION_EVENTS = ['pointerover', 'pointerdown', 'focusin', 'touchstart'];
11
- /** Server side: marks the host as an island unless it hydrates on load. */
12
- export function markIsland(host, strategy) {
13
- if (strategy === undefined || strategy === 'load')
14
- return;
15
- host.setAttribute(DEFER, '');
16
- host.setAttribute(ISLAND_ATTRIBUTE, strategy);
17
- }
18
11
  const scheduled = new WeakSet();
19
12
  /** requestIdleCallback is not Baseline widely available; fall back to a short timeout. */
20
13
  function whenIdle(run) {
@@ -35,7 +28,7 @@ export function scheduleIsland(host) {
35
28
  scheduled.add(host);
36
29
  const release = () => {
37
30
  host.removeAttribute(ISLAND_ATTRIBUTE);
38
- host.removeAttribute(DEFER); // Lit's hydrate support hydrates it now
31
+ host.removeAttribute(DEFER); // attributeChangedCallback connects it now
39
32
  };
40
33
  if (strategy === 'idle') {
41
34
  whenIdle(release);
@@ -1 +1 @@
1
- {"version":3,"file":"islands.js","sourceRoot":"","sources":["../src/islands.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,6FAA6F;AAC7F,2FAA2F;AAC3F,4FAA4F;AAC5F,6FAA6F;AAK7F,0FAA0F;AAC1F,MAAM,CAAC,MAAM,gBAAgB,GAAG,oBAAoB,CAAC;AACrD,MAAM,KAAK,GAAG,iBAAiB,CAAC;AAEhC,2FAA2F;AAC3F,MAAM,kBAAkB,GAAG,CAAC,aAAa,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,CAAU,CAAC;AAE5F,2EAA2E;AAC3E,MAAM,UAAU,UAAU,CAAC,IAAa,EAAE,QAAqC;IAC7E,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,MAAM;QAAE,OAAO;IAC1D,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC7B,IAAI,CAAC,YAAY,CAAC,gBAAgB,EAAE,QAAQ,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,SAAS,GAAG,IAAI,OAAO,EAAW,CAAC;AAIzC,0FAA0F;AAC1F,SAAS,QAAQ,CAAC,GAAe;IAC/B,MAAM,IAAI,GAAI,UAAqD,CAAC,mBAAmB,CAAC;IACxF,IAAI,IAAI,KAAK,SAAS;QAAE,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;;QACxC,IAAI,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;AACpC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,IAAiB;IAC9C,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC;IACrD,IAAI,QAAQ,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO;IAClF,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACpB,MAAM,OAAO,GAAG,GAAS,EAAE;QACzB,IAAI,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC;QACvC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,wCAAwC;IACvE,CAAC,CAAC;IACF,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;QACxB,QAAQ,CAAC,OAAO,CAAC,CAAC;IACpB,CAAC;SAAM,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAClC,MAAM,QAAQ,GAAG,IAAI,oBAAoB,CAAC,CAAC,OAAO,EAAE,EAAE;YACpD,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC;gBAClD,QAAQ,CAAC,UAAU,EAAE,CAAC;gBACtB,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC,CAAC,CAAC;QACH,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC;SAAM,CAAC;QACN,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,IAAI,GAAG,GAAS,EAAE;YACtB,UAAU,CAAC,KAAK,EAAE,CAAC;YACnB,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC;QACF,KAAK,MAAM,IAAI,IAAI,kBAAkB,EAAE,CAAC;YACtC,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;QAClF,CAAC;IACH,CAAC;AACH,CAAC","sourcesContent":["// Lazy hydration islands (gyral-4k7.4, ADR 0012 addendum). A server-rendered component may\n// hydrate later than page load: when the browser is idle, when it scrolls into view, or when\n// the user first reaches for it. The server marks it with Lit's `defer-hydration` plus the\n// strategy; the client removes `defer-hydration` when the strategy fires, and Lit's hydrate\n// support hydrates it in place (define() finishes connecting from attributeChangedCallback).\n\n/** When a server-rendered component hydrates. `load` (the default) means right away. */\nexport type HydrateStrategy = 'load' | 'idle' | 'visible' | 'interaction';\n\n/** Server-written strategy for a deferred island; removed when the island is released. */\nexport const ISLAND_ATTRIBUTE = 'data-gyral-hydrate';\nconst DEFER = 'defer-hydration';\n\n/** Events that mean the user is about to interact: they arrive before the click itself. */\nconst INTERACTION_EVENTS = ['pointerover', 'pointerdown', 'focusin', 'touchstart'] as const;\n\n/** Server side: marks the host as an island unless it hydrates on load. */\nexport function markIsland(host: Element, strategy: HydrateStrategy | undefined): void {\n if (strategy === undefined || strategy === 'load') return;\n host.setAttribute(DEFER, '');\n host.setAttribute(ISLAND_ATTRIBUTE, strategy);\n}\n\nconst scheduled = new WeakSet<Element>();\n\ntype IdleCallback = (callback: () => void, options?: { timeout: number }) => number;\n\n/** requestIdleCallback is not Baseline widely available; fall back to a short timeout. */\nfunction whenIdle(run: () => void): void {\n const idle = (globalThis as { requestIdleCallback?: IdleCallback }).requestIdleCallback;\n if (idle === undefined) setTimeout(run, 200);\n else idle(run, { timeout: 2000 });\n}\n\n/**\n * Client side: if `host` is a deferred island, releases it when its strategy fires. Called on\n * connect; scheduling happens once per element.\n */\nexport function scheduleIsland(host: HTMLElement): void {\n const strategy = host.getAttribute(ISLAND_ATTRIBUTE);\n if (strategy === null || !host.hasAttribute(DEFER) || scheduled.has(host)) return;\n scheduled.add(host);\n const release = (): void => {\n host.removeAttribute(ISLAND_ATTRIBUTE);\n host.removeAttribute(DEFER); // Lit's hydrate support hydrates it now\n };\n if (strategy === 'idle') {\n whenIdle(release);\n } else if (strategy === 'visible') {\n const observer = new IntersectionObserver((entries) => {\n if (entries.some((entry) => entry.isIntersecting)) {\n observer.disconnect();\n release();\n }\n });\n observer.observe(host);\n } else {\n const controller = new AbortController();\n const once = (): void => {\n controller.abort();\n release();\n };\n for (const type of INTERACTION_EVENTS) {\n host.addEventListener(type, once, { capture: true, signal: controller.signal });\n }\n }\n}\n"]}
1
+ {"version":3,"file":"islands.js","sourceRoot":"","sources":["../src/islands.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,6FAA6F;AAC7F,8FAA8F;AAC9F,yFAAyF;AACzF,+FAA+F;AAK/F,0FAA0F;AAC1F,MAAM,CAAC,MAAM,gBAAgB,GAAG,oBAAoB,CAAC;AACrD,MAAM,KAAK,GAAG,iBAAiB,CAAC;AAEhC,2FAA2F;AAC3F,MAAM,kBAAkB,GAAG,CAAC,aAAa,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,CAAU,CAAC;AAE5F,MAAM,SAAS,GAAG,IAAI,OAAO,EAAW,CAAC;AAIzC,0FAA0F;AAC1F,SAAS,QAAQ,CAAC,GAAe;IAC/B,MAAM,IAAI,GAAI,UAAqD,CAAC,mBAAmB,CAAC;IACxF,IAAI,IAAI,KAAK,SAAS;QAAE,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;;QACxC,IAAI,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;AACpC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,IAAiB;IAC9C,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC;IACrD,IAAI,QAAQ,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO;IAClF,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACpB,MAAM,OAAO,GAAG,GAAS,EAAE;QACzB,IAAI,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC;QACvC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,2CAA2C;IAC1E,CAAC,CAAC;IACF,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;QACxB,QAAQ,CAAC,OAAO,CAAC,CAAC;IACpB,CAAC;SAAM,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAClC,MAAM,QAAQ,GAAG,IAAI,oBAAoB,CAAC,CAAC,OAAO,EAAE,EAAE;YACpD,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC;gBAClD,QAAQ,CAAC,UAAU,EAAE,CAAC;gBACtB,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC,CAAC,CAAC;QACH,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC;SAAM,CAAC;QACN,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,IAAI,GAAG,GAAS,EAAE;YACtB,UAAU,CAAC,KAAK,EAAE,CAAC;YACnB,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC;QACF,KAAK,MAAM,IAAI,IAAI,kBAAkB,EAAE,CAAC;YACtC,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;QAClF,CAAC;IACH,CAAC;AACH,CAAC","sourcesContent":["// Lazy hydration islands (gyral-4k7.4, ADR 0012 addendum). A server-rendered component may\n// hydrate later than page load: when the browser is idle, when it scrolls into view, or when\n// the user first reaches for it. The server marks it with `defer-hydration` plus the strategy\n// (view/06-server.md); the client removes `defer-hydration` when the strategy fires, and\n// define() finishes connecting from attributeChangedCallback (view/07-hydration.md \"Islands\").\n\n/** When a server-rendered component hydrates. `load` (the default) means right away. */\nexport type HydrateStrategy = 'load' | 'idle' | 'visible' | 'interaction';\n\n/** Server-written strategy for a deferred island; removed when the island is released. */\nexport const ISLAND_ATTRIBUTE = 'data-gyral-hydrate';\nconst DEFER = 'defer-hydration';\n\n/** Events that mean the user is about to interact: they arrive before the click itself. */\nconst INTERACTION_EVENTS = ['pointerover', 'pointerdown', 'focusin', 'touchstart'] as const;\n\nconst scheduled = new WeakSet<Element>();\n\ntype IdleCallback = (callback: () => void, options?: { timeout: number }) => number;\n\n/** requestIdleCallback is not Baseline widely available; fall back to a short timeout. */\nfunction whenIdle(run: () => void): void {\n const idle = (globalThis as { requestIdleCallback?: IdleCallback }).requestIdleCallback;\n if (idle === undefined) setTimeout(run, 200);\n else idle(run, { timeout: 2000 });\n}\n\n/**\n * Client side: if `host` is a deferred island, releases it when its strategy fires. Called on\n * connect; scheduling happens once per element.\n */\nexport function scheduleIsland(host: HTMLElement): void {\n const strategy = host.getAttribute(ISLAND_ATTRIBUTE);\n if (strategy === null || !host.hasAttribute(DEFER) || scheduled.has(host)) return;\n scheduled.add(host);\n const release = (): void => {\n host.removeAttribute(ISLAND_ATTRIBUTE);\n host.removeAttribute(DEFER); // attributeChangedCallback connects it now\n };\n if (strategy === 'idle') {\n whenIdle(release);\n } else if (strategy === 'visible') {\n const observer = new IntersectionObserver((entries) => {\n if (entries.some((entry) => entry.isIntersecting)) {\n observer.disconnect();\n release();\n }\n });\n observer.observe(host);\n } else {\n const controller = new AbortController();\n const once = (): void => {\n controller.abort();\n release();\n };\n for (const type of INTERACTION_EVENTS) {\n host.addEventListener(type, once, { capture: true, signal: controller.signal });\n }\n }\n}\n"]}
@@ -1,61 +1,12 @@
1
- import { type CSSResultGroup, type CSSResultOrNative } from 'lit';
2
- import { type Styles } from './styles.js';
3
1
  interface SpecLike {
4
- readonly shadow?: boolean;
5
- readonly styles?: Styles;
2
+ readonly shadow?: unknown;
6
3
  }
7
4
  export declare const isLight: (spec: SpecLike) => boolean;
8
- /** Shadow components keep their styles; light ones use the document's (and warn if given). */
9
- export declare function componentStyles(spec: SpecLike, tag: string): CSSResultGroup;
10
- /**
11
- * Is this class a light-DOM Gyral component? Used by @gyral/ssr to render its view as plain
12
- * children instead of Declarative Shadow DOM.
13
- */
5
+ /** Is this class a light-DOM Gyral component (`shadow: false`)? */
14
6
  export declare function isLightComponent(ctor: unknown): boolean;
15
7
  /**
16
- * Server-rendered light hosts carry this attribute (ADR 0014 addendum). Hydration uses it to
17
- * tell a host's own markers from those of light hosts nested inside it.
8
+ * Server-rendered light hosts carry this attribute (ADR 0014 addendum, view/06-server.md
9
+ * "Components"), so a parent's hydration walk leaves a light child's content alone (view/07).
18
10
  */
19
11
  export declare const LIGHT_ATTRIBUTE = "data-gyral-light";
20
- /** Prefix @gyral/ssr puts on Lit's markers inside light views so no hydrate() walk sees them. */
21
- export declare const HIDDEN_MARKER = "gyral:";
22
- /** Server side: marks a light host so the client can scope its markers. */
23
- export declare function markLightHost(host: Element): void;
24
- /**
25
- * Client side, on a server-rendered light host's first update: turns the host's own hidden
26
- * markers back into Lit's, leaving nested light hosts' markers hidden until they hydrate.
27
- * Returns whether the host's root part marker was found (so Lit can hydrate in place).
28
- */
29
- export declare function revealLightMarkers(host: Element): boolean;
30
- /** Lit's public `hydrate()` from `@lit-labs/ssr-client`. */
31
- export type Hydrate = (value: unknown, container: HTMLElement | DocumentFragment, options?: object) => void;
32
- /**
33
- * Where `@gyral/ssr/hydrate` registers Lit's public `hydrate()` (gyral-czi.38). A global
34
- * symbol, not an import, so core doesn't depend on `@lit-labs/ssr-client` and apps without
35
- * SSR don't ship it.
36
- */
37
- export declare const HYDRATE_KEY: unique symbol;
38
- /**
39
- * Lit's `hydrate()`, if a server-rendered app loaded `@gyral/ssr/hydrate`. Used for light hosts
40
- * and, since gyral-czi.41, for server-rendered shadow roots too: Gyral hydrates both itself, so
41
- * it never depends on Lit's hydrate support having patched LitElement before Lit evaluated.
42
- */
43
- export declare const hydrator: () => Hydrate | undefined;
44
- /**
45
- * First update of a server-rendered (declarative) shadow root: hydrate the server's view in
46
- * place with Lit's public hydrate(), which leaves the root part on the shadow root so the
47
- * render() inside LitElement's update() updates it instead of appending a second copy
48
- * (gyral-czi.41). Without `@gyral/ssr/hydrate` loaded, clear the server's view and let Lit
49
- * render fresh, adopting the styles Lit's own createRenderRoot would have.
50
- */
51
- export declare function hydrateShadow(root: ShadowRoot, view: unknown, options: object, styles: CSSResultOrNative[]): void;
52
- /**
53
- * First update of a server-rendered light host: reveal this host's own hidden markers now (not
54
- * on connect: a deferred child connects mid-way through its parent's hydrate walk), then call
55
- * Lit's public hydrate(). It leaves the root part on the host, so the render() inside
56
- * LitElement's update() updates it in place instead of appending a second copy. No Lit private
57
- * fields: their names are mangled in Lit's production build (ADR 0014, gyral-czi.38). Without
58
- * `@gyral/ssr/hydrate` loaded, clear the server's view and let Lit render fresh.
59
- */
60
- export declare function hydrateLight(host: HTMLElement, view: unknown, options: object): void;
61
12
  export {};
package/dist/light-dom.js CHANGED
@@ -1,109 +1,14 @@
1
- // Light-DOM render mode (docs/design-docs/0014-light-dom.md).
2
- import { adoptStyles } from 'lit';
3
- import { toCssResultGroup } from './styles.js';
1
+ // Light-DOM render mode (docs/design-docs/0014-light-dom.md): `shadow: false` renders the view
2
+ // as the host's own children, styled by document CSS.
4
3
  export const isLight = (spec) => spec.shadow === false;
5
- /** Shadow components keep their styles; light ones use the document's (and warn if given). */
6
- export function componentStyles(spec, tag) {
7
- if (!isLight(spec))
8
- return spec.styles === undefined ? [] : toCssResultGroup(spec.styles);
9
- if (spec.styles !== undefined) {
10
- console.warn(`<${tag}> has shadow: false, so its styles are ignored; use document CSS.`);
11
- }
12
- return [];
13
- }
14
- /**
15
- * Is this class a light-DOM Gyral component? Used by @gyral/ssr to render its view as plain
16
- * children instead of Declarative Shadow DOM.
17
- */
4
+ /** Is this class a light-DOM Gyral component (`shadow: false`)? */
18
5
  export function isLightComponent(ctor) {
19
6
  const spec = ctor?.spec;
20
7
  return spec !== undefined && isLight(spec);
21
8
  }
22
9
  /**
23
- * Server-rendered light hosts carry this attribute (ADR 0014 addendum). Hydration uses it to
24
- * tell a host's own markers from those of light hosts nested inside it.
10
+ * Server-rendered light hosts carry this attribute (ADR 0014 addendum, view/06-server.md
11
+ * "Components"), so a parent's hydration walk leaves a light child's content alone (view/07).
25
12
  */
26
13
  export const LIGHT_ATTRIBUTE = 'data-gyral-light';
27
- /** Prefix @gyral/ssr puts on Lit's markers inside light views so no hydrate() walk sees them. */
28
- export const HIDDEN_MARKER = 'gyral:';
29
- const LIT_MARKER = /^(?:lit-part|\/lit-part|lit-node)\b/;
30
- /** Server side: marks a light host so the client can scope its markers. */
31
- export function markLightHost(host) {
32
- host.setAttribute(LIGHT_ATTRIBUTE, '');
33
- }
34
- /** Is the comment inside `host`'s own light view, not a nested light host's? */
35
- function ownedBy(comment, host) {
36
- for (let el = comment.parentElement; el !== null; el = el.parentElement) {
37
- if (el === host)
38
- return true;
39
- if (el.hasAttribute(LIGHT_ATTRIBUTE))
40
- return false;
41
- }
42
- return false;
43
- }
44
- /**
45
- * Client side, on a server-rendered light host's first update: turns the host's own hidden
46
- * markers back into Lit's, leaving nested light hosts' markers hidden until they hydrate.
47
- * Returns whether the host's root part marker was found (so Lit can hydrate in place).
48
- */
49
- export function revealLightMarkers(host) {
50
- const walker = document.createTreeWalker(host, NodeFilter.SHOW_COMMENT);
51
- const own = [];
52
- for (let node = walker.nextNode(); node !== null; node = walker.nextNode()) {
53
- const comment = node;
54
- const data = comment.data.slice(HIDDEN_MARKER.length);
55
- if (comment.data.startsWith(HIDDEN_MARKER) && LIT_MARKER.test(data) && ownedBy(comment, host)) {
56
- own.push(comment);
57
- }
58
- }
59
- for (const comment of own)
60
- comment.data = comment.data.slice(HIDDEN_MARKER.length);
61
- return own[0]?.data.startsWith('lit-part') === true;
62
- }
63
- /**
64
- * Where `@gyral/ssr/hydrate` registers Lit's public `hydrate()` (gyral-czi.38). A global
65
- * symbol, not an import, so core doesn't depend on `@lit-labs/ssr-client` and apps without
66
- * SSR don't ship it.
67
- */
68
- export const HYDRATE_KEY = Symbol.for('gyral.hydrate');
69
- /**
70
- * Lit's `hydrate()`, if a server-rendered app loaded `@gyral/ssr/hydrate`. Used for light hosts
71
- * and, since gyral-czi.41, for server-rendered shadow roots too: Gyral hydrates both itself, so
72
- * it never depends on Lit's hydrate support having patched LitElement before Lit evaluated.
73
- */
74
- export const hydrator = () => {
75
- const fn = globalThis[HYDRATE_KEY];
76
- return typeof fn === 'function' ? fn : undefined;
77
- };
78
- /**
79
- * First update of a server-rendered (declarative) shadow root: hydrate the server's view in
80
- * place with Lit's public hydrate(), which leaves the root part on the shadow root so the
81
- * render() inside LitElement's update() updates it instead of appending a second copy
82
- * (gyral-czi.41). Without `@gyral/ssr/hydrate` loaded, clear the server's view and let Lit
83
- * render fresh, adopting the styles Lit's own createRenderRoot would have.
84
- */
85
- export function hydrateShadow(root, view, options, styles) {
86
- const hydrate = hydrator();
87
- if (hydrate !== undefined) {
88
- hydrate(view, root, options);
89
- return;
90
- }
91
- root.replaceChildren();
92
- adoptStyles(root, styles);
93
- }
94
- /**
95
- * First update of a server-rendered light host: reveal this host's own hidden markers now (not
96
- * on connect: a deferred child connects mid-way through its parent's hydrate walk), then call
97
- * Lit's public hydrate(). It leaves the root part on the host, so the render() inside
98
- * LitElement's update() updates it in place instead of appending a second copy. No Lit private
99
- * fields: their names are mangled in Lit's production build (ADR 0014, gyral-czi.38). Without
100
- * `@gyral/ssr/hydrate` loaded, clear the server's view and let Lit render fresh.
101
- */
102
- export function hydrateLight(host, view, options) {
103
- const hydrate = hydrator();
104
- if (hydrate !== undefined && revealLightMarkers(host))
105
- hydrate(view, host, options);
106
- else
107
- host.replaceChildren();
108
- }
109
14
  //# sourceMappingURL=light-dom.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"light-dom.js","sourceRoot":"","sources":["../src/light-dom.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,OAAO,EAAE,WAAW,EAA+C,MAAM,KAAK,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAe,MAAM,aAAa,CAAC;AAO5D,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,IAAc,EAAW,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC;AAE1E,8FAA8F;AAC9F,MAAM,UAAU,eAAe,CAAC,IAAc,EAAE,GAAW;IACzD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1F,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,CAAC,IAAI,CAAC,IAAI,GAAG,mEAAmE,CAAC,CAAC;IAC3F,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAa;IAC5C,MAAM,IAAI,GAAI,IAA4C,EAAE,IAAI,CAAC;IACjE,OAAO,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;AAC7C,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,kBAAkB,CAAC;AAElD,iGAAiG;AACjG,MAAM,CAAC,MAAM,aAAa,GAAG,QAAQ,CAAC;AAEtC,MAAM,UAAU,GAAG,qCAAqC,CAAC;AAEzD,2EAA2E;AAC3E,MAAM,UAAU,aAAa,CAAC,IAAa;IACzC,IAAI,CAAC,YAAY,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;AACzC,CAAC;AAED,gFAAgF;AAChF,SAAS,OAAO,CAAC,OAAgB,EAAE,IAAa;IAC9C,KAAK,IAAI,EAAE,GAAG,OAAO,CAAC,aAAa,EAAE,EAAE,KAAK,IAAI,EAAE,EAAE,GAAG,EAAE,CAAC,aAAa,EAAE,CAAC;QACxE,IAAI,EAAE,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QAC7B,IAAI,EAAE,CAAC,YAAY,CAAC,eAAe,CAAC;YAAE,OAAO,KAAK,CAAC;IACrD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAa;IAC9C,MAAM,MAAM,GAAG,QAAQ,CAAC,gBAAgB,CAAC,IAAI,EAAE,UAAU,CAAC,YAAY,CAAC,CAAC;IACxE,MAAM,GAAG,GAAc,EAAE,CAAC;IAC1B,KAAK,IAAI,IAAI,GAAG,MAAM,CAAC,QAAQ,EAAE,EAAE,IAAI,KAAK,IAAI,EAAE,IAAI,GAAG,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;QAC3E,MAAM,OAAO,GAAG,IAAe,CAAC;QAChC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QACtD,IAAI,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;YAC9F,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpB,CAAC;IACH,CAAC;IACD,KAAK,MAAM,OAAO,IAAI,GAAG;QAAE,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IACnF,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;AACtD,CAAC;AASD;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAkB,MAAM,CAAC,GAAG,CAAC,eAAe,CAAU,CAAC;AAE/E;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAwB,EAAE;IAChD,MAAM,EAAE,GAAI,UAA0C,CAAC,WAAW,CAAC,CAAC;IACpE,OAAO,OAAO,EAAE,KAAK,UAAU,CAAC,CAAC,CAAE,EAAc,CAAC,CAAC,CAAC,SAAS,CAAC;AAChE,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAC3B,IAAgB,EAChB,IAAa,EACb,OAAe,EACf,MAA2B;IAE3B,MAAM,OAAO,GAAG,QAAQ,EAAE,CAAC;IAC3B,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QAC7B,OAAO;IACT,CAAC;IACD,IAAI,CAAC,eAAe,EAAE,CAAC;IACvB,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC5B,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,IAAiB,EAAE,IAAa,EAAE,OAAe;IAC5E,MAAM,OAAO,GAAG,QAAQ,EAAE,CAAC;IAC3B,IAAI,OAAO,KAAK,SAAS,IAAI,kBAAkB,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;;QAC/E,IAAI,CAAC,eAAe,EAAE,CAAC;AAC9B,CAAC","sourcesContent":["// Light-DOM render mode (docs/design-docs/0014-light-dom.md).\nimport { adoptStyles, type CSSResultGroup, type CSSResultOrNative } from 'lit';\nimport { toCssResultGroup, type Styles } from './styles.js';\n\ninterface SpecLike {\n readonly shadow?: boolean;\n readonly styles?: Styles;\n}\n\nexport const isLight = (spec: SpecLike): boolean => spec.shadow === false;\n\n/** Shadow components keep their styles; light ones use the document's (and warn if given). */\nexport function componentStyles(spec: SpecLike, tag: string): CSSResultGroup {\n if (!isLight(spec)) return spec.styles === undefined ? [] : toCssResultGroup(spec.styles);\n if (spec.styles !== undefined) {\n console.warn(`<${tag}> has shadow: false, so its styles are ignored; use document CSS.`);\n }\n return [];\n}\n\n/**\n * Is this class a light-DOM Gyral component? Used by @gyral/ssr to render its view as plain\n * children instead of Declarative Shadow DOM.\n */\nexport function isLightComponent(ctor: unknown): boolean {\n const spec = (ctor as { readonly spec?: SpecLike } | null)?.spec;\n return spec !== undefined && isLight(spec);\n}\n\n/**\n * Server-rendered light hosts carry this attribute (ADR 0014 addendum). Hydration uses it to\n * tell a host's own markers from those of light hosts nested inside it.\n */\nexport const LIGHT_ATTRIBUTE = 'data-gyral-light';\n\n/** Prefix @gyral/ssr puts on Lit's markers inside light views so no hydrate() walk sees them. */\nexport const HIDDEN_MARKER = 'gyral:';\n\nconst LIT_MARKER = /^(?:lit-part|\\/lit-part|lit-node)\\b/;\n\n/** Server side: marks a light host so the client can scope its markers. */\nexport function markLightHost(host: Element): void {\n host.setAttribute(LIGHT_ATTRIBUTE, '');\n}\n\n/** Is the comment inside `host`'s own light view, not a nested light host's? */\nfunction ownedBy(comment: Comment, host: Element): boolean {\n for (let el = comment.parentElement; el !== null; el = el.parentElement) {\n if (el === host) return true;\n if (el.hasAttribute(LIGHT_ATTRIBUTE)) return false;\n }\n return false;\n}\n\n/**\n * Client side, on a server-rendered light host's first update: turns the host's own hidden\n * markers back into Lit's, leaving nested light hosts' markers hidden until they hydrate.\n * Returns whether the host's root part marker was found (so Lit can hydrate in place).\n */\nexport function revealLightMarkers(host: Element): boolean {\n const walker = document.createTreeWalker(host, NodeFilter.SHOW_COMMENT);\n const own: Comment[] = [];\n for (let node = walker.nextNode(); node !== null; node = walker.nextNode()) {\n const comment = node as Comment;\n const data = comment.data.slice(HIDDEN_MARKER.length);\n if (comment.data.startsWith(HIDDEN_MARKER) && LIT_MARKER.test(data) && ownedBy(comment, host)) {\n own.push(comment);\n }\n }\n for (const comment of own) comment.data = comment.data.slice(HIDDEN_MARKER.length);\n return own[0]?.data.startsWith('lit-part') === true;\n}\n\n/** Lit's public `hydrate()` from `@lit-labs/ssr-client`. */\nexport type Hydrate = (\n value: unknown,\n container: HTMLElement | DocumentFragment,\n options?: object,\n) => void;\n\n/**\n * Where `@gyral/ssr/hydrate` registers Lit's public `hydrate()` (gyral-czi.38). A global\n * symbol, not an import, so core doesn't depend on `@lit-labs/ssr-client` and apps without\n * SSR don't ship it.\n */\nexport const HYDRATE_KEY: unique symbol = Symbol.for('gyral.hydrate') as never;\n\n/**\n * Lit's `hydrate()`, if a server-rendered app loaded `@gyral/ssr/hydrate`. Used for light hosts\n * and, since gyral-czi.41, for server-rendered shadow roots too: Gyral hydrates both itself, so\n * it never depends on Lit's hydrate support having patched LitElement before Lit evaluated.\n */\nexport const hydrator = (): Hydrate | undefined => {\n const fn = (globalThis as { [HYDRATE_KEY]?: unknown })[HYDRATE_KEY];\n return typeof fn === 'function' ? (fn as Hydrate) : undefined;\n};\n\n/**\n * First update of a server-rendered (declarative) shadow root: hydrate the server's view in\n * place with Lit's public hydrate(), which leaves the root part on the shadow root so the\n * render() inside LitElement's update() updates it instead of appending a second copy\n * (gyral-czi.41). Without `@gyral/ssr/hydrate` loaded, clear the server's view and let Lit\n * render fresh, adopting the styles Lit's own createRenderRoot would have.\n */\nexport function hydrateShadow(\n root: ShadowRoot,\n view: unknown,\n options: object,\n styles: CSSResultOrNative[],\n): void {\n const hydrate = hydrator();\n if (hydrate !== undefined) {\n hydrate(view, root, options);\n return;\n }\n root.replaceChildren();\n adoptStyles(root, styles);\n}\n\n/**\n * First update of a server-rendered light host: reveal this host's own hidden markers now (not\n * on connect: a deferred child connects mid-way through its parent's hydrate walk), then call\n * Lit's public hydrate(). It leaves the root part on the host, so the render() inside\n * LitElement's update() updates it in place instead of appending a second copy. No Lit private\n * fields: their names are mangled in Lit's production build (ADR 0014, gyral-czi.38). Without\n * `@gyral/ssr/hydrate` loaded, clear the server's view and let Lit render fresh.\n */\nexport function hydrateLight(host: HTMLElement, view: unknown, options: object): void {\n const hydrate = hydrator();\n if (hydrate !== undefined && revealLightMarkers(host)) hydrate(view, host, options);\n else host.replaceChildren();\n}\n"]}
1
+ {"version":3,"file":"light-dom.js","sourceRoot":"","sources":["../src/light-dom.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,sDAAsD;AAMtD,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,IAAc,EAAW,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC;AAE1E,mEAAmE;AACnE,MAAM,UAAU,gBAAgB,CAAC,IAAa;IAC5C,MAAM,IAAI,GAAI,IAA4C,EAAE,IAAI,CAAC;IACjE,OAAO,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;AAC7C,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,kBAAkB,CAAC","sourcesContent":["// Light-DOM render mode (docs/design-docs/0014-light-dom.md): `shadow: false` renders the view\n// as the host's own children, styled by document CSS.\n\ninterface SpecLike {\n readonly shadow?: unknown;\n}\n\nexport const isLight = (spec: SpecLike): boolean => spec.shadow === false;\n\n/** Is this class a light-DOM Gyral component (`shadow: false`)? */\nexport function isLightComponent(ctor: unknown): boolean {\n const spec = (ctor as { readonly spec?: SpecLike } | null)?.spec;\n return spec !== undefined && isLight(spec);\n}\n\n/**\n * Server-rendered light hosts carry this attribute (ADR 0014 addendum, view/06-server.md\n * \"Components\"), so a parent's hydration walk leaves a light child's content alone (view/07).\n */\nexport const LIGHT_ATTRIBUTE = 'data-gyral-light';\n"]}
package/dist/prop.d.ts ADDED
@@ -0,0 +1,89 @@
1
+ import type { StandardSchemaV1 } from '@standard-schema/spec';
2
+ declare const OUTPUT: unique symbol;
3
+ export type PropKind = 'string' | 'number' | 'boolean' | 'json' | 'value';
4
+ /** One declared prop: what a builder returns. */
5
+ export interface Prop<T> {
6
+ readonly kind: PropKind;
7
+ /** The attribute name, `false` for property only, `undefined` for the kebab-case default. */
8
+ readonly attribute: string | false | undefined;
9
+ /**
10
+ * Refines (string/number/boolean) or defines (json/value) the accepted values: a Standard
11
+ * Schema, or for json/value a type guard (props.ts `checkValue` tells them apart).
12
+ */
13
+ readonly schema: StandardSchemaV1 | PropGuard<unknown> | undefined;
14
+ /** A missing value is a bug: warned once per instance at first render. */
15
+ readonly required: boolean;
16
+ /** Used whenever the element's value is missing (`boolean` props default to `false`). */
17
+ readonly default?: unknown;
18
+ /**
19
+ * When a new value counts as unchanged (no re-render, no `PropsChanged`): `Object.is`, the
20
+ * same JSON for `prop.json`, or the `equals` option of `prop.json`/`prop.value`.
21
+ */
22
+ readonly equals: (a: unknown, b: unknown) => boolean;
23
+ /** Type-only: the value components see. Never set. */
24
+ readonly [OUTPUT]?: () => T;
25
+ }
26
+ /** The props type of a table of builders: `PropsOf<typeof props>`. */
27
+ export type PropsOf<T extends Readonly<Record<string, Prop<unknown>>>> = {
28
+ readonly [K in keyof T]: T[K] extends Prop<infer V> ? V : never;
29
+ };
30
+ interface Common {
31
+ /** Attribute name, or `false` for property only. Default: kebab-case of the prop name. */
32
+ readonly attribute?: string | false;
33
+ }
34
+ type Schema<O> = StandardSchemaV1<unknown, O>;
35
+ /** A plain type guard, accepted by `prop.value` and `prop.json` in place of a schema. */
36
+ export type PropGuard<T> = (value: unknown) => value is T;
37
+ /** What `prop.value` and `prop.json` accept: a Standard Schema or a type guard. */
38
+ type Check = StandardSchemaV1 | PropGuard<unknown>;
39
+ type Out<S extends Check> = S extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<S> : S extends (value: unknown) => value is infer T ? T : never;
40
+ interface Required {
41
+ readonly required: true;
42
+ readonly default?: undefined;
43
+ }
44
+ interface Defaulted<T> {
45
+ readonly required?: false;
46
+ readonly default: T;
47
+ }
48
+ interface Optional {
49
+ readonly required?: false;
50
+ readonly default?: undefined;
51
+ }
52
+ type Refined<O> = Common & {
53
+ readonly schema?: Schema<O>;
54
+ };
55
+ interface Scalar<B> {
56
+ <O extends B = B>(opts: Refined<O> & (Required | Defaulted<NoInfer<O>>)): Prop<O>;
57
+ <O extends B = B>(opts?: Refined<O> & Optional): Prop<O | undefined>;
58
+ }
59
+ /** `equals` for `prop.json`/`prop.value`: the old and new value (`undefined` when unset). */
60
+ interface Equals<T> {
61
+ readonly equals?: (a: T | undefined, b: T | undefined) => boolean;
62
+ }
63
+ interface WithSchema {
64
+ <S extends Check>(schema: S, opts: Common & Equals<NoInfer<Out<S>>> & (Required | Defaulted<NoInfer<Out<S>>>)): Prop<Out<S>>;
65
+ <S extends Check>(schema: S, opts?: Common & Equals<NoInfer<Out<S>>> & Optional): Prop<Out<S> | undefined>;
66
+ }
67
+ /** The prop builders. */
68
+ export declare const prop: {
69
+ /** Attribute parsed as is. */
70
+ readonly string: Scalar<string>;
71
+ /** Attribute parsed with `Number(v)`; empty or `NaN` is invalid. */
72
+ readonly number: Scalar<number>;
73
+ /** Attribute present → `true`, absent → `false` (the default). */
74
+ readonly boolean: <O extends boolean = boolean>(opts?: Refined<O> & {
75
+ readonly default?: NoInfer<O>;
76
+ }) => Prop<O>;
77
+ /**
78
+ * Attribute parsed with `JSON.parse`, then the schema (or type guard). Compared by value: a
79
+ * new but equal object (a fresh `.prop=${{…}}` each render) changes nothing.
80
+ */
81
+ readonly json: WithSchema;
82
+ /**
83
+ * Property only: no attribute. Validated in development by the schema (or type guard), and
84
+ * the object set is kept as is (production skips the check). Compared with `Object.is`
85
+ * unless `equals` is given.
86
+ */
87
+ readonly value: WithSchema;
88
+ };
89
+ export {};
package/dist/prop.js ADDED
@@ -0,0 +1,41 @@
1
+ import { features } from './features.js';
2
+ import { propFeature } from './props.js';
3
+ import { DEV } from '#view-dev';
4
+ /** `prop.json` values are JSON: the same JSON text is the same value. */
5
+ // `prop.json`'s default `equals`: the same JSON text. A value JSON can't encode (a cycle, a
6
+ // BigInt) is never equal, so the write always lands instead of throwing from the setter.
7
+ let warned = false;
8
+ function sameJson(a, b) {
9
+ try {
10
+ return JSON.stringify(a) === JSON.stringify(b);
11
+ }
12
+ catch (error) {
13
+ if (DEV && !warned) {
14
+ warned = true;
15
+ console.warn(`prop.json got a value JSON can't encode (${String(error)}); every write of it counts ` +
16
+ 'as a change. Use prop.value for non-JSON values, or pass equals.');
17
+ }
18
+ return false;
19
+ }
20
+ }
21
+ function make(kind, opts = {}, schema) {
22
+ features.props = propFeature; // components can declare props now (features.ts)
23
+ const value = opts.default !== undefined ? opts.default : kind === 'boolean' ? false : undefined;
24
+ const base = {
25
+ kind,
26
+ attribute: kind === 'value' ? false : opts.attribute,
27
+ schema: schema ?? opts.schema,
28
+ required: opts.required === true,
29
+ equals: opts.equals ?? (kind === 'json' ? sameJson : Object.is),
30
+ };
31
+ return value === undefined ? base : { ...base, default: value };
32
+ }
33
+ /** The prop builders. */
34
+ export const prop = {
35
+ string: (opts) => make('string', opts),
36
+ number: (opts) => make('number', opts),
37
+ boolean: ((opts) => make('boolean', opts)),
38
+ json: (schema, opts) => make('json', opts, schema),
39
+ value: (schema, opts) => make('value', opts, schema),
40
+ };
41
+ //# sourceMappingURL=prop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prop.js","sourceRoot":"","sources":["../src/prop.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAgGhC,yEAAyE;AACzE,4FAA4F;AAC5F,yFAAyF;AACzF,IAAI,MAAM,GAAG,KAAK,CAAC;AACnB,SAAS,QAAQ,CAAC,CAAU,EAAE,CAAU;IACtC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;YACnB,MAAM,GAAG,IAAI,CAAC;YACd,OAAO,CAAC,IAAI,CACV,4CAA4C,MAAM,CAAC,KAAK,CAAC,8BAA8B;gBACrF,kEAAkE,CACrE,CAAC;QACJ,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,IAAI,CAAC,IAAc,EAAE,OAAgB,EAAE,EAAE,MAAc;IAC9D,QAAQ,CAAC,KAAK,GAAG,WAAW,CAAC,CAAC,iDAAiD;IAC/E,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IACjG,MAAM,IAAI,GAAG;QACX,IAAI;QACJ,SAAS,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS;QACpD,MAAM,EAAE,MAAM,IAAI,IAAI,CAAC,MAAM;QAC7B,QAAQ,EAAE,IAAI,CAAC,QAAQ,KAAK,IAAI;QAChC,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;KAChE,CAAC;IACF,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAClE,CAAC;AAED,yBAAyB;AACzB,MAAM,CAAC,MAAM,IAAI,GAoBb;IACF,MAAM,EAAE,CAAC,IAAc,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC;IAChD,MAAM,EAAE,CAAC,IAAc,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC;IAChD,OAAO,EAAE,CAAC,CAAC,IAAc,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAqC;IACxF,IAAI,EAAE,CAAC,MAAa,EAAE,IAAc,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC;IACnE,KAAK,EAAE,CAAC,MAAa,EAAE,IAAc,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC;CACtE,CAAC","sourcesContent":["// Prop builders (docs/design-docs/view/05-element.md \"Props\"): every component input is\n// declared with a builder over Standard Schema, so \"parse at boundaries\" covers attributes.\n//\n// props: {\n// label: prop.string({ required: true }), // attribute \"label\"\n// minPrice: prop.number({ default: 0 }), // attribute \"min-price\"\n// items: prop.value(v.array(Item), { default: [] }), // property only\n// }\n//\n// A prop's type is inferred from its schema's output. The honesty rule (ADR 0007) holds by\n// construction: a prop without `required` or `default` includes `undefined`. `prop.value` and\n// `prop.json` also take a plain type guard (`(u: unknown) => u is T`) instead of a schema.\n// Schemas and guards check; they don't decode: a property set keeps the object it was given.\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport { features } from './features.js';\nimport { propFeature } from './props.js';\nimport { DEV } from '#view-dev';\n\ndeclare const OUTPUT: unique symbol;\n\nexport type PropKind = 'string' | 'number' | 'boolean' | 'json' | 'value';\n\n/** One declared prop: what a builder returns. */\nexport interface Prop<T> {\n readonly kind: PropKind;\n /** The attribute name, `false` for property only, `undefined` for the kebab-case default. */\n readonly attribute: string | false | undefined;\n /**\n * Refines (string/number/boolean) or defines (json/value) the accepted values: a Standard\n * Schema, or for json/value a type guard (props.ts `checkValue` tells them apart).\n */\n readonly schema: StandardSchemaV1 | PropGuard<unknown> | undefined;\n /** A missing value is a bug: warned once per instance at first render. */\n readonly required: boolean;\n /** Used whenever the element's value is missing (`boolean` props default to `false`). */\n readonly default?: unknown;\n /**\n * When a new value counts as unchanged (no re-render, no `PropsChanged`): `Object.is`, the\n * same JSON for `prop.json`, or the `equals` option of `prop.json`/`prop.value`.\n */\n readonly equals: (a: unknown, b: unknown) => boolean;\n /** Type-only: the value components see. Never set. */\n readonly [OUTPUT]?: () => T;\n}\n\n/** The props type of a table of builders: `PropsOf<typeof props>`. */\nexport type PropsOf<T extends Readonly<Record<string, Prop<unknown>>>> = {\n readonly [K in keyof T]: T[K] extends Prop<infer V> ? V : never;\n};\n\ninterface Common {\n /** Attribute name, or `false` for property only. Default: kebab-case of the prop name. */\n readonly attribute?: string | false;\n}\n\ntype Schema<O> = StandardSchemaV1<unknown, O>;\n\n/** A plain type guard, accepted by `prop.value` and `prop.json` in place of a schema. */\nexport type PropGuard<T> = (value: unknown) => value is T;\n\n/** What `prop.value` and `prop.json` accept: a Standard Schema or a type guard. */\ntype Check = StandardSchemaV1 | PropGuard<unknown>;\ntype Out<S extends Check> = S extends StandardSchemaV1\n ? StandardSchemaV1.InferOutput<S>\n : S extends (value: unknown) => value is infer T\n ? T\n : never;\n\ninterface Required {\n readonly required: true;\n readonly default?: undefined;\n}\ninterface Defaulted<T> {\n readonly required?: false;\n readonly default: T;\n}\ninterface Optional {\n readonly required?: false;\n readonly default?: undefined;\n}\n\ntype Refined<O> = Common & { readonly schema?: Schema<O> };\n\ninterface Scalar<B> {\n <O extends B = B>(opts: Refined<O> & (Required | Defaulted<NoInfer<O>>)): Prop<O>;\n <O extends B = B>(opts?: Refined<O> & Optional): Prop<O | undefined>;\n}\n\n/** `equals` for `prop.json`/`prop.value`: the old and new value (`undefined` when unset). */\ninterface Equals<T> {\n readonly equals?: (a: T | undefined, b: T | undefined) => boolean;\n}\n\ninterface WithSchema {\n <S extends Check>(\n schema: S,\n opts: Common & Equals<NoInfer<Out<S>>> & (Required | Defaulted<NoInfer<Out<S>>>),\n ): Prop<Out<S>>;\n <S extends Check>(\n schema: S,\n opts?: Common & Equals<NoInfer<Out<S>>> & Optional,\n ): Prop<Out<S> | undefined>;\n}\n\ninterface Options {\n readonly attribute?: string | false;\n readonly schema?: StandardSchemaV1;\n readonly required?: boolean;\n readonly default?: unknown;\n readonly equals?: (a: unknown, b: unknown) => boolean;\n}\n\n/** `prop.json` values are JSON: the same JSON text is the same value. */\n// `prop.json`'s default `equals`: the same JSON text. A value JSON can't encode (a cycle, a\n// BigInt) is never equal, so the write always lands instead of throwing from the setter.\nlet warned = false;\nfunction sameJson(a: unknown, b: unknown): boolean {\n try {\n return JSON.stringify(a) === JSON.stringify(b);\n } catch (error) {\n if (DEV && !warned) {\n warned = true;\n console.warn(\n `prop.json got a value JSON can't encode (${String(error)}); every write of it counts ` +\n 'as a change. Use prop.value for non-JSON values, or pass equals.',\n );\n }\n return false;\n }\n}\n\nfunction make(kind: PropKind, opts: Options = {}, schema?: Check): Prop<unknown> {\n features.props = propFeature; // components can declare props now (features.ts)\n const value = opts.default !== undefined ? opts.default : kind === 'boolean' ? false : undefined;\n const base = {\n kind,\n attribute: kind === 'value' ? false : opts.attribute,\n schema: schema ?? opts.schema,\n required: opts.required === true,\n equals: opts.equals ?? (kind === 'json' ? sameJson : Object.is),\n };\n return value === undefined ? base : { ...base, default: value };\n}\n\n/** The prop builders. */\nexport const prop: {\n /** Attribute parsed as is. */\n readonly string: Scalar<string>;\n /** Attribute parsed with `Number(v)`; empty or `NaN` is invalid. */\n readonly number: Scalar<number>;\n /** Attribute present → `true`, absent → `false` (the default). */\n readonly boolean: <O extends boolean = boolean>(\n opts?: Refined<O> & { readonly default?: NoInfer<O> },\n ) => Prop<O>;\n /**\n * Attribute parsed with `JSON.parse`, then the schema (or type guard). Compared by value: a\n * new but equal object (a fresh `.prop=${{…}}` each render) changes nothing.\n */\n readonly json: WithSchema;\n /**\n * Property only: no attribute. Validated in development by the schema (or type guard), and\n * the object set is kept as is (production skips the check). Compared with `Object.is`\n * unless `equals` is given.\n */\n readonly value: WithSchema;\n} = {\n string: (opts?: Options) => make('string', opts),\n number: (opts?: Options) => make('number', opts),\n boolean: ((opts?: Options) => make('boolean', opts)) as <O extends boolean>() => Prop<O>,\n json: (schema: Check, opts?: Options) => make('json', opts, schema),\n value: (schema: Check, opts?: Options) => make('value', opts, schema),\n};\n"]}
package/dist/props.d.ts CHANGED
@@ -1,26 +1,62 @@
1
- import type { PropertyDeclaration } from 'lit';
1
+ import type { Prop } from './prop.js';
2
2
  type Bag = Readonly<Record<string, unknown>>;
3
- /** Gyral's view of a declaration: Lit's options plus `required` and `default`. */
4
- export interface PropInfo extends PropertyDeclaration {
5
- readonly required?: boolean;
6
- readonly default?: unknown;
7
- }
8
- export type PropTable = Readonly<Record<string, PropInfo>>;
9
- /** The element's declared props as set on it (no defaults): what a seed must carry. */
10
- export declare function readRawProps(el: object, table: PropTable): Bag;
11
- /** The element's declared props as components see them: `default` fills `undefined`. */
12
- export declare function readProps(el: object, table: PropTable): Bag;
13
- /** Required props that are still `undefined` (ADR 0007 addendum). */
14
- export declare function missingRequired(el: object, table: PropTable): string[];
15
- /** True when every declared prop is identical (`Object.is`) in both snapshots. */
16
- export declare function sameProps<P>(names: readonly string[], a: P, b: P): boolean;
17
- /** Hydration: sets props that only travelled in the seed, unless the page already set them. */
18
- export declare function restoreProps(el: object, names: readonly string[], seeded: Bag): void;
3
+ export type PropTable = Readonly<Record<string, Prop<unknown>>>;
4
+ /** `minPrice` → `min-price`. */
5
+ export declare const kebab: (name: string) => string;
6
+ /** The prop's attribute, or undefined for a property-only prop. */
7
+ export declare function attributeOf(name: string, def: Prop<unknown>): string | undefined;
8
+ export type Checked = {
9
+ readonly ok: true;
10
+ readonly value: unknown;
11
+ } | {
12
+ readonly ok: false;
13
+ readonly issues: readonly string[];
14
+ };
15
+ /** Runs the built-in type check and the prop's schema. Schemas must be synchronous. */
16
+ export declare function checkValue(tag: string, name: string, def: Prop<unknown>, value: unknown): Checked;
17
+ /** Parses an attribute value (`null`: absent) per the builder table; undefined means missing. */
18
+ export declare function parseAttribute(def: Prop<unknown>, raw: string | null): Checked | undefined;
19
+ /** Logs an invalid value; the caller then treats the prop as missing. */
20
+ export declare function reportInvalid(tag: string, name: string, from: string, issues: readonly string[]): void;
19
21
  /**
20
- * Declared props that collide with a built-in element property (`hidden`, `title`, `id`, …).
21
- * Lit's reactive accessor replaces the built-in, so setting the prop silently changes what the
22
- * platform does with it: a prop named `hidden` hides the element (gyral-czi.33). Browser only:
23
- * the server's DOM shim doesn't model the full prototype chain.
22
+ * An attribute's value for prop `name` (view/05-element.md "When props are validated"):
23
+ * parsed per the builder and always validated; invalid or absent values are missing.
24
+ */
25
+ export declare function attributeValue(tag: string, name: string, def: Prop<unknown> | undefined, attr: string, raw: string | null): unknown;
26
+ /**
27
+ * A property set's (or seed's) value for prop `name`: validated in development only, where an
28
+ * invalid value is missing and a schema that transforms warns. Production keeps the input
29
+ * without calling this (propFeature, element.ts: gyral-c5d.14).
30
+ */
31
+ export declare function propertyValue(tag: string, name: string, def: Prop<unknown> | undefined, value: unknown, from?: string): unknown;
32
+ /** Structural equality for plain data (arrays, plain objects), `Object.is` for the rest. */
33
+ export declare function sameData(a: unknown, b: unknown): boolean;
34
+ /** The declared props as components see them: `default` fills missing values. */
35
+ export declare function readProps(values: Bag, table: PropTable): Bag;
36
+ /** Required props that are still missing (ADR 0007 addendum). */
37
+ export declare function missingRequired(values: Bag, table: PropTable): string[];
38
+ /** Warns about required props that are still missing, at first render. */
39
+ export declare function warnMissing(tag: string, values: Bag, table: PropTable): void;
40
+ /**
41
+ * Declared props that collide with a built-in element property (`hidden`, `title`, `id`, …):
42
+ * the accessor replaces the built-in, so setting the prop silently changes what the platform
43
+ * does with it (gyral-czi.33).
24
44
  */
25
45
  export declare function shadowedBuiltins(names: readonly string[]): string[];
46
+ /** define(): a prop named like a built-in property is an error in development, else a warning. */
47
+ export declare function checkShadowed(tag: string, names: readonly string[]): void;
48
+ /**
49
+ * What the element uses, registered by the prop builders (features.ts). Property sets and seeds
50
+ * go through `propertyValue` in development only: production keeps the value as given, so the
51
+ * property path's schema and guard handling stay out of production bundles (gyral-c5d.14).
52
+ */
53
+ export declare const propFeature: {
54
+ attributeOf: typeof attributeOf;
55
+ attributeValue: typeof attributeValue;
56
+ propertyValue: typeof propertyValue | undefined;
57
+ warnMissing: typeof warnMissing;
58
+ readProps: typeof readProps;
59
+ checkShadowed: typeof checkShadowed;
60
+ };
61
+ export type PropFeature = typeof propFeature;
26
62
  export {};