@e280/sly 0.2.0-9 → 0.2.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 (275) hide show
  1. package/README.md +363 -124
  2. package/package.json +14 -7
  3. package/s/{views/base-element.ts → base/element.ts} +18 -10
  4. package/s/base/index.ts +6 -0
  5. package/s/{views → base}/use.ts +15 -6
  6. package/s/{views → base}/utils/reactor.ts +13 -4
  7. package/s/base/utils/states.ts +49 -0
  8. package/s/base/utils/use-attrs.ts +36 -0
  9. package/s/demo/demo.bundle.ts +6 -19
  10. package/s/demo/views/counter.ts +14 -25
  11. package/s/demo/views/demo.ts +9 -16
  12. package/s/demo/views/{incredi.ts → fastcount.ts} +5 -5
  13. package/s/demo/views/loaders.ts +7 -7
  14. package/s/dom/attrs/attrs.ts +6 -6
  15. package/s/dom/attrs/parts/attr-fns.ts +64 -34
  16. package/s/dom/attrs/parts/attr-proxies.ts +10 -10
  17. package/s/dom/attrs/parts/attr-spec.ts +7 -7
  18. package/s/dom/dom.ts +19 -57
  19. package/s/dom/index.ts +4 -0
  20. package/s/dom/parts/dom-scope.ts +46 -0
  21. package/s/dom/parts/el.ts +14 -0
  22. package/s/dom/parts/elmer.ts +38 -0
  23. package/s/dom/parts/eve.ts +24 -0
  24. package/s/dom/parts/mk.ts +9 -0
  25. package/s/dom/parts/queries.ts +26 -0
  26. package/s/dom/types.ts +5 -0
  27. package/s/index.html.ts +4 -4
  28. package/s/index.ts +7 -17
  29. package/s/loaders/index.barrel.ts +10 -0
  30. package/s/loaders/index.ts +4 -0
  31. package/s/loaders/make.ts +14 -0
  32. package/s/loaders/mock.ts +11 -0
  33. package/s/{ops/loaders → loaders}/parts/anims.ts +1 -1
  34. package/s/{ops/loaders → loaders}/parts/ascii-anim.ts +6 -5
  35. package/s/{ops/loaders → loaders}/parts/error-display.ts +2 -2
  36. package/s/loaders/types.ts +6 -0
  37. package/s/loot/index.barrel.ts +5 -0
  38. package/s/loot/index.ts +2 -3
  39. package/s/ops/index.ts +5 -0
  40. package/s/ops/op.ts +1 -0
  41. package/s/spa/index.barrel.ts +6 -0
  42. package/s/spa/index.ts +4 -0
  43. package/s/spa/plumbing/braces.ts +76 -0
  44. package/s/spa/plumbing/primitives.ts +85 -0
  45. package/s/spa/plumbing/router-core.ts +49 -0
  46. package/s/spa/plumbing/types.ts +45 -0
  47. package/s/spa/router.ts +49 -0
  48. package/s/spa/spa.test.ts +91 -0
  49. package/s/tests.test.ts +4 -1
  50. package/s/view/index.ts +7 -0
  51. package/s/view/types.ts +39 -0
  52. package/s/view/utils/contextualize.ts +45 -0
  53. package/s/view/utils/make-component.ts +34 -0
  54. package/s/view/utils/make-view.ts +48 -0
  55. package/s/view/utils/parts/capsule.ts +67 -0
  56. package/s/view/utils/parts/chain.ts +40 -0
  57. package/s/view/utils/parts/context.ts +11 -0
  58. package/s/view/utils/parts/directive.ts +29 -0
  59. package/s/view/utils/parts/sly-view.ts +15 -0
  60. package/s/view/view.ts +24 -0
  61. package/x/base/css-reset.js.map +1 -0
  62. package/x/base/element.d.ts +19 -0
  63. package/x/{views/base-element.js → base/element.js} +14 -6
  64. package/x/base/element.js.map +1 -0
  65. package/x/base/index.d.ts +4 -0
  66. package/x/base/index.js +5 -0
  67. package/x/base/index.js.map +1 -0
  68. package/x/{views → base}/use.d.ts +6 -2
  69. package/x/{views → base}/use.js +12 -4
  70. package/x/base/use.js.map +1 -0
  71. package/x/base/utils/apply-styles.js.map +1 -0
  72. package/x/base/utils/attr-watcher.js.map +1 -0
  73. package/x/base/utils/mounts.js.map +1 -0
  74. package/x/{views → base}/utils/reactor.d.ts +0 -1
  75. package/x/{views → base}/utils/reactor.js +10 -3
  76. package/x/base/utils/reactor.js.map +1 -0
  77. package/x/base/utils/states.d.ts +13 -0
  78. package/x/base/utils/states.js +41 -0
  79. package/x/base/utils/states.js.map +1 -0
  80. package/x/base/utils/use-attrs.d.ts +11 -0
  81. package/x/base/utils/use-attrs.js +18 -0
  82. package/x/base/utils/use-attrs.js.map +1 -0
  83. package/x/demo/demo.bundle.js +6 -16
  84. package/x/demo/demo.bundle.js.map +1 -1
  85. package/x/demo/demo.bundle.min.js +20 -30
  86. package/x/demo/demo.bundle.min.js.map +4 -4
  87. package/x/demo/views/counter.d.ts +370 -3
  88. package/x/demo/views/counter.js +14 -23
  89. package/x/demo/views/counter.js.map +1 -1
  90. package/x/demo/views/demo.d.ts +4 -1
  91. package/x/demo/views/demo.js +9 -13
  92. package/x/demo/views/demo.js.map +1 -1
  93. package/x/demo/views/{incredi.d.ts → fastcount.d.ts} +3 -3
  94. package/x/demo/views/{incredi.js → fastcount.js} +5 -5
  95. package/x/demo/views/fastcount.js.map +1 -0
  96. package/x/demo/views/loaders.js +6 -6
  97. package/x/demo/views/loaders.js.map +1 -1
  98. package/x/dom/attrs/attrs.d.ts +6 -3
  99. package/x/dom/attrs/attrs.js +6 -6
  100. package/x/dom/attrs/attrs.js.map +1 -1
  101. package/x/dom/attrs/parts/attr-fns.d.ts +15 -12
  102. package/x/dom/attrs/parts/attr-fns.js +60 -38
  103. package/x/dom/attrs/parts/attr-fns.js.map +1 -1
  104. package/x/dom/attrs/parts/attr-proxies.d.ts +3 -3
  105. package/x/dom/attrs/parts/attr-proxies.js +10 -10
  106. package/x/dom/attrs/parts/attr-proxies.js.map +1 -1
  107. package/x/dom/attrs/parts/attr-spec.js +7 -7
  108. package/x/dom/attrs/parts/attr-spec.js.map +1 -1
  109. package/x/dom/dom.d.ts +14 -26
  110. package/x/dom/dom.js +18 -44
  111. package/x/dom/dom.js.map +1 -1
  112. package/x/dom/index.d.ts +2 -0
  113. package/x/dom/index.js +3 -0
  114. package/x/dom/index.js.map +1 -0
  115. package/x/dom/parts/dom-scope.d.ts +15 -0
  116. package/x/dom/parts/dom-scope.js +35 -0
  117. package/x/dom/parts/dom-scope.js.map +1 -0
  118. package/x/dom/parts/el.d.ts +2 -0
  119. package/x/dom/parts/el.js +7 -0
  120. package/x/dom/parts/el.js.map +1 -0
  121. package/x/dom/parts/elmer.d.ts +11 -0
  122. package/x/dom/parts/elmer.js +32 -0
  123. package/x/dom/parts/elmer.js.map +1 -0
  124. package/x/dom/parts/eve.d.ts +7 -0
  125. package/x/dom/parts/eve.js +16 -0
  126. package/x/dom/parts/eve.js.map +1 -0
  127. package/x/dom/parts/mk.d.ts +2 -0
  128. package/x/dom/parts/mk.js +7 -0
  129. package/x/dom/parts/mk.js.map +1 -0
  130. package/x/dom/parts/queries.d.ts +4 -0
  131. package/x/dom/parts/queries.js +13 -0
  132. package/x/dom/parts/queries.js.map +1 -0
  133. package/x/dom/types.d.ts +3 -0
  134. package/x/index.d.ts +7 -14
  135. package/x/index.html +6 -6
  136. package/x/index.html.js +4 -4
  137. package/x/index.js +7 -14
  138. package/x/index.js.map +1 -1
  139. package/x/loaders/index.barrel.d.ts +7 -0
  140. package/x/loaders/index.barrel.js +7 -0
  141. package/x/loaders/index.barrel.js.map +1 -0
  142. package/x/loaders/index.d.ts +2 -0
  143. package/x/loaders/index.js +2 -0
  144. package/x/loaders/index.js.map +1 -0
  145. package/x/loaders/make.d.ts +3 -0
  146. package/x/loaders/make.js +6 -0
  147. package/x/loaders/make.js.map +1 -0
  148. package/x/loaders/mock.d.ts +2 -0
  149. package/x/loaders/mock.js +8 -0
  150. package/x/loaders/mock.js.map +1 -0
  151. package/x/{ops/loaders → loaders}/parts/anims.d.ts +1 -1
  152. package/x/loaders/parts/anims.js.map +1 -0
  153. package/x/{ops/loaders → loaders}/parts/ascii-anim.d.ts +2 -2
  154. package/x/{ops/loaders → loaders}/parts/ascii-anim.js +4 -4
  155. package/x/loaders/parts/ascii-anim.js.map +1 -0
  156. package/x/loaders/parts/error-display.d.ts +1 -0
  157. package/x/{ops/loaders → loaders}/parts/error-display.js +2 -2
  158. package/x/loaders/parts/error-display.js.map +1 -0
  159. package/x/loaders/types.d.ts +3 -0
  160. package/x/loaders/types.js.map +1 -0
  161. package/x/loot/index.barrel.d.ts +3 -0
  162. package/x/loot/index.barrel.js +4 -0
  163. package/x/loot/index.barrel.js.map +1 -0
  164. package/x/loot/index.d.ts +2 -3
  165. package/x/loot/index.js +1 -3
  166. package/x/loot/index.js.map +1 -1
  167. package/x/ops/index.d.ts +3 -0
  168. package/x/ops/index.js +4 -0
  169. package/x/ops/index.js.map +1 -0
  170. package/x/ops/op.js +1 -0
  171. package/x/ops/op.js.map +1 -1
  172. package/x/spa/index.barrel.d.ts +4 -0
  173. package/x/spa/index.barrel.js +3 -0
  174. package/x/spa/index.barrel.js.map +1 -0
  175. package/x/spa/index.d.ts +2 -0
  176. package/x/spa/index.js +2 -0
  177. package/x/spa/index.js.map +1 -0
  178. package/x/spa/plumbing/braces.d.ts +12 -0
  179. package/x/spa/plumbing/braces.js +55 -0
  180. package/x/spa/plumbing/braces.js.map +1 -0
  181. package/x/spa/plumbing/primitives.d.ts +22 -0
  182. package/x/spa/plumbing/primitives.js +65 -0
  183. package/x/spa/plumbing/primitives.js.map +1 -0
  184. package/x/spa/plumbing/router-core.d.ts +13 -0
  185. package/x/spa/plumbing/router-core.js +38 -0
  186. package/x/spa/plumbing/router-core.js.map +1 -0
  187. package/x/spa/plumbing/types.d.ts +35 -0
  188. package/x/spa/plumbing/types.js +2 -0
  189. package/x/spa/plumbing/types.js.map +1 -0
  190. package/x/spa/router.d.ts +13 -0
  191. package/x/spa/router.js +39 -0
  192. package/x/spa/router.js.map +1 -0
  193. package/x/spa/spa.test.d.ts +15 -0
  194. package/x/spa/spa.test.js +78 -0
  195. package/x/spa/spa.test.js.map +1 -0
  196. package/x/tests.test.js +4 -1
  197. package/x/tests.test.js.map +1 -1
  198. package/x/view/index.d.ts +5 -0
  199. package/x/view/index.js +6 -0
  200. package/x/view/index.js.map +1 -0
  201. package/x/view/types.d.ts +21 -0
  202. package/x/view/types.js +2 -0
  203. package/x/{views → view}/types.js.map +1 -1
  204. package/x/view/utils/contextualize.d.ts +13 -0
  205. package/x/view/utils/contextualize.js +18 -0
  206. package/x/view/utils/contextualize.js.map +1 -0
  207. package/x/view/utils/make-component.d.ts +5 -0
  208. package/x/view/utils/make-component.js +17 -0
  209. package/x/view/utils/make-component.js.map +1 -0
  210. package/x/view/utils/make-view.d.ts +2 -0
  211. package/x/view/utils/make-view.js +24 -0
  212. package/x/view/utils/make-view.js.map +1 -0
  213. package/x/view/utils/parts/capsule.d.ts +13 -0
  214. package/x/view/utils/parts/capsule.js +49 -0
  215. package/x/view/utils/parts/capsule.js.map +1 -0
  216. package/x/view/utils/parts/chain.d.ts +13 -0
  217. package/x/view/utils/parts/chain.js +26 -0
  218. package/x/view/utils/parts/chain.js.map +1 -0
  219. package/x/view/utils/parts/context.d.ts +9 -0
  220. package/x/view/utils/parts/context.js +10 -0
  221. package/x/view/utils/parts/context.js.map +1 -0
  222. package/x/view/utils/parts/directive.d.ts +5 -0
  223. package/x/view/utils/parts/directive.js +18 -0
  224. package/x/view/utils/parts/directive.js.map +1 -0
  225. package/x/view/utils/parts/sly-view.d.ts +5 -0
  226. package/x/view/utils/parts/sly-view.js +13 -0
  227. package/x/view/utils/parts/sly-view.js.map +1 -0
  228. package/x/view/view.d.ts +11 -0
  229. package/x/view/view.js +15 -0
  230. package/x/view/view.js.map +1 -0
  231. package/s/demo/views/divine.ts +0 -22
  232. package/s/ops/loaders/make-loader.ts +0 -18
  233. package/s/views/types.ts +0 -49
  234. package/s/views/utils/apply-attrs.ts +0 -33
  235. package/s/views/view.ts +0 -185
  236. package/x/demo/views/divine.d.ts +0 -8
  237. package/x/demo/views/divine.js +0 -19
  238. package/x/demo/views/divine.js.map +0 -1
  239. package/x/demo/views/incredi.js.map +0 -1
  240. package/x/ops/loaders/make-loader.d.ts +0 -5
  241. package/x/ops/loaders/make-loader.js +0 -7
  242. package/x/ops/loaders/make-loader.js.map +0 -1
  243. package/x/ops/loaders/parts/anims.js.map +0 -1
  244. package/x/ops/loaders/parts/ascii-anim.js.map +0 -1
  245. package/x/ops/loaders/parts/error-display.d.ts +0 -1
  246. package/x/ops/loaders/parts/error-display.js.map +0 -1
  247. package/x/views/base-element.d.ts +0 -14
  248. package/x/views/base-element.js.map +0 -1
  249. package/x/views/css-reset.js.map +0 -1
  250. package/x/views/types.d.ts +0 -36
  251. package/x/views/use.js.map +0 -1
  252. package/x/views/utils/apply-attrs.d.ts +0 -2
  253. package/x/views/utils/apply-attrs.js +0 -21
  254. package/x/views/utils/apply-attrs.js.map +0 -1
  255. package/x/views/utils/apply-styles.js.map +0 -1
  256. package/x/views/utils/attr-watcher.js.map +0 -1
  257. package/x/views/utils/mounts.js.map +0 -1
  258. package/x/views/utils/reactor.js.map +0 -1
  259. package/x/views/view.d.ts +0 -13
  260. package/x/views/view.js +0 -145
  261. package/x/views/view.js.map +0 -1
  262. /package/s/{views → base}/css-reset.ts +0 -0
  263. /package/s/{views → base}/utils/apply-styles.ts +0 -0
  264. /package/s/{views → base}/utils/attr-watcher.ts +0 -0
  265. /package/s/{views → base}/utils/mounts.ts +0 -0
  266. /package/x/{views → base}/css-reset.d.ts +0 -0
  267. /package/x/{views → base}/css-reset.js +0 -0
  268. /package/x/{views → base}/utils/apply-styles.d.ts +0 -0
  269. /package/x/{views → base}/utils/apply-styles.js +0 -0
  270. /package/x/{views → base}/utils/attr-watcher.d.ts +0 -0
  271. /package/x/{views → base}/utils/attr-watcher.js +0 -0
  272. /package/x/{views → base}/utils/mounts.d.ts +0 -0
  273. /package/x/{views → base}/utils/mounts.js +0 -0
  274. /package/x/{ops/loaders → loaders}/parts/anims.js +0 -0
  275. /package/x/{views → loaders}/types.js +0 -0
@@ -1,6 +1,6 @@
1
1
 
2
+ import {attrGet, attrSet} from "./attr-fns.js"
2
3
  import {AttrSpec, AttrTypes} from "../../types.js"
3
- import {attrFns} from "./attr-fns.js"
4
4
 
5
5
  /** specify available html attributes and their types and create a proxy accessor */
6
6
  export const attrSpec = <A extends AttrSpec>(
@@ -10,18 +10,18 @@ export const attrSpec = <A extends AttrSpec>(
10
10
 
11
11
  get: (_target, key: string) => {
12
12
  switch (spec[key]) {
13
- case String: return attrFns.get.string(e, key)
14
- case Number: return attrFns.get.number(e, key)
15
- case Boolean: return attrFns.get.boolean(e, key)
13
+ case String: return attrGet.string(e, key)
14
+ case Number: return attrGet.number(e, key)
15
+ case Boolean: return attrGet.boolean(e, key)
16
16
  default: throw new Error(`invalid attribute type for "${key}"`)
17
17
  }
18
18
  },
19
19
 
20
20
  set: (_target, key: string, value: any) => {
21
21
  switch (spec[key]) {
22
- case String: return attrFns.set.string(e, key, value)
23
- case Number: return attrFns.set.number(e, key, value)
24
- case Boolean: return attrFns.set.boolean(e, key, value)
22
+ case String: return attrSet.string(e, key, value)
23
+ case Number: return attrSet.number(e, key, value)
24
+ case Boolean: return attrSet.boolean(e, key, value)
25
25
  default: throw new Error(`invalid attribute type for "${key}"`)
26
26
  }
27
27
  },
package/s/dom/dom.ts CHANGED
@@ -1,70 +1,32 @@
1
1
 
2
2
  import {render} from "lit"
3
- import {AttrSpec} from "./types.js"
3
+ import {el} from "./parts/el.js"
4
+ import {mk} from "./parts/mk.js"
5
+ import {eve} from "./parts/eve.js"
4
6
  import {attrs} from "./attrs/attrs.js"
5
- import {Content} from "../views/types.js"
7
+ import {elmer} from "./parts/elmer.js"
8
+ import {Content} from "../view/types.js"
9
+ import {Dom} from "./parts/dom-scope.js"
6
10
  import {register} from "./parts/register.js"
11
+ import {Queryable, Renderable} from "./types.js"
12
+ import {queryAll, queryMaybe, queryRequire} from "./parts/queries.js"
7
13
 
8
- export type Renderable = HTMLElement | ShadowRoot | DocumentFragment
9
- export type Queryable = HTMLElement | ShadowRoot | Element | Document | DocumentFragment
10
-
11
- function require<E extends Element>(
12
- container: Queryable,
13
- selector: string,
14
- ) {
15
- const e = container.querySelector<E>(selector)
16
- if (!e) throw new Error(`element not found (${selector})`)
17
- return e
18
- }
19
-
20
- export class Dom<C extends Queryable> {
21
- constructor(public element: C) {}
22
-
23
- in<E extends HTMLElement>(selectorOrElement: string | E) {
24
- return new Dom<E>(
25
- (typeof selectorOrElement === "string")
26
- ? require(this.element, selectorOrElement) as E
27
- : selectorOrElement
28
- )
29
- }
30
-
31
- require<E extends Element = HTMLElement>(selector: string) {
32
- const e = this.element.querySelector<E>(selector)
33
- if (!e) throw new Error(`element not found (${selector})`)
34
- return e
35
- }
36
-
37
- maybe<E extends Element = HTMLElement>(selector: string) {
38
- return this.element.querySelector<E>(selector)
39
- }
40
-
41
- all<E extends Element = HTMLElement>(selector: string) {
42
- return Array.from(this.element.querySelectorAll<E>(selector))
43
- }
44
-
45
- render(...content: Content[]) {
46
- return render(content, this.element as Renderable)
47
- }
48
-
49
- attrs() {
50
- return attrs(this.element as HTMLElement)
51
- }
14
+ export function dom<E extends Element>(selector: string, container: Queryable = document): E {
15
+ return queryRequire<E>(selector, container)
52
16
  }
53
17
 
54
- export function dom<E extends Queryable>(selector: string): E
55
- export function dom<E extends Queryable>(element: E): Dom<E>
56
- export function dom<E extends Queryable>(selectorOrElement: string | E): E | Dom<E> {
57
- return (typeof selectorOrElement === "string")
58
- ? require(document, selectorOrElement) as E
59
- : new Dom(selectorOrElement)
18
+ dom.in = <E extends HTMLElement>(selectorOrElement: string | E, container: Queryable = document) => {
19
+ return new Dom(container).in(selectorOrElement)
60
20
  }
61
21
 
62
- const doc = new Dom(document)
63
- dom.in = doc.in.bind(doc)
64
- dom.require = doc.require.bind(doc)
65
- dom.maybe = doc.maybe.bind(doc)
66
- dom.all = doc.all.bind(doc)
22
+ dom.require = queryRequire
23
+ dom.maybe = queryMaybe
24
+ dom.all = queryAll
67
25
 
26
+ dom.el = el
27
+ dom.elmer = elmer
28
+ dom.mk = mk
29
+ dom.events = eve
68
30
  dom.attrs = attrs
69
31
  dom.register = register
70
32
  dom.render = (container: Renderable, ...content: Content[]) => {
package/s/dom/index.ts ADDED
@@ -0,0 +1,4 @@
1
+
2
+ export * from "./types.js"
3
+ export * from "./dom.js"
4
+
@@ -0,0 +1,46 @@
1
+
2
+ import {render} from "lit"
3
+ import {eve, EveSpec} from "./eve.js"
4
+ import {attrs} from "../attrs/attrs.js"
5
+ import {Content} from "../../view/types.js"
6
+ import {Attrs, Queryable, Renderable} from "../types.js"
7
+ import {queryAll, queryMaybe, queryRequire} from "./queries.js"
8
+
9
+ export class Dom<C extends Queryable> {
10
+ #attrs?: Attrs
11
+
12
+ constructor(public element: C) {}
13
+
14
+ in<E extends HTMLElement>(selectorOrElement: string | E) {
15
+ return new Dom<E>(
16
+ (typeof selectorOrElement === "string")
17
+ ? queryRequire(selectorOrElement, this.element) as E
18
+ : selectorOrElement
19
+ )
20
+ }
21
+
22
+ require<E extends Element = HTMLElement>(selector: string) {
23
+ return queryRequire<E>(selector, this.element)
24
+ }
25
+
26
+ maybe<E extends Element = HTMLElement>(selector: string) {
27
+ return queryMaybe<E>(selector, this.element)
28
+ }
29
+
30
+ all<E extends Element = HTMLElement>(selector: string) {
31
+ return queryAll<E>(selector, this.element)
32
+ }
33
+
34
+ render(...content: Content[]) {
35
+ return render(content, this.element as Renderable)
36
+ }
37
+
38
+ get attrs(): Attrs {
39
+ return this.#attrs ??= attrs(this.element as HTMLElement)
40
+ }
41
+
42
+ events(spec: EveSpec) {
43
+ return eve(this.element, spec)
44
+ }
45
+ }
46
+
@@ -0,0 +1,14 @@
1
+
2
+ import {AttrValue} from "../types.js"
3
+ import {attrSet} from "../attrs/parts/attr-fns.js"
4
+
5
+ export function el<E extends HTMLElement>(
6
+ tagName: string,
7
+ attrs: Record<string, AttrValue> = {},
8
+ ) {
9
+
10
+ const element = document.createElement(tagName) as E
11
+ attrSet.record(element, attrs)
12
+ return element
13
+ }
14
+
@@ -0,0 +1,38 @@
1
+
2
+ import {AttrValue} from "../types.js"
3
+ import {attrSet} from "../attrs/parts/attr-fns.js"
4
+
5
+ export function elmer<E extends HTMLElement = HTMLElement>(tagName: string) {
6
+ return new Elmer<E>(tagName)
7
+ }
8
+
9
+ export class Elmer<E extends HTMLElement = HTMLElement> {
10
+ #attrs = new Map<string, AttrValue>()
11
+ #children: (Node | string)[] = []
12
+
13
+ constructor(public tagName: string) {}
14
+
15
+ attr(key: string, value: AttrValue = true) {
16
+ this.#attrs.set(key, value)
17
+ return this
18
+ }
19
+
20
+ attrs(record: Record<string, AttrValue>) {
21
+ for (const [key, value] of Object.entries(record))
22
+ this.attr(key, value)
23
+ return this
24
+ }
25
+
26
+ children(...elements: (Node | string)[]) {
27
+ this.#children.push(...elements)
28
+ return this
29
+ }
30
+
31
+ done() {
32
+ const element = document.createElement(this.tagName)
33
+ attrSet.entries(element, this.#attrs)
34
+ element.append(...this.#children)
35
+ return element as E
36
+ }
37
+ }
38
+
@@ -0,0 +1,24 @@
1
+
2
+ export type EveFn = (event: any) => void
3
+ export type EveConfig = [options: AddEventListenerOptions, fn: EveFn]
4
+ export type EveHandler = EveFn | EveConfig
5
+ export type EveSpec = {[eventName: string]: EveHandler}
6
+
7
+ export function eve(target: EventTarget, events: EveSpec) {
8
+ let detachers: (() => void)[] = []
9
+
10
+ for (const [eventName, handler] of Object.entries(events)) {
11
+ if (typeof handler === "function") {
12
+ target.addEventListener(eventName, handler)
13
+ detachers.push(() => target.removeEventListener(eventName, handler))
14
+ }
15
+ else {
16
+ const [options, fn] = handler
17
+ target.addEventListener(eventName, fn, options)
18
+ detachers.push(() => target.removeEventListener(eventName, fn))
19
+ }
20
+ }
21
+
22
+ return () => detachers.forEach(d => d())
23
+ }
24
+
@@ -0,0 +1,9 @@
1
+
2
+ import {render, TemplateResult} from "lit"
3
+
4
+ export function mk<E extends Element = HTMLElement>(template: TemplateResult) {
5
+ const fragment = document.createDocumentFragment()
6
+ render(template, fragment)
7
+ return fragment.firstElementChild as E
8
+ }
9
+
@@ -0,0 +1,26 @@
1
+
2
+ import {Queryable} from "../types.js"
3
+
4
+ export function queryRequire<E extends Element>(
5
+ selector: string,
6
+ container: Queryable = document,
7
+ ) {
8
+ const e = container.querySelector<E>(selector)
9
+ if (!e) throw new Error(`element not found (${selector})`)
10
+ return e
11
+ }
12
+
13
+ export function queryMaybe<E extends Element>(
14
+ selector: string,
15
+ container: Queryable = document,
16
+ ) {
17
+ return container.querySelector<E>(selector)
18
+ }
19
+
20
+ export function queryAll<E extends Element>(
21
+ selector: string,
22
+ container: Queryable = document,
23
+ ) {
24
+ return Array.from(container.querySelectorAll<E>(selector))
25
+ }
26
+
package/s/dom/types.ts CHANGED
@@ -1,8 +1,13 @@
1
1
 
2
2
  import {attrs} from "./attrs/attrs.js"
3
3
 
4
+ export type Renderable = HTMLElement | ShadowRoot | DocumentFragment
5
+ export type Queryable = HTMLElement | ShadowRoot | Element | Document | DocumentFragment
6
+
4
7
  // attrs
5
8
 
9
+ export type AttrValue = string | boolean | number | undefined | null | void
10
+
6
11
  export type AttrKind = (
7
12
  | typeof String
8
13
  | typeof Number
package/s/index.html.ts CHANGED
@@ -29,10 +29,10 @@ export default ssg.page(import.meta.url, async orb => ({
29
29
  <h1>sly testing page</h1>
30
30
  <p><a href="https://github.com/e280/sly">github.com/e280/sly</a></p>
31
31
  <p class=lil>v${orb.packageVersion()}</p>
32
- <incredi-element></incredi-element>
33
- <divine-element></divine-element>
34
- <demo-counter initial="-1">component</demo-counter>
35
- <div class=demo></div>
32
+
33
+ <fastcount-element></fastcount-element>
34
+ <counter-component start=280 step=2>component</counter-component>
35
+ <demo-component></demo-component>
36
36
  `,
37
37
  }))
38
38
 
package/s/index.ts CHANGED
@@ -1,19 +1,9 @@
1
1
 
2
- export * from "./dom/types.js"
3
- export * from "./dom/dom.js"
4
-
5
- export * from "./ops/loaders/make-loader.js"
6
- export * from "./ops/loaders/parts/ascii-anim.js"
7
- export * from "./ops/loaders/parts/error-display.js"
8
- export * from "./ops/op.js"
9
- export * from "./ops/podium.js"
10
- export * from "./ops/types.js"
11
-
12
- export * as loot from "./loot/index.js"
13
-
14
- export * from "./views/base-element.js"
15
- export * from "./views/css-reset.js"
16
- export * from "./views/types.js"
17
- export * from "./views/use.js"
18
- export * from "./views/view.js"
2
+ export * from "./base/index.js"
3
+ export * from "./dom/index.js"
4
+ export * from "./loaders/index.js"
5
+ export * from "./loot/index.js"
6
+ export * from "./ops/index.js"
7
+ export * from "./spa/index.js"
8
+ export * from "./view/index.js"
19
9
 
@@ -0,0 +1,10 @@
1
+
2
+ export * as anims from "./parts/anims.js"
3
+ export type * from "./parts/anims.js"
4
+ export * from "./parts/ascii-anim.js"
5
+ export * from "./parts/error-display.js"
6
+ export * from "./make.js"
7
+ export * from "./mock.js"
8
+ export * from "./types.js"
9
+
10
+
@@ -0,0 +1,4 @@
1
+
2
+ export * as loaders from "./index.barrel.js"
3
+ export type * from "./index.barrel.js"
4
+
@@ -0,0 +1,14 @@
1
+
2
+ import {Loader} from "./types.js"
3
+ import {earth} from "./parts/anims.js"
4
+ import type {Content} from "../view/types.js"
5
+ import {ErrorDisplay} from "./parts/error-display.js"
6
+
7
+ export function make(
8
+ loading: () => Content = earth,
9
+ error: (error: any) => Content = (error: any) => ErrorDisplay(error),
10
+ ): Loader {
11
+
12
+ return (op, ready) => op.select({loading, ready, error})
13
+ }
14
+
@@ -0,0 +1,11 @@
1
+
2
+ import {Loader} from "./types.js"
3
+
4
+ export function mock(): Loader {
5
+ return (op, ready) => op.select({
6
+ ready,
7
+ loading: () => `[loading]`,
8
+ error: () => `[error]`,
9
+ })
10
+ }
11
+
@@ -1,6 +1,6 @@
1
1
 
2
2
  import {makeAsciiAnim} from "./ascii-anim.js"
3
- import {Content} from "../../../views/types.js"
3
+ import type {Content} from "../../view/types.js"
4
4
 
5
5
  const fast = 20
6
6
  const mid = 10
@@ -1,10 +1,10 @@
1
1
 
2
2
  import {css} from "lit"
3
- import {nap, repeat} from "@e280/stz"
3
+ import {nap, cycle} from "@e280/stz"
4
4
 
5
- import {view} from "../../../views/view.js"
6
- import {Content} from "../../../views/types.js"
7
- import {cssReset} from "../../../views/css-reset.js"
5
+ import {view} from "../../view/view.js"
6
+ import {Content} from "../../view/types.js"
7
+ import {cssReset} from "../../base/css-reset.js"
8
8
 
9
9
  export function makeAsciiAnim(hz: number, frames: string[]): () => Content {
10
10
  return () => AsciiAnim({hz, frames})
@@ -17,9 +17,10 @@ export const AsciiAnim = view(use => ({hz, frames}: {
17
17
 
18
18
  use.name("loading")
19
19
  use.styles(cssReset, style)
20
+
20
21
  const frame = use.signal(0)
21
22
 
22
- use.mount(() => repeat(async() => {
23
+ use.mount(() => cycle(async() => {
23
24
  await nap(1000 / hz)
24
25
  const next = frame.get() + 1
25
26
  frame.set(next >= frames.length ? 0 : next)
@@ -1,7 +1,7 @@
1
1
 
2
2
  import {css, html} from "lit"
3
- import {view} from "../../../views/view.js"
4
- import {cssReset} from "../../../views/css-reset.js"
3
+ import {view} from "../../view/view.js"
4
+ import {cssReset} from "../../base/css-reset.js"
5
5
 
6
6
  export const ErrorDisplay = view(use => (error: any) => {
7
7
  use.name("error")
@@ -0,0 +1,6 @@
1
+
2
+ import type {Op} from "../ops/op.js"
3
+ import type {Content} from "../view/types.js"
4
+
5
+ export type Loader = <V>(op: Op<V>, ready: (value: V) => Content) => Content
6
+
@@ -0,0 +1,5 @@
1
+
2
+ export * from "./drag-and-drops.js"
3
+ export * from "./drops.js"
4
+ export * from "./helpers.js"
5
+
package/s/loot/index.ts CHANGED
@@ -1,5 +1,4 @@
1
1
 
2
- export * from "./drag-and-drops.js"
3
- export * from "./drops.js"
4
- export * from "./helpers.js"
2
+ export * as loot from "./index.barrel.js"
3
+ export type * from "./index.barrel.js"
5
4
 
package/s/ops/index.ts ADDED
@@ -0,0 +1,5 @@
1
+
2
+ export * from "./op.js"
3
+ export * from "./podium.js"
4
+ export * from "./types.js"
5
+
package/s/ops/op.ts CHANGED
@@ -69,6 +69,7 @@ export class Op<V> {
69
69
  return value
70
70
  }
71
71
  catch (error) {
72
+ console.error(error)
72
73
  if (count === this.#count)
73
74
  await this.setError(error)
74
75
  }
@@ -0,0 +1,6 @@
1
+
2
+ export {route} from "./plumbing/braces.js"
3
+ export type {Navigable} from "./plumbing/primitives.js"
4
+ export {RouterOptions, Hasher, Route, Routes, Navigables, Params} from "./plumbing/types.js"
5
+ export {Router} from "./router.js"
6
+
package/s/spa/index.ts ADDED
@@ -0,0 +1,4 @@
1
+
2
+ export * as spa from "./index.barrel.js"
3
+ export type * from "./index.barrel.js"
4
+
@@ -0,0 +1,76 @@
1
+
2
+ import {Hasher, Route} from "./types.js"
3
+ import type {Content} from "../../view/types.js"
4
+
5
+ type ParamKeys<S extends string> =
6
+ S extends `${string}{${infer P}}${infer R}` ? (string & P) | ParamKeys<R> : never
7
+
8
+ type ParamsOf<S extends string> =
9
+ [ParamKeys<S>] extends [never] ? {} : { [K in ParamKeys<S>]: string }
10
+
11
+ type ParamsTuple<S extends string> =
12
+ keyof ParamsOf<S> extends never ? [] : [ParamsOf<S>]
13
+
14
+ export function hasher<S extends string>(spec: S): Hasher<ParamsTuple<S>> {
15
+ if (!spec.startsWith("#/"))
16
+ throw new Error(`hash route spec must start with "#/"`)
17
+
18
+ const specparts = spec.split("/")
19
+ const braceregex = /\{([^\}\/]+)\}/
20
+
21
+ function parse(hash: string): ParamsTuple<S> | null {
22
+ if (!hash.startsWith("#/"))
23
+ throw new Error(`hash must start with "#/"`)
24
+
25
+ const hashparts = hash.split("/")
26
+ const params: Record<string, string> = {}
27
+
28
+ if (hashparts.length !== specparts.length)
29
+ return null
30
+
31
+ for (const [index, specpart] of specparts.entries()) {
32
+ const hashpart = hashparts.at(index)
33
+ if (hashpart === undefined) return null
34
+ const bracematch = specpart.match(braceregex)
35
+ try {
36
+ if (bracematch) params[bracematch[1]] = decodeURIComponent(hashpart)
37
+ else if (hashpart !== specpart) return null
38
+ }
39
+ catch {
40
+ return null
41
+ }
42
+ }
43
+
44
+ return (Object.keys(params).length === 0)
45
+ ? ([] as ParamsTuple<S>)
46
+ : ([params as ParamsOf<S>] as ParamsTuple<S>)
47
+ }
48
+
49
+ function make(...[braces]: any[]): string {
50
+ const get = (param: string) => {
51
+ const p = param as any
52
+ if (p in braces) return braces[p]
53
+ else throw new Error(`missing param "${p}"`)
54
+ }
55
+ return specparts.map(specpart => {
56
+ const bracematch = specpart.match(braceregex)
57
+ return bracematch
58
+ ? encodeURIComponent(get(bracematch[1]))
59
+ : specpart
60
+ }).join("/")
61
+ }
62
+
63
+ return {parse, make}
64
+ }
65
+
66
+ export function route<S extends string>(
67
+ spec: S,
68
+ fn: (...params: ParamsTuple<S>) => Promise<Content>,
69
+ ): Route<ParamsTuple<S>> {
70
+
71
+ return {
72
+ hasher: hasher(spec),
73
+ fn,
74
+ }
75
+ }
76
+
@@ -0,0 +1,85 @@
1
+
2
+ import {ev, ob} from "@e280/stz"
3
+ import {Op} from "../../ops/op.js"
4
+ import {ResolvedRoute, Route, Params, Routes} from "./types.js"
5
+
6
+ export function eraseWindowHash() {
7
+ const {pathname, search} = window.location
8
+ history.replaceState(null, "", pathname + search)
9
+ }
10
+
11
+ export function normalizeHash(hash: string) {
12
+ const homeEquivalents = [/^$/, /^#$/, /^#\/$/]
13
+ return (homeEquivalents.some(regex => regex.test(hash)))
14
+ ? "#/"
15
+ : hash
16
+ }
17
+
18
+ export class HashNormalizer {
19
+ constructor(public location: Location) {}
20
+
21
+ get hash() {
22
+ const hash = normalizeHash(this.location.hash)
23
+ if (hash === "#/") eraseWindowHash()
24
+ return hash
25
+ }
26
+
27
+ set hash(hash: string) {
28
+ this.location.hash = hash
29
+ }
30
+ }
31
+
32
+ export class Navigable<P extends any[] = any[]> {
33
+ static all<R extends Routes>(
34
+ routes: R,
35
+ getRoute: () => Route | null,
36
+ navigate: (hash: string) => Promise<ResolvedRoute>,
37
+ ): {[K in keyof R]: Navigable<Params<R[K]>>} {
38
+
39
+ return ob(routes).map(route => new this(
40
+ route,
41
+ () => (getRoute() === route),
42
+ async(...params: any[]) => navigate(route.hasher.make(...params)),
43
+ )) as any
44
+ }
45
+
46
+ constructor(
47
+ public route: Route<P>,
48
+ private isActive: () => boolean,
49
+ public go: (...params: P) => Promise<ResolvedRoute<P>>,
50
+ ) {}
51
+
52
+ get active() {
53
+ return this.isActive()
54
+ }
55
+
56
+ hash(...params: P) {
57
+ return this.route.hasher.make(...params)
58
+ }
59
+ }
60
+
61
+ export function resolveRoute<R extends Routes>(
62
+ hash: string,
63
+ routes: R,
64
+ ): ResolvedRoute | null {
65
+
66
+ for (const key in routes) {
67
+ const route = routes[key]
68
+ const params = route.hasher.parse(hash)
69
+ if (params) {
70
+ return {
71
+ key,
72
+ route,
73
+ params,
74
+ op: Op.promise(route.fn(...params))
75
+ }
76
+ }
77
+ }
78
+
79
+ return null
80
+ }
81
+
82
+ export function onHashChange(fn: (event: HashChangeEvent) => void) {
83
+ return ev(window, {hashchange: fn})
84
+ }
85
+