mirror of
https://github.com/lainbo/component-party.git
synced 2026-04-05 13:09:03 +08:00
feat: add Svelte 5 runes (#188)
This commit is contained in:
5
content/1-reactivity/1-declare-state/svelte5/Name.svelte
Normal file
5
content/1-reactivity/1-declare-state/svelte5/Name.svelte
Normal file
@@ -0,0 +1,5 @@
|
||||
<script>
|
||||
let name = $state("John");
|
||||
</script>
|
||||
|
||||
<h1>Hello {name}</h1>
|
||||
6
content/1-reactivity/2-update-state/svelte5/Name.svelte
Normal file
6
content/1-reactivity/2-update-state/svelte5/Name.svelte
Normal file
@@ -0,0 +1,6 @@
|
||||
<script>
|
||||
let name = $state("John");
|
||||
name = "Jane";
|
||||
</script>
|
||||
|
||||
<h1>Hello {name}</h1>
|
||||
@@ -0,0 +1,6 @@
|
||||
<script>
|
||||
let count = $state(10);
|
||||
const doubleCount = $derived(count * 2);
|
||||
</script>
|
||||
|
||||
<div>{doubleCount}</div>
|
||||
8
content/2-templating/2-styling/svelte5/CssStyle.svelte
Normal file
8
content/2-templating/2-styling/svelte5/CssStyle.svelte
Normal file
@@ -0,0 +1,8 @@
|
||||
<h1 class="title">I am red</h1>
|
||||
<button style="font-size: 10rem;">I am a button</button>
|
||||
|
||||
<style>
|
||||
.title {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
9
content/2-templating/3-loop/svelte5/Colors.svelte
Normal file
9
content/2-templating/3-loop/svelte5/Colors.svelte
Normal file
@@ -0,0 +1,9 @@
|
||||
<script>
|
||||
const colors = ["red", "green", "blue"];
|
||||
</script>
|
||||
|
||||
<ul>
|
||||
{#each colors as color (color)}
|
||||
<li>{color}</li>
|
||||
{/each}
|
||||
</ul>
|
||||
10
content/2-templating/4-event-click/svelte5/Counter.svelte
Normal file
10
content/2-templating/4-event-click/svelte5/Counter.svelte
Normal file
@@ -0,0 +1,10 @@
|
||||
<script>
|
||||
let count = $state(0);
|
||||
|
||||
function incrementCount() {
|
||||
count++;
|
||||
}
|
||||
</script>
|
||||
|
||||
<p>Counter: {count}</p>
|
||||
<button on:click={incrementCount}>+1</button>
|
||||
@@ -0,0 +1,9 @@
|
||||
<script>
|
||||
let inputElement;
|
||||
|
||||
$effect(() => {
|
||||
inputElement.focus();
|
||||
});
|
||||
</script>
|
||||
|
||||
<input bind:this={inputElement} />
|
||||
@@ -0,0 +1,23 @@
|
||||
<script>
|
||||
const TRAFFIC_LIGHTS = ["red", "orange", "green"];
|
||||
let lightIndex = $state(0);
|
||||
|
||||
const light = $derived(TRAFFIC_LIGHTS[lightIndex]);
|
||||
|
||||
function nextLight() {
|
||||
lightIndex = (lightIndex + 1) % TRAFFIC_LIGHTS.length;
|
||||
}
|
||||
</script>
|
||||
|
||||
<button on:click={nextLight}>Next light</button>
|
||||
<p>Light is: {light}</p>
|
||||
<p>
|
||||
You must
|
||||
{#if light === "red"}
|
||||
<span>STOP</span>
|
||||
{:else if light === "orange"}
|
||||
<span>SLOW DOWN</span>
|
||||
{:else if light === "green"}
|
||||
<span>GO</span>
|
||||
{/if}
|
||||
</p>
|
||||
8
content/3-lifecycle/1-on-mount/svelte5/PageTitle.svelte
Normal file
8
content/3-lifecycle/1-on-mount/svelte5/PageTitle.svelte
Normal file
@@ -0,0 +1,8 @@
|
||||
<script>
|
||||
let pageTitle = "";
|
||||
$effect(() => {
|
||||
pageTitle = document.title;
|
||||
});
|
||||
</script>
|
||||
|
||||
<p>Page title is: {pageTitle}</p>
|
||||
13
content/3-lifecycle/2-on-unmount/svelte5/Time.svelte
Normal file
13
content/3-lifecycle/2-on-unmount/svelte5/Time.svelte
Normal file
@@ -0,0 +1,13 @@
|
||||
<script>
|
||||
let time = $state(new Date().toLocaleTimeString());
|
||||
|
||||
$effect(() => {
|
||||
const timer = setInterval(() => {
|
||||
time = new Date().toLocaleTimeString();
|
||||
}, 1000);
|
||||
|
||||
return () => clearInterval(timer);
|
||||
});
|
||||
</script>
|
||||
|
||||
<p>Current time: {time}</p>
|
||||
10
content/4-component-composition/1-props/svelte5/App.svelte
Normal file
10
content/4-component-composition/1-props/svelte5/App.svelte
Normal file
@@ -0,0 +1,10 @@
|
||||
<script>
|
||||
import UserProfile from "./UserProfile.svelte";
|
||||
</script>
|
||||
|
||||
<UserProfile
|
||||
name="John"
|
||||
age={20}
|
||||
favouriteColors={["green", "blue", "red"]}
|
||||
isAvailable
|
||||
/>
|
||||
@@ -0,0 +1,13 @@
|
||||
<script>
|
||||
const {
|
||||
name = "",
|
||||
age = null,
|
||||
favouriteColors = [],
|
||||
isAvailable = false,
|
||||
} = $props();
|
||||
</script>
|
||||
|
||||
<p>My name is {name}!</p>
|
||||
<p>My age is {age}!</p>
|
||||
<p>My favourite colors are {favouriteColors.join(", ")}!</p>
|
||||
<p>I am {isAvailable ? "available" : "not available"}</p>
|
||||
@@ -0,0 +1,17 @@
|
||||
<script>
|
||||
import { createEventDispatcher } from "svelte";
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
function clickYes() {
|
||||
dispatch("yes");
|
||||
}
|
||||
|
||||
function clickNo() {
|
||||
dispatch("no");
|
||||
}
|
||||
</script>
|
||||
|
||||
<button on:click={clickYes}> YES </button>
|
||||
|
||||
<button on:click={clickNo}> NO </button>
|
||||
@@ -0,0 +1,17 @@
|
||||
<script>
|
||||
import AnswerButton from "./AnswerButton.svelte";
|
||||
|
||||
let isHappy = $state(true);
|
||||
|
||||
function onAnswerNo() {
|
||||
isHappy = false;
|
||||
}
|
||||
|
||||
function onAnswerYes() {
|
||||
isHappy = true;
|
||||
}
|
||||
</script>
|
||||
|
||||
<p>Are you happy?</p>
|
||||
<AnswerButton on:yes={onAnswerYes} on:no={onAnswerNo} />
|
||||
<p style="font-size: 50px;">{isHappy ? "😀" : "😥"}</p>
|
||||
@@ -0,0 +1,5 @@
|
||||
<script>
|
||||
import FunnyButton from "./FunnyButton.svelte";
|
||||
</script>
|
||||
|
||||
<FunnyButton>Click me!</FunnyButton>
|
||||
@@ -0,0 +1,5 @@
|
||||
<button
|
||||
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;"
|
||||
>
|
||||
<slot />
|
||||
</button>
|
||||
@@ -0,0 +1,6 @@
|
||||
<script>
|
||||
import FunnyButton from "./FunnyButton.svelte";
|
||||
</script>
|
||||
|
||||
<FunnyButton />
|
||||
<FunnyButton>I got content!</FunnyButton>
|
||||
@@ -0,0 +1,7 @@
|
||||
<button
|
||||
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;"
|
||||
>
|
||||
<slot>
|
||||
<span>No content found</span>
|
||||
</slot>
|
||||
</button>
|
||||
17
content/4-component-composition/5-context/svelte5/App.svelte
Normal file
17
content/4-component-composition/5-context/svelte5/App.svelte
Normal file
@@ -0,0 +1,17 @@
|
||||
<script>
|
||||
import { setContext } from "svelte";
|
||||
import UserProfile from "./UserProfile.svelte";
|
||||
import createUserState from "./createUserState.js";
|
||||
|
||||
// In a real app, you would fetch the user data from an API
|
||||
const user = createUserState({
|
||||
id: 1,
|
||||
username: "unicorn42",
|
||||
email: "unicorn42@example.com",
|
||||
});
|
||||
|
||||
setContext("user", user);
|
||||
</script>
|
||||
|
||||
<h1>Welcome back, {user.value.username}</h1>
|
||||
<UserProfile />
|
||||
@@ -0,0 +1,14 @@
|
||||
<script>
|
||||
import { getContext } from "svelte";
|
||||
|
||||
const user = getContext("user");
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<h2>My Profile</h2>
|
||||
<p>Username: {user.value.username}</p>
|
||||
<p>Email: {user.value.email}</p>
|
||||
<button on:click={() => user.updateUsername("Jane")}>
|
||||
Update username to Jane
|
||||
</button>
|
||||
</div>
|
||||
@@ -0,0 +1,14 @@
|
||||
export default function createUserState(initial) {
|
||||
let user = $state(initial);
|
||||
return {
|
||||
get value() {
|
||||
return user;
|
||||
},
|
||||
updateUsername(newUsername) {
|
||||
user = {
|
||||
...user,
|
||||
username: newUsername,
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<script>
|
||||
let text = $state("Hello World");
|
||||
</script>
|
||||
|
||||
<p>{text}</p>
|
||||
<input bind:value={text} />
|
||||
@@ -0,0 +1,6 @@
|
||||
<script>
|
||||
let isAvailable = $state(false);
|
||||
</script>
|
||||
|
||||
<input id="is-available" type="checkbox" bind:checked={isAvailable} />
|
||||
<label for="is-available">Is available</label>
|
||||
11
content/6-form-input/3-radio/svelte5/PickPill.svelte
Normal file
11
content/6-form-input/3-radio/svelte5/PickPill.svelte
Normal file
@@ -0,0 +1,11 @@
|
||||
<script>
|
||||
let picked = $state("red");
|
||||
</script>
|
||||
|
||||
<div>Picked: {picked}</div>
|
||||
|
||||
<input id="blue-pill" bind:group={picked} type="radio" value="blue" />
|
||||
<label for="blue-pill">Blue pill</label>
|
||||
|
||||
<input id="red-pill" bind:group={picked} type="radio" value="red" />
|
||||
<label for="red-pill">Red pill</label>
|
||||
18
content/6-form-input/4-select/svelte5/ColorSelect.svelte
Normal file
18
content/6-form-input/4-select/svelte5/ColorSelect.svelte
Normal file
@@ -0,0 +1,18 @@
|
||||
<script>
|
||||
let selectedColorId = $state(2);
|
||||
|
||||
const colors = [
|
||||
{ id: 1, text: "red" },
|
||||
{ id: 2, text: "blue" },
|
||||
{ id: 3, text: "green" },
|
||||
{ id: 4, text: "gray", isDisabled: true },
|
||||
];
|
||||
</script>
|
||||
|
||||
<select bind:value={selectedColorId}>
|
||||
{#each colors as color}
|
||||
<option value={color.id} disabled={color.isDisabled}>
|
||||
{color.text}
|
||||
</option>
|
||||
{/each}
|
||||
</select>
|
||||
@@ -0,0 +1 @@
|
||||
<h1>Hello world</h1>
|
||||
@@ -0,0 +1 @@
|
||||
<h1>Hello world</h1>
|
||||
7
content/7-webapp-features/1-render-app/svelte5/app.js
Normal file
7
content/7-webapp-features/1-render-app/svelte5/app.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import App from "./App.svelte";
|
||||
|
||||
const app = new App({
|
||||
target: document.getElementById("app"),
|
||||
});
|
||||
|
||||
export default app;
|
||||
@@ -0,0 +1,7 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="./app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
23
content/7-webapp-features/2-fetch-data/svelte5/App.svelte
Normal file
23
content/7-webapp-features/2-fetch-data/svelte5/App.svelte
Normal file
@@ -0,0 +1,23 @@
|
||||
<script>
|
||||
import useFetchUsers from "./useFetchUsers";
|
||||
|
||||
const response = useFetchUsers();
|
||||
</script>
|
||||
|
||||
{#if response.isLoading}
|
||||
<p>Fetching users...</p>
|
||||
{:else if response.error}
|
||||
<p>An error occured while fetching users</p>
|
||||
{:else if response.users}
|
||||
<ul>
|
||||
{#each response.users as user}
|
||||
<li>
|
||||
<img src={user.picture.thumbnail} alt="user" />
|
||||
<p>
|
||||
{user.name.first}
|
||||
{user.name.last}
|
||||
</p>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
@@ -0,0 +1,29 @@
|
||||
export default function useFetchUsers() {
|
||||
const users = $state();
|
||||
const error = $state();
|
||||
const isLoading = $state(false);
|
||||
|
||||
async function fetchData() {
|
||||
isLoading = true;
|
||||
try {
|
||||
const response = await fetch("https://randomuser.me/api/?results=3");
|
||||
users = (await response.json()).results;
|
||||
} catch (err) {
|
||||
error = err;
|
||||
}
|
||||
isLoading = false;
|
||||
}
|
||||
fetchData();
|
||||
|
||||
return {
|
||||
get isLoading() {
|
||||
return isLoading;
|
||||
},
|
||||
get error() {
|
||||
return error;
|
||||
},
|
||||
get users() {
|
||||
return users;
|
||||
},
|
||||
};
|
||||
}
|
||||
12
content/7-webapp-features/3-router-link/svelte5/sveltekit.md
Normal file
12
content/7-webapp-features/3-router-link/svelte5/sveltekit.md
Normal file
@@ -0,0 +1,12 @@
|
||||
With <a href="https://kit.svelte.dev/docs/routing#pages">SvelteKit</a>
|
||||
|
||||
```svelte
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/">Home</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/about">About us</a>
|
||||
</li>
|
||||
</ul>
|
||||
```
|
||||
10
content/7-webapp-features/4-routing/svelte5/sveltekit.md
Normal file
10
content/7-webapp-features/4-routing/svelte5/sveltekit.md
Normal file
@@ -0,0 +1,10 @@
|
||||
With <a href="https://kit.svelte.dev/docs/routing#pages">SvelteKit</a>
|
||||
|
||||
```
|
||||
|-- routes/
|
||||
|-- +page.svelte // index page "/"
|
||||
|-- about/
|
||||
|-- +page.svelte // about page "/about"
|
||||
|-- +error.svelte // handle HTTP errors 404, 500,...
|
||||
|-- +layout.svelte // global app layout
|
||||
```
|
||||
@@ -10,11 +10,11 @@ function sortAllFilenames(files, filenamesSorted) {
|
||||
|
||||
export default [
|
||||
{
|
||||
id: "svelte",
|
||||
title: "Svelte",
|
||||
id: "svelte4",
|
||||
title: "Svelte 4",
|
||||
img: "framework/svelte.svg",
|
||||
eslint: {
|
||||
files: ["*.svelte"],
|
||||
files: ["**/svelte4/*.svelte"],
|
||||
parser: "svelte-eslint-parser",
|
||||
},
|
||||
playgroundURL: "https://svelte.dev/repl",
|
||||
@@ -336,4 +336,20 @@ export default [
|
||||
repositoryLink: "https://github.com/aurelia/framework",
|
||||
mainPackageName: "aurelia-framework",
|
||||
},
|
||||
{
|
||||
id: "svelte5",
|
||||
title: "Svelte 5 (preview)",
|
||||
img: "framework/svelte.svg",
|
||||
eslint: {
|
||||
files: ["**/TODO-THIS-IS-DISABLED-svelte5/*.svelte"],
|
||||
parser: "svelte-eslint-parser",
|
||||
},
|
||||
playgroundURL: "https://svelte-5-preview.vercel.app/",
|
||||
documentationURL: "https://svelte-5-preview.vercel.app/docs",
|
||||
filesSorter(files) {
|
||||
return sortAllFilenames(files, ["index.html", "app.js", "App.svelte"]);
|
||||
},
|
||||
repositoryLink: "https://github.com/sveltejs/svelte",
|
||||
mainPackageName: "svelte",
|
||||
},
|
||||
];
|
||||
|
||||
@@ -85,7 +85,8 @@
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,jsx,ts,tsx,svelte,vue}": "eslint --cache --fix",
|
||||
"*.{js,jsx,ts,tsx,vue}": "eslint --cache --fix",
|
||||
"**/svelte4/*.svelte": "eslint --cache --fix",
|
||||
"*.{js,jsx,ts,tsx,svelte,vue,html,md,css,hbs}": "prettier --cache --write"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,12 +65,14 @@
|
||||
if (frameworkIdsSelectedOnInit.length === 0) {
|
||||
const frameworkIdsFromStorage = frameworkIdsStorage.getJSON();
|
||||
if (frameworkIdsFromStorage?.length > 0) {
|
||||
frameworkIdsSelectedOnInit = frameworkIdsFromStorage;
|
||||
frameworkIdsSelectedOnInit = frameworkIdsFromStorage.map((x) =>
|
||||
x === "svelte" ? "svelte4" : x
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (frameworkIdsSelectedOnInit.length === 0) {
|
||||
frameworkIdsSelectedOnInit = ["svelte", "react"];
|
||||
frameworkIdsSelectedOnInit = ["svelte4", "react"];
|
||||
}
|
||||
|
||||
frameworkIdsSelected = new Set(frameworkIdsSelectedOnInit);
|
||||
@@ -388,7 +390,9 @@
|
||||
margin-left: -0.87em;
|
||||
padding-right: 0.23em;
|
||||
font-weight: 500;
|
||||
transition: color 0.25s, opacity 0.25s;
|
||||
transition:
|
||||
color 0.25s,
|
||||
opacity 0.25s;
|
||||
opacity: 0;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user