chore(apps): Setup prettier + eslint for all our apps (#254)

* chore(apps): setup prettier + eslint for all our apps

* fix(docs): Fixed the use of implicit any type

* chore(apps): Added .eslintignore files
This commit is contained in:
Lalit 2023-01-14 15:10:40 +05:30 committed by GitHub
parent 0abe83aea9
commit f79ce72a1c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
57 changed files with 1349 additions and 1265 deletions

2
apps/demo/.eslintignore Normal file
View file

@ -0,0 +1,2 @@
dist
node_modules

5
apps/demo/.eslintrc.cjs Normal file
View file

@ -0,0 +1,5 @@
/** @type {import("@types/eslint").Linter.Config} */
module.exports = {
root: true,
extends: ['@astro-reactive/eslint-config-custom'],
};

24
apps/demo/.prettierrc.cjs Normal file
View file

@ -0,0 +1,24 @@
/** @type {import("@types/prettier").Options} */
module.exports = {
printWidth: 100,
semi: true,
singleQuote: true,
tabWidth: 2,
trailingComma: 'es5',
useTabs: true,
plugins: ['../../node_modules/prettier-plugin-astro'],
overrides: [
{
files: '*.astro',
options: {
parser: 'astro',
},
},
{
files: ['.*', '*.json', '*.md', '*.toml', '*.yml'],
options: {
useTabs: false,
},
},
],
};

View file

@ -5,4 +5,3 @@
Start the dev server by running: `npm start` Start the dev server by running: `npm start`
👉 _[Join our contributors!](https://github.com/astro-reactive/astro-reactive/blob/main/CONTRIBUTING.md)_ 👉 _[Join our contributors!](https://github.com/astro-reactive/astro-reactive/blob/main/CONTRIBUTING.md)_

View file

@ -1,4 +1,4 @@
import { defineConfig } from "astro/config"; import { defineConfig } from 'astro/config';
// https://astro.build/config // https://astro.build/config
export default defineConfig({}); export default defineConfig({});

View file

@ -12,10 +12,12 @@
"build": "astro build", "build": "astro build",
"preview": "astro preview", "preview": "astro preview",
"astro": "astro", "astro": "astro",
"format": "prettier -w .",
"lint": "eslint . --ext .ts,.js",
"lint:fix": "eslint --fix . --ext .ts,.js",
"clean": "rimraf node_modules .turbo dist" "clean": "rimraf node_modules .turbo dist"
}, },
"dependencies": { "dependencies": {
"@astro-reactive/tsconfig": "*",
"@astro-reactive/form": "*", "@astro-reactive/form": "*",
"@astro-reactive/validator": "*", "@astro-reactive/validator": "*",
"astro": "^1.6.5" "astro": "^1.6.5"
@ -31,7 +33,13 @@
}, },
"homepage": "https://github.com/astro-reactive/astro-reactive#readme", "homepage": "https://github.com/astro-reactive/astro-reactive#readme",
"devDependencies": { "devDependencies": {
"@astro-reactive/eslint-config-custom": "*",
"@astro-reactive/tsconfig": "*",
"@types/eslint": "^8.4.10",
"@types/prettier": "^2.7.2",
"eslint": "^8.31.0",
"prettier": "^2.8.3",
"prettier-plugin-astro": "^0.7.2",
"rimraf": "^3.0.2" "rimraf": "^3.0.2"
} }
} }

View file

@ -1,30 +1,30 @@
--- ---
import Nav from "./Nav.astro"; import Nav from './Nav.astro';
export interface Props { export interface Props {
title: string; title: string;
theme?: "dark" | "light"; theme?: 'dark' | 'light';
} }
const { theme = "light", title } = Astro.props; const { theme = 'light', title } = Astro.props;
--- ---
<html lang="en" class={theme}> <html lang="en" class={theme}>
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<link rel="icon" type="image/x-icon" href="/favicon.ico" /> <link rel="icon" type="image/x-icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width" /> <meta name="viewport" content="width=device-width" />
<meta name="generator" content={Astro.generator} /> <meta name="generator" content={Astro.generator} />
<title>{title} | Astro Reactive Demo</title> <title>{title} | Astro Reactive Demo</title>
</head> </head>
<body class={theme}> <body class={theme}>
<Nav /> <Nav />
<h1>{title}</h1> <h1>{title}</h1>
<slot /> <slot />
</body> </body>
<style> <style>
html.dark, html.dark,
body.dark { body.dark {
color-scheme: dark; color-scheme: dark;
} }
</style> </style>
</html> </html>

View file

@ -1,25 +1,25 @@
--- ---
const links = [ const links = [
{ label: "Home", url: "/" }, { label: 'Home', url: '/' },
{ label: "Pizza Delivery", url: "/pizza-delivery" }, { label: 'Pizza Delivery', url: '/pizza-delivery' },
{ label: "Job Application", url: "/job-application" }, { label: 'Job Application', url: '/job-application' },
{ label: "Docs Examples", url: "/examples" }, { label: 'Docs Examples', url: '/examples' },
{ label: "Experimental", url: "/experimental" }, { label: 'Experimental', url: '/experimental' },
]; ];
--- ---
<nav> <nav>
{links.map((link) => <a href={link.url}>{link.label}</a>)} {links.map((link) => <a href={link.url}>{link.label}</a>)}
</nav> </nav>
<style> <style>
nav a::after { nav a::after {
content: " | "; content: ' | ';
} }
nav a { nav a {
text-decoration: none; text-decoration: none;
} }
nav a:hover { nav a:hover {
text-decoration: underline; text-decoration: underline;
} }
</style> </style>

View file

@ -1,69 +1,69 @@
--- ---
import type { Submit } from "@astro-reactive/common"; import type { Submit } from '@astro-reactive/common';
import Form, { FormGroup } from "@astro-reactive/form"; import Form, { FormGroup } from '@astro-reactive/form';
import Layout from "../../components/Layout.astro"; import Layout from '../../components/Layout.astro';
const simpleForm = new FormGroup([ const simpleForm = new FormGroup([
{ {
name: "username", name: 'username',
label: "Username", label: 'Username',
value: "awesome_dev", value: 'awesome_dev',
}, },
{ {
name: "comment", name: 'comment',
label: "Feedback", label: 'Feedback',
type: "textarea", type: 'textarea',
value: "Nice!", value: 'Nice!',
}, },
{ {
name: "size", name: 'size',
label: "Size", label: 'Size',
type: "dropdown", type: 'dropdown',
options: ["S", "M", "L", "XL", "XXL"], options: ['S', 'M', 'L', 'XL', 'XXL'],
placeholder: "-- Please choose an option --", placeholder: '-- Please choose an option --',
}, },
]); ]);
const nameForm = new FormGroup( const nameForm = new FormGroup(
[ [
{ {
name: "firstName", name: 'firstName',
label: "First Name", label: 'First Name',
value: "John", value: 'John',
}, },
{ {
name: "lastName", name: 'lastName',
label: "Last Name", label: 'Last Name',
value: "Doe", value: 'Doe',
}, },
], ],
"Name" 'Name'
); );
const skills = new FormGroup( const skills = new FormGroup(
[ [
{ {
name: "JavaScript", name: 'JavaScript',
type: "checkbox", type: 'checkbox',
label: "JavaScript", label: 'JavaScript',
}, },
{ {
name: "TypeScript", name: 'TypeScript',
type: "checkbox", type: 'checkbox',
label: "TypeScript", label: 'TypeScript',
}, },
{ {
name: "React", name: 'React',
type: "checkbox", type: 'checkbox',
label: "React", label: 'React',
}, },
{ {
name: "Vue", name: 'Vue',
type: "checkbox", type: 'checkbox',
label: "Vue", label: 'Vue',
}, },
], ],
"Skills" 'Skills'
); );
/** /**
@ -71,15 +71,15 @@ const skills = new FormGroup(
*/ */
const submitControl: Submit = { const submitControl: Submit = {
name: "submit", name: 'submit',
type: "submit", type: 'submit',
}; };
--- ---
<Layout title="Form API examples"> <Layout title="Form API examples">
<h2>Simple Form</h2> <h2>Simple Form</h2>
<Form formGroups={simpleForm} submitControl={submitControl} /> <Form formGroups={simpleForm} submitControl={submitControl} />
<h2>Form with nested form groups</h2> <h2>Form with nested form groups</h2>
<Form formGroups={[nameForm, skills]} /> <Form formGroups={[nameForm, skills]} />
</Layout> </Layout>

View file

@ -1,9 +1,9 @@
--- ---
import Layout from "../../components/Layout.astro"; import Layout from '../../components/Layout.astro';
--- ---
<Layout title="Docs Examples"> <Layout title="Docs Examples">
<ul> <ul>
<li><a href="./examples/form-component">Form Component</a></li> <li><a href="./examples/form-component">Form Component</a></li>
</ul> </ul>
</Layout> </Layout>

View file

@ -1,23 +1,23 @@
--- ---
import Layout from "../../components/Layout.astro"; import Layout from '../../components/Layout.astro';
const Counter = { const Counter = {
count: 0, count: 0,
increment() { increment() {
this.count++; this.count++;
}, },
decrement() { decrement() {
this.count--; this.count--;
}, },
}; };
--- ---
<Layout title="Hyperdrive Experiment"> <Layout title="Hyperdrive Experiment">
<!-- PROBLEM STATEMENT <!-- PROBLEM STATEMENT
This is the problem that `hyperdrive` is trying to solve. This is the problem that `hyperdrive` is trying to solve.
After this is rendered in the server, the Counter object is not serialized. After this is rendered in the server, the Counter object is not serialized.
When the HTML reaches the browser, it has no idea what Counter is. When the HTML reaches the browser, it has no idea what Counter is.
--> -->
<button onclick="Counter.increment()"> <button onclick="Counter.increment()">
{Counter.count} {Counter.count}
</button> </button>
</Layout> </Layout>

View file

@ -1,9 +1,9 @@
--- ---
import Layout from "../../components/Layout.astro"; import Layout from '../../components/Layout.astro';
--- ---
<Layout title="Experimental Demos"> <Layout title="Experimental Demos">
<ul> <ul>
<li><a href="./experimental/hyperdrive">Hyperdrive</a></li> <li><a href="./experimental/hyperdrive">Hyperdrive</a></li>
</ul> </ul>
</Layout> </Layout>

View file

@ -1,116 +1,112 @@
--- ---
import Form, { import Form, { ControlConfig, FormGroup, FormControl } from '@astro-reactive/form';
ControlConfig, import type { Submit } from '@astro-reactive/common/types';
FormGroup, import { Validators } from '@astro-reactive/validator';
FormControl, import Layout from '../components/Layout.astro';
} from "@astro-reactive/form";
import type { Submit } from "@astro-reactive/common/types";
import { Validators } from "@astro-reactive/validator";
import Layout from "../components/Layout.astro";
const form = new FormGroup([ const form = new FormGroup([
{ {
name: "username", name: 'username',
label: "Username", label: 'Username',
validators: [ validators: [
{ {
validator: Validators.required, validator: Validators.required,
category: "info", category: 'info',
}, },
], ],
}, },
{ {
name: "email", name: 'email',
label: "Email", label: 'Email',
validators: [ validators: [
{ validator: Validators.required }, { validator: Validators.required },
{ validator: Validators.email, category: "warn" }, { validator: Validators.email, category: 'warn' },
], ],
}, },
{ {
name: "password", name: 'password',
label: "Password", label: 'Password',
type: "password", type: 'password',
validators: [Validators.required, Validators.minLength(8)], validators: [Validators.required, Validators.minLength(8)],
}, },
{ {
name: "rating", name: 'rating',
label: "Rating", label: 'Rating',
type: "radio", type: 'radio',
value: "5", value: '5',
options: ["1", "2", "3", "4", "5"], options: ['1', '2', '3', '4', '5'],
}, },
{ {
name: "agreement", name: 'agreement',
label: "Agreement", label: 'Agreement',
type: "radio", type: 'radio',
value: "yes", value: 'yes',
options: [ options: [
{ label: "Agree", value: "yes" }, { label: 'Agree', value: 'yes' },
{ label: "Disagree", value: "no" }, { label: 'Disagree', value: 'no' },
], ],
}, },
{ {
name: "size", name: 'size',
label: "Size", label: 'Size',
type: "dropdown", type: 'dropdown',
options: ["S", "M", "L", "XL", "XXL"], options: ['S', 'M', 'L', 'XL', 'XXL'],
placeholder: "-- Please choose an option --", placeholder: '-- Please choose an option --',
}, },
{ {
name: "comment", name: 'comment',
label: "Feedback", label: 'Feedback',
type: "textarea", type: 'textarea',
value: "Nice!", value: 'Nice!',
}, },
{ {
name: "terms", name: 'terms',
label: "Terms and Conditions", label: 'Terms and Conditions',
type: "checkbox", type: 'checkbox',
validators: [Validators.requiredChecked], validators: [Validators.requiredChecked],
}, },
]); ]);
form.name = "Simple Form"; form.name = 'Simple Form';
const config: ControlConfig = { const config: ControlConfig = {
type: "checkbox", type: 'checkbox',
name: "is-awesome", name: 'is-awesome',
label: "is Awesome?", label: 'is Awesome?',
}; };
// insert a control // insert a control
form.controls.push(new FormControl(config)); form.controls.push(new FormControl(config));
// get the FormControl object // get the FormControl object
const userNameControl = form.get("username"); const userNameControl = form.get('username');
// set values dynamically // set values dynamically
userNameControl?.setValue("RAMOOOON"); userNameControl?.setValue('RAMOOOON');
form.get("is-awesome")?.setValue("checked"); form.get('is-awesome')?.setValue('checked');
// setting an invalid value will cause errors as server-rendered // setting an invalid value will cause errors as server-rendered
form.get("email")?.setValue("invalid-email"); form.get('email')?.setValue('invalid-email');
// switch between light and dark mode // switch between light and dark mode
const title = "Form Demo"; const title = 'Form Demo';
const theme = "dark"; const theme = 'dark';
const submit: Submit = { const submit: Submit = {
name: "submit", name: 'submit',
type: "submit", type: 'submit',
value: "Let's go!", value: "Let's go!",
}; };
--- ---
<Layout title={title} theme={theme}> <Layout title={title} theme={theme}>
<Form <Form
validateOnLoad validateOnLoad
showValidationHints showValidationHints
formGroups={form} formGroups={form}
theme={theme} theme={theme}
submitControl={submit} submitControl={submit}
action="https://localhost" action="https://localhost"
method="post" method="post"
/> />
</Layout> </Layout>

View file

@ -1,127 +1,111 @@
--- ---
import Form, { import Form, { ControlConfig, FormControl, FormGroup } from '@astro-reactive/form';
ControlConfig, import { Validators } from '@astro-reactive/validator';
FormControl, import type { Submit } from '@astro-reactive/common';
FormGroup, import Layout from '../components/Layout.astro';
} from "@astro-reactive/form";
import { Validators } from "@astro-reactive/validator";
import type { Submit } from "@astro-reactive/common";
import Layout from "../components/Layout.astro";
const infoForm = new FormGroup([ const infoForm = new FormGroup([
{ {
name: "firstName", name: 'firstName',
label: "First Name", label: 'First Name',
placeholder: "ex. John", placeholder: 'ex. John',
validators: [Validators.required], validators: [Validators.required],
}, },
{ {
name: "lastName", name: 'lastName',
label: "Last Name", label: 'Last Name',
placeholder: "ex. Doe", placeholder: 'ex. Doe',
validators: [Validators.required], validators: [Validators.required],
}, },
{ {
name: "email", name: 'email',
label: "Email", label: 'Email',
placeholder: "ex. john.doe@email.com", placeholder: 'ex. john.doe@email.com',
validators: [Validators.email, Validators.required], validators: [Validators.email, Validators.required],
}, },
{ {
name: "whyHire", name: 'whyHire',
label: "Why should we hire you?", label: 'Why should we hire you?',
}, },
{ {
name: "country", name: 'country',
label: "Country of Residence", label: 'Country of Residence',
type: "dropdown", type: 'dropdown',
options: [ options: ['U.S.A', 'Canada', 'Mexico', 'Cuba', 'Guatamala', 'Greenland', 'Haiti'],
"U.S.A", placeholder: 'Choose Your Country',
"Canada", },
"Mexico", {
"Cuba", name: 'eligible',
"Guatamala", label: 'Are you eligible to work?',
"Greenland", type: 'radio',
"Haiti", options: [
], { label: 'Yes', value: 'yes' },
placeholder: "Choose Your Country", { label: 'No', value: 'no' },
}, ],
{ },
name: "eligible",
label: "Are you eligible to work?",
type: "radio",
options: [
{ label: "Yes", value: "yes" },
{ label: "No", value: "no" },
],
},
]); ]);
const skillsForm = new FormGroup([ const skillsForm = new FormGroup([
{ {
name: "js", name: 'js',
label: "Javascript", label: 'Javascript',
type: "checkbox", type: 'checkbox',
}, },
{ {
name: "java", name: 'java',
label: "Java", label: 'Java',
type: "checkbox", type: 'checkbox',
}, },
{ {
name: "astro", name: 'astro',
label: "Astro", label: 'Astro',
type: "checkbox", type: 'checkbox',
}, },
{ {
name: "cpp", name: 'cpp',
label: "C/C++", label: 'C/C++',
type: "checkbox", type: 'checkbox',
}, },
{ {
name: "sql", name: 'sql',
label: "SQL", label: 'SQL',
type: "checkbox", type: 'checkbox',
}, },
{ {
name: "devops", name: 'devops',
label: "DevOps", label: 'DevOps',
type: "checkbox", type: 'checkbox',
}, },
]); ]);
const resume: ControlConfig = { const resume: ControlConfig = {
name: "resume", name: 'resume',
label: "Upload Resume", label: 'Upload Resume',
type: "file", type: 'file',
}; };
const submit: Submit = { const submit: Submit = {
name: "submit", name: 'submit',
type: "submit", type: 'submit',
value: "Let's go!", value: "Let's go!",
}; };
const values = { const values = {
firstName: "James", firstName: 'James',
lastName: "Bond", lastName: 'Bond',
email: "james.bond@gmail.com", email: 'james.bond@gmail.com',
country: "U.S.A", country: 'U.S.A',
eligible: "yes", eligible: 'yes',
}; };
infoForm.setValue(values); infoForm.setValue(values);
infoForm.name = "Application Form"; infoForm.name = 'Application Form';
skillsForm.name = "Skills"; skillsForm.name = 'Skills';
skillsForm.controls.push(new FormControl(resume)); skillsForm.controls.push(new FormControl(resume));
--- ---
<Layout title="Programmer Job Application"> <Layout title="Programmer Job Application">
<Form <Form showValidationHints formGroups={[infoForm, skillsForm]} submitControl={submit} />
showValidationHints
formGroups={[infoForm, skillsForm]}
submitControl={submit}
/>
</Layout> </Layout>

View file

@ -1,96 +1,96 @@
--- ---
import Form, { FormGroup } from "@astro-reactive/form"; import Form, { FormGroup } from '@astro-reactive/form';
import { Validators } from "@astro-reactive/validator"; import { Validators } from '@astro-reactive/validator';
import Layout from "../components/Layout.astro"; import Layout from '../components/Layout.astro';
const baseForm = new FormGroup([ const baseForm = new FormGroup([
{ {
name: "crust", name: 'crust',
label: "Crust", label: 'Crust',
type: "radio", type: 'radio',
options: [{ label: "Garlic", value: "garlic" }], options: [{ label: 'Garlic', value: 'garlic' }],
}, },
{ {
name: "size", name: 'size',
label: "Size", label: 'Size',
type: "radio", type: 'radio',
options: ["Small", "Medium", "Large"], options: ['Small', 'Medium', 'Large'],
}, },
{ {
name: "sauce", name: 'sauce',
label: "Sauce", label: 'Sauce',
type: "radio", type: 'radio',
options: ["Tomato", "Barbeque"], options: ['Tomato', 'Barbeque'],
}, },
]); ]);
const toppingsForm = new FormGroup([ const toppingsForm = new FormGroup([
{ {
name: "mushrooms", name: 'mushrooms',
label: "Mushrooms", label: 'Mushrooms',
type: "checkbox", type: 'checkbox',
}, },
{ {
name: "extraCheese", name: 'extraCheese',
label: "Extra Cheese", label: 'Extra Cheese',
type: "checkbox", type: 'checkbox',
}, },
{ {
name: "onions", name: 'onions',
label: "Onions", label: 'Onions',
type: "checkbox", type: 'checkbox',
}, },
{ {
name: "peppers", name: 'peppers',
label: "Peppers", label: 'Peppers',
type: "checkbox", type: 'checkbox',
}, },
{ {
name: "pepperoni", name: 'pepperoni',
label: "Pepperoni", label: 'Pepperoni',
type: "checkbox", type: 'checkbox',
}, },
{ {
name: "sausage", name: 'sausage',
label: "Sausage", label: 'Sausage',
type: "checkbox", type: 'checkbox',
}, },
{ {
name: "chicken", name: 'chicken',
label: "Chicken", label: 'Chicken',
type: "checkbox", type: 'checkbox',
}, },
{ {
name: "pineapple", name: 'pineapple',
label: "Pineapple", label: 'Pineapple',
type: "checkbox", type: 'checkbox',
}, },
]); ]);
const infoForm = new FormGroup([ const infoForm = new FormGroup([
{ {
name: "name", name: 'name',
label: "Name", label: 'Name',
validators: [Validators.required], validators: [Validators.required],
}, },
{ {
name: "address", name: 'address',
label: "Delivery Address", label: 'Delivery Address',
validators: [Validators.required], validators: [Validators.required],
}, },
{ {
name: "contact", name: 'contact',
label: "Contact Number", label: 'Contact Number',
validators: [Validators.required], validators: [Validators.required],
}, },
]); ]);
baseForm.name = "Base"; baseForm.name = 'Base';
toppingsForm.name = "Toppings"; toppingsForm.name = 'Toppings';
infoForm.name = "Customer Info"; infoForm.name = 'Customer Info';
infoForm.get("contact")?.setValidators([Validators.minLength(9)]); infoForm.get('contact')?.setValidators([Validators.minLength(9)]);
--- ---
<Layout title="Pizza Form Demo"> <Layout title="Pizza Form Demo">
<Form showValidationHints formGroups={[baseForm, toppingsForm, infoForm]} /> <Form showValidationHints formGroups={[baseForm, toppingsForm, infoForm]} />
</Layout> </Layout>

2
apps/docs/.eslintignore Normal file
View file

@ -0,0 +1,2 @@
dist
node_modules

5
apps/docs/.eslintrc.cjs Normal file
View file

@ -0,0 +1,5 @@
/** @type {import("@types/eslint").Linter.Config} */
module.exports = {
root: true,
extends: ['@astro-reactive/eslint-config-custom'],
};

24
apps/docs/.prettierrc.cjs Normal file
View file

@ -0,0 +1,24 @@
/** @type {import("@types/prettier").Options} */
module.exports = {
printWidth: 100,
semi: true,
singleQuote: true,
tabWidth: 2,
trailingComma: "es5",
useTabs: true,
plugins: ["../../node_modules/prettier-plugin-astro"],
overrides: [
{
files: "*.astro",
options: {
parser: "astro",
},
},
{
files: [".*", "*.json", "*.md", "*.toml", "*.yml"],
options: {
useTabs: false,
},
},
],
};

View file

@ -5,4 +5,3 @@
Start the dev server by running: `npm run docs` Start the dev server by running: `npm run docs`
👉 _[Join our contributors!](https://github.com/astro-reactive/astro-reactive/blob/main/CONTRIBUTING.md)_ 👉 _[Join our contributors!](https://github.com/astro-reactive/astro-reactive/blob/main/CONTRIBUTING.md)_

View file

@ -11,6 +11,9 @@
"build": "astro build", "build": "astro build",
"preview": "astro preview", "preview": "astro preview",
"astro": "astro", "astro": "astro",
"format": "prettier -w .",
"lint": "eslint . --ext .ts,.js",
"lint:fix": "eslint --fix . --ext .ts,.js",
"clean": "rimraf node_modules .turbo dist" "clean": "rimraf node_modules .turbo dist"
}, },
"dependencies": { "dependencies": {
@ -24,7 +27,6 @@
"@types/react-dom": "^18.0.0", "@types/react-dom": "^18.0.0",
"astro": "^1.4.4", "astro": "^1.4.4",
"preact": "^10.7.3", "preact": "^10.7.3",
"prettier-plugin-astro": "^0.7.0",
"react": "^18.1.0", "react": "^18.1.0",
"react-dom": "^18.1.0" "react-dom": "^18.1.0"
}, },
@ -41,7 +43,13 @@
}, },
"homepage": "https://github.com/astro-reactive/astro-reactive#readme", "homepage": "https://github.com/astro-reactive/astro-reactive#readme",
"devDependencies": { "devDependencies": {
"@astro-reactive/eslint-config-custom": "*",
"@astro-reactive/tsconfig": "*",
"@types/eslint": "^8.4.10",
"@types/prettier": "^2.7.2",
"eslint": "^8.31.0",
"prettier": "^2.8.3",
"prettier-plugin-astro": "^0.7.2",
"rimraf": "^3.0.2" "rimraf": "^3.0.2"
} }
} }

View file

@ -1,3 +1,4 @@
// eslint-disable-next-line no-undef
Array.from(document.getElementsByTagName('pre')).forEach((element) => { Array.from(document.getElementsByTagName('pre')).forEach((element) => {
element.setAttribute('tabindex', '0'); element.setAttribute('tabindex', '0');
}); });

View file

@ -1,7 +1,7 @@
--- ---
// fetch all commits for just this page's path // fetch all commits for just this page's path
type Props = { type Props = {
path: string; path: string;
}; };
const { path } = Astro.props as Props; const { path } = Astro.props as Props;
const resolvedPath = `apps/docs/${path}`; const resolvedPath = `apps/docs/${path}`;
@ -9,58 +9,58 @@ const url = `https://api.github.com/repos/astro-reactive/astro-reactive/commits?
const commitsURL = `https://github.com/astro-reactive/astro-reactive/commits/main/${resolvedPath}`; const commitsURL = `https://github.com/astro-reactive/astro-reactive/commits/main/${resolvedPath}`;
type Commit = { type Commit = {
author: { author: {
id: string; id: string;
login: string; login: string;
}; };
}; };
async function getCommits(url: string) { async function getCommits(url: string) {
try { try {
const token = import.meta.env.SNOWPACK_PUBLIC_GITHUB_TOKEN ?? "hello"; const token = import.meta.env.SNOWPACK_PUBLIC_GITHUB_TOKEN ?? 'hello';
if (!token) { if (!token) {
throw new Error( throw new Error(
'Cannot find "SNOWPACK_PUBLIC_GITHUB_TOKEN" used for escaping rate-limiting.' 'Cannot find "SNOWPACK_PUBLIC_GITHUB_TOKEN" used for escaping rate-limiting.'
); );
} }
const auth = `Basic ${Buffer.from(token, "binary").toString("base64")}`; const auth = `Basic ${Buffer.from(token, 'binary').toString('base64')}`;
const res = await fetch(url, { const res = await fetch(url, {
method: "GET", method: 'GET',
headers: { headers: {
Authorization: auth, Authorization: auth,
"User-Agent": "astro-docs/1.0", 'User-Agent': 'astro-docs/1.0',
}, },
}); });
const data = await res.json(); const data = await res.json();
if (!res.ok) { if (!res.ok) {
throw new Error( throw new Error(
`Request to fetch commits failed. Reason: ${res.statusText} `Request to fetch commits failed. Reason: ${res.statusText}
Message: ${data.message}` Message: ${data.message}`
); );
} }
return data as Commit[]; return data as Commit[];
} catch (e) { } catch (e) {
console.warn(`[error] /src/components/AvatarList.astro console.warn(`[error] /src/components/AvatarList.astro
${(e as any)?.message ?? e}`); ${(e as any)?.message ?? e}`);
return [] as Commit[]; return [] as Commit[];
} }
} }
function removeDups(arr: Commit[]) { function removeDups(arr: Commit[]) {
const map = new Map<string, Commit["author"]>(); const map = new Map<string, Commit['author']>();
for (let item of arr) { for (let item of arr) {
const author = item.author; const author = item.author;
// Deduplicate based on author.id // Deduplicate based on author.id
map.set(author.id, { login: author.login, id: author.id }); map.set(author.id, { login: author.login, id: author.id });
} }
return [...map.values()]; return [...map.values()];
} }
const data = await getCommits(url); const data = await getCommits(url);
@ -71,112 +71,101 @@ const additionalContributors = unique.length - recentContributors.length; // lis
<!-- Thanks to @5t3ph for https://smolcss.dev/#smol-avatar-list! --> <!-- Thanks to @5t3ph for https://smolcss.dev/#smol-avatar-list! -->
<div class="contributors"> <div class="contributors">
<ul <ul class="avatar-list" style={`--avatar-count: ${recentContributors.length}`}>
class="avatar-list" {
style={`--avatar-count: ${recentContributors.length}`} recentContributors.map((item) => (
> <li>
{ <a href={`https://github.com/${item.login}`}>
recentContributors.map((item) => ( <img
<li> alt={`Contributor ${item.login}`}
<a href={`https://github.com/${item.login}`}> title={`Contributor ${item.login}`}
<img width="64"
alt={`Contributor ${item.login}`} height="64"
title={`Contributor ${item.login}`} src={`https://avatars.githubusercontent.com/u/${item.id}`}
width="64" />
height="64" </a>
src={`https://avatars.githubusercontent.com/u/${item.id}`} </li>
/> ))
</a> }
</li> </ul>
)) {
} additionalContributors > 0 && (
</ul> <span>
{ <a href={commitsURL}>{`and ${additionalContributors} additional contributor${
additionalContributors > 0 && ( additionalContributors > 1 ? 's' : ''
<span> }.`}</a>
<a </span>
href={commitsURL} )
>{`and ${additionalContributors} additional contributor${ }
additionalContributors > 1 ? "s" : "" {unique.length === 0 && <a href={commitsURL}>Contributors</a>}
}.`}</a>
</span>
)
}
{unique.length === 0 && <a href={commitsURL}>Contributors</a>}
</div> </div>
<style> <style>
.avatar-list { .avatar-list {
--avatar-size: 2.5rem; --avatar-size: 2.5rem;
--avatar-count: 3; --avatar-count: 3;
display: grid; display: grid;
list-style: none; list-style: none;
/* Default to displaying most of the avatar to /* Default to displaying most of the avatar to
enable easier access on touch devices, ensuring enable easier access on touch devices, ensuring
the WCAG touch target size is met or exceeded */ the WCAG touch target size is met or exceeded */
grid-template-columns: repeat( grid-template-columns: repeat(var(--avatar-count), max(44px, calc(var(--avatar-size) / 1.15)));
var(--avatar-count), /* `padding` matches added visual dimensions of
max(44px, calc(var(--avatar-size) / 1.15))
);
/* `padding` matches added visual dimensions of
the `box-shadow` to help create a more accurate the `box-shadow` to help create a more accurate
computed component size */ computed component size */
padding: 0.08em; padding: 0.08em;
font-size: var(--avatar-size); font-size: var(--avatar-size);
} }
@media (any-hover: hover) and (any-pointer: fine) { @media (any-hover: hover) and (any-pointer: fine) {
.avatar-list { .avatar-list {
/* We create 1 extra cell to enable the computed /* We create 1 extra cell to enable the computed
width to match the final visual width */ width to match the final visual width */
grid-template-columns: repeat( grid-template-columns: repeat(calc(var(--avatar-count) + 1), calc(var(--avatar-size) / 1.75));
calc(var(--avatar-count) + 1), }
calc(var(--avatar-size) / 1.75) }
);
}
}
.avatar-list li { .avatar-list li {
width: var(--avatar-size); width: var(--avatar-size);
height: var(--avatar-size); height: var(--avatar-size);
} }
.avatar-list li:hover ~ li a, .avatar-list li:hover ~ li a,
.avatar-list li:focus-within ~ li a { .avatar-list li:focus-within ~ li a {
transform: translateX(33%); transform: translateX(33%);
} }
.avatar-list img, .avatar-list img,
.avatar-list a { .avatar-list a {
display: block; display: block;
border-radius: 50%; border-radius: 50%;
} }
.avatar-list a { .avatar-list a {
transition: transform 180ms ease-in-out; transition: transform 180ms ease-in-out;
} }
.avatar-list img { .avatar-list img {
width: 100%; width: 100%;
height: 100%; height: 100%;
object-fit: cover; object-fit: cover;
background-color: #fff; background-color: #fff;
box-shadow: 0 0 0 0.05em #fff, 0 0 0 0.08em rgba(0, 0, 0, 0.15); box-shadow: 0 0 0 0.05em #fff, 0 0 0 0.08em rgba(0, 0, 0, 0.15);
} }
.avatar-list a:focus { .avatar-list a:focus {
outline: 2px solid transparent; outline: 2px solid transparent;
/* Double-layer trick to work for dark and light backgrounds */ /* 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; box-shadow: 0 0 0 0.08em var(--theme-accent), 0 0 0 0.12em white;
} }
.contributors { .contributors {
display: flex; display: flex;
align-items: center; align-items: center;
} }
.contributors > * + * { .contributors > * + * {
margin-left: 0.75rem; margin-left: 0.75rem;
} }
</style> </style>

View file

@ -21,9 +21,7 @@ import '../styles/index.css';
/> />
<!-- Scrollable a11y code helper --> <!-- Scrollable a11y code helper -->
<script src="/make-scrollable-code-focusable.js" is:inline> <script src="/make-scrollable-code-focusable.js" is:inline></script>
</script>
<!-- This is intentionally inlined to avoid FOUC --> <!-- This is intentionally inlined to avoid FOUC -->
<script is:inline> <script is:inline>

View file

@ -1,15 +1,15 @@
--- ---
import { getLanguageFromURL, KNOWN_LANGUAGE_CODES } from "../../languages"; import { getLanguageFromURL, KNOWN_LANGUAGE_CODES } from '../../languages';
import ThemeToggleButton from "./ThemeToggleButton"; import ThemeToggleButton from './ThemeToggleButton';
import * as CONFIG from "../../config"; import * as CONFIG from '../../config';
// import AstroLogo from "./AstroLogo.astro"; // import AstroLogo from "./AstroLogo.astro";
import SkipToContent from "./SkipToContent.astro"; import SkipToContent from './SkipToContent.astro';
import SidebarToggle from "./SidebarToggle"; import SidebarToggle from './SidebarToggle';
import LanguageSelect from "./LanguageSelect"; import LanguageSelect from './LanguageSelect';
// import Search from "./Search"; // import Search from "./Search";
type Props = { type Props = {
currentPage: string; currentPage: string;
}; };
const { currentPage } = Astro.props as Props; const { currentPage } = Astro.props as Props;
@ -17,140 +17,136 @@ const lang = getLanguageFromURL(currentPage);
--- ---
<header> <header>
<SkipToContent /> <SkipToContent />
<nav class="nav-wrapper" title="Top Navigation"> <nav class="nav-wrapper" title="Top Navigation">
<div class="menu-toggle"> <div class="menu-toggle">
<SidebarToggle client:idle /> <SidebarToggle client:idle />
</div> </div>
<div class="logo flex"> <div class="logo flex">
<a href="/"> <a href="/">
<h1>{CONFIG.SITE.title ?? "Documentation"}</h1> <h1>{CONFIG.SITE.title ?? 'Documentation'}</h1>
</a> </a>
</div> </div>
<div style="flex-grow: 1;"></div> <div style="flex-grow: 1;"></div>
{ {KNOWN_LANGUAGE_CODES.length > 1 && <LanguageSelect lang={lang} client:idle />}
KNOWN_LANGUAGE_CODES.length > 1 && ( <!-- TODO: enable search -->
<LanguageSelect lang={lang} client:idle /> <!-- <div class="search-item">
)
}
<!-- TODO: enable search -->
<!-- <div class="search-item">
<Search client:idle /> <Search client:idle />
</div> --> </div> -->
<ThemeToggleButton client:visible /> <ThemeToggleButton client:visible />
</nav> </nav>
</header> </header>
<style> <style>
header { header {
z-index: 11; z-index: 11;
height: var(--theme-navbar-height); height: var(--theme-navbar-height);
width: 100%; width: 100%;
background-color: var(--theme-navbar-bg); background-color: var(--theme-navbar-bg);
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
overflow: hidden; overflow: hidden;
position: sticky; position: sticky;
top: 0; top: 0;
} }
.logo { .logo {
flex: 1; flex: 1;
display: flex; display: flex;
overflow: hidden; overflow: hidden;
width: 30px; width: 30px;
font-size: 2rem; font-size: 2rem;
flex-shrink: 0; flex-shrink: 0;
font-weight: 600; font-weight: 600;
line-height: 1; line-height: 1;
color: hsla(var(--color-base-white), 100%, 1); color: hsla(var(--color-base-white), 100%, 1);
gap: 0.25em; gap: 0.25em;
z-index: -1; z-index: -1;
} }
.logo a { .logo a {
display: flex; display: flex;
padding: 0.5em 0.25em; padding: 0.5em 0.25em;
margin: -0.5em -0.25em; margin: -0.5em -0.25em;
text-decoration: none; text-decoration: none;
font-weight: bold; font-weight: bold;
} }
.logo a { .logo a {
transition: color 100ms ease-out; transition: color 100ms ease-out;
color: var(--theme-text); color: var(--theme-text);
} }
.logo a:hover, .logo a:hover,
.logo a:focus { .logo a:focus {
color: var(--theme-text-accent); color: var(--theme-text-accent);
} }
.logo h1 { .logo h1 {
display: none; display: none;
font: inherit; font: inherit;
color: inherit; color: inherit;
margin: 0; margin: 0;
} }
.nav-wrapper { .nav-wrapper {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: flex-end; justify-content: flex-end;
gap: 1em; gap: 1em;
width: 100%; width: 100%;
max-width: 82em; max-width: 82em;
padding: 0 2rem; padding: 0 2rem;
} }
@media (min-width: 50em) { @media (min-width: 50em) {
header { header {
position: static; position: static;
padding: 2rem 0rem; padding: 2rem 0rem;
} }
.logo { .logo {
width: auto; width: auto;
margin: 0; margin: 0;
z-index: 0; z-index: 0;
} }
.logo h1 { .logo h1 {
display: initial; display: initial;
} }
.menu-toggle { .menu-toggle {
display: none; display: none;
} }
} }
/** Style Algolia */ /** Style Algolia */
:root { :root {
--docsearch-primary-color: var(--theme-accent); --docsearch-primary-color: var(--theme-accent);
--docsearch-logo-color: var(--theme-text); --docsearch-logo-color: var(--theme-text);
} }
.search-item { .search-item {
display: none; display: none;
position: relative; position: relative;
z-index: 10; z-index: 10;
flex-grow: 1; flex-grow: 1;
padding-right: 0.7rem; padding-right: 0.7rem;
display: flex; display: flex;
max-width: 200px; max-width: 200px;
} }
@media (min-width: 50em) { @media (min-width: 50em) {
.search-item { .search-item {
max-width: 400px; max-width: 400px;
} }
} }
</style> </style>
<style is:global> <style is:global>
.search-item > * { .search-item > * {
flex-grow: 1; flex-grow: 1;
} }
</style> </style>

View file

@ -28,7 +28,7 @@ export default function Search() {
}, [setIsOpen]); }, [setIsOpen]);
const onInput = useCallback( const onInput = useCallback(
(e) => { (e: KeyboardEvent) => {
setIsOpen(true); setIsOpen(true);
setInitialQuery(e.key); setInitialQuery(e.key);
}, },

View file

@ -1,124 +1,119 @@
--- ---
import { getLanguageFromURL } from "../../languages"; import { getLanguageFromURL } from '../../languages';
import { SIDEBAR } from "../../config"; import { SIDEBAR } from '../../config';
type Props = { type Props = {
currentPage: string; currentPage: string;
}; };
const { currentPage } = Astro.props as Props; const { currentPage } = Astro.props as Props;
const currentPageMatch = currentPage.endsWith("/") const currentPageMatch = currentPage.endsWith('/')
? currentPage.slice(1, -1) ? currentPage.slice(1, -1)
: currentPage.slice(1); : currentPage.slice(1);
const langCode = getLanguageFromURL(currentPage); const langCode = getLanguageFromURL(currentPage);
const sidebar = SIDEBAR[langCode]; const sidebar = SIDEBAR[langCode];
--- ---
<nav aria-labelledby="grid-left"> <nav aria-labelledby="grid-left">
<ul class="nav-groups"> <ul class="nav-groups">
{ {
Object.entries(sidebar).map(([header, children]) => ( Object.entries(sidebar).map(([header, children]) => (
<li> <li>
<div class="nav-group"> <div class="nav-group">
<h2>{header}</h2> <h2>{header}</h2>
<ul> <ul>
{children.map((child) => { {children.map((child) => {
const url = Astro.site?.pathname + child.link; const url = Astro.site?.pathname + child.link;
return ( return (
<li class="nav-link"> <li class="nav-link">
<a <a href={url} aria-current={currentPageMatch === child.link ? 'page' : false}>
href={url} {child.text}
aria-current={ </a>
currentPageMatch === child.link ? "page" : false </li>
} );
> })}
{child.text} </ul>
</a> </div>
</li> </li>
); ))
})} }
</ul> </ul>
</div>
</li>
))
}
</ul>
</nav> </nav>
<script is:inline> <script is:inline>
window.addEventListener("DOMContentLoaded", () => { window.addEventListener('DOMContentLoaded', () => {
var target = document.querySelector('[aria-current="page"]'); var target = document.querySelector('[aria-current="page"]');
if (target && target.offsetTop > window.innerHeight - 100) { if (target && target.offsetTop > window.innerHeight - 100) {
document.querySelector(".nav-groups").scrollTop = target.offsetTop; document.querySelector('.nav-groups').scrollTop = target.offsetTop;
} }
}); });
</script> </script>
<style> <style>
nav { nav {
width: 100%; width: 100%;
margin-right: 1rem; margin-right: 1rem;
} }
.nav-groups { .nav-groups {
height: 100%; height: 100%;
padding: 2rem; padding: 2rem;
overflow-x: visible; overflow-x: visible;
overflow-y: auto; overflow-y: auto;
max-height: 100vh; max-height: 100vh;
} }
.nav-groups > li + li { .nav-groups > li + li {
margin-top: 2rem; margin-top: 2rem;
} }
.nav-groups > :first-child { .nav-groups > :first-child {
padding-top: var(--doc-padding); padding-top: var(--doc-padding);
} }
.nav-groups > :last-child { .nav-groups > :last-child {
padding-bottom: 2rem; padding-bottom: 2rem;
margin-bottom: var(--theme-navbar-height); margin-bottom: var(--theme-navbar-height);
} }
.nav-group-title { .nav-group-title {
font-size: 1rem; font-size: 1rem;
font-weight: 700; font-weight: 700;
padding: 0.1rem 1rem; padding: 0.1rem 1rem;
text-transform: uppercase; text-transform: uppercase;
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
} }
.nav-link a { .nav-link a {
font-size: 1rem; font-size: 1rem;
margin: 1px; margin: 1px;
padding: 0.3rem 1rem; padding: 0.3rem 1rem;
font: inherit; font: inherit;
color: inherit; color: inherit;
text-decoration: none; text-decoration: none;
display: block; display: block;
} }
.nav-link a:hover, .nav-link a:hover,
.nav-link a:focus { .nav-link a:focus {
background-color: var(--theme-bg-hover); background-color: var(--theme-bg-hover);
} }
.nav-link a[aria-current="page"] { .nav-link a[aria-current='page'] {
color: var(--theme-text-accent); color: var(--theme-text-accent);
background-color: var(--theme-bg-accent); background-color: var(--theme-bg-accent);
font-weight: 600; font-weight: 600;
} }
@media (min-width: 50em) { @media (min-width: 50em) {
.nav-groups { .nav-groups {
padding: 0; padding: 0;
} }
} }
</style> </style>
<style is:global> <style is:global>
:root.theme-dark .nav-link a[aria-current="page"] { :root.theme-dark .nav-link a[aria-current='page'] {
color: hsla(var(--color-base-white), 100%, 1); color: hsla(var(--color-base-white), 100%, 1);
} }
</style> </style>

View file

@ -1,13 +1,13 @@
--- ---
import type { Frontmatter } from "../../config"; import type { Frontmatter } from '../../config';
import MoreMenu from "../RightSidebar/MoreMenu.astro"; import MoreMenu from '../RightSidebar/MoreMenu.astro';
import TableOfContents from "../RightSidebar/TableOfContents"; import TableOfContents from '../RightSidebar/TableOfContents';
import type { MarkdownHeading } from "astro"; import type { MarkdownHeading } from 'astro';
type Props = { type Props = {
frontmatter: Frontmatter; frontmatter: Frontmatter;
headings: MarkdownHeading[]; headings: MarkdownHeading[];
githubEditUrl: string; githubEditUrl: string;
}; };
const { frontmatter, headings, githubEditUrl } = Astro.props as Props; const { frontmatter, headings, githubEditUrl } = Astro.props as Props;
@ -15,39 +15,39 @@ const title = frontmatter.title;
--- ---
<article id="article" class="content"> <article id="article" class="content">
<section class="main-section"> <section class="main-section">
<h1 class="content-title" id="overview">{title}</h1> <h1 class="content-title" id="overview">{title}</h1>
<nav class="block sm:hidden"> <nav class="block sm:hidden">
<TableOfContents client:media="(max-width: 50em)" headings={headings} /> <TableOfContents client:media="(max-width: 50em)" headings={headings} />
</nav> </nav>
<slot /> <slot />
</section> </section>
<nav class="block sm:hidden"> <nav class="block sm:hidden">
<MoreMenu editHref={githubEditUrl} /> <MoreMenu editHref={githubEditUrl} />
</nav> </nav>
</article> </article>
<style> <style>
.content { .content {
padding: 0; padding: 0;
max-width: 75ch; max-width: 75ch;
width: 100%; width: 100%;
height: 100%; height: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.content > section { .content > section {
margin-bottom: 4rem; margin-bottom: 4rem;
} }
.block { .block {
display: block; display: block;
} }
@media (min-width: 50em) { @media (min-width: 50em) {
.sm\:hidden { .sm\:hidden {
display: none; display: none;
} }
} }
</style> </style>

View file

@ -1,8 +1,8 @@
--- ---
import * as CONFIG from "../../config"; import * as CONFIG from '../../config';
type Props = { type Props = {
editHref: string; editHref: string;
}; };
const { editHref } = Astro.props as Props; const { editHref } = Astro.props as Props;
@ -11,65 +11,65 @@ const showMoreSection = CONFIG.COMMUNITY_INVITE_URL;
{showMoreSection && <h2 class="heading">More</h2>} {showMoreSection && <h2 class="heading">More</h2>}
<ul> <ul>
{ {
editHref && ( editHref && (
<li class={`heading-link depth-2`}> <li class={`heading-link depth-2`}>
<a class="edit-on-github" href={editHref} target="_blank"> <a class="edit-on-github" href={editHref} target="_blank">
<svg <svg
aria-hidden="true" aria-hidden="true"
focusable="false" focusable="false"
data-prefix="fas" data-prefix="fas"
data-icon="pen" data-icon="pen"
class="svg-inline--fa fa-pen fa-w-16" class="svg-inline--fa fa-pen fa-w-16"
role="img" role="img"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512" viewBox="0 0 512 512"
height="1em" height="1em"
width="1em" width="1em"
> >
<path <path
fill="currentColor" 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" 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> </svg>
<span>Edit this page</span> <span>Edit this page</span>
</a> </a>
</li> </li>
) )
} }
{ {
CONFIG.COMMUNITY_INVITE_URL && ( CONFIG.COMMUNITY_INVITE_URL && (
<li class={`heading-link depth-2`}> <li class={`heading-link depth-2`}>
<a href={CONFIG.COMMUNITY_INVITE_URL} target="_blank"> <a href={CONFIG.COMMUNITY_INVITE_URL} target="_blank">
<svg <svg
aria-hidden="true" aria-hidden="true"
focusable="false" focusable="false"
data-prefix="fas" data-prefix="fas"
data-icon="comment-alt" data-icon="comment-alt"
class="svg-inline--fa fa-comment-alt fa-w-16" class="svg-inline--fa fa-comment-alt fa-w-16"
role="img" role="img"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512" viewBox="0 0 512 512"
height="1em" height="1em"
width="1em" width="1em"
> >
<path <path
fill="currentColor" 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" 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> </svg>
<span>Join our community</span> <span>Join our community</span>
</a> </a>
</li> </li>
) )
} }
</ul> </ul>
<style> <style>
.edit-on-github { .edit-on-github {
text-decoration: none; text-decoration: none;
font: inherit; font: inherit;
color: inherit; color: inherit;
font-size: 1rem; font-size: 1rem;
} }
</style> </style>

View file

@ -1,31 +1,30 @@
export const SITE = { export const SITE = {
title: "Astro Reactive Docs", title: 'Astro Reactive Docs',
description: description: 'Let your data build your UI with native Astro components and architecture.',
"Let your data build your UI with native Astro components and architecture.", defaultLanguage: 'en_US',
defaultLanguage: "en_US",
}; };
export const OPEN_GRAPH = { export const OPEN_GRAPH = {
image: { image: {
src: "https://github.com/astro-reactive/astro-reactive/blob/main/.github/assets/astro-reactive-library-cover.png?raw=true", src: 'https://github.com/astro-reactive/astro-reactive/blob/main/.github/assets/astro-reactive-library-cover.png?raw=true',
alt: "astro logo and astro reactive library text on a starry expanse of space", alt: 'astro logo and astro reactive library text on a starry expanse of space',
}, },
twitter: "astroreactive", twitter: 'astroreactive',
}; };
// This is the type of the frontmatter you put in the docs markdown files. // This is the type of the frontmatter you put in the docs markdown files.
export type Frontmatter = { export type Frontmatter = {
title: string; title: string;
description: string; description: string;
layout: string; layout: string;
image?: { src: string; alt: string }; image?: { src: string; alt: string };
dir?: "ltr" | "rtl"; dir?: 'ltr' | 'rtl';
ogLocale?: string; ogLocale?: string;
lang?: string; lang?: string;
}; };
export const KNOWN_LANGUAGES = { export const KNOWN_LANGUAGES = {
English: "en", English: 'en',
} as const; } as const;
export const KNOWN_LANGUAGE_CODES = Object.values(KNOWN_LANGUAGES); export const KNOWN_LANGUAGE_CODES = Object.values(KNOWN_LANGUAGES);
@ -35,35 +34,35 @@ export const COMMUNITY_INVITE_URL = `https://discord.gg/fkpkKdPJ`;
// See "Algolia" section of the README for more information. // See "Algolia" section of the README for more information.
export const ALGOLIA = { export const ALGOLIA = {
indexName: "XXXXXXXXXX", indexName: 'XXXXXXXXXX',
appId: "XXXXXXXXXX", appId: 'XXXXXXXXXX',
apiKey: "XXXXXXXXXX", apiKey: 'XXXXXXXXXX',
}; };
export type Sidebar = Record< export type Sidebar = Record<
typeof KNOWN_LANGUAGE_CODES[number], (typeof KNOWN_LANGUAGE_CODES)[number],
Record<string, { text: string; link: string }[]> Record<string, { text: string; link: string }[]>
>; >;
export const SIDEBAR: Sidebar = { export const SIDEBAR: Sidebar = {
en: { en: {
// TODO: create tutorial // TODO: create tutorial
// Tutorial: [ // Tutorial: [
// { text: "Getting Started", link: "en/getting-started" }, // { text: "Getting Started", link: "en/getting-started" },
// { text: "Page 2", link: "en/page-2" }, // { text: "Page 2", link: "en/page-2" },
// { text: "Page 3", link: "en/page-3" }, // { text: "Page 3", link: "en/page-3" },
// ], // ],
// TODO: create overview // TODO: create overview
Introduction: [ Introduction: [
{ text: "Overview", link: "en/introduction" }, { text: 'Overview', link: 'en/introduction' },
// { text: "Philosophy", link: "en/philosophy" }, // { text: "Philosophy", link: "en/philosophy" },
], ],
"API Docs": [ 'API Docs': [
{ text: "Form", link: "en/api/form/form-component" }, { text: 'Form', link: 'en/api/form/form-component' },
{ text: "FormGroup", link: "en/api/form/form-group" }, { text: 'FormGroup', link: 'en/api/form/form-group' },
{ text: "FormControl", link: "en/api/form/form-control" }, { text: 'FormControl', link: 'en/api/form/form-control' },
{ text: "Validators", link: "en/api/validator/validators" }, { text: 'Validators', link: 'en/api/validator/validators' },
], ],
}, },
}; };

View file

@ -6,5 +6,5 @@ export const langPathRegex = /\/([a-z]{2}-?[A-Z]{0,2})\//;
export function getLanguageFromURL(pathname: string) { export function getLanguageFromURL(pathname: string) {
const langCodeMatch = pathname.match(langPathRegex); const langCodeMatch = pathname.match(langPathRegex);
const langCode = langCodeMatch ? langCodeMatch[1] : 'en'; const langCode = langCodeMatch ? langCodeMatch[1] : 'en';
return langCode as typeof KNOWN_LANGUAGE_CODES[number]; return langCode as (typeof KNOWN_LANGUAGE_CODES)[number];
} }

View file

@ -1,167 +1,153 @@
--- ---
import HeadCommon from "../components/HeadCommon.astro"; import HeadCommon from '../components/HeadCommon.astro';
import HeadSEO from "../components/HeadSEO.astro"; import HeadSEO from '../components/HeadSEO.astro';
import Header from "../components/Header/Header.astro"; import Header from '../components/Header/Header.astro';
import PageContent from "../components/PageContent/PageContent.astro"; import PageContent from '../components/PageContent/PageContent.astro';
import LeftSidebar from "../components/LeftSidebar/LeftSidebar.astro"; import LeftSidebar from '../components/LeftSidebar/LeftSidebar.astro';
import RightSidebar from "../components/RightSidebar/RightSidebar.astro"; import RightSidebar from '../components/RightSidebar/RightSidebar.astro';
import * as CONFIG from "../config"; import * as CONFIG from '../config';
import type { MarkdownHeading } from "astro"; import type { MarkdownHeading } from 'astro';
import Footer from "../components/Footer/Footer.astro"; import Footer from '../components/Footer/Footer.astro';
type Props = { type Props = {
frontmatter: CONFIG.Frontmatter; frontmatter: CONFIG.Frontmatter;
headings: MarkdownHeading[]; headings: MarkdownHeading[];
}; };
const { frontmatter, headings } = Astro.props as Props; const { frontmatter, headings } = Astro.props as Props;
const canonicalURL = new URL(Astro.url.pathname, Astro.site); const canonicalURL = new URL(Astro.url.pathname, Astro.site);
const currentPage = Astro.url.pathname; const currentPage = Astro.url.pathname;
const currentFile = `src/pages${currentPage.replace(/\/$/, "")}.md`; const currentFile = `src/pages${currentPage.replace(/\/$/, '')}.md`;
const githubEditUrl = `${CONFIG.GITHUB_EDIT_URL}/${currentFile}`; const githubEditUrl = `${CONFIG.GITHUB_EDIT_URL}/${currentFile}`;
--- ---
<html <html dir={frontmatter.dir ?? 'ltr'} lang={frontmatter.lang ?? 'en-us'} class="initial">
dir={frontmatter.dir ?? "ltr"} <head>
lang={frontmatter.lang ?? "en-us"} <HeadCommon />
class="initial" <HeadSEO frontmatter={frontmatter} canonicalUrl={canonicalURL} />
> <title>
<head> {frontmatter.title ? `${frontmatter.title} | ${CONFIG.SITE.title}` : CONFIG.SITE.title}
<HeadCommon /> </title>
<HeadSEO frontmatter={frontmatter} canonicalUrl={canonicalURL} /> <style>
<title> body {
{ width: 100%;
frontmatter.title display: grid;
? `${frontmatter.title} | ${CONFIG.SITE.title}` grid-template-rows: var(--theme-navbar-height) 1fr;
: CONFIG.SITE.title --gutter: 0.5rem;
} --doc-padding: 2rem;
</title> }
<style>
body {
width: 100%;
display: grid;
grid-template-rows: var(--theme-navbar-height) 1fr;
--gutter: 0.5rem;
--doc-padding: 2rem;
}
.layout { .layout {
display: grid; display: grid;
grid-auto-flow: column; grid-auto-flow: column;
grid-template-columns: grid-template-columns:
minmax(var(--gutter), 1fr) minmax(0, var(--max-width)) minmax(var(--gutter), 1fr) minmax(0, var(--max-width))
minmax(var(--gutter), 1fr); minmax(var(--gutter), 1fr);
overflow-x: hidden; overflow-x: hidden;
} }
.grid-sidebar { .grid-sidebar {
height: 100vh; height: 100vh;
position: sticky; position: sticky;
top: 0; top: 0;
padding: 0; padding: 0;
} }
#grid-left { #grid-left {
position: fixed; position: fixed;
background-color: var(--theme-bg); background-color: var(--theme-bg);
z-index: 10; z-index: 10;
display: none; display: none;
} }
#grid-main { #grid-main {
padding: 0 var(--gutter); padding: 0 var(--gutter);
grid-column: 2; grid-column: 2;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
height: 100%; height: 100%;
} }
#grid-right { #grid-right {
display: none; display: none;
} }
@media (min-width: 50em) { @media (min-width: 50em) {
.layout { .layout {
overflow: initial; overflow: initial;
grid-template-columns: 20rem minmax(0, var(--max-width)); grid-template-columns: 20rem minmax(0, var(--max-width));
gap: 1em; gap: 1em;
} }
#grid-left { #grid-left {
display: flex; display: flex;
padding-left: 2rem; padding-left: 2rem;
position: sticky; position: sticky;
grid-column: 1; grid-column: 1;
} }
} }
@media (min-width: 72em) { @media (min-width: 72em) {
.layout { .layout {
grid-template-columns: 20rem minmax(0, var(--max-width)) 18rem; grid-template-columns: 20rem minmax(0, var(--max-width)) 18rem;
padding-left: 0; padding-left: 0;
padding-right: 0; padding-right: 0;
margin: 0 auto; margin: 0 auto;
} }
#grid-right { #grid-right {
grid-column: 3; grid-column: 3;
display: flex; display: flex;
} }
} }
</style> </style>
<style is:global> <style is:global>
.warning { .warning {
background-color: var(--theme-bg-accent); background-color: var(--theme-bg-accent);
color: var(--theme-text-accent); color: var(--theme-text-accent);
margin: 2rem 0; margin: 2rem 0;
padding: 1.25em 1.5rem; padding: 1.25em 1.5rem;
border-radius: 0 0.25rem 0.25rem 0; border-radius: 0 0.25rem 0.25rem 0;
border-left: 3px solid var(--theme-text-accent); border-left: 3px solid var(--theme-text-accent);
} }
.layout > * { .layout > * {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
.mobile-sidebar-toggle { .mobile-sidebar-toggle {
overflow: hidden; overflow: hidden;
} }
.mobile-sidebar-toggle #grid-left { .mobile-sidebar-toggle #grid-left {
display: block; display: block;
top: 2rem; top: 2rem;
} }
</style> </style>
</head> </head>
<body> <body>
<Header currentPage={currentPage} /> <Header currentPage={currentPage} />
<main class="layout"> <main class="layout">
<aside id="grid-left" class="grid-sidebar" title="Site Navigation"> <aside id="grid-left" class="grid-sidebar" title="Site Navigation">
<LeftSidebar currentPage={currentPage} /> <LeftSidebar currentPage={currentPage} />
</aside> </aside>
<div id="grid-main"> <div id="grid-main">
<div class="warning"> <div class="warning">
<strong>🛠 Under Construction:</strong> This library and the documentation <strong>🛠 Under Construction:</strong> This library and the documentation are undergoing rigorous
are undergoing rigorous development. Read and join our <a development. Read and join our <a
href="https://github.com/astro-reactive/astro-reactive/discussions" href="https://github.com/astro-reactive/astro-reactive/discussions">discussions</a
>discussions</a > for questions, suggestions, or feedback.
> for questions, suggestions, or feedback. </div>
</div> <PageContent frontmatter={frontmatter} headings={headings} githubEditUrl={githubEditUrl}>
<PageContent <slot />
frontmatter={frontmatter} </PageContent>
headings={headings} </div>
githubEditUrl={githubEditUrl} <aside id="grid-right" class="grid-sidebar" title="Table of Contents">
> <RightSidebar headings={headings} githubEditUrl={githubEditUrl} />
<slot /> </aside>
</PageContent> </main>
</div> <Footer path={currentFile} />
<aside id="grid-right" class="grid-sidebar" title="Table of Contents"> </body>
<RightSidebar headings={headings} githubEditUrl={githubEditUrl} />
</aside>
</main>
<Footer path={currentFile} />
</body>
</html> </html>

View file

@ -1,7 +1,7 @@
--- ---
title: Form title: Form
type: component type: component
package: "@astro-reactive/form" package: '@astro-reactive/form'
description: The Reactive Form component for Astro description: The Reactive Form component for Astro
layout: ../../../../layouts/MainLayout.astro layout: ../../../../layouts/MainLayout.astro
--- ---
@ -10,7 +10,7 @@ The `Form` component renders a form element and various control components (e.g.
```astro ```astro
--- ---
import Form, { FormGroup } from "@astro-reactive/form"; import Form, { FormGroup } from '@astro-reactive/form';
const form = new FormGroup(); const form = new FormGroup();
// your controls configuration data // your controls configuration data
--- ---
@ -36,26 +36,26 @@ Assigning a `FormGroup` object to the `formGroup` property will set up a form.
```astro ```astro
--- ---
import Form, { FormGroup } from "@astro-reactive/form"; import Form, { FormGroup } from '@astro-reactive/form';
const form = new FormGroup([ const form = new FormGroup([
{ {
name: "username", name: 'username',
label: "Username", label: 'Username',
value: "awesome_dev", value: 'awesome_dev',
}, },
{ {
name: "comment", name: 'comment',
label: "Feedback", label: 'Feedback',
type: "textarea", type: 'textarea',
value: "Nice!", value: 'Nice!',
}, },
{ {
name: "size", name: 'size',
label: "Size", label: 'Size',
type: "dropdown", type: 'dropdown',
options: ["S", "M", "L", "XL", "XXL"], options: ['S', 'M', 'L', 'XL', 'XXL'],
placeholder: "-- Please choose an option --", placeholder: '-- Please choose an option --',
}, },
]); ]);
--- ---
@ -77,48 +77,48 @@ To render a form with multiple field sets, assign an array `FormGroup[]` to the
```astro ```astro
--- ---
import Form, { FormGroup } from "@astro-reactive/form"; import Form, { FormGroup } from '@astro-reactive/form';
const nameForm = new FormGroup( const nameForm = new FormGroup(
[ [
{ {
name: "firstName", name: 'firstName',
label: "First Name", label: 'First Name',
value: "John", value: 'John',
}, },
{ {
name: "lastName", name: 'lastName',
label: "Last Name", label: 'Last Name',
value: "Doe", value: 'Doe',
}, },
], ],
"Name" 'Name'
); );
const skills = new FormGroup( const skills = new FormGroup(
[ [
{ {
name: "JavaScript", name: 'JavaScript',
type: "checkbox", type: 'checkbox',
label: "JavaScript", label: 'JavaScript',
}, },
{ {
name: "TypeScript", name: 'TypeScript',
type: "checkbox", type: 'checkbox',
label: "TypeScript", label: 'TypeScript',
}, },
{ {
name: "React", name: 'React',
type: "checkbox", type: 'checkbox',
label: "React", label: 'React',
}, },
{ {
name: "Vue", name: 'Vue',
type: "checkbox", type: 'checkbox',
label: "Vue", label: 'Vue',
}, },
], ],
"Skills" 'Skills'
); );
--- ---
@ -139,13 +139,13 @@ This implementation is to distinguish the submit button from other buttons and l
```astro ```astro
--- ---
import Form, { FormGroup } from "@astro-reactive/form"; import Form, { FormGroup } from '@astro-reactive/form';
const form = new FormGroup([]); const form = new FormGroup([]);
const submitControl: Submit = { const submitControl: Submit = {
name: "submit", name: 'submit',
type: "submit", type: 'submit',
}; };
--- ---
@ -160,16 +160,16 @@ This is a very crude solution to prevent having multiple submit buttons. For sug
The following are input properties a `Form` component can take. Only the `formGroups` property is required. The following are input properties a `Form` component can take. Only the `formGroups` property is required.
| Property | Type | | | Property | Type | |
| ------------------------------------------- | -------------------------- | ----------------------------------- | | ------------------------------------------- | ----------------------------- | -------- |
| [formGroups](#formgroups) | `FormGroup \| FormGroup[]` | required | | [formGroups](#formgroups) | `FormGroup \| FormGroup[]` | required |
| [action](#action) | `string` | optional | | [action](#action) | `string` | optional |
| [method](#method) | `'get' \| 'post' \| 'dialog'` | optional | | [method](#method) | `'get' \| 'post' \| 'dialog'` | optional |
| [readOnly](#readonly) | `boolean` | optional | | [readOnly](#readonly) | `boolean` | optional |
| [showValidationHints](#showvalidationhints) | `boolean` | optional | | [showValidationHints](#showvalidationhints) | `boolean` | optional |
| [submitControl](#submitcontrol) | `Submit` | optional | | [submitControl](#submitcontrol) | `Submit` | optional |
| [theme](#theme) | `'light' \| 'dark'` | optional | | [theme](#theme) | `'light' \| 'dark'` | optional |
| [validateOnLoad](#validateOnLoad) | `boolean` | optional | | [validateOnLoad](#validateOnLoad) | `boolean` | optional |
### `formGroups` ### `formGroups`
@ -190,6 +190,7 @@ Type: HTTPSubmitMethod
Sets the `method` [attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#attr-method) for the form. Set this to the HTTP method to submit the form: 'post', 'get', or 'dialog'. Sets the `method` [attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#attr-method) for the form. Set this to the HTTP method to submit the form: 'post', 'get', or 'dialog'.
From [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#attr-method): From [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#attr-method):
- `post` - The POST method; form data sent as the request body. - `post` - The POST method; form data sent as the request body.
- `get (default)` - The GET method; form data appended to the action URL with a ? separator. Use this method when the form has no side effects. - `get (default)` - The GET method; form data appended to the action URL with a ? separator. Use this method when the form has no side effects.
- `dialog` - When the form is inside a <dialog>, closes the dialog and throws a submit event on submission without submitting data or clearing the form. - `dialog` - When the form is inside a <dialog>, closes the dialog and throws a submit event on submission without submitting data or clearing the form.
@ -218,8 +219,8 @@ A special button that triggers the submit event for a form.
```ts ```ts
const submit: Submit = { const submit: Submit = {
type: 'submit', type: 'submit',
value: 'Let\'s go!' value: "Let's go!",
} };
``` ```
### `theme` ### `theme`
@ -233,4 +234,3 @@ Sets the form to use light or dark mode.
Type: `boolean` Type: `boolean`
When used with our `validator` package, the `Form` component is able to render validation errors on server-side rendering when `validateOnLoad` is set to true. Otherwise, the validation errors will only be rendered on the client-side upon user interaction. When used with our `validator` package, the `Form` component is able to render validation errors on server-side rendering when `validateOnLoad` is set to true. Otherwise, the validation errors will only be rendered on the client-side upon user interaction.

View file

@ -1,7 +1,7 @@
--- ---
title: FormControl title: FormControl
type: class type: class
package: "@astro-reactive/form" package: '@astro-reactive/form'
description: FormControl class description: FormControl class
layout: ../../../../layouts/MainLayout.astro layout: ../../../../layouts/MainLayout.astro
--- ---

View file

@ -1,7 +1,7 @@
--- ---
title: FormGroup title: FormGroup
type: class type: class
package: "@astro-reactive/form" package: '@astro-reactive/form'
description: The FormGroup class represents a group of controls that will be rendered as a fieldset element in a form. description: The FormGroup class represents a group of controls that will be rendered as a fieldset element in a form.
layout: ../../../../layouts/MainLayout.astro layout: ../../../../layouts/MainLayout.astro
--- ---
@ -12,10 +12,10 @@ The `FormGroup` class represents a group of controls that will be rendered as a
## Properties ## Properties
| Property | Type | | | Property | Type | |
|---|---|---| | --------------------- | --------------- | -------- |
| [controls](#controls) | `FormControl[]` | required | | [controls](#controls) | `FormControl[]` | required |
| [name](#name) | `string` | optional | | [name](#name) | `string` | optional |
### controls ### controls

View file

@ -1,5 +1,5 @@
<script is:inline> <script is:inline>
// Redirect your homepage to the first page of documentation. // Redirect your homepage to the first page of documentation.
// If you have a landing page, remove this script and add it here! // If you have a landing page, remove this script and add it here!
window.location.pathname = `/en/api/form/form-component`; window.location.pathname = `/en/api/form/form-component`;
</script> </script>

View file

@ -1,5 +1,5 @@
<script is:inline> <script is:inline>
// Redirect your homepage to the first page of documentation. // Redirect your homepage to the first page of documentation.
// If you have a landing page, remove this script and add it here! // If you have a landing page, remove this script and add it here!
window.location.pathname = `/en/api/form/form-component`; window.location.pathname = `/en/api/form/form-component`;
</script> </script>

View file

@ -1,3 +1,3 @@
<script is:inline> <script is:inline>
window.location.pathname = `/en/api/validator/validators`; window.location.pathname = `/en/api/validator/validators`;
</script> </script>

View file

@ -1,7 +1,7 @@
--- ---
title: Validators title: Validators
type: class type: class
package: "@astro-reactive/validators" package: '@astro-reactive/validators'
description: Validator package for @astro-reactive/forms package for providing validation to forms. description: Validator package for @astro-reactive/forms package for providing validation to forms.
layout: ../../../../layouts/MainLayout.astro layout: ../../../../layouts/MainLayout.astro
--- ---
@ -10,21 +10,21 @@ The `Validators` class provides a set of built-in validators that can be used by
```astro ```astro
--- ---
import Form, {FormGroup} from "@astro-reactive/form" import Form, { FormGroup } from '@astro-reactive/form';
import {Validators} from "@astro-reactive/validator" import { Validators } from '@astro-reactive/validator';
const form = new FormGroup([ const form = new FormGroup([
{ {
name: "username", name: 'username',
label: "Username", label: 'Username',
validators: [Validators.required], validators: [Validators.required],
}, },
{ {
name: "password", name: 'password',
label: "Password", label: 'Password',
validators: [Validators.required, Validators.minLength(8)], validators: [Validators.required, Validators.minLength(8)],
}, },
]) ]);
--- ---
<Form formGroups={form} /> <Form formGroups={form} />
@ -48,16 +48,16 @@ The `Validators.required` validator is used to ensure that a form control has a
```astro ```astro
--- ---
import Form, {FormGroup} from "@astro-reactive/form" import Form, { FormGroup } from '@astro-reactive/form';
import {Validators} from "@astro-reactive/validator" import { Validators } from '@astro-reactive/validator';
const form = new FormGroup([ const form = new FormGroup([
{ {
name: "username", name: 'username',
label: "Username", label: 'Username',
validators: [Validators.required], validators: [Validators.required],
}, },
]) ]);
--- ---
<Form formGroups={form} /> <Form formGroups={form} />
@ -69,17 +69,17 @@ The `Validators.requiredChecked` validator is used to ensure that a checkbox is
```astro ```astro
--- ---
import Form, {FormGroup} from "@astro-reactive/form" import Form, { FormGroup } from '@astro-reactive/form';
import {Validators} from "@astro-reactive/validator" import { Validators } from '@astro-reactive/validator';
const form = new FormGroup([ const form = new FormGroup([
{ {
name: "terms", name: 'terms',
label: "Terms and Conditions", label: 'Terms and Conditions',
type: "checkbox", type: 'checkbox',
validators: [Validators.requiredChecked], validators: [Validators.requiredChecked],
}, },
]) ]);
--- ---
<Form formGroups={form} /> <Form formGroups={form} />
@ -91,16 +91,16 @@ The `Validators.email` validator is used to ensure that a form control has a val
```astro ```astro
--- ---
import Form, {FormGroup} from "@astro-reactive/form" import Form, { FormGroup } from '@astro-reactive/form';
import {Validators} from "@astro-reactive/validator" import { Validators } from '@astro-reactive/validator';
const form = new FormGroup([ const form = new FormGroup([
{ {
name: "email", name: 'email',
label: "Email", label: 'Email',
validators: [Validators.email], validators: [Validators.email],
}, },
]) ]);
--- ---
<Form formGroups={form} /> <Form formGroups={form} />
@ -112,17 +112,17 @@ The `Validators.min` validator is used to ensure that the numeric value of form
```astro ```astro
--- ---
import Form, {FormGroup} from "@astro-reactive/form" import Form, { FormGroup } from '@astro-reactive/form';
import {Validators} from "@astro-reactive/validator" import { Validators } from '@astro-reactive/validator';
const form = new FormGroup([ const form = new FormGroup([
{ {
name: "price", name: 'price',
label: "Price", label: 'Price',
type: "number", type: 'number',
validators: [Validators.min(8)], validators: [Validators.min(8)],
}, },
]) ]);
--- ---
<Form formGroups={forms} /> <Form formGroups={forms} />
@ -134,17 +134,17 @@ The `Validators.max` validator is used to ensure that the numeric value of form
```astro ```astro
--- ---
import Form, {FormGroup} from "@astro-reactive/form" import Form, { FormGroup } from '@astro-reactive/form';
import {Validators} from "@astro-reactive/validator" import { Validators } from '@astro-reactive/validator';
const form = new FormGroup([ const form = new FormGroup([
{ {
name: "price", name: 'price',
label: "Price", label: 'Price',
type: "number", type: 'number',
validators: [Validators.max(8)], validators: [Validators.max(8)],
}, },
]) ]);
--- ---
<Form formGroups={forms} /> <Form formGroups={forms} />
@ -156,16 +156,16 @@ The `Validators.minLength` validator is used to ensure that the length of the va
```astro ```astro
--- ---
import Form, {FormGroup} from "@astro-reactive/form" import Form, { FormGroup } from '@astro-reactive/form';
import {Validators} from "@astro-reactive/validator" import { Validators } from '@astro-reactive/validator';
const form = new FormGroup([ const form = new FormGroup([
{ {
name: "password", name: 'password',
label: "Password", label: 'Password',
validators: [Validators.minLength(8)], validators: [Validators.minLength(8)],
}, },
]) ]);
--- ---
<Form formGroups={forms} /> <Form formGroups={forms} />
@ -177,16 +177,16 @@ The `Validators.maxLength` validator is used to ensure that the length of the va
```astro ```astro
--- ---
import Form, {FormGroup} from "@astro-reactive/form" import Form, { FormGroup } from '@astro-reactive/form';
import {Validators} from "@astro-reactive/validator" import { Validators } from '@astro-reactive/validator';
const form = new FormGroup([ const form = new FormGroup([
{ {
name: "password", name: 'password',
label: "Password", label: 'Password',
validators: [Validators.maxLength(8)], validators: [Validators.maxLength(8)],
}, },
]) ]);
--- ---
<Form formGroups={forms} /> <Form formGroups={forms} />

View file

@ -1,5 +1,5 @@
<script is:inline> <script is:inline>
// Redirect your homepage to the first page of documentation. // Redirect your homepage to the first page of documentation.
// If you have a landing page, remove this script and add it here! // If you have a landing page, remove this script and add it here!
window.location.pathname = `/en/introduction`; window.location.pathname = `/en/introduction`;
</script> </script>

View file

@ -48,11 +48,10 @@ We will also make this clear in our library documentation as we see them.
## Packages ## Packages
| Package | Release notes | Description | | Package | Release notes | Description |
| ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | | ---------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- |
| [form](/en/api/form/form-component) | [![npm](https://img.shields.io/npm/v/@astro-reactive/form)](https://github.com/astro-reactive/astro-reactive/blob/main/packages/form/RELEASE.md) | a dynamic form which can be modified programmatically | | [form](/en/api/form/form-component) | [![npm](https://img.shields.io/npm/v/@astro-reactive/form)](https://github.com/astro-reactive/astro-reactive/blob/main/packages/form/RELEASE.md) | a dynamic form which can be modified programmatically |
| [validator](https://github.com/astro-reactive/astro-reactive/blob/main/packages/validator/README.md) | [![npm](https://img.shields.io/npm/v/@astro-reactive/validator)](https://github.com/astro-reactive/astro-reactive/blob/main/packages/validator/RELEASE.md) | validators for editable fields | | [validator](https://github.com/astro-reactive/astro-reactive/blob/main/packages/validator/README.md) | [![npm](https://img.shields.io/npm/v/@astro-reactive/validator)](https://github.com/astro-reactive/astro-reactive/blob/main/packages/validator/RELEASE.md) | validators for editable fields |
| data-grid | 🛠 | a dynamic data grid of values | | data-grid | 🛠 | a dynamic data grid of values |
| themes | 🛠 | easy-to-use, accessible, consistent cross-browser styles | | themes | 🛠 | easy-to-use, accessible, consistent cross-browser styles |
| viz | 🛠 | data visualization that emits and responds to events | | viz | 🛠 | data visualization that emits and responds to events |

View file

@ -6,26 +6,24 @@ layout: ../../../layouts/MainLayout.astro
Consider the following code: Consider the following code:
```astro
``` astro
--- ---
import Form { FormGroup } from '@astro-reactive/form'; import Form, { FormGroup } from '@astro-reactive/form';
import { Validators } from '@astro-reactive/validator'; import { Validators } from '@astro-reactive/validator';
const form = new FormGroup([ const form = new FormGroup([
{ {
name: 'username', name: 'username',
label: 'Username', label: 'Username',
validators: [Validators.required] validators: [Validators.required],
}, },
{ {
name: 'password', name: 'password',
label: 'Password', label: 'Password',
validators: [Validators.required, Validators.minLength(8)] validators: [Validators.required, Validators.minLength(8)],
}, },
]); ]);
--- ---
<Form formGroups={form} /> <Form formGroups={form} />
``` ```

View file

@ -33,45 +33,44 @@ Use in an Astro page:
```astro ```astro
--- ---
import { FormControl, FormGroup } from "@astro-reactive/form/core"; import { FormControl, FormGroup } from '@astro-reactive/form/core';
import Form from "@astro-reactive/form"; import Form from '@astro-reactive/form';
// create a form group // create a form group
const form = new FormGroup([ const form = new FormGroup([
{ {
name: "username", name: 'username',
label: "Username", label: 'Username',
}, },
{ {
name: "password", name: 'password',
label: "Password", label: 'Password',
type: "password", type: 'password',
}, },
]); ]);
// set the name optionally // set the name optionally
form.name = "Simple Form"; form.name = 'Simple Form';
// you can insert a control at any point // you can insert a control at any point
form.controls.push( form.controls.push(
new FormControl({ new FormControl({
type: "checkbox", type: 'checkbox',
name: "is-awesome", name: 'is-awesome',
label: "is Awesome?", label: 'is Awesome?',
}) })
); );
// you can get a FormControl object // you can get a FormControl object
const userNameControl = form.get("username"); const userNameControl = form.get('username');
// you can set values dynamically // you can set values dynamically
userNameControl?.setValue("RAMOOOON"); userNameControl?.setValue('RAMOOOON');
form.get('is-awesome')?.setValue("checked"); form.get('is-awesome')?.setValue('checked');
--- ---
<!-- the formGroups attribute takes an array of FormGroup--> <!-- the formGroups attribute takes an array of FormGroup-->
<Form formGroups={[form]} /> <Form formGroups={[form]} />
``` ```
# Screenshots # Screenshots
@ -105,4 +104,3 @@ Currently this only supports very basic form creation, but the goal of the proje
... and so much more ... and so much more
_All contributions are welcome. Let's make the fastest web form component powered by Astro_ _All contributions are welcome. Let's make the fastest web form component powered by Astro_

View file

@ -1,5 +1,5 @@
<script is:inline> <script is:inline>
// Redirect your homepage to the first page of documentation. // Redirect your homepage to the first page of documentation.
// If you have a landing page, remove this script and add it here! // If you have a landing page, remove this script and add it here!
window.location.pathname = `/en/introduction/`; window.location.pathname = `/en/introduction/`;
</script> </script>

View file

@ -1,7 +1,6 @@
{ {
"extends": "astro/tsconfigs/base", "extends": "@astro-reactive/tsconfig/astro-library.json",
"compilerOptions": { "compilerOptions": {
"jsx": "preserve", "jsx": "preserve"
"skipLibCheck": true
} }
} }

View file

@ -0,0 +1,2 @@
dist
node_modules

View file

@ -0,0 +1,5 @@
/** @type {import("@types/eslint").Linter.Config} */
module.exports = {
root: true,
extends: ['@astro-reactive/eslint-config-custom'],
};

View file

@ -0,0 +1,24 @@
/** @type {import("@types/prettier").Options} */
module.exports = {
printWidth: 100,
semi: true,
singleQuote: true,
tabWidth: 2,
trailingComma: 'es5',
useTabs: true,
plugins: ['../../node_modules/prettier-plugin-astro'],
overrides: [
{
files: '*.astro',
options: {
parser: 'astro',
},
},
{
files: ['.*', '*.json', '*.md', '*.toml', '*.yml'],
options: {
useTabs: false,
},
},
],
};

View file

@ -1 +0,0 @@
{}

View file

@ -1,12 +1,12 @@
import tailwind from "@astrojs/tailwind"; import tailwind from '@astrojs/tailwind';
import { defineConfig } from "astro/config"; import { defineConfig } from 'astro/config';
export default defineConfig({ export default defineConfig({
site: "https://astro-reactive.dev", site: 'https://astro-reactive.dev',
integrations: [tailwind()], integrations: [tailwind()],
vite: { vite: {
ssr: { ssr: {
external: ["svgo"], external: ['svgo'],
}, },
}, },
}); });

View file

@ -10,16 +10,22 @@
"build": "astro build", "build": "astro build",
"preview": "astro preview", "preview": "astro preview",
"astro": "astro", "astro": "astro",
"format": "prettier --write .", "format": "prettier -w .",
"lint": "eslint . --ext .ts,.js",
"lint:fix": "eslint --fix . --ext .ts,.js",
"clean": "rimraf dist node_modules dist .turbo" "clean": "rimraf dist node_modules dist .turbo"
}, },
"devDependencies": { "devDependencies": {
"@astro-reactive/eslint-config-custom": "*",
"@astrojs/tailwind": "^2.0.2", "@astrojs/tailwind": "^2.0.2",
"@types/eslint": "^8.4.10",
"@types/micromodal": "^0.3.3", "@types/micromodal": "^0.3.3",
"@types/prettier": "^2.7.2",
"astro": "^1.4.7", "astro": "^1.4.7",
"astro-icon": "^0.8.0", "astro-icon": "^0.8.0",
"prettier": "2.7.1", "eslint": "^8.31.0",
"prettier-plugin-astro": "^0.7.0", "prettier": "^2.7.1",
"prettier-plugin-astro": "^0.7.2",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"tailwindcss-fluid-type": "^2.0.3" "tailwindcss-fluid-type": "^2.0.3"
}, },
@ -41,4 +47,3 @@
}, },
"homepage": "https://github.com/astro-reactive/astro-reactive#readme" "homepage": "https://github.com/astro-reactive/astro-reactive#readme"
} }

View file

@ -1,12 +1,12 @@
/* TODO: consider creating <Button> and <GradientText> components */ /* TODO: consider creating <Button> and <GradientText> components */
a, a,
.btn { .btn {
@apply transition-colors duration-200; @apply transition-colors duration-200;
@apply hover:text-secondary; @apply hover:text-secondary;
@apply focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-transparent focus:ring-secondary; @apply focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-transparent focus:ring-secondary;
} }
.gradient-text { .gradient-text {
@apply text-transparent bg-clip-text; @apply text-transparent bg-clip-text;
@apply bg-gradient-to-br from-indigo-500 via-fuchsia-500 to-pink-500; @apply bg-gradient-to-br from-indigo-500 via-fuchsia-500 to-pink-500;
} }

View file

@ -1,2 +1,2 @@
@import "global.css"; @import 'global.css';
@import "theme.css"; @import 'theme.css';

View file

@ -1,19 +1,19 @@
[data-theme="light"] { [data-theme='light'] {
--color-primary: theme("colors.pink.500"); --color-primary: theme('colors.pink.500');
--color-secondary: theme("colors.indigo.500"); --color-secondary: theme('colors.indigo.500');
--color-text: theme("colors.gray.900"); --color-text: theme('colors.gray.900');
--color-text-offset: theme("colors.gray.600"); --color-text-offset: theme('colors.gray.600');
--color-background: theme("colors.gray.50"); --color-background: theme('colors.gray.50');
--color-background-offset: theme("colors.gray.100"); --color-background-offset: theme('colors.gray.100');
--color-border: theme("colors.gray.900" / 10%); --color-border: theme('colors.gray.900' / 10%);
} }
[data-theme="dark"] { [data-theme='dark'] {
--color-primary: theme("colors.pink.400"); --color-primary: theme('colors.pink.400');
--color-secondary: theme("colors.indigo.400"); --color-secondary: theme('colors.indigo.400');
--color-text: theme("colors.gray.50"); --color-text: theme('colors.gray.50');
--color-text-offset: theme("colors.gray.400"); --color-text-offset: theme('colors.gray.400');
--color-background: theme("colors.gray.900"); --color-background: theme('colors.gray.900');
--color-background-offset: theme("colors.gray.800"); --color-background-offset: theme('colors.gray.800');
--color-border: theme("colors.gray.50" / 10%); --color-border: theme('colors.gray.50' / 10%);
} }

View file

@ -1,38 +1,38 @@
const defaultTheme = require("tailwindcss/defaultTheme"); const defaultTheme = require('tailwindcss/defaultTheme');
module.exports = { module.exports = {
content: ["./src/**/*.{astro,html,js,jsx,svelte,ts,tsx,vue}"], content: ['./src/**/*.{astro,html,js,jsx,svelte,ts,tsx,vue}'],
theme: { theme: {
screens: { screens: {
"astro-sm": { max: "1000px" }, 'astro-sm': { max: '1000px' },
"astro-md": { min: "640px", max: "1000px" }, 'astro-md': { min: '640px', max: '1000px' },
"astro-img": { min: "600px", max: "1000px" }, 'astro-img': { min: '600px', max: '1000px' },
"astro-lg": { min: "1000px" }, 'astro-lg': { min: '1000px' },
...defaultTheme.screens, ...defaultTheme.screens,
}, },
extend: { extend: {
fontFamily: { fontFamily: {
sans: ["Inter", ...defaultTheme.fontFamily.sans], sans: ['Inter', ...defaultTheme.fontFamily.sans],
}, },
colors: { colors: {
primary: "var(--color-primary)", primary: 'var(--color-primary)',
secondary: "var(--color-secondary)", secondary: 'var(--color-secondary)',
}, },
textColor: { textColor: {
default: "var(--color-text)", default: 'var(--color-text)',
offset: "var(--color-text-offset)", offset: 'var(--color-text-offset)',
}, },
backgroundColor: { backgroundColor: {
default: "var(--color-background)", default: 'var(--color-background)',
offset: "var(--color-background-offset)", offset: 'var(--color-background-offset)',
}, },
borderColor: { borderColor: {
default: "var(--color-border)", default: 'var(--color-border)',
}, },
}, },
}, },
corePlugins: { corePlugins: {
fontSize: false, fontSize: false,
}, },
plugins: [require("tailwindcss-fluid-type")], plugins: [require('tailwindcss-fluid-type')],
}; };

59
package-lock.json generated
View file

@ -30,11 +30,17 @@
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@astro-reactive/form": "*", "@astro-reactive/form": "*",
"@astro-reactive/tsconfig": "*",
"@astro-reactive/validator": "*", "@astro-reactive/validator": "*",
"astro": "^1.6.5" "astro": "^1.6.5"
}, },
"devDependencies": { "devDependencies": {
"@astro-reactive/eslint-config-custom": "*",
"@astro-reactive/tsconfig": "*",
"@types/eslint": "^8.4.10",
"@types/prettier": "^2.7.2",
"eslint": "^8.31.0",
"prettier": "^2.8.3",
"prettier-plugin-astro": "^0.7.2",
"rimraf": "^3.0.2" "rimraf": "^3.0.2"
} }
}, },
@ -53,11 +59,17 @@
"@types/react-dom": "^18.0.0", "@types/react-dom": "^18.0.0",
"astro": "^1.4.4", "astro": "^1.4.4",
"preact": "^10.7.3", "preact": "^10.7.3",
"prettier-plugin-astro": "^0.7.0",
"react": "^18.1.0", "react": "^18.1.0",
"react-dom": "^18.1.0" "react-dom": "^18.1.0"
}, },
"devDependencies": { "devDependencies": {
"@astro-reactive/eslint-config-custom": "*",
"@astro-reactive/tsconfig": "*",
"@types/eslint": "^8.4.10",
"@types/prettier": "^2.7.2",
"eslint": "^8.31.0",
"prettier": "^2.8.3",
"prettier-plugin-astro": "^0.7.2",
"rimraf": "^3.0.2" "rimraf": "^3.0.2"
} }
}, },
@ -71,20 +83,25 @@
"tailwindcss": "^3.1.8" "tailwindcss": "^3.1.8"
}, },
"devDependencies": { "devDependencies": {
"@astro-reactive/eslint-config-custom": "*",
"@astrojs/tailwind": "^2.0.2", "@astrojs/tailwind": "^2.0.2",
"@types/eslint": "^8.4.10",
"@types/micromodal": "^0.3.3", "@types/micromodal": "^0.3.3",
"@types/prettier": "^2.7.2",
"astro": "^1.4.7", "astro": "^1.4.7",
"astro-icon": "^0.8.0", "astro-icon": "^0.8.0",
"prettier": "2.7.1", "eslint": "^8.31.0",
"prettier-plugin-astro": "^0.7.0", "prettier": "^2.7.1",
"prettier-plugin-astro": "^0.7.2",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"tailwindcss-fluid-type": "^2.0.3" "tailwindcss-fluid-type": "^2.0.3"
} }
}, },
"apps/landing-page/node_modules/prettier": { "apps/landing-page/node_modules/prettier": {
"version": "2.7.1", "version": "2.7.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
"integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
"dev": true, "dev": true,
"license": "MIT",
"bin": { "bin": {
"prettier": "bin-prettier.js" "prettier": "bin-prettier.js"
}, },
@ -6450,9 +6467,9 @@
} }
}, },
"node_modules/prettier": { "node_modules/prettier": {
"version": "2.8.1", "version": "2.8.3",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.1.tgz", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.3.tgz",
"integrity": "sha512-lqGoSJBQNJidqCHE80vqZJHWHRFoNYsSpP9AjFhlhi9ODCJA541svILes/+/1GM3VaL/abZi7cpFzOpdR9UPKg==", "integrity": "sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==",
"bin": { "bin": {
"prettier": "bin-prettier.js" "prettier": "bin-prettier.js"
}, },
@ -8647,10 +8664,16 @@
"@astro-reactive/demo": { "@astro-reactive/demo": {
"version": "file:apps/demo", "version": "file:apps/demo",
"requires": { "requires": {
"@astro-reactive/eslint-config-custom": "*",
"@astro-reactive/form": "*", "@astro-reactive/form": "*",
"@astro-reactive/tsconfig": "*", "@astro-reactive/tsconfig": "*",
"@astro-reactive/validator": "*", "@astro-reactive/validator": "*",
"@types/eslint": "^8.4.10",
"@types/prettier": "^2.7.2",
"astro": "^1.6.5", "astro": "^1.6.5",
"eslint": "^8.31.0",
"prettier": "^2.8.3",
"prettier-plugin-astro": "^0.7.2",
"rimraf": "^3.0.2" "rimraf": "^3.0.2"
} }
}, },
@ -8658,16 +8681,22 @@
"version": "file:apps/docs", "version": "file:apps/docs",
"requires": { "requires": {
"@algolia/client-search": "^4.13.1", "@algolia/client-search": "^4.13.1",
"@astro-reactive/eslint-config-custom": "*",
"@astro-reactive/tsconfig": "*",
"@astrojs/preact": "^1.1.1", "@astrojs/preact": "^1.1.1",
"@astrojs/react": "^1.1.4", "@astrojs/react": "^1.1.4",
"@docsearch/css": "^3.1.0", "@docsearch/css": "^3.1.0",
"@docsearch/react": "^3.1.0", "@docsearch/react": "^3.1.0",
"@types/eslint": "^8.4.10",
"@types/node": "^18.0.0", "@types/node": "^18.0.0",
"@types/prettier": "^2.7.2",
"@types/react": "^18.0.24", "@types/react": "^18.0.24",
"@types/react-dom": "^18.0.0", "@types/react-dom": "^18.0.0",
"astro": "^1.4.4", "astro": "^1.4.4",
"eslint": "^8.31.0",
"preact": "^10.7.3", "preact": "^10.7.3",
"prettier-plugin-astro": "^0.7.0", "prettier": "^2.8.3",
"prettier-plugin-astro": "^0.7.2",
"react": "^18.1.0", "react": "^18.1.0",
"react-dom": "^18.1.0", "react-dom": "^18.1.0",
"rimraf": "^3.0.2" "rimraf": "^3.0.2"
@ -8709,11 +8738,15 @@
"@astro-reactive/landing-page": { "@astro-reactive/landing-page": {
"version": "file:apps/landing-page", "version": "file:apps/landing-page",
"requires": { "requires": {
"@astro-reactive/eslint-config-custom": "*",
"@astro-reactive/tsconfig": "*", "@astro-reactive/tsconfig": "*",
"@astrojs/tailwind": "^2.0.2", "@astrojs/tailwind": "^2.0.2",
"@types/eslint": "*",
"@types/micromodal": "^0.3.3", "@types/micromodal": "^0.3.3",
"@types/prettier": "*",
"astro": "^1.4.7", "astro": "^1.4.7",
"astro-icon": "^0.8.0", "astro-icon": "^0.8.0",
"eslint": "*",
"micromodal": "^0.4.10", "micromodal": "^0.4.10",
"prettier": "2.7.1", "prettier": "2.7.1",
"prettier-plugin-astro": "^0.7.0", "prettier-plugin-astro": "^0.7.0",
@ -8724,6 +8757,8 @@
"dependencies": { "dependencies": {
"prettier": { "prettier": {
"version": "2.7.1", "version": "2.7.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
"integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
"dev": true "dev": true
} }
} }
@ -12904,9 +12939,9 @@
"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==" "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="
}, },
"prettier": { "prettier": {
"version": "2.8.1", "version": "2.8.3",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.1.tgz", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.3.tgz",
"integrity": "sha512-lqGoSJBQNJidqCHE80vqZJHWHRFoNYsSpP9AjFhlhi9ODCJA541svILes/+/1GM3VaL/abZi7cpFzOpdR9UPKg==" "integrity": "sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw=="
}, },
"prettier-linter-helpers": { "prettier-linter-helpers": {
"version": "1.0.0", "version": "1.0.0",