@e280/sly 0.2.0-9 → 0.2.0
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 +363 -124
- package/package.json +14 -7
- package/s/{views/base-element.ts → base/element.ts} +18 -10
- package/s/base/index.ts +6 -0
- package/s/{views → base}/use.ts +15 -6
- package/s/{views → base}/utils/reactor.ts +13 -4
- package/s/base/utils/states.ts +49 -0
- package/s/base/utils/use-attrs.ts +36 -0
- package/s/demo/demo.bundle.ts +6 -19
- package/s/demo/views/counter.ts +14 -25
- package/s/demo/views/demo.ts +9 -16
- package/s/demo/views/{incredi.ts → fastcount.ts} +5 -5
- package/s/demo/views/loaders.ts +7 -7
- package/s/dom/attrs/attrs.ts +6 -6
- package/s/dom/attrs/parts/attr-fns.ts +64 -34
- package/s/dom/attrs/parts/attr-proxies.ts +10 -10
- package/s/dom/attrs/parts/attr-spec.ts +7 -7
- package/s/dom/dom.ts +19 -57
- package/s/dom/index.ts +4 -0
- package/s/dom/parts/dom-scope.ts +46 -0
- package/s/dom/parts/el.ts +14 -0
- package/s/dom/parts/elmer.ts +38 -0
- package/s/dom/parts/eve.ts +24 -0
- package/s/dom/parts/mk.ts +9 -0
- package/s/dom/parts/queries.ts +26 -0
- package/s/dom/types.ts +5 -0
- package/s/index.html.ts +4 -4
- package/s/index.ts +7 -17
- package/s/loaders/index.barrel.ts +10 -0
- package/s/loaders/index.ts +4 -0
- package/s/loaders/make.ts +14 -0
- package/s/loaders/mock.ts +11 -0
- package/s/{ops/loaders → loaders}/parts/anims.ts +1 -1
- package/s/{ops/loaders → loaders}/parts/ascii-anim.ts +6 -5
- package/s/{ops/loaders → loaders}/parts/error-display.ts +2 -2
- package/s/loaders/types.ts +6 -0
- package/s/loot/index.barrel.ts +5 -0
- package/s/loot/index.ts +2 -3
- package/s/ops/index.ts +5 -0
- package/s/ops/op.ts +1 -0
- package/s/spa/index.barrel.ts +6 -0
- package/s/spa/index.ts +4 -0
- package/s/spa/plumbing/braces.ts +76 -0
- package/s/spa/plumbing/primitives.ts +85 -0
- package/s/spa/plumbing/router-core.ts +49 -0
- package/s/spa/plumbing/types.ts +45 -0
- package/s/spa/router.ts +49 -0
- package/s/spa/spa.test.ts +91 -0
- package/s/tests.test.ts +4 -1
- package/s/view/index.ts +7 -0
- package/s/view/types.ts +39 -0
- package/s/view/utils/contextualize.ts +45 -0
- package/s/view/utils/make-component.ts +34 -0
- package/s/view/utils/make-view.ts +48 -0
- package/s/view/utils/parts/capsule.ts +67 -0
- package/s/view/utils/parts/chain.ts +40 -0
- package/s/view/utils/parts/context.ts +11 -0
- package/s/view/utils/parts/directive.ts +29 -0
- package/s/view/utils/parts/sly-view.ts +15 -0
- package/s/view/view.ts +24 -0
- package/x/base/css-reset.js.map +1 -0
- package/x/base/element.d.ts +19 -0
- package/x/{views/base-element.js → base/element.js} +14 -6
- package/x/base/element.js.map +1 -0
- package/x/base/index.d.ts +4 -0
- package/x/base/index.js +5 -0
- package/x/base/index.js.map +1 -0
- package/x/{views → base}/use.d.ts +6 -2
- package/x/{views → base}/use.js +12 -4
- package/x/base/use.js.map +1 -0
- package/x/base/utils/apply-styles.js.map +1 -0
- package/x/base/utils/attr-watcher.js.map +1 -0
- package/x/base/utils/mounts.js.map +1 -0
- package/x/{views → base}/utils/reactor.d.ts +0 -1
- package/x/{views → base}/utils/reactor.js +10 -3
- package/x/base/utils/reactor.js.map +1 -0
- package/x/base/utils/states.d.ts +13 -0
- package/x/base/utils/states.js +41 -0
- package/x/base/utils/states.js.map +1 -0
- package/x/base/utils/use-attrs.d.ts +11 -0
- package/x/base/utils/use-attrs.js +18 -0
- package/x/base/utils/use-attrs.js.map +1 -0
- package/x/demo/demo.bundle.js +6 -16
- package/x/demo/demo.bundle.js.map +1 -1
- package/x/demo/demo.bundle.min.js +16 -26
- package/x/demo/demo.bundle.min.js.map +4 -4
- package/x/demo/views/counter.d.ts +370 -3
- package/x/demo/views/counter.js +14 -23
- package/x/demo/views/counter.js.map +1 -1
- package/x/demo/views/demo.d.ts +4 -1
- package/x/demo/views/demo.js +9 -13
- package/x/demo/views/demo.js.map +1 -1
- package/x/demo/views/{incredi.d.ts → fastcount.d.ts} +3 -3
- package/x/demo/views/{incredi.js → fastcount.js} +5 -5
- package/x/demo/views/fastcount.js.map +1 -0
- package/x/demo/views/loaders.js +6 -6
- package/x/demo/views/loaders.js.map +1 -1
- package/x/dom/attrs/attrs.d.ts +6 -3
- package/x/dom/attrs/attrs.js +6 -6
- package/x/dom/attrs/attrs.js.map +1 -1
- package/x/dom/attrs/parts/attr-fns.d.ts +15 -12
- package/x/dom/attrs/parts/attr-fns.js +60 -38
- package/x/dom/attrs/parts/attr-fns.js.map +1 -1
- package/x/dom/attrs/parts/attr-proxies.d.ts +3 -3
- package/x/dom/attrs/parts/attr-proxies.js +10 -10
- package/x/dom/attrs/parts/attr-proxies.js.map +1 -1
- package/x/dom/attrs/parts/attr-spec.js +7 -7
- package/x/dom/attrs/parts/attr-spec.js.map +1 -1
- package/x/dom/dom.d.ts +14 -26
- package/x/dom/dom.js +18 -44
- package/x/dom/dom.js.map +1 -1
- package/x/dom/index.d.ts +2 -0
- package/x/dom/index.js +3 -0
- package/x/dom/index.js.map +1 -0
- package/x/dom/parts/dom-scope.d.ts +15 -0
- package/x/dom/parts/dom-scope.js +35 -0
- package/x/dom/parts/dom-scope.js.map +1 -0
- package/x/dom/parts/el.d.ts +2 -0
- package/x/dom/parts/el.js +7 -0
- package/x/dom/parts/el.js.map +1 -0
- package/x/dom/parts/elmer.d.ts +11 -0
- package/x/dom/parts/elmer.js +32 -0
- package/x/dom/parts/elmer.js.map +1 -0
- package/x/dom/parts/eve.d.ts +7 -0
- package/x/dom/parts/eve.js +16 -0
- package/x/dom/parts/eve.js.map +1 -0
- package/x/dom/parts/mk.d.ts +2 -0
- package/x/dom/parts/mk.js +7 -0
- package/x/dom/parts/mk.js.map +1 -0
- package/x/dom/parts/queries.d.ts +4 -0
- package/x/dom/parts/queries.js +13 -0
- package/x/dom/parts/queries.js.map +1 -0
- package/x/dom/types.d.ts +3 -0
- package/x/index.d.ts +7 -14
- package/x/index.html +6 -6
- package/x/index.html.js +4 -4
- package/x/index.js +7 -14
- package/x/index.js.map +1 -1
- package/x/loaders/index.barrel.d.ts +7 -0
- package/x/loaders/index.barrel.js +7 -0
- package/x/loaders/index.barrel.js.map +1 -0
- package/x/loaders/index.d.ts +2 -0
- package/x/loaders/index.js +2 -0
- package/x/loaders/index.js.map +1 -0
- package/x/loaders/make.d.ts +3 -0
- package/x/loaders/make.js +6 -0
- package/x/loaders/make.js.map +1 -0
- package/x/loaders/mock.d.ts +2 -0
- package/x/loaders/mock.js +8 -0
- package/x/loaders/mock.js.map +1 -0
- package/x/{ops/loaders → loaders}/parts/anims.d.ts +1 -1
- package/x/loaders/parts/anims.js.map +1 -0
- package/x/{ops/loaders → loaders}/parts/ascii-anim.d.ts +2 -2
- package/x/{ops/loaders → loaders}/parts/ascii-anim.js +4 -4
- package/x/loaders/parts/ascii-anim.js.map +1 -0
- package/x/loaders/parts/error-display.d.ts +1 -0
- package/x/{ops/loaders → loaders}/parts/error-display.js +2 -2
- package/x/loaders/parts/error-display.js.map +1 -0
- package/x/loaders/types.d.ts +3 -0
- package/x/loaders/types.js.map +1 -0
- package/x/loot/index.barrel.d.ts +3 -0
- package/x/loot/index.barrel.js +4 -0
- package/x/loot/index.barrel.js.map +1 -0
- package/x/loot/index.d.ts +2 -3
- package/x/loot/index.js +1 -3
- package/x/loot/index.js.map +1 -1
- package/x/ops/index.d.ts +3 -0
- package/x/ops/index.js +4 -0
- package/x/ops/index.js.map +1 -0
- package/x/ops/op.js +1 -0
- package/x/ops/op.js.map +1 -1
- package/x/spa/index.barrel.d.ts +4 -0
- package/x/spa/index.barrel.js +3 -0
- package/x/spa/index.barrel.js.map +1 -0
- package/x/spa/index.d.ts +2 -0
- package/x/spa/index.js +2 -0
- package/x/spa/index.js.map +1 -0
- package/x/spa/plumbing/braces.d.ts +12 -0
- package/x/spa/plumbing/braces.js +55 -0
- package/x/spa/plumbing/braces.js.map +1 -0
- package/x/spa/plumbing/primitives.d.ts +22 -0
- package/x/spa/plumbing/primitives.js +65 -0
- package/x/spa/plumbing/primitives.js.map +1 -0
- package/x/spa/plumbing/router-core.d.ts +13 -0
- package/x/spa/plumbing/router-core.js +38 -0
- package/x/spa/plumbing/router-core.js.map +1 -0
- package/x/spa/plumbing/types.d.ts +35 -0
- package/x/spa/plumbing/types.js +2 -0
- package/x/spa/plumbing/types.js.map +1 -0
- package/x/spa/router.d.ts +13 -0
- package/x/spa/router.js +39 -0
- package/x/spa/router.js.map +1 -0
- package/x/spa/spa.test.d.ts +15 -0
- package/x/spa/spa.test.js +78 -0
- package/x/spa/spa.test.js.map +1 -0
- package/x/tests.test.js +4 -1
- package/x/tests.test.js.map +1 -1
- package/x/view/index.d.ts +5 -0
- package/x/view/index.js +6 -0
- package/x/view/index.js.map +1 -0
- package/x/view/types.d.ts +21 -0
- package/x/view/types.js +2 -0
- package/x/{views → view}/types.js.map +1 -1
- package/x/view/utils/contextualize.d.ts +13 -0
- package/x/view/utils/contextualize.js +18 -0
- package/x/view/utils/contextualize.js.map +1 -0
- package/x/view/utils/make-component.d.ts +5 -0
- package/x/view/utils/make-component.js +17 -0
- package/x/view/utils/make-component.js.map +1 -0
- package/x/view/utils/make-view.d.ts +2 -0
- package/x/view/utils/make-view.js +24 -0
- package/x/view/utils/make-view.js.map +1 -0
- package/x/view/utils/parts/capsule.d.ts +13 -0
- package/x/view/utils/parts/capsule.js +49 -0
- package/x/view/utils/parts/capsule.js.map +1 -0
- package/x/view/utils/parts/chain.d.ts +13 -0
- package/x/view/utils/parts/chain.js +26 -0
- package/x/view/utils/parts/chain.js.map +1 -0
- package/x/view/utils/parts/context.d.ts +9 -0
- package/x/view/utils/parts/context.js +10 -0
- package/x/view/utils/parts/context.js.map +1 -0
- package/x/view/utils/parts/directive.d.ts +5 -0
- package/x/view/utils/parts/directive.js +18 -0
- package/x/view/utils/parts/directive.js.map +1 -0
- package/x/view/utils/parts/sly-view.d.ts +5 -0
- package/x/view/utils/parts/sly-view.js +13 -0
- package/x/view/utils/parts/sly-view.js.map +1 -0
- package/x/view/view.d.ts +11 -0
- package/x/view/view.js +15 -0
- package/x/view/view.js.map +1 -0
- package/s/demo/views/divine.ts +0 -22
- package/s/ops/loaders/make-loader.ts +0 -18
- package/s/views/types.ts +0 -49
- package/s/views/utils/apply-attrs.ts +0 -33
- package/s/views/view.ts +0 -185
- package/x/demo/views/divine.d.ts +0 -8
- package/x/demo/views/divine.js +0 -19
- package/x/demo/views/divine.js.map +0 -1
- package/x/demo/views/incredi.js.map +0 -1
- package/x/ops/loaders/make-loader.d.ts +0 -5
- package/x/ops/loaders/make-loader.js +0 -7
- package/x/ops/loaders/make-loader.js.map +0 -1
- package/x/ops/loaders/parts/anims.js.map +0 -1
- package/x/ops/loaders/parts/ascii-anim.js.map +0 -1
- package/x/ops/loaders/parts/error-display.d.ts +0 -1
- package/x/ops/loaders/parts/error-display.js.map +0 -1
- package/x/views/base-element.d.ts +0 -14
- package/x/views/base-element.js.map +0 -1
- package/x/views/css-reset.js.map +0 -1
- package/x/views/types.d.ts +0 -36
- package/x/views/use.js.map +0 -1
- package/x/views/utils/apply-attrs.d.ts +0 -2
- package/x/views/utils/apply-attrs.js +0 -21
- package/x/views/utils/apply-attrs.js.map +0 -1
- package/x/views/utils/apply-styles.js.map +0 -1
- package/x/views/utils/attr-watcher.js.map +0 -1
- package/x/views/utils/mounts.js.map +0 -1
- package/x/views/utils/reactor.js.map +0 -1
- package/x/views/view.d.ts +0 -13
- package/x/views/view.js +0 -145
- package/x/views/view.js.map +0 -1
- /package/s/{views → base}/css-reset.ts +0 -0
- /package/s/{views → base}/utils/apply-styles.ts +0 -0
- /package/s/{views → base}/utils/attr-watcher.ts +0 -0
- /package/s/{views → base}/utils/mounts.ts +0 -0
- /package/x/{views → base}/css-reset.d.ts +0 -0
- /package/x/{views → base}/css-reset.js +0 -0
- /package/x/{views → base}/utils/apply-styles.d.ts +0 -0
- /package/x/{views → base}/utils/apply-styles.js +0 -0
- /package/x/{views → base}/utils/attr-watcher.d.ts +0 -0
- /package/x/{views → base}/utils/attr-watcher.js +0 -0
- /package/x/{views → base}/utils/mounts.d.ts +0 -0
- /package/x/{views → base}/utils/mounts.js +0 -0
- /package/x/{ops/loaders → loaders}/parts/anims.js +0 -0
- /package/x/{views → loaders}/types.js +0 -0
package/README.md
CHANGED
|
@@ -4,13 +4,16 @@
|
|
|
4
4
|
# 🦝 sly
|
|
5
5
|
> *mischievous shadow views*
|
|
6
6
|
|
|
7
|
-
[@e280](https://e280.org/)'s
|
|
8
|
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
7
|
+
[@e280](https://e280.org/)'s new [lit](https://lit.dev/)-based frontend webdev library. *(sly replaces its predecessor, [slate](https://github.com/benevolent-games/slate))*
|
|
8
|
+
|
|
9
|
+
- **✨[shiny](https://shiny.e280.org/)✨** — our wip component library https://shiny.e280.org/
|
|
10
|
+
- 🍋 [**#views**](#views) — shadow-dom'd, hooks-based, componentizable
|
|
11
|
+
- 🪵 [**#base-element**](#base-element) — for a more classical experience
|
|
12
|
+
- 🪄 [**#dom**](#dom) — the "it's not jquery" multitool
|
|
13
|
+
- 🫛 [**#ops**](#ops) — reactive tooling for async operations
|
|
14
|
+
- ⏳ [**#loaders**](#loaders) — animated loading spinners for rendering ops
|
|
15
|
+
- 💅 [**#spa**](#spa) — hash routing for your spa-day
|
|
16
|
+
- 🪙 [**#loot**](#loot) — drag-and-drop facilities
|
|
14
17
|
- 🧪 testing page — https://sly.e280.org/
|
|
15
18
|
|
|
16
19
|
|
|
@@ -18,6 +21,7 @@
|
|
|
18
21
|
<br/><br/>
|
|
19
22
|
|
|
20
23
|
## 🦝 sly and friends
|
|
24
|
+
> `@e280/sly`
|
|
21
25
|
|
|
22
26
|
```sh
|
|
23
27
|
npm install @e280/sly lit @e280/strata @e280/stz
|
|
@@ -29,81 +33,87 @@ npm install @e280/sly lit @e280/strata @e280/stz
|
|
|
29
33
|
> - 🏂 [@e280/stz](https://github.com/e280/stz), our ts standard library
|
|
30
34
|
> - 🐢 [@e280/scute](https://github.com/e280/scute), our buildy-bundly-buddy
|
|
31
35
|
|
|
36
|
+
> [!TIP]
|
|
37
|
+
> you can import everything in sly from `@e280/sly`,
|
|
38
|
+
> or from specific subpackages like `@e280/sly/view`, `@e280/sly/dom`, etc...
|
|
39
|
+
|
|
32
40
|
|
|
33
41
|
|
|
34
42
|
<br/><br/>
|
|
35
43
|
<a id="views"></a>
|
|
36
44
|
|
|
37
|
-
##
|
|
38
|
-
>
|
|
45
|
+
## 🍋🦝 sly views
|
|
46
|
+
> `@e280/sly/view`
|
|
47
|
+
> *the crown jewel of sly*
|
|
39
48
|
|
|
40
49
|
```ts
|
|
41
50
|
view(use => () => html`<p>hello world</p>`)
|
|
42
51
|
```
|
|
43
52
|
|
|
44
|
-
-
|
|
45
|
-
-
|
|
46
|
-
-
|
|
47
|
-
-
|
|
53
|
+
- 🪶 **no compile step** — just god's honest javascript, via [lit](https://lit.dev/)-html tagged-template-literals
|
|
54
|
+
- 🥷 **shadow dom'd** — each view gets its own cozy [shadow](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM) bubble, and supports [slots](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_templates_and_slots)
|
|
55
|
+
- 🪝 **hooks-based** — declarative rendering with the [`use`](#use) family of ergonomic hooks
|
|
56
|
+
- ⚡ **reactive** — they auto-rerender whenever any [strata](https://github.com/e280/strata)-compatible state changes
|
|
57
|
+
- 🧐 **not components, per se** — they're comfy typescript-native ui building blocks [(technically, lit directives)](https://lit.dev/docs/templates/custom-directives/)
|
|
58
|
+
- 🧩 **componentizable** — any view can be magically converted into a proper [web component](https://developer.mozilla.org/en-US/docs/Web/API/Web_components)
|
|
48
59
|
|
|
49
60
|
### 🍋 view example
|
|
50
61
|
```ts
|
|
51
|
-
import {view, dom} from "@e280/sly"
|
|
62
|
+
import {view, dom, BaseElement} from "@e280/sly"
|
|
52
63
|
import {html, css} from "lit"
|
|
53
64
|
```
|
|
54
|
-
- **declare
|
|
65
|
+
- **declare view**
|
|
55
66
|
```ts
|
|
56
67
|
export const CounterView = view(use => (start: number) => {
|
|
57
|
-
use.name("counter")
|
|
58
68
|
use.styles(css`p {color: green}`)
|
|
59
69
|
|
|
60
70
|
const $count = use.signal(start)
|
|
61
71
|
const increment = () => $count.value++
|
|
62
72
|
|
|
63
73
|
return html`
|
|
64
|
-
<
|
|
65
|
-
|
|
74
|
+
<button @click="${increment}">
|
|
75
|
+
${$count.value}
|
|
76
|
+
</button>
|
|
66
77
|
`
|
|
67
78
|
})
|
|
68
79
|
```
|
|
69
|
-
-
|
|
70
|
-
- **inject
|
|
80
|
+
- `$count` is a [strata signal](https://github.com/e280/strata#readme) *(we like those)*
|
|
81
|
+
- **inject view into dom**
|
|
71
82
|
```ts
|
|
72
83
|
dom.in(".app").render(html`
|
|
73
84
|
<h1>cool counter demo</h1>
|
|
74
85
|
${CounterView(1)}
|
|
75
86
|
`)
|
|
76
87
|
```
|
|
77
|
-
- 🤯 **register
|
|
88
|
+
- 🤯 **register view as web component**
|
|
78
89
|
```ts
|
|
79
90
|
dom.register({
|
|
80
91
|
MyCounter: CounterView
|
|
81
92
|
.component()
|
|
82
|
-
.props(
|
|
93
|
+
.props(() => [1]),
|
|
83
94
|
})
|
|
84
95
|
```
|
|
85
96
|
```html
|
|
86
|
-
<my-counter
|
|
97
|
+
<my-counter></my-counter>
|
|
87
98
|
```
|
|
88
99
|
|
|
89
|
-
### 🍋 view
|
|
90
|
-
-
|
|
100
|
+
### 🍋 view settings
|
|
101
|
+
- optional settings for views you should know about
|
|
91
102
|
```ts
|
|
92
103
|
export const CoolView = view
|
|
93
104
|
.settings({mode: "open", delegatesFocus: true})
|
|
94
|
-
.render(use => (greeting: string) => {
|
|
95
|
-
return html`😎 ${greeting} <slot></slot>`
|
|
96
|
-
})
|
|
105
|
+
.render(use => (greeting: string) => html`😎 ${greeting} <slot></slot>`)
|
|
97
106
|
```
|
|
98
107
|
- all [attachShadow params](https://developer.mozilla.org/en-US/docs/Web/API/Element/attachShadow#parameters) (like `mode` and `delegatesFocus`) are valid `settings`
|
|
99
108
|
- note the `<slot></slot>` we'll use in the next example lol
|
|
100
109
|
|
|
101
|
-
### 🍋 view
|
|
102
|
-
-
|
|
110
|
+
### 🍋 view chains
|
|
111
|
+
- views have this sick chaining syntax for supplying more stuff at the template injection site
|
|
103
112
|
```ts
|
|
104
113
|
dom.in(".app").render(html`
|
|
105
114
|
<h2>cool example</h2>
|
|
106
|
-
${CoolView
|
|
115
|
+
${CoolView
|
|
116
|
+
.props("hello")
|
|
107
117
|
.attr("class", "hero")
|
|
108
118
|
.children(html`<em>spongebob</em>`)
|
|
109
119
|
.render()}
|
|
@@ -111,78 +121,100 @@ import {html, css} from "lit"
|
|
|
111
121
|
```
|
|
112
122
|
- `props` — provide props and start a view chain
|
|
113
123
|
- `attr` — set html attributes on the `<sly-view>` host element
|
|
114
|
-
- `children` — nested
|
|
124
|
+
- `children` — add nested [slottable](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_templates_and_slots) content
|
|
115
125
|
- `render` — end the view chain and render the lit directive
|
|
116
126
|
|
|
117
127
|
### 🍋 view/component universality
|
|
118
|
-
- **start with a view,**
|
|
128
|
+
- **you can start with a view,**
|
|
119
129
|
```ts
|
|
120
130
|
export const GreeterView = view(use => (name: string) => {
|
|
121
131
|
return html`<p>hello ${name}</p>`
|
|
122
132
|
})
|
|
123
|
-
|
|
124
|
-
// view usage:
|
|
125
|
-
// GreeterView("pimsley")
|
|
126
133
|
```
|
|
127
|
-
|
|
134
|
+
- view usage
|
|
135
|
+
```ts
|
|
136
|
+
GreeterView("pimsley")
|
|
137
|
+
```
|
|
138
|
+
**then you can convert it to a component.**
|
|
128
139
|
```ts
|
|
129
|
-
export class GreeterComponent extends (
|
|
130
|
-
|
|
131
|
-
|
|
140
|
+
export class GreeterComponent extends (
|
|
141
|
+
GreeterView
|
|
142
|
+
.component()
|
|
143
|
+
.props(component => [component.getAttribute("name") ?? "unknown"])
|
|
132
144
|
) {}
|
|
133
|
-
|
|
134
|
-
// html usage:
|
|
135
|
-
// <greeter-component name="pimsley"></greeter-component>
|
|
136
145
|
```
|
|
137
|
-
-
|
|
146
|
+
- html usage
|
|
147
|
+
```html
|
|
148
|
+
<greeter-component name="pimsley"></greeter-component>
|
|
149
|
+
```
|
|
150
|
+
- **you can start with a component,**
|
|
138
151
|
```ts
|
|
139
|
-
export class GreeterComponent extends (
|
|
140
|
-
|
|
141
|
-
.props(component => [component.getAttribute("name") ?? "unknown"])
|
|
142
|
-
.render(use => (name: string) => {
|
|
152
|
+
export class GreeterComponent extends (
|
|
153
|
+
view(use => (name: string) => {
|
|
143
154
|
return html`<p>hello ${name}</p>`
|
|
144
155
|
})
|
|
156
|
+
.component()
|
|
157
|
+
.props(component => [component.getAttribute("name") ?? "unknown"])
|
|
145
158
|
) {}
|
|
146
|
-
|
|
147
|
-
// html usage:
|
|
148
|
-
// <greeter-component name="pimsley"></greeter-component>
|
|
149
|
-
```
|
|
150
|
-
then you can already use it as a view
|
|
151
|
-
```ts
|
|
152
|
-
// view usage:
|
|
153
|
-
// GreeterComponent.view("pimsley")
|
|
154
159
|
```
|
|
155
|
-
-
|
|
160
|
+
- html usage
|
|
161
|
+
```html
|
|
162
|
+
<greeter-component name="pimsley"></greeter-component>
|
|
163
|
+
```
|
|
164
|
+
**and it already has `.view` ready for you.**
|
|
165
|
+
- view usage
|
|
166
|
+
```ts
|
|
167
|
+
GreeterComponent.view("pimsley")
|
|
168
|
+
```
|
|
169
|
+
- **understanding `.component(BaseElement)` and `.props(fn)`**
|
|
156
170
|
- `.props` takes a fn that is called every render, which returns the props given to the view
|
|
157
171
|
```ts
|
|
158
|
-
.component()
|
|
159
172
|
.props(() => ["pimsley"])
|
|
160
173
|
```
|
|
161
|
-
the props fn receives the component instance, so you can query html attributes
|
|
174
|
+
the props fn receives the component instance, so you can query html attributes or instance properties
|
|
162
175
|
```ts
|
|
163
|
-
.component()
|
|
164
176
|
.props(component => [component.getAttribute("name") ?? "unknown"])
|
|
165
177
|
```
|
|
166
|
-
- `.component`
|
|
178
|
+
- `.component` accepts a subclass of `BaseElement`, so you can define your own properties and methods for your component class
|
|
167
179
|
```ts
|
|
168
|
-
|
|
169
|
-
|
|
180
|
+
const GreeterComponent = GreeterView
|
|
181
|
+
|
|
182
|
+
// declare your own custom class
|
|
183
|
+
.component(class extends BaseElement {
|
|
184
|
+
$name = signal("jim raynor")
|
|
185
|
+
updateName(name: string) {
|
|
186
|
+
this.$name.value = name
|
|
187
|
+
}
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
// props gets the right types on 'component'
|
|
191
|
+
.props(component => [component.$name.value])
|
|
170
192
|
```
|
|
171
|
-
- `.component`
|
|
193
|
+
- `.component` provides the devs interacting with your component, with noice typings
|
|
172
194
|
```ts
|
|
173
|
-
|
|
174
|
-
component.$name = signal("pimsley")
|
|
175
|
-
})
|
|
176
|
-
.props(component => [component.$name])
|
|
177
|
-
```
|
|
178
|
-
- `.component` lets you set instance properties, that devs can interact with via the dom
|
|
179
|
-
```ts
|
|
180
|
-
dom<GreeterComponent>("my-component").$name.value = "mortimer"
|
|
195
|
+
dom<GreeterComponent>("greeter-component").updateName("mortimer")
|
|
181
196
|
```
|
|
197
|
+
- typescript class wizardry
|
|
198
|
+
- ❌ smol-brain approach exports class value, but NOT the typings
|
|
199
|
+
```ts
|
|
200
|
+
export const GreeterComponent = (...)
|
|
201
|
+
```
|
|
202
|
+
- ✅ giga-brain approach exports class value AND the typings
|
|
203
|
+
```ts
|
|
204
|
+
export class GreeterComponent extends (...) {}
|
|
205
|
+
```
|
|
182
206
|
- **register web components to the dom**
|
|
183
207
|
```ts
|
|
184
208
|
dom.register({GreeterComponent})
|
|
185
209
|
```
|
|
210
|
+
- **oh and don't miss out on the insta-component shorthand**
|
|
211
|
+
```ts
|
|
212
|
+
dom.register({
|
|
213
|
+
QuickComponent: view.component(use => html`⚡ incredi`),
|
|
214
|
+
})
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
<a id="use"></a>
|
|
186
218
|
|
|
187
219
|
### 🍋 "use" hooks reference
|
|
188
220
|
- 👮 **follow the hooks rules**
|
|
@@ -254,20 +286,46 @@ import {html, css} from "lit"
|
|
|
254
286
|
|
|
255
287
|
v // 123
|
|
256
288
|
```
|
|
257
|
-
- **use.
|
|
258
|
-
*(see [dom.attrs](#dom.attrs) for more details)*
|
|
289
|
+
- **use.events** — attach event listeners to the element (auto-cleaned up)
|
|
259
290
|
```ts
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
active: Boolean,
|
|
291
|
+
use.events({
|
|
292
|
+
keydown: (e: KeyboardEvent) => console.log("keydown", e.code),
|
|
293
|
+
keyup: (e: KeyboardEvent) => console.log("keyup", e.code),
|
|
264
294
|
})
|
|
265
295
|
```
|
|
296
|
+
- **use.states** — [internal states](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/states) helper
|
|
266
297
|
```ts
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
298
|
+
const states = use.states()
|
|
299
|
+
states.assign("active", "cool")
|
|
300
|
+
```
|
|
301
|
+
```css
|
|
302
|
+
[view="my-view"]::state(active) { color: yellow; }
|
|
303
|
+
[view="my-view"]::state(cool) { outline: 1px solid cyan; }
|
|
270
304
|
```
|
|
305
|
+
- **use.attrs** — ergonomic typed html attribute access
|
|
306
|
+
- `use.attrs` is similar to [#dom.attrs](#dom.attrs)
|
|
307
|
+
```ts
|
|
308
|
+
const attrs = use.attrs({
|
|
309
|
+
name: String,
|
|
310
|
+
count: Number,
|
|
311
|
+
active: Boolean,
|
|
312
|
+
})
|
|
313
|
+
```
|
|
314
|
+
```ts
|
|
315
|
+
attrs.name // "chase"
|
|
316
|
+
attrs.count // 123
|
|
317
|
+
attrs.active // true
|
|
318
|
+
```
|
|
319
|
+
- use.attrs.{strings/numbers/booleans}
|
|
320
|
+
```ts
|
|
321
|
+
use.attrs.strings.name // "chase"
|
|
322
|
+
use.attrs.numbers.count // 123
|
|
323
|
+
use.attrs.booleans.active // true
|
|
324
|
+
```
|
|
325
|
+
- use.attrs.on
|
|
326
|
+
```ts
|
|
327
|
+
use.attrs.on(() => console.log("an attribute changed"))
|
|
328
|
+
```
|
|
271
329
|
- **use.render** — rerender the view (debounced)
|
|
272
330
|
```ts
|
|
273
331
|
use.render()
|
|
@@ -296,14 +354,14 @@ import {html, css} from "lit"
|
|
|
296
354
|
```
|
|
297
355
|
|
|
298
356
|
### 🍋 "use" recipes
|
|
299
|
-
- make a ticker — mount,
|
|
357
|
+
- make a ticker — mount, cycle, and nap
|
|
300
358
|
```ts
|
|
301
|
-
import {
|
|
359
|
+
import {cycle, nap} from "@e280/stz"
|
|
302
360
|
```
|
|
303
361
|
```ts
|
|
304
362
|
const $seconds = use.signal(0)
|
|
305
363
|
|
|
306
|
-
use.mount(() =>
|
|
364
|
+
use.mount(() => cycle(async() => {
|
|
307
365
|
await nap(1000)
|
|
308
366
|
$seconds.value++
|
|
309
367
|
}))
|
|
@@ -320,19 +378,36 @@ import {html, css} from "lit"
|
|
|
320
378
|
<br/><br/>
|
|
321
379
|
<a id="base-element"></a>
|
|
322
380
|
|
|
323
|
-
##
|
|
324
|
-
>
|
|
381
|
+
## 🪵🦝 sly base element
|
|
382
|
+
> `@e280/sly/base`
|
|
383
|
+
> *the classic experience*
|
|
325
384
|
|
|
326
385
|
```ts
|
|
327
386
|
import {BaseElement, Use, dom} from "@e280/sly"
|
|
328
387
|
import {html, css} from "lit"
|
|
329
388
|
```
|
|
330
389
|
|
|
331
|
-
`BaseElement` is
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
390
|
+
`BaseElement` is more of an old-timey class-based "boomer" approach to making web components, but with a millennial twist — its `render` method gives you the same `use` hooks that views enjoy.
|
|
391
|
+
|
|
392
|
+
👮 a *BaseElement* is not a *View*, and cannot be converted into a *View*.
|
|
393
|
+
|
|
394
|
+
### 🪵 let's clarify some sly terminology
|
|
395
|
+
- "Element"
|
|
396
|
+
- an html element; any subclass of the browser's HTMLElement
|
|
397
|
+
- all genuine ["web components"](https://developer.mozilla.org/en-US/docs/Web/API/Web_components) are elements
|
|
398
|
+
- "BaseElement"
|
|
399
|
+
- sly's own subclass of the browser-native HTMLElement
|
|
400
|
+
- is a true element and web component (can be registered to the dom)
|
|
401
|
+
- "View"
|
|
402
|
+
- sly's own magic concept that uses a lit-directive to render stuff
|
|
403
|
+
- NOT an element or web component (can NOT be registered to the dom)
|
|
404
|
+
- NOT related to BaseElement
|
|
405
|
+
- can be converted into a Component via `view.component().props(() => [])`
|
|
406
|
+
- "Component"
|
|
407
|
+
- a sly view that has been converted into an element
|
|
408
|
+
- is a true element and web component (can be registered to the dom)
|
|
409
|
+
- actually a subclass of BaseElement
|
|
410
|
+
- actually contains the view on `Component.view`
|
|
336
411
|
|
|
337
412
|
### 🪵 base element setup
|
|
338
413
|
- **declare your element class**
|
|
@@ -341,7 +416,7 @@ base element enjoys the same `use` hooks as views.
|
|
|
341
416
|
static styles = css`span{color:orange}`
|
|
342
417
|
|
|
343
418
|
// custom property
|
|
344
|
-
start = 10
|
|
419
|
+
$start = signal(10)
|
|
345
420
|
|
|
346
421
|
// custom attributes
|
|
347
422
|
attrs = dom.attrs(this).spec({
|
|
@@ -357,9 +432,9 @@ base element enjoys the same `use` hooks as views.
|
|
|
357
432
|
const $count = use.signal(1)
|
|
358
433
|
const increment = () => $count.value++
|
|
359
434
|
|
|
360
|
-
const {start} = this
|
|
435
|
+
const {$start} = this
|
|
361
436
|
const {multiply = 1} = this.attrs
|
|
362
|
-
const result = start + (multiply * $count())
|
|
437
|
+
const result = $start() + (multiply * $count())
|
|
363
438
|
|
|
364
439
|
return html`
|
|
365
440
|
<span>${result}</span>
|
|
@@ -385,7 +460,7 @@ base element enjoys the same `use` hooks as views.
|
|
|
385
460
|
const myElement = dom<MyElement>("my-element")
|
|
386
461
|
|
|
387
462
|
// js property
|
|
388
|
-
myElement
|
|
463
|
+
myElement.$start(100)
|
|
389
464
|
|
|
390
465
|
// html attributes
|
|
391
466
|
myElement.attrs.multiply = 2
|
|
@@ -400,8 +475,9 @@ base element enjoys the same `use` hooks as views.
|
|
|
400
475
|
<br/><br/>
|
|
401
476
|
<a id="dom"></a>
|
|
402
477
|
|
|
403
|
-
##
|
|
404
|
-
>
|
|
478
|
+
## 🪄🦝 sly dom
|
|
479
|
+
> `@e280/sly/dom`
|
|
480
|
+
> *the "it's not jquery!" multitool*
|
|
405
481
|
|
|
406
482
|
```ts
|
|
407
483
|
import {dom} from "@e280/sly"
|
|
@@ -413,49 +489,98 @@ import {dom} from "@e280/sly"
|
|
|
413
489
|
dom(".demo")
|
|
414
490
|
// HTMLElement (or throws)
|
|
415
491
|
```
|
|
492
|
+
```ts
|
|
493
|
+
// alias
|
|
494
|
+
dom.require(".demo")
|
|
495
|
+
// HTMLElement (or throws)
|
|
496
|
+
```
|
|
416
497
|
- `maybe` get an element
|
|
417
498
|
```ts
|
|
418
499
|
dom.maybe(".demo")
|
|
419
500
|
// HTMLElement | undefined
|
|
420
501
|
```
|
|
421
|
-
- `
|
|
502
|
+
- `all` matching elements in an array
|
|
422
503
|
```ts
|
|
423
504
|
dom.all(".demo ul li")
|
|
424
505
|
// HTMLElement[]
|
|
425
506
|
```
|
|
426
|
-
|
|
507
|
+
|
|
508
|
+
### 🪄 dom.in scope
|
|
509
|
+
- make a scope
|
|
427
510
|
```ts
|
|
428
|
-
dom
|
|
429
|
-
//
|
|
511
|
+
dom.in(".demo") // selector
|
|
512
|
+
// Dom instance
|
|
430
513
|
```
|
|
431
514
|
```ts
|
|
432
|
-
dom
|
|
433
|
-
//
|
|
515
|
+
dom.in(demoElement) // element
|
|
516
|
+
// Dom instance
|
|
434
517
|
```
|
|
518
|
+
- run queries in that scope
|
|
435
519
|
```ts
|
|
436
|
-
dom(
|
|
437
|
-
|
|
520
|
+
dom.in(demoElement).require(".button")
|
|
521
|
+
```
|
|
522
|
+
```ts
|
|
523
|
+
dom.in(demoElement).maybe(".button")
|
|
524
|
+
```
|
|
525
|
+
```ts
|
|
526
|
+
dom.in(demoElement).all("ol li")
|
|
438
527
|
```
|
|
439
528
|
|
|
440
529
|
### 🪄 dom utilities
|
|
441
|
-
- `register` web components
|
|
530
|
+
- `dom.register` web components
|
|
442
531
|
```ts
|
|
443
532
|
dom.register({MyComponent, AnotherCoolComponent})
|
|
444
533
|
// <my-component>
|
|
445
534
|
// <another-cool-component>
|
|
446
535
|
```
|
|
447
536
|
- `dom.register` automatically dashes the tag names (`MyComponent` becomes `<my-component>`)
|
|
448
|
-
- `render` content into an element
|
|
537
|
+
- `dom.render` content into an element
|
|
449
538
|
```ts
|
|
450
|
-
dom
|
|
539
|
+
dom.render(element, html`<p>hello world</p>`)
|
|
451
540
|
```
|
|
452
541
|
```ts
|
|
453
542
|
dom.in(".demo").render(html`<p>hello world</p>`)
|
|
454
543
|
```
|
|
544
|
+
- `dom.el` little element builder
|
|
455
545
|
```ts
|
|
456
|
-
dom.
|
|
546
|
+
const div = dom.el("div", {"data-whatever": 123, "data-active": true})
|
|
547
|
+
// <div data-whatever="123" data-active></div>
|
|
548
|
+
```
|
|
549
|
+
- `dom.elmer` make an element with a fluent chain
|
|
550
|
+
```ts
|
|
551
|
+
const div = dom.elmer("div")
|
|
552
|
+
.attr("data-whatever", 123)
|
|
553
|
+
.attr("data-active")
|
|
554
|
+
.children("hello world")
|
|
555
|
+
.done()
|
|
556
|
+
// HTMLElement
|
|
557
|
+
```
|
|
558
|
+
- `dom.mk` make an element with a lit template (returns the first)
|
|
559
|
+
```ts
|
|
560
|
+
const div = dom.mk(html`
|
|
561
|
+
<div data-whatever="123" data-active>
|
|
562
|
+
hello world
|
|
563
|
+
</div>
|
|
564
|
+
`) // HTMLElement
|
|
565
|
+
```
|
|
566
|
+
- `dom.events` <a id="dom.events"></a> to attach event listeners
|
|
567
|
+
```ts
|
|
568
|
+
const detach = dom.events(element, {
|
|
569
|
+
keydown: (e: KeyboardEvent) => console.log("keydown", e.code),
|
|
570
|
+
keyup: (e: KeyboardEvent) => console.log("keyup", e.code),
|
|
571
|
+
})
|
|
572
|
+
```
|
|
573
|
+
```ts
|
|
574
|
+
const detach = dom.in(".demo").events({
|
|
575
|
+
keydown: (e: KeyboardEvent) => console.log("keydown", e.code),
|
|
576
|
+
keyup: (e: KeyboardEvent) => console.log("keyup", e.code),
|
|
577
|
+
})
|
|
457
578
|
```
|
|
458
|
-
|
|
579
|
+
```ts
|
|
580
|
+
// unattach those event listeners when you're done
|
|
581
|
+
detach()
|
|
582
|
+
```
|
|
583
|
+
- `dom.attrs` <a id="dom.attrs"></a> to setup a type-happy html attribute helper
|
|
459
584
|
```ts
|
|
460
585
|
const attrs = dom.attrs(element).spec({
|
|
461
586
|
name: String,
|
|
@@ -464,6 +589,13 @@ import {dom} from "@e280/sly"
|
|
|
464
589
|
})
|
|
465
590
|
```
|
|
466
591
|
```ts
|
|
592
|
+
const attrs = dom.in(".demo").attrs.spec({
|
|
593
|
+
name: String,
|
|
594
|
+
count: Number,
|
|
595
|
+
active: Boolean,
|
|
596
|
+
})
|
|
597
|
+
```
|
|
598
|
+
```ts
|
|
467
599
|
attrs.name // "chase"
|
|
468
600
|
attrs.count // 123
|
|
469
601
|
attrs.active // true
|
|
@@ -477,11 +609,12 @@ import {dom} from "@e280/sly"
|
|
|
477
609
|
attrs.name = undefined // removes the attr
|
|
478
610
|
attrs.count = undefined // removes the attr
|
|
479
611
|
```
|
|
480
|
-
or if you wanna be more loosey-
|
|
612
|
+
or if you wanna be more loosey-goosey, skip the spec
|
|
481
613
|
```ts
|
|
482
|
-
dom.
|
|
483
|
-
|
|
484
|
-
|
|
614
|
+
const a = dom.in(".demo").attrs
|
|
615
|
+
a.strings.name = "pimsley"
|
|
616
|
+
a.numbers.count = 125
|
|
617
|
+
a.booleans.active = true
|
|
485
618
|
```
|
|
486
619
|
|
|
487
620
|
|
|
@@ -489,12 +622,13 @@ import {dom} from "@e280/sly"
|
|
|
489
622
|
<br/><br/>
|
|
490
623
|
<a id="ops"></a>
|
|
491
624
|
|
|
492
|
-
##
|
|
493
|
-
>
|
|
625
|
+
## 🫛🦝 sly ops
|
|
626
|
+
> `@e280/sly/ops`
|
|
627
|
+
> *tools for async operations and loading spinners*
|
|
494
628
|
|
|
495
629
|
```ts
|
|
496
630
|
import {nap} from "@e280/stz"
|
|
497
|
-
import {Pod, podium, Op,
|
|
631
|
+
import {Pod, podium, Op, loaders} from "@e280/sly"
|
|
498
632
|
```
|
|
499
633
|
|
|
500
634
|
### 🫛 pods: loading/ready/error
|
|
@@ -593,14 +727,29 @@ import {Pod, podium, Op, makeLoader, anims} from "@e280/sly"
|
|
|
593
727
|
- loading if any ops are in loading, otherwise
|
|
594
728
|
- ready if all the ops are ready
|
|
595
729
|
|
|
596
|
-
|
|
597
|
-
|
|
730
|
+
|
|
731
|
+
|
|
732
|
+
<br/><br/>
|
|
733
|
+
<a id="loaders"></a>
|
|
734
|
+
|
|
735
|
+
## ⏳🦝 sly loaders
|
|
736
|
+
> `@e280/sly/loaders`
|
|
737
|
+
> *animated loading spinners for ops*
|
|
738
|
+
|
|
739
|
+
```ts
|
|
740
|
+
import {loaders} from "@e280/sly"
|
|
741
|
+
```
|
|
742
|
+
|
|
743
|
+
### ⏳ make a loader, choose an anim
|
|
744
|
+
- create a loader fn
|
|
598
745
|
```ts
|
|
599
|
-
const loader =
|
|
746
|
+
const loader = loaders.make(loaders.anims.dots)
|
|
600
747
|
```
|
|
601
748
|
- see all the anims available on the testing page https://sly.e280.org/
|
|
602
749
|
- ngl, i made too many.. *i was having fun, okay?*
|
|
603
|
-
|
|
750
|
+
|
|
751
|
+
### ⏳ render an op with it
|
|
752
|
+
- use your loader to render an op
|
|
604
753
|
```ts
|
|
605
754
|
return html`
|
|
606
755
|
<h2>cool stuff</h2>
|
|
@@ -616,11 +765,101 @@ import {Pod, podium, Op, makeLoader, anims} from "@e280/sly"
|
|
|
616
765
|
|
|
617
766
|
|
|
618
767
|
|
|
768
|
+
<br/><br/>
|
|
769
|
+
<a id="spa"></a>
|
|
770
|
+
|
|
771
|
+
## 💅🦝 sly spa
|
|
772
|
+
> `@e280/sly/spa`
|
|
773
|
+
> *hash router for single-page-apps*
|
|
774
|
+
|
|
775
|
+
```ts
|
|
776
|
+
import {spa, html} from "@e280/sly"
|
|
777
|
+
```
|
|
778
|
+
|
|
779
|
+
### 💅 spa.Router basics
|
|
780
|
+
- **make a spa router**
|
|
781
|
+
```ts
|
|
782
|
+
const router = new spa.Router({
|
|
783
|
+
routes: {
|
|
784
|
+
home: spa.route("#/", async() => html`home`),
|
|
785
|
+
settings: spa.route("#/settings", async() => html`settings`),
|
|
786
|
+
user: spa.route("#/user/{userId}", async({userId}) => html`user ${userId}`),
|
|
787
|
+
},
|
|
788
|
+
})
|
|
789
|
+
```
|
|
790
|
+
- all route strings must start with `#/`
|
|
791
|
+
- use braces like `{userId}` to accept string params
|
|
792
|
+
- home-equivalent hashes like `""` and `"#"` are normalized to `"#/"`
|
|
793
|
+
- the router has an effect on the appearance of the url in the browser address bar -- the home `#/` is removed, aesthetically, eg, `e280.org/#/` is rewritten to `e280.org` using *history.replaceState*
|
|
794
|
+
- you can provide `loader` option if you want to specify the loading spinner (defaults to `loaders.make()`)
|
|
795
|
+
- you can provide `notFound` option, if you want to specify what is shown on invalid routes (defaults to `() => null`)
|
|
796
|
+
- when `auto` is true (default), the router calls `.refresh()` and `.listen()` in the constructor.. set it to `false` if you want manual control
|
|
797
|
+
- you can set `auto` option false if you want to omit the default initial refresh and listen calls
|
|
798
|
+
- **render your current page**
|
|
799
|
+
```ts
|
|
800
|
+
return html`
|
|
801
|
+
<div class="my-page">
|
|
802
|
+
${router.render()}
|
|
803
|
+
</div>
|
|
804
|
+
`
|
|
805
|
+
```
|
|
806
|
+
- returns lit content
|
|
807
|
+
- shows a loading spinner when pages are loading
|
|
808
|
+
- will display the notFound content for invalid routes (defaults to null)
|
|
809
|
+
- **perform navigations**
|
|
810
|
+
- go to settings page
|
|
811
|
+
```ts
|
|
812
|
+
await router.nav.settings.go()
|
|
813
|
+
// goes to "#/settings"
|
|
814
|
+
```
|
|
815
|
+
- go to user page
|
|
816
|
+
```ts
|
|
817
|
+
await router.nav.user.go("123")
|
|
818
|
+
// goes to "#/user/123"
|
|
819
|
+
```
|
|
820
|
+
|
|
821
|
+
### 💅 spa.Router advanced
|
|
822
|
+
- **generate a route's hash string**
|
|
823
|
+
```ts
|
|
824
|
+
const hash = router.nav.user.hash("123")
|
|
825
|
+
// "#/user/123"
|
|
826
|
+
|
|
827
|
+
html`<a href="${hash}">user 123</a>`
|
|
828
|
+
```
|
|
829
|
+
- **check if a route is the currently-active one**
|
|
830
|
+
```ts
|
|
831
|
+
const hash = router.nav.user.active
|
|
832
|
+
// true
|
|
833
|
+
```
|
|
834
|
+
- **force-refresh the router**
|
|
835
|
+
```ts
|
|
836
|
+
await router.refresh()
|
|
837
|
+
```
|
|
838
|
+
- **force-navigate the router by hash**
|
|
839
|
+
```ts
|
|
840
|
+
await router.refresh("#/user/123")
|
|
841
|
+
```
|
|
842
|
+
- **get the current hash string (normalized)**
|
|
843
|
+
```ts
|
|
844
|
+
router.hash
|
|
845
|
+
// "#/user/123"
|
|
846
|
+
```
|
|
847
|
+
- **the `route(...)` helper fn enables the braces-params syntax**
|
|
848
|
+
- but, if you wanna do it differently, you *can* implement your own hash parser to do your own funky syntax
|
|
849
|
+
- **dispose the router when you're done with it**
|
|
850
|
+
```ts
|
|
851
|
+
router.dispose()
|
|
852
|
+
// stop listening to hashchange events
|
|
853
|
+
```
|
|
854
|
+
|
|
855
|
+
|
|
856
|
+
|
|
619
857
|
<br/><br/>
|
|
620
858
|
<a id="loot"></a>
|
|
621
859
|
|
|
622
|
-
##
|
|
623
|
-
>
|
|
860
|
+
## 🪙🦝 loot
|
|
861
|
+
> `@e280/sly/loot`
|
|
862
|
+
> *drag-and-drop facilities*
|
|
624
863
|
|
|
625
864
|
```ts
|
|
626
865
|
import {loot, view, dom} from "@e280/sly"
|
|
@@ -741,7 +980,7 @@ import {ev} from "@e280/stz"
|
|
|
741
980
|
<br/><br/>
|
|
742
981
|
<a id="e280"></a>
|
|
743
982
|
|
|
744
|
-
##
|
|
983
|
+
## 🧑💻🦝 sly is by e280
|
|
745
984
|
reward us with github stars
|
|
746
985
|
build with us at https://e280.org/ but only if you're cool
|
|
747
986
|
|