@e280/shiny 0.1.0-2 → 0.1.0-20

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 (246) hide show
  1. package/README.md +51 -63
  2. package/package.json +19 -26
  3. package/s/_archive/components/button/component.ts +30 -0
  4. package/s/_archive/components/button/showcase.ts +119 -0
  5. package/s/_archive/components/button/style.css.ts +63 -0
  6. package/s/{ui → _archive/components}/copy/component.ts +12 -5
  7. package/s/_archive/components/copy/showcase.ts +51 -0
  8. package/s/{ui → _archive/components}/copy/style.css.ts +6 -6
  9. package/s/_archive/components/drawer/component.ts +90 -0
  10. package/s/_archive/components/drawer/control.ts +31 -0
  11. package/s/_archive/components/drawer/showcase.ts +111 -0
  12. package/s/_archive/components/drawer/style.css.ts +127 -0
  13. package/s/{ui → _archive/components}/example/component.ts +6 -4
  14. package/s/_archive/components/example/showcase.ts +32 -0
  15. package/s/{ui → _archive/components}/example/style.css.ts +2 -2
  16. package/s/_archive/components/foundation.css.ts +15 -0
  17. package/s/{ui → _archive/components}/framework.ts +1 -2
  18. package/s/_archive/components/raw-components.ts +15 -0
  19. package/s/_archive/components/tabs/component.ts +70 -0
  20. package/s/_archive/components/tabs/control.ts +31 -0
  21. package/s/_archive/components/tabs/showcase.ts +171 -0
  22. package/s/_archive/components/tabs/style.css.ts +46 -0
  23. package/s/_archive/demo/demo.bundle.ts +47 -0
  24. package/s/{demo → _archive/demo}/demo.css +1 -0
  25. package/s/_archive/demo/lipsum.ts +6 -0
  26. package/s/_archive/demo/utils/lipsum.ts +19 -0
  27. package/s/_archive/demo/views/exhibit/style.css.ts +85 -0
  28. package/s/_archive/demo/views/exhibit/view.ts +61 -0
  29. package/s/_archive/demo/views/showcase/style.css.ts +53 -0
  30. package/s/_archive/demo/views/showcase/view.ts +54 -0
  31. package/s/_archive/demo/viewsets.ts +12 -0
  32. package/s/_archive/index.html.ts +34 -0
  33. package/s/_archive/index.ts +19 -0
  34. package/s/_archive/install/aura.bundle.ts +9 -0
  35. package/s/_archive/install/plain.bundle.ts +9 -0
  36. package/s/{shiny.ts → _archive/shiny.ts} +2 -2
  37. package/s/_archive/themes/aura.css.ts +86 -0
  38. package/s/_archive/themes/index.barrel.ts +4 -0
  39. package/s/{themes → _archive/themes}/index.ts +1 -0
  40. package/s/_archive/themes/infra/css-vars.ts +46 -0
  41. package/s/_archive/themes/plain.css.ts +11 -0
  42. package/s/_archive/utils/states.ts +15 -0
  43. package/s/demo/main.bundle.ts +16 -0
  44. package/s/demo/main.css +71 -0
  45. package/s/demo/parts/exhibit.ts +15 -0
  46. package/s/demo/utils/lipsum.ts +19 -0
  47. package/s/demo/views/codebox/style.css.ts +45 -0
  48. package/s/demo/views/codebox/use-prism-styles.ts +13 -0
  49. package/s/demo/views/codebox/view.ts +39 -0
  50. package/s/demo/views/showcase/style.css.ts +80 -0
  51. package/s/demo/views/showcase/view.ts +50 -0
  52. package/s/demo/views/stylebox/view.ts +21 -0
  53. package/s/icons/tabler/menu-2.svg.ts +4 -0
  54. package/s/icons/tabler/x.svg.ts +4 -0
  55. package/s/index.html.ts +42 -32
  56. package/s/index.ts +4 -7
  57. package/s/test.ts +5 -0
  58. package/s/theme/parts/core.ts +34 -0
  59. package/s/theme/parts/reset.ts +20 -0
  60. package/s/theme/parts/vars.ts +41 -0
  61. package/s/theme/theme-string.ts +15 -0
  62. package/s/theme/theme.css.ts +7 -0
  63. package/s/utils/states.ts +15 -0
  64. package/s/views/button/showcase.ts +43 -0
  65. package/s/views/button/style.css.ts +110 -0
  66. package/s/views/button/view.ts +32 -0
  67. package/s/views/copy/parts/copy-status.ts +3 -0
  68. package/s/views/copy/parts/determine-base-status.ts +7 -0
  69. package/s/views/copy/parts/use-copier.ts +20 -0
  70. package/s/views/copy/showcase.ts +54 -0
  71. package/s/views/copy/style.css.ts +51 -0
  72. package/s/views/copy/view.ts +60 -0
  73. package/s/views/drawer/control.ts +31 -0
  74. package/s/views/drawer/showcase.ts +83 -0
  75. package/s/views/drawer/style.css.ts +128 -0
  76. package/s/views/drawer/view.ts +76 -0
  77. package/s/views/tabs/control.ts +31 -0
  78. package/s/views/tabs/showcase.ts +89 -0
  79. package/s/views/tabs/style.css.ts +46 -0
  80. package/s/views/tabs/view.ts +66 -0
  81. package/x/{demo → _archive/demo}/demo.css +1 -0
  82. package/x/demo/main.bundle.js +13 -0
  83. package/x/demo/main.bundle.js.map +1 -0
  84. package/x/demo/main.bundle.min.js +800 -0
  85. package/x/demo/main.bundle.min.js.map +7 -0
  86. package/x/demo/main.css +71 -0
  87. package/x/demo/parts/exhibit.d.ts +11 -0
  88. package/x/demo/parts/exhibit.js +2 -0
  89. package/x/demo/parts/exhibit.js.map +1 -0
  90. package/x/demo/utils/lipsum.d.ts +2 -0
  91. package/x/demo/utils/lipsum.js +11 -0
  92. package/x/demo/utils/lipsum.js.map +1 -0
  93. package/x/demo/views/codebox/style.css.js +44 -0
  94. package/x/demo/views/codebox/style.css.js.map +1 -0
  95. package/x/demo/views/codebox/use-prism-styles.d.ts +1 -0
  96. package/x/demo/views/codebox/use-prism-styles.js +12 -0
  97. package/x/demo/views/codebox/use-prism-styles.js.map +1 -0
  98. package/x/demo/views/codebox/view.d.ts +2 -0
  99. package/x/demo/views/codebox/view.js +29 -0
  100. package/x/demo/views/codebox/view.js.map +1 -0
  101. package/x/demo/views/showcase/style.css.js +79 -0
  102. package/x/demo/views/showcase/style.css.js.map +1 -0
  103. package/x/demo/views/showcase/view.d.ts +2 -0
  104. package/x/demo/views/showcase/view.js +44 -0
  105. package/x/demo/views/showcase/view.js.map +1 -0
  106. package/x/demo/views/stylebox/view.d.ts +3 -0
  107. package/x/demo/views/stylebox/view.js +13 -0
  108. package/x/demo/views/stylebox/view.js.map +1 -0
  109. package/x/icons/tabler/menu-2.svg.d.ts +2 -0
  110. package/x/icons/tabler/menu-2.svg.js +3 -0
  111. package/x/icons/tabler/menu-2.svg.js.map +1 -0
  112. package/x/icons/tabler/x.svg.d.ts +2 -0
  113. package/x/icons/tabler/x.svg.js +3 -0
  114. package/x/icons/tabler/x.svg.js.map +1 -0
  115. package/x/index.d.ts +4 -5
  116. package/x/index.html +212 -61
  117. package/x/index.html.js +40 -29
  118. package/x/index.html.js.map +1 -1
  119. package/x/index.js +4 -5
  120. package/x/index.js.map +1 -1
  121. package/x/test.js +3 -0
  122. package/x/test.js.map +1 -0
  123. package/x/theme/parts/core.d.ts +1 -0
  124. package/x/theme/parts/core.js +33 -0
  125. package/x/theme/parts/core.js.map +1 -0
  126. package/x/theme/parts/reset.d.ts +1 -0
  127. package/x/theme/parts/reset.js +19 -0
  128. package/x/theme/parts/reset.js.map +1 -0
  129. package/x/theme/parts/vars.d.ts +1 -0
  130. package/x/theme/parts/vars.js +34 -0
  131. package/x/theme/parts/vars.js.map +1 -0
  132. package/x/theme/theme-string.d.ts +1 -0
  133. package/x/theme/theme-string.js +14 -0
  134. package/x/theme/theme-string.js.map +1 -0
  135. package/x/theme/theme.css.d.ts +1 -0
  136. package/x/theme/theme.css.js +4 -0
  137. package/x/theme/theme.css.js.map +1 -0
  138. package/x/utils/states.d.ts +5 -0
  139. package/x/utils/states.js +13 -0
  140. package/x/utils/states.js.map +1 -0
  141. package/x/views/button/showcase.d.ts +1 -0
  142. package/x/views/button/showcase.js +41 -0
  143. package/x/views/button/showcase.js.map +1 -0
  144. package/x/views/button/style.css.js +109 -0
  145. package/x/views/button/style.css.js.map +1 -0
  146. package/x/views/button/view.d.ts +5 -0
  147. package/x/views/button/view.js +23 -0
  148. package/x/views/button/view.js.map +1 -0
  149. package/x/views/copy/parts/copy-status.d.ts +1 -0
  150. package/x/views/copy/parts/copy-status.js +2 -0
  151. package/x/views/copy/parts/copy-status.js.map +1 -0
  152. package/x/views/copy/parts/determine-base-status.d.ts +1 -0
  153. package/x/views/copy/parts/determine-base-status.js +6 -0
  154. package/x/views/copy/parts/determine-base-status.js.map +1 -0
  155. package/x/views/copy/parts/use-copier.d.ts +6 -0
  156. package/x/views/copy/parts/use-copier.js +13 -0
  157. package/x/views/copy/parts/use-copier.js.map +1 -0
  158. package/x/views/copy/showcase.d.ts +1 -0
  159. package/x/views/copy/showcase.js +51 -0
  160. package/x/views/copy/showcase.js.map +1 -0
  161. package/x/views/copy/style.css.d.ts +2 -0
  162. package/x/{ui → views}/copy/style.css.js +14 -9
  163. package/x/views/copy/style.css.js.map +1 -0
  164. package/x/views/copy/view.d.ts +4 -0
  165. package/x/views/copy/view.js +49 -0
  166. package/x/views/copy/view.js.map +1 -0
  167. package/x/views/drawer/control.d.ts +9 -0
  168. package/x/views/drawer/control.js +24 -0
  169. package/x/views/drawer/control.js.map +1 -0
  170. package/x/views/drawer/showcase.d.ts +1 -0
  171. package/x/views/drawer/showcase.js +75 -0
  172. package/x/views/drawer/showcase.js.map +1 -0
  173. package/x/views/drawer/style.css.d.ts +2 -0
  174. package/x/views/drawer/style.css.js +127 -0
  175. package/x/views/drawer/style.css.js.map +1 -0
  176. package/x/views/drawer/view.d.ts +6 -0
  177. package/x/views/drawer/view.js +60 -0
  178. package/x/views/drawer/view.js.map +1 -0
  179. package/x/views/tabs/control.d.ts +9 -0
  180. package/x/views/tabs/control.js +24 -0
  181. package/x/views/tabs/control.js.map +1 -0
  182. package/x/views/tabs/showcase.d.ts +1 -0
  183. package/x/views/tabs/showcase.js +86 -0
  184. package/x/views/tabs/showcase.js.map +1 -0
  185. package/x/views/tabs/style.css.d.ts +2 -0
  186. package/x/views/tabs/style.css.js +45 -0
  187. package/x/views/tabs/style.css.js.map +1 -0
  188. package/x/views/tabs/view.d.ts +5 -0
  189. package/x/views/tabs/view.js +52 -0
  190. package/x/views/tabs/view.js.map +1 -0
  191. package/s/demo/demo.bundle.ts +0 -42
  192. package/s/demo/views/demonstration/style.css.ts +0 -108
  193. package/s/demo/views/demonstration/view.ts +0 -49
  194. package/s/install.bundle.ts +0 -9
  195. package/s/themes/basic.css.ts +0 -18
  196. package/s/themes/index.barrel.ts +0 -3
  197. package/s/ui/raw-components.ts +0 -9
  198. package/x/demo/demo.bundle.js +0 -37
  199. package/x/demo/demo.bundle.js.map +0 -1
  200. package/x/demo/demo.bundle.min.js +0 -277
  201. package/x/demo/demo.bundle.min.js.map +0 -7
  202. package/x/demo/views/demonstration/style.css.js +0 -107
  203. package/x/demo/views/demonstration/style.css.js.map +0 -1
  204. package/x/demo/views/demonstration/view.d.ts +0 -10
  205. package/x/demo/views/demonstration/view.js +0 -36
  206. package/x/demo/views/demonstration/view.js.map +0 -1
  207. package/x/install.bundle.js +0 -5
  208. package/x/install.bundle.js.map +0 -1
  209. package/x/install.bundle.min.js +0 -135
  210. package/x/install.bundle.min.js.map +0 -7
  211. package/x/shiny.d.ts +0 -14
  212. package/x/shiny.js +0 -8
  213. package/x/shiny.js.map +0 -1
  214. package/x/tests.test.d.ts +0 -1
  215. package/x/tests.test.js +0 -3
  216. package/x/tests.test.js.map +0 -1
  217. package/x/themes/basic.css.d.ts +0 -1
  218. package/x/themes/basic.css.js +0 -17
  219. package/x/themes/basic.css.js.map +0 -1
  220. package/x/themes/index.barrel.d.ts +0 -1
  221. package/x/themes/index.barrel.js +0 -2
  222. package/x/themes/index.barrel.js.map +0 -1
  223. package/x/themes/index.d.ts +0 -1
  224. package/x/themes/index.js +0 -2
  225. package/x/themes/index.js.map +0 -1
  226. package/x/ui/copy/component.d.ts +0 -372
  227. package/x/ui/copy/component.js +0 -56
  228. package/x/ui/copy/component.js.map +0 -1
  229. package/x/ui/copy/style.css.js.map +0 -1
  230. package/x/ui/example/component.d.ts +0 -371
  231. package/x/ui/example/component.js +0 -20
  232. package/x/ui/example/component.js.map +0 -1
  233. package/x/ui/example/style.css.js +0 -10
  234. package/x/ui/example/style.css.js.map +0 -1
  235. package/x/ui/framework.d.ts +0 -8
  236. package/x/ui/framework.js +0 -6
  237. package/x/ui/framework.js.map +0 -1
  238. package/x/ui/raw-components.d.ts +0 -6
  239. package/x/ui/raw-components.js +0 -7
  240. package/x/ui/raw-components.js.map +0 -1
  241. /package/s/{tests.test.ts → _archive/tests.test.ts} +0 -0
  242. /package/x/demo/{demo.bundle.d.ts → main.bundle.d.ts} +0 -0
  243. /package/x/demo/views/{demonstration → codebox}/style.css.d.ts +0 -0
  244. /package/x/{ui/copy → demo/views/showcase}/style.css.d.ts +0 -0
  245. /package/x/{install.bundle.d.ts → test.d.ts} +0 -0
  246. /package/x/{ui/example → views/button}/style.css.d.ts +0 -0
@@ -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,111 @@
1
+
2
+ import {css, html} from "lit"
3
+ import {lipsum} from "../../demo/lipsum.js"
4
+ import {Showcase} from "../../demo/views/showcase/view.js"
5
+ import {ExhibitParams} from "../../demo/views/exhibit/view.js"
6
+
7
+ const lip1 = lipsum()
8
+ const lip2 = lipsum()
9
+ const lip3 = lipsum()
10
+
11
+ const cssSnippet = `
12
+ [view="shiny-drawer"] {
13
+ --button-size: 2em;
14
+ --anim-duration: 200ms;
15
+ --slate-hidden-opacity: 1;
16
+ --blanket-backdrop-filter: blur(0.5em);
17
+ --blanket-bg: color-mix(
18
+ in oklab,
19
+ transparent,
20
+ var(--bg)
21
+ );
22
+ --slate-bg: linear-gradient(
23
+ to top right,
24
+ color-mix(in oklab, var(--calm), #222 50%),
25
+ color-mix(in oklab, var(--calm), #888 50%)
26
+ );
27
+
28
+ &:state(opened) {}
29
+ &:state(closed) {}
30
+
31
+ &:state(left) {}
32
+ &:state(right) {}
33
+
34
+ &::part(tray) {}
35
+ &::part(blanket) {}
36
+ &::part(button) {}
37
+ &::part(slate) {}
38
+
39
+ &::part(plate) {}
40
+ }
41
+ `
42
+
43
+ const makeExhibit = (side: "left" | "right"): ExhibitParams => ({
44
+ label: side,
45
+ explain: html`<p>slide-out panel. button optional.</p>`,
46
+ snippets: [
47
+ {label: "html", code: `
48
+ <shiny-drawer button side=${side}>
49
+ <header>example</header>
50
+ <section slot=plate>lorem kettlebell..</section>
51
+ </shiny-drawer>
52
+ `},
53
+ {label: "view", code: `
54
+ ShinyDrawer
55
+ .props({button: true, side: "${side}"})
56
+ .children(html\`
57
+ <header>example</header>
58
+ <section slot=plate>lorem kettlebell..</section>
59
+ \`)
60
+ .render()
61
+ `},
62
+ {label: "css", code: cssSnippet},
63
+ ],
64
+ style: css``,
65
+ presentation: views => html`
66
+ ${views.ShinyDrawer
67
+ .props({button: true, side})
68
+ .children(html`
69
+ <header>
70
+ <h2>example drawer</h2>
71
+ <p>you can put any content in here.</p>
72
+ <p class=lipsum>${lip1}</p>
73
+ </header>
74
+ <section slot=plate>
75
+ <p class=lipsum>${lip2}</p>
76
+ <p class=lipsum>${lip3}</p>
77
+ </section>
78
+ `)
79
+ .render()}
80
+ `,
81
+ })
82
+
83
+ export const drawerShowcase = () => Showcase({
84
+ name: "drawer",
85
+ style: css`
86
+ .box sly-view {
87
+ border-radius: 0.5em;
88
+ overflow: hidden;
89
+ --button-size: 3em;
90
+
91
+ header {
92
+ > * + * { margin-top: 0.5em; }
93
+ }
94
+
95
+ section {
96
+ display: flex;
97
+ flex-direction: column;
98
+ justify-content: center;
99
+ min-height: 100%;
100
+ padding: 1em;
101
+ padding-top: 3em;
102
+ > * + * { margin-top: 0.5em; }
103
+ }
104
+ }
105
+ `,
106
+ exhibits: [
107
+ makeExhibit("left"),
108
+ makeExhibit("right"),
109
+ ],
110
+ })
111
+
@@ -0,0 +1,127 @@
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
+ --slate-bg: transparent;
10
+ --button-size: 2em;
11
+ --blanket-backdrop-filter: blur(0.5em);
12
+ --slate-hidden-opacity: 1;
13
+ --blanket-bg: color-mix(in oklab, transparent, var(--bg));
14
+ }
15
+
16
+ .shell {
17
+ position: relative;
18
+ width: 100%;
19
+ height: 100%;
20
+
21
+ [part="blanket"] {
22
+ opacity: 0;
23
+
24
+ content: "";
25
+ display: block;
26
+ position: absolute;
27
+ inset: 0;
28
+
29
+ background: var(--blanket-bg);
30
+ backdrop-filter: var(--blanket-backdrop-filter);
31
+
32
+ will-change: opacity;
33
+ transition: all var(--anim-duration) ease;
34
+ }
35
+
36
+ .clipper {
37
+ pointer-events: none;
38
+ position: absolute;
39
+ inset: 0;
40
+ width: 100%;
41
+ height: 100%;
42
+ overflow: hidden;
43
+ > * { pointer-events: all; }
44
+ }
45
+
46
+ [part="tray"] {
47
+ position: absolute;
48
+ top: 0;
49
+ width: calc(100% - var(--button-size));
50
+
51
+ display: flex;
52
+ flex-direction: column;
53
+ height: auto;
54
+ max-height: 100%;
55
+
56
+ transform: translateX(-100%);
57
+ will-change: opacity, transform;
58
+ transition: all var(--anim-duration) ease;
59
+
60
+ > [part="slate"] {
61
+ opacity: var(--slate-hidden-opacity);
62
+ will-change: opacity;
63
+ transition: opacity var(--anim-duration) ease;
64
+
65
+ display: block;
66
+ height: 100%;
67
+ overflow-y: auto;
68
+ background: var(--slate-bg);
69
+ }
70
+
71
+ > button {
72
+ position: absolute;
73
+ top: 0;
74
+ left: 100%;
75
+
76
+ opacity: var(--inactive-opacity);
77
+ background: transparent;
78
+ border: none;
79
+ cursor: pointer;
80
+
81
+ &:is(:hover, :focus-visible) {
82
+ opacity: 1;
83
+ }
84
+
85
+ > slot {
86
+ display: contents;
87
+ }
88
+
89
+ svg {
90
+ width: var(--button-size);
91
+ height: var(--button-size);
92
+ }
93
+ }
94
+ }
95
+
96
+ &[data-side="right"] {
97
+ [part="tray"] {
98
+ right: 0;
99
+ transform: translateX(100%);
100
+ > button {
101
+ left: unset;
102
+ right: 100%;
103
+ }
104
+ }
105
+ }
106
+
107
+ slot[name="plate"] {
108
+ display: block;
109
+ width: 100%;
110
+ height: 100%;
111
+ }
112
+
113
+ &[data-open] {
114
+ [part="blanket"] {
115
+ opacity: 1;
116
+ }
117
+ [part="tray"] {
118
+ transform: translateX(0%);
119
+ > [part="slate"] {
120
+ opacity: 1;
121
+ }
122
+ }
123
+ }
124
+ }
125
+
126
+ }`
127
+
@@ -1,12 +1,14 @@
1
1
 
2
- import {dom, view} from "@e280/sly"
3
2
  import {html} from "lit"
3
+ import {dom, view} from "@e280/sly"
4
4
  import styleCss from "./style.css.js"
5
+ import {foundationCss} from "../foundation.css.js"
5
6
  import {ShinyContext, ShinyElement} from "../framework.js"
6
7
 
7
8
  export class ShinyExample extends (
8
- view(use => (context: ShinyContext, start: number) => {
9
- use.styles(context.theme, styleCss)
9
+ view(use => (context: ShinyContext, start = 1) => {
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.context, el.attrs.start ?? 1] as const)
25
+ .props(el => [el.context, el.attrs.start] as const)
24
26
  ) {}
25
27
 
@@ -0,0 +1,32 @@
1
+
2
+ import {css, html} from "lit"
3
+ import {Showcase} from "../../demo/views/showcase/view.js"
4
+
5
+ export const drawerShowcase = () => Showcase({
6
+ name: "drawer",
7
+ style: css`
8
+ .box {}
9
+ `,
10
+ exhibits: [
11
+ {
12
+ label: "example",
13
+ explain: html`<p>example component.</p>`,
14
+ snippets: [
15
+ {label: "html", code: `
16
+ <shiny-example></shiny-example>
17
+ `},
18
+ {label: "view", code: `
19
+ ShinyExample()
20
+ `},
21
+ {label: "css", code: `
22
+ [view="shiny-example"] {}
23
+ `},
24
+ ],
25
+ style: css``,
26
+ presentation: views => html`
27
+ ${views.ShinyExample()}
28
+ `,
29
+ },
30
+ ],
31
+ })
32
+
@@ -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
+
@@ -1,11 +1,10 @@
1
1
 
2
2
  import {CSSResultGroup} from "lit"
3
3
  import {BaseElement} from "@e280/sly"
4
- import {basic} from "../themes/basic.css.js"
5
4
 
6
5
  export type ShinyContext = {theme: CSSResultGroup}
7
6
 
8
7
  export class ShinyElement extends BaseElement {
9
- context: ShinyContext = {theme: basic}
8
+ context!: ShinyContext
10
9
  }
11
10
 
@@ -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
+
@@ -0,0 +1,70 @@
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
+ function isNeighborActive(index: number, delta: number) {
33
+ const nextIndex = control.clamp(index + delta)
34
+ if (nextIndex === index) return false
35
+ return (nextIndex === control.index)
36
+ }
37
+
38
+ for (const [index, tab] of $tabs().entries()) {
39
+ const active = (index === control.index)
40
+ const tabAttrs = dom.attrs(tab)
41
+ tabAttrs.booleans.disabled = active
42
+ tabAttrs.booleans["data-active"] = active
43
+ tabAttrs.booleans["data-first"] = (index === 0)
44
+ tabAttrs.booleans["data-last"] = (index === (control.length - 1))
45
+ tabAttrs.booleans["data-next-is-active"] = isNeighborActive(index, 1)
46
+ tabAttrs.booleans["data-previous-is-active"] = isNeighborActive(index, -1)
47
+ tab.onclick = () => control.setIndex(index)
48
+ }
49
+
50
+ for (const [index, tab] of $panels().entries()) {
51
+ const active = (index === control.index)
52
+ dom.attrs(tab).booleans.active = active
53
+ dom.attrs(tab).booleans.hidden = !active
54
+ }
55
+
56
+ return html`
57
+ <slot part=tabs @slotchange="${tabchange}"></slot>
58
+ <slot part=panels name=panel @slotchange="${panelchange}"></slot>
59
+ `
60
+ })
61
+ .component(class extends ShinyElement {
62
+ control = new TabControl()
63
+ get index() { return this.control.index }
64
+ get length() { return this.control.length }
65
+ setIndex = this.control.setIndex.bind(this.control)
66
+ shimmy = this.control.shimmy.bind(this.control)
67
+ })
68
+ .props(el => [el.context, el.control] as const)
69
+ ) {}
70
+
@@ -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,171 @@
1
+
2
+ import {css, html} from "lit"
3
+ import {lipsum} from "../../demo/lipsum.js"
4
+ import {Showcase} from "../../demo/views/showcase/view.js"
5
+
6
+ const lip1 = lipsum()
7
+ const lip2 = lipsum()
8
+ const lip3 = lipsum()
9
+
10
+ const cssSnippet = `
11
+ [view="shiny-tabs"] {
12
+ &::part(tabs) {}
13
+ &::part(panels) {}
14
+
15
+ /* buttons */
16
+ > :not([slot="panel"]) {}
17
+
18
+ /* panels */
19
+ > [slot="panel"] {}
20
+ }
21
+ `
22
+
23
+ export const tabsShowcase = () => Showcase({
24
+ name: "tabs",
25
+ style: css`
26
+ .box {
27
+ place-content: start start;
28
+ p { margin-top: 0.5em; }
29
+ button { padding: 1em; }
30
+ }
31
+ `,
32
+ exhibits: [
33
+ {
34
+ label: "shiny snug",
35
+ explain: html`<p>button bar. panels optional.</p>`,
36
+ snippets: [
37
+ {label: "html", code: `
38
+ <shiny-tabs snug>
39
+ <shiny-button>tab1</shiny-button>
40
+ <shiny-button>tab2</shiny-button>
41
+ <shiny-button>tab3</shiny-button>
42
+ <div slot=panel>panel1</div>
43
+ <div slot=panel>panel2</div>
44
+ <div slot=panel>panel3</div>
45
+ </shiny-tabs>
46
+ `},
47
+ {label: "view", code: `
48
+ ShinyTabs
49
+ .props()
50
+ .attr("snug")
51
+ .children(html\`
52
+ \${ShinyButton.props().children("tab1").render()}
53
+ \${ShinyButton.props().children("tab2").render()}
54
+ \${ShinyButton.props().children("tab3").render()}
55
+ <div slot=panel>panel1</div>
56
+ <div slot=panel>panel2</div>
57
+ <div slot=panel>panel3</div>
58
+ \`)
59
+ .render()
60
+ `},
61
+ {label: "css", code: cssSnippet},
62
+ ],
63
+ style: css``,
64
+ presentation: views => html`
65
+ ${views.ShinyTabs
66
+ .props()
67
+ .attr("snug")
68
+ .children(html`
69
+ ${views.ShinyButton.props().children("tab1").render()}
70
+ ${views.ShinyButton.props().children("tab2").render()}
71
+ ${views.ShinyButton.props().children("tab3").render()}
72
+ <p slot=panel class=lipsum>${lip1}</p>
73
+ <p slot=panel class=lipsum>${lip2}</p>
74
+ <p slot=panel class=lipsum>${lip3}</p>
75
+ `)
76
+ .render()}
77
+ `,
78
+ },
79
+ {
80
+ label: "regular",
81
+ explain: html`<p>button bar. panels optional.</p>`,
82
+ snippets: [
83
+ {label: "html", code: `
84
+ <shiny-tabs>
85
+ <button>tab1</button>
86
+ <button>tab2</button>
87
+ <button>tab3</button>
88
+ <div slot=panel>panel1</div>
89
+ <div slot=panel>panel2</div>
90
+ <div slot=panel>panel3</div>
91
+ </shiny-tabs>
92
+ `},
93
+ {label: "view", code: `
94
+ ShinyTabs
95
+ .props()
96
+ .children(html\`
97
+ <button>tab1</button>
98
+ <button>tab2</button>
99
+ <button>tab3</button>
100
+ <div slot=panel>panel1</div>
101
+ <div slot=panel>panel2</div>
102
+ <div slot=panel>panel3</div>
103
+ \`)
104
+ .render()
105
+ `},
106
+ {label: "css", code: cssSnippet},
107
+ ],
108
+ style: css``,
109
+ presentation: views => html`
110
+ ${views.ShinyTabs
111
+ .props()
112
+ .children(html`
113
+ <button>tab1</button>
114
+ <button>tab2</button>
115
+ <button>tab3</button>
116
+ <p slot=panel class=lipsum>${lip1}</p>
117
+ <p slot=panel class=lipsum>${lip2}</p>
118
+ <p slot=panel class=lipsum>${lip3}</p>
119
+ `)
120
+ .render()}
121
+ `,
122
+ },
123
+ {
124
+ label: "regular snug",
125
+ explain: html`<p>button bar. panels optional.</p>`,
126
+ snippets: [
127
+ {label: "html", code: `
128
+ <shiny-tabs snug>
129
+ <button>tab1</button>
130
+ <button>tab2</button>
131
+ <button>tab3</button>
132
+ <div slot=panel>panel1</div>
133
+ <div slot=panel>panel2</div>
134
+ <div slot=panel>panel3</div>
135
+ </shiny-tabs>
136
+ `},
137
+ {label: "view", code: `
138
+ ShinyTabs
139
+ .props()
140
+ .attr("snug")
141
+ .children(html\`
142
+ <button>tab1</button>
143
+ <button>tab2</button>
144
+ <button>tab3</button>
145
+ <div slot=panel>panel1</div>
146
+ <div slot=panel>panel2</div>
147
+ <div slot=panel>panel3</div>
148
+ \`)
149
+ .render()
150
+ `},
151
+ {label: "css", code: cssSnippet},
152
+ ],
153
+ style: css``,
154
+ presentation: views => html`
155
+ ${views.ShinyTabs
156
+ .props()
157
+ .attr("snug")
158
+ .children(html`
159
+ <button>tab1</button>
160
+ <button>tab2</button>
161
+ <button>tab3</button>
162
+ <p slot=panel class=lipsum>${lip1}</p>
163
+ <p slot=panel class=lipsum>${lip2}</p>
164
+ <p slot=panel class=lipsum>${lip3}</p>
165
+ `)
166
+ .render()}
167
+ `,
168
+ },
169
+ ],
170
+ })
171
+
@@ -0,0 +1,46 @@
1
+
2
+ import {css} from "lit"
3
+ export default css`@layer view {
4
+
5
+ :host {
6
+ display: inline-flex;
7
+ flex-direction: column;
8
+ }
9
+
10
+ slot[part="tabs"] {
11
+ display: flex;
12
+ flex-wrap: wrap;
13
+
14
+ &::slotted([data-active]) {
15
+ opacity: 1;
16
+ color: currentColor;
17
+ text-decoration: underline;
18
+ }
19
+ }
20
+
21
+ :host([snug]) slot[part="tabs"] {
22
+ &::slotted(*) {
23
+ border-radius: 0.3em;
24
+ }
25
+
26
+ &::slotted(:not([data-last], [data-next-is-active])) {
27
+ border-right: none;
28
+ }
29
+
30
+ &::slotted([data-active]:not([data-first])) {
31
+ border-left: none;
32
+ }
33
+
34
+ &::slotted(:not([data-last])) {
35
+ border-top-right-radius: 0;
36
+ border-bottom-right-radius: 0;
37
+ }
38
+
39
+ &::slotted(:not([data-first])) {
40
+ border-top-left-radius: 0;
41
+ border-bottom-left-radius: 0;
42
+ }
43
+ }
44
+
45
+ } `
46
+