docs: add documentation site as new workspace (#64)
* add documentation site as new workspace * update package-lock.json * Update docs/package.json Co-authored-by: Ayo Ayco <ramon.aycojr@gmail.com> * Update docs/src/components/Footer/AvatarList.astro with correct URL's Co-authored-by: Ayo Ayco <ramon.aycojr@gmail.com> * Update docs/src/config.ts Co-authored-by: Ayo Ayco <ramon.aycojr@gmail.com> * Update docs/src/config.ts Correct GITHUB_EDIT_URL Co-authored-by: Ayo Ayco <ramon.aycojr@gmail.com> Co-authored-by: Ayo Ayco <ramon.aycojr@gmail.com>
This commit is contained in:
parent
e924e56d38
commit
a359349086
43 changed files with 14221 additions and 30 deletions
19
docs/.gitignore
vendored
Normal file
19
docs/.gitignore
vendored
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# build output
|
||||||
|
dist/
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# logs
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
|
||||||
|
|
||||||
|
# environment variables
|
||||||
|
.env
|
||||||
|
.env.production
|
||||||
|
|
||||||
|
# macOS-specific files
|
||||||
|
.DS_Store
|
4
docs/.vscode/extensions.json
vendored
Normal file
4
docs/.vscode/extensions.json
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"recommendations": ["astro-build.astro-vscode"],
|
||||||
|
"unwantedRecommendations": []
|
||||||
|
}
|
11
docs/.vscode/launch.json
vendored
Normal file
11
docs/.vscode/launch.json
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"command": "./node_modules/.bin/astro dev",
|
||||||
|
"name": "Development server",
|
||||||
|
"request": "launch",
|
||||||
|
"type": "node-terminal"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
173
docs/README.md
Normal file
173
docs/README.md
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
# Astro Starter Kit: Docs Site
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm create astro@latest -- --template docs
|
||||||
|
```
|
||||||
|
|
||||||
|
[](https://stackblitz.com/github/withastro/astro/tree/latest/examples/docs)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- ✅ **Full Markdown support**
|
||||||
|
- ✅ **Responsive mobile-friendly design**
|
||||||
|
- ✅ **Sidebar navigation**
|
||||||
|
- ✅ **Search (powered by Algolia)**
|
||||||
|
- ✅ **Multi-language i18n**
|
||||||
|
- ✅ **Automatic table of contents**
|
||||||
|
- ✅ **Automatic list of contributors**
|
||||||
|
- ✅ (and, best of all) **dark mode**
|
||||||
|
|
||||||
|
## Commands Cheatsheet
|
||||||
|
|
||||||
|
All commands are run from the root of the project, from a terminal:
|
||||||
|
|
||||||
|
| Command | Action |
|
||||||
|
| :--------------------- | :----------------------------------------------- |
|
||||||
|
| `npm install` | Installs dependencies |
|
||||||
|
| `npm run dev` | Starts local dev server at `localhost:3000` |
|
||||||
|
| `npm run build` | Build your production site to `./dist/` |
|
||||||
|
| `npm run preview` | Preview your build locally, before deploying |
|
||||||
|
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
|
||||||
|
| `npm run astro --help` | Get help using the Astro CLI |
|
||||||
|
|
||||||
|
To deploy your site to production, check out our [Deploy an Astro Website](https://docs.astro.build/guides/deploy) guide.
|
||||||
|
|
||||||
|
## New to Astro?
|
||||||
|
|
||||||
|
Welcome! Check out [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).
|
||||||
|
|
||||||
|
## Customize This Theme
|
||||||
|
|
||||||
|
### Site metadata
|
||||||
|
|
||||||
|
`src/config.ts` contains several data objects that describe metadata about your site like title, description, default language, and Open Graph details. You can customize these to match your project.
|
||||||
|
|
||||||
|
### CSS styling
|
||||||
|
|
||||||
|
The theme's look and feel is controlled by a few key variables that you can customize yourself. You'll find them in the `src/styles/theme.css` CSS file.
|
||||||
|
|
||||||
|
If you've never worked with CSS variables before, give [MDN's guide on CSS variables](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties) a quick read.
|
||||||
|
|
||||||
|
This theme uses a "cool blue" accent color by default. To customize this for your project, change the `--theme-accent` variable to whatever color you'd like:
|
||||||
|
|
||||||
|
```diff
|
||||||
|
/* src/styles/theme.css */
|
||||||
|
:root {
|
||||||
|
color-scheme: light;
|
||||||
|
- --theme-accent: hsla(var(--color-blue), 1);
|
||||||
|
+ --theme-accent: hsla(var(--color-red), 1); /* or: hsla(#FF0000, 1); */
|
||||||
|
```
|
||||||
|
|
||||||
|
## Page metadata
|
||||||
|
|
||||||
|
Astro uses frontmatter in Markdown pages to choose layouts and pass properties to those layouts. If you are using the default layout, you can customize the page in many different ways to optimize SEO and other things. For example, you can use the `title` and `description` properties to set the document title, meta title, meta description, and Open Graph description.
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
title: Example title
|
||||||
|
description: Really cool docs example that uses Astro
|
||||||
|
layout: ../../layouts/MainLayout.astro
|
||||||
|
---
|
||||||
|
|
||||||
|
# Page content...
|
||||||
|
```
|
||||||
|
|
||||||
|
For more SEO related properties, look at `src/components/HeadSEO.astro`
|
||||||
|
|
||||||
|
### Sidebar navigation
|
||||||
|
|
||||||
|
The sidebar navigation is controlled by the `SIDEBAR` variable in your `src/config.ts` file. You can customize the sidebar by modifying this object. A default, starter navigation has already been created for you.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export const SIDEBAR = {
|
||||||
|
en: [
|
||||||
|
{ text: "Section Header", header: true },
|
||||||
|
{ text: "Introduction", link: "en/introduction" },
|
||||||
|
{ text: "Page 2", link: "en/page-2" },
|
||||||
|
{ text: "Page 3", link: "en/page-3" },
|
||||||
|
|
||||||
|
{ text: "Another Section", header: true },
|
||||||
|
{ text: "Page 4", link: "en/page-4" },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Note the top-level `en` key: This is needed for multi-language support. You can change it to whatever language you'd like, or add new languages as you go. More details on this below.
|
||||||
|
|
||||||
|
### Multiple Languages support
|
||||||
|
|
||||||
|
The Astro docs template supports multiple langauges out of the box. The default theme only shows `en` documentation, but you can enable multi-language support features by adding a second language to your project.
|
||||||
|
|
||||||
|
To add a new language to your project, you'll want to extend the current `src/pages/[lang]/...` layout:
|
||||||
|
|
||||||
|
```diff
|
||||||
|
📂 src/pages
|
||||||
|
┣ 📂 en
|
||||||
|
┃ ┣ 📜 page-1.md
|
||||||
|
┃ ┣ 📜 page-2.md
|
||||||
|
┃ ┣ 📜 page-3.astro
|
||||||
|
+ ┣ 📂 es
|
||||||
|
+ ┃ ┣ 📜 page-1.md
|
||||||
|
+ ┃ ┣ 📜 page-2.md
|
||||||
|
+ ┃ ┣ 📜 page-3.astro
|
||||||
|
```
|
||||||
|
|
||||||
|
You'll also need to add the new language name to the `KNOWN_LANGUAGES` map in your `src/config.ts` file. This will enable your new language switcher in the site header.
|
||||||
|
|
||||||
|
```diff
|
||||||
|
// src/config.ts
|
||||||
|
export const KNOWN_LANGUAGES = {
|
||||||
|
English: 'en',
|
||||||
|
+ Spanish: 'es',
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Last step: you'll need to add a new entry to your sidebar, to create the table of contents for that language. While duplicating every page might not sound ideal to everyone, this extra control allows you to create entirely custom content for every language.
|
||||||
|
|
||||||
|
> Make sure the sidebar `link` value points to the correct language!
|
||||||
|
|
||||||
|
```diff
|
||||||
|
// src/config.ts
|
||||||
|
export const SIDEBAR = {
|
||||||
|
en: [
|
||||||
|
{ text: 'Section Header', header: true, },
|
||||||
|
{ text: 'Introduction', link: 'en/introduction' },
|
||||||
|
// ...
|
||||||
|
],
|
||||||
|
+ es: [
|
||||||
|
+ { text: 'Encabezado de sección', header: true, },
|
||||||
|
+ { text: 'Introducción', link: 'es/introduction' },
|
||||||
|
+ // ...
|
||||||
|
+ ],
|
||||||
|
};
|
||||||
|
|
||||||
|
// ...
|
||||||
|
```
|
||||||
|
|
||||||
|
If you plan to use Spanish as the the default language, you just need to modify the redirect path in `src/pages/index.astro`:
|
||||||
|
|
||||||
|
```diff
|
||||||
|
<script>
|
||||||
|
- window.location.pathname = `/en/introduction`;
|
||||||
|
+ window.location.pathname = `/es/introduction`;
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also remove the above script and write a landing page in Spanish instead.
|
||||||
|
|
||||||
|
### What if I don't plan to support multiple languages?
|
||||||
|
|
||||||
|
That's totally fine! Not all projects need (or can support) multiple languages. You can continue to use this theme without ever adding a second language.
|
||||||
|
|
||||||
|
If that single language is not English, you can just replace `en` in directory layouts and configurations with the preferred language.
|
||||||
|
|
||||||
|
### Search (Powered by Algolia)
|
||||||
|
|
||||||
|
[Algolia](https://www.algolia.com/) offers a free service to qualified open source projects called [DocSearch](https://docsearch.algolia.com/). If you are accepted to the DocSearch program, provide your API Key & index name in `src/config.ts` and a search box will automatically appear in your site header.
|
||||||
|
|
||||||
|
Note that Aglolia and Astro are not affiliated. We have no say over acceptance to the DocSearch program.
|
||||||
|
|
||||||
|
If you'd prefer to remove Algolia's search and replace it with your own, check out the `src/components/Header.astro` component to see where the component is added.
|
14
docs/astro.config.mjs
Normal file
14
docs/astro.config.mjs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import { defineConfig } from 'astro/config';
|
||||||
|
import preact from '@astrojs/preact';
|
||||||
|
import react from '@astrojs/react';
|
||||||
|
|
||||||
|
// https://astro.build/config
|
||||||
|
export default defineConfig({
|
||||||
|
integrations: [
|
||||||
|
// Enable Preact to support Preact JSX components.
|
||||||
|
preact(),
|
||||||
|
// Enable React for the Algolia search component.
|
||||||
|
react(),
|
||||||
|
],
|
||||||
|
site: `http://astro.build`,
|
||||||
|
});
|
10855
docs/package-lock.json
generated
Normal file
10855
docs/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
40
docs/package.json
Normal file
40
docs/package.json
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
{
|
||||||
|
"name": "docs-astro-reactive-library",
|
||||||
|
"type": "module",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "astro dev",
|
||||||
|
"start": "astro dev",
|
||||||
|
"check": "astro check && tsc",
|
||||||
|
"build": "astro build",
|
||||||
|
"preview": "astro preview",
|
||||||
|
"astro": "astro"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"astro": "^1.4.4",
|
||||||
|
"preact": "^10.7.3",
|
||||||
|
"react": "^18.1.0",
|
||||||
|
"react-dom": "^18.1.0",
|
||||||
|
"@astrojs/react": "^1.1.4",
|
||||||
|
"@astrojs/preact": "^1.1.1",
|
||||||
|
"@algolia/client-search": "^4.13.1",
|
||||||
|
"@docsearch/css": "^3.1.0",
|
||||||
|
"@docsearch/react": "^3.1.0",
|
||||||
|
"@types/react": "^17.0.45",
|
||||||
|
"@types/node": "^18.0.0",
|
||||||
|
"@types/react-dom": "^18.0.0"
|
||||||
|
},
|
||||||
|
"description": "```bash npm create astro@latest -- --template docs ```",
|
||||||
|
"main": "index.js",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/Rishav-12/astro-reactive-library.git"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/Rishav-12/astro-reactive-library/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/Rishav-12/astro-reactive-library#readme"
|
||||||
|
}
|
BIN
docs/public/default-og-image.png
Normal file
BIN
docs/public/default-og-image.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 731 KiB |
13
docs/public/favicon.svg
Normal file
13
docs/public/favicon.svg
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 36 36">
|
||||||
|
<path fill="#000" d="M22.25 4h-8.5a1 1 0 0 0-.96.73l-5.54 19.4a.5.5 0 0 0 .62.62l5.05-1.44a2 2 0 0 0 1.38-1.4l3.22-11.66a.5.5 0 0 1 .96 0l3.22 11.67a2 2 0 0 0 1.38 1.39l5.05 1.44a.5.5 0 0 0 .62-.62l-5.54-19.4a1 1 0 0 0-.96-.73Z"/>
|
||||||
|
<path fill="url(#gradient)" d="M18 28a7.63 7.63 0 0 1-5-2c-1.4 2.1-.35 4.35.6 5.55.14.17.41.07.47-.15.44-1.8 2.93-1.22 2.93.6 0 2.28.87 3.4 1.72 3.81.34.16.59-.2.49-.56-.31-1.05-.29-2.46 1.29-3.25 3-1.5 3.17-4.83 2.5-6-.67.67-2.6 2-5 2Z"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="gradient" x1="16" x2="16" y1="32" y2="24" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#000"/>
|
||||||
|
<stop offset="1" stop-color="#000" stop-opacity="0"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<style>
|
||||||
|
@media (prefers-color-scheme:dark){:root{filter:invert(100%)}}
|
||||||
|
</style>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 873 B |
3
docs/public/make-scrollable-code-focusable.js
Normal file
3
docs/public/make-scrollable-code-focusable.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
Array.from(document.getElementsByTagName('pre')).forEach((element) => {
|
||||||
|
element.setAttribute('tabindex', '0');
|
||||||
|
});
|
167
docs/src/components/Footer/AvatarList.astro
Normal file
167
docs/src/components/Footer/AvatarList.astro
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
---
|
||||||
|
// fetch all commits for just this page's path
|
||||||
|
type Props = {
|
||||||
|
path: string;
|
||||||
|
};
|
||||||
|
const { path } = Astro.props as Props;
|
||||||
|
const resolvedPath = `examples/docs/${path}`;
|
||||||
|
const url = `https://api.github.com/repos/ayoayco/astro-reactive-library/commits?path=${resolvedPath}`;
|
||||||
|
const commitsURL = `https://github.com/ayoayco/astro-reactive-library/commits/main/${resolvedPath}`;
|
||||||
|
|
||||||
|
type Commit = {
|
||||||
|
author: {
|
||||||
|
id: string;
|
||||||
|
login: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
async function getCommits(url: string) {
|
||||||
|
try {
|
||||||
|
const token = import.meta.env.SNOWPACK_PUBLIC_GITHUB_TOKEN ?? 'hello';
|
||||||
|
if (!token) {
|
||||||
|
throw new Error(
|
||||||
|
'Cannot find "SNOWPACK_PUBLIC_GITHUB_TOKEN" used for escaping rate-limiting.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auth = `Basic ${Buffer.from(token, 'binary').toString('base64')}`;
|
||||||
|
|
||||||
|
const res = await fetch(url, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
Authorization: auth,
|
||||||
|
'User-Agent': 'astro-docs/1.0',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
throw new Error(
|
||||||
|
`Request to fetch commits failed. Reason: ${res.statusText}
|
||||||
|
Message: ${data.message}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data as Commit[];
|
||||||
|
} catch (e) {
|
||||||
|
console.warn(`[error] /src/components/AvatarList.astro
|
||||||
|
${(e as any)?.message ?? e}`);
|
||||||
|
return [] as Commit[];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeDups(arr: Commit[]) {
|
||||||
|
const map = new Map<string, Commit['author']>();
|
||||||
|
|
||||||
|
for (let item of arr) {
|
||||||
|
const author = item.author;
|
||||||
|
// Deduplicate based on author.id
|
||||||
|
map.set(author.id, { login: author.login, id: author.id });
|
||||||
|
}
|
||||||
|
|
||||||
|
return [...map.values()];
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await getCommits(url);
|
||||||
|
const unique = removeDups(data);
|
||||||
|
const recentContributors = unique.slice(0, 3); // only show avatars for the 3 most recent contributors
|
||||||
|
const additionalContributors = unique.length - recentContributors.length; // list the rest of them as # of extra contributors
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- Thanks to @5t3ph for https://smolcss.dev/#smol-avatar-list! -->
|
||||||
|
<div class="contributors">
|
||||||
|
<ul class="avatar-list" style={`--avatar-count: ${recentContributors.length}`}>
|
||||||
|
{recentContributors.map((item) => (
|
||||||
|
<li>
|
||||||
|
<a href={`https://github.com/${item.login}`}>
|
||||||
|
<img
|
||||||
|
alt={`Contributor ${item.login}`}
|
||||||
|
title={`Contributor ${item.login}`}
|
||||||
|
width="64"
|
||||||
|
height="64"
|
||||||
|
src={`https://avatars.githubusercontent.com/u/${item.id}`}
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
{additionalContributors > 0 && (
|
||||||
|
<span>
|
||||||
|
<a href={commitsURL}>{`and ${additionalContributors} additional contributor${
|
||||||
|
additionalContributors > 1 ? 's' : ''
|
||||||
|
}.`}</a>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{unique.length === 0 && <a href={commitsURL}>Contributors</a>}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.avatar-list {
|
||||||
|
--avatar-size: 2.5rem;
|
||||||
|
--avatar-count: 3;
|
||||||
|
|
||||||
|
display: grid;
|
||||||
|
list-style: none;
|
||||||
|
/* Default to displaying most of the avatar to
|
||||||
|
enable easier access on touch devices, ensuring
|
||||||
|
the WCAG touch target size is met or exceeded */
|
||||||
|
grid-template-columns: repeat(var(--avatar-count), max(44px, calc(var(--avatar-size) / 1.15)));
|
||||||
|
/* `padding` matches added visual dimensions of
|
||||||
|
the `box-shadow` to help create a more accurate
|
||||||
|
computed component size */
|
||||||
|
padding: 0.08em;
|
||||||
|
font-size: var(--avatar-size);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (any-hover: hover) and (any-pointer: fine) {
|
||||||
|
.avatar-list {
|
||||||
|
/* We create 1 extra cell to enable the computed
|
||||||
|
width to match the final visual width */
|
||||||
|
grid-template-columns: repeat(calc(var(--avatar-count) + 1), calc(var(--avatar-size) / 1.75));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-list li {
|
||||||
|
width: var(--avatar-size);
|
||||||
|
height: var(--avatar-size);
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-list li:hover ~ li a,
|
||||||
|
.avatar-list li:focus-within ~ li a {
|
||||||
|
transform: translateX(33%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-list img,
|
||||||
|
.avatar-list a {
|
||||||
|
display: block;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-list a {
|
||||||
|
transition: transform 180ms ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-list img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
background-color: #fff;
|
||||||
|
box-shadow: 0 0 0 0.05em #fff, 0 0 0 0.08em rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-list a:focus {
|
||||||
|
outline: 2px solid transparent;
|
||||||
|
/* Double-layer trick to work for dark and light backgrounds */
|
||||||
|
box-shadow: 0 0 0 0.08em var(--theme-accent), 0 0 0 0.12em white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contributors {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contributors > * + * {
|
||||||
|
margin-left: 0.75rem;
|
||||||
|
}
|
||||||
|
</style>
|
19
docs/src/components/Footer/Footer.astro
Normal file
19
docs/src/components/Footer/Footer.astro
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
---
|
||||||
|
import AvatarList from './AvatarList.astro';
|
||||||
|
type Props = {
|
||||||
|
path: string;
|
||||||
|
};
|
||||||
|
const { path } = Astro.props as Props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<AvatarList path={path} />
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
footer {
|
||||||
|
margin-top: auto;
|
||||||
|
padding: 2rem;
|
||||||
|
border-top: 3px solid var(--theme-divider);
|
||||||
|
}
|
||||||
|
</style>
|
46
docs/src/components/HeadCommon.astro
Normal file
46
docs/src/components/HeadCommon.astro
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
---
|
||||||
|
import '../styles/theme.css';
|
||||||
|
import '../styles/index.css';
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- Global Metadata -->
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width" />
|
||||||
|
<meta name="generator" content={Astro.generator} />
|
||||||
|
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
|
|
||||||
|
<link rel="sitemap" href="/sitemap.xml" />
|
||||||
|
|
||||||
|
<!-- Preload Fonts -->
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
|
<link
|
||||||
|
href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital@0;1&display=swap"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- Scrollable a11y code helper -->
|
||||||
|
<script src="/make-scrollable-code-focusable.js" is:inline>
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- This is intentionally inlined to avoid FOUC -->
|
||||||
|
<script is:inline>
|
||||||
|
const root = document.documentElement;
|
||||||
|
const theme = localStorage.getItem('theme');
|
||||||
|
if (theme === 'dark' || (!theme && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
||||||
|
root.classList.add('theme-dark');
|
||||||
|
} else {
|
||||||
|
root.classList.remove('theme-dark');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||||||
|
<!-- <script async src="https://www.googletagmanager.com/gtag/js?id=G-TEL60V1WM9" is:inline></script>
|
||||||
|
<script>
|
||||||
|
window.dataLayer = window.dataLayer || [];
|
||||||
|
function gtag(){dataLayer.push(arguments);}
|
||||||
|
gtag('js', new Date());
|
||||||
|
gtag('config', 'G-TEL60V1WM9');
|
||||||
|
</script> -->
|
46
docs/src/components/HeadSEO.astro
Normal file
46
docs/src/components/HeadSEO.astro
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
---
|
||||||
|
import { SITE, OPEN_GRAPH, Frontmatter } from '../config';
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
frontmatter: Frontmatter;
|
||||||
|
canonicalUrl: URL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { frontmatter, canonicalUrl } = Astro.props as Props;
|
||||||
|
const formattedContentTitle = `${frontmatter.title} 🚀 ${SITE.title}`;
|
||||||
|
const imageSrc = frontmatter.image?.src ?? OPEN_GRAPH.image.src;
|
||||||
|
const canonicalImageSrc = new URL(imageSrc, Astro.site);
|
||||||
|
const imageAlt = frontmatter.image?.alt ?? OPEN_GRAPH.image.alt;
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- Page Metadata -->
|
||||||
|
<link rel="canonical" href={canonicalUrl} />
|
||||||
|
|
||||||
|
<!-- OpenGraph Tags -->
|
||||||
|
<meta property="og:title" content={formattedContentTitle} />
|
||||||
|
<meta property="og:type" content="article" />
|
||||||
|
<meta property="og:url" content={canonicalUrl} />
|
||||||
|
<meta property="og:locale" content={frontmatter.ogLocale ?? SITE.defaultLanguage} />
|
||||||
|
<meta property="og:image" content={canonicalImageSrc} />
|
||||||
|
<meta property="og:image:alt" content={imageAlt} />
|
||||||
|
<meta
|
||||||
|
name="description"
|
||||||
|
property="og:description"
|
||||||
|
content={frontmatter.description ?? SITE.description}
|
||||||
|
/>
|
||||||
|
<meta property="og:site_name" content={SITE.title} />
|
||||||
|
|
||||||
|
<!-- Twitter Tags -->
|
||||||
|
<meta name="twitter:card" content="summary_large_image" />
|
||||||
|
<meta name="twitter:site" content={OPEN_GRAPH.twitter} />
|
||||||
|
<meta name="twitter:title" content={formattedContentTitle} />
|
||||||
|
<meta name="twitter:description" content={frontmatter.description ?? SITE.description} />
|
||||||
|
<meta name="twitter:image" content={canonicalImageSrc} />
|
||||||
|
<meta name="twitter:image:alt" content={imageAlt} />
|
||||||
|
|
||||||
|
<!--
|
||||||
|
TODO: Add json+ld data, maybe https://schema.org/APIReference makes sense?
|
||||||
|
Docs: https://developers.google.com/search/docs/advanced/structured-data/intro-structured-data
|
||||||
|
https://www.npmjs.com/package/schema-dts seems like a great resource for implementing this.
|
||||||
|
Even better, there's a React component that integrates with `schema-dts`: https://github.com/google/react-schemaorg
|
||||||
|
-->
|
40
docs/src/components/Header/AstroLogo.astro
Normal file
40
docs/src/components/Header/AstroLogo.astro
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
---
|
||||||
|
type Props = {
|
||||||
|
size: number;
|
||||||
|
};
|
||||||
|
const { size } = Astro.props as Props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<svg
|
||||||
|
class="logo"
|
||||||
|
width={size}
|
||||||
|
height={size}
|
||||||
|
viewBox="0 0 256 256"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<style>
|
||||||
|
#flame {
|
||||||
|
fill: var(--theme-text-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
#a {
|
||||||
|
fill: var(--theme-text-accent);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<title>Logo</title>
|
||||||
|
<path
|
||||||
|
id="a"
|
||||||
|
fill-rule="evenodd"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
d="M163.008 18.929c1.944 2.413 2.935 5.67 4.917 12.181l43.309 142.27a180.277 180.277 0 00-51.778-17.53l-28.198-95.29a3.67 3.67 0 00-7.042.01l-27.857 95.232a180.225 180.225 0 00-52.01 17.557l43.52-142.281c1.99-6.502 2.983-9.752 4.927-12.16a15.999 15.999 0 016.484-4.798c2.872-1.154 6.271-1.154 13.07-1.154h31.085c6.807 0 10.211 0 13.086 1.157a16.004 16.004 0 016.487 4.806z"
|
||||||
|
>
|
||||||
|
</path>
|
||||||
|
<path
|
||||||
|
id="flame"
|
||||||
|
fill-rule="evenodd"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
d="M168.19 180.151c-7.139 6.105-21.39 10.268-37.804 10.268-20.147 0-37.033-6.272-41.513-14.707-1.602 4.835-1.961 10.367-1.961 13.902 0 0-1.056 17.355 11.015 29.426 0-6.268 5.081-11.349 11.349-11.349 10.743 0 10.731 9.373 10.721 16.977v.679c0 11.542 7.054 21.436 17.086 25.606a23.27 23.27 0 01-2.339-10.2c0-11.008 6.463-15.107 13.974-19.87 5.976-3.79 12.616-8.001 17.192-16.449a31.024 31.024 0 003.743-14.82c0-3.299-.513-6.479-1.463-9.463z"
|
||||||
|
>
|
||||||
|
</path>
|
||||||
|
</svg>
|
149
docs/src/components/Header/Header.astro
Normal file
149
docs/src/components/Header/Header.astro
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
---
|
||||||
|
import { getLanguageFromURL, KNOWN_LANGUAGE_CODES } from '../../languages';
|
||||||
|
import * as CONFIG from '../../config';
|
||||||
|
import AstroLogo from './AstroLogo.astro';
|
||||||
|
import SkipToContent from './SkipToContent.astro';
|
||||||
|
import SidebarToggle from './SidebarToggle';
|
||||||
|
import LanguageSelect from './LanguageSelect';
|
||||||
|
import Search from './Search';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
currentPage: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const { currentPage } = Astro.props as Props;
|
||||||
|
const lang = getLanguageFromURL(currentPage);
|
||||||
|
---
|
||||||
|
|
||||||
|
<header>
|
||||||
|
<SkipToContent />
|
||||||
|
<nav class="nav-wrapper" title="Top Navigation">
|
||||||
|
<div class="menu-toggle">
|
||||||
|
<SidebarToggle client:idle />
|
||||||
|
</div>
|
||||||
|
<div class="logo flex">
|
||||||
|
<a href="/">
|
||||||
|
<AstroLogo size={40} />
|
||||||
|
<h1>{CONFIG.SITE.title ?? 'Documentation'}</h1>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div style="flex-grow: 1;"></div>
|
||||||
|
{KNOWN_LANGUAGE_CODES.length > 1 && <LanguageSelect lang={lang} client:idle />}
|
||||||
|
<div class="search-item">
|
||||||
|
<Search client:idle />
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
header {
|
||||||
|
z-index: 11;
|
||||||
|
height: var(--theme-navbar-height);
|
||||||
|
width: 100%;
|
||||||
|
background-color: var(--theme-navbar-bg);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
overflow: hidden;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
overflow: hidden;
|
||||||
|
width: 30px;
|
||||||
|
font-size: 2rem;
|
||||||
|
flex-shrink: 0;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1;
|
||||||
|
color: hsla(var(--color-base-white), 100%, 1);
|
||||||
|
gap: 0.25em;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo a {
|
||||||
|
display: flex;
|
||||||
|
padding: 0.5em 0.25em;
|
||||||
|
margin: -0.5em -0.25em;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo a {
|
||||||
|
transition: color 100ms ease-out;
|
||||||
|
color: var(--theme-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo a:hover,
|
||||||
|
.logo a:focus {
|
||||||
|
color: var(--theme-text-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo h1 {
|
||||||
|
display: none;
|
||||||
|
font: inherit;
|
||||||
|
color: inherit;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-wrapper {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 1em;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 82em;
|
||||||
|
padding: 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 50em) {
|
||||||
|
header {
|
||||||
|
position: static;
|
||||||
|
padding: 2rem 0rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
width: auto;
|
||||||
|
margin: 0;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo h1 {
|
||||||
|
display: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-toggle {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Style Algolia */
|
||||||
|
:root {
|
||||||
|
--docsearch-primary-color: var(--theme-accent);
|
||||||
|
--docsearch-logo-color: var(--theme-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-item {
|
||||||
|
display: none;
|
||||||
|
position: relative;
|
||||||
|
z-index: 10;
|
||||||
|
flex-grow: 1;
|
||||||
|
padding-right: 0.7rem;
|
||||||
|
display: flex;
|
||||||
|
max-width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 50em) {
|
||||||
|
.search-item {
|
||||||
|
max-width: 400px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style is:global>
|
||||||
|
.search-item > * {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
</style>
|
47
docs/src/components/Header/LanguageSelect.css
Normal file
47
docs/src/components/Header/LanguageSelect.css
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
.language-select {
|
||||||
|
flex-grow: 1;
|
||||||
|
width: 48px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0.33em 0.5em;
|
||||||
|
overflow: visible;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-family: inherit;
|
||||||
|
line-height: inherit;
|
||||||
|
background-color: var(--theme-bg);
|
||||||
|
border-color: var(--theme-text-lighter);
|
||||||
|
color: var(--theme-text-light);
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 1px;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
outline: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
transition-timing-function: ease-out;
|
||||||
|
transition-duration: 0.2s;
|
||||||
|
transition-property: border-color, color;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
padding-left: 30px;
|
||||||
|
padding-right: 1rem;
|
||||||
|
}
|
||||||
|
.language-select-wrapper .language-select:hover,
|
||||||
|
.language-select-wrapper .language-select:focus {
|
||||||
|
color: var(--theme-text);
|
||||||
|
border-color: var(--theme-text-light);
|
||||||
|
}
|
||||||
|
.language-select-wrapper {
|
||||||
|
color: var(--theme-text-light);
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.language-select-wrapper > svg {
|
||||||
|
position: absolute;
|
||||||
|
top: 7px;
|
||||||
|
left: 10px;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 50em) {
|
||||||
|
.language-select {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
49
docs/src/components/Header/LanguageSelect.tsx
Normal file
49
docs/src/components/Header/LanguageSelect.tsx
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/** @jsxImportSource react */
|
||||||
|
import type { FunctionComponent } from 'react';
|
||||||
|
import './LanguageSelect.css';
|
||||||
|
import { KNOWN_LANGUAGES, langPathRegex } from '../../languages';
|
||||||
|
|
||||||
|
const LanguageSelect: FunctionComponent<{ lang: string }> = ({ lang }) => {
|
||||||
|
return (
|
||||||
|
<div className="language-select-wrapper">
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
focusable="false"
|
||||||
|
role="img"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 88.6 77.3"
|
||||||
|
height="1.2em"
|
||||||
|
width="1.2em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M61,24.6h7.9l18.7,51.6h-7.7l-5.4-15.5H54.3l-5.6,15.5h-7.2L61,24.6z M72.6,55l-8-22.8L56.3,55H72.6z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M53.6,60.6c-10-4-16-9-22-14c0,0,1.3,1.3,0,0c-6,5-20,13-20,13l-4-6c8-5,10-6,19-13c-2.1-1.9-12-13-13-19h8 c4,9,10,14,10,14c10-8,10-19,10-19h8c0,0-1,13-12,24l0,0c5,5,10,9,19,13L53.6,60.6z M1.6,16.6h56v-8h-23v-7h-9v7h-24V16.6z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<select
|
||||||
|
className="language-select"
|
||||||
|
value={lang}
|
||||||
|
onChange={(e) => {
|
||||||
|
const newLang = e.target.value;
|
||||||
|
let actualDest = window.location.pathname.replace(langPathRegex, '/');
|
||||||
|
if (actualDest == '/') actualDest = `/introduction`;
|
||||||
|
window.location.pathname = '/' + newLang + actualDest;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{Object.entries(KNOWN_LANGUAGES).map(([key, value]) => {
|
||||||
|
return (
|
||||||
|
<option value={value} key={value}>
|
||||||
|
<span>{key}</span>
|
||||||
|
</option>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LanguageSelect;
|
76
docs/src/components/Header/Search.css
Normal file
76
docs/src/components/Header/Search.css
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
/** Style Algolia */
|
||||||
|
:root {
|
||||||
|
--docsearch-primary-color: var(--theme-accent);
|
||||||
|
--docsearch-logo-color: var(--theme-text);
|
||||||
|
}
|
||||||
|
.search-input {
|
||||||
|
flex-grow: 1;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0.33em 0.5em;
|
||||||
|
overflow: visible;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-family: inherit;
|
||||||
|
line-height: inherit;
|
||||||
|
background-color: var(--theme-divider);
|
||||||
|
border-color: var(--theme-divider);
|
||||||
|
color: var(--theme-text-light);
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 1px;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
outline: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
transition-timing-function: ease-out;
|
||||||
|
transition-duration: 0.2s;
|
||||||
|
transition-property: border-color, color;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
}
|
||||||
|
.search-input:hover,
|
||||||
|
.search-input:focus {
|
||||||
|
color: var(--theme-text);
|
||||||
|
border-color: var(--theme-text-light);
|
||||||
|
}
|
||||||
|
.search-input:hover::placeholder,
|
||||||
|
.search-input:focus::placeholder {
|
||||||
|
color: var(--theme-text-light);
|
||||||
|
}
|
||||||
|
.search-input::placeholder {
|
||||||
|
color: var(--theme-text-light);
|
||||||
|
}
|
||||||
|
.search-hint {
|
||||||
|
position: absolute;
|
||||||
|
top: 7px;
|
||||||
|
right: 19px;
|
||||||
|
padding: 3px 5px;
|
||||||
|
display: none;
|
||||||
|
display: none;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
letter-spacing: 0.125em;
|
||||||
|
font-size: 13px;
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
pointer-events: none;
|
||||||
|
border-color: var(--theme-text-lighter);
|
||||||
|
color: var(--theme-text-light);
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 1px;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
line-height: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 50em) {
|
||||||
|
.search-hint {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ *\
|
||||||
|
DocSearch (Algolia)
|
||||||
|
\* ------------------------------------------------------------ */
|
||||||
|
|
||||||
|
.DocSearch-Modal .DocSearch-Hit a {
|
||||||
|
box-shadow: none;
|
||||||
|
border: 1px solid var(--theme-accent);
|
||||||
|
}
|
97
docs/src/components/Header/Search.tsx
Normal file
97
docs/src/components/Header/Search.tsx
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
/** @jsxImportSource react */
|
||||||
|
import { useState, useCallback, useRef } from 'react';
|
||||||
|
import { ALGOLIA } from '../../config';
|
||||||
|
import '@docsearch/css';
|
||||||
|
import './Search.css';
|
||||||
|
|
||||||
|
import { createPortal } from 'react-dom';
|
||||||
|
import * as docSearchReact from '@docsearch/react';
|
||||||
|
|
||||||
|
/** FIXME: This is still kinda nasty, but DocSearch is not ESM ready. */
|
||||||
|
const DocSearchModal =
|
||||||
|
docSearchReact.DocSearchModal || (docSearchReact as any).default.DocSearchModal;
|
||||||
|
const useDocSearchKeyboardEvents =
|
||||||
|
docSearchReact.useDocSearchKeyboardEvents ||
|
||||||
|
(docSearchReact as any).default.useDocSearchKeyboardEvents;
|
||||||
|
|
||||||
|
export default function Search() {
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
const searchButtonRef = useRef<HTMLButtonElement>(null);
|
||||||
|
const [initialQuery, setInitialQuery] = useState('');
|
||||||
|
|
||||||
|
const onOpen = useCallback(() => {
|
||||||
|
setIsOpen(true);
|
||||||
|
}, [setIsOpen]);
|
||||||
|
|
||||||
|
const onClose = useCallback(() => {
|
||||||
|
setIsOpen(false);
|
||||||
|
}, [setIsOpen]);
|
||||||
|
|
||||||
|
const onInput = useCallback(
|
||||||
|
(e) => {
|
||||||
|
setIsOpen(true);
|
||||||
|
setInitialQuery(e.key);
|
||||||
|
},
|
||||||
|
[setIsOpen, setInitialQuery]
|
||||||
|
);
|
||||||
|
|
||||||
|
useDocSearchKeyboardEvents({
|
||||||
|
isOpen,
|
||||||
|
onOpen,
|
||||||
|
onClose,
|
||||||
|
onInput,
|
||||||
|
searchButtonRef,
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<button type="button" ref={searchButtonRef} onClick={onOpen} className="search-input">
|
||||||
|
<svg width="24" height="24" fill="none">
|
||||||
|
<path
|
||||||
|
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="2"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
<span>Search</span>
|
||||||
|
|
||||||
|
<span className="search-hint">
|
||||||
|
<span className="sr-only">Press </span>
|
||||||
|
|
||||||
|
<kbd>/</kbd>
|
||||||
|
|
||||||
|
<span className="sr-only"> to search</span>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{isOpen &&
|
||||||
|
createPortal(
|
||||||
|
<DocSearchModal
|
||||||
|
initialQuery={initialQuery}
|
||||||
|
initialScrollY={window.scrollY}
|
||||||
|
onClose={onClose}
|
||||||
|
indexName={ALGOLIA.indexName}
|
||||||
|
appId={ALGOLIA.appId}
|
||||||
|
apiKey={ALGOLIA.apiKey}
|
||||||
|
transformItems={(items) => {
|
||||||
|
return items.map((item) => {
|
||||||
|
// We transform the absolute URL into a relative URL to
|
||||||
|
// work better on localhost, preview URLS.
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = item.url;
|
||||||
|
const hash = a.hash === '#overview' ? '' : a.hash;
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
url: `${a.pathname}${hash}`,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>,
|
||||||
|
document.body
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
44
docs/src/components/Header/SidebarToggle.tsx
Normal file
44
docs/src/components/Header/SidebarToggle.tsx
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/** @jsxImportSource preact */
|
||||||
|
import type { FunctionalComponent } from 'preact';
|
||||||
|
import { useState, useEffect } from 'preact/hooks';
|
||||||
|
|
||||||
|
const MenuToggle: FunctionalComponent = () => {
|
||||||
|
const [sidebarShown, setSidebarShown] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const body = document.querySelector('body')!;
|
||||||
|
if (sidebarShown) {
|
||||||
|
body.classList.add('mobile-sidebar-toggle');
|
||||||
|
} else {
|
||||||
|
body.classList.remove('mobile-sidebar-toggle');
|
||||||
|
}
|
||||||
|
}, [sidebarShown]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
aria-pressed={sidebarShown ? 'true' : 'false'}
|
||||||
|
id="menu-toggle"
|
||||||
|
onClick={() => setSidebarShown(!sidebarShown)}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="1em"
|
||||||
|
height="1em"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M4 6h16M4 12h16M4 18h16"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span className="sr-only">Toggle sidebar</span>
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MenuToggle;
|
26
docs/src/components/Header/SkipToContent.astro
Normal file
26
docs/src/components/Header/SkipToContent.astro
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
---
|
||||||
|
type Props = {};
|
||||||
|
---
|
||||||
|
|
||||||
|
<a href="#article" class="sr-only focus:not-sr-only skiplink"><span>Skip to Content</span></a>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.skiplink,
|
||||||
|
.skiplink:focus,
|
||||||
|
.skiplink:focus-visible {
|
||||||
|
position: absolute;
|
||||||
|
padding: 0.25em;
|
||||||
|
font-size: larger;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 9;
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
background-color: var(--theme-text-accent);
|
||||||
|
color: var(--theme-bg);
|
||||||
|
border-radius: 0.25em;
|
||||||
|
outline: var(--theme-bg) solid 1px;
|
||||||
|
outline-offset: 0;
|
||||||
|
}
|
||||||
|
</style>
|
117
docs/src/components/LeftSidebar/LeftSidebar.astro
Normal file
117
docs/src/components/LeftSidebar/LeftSidebar.astro
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
---
|
||||||
|
import { getLanguageFromURL } from '../../languages';
|
||||||
|
import { SIDEBAR } from '../../config';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
currentPage: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const { currentPage } = Astro.props as Props;
|
||||||
|
const currentPageMatch = currentPage.endsWith('/')
|
||||||
|
? currentPage.slice(1, -1)
|
||||||
|
: currentPage.slice(1);
|
||||||
|
const langCode = getLanguageFromURL(currentPage);
|
||||||
|
const sidebar = SIDEBAR[langCode];
|
||||||
|
---
|
||||||
|
|
||||||
|
<nav aria-labelledby="grid-left">
|
||||||
|
<ul class="nav-groups">
|
||||||
|
{Object.entries(sidebar).map(([header, children]) => (
|
||||||
|
<li>
|
||||||
|
<div class="nav-group">
|
||||||
|
<h2>{header}</h2>
|
||||||
|
<ul>
|
||||||
|
{children.map((child) => {
|
||||||
|
const url = Astro.site?.pathname + child.link;
|
||||||
|
return (
|
||||||
|
<li class="nav-link">
|
||||||
|
<a href={url} aria-current={currentPageMatch === child.link ? 'page' : false}>
|
||||||
|
{child.text}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<script is:inline>
|
||||||
|
window.addEventListener('DOMContentLoaded', () => {
|
||||||
|
var target = document.querySelector('[aria-current="page"]');
|
||||||
|
if (target && target.offsetTop > window.innerHeight - 100) {
|
||||||
|
document.querySelector('.nav-groups').scrollTop = target.offsetTop;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
nav {
|
||||||
|
width: 100%;
|
||||||
|
margin-right: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-groups {
|
||||||
|
height: 100%;
|
||||||
|
padding: 2rem 0;
|
||||||
|
overflow-x: visible;
|
||||||
|
overflow-y: auto;
|
||||||
|
max-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-groups > li + li {
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-groups > :first-child {
|
||||||
|
padding-top: var(--doc-padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-groups > :last-child {
|
||||||
|
padding-bottom: 2rem;
|
||||||
|
margin-bottom: var(--theme-navbar-height);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-group-title {
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 700;
|
||||||
|
padding: 0.1rem 1rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-link a {
|
||||||
|
font-size: 1rem;
|
||||||
|
margin: 1px;
|
||||||
|
padding: 0.3rem 1rem;
|
||||||
|
font: inherit;
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-link a:hover,
|
||||||
|
.nav-link a:focus {
|
||||||
|
background-color: var(--theme-bg-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-link a[aria-current='page'] {
|
||||||
|
color: var(--theme-text-accent);
|
||||||
|
background-color: var(--theme-bg-accent);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 50em) {
|
||||||
|
.nav-groups {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style is:global>
|
||||||
|
:root.theme-dark .nav-link a[aria-current='page'] {
|
||||||
|
color: hsla(var(--color-base-white), 100%, 1);
|
||||||
|
}
|
||||||
|
</style>
|
53
docs/src/components/PageContent/PageContent.astro
Normal file
53
docs/src/components/PageContent/PageContent.astro
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
---
|
||||||
|
import type { Frontmatter } from '../../config';
|
||||||
|
import MoreMenu from '../RightSidebar/MoreMenu.astro';
|
||||||
|
import TableOfContents from '../RightSidebar/TableOfContents';
|
||||||
|
import type { MarkdownHeading } from 'astro';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
frontmatter: Frontmatter;
|
||||||
|
headings: MarkdownHeading[];
|
||||||
|
githubEditUrl: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const { frontmatter, headings, githubEditUrl } = Astro.props as Props;
|
||||||
|
const title = frontmatter.title;
|
||||||
|
---
|
||||||
|
|
||||||
|
<article id="article" class="content">
|
||||||
|
<section class="main-section">
|
||||||
|
<h1 class="content-title" id="overview">{title}</h1>
|
||||||
|
<nav class="block sm:hidden">
|
||||||
|
<TableOfContents client:media="(max-width: 50em)" headings={headings} />
|
||||||
|
</nav>
|
||||||
|
<slot />
|
||||||
|
</section>
|
||||||
|
<nav class="block sm:hidden">
|
||||||
|
<MoreMenu editHref={githubEditUrl} />
|
||||||
|
</nav>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.content {
|
||||||
|
padding: 0;
|
||||||
|
max-width: 75ch;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content > section {
|
||||||
|
margin-bottom: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.block {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 50em) {
|
||||||
|
.sm\:hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
75
docs/src/components/RightSidebar/MoreMenu.astro
Normal file
75
docs/src/components/RightSidebar/MoreMenu.astro
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
---
|
||||||
|
import ThemeToggleButton from './ThemeToggleButton';
|
||||||
|
import * as CONFIG from '../../config';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
editHref: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const { editHref } = Astro.props as Props;
|
||||||
|
const showMoreSection = CONFIG.COMMUNITY_INVITE_URL;
|
||||||
|
---
|
||||||
|
|
||||||
|
{showMoreSection && <h2 class="heading">More</h2>}
|
||||||
|
<ul>
|
||||||
|
{editHref && (
|
||||||
|
<li class={`heading-link depth-2`}>
|
||||||
|
<a class="edit-on-github" href={editHref} target="_blank">
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
focusable="false"
|
||||||
|
data-prefix="fas"
|
||||||
|
data-icon="pen"
|
||||||
|
class="svg-inline--fa fa-pen fa-w-16"
|
||||||
|
role="img"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 512 512"
|
||||||
|
height="1em"
|
||||||
|
width="1em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M290.74 93.24l128.02 128.02-277.99 277.99-114.14 12.6C11.35 513.54-1.56 500.62.14 485.34l12.7-114.22 277.9-277.88zm207.2-19.06l-60.11-60.11c-18.75-18.75-49.16-18.75-67.91 0l-56.55 56.55 128.02 128.02 56.55-56.55c18.75-18.76 18.75-49.16 0-67.91z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span>Edit this page</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
{CONFIG.COMMUNITY_INVITE_URL && (
|
||||||
|
<li class={`heading-link depth-2`}>
|
||||||
|
<a href={CONFIG.COMMUNITY_INVITE_URL} target="_blank">
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
focusable="false"
|
||||||
|
data-prefix="fas"
|
||||||
|
data-icon="comment-alt"
|
||||||
|
class="svg-inline--fa fa-comment-alt fa-w-16"
|
||||||
|
role="img"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 512 512"
|
||||||
|
height="1em"
|
||||||
|
width="1em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M448 0H64C28.7 0 0 28.7 0 64v288c0 35.3 28.7 64 64 64h96v84c0 9.8 11.2 15.5 19.1 9.7L304 416h144c35.3 0 64-28.7 64-64V64c0-35.3-28.7-64-64-64z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span>Join our community</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
<div style="margin: 2rem 0; text-align: center;">
|
||||||
|
<ThemeToggleButton client:visible />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.edit-on-github {
|
||||||
|
text-decoration: none;
|
||||||
|
font: inherit;
|
||||||
|
color: inherit;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
</style>
|
34
docs/src/components/RightSidebar/RightSidebar.astro
Normal file
34
docs/src/components/RightSidebar/RightSidebar.astro
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
---
|
||||||
|
import TableOfContents from './TableOfContents';
|
||||||
|
import MoreMenu from './MoreMenu.astro';
|
||||||
|
import type { MarkdownHeading } from 'astro';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
headings: MarkdownHeading[];
|
||||||
|
githubEditUrl: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const { headings, githubEditUrl } = Astro.props as Props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<nav class="sidebar-nav" aria-labelledby="grid-right">
|
||||||
|
<div class="sidebar-nav-inner">
|
||||||
|
<TableOfContents client:media="(min-width: 50em)" headings={headings} />
|
||||||
|
<MoreMenu editHref={githubEditUrl} />
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.sidebar-nav {
|
||||||
|
width: 100%;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-nav-inner {
|
||||||
|
height: 100%;
|
||||||
|
padding: 0;
|
||||||
|
padding-top: var(--doc-padding);
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
</style>
|
56
docs/src/components/RightSidebar/TableOfContents.tsx
Normal file
56
docs/src/components/RightSidebar/TableOfContents.tsx
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
import type { FunctionalComponent } from 'preact';
|
||||||
|
import { useState, useEffect, useRef } from 'preact/hooks';
|
||||||
|
import type { MarkdownHeading } from 'astro';
|
||||||
|
|
||||||
|
type ItemOffsets = {
|
||||||
|
id: string;
|
||||||
|
topOffset: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
const TableOfContents: FunctionalComponent<{ headings: MarkdownHeading[] }> = ({
|
||||||
|
headings = [],
|
||||||
|
}) => {
|
||||||
|
const itemOffsets = useRef<ItemOffsets[]>([]);
|
||||||
|
// FIXME: Not sure what this state is doing. It was never set to anything truthy.
|
||||||
|
const [activeId] = useState<string>('');
|
||||||
|
useEffect(() => {
|
||||||
|
const getItemOffsets = () => {
|
||||||
|
const titles = document.querySelectorAll('article :is(h1, h2, h3, h4)');
|
||||||
|
itemOffsets.current = Array.from(titles).map((title) => ({
|
||||||
|
id: title.id,
|
||||||
|
topOffset: title.getBoundingClientRect().top + window.scrollY,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
getItemOffsets();
|
||||||
|
window.addEventListener('resize', getItemOffsets);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('resize', getItemOffsets);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h2 className="heading">On this page</h2>
|
||||||
|
<ul>
|
||||||
|
<li className={`heading-link depth-2 ${activeId === 'overview' ? 'active' : ''}`.trim()}>
|
||||||
|
<a href="#overview">Overview</a>
|
||||||
|
</li>
|
||||||
|
{headings
|
||||||
|
.filter(({ depth }) => depth > 1 && depth < 4)
|
||||||
|
.map((heading) => (
|
||||||
|
<li
|
||||||
|
className={`heading-link depth-${heading.depth} ${
|
||||||
|
activeId === heading.slug ? 'active' : ''
|
||||||
|
}`.trim()}
|
||||||
|
>
|
||||||
|
<a href={`#${heading.slug}`}>{heading.text}</a>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TableOfContents;
|
37
docs/src/components/RightSidebar/ThemeToggleButton.css
Normal file
37
docs/src/components/RightSidebar/ThemeToggleButton.css
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
.theme-toggle {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.25em;
|
||||||
|
padding: 0.33em 0.67em;
|
||||||
|
border-radius: 99em;
|
||||||
|
background-color: var(--theme-code-inline-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-toggle > label:focus-within {
|
||||||
|
outline: 2px solid transparent;
|
||||||
|
box-shadow: 0 0 0 0.08em var(--theme-accent), 0 0 0 0.12em white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-toggle > label {
|
||||||
|
color: var(--theme-code-inline-text);
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-toggle .checked {
|
||||||
|
color: var(--theme-accent);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[name='theme-toggle'] {
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
82
docs/src/components/RightSidebar/ThemeToggleButton.tsx
Normal file
82
docs/src/components/RightSidebar/ThemeToggleButton.tsx
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
import type { FunctionalComponent } from 'preact';
|
||||||
|
import { useState, useEffect } from 'preact/hooks';
|
||||||
|
import './ThemeToggleButton.css';
|
||||||
|
|
||||||
|
const themes = ['light', 'dark'];
|
||||||
|
|
||||||
|
const icons = [
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"
|
||||||
|
clipRule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>,
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z" />
|
||||||
|
</svg>,
|
||||||
|
];
|
||||||
|
|
||||||
|
const ThemeToggle: FunctionalComponent = () => {
|
||||||
|
const [theme, setTheme] = useState(() => {
|
||||||
|
if (import.meta.env.SSR) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if (typeof localStorage !== undefined && localStorage.getItem('theme')) {
|
||||||
|
return localStorage.getItem('theme');
|
||||||
|
}
|
||||||
|
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||||
|
return 'dark';
|
||||||
|
}
|
||||||
|
return 'light';
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const root = document.documentElement;
|
||||||
|
if (theme === 'light') {
|
||||||
|
root.classList.remove('theme-dark');
|
||||||
|
} else {
|
||||||
|
root.classList.add('theme-dark');
|
||||||
|
}
|
||||||
|
}, [theme]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="theme-toggle">
|
||||||
|
{themes.map((t, i) => {
|
||||||
|
const icon = icons[i];
|
||||||
|
const checked = t === theme;
|
||||||
|
return (
|
||||||
|
<label className={checked ? ' checked' : ''}>
|
||||||
|
{icon}
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="theme-toggle"
|
||||||
|
checked={checked}
|
||||||
|
value={t}
|
||||||
|
title={`Use ${t} theme`}
|
||||||
|
aria-label={`Use ${t} theme`}
|
||||||
|
onChange={() => {
|
||||||
|
localStorage.setItem('theme', t);
|
||||||
|
setTheme(t);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ThemeToggle;
|
57
docs/src/config.ts
Normal file
57
docs/src/config.ts
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
export const SITE = {
|
||||||
|
title: 'Astro Reactive Library Docs',
|
||||||
|
description: 'Documentation for the Astro Reactive Library',
|
||||||
|
defaultLanguage: 'en_US',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const OPEN_GRAPH = {
|
||||||
|
image: {
|
||||||
|
src: 'https://github.com/withastro/astro/blob/main/assets/social/banner.jpg?raw=true',
|
||||||
|
alt:
|
||||||
|
'astro logo on a starry expanse of space,' +
|
||||||
|
' with a purple saturn-like planet floating in the right foreground',
|
||||||
|
},
|
||||||
|
twitter: 'astrodotbuild',
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is the type of the frontmatter you put in the docs markdown files.
|
||||||
|
export type Frontmatter = {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
layout: string;
|
||||||
|
image?: { src: string; alt: string };
|
||||||
|
dir?: 'ltr' | 'rtl';
|
||||||
|
ogLocale?: string;
|
||||||
|
lang?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const KNOWN_LANGUAGES = {
|
||||||
|
English: 'en',
|
||||||
|
} as const;
|
||||||
|
export const KNOWN_LANGUAGE_CODES = Object.values(KNOWN_LANGUAGES);
|
||||||
|
|
||||||
|
export const GITHUB_EDIT_URL = `https://github.com/ayoayco/astro-reactive-library/tree/main/docs`;
|
||||||
|
|
||||||
|
export const COMMUNITY_INVITE_URL = `https://astro.build/chat`;
|
||||||
|
|
||||||
|
// See "Algolia" section of the README for more information.
|
||||||
|
export const ALGOLIA = {
|
||||||
|
indexName: 'XXXXXXXXXX',
|
||||||
|
appId: 'XXXXXXXXXX',
|
||||||
|
apiKey: 'XXXXXXXXXX',
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Sidebar = Record<
|
||||||
|
typeof KNOWN_LANGUAGE_CODES[number],
|
||||||
|
Record<string, { text: string; link: string }[]>
|
||||||
|
>;
|
||||||
|
export const SIDEBAR: Sidebar = {
|
||||||
|
en: {
|
||||||
|
'Section Header': [
|
||||||
|
{ text: 'Introduction', link: 'en/introduction' },
|
||||||
|
{ text: 'Page 2', link: 'en/page-2' },
|
||||||
|
{ text: 'Page 3', link: 'en/page-3' },
|
||||||
|
],
|
||||||
|
'Another Section': [{ text: 'Page 4', link: 'en/page-4' }],
|
||||||
|
},
|
||||||
|
};
|
1
docs/src/env.d.ts
vendored
Normal file
1
docs/src/env.d.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/// <reference types="astro/client" />
|
10
docs/src/languages.ts
Normal file
10
docs/src/languages.ts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import { KNOWN_LANGUAGES, KNOWN_LANGUAGE_CODES } from './config';
|
||||||
|
export { KNOWN_LANGUAGES, KNOWN_LANGUAGE_CODES };
|
||||||
|
|
||||||
|
export const langPathRegex = /\/([a-z]{2}-?[A-Z]{0,2})\//;
|
||||||
|
|
||||||
|
export function getLanguageFromURL(pathname: string) {
|
||||||
|
const langCodeMatch = pathname.match(langPathRegex);
|
||||||
|
const langCode = langCodeMatch ? langCodeMatch[1] : 'en';
|
||||||
|
return langCode as typeof KNOWN_LANGUAGE_CODES[number];
|
||||||
|
}
|
139
docs/src/layouts/MainLayout.astro
Normal file
139
docs/src/layouts/MainLayout.astro
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
---
|
||||||
|
import HeadCommon from '../components/HeadCommon.astro';
|
||||||
|
import HeadSEO from '../components/HeadSEO.astro';
|
||||||
|
import Header from '../components/Header/Header.astro';
|
||||||
|
import PageContent from '../components/PageContent/PageContent.astro';
|
||||||
|
import LeftSidebar from '../components/LeftSidebar/LeftSidebar.astro';
|
||||||
|
import RightSidebar from '../components/RightSidebar/RightSidebar.astro';
|
||||||
|
import * as CONFIG from '../config';
|
||||||
|
import type { MarkdownHeading } from 'astro';
|
||||||
|
import Footer from '../components/Footer/Footer.astro';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
frontmatter: CONFIG.Frontmatter;
|
||||||
|
headings: MarkdownHeading[];
|
||||||
|
};
|
||||||
|
|
||||||
|
const { frontmatter, headings } = Astro.props as Props;
|
||||||
|
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
|
||||||
|
const currentPage = Astro.url.pathname;
|
||||||
|
const currentFile = `src/pages${currentPage.replace(/\/$/, '')}.md`;
|
||||||
|
const githubEditUrl = `${CONFIG.GITHUB_EDIT_URL}/${currentFile}`;
|
||||||
|
---
|
||||||
|
|
||||||
|
<html dir={frontmatter.dir ?? 'ltr'} lang={frontmatter.lang ?? 'en-us'} class="initial">
|
||||||
|
<head>
|
||||||
|
<HeadCommon />
|
||||||
|
<HeadSEO frontmatter={frontmatter} canonicalUrl={canonicalURL} />
|
||||||
|
<title>
|
||||||
|
{frontmatter.title ? `${frontmatter.title} 🚀 ${CONFIG.SITE.title}` : CONFIG.SITE.title}
|
||||||
|
</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
width: 100%;
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: var(--theme-navbar-height) 1fr;
|
||||||
|
--gutter: 0.5rem;
|
||||||
|
--doc-padding: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout {
|
||||||
|
display: grid;
|
||||||
|
grid-auto-flow: column;
|
||||||
|
grid-template-columns: minmax(var(--gutter), 1fr) minmax(0, var(--max-width)) minmax(
|
||||||
|
var(--gutter),
|
||||||
|
1fr
|
||||||
|
);
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-sidebar {
|
||||||
|
height: 100vh;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#grid-left {
|
||||||
|
position: fixed;
|
||||||
|
background-color: var(--theme-bg);
|
||||||
|
z-index: 10;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#grid-main {
|
||||||
|
padding: var(--doc-padding) var(--gutter);
|
||||||
|
grid-column: 2;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#grid-right {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 50em) {
|
||||||
|
.layout {
|
||||||
|
overflow: initial;
|
||||||
|
grid-template-columns: 20rem minmax(0, var(--max-width));
|
||||||
|
gap: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#grid-left {
|
||||||
|
display: flex;
|
||||||
|
padding-left: 2rem;
|
||||||
|
position: sticky;
|
||||||
|
grid-column: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 72em) {
|
||||||
|
.layout {
|
||||||
|
grid-template-columns: 20rem minmax(0, var(--max-width)) 18rem;
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#grid-right {
|
||||||
|
grid-column: 3;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style is:global>
|
||||||
|
.layout > * {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-sidebar-toggle {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-sidebar-toggle #grid-left {
|
||||||
|
display: block;
|
||||||
|
top: 2rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<Header currentPage={currentPage} />
|
||||||
|
<main class="layout">
|
||||||
|
<aside id="grid-left" class="grid-sidebar" title="Site Navigation">
|
||||||
|
<LeftSidebar currentPage={currentPage} />
|
||||||
|
</aside>
|
||||||
|
<div id="grid-main">
|
||||||
|
<PageContent frontmatter={frontmatter} headings={headings} githubEditUrl={githubEditUrl}>
|
||||||
|
<slot />
|
||||||
|
</PageContent>
|
||||||
|
</div>
|
||||||
|
<aside id="grid-right" class="grid-sidebar" title="Table of Contents">
|
||||||
|
<RightSidebar headings={headings} githubEditUrl={githubEditUrl} />
|
||||||
|
</aside>
|
||||||
|
</main>
|
||||||
|
<Footer path={currentFile} />
|
||||||
|
</body>
|
||||||
|
</html>
|
70
docs/src/pages/en/introduction.md
Normal file
70
docs/src/pages/en/introduction.md
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
---
|
||||||
|
title: Astro Reactive Library
|
||||||
|
description: Library homepage
|
||||||
|
layout: ../../layouts/MainLayout.astro
|
||||||
|
---
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
[](https://github.com/ayoayco/astro-reactive-library/actions/workflows/build-and-test.yml)
|
||||||
|
[](https://github.com/ayoayco/astro-reactive-library)
|
||||||
|
|
||||||
|
# Components and utilities for building reactive user interfaces 🔥
|
||||||
|
|
||||||
|
Let your data build your UI. Blazing-fast, reactive user interfaces with native [Astro](https://astro.build) components and architecture.
|
||||||
|
|
||||||
|
| Packages | Version | Docs | Description |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| [astro-reactive-form](https://github.com/ayoayco/astro-reactive-library/blob/main/packages/astro-reactive-form/README.md) | [](https://www.npmjs.com/package/astro-reactive-form) | 🛠 | generate a dynamic form which can be modified programatically |
|
||||||
|
| astro-reactive-validator | 🛠 | 🛠 | set of utilities for validating inputs |
|
||||||
|
| astro-reactive-datagrid | 🛠 | 🛠 | generate a dynamic datagrid or table of values |
|
||||||
|
|
||||||
|
# Running locally
|
||||||
|
|
||||||
|
We mainly use the `demo` app to see changes we make on the packages. Do the following to start hacking:
|
||||||
|
|
||||||
|
1. Fork the project then clone to your computer
|
||||||
|
|
||||||
|
```
|
||||||
|
git clone git@github.com:<your-user-name>/astro-reactive-library.git
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Go into the project directory
|
||||||
|
|
||||||
|
```
|
||||||
|
cd astro-reactive-library
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Install the node dependencies
|
||||||
|
|
||||||
|
```
|
||||||
|
npm i
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Run the demo application
|
||||||
|
|
||||||
|
```
|
||||||
|
npm start
|
||||||
|
```
|
||||||
|
|
||||||
|
5. Open the demo application on you browser. Browse to the address:
|
||||||
|
|
||||||
|
```
|
||||||
|
https://localhost:3000
|
||||||
|
```
|
||||||
|
|
||||||
|
6. To run the tests:
|
||||||
|
|
||||||
|
```
|
||||||
|
npm test
|
||||||
|
```
|
||||||
|
|
||||||
|
_[Please report issues and suggestions](https://github.com/ayoayco/astro-reactive-library/issues)_
|
||||||
|
|
||||||
|
# Contributors
|
||||||
|
|
||||||
|
<a href="https://github.com/ayoayco/astro-reactive-library/graphs/contributors">
|
||||||
|
<img src="https://contrib.rocks/image?repo=ayoayco/astro-reactive-library" />
|
||||||
|
</a>
|
||||||
|
|
||||||
|
👉 _[Join our contributors!](https://github.com/ayoayco/astro-reactive-library/blob/main/CONTRIBUTING.md)_
|
106
docs/src/pages/en/page-2.md
Normal file
106
docs/src/pages/en/page-2.md
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
---
|
||||||
|
title: Reactive Form
|
||||||
|
description: Lorem ipsum dolor sit amet - 2
|
||||||
|
layout: ../../layouts/MainLayout.astro
|
||||||
|
---
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
[](https://www.npmjs.com/package/astro-reactive-form)
|
||||||
|
[](https://www.npmjs.com/package/astro-reactive-form)
|
||||||
|
[](https://www.npmjs.com/package/astro-reactive-form)
|
||||||
|
[](https://www.npmjs.com/package/astro-reactive-form)
|
||||||
|
|
||||||
|
# Astro Reactive Form 🔥
|
||||||
|
|
||||||
|
Generate a dynamic form based on your data, and modify programatically.
|
||||||
|
|
||||||
|
The Reactive Form component for [Astro](https://astro.build) 🔥
|
||||||
|
|
||||||
|
_[All contributions are welcome.](https://github.com/ayoayco/astro-reactive-library/issues)_
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
In your Astro project:
|
||||||
|
|
||||||
|
```
|
||||||
|
npm i astro-reactive-form
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
Use in an Astro page:
|
||||||
|
|
||||||
|
```astro
|
||||||
|
---
|
||||||
|
import { FormControl, FormGroup } from "astro-reactive-form/core";
|
||||||
|
import Form from "astro-reactive-form";
|
||||||
|
|
||||||
|
// create a form group
|
||||||
|
const form = new FormGroup([
|
||||||
|
{
|
||||||
|
name: "username",
|
||||||
|
label: "Username",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "password",
|
||||||
|
label: "Password",
|
||||||
|
type: "password",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// set the name optionally
|
||||||
|
form.name = "Simple Form";
|
||||||
|
|
||||||
|
// you can insert a control at any point
|
||||||
|
form.controls.push(
|
||||||
|
new FormControl({
|
||||||
|
type: "checkbox",
|
||||||
|
name: "is-awesome",
|
||||||
|
label: "is Awesome?",
|
||||||
|
labelPosition: "right",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// you can get a FormControl object
|
||||||
|
const userNameControl = form.get("username");
|
||||||
|
|
||||||
|
// you can set values dynamically
|
||||||
|
userNameControl?.setValue("RAMOOOON");
|
||||||
|
form.get('is-awesome')?.setValue("checked");
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- the formGroups attribute takes an array of FormGroup-->
|
||||||
|
<Form formGroups={[form]} />
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
# Screenshots
|
||||||
|
|
||||||
|
Result of example above:
|
||||||
|
|
||||||
|
<img width="535" alt="Screen Shot 2022-10-01 at 7 29 00 PM" src="https://user-images.githubusercontent.com/4262489/193421174-5c604aca-7d16-4cd6-a7b1-f5b8752c838e.png">
|
||||||
|
|
||||||
|
Example of multiple form groups:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
# Future Plans
|
||||||
|
|
||||||
|
Currently this only supports very basic form creation, but the goal of the project is ambitious:
|
||||||
|
|
||||||
|
1. Validator library for common validation scenarios
|
||||||
|
1. Client-side validation
|
||||||
|
1. Server-side validation
|
||||||
|
1. validation hooks - onFocus, onBlur, onSubmit
|
||||||
|
1. Themes - unstyled, light mode, dark mode, compact, large
|
||||||
|
1. FormGroup class
|
||||||
|
1. `statusChanges` - observable that emits the form status when it changes
|
||||||
|
1. `valueChanges` - observable that emits the values of all controls when they change
|
||||||
|
1. FormControl class
|
||||||
|
1. `statusChanges` - observable that emits the control status when it changes
|
||||||
|
1. `valueChanges` - observable that emits the control value when it changes
|
||||||
|
1. `value` - property that reflects the control value
|
||||||
|
1. Documentation website
|
||||||
|
|
||||||
|
... and so much more
|
||||||
|
|
||||||
|
_All contributions are welcome. Let's make the fastest web form component powered by Astro_
|
37
docs/src/pages/en/page-3.md
Normal file
37
docs/src/pages/en/page-3.md
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
---
|
||||||
|
title: Page 3
|
||||||
|
description: Lorem ipsum dolor sit amet - 3
|
||||||
|
layout: ../../layouts/MainLayout.astro
|
||||||
|
---
|
||||||
|
|
||||||
|
This is a fully-featured page, written in Markdown!
|
||||||
|
|
||||||
|
## Section A
|
||||||
|
|
||||||
|
Lorem ipsum dolor sit amet, **consectetur adipiscing elit**. Sed ut tortor _suscipit_, posuere ante id, vulputate urna. Pellentesque molestie aliquam dui sagittis aliquet. Sed sed felis convallis, lacinia lorem sit amet, fermentum ex. Etiam hendrerit mauris at elementum egestas. Vivamus id gravida ante. Praesent consectetur fermentum turpis, quis blandit tortor feugiat in. Aliquam erat volutpat. In elementum purus et tristique ornare. Suspendisse sollicitudin dignissim est a ultrices. Pellentesque sed ipsum finibus, condimentum metus eget, sagittis elit. Sed id lorem justo. Vivamus in sem ac mi molestie ornare.
|
||||||
|
|
||||||
|
## Section B
|
||||||
|
|
||||||
|
Nam quam dolor, pellentesque sed odio euismod, feugiat tempus tellus. Quisque arcu velit, ultricies in faucibus sed, ultrices ac enim. Nunc eget dictum est. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam ex nisi, egestas mollis ultricies ut, laoreet suscipit libero. Nam condimentum molestie turpis. Sed vestibulum sagittis congue. Maecenas tristique enim et tincidunt tempor. Curabitur ac scelerisque nulla, in malesuada libero. Praesent eu tempus odio. Pellentesque aliquam ullamcorper quam at gravida. Sed non fringilla mauris. Aenean sit amet ultrices erat. Vestibulum congue venenatis tortor, nec suscipit tortor. Aenean pellentesque mauris eget tortor tincidunt pharetra.
|
||||||
|
|
||||||
|
## Section C
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
title: Markdown Page!
|
||||||
|
lang: en
|
||||||
|
layout: ~/layouts/MainLayout.astro
|
||||||
|
---
|
||||||
|
|
||||||
|
# Markdown example
|
||||||
|
|
||||||
|
This is a fully-featured page, written in Markdown!
|
||||||
|
|
||||||
|
## Section A
|
||||||
|
|
||||||
|
Lorem ipsum dolor sit amet, **consectetur adipiscing elit**. Sed ut tortor _suscipit_, posuere ante id, vulputate urna. Pellentesque molestie aliquam dui sagittis aliquet. Sed sed felis convallis, lacinia lorem sit amet, fermentum ex. Etiam hendrerit mauris at elementum egestas. Vivamus id gravida ante. Praesent consectetur fermentum turpis, quis blandit tortor feugiat in. Aliquam erat volutpat. In elementum purus et tristique ornare. Suspendisse sollicitudin dignissim est a ultrices. Pellentesque sed ipsum finibus, condimentum metus eget, sagittis elit. Sed id lorem justo. Vivamus in sem ac mi molestie ornare.
|
||||||
|
|
||||||
|
## Section B
|
||||||
|
|
||||||
|
Nam quam dolor, pellentesque sed odio euismod, feugiat tempus tellus. Quisque arcu velit, ultricies in faucibus sed, ultrices ac enim. Nunc eget dictum est. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam ex nisi, egestas mollis ultricies ut, laoreet suscipit libero. Nam condimentum molestie turpis. Sed vestibulum sagittis congue. Maecenas tristique enim et tincidunt tempor. Curabitur ac scelerisque nulla, in malesuada libero. Praesent eu tempus odio. Pellentesque aliquam ullamcorper quam at gravida. Sed non fringilla mauris. Aenean sit amet ultrices erat. Vestibulum congue venenatis tortor, nec suscipit tortor. Aenean pellentesque mauris eget tortor tincidunt pharetra.
|
||||||
|
```
|
37
docs/src/pages/en/page-4.md
Normal file
37
docs/src/pages/en/page-4.md
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
---
|
||||||
|
title: Page 4
|
||||||
|
description: Lorem ipsum dolor sit amet - 4
|
||||||
|
layout: ../../layouts/MainLayout.astro
|
||||||
|
---
|
||||||
|
|
||||||
|
This is a fully-featured page, written in Markdown!
|
||||||
|
|
||||||
|
## Section A
|
||||||
|
|
||||||
|
Lorem ipsum dolor sit amet, **consectetur adipiscing elit**. Sed ut tortor _suscipit_, posuere ante id, vulputate urna. Pellentesque molestie aliquam dui sagittis aliquet. Sed sed felis convallis, lacinia lorem sit amet, fermentum ex. Etiam hendrerit mauris at elementum egestas. Vivamus id gravida ante. Praesent consectetur fermentum turpis, quis blandit tortor feugiat in. Aliquam erat volutpat. In elementum purus et tristique ornare. Suspendisse sollicitudin dignissim est a ultrices. Pellentesque sed ipsum finibus, condimentum metus eget, sagittis elit. Sed id lorem justo. Vivamus in sem ac mi molestie ornare.
|
||||||
|
|
||||||
|
## Section B
|
||||||
|
|
||||||
|
Nam quam dolor, pellentesque sed odio euismod, feugiat tempus tellus. Quisque arcu velit, ultricies in faucibus sed, ultrices ac enim. Nunc eget dictum est. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam ex nisi, egestas mollis ultricies ut, laoreet suscipit libero. Nam condimentum molestie turpis. Sed vestibulum sagittis congue. Maecenas tristique enim et tincidunt tempor. Curabitur ac scelerisque nulla, in malesuada libero. Praesent eu tempus odio. Pellentesque aliquam ullamcorper quam at gravida. Sed non fringilla mauris. Aenean sit amet ultrices erat. Vestibulum congue venenatis tortor, nec suscipit tortor. Aenean pellentesque mauris eget tortor tincidunt pharetra.
|
||||||
|
|
||||||
|
## Section C
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
title: Markdown Page!
|
||||||
|
lang: en
|
||||||
|
layout: ~/layouts/MainLayout.astro
|
||||||
|
---
|
||||||
|
|
||||||
|
# Markdown example
|
||||||
|
|
||||||
|
This is a fully-featured page, written in Markdown!
|
||||||
|
|
||||||
|
## Section A
|
||||||
|
|
||||||
|
Lorem ipsum dolor sit amet, **consectetur adipiscing elit**. Sed ut tortor _suscipit_, posuere ante id, vulputate urna. Pellentesque molestie aliquam dui sagittis aliquet. Sed sed felis convallis, lacinia lorem sit amet, fermentum ex. Etiam hendrerit mauris at elementum egestas. Vivamus id gravida ante. Praesent consectetur fermentum turpis, quis blandit tortor feugiat in. Aliquam erat volutpat. In elementum purus et tristique ornare. Suspendisse sollicitudin dignissim est a ultrices. Pellentesque sed ipsum finibus, condimentum metus eget, sagittis elit. Sed id lorem justo. Vivamus in sem ac mi molestie ornare.
|
||||||
|
|
||||||
|
## Section B
|
||||||
|
|
||||||
|
Nam quam dolor, pellentesque sed odio euismod, feugiat tempus tellus. Quisque arcu velit, ultricies in faucibus sed, ultrices ac enim. Nunc eget dictum est. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam ex nisi, egestas mollis ultricies ut, laoreet suscipit libero. Nam condimentum molestie turpis. Sed vestibulum sagittis congue. Maecenas tristique enim et tincidunt tempor. Curabitur ac scelerisque nulla, in malesuada libero. Praesent eu tempus odio. Pellentesque aliquam ullamcorper quam at gravida. Sed non fringilla mauris. Aenean sit amet ultrices erat. Vestibulum congue venenatis tortor, nec suscipit tortor. Aenean pellentesque mauris eget tortor tincidunt pharetra.
|
||||||
|
```
|
5
docs/src/pages/index.astro
Normal file
5
docs/src/pages/index.astro
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<script is:inline>
|
||||||
|
// Redirect your homepage to the first page of documentation.
|
||||||
|
// If you have a landing page, remove this script and add it here!
|
||||||
|
window.location.pathname = `/en/introduction`;
|
||||||
|
</script>
|
382
docs/src/styles/index.css
Normal file
382
docs/src/styles/index.css
Normal file
|
@ -0,0 +1,382 @@
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Global focus outline reset */
|
||||||
|
*:focus:not(:focus-visible) {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--user-font-scale: 1rem - 16px;
|
||||||
|
--max-width: calc(100% - 1rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 50em) {
|
||||||
|
:root {
|
||||||
|
--max-width: 46em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 100vh;
|
||||||
|
font-family: var(--font-body);
|
||||||
|
font-size: 1rem;
|
||||||
|
font-size: clamp(0.9rem, 0.75rem + 0.375vw + var(--user-font-scale), 1rem);
|
||||||
|
line-height: 1.5;
|
||||||
|
max-width: 100vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content > section > * + * {
|
||||||
|
margin-top: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content > section > :first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Typography */
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
max-width: 40ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
:is(h2, h3):not(:first-child) {
|
||||||
|
margin-top: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
:is(h4, h5, h6):not(:first-child) {
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 3.25rem;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
font-size: 1.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h5 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
line-height: 1.65em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content ul {
|
||||||
|
line-height: 1.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
p,
|
||||||
|
.content ul {
|
||||||
|
color: var(--theme-text-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
small,
|
||||||
|
.text_small {
|
||||||
|
font-size: 0.833rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: var(--theme-text-accent);
|
||||||
|
font-weight: 400;
|
||||||
|
text-underline-offset: 0.08em;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
article > section :is(ul, ol) > * + * {
|
||||||
|
margin-top: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
article > section nav :is(ul, ol) > * + * {
|
||||||
|
margin-top: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
article > section li > :is(p, pre, blockquote):not(:first-child) {
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
article > section :is(ul, ol) {
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
article > section nav :is(ul, ol) {
|
||||||
|
padding-left: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
article > section nav {
|
||||||
|
margin-top: 1rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
article > section ::marker {
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--theme-text-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
article > section iframe {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
aspect-ratio: 16 / 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
a > code {
|
||||||
|
position: relative;
|
||||||
|
color: var(--theme-text-accent);
|
||||||
|
background: transparent;
|
||||||
|
text-underline-offset: var(--padding-block);
|
||||||
|
}
|
||||||
|
|
||||||
|
a > code::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
display: block;
|
||||||
|
background: var(--theme-accent);
|
||||||
|
opacity: var(--theme-accent-opacity);
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover,
|
||||||
|
a:focus {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:focus {
|
||||||
|
outline: 2px solid currentColor;
|
||||||
|
outline-offset: 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
strong {
|
||||||
|
font-weight: 600;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Supporting Content */
|
||||||
|
|
||||||
|
code {
|
||||||
|
--border-radius: 3px;
|
||||||
|
--padding-block: 0.2rem;
|
||||||
|
--padding-inline: 0.33rem;
|
||||||
|
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 0.85em;
|
||||||
|
color: inherit;
|
||||||
|
background-color: var(--theme-code-inline-bg);
|
||||||
|
padding: var(--padding-block) var(--padding-inline);
|
||||||
|
margin: calc(var(--padding-block) * -1) -0.125em;
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.astro-code > code {
|
||||||
|
all: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre > code {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
table,
|
||||||
|
pre {
|
||||||
|
position: relative;
|
||||||
|
--padding-block: 1rem;
|
||||||
|
--padding-inline: 2rem;
|
||||||
|
padding: var(--padding-block) var(--padding-inline);
|
||||||
|
padding-right: calc(var(--padding-inline) * 2);
|
||||||
|
margin-left: calc(var(--padding-inline) * -1);
|
||||||
|
margin-right: calc(var(--padding-inline) * -1);
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
|
||||||
|
line-height: 1.5;
|
||||||
|
font-size: 0.85em;
|
||||||
|
overflow-y: hidden;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
padding: var(--padding-block) 0;
|
||||||
|
margin: 0;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Zebra striping */
|
||||||
|
tr:nth-of-type(odd) {
|
||||||
|
background: var(--theme-bg-hover);
|
||||||
|
}
|
||||||
|
th {
|
||||||
|
background: var(--color-black);
|
||||||
|
color: var(--theme-color);
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
td,
|
||||||
|
th {
|
||||||
|
padding: 6px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background-color: var(--theme-code-bg);
|
||||||
|
color: var(--theme-code-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote code {
|
||||||
|
background-color: var(--theme-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 37.75em) {
|
||||||
|
pre {
|
||||||
|
--padding-inline: 1.25rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
margin: 2rem 0;
|
||||||
|
padding: 1.25em 1.5rem;
|
||||||
|
border-left: 3px solid var(--theme-text-light);
|
||||||
|
background-color: var(--theme-bg-offset);
|
||||||
|
border-radius: 0 0.25rem 0.25rem 0;
|
||||||
|
line-height: 1.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-items: center;
|
||||||
|
gap: 0.25em;
|
||||||
|
padding: 0.33em 0.67em;
|
||||||
|
border: 0;
|
||||||
|
background: var(--theme-bg);
|
||||||
|
display: flex;
|
||||||
|
font-size: 1rem;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.25em;
|
||||||
|
border-radius: 99em;
|
||||||
|
color: var(--theme-text);
|
||||||
|
background-color: var(--theme-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
h2.heading {
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 700;
|
||||||
|
padding: 0.1rem 1rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading-link {
|
||||||
|
font-size: 1rem;
|
||||||
|
padding: 0.1rem 0 0.1rem 1rem;
|
||||||
|
border-left: 4px solid var(--theme-divider);
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading-link:hover,
|
||||||
|
.heading-link:focus {
|
||||||
|
border-left-color: var(--theme-accent);
|
||||||
|
color: var(--theme-accent);
|
||||||
|
}
|
||||||
|
.heading-link:focus-within {
|
||||||
|
color: var(--theme-text-light);
|
||||||
|
border-left-color: hsla(var(--color-gray-40), 1);
|
||||||
|
}
|
||||||
|
.heading-link svg {
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
.heading-link:hover svg {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
.heading-link a {
|
||||||
|
display: inline-flex;
|
||||||
|
gap: 0.5em;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.15em 0 0.15em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading-link.depth-3 {
|
||||||
|
padding-left: 2rem;
|
||||||
|
}
|
||||||
|
.heading-link.depth-4 {
|
||||||
|
padding-left: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading-link a {
|
||||||
|
font: inherit;
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Screenreader Only Text */
|
||||||
|
.sr-only {
|
||||||
|
position: absolute;
|
||||||
|
width: 1px;
|
||||||
|
height: 1px;
|
||||||
|
padding: 0;
|
||||||
|
margin: -1px;
|
||||||
|
overflow: hidden;
|
||||||
|
clip: rect(0, 0, 0, 0);
|
||||||
|
white-space: nowrap;
|
||||||
|
border-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.focus\:not-sr-only:focus,
|
||||||
|
.focus\:not-sr-only:focus-visible {
|
||||||
|
position: static;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
overflow: visible;
|
||||||
|
clip: auto;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
:target {
|
||||||
|
scroll-margin: calc(var(--theme-sidebar-offset, 5rem) + 2rem) 0 2rem;
|
||||||
|
}
|
125
docs/src/styles/theme.css
Normal file
125
docs/src/styles/theme.css
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
:root {
|
||||||
|
--font-fallback: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif,
|
||||||
|
Apple Color Emoji, Segoe UI Emoji;
|
||||||
|
--font-body: system-ui, var(--font-fallback);
|
||||||
|
--font-mono: 'IBM Plex Mono', Consolas, 'Andale Mono WT', 'Andale Mono', 'Lucida Console',
|
||||||
|
'Lucida Sans Typewriter', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Liberation Mono',
|
||||||
|
'Nimbus Mono L', Monaco, 'Courier New', Courier, monospace;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Variables with --color-base prefix define
|
||||||
|
* the hue, and saturation values to be used for
|
||||||
|
* hsla colors.
|
||||||
|
*
|
||||||
|
* ex:
|
||||||
|
*
|
||||||
|
* --color-base-{color}: {hue}, {saturation};
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
--color-base-white: 0, 0%;
|
||||||
|
--color-base-black: 240, 100%;
|
||||||
|
--color-base-gray: 215, 14%;
|
||||||
|
--color-base-blue: 212, 100%;
|
||||||
|
--color-base-blue-dark: 212, 72%;
|
||||||
|
--color-base-green: 158, 79%;
|
||||||
|
--color-base-orange: 22, 100%;
|
||||||
|
--color-base-purple: 269, 79%;
|
||||||
|
--color-base-red: 351, 100%;
|
||||||
|
--color-base-yellow: 41, 100%;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Color palettes are made using --color-base
|
||||||
|
* variables, along with a lightness value to
|
||||||
|
* define different variants.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
--color-gray-5: var(--color-base-gray), 5%;
|
||||||
|
--color-gray-10: var(--color-base-gray), 10%;
|
||||||
|
--color-gray-20: var(--color-base-gray), 20%;
|
||||||
|
--color-gray-30: var(--color-base-gray), 30%;
|
||||||
|
--color-gray-40: var(--color-base-gray), 40%;
|
||||||
|
--color-gray-50: var(--color-base-gray), 50%;
|
||||||
|
--color-gray-60: var(--color-base-gray), 60%;
|
||||||
|
--color-gray-70: var(--color-base-gray), 70%;
|
||||||
|
--color-gray-80: var(--color-base-gray), 80%;
|
||||||
|
--color-gray-90: var(--color-base-gray), 90%;
|
||||||
|
--color-gray-95: var(--color-base-gray), 95%;
|
||||||
|
|
||||||
|
--color-blue: var(--color-base-blue), 61%;
|
||||||
|
--color-blue-dark: var(--color-base-blue-dark), 39%;
|
||||||
|
--color-green: var(--color-base-green), 42%;
|
||||||
|
--color-orange: var(--color-base-orange), 50%;
|
||||||
|
--color-purple: var(--color-base-purple), 54%;
|
||||||
|
--color-red: var(--color-base-red), 54%;
|
||||||
|
--color-yellow: var(--color-base-yellow), 59%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
color-scheme: light;
|
||||||
|
--theme-accent: hsla(var(--color-blue), 1);
|
||||||
|
--theme-text-accent: hsla(var(--color-blue), 1);
|
||||||
|
--theme-accent-opacity: 0.15;
|
||||||
|
--theme-divider: hsla(var(--color-gray-95), 1);
|
||||||
|
--theme-text: hsla(var(--color-gray-10), 1);
|
||||||
|
--theme-text-light: hsla(var(--color-gray-40), 1);
|
||||||
|
/* @@@: not used anywhere */
|
||||||
|
--theme-text-lighter: hsla(var(--color-gray-80), 1);
|
||||||
|
--theme-bg: hsla(var(--color-base-white), 100%, 1);
|
||||||
|
--theme-bg-hover: hsla(var(--color-gray-95), 1);
|
||||||
|
--theme-bg-offset: hsla(var(--color-gray-90), 1);
|
||||||
|
--theme-bg-accent: hsla(var(--color-blue), var(--theme-accent-opacity));
|
||||||
|
--theme-code-inline-bg: hsla(var(--color-gray-95), 1);
|
||||||
|
--theme-code-inline-text: var(--theme-text);
|
||||||
|
--theme-code-bg: hsla(217, 19%, 27%, 1);
|
||||||
|
--theme-code-text: hsla(var(--color-gray-95), 1);
|
||||||
|
--theme-navbar-bg: hsla(var(--color-base-white), 100%, 1);
|
||||||
|
--theme-navbar-height: 6rem;
|
||||||
|
--theme-selection-color: hsla(var(--color-blue), 1);
|
||||||
|
--theme-selection-bg: hsla(var(--color-blue), var(--theme-accent-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: var(--theme-bg);
|
||||||
|
color: var(--theme-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.theme-dark {
|
||||||
|
color-scheme: dark;
|
||||||
|
--theme-accent-opacity: 0.15;
|
||||||
|
--theme-accent: hsla(var(--color-blue), 1);
|
||||||
|
--theme-text-accent: hsla(var(--color-blue), 1);
|
||||||
|
--theme-divider: hsla(var(--color-gray-10), 1);
|
||||||
|
--theme-text: hsla(var(--color-gray-90), 1);
|
||||||
|
--theme-text-light: hsla(var(--color-gray-80), 1);
|
||||||
|
|
||||||
|
/* @@@: not used anywhere */
|
||||||
|
--theme-text-lighter: hsla(var(--color-gray-40), 1);
|
||||||
|
--theme-bg: hsla(215, 28%, 17%, 1);
|
||||||
|
--theme-bg-hover: hsla(var(--color-gray-40), 1);
|
||||||
|
--theme-bg-offset: hsla(var(--color-gray-5), 1);
|
||||||
|
--theme-code-inline-bg: hsla(var(--color-gray-10), 1);
|
||||||
|
--theme-code-inline-text: hsla(var(--color-base-white), 100%, 1);
|
||||||
|
--theme-code-bg: hsla(var(--color-gray-5), 1);
|
||||||
|
--theme-code-text: hsla(var(--color-base-white), 100%, 1);
|
||||||
|
--theme-navbar-bg: hsla(215, 28%, 17%, 1);
|
||||||
|
--theme-selection-color: hsla(var(--color-base-white), 100%, 1);
|
||||||
|
--theme-selection-bg: hsla(var(--color-purple), var(--theme-accent-opacity));
|
||||||
|
|
||||||
|
/* DocSearch [Algolia] */
|
||||||
|
--docsearch-modal-background: var(--theme-bg);
|
||||||
|
--docsearch-searchbox-focus-background: var(--theme-divider);
|
||||||
|
--docsearch-footer-background: var(--theme-divider);
|
||||||
|
--docsearch-text-color: var(--theme-text);
|
||||||
|
--docsearch-hit-background: var(--theme-divider);
|
||||||
|
--docsearch-hit-shadow: none;
|
||||||
|
--docsearch-hit-color: var(--theme-text);
|
||||||
|
--docsearch-footer-shadow: inset 0 2px 10px #000;
|
||||||
|
--docsearch-modal-shadow: inset 0 0 8px #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
::selection {
|
||||||
|
color: var(--theme-selection-color);
|
||||||
|
background-color: var(--theme-selection-bg);
|
||||||
|
}
|
7
docs/tsconfig.json
Normal file
7
docs/tsconfig.json
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"extends": "astro/tsconfigs/base",
|
||||||
|
"compilerOptions": {
|
||||||
|
"jsx": "preserve",
|
||||||
|
"skipLibCheck": true
|
||||||
|
}
|
||||||
|
}
|
880
package-lock.json
generated
880
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -30,6 +30,7 @@
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"demo",
|
"demo",
|
||||||
"packages/astro-reactive-form",
|
"packages/astro-reactive-form",
|
||||||
"packages/astro-reactive-validator"
|
"packages/astro-reactive-validator",
|
||||||
|
"docs"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue