@e280/sly 0.3.0-2 โ 0.3.0-3
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 +57 -52
- package/package.json +1 -1
- package/x/index.html +1 -1
package/README.md
CHANGED
|
@@ -2,21 +2,20 @@
|
|
|
2
2
|
<div align="center"><img alt="" width="256" src="./assets/favicon.png"/></div>
|
|
3
3
|
|
|
4
4
|
# ๐ฆ sly
|
|
5
|
-
> *mischievous shadow views*
|
|
6
5
|
|
|
7
6
|
```sh
|
|
8
7
|
npm install lit @e280/sly @e280/strata @e280/stz
|
|
9
8
|
```
|
|
10
9
|
|
|
11
|
-
[@e280](https://e280.org/)'s
|
|
10
|
+
#### [@e280](https://e280.org/)'s [lit-based](https://lit.dev/) web library for reactive light or shadow views
|
|
12
11
|
|
|
13
|
-
- ๐ญ [**#views
|
|
14
|
-
- ๐ช [**#hooks
|
|
15
|
-
- ๐ซ [**#ops
|
|
16
|
-
- โณ [**#loaders
|
|
17
|
-
- ๐ช [**#loot
|
|
18
|
-
- ๐ช [**#dom
|
|
19
|
-
- ๐งช https://sly.e280.org
|
|
12
|
+
- ๐ญ [**#views,**](#views) reactive lit views, light-dom or shadow-dom
|
|
13
|
+
- ๐ช [**#hooks,**](#hooks) react-like composable hooks
|
|
14
|
+
- ๐ซ [**#ops,**](#ops) tooling for async operations ui
|
|
15
|
+
- โณ [**#loaders,**](#loaders) render ops with animated loading spinners
|
|
16
|
+
- ๐ช [**#loot,**](#loot) drag-and-drop facilities
|
|
17
|
+
- ๐ช [**#dom,**](#dom) the "it's not jquery" multitool
|
|
18
|
+
- ๐งช **https://sly.e280.org/** sly's testing page
|
|
20
19
|
|
|
21
20
|
|
|
22
21
|
|
|
@@ -24,12 +23,13 @@ npm install lit @e280/sly @e280/strata @e280/stz
|
|
|
24
23
|
<a id="views"></a>
|
|
25
24
|
|
|
26
25
|
## ๐ญ views
|
|
27
|
-
> *
|
|
26
|
+
> *"flourish in the light.. or thrive in the darkness"*
|
|
28
27
|
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
-
|
|
28
|
+
- ๐ **light or shadow,** render nakedly on the page, or within a cozy shadow bubble
|
|
29
|
+
- ๐ช **hooks-based,** familiar react-style [hooks](#hooks)
|
|
30
|
+
- โก **auto-reactive,** views magically rerender on [strata](https://github.com/e280/strata)-compatible state changes
|
|
31
|
+
- ๐ชถ **no compile step,** just god's honest javascript via [lit](https://lit.dev/)-html tagged-template-literals
|
|
32
|
+
- ๐งฉ **not web components,** no dom registration needed, just vibes and good typings
|
|
33
33
|
|
|
34
34
|
```ts
|
|
35
35
|
import {html} from "lit"
|
|
@@ -41,7 +41,7 @@ export const MyShadowView = shadow(() => html`<p>shrouded in darkness</p>`)
|
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
### ๐ light views
|
|
44
|
-
> *just pretend it's react*
|
|
44
|
+
> *"just pretend it's react, without jsx"*
|
|
45
45
|
|
|
46
46
|
- **define a light view**
|
|
47
47
|
```ts
|
|
@@ -64,9 +64,10 @@ export const MyShadowView = shadow(() => html`<p>shrouded in darkness</p>`)
|
|
|
64
64
|
${MyCounter(123)}
|
|
65
65
|
`)
|
|
66
66
|
```
|
|
67
|
+
- **light views are naked,** they don't have a containing host element
|
|
67
68
|
|
|
68
69
|
### ๐ shadow views
|
|
69
|
-
> *each shadow view gets its own cozy [shadow-dom](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM) bubble and supports [
|
|
70
|
+
> *each shadow view gets its own cozy [shadow-dom](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM) bubble and supports [slotting](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_templates_and_slots)*
|
|
70
71
|
|
|
71
72
|
- **define a shadow view**
|
|
72
73
|
```ts
|
|
@@ -81,7 +82,7 @@ export const MyShadowView = shadow(() => html`<p>shrouded in darkness</p>`)
|
|
|
81
82
|
const increment = () => $count.value++
|
|
82
83
|
|
|
83
84
|
return html`
|
|
84
|
-
<button @click="${increment}">${$count
|
|
85
|
+
<button @click="${increment}">${$count.value}</button>
|
|
85
86
|
<slot></slot>
|
|
86
87
|
`
|
|
87
88
|
})
|
|
@@ -109,12 +110,15 @@ export const MyShadowView = shadow(() => html`<p>shrouded in darkness</p>`)
|
|
|
109
110
|
```
|
|
110
111
|
- **you can do custom shadow config if needed**
|
|
111
112
|
```ts
|
|
112
|
-
const
|
|
113
|
+
const customShadow = shadow.config(() => {
|
|
113
114
|
const host = document.createElement("div")
|
|
114
115
|
const shadow = host.attachShadow({mode: "open"})
|
|
115
116
|
return {host, shadow}
|
|
116
|
-
})
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
const MyShadowView = customShadow(() => html`<p>shrouded in darkness</p>`)
|
|
117
120
|
```
|
|
121
|
+
- **shadow views are rendered inside** a `<sly-shadow>` host element by default
|
|
118
122
|
|
|
119
123
|
|
|
120
124
|
|
|
@@ -122,48 +126,48 @@ export const MyShadowView = shadow(() => html`<p>shrouded in darkness</p>`)
|
|
|
122
126
|
<a id="hooks"></a>
|
|
123
127
|
|
|
124
128
|
## ๐ช hooks
|
|
125
|
-
> *composable view state and utilities*
|
|
129
|
+
> *composable view state and utilities*
|
|
126
130
|
|
|
127
131
|
### ๐ฎ follow the hooks rules
|
|
128
132
|
|
|
129
|
-
just like [react hooks](https://react.dev/warnings/invalid-hook-call-warning), the execution order of
|
|
133
|
+
just like [react hooks](https://react.dev/warnings/invalid-hook-call-warning), the execution order of hooks seriously matters.
|
|
130
134
|
|
|
131
|
-
you must not call these hooks under
|
|
135
|
+
you must not call these hooks under if-conditionals, or for-loops, or inside callback functions, or after a conditional return statement, or anything like that.. *otherwise, heed my warning: weird bad stuff will happen..*
|
|
132
136
|
|
|
133
137
|
### ๐ shadow-only hooks
|
|
134
|
-
- **useName
|
|
138
|
+
- **useName,** set the "view" attribute value
|
|
135
139
|
```ts
|
|
136
140
|
useName("squarepants")
|
|
137
141
|
// <sly-shadow view="squarepants">
|
|
138
142
|
```
|
|
139
|
-
- **useCss
|
|
143
|
+
- **useCss,** attach stylesheets (use lit's `css`!) to the shadow root
|
|
140
144
|
```ts
|
|
141
145
|
useCss(css1, css2, css3)
|
|
142
146
|
```
|
|
143
|
-
- **useHost
|
|
147
|
+
- **useHost,** get the host element
|
|
144
148
|
```ts
|
|
145
149
|
const host = useHost()
|
|
146
150
|
```
|
|
147
|
-
- **useShadow
|
|
151
|
+
- **useShadow,** get the shadow root
|
|
148
152
|
```ts
|
|
149
153
|
const shadow = useShadow()
|
|
150
154
|
```
|
|
151
155
|
|
|
152
156
|
### ๐ universal hooks
|
|
153
|
-
- **useState
|
|
157
|
+
- **useState,** react-like hook to create some reactive state (we prefer signals)
|
|
154
158
|
```ts
|
|
155
159
|
const [count, setCount] = useState(0)
|
|
156
160
|
|
|
157
161
|
const increment = () => setCount(n => n + 1)
|
|
158
162
|
```
|
|
159
|
-
- **useRef
|
|
163
|
+
- **useRef,** react-like hook to make a non-reactive box for a value
|
|
160
164
|
```ts
|
|
161
165
|
const ref = useRef(0)
|
|
162
166
|
|
|
163
167
|
ref.current // 0
|
|
164
168
|
ref.current = 1 // does not trigger rerender
|
|
165
169
|
```
|
|
166
|
-
- **useSignal
|
|
170
|
+
- **useSignal,** create a [strata](https://github.com/e280/strata) signal
|
|
167
171
|
```ts
|
|
168
172
|
const $count = useSignal(1)
|
|
169
173
|
|
|
@@ -174,12 +178,12 @@ you must not call these hooks under `if` conditionals, or `for` loops, or in cal
|
|
|
174
178
|
$count(2)
|
|
175
179
|
```
|
|
176
180
|
- see [strata readme](https://github.com/e280/strata)
|
|
177
|
-
- **useDerived
|
|
181
|
+
- **useDerived,** create a [strata](https://github.com/e280/strata) derived signal
|
|
178
182
|
```ts
|
|
179
183
|
const $product = useDerived(() => $count() * $whatever())
|
|
180
184
|
```
|
|
181
185
|
- see [strata readme](https://github.com/e280/strata)
|
|
182
|
-
- **useOnce
|
|
186
|
+
- **useOnce,** run fn at initialization, and return a value
|
|
183
187
|
```ts
|
|
184
188
|
const whatever = useOnce(() => {
|
|
185
189
|
console.log("happens one time")
|
|
@@ -188,14 +192,14 @@ you must not call these hooks under `if` conditionals, or `for` loops, or in cal
|
|
|
188
192
|
|
|
189
193
|
whatever // 123
|
|
190
194
|
```
|
|
191
|
-
- **useMount
|
|
195
|
+
- **useMount,** setup mount/unmount lifecycle
|
|
192
196
|
```ts
|
|
193
197
|
useMount(() => {
|
|
194
198
|
console.log("mounted")
|
|
195
199
|
return () => console.log("unmounted")
|
|
196
200
|
})
|
|
197
201
|
```
|
|
198
|
-
- **useWake
|
|
202
|
+
- **useWake,** run fn each time mounted, and return value
|
|
199
203
|
```ts
|
|
200
204
|
const whatever = useWake(() => {
|
|
201
205
|
console.log("mounted")
|
|
@@ -204,7 +208,7 @@ you must not call these hooks under `if` conditionals, or `for` loops, or in cal
|
|
|
204
208
|
|
|
205
209
|
whatever // 123
|
|
206
210
|
```
|
|
207
|
-
- **useLife
|
|
211
|
+
- **useLife,** mount/unmount lifecycle, but also return a value
|
|
208
212
|
```ts
|
|
209
213
|
const whatever = useLife(() => {
|
|
210
214
|
console.log("mounted")
|
|
@@ -214,30 +218,30 @@ you must not call these hooks under `if` conditionals, or `for` loops, or in cal
|
|
|
214
218
|
|
|
215
219
|
whatever // 123
|
|
216
220
|
```
|
|
217
|
-
- **useRender
|
|
221
|
+
- **useRender,** returns a fn to rerender the view (debounced)
|
|
218
222
|
```ts
|
|
219
223
|
const render = useRender()
|
|
220
224
|
|
|
221
225
|
render().then(() => console.log("render done"))
|
|
222
226
|
```
|
|
223
|
-
- **useRendered
|
|
227
|
+
- **useRendered,** get a promise that resolves *after* the next render
|
|
224
228
|
```ts
|
|
225
229
|
useRendered().then(() => console.log("rendered"))
|
|
226
230
|
```
|
|
227
|
-
- **useOp
|
|
231
|
+
- **useOp,** start loading an op based on an async fn
|
|
228
232
|
```ts
|
|
229
233
|
const op = useOp(async() => {
|
|
230
234
|
await nap(5000)
|
|
231
235
|
return 123
|
|
232
236
|
})
|
|
233
237
|
```
|
|
234
|
-
- **useOpPromise
|
|
238
|
+
- **useOpPromise,** start loading an op based on a promise
|
|
235
239
|
```ts
|
|
236
240
|
const op = useOpPromise(doAsyncWork())
|
|
237
241
|
```
|
|
238
242
|
|
|
239
243
|
### ๐งโ๐ณ happy hooks recipes
|
|
240
|
-
- make a ticker
|
|
244
|
+
- make a ticker, mount, cycle, and nap
|
|
241
245
|
```ts
|
|
242
246
|
import {cycle, nap} from "@e280/stz"
|
|
243
247
|
```
|
|
@@ -251,7 +255,9 @@ you must not call these hooks under `if` conditionals, or `for` loops, or in cal
|
|
|
251
255
|
```
|
|
252
256
|
- wake + rendered, to do something after each mount's first render
|
|
253
257
|
```ts
|
|
254
|
-
|
|
258
|
+
const rendered = useRendered()
|
|
259
|
+
|
|
260
|
+
useWake(() => rendered.then(() => {
|
|
255
261
|
console.log("after first render")
|
|
256
262
|
}))
|
|
257
263
|
```
|
|
@@ -262,7 +268,7 @@ you must not call these hooks under `if` conditionals, or `for` loops, or in cal
|
|
|
262
268
|
<a id="ops"></a>
|
|
263
269
|
|
|
264
270
|
## ๐ซ ops
|
|
265
|
-
> *
|
|
271
|
+
> *helpers for async operations*
|
|
266
272
|
|
|
267
273
|
```ts
|
|
268
274
|
import {nap} from "@e280/stz"
|
|
@@ -300,19 +306,19 @@ import {Pod, podium, Op, loaders} from "@e280/sly"
|
|
|
300
306
|
- see more at [podium.ts](./s/ops/podium.ts)
|
|
301
307
|
|
|
302
308
|
### ๐ซ ops: nice pod ergonomics
|
|
303
|
-
- an `Op<V>` wraps a pod with a signal for reactivity
|
|
309
|
+
- an `Op<V>` wraps a pod with a strata signal for reactivity
|
|
304
310
|
- create an op
|
|
305
311
|
```ts
|
|
306
|
-
|
|
312
|
+
new Op<number>() // loading status by default
|
|
307
313
|
```
|
|
308
314
|
```ts
|
|
309
|
-
|
|
315
|
+
Op.loading<number>()
|
|
310
316
|
```
|
|
311
317
|
```ts
|
|
312
|
-
|
|
318
|
+
Op.ready<number>(123)
|
|
313
319
|
```
|
|
314
320
|
```ts
|
|
315
|
-
|
|
321
|
+
Op.error<number>(new Error())
|
|
316
322
|
```
|
|
317
323
|
- ๐ฅ create an op that calls and tracks an async fn
|
|
318
324
|
```ts
|
|
@@ -339,13 +345,12 @@ import {Pod, podium, Op, loaders} from "@e280/sly"
|
|
|
339
345
|
- select executes a fn based on the status
|
|
340
346
|
```ts
|
|
341
347
|
const result = op.select({
|
|
342
|
-
loading: () => "
|
|
348
|
+
loading: () => "still loading...",
|
|
343
349
|
ready: value => `dude, it's ready! ${value}`,
|
|
344
|
-
error: err => `
|
|
350
|
+
error: err => `ack! an error!`,
|
|
345
351
|
})
|
|
346
352
|
|
|
347
|
-
result
|
|
348
|
-
// "dude, it's ready! 123"
|
|
353
|
+
result // "dude, it's ready! 123"
|
|
349
354
|
```
|
|
350
355
|
- morph returns a new pod, transforming the value if ready
|
|
351
356
|
```ts
|
|
@@ -371,7 +376,7 @@ import {Pod, podium, Op, loaders} from "@e280/sly"
|
|
|
371
376
|
<a id="loaders"></a>
|
|
372
377
|
|
|
373
378
|
## โณ loaders
|
|
374
|
-
> *animated loading spinners for ops*
|
|
379
|
+
> *animated loading spinners for ops*
|
|
375
380
|
|
|
376
381
|
```ts
|
|
377
382
|
import {loaders} from "@e280/sly"
|
|
@@ -528,7 +533,7 @@ import {ev} from "@e280/stz"
|
|
|
528
533
|
<a id="dom"></a>
|
|
529
534
|
|
|
530
535
|
## ๐ช dom
|
|
531
|
-
> *the "it's not jquery!" multitool*
|
|
536
|
+
> *the "it's not jquery!" multitool*
|
|
532
537
|
|
|
533
538
|
```ts
|
|
534
539
|
import {dom} from "@e280/sly"
|
package/package.json
CHANGED
package/x/index.html
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
<img class=icon alt="" src="/assets/favicon.png"/>
|
|
26
26
|
<h1>sly testing page</h1>
|
|
27
27
|
<p><a href="https://github.com/e280/sly">github.com/e280/sly</a></p>
|
|
28
|
-
<p class=lil>v0.3.0-
|
|
28
|
+
<p class=lil>v0.3.0-3</p>
|
|
29
29
|
<div class="demo"></div>
|
|
30
30
|
</body>
|
|
31
31
|
</html>
|