@e280/sly 0.0.0-3 → 0.0.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 +108 -87
- package/package.json +3 -3
- package/s/demo/demo.bundle.ts +3 -47
- package/s/demo/demo.css +13 -6
- package/s/demo/views/counter.ts +42 -0
- package/s/demo/views/demo.ts +25 -0
- package/s/demo/views/loaders.ts +58 -0
- package/s/features/dom/dollar.ts +13 -9
- package/s/features/op/loaders/make-loader.ts +18 -0
- package/s/features/op/loaders/parts/anims.ts +277 -0
- package/s/features/op/loaders/parts/ascii-anim.ts +38 -0
- package/s/features/{loady → op/loaders}/parts/error-display.ts +10 -10
- package/s/features/op/op.ts +42 -20
- package/s/features/op/podium.ts +67 -0
- package/s/features/views/types.ts +9 -2
- package/s/features/views/use.ts +20 -9
- package/s/features/views/view.ts +15 -8
- package/s/index.html.ts +3 -3
- package/s/index.ts +4 -3
- package/x/demo/demo.bundle.js +2 -36
- package/x/demo/demo.bundle.js.map +1 -1
- package/x/demo/demo.bundle.min.js +61 -12
- package/x/demo/demo.bundle.min.js.map +4 -4
- package/x/demo/demo.css +13 -6
- package/x/demo/views/counter.d.ts +1 -0
- package/x/demo/views/counter.js +34 -0
- package/x/demo/views/counter.js.map +1 -0
- package/x/demo/views/demo.d.ts +1 -0
- package/x/demo/views/demo.js +21 -0
- package/x/demo/views/demo.js.map +1 -0
- package/x/demo/views/loaders.d.ts +1 -0
- package/x/demo/views/loaders.js +50 -0
- package/x/demo/views/loaders.js.map +1 -0
- package/x/features/dom/dollar.d.ts +6 -5
- package/x/features/dom/dollar.js +8 -7
- package/x/features/dom/dollar.js.map +1 -1
- package/x/features/op/loaders/make-loader.d.ts +5 -0
- package/x/features/op/loaders/make-loader.js +7 -0
- package/x/features/op/loaders/make-loader.js.map +1 -0
- package/x/features/op/loaders/parts/anims.d.ts +24 -0
- package/x/features/op/loaders/parts/anims.js +251 -0
- package/x/features/op/loaders/parts/anims.js.map +1 -0
- package/x/features/op/loaders/parts/ascii-anim.d.ts +6 -0
- package/x/features/op/loaders/parts/ascii-anim.js +26 -0
- package/x/features/op/loaders/parts/ascii-anim.js.map +1 -0
- package/x/features/op/loaders/parts/error-display.d.ts +1 -0
- package/x/features/{loady → op/loaders}/parts/error-display.js +9 -9
- package/x/features/op/loaders/parts/error-display.js.map +1 -0
- package/x/features/op/op.d.ts +12 -3
- package/x/features/op/op.js +33 -17
- package/x/features/op/op.js.map +1 -1
- package/x/features/op/podium.d.ts +9 -0
- package/x/features/op/podium.js +53 -0
- package/x/features/op/podium.js.map +1 -0
- package/x/features/views/types.d.ts +9 -2
- package/x/features/views/use.d.ts +8 -6
- package/x/features/views/use.js +21 -10
- package/x/features/views/use.js.map +1 -1
- package/x/features/views/view.d.ts +2 -10
- package/x/features/views/view.js +12 -6
- package/x/features/views/view.js.map +1 -1
- package/x/index.d.ts +4 -3
- package/x/index.html +18 -11
- package/x/index.html.js +3 -3
- package/x/index.html.js.map +1 -1
- package/x/index.js +4 -3
- package/x/index.js.map +1 -1
- package/s/features/loady/ascii-loader.ts +0 -38
- package/s/features/loady/parts/ascii-anim.ts +0 -27
- package/s/features/loady/parts/ascii-loader.ts +0 -14
- package/s/features/op/pod.ts +0 -19
- package/x/features/loady/ascii-loader.d.ts +0 -5
- package/x/features/loady/ascii-loader.js +0 -33
- package/x/features/loady/ascii-loader.js.map +0 -1
- package/x/features/loady/parts/ascii-anim.d.ts +0 -8
- package/x/features/loady/parts/ascii-anim.js +0 -21
- package/x/features/loady/parts/ascii-anim.js.map +0 -1
- package/x/features/loady/parts/ascii-loader.d.ts +0 -3
- package/x/features/loady/parts/ascii-loader.js +0 -10
- package/x/features/loady/parts/ascii-loader.js.map +0 -1
- package/x/features/loady/parts/error-display.d.ts +0 -8
- package/x/features/loady/parts/error-display.js.map +0 -1
- package/x/features/op/pod.d.ts +0 -5
- package/x/features/op/pod.js +0 -16
- package/x/features/op/pod.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
|
|
2
2
|
<div align="center"><img alt="" width="256" src="./assets/favicon.png"/></div>
|
|
3
3
|
|
|
4
|
-
# 🦝 sly —
|
|
5
|
-
|
|
4
|
+
# 🦝 sly — mischievous shadow views
|
|
5
|
+
> testing page at https://sly.e280.org/
|
|
6
|
+
|
|
7
|
+
- 🪒 lean view framework for [lit](https://lit.dev/) web devs
|
|
6
8
|
- 🌅 sly is the successor to [@benev/slate](https://github.com/benevolent-games/slate)
|
|
7
9
|
- 🏂 commonly used with stz standard library [@e280/stz](https://github.com/e280/stz)
|
|
8
10
|
- ⛏️ integrates signals and state trees from [@e280/strata](https://github.com/e280/strata)
|
|
@@ -11,8 +13,7 @@
|
|
|
11
13
|
|
|
12
14
|
<br/>
|
|
13
15
|
|
|
14
|
-
## 🦝 INSTALL SLY AND
|
|
15
|
-
they all super work together.
|
|
16
|
+
## 🦝 INSTALL SLY AND PALS
|
|
16
17
|
|
|
17
18
|
```sh
|
|
18
19
|
npm install @e280/sly @e280/stz @e280/strata lit
|
|
@@ -20,50 +21,90 @@ npm install @e280/sly @e280/stz @e280/strata lit
|
|
|
20
21
|
|
|
21
22
|
<br/>
|
|
22
23
|
|
|
23
|
-
## 🦝 VIEWS
|
|
24
|
+
## 🦝 SLY VIEWS
|
|
24
25
|
views are the crown jewel of sly. shadow-dom'd. hooks-based. fancy ergonomics. not components.
|
|
25
26
|
|
|
26
|
-
views are leaner than web components.. no dom registration, string tag names.. just import 'em, and the types work.. web components are fine, but they're for providing html authors with entrypoints to your cool widgets.. whereas views are the building blocks for frontend app devs.
|
|
27
|
+
views are leaner than web components.. no dom registration, no string tag names.. just import 'em, and the types work.. web components are fine, but they're for providing html authors with entrypoints to your cool widgets.. whereas views are the building blocks for frontend app devs.
|
|
27
28
|
|
|
28
29
|
sly views are wired to automatically rerender whenever they're using any state stuff from [@e280/strata](https://github.com/e280/strata).
|
|
29
30
|
|
|
30
31
|
### 🍋 basic view example
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
import {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
-
|
|
32
|
+
- views are hooks-based functional components with a [shadow root](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM)
|
|
33
|
+
- **declaring a view**
|
|
34
|
+
```ts
|
|
35
|
+
import {view} from "@e280/sly"
|
|
36
|
+
import {html, css} from "lit"
|
|
37
|
+
|
|
38
|
+
export const CounterView = view(use => (start: number) => {
|
|
39
|
+
use.name("counter")
|
|
40
|
+
use.styles(css`p {color: green}`)
|
|
41
|
+
const count = use.signal(start)
|
|
42
|
+
|
|
43
|
+
return html`
|
|
44
|
+
<p>count ${count()}</p>
|
|
45
|
+
<button @click="${() => { count.value++ }}"></button>
|
|
46
|
+
`
|
|
47
|
+
})
|
|
48
|
+
```
|
|
49
|
+
- each view renders into a `<sly-view>` host, with the provided `name` set as its view attribute, eg `<sly-view view="counter">`
|
|
50
|
+
- **injecting a view into the dom**
|
|
51
|
+
```ts
|
|
52
|
+
import {render, html} from "lit"
|
|
53
|
+
import {CounterView} from "./my-counter.js"
|
|
50
54
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
+
const content = html`
|
|
56
|
+
<h1>my demo page</h1>
|
|
57
|
+
${CounterView(1)}
|
|
58
|
+
`
|
|
55
59
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
${CounterView(1)}
|
|
59
|
-
`
|
|
60
|
+
render(content, document.querySelector(".app")!)
|
|
61
|
+
```
|
|
60
62
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
+
### 🍋 view declaration settings
|
|
64
|
+
- special settings for views at declaration-time
|
|
65
|
+
```ts
|
|
66
|
+
import {view} from "@e280/sly"
|
|
67
|
+
import {html} from "lit"
|
|
63
68
|
|
|
64
|
-
|
|
65
|
-
|
|
69
|
+
export const CoolView = view
|
|
70
|
+
.settings({mode: "open", delegatesFocus: true})
|
|
71
|
+
.view(use => (greeting: string) => {
|
|
72
|
+
|
|
73
|
+
return html`😎 ${greeting} <slot></slot>`
|
|
74
|
+
})
|
|
75
|
+
```
|
|
76
|
+
- these `settings` like `mode` and `delegatesFocus` are [attachShadow params](https://developer.mozilla.org/en-US/docs/Web/API/Element/attachShadow#parameters)
|
|
77
|
+
- note the `<slot></slot>` we'll use in the next example lol
|
|
66
78
|
|
|
79
|
+
### 🍋 view injection options
|
|
80
|
+
- options for views at the template injection site
|
|
81
|
+
```ts
|
|
82
|
+
import {render, html} from "lit"
|
|
83
|
+
import {CoolView} from "./cool-view.js"
|
|
84
|
+
|
|
85
|
+
const content = html`
|
|
86
|
+
<h2>super cool example</h2>
|
|
87
|
+
${CoolView
|
|
88
|
+
.attr("class", "hero")
|
|
89
|
+
.children(html`<em>spongebob</em>`)
|
|
90
|
+
.props("hello")}
|
|
91
|
+
`
|
|
92
|
+
|
|
93
|
+
render(content, document.querySelector(".app")!)
|
|
94
|
+
```
|
|
95
|
+
- `attr` — set html attributes on the `<sly-view>` host element
|
|
96
|
+
- `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)
|
|
97
|
+
- `props` — finally inject the view by providing its props
|
|
98
|
+
|
|
99
|
+
### 🍋 view `use` reference
|
|
100
|
+
- **use.name** — set the "view" attr value, eg `<sly-view view="squarepants">`
|
|
101
|
+
```ts
|
|
102
|
+
use.name("squarepants")
|
|
103
|
+
```
|
|
104
|
+
- **use.styles** — attach stylesheets into the view's shadow dom
|
|
105
|
+
```ts
|
|
106
|
+
use.styles(css1, css2, css3)
|
|
107
|
+
```
|
|
67
108
|
- **use.signal** — create a [strata signal](https://github.com/e280/strata)
|
|
68
109
|
```ts
|
|
69
110
|
const count = use.signal(1)
|
|
@@ -93,25 +134,40 @@ render(content, document.body)
|
|
|
93
134
|
}
|
|
94
135
|
})
|
|
95
136
|
```
|
|
96
|
-
- **use.
|
|
137
|
+
- **use.life** — mount/unmount lifecycle, but also return a value
|
|
97
138
|
```ts
|
|
98
|
-
use.
|
|
139
|
+
const v = use.life(() => {
|
|
140
|
+
console.log("mounted")
|
|
141
|
+
const value = 123
|
|
142
|
+
return [value, () => console.log("unmounted")]
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
v //-> 123
|
|
99
146
|
```
|
|
100
|
-
- **use.
|
|
147
|
+
- **use.render** — force a hard render (not debounced)
|
|
101
148
|
```ts
|
|
102
|
-
use.
|
|
149
|
+
use.render()
|
|
103
150
|
```
|
|
104
|
-
- **use.rendered** — promise that resolves *after*
|
|
151
|
+
- **use.rendered** — promise that resolves *after* the next render
|
|
105
152
|
```ts
|
|
106
153
|
use.rendered.then(() => {
|
|
107
154
|
const slot = use.shadow.querySelector("slot")!
|
|
108
155
|
console.log(slot)
|
|
109
156
|
})
|
|
110
157
|
```
|
|
158
|
+
- **use.op.fn** — start with an op based on an async fn
|
|
159
|
+
```ts
|
|
160
|
+
const op = use.op.fn(async() => {
|
|
161
|
+
await nap(5000)
|
|
162
|
+
return 123
|
|
163
|
+
})
|
|
164
|
+
```
|
|
165
|
+
- **use.op.promise** — start with an op based on a promise
|
|
166
|
+
```ts
|
|
167
|
+
const op = use.op.promise(doAsyncWork())
|
|
168
|
+
```
|
|
111
169
|
|
|
112
170
|
### 🍋 neat tricks to impress the ladies
|
|
113
|
-
> common patterns and snippets
|
|
114
|
-
|
|
115
171
|
- make a ticker — mount, repeat, and nap
|
|
116
172
|
```ts
|
|
117
173
|
import {repeat, nap} from "@e280/stz"
|
|
@@ -131,55 +187,20 @@ render(content, document.body)
|
|
|
131
187
|
}))
|
|
132
188
|
```
|
|
133
189
|
|
|
134
|
-
### 🍋 view declaration settings
|
|
135
|
-
> special settings for views at declaration-time
|
|
136
|
-
|
|
137
|
-
```ts
|
|
138
|
-
import {view} from "@e280/sly"
|
|
139
|
-
import {html} from "lit"
|
|
140
|
-
|
|
141
|
-
export const CoolView = view
|
|
142
|
-
.settings({mode: "open", delegatesFocus: true})
|
|
143
|
-
.view(use => (greeting: string) => {
|
|
144
|
-
|
|
145
|
-
return html`😎 ${greeting} <slot></slot>`
|
|
146
|
-
})
|
|
147
|
-
```
|
|
148
|
-
- these `settings` like `mode` and `delegatesFocus` are [attachShadow params](https://developer.mozilla.org/en-US/docs/Web/API/Element/attachShadow#parameters)
|
|
149
|
-
- note the `<slot></slot>` we'll use in the next example lol
|
|
150
|
-
|
|
151
|
-
### 🍋 view injection options
|
|
152
|
-
> options for views at the template injection site
|
|
153
|
-
|
|
154
|
-
```ts
|
|
155
|
-
import {render, html} from "lit"
|
|
156
|
-
import {CoolView} from "./cool-view.js"
|
|
157
|
-
|
|
158
|
-
const content = html`
|
|
159
|
-
<h2>super cool example</h2>
|
|
160
|
-
${CoolView
|
|
161
|
-
.attr("class", "hero")
|
|
162
|
-
.children(html`<em>spongebob</em>`)
|
|
163
|
-
.props("hello")}
|
|
164
|
-
`
|
|
165
|
-
|
|
166
|
-
render(content, document.body)
|
|
167
|
-
```
|
|
168
|
-
- `attr` — set html attributes on the `<sly-view>` host element
|
|
169
|
-
- `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)
|
|
170
|
-
- `props` — finally inject the view by providing its props
|
|
171
|
-
|
|
172
190
|
<br/>
|
|
173
191
|
|
|
174
|
-
## 🦝 OPS
|
|
175
|
-
> ***TODO*** *
|
|
176
|
-
- `Pod` is a type for
|
|
192
|
+
## 🦝 SLY OPS, PODS, AND LOADERS
|
|
193
|
+
> ***TODO*** *we need to write real docs for this, lol*
|
|
194
|
+
- `Pod` is a type for loading/ready/error states
|
|
195
|
+
- `podium` is a tool with fns for working with pods
|
|
177
196
|
- `Op` class wraps a pod signal and has some ergonomic fns
|
|
178
|
-
- `
|
|
197
|
+
- `makeLoader(anims.bar2)` makes it easy to create a loader
|
|
198
|
+
- see the available `anims` on the testing page: https://sly.e280.org/
|
|
199
|
+
- a loader's job is to render an op, with a nice loading anim and error display view
|
|
179
200
|
|
|
180
201
|
<br/>
|
|
181
202
|
|
|
182
|
-
## 🧑💻
|
|
203
|
+
## 🧑💻 SLY BY E280
|
|
183
204
|
reward us with github stars
|
|
184
205
|
build with us at https://e280.org/ but only if you're cool
|
|
185
206
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@e280/sly",
|
|
3
|
-
"version": "0.0.0-
|
|
3
|
+
"version": "0.0.0-5",
|
|
4
4
|
"description": "web shadow views",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
"s"
|
|
14
14
|
],
|
|
15
15
|
"peerDependencies": {
|
|
16
|
-
"@e280/stz": "^0.0.0-35",
|
|
17
16
|
"@e280/strata": "^0.0.0-10",
|
|
17
|
+
"@e280/stz": "^0.0.0-36",
|
|
18
18
|
"lit": "^3.3.1"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
},
|
|
27
27
|
"scripts": {
|
|
28
28
|
"build": "run-s _clean _ln _tsc _scute",
|
|
29
|
-
"
|
|
29
|
+
"start": "octo 'scute -vw' 'tsc -w' 'node --watch x/tests.test.js' 'http-server x'",
|
|
30
30
|
"count": "find s -path '*/_archive' -prune -o -name '*.ts' -exec wc -l {} +",
|
|
31
31
|
"test": "node x/tests.test.js",
|
|
32
32
|
"test-inspect": "node inspect x/tests.test.js",
|
package/s/demo/demo.bundle.ts
CHANGED
|
@@ -1,52 +1,8 @@
|
|
|
1
1
|
|
|
2
|
-
import {
|
|
3
|
-
import {css, html, render} from "lit"
|
|
4
|
-
|
|
2
|
+
import {DemoView} from "./views/demo.js"
|
|
5
3
|
import {$} from "../features/dom/dollar.js"
|
|
6
|
-
import {view} from "../features/views/view.js"
|
|
7
|
-
import {cssReset} from "../features/views/css-reset.js"
|
|
8
|
-
import {loady} from "../features/loady/ascii-loader.js"
|
|
9
|
-
|
|
10
|
-
console.log("🦝 sly")
|
|
11
|
-
|
|
12
|
-
const styles = css`
|
|
13
|
-
:host {
|
|
14
|
-
display: flex;
|
|
15
|
-
flex-direction: column;
|
|
16
|
-
justify-content: center;
|
|
17
|
-
text-align: center;
|
|
18
|
-
}
|
|
19
|
-
`
|
|
20
|
-
|
|
21
|
-
const MyView = view(use => (greeting: string) => {
|
|
22
|
-
use.name("my-view")
|
|
23
|
-
use.styles(cssReset, styles)
|
|
24
|
-
const count = use.signal(0)
|
|
25
4
|
|
|
26
|
-
|
|
27
|
-
await nap(1000)
|
|
28
|
-
count.value++
|
|
29
|
-
}))
|
|
5
|
+
$.render($(".demo"), DemoView())
|
|
30
6
|
|
|
31
|
-
|
|
32
|
-
console.log("slot", $("slot", use.shadow))
|
|
33
|
-
}))
|
|
34
|
-
|
|
35
|
-
const op = use.op.fn(async() => {
|
|
36
|
-
await nap(5000)
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
return html`
|
|
40
|
-
<p>${greeting} <slot></slot> ${count()}</p>
|
|
41
|
-
<p>${loady.dots(op, () => "op loaded")}</p>
|
|
42
|
-
`
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
render(
|
|
46
|
-
MyView
|
|
47
|
-
.attr("class", "incredi")
|
|
48
|
-
.children("world")
|
|
49
|
-
.props("hello"),
|
|
50
|
-
$(".demo"),
|
|
51
|
-
)
|
|
7
|
+
console.log("🦝 sly")
|
|
52
8
|
|
package/s/demo/demo.css
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
:root {
|
|
6
6
|
--prime: #1eff00;
|
|
7
7
|
--accent: #387d42;
|
|
8
|
+
--pill: #12763959;
|
|
8
9
|
--bg: #0e2316;
|
|
9
10
|
--link: cyan;
|
|
10
11
|
}
|
|
@@ -51,15 +52,12 @@
|
|
|
51
52
|
|
|
52
53
|
@layer page {
|
|
53
54
|
:root {
|
|
54
|
-
color-scheme: dark;
|
|
55
|
-
|
|
56
|
-
padding: 5vw 0.5em;
|
|
57
|
-
min-height: 100%;
|
|
58
|
-
scrollbar-gutter: stable;
|
|
59
|
-
|
|
60
55
|
font-size: 21px;
|
|
61
56
|
font-family: sans-serif;
|
|
62
57
|
|
|
58
|
+
color-scheme: dark;
|
|
59
|
+
scrollbar-gutter: stable;
|
|
60
|
+
|
|
63
61
|
color: color-mix(in lch, var(--prime), #fff8 50%);
|
|
64
62
|
background: radial-gradient(
|
|
65
63
|
circle,
|
|
@@ -69,6 +67,11 @@
|
|
|
69
67
|
}
|
|
70
68
|
|
|
71
69
|
body {
|
|
70
|
+
width: 100%;
|
|
71
|
+
max-width: 32em;
|
|
72
|
+
margin: auto;
|
|
73
|
+
padding: 1em;
|
|
74
|
+
|
|
72
75
|
display: flex;
|
|
73
76
|
flex-direction: column;
|
|
74
77
|
align-items: center;
|
|
@@ -88,6 +91,10 @@
|
|
|
88
91
|
font-size: 0.8em;
|
|
89
92
|
}
|
|
90
93
|
|
|
94
|
+
.demo {
|
|
95
|
+
width: 100%;
|
|
96
|
+
}
|
|
97
|
+
|
|
91
98
|
:not(:defined) {
|
|
92
99
|
display: none;
|
|
93
100
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
|
|
2
|
+
import {css, html} from "lit"
|
|
3
|
+
import {repeat} from "@e280/stz"
|
|
4
|
+
|
|
5
|
+
import {view} from "../../features/views/view.js"
|
|
6
|
+
import {cssReset} from "../../features/views/css-reset.js"
|
|
7
|
+
|
|
8
|
+
export const CounterView = view(use => () => {
|
|
9
|
+
use.name("counter")
|
|
10
|
+
use.styles(cssReset, styles)
|
|
11
|
+
|
|
12
|
+
const start = use.once(() => Date.now())
|
|
13
|
+
const seconds = use.signal(0)
|
|
14
|
+
|
|
15
|
+
use.mount(() => repeat(async() => {
|
|
16
|
+
const since = Date.now() - start
|
|
17
|
+
seconds(Math.floor(since / 1000))
|
|
18
|
+
}))
|
|
19
|
+
|
|
20
|
+
const count = use.signal(0)
|
|
21
|
+
const increment = () => count(count() + 1)
|
|
22
|
+
|
|
23
|
+
return html`
|
|
24
|
+
<div>
|
|
25
|
+
<span>${seconds()}</span>
|
|
26
|
+
</div>
|
|
27
|
+
<div>
|
|
28
|
+
<span>${count()}</span>
|
|
29
|
+
<button @click="${increment}">+</button>
|
|
30
|
+
</div>
|
|
31
|
+
`
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
const styles = css`
|
|
35
|
+
:host {
|
|
36
|
+
display: flex;
|
|
37
|
+
flex-direction: column;
|
|
38
|
+
justify-content: center;
|
|
39
|
+
text-align: center;
|
|
40
|
+
}
|
|
41
|
+
`
|
|
42
|
+
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
|
|
2
|
+
import {css, html} from "lit"
|
|
3
|
+
import {CounterView} from "./counter.js"
|
|
4
|
+
import {LoadersView} from "./loaders.js"
|
|
5
|
+
import {view} from "../../features/views/view.js"
|
|
6
|
+
import {cssReset} from "../../features/views/css-reset.js"
|
|
7
|
+
|
|
8
|
+
export const DemoView = view(use => () => {
|
|
9
|
+
use.name("demo")
|
|
10
|
+
use.styles(cssReset, styles)
|
|
11
|
+
|
|
12
|
+
return html`
|
|
13
|
+
${CounterView()}
|
|
14
|
+
${LoadersView()}
|
|
15
|
+
`
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
const styles = css`
|
|
19
|
+
:host {
|
|
20
|
+
display: flex;
|
|
21
|
+
flex-direction: column;
|
|
22
|
+
gap: 1em;
|
|
23
|
+
}
|
|
24
|
+
`
|
|
25
|
+
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
|
|
2
|
+
import {css, html} from "lit"
|
|
3
|
+
import {Op} from "../../features/op/op.js"
|
|
4
|
+
import {view} from "../../features/views/view.js"
|
|
5
|
+
import {cssReset} from "../../features/views/css-reset.js"
|
|
6
|
+
import {anims, makeLoader} from "../../features/op/loaders/make-loader.js"
|
|
7
|
+
|
|
8
|
+
export const LoadersView = view(use => () => {
|
|
9
|
+
use.name("loaders")
|
|
10
|
+
use.styles(cssReset, styles)
|
|
11
|
+
|
|
12
|
+
const op = use.once(() => Op.loading())
|
|
13
|
+
|
|
14
|
+
const loaders = use.once(() =>
|
|
15
|
+
Object.entries(anims).map(([key, anim]) => ({
|
|
16
|
+
key,
|
|
17
|
+
loader: makeLoader(anim)
|
|
18
|
+
}))
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
return loaders.map(({key, loader}) => html`
|
|
22
|
+
<div data-anim="${key}">
|
|
23
|
+
<span>${key}</span>
|
|
24
|
+
<span>${loader(op, () => null)}</span>
|
|
25
|
+
</div>
|
|
26
|
+
`)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
const styles = css`
|
|
30
|
+
:host {
|
|
31
|
+
display: flex;
|
|
32
|
+
flex-direction: row;
|
|
33
|
+
justify-content: center;
|
|
34
|
+
flex-wrap: wrap;
|
|
35
|
+
|
|
36
|
+
gap: 0.2em;
|
|
37
|
+
padding: 1em;
|
|
38
|
+
|
|
39
|
+
width: 100%;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
div {
|
|
43
|
+
font-family: monospace;
|
|
44
|
+
|
|
45
|
+
display: flex;
|
|
46
|
+
flex-direction: column;
|
|
47
|
+
align-items: center;
|
|
48
|
+
gap: 0.4em;
|
|
49
|
+
|
|
50
|
+
padding: 0.2em 0.5em;
|
|
51
|
+
background: var(--pill);
|
|
52
|
+
border-radius: 0.5em;
|
|
53
|
+
|
|
54
|
+
span:nth-child(1) { font-size: 0.6em; }
|
|
55
|
+
span:nth-child(2) { font-size: 1.2em; }
|
|
56
|
+
}
|
|
57
|
+
`
|
|
58
|
+
|
package/s/features/dom/dollar.ts
CHANGED
|
@@ -1,21 +1,25 @@
|
|
|
1
1
|
|
|
2
|
-
|
|
2
|
+
import {render} from "lit"
|
|
3
|
+
import {Content} from "../views/types.js"
|
|
3
4
|
|
|
4
|
-
export type
|
|
5
|
+
export type Container = HTMLElement | ShadowRoot | DocumentFragment
|
|
6
|
+
export type Queryable = HTMLElement | ShadowRoot | Element | Document | DocumentFragment
|
|
5
7
|
|
|
6
|
-
function
|
|
7
|
-
return Array.from(context.querySelectorAll<E>(selector))
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
function one<E extends HTMLElement = HTMLElement>(selector: string, context: Queryable = document) {
|
|
8
|
+
export function $<E extends HTMLElement = HTMLElement>(selector: string, context: Queryable = document) {
|
|
11
9
|
const e = context.querySelector<E>(selector)
|
|
12
10
|
if (!e) throw new Error(`$1 ${selector} not found`)
|
|
13
11
|
return e
|
|
14
12
|
}
|
|
15
13
|
|
|
16
|
-
|
|
14
|
+
function all<E extends HTMLElement = HTMLElement>(selector: string, context: Queryable = document) {
|
|
15
|
+
return Array.from(context.querySelectorAll<E>(selector))
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
$.maybe = <E extends HTMLElement = HTMLElement>(selector: string, context: Queryable = document) => {
|
|
17
19
|
return context.querySelector<E>(selector)
|
|
18
20
|
}
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
$.all = all
|
|
23
|
+
|
|
24
|
+
$.render = (container: Container, ...content: Content[]) => render(content, container)
|
|
21
25
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
|
|
2
|
+
import {Op} from "../op.js"
|
|
3
|
+
import {braille} from "./parts/anims.js"
|
|
4
|
+
import {Content} from "../../views/types.js"
|
|
5
|
+
import {ErrorDisplay} from "./parts/error-display.js"
|
|
6
|
+
|
|
7
|
+
export * as anims from "./parts/anims.js"
|
|
8
|
+
|
|
9
|
+
export type Loader = <V>(op: Op<V>, ready: (value: V) => Content) => Content
|
|
10
|
+
|
|
11
|
+
export function makeLoader(
|
|
12
|
+
loading: () => Content = braille,
|
|
13
|
+
error: (error: any) => Content = (error: any) => ErrorDisplay(error),
|
|
14
|
+
): Loader {
|
|
15
|
+
|
|
16
|
+
return (op, ready) => op.select({loading, ready, error})
|
|
17
|
+
}
|
|
18
|
+
|