@e280/sly 0.2.0-0 โ 0.2.0-2
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 +94 -65
- package/package.json +3 -3
- package/s/demo/demo.bundle.ts +3 -3
- package/s/demo/views/counter.ts +14 -7
- package/s/dom/dom.ts +51 -0
- package/s/dom/types.ts +3 -0
- package/s/index.ts +2 -2
- package/s/loot/drag-drop.ts +76 -0
- package/s/loot/drop.ts +44 -0
- package/s/loot/helpers.ts +31 -0
- package/s/loot/index.ts +5 -0
- package/s/views/use.ts +21 -3
- package/x/demo/demo.bundle.js +3 -3
- package/x/demo/demo.bundle.js.map +1 -1
- package/x/demo/demo.bundle.min.js +20 -15
- package/x/demo/demo.bundle.min.js.map +4 -4
- package/x/demo/views/counter.js +13 -6
- package/x/demo/views/counter.js.map +1 -1
- package/x/dom/dom.d.ts +21 -0
- package/x/dom/dom.js +41 -0
- package/x/dom/dom.js.map +1 -0
- package/x/dom/types.d.ts +2 -0
- package/x/index.d.ts +1 -1
- package/x/index.html +2 -2
- package/x/index.js +1 -1
- package/x/index.js.map +1 -1
- package/x/loot/drag-drop.d.ts +29 -0
- package/x/loot/drag-drop.js +54 -0
- package/x/loot/drag-drop.js.map +1 -0
- package/x/loot/drop.d.ts +16 -0
- package/x/loot/drop.js +32 -0
- package/x/loot/drop.js.map +1 -0
- package/x/loot/helpers.d.ts +3 -0
- package/x/loot/helpers.js +21 -0
- package/x/loot/helpers.js.map +1 -0
- package/x/loot/index.d.ts +3 -0
- package/x/loot/index.js +4 -0
- package/x/loot/index.js.map +1 -0
- package/x/views/use.d.ts +8 -1
- package/x/views/use.js +18 -2
- package/x/views/use.js.map +1 -1
- package/s/dom/dollar.ts +0 -27
- package/x/dom/dollar.d.ts +0 -10
- package/x/dom/dollar.js +0 -18
- package/x/dom/dollar.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
|
|
2
2
|
<div align="center"><img alt="" width="256" src="./assets/favicon.png"/></div>
|
|
3
3
|
|
|
4
|
-
# ๐ฆ sly
|
|
5
|
-
>
|
|
4
|
+
# ๐ฆ sly
|
|
5
|
+
> *mischievous shadow views*
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
- ๐คฏ register any view as a web component
|
|
10
|
-
- ๐ฒ handy little dom multitool
|
|
11
|
-
- ๐ซ ops for fancy loading spinners
|
|
12
|
-
- ๐งโโ๏ธ took many years to get it right
|
|
13
|
-
- ๐
sly is the successor that replaces [@benev/slate](https://github.com/benevolent-games/slate)
|
|
14
|
-
- ๐งโ๐ป project by [@e280](https://e280.org/)
|
|
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).
|
|
15
9
|
|
|
16
|
-
|
|
10
|
+
- ๐ **views** โ hooks-based, shadow-dom'd, componentizable
|
|
11
|
+
- ๐ช **dom** โ the "it's not jquery" multitool
|
|
12
|
+
- ๐ซ **ops** โ tools for async operations and loading spinners
|
|
13
|
+
- ๐งช **testing page** โ https://sly.e280.org/
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
<br/><br/>
|
|
17
18
|
|
|
18
19
|
## ๐ฆ sly and friends
|
|
19
20
|
|
|
@@ -23,13 +24,15 @@ npm install @e280/sly lit
|
|
|
23
24
|
|
|
24
25
|
> [!NOTE]
|
|
25
26
|
> - ๐ฅ [lit](https://lit.dev/) for html rendering
|
|
26
|
-
> - โ๏ธ [@e280/strata](https://github.com/e280/strata) for state management (signals, state trees)
|
|
27
|
-
> - ๐ [@e280/stz](https://github.com/e280/stz)
|
|
28
|
-
> - ๐ข [scute](https://github.com/e280/scute)
|
|
27
|
+
> - โ๏ธ [@e280/strata](https://github.com/e280/strata), for state management (signals, state trees)
|
|
28
|
+
> - ๐ [@e280/stz](https://github.com/e280/stz) is our ts standard library
|
|
29
|
+
> - ๐ข [scute](https://github.com/e280/scute) is our buildy-bundly-buddy
|
|
30
|
+
|
|
29
31
|
|
|
30
|
-
<br/>
|
|
31
32
|
|
|
32
|
-
|
|
33
|
+
<br/><br/>
|
|
34
|
+
|
|
35
|
+
## ๐ฆ๐ sly views
|
|
33
36
|
> *views are the crown jewel of sly.. shadow-dom'd.. hooks-based.. "ergonomics"..*
|
|
34
37
|
|
|
35
38
|
```ts
|
|
@@ -44,7 +47,7 @@ view(use => () => html`<p>hello world</p>`)
|
|
|
44
47
|
### ๐ view example
|
|
45
48
|
- **import stuff**
|
|
46
49
|
```ts
|
|
47
|
-
import {
|
|
50
|
+
import {view, dom} from "@e280/sly"
|
|
48
51
|
import {html, css} from "lit"
|
|
49
52
|
```
|
|
50
53
|
- **declare a view**
|
|
@@ -53,11 +56,11 @@ view(use => () => html`<p>hello world</p>`)
|
|
|
53
56
|
use.name("counter")
|
|
54
57
|
use.styles(css`p {color: green}`)
|
|
55
58
|
|
|
56
|
-
const count = use.signal(start)
|
|
57
|
-
const increment = () =>
|
|
59
|
+
const $count = use.signal(start)
|
|
60
|
+
const increment = () => $count.value++
|
|
58
61
|
|
|
59
62
|
return html`
|
|
60
|
-
<p>count ${count
|
|
63
|
+
<p>count ${$count.value}</p>
|
|
61
64
|
<button @click="${increment}">+</button>
|
|
62
65
|
`
|
|
63
66
|
})
|
|
@@ -65,15 +68,14 @@ view(use => () => html`<p>hello world</p>`)
|
|
|
65
68
|
- each view renders into a `<sly-view view="counter">` host (where "counter" is the `use.name` you provided)
|
|
66
69
|
- **inject a view into the dom**
|
|
67
70
|
```ts
|
|
68
|
-
|
|
69
|
-
<h1>
|
|
70
|
-
|
|
71
|
+
dom.in(".app").render(html`
|
|
72
|
+
<h1>cool counter demo</h1>
|
|
71
73
|
${CounterView(1)}
|
|
72
74
|
`)
|
|
73
75
|
```
|
|
74
76
|
- ๐คฏ **register a view as a web component**
|
|
75
77
|
```ts
|
|
76
|
-
|
|
78
|
+
dom.register({MyCounter: CounterView.component(1)})
|
|
77
79
|
// <my-counter></my-counter>
|
|
78
80
|
```
|
|
79
81
|
|
|
@@ -92,9 +94,8 @@ view(use => () => html`<p>hello world</p>`)
|
|
|
92
94
|
### ๐ view injection options
|
|
93
95
|
- options for views at the template injection site
|
|
94
96
|
```ts
|
|
95
|
-
|
|
96
|
-
<h2>
|
|
97
|
-
|
|
97
|
+
dom.in(".app").render(html`
|
|
98
|
+
<h2>cool example</h2>
|
|
98
99
|
${CoolView.props("hello")
|
|
99
100
|
.attr("class", "hero")
|
|
100
101
|
.children(html`<em>spongebob</em>`)
|
|
@@ -106,7 +107,7 @@ view(use => () => html`<p>hello world</p>`)
|
|
|
106
107
|
- `children` โ nested content in the host element, can be [slotted](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_templates_and_slots)
|
|
107
108
|
- `render` โ end the view chain and render the lit directive
|
|
108
109
|
|
|
109
|
-
### ๐ web components
|
|
110
|
+
### ๐ view web components
|
|
110
111
|
- **build a component directly**
|
|
111
112
|
```ts
|
|
112
113
|
const MyComponent = view.component(use => html`<p>hello world</p>`)
|
|
@@ -120,11 +121,11 @@ view(use => () => html`<p>hello world</p>`)
|
|
|
120
121
|
- note that the component instance has a render method like `element.render(2)` which can take new props at runtime
|
|
121
122
|
- **register web components to the dom**
|
|
122
123
|
```ts
|
|
123
|
-
|
|
124
|
+
dom.register({MyComponent, MyCounter})
|
|
124
125
|
// <my-component></my-component>
|
|
125
126
|
// <my-counter></my-counter>
|
|
126
127
|
```
|
|
127
|
-
-
|
|
128
|
+
- `dom.register` automatically dashes the tag names (`MyComponent` becomes `<my-component>`)
|
|
128
129
|
|
|
129
130
|
### ๐ view "use" hooks reference
|
|
130
131
|
- ๐ฎ **follow the hooks rules**
|
|
@@ -138,16 +139,26 @@ view(use => () => html`<p>hello world</p>`)
|
|
|
138
139
|
```ts
|
|
139
140
|
use.styles(css1, css2, css3)
|
|
140
141
|
```
|
|
142
|
+
*(alias `use.css`)*
|
|
141
143
|
- **use.signal** โ create a [strata signal](https://github.com/e280/strata)
|
|
142
144
|
```ts
|
|
143
|
-
const count = use.signal(1)
|
|
145
|
+
const $count = use.signal(1)
|
|
144
146
|
|
|
145
147
|
// read the signal
|
|
146
|
-
count()
|
|
148
|
+
$count()
|
|
147
149
|
|
|
148
150
|
// write the signal
|
|
149
|
-
count(2)
|
|
150
|
-
```
|
|
151
|
+
$count(2)
|
|
152
|
+
```
|
|
153
|
+
- `derive` signals
|
|
154
|
+
```ts
|
|
155
|
+
const $product = use.derive(() => $count() * $whatever())
|
|
156
|
+
```
|
|
157
|
+
- `lazy` signals
|
|
158
|
+
```ts
|
|
159
|
+
const $product = use.lazy(() => $count() * $whatever())
|
|
160
|
+
```
|
|
161
|
+
- go read the [strata readme](https://github.com/e280/strata) about this stuff
|
|
151
162
|
- **use.once** โ run fn at initialization, and return a value
|
|
152
163
|
```ts
|
|
153
164
|
const whatever = use.once(() => {
|
|
@@ -240,11 +251,11 @@ view(use => () => html`<p>hello world</p>`)
|
|
|
240
251
|
import {repeat, nap} from "@e280/stz"
|
|
241
252
|
```
|
|
242
253
|
```ts
|
|
243
|
-
const seconds = use.signal(0)
|
|
254
|
+
const $seconds = use.signal(0)
|
|
244
255
|
|
|
245
256
|
use.mount(() => repeat(async() => {
|
|
246
257
|
await nap(1000)
|
|
247
|
-
seconds.value++
|
|
258
|
+
$seconds.value++
|
|
248
259
|
}))
|
|
249
260
|
```
|
|
250
261
|
- wake + rendered, to do something after each mount's first render
|
|
@@ -254,55 +265,71 @@ view(use => () => html`<p>hello world</p>`)
|
|
|
254
265
|
}))
|
|
255
266
|
```
|
|
256
267
|
|
|
257
|
-
<br/>
|
|
258
268
|
|
|
259
|
-
## ๐ฆ sly dom multitool
|
|
260
|
-
> *"it's not jquery!"*
|
|
261
269
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
270
|
+
<br/><br/>
|
|
271
|
+
|
|
272
|
+
## ๐ฆ๐ช sly dom
|
|
273
|
+
> *the "it's not jquery!" multitool*
|
|
274
|
+
|
|
275
|
+
```ts
|
|
276
|
+
import {dom} from "@e280/sly"
|
|
277
|
+
```
|
|
267
278
|
|
|
268
|
-
###
|
|
279
|
+
### ๐ช dom queries
|
|
269
280
|
- require an element
|
|
270
281
|
```ts
|
|
271
|
-
|
|
272
|
-
// HTMLElement (or throws
|
|
282
|
+
dom(".demo")
|
|
283
|
+
// HTMLElement (or throws)
|
|
273
284
|
```
|
|
274
|
-
-
|
|
285
|
+
- maybe get an element
|
|
275
286
|
```ts
|
|
276
|
-
|
|
287
|
+
dom.maybe(".demo")
|
|
277
288
|
// HTMLElement | undefined
|
|
278
289
|
```
|
|
279
|
-
-
|
|
290
|
+
- select all elements
|
|
280
291
|
```ts
|
|
281
|
-
|
|
282
|
-
|
|
292
|
+
dom.all(".demo ul li")
|
|
293
|
+
// HTMLElement[]
|
|
283
294
|
```
|
|
284
|
-
-
|
|
295
|
+
- within a specific container
|
|
285
296
|
```ts
|
|
286
|
-
|
|
287
|
-
// HTMLElement
|
|
297
|
+
dom.in(element).require("li")
|
|
298
|
+
// HTMLElement (or throws)
|
|
288
299
|
```
|
|
289
|
-
|
|
290
|
-
### ๐ฒ dom utilities
|
|
291
|
-
- render content into an element
|
|
292
300
|
```ts
|
|
293
|
-
|
|
301
|
+
dom.in(element).maybe("li")
|
|
302
|
+
// HTMLElement | undefined
|
|
303
|
+
```
|
|
304
|
+
```ts
|
|
305
|
+
dom.in(element).all("li")
|
|
306
|
+
// HTMLElement[]
|
|
294
307
|
```
|
|
308
|
+
|
|
309
|
+
### ๐ช dom utilities
|
|
295
310
|
- register web components
|
|
296
311
|
```ts
|
|
297
|
-
|
|
312
|
+
dom.register({MyComponent, AnotherCoolComponent})
|
|
298
313
|
// <my-component>
|
|
299
314
|
// <another-cool-component>
|
|
300
315
|
```
|
|
316
|
+
- render content into an element
|
|
317
|
+
```ts
|
|
318
|
+
dom.render(element, html`<p>hello world</p>`)
|
|
319
|
+
```
|
|
320
|
+
```ts
|
|
321
|
+
dom.in(element).render(html`<p>hello world</p>`)
|
|
322
|
+
```
|
|
323
|
+
```ts
|
|
324
|
+
dom.in(".demo").render(html`<p>hello world</p>`)
|
|
325
|
+
```
|
|
326
|
+
|
|
301
327
|
|
|
302
|
-
<br/>
|
|
303
328
|
|
|
304
|
-
|
|
305
|
-
|
|
329
|
+
<br/><br/>
|
|
330
|
+
|
|
331
|
+
## ๐ฆ๐ซ sly ops
|
|
332
|
+
> *tools for async operations and loading spinners*
|
|
306
333
|
|
|
307
334
|
```ts
|
|
308
335
|
import {nap} from "@e280/stz"
|
|
@@ -426,9 +453,11 @@ import {Pod, podium, Op, makeLoader, anims} from "@e280/sly"
|
|
|
426
453
|
- when the op is in error, the error will be displayed
|
|
427
454
|
- when the op is ready, your fn is called and given the value
|
|
428
455
|
|
|
429
|
-
<br/>
|
|
430
456
|
|
|
431
|
-
|
|
457
|
+
|
|
458
|
+
<br/><br/>
|
|
459
|
+
|
|
460
|
+
## ๐ฆ๐งโ๐ป sly is by e280
|
|
432
461
|
reward us with github stars
|
|
433
462
|
build with us at https://e280.org/ but only if you're cool
|
|
434
463
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@e280/sly",
|
|
3
|
-
"version": "0.2.0-
|
|
3
|
+
"version": "0.2.0-2",
|
|
4
4
|
"description": "web shadow views",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -16,11 +16,11 @@
|
|
|
16
16
|
"lit": "^3.3.1"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@e280/strata": "^0.2.0-
|
|
19
|
+
"@e280/strata": "^0.2.0-6",
|
|
20
20
|
"@e280/stz": "^0.2.0"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@e280/science": "^0.1.
|
|
23
|
+
"@e280/science": "^0.1.2",
|
|
24
24
|
"@e280/scute": "^0.0.0",
|
|
25
25
|
"http-server": "^14.1.1",
|
|
26
26
|
"npm-run-all": "^4.1.5",
|
package/s/demo/demo.bundle.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
|
|
2
|
-
import {
|
|
2
|
+
import {dom} from "../dom/dom.js"
|
|
3
3
|
import {DemoView} from "./views/demo.js"
|
|
4
4
|
import {CounterView} from "./views/counter.js"
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
dom.in(".demo").render(DemoView())
|
|
7
|
+
dom.register({DemoCounter: CounterView.component(1)})
|
|
8
8
|
|
|
9
9
|
console.log("๐ฆ sly")
|
|
10
10
|
|
package/s/demo/views/counter.ts
CHANGED
|
@@ -9,24 +9,31 @@ export const CounterView = view(use => (initial: number) => {
|
|
|
9
9
|
use.name("counter")
|
|
10
10
|
use.styles(cssReset, styles)
|
|
11
11
|
|
|
12
|
+
const $seconds = use.signal(0)
|
|
12
13
|
const start = use.once(() => Date.now())
|
|
13
|
-
const seconds = use.signal(0)
|
|
14
|
-
|
|
15
14
|
use.mount(() => repeat(async() => {
|
|
16
15
|
const since = Date.now() - start
|
|
17
|
-
seconds.set(Math.floor(since / 1000))
|
|
16
|
+
$seconds.set(Math.floor(since / 1000))
|
|
18
17
|
}))
|
|
19
18
|
|
|
20
|
-
const count = use.signal(initial)
|
|
21
|
-
const increment = () => count.value++
|
|
19
|
+
const $count = use.signal(initial)
|
|
20
|
+
const increment = () => $count.value++
|
|
21
|
+
|
|
22
|
+
const $product = use.signal
|
|
23
|
+
.derive(() => $count() * $seconds())
|
|
22
24
|
|
|
23
25
|
return html`
|
|
24
26
|
<slot></slot>
|
|
25
27
|
<div>
|
|
26
|
-
<span>${seconds.get()}</span>
|
|
28
|
+
<span>${$seconds.get()}</span>
|
|
29
|
+
</div>
|
|
30
|
+
<div>
|
|
31
|
+
<span>${$count.get()}</span>
|
|
32
|
+
</div>
|
|
33
|
+
<div>
|
|
34
|
+
<span>${$product.get()}</span>
|
|
27
35
|
</div>
|
|
28
36
|
<div>
|
|
29
|
-
<span>${count.get()}</span>
|
|
30
37
|
<button @click="${increment}">+</button>
|
|
31
38
|
</div>
|
|
32
39
|
`
|
package/s/dom/dom.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
|
|
2
|
+
import {render} from "lit"
|
|
3
|
+
import {register} from "./register.js"
|
|
4
|
+
import {Content} from "../views/types.js"
|
|
5
|
+
import {Queryable, Renderable} from "./types.js"
|
|
6
|
+
|
|
7
|
+
export class Dom<C extends Queryable> {
|
|
8
|
+
constructor(public element: C) {}
|
|
9
|
+
|
|
10
|
+
in<E extends HTMLElement>(elementOrSelector: E | string) {
|
|
11
|
+
return new Dom(
|
|
12
|
+
typeof elementOrSelector === "string"
|
|
13
|
+
? this.require<E>(elementOrSelector)
|
|
14
|
+
: elementOrSelector
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
require<E extends Element = HTMLElement>(selector: string) {
|
|
19
|
+
const e = this.element.querySelector<E>(selector)
|
|
20
|
+
if (!e) throw new Error(`$1 ${selector} not found`)
|
|
21
|
+
return e
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
maybe<E extends Element = HTMLElement>(selector: string) {
|
|
25
|
+
return this.element.querySelector<E>(selector)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
all<E extends Element = HTMLElement>(selector: string) {
|
|
29
|
+
return Array.from(this.element.querySelectorAll<E>(selector))
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
render(...content: Content[]) {
|
|
33
|
+
return render(content, this.element as Renderable)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function dom(selector: string) {
|
|
38
|
+
return new Dom(document).require(selector)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const doc = new Dom(document)
|
|
42
|
+
dom.register = register
|
|
43
|
+
dom.render = (container: Renderable, ...content: Content[]) => {
|
|
44
|
+
return render(content, container)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
dom.in = doc.in.bind(doc)
|
|
48
|
+
dom.require = doc.require.bind(doc)
|
|
49
|
+
dom.maybe = doc.maybe.bind(doc)
|
|
50
|
+
dom.all = doc.all.bind(doc)
|
|
51
|
+
|
package/s/dom/types.ts
CHANGED
package/s/index.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
|
|
2
2
|
export * from "./dom/dashify.js"
|
|
3
|
-
export * from "./dom/dollar.js"
|
|
4
3
|
export * from "./dom/register.js"
|
|
5
4
|
export * from "./dom/types.js"
|
|
6
5
|
|
|
7
6
|
export * from "./ops/loaders/make-loader.js"
|
|
8
7
|
export * from "./ops/loaders/parts/ascii-anim.js"
|
|
9
8
|
export * from "./ops/loaders/parts/error-display.js"
|
|
10
|
-
|
|
11
9
|
export * from "./ops/op.js"
|
|
12
10
|
export * from "./ops/podium.js"
|
|
13
11
|
export * from "./ops/types.js"
|
|
14
12
|
|
|
13
|
+
export * as loot from "./loot/index.js"
|
|
14
|
+
|
|
15
15
|
export * from "./views/attributes.js"
|
|
16
16
|
export * from "./views/css-reset.js"
|
|
17
17
|
export * from "./views/types.js"
|
|
@@ -0,0 +1,76 @@
|
|
|
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
|
+
|
package/s/loot/drop.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
|
|
2
|
+
import {signal} from "@e280/strata"
|
|
3
|
+
import {dragIsOutsideCurrentTarget} from "./helpers.js"
|
|
4
|
+
|
|
5
|
+
/** dropzone that accepts dropped stuff like files */
|
|
6
|
+
export class Drop {
|
|
7
|
+
#$indicator = signal(false)
|
|
8
|
+
|
|
9
|
+
constructor(private params: {
|
|
10
|
+
|
|
11
|
+
/** whether or not the dragged item is acceptable for a drop */
|
|
12
|
+
predicate: (event: DragEvent) => boolean
|
|
13
|
+
|
|
14
|
+
/** fn to handle the drop of an acceptable item */
|
|
15
|
+
acceptDrop: (event: DragEvent) => void
|
|
16
|
+
}) {}
|
|
17
|
+
|
|
18
|
+
get indicator() {
|
|
19
|
+
return this.#$indicator.value
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
resetIndicator = () => {
|
|
23
|
+
this.#$indicator.value = false
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
dragover = (event: DragEvent) => {
|
|
27
|
+
event.preventDefault()
|
|
28
|
+
if (this.params.predicate(event))
|
|
29
|
+
this.#$indicator.value = true
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
dragleave = (event: DragEvent) => {
|
|
33
|
+
if (dragIsOutsideCurrentTarget(event))
|
|
34
|
+
this.#$indicator.value = false
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
drop = (event: DragEvent) => {
|
|
38
|
+
event.preventDefault()
|
|
39
|
+
this.#$indicator.value = false
|
|
40
|
+
if (this.params.predicate(event))
|
|
41
|
+
this.params.acceptDrop(event)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
|
|
2
|
+
export function dragHasFiles(event: DragEvent) {
|
|
3
|
+
return !!(
|
|
4
|
+
event.dataTransfer &&
|
|
5
|
+
event.dataTransfer.types.includes("Files")
|
|
6
|
+
)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function droppedFiles(event: DragEvent) {
|
|
10
|
+
return event.dataTransfer
|
|
11
|
+
? Array.from(event.dataTransfer.files)
|
|
12
|
+
: []
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function dragIsOutsideCurrentTarget(event: DragEvent) {
|
|
16
|
+
const isCursorOutsideViewport = !event.relatedTarget || (
|
|
17
|
+
event.clientX === 0 &&
|
|
18
|
+
event.clientY === 0
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
if (isCursorOutsideViewport)
|
|
22
|
+
return true
|
|
23
|
+
|
|
24
|
+
const rect = (event.currentTarget as any).getBoundingClientRect()
|
|
25
|
+
const withinX = event.clientX >= rect.left && event.clientX <= rect.right
|
|
26
|
+
const withinY = event.clientY >= rect.top && event.clientY <= rect.bottom
|
|
27
|
+
const cursorOutsideCurrentTarget = !(withinX && withinY)
|
|
28
|
+
|
|
29
|
+
return cursorOutsideCurrentTarget
|
|
30
|
+
}
|
|
31
|
+
|
package/s/loot/index.ts
ADDED
package/s/views/use.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
import {CSSResultGroup} from "lit"
|
|
3
3
|
import {defer, MapG} from "@e280/stz"
|
|
4
|
-
import {signal} from "@e280/strata/signals"
|
|
4
|
+
import {Derive, Lazy, Signal, signal, SignalOptions} from "@e280/strata/signals"
|
|
5
5
|
|
|
6
6
|
import {Op} from "../ops/op.js"
|
|
7
7
|
import {Mounts} from "./utils/mounts.js"
|
|
@@ -101,8 +101,26 @@ export class Use {
|
|
|
101
101
|
return op
|
|
102
102
|
})()
|
|
103
103
|
|
|
104
|
-
signal
|
|
105
|
-
|
|
104
|
+
signal = (() => {
|
|
105
|
+
const that = this
|
|
106
|
+
function sig<V>(value: V, options?: Partial<SignalOptions>) {
|
|
107
|
+
return that.once(() => signal<V>(value, options))
|
|
108
|
+
}
|
|
109
|
+
sig.derive = function derive<V>(formula: () => V, options?: Partial<SignalOptions>) {
|
|
110
|
+
return that.once(() => signal.derive<V>(formula, options))
|
|
111
|
+
}
|
|
112
|
+
sig.lazy = function lazy<V>(formula: () => V, options?: Partial<SignalOptions>) {
|
|
113
|
+
return that.once(() => signal.lazy<V>(formula, options))
|
|
114
|
+
}
|
|
115
|
+
return sig
|
|
116
|
+
})()
|
|
117
|
+
|
|
118
|
+
derive<V>(formula: () => V, options?: Partial<SignalOptions>) {
|
|
119
|
+
return this.once(() => signal.derive<V>(formula, options))
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
lazy<V>(formula: () => V, options?: Partial<SignalOptions>) {
|
|
123
|
+
return this.once(() => signal.lazy<V>(formula, options))
|
|
106
124
|
}
|
|
107
125
|
}
|
|
108
126
|
|
package/x/demo/demo.bundle.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { dom } from "../dom/dom.js";
|
|
2
2
|
import { DemoView } from "./views/demo.js";
|
|
3
3
|
import { CounterView } from "./views/counter.js";
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
dom.in(".demo").render(DemoView());
|
|
5
|
+
dom.register({ DemoCounter: CounterView.component(1) });
|
|
6
6
|
console.log("๐ฆ sly");
|
|
7
7
|
//# sourceMappingURL=demo.bundle.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"demo.bundle.js","sourceRoot":"","sources":["../../s/demo/demo.bundle.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,
|
|
1
|
+
{"version":3,"file":"demo.bundle.js","sourceRoot":"","sources":["../../s/demo/demo.bundle.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,GAAG,EAAC,MAAM,eAAe,CAAA;AACjC,OAAO,EAAC,QAAQ,EAAC,MAAM,iBAAiB,CAAA;AACxC,OAAO,EAAC,WAAW,EAAC,MAAM,oBAAoB,CAAA;AAE9C,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAA;AAClC,GAAG,CAAC,QAAQ,CAAC,EAAC,WAAW,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,EAAC,CAAC,CAAA;AAErD,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA"}
|