@universal-ember/docs-support 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +9 -0
- package/README.md +3 -21
- package/declarations/{article.gts.d.ts → article.d.ts} +1 -1
- package/declarations/article.d.ts.map +1 -0
- package/declarations/{callout.gts.d.ts → callout.d.ts} +1 -1
- package/declarations/callout.d.ts.map +1 -0
- package/declarations/{errors.gts.d.ts → errors.d.ts} +1 -1
- package/declarations/errors.d.ts.map +1 -0
- package/declarations/{h2.gts.d.ts → h2.d.ts} +1 -1
- package/declarations/h2.d.ts.map +1 -0
- package/declarations/{icons.gts.d.ts → icons.d.ts} +1 -1
- package/declarations/icons.d.ts.map +1 -0
- package/declarations/{index-page.gts.d.ts → index-page.d.ts} +2 -2
- package/declarations/index-page.d.ts.map +1 -0
- package/declarations/index.d.ts +12 -0
- package/declarations/index.d.ts.map +1 -0
- package/declarations/{links.gts.d.ts → links.d.ts} +1 -1
- package/declarations/links.d.ts.map +1 -0
- package/declarations/{menu-layout.gts.d.ts → menu-layout.d.ts} +1 -1
- package/declarations/menu-layout.d.ts.map +1 -0
- package/declarations/{page-layout.gts.d.ts → page-layout.d.ts} +1 -1
- package/declarations/page-layout.d.ts.map +1 -0
- package/declarations/{shell.gts.d.ts → shell.d.ts} +1 -1
- package/declarations/shell.d.ts.map +1 -0
- package/declarations/{side-nav.gts.d.ts → side-nav.d.ts} +2 -3
- package/declarations/side-nav.d.ts.map +1 -0
- package/declarations/{text.gts.d.ts → text.d.ts} +1 -1
- package/declarations/text.d.ts.map +1 -0
- package/declarations/{theme-toggle.gts.d.ts → theme-toggle.d.ts} +1 -1
- package/declarations/theme-toggle.d.ts.map +1 -0
- package/dist/icons.js +11 -11
- package/dist/icons.js.map +1 -1
- package/dist/index.js +340 -11
- package/dist/index.js.map +1 -1
- package/dist/site-css/featured-demo.css +2 -2
- package/package.json +33 -42
- package/{dist/article.js → src/article.gts} +6 -11
- package/src/callout.gts +18 -0
- package/src/errors.gts +19 -0
- package/src/h2.gts +5 -0
- package/src/icons.gts +150 -0
- package/src/index-page.css +22 -0
- package/src/index-page.gts +41 -0
- package/{declarations/index.gts.d.ts → src/index.gts} +6 -7
- package/src/links.gts +31 -0
- package/src/menu-layout.gts +43 -0
- package/src/page-layout.gts +137 -0
- package/src/shell.gts +37 -0
- package/src/side-nav.gts +190 -0
- package/src/site-css/components.css +23 -0
- package/src/site-css/featured-demo.css +9 -0
- package/src/site-css/shell.css +102 -0
- package/src/site-css/shiki.css +27 -0
- package/src/site-css/site.css +77 -0
- package/src/text.gts +5 -0
- package/src/theme-toggle.css +48 -0
- package/src/theme-toggle.gts +36 -0
- package/declarations/article.gts.d.ts.map +0 -1
- package/declarations/callout.gts.d.ts.map +0 -1
- package/declarations/errors.gts.d.ts.map +0 -1
- package/declarations/h2.gts.d.ts.map +0 -1
- package/declarations/icons.gts.d.ts.map +0 -1
- package/declarations/index-page.gts.d.ts.map +0 -1
- package/declarations/index.gts.d.ts.map +0 -1
- package/declarations/links.gts.d.ts.map +0 -1
- package/declarations/menu-layout.gts.d.ts.map +0 -1
- package/declarations/page-layout.gts.d.ts.map +0 -1
- package/declarations/shell.gts.d.ts.map +0 -1
- package/declarations/side-nav.gts.d.ts.map +0 -1
- package/declarations/text.gts.d.ts.map +0 -1
- package/declarations/theme-toggle.gts.d.ts.map +0 -1
- package/dist/article.js.map +0 -1
- package/dist/callout.js +0 -14
- package/dist/callout.js.map +0 -1
- package/dist/errors.js +0 -10
- package/dist/errors.js.map +0 -1
- package/dist/h2.js +0 -10
- package/dist/h2.js.map +0 -1
- package/dist/index-page.js +0 -15
- package/dist/index-page.js.map +0 -1
- package/dist/links.js +0 -30
- package/dist/links.js.map +0 -1
- package/dist/menu-layout.js +0 -26
- package/dist/menu-layout.js.map +0 -1
- package/dist/page-layout.js +0 -60
- package/dist/page-layout.js.map +0 -1
- package/dist/shell.js +0 -30
- package/dist/shell.js.map +0 -1
- package/dist/side-nav.js +0 -116
- package/dist/side-nav.js.map +0 -1
- package/dist/text.js +0 -10
- package/dist/text.js.map +0 -1
- package/dist/theme-toggle.js +0 -33
- package/dist/theme-toggle.js.map +0 -1
package/src/icons.gts
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import type { TOC } from '@ember/component/template-only';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Copied from font-awesome directly,
|
|
5
|
+
* but with the addition of fill="currentColor"
|
|
6
|
+
*
|
|
7
|
+
* Font Awesome Free 6.6.0 by @fontawesome
|
|
8
|
+
* - https://fontawesome.com License
|
|
9
|
+
* - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.
|
|
10
|
+
*/
|
|
11
|
+
export const XTwitter: TOC<{ Element: SVGElement }> = <template>
|
|
12
|
+
<svg aria-hidden="true" ...attributes>
|
|
13
|
+
<use xlink:href="#social-xtwitter" />
|
|
14
|
+
</svg>
|
|
15
|
+
</template>;
|
|
16
|
+
|
|
17
|
+
export const Discord: TOC<{ Element: SVGElement }> = <template>
|
|
18
|
+
<svg aria-hidden="true" ...attributes>
|
|
19
|
+
<use xlink:href="#social-discord" />
|
|
20
|
+
</svg>
|
|
21
|
+
</template>;
|
|
22
|
+
|
|
23
|
+
export const Threads: TOC<{ Element: SVGElement }> = <template>
|
|
24
|
+
<svg aria-hidden="true" ...attributes>
|
|
25
|
+
<use xlink:href="#social-threads" />
|
|
26
|
+
</svg>
|
|
27
|
+
</template>;
|
|
28
|
+
|
|
29
|
+
export const BlueSky: TOC<{ Element: SVGElement }> = <template>
|
|
30
|
+
<svg aria-hidden="true" ...attributes>
|
|
31
|
+
<use xlink:href="#social-bluesky" />
|
|
32
|
+
</svg>
|
|
33
|
+
</template>;
|
|
34
|
+
|
|
35
|
+
export const Mastodon: TOC<{ Element: SVGElement }> = <template>
|
|
36
|
+
<svg aria-hidden="true" ...attributes>
|
|
37
|
+
<use xlink:href="#social-mastodon" />
|
|
38
|
+
</svg>
|
|
39
|
+
</template>;
|
|
40
|
+
|
|
41
|
+
export const GitHub: TOC<{ Element: SVGElement }> = <template>
|
|
42
|
+
<svg aria-hidden="true" ...attributes>
|
|
43
|
+
<use xlink:href="#social-github" />
|
|
44
|
+
</svg>
|
|
45
|
+
</template>;
|
|
46
|
+
|
|
47
|
+
export const Flask: TOC<{ Element: SVGElement }> = <template>
|
|
48
|
+
<svg
|
|
49
|
+
fill="currentColor"
|
|
50
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
51
|
+
height="1em"
|
|
52
|
+
viewBox="0 0 448 512"
|
|
53
|
+
...attributes
|
|
54
|
+
>{{!! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. }}<path
|
|
55
|
+
d="M288 0H160 128C110.3 0 96 14.3 96 32s14.3 32 32 32V196.8c0 11.8-3.3 23.5-9.5 33.5L10.3 406.2C3.6 417.2 0 429.7 0 442.6C0 480.9 31.1 512 69.4 512H378.6c38.3 0 69.4-31.1 69.4-69.4c0-12.8-3.6-25.4-10.3-36.4L329.5 230.4c-6.2-10.1-9.5-21.7-9.5-33.5V64c17.7 0 32-14.3 32-32s-14.3-32-32-32H288zM192 196.8V64h64V196.8c0 23.7 6.6 46.9 19 67.1L309.5 320h-171L173 263.9c12.4-20.2 19-43.4 19-67.1z"
|
|
56
|
+
/></svg>
|
|
57
|
+
</template>;
|
|
58
|
+
|
|
59
|
+
export const Menu: TOC<{ Element: SVGElement }> = <template>
|
|
60
|
+
<svg
|
|
61
|
+
aria-hidden="true"
|
|
62
|
+
viewBox="0 0 24 24"
|
|
63
|
+
fill="none"
|
|
64
|
+
stroke-width="2"
|
|
65
|
+
stroke-linecap="round"
|
|
66
|
+
...attributes
|
|
67
|
+
>
|
|
68
|
+
<path d="M4 7h16M4 12h16M4 17h16" />
|
|
69
|
+
</svg>
|
|
70
|
+
</template>;
|
|
71
|
+
|
|
72
|
+
export const Sun: TOC<{ Element: SVGElement }> = <template>
|
|
73
|
+
<svg aria-hidden="true" viewBox="0 0 16 16" ...attributes>
|
|
74
|
+
<path
|
|
75
|
+
fill-rule="evenodd"
|
|
76
|
+
clip-rule="evenodd"
|
|
77
|
+
d="M7 1a1 1 0 0 1 2 0v1a1 1 0 1 1-2 0V1Zm4 7a3 3 0 1 1-6 0 3 3 0 0 1 6 0Zm2.657-5.657a1 1 0 0 0-1.414 0l-.707.707a1 1 0 0 0 1.414 1.414l.707-.707a1 1 0 0 0 0-1.414Zm-1.415 11.313-.707-.707a1 1 0 0 1 1.415-1.415l.707.708a1 1 0 0 1-1.415 1.414ZM16 7.999a1 1 0 0 0-1-1h-1a1 1 0 1 0 0 2h1a1 1 0 0 0 1-1ZM7 14a1 1 0 1 1 2 0v1a1 1 0 1 1-2 0v-1Zm-2.536-2.464a1 1 0 0 0-1.414 0l-.707.707a1 1 0 0 0 1.414 1.414l.707-.707a1 1 0 0 0 0-1.414Zm0-8.486A1 1 0 0 1 3.05 4.464l-.707-.707a1 1 0 0 1 1.414-1.414l.707.707ZM3 8a1 1 0 0 0-1-1H1a1 1 0 0 0 0 2h1a1 1 0 0 0 1-1Z"
|
|
78
|
+
/>
|
|
79
|
+
</svg>
|
|
80
|
+
</template>;
|
|
81
|
+
|
|
82
|
+
export const Moon: TOC<{ Element: SVGElement }> = <template>
|
|
83
|
+
<svg aria-hidden="true" viewBox="0 0 16 16" ...attributes>
|
|
84
|
+
<path
|
|
85
|
+
fill-rule="evenodd"
|
|
86
|
+
clip-rule="evenodd"
|
|
87
|
+
d="M7.23 3.333C7.757 2.905 7.68 2 7 2a6 6 0 1 0 0 12c.68 0 .758-.905.23-1.332A5.989 5.989 0 0 1 5 8c0-1.885.87-3.568 2.23-4.668ZM12 5a1 1 0 0 1 1 1 1 1 0 0 0 1 1 1 1 0 1 1 0 2 1 1 0 0 0-1 1 1 1 0 1 1-2 0 1 1 0 0 0-1-1 1 1 0 1 1 0-2 1 1 0 0 0 1-1 1 1 0 0 1 1-1Z"
|
|
88
|
+
/>
|
|
89
|
+
</svg>
|
|
90
|
+
</template>;
|
|
91
|
+
|
|
92
|
+
export const LightBulb: TOC<{ Element: SVGElement }> = <template>
|
|
93
|
+
<svg
|
|
94
|
+
aria-hidden="true"
|
|
95
|
+
viewBox="0 0 32 32"
|
|
96
|
+
fill="none"
|
|
97
|
+
class="[--icon-foreground:theme(colors.slate.900)] [--icon-background:theme(colors.white)]"
|
|
98
|
+
...attributes
|
|
99
|
+
>
|
|
100
|
+
<defs>
|
|
101
|
+
<radialGradient
|
|
102
|
+
cx="0"
|
|
103
|
+
cy="0"
|
|
104
|
+
r="1"
|
|
105
|
+
gradientUnits="userSpaceOnUse"
|
|
106
|
+
id=":S6:-gradient"
|
|
107
|
+
gradientTransform="matrix(0 21 -21 0 20 11)"
|
|
108
|
+
>
|
|
109
|
+
<stop stop-color="#0EA5E9"></stop><stop stop-color="#22D3EE" offset=".527"></stop>
|
|
110
|
+
<stop stop-color="#818CF8" offset="1"></stop>
|
|
111
|
+
</radialGradient>
|
|
112
|
+
<radialGradient
|
|
113
|
+
cx="0"
|
|
114
|
+
cy="0"
|
|
115
|
+
r="1"
|
|
116
|
+
gradientUnits="userSpaceOnUse"
|
|
117
|
+
id=":S6:-gradient-dark"
|
|
118
|
+
gradientTransform="matrix(0 24.5001 -19.2498 0 16 5.5)"
|
|
119
|
+
>
|
|
120
|
+
<stop stop-color="#0EA5E9"></stop><stop stop-color="#22D3EE" offset=".527"></stop>
|
|
121
|
+
<stop stop-color="#818CF8" offset="1"></stop>
|
|
122
|
+
</radialGradient></defs>
|
|
123
|
+
<g class="dark:hidden">
|
|
124
|
+
<circle cx="20" cy="20" r="12" fill="url(#:S6:-gradient)"></circle>
|
|
125
|
+
<path
|
|
126
|
+
fill-rule="evenodd"
|
|
127
|
+
clip-rule="evenodd"
|
|
128
|
+
d="M20 24.995c0-1.855 1.094-3.501 2.427-4.792C24.61 18.087 26 15.07 26 12.231 26 7.133 21.523 3 16 3S6 7.133 6 12.23c0 2.84 1.389 5.857 3.573 7.973C10.906 21.494 12 23.14 12 24.995V27a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2v-2.005Z"
|
|
129
|
+
class="fill-[var(--icon-background)]"
|
|
130
|
+
fill-opacity="0.5"
|
|
131
|
+
></path>
|
|
132
|
+
<path
|
|
133
|
+
d="M25 12.23c0 2.536-1.254 5.303-3.269 7.255l1.391 1.436c2.354-2.28 3.878-5.547 3.878-8.69h-2ZM16 4c5.047 0 9 3.759 9 8.23h2C27 6.508 21.998 2 16 2v2Zm-9 8.23C7 7.76 10.953 4 16 4V2C10.002 2 5 6.507 5 12.23h2Zm3.269 7.255C8.254 17.533 7 14.766 7 12.23H5c0 3.143 1.523 6.41 3.877 8.69l1.392-1.436ZM13 27v-2.005h-2V27h2Zm1 1a1 1 0 0 1-1-1h-2a3 3 0 0 0 3 3v-2Zm4 0h-4v2h4v-2Zm1-1a1 1 0 0 1-1 1v2a3 3 0 0 0 3-3h-2Zm0-2.005V27h2v-2.005h-2ZM8.877 20.921C10.132 22.136 11 23.538 11 24.995h2c0-2.253-1.32-4.143-2.731-5.51L8.877 20.92Zm12.854-1.436C20.32 20.852 19 22.742 19 24.995h2c0-1.457.869-2.859 2.122-4.074l-1.391-1.436Z"
|
|
134
|
+
class="fill-[var(--icon-foreground)]"
|
|
135
|
+
></path>
|
|
136
|
+
<path
|
|
137
|
+
d="M20 26a1 1 0 1 0 0-2v2Zm-8-2a1 1 0 1 0 0 2v-2Zm2 0h-2v2h2v-2Zm1 1V13.5h-2V25h2Zm-5-11.5v1h2v-1h-2Zm3.5 4.5h5v-2h-5v2Zm8.5-3.5v-1h-2v1h2ZM20 24h-2v2h2v-2Zm-2 0h-4v2h4v-2Zm-1-10.5V25h2V13.5h-2Zm2.5-2.5a2.5 2.5 0 0 0-2.5 2.5h2a.5.5 0 0 1 .5-.5v-2Zm2.5 2.5a2.5 2.5 0 0 0-2.5-2.5v2a.5.5 0 0 1 .5.5h2ZM18.5 18a3.5 3.5 0 0 0 3.5-3.5h-2a1.5 1.5 0 0 1-1.5 1.5v2ZM10 14.5a3.5 3.5 0 0 0 3.5 3.5v-2a1.5 1.5 0 0 1-1.5-1.5h-2Zm2.5-3.5a2.5 2.5 0 0 0-2.5 2.5h2a.5.5 0 0 1 .5-.5v-2Zm2.5 2.5a2.5 2.5 0 0 0-2.5-2.5v2a.5.5 0 0 1 .5.5h2Z"
|
|
138
|
+
class="fill-[var(--icon-foreground)]"
|
|
139
|
+
></path>
|
|
140
|
+
</g>
|
|
141
|
+
<g class="hidden dark:inline">
|
|
142
|
+
<path
|
|
143
|
+
fill-rule="evenodd"
|
|
144
|
+
clip-rule="evenodd"
|
|
145
|
+
d="M16 2C10.002 2 5 6.507 5 12.23c0 3.144 1.523 6.411 3.877 8.691.75.727 1.363 1.52 1.734 2.353.185.415.574.726 1.028.726H12a1 1 0 0 0 1-1v-4.5a.5.5 0 0 0-.5-.5A3.5 3.5 0 0 1 9 14.5V14a3 3 0 1 1 6 0v9a1 1 0 1 0 2 0v-9a3 3 0 1 1 6 0v.5a3.5 3.5 0 0 1-3.5 3.5.5.5 0 0 0-.5.5V23a1 1 0 0 0 1 1h.36c.455 0 .844-.311 1.03-.726.37-.833.982-1.626 1.732-2.353 2.354-2.28 3.878-5.547 3.878-8.69C27 6.507 21.998 2 16 2Zm5 25a1 1 0 0 0-1-1h-8a1 1 0 0 0-1 1 3 3 0 0 0 3 3h4a3 3 0 0 0 3-3Zm-8-13v1.5a.5.5 0 0 1-.5.5 1.5 1.5 0 0 1-1.5-1.5V14a1 1 0 1 1 2 0Zm6.5 2a.5.5 0 0 1-.5-.5V14a1 1 0 1 1 2 0v.5a1.5 1.5 0 0 1-1.5 1.5Z"
|
|
146
|
+
fill="url(#:S6:-gradient-dark)"
|
|
147
|
+
></path>
|
|
148
|
+
</g>
|
|
149
|
+
</svg>
|
|
150
|
+
</template>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
.gradient-background {
|
|
2
|
+
background-image: linear-gradient(-45deg in oklch, #1252e3, #485de5, #7812e5, #3512c5);
|
|
3
|
+
background-size: 400% 400%;
|
|
4
|
+
animation: gradient-animation 16s ease infinite;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
body.dark .gradient-background {
|
|
8
|
+
background-image: linear-gradient(-45deg in oklch, #110043, #182d75, #280065, #350076);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
@keyframes gradient-animation {
|
|
12
|
+
0% {
|
|
13
|
+
background-position: 0% 50%;
|
|
14
|
+
}
|
|
15
|
+
50% {
|
|
16
|
+
background-position: 100% 50%;
|
|
17
|
+
}
|
|
18
|
+
100% {
|
|
19
|
+
background-position: 0% 50%;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import './index-page.css';
|
|
2
|
+
|
|
3
|
+
import { Hero } from 'ember-primitives/layout/hero';
|
|
4
|
+
|
|
5
|
+
import type { TOC } from '@ember/component/template-only';
|
|
6
|
+
|
|
7
|
+
export const IndexPage: TOC<{
|
|
8
|
+
Blocks: {
|
|
9
|
+
logo: [];
|
|
10
|
+
header: [];
|
|
11
|
+
tagline: [];
|
|
12
|
+
callToAction: [];
|
|
13
|
+
content: [];
|
|
14
|
+
footer: [];
|
|
15
|
+
};
|
|
16
|
+
}> = <template>
|
|
17
|
+
<Hero class="shadow-xl shadow-slate-900/5 gradient-background">
|
|
18
|
+
<header class="absolute md:sticky right-0 bottom-0 md:top-0 z-50 p-4 flex items-center">
|
|
19
|
+
{{yield to="header"}}
|
|
20
|
+
</header>
|
|
21
|
+
|
|
22
|
+
<div class="h-full flex flex-col gap-8 justify-center items-center">
|
|
23
|
+
<div style="width: 66%; margin: 0 auto; transform: translateY(-20%);" class="grid gap-4">
|
|
24
|
+
<h1 style="filter: drop-shadow(3px 5px 0px rgba(0, 0, 0, 0.4));">
|
|
25
|
+
{{yield to="logo"}}
|
|
26
|
+
</h1>
|
|
27
|
+
<p class="italic text-white w-full md:w-1/2 mx-auto">
|
|
28
|
+
{{yield to="tagline"}}
|
|
29
|
+
</p>
|
|
30
|
+
</div>
|
|
31
|
+
{{yield to="callToAction"}}
|
|
32
|
+
</div>
|
|
33
|
+
</Hero>
|
|
34
|
+
|
|
35
|
+
{{yield to="content"}}
|
|
36
|
+
|
|
37
|
+
<hr />
|
|
38
|
+
<footer style="padding: 3rem; width: 66%;" class="mx-auto gap-12 flex-wrap flex justify-between">
|
|
39
|
+
{{yield to="footer"}}
|
|
40
|
+
</footer>
|
|
41
|
+
</template>;
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
export { H2 } from './h2.gts';
|
|
2
|
-
export { Callout } from './callout.gts';
|
|
3
|
-
export { Text } from './text.gts';
|
|
4
1
|
export { Article } from './article.gts';
|
|
5
|
-
export {
|
|
6
|
-
export { IndexPage } from './index-page.gts';
|
|
7
|
-
export { Link, InternalLink } from './links.gts';
|
|
2
|
+
export { Callout } from './callout.gts';
|
|
8
3
|
export { OopsError } from './errors.gts';
|
|
4
|
+
export { H2 } from './h2.gts';
|
|
5
|
+
export { IndexPage } from './index-page.gts';
|
|
6
|
+
export { InternalLink,Link } from './links.gts';
|
|
9
7
|
export { ResponsiveMenuLayout } from './menu-layout.gts';
|
|
10
8
|
export { PageLayout, TopRight } from './page-layout.gts';
|
|
9
|
+
export { Shell } from './shell.gts';
|
|
10
|
+
export { Text } from './text.gts';
|
|
11
11
|
export { ThemeToggle } from './theme-toggle.gts';
|
|
12
|
-
//# sourceMappingURL=index.gts.d.ts.map
|
package/src/links.gts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { ExternalLink } from 'ember-primitives/components/external-link';
|
|
2
|
+
|
|
3
|
+
import type { TOC } from '@ember/component/template-only';
|
|
4
|
+
|
|
5
|
+
const linkClasses = `
|
|
6
|
+
text-sm font-semibold
|
|
7
|
+
dark:text-sky-400
|
|
8
|
+
no-underline shadow-[inset_0_-2px_0_0_var(--tw-prose-background,#fff),inset_0_calc(-1*(var(--tw-prose-underline-size,4px)+2px))_0_0_var(--tw-prose-underline,theme(colors.sky.300))]
|
|
9
|
+
hover:[--tw-prose-underline-size:6px]
|
|
10
|
+
dark:[--tw-prose-background:theme(colors.slate.900)]
|
|
11
|
+
dark:shadow-[inset_0_calc(-1*var(--tw-prose-underline-size,2px))_0_0_var(--tw-prose-underline,theme(colors.sky.800))]
|
|
12
|
+
dark:hover:[--tw-prose-underline-size:6px]
|
|
13
|
+
`;
|
|
14
|
+
|
|
15
|
+
export const InternalLink: TOC<{
|
|
16
|
+
Element: HTMLAnchorElement;
|
|
17
|
+
Blocks: { default: [] };
|
|
18
|
+
}> = <template>
|
|
19
|
+
<a class={{linkClasses}} href="#" ...attributes>
|
|
20
|
+
{{yield}}
|
|
21
|
+
</a>
|
|
22
|
+
</template>;
|
|
23
|
+
|
|
24
|
+
export const Link: TOC<{
|
|
25
|
+
Element: HTMLAnchorElement;
|
|
26
|
+
Blocks: { default: [] };
|
|
27
|
+
}> = <template>
|
|
28
|
+
<ExternalLink class={{linkClasses}} ...attributes>
|
|
29
|
+
{{yield}}
|
|
30
|
+
</ExternalLink>
|
|
31
|
+
</template>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// @ts-expect-error - no types are provided for ember-mobile-menu
|
|
2
|
+
import MenuWrapper from 'ember-mobile-menu/components/mobile-menu-wrapper';
|
|
3
|
+
|
|
4
|
+
import { Menu } from './icons.gts';
|
|
5
|
+
import { SideNav } from './side-nav.gts';
|
|
6
|
+
|
|
7
|
+
import type { TOC } from '@ember/component/template-only';
|
|
8
|
+
import type { ComponentLike, WithBoundArgs } from '@glint/template';
|
|
9
|
+
|
|
10
|
+
const Toggle: TOC<{
|
|
11
|
+
Args: {
|
|
12
|
+
toggle: ComponentLike<{ Blocks: { default: [] } }>;
|
|
13
|
+
};
|
|
14
|
+
}> = <template>
|
|
15
|
+
<@toggle>
|
|
16
|
+
<Menu class="w-6 h-6 stroke-slate-500" />
|
|
17
|
+
</@toggle>
|
|
18
|
+
</template>;
|
|
19
|
+
|
|
20
|
+
export const ResponsiveMenuLayout: TOC<{
|
|
21
|
+
Blocks: {
|
|
22
|
+
content: [];
|
|
23
|
+
header: [toggle: WithBoundArgs<typeof Toggle, 'toggle'>];
|
|
24
|
+
};
|
|
25
|
+
}> = <template>
|
|
26
|
+
<MenuWrapper as |mmw|>
|
|
27
|
+
<mmw.MobileMenu @mode="push" @maxWidth={{300}} as |mm|>
|
|
28
|
+
<SideNav @onClick={{mm.actions.close}} />
|
|
29
|
+
</mmw.MobileMenu>
|
|
30
|
+
|
|
31
|
+
<mmw.Content>
|
|
32
|
+
{{yield (component Toggle toggle=mmw.Toggle) to="header"}}
|
|
33
|
+
|
|
34
|
+
<div class="outer-content">
|
|
35
|
+
<SideNav />
|
|
36
|
+
|
|
37
|
+
<main class="relative grid justify-center flex-auto w-full mx-auto max-w-8xl">
|
|
38
|
+
{{yield to="content"}}
|
|
39
|
+
</main>
|
|
40
|
+
</div>
|
|
41
|
+
</mmw.Content>
|
|
42
|
+
</MenuWrapper>
|
|
43
|
+
</template>;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { modifier } from 'ember-modifier';
|
|
2
|
+
import { cell } from 'ember-resources';
|
|
3
|
+
import { Page } from 'kolay/components';
|
|
4
|
+
|
|
5
|
+
import { Article } from './article.gts';
|
|
6
|
+
import { Link } from './links.gts';
|
|
7
|
+
import { ResponsiveMenuLayout } from './menu-layout.gts';
|
|
8
|
+
import { ThemeToggle } from './theme-toggle.gts';
|
|
9
|
+
|
|
10
|
+
import type { TOC } from '@ember/component/template-only';
|
|
11
|
+
|
|
12
|
+
// Removes the App Shell / welcome UI
|
|
13
|
+
// before initial rending and chunk loading finishes
|
|
14
|
+
function removeLoader() {
|
|
15
|
+
document.querySelector('#initial-loader')?.remove();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
function resetScroll(..._args: unknown[]) {
|
|
20
|
+
document.querySelector('html')?.scrollTo(0, 0);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const isScrolled = cell(false);
|
|
24
|
+
|
|
25
|
+
const onWindowScroll = modifier(() => {
|
|
26
|
+
function onScroll() {
|
|
27
|
+
isScrolled.current = window.scrollY > 0;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
onScroll();
|
|
31
|
+
window.addEventListener('scroll', onScroll, { passive: true });
|
|
32
|
+
|
|
33
|
+
return () => {
|
|
34
|
+
window.removeEventListener('scroll', onScroll);
|
|
35
|
+
};
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
export const PageLayout: TOC<{
|
|
39
|
+
Blocks: {
|
|
40
|
+
logoLink: [];
|
|
41
|
+
topRight: [];
|
|
42
|
+
editLink: [typeof EditLink];
|
|
43
|
+
error: [error: string];
|
|
44
|
+
};
|
|
45
|
+
}> = <template>
|
|
46
|
+
<ResponsiveMenuLayout>
|
|
47
|
+
<:header as |Toggle|>
|
|
48
|
+
<header
|
|
49
|
+
class="sticky top-0 z-50 transition duration-500 shadow-md shadow-slate-900/5 dark:shadow-none bg-white/95
|
|
50
|
+
{{if
|
|
51
|
+
isScrolled.current
|
|
52
|
+
'dark:bg-slate-900/95 dark:backdrop-blur dark:[@supports(backdrop-filter:blur(0))]:bg-slate-900/75'
|
|
53
|
+
'dark:bg-slate-900/95'
|
|
54
|
+
}}"
|
|
55
|
+
{{onWindowScroll}}
|
|
56
|
+
>
|
|
57
|
+
<div class="outer-content flex flex-none flex-wrap items-center justify-between py-4">
|
|
58
|
+
<div class="flex mr-6 lg:hidden">
|
|
59
|
+
<Toggle />
|
|
60
|
+
</div>
|
|
61
|
+
<div class="relative flex items-center flex-grow basis-0">
|
|
62
|
+
<a href="/" aria-label="Home page">
|
|
63
|
+
{{yield to="logoLink"}}
|
|
64
|
+
</a>
|
|
65
|
+
</div>
|
|
66
|
+
{{!
|
|
67
|
+
If we ever have a search bar
|
|
68
|
+
<div class="mr-6 -my-5 sm:mr-8 md:mr-0">
|
|
69
|
+
input here
|
|
70
|
+
</div>
|
|
71
|
+
}}
|
|
72
|
+
<TopRight>
|
|
73
|
+
{{yield to="topRight"}}
|
|
74
|
+
</TopRight>
|
|
75
|
+
</div>
|
|
76
|
+
</header>
|
|
77
|
+
</:header>
|
|
78
|
+
<:content>
|
|
79
|
+
<section data-main-scroll-container class="flex-auto max-w-2xl min-w-0 py-4 lg:max-w-none">
|
|
80
|
+
<Article>
|
|
81
|
+
<Page>
|
|
82
|
+
<:pending>
|
|
83
|
+
<div
|
|
84
|
+
class="fixed top-12 p-4 rounded z-50 transition border border-slate-800 duration-500 shadow-xl shadow-slate-900/5 bg-white/95 'dark:bg-slate-900/95 dark:backdrop-blur dark:[@supports(backdrop-filter:blur(0))]:bg-slate-900/75'"
|
|
85
|
+
>
|
|
86
|
+
Loading, Compiling, etc
|
|
87
|
+
</div>
|
|
88
|
+
</:pending>
|
|
89
|
+
|
|
90
|
+
<:error as |error|>
|
|
91
|
+
<section>
|
|
92
|
+
{{yield error to="error"}}
|
|
93
|
+
</section>
|
|
94
|
+
</:error>
|
|
95
|
+
|
|
96
|
+
<:success as |prose|>
|
|
97
|
+
<prose />
|
|
98
|
+
{{(removeLoader)}}
|
|
99
|
+
{{! this is probably really bad, and anti-patterny
|
|
100
|
+
but ember doesn't have a good way to have libraries
|
|
101
|
+
tie in to the URL without a bunch of setup -- which is maybe fine?
|
|
102
|
+
needs some experimenting -- there is a bit of a disconnect with
|
|
103
|
+
deriving data from the URL, and the timing of the model hooks.
|
|
104
|
+
It might be possible to have an afterModel hook wait until the page is
|
|
105
|
+
compiled.
|
|
106
|
+
(that's why we have async state, because we're compiling, not loading)
|
|
107
|
+
}}
|
|
108
|
+
{{resetScroll prose}}
|
|
109
|
+
</:success>
|
|
110
|
+
</Page>
|
|
111
|
+
</Article>
|
|
112
|
+
|
|
113
|
+
{{#if (has-block "editLink")}}
|
|
114
|
+
|
|
115
|
+
<div class="flex justify-end pt-6 mt-12 border-t border-slate-200 dark:border-slate-800">
|
|
116
|
+
|
|
117
|
+
{{yield EditLink to="editLink"}}
|
|
118
|
+
</div>
|
|
119
|
+
{{/if}}
|
|
120
|
+
</section>
|
|
121
|
+
</:content>
|
|
122
|
+
|
|
123
|
+
</ResponsiveMenuLayout>
|
|
124
|
+
</template>;
|
|
125
|
+
|
|
126
|
+
const EditLink: TOC<{ Args: { href: string }; Blocks: { default: [] } }> = <template>
|
|
127
|
+
<Link class="edit-page flex" href={{@href}}>
|
|
128
|
+
{{yield}}
|
|
129
|
+
</Link>
|
|
130
|
+
</template>;
|
|
131
|
+
|
|
132
|
+
export const TopRight: TOC<{ Blocks: { default: [] } }> = <template>
|
|
133
|
+
<div class="relative flex justify-end gap-6 basis-0 sm:gap-8 md:flex-grow">
|
|
134
|
+
<ThemeToggle />
|
|
135
|
+
{{yield}}
|
|
136
|
+
</div>
|
|
137
|
+
</template>;
|
package/src/shell.gts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import 'ember-mobile-menu/themes/android';
|
|
2
|
+
/**
|
|
3
|
+
* NOTE: while this project uses tailwind,
|
|
4
|
+
* CSS is better than tailwind for
|
|
5
|
+
* - global styles
|
|
6
|
+
* - styling some recursive structures generated by other libraries.
|
|
7
|
+
*
|
|
8
|
+
* Using both together is *very nice* 🎉
|
|
9
|
+
*/
|
|
10
|
+
import './site-css/site.css';
|
|
11
|
+
import './site-css/components.css';
|
|
12
|
+
import './site-css/featured-demo.css';
|
|
13
|
+
import './site-css/shiki.css';
|
|
14
|
+
import './site-css/shell.css';
|
|
15
|
+
|
|
16
|
+
import { colorScheme } from 'ember-primitives/color-scheme';
|
|
17
|
+
|
|
18
|
+
import type { TOC } from '@ember/component/template-only';
|
|
19
|
+
|
|
20
|
+
export const Shell: TOC<{ Blocks: { default: [] } }> = <template>
|
|
21
|
+
{{(syncBodyClass)}}
|
|
22
|
+
{{yield}}
|
|
23
|
+
</template>;
|
|
24
|
+
|
|
25
|
+
function syncBodyClass() {
|
|
26
|
+
if (colorScheme.isDark) {
|
|
27
|
+
document.body.classList.add('dark');
|
|
28
|
+
document.body.classList.add('theme-dark');
|
|
29
|
+
document.body.classList.remove('theme-light');
|
|
30
|
+
document.body.classList.remove('light');
|
|
31
|
+
} else {
|
|
32
|
+
document.body.classList.remove('theme-dark');
|
|
33
|
+
document.body.classList.remove('dark');
|
|
34
|
+
document.body.classList.add('theme-light');
|
|
35
|
+
document.body.classList.add('light');
|
|
36
|
+
}
|
|
37
|
+
}
|
package/src/side-nav.gts
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { on } from '@ember/modifier';
|
|
3
|
+
import { service } from '@ember/service';
|
|
4
|
+
|
|
5
|
+
import { sentenceCase } from 'change-case';
|
|
6
|
+
import { link } from 'ember-primitives/helpers';
|
|
7
|
+
import { selected } from 'kolay';
|
|
8
|
+
import { PageNav } from 'kolay/components';
|
|
9
|
+
import { getAnchor } from 'should-handle-link';
|
|
10
|
+
|
|
11
|
+
import type { TOC } from '@ember/component/template-only';
|
|
12
|
+
import type RouterService from '@ember/routing/router-service';
|
|
13
|
+
import type { Page } from 'kolay';
|
|
14
|
+
|
|
15
|
+
type CustomPage = Page & {
|
|
16
|
+
title?: string;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
function fixWords(text: string) {
|
|
20
|
+
switch (text.toLowerCase()) {
|
|
21
|
+
case 'ui':
|
|
22
|
+
return 'UI';
|
|
23
|
+
case 'iframe':
|
|
24
|
+
return 'IFrame';
|
|
25
|
+
default:
|
|
26
|
+
return text;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const joinUrl = (...strs: string[]) => {
|
|
31
|
+
const prefix = strs[0]?.startsWith('/') ? '/' : '';
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
prefix +
|
|
35
|
+
strs
|
|
36
|
+
.map((s) => s.replace(/^\//, '').replace(/\/$/, ''))
|
|
37
|
+
.filter((x) => !!x)
|
|
38
|
+
.join('/')
|
|
39
|
+
);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Converts 1-2-hyphenated-thing
|
|
44
|
+
* to
|
|
45
|
+
* Hyphenated Thing
|
|
46
|
+
*/
|
|
47
|
+
const titleize = (str: string) => {
|
|
48
|
+
return (
|
|
49
|
+
str
|
|
50
|
+
.split(/-|\s/)
|
|
51
|
+
.filter(Boolean)
|
|
52
|
+
.filter((text) => !text.match(/^[\d]+$/))
|
|
53
|
+
.map((text) => `${text[0]?.toLocaleUpperCase()}${text.slice(1, text.length)}`)
|
|
54
|
+
.map((text) => fixWords(text))
|
|
55
|
+
.join(' ')
|
|
56
|
+
.split('.')[0] || ''
|
|
57
|
+
);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
function nameFor(x: Page): string {
|
|
61
|
+
if ('componentName' in x) {
|
|
62
|
+
return String(x.componentName);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const page = x as CustomPage;
|
|
66
|
+
|
|
67
|
+
return page.title ? page.title : sentenceCase(page.name);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const asComponent = (str: string) => {
|
|
71
|
+
return `<${str.split('.')[0]?.replaceAll(' ', '')} />`;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const isComponents = (str: string) => str === 'components';
|
|
75
|
+
|
|
76
|
+
const SectionLink: TOC<{ Element: HTMLAnchorElement; Args: { href: string; name: string } }> =
|
|
77
|
+
<template>
|
|
78
|
+
{{#let (link @href) as |l|}}
|
|
79
|
+
<a
|
|
80
|
+
href={{@href}}
|
|
81
|
+
class="font-medium font-display
|
|
82
|
+
{{if
|
|
83
|
+
l.isActive
|
|
84
|
+
'text-sky-500'
|
|
85
|
+
'text-slate-900 hover:text-slate-600 dark:text-white dark:hover:text-slate-300'
|
|
86
|
+
}}"
|
|
87
|
+
{{on "click" l.handleClick}}
|
|
88
|
+
...attributes
|
|
89
|
+
>
|
|
90
|
+
{{#if (isComponents @name)}}
|
|
91
|
+
{{asComponent (titleize @name)}}
|
|
92
|
+
{{else}}
|
|
93
|
+
{{titleize @name}}
|
|
94
|
+
{{/if}}
|
|
95
|
+
</a>
|
|
96
|
+
{{/let}}
|
|
97
|
+
</template>;
|
|
98
|
+
|
|
99
|
+
const SubSectionLink: TOC<{ Element: HTMLAnchorElement; Args: { href: string; name: string } }> =
|
|
100
|
+
<template>
|
|
101
|
+
{{#let (link @href) as |l|}}
|
|
102
|
+
<a
|
|
103
|
+
href={{@href}}
|
|
104
|
+
class="block w-full before:pointer-events-none before:absolute before:-left-1 before:top-1/2 before:h-1.5 before:w-1.5 before:-translate-y-1/2 before:rounded-full
|
|
105
|
+
{{if
|
|
106
|
+
l.isActive
|
|
107
|
+
'font-semibold text-sky-500 before:bg-sky-500'
|
|
108
|
+
'text-slate-500 before:hidden before:bg-slate-300 hover:text-slate-600 hover:before:block dark:text-slate-400 dark:before:bg-slate-700 dark:hover:text-slate-300'
|
|
109
|
+
}}"
|
|
110
|
+
{{on "click" l.handleClick}}
|
|
111
|
+
...attributes
|
|
112
|
+
>
|
|
113
|
+
{{#if (isComponents @name)}}
|
|
114
|
+
{{asComponent (titleize @name)}}
|
|
115
|
+
{{else}}
|
|
116
|
+
{{titleize @name}}
|
|
117
|
+
{{/if}}
|
|
118
|
+
</a>
|
|
119
|
+
{{/let}}
|
|
120
|
+
</template>;
|
|
121
|
+
|
|
122
|
+
export class SideNav extends Component<{
|
|
123
|
+
Element: HTMLElement;
|
|
124
|
+
Args: {
|
|
125
|
+
onClick?: () => void;
|
|
126
|
+
};
|
|
127
|
+
}> {
|
|
128
|
+
get #selected() {
|
|
129
|
+
return selected(this);
|
|
130
|
+
}
|
|
131
|
+
@service('router') declare router: RouterService;
|
|
132
|
+
|
|
133
|
+
get humanSelected() {
|
|
134
|
+
const path = this.#selected?.path;
|
|
135
|
+
|
|
136
|
+
if (!path) return undefined;
|
|
137
|
+
|
|
138
|
+
return path.split('/').filter(Boolean).map(titleize).join(' / ');
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
get rootUrl() {
|
|
142
|
+
return this.router.rootURL;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
closeNav = (event: Event) => {
|
|
146
|
+
if (!getAnchor(event)) return;
|
|
147
|
+
|
|
148
|
+
this.args.onClick?.();
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
*
|
|
153
|
+
* This nav needs an aria-label to get around
|
|
154
|
+
* "Ensure landmarks are unique"
|
|
155
|
+
* because some demos render navs, and it's important that those
|
|
156
|
+
* demos are as simple as possible.
|
|
157
|
+
*
|
|
158
|
+
*
|
|
159
|
+
* nav isn't actually made in to an interactive element,
|
|
160
|
+
* it's an event delegation handler.
|
|
161
|
+
* The links themselves remain the actual interactive elements.
|
|
162
|
+
*/
|
|
163
|
+
<template>
|
|
164
|
+
<aside class="bg-white dark:bg-slate-900" ...attributes>
|
|
165
|
+
<PageNav aria-label="Main Navigation">
|
|
166
|
+
<:page as |x|>
|
|
167
|
+
<SubSectionLink
|
|
168
|
+
@href={{joinUrl this.rootUrl x.page.path}}
|
|
169
|
+
@name={{nameFor x.page}}
|
|
170
|
+
{{on "click" this.closeNav}}
|
|
171
|
+
/>
|
|
172
|
+
</:page>
|
|
173
|
+
|
|
174
|
+
<:collection as |x|>
|
|
175
|
+
{{#if x.index}}
|
|
176
|
+
<SectionLink
|
|
177
|
+
@href={{joinUrl this.rootUrl x.index.page.path}}
|
|
178
|
+
@name={{titleize x.collection.name}}
|
|
179
|
+
{{on "click" this.closeNav}}
|
|
180
|
+
/>
|
|
181
|
+
{{else}}
|
|
182
|
+
<h2>
|
|
183
|
+
{{titleize x.collection.name}}
|
|
184
|
+
</h2>
|
|
185
|
+
{{/if}}
|
|
186
|
+
</:collection>
|
|
187
|
+
</PageNav>
|
|
188
|
+
</aside>
|
|
189
|
+
</template>
|
|
190
|
+
}
|