@e280/sly 0.2.0-4 → 0.2.0-5

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.
package/README.md CHANGED
@@ -11,6 +11,7 @@ sly replaces its predecessor, [slate](https://github.com/benevolent-games/slate)
11
11
  - 🪄 **dom** — the "it's not jquery" multitool
12
12
  - 🪵 **base element** — for a more classical experience
13
13
  - 🫛 **ops** — tools for async operations and loading spinners
14
+ - 🪙 **loot** — drag-and-drop facilities
14
15
  - 🧪 **testing page** — https://sly.e280.org/
15
16
 
16
17
 
@@ -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) => {
@@ -273,18 +273,18 @@ view(use => () => html`<p>hello world</p>`)
273
273
  ## 🦝🪵 sly base element
274
274
  > *the classic experience*
275
275
 
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.
276
+ ```ts
277
+ import {BaseElement, Use, attributes, dom} from "@e280/sly"
278
+ import {html, css} from "lit"
279
+ ```
280
+
281
+ `BaseElement` is a class-based approach to create a custom element web component.
282
+
283
+ 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
284
 
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.
285
+ base element enjoys the same `use` hooks as views.
281
286
 
282
287
  ### 🪵 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
288
  - **declare your element class**
289
289
  ```ts
290
290
  export class MyElement extends BaseElement {
@@ -295,7 +295,7 @@ it's a proper class-based element, but it lets you have the same `use` hooks tha
295
295
 
296
296
  // custom attributes
297
297
  attrs = attributes(this, {
298
- multiply: Number
298
+ multiply: Number,
299
299
  })
300
300
 
301
301
  // custom methods
@@ -535,6 +535,126 @@ import {Pod, podium, Op, makeLoader, anims} from "@e280/sly"
535
535
 
536
536
 
537
537
 
538
+ <br/><br/>
539
+
540
+ ## 🦝🪙 loot
541
+ > *drag-and-drop facilities*
542
+
543
+ ```ts
544
+ import {loot, ev, view} from "@e280/sly"
545
+ ```
546
+
547
+ ### 🪙 `loot.Drops`
548
+ > *accept the user dropping stuff like files onto the page*
549
+ - **setup drops**
550
+ ```ts
551
+ const drops = new loot.Drops({
552
+ predicate: loot.hasFiles,
553
+ acceptDrop: event => {
554
+ const files = loot.files(event)
555
+ console.log("files dropped", files)
556
+ },
557
+ })
558
+ ```
559
+ - **attach event listeners to your dropzone,** one of these ways:
560
+ - **view example**
561
+ ```ts
562
+ view(() => () => html`
563
+ <div
564
+ ?data-indicator="${drops.$indicator()}"
565
+ @dragover="${drops.dragover}"
566
+ @dragleave="${drops.dragleave}"
567
+ @drop="${drops.drop}">
568
+ my dropzone
569
+ </div>
570
+ `)
571
+ ```
572
+ - **vanilla-js whole-page example**
573
+ ```ts
574
+ // attach listeners to accept drops and stuff
575
+ ev(document.body, {
576
+ dragover: drops.dragover,
577
+ dragleave: drops.dragleave,
578
+ drop: drops.drop,
579
+ })
580
+
581
+ // update indicator attribute on body
582
+ drops.$indicator.on(indicator => {
583
+ if (indicator) document.body.setAttribute("data-indicator", "")
584
+ else document.body.removeAttribute("data-indicator")
585
+ })
586
+ ```
587
+ - **flashy css indicator for the dropzone,** so the user knows your app is eager to accept the drop
588
+ ```css
589
+ [data-indicator] {
590
+ border: 0.5em dashed cyan;
591
+ }
592
+ ```
593
+
594
+ ### 🪙 `loot.DragAndDrops`
595
+ > *setup drag-and-drops between items within your page*
596
+ - **declare types for your grabbable and hoverable things**
597
+ ```ts
598
+ // money that can be picked up and dragged
599
+ type Money = {value: number}
600
+ // dnd will call this a "draggy"
601
+
602
+ // bag that money can be dropped into
603
+ type Bag = {id: number}
604
+ // dnd will call this a "droppy"
605
+ ```
606
+ - **make your dnd**
607
+ ```ts
608
+ const dnd = new loot.DragAndDrops<Money, Bag>({
609
+ acceptDrop: (event, money, bag) => {
610
+ console.log("drop!", {money, bag})
611
+ },
612
+ })
613
+ ```
614
+ - **attach dragzone listeners**
615
+ (there can be many dragzones...)
616
+ ```ts
617
+ view(use => () => {
618
+ const money = use.once((): Money => ({value: 280}))
619
+ const dragzone = use.once(() => dnd.dragzone(() => money))
620
+
621
+ return html`
622
+ <div
623
+ draggable="${dragzone.draggable}"
624
+ @dragstart="${dragzone.dragstart}"
625
+ @dragend="${dragzone.dragend}">
626
+ money ${money.value}
627
+ </div>
628
+ `
629
+ })
630
+ ```
631
+ - **attach dropzone listeners**
632
+ (there can be many dropzones...)
633
+ ```ts
634
+ view(use => () => {
635
+ const bag = use.once((): Bag => ({id: 1}))
636
+ const dropzone = use.once(() => dnd.dropzone(() => bag))
637
+ const indicator = !!(dnd.dragging && dnd.hovering === bag)
638
+
639
+ return html`
640
+ <div
641
+ ?data-indicator="${indicator}"
642
+ @dragenter="${dropzone.dragenter}"
643
+ @dragleave="${dropzone.dragleave}"
644
+ @dragover="${dropzone.dragover}"
645
+ @drop="${dropzone.drop}">
646
+ bag ${bag.id}
647
+ </div>
648
+ `
649
+ })
650
+ ```
651
+
652
+ ### 🪙 loot helpers
653
+ - **`loot.hasFiles(event)`** — return true if `DragEvent` contains any files (useful in `predicate`)
654
+ - **`loot.files(event)`** — returns an array of files in a drop's `DragEvent` (useful in `acceptDrop`)
655
+
656
+
657
+
538
658
  <br/><br/>
539
659
 
540
660
  ## 🦝🧑‍💻 sly is by e280
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-5",
4
4
  "description": "web shadow views",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -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
 
package/x/index.html CHANGED
@@ -131,7 +131,7 @@ body {
131
131
  <img class=icon alt="" src="/assets/favicon.png"/>
132
132
  <h1>sly testing page</h1>
133
133
  <p><a href="https://github.com/e280/sly">github.com/e280/sly</a></p>
134
- <p class=lil>v0.2.0-4</p>
134
+ <p class=lil>v0.2.0-5</p>
135
135
  <incredi-element></incredi-element>
136
136
  <demo-counter>component</demo-counter>
137
137
  <div class=demo></div>
@@ -0,0 +1,30 @@
1
+ import { Drops } from "./drops.js";
2
+ /** respond to user dragging-and-dropping things around on a webpage */
3
+ export declare class DragAndDrops<Draggy, Droppy> {
4
+ private params;
5
+ /** what is currently being dragged */
6
+ $draggy: import("@e280/strata").SignalFn<Draggy | undefined>;
7
+ /** what dropzone are we curently hovering over */
8
+ $droppy: import("@e280/strata").SignalFn<Droppy | undefined>;
9
+ constructor(params: {
10
+ /** accept a dropped item that was declared within this system */
11
+ acceptDrop: (event: DragEvent, draggy: Draggy, droppy: Droppy) => void;
12
+ /** also accept drops on the side */
13
+ backchannelDrops?: Drops;
14
+ });
15
+ get dragging(): Draggy | undefined;
16
+ get hovering(): Droppy | undefined;
17
+ /** make event listeners to attach to your dragzone(s) */
18
+ dragzone: (getDraggy: () => Draggy) => {
19
+ draggable: string;
20
+ dragstart: (_: DragEvent) => void;
21
+ dragend: (_: DragEvent) => void;
22
+ };
23
+ /** make event listeners to attach to your dropzones(s) */
24
+ dropzone: (getDroppy: () => Droppy) => {
25
+ dragenter: (_: DragEvent) => void;
26
+ dragover: (event: DragEvent) => void;
27
+ dragleave: (event: DragEvent) => void;
28
+ drop: (event: DragEvent) => void;
29
+ };
30
+ }
@@ -0,0 +1,63 @@
1
+ import { signal } from "@e280/strata";
2
+ import { outsideCurrentTarget } from "./helpers.js";
3
+ /** respond to user dragging-and-dropping things around on a webpage */
4
+ export class DragAndDrops {
5
+ params;
6
+ /** what is currently being dragged */
7
+ $draggy = signal(undefined);
8
+ /** what dropzone are we curently hovering over */
9
+ $droppy = signal(undefined);
10
+ constructor(params) {
11
+ this.params = params;
12
+ }
13
+ get dragging() {
14
+ return this.$draggy();
15
+ }
16
+ get hovering() {
17
+ return this.$droppy();
18
+ }
19
+ /** make event listeners to attach to your dragzone(s) */
20
+ dragzone = (getDraggy) => ({
21
+ draggable: "true",
22
+ dragstart: (_) => {
23
+ this.$draggy.value = getDraggy();
24
+ },
25
+ dragend: (_) => {
26
+ this.$draggy.value = undefined;
27
+ this.$droppy.value = undefined;
28
+ },
29
+ });
30
+ /** make event listeners to attach to your dropzones(s) */
31
+ dropzone = (getDroppy) => ({
32
+ dragenter: (_) => { },
33
+ dragover: (event) => {
34
+ event.preventDefault();
35
+ if (this.$draggy())
36
+ this.$droppy.value = getDroppy();
37
+ else
38
+ this.params.backchannelDrops?.dragover(event);
39
+ },
40
+ dragleave: (event) => {
41
+ if (outsideCurrentTarget(event))
42
+ this.$droppy.value = undefined;
43
+ this.params.backchannelDrops?.dragleave(event);
44
+ },
45
+ drop: (event) => {
46
+ event.preventDefault();
47
+ const { acceptDrop } = this.params;
48
+ const draggy = this.$draggy();
49
+ const droppy = this.$droppy();
50
+ try {
51
+ if (draggy && droppy)
52
+ acceptDrop(event, draggy, droppy);
53
+ else
54
+ this.params.backchannelDrops?.drop(event);
55
+ }
56
+ finally {
57
+ this.$draggy.value = undefined;
58
+ this.$droppy.value = undefined;
59
+ }
60
+ },
61
+ });
62
+ }
63
+ //# sourceMappingURL=drag-and-drops.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drag-and-drops.js","sourceRoot":"","sources":["../../s/loot/drag-and-drops.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,MAAM,EAAC,MAAM,cAAc,CAAA;AAEnC,OAAO,EAAC,oBAAoB,EAAC,MAAM,cAAc,CAAA;AAEjD,uEAAuE;AACvE,MAAM,OAAO,YAAY;IAQJ;IANpB,sCAAsC;IACtC,OAAO,GAAG,MAAM,CAAqB,SAAS,CAAC,CAAA;IAE/C,kDAAkD;IAClD,OAAO,GAAG,MAAM,CAAqB,SAAS,CAAC,CAAA;IAE/C,YAAoB,MAOnB;QAPmB,WAAM,GAAN,MAAM,CAOzB;IAAG,CAAC;IAEL,IAAI,QAAQ;QACX,OAAO,IAAI,CAAC,OAAO,EAAE,CAAA;IACtB,CAAC;IAED,IAAI,QAAQ;QACX,OAAO,IAAI,CAAC,OAAO,EAAE,CAAA;IACtB,CAAC;IAED,yDAAyD;IACzD,QAAQ,GAAG,CAAC,SAAuB,EAAE,EAAE,CAAC,CAAC;QACxC,SAAS,EAAE,MAAM;QAEjB,SAAS,EAAE,CAAC,CAAY,EAAE,EAAE;YAC3B,IAAI,CAAC,OAAO,CAAC,KAAK,GAAG,SAAS,EAAE,CAAA;QACjC,CAAC;QAED,OAAO,EAAE,CAAC,CAAY,EAAE,EAAE;YACzB,IAAI,CAAC,OAAO,CAAC,KAAK,GAAG,SAAS,CAAA;YAC9B,IAAI,CAAC,OAAO,CAAC,KAAK,GAAG,SAAS,CAAA;QAC/B,CAAC;KACD,CAAC,CAAA;IAEF,0DAA0D;IAC1D,QAAQ,GAAG,CAAC,SAAuB,EAAE,EAAE,CAAC,CAAC;QACxC,SAAS,EAAE,CAAC,CAAY,EAAE,EAAE,GAAE,CAAC;QAE/B,QAAQ,EAAE,CAAC,KAAgB,EAAE,EAAE;YAC9B,KAAK,CAAC,cAAc,EAAE,CAAA;YACtB,IAAI,IAAI,CAAC,OAAO,EAAE;gBACjB,IAAI,CAAC,OAAO,CAAC,KAAK,GAAG,SAAS,EAAE,CAAA;;gBAEhC,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAA;QAC/C,CAAC;QAED,SAAS,EAAE,CAAC,KAAgB,EAAE,EAAE;YAC/B,IAAI,oBAAoB,CAAC,KAAK,CAAC;gBAC9B,IAAI,CAAC,OAAO,CAAC,KAAK,GAAG,SAAS,CAAA;YAC/B,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,SAAS,CAAC,KAAK,CAAC,CAAA;QAC/C,CAAC;QAED,IAAI,EAAE,CAAC,KAAgB,EAAE,EAAE;YAC1B,KAAK,CAAC,cAAc,EAAE,CAAA;YACtB,MAAM,EAAC,UAAU,EAAC,GAAG,IAAI,CAAC,MAAM,CAAA;YAChC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,CAAA;YAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,CAAA;YAC7B,IAAI,CAAC;gBACJ,IAAI,MAAM,IAAI,MAAM;oBACnB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;;oBAEjC,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,IAAI,CAAC,KAAK,CAAC,CAAA;YAC3C,CAAC;oBACO,CAAC;gBACR,IAAI,CAAC,OAAO,CAAC,KAAK,GAAG,SAAS,CAAA;gBAC9B,IAAI,CAAC,OAAO,CAAC,KAAK,GAAG,SAAS,CAAA;YAC/B,CAAC;QACF,CAAC;KACD,CAAC,CAAA;CACF"}
@@ -1,15 +1,13 @@
1
- /** dropzone that accepts dropped stuff like files */
2
- export declare class Drop {
3
- #private;
1
+ /** dropzone that accepts user-dropped stuff like files */
2
+ export declare class Drops {
4
3
  private params;
4
+ $indicator: import("@e280/strata").SignalFn<boolean>;
5
5
  constructor(params: {
6
6
  /** whether or not the dragged item is acceptable for a drop */
7
7
  predicate: (event: DragEvent) => boolean;
8
8
  /** fn to handle the drop of an acceptable item */
9
9
  acceptDrop: (event: DragEvent) => void;
10
10
  });
11
- get indicator(): boolean;
12
- resetIndicator: () => void;
13
11
  dragover: (event: DragEvent) => void;
14
12
  dragleave: (event: DragEvent) => void;
15
13
  drop: (event: DragEvent) => void;
@@ -0,0 +1,25 @@
1
+ import { signal } from "@e280/strata";
2
+ import { outsideCurrentTarget } from "./helpers.js";
3
+ /** dropzone that accepts user-dropped stuff like files */
4
+ export class Drops {
5
+ params;
6
+ $indicator = signal(false);
7
+ constructor(params) {
8
+ this.params = params;
9
+ }
10
+ dragover = (event) => {
11
+ event.preventDefault();
12
+ this.$indicator.value = this.params.predicate(event);
13
+ };
14
+ dragleave = (event) => {
15
+ if (outsideCurrentTarget(event))
16
+ this.$indicator.value = false;
17
+ };
18
+ drop = (event) => {
19
+ event.preventDefault();
20
+ this.$indicator.value = false;
21
+ if (this.params.predicate(event))
22
+ this.params.acceptDrop(event);
23
+ };
24
+ }
25
+ //# sourceMappingURL=drops.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drops.js","sourceRoot":"","sources":["../../s/loot/drops.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,MAAM,EAAC,MAAM,cAAc,CAAA;AACnC,OAAO,EAAC,oBAAoB,EAAC,MAAM,cAAc,CAAA;AAEjD,0DAA0D;AAC1D,MAAM,OAAO,KAAK;IAGG;IAFpB,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;IAE1B,YAAoB,MAOnB;QAPmB,WAAM,GAAN,MAAM,CAOzB;IAAG,CAAC;IAEL,QAAQ,GAAG,CAAC,KAAgB,EAAE,EAAE;QAC/B,KAAK,CAAC,cAAc,EAAE,CAAA;QACtB,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;IACrD,CAAC,CAAA;IAED,SAAS,GAAG,CAAC,KAAgB,EAAE,EAAE;QAChC,IAAI,oBAAoB,CAAC,KAAK,CAAC;YAC9B,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG,KAAK,CAAA;IAC/B,CAAC,CAAA;IAED,IAAI,GAAG,CAAC,KAAgB,EAAE,EAAE;QAC3B,KAAK,CAAC,cAAc,EAAE,CAAA;QACtB,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG,KAAK,CAAA;QAC7B,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;YAC/B,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;IAC/B,CAAC,CAAA;CACD"}
@@ -1,3 +1,3 @@
1
- export declare function dragHasFiles(event: DragEvent): boolean;
2
- export declare function droppedFiles(event: DragEvent): File[];
3
- export declare function dragIsOutsideCurrentTarget(event: DragEvent): boolean;
1
+ export declare function hasFiles(event: DragEvent): boolean;
2
+ export declare function files(event: DragEvent): File[];
3
+ export declare function outsideCurrentTarget(event: DragEvent): boolean;
package/x/loot/helpers.js CHANGED
@@ -1,13 +1,13 @@
1
- export function dragHasFiles(event) {
1
+ export function hasFiles(event) {
2
2
  return !!(event.dataTransfer &&
3
3
  event.dataTransfer.types.includes("Files"));
4
4
  }
5
- export function droppedFiles(event) {
5
+ export function files(event) {
6
6
  return event.dataTransfer
7
7
  ? Array.from(event.dataTransfer.files)
8
8
  : [];
9
9
  }
10
- export function dragIsOutsideCurrentTarget(event) {
10
+ export function outsideCurrentTarget(event) {
11
11
  const isCursorOutsideViewport = !event.relatedTarget || (event.clientX === 0 &&
12
12
  event.clientY === 0);
13
13
  if (isCursorOutsideViewport)
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../s/loot/helpers.ts"],"names":[],"mappings":"AACA,MAAM,UAAU,YAAY,CAAC,KAAgB;IAC5C,OAAO,CAAC,CAAC,CACR,KAAK,CAAC,YAAY;QAClB,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAC1C,CAAA;AACF,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAgB;IAC5C,OAAO,KAAK,CAAC,YAAY;QACxB,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC;QACtC,CAAC,CAAC,EAAE,CAAA;AACN,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,KAAgB;IAC1D,MAAM,uBAAuB,GAAG,CAAC,KAAK,CAAC,aAAa,IAAI,CACvD,KAAK,CAAC,OAAO,KAAK,CAAC;QACnB,KAAK,CAAC,OAAO,KAAK,CAAC,CACnB,CAAA;IAED,IAAI,uBAAuB;QAC1B,OAAO,IAAI,CAAA;IAEZ,MAAM,IAAI,GAAI,KAAK,CAAC,aAAqB,CAAC,qBAAqB,EAAE,CAAA;IACjE,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,KAAK,CAAA;IACzE,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,GAAG,IAAI,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,MAAM,CAAA;IACzE,MAAM,0BAA0B,GAAG,CAAC,CAAC,OAAO,IAAI,OAAO,CAAC,CAAA;IAExD,OAAO,0BAA0B,CAAA;AAClC,CAAC"}
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../s/loot/helpers.ts"],"names":[],"mappings":"AACA,MAAM,UAAU,QAAQ,CAAC,KAAgB;IACxC,OAAO,CAAC,CAAC,CACR,KAAK,CAAC,YAAY;QAClB,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAC1C,CAAA;AACF,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,KAAgB;IACrC,OAAO,KAAK,CAAC,YAAY;QACxB,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC;QACtC,CAAC,CAAC,EAAE,CAAA;AACN,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAgB;IACpD,MAAM,uBAAuB,GAAG,CAAC,KAAK,CAAC,aAAa,IAAI,CACvD,KAAK,CAAC,OAAO,KAAK,CAAC;QACnB,KAAK,CAAC,OAAO,KAAK,CAAC,CACnB,CAAA;IAED,IAAI,uBAAuB;QAC1B,OAAO,IAAI,CAAA;IAEZ,MAAM,IAAI,GAAI,KAAK,CAAC,aAAqB,CAAC,qBAAqB,EAAE,CAAA;IACjE,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,KAAK,CAAA;IACzE,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,GAAG,IAAI,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,MAAM,CAAA;IACzE,MAAM,0BAA0B,GAAG,CAAC,CAAC,OAAO,IAAI,OAAO,CAAC,CAAA;IAExD,OAAO,0BAA0B,CAAA;AAClC,CAAC"}
package/x/loot/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export * from "./drag-drop.js";
2
- export * from "./drop.js";
1
+ export * from "./drag-and-drops.js";
2
+ export * from "./drops.js";
3
3
  export * from "./helpers.js";
package/x/loot/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export * from "./drag-drop.js";
2
- export * from "./drop.js";
1
+ export * from "./drag-and-drops.js";
2
+ export * from "./drops.js";
3
3
  export * from "./helpers.js";
4
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../s/loot/index.ts"],"names":[],"mappings":"AACA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../s/loot/index.ts"],"names":[],"mappings":"AACA,cAAc,qBAAqB,CAAA;AACnC,cAAc,YAAY,CAAA;AAC1B,cAAc,cAAc,CAAA"}
@@ -1,76 +0,0 @@
1
-
2
- import {signal} from "@e280/strata"
3
- import {dragIsOutsideCurrentTarget} from "./helpers.js"
4
-
5
- /** system for dragging-and-dropping things around on a webpage */
6
- export class DragDrop<Grabbed, Hovering> {
7
- #$grabbed = signal<Grabbed | undefined>(undefined)
8
- #$hovering = signal<Hovering | undefined>(undefined)
9
-
10
- constructor(private params: {
11
-
12
- /** accept a dropped item that was declared within this system */
13
- acceptDrop: (event: DragEvent, grabbed: Grabbed, hovering: Hovering) => void
14
-
15
- /** accept undeclared drops from outside this system */
16
- fromOutside?: {
17
- predicate: (event: DragEvent, hovering: Hovering) => boolean
18
- acceptDrop: (event: DragEvent, hovering: Hovering) => void
19
- }
20
- }) {}
21
-
22
- /** make event listeners to attach to your dragzone(s) */
23
- readonly dragzone = {
24
- draggable: () => "true",
25
-
26
- dragstart: (grabbed: Grabbed) => (_: DragEvent) => {
27
- this.#$grabbed.value = grabbed
28
- },
29
-
30
- dragend: () => (_: DragEvent) => {
31
- this.#$grabbed.value = undefined
32
- this.#$hovering.value = undefined
33
- },
34
- }
35
-
36
- /** make event listeners to attach to your dropzones(s) */
37
- readonly dropzone = {
38
- dragenter: () => (_: DragEvent) => {},
39
-
40
- dragleave: () => (event: DragEvent) => {
41
- if (dragIsOutsideCurrentTarget(event))
42
- this.#$hovering.value = undefined
43
- },
44
-
45
- dragover: (hovering: Hovering) => (event: DragEvent) => {
46
- event.preventDefault()
47
- const {fromOutside} = this.params
48
-
49
- if (this.#$grabbed() || (fromOutside && fromOutside.predicate(event, hovering)))
50
- this.#$hovering.value = hovering
51
- },
52
-
53
- drop: (hovering: Hovering) => (event: DragEvent) => {
54
- event.preventDefault()
55
- const {acceptDrop, fromOutside} = this.params
56
-
57
- const grabbed = this.#$grabbed()
58
- this.#$grabbed.value = undefined
59
- this.#$hovering.value = undefined
60
-
61
- if (grabbed)
62
- acceptDrop(event, grabbed, hovering)
63
- else if (fromOutside && fromOutside.predicate(event, hovering))
64
- fromOutside.acceptDrop(event, hovering)
65
- },
66
- }
67
-
68
- get grabbed() {
69
- return this.#$grabbed()
70
- }
71
-
72
- get hovering() {
73
- return this.#$hovering()
74
- }
75
- }
76
-
@@ -1,29 +0,0 @@
1
- /** system for dragging-and-dropping things around on a webpage */
2
- export declare class DragDrop<Grabbed, Hovering> {
3
- #private;
4
- private params;
5
- constructor(params: {
6
- /** accept a dropped item that was declared within this system */
7
- acceptDrop: (event: DragEvent, grabbed: Grabbed, hovering: Hovering) => void;
8
- /** accept undeclared drops from outside this system */
9
- fromOutside?: {
10
- predicate: (event: DragEvent, hovering: Hovering) => boolean;
11
- acceptDrop: (event: DragEvent, hovering: Hovering) => void;
12
- };
13
- });
14
- /** make event listeners to attach to your dragzone(s) */
15
- readonly dragzone: {
16
- draggable: () => string;
17
- dragstart: (grabbed: Grabbed) => (_: DragEvent) => void;
18
- dragend: () => (_: DragEvent) => void;
19
- };
20
- /** make event listeners to attach to your dropzones(s) */
21
- readonly dropzone: {
22
- dragenter: () => (_: DragEvent) => void;
23
- dragleave: () => (event: DragEvent) => void;
24
- dragover: (hovering: Hovering) => (event: DragEvent) => void;
25
- drop: (hovering: Hovering) => (event: DragEvent) => void;
26
- };
27
- get grabbed(): Grabbed | undefined;
28
- get hovering(): Hovering | undefined;
29
- }
@@ -1,54 +0,0 @@
1
- import { signal } from "@e280/strata";
2
- import { dragIsOutsideCurrentTarget } from "./helpers.js";
3
- /** system for dragging-and-dropping things around on a webpage */
4
- export class DragDrop {
5
- params;
6
- #$grabbed = signal(undefined);
7
- #$hovering = signal(undefined);
8
- constructor(params) {
9
- this.params = params;
10
- }
11
- /** make event listeners to attach to your dragzone(s) */
12
- dragzone = {
13
- draggable: () => "true",
14
- dragstart: (grabbed) => (_) => {
15
- this.#$grabbed.value = grabbed;
16
- },
17
- dragend: () => (_) => {
18
- this.#$grabbed.value = undefined;
19
- this.#$hovering.value = undefined;
20
- },
21
- };
22
- /** make event listeners to attach to your dropzones(s) */
23
- dropzone = {
24
- dragenter: () => (_) => { },
25
- dragleave: () => (event) => {
26
- if (dragIsOutsideCurrentTarget(event))
27
- this.#$hovering.value = undefined;
28
- },
29
- dragover: (hovering) => (event) => {
30
- event.preventDefault();
31
- const { fromOutside } = this.params;
32
- if (this.#$grabbed() || (fromOutside && fromOutside.predicate(event, hovering)))
33
- this.#$hovering.value = hovering;
34
- },
35
- drop: (hovering) => (event) => {
36
- event.preventDefault();
37
- const { acceptDrop, fromOutside } = this.params;
38
- const grabbed = this.#$grabbed();
39
- this.#$grabbed.value = undefined;
40
- this.#$hovering.value = undefined;
41
- if (grabbed)
42
- acceptDrop(event, grabbed, hovering);
43
- else if (fromOutside && fromOutside.predicate(event, hovering))
44
- fromOutside.acceptDrop(event, hovering);
45
- },
46
- };
47
- get grabbed() {
48
- return this.#$grabbed();
49
- }
50
- get hovering() {
51
- return this.#$hovering();
52
- }
53
- }
54
- //# sourceMappingURL=drag-drop.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"drag-drop.js","sourceRoot":"","sources":["../../s/loot/drag-drop.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,MAAM,EAAC,MAAM,cAAc,CAAA;AACnC,OAAO,EAAC,0BAA0B,EAAC,MAAM,cAAc,CAAA;AAEvD,kEAAkE;AAClE,MAAM,OAAO,QAAQ;IAIA;IAHpB,SAAS,GAAG,MAAM,CAAsB,SAAS,CAAC,CAAA;IAClD,UAAU,GAAG,MAAM,CAAuB,SAAS,CAAC,CAAA;IAEpD,YAAoB,MAUnB;QAVmB,WAAM,GAAN,MAAM,CAUzB;IAAG,CAAC;IAEL,yDAAyD;IAChD,QAAQ,GAAG;QACnB,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM;QAEvB,SAAS,EAAE,CAAC,OAAgB,EAAE,EAAE,CAAC,CAAC,CAAY,EAAE,EAAE;YACjD,IAAI,CAAC,SAAS,CAAC,KAAK,GAAG,OAAO,CAAA;QAC/B,CAAC;QAED,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAY,EAAE,EAAE;YAC/B,IAAI,CAAC,SAAS,CAAC,KAAK,GAAG,SAAS,CAAA;YAChC,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG,SAAS,CAAA;QAClC,CAAC;KACD,CAAA;IAED,0DAA0D;IACjD,QAAQ,GAAG;QACnB,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC,CAAY,EAAE,EAAE,GAAE,CAAC;QAErC,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC,KAAgB,EAAE,EAAE;YACrC,IAAI,0BAA0B,CAAC,KAAK,CAAC;gBACpC,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG,SAAS,CAAA;QACnC,CAAC;QAED,QAAQ,EAAE,CAAC,QAAkB,EAAE,EAAE,CAAC,CAAC,KAAgB,EAAE,EAAE;YACtD,KAAK,CAAC,cAAc,EAAE,CAAA;YACtB,MAAM,EAAC,WAAW,EAAC,GAAG,IAAI,CAAC,MAAM,CAAA;YAEjC,IAAI,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,WAAW,IAAI,WAAW,CAAC,SAAS,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;gBAC9E,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG,QAAQ,CAAA;QAClC,CAAC;QAED,IAAI,EAAE,CAAC,QAAkB,EAAE,EAAE,CAAC,CAAC,KAAgB,EAAE,EAAE;YAClD,KAAK,CAAC,cAAc,EAAE,CAAA;YACtB,MAAM,EAAC,UAAU,EAAE,WAAW,EAAC,GAAG,IAAI,CAAC,MAAM,CAAA;YAE7C,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE,CAAA;YAChC,IAAI,CAAC,SAAS,CAAC,KAAK,GAAG,SAAS,CAAA;YAChC,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG,SAAS,CAAA;YAEjC,IAAI,OAAO;gBACV,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAA;iBAChC,IAAI,WAAW,IAAI,WAAW,CAAC,SAAS,CAAC,KAAK,EAAE,QAAQ,CAAC;gBAC7D,WAAW,CAAC,UAAU,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;QACzC,CAAC;KACD,CAAA;IAED,IAAI,OAAO;QACV,OAAO,IAAI,CAAC,SAAS,EAAE,CAAA;IACxB,CAAC;IAED,IAAI,QAAQ;QACX,OAAO,IAAI,CAAC,UAAU,EAAE,CAAA;IACzB,CAAC;CACD"}
package/x/loot/drop.js DELETED
@@ -1,32 +0,0 @@
1
- import { signal } from "@e280/strata";
2
- import { dragIsOutsideCurrentTarget } from "./helpers.js";
3
- /** dropzone that accepts dropped stuff like files */
4
- export class Drop {
5
- params;
6
- #$indicator = signal(false);
7
- constructor(params) {
8
- this.params = params;
9
- }
10
- get indicator() {
11
- return this.#$indicator.value;
12
- }
13
- resetIndicator = () => {
14
- this.#$indicator.value = false;
15
- };
16
- dragover = (event) => {
17
- event.preventDefault();
18
- if (this.params.predicate(event))
19
- this.#$indicator.value = true;
20
- };
21
- dragleave = (event) => {
22
- if (dragIsOutsideCurrentTarget(event))
23
- this.#$indicator.value = false;
24
- };
25
- drop = (event) => {
26
- event.preventDefault();
27
- this.#$indicator.value = false;
28
- if (this.params.predicate(event))
29
- this.params.acceptDrop(event);
30
- };
31
- }
32
- //# sourceMappingURL=drop.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"drop.js","sourceRoot":"","sources":["../../s/loot/drop.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,MAAM,EAAC,MAAM,cAAc,CAAA;AACnC,OAAO,EAAC,0BAA0B,EAAC,MAAM,cAAc,CAAA;AAEvD,qDAAqD;AACrD,MAAM,OAAO,IAAI;IAGI;IAFpB,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;IAE3B,YAAoB,MAOnB;QAPmB,WAAM,GAAN,MAAM,CAOzB;IAAG,CAAC;IAEL,IAAI,SAAS;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC,KAAK,CAAA;IAC9B,CAAC;IAED,cAAc,GAAG,GAAG,EAAE;QACrB,IAAI,CAAC,WAAW,CAAC,KAAK,GAAG,KAAK,CAAA;IAC/B,CAAC,CAAA;IAED,QAAQ,GAAG,CAAC,KAAgB,EAAE,EAAE;QAC/B,KAAK,CAAC,cAAc,EAAE,CAAA;QACtB,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;YAC/B,IAAI,CAAC,WAAW,CAAC,KAAK,GAAG,IAAI,CAAA;IAC/B,CAAC,CAAA;IAED,SAAS,GAAG,CAAC,KAAgB,EAAE,EAAE;QAChC,IAAI,0BAA0B,CAAC,KAAK,CAAC;YACpC,IAAI,CAAC,WAAW,CAAC,KAAK,GAAG,KAAK,CAAA;IAChC,CAAC,CAAA;IAED,IAAI,GAAG,CAAC,KAAgB,EAAE,EAAE;QAC3B,KAAK,CAAC,cAAc,EAAE,CAAA;QACtB,IAAI,CAAC,WAAW,CAAC,KAAK,GAAG,KAAK,CAAA;QAC9B,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;YAC/B,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;IAC/B,CAAC,CAAA;CACD"}