feat: Added Alpine JS

Added Alpine JS as another framework library
This commit is contained in:
P. Christopher Bowers
2022-05-10 16:52:05 -04:00
parent c133066ea8
commit 1b5a997720
28 changed files with 1801 additions and 23 deletions

View File

@@ -15,16 +15,14 @@ How do we solve this ? Developers love having framework overview by examples. It
- \[ ] Add EmberJS
- \[ ] Add Preact
- \[ ] Add Alpine
- \[ ] Add Stencil
- \[ ] Add Alpine
- \[ ] Add native JS ?
## Progression
<details>
<summary>
<img width="18" height="18" src="https://raw.githubusercontent.com/matschik/component-party/main/public/framework/svelte.svg" />
<img width="18" height="18" src="public/framework/svelte.svg" />
<b>Svelte</b>
<img src="https://us-central1-progress-markdown.cloudfunctions.net/progress/100" /></summary>
@@ -58,7 +56,7 @@ How do we solve this ? Developers love having framework overview by examples. It
</details><details>
<summary>
<img width="18" height="18" src="https://raw.githubusercontent.com/matschik/component-party/main/public/framework/react.svg" />
<img width="18" height="18" src="public/framework/react.svg" />
<b>React</b>
<img src="https://us-central1-progress-markdown.cloudfunctions.net/progress/100" /></summary>
@@ -92,7 +90,7 @@ How do we solve this ? Developers love having framework overview by examples. It
</details><details>
<summary>
<img width="18" height="18" src="https://raw.githubusercontent.com/matschik/component-party/main/public/framework/vue.svg" />
<img width="18" height="18" src="public/framework/vue.svg" />
<b>Vue 3</b>
<img src="https://us-central1-progress-markdown.cloudfunctions.net/progress/100" /></summary>
@@ -126,7 +124,7 @@ How do we solve this ? Developers love having framework overview by examples. It
</details><details>
<summary>
<img width="18" height="18" src="https://raw.githubusercontent.com/matschik/component-party/main/public/framework/angular.svg" />
<img width="18" height="18" src="public/framework/angular.svg" />
<b>Angular</b>
<img src="https://us-central1-progress-markdown.cloudfunctions.net/progress/100" /></summary>
@@ -160,7 +158,7 @@ How do we solve this ? Developers love having framework overview by examples. It
</details><details>
<summary>
<img width="18" height="18" src="https://raw.githubusercontent.com/matschik/component-party/main/public/framework/solid.svg" />
<img width="18" height="18" src="public/framework/solid.svg" />
<b>SolidJS</b>
<img src="https://us-central1-progress-markdown.cloudfunctions.net/progress/91" /></summary>
@@ -194,7 +192,7 @@ How do we solve this ? Developers love having framework overview by examples. It
</details><details>
<summary>
<img width="18" height="18" src="https://raw.githubusercontent.com/matschik/component-party/main/public/framework/lit.svg" />
<img width="18" height="18" src="public/framework/lit.svg" />
<b>Lit</b>
<img src="https://us-central1-progress-markdown.cloudfunctions.net/progress/5" /></summary>
@@ -226,6 +224,40 @@ How do we solve this ? Developers love having framework overview by examples. It
- [ ] Routing
- [ ] Router link
</details><details>
<summary>
<img width="18" height="18" src="public/framework/alpine.svg" />
<b>Alpine.js</b>
<img src="https://us-central1-progress-markdown.cloudfunctions.net/progress/86" /></summary>
- [x] Reactivity
- [x] Declare state
- [x] Update state
- [x] Computed state
- [x] Templating
- [x] Minimal template
- [x] Styling
- [x] Loop
- [x] Event click
- [x] Dom ref
- [x] Conditional
- [x] Lifecycle
- [x] On mount
- [x] On unmount
- [x] Component composition
- [x] Props
- [x] Emit to parent
- [x] Slot
- [x] Slot fallback
- [ ] Form input
- [x] Input text
- [x] Checkbox
- [x] Radio
- [ ] Select
- [ ] Webapp features
- [ ] Routing
- [ ] Router link
</details>
## Contributing
@@ -245,5 +277,5 @@ This project requires Node.js to be `v14.0.0` or higher, because we use new Java
1. Fork the project and create a new branch
2. Add the new framework SVG logo in `public/framework`
3. Install the ESLint plugin assiociated to the framework
3. Install the ESLint plugin associated to the framework
4. On `config.cjs` and `src/frameworks.js`, add a new entry with SVG link and ESLint configuration

View File

@@ -3,7 +3,7 @@ const FRAMEWORKS = [
id: 'svelte',
title: 'Svelte',
ext: 'svelte',
img: 'https://raw.githubusercontent.com/matschik/component-party/main/public/framework/svelte.svg',
img: 'framework/svelte.svg',
eslint: {
files: ['*.svelte'],
processor: 'svelte3/svelte3',
@@ -19,7 +19,7 @@ const FRAMEWORKS = [
id: 'react',
title: 'React',
ext: 'jsx',
img: 'https://raw.githubusercontent.com/matschik/component-party/main/public/framework/react.svg',
img: 'framework/react.svg',
eslint: {
files: ['**/react/*.jsx', '**/react/*.tsx'],
extends: ['eslint:recommended', 'plugin:react/recommended', 'plugin:react/jsx-runtime'],
@@ -39,7 +39,7 @@ const FRAMEWORKS = [
id: 'vue3',
title: 'Vue 3',
ext: 'vue',
img: 'https://raw.githubusercontent.com/matschik/component-party/main/public/framework/vue.svg',
img: 'framework/vue.svg',
eslint: {
files: ['*.vue'],
env: {
@@ -60,7 +60,7 @@ const FRAMEWORKS = [
id: 'angular',
title: 'Angular',
ext: 'ts',
img: 'https://raw.githubusercontent.com/matschik/component-party/main/public/framework/angular.svg',
img: 'framework/angular.svg',
eslint: [
{
files: ['**/angular/**'],
@@ -112,7 +112,7 @@ const FRAMEWORKS = [
id: 'solid',
title: 'SolidJS',
ext: 'jsx',
img: '/framework/solid.svg',
img: 'framework/solid.svg',
eslint: {
files: ['**/solid/*.jsx'],
plugins: ['solid'],
@@ -128,7 +128,7 @@ const FRAMEWORKS = [
id: 'lit',
title: 'Lit',
ext: 'js',
img: 'https://raw.githubusercontent.com/matschik/component-party/main/public/framework/lit.svg',
img: 'framework/lit.svg',
eslint: {
files: ['**/lit/**'],
plugins: ['lit'],
@@ -140,6 +140,21 @@ const FRAMEWORKS = [
return files;
},
},
{
id: 'alpine',
title: 'Alpine.js',
ext: 'alpine',
img: 'framework/alpine.svg',
eslint: {
files: ['**/alpine/**'],
extends: ['eslint:recommended'],
},
playgroundURL: 'https://codesandbox.io/s/alpinejs-sild2',
documentationURL: 'https://alpinejs.dev/start-here',
filesSorter(files) {
return files;
},
},
];
module.exports = { FRAMEWORKS };

View File

@@ -0,0 +1 @@
<h1 x-data="{ name: 'John' }" x-text="name"></h1>

View File

@@ -0,0 +1 @@
<h1 x-data="{ name: 'John' }" x-init="name = 'Jane'" x-text="name"></h1>

View File

@@ -0,0 +1,4 @@
<h1 x-data="{
count : 10,
get doubleCount() { return this.count * 2 }
}" x-text="doubleCount"></h1>

View File

@@ -0,0 +1 @@
<h1>Hello world</h1>

View File

@@ -0,0 +1,5 @@
<ul x-data="{ colors: ['red', 'green', 'blue'] }">
<template x-for="color in colors">
<li x-text="color"></li>
</template>
</ul>

View File

@@ -0,0 +1,5 @@
<ul x-data="{ colors: ['red', 'green', 'blue'] }">
<template x-for="color in colors">
<li x-text="color"></li>
</template>
</ul>

View File

@@ -0,0 +1,4 @@
<div x-data="{ count: 0 }">
<p>Counter: <span x-text="count"></span></p>
<button x-on:click="count++">+1</button>
</div>

View File

@@ -0,0 +1 @@
<input x-init="$el.focus();" />

View File

@@ -0,0 +1,21 @@
<div x-data="{
TRAFFIC_LIGHTS: ['red', 'orange', 'green'],
lightIndex: 0,
get light() { return this.TRAFFIC_LIGHTS[this.lightIndex] },
nextLight() {
if (this.lightIndex + 1 > this.TRAFFIC_LIGHTS.length - 1) {
this.lightIndex = 0
} else {
this.lightIndex++
}
}
}">
<button x-on:click="nextLight">Next light</button>
<p>Light is: <span x-text="light"></span></p>
<p>
You must
<span x-show="light === 'red'">STOP</span>
<span x-show="light === 'orange'">SLOW DOWN</span>
<span x-show="light === 'green'">GO</span>
</p>
</div>

View File

@@ -0,0 +1,3 @@
<p x-data="{ pageTitle: '' }" x-init="$nextTick(() => { pageTitle = document.title })">
Page title: <span x-text="pageTitle"></span>
</p>

View File

@@ -0,0 +1,6 @@
<p x-data="{
time: new Date().toLocaleTimeString(),
timer: null,
init() { this.timer = setInterval(() => (this.time = new Date().toLocaleTimeString()), 1000) },
destroy() { clearInterval(this.timer) }
}">Current time: <span x-text="time"></span></p>

View File

@@ -0,0 +1,13 @@
<!--Alpine JS suggests using a server-side templating engine or another frontend framework in conjunction with Alpine to do this-->
<div x-data="{
name: 'John',
age: 20,
favouriteColors: ['green', 'blue', 'red'],
isAvailable: true
}">
<p>My name is <span x-text="John"></span></p>
<p>My age is <span x-text="age"></span></p>
<p>My favourite colors are <span x-text="favouriteColors.join(', ')"></span></p>
<p>I am <span x-text="isAvailable ? 'available' : 'not available'"></span></p>
</div>

View File

@@ -0,0 +1,8 @@
<div x-data="{ canCome: true }" x-on:yes="canCome = true" x-on:no="canCome = false">
<p>Can I come ?</p>
<div>
<button x-on:click="$dispatch('yes')"> YES </button>
<button x-on:click="$dispatch('no')"> NO </button>
</div>
<p style="font-size: 50px;" x-text="canCome ? '😀' : '😥'"></p>
</div>

View File

@@ -0,0 +1,16 @@
<!--Alpine JS suggests using a server-side templating engine or another frontend framework in conjunction with Alpine to do this-->
<button x-data x-text="'Click me !'" style="
background: rgba(0, 0, 0, 0.4);
color: #fff;
padding: 10px 20px;
font-size: 30px;
border: 2px solid #fff;
margin: 8px;
transform: scale(0.9);
box-shadow: 4px 4px rgba(0, 0, 0, 0.4);
transition: transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s;
outline: 0;
">
<span>No content found</span>
</button>

View File

@@ -0,0 +1,31 @@
<!--Alpine JS suggests using a server-side templating engine or another frontend framework in conjunction with Alpine to do this-->
<button x-data style="
background: rgba(0, 0, 0, 0.4);
color: #fff;
padding: 10px 20px;
font-size: 30px;
border: 2px solid #fff;
margin: 8px;
transform: scale(0.9);
box-shadow: 4px 4px rgba(0, 0, 0, 0.4);
transition: transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s;
outline: 0;
">
<span>No content found</span>
</button>
<button x-data x-text="'I got content !'" style="
background: rgba(0, 0, 0, 0.4);
color: #fff;
padding: 10px 20px;
font-size: 30px;
border: 2px solid #fff;
margin: 8px;
transform: scale(0.9);
box-shadow: 4px 4px rgba(0, 0, 0, 0.4);
transition: transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s;
outline: 0;
">
<span>No content found</span>
</button>

View File

@@ -0,0 +1,4 @@
<div x-data="{ text: 'Hello World' }">
<p x-text="text"></p>
<input x-model="text" />
</div>

View File

@@ -0,0 +1,4 @@
<div x-data="{ isAvailable: true }">
<input id="is-available" x-model="isAvailable" type="checkbox" />
<label for="is-available">Is available</label>
</div>

View File

@@ -0,0 +1,15 @@
<div x-data="{
selectedColorId: 2,
colors: [
{ id: 1, text: 'red' },
{ id: 2, text: 'blue' },
{ id: 3, text: 'green' },
{ id: 4, text: 'gray', isDisabled: true }
]
}">
<select x-model.number="selectedColorId">
<template x-for="color in colors" x-bind:key="color.id">
<option x-text="color.text" x-bind:value="color.id" x-bind:disabled="!!color.isDisabled" x-bind:selected="color.id === selectedColorId"></option>
</template>
</select>
</div>

View File

@@ -38,6 +38,7 @@
"@typescript-eslint/parser": "^5.20.0",
"astro": "^1.0.0-beta.12",
"autoprefixer": "^10.4.4",
"codesandbox": "^2.2.3",
"eslint": "^8.13.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-lit": "^1.6.1",

1524
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 180 83" fill="none">
<path d="M139.553 0L179.425 39.6972L139.553 79.3944L99.6807 39.6972L139.553 0Z" fill="#77C1D2"/>
<path d="M39.8721 0L122.532 82.2973H42.7877L0 39.6972L39.8721 0Z" fill="#2D3441"/>
</svg>

After

Width:  |  Height:  |  Size: 261 B

View File

@@ -132,7 +132,7 @@ async function main() {
const percent = Math.ceil((allChecks.filter((v) => v).length / allChecks.length) * 100);
let frameworkContent = `<details>
<summary>
<img width="18" height="18" src="${framework.img}" />
<img width="18" height="18" src="public/${framework.img}" />
<b>${framework.title}</b>
<img src="https://us-central1-progress-markdown.cloudfunctions.net/progress/${percent}" /></summary>

View File

@@ -3,9 +3,11 @@ import FRAMEWORKS from '../frameworks';
const {id, size = 20} = Astro.props
const framework = FRAMEWORKS.find((f) => f.id === id);
const baseURL = import.meta.env.MODE === 'development' ? '' : 'https://raw.githubusercontent.com/matschik/component-party/main/public/';
---
<div class="flex items-center space-x-1">
{framework?.img && <img src={framework.img} alt={framework.id} width={size} height={size} class="inline mr-[5px] mb-0 mt-0" />}
{framework?.img && <img src={baseURL + framework.img} alt={framework.id} width={size} height={size} class="inline mr-[5px] mb-0 mt-0" />}
<span class="flex-shrink-0">{framework.title}</span>
</div>

View File

@@ -9,6 +9,7 @@ import FRAMEWORKS from '../frameworks';
import CodeViewer from "./CodeViewer.astro"
import createVue3REPL from "../utils/createVue3REPL"
import createSvelteREPL from "../utils/createSvelteREPL"
import createAlpineREPL from "../utils/createAlpineREPL"
const { path: sectionPath } = Astro.props
@@ -27,6 +28,7 @@ function capitalize(string) {
const vue3REPL = createVue3REPL()
const svelteREPL = createSvelteREPL()
const alpineREPL = createAlpineREPL()
function generatePlaygroundURL(frameworkId, files){
let playgroundURL
@@ -42,6 +44,12 @@ function generatePlaygroundURL(frameworkId, files){
return acc
}, {})
playgroundURL = svelteREPL.fromContentByFilename(contentByFilename)
} else if(frameworkId === 'alpine'){
const contentByFilename = files.reduce((acc, file) => {
acc[file.fileName] = { content: file.content }
return acc
}, {})
playgroundURL = alpineREPL.fromContentByFilename(contentByFilename)
}
return playgroundURL
}

View File

@@ -3,7 +3,7 @@ export default [
id: 'svelte',
title: 'Svelte',
ext: 'svelte',
img: 'https://raw.githubusercontent.com/matschik/component-party/main/public/framework/svelte.svg',
img: 'framework/svelte.svg',
eslint: {
files: ['*.svelte'],
processor: 'svelte3/svelte3',
@@ -19,7 +19,7 @@ export default [
id: 'react',
title: 'React',
ext: 'jsx',
img: 'https://raw.githubusercontent.com/matschik/component-party/main/public/framework/react.svg',
img: 'framework/react.svg',
eslint: {
files: ['**/react/*.jsx', '**/react/*.tsx'],
extends: ['eslint:recommended', 'plugin:react/recommended', 'plugin:react/jsx-runtime'],
@@ -39,7 +39,7 @@ export default [
id: 'vue3',
title: 'Vue 3',
ext: 'vue',
img: 'https://raw.githubusercontent.com/matschik/component-party/main/public/framework/vue.svg',
img: 'framework/vue.svg',
eslint: {
files: ['*.vue'],
env: {
@@ -60,7 +60,7 @@ export default [
id: 'angular',
title: 'Angular',
ext: 'ts',
img: 'https://raw.githubusercontent.com/matschik/component-party/main/public/framework/angular.svg',
img: 'framework/angular.svg',
eslint: [
{
files: ['**/angular/**'],
@@ -112,7 +112,7 @@ export default [
id: 'solid',
title: 'SolidJS',
ext: 'jsx',
img: 'https://raw.githubusercontent.com/matschik/component-party/main/public/framework/solid.svg',
img: 'framework/solid.svg',
eslint: {
files: ['**/solid/*.jsx'],
plugins: ['solid'],
@@ -128,7 +128,7 @@ export default [
id: 'lit',
title: 'Lit',
ext: 'js',
img: 'https://raw.githubusercontent.com/matschik/component-party/main/public/framework/lit.svg',
img: 'framework/lit.svg',
eslint: {
files: ['**/lit/**'],
plugins: ['lit'],
@@ -140,4 +140,19 @@ export default [
return files;
},
},
{
id: 'alpine',
title: 'Alpine.js',
ext: 'alpine',
img: 'framework/alpine.svg',
eslint: {
files: ['**/alpine/**'],
extends: ['eslint:recommended'],
},
playgroundURL: 'https://codesandbox.io/s/alpinejs-sild2',
documentationURL: 'https://alpinejs.dev/start-here',
filesSorter(files) {
return files;
},
},
];

View File

@@ -0,0 +1,34 @@
import { getParameters } from 'codesandbox/lib/api/define';
export default function createVue3REPL() {
const BASE_URL = 'https://codesandbox.io/api/v1/sandboxes/define?embed=1&parameters=';
const BASE_PREFIX = `<!DOCTYPE html>\n<html lang="en">\n <head>\n <meta charset="UTF-8" />\n <meta name="viewport" content="width=device-width, initial-scale=1.0" />\n <meta http-equiv="X-UA-Compatible" content="ie=edge" />\n <title>Alpine.js Playground</title>\n <script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>\n </head>\n <body>\n\n`;
const BASE_SUFFIX = `\n </body>\n</html>`;
function generateURLFromData(parameters) {
return `${BASE_URL}${parameters}`;
}
function fromContentByFilename(contentByFilename) {
const parameters = getParameters({
files: {
...contentByFilename,
'package.json': {
content: { dependencies: {} },
},
'index.html': {
content: BASE_PREFIX + (contentByFilename['index.html']?.content || '') + BASE_SUFFIX,
},
'sandbox.config.json': {
content: '{\n "template": "static"\n}',
},
},
});
return generateURLFromData(parameters);
}
return {
fromContentByFilename,
};
}