@e280/sly 0.2.0-4 → 0.2.0-6

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 (58) hide show
  1. package/README.md +181 -36
  2. package/package.json +1 -1
  3. package/s/demo/views/incredi.ts +2 -2
  4. package/s/dom/dom.ts +10 -1
  5. package/s/dom/register.ts +4 -1
  6. package/s/index.ts +2 -2
  7. package/s/loot/drag-and-drops.ts +82 -0
  8. package/s/loot/{drop.ts → drops.ts} +8 -17
  9. package/s/loot/helpers.ts +3 -3
  10. package/s/loot/index.ts +2 -2
  11. package/s/views/base-element.ts +1 -1
  12. package/s/views/use.ts +3 -2
  13. package/x/demo/demo.bundle.min.js +13 -13
  14. package/x/demo/demo.bundle.min.js.map +4 -4
  15. package/x/demo/views/incredi.d.ts +1 -1
  16. package/x/demo/views/incredi.js +2 -2
  17. package/x/demo/views/incredi.js.map +1 -1
  18. package/x/dom/attributes.js.map +1 -0
  19. package/x/dom/dom.d.ts +5 -1
  20. package/x/dom/dom.js +5 -0
  21. package/x/dom/dom.js.map +1 -1
  22. package/x/dom/register.d.ts +5 -1
  23. package/x/dom/register.js.map +1 -1
  24. package/x/index.d.ts +2 -2
  25. package/x/index.html +2 -2
  26. package/x/index.js +2 -2
  27. package/x/index.js.map +1 -1
  28. package/x/loot/drag-and-drops.d.ts +30 -0
  29. package/x/loot/drag-and-drops.js +63 -0
  30. package/x/loot/drag-and-drops.js.map +1 -0
  31. package/x/loot/{drop.d.ts → drops.d.ts} +3 -5
  32. package/x/loot/drops.js +25 -0
  33. package/x/loot/drops.js.map +1 -0
  34. package/x/loot/helpers.d.ts +3 -3
  35. package/x/loot/helpers.js +3 -3
  36. package/x/loot/helpers.js.map +1 -1
  37. package/x/loot/index.d.ts +2 -2
  38. package/x/loot/index.js +2 -2
  39. package/x/loot/index.js.map +1 -1
  40. package/x/views/base-element.js +1 -1
  41. package/x/views/base-element.js.map +1 -1
  42. package/x/views/use.d.ts +2 -2
  43. package/x/views/use.js +3 -2
  44. package/x/views/use.js.map +1 -1
  45. package/s/dom/types.ts +0 -8
  46. package/s/loot/drag-drop.ts +0 -76
  47. package/x/dom/types.d.ts +0 -7
  48. package/x/dom/types.js +0 -2
  49. package/x/dom/types.js.map +0 -1
  50. package/x/loot/drag-drop.d.ts +0 -29
  51. package/x/loot/drag-drop.js +0 -54
  52. package/x/loot/drag-drop.js.map +0 -1
  53. package/x/loot/drop.js +0 -32
  54. package/x/loot/drop.js.map +0 -1
  55. package/x/views/attributes.js.map +0 -1
  56. /package/s/{views → dom}/attributes.ts +0 -0
  57. /package/x/{views → dom}/attributes.d.ts +0 -0
  58. /package/x/{views → dom}/attributes.js +0 -0
package/README.md CHANGED
@@ -4,14 +4,14 @@
4
4
  # 🦝 sly
5
5
  > *mischievous shadow views*
6
6
 
7
- [@e280](https://e280.org/)'s shiny, tasteful, incredible new [lit](https://lit.dev/)-based toolkit for frontend web developers.
8
- sly replaces its predecessor, [slate](https://github.com/benevolent-games/slate).
7
+ [@e280](https://e280.org/)'s shiny new [lit](https://lit.dev/)-based frontend lib for webdevs. *(sly replaces its predecessor, [slate](https://github.com/benevolent-games/slate))*
9
8
 
10
- - 🍋 **views** — hooks-based, shadow-dom'd, componentizable
11
- - 🪄 **dom** — the "it's not jquery" multitool
12
- - 🪵 **base element** — for a more classical experience
13
- - 🫛 **ops** — tools for async operations and loading spinners
14
- - 🧪 **testing page** — https://sly.e280.org/
9
+ - 🍋 [**views**](#views) — hooks-based, shadow-dom'd, componentizable
10
+ - 🪵 [**base element**](#base-element)for a more classical experience
11
+ - 🪄 [**dom**](#dom)the "it's not jquery" multitool
12
+ - 🫛 [**ops**](#ops) — tools for async operations and loading spinners
13
+ - 🪙 [**loot**](#loot)drag-and-drop facilities
14
+ - 🧪 testing page — https://sly.e280.org/
15
15
 
16
16
 
17
17
 
@@ -24,14 +24,15 @@ npm install @e280/sly lit
24
24
  ```
25
25
 
26
26
  > [!NOTE]
27
- > - 🔥 [lit](https://lit.dev/) for html rendering
27
+ > - 🔥 [lit](https://lit.dev/), for html rendering
28
28
  > - ⛏️ [@e280/strata](https://github.com/e280/strata), for state management (signals, state trees)
29
- > - 🏂 [@e280/stz](https://github.com/e280/stz) is our ts standard library
30
- > - 🐢 [scute](https://github.com/e280/scute) is our buildy-bundly-buddy
29
+ > - 🏂 [@e280/stz](https://github.com/e280/stz), our ts standard library
30
+ > - 🐢 [@e280/scute](https://github.com/e280/scute), our buildy-bundly-buddy
31
31
 
32
32
 
33
33
 
34
34
  <br/><br/>
35
+ <a id="views"></a>
35
36
 
36
37
  ## 🦝🍋 sly views
37
38
  > *views are the crown jewel of sly.. shadow-dom'd.. hooks-based.. "ergonomics"..*
@@ -46,11 +47,10 @@ view(use => () => html`<p>hello world</p>`)
46
47
  - views automatically rerender whenever any [strata-compatible](https://github.com/e280/strata) state changes
47
48
 
48
49
  ### 🍋 view example
49
- - **import stuff**
50
- ```ts
51
- import {view, dom} from "@e280/sly"
52
- import {html, css} from "lit"
53
- ```
50
+ ```ts
51
+ import {view, dom} from "@e280/sly"
52
+ import {html, css} from "lit"
53
+ ```
54
54
  - **declare a view**
55
55
  ```ts
56
56
  export const CounterView = view(use => (start: number) => {
@@ -198,7 +198,8 @@ view(use => () => html`<p>hello world</p>`)
198
198
 
199
199
  v // 123
200
200
  ```
201
- - **use.attrs** — ergonomic typed html attribute access
201
+ - **use.attrs** — ergonomic typed html attribute access
202
+ *(see [dom.attrs](#dom.attrs) for more details)*
202
203
  ```ts
203
204
  const attrs = use.attrs({
204
205
  name: String,
@@ -211,14 +212,6 @@ view(use => () => html`<p>hello world</p>`)
211
212
  attrs.count // 123
212
213
  attrs.active // true
213
214
  ```
214
- ```ts
215
- attrs.name = "zenky"
216
- attrs.count = 124
217
- attrs.active = false // removes html attr
218
- ```
219
- ```ts
220
- attrs.name = undefined // removes the attr
221
- ```
222
215
  - **use.render** — rerender the view (debounced)
223
216
  ```ts
224
217
  use.render()
@@ -269,22 +262,23 @@ view(use => () => html`<p>hello world</p>`)
269
262
 
270
263
 
271
264
  <br/><br/>
265
+ <a id="base-element"></a>
272
266
 
273
267
  ## 🦝🪵 sly base element
274
268
  > *the classic experience*
275
269
 
276
- so views are great, and they can be converted into components..
277
- ..but views have one drawback — you can't actually expose properties on the element instance itself.
270
+ ```ts
271
+ import {BaseElement, Use, dom} from "@e280/sly"
272
+ import {html, css} from "lit"
273
+ ```
274
+
275
+ `BaseElement` is a class-based approach to create a custom element web component.
278
276
 
279
- that's where `BaseElement` comes in.
280
- it's a proper class-based element, but it lets you have the same `use` hooks that views enjoy.
277
+ it lets you expose js properties on the element instance, which helps you setup a better developer experience for people interacting with your element through the dom.
278
+
279
+ base element enjoys the same `use` hooks as views.
281
280
 
282
281
  ### 🪵 base element setup
283
- - **import stuff**
284
- ```ts
285
- import {BaseElement, Use, attributes, dom} from "@e280/sly"
286
- import {html, css} from "lit"
287
- ```
288
282
  - **declare your element class**
289
283
  ```ts
290
284
  export class MyElement extends BaseElement {
@@ -294,8 +288,8 @@ it's a proper class-based element, but it lets you have the same `use` hooks tha
294
288
  start = 10
295
289
 
296
290
  // custom attributes
297
- attrs = attributes(this, {
298
- multiply: Number
291
+ attrs = dom.attrs(this, {
292
+ multiply: Number,
299
293
  })
300
294
 
301
295
  // custom methods
@@ -338,7 +332,7 @@ it's a proper class-based element, but it lets you have the same `use` hooks tha
338
332
  myElement.start = 100
339
333
 
340
334
  // html attributes
341
- myElement.attr.multiply = 2
335
+ myElement.attrs.multiply = 2
342
336
 
343
337
  // methods
344
338
  myElement.hello()
@@ -348,6 +342,7 @@ it's a proper class-based element, but it lets you have the same `use` hooks tha
348
342
 
349
343
 
350
344
  <br/><br/>
345
+ <a id="dom"></a>
351
346
 
352
347
  ## 🦝🪄 sly dom
353
348
  > *the "it's not jquery!" multitool*
@@ -403,10 +398,33 @@ import {dom} from "@e280/sly"
403
398
  ```ts
404
399
  dom.render(element, html`<p>hello world</p>`)
405
400
  ```
401
+ - `attrs` <a id="dom.attrs"></a> to setup a type-happy html attribute helper
402
+ ```ts
403
+ const attrs = dom.attrs({
404
+ name: String,
405
+ count: Number,
406
+ active: Boolean,
407
+ })
408
+ ```
409
+ ```ts
410
+ attrs.name // "chase"
411
+ attrs.count // 123
412
+ attrs.active // true
413
+ ```
414
+ ```ts
415
+ attrs.name = "zenky"
416
+ attrs.count = 124
417
+ attrs.active = false // removes html attr
418
+ ```
419
+ ```ts
420
+ attrs.name = undefined // removes the attr
421
+ attrs.count = undefined // removes the attr
422
+ ```
406
423
 
407
424
 
408
425
 
409
426
  <br/><br/>
427
+ <a id="ops"></a>
410
428
 
411
429
  ## 🦝🫛 sly ops
412
430
  > *tools for async operations and loading spinners*
@@ -536,8 +554,135 @@ import {Pod, podium, Op, makeLoader, anims} from "@e280/sly"
536
554
 
537
555
 
538
556
  <br/><br/>
557
+ <a id="loot"></a>
558
+
559
+ ## 🦝🪙 loot
560
+ > *drag-and-drop facilities*
561
+
562
+ ```ts
563
+ import {loot, view, dom} from "@e280/sly"
564
+ import {ev} from "@e280/stz"
565
+ ```
566
+
567
+ ### 🪙 `loot.Drops`
568
+ > *accept the user dropping stuff like files onto the page*
569
+ - **setup drops**
570
+ ```ts
571
+ const drops = new loot.Drops({
572
+ predicate: loot.hasFiles,
573
+ acceptDrop: event => {
574
+ const files = loot.files(event)
575
+ console.log("files dropped", files)
576
+ },
577
+ })
578
+ ```
579
+ - **attach event listeners to your dropzone,** one of these ways:
580
+ - **view example**
581
+ ```ts
582
+ view(() => () => html`
583
+ <div
584
+ ?data-indicator="${drops.$indicator()}"
585
+ @dragover="${drops.dragover}"
586
+ @dragleave="${drops.dragleave}"
587
+ @drop="${drops.drop}">
588
+ my dropzone
589
+ </div>
590
+ `)
591
+ ```
592
+ - **vanilla-js whole-page example**
593
+ ```ts
594
+ // attach listeners to the body
595
+ ev(document.body, {
596
+ dragover: drops.dragover,
597
+ dragleave: drops.dragleave,
598
+ drop: drops.drop,
599
+ })
600
+
601
+ // sly attribute handler for the body
602
+ const attrs = dom.attrs(document.body, {
603
+ "data-indicator": Boolean,
604
+ })
605
+
606
+ // sync the data-indicator attribute
607
+ drops.$indicator.on(bool => attrs["data-indicator"] = bool)
608
+ ```
609
+ - **flashy css indicator for the dropzone,** so the user knows your app is eager to accept the drop
610
+ ```css
611
+ [data-indicator] {
612
+ border: 0.5em dashed cyan;
613
+ }
614
+ ```
615
+
616
+ ### 🪙 `loot.DragAndDrops`
617
+ > *setup drag-and-drops between items within your page*
618
+ - **declare types for your draggy and droppy things**
619
+ ```ts
620
+ // money that can be picked up and dragged
621
+ type Money = {value: number}
622
+ // dnd will call this a "draggy"
623
+
624
+ // bag that money can be dropped into
625
+ type Bag = {id: number}
626
+ // dnd will call this a "droppy"
627
+ ```
628
+ - **make your dnd**
629
+ ```ts
630
+ const dnd = new loot.DragAndDrops<Money, Bag>({
631
+ acceptDrop: (event, money, bag) => {
632
+ console.log("drop!", {money, bag})
633
+ },
634
+ })
635
+ ```
636
+ - **attach dragzone listeners** (there can be many dragzones...)
637
+ ```ts
638
+ view(use => () => {
639
+ const money = use.once((): Money => ({value: 280}))
640
+ const dragzone = use.once(() => dnd.dragzone(() => money))
641
+
642
+ return html`
643
+ <div
644
+ draggable="${dragzone.draggable}"
645
+ @dragstart="${dragzone.dragstart}"
646
+ @dragend="${dragzone.dragend}">
647
+ money ${money.value}
648
+ </div>
649
+ `
650
+ })
651
+ ```
652
+ - **attach dropzone listeners** (there can be many dropzones...)
653
+ ```ts
654
+ view(use => () => {
655
+ const bag = use.once((): Bag => ({id: 1}))
656
+ const dropzone = use.once(() => dnd.dropzone(() => bag))
657
+ const indicator = !!(dnd.dragging && dnd.hovering === bag)
658
+
659
+ return html`
660
+ <div
661
+ ?data-indicator="${indicator}"
662
+ @dragenter="${dropzone.dragenter}"
663
+ @dragleave="${dropzone.dragleave}"
664
+ @dragover="${dropzone.dragover}"
665
+ @drop="${dropzone.drop}">
666
+ bag ${bag.id}
667
+ </div>
668
+ `
669
+ })
670
+ ```
671
+
672
+ ### 🪙 loot helpers
673
+ - **`loot.hasFiles(event)`** — return true if `DragEvent` contains any files (useful in `predicate`)
674
+ - **`loot.files(event)`** — returns an array of files in a drop's `DragEvent` (useful in `acceptDrop`)
675
+
676
+
677
+
678
+ <br/><br/>
679
+ <a id="e280"></a>
539
680
 
540
681
  ## 🦝🧑‍💻 sly is by e280
541
682
  reward us with github stars
542
683
  build with us at https://e280.org/ but only if you're cool
543
684
 
685
+
686
+
687
+ <br/><br/>
688
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@e280/sly",
3
- "version": "0.2.0-4",
3
+ "version": "0.2.0-6",
4
4
  "description": "web shadow views",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -2,13 +2,13 @@
2
2
  import {css, html} from "lit"
3
3
  import {nap, repeat} from "@e280/stz"
4
4
 
5
+ import {dom} from "../../dom/dom.js"
5
6
  import {Use} from "../../views/use.js"
6
- import {attributes} from "../../views/attributes.js"
7
7
  import {BaseElement} from "../../views/base-element.js"
8
8
 
9
9
  export class IncrediElement extends BaseElement {
10
10
  static styles = css`span{color:orange}`
11
- attrs = attributes(this, {value: Number})
11
+ attrs = dom.attrs(this, {value: Number})
12
12
  something = {whatever: "rofl"}
13
13
 
14
14
  render(use: Use) {
package/s/dom/dom.ts CHANGED
@@ -2,7 +2,10 @@
2
2
  import {render} from "lit"
3
3
  import {register} from "./register.js"
4
4
  import {Content} from "../views/types.js"
5
- import {Queryable, Renderable} from "./types.js"
5
+ import {attributes, AttrSpec, AttrTypes} from "./attributes.js"
6
+
7
+ export type Renderable = HTMLElement | ShadowRoot | DocumentFragment
8
+ export type Queryable = HTMLElement | ShadowRoot | Element | Document | DocumentFragment
6
9
 
7
10
  function require<E extends Element>(
8
11
  container: Queryable,
@@ -41,6 +44,10 @@ export class Dom<C extends Queryable> {
41
44
  render(...content: Content[]) {
42
45
  return render(content, this.element as Renderable)
43
46
  }
47
+
48
+ attrs<A extends AttrSpec>(spec: A) {
49
+ return attributes(this.element as HTMLElement, spec)
50
+ }
44
51
  }
45
52
 
46
53
  export function dom<E extends Queryable>(selector: string): E
@@ -56,6 +63,8 @@ dom.in = doc.in.bind(doc)
56
63
  dom.require = doc.require.bind(doc)
57
64
  dom.maybe = doc.maybe.bind(doc)
58
65
  dom.all = doc.all.bind(doc)
66
+
67
+ dom.attrs = attributes
59
68
  dom.register = register
60
69
  dom.render = (container: Renderable, ...content: Content[]) => {
61
70
  return render(content, container)
package/s/dom/register.ts CHANGED
@@ -1,6 +1,9 @@
1
1
 
2
2
  import {dashify} from "./dashify.js"
3
- import {HTMLElementClasses} from "./types.js"
3
+
4
+ export type HTMLElementClasses = {
5
+ [key: string]: {new(...args: any[]): HTMLElement}
6
+ }
4
7
 
5
8
  export type RegistrationOptions = {
6
9
  soft: boolean
package/s/index.ts CHANGED
@@ -1,8 +1,8 @@
1
1
 
2
+ export * from "./dom/attributes.js"
2
3
  export * from "./dom/dashify.js"
3
4
  export * from "./dom/dom.js"
4
5
  export * from "./dom/register.js"
5
- export * from "./dom/types.js"
6
6
 
7
7
  export * from "./ops/loaders/make-loader.js"
8
8
  export * from "./ops/loaders/parts/ascii-anim.js"
@@ -13,7 +13,7 @@ export * from "./ops/types.js"
13
13
 
14
14
  export * as loot from "./loot/index.js"
15
15
 
16
- export * from "./views/attributes.js"
16
+ export * from "./dom/attributes.js"
17
17
  export * from "./views/base-element.js"
18
18
  export * from "./views/css-reset.js"
19
19
  export * from "./views/types.js"
@@ -0,0 +1,82 @@
1
+
2
+ import {signal} from "@e280/strata"
3
+ import {Drops} from "./drops.js"
4
+ import {outsideCurrentTarget} from "./helpers.js"
5
+
6
+ /** respond to user dragging-and-dropping things around on a webpage */
7
+ export class DragAndDrops<Draggy, Droppy> {
8
+
9
+ /** what is currently being dragged */
10
+ $draggy = signal<Draggy | undefined>(undefined)
11
+
12
+ /** what dropzone are we curently hovering over */
13
+ $droppy = signal<Droppy | undefined>(undefined)
14
+
15
+ constructor(private params: {
16
+
17
+ /** accept a dropped item that was declared within this system */
18
+ acceptDrop: (event: DragEvent, draggy: Draggy, droppy: Droppy) => void
19
+
20
+ /** also accept drops on the side */
21
+ backchannelDrops?: Drops
22
+ }) {}
23
+
24
+ get dragging() {
25
+ return this.$draggy()
26
+ }
27
+
28
+ get hovering() {
29
+ return this.$droppy()
30
+ }
31
+
32
+ /** make event listeners to attach to your dragzone(s) */
33
+ dragzone = (getDraggy: () => Draggy) => ({
34
+ draggable: "true",
35
+
36
+ dragstart: (_: DragEvent) => {
37
+ this.$draggy.value = getDraggy()
38
+ },
39
+
40
+ dragend: (_: DragEvent) => {
41
+ this.$draggy.value = undefined
42
+ this.$droppy.value = undefined
43
+ },
44
+ })
45
+
46
+ /** make event listeners to attach to your dropzones(s) */
47
+ dropzone = (getDroppy: () => Droppy) => ({
48
+ dragenter: (_: DragEvent) => {},
49
+
50
+ dragover: (event: DragEvent) => {
51
+ event.preventDefault()
52
+ if (this.$draggy())
53
+ this.$droppy.value = getDroppy()
54
+ else
55
+ this.params.backchannelDrops?.dragover(event)
56
+ },
57
+
58
+ dragleave: (event: DragEvent) => {
59
+ if (outsideCurrentTarget(event))
60
+ this.$droppy.value = undefined
61
+ this.params.backchannelDrops?.dragleave(event)
62
+ },
63
+
64
+ drop: (event: DragEvent) => {
65
+ event.preventDefault()
66
+ const {acceptDrop} = this.params
67
+ const draggy = this.$draggy()
68
+ const droppy = this.$droppy()
69
+ try {
70
+ if (draggy && droppy)
71
+ acceptDrop(event, draggy, droppy)
72
+ else
73
+ this.params.backchannelDrops?.drop(event)
74
+ }
75
+ finally {
76
+ this.$draggy.value = undefined
77
+ this.$droppy.value = undefined
78
+ }
79
+ },
80
+ })
81
+ }
82
+
@@ -1,10 +1,10 @@
1
1
 
2
2
  import {signal} from "@e280/strata"
3
- import {dragIsOutsideCurrentTarget} from "./helpers.js"
3
+ import {outsideCurrentTarget} from "./helpers.js"
4
4
 
5
- /** dropzone that accepts dropped stuff like files */
6
- export class Drop {
7
- #$indicator = signal(false)
5
+ /** dropzone that accepts user-dropped stuff like files */
6
+ export class Drops {
7
+ $indicator = signal(false)
8
8
 
9
9
  constructor(private params: {
10
10
 
@@ -15,28 +15,19 @@ export class Drop {
15
15
  acceptDrop: (event: DragEvent) => void
16
16
  }) {}
17
17
 
18
- get indicator() {
19
- return this.#$indicator.value
20
- }
21
-
22
- resetIndicator = () => {
23
- this.#$indicator.value = false
24
- }
25
-
26
18
  dragover = (event: DragEvent) => {
27
19
  event.preventDefault()
28
- if (this.params.predicate(event))
29
- this.#$indicator.value = true
20
+ this.$indicator.value = this.params.predicate(event)
30
21
  }
31
22
 
32
23
  dragleave = (event: DragEvent) => {
33
- if (dragIsOutsideCurrentTarget(event))
34
- this.#$indicator.value = false
24
+ if (outsideCurrentTarget(event))
25
+ this.$indicator.value = false
35
26
  }
36
27
 
37
28
  drop = (event: DragEvent) => {
38
29
  event.preventDefault()
39
- this.#$indicator.value = false
30
+ this.$indicator.value = false
40
31
  if (this.params.predicate(event))
41
32
  this.params.acceptDrop(event)
42
33
  }
package/s/loot/helpers.ts CHANGED
@@ -1,18 +1,18 @@
1
1
 
2
- export function dragHasFiles(event: DragEvent) {
2
+ export function hasFiles(event: DragEvent) {
3
3
  return !!(
4
4
  event.dataTransfer &&
5
5
  event.dataTransfer.types.includes("Files")
6
6
  )
7
7
  }
8
8
 
9
- export function droppedFiles(event: DragEvent) {
9
+ export function files(event: DragEvent) {
10
10
  return event.dataTransfer
11
11
  ? Array.from(event.dataTransfer.files)
12
12
  : []
13
13
  }
14
14
 
15
- export function dragIsOutsideCurrentTarget(event: DragEvent) {
15
+ export function outsideCurrentTarget(event: DragEvent) {
16
16
  const isCursorOutsideViewport = !event.relatedTarget || (
17
17
  event.clientX === 0 &&
18
18
  event.clientY === 0
package/s/loot/index.ts CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
- export * from "./drag-drop.js"
3
- export * from "./drop.js"
2
+ export * from "./drag-and-drops.js"
3
+ export * from "./drops.js"
4
4
  export * from "./helpers.js"
5
5
 
@@ -5,7 +5,7 @@ import {debounce, MapG} from "@e280/stz"
5
5
 
6
6
  import {dom} from "../dom/dom.js"
7
7
  import {Content} from "./types.js"
8
- import {onAttrChange} from "./attributes.js"
8
+ import {onAttrChange} from "../dom/attributes.js"
9
9
  import {applyStyles} from "./utils/apply-styles.js"
10
10
  import {Use, _disconnect, _reconnect, _wrap} from "./use.js"
11
11
 
package/s/views/use.ts CHANGED
@@ -4,9 +4,10 @@ import {defer, MapG} from "@e280/stz"
4
4
  import {signal, SignalOptions} from "@e280/strata/signals"
5
5
 
6
6
  import {Op} from "../ops/op.js"
7
+ import {dom} from "../dom/dom.js"
7
8
  import {Mounts} from "./utils/mounts.js"
8
9
  import {applyStyles} from "./utils/apply-styles.js"
9
- import {attributes, AttrSpec, onAttrChange} from "./attributes.js"
10
+ import {AttrSpec, onAttrChange} from "../dom/attributes.js"
10
11
 
11
12
  export const _wrap = Symbol()
12
13
  export const _disconnect = Symbol()
@@ -66,7 +67,7 @@ export class Use {
66
67
 
67
68
  attrs<A extends AttrSpec>(spec: A) {
68
69
  this.mount(() => onAttrChange(this.element, this.render))
69
- return this.once(() => attributes(this.element, spec))
70
+ return this.once(() => dom.attrs(this.element, spec))
70
71
  }
71
72
 
72
73
  once<V>(fn: () => V) {