@e280/sly 0.2.0-26 → 0.2.0-27

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 (70) hide show
  1. package/README.md +86 -21
  2. package/package.json +4 -4
  3. package/s/base/use.ts +5 -0
  4. package/s/demo/views/fastcount.ts +2 -2
  5. package/s/dom/attrs/attrs.ts +3 -3
  6. package/s/dom/attrs/parts/attr-fns.ts +64 -34
  7. package/s/dom/attrs/parts/attr-proxies.ts +7 -7
  8. package/s/dom/attrs/parts/attr-spec.ts +7 -7
  9. package/s/dom/dom.ts +15 -61
  10. package/s/dom/parts/dom-scope.ts +46 -0
  11. package/s/dom/parts/el.ts +4 -4
  12. package/s/dom/parts/elmer.ts +38 -0
  13. package/s/dom/parts/mk.ts +9 -0
  14. package/s/dom/parts/queries.ts +26 -0
  15. package/s/dom/types.ts +5 -0
  16. package/s/loaders/parts/ascii-anim.ts +2 -2
  17. package/s/view/types.ts +0 -1
  18. package/s/view/utils/parts/capsule.ts +2 -2
  19. package/s/view/utils/parts/chain.ts +3 -2
  20. package/s/view/utils/parts/context.ts +2 -1
  21. package/x/base/use.d.ts +2 -0
  22. package/x/base/use.js +4 -0
  23. package/x/base/use.js.map +1 -1
  24. package/x/demo/demo.bundle.min.js +15 -15
  25. package/x/demo/demo.bundle.min.js.map +4 -4
  26. package/x/demo/views/fastcount.js +2 -2
  27. package/x/demo/views/fastcount.js.map +1 -1
  28. package/x/dom/attrs/attrs.d.ts +3 -0
  29. package/x/dom/attrs/attrs.js +3 -3
  30. package/x/dom/attrs/attrs.js.map +1 -1
  31. package/x/dom/attrs/parts/attr-fns.d.ts +15 -12
  32. package/x/dom/attrs/parts/attr-fns.js +60 -38
  33. package/x/dom/attrs/parts/attr-fns.js.map +1 -1
  34. package/x/dom/attrs/parts/attr-proxies.js +7 -7
  35. package/x/dom/attrs/parts/attr-proxies.js.map +1 -1
  36. package/x/dom/attrs/parts/attr-spec.js +7 -7
  37. package/x/dom/attrs/parts/attr-spec.js.map +1 -1
  38. package/x/dom/dom.d.ts +11 -27
  39. package/x/dom/dom.js +15 -48
  40. package/x/dom/dom.js.map +1 -1
  41. package/x/dom/parts/dom-scope.d.ts +15 -0
  42. package/x/dom/parts/dom-scope.js +35 -0
  43. package/x/dom/parts/dom-scope.js.map +1 -0
  44. package/x/dom/parts/el.d.ts +2 -2
  45. package/x/dom/parts/el.js +3 -3
  46. package/x/dom/parts/el.js.map +1 -1
  47. package/x/dom/parts/elmer.d.ts +11 -0
  48. package/x/dom/parts/elmer.js +32 -0
  49. package/x/dom/parts/elmer.js.map +1 -0
  50. package/x/dom/parts/mk.d.ts +2 -0
  51. package/x/dom/parts/mk.js +7 -0
  52. package/x/dom/parts/mk.js.map +1 -0
  53. package/x/dom/parts/queries.d.ts +4 -0
  54. package/x/dom/parts/queries.js +13 -0
  55. package/x/dom/parts/queries.js.map +1 -0
  56. package/x/dom/types.d.ts +3 -0
  57. package/x/index.html +2 -2
  58. package/x/loaders/parts/ascii-anim.js +2 -2
  59. package/x/loaders/parts/ascii-anim.js.map +1 -1
  60. package/x/view/types.d.ts +0 -1
  61. package/x/view/utils/parts/capsule.js +2 -2
  62. package/x/view/utils/parts/capsule.js.map +1 -1
  63. package/x/view/utils/parts/chain.d.ts +3 -2
  64. package/x/view/utils/parts/chain.js.map +1 -1
  65. package/x/view/utils/parts/context.d.ts +2 -1
  66. package/x/view/utils/parts/context.js.map +1 -1
  67. package/s/view/utils/parts/set-attrs.ts +0 -33
  68. package/x/view/utils/parts/set-attrs.d.ts +0 -3
  69. package/x/view/utils/parts/set-attrs.js +0 -21
  70. package/x/view/utils/parts/set-attrs.js.map +0 -1
package/README.md CHANGED
@@ -4,8 +4,9 @@
4
4
  # 🦝 sly
5
5
  > *mischievous shadow views*
6
6
 
7
- [@e280](https://e280.org/)'s shiny new [lit](https://lit.dev/)-based frontend webdev library. *(sly replaces its predecessor, [slate](https://github.com/benevolent-games/slate))*
7
+ [@e280](https://e280.org/)'s new [lit](https://lit.dev/)-based frontend webdev library. *(sly replaces its predecessor, [slate](https://github.com/benevolent-games/slate))*
8
8
 
9
+ - **✨[shiny](https://shiny.e280.org/)✨** — our wip component library https://shiny.e280.org/
9
10
  - 🍋 [**#views**](#views) — shadow-dom'd, hooks-based, componentizable
10
11
  - 🪵 [**#base-element**](#base-element) — for a more classical experience
11
12
  - 🪄 [**#dom**](#dom) — the "it's not jquery" multitool
@@ -285,8 +286,15 @@ import {html, css} from "lit"
285
286
 
286
287
  v // 123
287
288
  ```
289
+ - **use.events** — attach event listeners to the element (auto-cleaned up)
290
+ ```ts
291
+ use.events({
292
+ keydown: (e: KeyboardEvent) => console.log("keydown", e.code),
293
+ keyup: (e: KeyboardEvent) => console.log("keyup", e.code),
294
+ })
295
+ ```
288
296
  - **use.attrs** — ergonomic typed html attribute access
289
- - `use.attrs` is a bit different than `dom.attrs`, just to properly memoize .spec and .on for the render fn
297
+ - `use.attrs` is a bit different than [#dom.attrs](#dom.attrs), just to properly memoize .spec and .on for the render fn
290
298
  - use.attrs.spec
291
299
  ```ts
292
300
  const attrs = use.attrs.spec({
@@ -338,14 +346,14 @@ import {html, css} from "lit"
338
346
  ```
339
347
 
340
348
  ### 🍋 "use" recipes
341
- - make a ticker — mount, repeat, and nap
349
+ - make a ticker — mount, cycle, and nap
342
350
  ```ts
343
- import {repeat, nap} from "@e280/stz"
351
+ import {cycle, nap} from "@e280/stz"
344
352
  ```
345
353
  ```ts
346
354
  const $seconds = use.signal(0)
347
355
 
348
- use.mount(() => repeat(async() => {
356
+ use.mount(() => cycle(async() => {
349
357
  await nap(1000)
350
358
  $seconds.value++
351
359
  }))
@@ -473,6 +481,11 @@ import {dom} from "@e280/sly"
473
481
  dom(".demo")
474
482
  // HTMLElement (or throws)
475
483
  ```
484
+ ```ts
485
+ // alias
486
+ dom.require(".demo")
487
+ // HTMLElement (or throws)
488
+ ```
476
489
  - `maybe` get an element
477
490
  ```ts
478
491
  dom.maybe(".demo")
@@ -483,39 +496,83 @@ import {dom} from "@e280/sly"
483
496
  dom.all(".demo ul li")
484
497
  // HTMLElement[]
485
498
  ```
486
- - scoped to an element
499
+
500
+ ### 🪄 dom.in scope
501
+ - make a scope
487
502
  ```ts
488
- dom(element).require("li")
489
- // HTMLElement (or throws)
503
+ dom.in(".demo") // selector
504
+ // Dom instance
490
505
  ```
491
506
  ```ts
492
- dom(element).maybe("li")
493
- // HTMLElement | undefined
507
+ dom.in(demoElement) // element
508
+ // Dom instance
494
509
  ```
510
+ - run queries in that scope
495
511
  ```ts
496
- dom(element).all("li")
497
- // HTMLElement[]
512
+ dom.in(demoElement).require(".button")
513
+ ```
514
+ ```ts
515
+ dom.in(demoElement).maybe(".button")
516
+ ```
517
+ ```ts
518
+ dom.in(demoElement).all("ol li")
498
519
  ```
499
520
 
500
521
  ### 🪄 dom utilities
501
- - `register` web components
522
+ - `dom.register` web components
502
523
  ```ts
503
524
  dom.register({MyComponent, AnotherCoolComponent})
504
525
  // <my-component>
505
526
  // <another-cool-component>
506
527
  ```
507
528
  - `dom.register` automatically dashes the tag names (`MyComponent` becomes `<my-component>`)
508
- - `render` content into an element
529
+ - `dom.render` content into an element
509
530
  ```ts
510
- dom(element).render(html`<p>hello world</p>`)
531
+ dom.render(element, html`<p>hello world</p>`)
511
532
  ```
512
533
  ```ts
513
534
  dom.in(".demo").render(html`<p>hello world</p>`)
514
535
  ```
536
+ - `dom.el` little element builder
515
537
  ```ts
516
- dom.render(element, html`<p>hello world</p>`)
538
+ const div = dom.el("div", {"data-whatever": 123, "data-active": true})
539
+ // <div data-whatever="123" data-active></div>
540
+ ```
541
+ - `dom.elmer` make an element with a fluent chain
542
+ ```ts
543
+ const div = dom.elmer("div")
544
+ .attr("data-whatever", 123)
545
+ .attr("data-active")
546
+ .children("hello world")
547
+ .done()
548
+ // HTMLElement
517
549
  ```
518
- - `attrs` <a id="dom.attrs"></a> to setup a type-happy html attribute helper
550
+ - `dom.mk` make an element with a lit template (returns the first)
551
+ ```ts
552
+ const div = dom.mk(html`
553
+ <div data-whatever="123" data-active>
554
+ hello world
555
+ </div>
556
+ `) // HTMLElement
557
+ ```
558
+ - `dom.events` <a id="dom.events"></a> to attach event listeners
559
+ ```ts
560
+ const detach = dom.events(element, {
561
+ keydown: (e: KeyboardEvent) => console.log("keydown", e.code),
562
+ keyup: (e: KeyboardEvent) => console.log("keyup", e.code),
563
+ })
564
+ ```
565
+ ```ts
566
+ const detach = dom.in(".demo").events({
567
+ keydown: (e: KeyboardEvent) => console.log("keydown", e.code),
568
+ keyup: (e: KeyboardEvent) => console.log("keyup", e.code),
569
+ })
570
+ ```
571
+ ```ts
572
+ // unattach those event listeners when you're done
573
+ detach()
574
+ ```
575
+ - `dom.attrs` <a id="dom.attrs"></a> to setup a type-happy html attribute helper
519
576
  ```ts
520
577
  const attrs = dom.attrs(element).spec({
521
578
  name: String,
@@ -524,6 +581,13 @@ import {dom} from "@e280/sly"
524
581
  })
525
582
  ```
526
583
  ```ts
584
+ const attrs = dom.in(".demo").attrs.spec({
585
+ name: String,
586
+ count: Number,
587
+ active: Boolean,
588
+ })
589
+ ```
590
+ ```ts
527
591
  attrs.name // "chase"
528
592
  attrs.count // 123
529
593
  attrs.active // true
@@ -537,11 +601,12 @@ import {dom} from "@e280/sly"
537
601
  attrs.name = undefined // removes the attr
538
602
  attrs.count = undefined // removes the attr
539
603
  ```
540
- or if you wanna be more loosey-goosy, skip the spec
604
+ or if you wanna be more loosey-goosey, skip the spec
541
605
  ```ts
542
- dom.attrs(element).strings.name = "pimsley"
543
- dom.attrs(element).numbers.count = 125
544
- dom.attrs(element).booleans.active = true
606
+ const a = dom.in(".demo").attrs
607
+ a.strings.name = "pimsley"
608
+ a.numbers.count = 125
609
+ a.booleans.active = true
545
610
  ```
546
611
 
547
612
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@e280/sly",
3
- "version": "0.2.0-26",
3
+ "version": "0.2.0-27",
4
4
  "description": "web shadow views",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -23,12 +23,12 @@
23
23
  "lit": "^3.3.1"
24
24
  },
25
25
  "dependencies": {
26
- "@e280/strata": "^0.2.0-14",
27
- "@e280/stz": "^0.2.9"
26
+ "@e280/strata": "^0.2.0",
27
+ "@e280/stz": "^0.2.10"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@e280/science": "^0.1.2",
31
- "@e280/scute": "^0.1.0",
31
+ "@e280/scute": "^0.1.1",
32
32
  "http-server": "^14.1.1",
33
33
  "npm-run-all": "^4.1.5",
34
34
  "typescript": "^5.9.3"
package/s/base/use.ts CHANGED
@@ -7,6 +7,7 @@ import {Op} from "../ops/op.js"
7
7
  import {Mounts} from "./utils/mounts.js"
8
8
  import {UseAttrs} from "./utils/use-attrs.js"
9
9
  import {applyStyles} from "./utils/apply-styles.js"
10
+ import { eve, EveSpec } from "../dom/parts/eve.js"
10
11
 
11
12
  export const _wrap = Symbol()
12
13
  export const _disconnect = Symbol()
@@ -90,6 +91,10 @@ export class Use {
90
91
  return this.life(() => [fn(), () => {}])
91
92
  }
92
93
 
94
+ events(spec: EveSpec) {
95
+ return this.mount(() => eve(this.element, spec))
96
+ }
97
+
93
98
  op = (() => {
94
99
  const that = this
95
100
  function op<V>(f: () => Promise<V>) {
@@ -1,6 +1,6 @@
1
1
 
2
2
  import {css, html} from "lit"
3
- import {nap, repeat} from "@e280/stz"
3
+ import {nap, cycle} from "@e280/stz"
4
4
 
5
5
  import {dom} from "../../dom/dom.js"
6
6
  import {Use} from "../../base/use.js"
@@ -16,7 +16,7 @@ export class FastcountElement extends BaseElement {
16
16
  const {value = 1} = this.attrs
17
17
  const $count = use.signal(0)
18
18
 
19
- use.mount(() => repeat(async() => {
19
+ use.mount(() => cycle(async() => {
20
20
  await nap(10)
21
21
  await $count($count() + 1)
22
22
  }))
@@ -1,9 +1,9 @@
1
1
 
2
2
  import {AttrSpec} from "../types.js"
3
3
  import {onAttrs} from "./parts/on-attrs.js"
4
- import {attrFns} from "./parts/attr-fns.js"
5
4
  import {attrSpec} from "./parts/attr-spec.js"
6
5
  import {AttrProxies} from "./parts/attr-proxies.js"
6
+ import {attrGet, attrSet} from "./parts/attr-fns.js"
7
7
 
8
8
  export function attrs(element: HTMLElement) {
9
9
  const proxies = new AttrProxies(element)
@@ -16,6 +16,6 @@ export function attrs(element: HTMLElement) {
16
16
  }
17
17
  }
18
18
 
19
- attrs.get = attrFns.get
20
- attrs.set = attrFns.set
19
+ attrs.get = attrGet
20
+ attrs.set = attrSet
21
21
 
@@ -1,38 +1,68 @@
1
1
 
2
- /** fns for getting and setting html attributes of various types */
3
- export const attrFns = {
4
- get: {
5
- string: (e: HTMLElement, key: string) => {
6
- return e.getAttribute(key) ?? undefined
7
- },
8
- number: (e: HTMLElement, key: string) => {
9
- const raw = e.getAttribute(key)
10
- return (raw === null || !raw)
11
- ? undefined
12
- : Number(raw)
13
- },
14
- boolean: (e: HTMLElement, key: string) => {
15
- const raw = e.getAttribute(key)
16
- return raw !== null
17
- },
18
- },
19
-
20
- set: {
21
- string: (e: HTMLElement, key: string, value: string | undefined) => {
22
- if (value === undefined) e.removeAttribute(key)
23
- else e.setAttribute(key, value)
24
- return true
25
- },
26
- number: (e: HTMLElement, key: string, value: number | undefined) => {
27
- if (value === undefined) e.removeAttribute(key)
28
- else e.setAttribute(key, value.toString())
29
- return true
30
- },
31
- boolean: (e: HTMLElement, key: string, value: boolean | undefined) => {
32
- if (value) e.setAttribute(key, "")
33
- else e.removeAttribute(key)
34
- return true
35
- },
2
+ import {AttrValue} from "../../types.js"
3
+
4
+ /** get html attributes */
5
+ export const attrGet = {
6
+ string: (e: HTMLElement, key: string) => {
7
+ return e.getAttribute(key) ?? undefined
8
+ },
9
+ number: (e: HTMLElement, key: string) => {
10
+ const raw = e.getAttribute(key)
11
+ return (raw === null || !raw)
12
+ ? undefined
13
+ : Number(raw)
14
+ },
15
+ boolean: (e: HTMLElement, key: string) => {
16
+ const raw = e.getAttribute(key)
17
+ return raw !== null
18
+ },
19
+ }
20
+
21
+ /** set html attributes */
22
+ export const attrSet = {
23
+ string: (e: HTMLElement, key: string, value: string | undefined) => {
24
+ if (value === undefined) e.removeAttribute(key)
25
+ else e.setAttribute(key, value)
26
+ return true
27
+ },
28
+ number: (e: HTMLElement, key: string, value: number | undefined) => {
29
+ if (value === undefined) e.removeAttribute(key)
30
+ else e.setAttribute(key, value.toString())
31
+ return true
32
+ },
33
+ boolean: (e: HTMLElement, key: string, value: boolean | undefined) => {
34
+ if (value) e.setAttribute(key, "")
35
+ else e.removeAttribute(key)
36
+ return true
37
+ },
38
+
39
+ any: (element: HTMLElement, key: string, value: AttrValue) => {
40
+ if (value === undefined || value === null)
41
+ element.removeAttribute(key)
42
+
43
+ else if (typeof value === "string")
44
+ element.setAttribute(key, value)
45
+
46
+ else if (typeof value === "number")
47
+ element.setAttribute(key, value.toString())
48
+
49
+ else if (typeof value === "boolean") {
50
+ if (value === true)
51
+ element.setAttribute(key, "")
52
+ else
53
+ element.removeAttribute(key)
54
+ }
55
+
56
+ else console.warn(`invalid attribute "${key}" type is "${typeof value}"`)
57
+ },
58
+
59
+ entries: (element: HTMLElement, entries: Iterable<[key: string, value: AttrValue]>) => {
60
+ for (const [key, value] of entries)
61
+ attrSet.any(element, key, value)
62
+ },
63
+
64
+ record: (element: HTMLElement, record: Record<string, AttrValue>) => {
65
+ return attrSet.entries(element, Object.entries(record))
36
66
  },
37
67
  }
38
68
 
@@ -1,5 +1,5 @@
1
1
 
2
- import {attrFns} from "./attr-fns.js"
2
+ import {attrGet, attrSet} from "./attr-fns.js"
3
3
 
4
4
  /** a typed proxy accessor for html attributes */
5
5
  export class AttrProxies {
@@ -7,28 +7,28 @@ export class AttrProxies {
7
7
 
8
8
  strings = new Proxy({}, {
9
9
  get: (_t, key: string) => (
10
- attrFns.get.string(this.element, key)
10
+ attrGet.string(this.element, key)
11
11
  ),
12
12
  set: (_t, key: string, value: string | undefined) => (
13
- attrFns.set.string(this.element, key, value)
13
+ attrSet.string(this.element, key, value)
14
14
  ),
15
15
  }) as Record<string, string | undefined>
16
16
 
17
17
  numbers = new Proxy({}, {
18
18
  get: (_t, key: string) => (
19
- attrFns.get.number(this.element, key)
19
+ attrGet.number(this.element, key)
20
20
  ),
21
21
  set: (_t, key: string, value: number | undefined) => (
22
- attrFns.set.number(this.element, key, value)
22
+ attrSet.number(this.element, key, value)
23
23
  ),
24
24
  }) as Record<string, number | undefined>
25
25
 
26
26
  booleans = new Proxy({}, {
27
27
  get: (_t, key: string) => (
28
- attrFns.get.boolean(this.element, key)
28
+ attrGet.boolean(this.element, key)
29
29
  ),
30
30
  set: (_t, key: string, value: boolean | undefined) => (
31
- attrFns.set.boolean(this.element, key, value)
31
+ attrSet.boolean(this.element, key, value)
32
32
  ),
33
33
  }) as Record<string, boolean | undefined>
34
34
  }
@@ -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,77 +1,31 @@
1
1
 
2
2
  import {render} from "lit"
3
3
  import {el} from "./parts/el.js"
4
- import {AttrSpec} from "./types.js"
4
+ import {mk} from "./parts/mk.js"
5
+ import {eve} from "./parts/eve.js"
5
6
  import {attrs} from "./attrs/attrs.js"
7
+ import {elmer} from "./parts/elmer.js"
6
8
  import {Content} from "../view/types.js"
7
- import {eve, EveSpec} from "./parts/eve.js"
9
+ import {Dom} from "./parts/dom-scope.js"
8
10
  import {register} from "./parts/register.js"
11
+ import {Queryable, Renderable} from "./types.js"
12
+ import {queryAll, queryMaybe, queryRequire} from "./parts/queries.js"
9
13
 
10
- export type Renderable = HTMLElement | ShadowRoot | DocumentFragment
11
- export type Queryable = HTMLElement | ShadowRoot | Element | Document | DocumentFragment
12
-
13
- function require<E extends Element>(
14
- container: Queryable,
15
- selector: string,
16
- ) {
17
- const e = container.querySelector<E>(selector)
18
- if (!e) throw new Error(`element not found (${selector})`)
19
- return e
20
- }
21
-
22
- export class Dom<C extends Queryable> {
23
- constructor(public element: C) {}
24
-
25
- in<E extends HTMLElement>(selectorOrElement: string | E) {
26
- return new Dom<E>(
27
- (typeof selectorOrElement === "string")
28
- ? require(this.element, selectorOrElement) as E
29
- : selectorOrElement
30
- )
31
- }
32
-
33
- require<E extends Element = HTMLElement>(selector: string) {
34
- const e = this.element.querySelector<E>(selector)
35
- if (!e) throw new Error(`element not found (${selector})`)
36
- return e
37
- }
38
-
39
- maybe<E extends Element = HTMLElement>(selector: string) {
40
- return this.element.querySelector<E>(selector)
41
- }
42
-
43
- all<E extends Element = HTMLElement>(selector: string) {
44
- return Array.from(this.element.querySelectorAll<E>(selector))
45
- }
46
-
47
- render(...content: Content[]) {
48
- return render(content, this.element as Renderable)
49
- }
50
-
51
- attrs() {
52
- return attrs(this.element as HTMLElement)
53
- }
54
-
55
- events(spec: EveSpec) {
56
- return eve(this.element, spec)
57
- }
14
+ export function dom<E extends Element>(selector: string, container: Queryable = document): E {
15
+ return queryRequire<E>(selector, container)
58
16
  }
59
17
 
60
- export function dom<E extends Queryable>(selector: string): E
61
- export function dom<E extends Queryable>(element: E): Dom<E>
62
- export function dom<E extends Queryable>(selectorOrElement: string | E): E | Dom<E> {
63
- return (typeof selectorOrElement === "string")
64
- ? require(document, selectorOrElement) as E
65
- : new Dom(selectorOrElement)
18
+ dom.in = <E extends HTMLElement>(selectorOrElement: string | E, container: Queryable = document) => {
19
+ return new Dom(container).in(selectorOrElement)
66
20
  }
67
21
 
68
- const doc = new Dom(document)
69
- dom.in = doc.in.bind(doc)
70
- dom.require = doc.require.bind(doc)
71
- dom.maybe = doc.maybe.bind(doc)
72
- dom.all = doc.all.bind(doc)
22
+ dom.require = queryRequire
23
+ dom.maybe = queryMaybe
24
+ dom.all = queryAll
73
25
 
74
26
  dom.el = el
27
+ dom.elmer = elmer
28
+ dom.mk = mk
75
29
  dom.events = eve
76
30
  dom.attrs = attrs
77
31
  dom.register = register
@@ -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
+
package/s/dom/parts/el.ts CHANGED
@@ -1,14 +1,14 @@
1
1
 
2
- import {AttrValue} from "../../view/types.js"
3
- import {setAttrs} from "../../view/utils/parts/set-attrs.js"
2
+ import {AttrValue} from "../types.js"
3
+ import {attrSet} from "../attrs/parts/attr-fns.js"
4
4
 
5
5
  export function el<E extends HTMLElement>(
6
6
  tagName: string,
7
- attrs: Record<string, AttrValue>,
7
+ attrs: Record<string, AttrValue> = {},
8
8
  ) {
9
9
 
10
10
  const element = document.createElement(tagName) as E
11
- setAttrs(element, Object.entries(attrs))
11
+ attrSet.record(element, attrs)
12
12
  return element
13
13
  }
14
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,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
+