@e280/shiny 0.1.0-1 → 0.1.0-10

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.
Files changed (154) hide show
  1. package/README.md +110 -3
  2. package/package.json +3 -3
  3. package/s/{ui → components}/copy/component.ts +11 -6
  4. package/s/{ui → components}/copy/style.css.ts +6 -6
  5. package/s/components/drawer/component.ts +92 -0
  6. package/s/components/drawer/control.ts +31 -0
  7. package/s/components/drawer/style.css.ts +120 -0
  8. package/s/{ui → components}/example/component.ts +7 -5
  9. package/s/{ui → components}/example/style.css.ts +2 -2
  10. package/s/components/foundation.css.ts +15 -0
  11. package/s/components/framework.ts +10 -0
  12. package/s/components/raw-components.ts +13 -0
  13. package/s/components/tabs/component.ts +59 -0
  14. package/s/components/tabs/control.ts +31 -0
  15. package/s/components/tabs/style.css.ts +6 -0
  16. package/s/demo/aura-views.ts +6 -0
  17. package/s/demo/demo.bundle.ts +204 -14
  18. package/s/demo/demo.css +3 -1
  19. package/s/demo/utils/lipsum.ts +19 -0
  20. package/s/demo/views/demonstration/style.css.ts +10 -2
  21. package/s/demo/views/demonstration/view.ts +18 -14
  22. package/s/icons/tabler/menu-2.svg.ts +4 -0
  23. package/s/icons/tabler/x.svg.ts +4 -0
  24. package/s/index.html.ts +2 -2
  25. package/s/index.ts +16 -4
  26. package/s/install/aura.bundle.ts +9 -0
  27. package/s/install/plain.bundle.ts +9 -0
  28. package/s/shiny.ts +15 -0
  29. package/s/themes/aura.css.ts +48 -0
  30. package/s/themes/index.barrel.ts +2 -1
  31. package/s/themes/index.ts +1 -0
  32. package/s/themes/infra/css-vars.ts +33 -0
  33. package/s/themes/plain.css.ts +12 -0
  34. package/s/utils/states.ts +15 -0
  35. package/x/{ui → components}/copy/component.d.ts +8 -4
  36. package/x/{ui → components}/copy/component.js +10 -5
  37. package/x/components/copy/component.js.map +1 -0
  38. package/x/{ui → components}/copy/style.css.js +6 -6
  39. package/x/components/copy/style.css.js.map +1 -0
  40. package/x/components/drawer/component.d.ts +387 -0
  41. package/x/components/drawer/component.js +76 -0
  42. package/x/components/drawer/component.js.map +1 -0
  43. package/x/components/drawer/control.d.ts +9 -0
  44. package/x/components/drawer/control.js +24 -0
  45. package/x/components/drawer/control.js.map +1 -0
  46. package/x/components/drawer/style.css.js +119 -0
  47. package/x/components/drawer/style.css.js.map +1 -0
  48. package/x/{ui → components}/example/component.d.ts +3 -3
  49. package/x/{ui → components}/example/component.js +6 -4
  50. package/x/components/example/component.js.map +1 -0
  51. package/x/components/example/style.css.d.ts +2 -0
  52. package/x/components/example/style.css.js +10 -0
  53. package/x/components/example/style.css.js.map +1 -0
  54. package/x/components/foundation.css.d.ts +1 -0
  55. package/x/components/foundation.css.js +14 -0
  56. package/x/components/foundation.css.js.map +1 -0
  57. package/x/components/framework.d.ts +8 -0
  58. package/x/components/framework.js +5 -0
  59. package/x/components/framework.js.map +1 -0
  60. package/x/components/raw-components.d.ts +10 -0
  61. package/x/components/raw-components.js +11 -0
  62. package/x/components/raw-components.js.map +1 -0
  63. package/x/components/tabs/component.d.ts +374 -0
  64. package/x/components/tabs/component.js +49 -0
  65. package/x/components/tabs/component.js.map +1 -0
  66. package/x/components/tabs/control.d.ts +9 -0
  67. package/x/components/tabs/control.js +24 -0
  68. package/x/components/tabs/control.js.map +1 -0
  69. package/x/components/tabs/style.css.d.ts +2 -0
  70. package/x/components/tabs/style.css.js +5 -0
  71. package/x/components/tabs/style.css.js.map +1 -0
  72. package/x/demo/aura-views.d.ts +14 -0
  73. package/x/demo/aura-views.js +4 -0
  74. package/x/demo/aura-views.js.map +1 -0
  75. package/x/demo/demo.bundle.js +198 -14
  76. package/x/demo/demo.bundle.js.map +1 -1
  77. package/x/demo/demo.bundle.min.js +383 -48
  78. package/x/demo/demo.bundle.min.js.map +4 -4
  79. package/x/demo/demo.css +3 -1
  80. package/x/demo/utils/lipsum.d.ts +2 -0
  81. package/x/demo/utils/lipsum.js +11 -0
  82. package/x/demo/utils/lipsum.js.map +1 -0
  83. package/x/demo/views/demonstration/style.css.js +10 -2
  84. package/x/demo/views/demonstration/style.css.js.map +1 -1
  85. package/x/demo/views/demonstration/view.d.ts +6 -4
  86. package/x/demo/views/demonstration/view.js +16 -10
  87. package/x/demo/views/demonstration/view.js.map +1 -1
  88. package/x/icons/tabler/menu-2.svg.d.ts +2 -0
  89. package/x/icons/tabler/menu-2.svg.js +3 -0
  90. package/x/icons/tabler/menu-2.svg.js.map +1 -0
  91. package/x/icons/tabler/x.svg.d.ts +2 -0
  92. package/x/icons/tabler/x.svg.js +3 -0
  93. package/x/icons/tabler/x.svg.js.map +1 -0
  94. package/x/index.d.ts +10 -4
  95. package/x/index.html +7 -5
  96. package/x/index.html.js +2 -2
  97. package/x/index.js +10 -4
  98. package/x/index.js.map +1 -1
  99. package/x/install/aura.bundle.d.ts +1 -0
  100. package/x/install/aura.bundle.js +5 -0
  101. package/x/install/aura.bundle.js.map +1 -0
  102. package/x/install/aura.bundle.min.js +321 -0
  103. package/x/install/aura.bundle.min.js.map +7 -0
  104. package/x/install/plain.bundle.d.ts +1 -0
  105. package/x/install/plain.bundle.js +5 -0
  106. package/x/install/plain.bundle.js.map +1 -0
  107. package/x/install/plain.bundle.min.js +287 -0
  108. package/x/install/plain.bundle.min.js.map +7 -0
  109. package/x/shiny.d.ts +42 -0
  110. package/x/shiny.js +8 -0
  111. package/x/shiny.js.map +1 -0
  112. package/x/themes/aura.css.d.ts +1 -0
  113. package/x/themes/aura.css.js +47 -0
  114. package/x/themes/aura.css.js.map +1 -0
  115. package/x/themes/index.barrel.d.ts +2 -1
  116. package/x/themes/index.barrel.js +2 -1
  117. package/x/themes/index.barrel.js.map +1 -1
  118. package/x/themes/index.d.ts +1 -0
  119. package/x/themes/infra/css-vars.d.ts +11 -0
  120. package/x/themes/infra/css-vars.js +18 -0
  121. package/x/themes/infra/css-vars.js.map +1 -0
  122. package/x/themes/plain.css.d.ts +1 -0
  123. package/x/themes/plain.css.js +11 -0
  124. package/x/themes/plain.css.js.map +1 -0
  125. package/x/utils/states.d.ts +5 -0
  126. package/x/utils/states.js +13 -0
  127. package/x/utils/states.js.map +1 -0
  128. package/s/themes/basic.css.ts +0 -18
  129. package/s/tools/untab.ts +0 -30
  130. package/s/ui/components.ts +0 -9
  131. package/s/ui/framework.ts +0 -8
  132. package/s/ui/themers.ts +0 -28
  133. package/x/themes/basic.css.d.ts +0 -1
  134. package/x/themes/basic.css.js +0 -17
  135. package/x/themes/basic.css.js.map +0 -1
  136. package/x/tools/untab.d.ts +0 -1
  137. package/x/tools/untab.js +0 -26
  138. package/x/tools/untab.js.map +0 -1
  139. package/x/ui/components.d.ts +0 -6
  140. package/x/ui/components.js +0 -7
  141. package/x/ui/components.js.map +0 -1
  142. package/x/ui/copy/component.js.map +0 -1
  143. package/x/ui/copy/style.css.js.map +0 -1
  144. package/x/ui/example/component.js.map +0 -1
  145. package/x/ui/example/style.css.js +0 -10
  146. package/x/ui/example/style.css.js.map +0 -1
  147. package/x/ui/framework.d.ts +0 -4
  148. package/x/ui/framework.js +0 -6
  149. package/x/ui/framework.js.map +0 -1
  150. package/x/ui/themers.d.ts +0 -8
  151. package/x/ui/themers.js +0 -12
  152. package/x/ui/themers.js.map +0 -1
  153. /package/x/{ui → components}/copy/style.css.d.ts +0 -0
  154. /package/x/{ui/example → components/drawer}/style.css.d.ts +0 -0
package/README.md CHANGED
@@ -1,10 +1,117 @@
1
1
 
2
- <div align="center"><img alt="" width="256" src="./assets/favicon.png"/></div>
2
+ ![](https://i.imgur.com/F1J78wH.png)
3
3
 
4
- # ✨ shiny
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: #afa;
97
+ --shiny-happy: #0fa;
98
+ --shiny-sad: #74f;
99
+ --shiny-angry: #f50;
100
+ --shiny-lame: #8888;
101
+ --shiny-inactive-opacity: 0.5;
102
+ }
103
+ </style>
104
+ ```
105
+
106
+
107
+
108
+ <br/><br/>
109
+
110
+ ## 🧑‍💻 by e280
111
+ reward us with github stars
112
+ build with us at https://e280.org/ if you're good at dev
113
+
114
+
8
115
 
9
116
  <br/><br/>
10
117
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@e280/shiny",
3
- "version": "0.1.0-1",
3
+ "version": "0.1.0-10",
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-21",
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.6"
22
+ "@e280/stz": "^0.2.9"
23
23
  },
24
24
  "devDependencies": {
25
25
  "@e280/science": "^0.1.2",
@@ -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 {ShinyElement} from "../framework.js"
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 => (theme: CSSResult, text: string | undefined, ms = 1000) => {
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.theme, el.attrs.text, el.attrs.ms])
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: 0.5;
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(--invalid);
25
+ color: var(--lame);
26
26
  }
27
27
 
28
28
  [data-status="good"] {
29
29
  opacity: 1;
30
- color: var(--good);
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(--bad);
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 {ShinyElement} from "../framework.js"
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 => (theme: CSSResult, start: number) => {
9
- use.styles(theme, styleCss)
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.theme, el.attrs.start ?? 1] as const)
25
+ .props(el => [el.context, el.attrs.start ?? 1] as const)
24
26
  ) {}
25
27
 
@@ -1,11 +1,11 @@
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
  padding: 1em;
7
7
  min-width: 4em;
8
8
  }
9
9
 
10
- `
10
+ }`
11
11
 
@@ -0,0 +1,15 @@
1
+
2
+ import {css} from "lit"
3
+ import {cssReset} from "@e280/sly"
4
+ export const foundationCss = css`
5
+
6
+ @layer reset, underlay, view, overlay;
7
+
8
+ ${cssReset}
9
+
10
+ @layer overlay {
11
+ [hidden] { display: none !important; }
12
+ }
13
+
14
+ `
15
+
@@ -0,0 +1,10 @@
1
+
2
+ import {CSSResultGroup} from "lit"
3
+ import {BaseElement} from "@e280/sly"
4
+
5
+ export type ShinyContext = {theme: CSSResultGroup}
6
+
7
+ export class ShinyElement extends BaseElement {
8
+ context!: ShinyContext
9
+ }
10
+
@@ -0,0 +1,13 @@
1
+
2
+ import {ShinyCopy} from "./copy/component.js"
3
+ import {ShinyDrawer} from "./drawer/component.js"
4
+ import {ShinyExample} from "./example/component.js"
5
+ import {ShinyTabs} from "./tabs/component.js"
6
+
7
+ export const rawComponents = {
8
+ ShinyCopy,
9
+ ShinyDrawer,
10
+ ShinyExample,
11
+ ShinyTabs,
12
+ }
13
+
@@ -0,0 +1,59 @@
1
+
2
+ import {html} from "lit"
3
+ import {dom, view} from "@e280/sly"
4
+ import styleCss from "./style.css.js"
5
+ import {TabControl} from "./control.js"
6
+ import {foundationCss} from "../foundation.css.js"
7
+ import {ShinyContext, ShinyElement} from "../framework.js"
8
+
9
+ export class ShinyTabs extends (
10
+ view(use => (context: ShinyContext, controlOption?: TabControl) => {
11
+ use.name("shiny-tabs")
12
+ use.styles(foundationCss, context.theme, styleCss)
13
+
14
+ const attrs = use.attrs.spec({index: Number})
15
+ const control = use.once(() => controlOption ?? new TabControl(attrs.index ?? 0))
16
+ const $tabs = use.signal<HTMLElement[]>([])
17
+ const $panels = use.signal<HTMLElement[]>([])
18
+
19
+ async function tabchange(event: Event) {
20
+ const slot = event.currentTarget! as HTMLSlotElement
21
+ await $tabs.set(slot.assignedElements() as HTMLElement[])
22
+ }
23
+
24
+ async function panelchange(event: Event) {
25
+ const slot = event.currentTarget! as HTMLSlotElement
26
+ await $panels.set(slot.assignedElements() as HTMLElement[])
27
+ }
28
+
29
+ attrs.index = control.$index()
30
+ control.length = $tabs().length
31
+
32
+ for (const [index, tab] of $tabs().entries()) {
33
+ const active = (index === control.index)
34
+ dom.attrs(tab).booleans.active = active
35
+ dom.attrs(tab).booleans.disabled = active
36
+ tab.onclick = () => control.setIndex(index)
37
+ }
38
+
39
+ for (const [index, tab] of $panels().entries()) {
40
+ const active = (index === control.index)
41
+ dom.attrs(tab).booleans.active = active
42
+ dom.attrs(tab).booleans.hidden = !active
43
+ }
44
+
45
+ return html`
46
+ <slot part=tabs @slotchange="${tabchange}"></slot>
47
+ <slot part=panels name=panel @slotchange="${panelchange}"></slot>
48
+ `
49
+ })
50
+ .component(class extends ShinyElement {
51
+ control = new TabControl()
52
+ get index() { return this.control.index }
53
+ get length() { return this.control.length }
54
+ setIndex = this.control.setIndex.bind(this.control)
55
+ shimmy = this.control.shimmy.bind(this.control)
56
+ })
57
+ .props(el => [el.context, el.control] as const)
58
+ ) {}
59
+
@@ -0,0 +1,31 @@
1
+
2
+ import {signal} from "@e280/strata"
3
+
4
+ export class TabControl {
5
+ length = 1
6
+ $index = signal(0)
7
+
8
+ constructor(start = 0) {
9
+ this.$index.value = start
10
+ }
11
+
12
+ #clamp(index: number) {
13
+ index = Math.min(index, this.length - 1)
14
+ index = Math.max(index, 0)
15
+ return index
16
+ }
17
+
18
+ get index() {
19
+ return this.#clamp(this.$index.get())
20
+ }
21
+
22
+ async setIndex(index: number) {
23
+ return this.$index.set(index)
24
+ }
25
+
26
+ async shimmy(delta: number) {
27
+ const index = this.#clamp(this.index + delta)
28
+ return this.setIndex(index)
29
+ }
30
+ }
31
+
@@ -0,0 +1,6 @@
1
+
2
+ import {css} from "lit"
3
+ export default css`@layer view {
4
+
5
+ }`
6
+
@@ -0,0 +1,6 @@
1
+
2
+ import {shiny} from "../shiny.js"
3
+ import {aura} from "../themes/aura.css.js"
4
+
5
+ export const auraViews = shiny({theme: aura}).views
6
+