@e280/sly 0.2.5 → 0.3.0-10

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 (350) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +356 -626
  3. package/package.json +22 -30
  4. package/s/_archive/README.md +1221 -0
  5. package/s/_archive/view/index.ts +7 -0
  6. package/s/_archive/view/types.ts +45 -0
  7. package/s/demo/demo.bundle.ts +5 -8
  8. package/s/demo/views/counter-light.ts +13 -0
  9. package/s/demo/views/counter-shadow.ts +16 -0
  10. package/s/demo/views/demo.ts +24 -20
  11. package/s/demo/views/loaders.ts +9 -9
  12. package/s/demo/views/time-light.ts +19 -0
  13. package/s/demo/views/time-shadow.ts +22 -0
  14. package/s/dom/attrs/attrs.ts +3 -3
  15. package/s/dom/attrs/parts/attr-spec.ts +17 -5
  16. package/s/dom/attrs/parts/on-attrs.ts +1 -1
  17. package/s/dom/dom.ts +1 -1
  18. package/s/index.html.ts +30 -33
  19. package/s/index.ts +2 -4
  20. package/s/{loaders → loader}/index.barrel.ts +0 -1
  21. package/s/{loaders → loader}/index.ts +0 -1
  22. package/s/{loaders → loader}/make.ts +1 -1
  23. package/s/{loaders → loader}/parts/ascii-anim.ts +6 -8
  24. package/s/loader/parts/error-display.ts +26 -0
  25. package/s/{loaders → loader}/types.ts +1 -1
  26. package/s/test.ts +5 -0
  27. package/s/view/common/css-reset.ts +19 -0
  28. package/s/view/common/sly-shadow.ts +14 -0
  29. package/s/view/elements/light.ts +14 -0
  30. package/s/view/elements/shadow.ts +52 -0
  31. package/s/view/hooks/plumbing/hooks.ts +28 -0
  32. package/s/view/hooks/plumbing/hookscope.ts +12 -0
  33. package/s/view/hooks/use-attrs.ts +28 -0
  34. package/s/view/hooks/use-css.ts +14 -0
  35. package/s/view/hooks/use-cx.ts +41 -0
  36. package/s/view/hooks/use-life.ts +17 -0
  37. package/s/view/hooks/use-mount.ts +30 -0
  38. package/s/view/hooks/use-name.ts +10 -0
  39. package/s/view/hooks/use-once.ts +9 -0
  40. package/s/view/hooks/use-op.ts +12 -0
  41. package/s/view/hooks/use-ref.ts +11 -0
  42. package/s/view/hooks/use-signal.ts +16 -0
  43. package/s/view/hooks/use-state.ts +20 -0
  44. package/s/view/hooks/use-wake.ts +8 -0
  45. package/s/view/index.ts +22 -4
  46. package/s/view/light.ts +50 -0
  47. package/s/view/parts/apply-attrs.ts +22 -0
  48. package/s/view/parts/apply-styles.ts +21 -0
  49. package/s/view/parts/cx.ts +26 -0
  50. package/s/view/parts/reactivity.ts +22 -0
  51. package/s/view/shadow.ts +93 -0
  52. package/s/view/types.ts +15 -34
  53. package/x/demo/demo.bundle.js +5 -8
  54. package/x/demo/demo.bundle.js.map +1 -1
  55. package/x/demo/demo.bundle.min.js +52 -63
  56. package/x/demo/demo.bundle.min.js.map +4 -4
  57. package/x/demo/views/counter-light.d.ts +1 -0
  58. package/x/demo/views/counter-light.js +10 -0
  59. package/x/demo/views/counter-light.js.map +1 -0
  60. package/x/demo/views/counter-shadow.d.ts +1 -0
  61. package/x/demo/views/counter-shadow.js +12 -0
  62. package/x/demo/views/counter-shadow.js.map +1 -0
  63. package/x/demo/views/demo.d.ts +1 -4
  64. package/x/demo/views/demo.js +24 -20
  65. package/x/demo/views/demo.js.map +1 -1
  66. package/x/demo/views/loaders.d.ts +1 -1
  67. package/x/demo/views/loaders.js +9 -9
  68. package/x/demo/views/loaders.js.map +1 -1
  69. package/x/demo/views/{counter.d.ts → time-light.d.ts} +3 -19
  70. package/x/demo/views/time-light.js +16 -0
  71. package/x/demo/views/time-light.js.map +1 -0
  72. package/x/demo/views/time-shadow.d.ts +365 -0
  73. package/x/demo/views/time-shadow.js +18 -0
  74. package/x/demo/views/time-shadow.js.map +1 -0
  75. package/x/dom/attrs/attrs.d.ts +3 -2
  76. package/x/dom/attrs/attrs.js +2 -2
  77. package/x/dom/attrs/attrs.js.map +1 -1
  78. package/x/dom/attrs/parts/attr-spec.d.ts +5 -1
  79. package/x/dom/attrs/parts/attr-spec.js +12 -6
  80. package/x/dom/attrs/parts/attr-spec.js.map +1 -1
  81. package/x/dom/attrs/parts/on-attrs.d.ts +1 -1
  82. package/x/dom/attrs/parts/on-attrs.js.map +1 -1
  83. package/x/dom/dom.d.ts +1 -1
  84. package/x/dom/dom.js.map +1 -1
  85. package/x/index.d.ts +2 -4
  86. package/x/index.html +30 -140
  87. package/x/index.html.js +31 -31
  88. package/x/index.html.js.map +1 -1
  89. package/x/index.js +2 -4
  90. package/x/index.js.map +1 -1
  91. package/x/{loaders → loader}/index.barrel.d.ts +0 -1
  92. package/x/loader/index.barrel.js.map +1 -0
  93. package/x/{loaders → loader}/index.d.ts +0 -1
  94. package/x/loader/index.js.map +1 -0
  95. package/x/{loaders → loader}/make.d.ts +1 -1
  96. package/x/loader/make.js.map +1 -0
  97. package/x/loader/mock.js.map +1 -0
  98. package/x/loader/parts/anims.js.map +1 -0
  99. package/x/{loaders → loader}/parts/ascii-anim.d.ts +1 -1
  100. package/x/{loaders → loader}/parts/ascii-anim.js +6 -7
  101. package/x/loader/parts/ascii-anim.js.map +1 -0
  102. package/x/loader/parts/error-display.d.ts +1 -0
  103. package/x/loader/parts/error-display.js +20 -0
  104. package/x/loader/parts/error-display.js.map +1 -0
  105. package/x/{loaders → loader}/types.d.ts +1 -1
  106. package/x/{loaders → loader}/types.js.map +1 -1
  107. package/x/loot/drag-and-drops.d.ts +2 -2
  108. package/x/loot/drops.d.ts +1 -1
  109. package/x/op/index.js.map +1 -0
  110. package/x/op/op.js.map +1 -0
  111. package/x/op/podium.js.map +1 -0
  112. package/x/{ops → op}/types.js.map +1 -1
  113. package/x/test.js +3 -0
  114. package/x/test.js.map +1 -0
  115. package/x/view/common/css-reset.js +17 -0
  116. package/x/view/common/css-reset.js.map +1 -0
  117. package/x/view/common/sly-shadow.d.ts +4 -0
  118. package/x/view/common/sly-shadow.js +11 -0
  119. package/x/view/common/sly-shadow.js.map +1 -0
  120. package/x/view/elements/light.d.ts +357 -0
  121. package/x/view/elements/light.js +10 -0
  122. package/x/view/elements/light.js.map +1 -0
  123. package/x/view/elements/shadow.d.ts +366 -0
  124. package/x/view/elements/shadow.js +42 -0
  125. package/x/view/elements/shadow.js.map +1 -0
  126. package/x/view/hooks/plumbing/hooks.d.ts +11 -0
  127. package/x/view/hooks/plumbing/hooks.js +26 -0
  128. package/x/view/hooks/plumbing/hooks.js.map +1 -0
  129. package/x/view/hooks/plumbing/hookscope.d.ts +10 -0
  130. package/x/view/hooks/plumbing/hookscope.js +12 -0
  131. package/x/view/hooks/plumbing/hookscope.js.map +1 -0
  132. package/x/view/hooks/use-attrs.d.ts +2 -0
  133. package/x/view/hooks/use-attrs.js +23 -0
  134. package/x/view/hooks/use-attrs.js.map +1 -0
  135. package/x/view/hooks/use-css.d.ts +4 -0
  136. package/x/view/hooks/use-css.js +10 -0
  137. package/x/view/hooks/use-css.js.map +1 -0
  138. package/x/view/hooks/use-cx.d.ts +10 -0
  139. package/x/view/hooks/use-cx.js +33 -0
  140. package/x/view/hooks/use-cx.js.map +1 -0
  141. package/x/view/hooks/use-life.d.ts +2 -0
  142. package/x/view/hooks/use-life.js +13 -0
  143. package/x/view/hooks/use-life.js.map +1 -0
  144. package/x/{base/utils/mounts.d.ts → view/hooks/use-mount.d.ts} +1 -0
  145. package/x/{base/utils/mounts.js → view/hooks/use-mount.js} +7 -1
  146. package/x/view/hooks/use-mount.js.map +1 -0
  147. package/x/view/hooks/use-name.d.ts +2 -0
  148. package/x/view/hooks/use-name.js +8 -0
  149. package/x/view/hooks/use-name.js.map +1 -0
  150. package/x/view/hooks/use-once.d.ts +2 -0
  151. package/x/view/hooks/use-once.js +7 -0
  152. package/x/view/hooks/use-once.js.map +1 -0
  153. package/x/view/hooks/use-op.d.ts +3 -0
  154. package/x/view/hooks/use-op.js +9 -0
  155. package/x/view/hooks/use-op.js.map +1 -0
  156. package/x/view/hooks/use-ref.d.ts +5 -0
  157. package/x/view/hooks/use-ref.js +11 -0
  158. package/x/view/hooks/use-ref.js.map +1 -0
  159. package/x/view/hooks/use-signal.d.ts +3 -0
  160. package/x/view/hooks/use-signal.js +12 -0
  161. package/x/view/hooks/use-signal.js.map +1 -0
  162. package/x/view/hooks/use-state.d.ts +1 -0
  163. package/x/view/hooks/use-state.js +17 -0
  164. package/x/view/hooks/use-state.js.map +1 -0
  165. package/x/view/hooks/use-wake.d.ts +2 -0
  166. package/x/view/hooks/use-wake.js +6 -0
  167. package/x/view/hooks/use-wake.js.map +1 -0
  168. package/x/view/index.d.ts +19 -4
  169. package/x/view/index.js +19 -4
  170. package/x/view/index.js.map +1 -1
  171. package/x/view/light.d.ts +2 -0
  172. package/x/view/light.js +41 -0
  173. package/x/view/light.js.map +1 -0
  174. package/x/view/parts/apply-attrs.d.ts +2 -0
  175. package/x/view/parts/apply-attrs.js +22 -0
  176. package/x/view/parts/apply-attrs.js.map +1 -0
  177. package/x/{base/utils → view/parts}/apply-styles.js.map +1 -1
  178. package/x/view/parts/cx.d.ts +12 -0
  179. package/x/view/parts/cx.js +24 -0
  180. package/x/view/parts/cx.js.map +1 -0
  181. package/x/view/parts/reactivity.d.ts +5 -0
  182. package/x/view/parts/reactivity.js +18 -0
  183. package/x/view/parts/reactivity.js.map +1 -0
  184. package/x/view/shadow.d.ts +6 -0
  185. package/x/view/shadow.js +71 -0
  186. package/x/view/shadow.js.map +1 -0
  187. package/x/view/types.d.ts +13 -21
  188. package/s/demo/views/counter.ts +0 -50
  189. package/s/demo/views/fastcount.ts +0 -29
  190. package/s/demo/views/mounting.ts +0 -36
  191. package/s/loaders/parts/error-display.ts +0 -26
  192. package/s/tests.test.ts +0 -8
  193. package/x/base/css-reset.js +0 -19
  194. package/x/base/css-reset.js.map +0 -1
  195. package/x/base/element.d.ts +0 -19
  196. package/x/base/element.js +0 -55
  197. package/x/base/element.js.map +0 -1
  198. package/x/base/index.d.ts +0 -5
  199. package/x/base/index.js +0 -6
  200. package/x/base/index.js.map +0 -1
  201. package/x/base/types.d.ts +0 -3
  202. package/x/base/types.js +0 -3
  203. package/x/base/types.js.map +0 -1
  204. package/x/base/use.d.ts +0 -59
  205. package/x/base/use.js +0 -129
  206. package/x/base/use.js.map +0 -1
  207. package/x/base/utils/attr-watcher.d.ts +0 -8
  208. package/x/base/utils/attr-watcher.js +0 -20
  209. package/x/base/utils/attr-watcher.js.map +0 -1
  210. package/x/base/utils/mounts.js.map +0 -1
  211. package/x/base/utils/reactor.d.ts +0 -5
  212. package/x/base/utils/reactor.js +0 -25
  213. package/x/base/utils/reactor.js.map +0 -1
  214. package/x/base/utils/states.d.ts +0 -13
  215. package/x/base/utils/states.js +0 -41
  216. package/x/base/utils/states.js.map +0 -1
  217. package/x/base/utils/use-attrs.d.ts +0 -11
  218. package/x/base/utils/use-attrs.js +0 -18
  219. package/x/base/utils/use-attrs.js.map +0 -1
  220. package/x/demo/views/counter.js +0 -42
  221. package/x/demo/views/counter.js.map +0 -1
  222. package/x/demo/views/fastcount.d.ts +0 -12
  223. package/x/demo/views/fastcount.js +0 -21
  224. package/x/demo/views/fastcount.js.map +0 -1
  225. package/x/demo/views/mounting.d.ts +0 -3
  226. package/x/demo/views/mounting.js +0 -28
  227. package/x/demo/views/mounting.js.map +0 -1
  228. package/x/loaders/index.barrel.js.map +0 -1
  229. package/x/loaders/index.js.map +0 -1
  230. package/x/loaders/make.js.map +0 -1
  231. package/x/loaders/mock.js.map +0 -1
  232. package/x/loaders/parts/anims.js.map +0 -1
  233. package/x/loaders/parts/ascii-anim.js.map +0 -1
  234. package/x/loaders/parts/error-display.d.ts +0 -1
  235. package/x/loaders/parts/error-display.js +0 -20
  236. package/x/loaders/parts/error-display.js.map +0 -1
  237. package/x/ops/index.js.map +0 -1
  238. package/x/ops/op.js.map +0 -1
  239. package/x/ops/podium.js.map +0 -1
  240. package/x/spa/index.barrel.d.ts +0 -4
  241. package/x/spa/index.barrel.js +0 -3
  242. package/x/spa/index.barrel.js.map +0 -1
  243. package/x/spa/index.d.ts +0 -2
  244. package/x/spa/index.js +0 -2
  245. package/x/spa/index.js.map +0 -1
  246. package/x/spa/plumbing/braces.d.ts +0 -12
  247. package/x/spa/plumbing/braces.js +0 -55
  248. package/x/spa/plumbing/braces.js.map +0 -1
  249. package/x/spa/plumbing/primitives.d.ts +0 -22
  250. package/x/spa/plumbing/primitives.js +0 -65
  251. package/x/spa/plumbing/primitives.js.map +0 -1
  252. package/x/spa/plumbing/router-core.d.ts +0 -13
  253. package/x/spa/plumbing/router-core.js +0 -38
  254. package/x/spa/plumbing/router-core.js.map +0 -1
  255. package/x/spa/plumbing/types.d.ts +0 -35
  256. package/x/spa/plumbing/types.js +0 -2
  257. package/x/spa/plumbing/types.js.map +0 -1
  258. package/x/spa/router.d.ts +0 -13
  259. package/x/spa/router.js +0 -39
  260. package/x/spa/router.js.map +0 -1
  261. package/x/spa/spa.test.d.ts +0 -15
  262. package/x/spa/spa.test.js +0 -78
  263. package/x/spa/spa.test.js.map +0 -1
  264. package/x/tests.test.js +0 -6
  265. package/x/tests.test.js.map +0 -1
  266. package/x/view/utils/contextualize.d.ts +0 -13
  267. package/x/view/utils/contextualize.js +0 -18
  268. package/x/view/utils/contextualize.js.map +0 -1
  269. package/x/view/utils/make-component.d.ts +0 -5
  270. package/x/view/utils/make-component.js +0 -17
  271. package/x/view/utils/make-component.js.map +0 -1
  272. package/x/view/utils/make-view.d.ts +0 -2
  273. package/x/view/utils/make-view.js +0 -32
  274. package/x/view/utils/make-view.js.map +0 -1
  275. package/x/view/utils/parts/capsule.d.ts +0 -12
  276. package/x/view/utils/parts/capsule.js +0 -56
  277. package/x/view/utils/parts/capsule.js.map +0 -1
  278. package/x/view/utils/parts/chain.d.ts +0 -13
  279. package/x/view/utils/parts/chain.js +0 -26
  280. package/x/view/utils/parts/chain.js.map +0 -1
  281. package/x/view/utils/parts/context.d.ts +0 -9
  282. package/x/view/utils/parts/context.js +0 -10
  283. package/x/view/utils/parts/context.js.map +0 -1
  284. package/x/view/utils/parts/directive.d.ts +0 -5
  285. package/x/view/utils/parts/directive.js +0 -20
  286. package/x/view/utils/parts/directive.js.map +0 -1
  287. package/x/view/utils/parts/naked.d.ts +0 -18
  288. package/x/view/utils/parts/naked.js +0 -57
  289. package/x/view/utils/parts/naked.js.map +0 -1
  290. package/x/view/utils/parts/sly-view.d.ts +0 -6
  291. package/x/view/utils/parts/sly-view.js +0 -16
  292. package/x/view/utils/parts/sly-view.js.map +0 -1
  293. package/x/view/view.d.ts +0 -11
  294. package/x/view/view.js +0 -15
  295. package/x/view/view.js.map +0 -1
  296. /package/s/{base → _archive/base}/css-reset.ts +0 -0
  297. /package/s/{base → _archive/base}/element.ts +0 -0
  298. /package/s/{base → _archive/base}/index.ts +0 -0
  299. /package/s/{base → _archive/base}/types.ts +0 -0
  300. /package/s/{base → _archive/base}/use.ts +0 -0
  301. /package/s/{base → _archive/base}/utils/apply-styles.ts +0 -0
  302. /package/s/{base → _archive/base}/utils/attr-watcher.ts +0 -0
  303. /package/s/{base → _archive/base}/utils/mounts.ts +0 -0
  304. /package/s/{base → _archive/base}/utils/reactor.ts +0 -0
  305. /package/s/{base → _archive/base}/utils/states.ts +0 -0
  306. /package/s/{base → _archive/base}/utils/use-attrs.ts +0 -0
  307. /package/s/{spa → _archive/spa}/index.barrel.ts +0 -0
  308. /package/s/{spa → _archive/spa}/index.ts +0 -0
  309. /package/s/{spa → _archive/spa}/plumbing/braces.ts +0 -0
  310. /package/s/{spa → _archive/spa}/plumbing/primitives.ts +0 -0
  311. /package/s/{spa → _archive/spa}/plumbing/router-core.ts +0 -0
  312. /package/s/{spa → _archive/spa}/plumbing/types.ts +0 -0
  313. /package/s/{spa → _archive/spa}/router.ts +0 -0
  314. /package/s/{spa → _archive/spa}/spa.test.ts +0 -0
  315. /package/s/{view → _archive/view}/utils/contextualize.ts +0 -0
  316. /package/s/{view → _archive/view}/utils/make-component.ts +0 -0
  317. /package/s/{view → _archive/view}/utils/make-view.ts +0 -0
  318. /package/s/{view → _archive/view}/utils/parts/capsule.ts +0 -0
  319. /package/s/{view → _archive/view}/utils/parts/chain.ts +0 -0
  320. /package/s/{view → _archive/view}/utils/parts/context.ts +0 -0
  321. /package/s/{view → _archive/view}/utils/parts/directive.ts +0 -0
  322. /package/s/{view → _archive/view}/utils/parts/naked.ts +0 -0
  323. /package/s/{view → _archive/view}/utils/parts/sly-view.ts +0 -0
  324. /package/s/{view → _archive/view}/view.ts +0 -0
  325. /package/s/{loaders → loader}/mock.ts +0 -0
  326. /package/s/{loaders → loader}/parts/anims.ts +0 -0
  327. /package/s/{ops → op}/index.ts +0 -0
  328. /package/s/{ops → op}/op.ts +0 -0
  329. /package/s/{ops → op}/podium.ts +0 -0
  330. /package/s/{ops → op}/types.ts +0 -0
  331. /package/x/{loaders → loader}/index.barrel.js +0 -0
  332. /package/x/{loaders → loader}/index.js +0 -0
  333. /package/x/{loaders → loader}/make.js +0 -0
  334. /package/x/{loaders → loader}/mock.d.ts +0 -0
  335. /package/x/{loaders → loader}/mock.js +0 -0
  336. /package/x/{loaders → loader}/parts/anims.d.ts +0 -0
  337. /package/x/{loaders → loader}/parts/anims.js +0 -0
  338. /package/x/{loaders → loader}/types.js +0 -0
  339. /package/x/{ops → op}/index.d.ts +0 -0
  340. /package/x/{ops → op}/index.js +0 -0
  341. /package/x/{ops → op}/op.d.ts +0 -0
  342. /package/x/{ops → op}/op.js +0 -0
  343. /package/x/{ops → op}/podium.d.ts +0 -0
  344. /package/x/{ops → op}/podium.js +0 -0
  345. /package/x/{ops → op}/types.d.ts +0 -0
  346. /package/x/{ops → op}/types.js +0 -0
  347. /package/x/{tests.test.d.ts → test.d.ts} +0 -0
  348. /package/x/{base → view/common}/css-reset.d.ts +0 -0
  349. /package/x/{base/utils → view/parts}/apply-styles.d.ts +0 -0
  350. /package/x/{base/utils → view/parts}/apply-styles.js +0 -0
@@ -0,0 +1,28 @@
1
+
2
+ import {useRef} from "./use-ref.js"
3
+ import {dom} from "../../dom/dom.js"
4
+ import {useOnce} from "./use-once.js"
5
+ import {useMount} from "./use-mount.js"
6
+ import {AttrSpec} from "../../dom/types.js"
7
+ import {useHost, useRender, useRendered} from "./use-cx.js"
8
+
9
+ export function useAttrs<A extends AttrSpec>(spec: A) {
10
+ const host = useHost()
11
+ const rerender = useRender()
12
+ const ourChanges = useRef(new Set<string>())
13
+
14
+ useMount(() => dom.attrs(host).on(records => {
15
+ for (const record of records) {
16
+ if (ourChanges.current.has(record.attributeName!)) continue
17
+ rerender()
18
+ break
19
+ }
20
+ }))
21
+
22
+ useRendered().then(() => ourChanges.current.clear())
23
+
24
+ return useOnce(() => dom.attrs(host).spec(spec, {
25
+ beforeSet: key => ourChanges.current.add(key),
26
+ }))
27
+ }
28
+
@@ -0,0 +1,14 @@
1
+
2
+ import {CSSResultGroup} from "lit"
3
+ import {useShadow} from "./use-cx.js"
4
+ import {useOnce} from "./use-once.js"
5
+ import {applyStyles} from "../parts/apply-styles.js"
6
+
7
+ /** attach stylesheets to the shadow root */
8
+ export function useCss(...styles: CSSResultGroup[]) {
9
+ const shadow = useShadow()
10
+ useOnce(() => applyStyles(shadow, styles))
11
+ }
12
+
13
+ export const useStyles = useCss
14
+
@@ -0,0 +1,41 @@
1
+
2
+ import {ShadowCx} from "../parts/cx.js"
3
+ import {hooks} from "./plumbing/hooks.js"
4
+
5
+ function useCx() {
6
+ const {scope} = hooks.increment()
7
+ return scope.cx
8
+ }
9
+
10
+ function useShadowCx() {
11
+ const cx = useCx()
12
+ if (!(cx instanceof ShadowCx))
13
+ throw new Error("this hook only works on shadow views (but was called in a light view)")
14
+ return cx
15
+ }
16
+
17
+ /** return the current count of how many times this view has been rendered (starts at 0) */
18
+ export function useCount() {
19
+ return useCx().count
20
+ }
21
+
22
+ /** return a function that triggers the view to rerender */
23
+ export function useRender() {
24
+ return useCx().render
25
+ }
26
+
27
+ /** return a promise that resolves after the next render is complete */
28
+ export function useRendered() {
29
+ return useCx().rendered.promise
30
+ }
31
+
32
+ /** return the shadow view's host element */
33
+ export function useHost() {
34
+ return useShadowCx().host
35
+ }
36
+
37
+ /** return the shadow root */
38
+ export function useShadow() {
39
+ return useShadowCx().shadow
40
+ }
41
+
@@ -0,0 +1,17 @@
1
+
2
+ import {useRef} from "./use-ref.js"
3
+ import {useMount} from "./use-mount.js"
4
+
5
+ /** mount/unmount lifecycle, but also return a value */
6
+ export function useLife<Value>(fn: () => [value: Value, dispose: () => void]) {
7
+ const ref = useRef<Value>(undefined as Value)
8
+
9
+ useMount(() => {
10
+ const [value, dispose] = fn()
11
+ ref.current = value
12
+ return dispose
13
+ })
14
+
15
+ return ref.current
16
+ }
17
+
@@ -0,0 +1,30 @@
1
+
2
+ import {useOnce} from "./use-once.js"
3
+ import {hooks} from "./plumbing/hooks.js"
4
+
5
+ export function useMount(fn: () => () => void) {
6
+ const {scope} = hooks.increment()
7
+ return useOnce(() => scope.mounts.mount(fn))
8
+ }
9
+
10
+ export class Mounts {
11
+ #mounters: (() => () => void)[] = []
12
+ #unmounters: (() => void)[] = []
13
+
14
+ mount(mount: () => () => void) {
15
+ this.#mounters.push(mount)
16
+ this.#unmounters.push(mount())
17
+ }
18
+
19
+ unmountAll() {
20
+ for (const unmount of this.#unmounters)
21
+ unmount()
22
+ this.#unmounters = []
23
+ }
24
+
25
+ remountAll() {
26
+ for (const mount of this.#mounters)
27
+ this.#unmounters.push(mount())
28
+ }
29
+ }
30
+
@@ -0,0 +1,10 @@
1
+
2
+ import {useHost} from "./use-cx.js"
3
+ import {useOnce} from "./use-once.js"
4
+
5
+ /** sets the host element's "data-view" attribute */
6
+ export function useName(name = "") {
7
+ const host = useHost()
8
+ useOnce(() => host.setAttribute("view", name))
9
+ }
10
+
@@ -0,0 +1,9 @@
1
+
2
+ import {hooks} from "./plumbing/hooks.js"
3
+
4
+ /** run the fn only one time */
5
+ export function useOnce<Value>(fn: () => Value) {
6
+ const {scope, position} = hooks.increment()
7
+ return scope.values.guarantee(position, fn) as Value
8
+ }
9
+
@@ -0,0 +1,12 @@
1
+
2
+ import {Op} from "../../op/op.js"
3
+ import {useOnce} from "./use-once.js"
4
+
5
+ export function useOp<Value>(fn: () => Promise<Value>) {
6
+ return useOnce(() => Op.load(fn))
7
+ }
8
+
9
+ export function useOpPromise<Value>(promise: Promise<Value>) {
10
+ return useOnce(() => Op.promise(promise))
11
+ }
12
+
@@ -0,0 +1,11 @@
1
+
2
+ import {useOnce} from "./use-once.js"
3
+
4
+ export function useRef<Value>(initial: Value) {
5
+ return useOnce(() => new Ref(initial))
6
+ }
7
+
8
+ export class Ref<Value> {
9
+ constructor(public current: Value) {}
10
+ }
11
+
@@ -0,0 +1,16 @@
1
+
2
+ import {signal} from "@e280/strata"
3
+ import {useOnce} from "./use-once.js"
4
+
5
+ export function useSignal<Value>(value: Value) {
6
+ return useOnce(() => signal(value))
7
+ }
8
+
9
+ export function useDerived<Value>(fn: () => Value) {
10
+ return useOnce(() => signal.derived(fn))
11
+ }
12
+
13
+ export function useLazy<Value>(fn: () => Value) {
14
+ return useOnce(() => signal.lazy(fn))
15
+ }
16
+
@@ -0,0 +1,20 @@
1
+
2
+ import {useRef} from "./use-ref.js"
3
+ import {useRender} from "./use-cx.js"
4
+
5
+ export function useState<Value>(value: Value) {
6
+ const render = useRender()
7
+ const ref = useRef(value)
8
+
9
+ const set = (next: Value | ((prev: Value) => Value)) => {
10
+ const value = typeof next === "function"
11
+ ? (next as (prev: Value) => Value)(ref.current)
12
+ : next
13
+ if (Object.is(value, ref.current)) return
14
+ ref.current = value
15
+ render()
16
+ }
17
+
18
+ return [ref.current, set] as const
19
+ }
20
+
@@ -0,0 +1,8 @@
1
+
2
+ import {useLife} from "./use-life.js";
3
+
4
+ /** run the fn whenever the view is mounted */
5
+ export function useWake<Value>(fn: () => Value) {
6
+ return useLife(() => [fn(), () => {}])
7
+ }
8
+
package/s/view/index.ts CHANGED
@@ -1,7 +1,25 @@
1
1
 
2
- export * from "./utils/parts/chain.js"
3
- export * from "./utils/parts/sly-view.js"
4
- export * from "./utils/contextualize.js"
2
+ export * from "./common/css-reset.js"
3
+ export * from "./common/sly-shadow.js"
4
+
5
+ export * from "./elements/light.js"
6
+ export * from "./elements/shadow.js"
7
+
8
+ export * from "./hooks/use-attrs.js"
9
+ export * from "./hooks/use-css.js"
10
+ export * from "./hooks/use-cx.js"
11
+ export * from "./hooks/use-life.js"
12
+ export * from "./hooks/use-mount.js"
13
+ export * from "./hooks/use-name.js"
14
+ export * from "./hooks/use-once.js"
15
+ export * from "./hooks/use-op.js"
16
+ export * from "./hooks/use-ref.js"
17
+ export * from "./hooks/use-signal.js"
18
+ export * from "./hooks/use-state.js"
19
+ export * from "./hooks/use-cx.js"
20
+ export * from "./hooks/use-wake.js"
21
+
22
+ export * from "./light.js"
23
+ export * from "./shadow.js"
5
24
  export * from "./types.js"
6
- export * from "./view.js"
7
25
 
@@ -0,0 +1,50 @@
1
+
2
+ import {microbounce} from "@e280/stz"
3
+
4
+ import {View} from "./types.js"
5
+ import {LightCx} from "./parts/cx.js"
6
+ import {hooks} from "./hooks/plumbing/hooks.js"
7
+ import {Reactivity} from "./parts/reactivity.js"
8
+ import {Hookscope} from "./hooks/plumbing/hookscope.js"
9
+ import {AsyncDirective, directive, Part} from "lit/async-directive.js"
10
+
11
+ export function light<Props extends any[]>(view: View<Props>) {
12
+ return directive(class D extends AsyncDirective {
13
+ #props!: Props
14
+ #cx = new LightCx(microbounce(() => {
15
+ if (!this.#props) throw new Error("cannot render before props")
16
+ if (this.isConnected) {
17
+ const content = this.render(...this.#props)
18
+ this.setValue(content)
19
+ this.#cx.doneRender()
20
+ }
21
+ }))
22
+ #hookscope = new Hookscope(this.#cx)
23
+ #reactivity = new Reactivity()
24
+
25
+ update(part: Part, props: any[]) {
26
+ const ret = super.update(part, props)
27
+ if (this.isConnected) this.#cx.doneRender()
28
+ return ret
29
+ }
30
+
31
+ render(...props: Props) {
32
+ this.#props = props
33
+ return this.#reactivity.observe(
34
+ () => hooks.wrap(this.#hookscope, () => view(...this.#props)),
35
+ this.#cx.render,
36
+ )
37
+ }
38
+
39
+ disconnected() {
40
+ this.#hookscope.mounts.unmountAll()
41
+ this.#reactivity.clear()
42
+ }
43
+
44
+ reconnected() {
45
+ this.#hookscope.mounts.remountAll()
46
+ this.#cx.render()
47
+ }
48
+ }) as View<Props>
49
+ }
50
+
@@ -0,0 +1,22 @@
1
+
2
+ import {ViewAttr, ViewAttrs} from "../types.js"
3
+
4
+ export function applyAttrs(element: HTMLElement, attrs: ViewAttrs) {
5
+ for (const [name, value] of Object.entries(attrs))
6
+ applyAttr(element, name, value)
7
+ }
8
+
9
+ function applyAttr(element: HTMLElement, name: string, value: ViewAttr) {
10
+ const existing = element.getAttribute(name)
11
+ const v = coerce(value)
12
+ if (v === existing) return
13
+ if (v === null) element.removeAttribute(name)
14
+ else element.setAttribute(name, v)
15
+ }
16
+
17
+ function coerce(value: ViewAttr) {
18
+ if (typeof value === "string") return value
19
+ else if (typeof value === "number") return value.toString()
20
+ return value ? "" : null
21
+ }
22
+
@@ -0,0 +1,21 @@
1
+
2
+ import {adoptStyles, CSSResultGroup, CSSResultOrNative, getCompatibleStyle} from "lit"
3
+
4
+ export function applyStyles(shadow: ShadowRoot, styles?: CSSResultGroup) {
5
+ adoptStyles(shadow, prepareStyles(styles))
6
+ }
7
+
8
+ function prepareStyles(styles?: CSSResultGroup): Array<CSSResultOrNative> {
9
+ const elementStyles = []
10
+
11
+ if (Array.isArray(styles)) {
12
+ const set = new Set((styles as Array<unknown>).flat(Infinity).reverse())
13
+ for (const s of set)
14
+ elementStyles.unshift(getCompatibleStyle(s as CSSResultOrNative))
15
+ }
16
+ else if (styles !== undefined)
17
+ elementStyles.push(getCompatibleStyle(styles))
18
+
19
+ return elementStyles
20
+ }
21
+
@@ -0,0 +1,26 @@
1
+
2
+ import {defer} from "@e280/stz"
3
+
4
+ export class LightCx {
5
+ count = 0
6
+ rendered = defer<void>()
7
+
8
+ constructor(public render: () => Promise<void>) {}
9
+
10
+ doneRender() {
11
+ this.count++
12
+ this.rendered.resolve()
13
+ this.rendered = defer()
14
+ }
15
+ }
16
+
17
+ export class ShadowCx extends LightCx {
18
+ constructor(
19
+ render: () => Promise<void>,
20
+ public host: HTMLElement,
21
+ public shadow: ShadowRoot,
22
+ ) {
23
+ super(render)
24
+ }
25
+ }
26
+
@@ -0,0 +1,22 @@
1
+
2
+ import {tracker} from "@e280/strata"
3
+
4
+ export class Reactivity {
5
+ #stoppers: (() => void)[] = []
6
+
7
+ clear() {
8
+ this.#stoppers.forEach(stop => stop())
9
+ this.#stoppers = []
10
+ }
11
+
12
+ observe<X>(fn: () => X, rerender: () => Promise<void>) {
13
+ const {seen, result} = tracker.observe(fn)
14
+ this.clear()
15
+ for (const item of seen) {
16
+ const stop = tracker.subscribe(item, rerender)
17
+ this.#stoppers.push(stop)
18
+ }
19
+ return result
20
+ }
21
+ }
22
+
@@ -0,0 +1,93 @@
1
+
2
+ import {microbounce} from "@e280/stz"
3
+ import {render as litRender} from "lit"
4
+
5
+ import {ShadowCx} from "./parts/cx.js"
6
+ import {hooks} from "./hooks/plumbing/hooks.js"
7
+ import {SlyShadow} from "./common/sly-shadow.js"
8
+ import {Reactivity} from "./parts/reactivity.js"
9
+ import {applyAttrs} from "./parts/apply-attrs.js"
10
+ import {Hookscope} from "./hooks/plumbing/hookscope.js"
11
+ import {View, Placement, ShadowSetup, ShadowView} from "./types.js"
12
+ import {AsyncDirective, directive, PartInfo} from "lit/async-directive.js"
13
+
14
+ export function shadowSetup(): ShadowSetup {
15
+ SlyShadow.register()
16
+ const host = document.createElement("sly-shadow")
17
+ const shadow = host.attachShadow({mode: "open"})
18
+ return {host, shadow}
19
+ }
20
+
21
+ export function shadow<Props extends any[]>(view: View<Props>) {
22
+ return rawShadow(shadowSetup, view)
23
+ }
24
+
25
+ shadow.setup = (setup: () => ShadowSetup) => (
26
+ <Props extends any[]>(view: View<Props>) => (
27
+ rawShadow(setup, view)
28
+ )
29
+ )
30
+
31
+ function rawShadow<Props extends any[]>(
32
+ setup: () => ShadowSetup,
33
+ view: View<Props>,
34
+ ) {
35
+
36
+ const directiveFn = directive(class extends AsyncDirective {
37
+ #cx
38
+ #hookscope
39
+ #props!: Props
40
+ #reactivity = new Reactivity()
41
+
42
+ constructor(part: PartInfo) {
43
+ super(part)
44
+ const {host, shadow} = setup()
45
+ const rerender = microbounce(() => {
46
+ if (!this.#props) throw new Error("cannot render before props")
47
+ if (!this.isConnected) return
48
+ const content = this.#renderContent(this.#props)
49
+ litRender(content, this.#cx.shadow)
50
+ this.#cx.doneRender()
51
+ })
52
+ this.#cx = new ShadowCx(rerender, host, shadow)
53
+ this.#hookscope = new Hookscope(this.#cx)
54
+ }
55
+
56
+ #renderContent(props: Props) {
57
+ this.#props = props
58
+ return this.#reactivity.observe(
59
+ () => hooks.wrap(this.#hookscope, () => view(...this.#props)),
60
+ this.#cx.render,
61
+ )
62
+ }
63
+
64
+ render({props, children, attrs}: Placement<Props>) {
65
+ const {host} = this.#cx
66
+ if (!this.isConnected) return host
67
+ if (attrs) applyAttrs(host, attrs)
68
+ litRender(children, this.#cx.host)
69
+ litRender(this.#renderContent(props), this.#cx.shadow)
70
+ this.#cx.doneRender()
71
+ return host
72
+ }
73
+
74
+ disconnected() {
75
+ this.#hookscope.mounts.unmountAll()
76
+ this.#reactivity.clear()
77
+ }
78
+
79
+ reconnected() {
80
+ this.#hookscope.mounts.remountAll()
81
+ this.#cx.render()
82
+ }
83
+ }) as ShadowView<[Placement<Props>]>
84
+
85
+ function shadowView(...props: Props) {
86
+ return directiveFn({props})
87
+ }
88
+
89
+ shadowView.with = directiveFn
90
+
91
+ return shadowView as ShadowView<Props>
92
+ }
93
+
package/s/view/types.ts CHANGED
@@ -1,45 +1,26 @@
1
1
 
2
2
  import {TemplateResult} from "lit"
3
- import {Constructor} from "@e280/stz"
4
- import {DirectiveResult} from "lit/directive.js"
5
-
6
- import {Use} from "../base/use.js"
7
- import {BaseElement} from "../base/element.js"
8
- import {ViewChain} from "./utils/parts/chain.js"
3
+ import {DirectiveResult} from "lit/async-directive.js"
9
4
 
10
5
  export type Content = TemplateResult | DirectiveResult | HTMLElement | string | null | undefined | void | Content[]
11
6
 
12
- export type ViewFn<Props extends any[]> = (
13
- (use: Use) =>
14
- (...props: Props) =>
15
- Content
16
- )
17
-
18
- export type View<Props extends any[]> = {
19
- (...props: Props): DirectiveResult
20
- props: (...props: Props) => ViewChain<Props>
21
- transmute: <PropsB extends any[]>(convert: (...propsB: PropsB) => Props) => View<PropsB>
22
- component: <B extends Constructor<BaseElement>>(Base?: B) => {
23
- props: (propFn: (component: InstanceType<B>) => Props) => (
24
- ComponentClass<B, Props>
25
- )
26
- }
27
- naked: (host: HTMLElement) => NakedView<Props>
28
- }
7
+ export type View<Props extends any[]> = (...props: Props) => Content
29
8
 
30
- export type ViewProps<V extends View<any>> = (
31
- V extends View<infer Props>
32
- ? Props
33
- : never
34
- )
9
+ export type ViewAttr = string | number | boolean
10
+ export type ViewAttrs = Record<string, ViewAttr>
35
11
 
36
- export type ComponentClass<B extends Constructor<BaseElement>, Props extends any[]> = {
37
- view: View<Props>
38
- new(): InstanceType<B>
39
- } & B
12
+ export type Placement<Props extends any[]> = {
13
+ props: Props
14
+ children?: Content
15
+ attrs?: ViewAttrs
16
+ }
17
+
18
+ export type ShadowView<Props extends any[]> = View<Props> & {
19
+ with: (placement: Placement<Props>) => Content
20
+ }
40
21
 
41
- export type NakedView<Props extends any[]> = {
22
+ export type ShadowSetup = {
42
23
  host: HTMLElement
43
- render: (...props: Props) => void
24
+ shadow: ShadowRoot
44
25
  }
45
26
 
@@ -1,11 +1,8 @@
1
1
  import { dom } from "../dom/dom.js";
2
- import { CounterComponent } from "./views/counter.js";
3
- import { DemoComponent } from "./views/demo.js";
4
- import { FastcountElement } from "./views/fastcount.js";
5
- dom.register({
6
- DemoComponent,
7
- CounterComponent,
8
- FastcountElement,
9
- });
2
+ import { Demo } from "./views/demo.js";
3
+ import { TimeLight } from "./views/time-light.js";
4
+ import { TimeShadow } from "./views/time-shadow.js";
5
+ dom.register({ TimeShadow, TimeLight });
6
+ dom.render(dom(".demo"), Demo());
10
7
  console.log("🦝 sly");
11
8
  //# sourceMappingURL=demo.bundle.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"demo.bundle.js","sourceRoot":"","sources":["../../s/demo/demo.bundle.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,GAAG,EAAC,MAAM,eAAe,CAAA;AACjC,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAA;AACnD,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAA;AAC7C,OAAO,EAAC,gBAAgB,EAAC,MAAM,sBAAsB,CAAA;AAErD,GAAG,CAAC,QAAQ,CAAC;IACZ,aAAa;IACb,gBAAgB;IAChB,gBAAgB;CAChB,CAAC,CAAA;AAEF,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA"}
1
+ {"version":3,"file":"demo.bundle.js","sourceRoot":"","sources":["../../s/demo/demo.bundle.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,GAAG,EAAC,MAAM,eAAe,CAAA;AACjC,OAAO,EAAC,IAAI,EAAC,MAAM,iBAAiB,CAAA;AACpC,OAAO,EAAC,SAAS,EAAC,MAAM,uBAAuB,CAAA;AAC/C,OAAO,EAAC,UAAU,EAAC,MAAM,wBAAwB,CAAA;AAEjD,GAAG,CAAC,QAAQ,CAAC,EAAC,UAAU,EAAE,SAAS,EAAC,CAAC,CAAA;AAErC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,CAAA;AAChC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA"}