@e280/shiny 0.1.0-1 → 0.1.0-11
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 +113 -3
- package/package.json +3 -3
- package/s/components/button/component.ts +30 -0
- package/s/components/button/style.css.ts +64 -0
- package/s/{ui → components}/copy/component.ts +11 -6
- package/s/{ui → components}/copy/style.css.ts +6 -6
- package/s/components/drawer/component.ts +92 -0
- package/s/components/drawer/control.ts +31 -0
- package/s/components/drawer/style.css.ts +120 -0
- package/s/{ui → components}/example/component.ts +7 -5
- package/s/{ui → components}/example/style.css.ts +2 -2
- package/s/components/foundation.css.ts +15 -0
- package/s/components/framework.ts +10 -0
- package/s/components/raw-components.ts +15 -0
- package/s/components/tabs/component.ts +70 -0
- package/s/components/tabs/control.ts +31 -0
- package/s/components/tabs/style.css.ts +43 -0
- package/s/demo/aura-views.ts +6 -0
- package/s/demo/demo.bundle.ts +287 -14
- package/s/demo/demo.css +3 -1
- package/s/demo/utils/lipsum.ts +19 -0
- package/s/demo/views/demonstration/style.css.ts +18 -2
- package/s/demo/views/demonstration/view.ts +24 -16
- package/s/icons/tabler/menu-2.svg.ts +4 -0
- package/s/icons/tabler/x.svg.ts +4 -0
- package/s/index.html.ts +2 -2
- package/s/index.ts +16 -4
- package/s/install/aura.bundle.ts +9 -0
- package/s/install/plain.bundle.ts +9 -0
- package/s/shiny.ts +15 -0
- package/s/themes/aura.css.ts +86 -0
- package/s/themes/index.barrel.ts +2 -1
- package/s/themes/index.ts +1 -0
- package/s/themes/infra/css-vars.ts +41 -0
- package/s/themes/plain.css.ts +11 -0
- package/s/utils/states.ts +15 -0
- package/x/components/button/component.d.ts +5 -0
- package/x/components/button/component.js +25 -0
- package/x/components/button/component.js.map +1 -0
- package/x/components/button/style.css.js +63 -0
- package/x/components/button/style.css.js.map +1 -0
- package/x/{ui → components}/copy/component.d.ts +8 -4
- package/x/{ui → components}/copy/component.js +10 -5
- package/x/components/copy/component.js.map +1 -0
- package/x/{ui → components}/copy/style.css.js +6 -6
- package/x/components/copy/style.css.js.map +1 -0
- package/x/components/drawer/component.d.ts +387 -0
- package/x/components/drawer/component.js +76 -0
- package/x/components/drawer/component.js.map +1 -0
- package/x/components/drawer/control.d.ts +9 -0
- package/x/components/drawer/control.js +24 -0
- package/x/components/drawer/control.js.map +1 -0
- package/x/components/drawer/style.css.d.ts +2 -0
- package/x/components/drawer/style.css.js +119 -0
- package/x/components/drawer/style.css.js.map +1 -0
- package/x/{ui → components}/example/component.d.ts +3 -3
- package/x/{ui → components}/example/component.js +6 -4
- package/x/components/example/component.js.map +1 -0
- package/x/components/example/style.css.d.ts +2 -0
- package/x/components/example/style.css.js +10 -0
- package/x/components/example/style.css.js.map +1 -0
- package/x/components/foundation.css.d.ts +1 -0
- package/x/components/foundation.css.js +14 -0
- package/x/components/foundation.css.js.map +1 -0
- package/x/components/framework.d.ts +8 -0
- package/x/components/framework.js +5 -0
- package/x/components/framework.js.map +1 -0
- package/x/components/raw-components.d.ts +12 -0
- package/x/components/raw-components.js +13 -0
- package/x/components/raw-components.js.map +1 -0
- package/x/components/tabs/component.d.ts +374 -0
- package/x/components/tabs/component.js +60 -0
- package/x/components/tabs/component.js.map +1 -0
- package/x/components/tabs/control.d.ts +9 -0
- package/x/components/tabs/control.js +24 -0
- package/x/components/tabs/control.js.map +1 -0
- package/x/components/tabs/style.css.d.ts +2 -0
- package/x/components/tabs/style.css.js +42 -0
- package/x/components/tabs/style.css.js.map +1 -0
- package/x/demo/aura-views.d.ts +15 -0
- package/x/demo/aura-views.js +4 -0
- package/x/demo/aura-views.js.map +1 -0
- package/x/demo/demo.bundle.js +280 -14
- package/x/demo/demo.bundle.js.map +1 -1
- package/x/demo/demo.bundle.min.js +561 -45
- package/x/demo/demo.bundle.min.js.map +4 -4
- package/x/demo/demo.css +3 -1
- package/x/demo/utils/lipsum.d.ts +2 -0
- package/x/demo/utils/lipsum.js +11 -0
- package/x/demo/utils/lipsum.js.map +1 -0
- package/x/demo/views/demonstration/style.css.js +18 -2
- package/x/demo/views/demonstration/style.css.js.map +1 -1
- package/x/demo/views/demonstration/view.d.ts +6 -4
- package/x/demo/views/demonstration/view.js +20 -12
- package/x/demo/views/demonstration/view.js.map +1 -1
- package/x/icons/tabler/menu-2.svg.d.ts +2 -0
- package/x/icons/tabler/menu-2.svg.js +3 -0
- package/x/icons/tabler/menu-2.svg.js.map +1 -0
- package/x/icons/tabler/x.svg.d.ts +2 -0
- package/x/icons/tabler/x.svg.js +3 -0
- package/x/icons/tabler/x.svg.js.map +1 -0
- package/x/index.d.ts +10 -4
- package/x/index.html +7 -5
- package/x/index.html.js +2 -2
- package/x/index.js +10 -4
- package/x/index.js.map +1 -1
- package/x/install/aura.bundle.d.ts +1 -0
- package/x/install/aura.bundle.js +5 -0
- package/x/install/aura.bundle.js.map +1 -0
- package/x/install/aura.bundle.min.js +463 -0
- package/x/install/aura.bundle.min.js.map +7 -0
- package/x/install/plain.bundle.d.ts +1 -0
- package/x/install/plain.bundle.js +5 -0
- package/x/install/plain.bundle.js.map +1 -0
- package/x/install/plain.bundle.min.js +390 -0
- package/x/install/plain.bundle.min.js.map +7 -0
- package/x/shiny.d.ts +47 -0
- package/x/shiny.js +8 -0
- package/x/shiny.js.map +1 -0
- package/x/themes/aura.css.d.ts +1 -0
- package/x/themes/aura.css.js +85 -0
- package/x/themes/aura.css.js.map +1 -0
- package/x/themes/index.barrel.d.ts +2 -1
- package/x/themes/index.barrel.js +2 -1
- package/x/themes/index.barrel.js.map +1 -1
- package/x/themes/index.d.ts +1 -0
- package/x/themes/infra/css-vars.d.ts +14 -0
- package/x/themes/infra/css-vars.js +21 -0
- package/x/themes/infra/css-vars.js.map +1 -0
- package/x/themes/plain.css.d.ts +1 -0
- package/x/themes/plain.css.js +10 -0
- package/x/themes/plain.css.js.map +1 -0
- package/x/utils/states.d.ts +5 -0
- package/x/utils/states.js +13 -0
- package/x/utils/states.js.map +1 -0
- package/s/themes/basic.css.ts +0 -18
- package/s/tools/untab.ts +0 -30
- package/s/ui/components.ts +0 -9
- package/s/ui/framework.ts +0 -8
- package/s/ui/themers.ts +0 -28
- package/x/themes/basic.css.d.ts +0 -1
- package/x/themes/basic.css.js +0 -17
- package/x/themes/basic.css.js.map +0 -1
- package/x/tools/untab.d.ts +0 -1
- package/x/tools/untab.js +0 -26
- package/x/tools/untab.js.map +0 -1
- package/x/ui/components.d.ts +0 -6
- package/x/ui/components.js +0 -7
- package/x/ui/components.js.map +0 -1
- package/x/ui/copy/component.js.map +0 -1
- package/x/ui/copy/style.css.js.map +0 -1
- package/x/ui/example/component.js.map +0 -1
- package/x/ui/example/style.css.js +0 -10
- package/x/ui/example/style.css.js.map +0 -1
- package/x/ui/framework.d.ts +0 -4
- package/x/ui/framework.js +0 -6
- package/x/ui/framework.js.map +0 -1
- package/x/ui/themers.d.ts +0 -8
- package/x/ui/themers.js +0 -12
- package/x/ui/themers.js.map +0 -1
- /package/x/{ui/copy → components/button}/style.css.d.ts +0 -0
- /package/x/{ui/example → components/copy}/style.css.d.ts +0 -0
package/README.md
CHANGED
|
@@ -1,10 +1,120 @@
|
|
|
1
1
|
|
|
2
|
-
|
|
2
|
+

|
|
3
3
|
|
|
4
|
-
# ✨
|
|
4
|
+
# ✨shiny✨
|
|
5
5
|
> *web ui components*
|
|
6
6
|
|
|
7
|
-
https://shiny.e280.org
|
|
7
|
+
- 💁 ***see all the components at https://shiny.e280.org/*** 👈
|
|
8
|
+
- 👷 built with [🦝sly](https://github.com/e280/sly) and [🔥lit](https://lit.dev/)
|
|
9
|
+
- 🎭 duality: all components are available as ***web components*** or ***sly views***
|
|
10
|
+
- 🧑💻 a project by https://e280.org/
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
<br/><br/>
|
|
15
|
+
|
|
16
|
+
## 🍭 instant html installation
|
|
17
|
+
- put this in your html `<head>`
|
|
18
|
+
```html
|
|
19
|
+
<script async src="https://shiny.e280.org/install/aura.bundle.min.js"></script>
|
|
20
|
+
```
|
|
21
|
+
- you can swap `aura` there for another theme
|
|
22
|
+
- you're ready to put shiny components in your html `<body>`
|
|
23
|
+
```html
|
|
24
|
+
<shiny-copy text="hello world"></shiny-copy>
|
|
25
|
+
```
|
|
26
|
+
- go pick your favorites at https://shiny.e280.org/
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
<br/><br/>
|
|
31
|
+
|
|
32
|
+
## 🍬 web app installation
|
|
33
|
+
- install shiny and friends
|
|
34
|
+
```sh
|
|
35
|
+
npm install @e280/shiny @e280/sly lit
|
|
36
|
+
```
|
|
37
|
+
- import stuff
|
|
38
|
+
```ts
|
|
39
|
+
import {dom} from "@e280/sly"
|
|
40
|
+
import {shiny, themes} from "@e280/shiny"
|
|
41
|
+
```
|
|
42
|
+
- prepare the components/views and choose a theme
|
|
43
|
+
```ts
|
|
44
|
+
const {components, views} = shiny({theme: themes.aura})
|
|
45
|
+
```
|
|
46
|
+
- `aura` — (default) cosmic dreamy seaside nebula vibes
|
|
47
|
+
- `plain` — bare-bones spartan theme, buttons look lame
|
|
48
|
+
- (optional) register the components
|
|
49
|
+
```ts
|
|
50
|
+
dom.register(components)
|
|
51
|
+
```
|
|
52
|
+
- or use views instead of components
|
|
53
|
+
- time to go shopping at https://shiny.e280.org/
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
<br/><br/>
|
|
58
|
+
|
|
59
|
+
## 😎 views are for the cool kids
|
|
60
|
+
- hey, remember those `views` you got from the install snippet?
|
|
61
|
+
```ts
|
|
62
|
+
const {components, views} = shiny({theme: themes.aura})
|
|
63
|
+
```
|
|
64
|
+
- well you can yoink out a view you wanna use
|
|
65
|
+
```ts
|
|
66
|
+
const {ShinyCopy} = views
|
|
67
|
+
```
|
|
68
|
+
- then you can render it directly in your lit templates
|
|
69
|
+
```ts
|
|
70
|
+
import {html} from "lit"
|
|
71
|
+
import {dom, view} from "@e280/sly"
|
|
72
|
+
|
|
73
|
+
dom.register({
|
|
74
|
+
MyComponent: view.component(use => html`
|
|
75
|
+
<div>
|
|
76
|
+
${ShinyCopy("hello world")}
|
|
77
|
+
</div>
|
|
78
|
+
`)
|
|
79
|
+
})
|
|
80
|
+
```
|
|
81
|
+
- you get nice typescript typings
|
|
82
|
+
- no juggling annoying web component dom registrations
|
|
83
|
+
- you're just using the shiny views directly
|
|
84
|
+
- learn more about [🦝sly](https://github.com/e280/sly) and [🔥lit](https://lit.dev/)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
<br/><br/>
|
|
89
|
+
|
|
90
|
+
## 💅 page-wide css customization
|
|
91
|
+
- put this in your `<head>` and you can customize colors and stuff
|
|
92
|
+
```html
|
|
93
|
+
<style>
|
|
94
|
+
html {
|
|
95
|
+
--shiny-bg: #111;
|
|
96
|
+
--shiny-alpha: #def;
|
|
97
|
+
--shiny-lame: #8888;
|
|
98
|
+
--shiny-inactive-opacity: 0.5;
|
|
99
|
+
--shiny-angry: #f50;
|
|
100
|
+
--shiny-zesty: #cf0;
|
|
101
|
+
--shiny-happy: #0fa;
|
|
102
|
+
--shiny-calm: #0af;
|
|
103
|
+
--shiny-sad: #74f;
|
|
104
|
+
--shiny-quirky: #f49;
|
|
105
|
+
}
|
|
106
|
+
</style>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
<br/><br/>
|
|
112
|
+
|
|
113
|
+
## 🧑💻 by e280
|
|
114
|
+
reward us with github stars
|
|
115
|
+
build with us at https://e280.org/ if you're good at dev
|
|
116
|
+
|
|
117
|
+
|
|
8
118
|
|
|
9
119
|
<br/><br/>
|
|
10
120
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@e280/shiny",
|
|
3
|
-
"version": "0.1.0-
|
|
3
|
+
"version": "0.1.0-11",
|
|
4
4
|
"description": "✨ web ui components",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
"s"
|
|
15
15
|
],
|
|
16
16
|
"peerDependencies": {
|
|
17
|
-
"@e280/sly": "^0.2.0-
|
|
17
|
+
"@e280/sly": "^0.2.0-25",
|
|
18
18
|
"lit": "^3.3.1"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@e280/strata": "^0.2.0-14",
|
|
22
|
-
"@e280/stz": "^0.2.
|
|
22
|
+
"@e280/stz": "^0.2.9"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@e280/science": "^0.1.2",
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
|
|
2
|
+
import {html} from "lit"
|
|
3
|
+
import {view} from "@e280/sly"
|
|
4
|
+
import styleCss from "./style.css.js"
|
|
5
|
+
import {foundationCss} from "../foundation.css.js"
|
|
6
|
+
import {ShinyContext, ShinyElement} from "../framework.js"
|
|
7
|
+
|
|
8
|
+
export class ShinyButton extends (
|
|
9
|
+
view(use => (context: ShinyContext) => {
|
|
10
|
+
use.name("shiny-button")
|
|
11
|
+
use.styles(foundationCss, context.theme, styleCss)
|
|
12
|
+
|
|
13
|
+
const attrs = use.attrs.spec({
|
|
14
|
+
disabled: Boolean,
|
|
15
|
+
hidden: Boolean,
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
return html`
|
|
19
|
+
<button
|
|
20
|
+
part=button
|
|
21
|
+
?disabled="${attrs.disabled}"
|
|
22
|
+
?hidden="${attrs.hidden}">
|
|
23
|
+
<slot></slot>
|
|
24
|
+
</button>
|
|
25
|
+
`
|
|
26
|
+
})
|
|
27
|
+
.component(ShinyElement)
|
|
28
|
+
.props(el => [el.context] as const)
|
|
29
|
+
) {}
|
|
30
|
+
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
|
|
2
|
+
import {css} from "lit"
|
|
3
|
+
export default css`@layer view {
|
|
4
|
+
|
|
5
|
+
:host {
|
|
6
|
+
opacity: 0.8;
|
|
7
|
+
display: inline-flex;
|
|
8
|
+
width: max-content;
|
|
9
|
+
height: max-content;
|
|
10
|
+
|
|
11
|
+
--padding: 0.3em;
|
|
12
|
+
border-radius: 0.2em;
|
|
13
|
+
border: 0.1em solid currentColor;
|
|
14
|
+
|
|
15
|
+
cursor: pointer;
|
|
16
|
+
background: transparent;
|
|
17
|
+
user-select: none;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
:host(:not([disabled]):is(:hover, :focus-visible)) { opacity: 1; }
|
|
21
|
+
:host(:not([disabled]):active) { opacity: 0.6; }
|
|
22
|
+
|
|
23
|
+
:host([disabled]) {
|
|
24
|
+
cursor: default;
|
|
25
|
+
color: var(--lame);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
:host([hidden]) {
|
|
29
|
+
display: none !important;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
:host([lame]) { color: var(--lame); }
|
|
33
|
+
:host([angry]) { color: var(--angry); }
|
|
34
|
+
:host([zesty]) { color: var(--zesty); }
|
|
35
|
+
:host([happy]) { color: var(--happy); }
|
|
36
|
+
:host([calm]) { color: var(--calm); }
|
|
37
|
+
:host([sad]) { color: var(--sad); }
|
|
38
|
+
:host([quirky]) { color: var(--quirky); }
|
|
39
|
+
|
|
40
|
+
button {
|
|
41
|
+
background: transparent;
|
|
42
|
+
border: none;
|
|
43
|
+
|
|
44
|
+
font: inherit;
|
|
45
|
+
color: inherit;
|
|
46
|
+
cursor: inherit;
|
|
47
|
+
outline: inherit;
|
|
48
|
+
text-shadow: inherit;
|
|
49
|
+
|
|
50
|
+
display: inline-flex;
|
|
51
|
+
justify-content: center;
|
|
52
|
+
align-items: center;
|
|
53
|
+
|
|
54
|
+
width: 100%;
|
|
55
|
+
height: 100%;
|
|
56
|
+
padding: var(--padding);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
slot {
|
|
60
|
+
display: contents;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
}`
|
|
64
|
+
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
|
|
2
|
+
import {html} from "lit"
|
|
2
3
|
import {debounce} from "@e280/stz"
|
|
3
4
|
import {dom, view} from "@e280/sly"
|
|
4
5
|
|
|
5
|
-
import {CSSResult, html} from "lit"
|
|
6
6
|
import styleCss from "./style.css.js"
|
|
7
|
-
import {
|
|
7
|
+
import {foundationCss} from "../foundation.css.js"
|
|
8
|
+
import {ShinyContext, ShinyElement} from "../framework.js"
|
|
8
9
|
import clipboardSvg from "../../icons/tabler/clipboard.svg.js"
|
|
9
10
|
import clipboardXFilledSvg from "../../icons/tabler/clipboard-x-filled.svg.js"
|
|
10
11
|
import clipboardCheckFilledSvg from "../../icons/tabler/clipboard-check-filled.svg.js"
|
|
11
12
|
|
|
12
13
|
export class ShinyCopy extends (
|
|
13
|
-
view(use => (
|
|
14
|
+
view(use => (context: ShinyContext, text: string | undefined, ms = 1000) => {
|
|
14
15
|
use.name("shiny-copy")
|
|
15
|
-
use.styles(theme, styleCss)
|
|
16
|
+
use.styles(foundationCss, context.theme, styleCss)
|
|
16
17
|
|
|
17
18
|
type Status = "neutral" | "good" | "bad" | "invalid"
|
|
18
19
|
|
|
@@ -56,11 +57,15 @@ export class ShinyCopy extends (
|
|
|
56
57
|
`
|
|
57
58
|
})
|
|
58
59
|
.component(class extends ShinyElement {
|
|
59
|
-
attrs = dom.attrs(this).spec({
|
|
60
|
+
#attrs = dom.attrs(this).spec({
|
|
60
61
|
text: String,
|
|
61
62
|
ms: Number,
|
|
62
63
|
})
|
|
64
|
+
get text() { return this.#attrs.text }
|
|
65
|
+
set text(v) { this.#attrs.text = v }
|
|
66
|
+
get ms() { return this.#attrs.ms }
|
|
67
|
+
set ms(v) { this.#attrs.ms = v }
|
|
63
68
|
})
|
|
64
|
-
.props(el => [el.
|
|
69
|
+
.props(el => [el.context, el.text, el.ms])
|
|
65
70
|
) {}
|
|
66
71
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
import {css} from "lit"
|
|
3
|
-
export default css
|
|
3
|
+
export default css`@layer view {
|
|
4
4
|
|
|
5
5
|
button {
|
|
6
6
|
background: transparent;
|
|
@@ -9,7 +9,7 @@ button {
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
button {
|
|
12
|
-
opacity:
|
|
12
|
+
opacity: var(--inactive-opacity);
|
|
13
13
|
cursor: pointer;
|
|
14
14
|
cursor: copy;
|
|
15
15
|
|
|
@@ -22,18 +22,18 @@ button {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
[data-status="invalid"] {
|
|
25
|
-
color: var(--
|
|
25
|
+
color: var(--lame);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
[data-status="good"] {
|
|
29
29
|
opacity: 1;
|
|
30
|
-
color: var(--
|
|
30
|
+
color: var(--happy);
|
|
31
31
|
filter: drop-shadow(0 0 0.3em color-mix(in oklab, transparent, currentColor 50%));
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
[data-status="bad"] {
|
|
35
35
|
opacity: 1;
|
|
36
|
-
color: var(--
|
|
36
|
+
color: var(--angry);
|
|
37
37
|
filter: drop-shadow(0 0 0.3em color-mix(in oklab, transparent, currentColor 50%));
|
|
38
38
|
}
|
|
39
39
|
|
|
@@ -42,5 +42,5 @@ svg {
|
|
|
42
42
|
height: 1em;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
`
|
|
45
|
+
}`
|
|
46
46
|
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
|
|
2
|
+
import {html} from "lit"
|
|
3
|
+
import {dom, view} from "@e280/sly"
|
|
4
|
+
|
|
5
|
+
import styleCss from "./style.css.js"
|
|
6
|
+
import {DrawerControl} from "./control.js"
|
|
7
|
+
import {States} from "../../utils/states.js"
|
|
8
|
+
import xSvg from "../../icons/tabler/x.svg.js"
|
|
9
|
+
import {foundationCss} from "../foundation.css.js"
|
|
10
|
+
import menu2Svg from "../../icons/tabler/menu-2.svg.js"
|
|
11
|
+
import {ShinyContext, ShinyElement} from "../framework.js"
|
|
12
|
+
|
|
13
|
+
export class ShinyDrawer extends (
|
|
14
|
+
view(use => (context: ShinyContext, options: {
|
|
15
|
+
button: boolean
|
|
16
|
+
side?: "left" | "right"
|
|
17
|
+
control?: DrawerControl
|
|
18
|
+
}) => {
|
|
19
|
+
|
|
20
|
+
use.name("shiny-drawer")
|
|
21
|
+
use.styles(foundationCss, context.theme, styleCss)
|
|
22
|
+
const states = use.once(() => new States(use.element))
|
|
23
|
+
|
|
24
|
+
const side = options.side ?? "left"
|
|
25
|
+
const drawer = use.once(() => (options.control ?? new DrawerControl()))
|
|
26
|
+
states.assign(side)
|
|
27
|
+
|
|
28
|
+
use.mount(() => dom.events(window, {keydown: (event: KeyboardEvent) => {
|
|
29
|
+
if (event.code === "Escape")
|
|
30
|
+
drawer.close()
|
|
31
|
+
}}))
|
|
32
|
+
|
|
33
|
+
dom.attrs(use.element).booleans.open = drawer.isOpen
|
|
34
|
+
|
|
35
|
+
return html`
|
|
36
|
+
<div class=shell ?data-open="${drawer.isOpen}" data-side="${side}">
|
|
37
|
+
<slot name=plate ?inert="${drawer.isOpen}"></slot>
|
|
38
|
+
|
|
39
|
+
<div class=clipper>
|
|
40
|
+
<div part=blanket @click="${drawer.close}" ?inert="${!drawer.isOpen}"></div>
|
|
41
|
+
|
|
42
|
+
<div part=tray>
|
|
43
|
+
<slot ?inert="${!drawer.isOpen}"></slot>
|
|
44
|
+
|
|
45
|
+
${options.button
|
|
46
|
+
? html`
|
|
47
|
+
<button @click="${drawer.toggle}">
|
|
48
|
+
${drawer.isOpen
|
|
49
|
+
? html`
|
|
50
|
+
<slot name=button-x>
|
|
51
|
+
${xSvg}
|
|
52
|
+
</slot>
|
|
53
|
+
`
|
|
54
|
+
: html`
|
|
55
|
+
<slot name=button>
|
|
56
|
+
${menu2Svg}
|
|
57
|
+
</slot>
|
|
58
|
+
`}
|
|
59
|
+
</button>
|
|
60
|
+
`
|
|
61
|
+
: null}
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
`
|
|
66
|
+
})
|
|
67
|
+
.component(class extends ShinyElement {
|
|
68
|
+
#attrs = dom.attrs(this).spec({
|
|
69
|
+
open: Boolean,
|
|
70
|
+
button: Boolean,
|
|
71
|
+
side: String,
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
get button() { return this.#attrs.button }
|
|
75
|
+
set button(v) { this.#attrs.button = v }
|
|
76
|
+
|
|
77
|
+
get side() { return this.#attrs.side === "right" ? "right" : "left" }
|
|
78
|
+
set side(v) { this.#attrs.side = v }
|
|
79
|
+
|
|
80
|
+
control = new DrawerControl(this.#attrs.open)
|
|
81
|
+
get isOpen() { return this.control.isOpen }
|
|
82
|
+
get toggle() { return this.control.toggle }
|
|
83
|
+
get open() { return this.control.open }
|
|
84
|
+
get close() { return this.control.close }
|
|
85
|
+
})
|
|
86
|
+
.props(el => [el.context, {
|
|
87
|
+
control: el.control,
|
|
88
|
+
button: el.button,
|
|
89
|
+
side: el.side,
|
|
90
|
+
}] as const)
|
|
91
|
+
) {}
|
|
92
|
+
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
|
|
2
|
+
import {signal} from "@e280/strata"
|
|
3
|
+
|
|
4
|
+
export class DrawerControl {
|
|
5
|
+
$open = signal(false)
|
|
6
|
+
|
|
7
|
+
constructor(startOpen = false) {
|
|
8
|
+
if (startOpen) this.$open.set(true)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
get isOpen() {
|
|
12
|
+
return this.$open.get()
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async setOpen(value: boolean) {
|
|
16
|
+
return this.$open.set(value)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
open = async() => {
|
|
20
|
+
await this.setOpen(true)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
close = async() => {
|
|
24
|
+
await this.setOpen(false)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
toggle = async() => {
|
|
28
|
+
return this.setOpen(!this.isOpen)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
|
|
2
|
+
import {css} from "lit"
|
|
3
|
+
export default css`@layer view {
|
|
4
|
+
|
|
5
|
+
:host {
|
|
6
|
+
display: block;
|
|
7
|
+
width: 100%;
|
|
8
|
+
height: 100%;
|
|
9
|
+
--button-size: 2em;
|
|
10
|
+
--anim-duration: 200ms;
|
|
11
|
+
--blanket-backdrop-filter: blur(0.5em);
|
|
12
|
+
--blanket-bg: color-mix(in oklab, transparent, var(--bg));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.shell {
|
|
16
|
+
position: relative;
|
|
17
|
+
width: 100%;
|
|
18
|
+
height: 100%;
|
|
19
|
+
|
|
20
|
+
[part="blanket"] {
|
|
21
|
+
opacity: 0;
|
|
22
|
+
|
|
23
|
+
content: "";
|
|
24
|
+
display: block;
|
|
25
|
+
position: absolute;
|
|
26
|
+
inset: 0;
|
|
27
|
+
|
|
28
|
+
background: var(--blanket-bg);
|
|
29
|
+
backdrop-filter: var(--blanket-backdrop-filter);
|
|
30
|
+
|
|
31
|
+
will-change: opacity;
|
|
32
|
+
transition: all var(--anim-duration) ease;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.clipper {
|
|
36
|
+
pointer-events: none;
|
|
37
|
+
position: absolute;
|
|
38
|
+
inset: 0;
|
|
39
|
+
width: 100%;
|
|
40
|
+
height: 100%;
|
|
41
|
+
overflow: hidden;
|
|
42
|
+
> * { pointer-events: all; }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
[part="tray"] {
|
|
46
|
+
position: absolute;
|
|
47
|
+
top: 0;
|
|
48
|
+
width: calc(100% - var(--button-size));
|
|
49
|
+
|
|
50
|
+
display: flex;
|
|
51
|
+
flex-direction: column;
|
|
52
|
+
height: auto;
|
|
53
|
+
max-height: 100%;
|
|
54
|
+
|
|
55
|
+
opacity: 1;
|
|
56
|
+
transform: translateX(-100%);
|
|
57
|
+
will-change: opacity, transform;
|
|
58
|
+
transition: all var(--anim-duration) ease;
|
|
59
|
+
|
|
60
|
+
> slot {
|
|
61
|
+
display: block;
|
|
62
|
+
height: 100%;
|
|
63
|
+
overflow-y: auto;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
> button {
|
|
67
|
+
position: absolute;
|
|
68
|
+
top: 0;
|
|
69
|
+
left: 100%;
|
|
70
|
+
|
|
71
|
+
opacity: var(--inactive-opacity);
|
|
72
|
+
background: transparent;
|
|
73
|
+
border: none;
|
|
74
|
+
cursor: pointer;
|
|
75
|
+
|
|
76
|
+
&:is(:hover, :focus-visible) {
|
|
77
|
+
opacity: 1;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
> slot {
|
|
81
|
+
display: contents;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
svg {
|
|
85
|
+
width: var(--button-size);
|
|
86
|
+
height: var(--button-size);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
&[data-side="right"] {
|
|
92
|
+
[part="tray"] {
|
|
93
|
+
right: 0;
|
|
94
|
+
transform: translateX(100%);
|
|
95
|
+
> button {
|
|
96
|
+
left: unset;
|
|
97
|
+
right: 100%;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
slot[name="plate"] {
|
|
103
|
+
display: block;
|
|
104
|
+
width: 100%;
|
|
105
|
+
height: 100%;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
&[data-open] {
|
|
109
|
+
[part="blanket"] {
|
|
110
|
+
opacity: 1;
|
|
111
|
+
}
|
|
112
|
+
[part="tray"] {
|
|
113
|
+
opacity: 1;
|
|
114
|
+
transform: translateX(0%);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
}`
|
|
120
|
+
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
|
|
2
|
+
import {html} from "lit"
|
|
2
3
|
import {dom, view} from "@e280/sly"
|
|
3
|
-
import {CSSResult, html} from "lit"
|
|
4
4
|
import styleCss from "./style.css.js"
|
|
5
|
-
import {
|
|
5
|
+
import {foundationCss} from "../foundation.css.js"
|
|
6
|
+
import {ShinyContext, ShinyElement} from "../framework.js"
|
|
6
7
|
|
|
7
8
|
export class ShinyExample extends (
|
|
8
|
-
view(use => (
|
|
9
|
-
use.
|
|
9
|
+
view(use => (context: ShinyContext, start: number) => {
|
|
10
|
+
use.name("shiny-example")
|
|
11
|
+
use.styles(foundationCss, context.theme, styleCss)
|
|
10
12
|
|
|
11
13
|
const $count = use.signal(start)
|
|
12
14
|
const increment = () => { $count.value++ }
|
|
@@ -20,6 +22,6 @@ export class ShinyExample extends (
|
|
|
20
22
|
.component(class extends ShinyElement {
|
|
21
23
|
attrs = dom.attrs(this).spec({start: Number})
|
|
22
24
|
})
|
|
23
|
-
.props(el => [el.
|
|
25
|
+
.props(el => [el.context, el.attrs.start ?? 1] as const)
|
|
24
26
|
) {}
|
|
25
27
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
|
|
2
|
+
import {ShinyButton} from "./button/component.js"
|
|
3
|
+
import {ShinyCopy} from "./copy/component.js"
|
|
4
|
+
import {ShinyDrawer} from "./drawer/component.js"
|
|
5
|
+
import {ShinyExample} from "./example/component.js"
|
|
6
|
+
import {ShinyTabs} from "./tabs/component.js"
|
|
7
|
+
|
|
8
|
+
export const rawComponents = {
|
|
9
|
+
ShinyButton,
|
|
10
|
+
ShinyCopy,
|
|
11
|
+
ShinyDrawer,
|
|
12
|
+
ShinyExample,
|
|
13
|
+
ShinyTabs,
|
|
14
|
+
}
|
|
15
|
+
|