Compare commits
361 Commits
sigpro-htm
...
af5bd1a537
| Author | SHA1 | Date | |
|---|---|---|---|
| af5bd1a537 | |||
| a792e72b63 | |||
| 13f7fba03c | |||
| 6b447b67a4 | |||
| a0711b3294 | |||
| f4654a938a | |||
| de4b09324d | |||
| a59d26f18a | |||
| 482ff19adb | |||
| f05511dad8 | |||
| 3d3de01aae | |||
| d166209ce6 | |||
| 2b786b290f | |||
| 3dde70d177 | |||
| df69877203 | |||
| 1c788f1dd1 | |||
| 99bf97a8d3 | |||
| b718fe20e4 | |||
| 8b45c84e67 | |||
| 2b86fec0ee | |||
| 7ba14217fb | |||
| 60682b3c60 | |||
| 4c2ef02e95 | |||
| 1a78879197 | |||
| d7bdfccb03 | |||
| dad4fc0aca | |||
| 8bdc86faf3 | |||
| 728abe0aa3 | |||
| 7d01ff13be | |||
| 49029b5eae | |||
| 91c72b6b9f | |||
| b472cb8921 | |||
| 5dbff9d499 | |||
| 1aee6a297d | |||
| 77b73cceef | |||
| 50d0d1319e | |||
| e203168ac1 | |||
| b21af833ac | |||
| b9207b1ddc | |||
| 51abd36724 | |||
| ef45d5f057 | |||
| f3f774fda1 | |||
| ac9527f9a3 | |||
| 9856eefa64 | |||
| 70e3c33bc8 | |||
| e06d5da447 | |||
| 9db278ea9b | |||
| 0aa57fb944 | |||
| 2e2a0b56f0 | |||
| bedd4ae225 | |||
| 1e470179ef | |||
| 4826892582 | |||
| c654c6ff1a | |||
| dc0dd14fd5 | |||
| f3b536e00e | |||
| 0fb71372ac | |||
| 4a8461903c | |||
| 9dd231fbc3 | |||
| 4d4f423ed7 | |||
| b835cd1992 | |||
| 9e469c975d | |||
| 873b3624c6 | |||
| f8fd9b4ae7 | |||
| 3ee77d4e9b | |||
| 32ab220ade | |||
| f50823c3cd | |||
| 71f2b2340b | |||
| 26d33c94bf | |||
| 5d3ab87940 | |||
| 5d3a9cdea4 | |||
| 80fa361da3 | |||
| 34c0b16595 | |||
| abeab4a8b6 | |||
| 5a0bec8837 | |||
| 0b124871fb | |||
| 0d119bcc35 | |||
| 8a71b86895 | |||
| c8e352ea96 | |||
| 73e019a582 | |||
| f14346cf39 | |||
| 14e4955acd | |||
| 23451f04df | |||
| 9f36e5e3fc | |||
| de607e3dda | |||
| 3000212961 | |||
| 541a3526a1 | |||
| 25188e7473 | |||
| 876d4c01f0 | |||
| 3c04a9433f | |||
| 5e90f62168 | |||
| 4a8959162c | |||
| 5a10974d0b | |||
| b8b42652d9 | |||
| 6f03422d64 | |||
| dc8568ae3a | |||
| f5bb657018 | |||
| 52ec5f46c3 | |||
| 64ead15875 | |||
| 43b8f4034c | |||
| a443d099ac | |||
| 8e4f071f52 | |||
| fb9b752cce | |||
| bc272e3d3c | |||
| 9adaeb5cae | |||
| 8b310805c3 | |||
| e40d39a26c | |||
| 59bf869686 | |||
| 1a8a33dd47 | |||
| 0ae2d56c37 | |||
| 45b34c9668 | |||
| 6d6c4ce703 | |||
| a43b624e00 | |||
| b7dbbd7add | |||
| 6d1539cf20 | |||
| e6b1f65055 | |||
| 205e5f5f06 | |||
| 1018c0bf9f | |||
| 0729f00fe2 | |||
| 1d09e8b382 | |||
| 7aac307af5 | |||
| bc23716280 | |||
| cf0e5b2913 | |||
| 627cfcd5d5 | |||
| d8ab8c75d8 | |||
| dcc669d6fe | |||
| f4032777a1 | |||
| 6ea0dcd3d7 | |||
| 5593c2e701 | |||
| 6813283c45 | |||
| f411c2e9bb | |||
| f38b3b4b46 | |||
| 9f524feb98 | |||
| 2e5142f073 | |||
| 8903be50ea | |||
| 3243f67431 | |||
| e9e0828206 | |||
| fbd9ddba47 | |||
| 03fe2a1b80 | |||
| b168761127 | |||
| 53fdaaa212 | |||
| 02ee84f8e5 | |||
| 9b9b345e48 | |||
| 9588bcbce8 | |||
| 52af01e128 | |||
| adafb8eb11 | |||
| 689febdbf4 | |||
| 98789b438b | |||
| 7a9c138b65 | |||
| d0c6663112 | |||
| ad96380e6f | |||
| 38b833e5c2 | |||
| 272c086e4f | |||
| 7350633a63 | |||
| d586af52b6 | |||
| d9cbbae40d | |||
| c4929e26e2 | |||
| 7879aa463b | |||
| d053ba39a1 | |||
| 215a3375b5 | |||
| 9c0acb83f8 | |||
| 557bd1428a | |||
| 4b5243052b | |||
| b2ba771b9c | |||
| 925a673775 | |||
| 2ac429c3f8 | |||
| 20022a361c | |||
| 150cad34d5 | |||
| fc148fdbcc | |||
| b75d1175a5 | |||
| 1e8b3ad803 | |||
| bfd79f8491 | |||
| a39d85ff89 | |||
| 9e36bb8041 | |||
| 75520a8499 | |||
| e9ca8d397b | |||
| 35bfbde6a7 | |||
| c56bdd4ba9 | |||
| 5f34c79fca | |||
| d15251c808 | |||
| 80ab4baf87 | |||
| 4e59bcb460 | |||
| d508a99290 | |||
| b2c6b8d398 | |||
| 4a9707819d | |||
| a0bebd41e5 | |||
| c1beda24ca | |||
| 59f464a70f | |||
| 5533cfe100 | |||
| b74903746f | |||
| c11d216c48 | |||
| 679c6a54c1 | |||
| 61635a23f7 | |||
| d864765359 | |||
| d632526597 | |||
| 3d2aca2b1f | |||
| 9069d44284 | |||
| 20d9023575 | |||
| bbae34dd38 | |||
| 86ba2f4db8 | |||
| e9be18a74a | |||
| d71dc7e2c1 | |||
| 42ea8424c1 | |||
| ebaccc0ce2 | |||
| f394a4720e | |||
| 7400d64f5a | |||
| 7b3621861e | |||
| 1716b0c80c | |||
| 7483700681 | |||
| f73432d5f7 | |||
| b5b0fb15ac | |||
| 74bfbe78f5 | |||
| 040dfffe8a | |||
| e6ab0a2052 | |||
| b3a8bcfa52 | |||
| 1bf92e7eda | |||
| ce34c2721f | |||
| 5312f5c194 | |||
| ff52f8e754 | |||
| 8204fd7fd1 | |||
| 53f7b7980d | |||
| 6060929a93 | |||
| 33be4d9448 | |||
| 37aab00ea9 | |||
| 323ab45f53 | |||
| 9666c3d034 | |||
| bf3069d439 | |||
| 5bbd2adf82 | |||
| 9e64161aa2 | |||
| 36bf11cf0a | |||
| c9db58363c | |||
| 7ec817ae8c | |||
| 1ee2788a73 | |||
| bc65d460f1 | |||
| 09f6f9d980 | |||
| 46e78818d5 | |||
| fa854647e3 | |||
| ad1a4ab84f | |||
| 203ff2a9da | |||
| ea9efa1367 | |||
| c69118c5a2 | |||
| 72b4e65162 | |||
|
|
5a92bd8cdf | ||
|
|
fd00b8d177 | ||
|
|
89de77e06c | ||
| f29d7d7571 | |||
| eec7765742 | |||
| e30d7925b5 | |||
| fe5d1946fe | |||
| 22ec847fdf | |||
| ebd69256f3 | |||
| e534825d83 | |||
| 087a5a3c6e | |||
| 80493ded82 | |||
| 05660fde2b | |||
| 196f82f240 | |||
| 6a51c9ef9b | |||
| 29c6451706 | |||
|
|
c0300e20d3 | ||
|
|
17f2d9866c | ||
| 022d75e262 | |||
| 1107b1e929 | |||
| 1fdc6657e7 | |||
| b9bcddaa12 | |||
| 13c7b3fc27 | |||
| e540099190 | |||
| 07948e8813 | |||
| 7e696d1d3d | |||
|
|
f62d7b2cf7 | ||
|
|
81f152ed95 | ||
|
|
df0d90cb9a | ||
|
|
bc2f688dcf | ||
|
|
f5f8e75527 | ||
| d0ffb69b95 | |||
|
|
770b1073dc | ||
|
|
787cf0ec3f | ||
|
|
c4005a903d | ||
|
|
e509cf3e5d | ||
|
|
9a9505528e | ||
| 5f19a62936 | |||
|
|
76081089c4 | ||
|
|
25d58d44d7 | ||
| c76afa7856 | |||
| 474c28bd01 | |||
| 9405875c13 | |||
| 49ec5399e3 | |||
| bf9a765b08 | |||
|
|
eacf4ff0ed | ||
|
|
bc638c7647 | ||
|
|
48e328d28a | ||
|
|
74441fb502 | ||
|
|
df9cd0c234 | ||
|
|
87b468454c | ||
|
|
62d872bec3 | ||
|
|
f35e04d666 | ||
|
|
1e27bfd987 | ||
|
|
091da9a8c1 | ||
|
|
8be3c24c28 | ||
|
|
39ae486f4e | ||
|
|
d5f3fddf4e | ||
|
|
f20b974114 | ||
|
|
aef353a983 | ||
|
|
002c37c632 | ||
|
|
351df2c503 | ||
|
|
9d5abe676c | ||
|
|
ec36f44fb6 | ||
|
|
2123ef2a0d | ||
|
|
5a502a7461 | ||
|
|
feea3971d4 | ||
|
|
7dbb681eba | ||
|
|
aecb44ea4c | ||
|
|
6bcd7f96eb | ||
|
|
794d53e85e | ||
|
|
978b34c39d | ||
| 34ecffbcf9 | |||
| 6d25d3929a | |||
|
|
b367b097e6 | ||
|
|
70c5a2d992 | ||
| 2b5b47ffe6 | |||
| 0809d4666c | |||
| dadc3bd23a | |||
| f3aa49a100 | |||
| 25481a2201 | |||
| d4fc935490 | |||
| 506e00282b | |||
| 110e2b1c50 | |||
| 33c886d32b | |||
| 6350509abd | |||
| 9e59377055 | |||
| 5701906e06 | |||
| c76950b3f8 | |||
| 95cdc2ca63 | |||
| ba5cbdb4a4 | |||
| 1424c42aea | |||
| ffbf7c9c5e | |||
| 656dde09ba | |||
| 1f2229ddda | |||
| b5da486820 | |||
| 72ea1fbaab | |||
| 617a5d32c6 | |||
| 90ff065f6d | |||
| 26177b7c4f | |||
| 5ab0837400 | |||
| 876874c2f0 | |||
|
|
adfe628dfd | ||
|
|
b1ee605e71 | ||
| 58f6876261 | |||
| 5d799608a3 | |||
| 44b8fa4a21 | |||
| 6479a559ef | |||
| 2e1617ebe2 | |||
| 8b742bd11a | |||
| f469d384cd | |||
| a285f2550c | |||
| 7630217643 | |||
| eaf1018dda | |||
| e60c1f69b4 | |||
| 11a6c97cc5 | |||
| 9e5b520e91 | |||
| 99c5625b43 | |||
| 36b853a673 | |||
| b95af97596 |
38
.github/workflows/deploy-docs.yaml
vendored
Normal file
38
.github/workflows/deploy-docs.yaml
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
name: Deploy Docs to Synology
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
paths:
|
||||||
|
- 'docs/**'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: node:20-bullseye
|
||||||
|
options: >-
|
||||||
|
--dns 192.168.1.1
|
||||||
|
--add-host git.natxocc.com:host-gateway
|
||||||
|
--add-host gitea:host-gateway
|
||||||
|
-v /volume1/webdocs/sigpro:/mnt/nas_docs # <--- Cambiamos el nombre interno
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout código
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 1
|
||||||
|
env:
|
||||||
|
# Mantenemos tu configuración original que SÍ llegaba a conectar
|
||||||
|
GIT_CONFIG_PARAMETERS: "'url.https://git.natxocc.com/.insteadOf=http://gitea:3000/'"
|
||||||
|
|
||||||
|
- name: Copiar archivos
|
||||||
|
run: |
|
||||||
|
# Copiamos a la ruta montada
|
||||||
|
cp -r docs/. /mnt/nas_docs/
|
||||||
|
|
||||||
|
# Esta es la prueba real. Si esto sale en el log y el runner
|
||||||
|
# está en modo 'privileged', los verás en el File Station.
|
||||||
|
ls -la /mnt/nas_docs
|
||||||
46
.github/workflows/publish-gitea.yml
vendored
Normal file
46
.github/workflows/publish-gitea.yml
vendored
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
name: Publicar Paquete SigPro (NPM)
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
publish:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: node:20-bullseye
|
||||||
|
options: >-
|
||||||
|
--dns 192.168.1.1
|
||||||
|
--add-host git.natxocc.com:host-gateway
|
||||||
|
--add-host gitea:host-gateway
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout código
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
env:
|
||||||
|
# ESTO ES LO QUE NO DEBÍ QUITAR: El mapeo de la URL interna a la externa
|
||||||
|
GIT_CONFIG_PARAMETERS: "'url.https://git.natxocc.com/.insteadOf=http://gitea:3000/'"
|
||||||
|
|
||||||
|
- name: Instalar Bun
|
||||||
|
run: |
|
||||||
|
curl -fsSL https://bun.sh/install | bash
|
||||||
|
echo "$HOME/.bun/bin" >> $GITHUB_PATH
|
||||||
|
|
||||||
|
- name: Instalar y Build
|
||||||
|
run: |
|
||||||
|
export PATH="$HOME/.bun/bin:$PATH"
|
||||||
|
bun install
|
||||||
|
bun run build
|
||||||
|
|
||||||
|
- name: Configurar Registro y Publicar
|
||||||
|
run: |
|
||||||
|
# 1. Definimos la URL del registro
|
||||||
|
REGISTRY="git.natxocc.com/api/packages/natxocc/npm/"
|
||||||
|
|
||||||
|
# 2. Configuramos el .npmrc usando tu secreto PACK_TOKEN
|
||||||
|
echo "//${REGISTRY}:_authToken=${{ secrets.PACK_TOKEN }}" > ~/.npmrc
|
||||||
|
|
||||||
|
# 3. Publicamos
|
||||||
|
npm publish --registry "https://${REGISTRY}" --userconfig ~/.npmrc
|
||||||
40
.github/workflows/publish.yml
vendored
40
.github/workflows/publish.yml
vendored
@@ -2,24 +2,42 @@ name: Publish to NPM
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
release:
|
release:
|
||||||
types: [created] # Se dispara cuando creas una "Release" en GitHub
|
types: [published]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: node:20-bullseye
|
||||||
|
options: >-
|
||||||
|
--dns 192.168.1.1
|
||||||
|
--add-host git.natxocc.com:host-gateway
|
||||||
|
--add-host gitea:host-gateway
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- name: Forzar Dominio Limpio
|
||||||
|
run: |
|
||||||
|
# Redirigimos cualquier intento (IP o nombre interno) al dominio limpio
|
||||||
|
git config --global url."http://git.natxocc.com/".insteadOf "http://gitea:3000/"
|
||||||
|
git config --global url."http://git.natxocc.com/".insteadOf "http://192.168.1.100:3333/"
|
||||||
|
|
||||||
|
git config --global --add safe.directory /workspace/natxocc/sigpro
|
||||||
|
git config --global http.sslVerify false
|
||||||
|
|
||||||
|
- name: Checkout código
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 1
|
||||||
|
env:
|
||||||
|
GIT_CONFIG_PARAMETERS: "'url.https://git.natxocc.com/.insteadOf=http://gitea:3000/'"
|
||||||
|
|
||||||
# Usamos Bun ya que tu proyecto lo usa
|
|
||||||
- uses: oven-sh/setup-bun@v1
|
- uses: oven-sh/setup-bun@v1
|
||||||
with:
|
with:
|
||||||
bun-version: latest
|
bun-version: latest
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install & Publish
|
||||||
run: bun install
|
run: |
|
||||||
|
bun install
|
||||||
- name: Authenticate with NPM
|
echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > .npmrc
|
||||||
run: echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > .npmrc
|
npm publish --access public
|
||||||
|
env:
|
||||||
- name: Publish to NPM
|
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
run: npm publish --access public
|
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -3,13 +3,13 @@ node_modules/
|
|||||||
jspm_packages/
|
jspm_packages/
|
||||||
|
|
||||||
# Build and Distribution
|
# Build and Distribution
|
||||||
dist/
|
|
||||||
lib-cov/
|
lib-cov/
|
||||||
coverage/
|
coverage/
|
||||||
*.lcov
|
*.lcov
|
||||||
.cache/
|
.cache/
|
||||||
.parcel-cache/
|
.parcel-cache/
|
||||||
.turbo/
|
.turbo/
|
||||||
|
*.lock
|
||||||
|
|
||||||
# Logs
|
# Logs
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
|
|||||||
510
bun.lock
510
bun.lock
@@ -1,510 +0,0 @@
|
|||||||
{
|
|
||||||
"lockfileVersion": 1,
|
|
||||||
"configVersion": 1,
|
|
||||||
"workspaces": {
|
|
||||||
"": {
|
|
||||||
"name": "sigpro",
|
|
||||||
"dependencies": {
|
|
||||||
"daisyui": "^5.5.19",
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@tailwindcss/vite": "^4.2.2",
|
|
||||||
"vite": "^8.0.0",
|
|
||||||
"vitepress": "^1.6.4",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"packages": {
|
|
||||||
"@algolia/abtesting": ["@algolia/abtesting@1.15.2", "", { "dependencies": { "@algolia/client-common": "5.49.2", "@algolia/requester-browser-xhr": "5.49.2", "@algolia/requester-fetch": "5.49.2", "@algolia/requester-node-http": "5.49.2" } }, "sha512-rF7vRVE61E0QORw8e2NNdnttcl3jmFMWS9B4hhdga12COe+lMa26bQLfcBn/Nbp9/AF/8gXdaRCPsVns3CnjsA=="],
|
|
||||||
|
|
||||||
"@algolia/autocomplete-core": ["@algolia/autocomplete-core@1.17.7", "", { "dependencies": { "@algolia/autocomplete-plugin-algolia-insights": "1.17.7", "@algolia/autocomplete-shared": "1.17.7" } }, "sha512-BjiPOW6ks90UKl7TwMv7oNQMnzU+t/wk9mgIDi6b1tXpUek7MW0lbNOUHpvam9pe3lVCf4xPFT+lK7s+e+fs7Q=="],
|
|
||||||
|
|
||||||
"@algolia/autocomplete-plugin-algolia-insights": ["@algolia/autocomplete-plugin-algolia-insights@1.17.7", "", { "dependencies": { "@algolia/autocomplete-shared": "1.17.7" }, "peerDependencies": { "search-insights": ">= 1 < 3" } }, "sha512-Jca5Ude6yUOuyzjnz57og7Et3aXjbwCSDf/8onLHSQgw1qW3ALl9mrMWaXb5FmPVkV3EtkD2F/+NkT6VHyPu9A=="],
|
|
||||||
|
|
||||||
"@algolia/autocomplete-preset-algolia": ["@algolia/autocomplete-preset-algolia@1.17.7", "", { "dependencies": { "@algolia/autocomplete-shared": "1.17.7" }, "peerDependencies": { "@algolia/client-search": ">= 4.9.1 < 6", "algoliasearch": ">= 4.9.1 < 6" } }, "sha512-ggOQ950+nwbWROq2MOCIL71RE0DdQZsceqrg32UqnhDz8FlO9rL8ONHNsI2R1MH0tkgVIDKI/D0sMiUchsFdWA=="],
|
|
||||||
|
|
||||||
"@algolia/autocomplete-shared": ["@algolia/autocomplete-shared@1.17.7", "", { "peerDependencies": { "@algolia/client-search": ">= 4.9.1 < 6", "algoliasearch": ">= 4.9.1 < 6" } }, "sha512-o/1Vurr42U/qskRSuhBH+VKxMvkkUVTLU6WZQr+L5lGZZLYWyhdzWjW0iGXY7EkwRTjBqvN2EsR81yCTGV/kmg=="],
|
|
||||||
|
|
||||||
"@algolia/client-abtesting": ["@algolia/client-abtesting@5.49.2", "", { "dependencies": { "@algolia/client-common": "5.49.2", "@algolia/requester-browser-xhr": "5.49.2", "@algolia/requester-fetch": "5.49.2", "@algolia/requester-node-http": "5.49.2" } }, "sha512-XyvKCm0RRmovMI/ChaAVjTwpZhXdbgt3iZofK914HeEHLqD1MUFFVLz7M0+Ou7F56UkHXwRbpHwb9xBDNopprQ=="],
|
|
||||||
|
|
||||||
"@algolia/client-analytics": ["@algolia/client-analytics@5.49.2", "", { "dependencies": { "@algolia/client-common": "5.49.2", "@algolia/requester-browser-xhr": "5.49.2", "@algolia/requester-fetch": "5.49.2", "@algolia/requester-node-http": "5.49.2" } }, "sha512-jq/3qvtmj3NijZlhq7A1B0Cl41GfaBpjJxcwukGsYds6aMSCWrEAJ9pUqw/C9B3hAmILYKl7Ljz3N9SFvekD3Q=="],
|
|
||||||
|
|
||||||
"@algolia/client-common": ["@algolia/client-common@5.49.2", "", {}, "sha512-bn0biLequn3epobCfjUqCxlIlurLr4RHu7RaE4trgN+RDcUq6HCVC3/yqq1hwbNYpVtulnTOJzcaxYlSr1fnuw=="],
|
|
||||||
|
|
||||||
"@algolia/client-insights": ["@algolia/client-insights@5.49.2", "", { "dependencies": { "@algolia/client-common": "5.49.2", "@algolia/requester-browser-xhr": "5.49.2", "@algolia/requester-fetch": "5.49.2", "@algolia/requester-node-http": "5.49.2" } }, "sha512-z14wfFs1T3eeYbCArC8pvntAWsPo9f6hnUGoj8IoRUJTwgJiiySECkm8bmmV47/x0oGHfsVn3kBdjMX0yq0sNA=="],
|
|
||||||
|
|
||||||
"@algolia/client-personalization": ["@algolia/client-personalization@5.49.2", "", { "dependencies": { "@algolia/client-common": "5.49.2", "@algolia/requester-browser-xhr": "5.49.2", "@algolia/requester-fetch": "5.49.2", "@algolia/requester-node-http": "5.49.2" } }, "sha512-GpRf7yuuAX93+Qt0JGEJZwgtL0MFdjFO9n7dn8s2pA9mTjzl0Sc5+uTk1VPbIAuf7xhCP9Mve+URGb6J+EYxgA=="],
|
|
||||||
|
|
||||||
"@algolia/client-query-suggestions": ["@algolia/client-query-suggestions@5.49.2", "", { "dependencies": { "@algolia/client-common": "5.49.2", "@algolia/requester-browser-xhr": "5.49.2", "@algolia/requester-fetch": "5.49.2", "@algolia/requester-node-http": "5.49.2" } }, "sha512-HZwApmNkp0DiAjZcLYdQLddcG4Agb88OkojiAHGgcm5DVXobT5uSZ9lmyrbw/tmQBJwgu2CNw4zTyXoIB7YbPA=="],
|
|
||||||
|
|
||||||
"@algolia/client-search": ["@algolia/client-search@5.49.2", "", { "dependencies": { "@algolia/client-common": "5.49.2", "@algolia/requester-browser-xhr": "5.49.2", "@algolia/requester-fetch": "5.49.2", "@algolia/requester-node-http": "5.49.2" } }, "sha512-y1IOpG6OSmTpGg/CT0YBb/EAhR2nsC18QWp9Jy8HO9iGySpcwaTvs5kHa17daP3BMTwWyaX9/1tDTDQshZzXdg=="],
|
|
||||||
|
|
||||||
"@algolia/ingestion": ["@algolia/ingestion@1.49.2", "", { "dependencies": { "@algolia/client-common": "5.49.2", "@algolia/requester-browser-xhr": "5.49.2", "@algolia/requester-fetch": "5.49.2", "@algolia/requester-node-http": "5.49.2" } }, "sha512-YYJRjaZ2bqk923HxE4um7j/Cm3/xoSkF2HC2ZweOF8cXL3sqnlndSUYmCaxHFjNPWLaSHk2IfssX6J/tdKTULw=="],
|
|
||||||
|
|
||||||
"@algolia/monitoring": ["@algolia/monitoring@1.49.2", "", { "dependencies": { "@algolia/client-common": "5.49.2", "@algolia/requester-browser-xhr": "5.49.2", "@algolia/requester-fetch": "5.49.2", "@algolia/requester-node-http": "5.49.2" } }, "sha512-9WgH+Dha39EQQyGKCHlGYnxW/7W19DIrEbCEbnzwAMpGAv1yTWCHMPXHxYa+LcL3eCp2V/5idD1zHNlIKmHRHg=="],
|
|
||||||
|
|
||||||
"@algolia/recommend": ["@algolia/recommend@5.49.2", "", { "dependencies": { "@algolia/client-common": "5.49.2", "@algolia/requester-browser-xhr": "5.49.2", "@algolia/requester-fetch": "5.49.2", "@algolia/requester-node-http": "5.49.2" } }, "sha512-K7Gp5u+JtVYgaVpBxF5rGiM+Ia8SsMdcAJMTDV93rwh00DKNllC19o1g+PwrDjDvyXNrnTEbofzbTs2GLfFyKA=="],
|
|
||||||
|
|
||||||
"@algolia/requester-browser-xhr": ["@algolia/requester-browser-xhr@5.49.2", "", { "dependencies": { "@algolia/client-common": "5.49.2" } }, "sha512-3UhYCcWX6fbtN8ABcxZlhaQEwXFh3CsFtARyyadQShHMPe3mJV9Wel4FpJTa+seugRkbezFz0tt6aPTZSYTBuA=="],
|
|
||||||
|
|
||||||
"@algolia/requester-fetch": ["@algolia/requester-fetch@5.49.2", "", { "dependencies": { "@algolia/client-common": "5.49.2" } }, "sha512-G94VKSGbsr+WjsDDOBe5QDQ82QYgxvpxRGJfCHZBnYKYsy/jv9qGIDb93biza+LJWizQBUtDj7bZzp3QZyzhPQ=="],
|
|
||||||
|
|
||||||
"@algolia/requester-node-http": ["@algolia/requester-node-http@5.49.2", "", { "dependencies": { "@algolia/client-common": "5.49.2" } }, "sha512-UuihBGHafG/ENsrcTGAn5rsOffrCIRuHMOsD85fZGLEY92ate+BMTUqxz60dv5zerh8ZumN4bRm8eW2z9L11jA=="],
|
|
||||||
|
|
||||||
"@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
|
|
||||||
|
|
||||||
"@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="],
|
|
||||||
|
|
||||||
"@babel/parser": ["@babel/parser@7.29.2", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": "./bin/babel-parser.js" }, "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA=="],
|
|
||||||
|
|
||||||
"@babel/types": ["@babel/types@7.29.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="],
|
|
||||||
|
|
||||||
"@docsearch/css": ["@docsearch/css@3.8.2", "", {}, "sha512-y05ayQFyUmCXze79+56v/4HpycYF3uFqB78pLPrSV5ZKAlDuIAAJNhaRi8tTdRNXh05yxX/TyNnzD6LwSM89vQ=="],
|
|
||||||
|
|
||||||
"@docsearch/js": ["@docsearch/js@3.8.2", "", { "dependencies": { "@docsearch/react": "3.8.2", "preact": "^10.0.0" } }, "sha512-Q5wY66qHn0SwA7Taa0aDbHiJvaFJLOJyHmooQ7y8hlwwQLQ/5WwCcoX0g7ii04Qi2DJlHsd0XXzJ8Ypw9+9YmQ=="],
|
|
||||||
|
|
||||||
"@docsearch/react": ["@docsearch/react@3.8.2", "", { "dependencies": { "@algolia/autocomplete-core": "1.17.7", "@algolia/autocomplete-preset-algolia": "1.17.7", "@docsearch/css": "3.8.2", "algoliasearch": "^5.14.2" }, "peerDependencies": { "@types/react": ">= 16.8.0 < 19.0.0", "react": ">= 16.8.0 < 19.0.0", "react-dom": ">= 16.8.0 < 19.0.0", "search-insights": ">= 1 < 3" }, "optionalPeers": ["@types/react", "react", "react-dom", "search-insights"] }, "sha512-xCRrJQlTt8N9GU0DG4ptwHRkfnSnD/YpdeaXe02iKfqs97TkZJv60yE+1eq/tjPcVnTW8dP5qLP7itifFVV5eg=="],
|
|
||||||
|
|
||||||
"@emnapi/core": ["@emnapi/core@1.9.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.0", "tslib": "^2.4.0" } }, "sha512-0DQ98G9ZQZOxfUcQn1waV2yS8aWdZ6kJMbYCJB3oUBecjWYO1fqJ+a1DRfPF3O5JEkwqwP1A9QEN/9mYm2Yd0w=="],
|
|
||||||
|
|
||||||
"@emnapi/runtime": ["@emnapi/runtime@1.9.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-QN75eB0IH2ywSpRpNddCRfQIhmJYBCJ1x5Lb3IscKAL8bMnVAKnRg8dCoXbHzVLLH7P38N2Z3mtulB7W0J0FKw=="],
|
|
||||||
|
|
||||||
"@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg=="],
|
|
||||||
|
|
||||||
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="],
|
|
||||||
|
|
||||||
"@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="],
|
|
||||||
|
|
||||||
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.21.5", "", { "os": "android", "cpu": "arm64" }, "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A=="],
|
|
||||||
|
|
||||||
"@esbuild/android-x64": ["@esbuild/android-x64@0.21.5", "", { "os": "android", "cpu": "x64" }, "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA=="],
|
|
||||||
|
|
||||||
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.21.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ=="],
|
|
||||||
|
|
||||||
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.21.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw=="],
|
|
||||||
|
|
||||||
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.21.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g=="],
|
|
||||||
|
|
||||||
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.21.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ=="],
|
|
||||||
|
|
||||||
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.21.5", "", { "os": "linux", "cpu": "arm" }, "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA=="],
|
|
||||||
|
|
||||||
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.21.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q=="],
|
|
||||||
|
|
||||||
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.21.5", "", { "os": "linux", "cpu": "ia32" }, "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg=="],
|
|
||||||
|
|
||||||
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg=="],
|
|
||||||
|
|
||||||
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg=="],
|
|
||||||
|
|
||||||
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.21.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w=="],
|
|
||||||
|
|
||||||
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA=="],
|
|
||||||
|
|
||||||
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.21.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A=="],
|
|
||||||
|
|
||||||
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.21.5", "", { "os": "linux", "cpu": "x64" }, "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ=="],
|
|
||||||
|
|
||||||
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.21.5", "", { "os": "none", "cpu": "x64" }, "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg=="],
|
|
||||||
|
|
||||||
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.21.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow=="],
|
|
||||||
|
|
||||||
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.21.5", "", { "os": "sunos", "cpu": "x64" }, "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg=="],
|
|
||||||
|
|
||||||
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.21.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A=="],
|
|
||||||
|
|
||||||
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.21.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA=="],
|
|
||||||
|
|
||||||
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="],
|
|
||||||
|
|
||||||
"@iconify-json/simple-icons": ["@iconify-json/simple-icons@1.2.74", "", { "dependencies": { "@iconify/types": "*" } }, "sha512-yqaohfY6jnYjTVpuTkaBQHrWbdUrQyWXhau0r/0EZiNWYXPX/P8WWwl1DoLH5CbvDjjcWQw5J0zADhgCUklOqA=="],
|
|
||||||
|
|
||||||
"@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="],
|
|
||||||
|
|
||||||
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
|
|
||||||
|
|
||||||
"@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],
|
|
||||||
|
|
||||||
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
|
|
||||||
|
|
||||||
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
|
|
||||||
|
|
||||||
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
|
|
||||||
|
|
||||||
"@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.1", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" } }, "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A=="],
|
|
||||||
|
|
||||||
"@oxc-project/runtime": ["@oxc-project/runtime@0.115.0", "", {}, "sha512-Rg8Wlt5dCbXhQnsXPrkOjL1DTSvXLgb2R/KYfnf1/K+R0k6UMLEmbQXPM+kwrWqSmWA2t0B1EtHy2/3zikQpvQ=="],
|
|
||||||
|
|
||||||
"@oxc-project/types": ["@oxc-project/types@0.115.0", "", {}, "sha512-4n91DKnebUS4yjUHl2g3/b2T+IUdCfmoZGhmwsovZCDaJSs+QkVAM+0AqqTxHSsHfeiMuueT75cZaZcT/m0pSw=="],
|
|
||||||
|
|
||||||
"@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-rc.9", "", { "os": "android", "cpu": "arm64" }, "sha512-lcJL0bN5hpgJfSIz/8PIf02irmyL43P+j1pTCfbD1DbLkmGRuFIA4DD3B3ZOvGqG0XiVvRznbKtN0COQVaKUTg=="],
|
|
||||||
|
|
||||||
"@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-rc.9", "", { "os": "darwin", "cpu": "arm64" }, "sha512-J7Zk3kLYFsLtuH6U+F4pS2sYVzac0qkjcO5QxHS7OS7yZu2LRs+IXo+uvJ/mvpyUljDJ3LROZPoQfgBIpCMhdQ=="],
|
|
||||||
|
|
||||||
"@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-rc.9", "", { "os": "darwin", "cpu": "x64" }, "sha512-iwtmmghy8nhfRGeNAIltcNXzD0QMNaaA5U/NyZc1Ia4bxrzFByNMDoppoC+hl7cDiUq5/1CnFthpT9n+UtfFyg=="],
|
|
||||||
|
|
||||||
"@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-rc.9", "", { "os": "freebsd", "cpu": "x64" }, "sha512-DLFYI78SCiZr5VvdEplsVC2Vx53lnA4/Ga5C65iyldMVaErr86aiqCoNBLl92PXPfDtUYjUh+xFFor40ueNs4Q=="],
|
|
||||||
|
|
||||||
"@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.9", "", { "os": "linux", "cpu": "arm" }, "sha512-CsjTmTwd0Hri6iTw/DRMK7kOZ7FwAkrO4h8YWKoX/kcj833e4coqo2wzIFywtch/8Eb5enQ/lwLM7w6JX1W5RQ=="],
|
|
||||||
|
|
||||||
"@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-rc.9", "", { "os": "linux", "cpu": "arm64" }, "sha512-2x9O2JbSPxpxMDhP9Z74mahAStibTlrBMW0520+epJH5sac7/LwZW5Bmg/E6CXuEF53JJFW509uP+lSedaUNxg=="],
|
|
||||||
|
|
||||||
"@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-rc.9", "", { "os": "linux", "cpu": "arm64" }, "sha512-JA1QRW31ogheAIRhIg9tjMfsYbglXXYGNPLdPEYrwFxdbkQCAzvpSCSHCDWNl4hTtrol8WeboCSEpjdZK8qrCg=="],
|
|
||||||
|
|
||||||
"@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.9", "", { "os": "linux", "cpu": "ppc64" }, "sha512-aOKU9dJheda8Kj8Y3w9gnt9QFOO+qKPAl8SWd7JPHP+Cu0EuDAE5wokQubLzIDQWg2myXq2XhTpOVS07qqvT+w=="],
|
|
||||||
|
|
||||||
"@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.0.0-rc.9", "", { "os": "linux", "cpu": "s390x" }, "sha512-OalO94fqj7IWRn3VdXWty75jC5dk4C197AWEuMhIpvVv2lw9fiPhud0+bW2ctCxb3YoBZor71QHbY+9/WToadA=="],
|
|
||||||
|
|
||||||
"@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-rc.9", "", { "os": "linux", "cpu": "x64" }, "sha512-cVEl1vZtBsBZna3YMjGXNvnYYrOJ7RzuWvZU0ffvJUexWkukMaDuGhUXn0rjnV0ptzGVkvc+vW9Yqy6h8YX4pg=="],
|
|
||||||
|
|
||||||
"@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-rc.9", "", { "os": "linux", "cpu": "x64" }, "sha512-UzYnKCIIc4heAKgI4PZ3dfBGUZefGCJ1TPDuLHoCzgrMYPb5Rv6TLFuYtyM4rWyHM7hymNdsg5ik2C+UD9VDbA=="],
|
|
||||||
|
|
||||||
"@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-rc.9", "", { "os": "none", "cpu": "arm64" }, "sha512-+6zoiF+RRyf5cdlFQP7nm58mq7+/2PFaY2DNQeD4B87N36JzfF/l9mdBkkmTvSYcYPE8tMh/o3cRlsx1ldLfog=="],
|
|
||||||
|
|
||||||
"@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-rc.9", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.1.1" }, "cpu": "none" }, "sha512-rgFN6sA/dyebil3YTlL2evvi/M+ivhfnyxec7AccTpRPccno/rPoNlqybEZQBkcbZu8Hy+eqNJCqfBR8P7Pg8g=="],
|
|
||||||
|
|
||||||
"@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-rc.9", "", { "os": "win32", "cpu": "arm64" }, "sha512-lHVNUG/8nlF1IQk1C0Ci574qKYyty2goMiPlRqkC5R+3LkXDkL5Dhx8ytbxq35m+pkHVIvIxviD+TWLdfeuadA=="],
|
|
||||||
|
|
||||||
"@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-rc.9", "", { "os": "win32", "cpu": "x64" }, "sha512-G0oA4+w1iY5AGi5HcDTxWsoxF509hrFIPB2rduV5aDqS9FtDg1CAfa7V34qImbjfhIcA8C+RekocJZA96EarwQ=="],
|
|
||||||
|
|
||||||
"@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.9", "", {}, "sha512-w6oiRWgEBl04QkFZgmW+jnU1EC9b57Oihi2ot3HNWIQRqgHp5PnYDia5iZ5FF7rpa4EQdiqMDXjlqKGXBhsoXw=="],
|
|
||||||
|
|
||||||
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.59.0", "", { "os": "android", "cpu": "arm" }, "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg=="],
|
|
||||||
|
|
||||||
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.59.0", "", { "os": "android", "cpu": "arm64" }, "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q=="],
|
|
||||||
|
|
||||||
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.59.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg=="],
|
|
||||||
|
|
||||||
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.59.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w=="],
|
|
||||||
|
|
||||||
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.59.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA=="],
|
|
||||||
|
|
||||||
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.59.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg=="],
|
|
||||||
|
|
||||||
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.59.0", "", { "os": "linux", "cpu": "arm" }, "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw=="],
|
|
||||||
|
|
||||||
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.59.0", "", { "os": "linux", "cpu": "arm" }, "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA=="],
|
|
||||||
|
|
||||||
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.59.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA=="],
|
|
||||||
|
|
||||||
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.59.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA=="],
|
|
||||||
|
|
||||||
"@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg=="],
|
|
||||||
|
|
||||||
"@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q=="],
|
|
||||||
|
|
||||||
"@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.59.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA=="],
|
|
||||||
|
|
||||||
"@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.59.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA=="],
|
|
||||||
|
|
||||||
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg=="],
|
|
||||||
|
|
||||||
"@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg=="],
|
|
||||||
|
|
||||||
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.59.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w=="],
|
|
||||||
|
|
||||||
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.59.0", "", { "os": "linux", "cpu": "x64" }, "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg=="],
|
|
||||||
|
|
||||||
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.59.0", "", { "os": "linux", "cpu": "x64" }, "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg=="],
|
|
||||||
|
|
||||||
"@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.59.0", "", { "os": "openbsd", "cpu": "x64" }, "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ=="],
|
|
||||||
|
|
||||||
"@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.59.0", "", { "os": "none", "cpu": "arm64" }, "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA=="],
|
|
||||||
|
|
||||||
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.59.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A=="],
|
|
||||||
|
|
||||||
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.59.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA=="],
|
|
||||||
|
|
||||||
"@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.59.0", "", { "os": "win32", "cpu": "x64" }, "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA=="],
|
|
||||||
|
|
||||||
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.59.0", "", { "os": "win32", "cpu": "x64" }, "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA=="],
|
|
||||||
|
|
||||||
"@shikijs/core": ["@shikijs/core@2.5.0", "", { "dependencies": { "@shikijs/engine-javascript": "2.5.0", "@shikijs/engine-oniguruma": "2.5.0", "@shikijs/types": "2.5.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.4" } }, "sha512-uu/8RExTKtavlpH7XqnVYBrfBkUc20ngXiX9NSrBhOVZYv/7XQRKUyhtkeflY5QsxC0GbJThCerruZfsUaSldg=="],
|
|
||||||
|
|
||||||
"@shikijs/engine-javascript": ["@shikijs/engine-javascript@2.5.0", "", { "dependencies": { "@shikijs/types": "2.5.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^3.1.0" } }, "sha512-VjnOpnQf8WuCEZtNUdjjwGUbtAVKuZkVQ/5cHy/tojVVRIRtlWMYVjyWhxOmIq05AlSOv72z7hRNRGVBgQOl0w=="],
|
|
||||||
|
|
||||||
"@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@2.5.0", "", { "dependencies": { "@shikijs/types": "2.5.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-pGd1wRATzbo/uatrCIILlAdFVKdxImWJGQ5rFiB5VZi2ve5xj3Ax9jny8QvkaV93btQEwR/rSz5ERFpC5mKNIw=="],
|
|
||||||
|
|
||||||
"@shikijs/langs": ["@shikijs/langs@2.5.0", "", { "dependencies": { "@shikijs/types": "2.5.0" } }, "sha512-Qfrrt5OsNH5R+5tJ/3uYBBZv3SuGmnRPejV9IlIbFH3HTGLDlkqgHymAlzklVmKBjAaVmkPkyikAV/sQ1wSL+w=="],
|
|
||||||
|
|
||||||
"@shikijs/themes": ["@shikijs/themes@2.5.0", "", { "dependencies": { "@shikijs/types": "2.5.0" } }, "sha512-wGrk+R8tJnO0VMzmUExHR+QdSaPUl/NKs+a4cQQRWyoc3YFbUzuLEi/KWK1hj+8BfHRKm2jNhhJck1dfstJpiw=="],
|
|
||||||
|
|
||||||
"@shikijs/transformers": ["@shikijs/transformers@2.5.0", "", { "dependencies": { "@shikijs/core": "2.5.0", "@shikijs/types": "2.5.0" } }, "sha512-SI494W5X60CaUwgi8u4q4m4s3YAFSxln3tzNjOSYqq54wlVgz0/NbbXEb3mdLbqMBztcmS7bVTaEd2w0qMmfeg=="],
|
|
||||||
|
|
||||||
"@shikijs/types": ["@shikijs/types@2.5.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-ygl5yhxki9ZLNuNpPitBWvcy9fsSKKaRuO4BAlMyagszQidxcpLAr0qiW/q43DtSIDxO6hEbtYLiFZNXO/hdGw=="],
|
|
||||||
|
|
||||||
"@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="],
|
|
||||||
|
|
||||||
"@tailwindcss/node": ["@tailwindcss/node@4.2.2", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "enhanced-resolve": "^5.19.0", "jiti": "^2.6.1", "lightningcss": "1.32.0", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.2.2" } }, "sha512-pXS+wJ2gZpVXqFaUEjojq7jzMpTGf8rU6ipJz5ovJV6PUGmlJ+jvIwGrzdHdQ80Sg+wmQxUFuoW1UAAwHNEdFA=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide": ["@tailwindcss/oxide@4.2.2", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.2.2", "@tailwindcss/oxide-darwin-arm64": "4.2.2", "@tailwindcss/oxide-darwin-x64": "4.2.2", "@tailwindcss/oxide-freebsd-x64": "4.2.2", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.2", "@tailwindcss/oxide-linux-arm64-gnu": "4.2.2", "@tailwindcss/oxide-linux-arm64-musl": "4.2.2", "@tailwindcss/oxide-linux-x64-gnu": "4.2.2", "@tailwindcss/oxide-linux-x64-musl": "4.2.2", "@tailwindcss/oxide-wasm32-wasi": "4.2.2", "@tailwindcss/oxide-win32-arm64-msvc": "4.2.2", "@tailwindcss/oxide-win32-x64-msvc": "4.2.2" } }, "sha512-qEUA07+E5kehxYp9BVMpq9E8vnJuBHfJEC0vPC5e7iL/hw7HR61aDKoVoKzrG+QKp56vhNZe4qwkRmMC0zDLvg=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.2.2", "", { "os": "android", "cpu": "arm64" }, "sha512-dXGR1n+P3B6748jZO/SvHZq7qBOqqzQ+yFrXpoOWWALWndF9MoSKAT3Q0fYgAzYzGhxNYOoysRvYlpixRBBoDg=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.2.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-iq9Qjr6knfMpZHj55/37ouZeykwbDqF21gPFtfnhCCKGDcPI/21FKC9XdMO/XyBM7qKORx6UIhGgg6jLl7BZlg=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.2.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-BlR+2c3nzc8f2G639LpL89YY4bdcIdUmiOOkv2GQv4/4M0vJlpXEa0JXNHhCHU7VWOKWT/CjqHdTP8aUuDJkuw=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.2.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-YUqUgrGMSu2CDO82hzlQ5qSb5xmx3RUrke/QgnoEx7KvmRJHQuZHZmZTLSuuHwFf0DJPybFMXMYf+WJdxHy/nQ=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.2.2", "", { "os": "linux", "cpu": "arm" }, "sha512-FPdhvsW6g06T9BWT0qTwiVZYE2WIFo2dY5aCSpjG/S/u1tby+wXoslXS0kl3/KXnULlLr1E3NPRRw0g7t2kgaQ=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.2.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-4og1V+ftEPXGttOO7eCmW7VICmzzJWgMx+QXAJRAhjrSjumCwWqMfkDrNu1LXEQzNAwz28NCUpucgQPrR4S2yw=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.2.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-oCfG/mS+/+XRlwNjnsNLVwnMWYH7tn/kYPsNPh+JSOMlnt93mYNCKHYzylRhI51X+TbR+ufNhhKKzm6QkqX8ag=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.2.2", "", { "os": "linux", "cpu": "x64" }, "sha512-rTAGAkDgqbXHNp/xW0iugLVmX62wOp2PoE39BTCGKjv3Iocf6AFbRP/wZT/kuCxC9QBh9Pu8XPkv/zCZB2mcMg=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.2.2", "", { "os": "linux", "cpu": "x64" }, "sha512-XW3t3qwbIwiSyRCggeO2zxe3KWaEbM0/kW9e8+0XpBgyKU4ATYzcVSMKteZJ1iukJ3HgHBjbg9P5YPRCVUxlnQ=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.2.2", "", { "dependencies": { "@emnapi/core": "^1.8.1", "@emnapi/runtime": "^1.8.1", "@emnapi/wasi-threads": "^1.1.0", "@napi-rs/wasm-runtime": "^1.1.1", "@tybys/wasm-util": "^0.10.1", "tslib": "^2.8.1" }, "cpu": "none" }, "sha512-eKSztKsmEsn1O5lJ4ZAfyn41NfG7vzCg496YiGtMDV86jz1q/irhms5O0VrY6ZwTUkFy/EKG3RfWgxSI3VbZ8Q=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.2.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-qPmaQM4iKu5mxpsrWZMOZRgZv1tOZpUm+zdhhQP0VhJfyGGO3aUKdbh3gDZc/dPLQwW4eSqWGrrcWNBZWUWaXQ=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.2.2", "", { "os": "win32", "cpu": "x64" }, "sha512-1T/37VvI7WyH66b+vqHj/cLwnCxt7Qt3WFu5Q8hk65aOvlwAhs7rAp1VkulBJw/N4tMirXjVnylTR72uI0HGcA=="],
|
|
||||||
|
|
||||||
"@tailwindcss/vite": ["@tailwindcss/vite@4.2.2", "", { "dependencies": { "@tailwindcss/node": "4.2.2", "@tailwindcss/oxide": "4.2.2", "tailwindcss": "4.2.2" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7 || ^8" } }, "sha512-mEiF5HO1QqCLXoNEfXVA1Tzo+cYsrqV7w9Juj2wdUFyW07JRenqMG225MvPwr3ZD9N1bFQj46X7r33iHxLUW0w=="],
|
|
||||||
|
|
||||||
"@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
|
||||||
|
|
||||||
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
|
|
||||||
|
|
||||||
"@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="],
|
|
||||||
|
|
||||||
"@types/linkify-it": ["@types/linkify-it@5.0.0", "", {}, "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q=="],
|
|
||||||
|
|
||||||
"@types/markdown-it": ["@types/markdown-it@14.1.2", "", { "dependencies": { "@types/linkify-it": "^5", "@types/mdurl": "^2" } }, "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog=="],
|
|
||||||
|
|
||||||
"@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="],
|
|
||||||
|
|
||||||
"@types/mdurl": ["@types/mdurl@2.0.0", "", {}, "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg=="],
|
|
||||||
|
|
||||||
"@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="],
|
|
||||||
|
|
||||||
"@types/web-bluetooth": ["@types/web-bluetooth@0.0.21", "", {}, "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA=="],
|
|
||||||
|
|
||||||
"@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],
|
|
||||||
|
|
||||||
"@vitejs/plugin-vue": ["@vitejs/plugin-vue@5.2.4", "", { "peerDependencies": { "vite": "^5.0.0 || ^6.0.0", "vue": "^3.2.25" } }, "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA=="],
|
|
||||||
|
|
||||||
"@vue/compiler-core": ["@vue/compiler-core@3.5.30", "", { "dependencies": { "@babel/parser": "^7.29.0", "@vue/shared": "3.5.30", "entities": "^7.0.1", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-s3DfdZkcu/qExZ+td75015ljzHc6vE+30cFMGRPROYjqkroYI5NV2X1yAMX9UeyBNWB9MxCfPcsjpLS11nzkkw=="],
|
|
||||||
|
|
||||||
"@vue/compiler-dom": ["@vue/compiler-dom@3.5.30", "", { "dependencies": { "@vue/compiler-core": "3.5.30", "@vue/shared": "3.5.30" } }, "sha512-eCFYESUEVYHhiMuK4SQTldO3RYxyMR/UQL4KdGD1Yrkfdx4m/HYuZ9jSfPdA+nWJY34VWndiYdW/wZXyiPEB9g=="],
|
|
||||||
|
|
||||||
"@vue/compiler-sfc": ["@vue/compiler-sfc@3.5.30", "", { "dependencies": { "@babel/parser": "^7.29.0", "@vue/compiler-core": "3.5.30", "@vue/compiler-dom": "3.5.30", "@vue/compiler-ssr": "3.5.30", "@vue/shared": "3.5.30", "estree-walker": "^2.0.2", "magic-string": "^0.30.21", "postcss": "^8.5.8", "source-map-js": "^1.2.1" } }, "sha512-LqmFPDn89dtU9vI3wHJnwaV6GfTRD87AjWpTWpyrdVOObVtjIuSeZr181z5C4PmVx/V3j2p+0f7edFKGRMpQ5A=="],
|
|
||||||
|
|
||||||
"@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.30", "", { "dependencies": { "@vue/compiler-dom": "3.5.30", "@vue/shared": "3.5.30" } }, "sha512-NsYK6OMTnx109PSL2IAyf62JP6EUdk4Dmj6AkWcJGBvN0dQoMYtVekAmdqgTtWQgEJo+Okstbf/1p7qZr5H+bA=="],
|
|
||||||
|
|
||||||
"@vue/devtools-api": ["@vue/devtools-api@7.7.9", "", { "dependencies": { "@vue/devtools-kit": "^7.7.9" } }, "sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g=="],
|
|
||||||
|
|
||||||
"@vue/devtools-kit": ["@vue/devtools-kit@7.7.9", "", { "dependencies": { "@vue/devtools-shared": "^7.7.9", "birpc": "^2.3.0", "hookable": "^5.5.3", "mitt": "^3.0.1", "perfect-debounce": "^1.0.0", "speakingurl": "^14.0.1", "superjson": "^2.2.2" } }, "sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA=="],
|
|
||||||
|
|
||||||
"@vue/devtools-shared": ["@vue/devtools-shared@7.7.9", "", { "dependencies": { "rfdc": "^1.4.1" } }, "sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA=="],
|
|
||||||
|
|
||||||
"@vue/reactivity": ["@vue/reactivity@3.5.30", "", { "dependencies": { "@vue/shared": "3.5.30" } }, "sha512-179YNgKATuwj9gB+66snskRDOitDiuOZqkYia7mHKJaidOMo/WJxHKF8DuGc4V4XbYTJANlfEKb0yxTQotnx4Q=="],
|
|
||||||
|
|
||||||
"@vue/runtime-core": ["@vue/runtime-core@3.5.30", "", { "dependencies": { "@vue/reactivity": "3.5.30", "@vue/shared": "3.5.30" } }, "sha512-e0Z+8PQsUTdwV8TtEsLzUM7SzC7lQwYKePydb7K2ZnmS6jjND+WJXkmmfh/swYzRyfP1EY3fpdesyYoymCzYfg=="],
|
|
||||||
|
|
||||||
"@vue/runtime-dom": ["@vue/runtime-dom@3.5.30", "", { "dependencies": { "@vue/reactivity": "3.5.30", "@vue/runtime-core": "3.5.30", "@vue/shared": "3.5.30", "csstype": "^3.2.3" } }, "sha512-2UIGakjU4WSQ0T4iwDEW0W7vQj6n7AFn7taqZ9Cvm0Q/RA2FFOziLESrDL4GmtI1wV3jXg5nMoJSYO66egDUBw=="],
|
|
||||||
|
|
||||||
"@vue/server-renderer": ["@vue/server-renderer@3.5.30", "", { "dependencies": { "@vue/compiler-ssr": "3.5.30", "@vue/shared": "3.5.30" }, "peerDependencies": { "vue": "3.5.30" } }, "sha512-v+R34icapydRwbZRD0sXwtHqrQJv38JuMB4JxbOxd8NEpGLny7cncMp53W9UH/zo4j8eDHjQ1dEJXwzFQknjtQ=="],
|
|
||||||
|
|
||||||
"@vue/shared": ["@vue/shared@3.5.30", "", {}, "sha512-YXgQ7JjaO18NeK2K9VTbDHaFy62WrObMa6XERNfNOkAhD1F1oDSf3ZJ7K6GqabZ0BvSDHajp8qfS5Sa2I9n8uQ=="],
|
|
||||||
|
|
||||||
"@vueuse/core": ["@vueuse/core@12.8.2", "", { "dependencies": { "@types/web-bluetooth": "^0.0.21", "@vueuse/metadata": "12.8.2", "@vueuse/shared": "12.8.2", "vue": "^3.5.13" } }, "sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ=="],
|
|
||||||
|
|
||||||
"@vueuse/integrations": ["@vueuse/integrations@12.8.2", "", { "dependencies": { "@vueuse/core": "12.8.2", "@vueuse/shared": "12.8.2", "vue": "^3.5.13" }, "peerDependencies": { "async-validator": "^4", "axios": "^1", "change-case": "^5", "drauu": "^0.4", "focus-trap": "^7", "fuse.js": "^7", "idb-keyval": "^6", "jwt-decode": "^4", "nprogress": "^0.2", "qrcode": "^1.5", "sortablejs": "^1", "universal-cookie": "^7" }, "optionalPeers": ["async-validator", "axios", "change-case", "drauu", "focus-trap", "fuse.js", "idb-keyval", "jwt-decode", "nprogress", "qrcode", "sortablejs", "universal-cookie"] }, "sha512-fbGYivgK5uBTRt7p5F3zy6VrETlV9RtZjBqd1/HxGdjdckBgBM4ugP8LHpjolqTj14TXTxSK1ZfgPbHYyGuH7g=="],
|
|
||||||
|
|
||||||
"@vueuse/metadata": ["@vueuse/metadata@12.8.2", "", {}, "sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A=="],
|
|
||||||
|
|
||||||
"@vueuse/shared": ["@vueuse/shared@12.8.2", "", { "dependencies": { "vue": "^3.5.13" } }, "sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w=="],
|
|
||||||
|
|
||||||
"algoliasearch": ["algoliasearch@5.49.2", "", { "dependencies": { "@algolia/abtesting": "1.15.2", "@algolia/client-abtesting": "5.49.2", "@algolia/client-analytics": "5.49.2", "@algolia/client-common": "5.49.2", "@algolia/client-insights": "5.49.2", "@algolia/client-personalization": "5.49.2", "@algolia/client-query-suggestions": "5.49.2", "@algolia/client-search": "5.49.2", "@algolia/ingestion": "1.49.2", "@algolia/monitoring": "1.49.2", "@algolia/recommend": "5.49.2", "@algolia/requester-browser-xhr": "5.49.2", "@algolia/requester-fetch": "5.49.2", "@algolia/requester-node-http": "5.49.2" } }, "sha512-1K0wtDaRONwfhL4h8bbJ9qTjmY6rhGgRvvagXkMBsAOMNr+3Q2SffHECh9DIuNVrMA1JwA0zCwhyepgBZVakng=="],
|
|
||||||
|
|
||||||
"birpc": ["birpc@2.9.0", "", {}, "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw=="],
|
|
||||||
|
|
||||||
"ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="],
|
|
||||||
|
|
||||||
"character-entities-html4": ["character-entities-html4@2.1.0", "", {}, "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA=="],
|
|
||||||
|
|
||||||
"character-entities-legacy": ["character-entities-legacy@3.0.0", "", {}, "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ=="],
|
|
||||||
|
|
||||||
"comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="],
|
|
||||||
|
|
||||||
"copy-anything": ["copy-anything@4.0.5", "", { "dependencies": { "is-what": "^5.2.0" } }, "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA=="],
|
|
||||||
|
|
||||||
"csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
|
|
||||||
|
|
||||||
"daisyui": ["daisyui@5.5.19", "", {}, "sha512-pbFAkl1VCEh/MPCeclKL61I/MqRIFFhNU7yiXoDDRapXN4/qNCoMxeCCswyxEEhqL5eiTTfwHvucFtOE71C9sA=="],
|
|
||||||
|
|
||||||
"dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="],
|
|
||||||
|
|
||||||
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
|
||||||
|
|
||||||
"devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="],
|
|
||||||
|
|
||||||
"emoji-regex-xs": ["emoji-regex-xs@1.0.0", "", {}, "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg=="],
|
|
||||||
|
|
||||||
"enhanced-resolve": ["enhanced-resolve@5.20.1", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.0" } }, "sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA=="],
|
|
||||||
|
|
||||||
"entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="],
|
|
||||||
|
|
||||||
"esbuild": ["esbuild@0.21.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", "@esbuild/android-arm64": "0.21.5", "@esbuild/android-x64": "0.21.5", "@esbuild/darwin-arm64": "0.21.5", "@esbuild/darwin-x64": "0.21.5", "@esbuild/freebsd-arm64": "0.21.5", "@esbuild/freebsd-x64": "0.21.5", "@esbuild/linux-arm": "0.21.5", "@esbuild/linux-arm64": "0.21.5", "@esbuild/linux-ia32": "0.21.5", "@esbuild/linux-loong64": "0.21.5", "@esbuild/linux-mips64el": "0.21.5", "@esbuild/linux-ppc64": "0.21.5", "@esbuild/linux-riscv64": "0.21.5", "@esbuild/linux-s390x": "0.21.5", "@esbuild/linux-x64": "0.21.5", "@esbuild/netbsd-x64": "0.21.5", "@esbuild/openbsd-x64": "0.21.5", "@esbuild/sunos-x64": "0.21.5", "@esbuild/win32-arm64": "0.21.5", "@esbuild/win32-ia32": "0.21.5", "@esbuild/win32-x64": "0.21.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw=="],
|
|
||||||
|
|
||||||
"estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
|
|
||||||
|
|
||||||
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
|
|
||||||
|
|
||||||
"focus-trap": ["focus-trap@7.8.0", "", { "dependencies": { "tabbable": "^6.4.0" } }, "sha512-/yNdlIkpWbM0ptxno3ONTuf+2g318kh2ez3KSeZN5dZ8YC6AAmgeWz+GasYYiBJPFaYcSAPeu4GfhUaChzIJXA=="],
|
|
||||||
|
|
||||||
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
|
|
||||||
|
|
||||||
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
|
||||||
|
|
||||||
"hast-util-to-html": ["hast-util-to-html@9.0.5", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-whitespace": "^3.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "stringify-entities": "^4.0.0", "zwitch": "^2.0.4" } }, "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw=="],
|
|
||||||
|
|
||||||
"hast-util-whitespace": ["hast-util-whitespace@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw=="],
|
|
||||||
|
|
||||||
"hookable": ["hookable@5.5.3", "", {}, "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="],
|
|
||||||
|
|
||||||
"html-void-elements": ["html-void-elements@3.0.0", "", {}, "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg=="],
|
|
||||||
|
|
||||||
"is-what": ["is-what@5.5.0", "", {}, "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw=="],
|
|
||||||
|
|
||||||
"jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="],
|
|
||||||
|
|
||||||
"lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.32.0", "lightningcss-darwin-arm64": "1.32.0", "lightningcss-darwin-x64": "1.32.0", "lightningcss-freebsd-x64": "1.32.0", "lightningcss-linux-arm-gnueabihf": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-musl": "1.32.0", "lightningcss-linux-x64-gnu": "1.32.0", "lightningcss-linux-x64-musl": "1.32.0", "lightningcss-win32-arm64-msvc": "1.32.0", "lightningcss-win32-x64-msvc": "1.32.0" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="],
|
|
||||||
|
|
||||||
"lightningcss-android-arm64": ["lightningcss-android-arm64@1.32.0", "", { "os": "android", "cpu": "arm64" }, "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg=="],
|
|
||||||
|
|
||||||
"lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.32.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ=="],
|
|
||||||
|
|
||||||
"lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.32.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w=="],
|
|
||||||
|
|
||||||
"lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.32.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig=="],
|
|
||||||
|
|
||||||
"lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.32.0", "", { "os": "linux", "cpu": "arm" }, "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw=="],
|
|
||||||
|
|
||||||
"lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ=="],
|
|
||||||
|
|
||||||
"lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg=="],
|
|
||||||
|
|
||||||
"lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA=="],
|
|
||||||
|
|
||||||
"lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg=="],
|
|
||||||
|
|
||||||
"lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.32.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw=="],
|
|
||||||
|
|
||||||
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.32.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q=="],
|
|
||||||
|
|
||||||
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
|
|
||||||
|
|
||||||
"mark.js": ["mark.js@8.11.1", "", {}, "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ=="],
|
|
||||||
|
|
||||||
"mdast-util-to-hast": ["mdast-util-to-hast@13.2.1", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@ungap/structured-clone": "^1.0.0", "devlop": "^1.0.0", "micromark-util-sanitize-uri": "^2.0.0", "trim-lines": "^3.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA=="],
|
|
||||||
|
|
||||||
"micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="],
|
|
||||||
|
|
||||||
"micromark-util-encode": ["micromark-util-encode@2.0.1", "", {}, "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw=="],
|
|
||||||
|
|
||||||
"micromark-util-sanitize-uri": ["micromark-util-sanitize-uri@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ=="],
|
|
||||||
|
|
||||||
"micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="],
|
|
||||||
|
|
||||||
"micromark-util-types": ["micromark-util-types@2.0.2", "", {}, "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA=="],
|
|
||||||
|
|
||||||
"minisearch": ["minisearch@7.2.0", "", {}, "sha512-dqT2XBYUOZOiC5t2HRnwADjhNS2cecp9u+TJRiJ1Qp/f5qjkeT5APcGPjHw+bz89Ms8Jp+cG4AlE+QZ/QnDglg=="],
|
|
||||||
|
|
||||||
"mitt": ["mitt@3.0.1", "", {}, "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="],
|
|
||||||
|
|
||||||
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
|
||||||
|
|
||||||
"oniguruma-to-es": ["oniguruma-to-es@3.1.1", "", { "dependencies": { "emoji-regex-xs": "^1.0.0", "regex": "^6.0.1", "regex-recursion": "^6.0.2" } }, "sha512-bUH8SDvPkH3ho3dvwJwfonjlQ4R80vjyvrU8YpxuROddv55vAEJrTuCuCVUhhsHbtlD9tGGbaNApGQckXhS8iQ=="],
|
|
||||||
|
|
||||||
"perfect-debounce": ["perfect-debounce@1.0.0", "", {}, "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA=="],
|
|
||||||
|
|
||||||
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
|
||||||
|
|
||||||
"picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
|
|
||||||
|
|
||||||
"postcss": ["postcss@8.5.8", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg=="],
|
|
||||||
|
|
||||||
"preact": ["preact@10.29.0", "", {}, "sha512-wSAGyk2bYR1c7t3SZ3jHcM6xy0lcBcDel6lODcs9ME6Th++Dx2KU+6D3HD8wMMKGA8Wpw7OMd3/4RGzYRpzwRg=="],
|
|
||||||
|
|
||||||
"property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="],
|
|
||||||
|
|
||||||
"regex": ["regex@6.1.0", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg=="],
|
|
||||||
|
|
||||||
"regex-recursion": ["regex-recursion@6.0.2", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg=="],
|
|
||||||
|
|
||||||
"regex-utilities": ["regex-utilities@2.3.0", "", {}, "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng=="],
|
|
||||||
|
|
||||||
"rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="],
|
|
||||||
|
|
||||||
"rolldown": ["rolldown@1.0.0-rc.9", "", { "dependencies": { "@oxc-project/types": "=0.115.0", "@rolldown/pluginutils": "1.0.0-rc.9" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.9", "@rolldown/binding-darwin-arm64": "1.0.0-rc.9", "@rolldown/binding-darwin-x64": "1.0.0-rc.9", "@rolldown/binding-freebsd-x64": "1.0.0-rc.9", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.9", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.9", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.9", "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.9", "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.9", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.9", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.9", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.9", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.9", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.9", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.9" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-9EbgWge7ZH+yqb4d2EnELAntgPTWbfL8ajiTW+SyhJEC4qhBbkCKbqFV4Ge4zmu5ziQuVbWxb/XwLZ+RIO7E8Q=="],
|
|
||||||
|
|
||||||
"rollup": ["rollup@4.59.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.59.0", "@rollup/rollup-android-arm64": "4.59.0", "@rollup/rollup-darwin-arm64": "4.59.0", "@rollup/rollup-darwin-x64": "4.59.0", "@rollup/rollup-freebsd-arm64": "4.59.0", "@rollup/rollup-freebsd-x64": "4.59.0", "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", "@rollup/rollup-linux-arm-musleabihf": "4.59.0", "@rollup/rollup-linux-arm64-gnu": "4.59.0", "@rollup/rollup-linux-arm64-musl": "4.59.0", "@rollup/rollup-linux-loong64-gnu": "4.59.0", "@rollup/rollup-linux-loong64-musl": "4.59.0", "@rollup/rollup-linux-ppc64-gnu": "4.59.0", "@rollup/rollup-linux-ppc64-musl": "4.59.0", "@rollup/rollup-linux-riscv64-gnu": "4.59.0", "@rollup/rollup-linux-riscv64-musl": "4.59.0", "@rollup/rollup-linux-s390x-gnu": "4.59.0", "@rollup/rollup-linux-x64-gnu": "4.59.0", "@rollup/rollup-linux-x64-musl": "4.59.0", "@rollup/rollup-openbsd-x64": "4.59.0", "@rollup/rollup-openharmony-arm64": "4.59.0", "@rollup/rollup-win32-arm64-msvc": "4.59.0", "@rollup/rollup-win32-ia32-msvc": "4.59.0", "@rollup/rollup-win32-x64-gnu": "4.59.0", "@rollup/rollup-win32-x64-msvc": "4.59.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg=="],
|
|
||||||
|
|
||||||
"search-insights": ["search-insights@2.17.3", "", {}, "sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ=="],
|
|
||||||
|
|
||||||
"shiki": ["shiki@2.5.0", "", { "dependencies": { "@shikijs/core": "2.5.0", "@shikijs/engine-javascript": "2.5.0", "@shikijs/engine-oniguruma": "2.5.0", "@shikijs/langs": "2.5.0", "@shikijs/themes": "2.5.0", "@shikijs/types": "2.5.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-mI//trrsaiCIPsja5CNfsyNOqgAZUb6VpJA+340toL42UpzQlXpwRV9nch69X6gaUxrr9kaOOa6e3y3uAkGFxQ=="],
|
|
||||||
|
|
||||||
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
|
||||||
|
|
||||||
"space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="],
|
|
||||||
|
|
||||||
"speakingurl": ["speakingurl@14.0.1", "", {}, "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ=="],
|
|
||||||
|
|
||||||
"stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="],
|
|
||||||
|
|
||||||
"superjson": ["superjson@2.2.6", "", { "dependencies": { "copy-anything": "^4" } }, "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA=="],
|
|
||||||
|
|
||||||
"tabbable": ["tabbable@6.4.0", "", {}, "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg=="],
|
|
||||||
|
|
||||||
"tailwindcss": ["tailwindcss@4.2.2", "", {}, "sha512-KWBIxs1Xb6NoLdMVqhbhgwZf2PGBpPEiwOqgI4pFIYbNTfBXiKYyWoTsXgBQ9WFg/OlhnvHaY+AEpW7wSmFo2Q=="],
|
|
||||||
|
|
||||||
"tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="],
|
|
||||||
|
|
||||||
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
|
|
||||||
|
|
||||||
"trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="],
|
|
||||||
|
|
||||||
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
|
||||||
|
|
||||||
"unist-util-is": ["unist-util-is@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g=="],
|
|
||||||
|
|
||||||
"unist-util-position": ["unist-util-position@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA=="],
|
|
||||||
|
|
||||||
"unist-util-stringify-position": ["unist-util-stringify-position@4.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ=="],
|
|
||||||
|
|
||||||
"unist-util-visit": ["unist-util-visit@5.1.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg=="],
|
|
||||||
|
|
||||||
"unist-util-visit-parents": ["unist-util-visit-parents@6.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ=="],
|
|
||||||
|
|
||||||
"vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="],
|
|
||||||
|
|
||||||
"vfile-message": ["vfile-message@4.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="],
|
|
||||||
|
|
||||||
"vite": ["vite@8.0.0", "", { "dependencies": { "@oxc-project/runtime": "0.115.0", "lightningcss": "^1.32.0", "picomatch": "^4.0.3", "postcss": "^8.5.8", "rolldown": "1.0.0-rc.9", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.0.0-alpha.31", "esbuild": "^0.27.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-fPGaRNj9Zytaf8LEiBhY7Z6ijnFKdzU/+mL8EFBaKr7Vw1/FWcTBAMW0wLPJAGMPX38ZPVCVgLceWiEqeoqL2Q=="],
|
|
||||||
|
|
||||||
"vitepress": ["vitepress@1.6.4", "", { "dependencies": { "@docsearch/css": "3.8.2", "@docsearch/js": "3.8.2", "@iconify-json/simple-icons": "^1.2.21", "@shikijs/core": "^2.1.0", "@shikijs/transformers": "^2.1.0", "@shikijs/types": "^2.1.0", "@types/markdown-it": "^14.1.2", "@vitejs/plugin-vue": "^5.2.1", "@vue/devtools-api": "^7.7.0", "@vue/shared": "^3.5.13", "@vueuse/core": "^12.4.0", "@vueuse/integrations": "^12.4.0", "focus-trap": "^7.6.4", "mark.js": "8.11.1", "minisearch": "^7.1.1", "shiki": "^2.1.0", "vite": "^5.4.14", "vue": "^3.5.13" }, "peerDependencies": { "markdown-it-mathjax3": "^4", "postcss": "^8" }, "optionalPeers": ["markdown-it-mathjax3", "postcss"], "bin": { "vitepress": "bin/vitepress.js" } }, "sha512-+2ym1/+0VVrbhNyRoFFesVvBvHAVMZMK0rw60E3X/5349M1GuVdKeazuksqopEdvkKwKGs21Q729jX81/bkBJg=="],
|
|
||||||
|
|
||||||
"vue": ["vue@3.5.30", "", { "dependencies": { "@vue/compiler-dom": "3.5.30", "@vue/compiler-sfc": "3.5.30", "@vue/runtime-dom": "3.5.30", "@vue/server-renderer": "3.5.30", "@vue/shared": "3.5.30" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-hTHLc6VNZyzzEH/l7PFGjpcTvUgiaPK5mdLkbjrTeWSRcEfxFrv56g/XckIYlE9ckuobsdwqd5mk2g1sBkMewg=="],
|
|
||||||
|
|
||||||
"zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.9.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-0DQ98G9ZQZOxfUcQn1waV2yS8aWdZ6kJMbYCJB3oUBecjWYO1fqJ+a1DRfPF3O5JEkwqwP1A9QEN/9mYm2Yd0w=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.9.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-QN75eB0IH2ywSpRpNddCRfQIhmJYBCJ1x5Lb3IscKAL8bMnVAKnRg8dCoXbHzVLLH7P38N2Z3mtulB7W0J0FKw=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.1", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" }, "bundled": true }, "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
|
||||||
|
|
||||||
"vitepress/vite": ["vite@5.4.21", "", { "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", "rollup": "^4.20.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw=="],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
602
dist/sigpro.esm.js
vendored
Normal file
602
dist/sigpro.esm.js
vendored
Normal file
@@ -0,0 +1,602 @@
|
|||||||
|
// sigpro.js
|
||||||
|
var isFunc = (f) => typeof f === "function";
|
||||||
|
var isObj = (o) => o && typeof o === "object";
|
||||||
|
var isArr = Array.isArray;
|
||||||
|
var doc = typeof document !== "undefined" ? document : null;
|
||||||
|
var ensureNode = (n) => n?._isRuntime ? n.container : n instanceof Node ? n : doc.createTextNode(n == null ? "" : String(n));
|
||||||
|
var activeEffect = null;
|
||||||
|
var activeOwner = null;
|
||||||
|
var isFlushing = false;
|
||||||
|
var batchDepth = 0;
|
||||||
|
var effectQueue = new Set;
|
||||||
|
var proxyCache = new WeakMap;
|
||||||
|
var ITER = Symbol("iter");
|
||||||
|
var MOUNTED_NODES = new WeakMap;
|
||||||
|
var dispose = (eff) => {
|
||||||
|
if (!eff || eff._disposed)
|
||||||
|
return;
|
||||||
|
eff._disposed = true;
|
||||||
|
const stack = [eff];
|
||||||
|
while (stack.length) {
|
||||||
|
const e = stack.pop();
|
||||||
|
if (e._cleanups) {
|
||||||
|
e._cleanups.forEach((fn) => fn());
|
||||||
|
e._cleanups.clear();
|
||||||
|
}
|
||||||
|
if (e._children) {
|
||||||
|
e._children.forEach((child) => stack.push(child));
|
||||||
|
e._children.clear();
|
||||||
|
}
|
||||||
|
if (e._deps) {
|
||||||
|
e._deps.forEach((depSet) => depSet.delete(e));
|
||||||
|
e._deps.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var onUnmount = (fn) => {
|
||||||
|
if (activeOwner)
|
||||||
|
(activeOwner._cleanups ||= new Set).add(fn);
|
||||||
|
};
|
||||||
|
var untrack = (fn) => {
|
||||||
|
const p = activeEffect;
|
||||||
|
activeEffect = null;
|
||||||
|
try {
|
||||||
|
return fn();
|
||||||
|
} finally {
|
||||||
|
activeEffect = p;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var createEffect = (fn, isComputed = false) => {
|
||||||
|
const effect = () => {
|
||||||
|
if (effect._disposed)
|
||||||
|
return;
|
||||||
|
if (effect._deps)
|
||||||
|
effect._deps.forEach((s) => s.delete(effect));
|
||||||
|
if (effect._cleanups) {
|
||||||
|
effect._cleanups.forEach((c) => c());
|
||||||
|
effect._cleanups.clear();
|
||||||
|
}
|
||||||
|
const prevEffect = activeEffect;
|
||||||
|
const prevOwner = activeOwner;
|
||||||
|
activeEffect = activeOwner = effect;
|
||||||
|
try {
|
||||||
|
return effect._result = fn();
|
||||||
|
} catch (e) {
|
||||||
|
console.error("[SigPro]", e);
|
||||||
|
} finally {
|
||||||
|
activeEffect = prevEffect;
|
||||||
|
activeOwner = prevOwner;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
effect._deps = effect._cleanups = effect._children = null;
|
||||||
|
effect._disposed = false;
|
||||||
|
effect._isComputed = isComputed;
|
||||||
|
effect._depth = activeEffect ? activeEffect._depth + 1 : 0;
|
||||||
|
effect._mounts = [];
|
||||||
|
effect._parent = activeOwner;
|
||||||
|
if (activeOwner)
|
||||||
|
(activeOwner._children ||= new Set).add(effect);
|
||||||
|
return effect;
|
||||||
|
};
|
||||||
|
var flush = () => {
|
||||||
|
if (isFlushing)
|
||||||
|
return;
|
||||||
|
isFlushing = true;
|
||||||
|
const sorted = Array.from(effectQueue).sort((a, b) => a._depth - b._depth);
|
||||||
|
effectQueue.clear();
|
||||||
|
for (const e of sorted)
|
||||||
|
if (!e._disposed)
|
||||||
|
e();
|
||||||
|
isFlushing = false;
|
||||||
|
};
|
||||||
|
var batch = (fn) => {
|
||||||
|
batchDepth++;
|
||||||
|
try {
|
||||||
|
return fn();
|
||||||
|
} finally {
|
||||||
|
batchDepth--;
|
||||||
|
if (batchDepth === 0 && effectQueue.size > 0 && !isFlushing) {
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var trackUpdate = (subs, trigger = false) => {
|
||||||
|
if (!trigger && activeEffect && !activeEffect._disposed) {
|
||||||
|
subs.add(activeEffect);
|
||||||
|
(activeEffect._deps ||= new Set).add(subs);
|
||||||
|
} else if (trigger && subs.size > 0) {
|
||||||
|
let hasQueue = false;
|
||||||
|
for (const e of subs) {
|
||||||
|
if (e === activeEffect || e._disposed)
|
||||||
|
continue;
|
||||||
|
if (e._isComputed) {
|
||||||
|
e._dirty = true;
|
||||||
|
if (e._subs)
|
||||||
|
trackUpdate(e._subs, true);
|
||||||
|
} else {
|
||||||
|
effectQueue.add(e);
|
||||||
|
hasQueue = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasQueue && !isFlushing && batchDepth === 0)
|
||||||
|
queueMicrotask(flush);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var $ = (val, key = null) => {
|
||||||
|
const subs = new Set;
|
||||||
|
if (isFunc(val)) {
|
||||||
|
let cache;
|
||||||
|
const computed = () => {
|
||||||
|
if (computed._dirty) {
|
||||||
|
const prev = activeEffect;
|
||||||
|
activeEffect = computed;
|
||||||
|
try {
|
||||||
|
const next = val();
|
||||||
|
if (!Object.is(cache, next)) {
|
||||||
|
cache = next;
|
||||||
|
trackUpdate(subs, true);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
activeEffect = prev;
|
||||||
|
}
|
||||||
|
computed._dirty = false;
|
||||||
|
}
|
||||||
|
trackUpdate(subs);
|
||||||
|
return cache;
|
||||||
|
};
|
||||||
|
computed._isComputed = true;
|
||||||
|
computed._subs = subs;
|
||||||
|
computed._dirty = true;
|
||||||
|
computed._deps = null;
|
||||||
|
computed._disposed = false;
|
||||||
|
computed.stop = () => {};
|
||||||
|
if (activeOwner)
|
||||||
|
onUnmount(computed.stop);
|
||||||
|
return computed;
|
||||||
|
}
|
||||||
|
if (key)
|
||||||
|
try {
|
||||||
|
val = JSON.parse(localStorage.getItem(key)) ?? val;
|
||||||
|
} catch (e) {}
|
||||||
|
return (...args) => {
|
||||||
|
if (args.length) {
|
||||||
|
const next = isFunc(args[0]) ? args[0](val) : args[0];
|
||||||
|
if (!Object.is(val, next)) {
|
||||||
|
val = next;
|
||||||
|
if (key)
|
||||||
|
localStorage.setItem(key, JSON.stringify(val));
|
||||||
|
trackUpdate(subs, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trackUpdate(subs);
|
||||||
|
return val;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
var $$ = (target) => {
|
||||||
|
if (!isObj(target))
|
||||||
|
return target;
|
||||||
|
const cached = proxyCache.get(target);
|
||||||
|
if (cached)
|
||||||
|
return cached;
|
||||||
|
const subs = new Map;
|
||||||
|
const getSubs = (key) => {
|
||||||
|
let set = subs.get(key);
|
||||||
|
if (!set)
|
||||||
|
subs.set(key, set = new Set);
|
||||||
|
return set;
|
||||||
|
};
|
||||||
|
const proxy = new Proxy(target, {
|
||||||
|
get(target2, key, receiver) {
|
||||||
|
if (typeof key !== "symbol")
|
||||||
|
trackUpdate(getSubs(key));
|
||||||
|
return $$(Reflect.get(target2, key, receiver));
|
||||||
|
},
|
||||||
|
set(target2, key, value, receiver) {
|
||||||
|
const hadKey = Reflect.has(target2, key);
|
||||||
|
const oldValue = Reflect.get(target2, key, receiver);
|
||||||
|
const result = Reflect.set(target2, key, value, receiver);
|
||||||
|
if (result && !Object.is(oldValue, value)) {
|
||||||
|
trackUpdate(getSubs(key), true);
|
||||||
|
if (!hadKey)
|
||||||
|
trackUpdate(getSubs(ITER), true);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
deleteProperty(target2, key) {
|
||||||
|
const result = Reflect.deleteProperty(target2, key);
|
||||||
|
if (result) {
|
||||||
|
trackUpdate(getSubs(key), true);
|
||||||
|
trackUpdate(getSubs(ITER), true);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
ownKeys(target2) {
|
||||||
|
trackUpdate(getSubs(ITER));
|
||||||
|
return Reflect.ownKeys(target2);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
proxyCache.set(target, proxy);
|
||||||
|
return proxy;
|
||||||
|
};
|
||||||
|
var watch = (sources, cb) => {
|
||||||
|
if (cb === undefined) {
|
||||||
|
const effect2 = createEffect(sources);
|
||||||
|
effect2();
|
||||||
|
return () => dispose(effect2);
|
||||||
|
}
|
||||||
|
const effect = createEffect(() => {
|
||||||
|
const vals = Array.isArray(sources) ? sources.map((s) => s()) : sources();
|
||||||
|
untrack(() => cb(vals));
|
||||||
|
});
|
||||||
|
effect();
|
||||||
|
return () => dispose(effect);
|
||||||
|
};
|
||||||
|
var cleanupNode = (node) => {
|
||||||
|
if (!node)
|
||||||
|
return;
|
||||||
|
if (node._cleanups) {
|
||||||
|
node._cleanups.forEach((fn) => fn());
|
||||||
|
node._cleanups.clear();
|
||||||
|
}
|
||||||
|
if (node._ownerEffect)
|
||||||
|
dispose(node._ownerEffect);
|
||||||
|
if (node.childNodes)
|
||||||
|
node.childNodes.forEach((n) => cleanupNode(n));
|
||||||
|
};
|
||||||
|
var DANGEROUS_PROTOCOL = /^\s*(javascript|data|vbscript):/i;
|
||||||
|
var isDangerousAttr = (key) => key === "src" || key === "href" || key.startsWith("on");
|
||||||
|
var validateAttr = (key, val) => {
|
||||||
|
if (val == null || val === false)
|
||||||
|
return null;
|
||||||
|
if (isDangerousAttr(key)) {
|
||||||
|
const sVal = String(val);
|
||||||
|
if (DANGEROUS_PROTOCOL.test(sVal)) {
|
||||||
|
console.warn(`[SigPro] Bloqueado protocolo peligroso en ${key}`);
|
||||||
|
return "#";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
};
|
||||||
|
var h = (tag, props = {}, children = []) => {
|
||||||
|
if (props instanceof Node || isArr(props) || !isObj(props)) {
|
||||||
|
children = props;
|
||||||
|
props = {};
|
||||||
|
}
|
||||||
|
if (isFunc(tag)) {
|
||||||
|
const effect = createEffect(() => {
|
||||||
|
const result2 = tag(props, {
|
||||||
|
children,
|
||||||
|
emit: (ev, ...args) => props[`on${ev[0].toUpperCase()}${ev.slice(1)}`]?.(...args)
|
||||||
|
});
|
||||||
|
effect._result = result2;
|
||||||
|
return result2;
|
||||||
|
});
|
||||||
|
effect();
|
||||||
|
const result = effect._result;
|
||||||
|
if (result == null)
|
||||||
|
return null;
|
||||||
|
const node = result instanceof Node || isArr(result) && result.every((n) => n instanceof Node) ? result : doc.createTextNode(String(result));
|
||||||
|
const attach = (n) => {
|
||||||
|
if (isObj(n) && !n._isRuntime) {
|
||||||
|
n._mounts = effect._mounts || [];
|
||||||
|
n._cleanups = effect._cleanups || new Set;
|
||||||
|
n._ownerEffect = effect;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
isArr(node) ? node.forEach(attach) : attach(node);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
const isSVG = /^(svg|path|circle|rect|line|poly(line|gon)|g|defs|text(path)?|tspan|use|symbol|image|marker|ellipse)$/i.test(tag);
|
||||||
|
const el = isSVG ? doc.createElementNS("http://www.w3.org/2000/svg", tag) : doc.createElement(tag);
|
||||||
|
el._cleanups = new Set;
|
||||||
|
for (let k in props) {
|
||||||
|
if (!props.hasOwnProperty(k))
|
||||||
|
continue;
|
||||||
|
let v = props[k];
|
||||||
|
if (k === "ref") {
|
||||||
|
isFunc(v) ? v(el) : v.current = el;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (isSVG && k.startsWith("xlink:")) {
|
||||||
|
const ns = "http://www.w3.org/1999/xlink";
|
||||||
|
v == null ? el.removeAttributeNS(ns, k.slice(6)) : el.setAttributeNS(ns, k.slice(6), v);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (k.startsWith("on")) {
|
||||||
|
const ev = k.slice(2).toLowerCase();
|
||||||
|
el.addEventListener(ev, v);
|
||||||
|
const off = () => el.removeEventListener(ev, v);
|
||||||
|
el._cleanups.add(off);
|
||||||
|
onUnmount(off);
|
||||||
|
} else if (isFunc(v)) {
|
||||||
|
const effect = createEffect(() => {
|
||||||
|
const val = validateAttr(k, v());
|
||||||
|
if (k === "class")
|
||||||
|
el.className = val || "";
|
||||||
|
else if (val == null)
|
||||||
|
el.removeAttribute(k);
|
||||||
|
else if (k in el && !isSVG)
|
||||||
|
el[k] = val;
|
||||||
|
else
|
||||||
|
el.setAttribute(k, val === true ? "" : val);
|
||||||
|
});
|
||||||
|
effect();
|
||||||
|
el._cleanups.add(() => dispose(effect));
|
||||||
|
onUnmount(() => dispose(effect));
|
||||||
|
if (/^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName) && (k === "value" || k === "checked")) {
|
||||||
|
const evType = k === "checked" ? "change" : "input";
|
||||||
|
el.addEventListener(evType, (ev) => v(ev.target[k]));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const val = validateAttr(k, v);
|
||||||
|
if (val != null) {
|
||||||
|
if (k in el && !isSVG)
|
||||||
|
el[k] = val;
|
||||||
|
else
|
||||||
|
el.setAttribute(k, val === true ? "" : val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const append = (c) => {
|
||||||
|
if (isArr(c))
|
||||||
|
return c.forEach(append);
|
||||||
|
if (isFunc(c)) {
|
||||||
|
const anchor = doc.createTextNode("");
|
||||||
|
el.appendChild(anchor);
|
||||||
|
let currentNodes = [];
|
||||||
|
const effect = createEffect(() => {
|
||||||
|
const res = c();
|
||||||
|
const next = (isArr(res) ? res : [res]).map(ensureNode);
|
||||||
|
currentNodes.forEach((n) => {
|
||||||
|
if (n._isRuntime)
|
||||||
|
n.destroy();
|
||||||
|
else
|
||||||
|
cleanupNode(n);
|
||||||
|
if (n.parentNode)
|
||||||
|
n.remove();
|
||||||
|
});
|
||||||
|
let ref = anchor;
|
||||||
|
for (let i = next.length - 1;i >= 0; i--) {
|
||||||
|
const node = next[i];
|
||||||
|
if (node.parentNode !== ref.parentNode)
|
||||||
|
ref.parentNode?.insertBefore(node, ref);
|
||||||
|
if (node._mounts)
|
||||||
|
node._mounts.forEach((fn) => fn());
|
||||||
|
ref = node;
|
||||||
|
}
|
||||||
|
currentNodes = next;
|
||||||
|
});
|
||||||
|
effect();
|
||||||
|
el._cleanups.add(() => dispose(effect));
|
||||||
|
onUnmount(() => dispose(effect));
|
||||||
|
} else {
|
||||||
|
const node = ensureNode(c);
|
||||||
|
el.appendChild(node);
|
||||||
|
if (node._mounts)
|
||||||
|
node._mounts.forEach((fn) => fn());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
append(children);
|
||||||
|
return el;
|
||||||
|
};
|
||||||
|
var render = (renderFn) => {
|
||||||
|
const cleanups = new Set;
|
||||||
|
const previousOwner = activeOwner;
|
||||||
|
const previousEffect = activeEffect;
|
||||||
|
const container = doc.createElement("div");
|
||||||
|
container.style.display = "contents";
|
||||||
|
container.setAttribute("role", "presentation");
|
||||||
|
activeOwner = { _cleanups: cleanups };
|
||||||
|
activeEffect = null;
|
||||||
|
const processResult = (result) => {
|
||||||
|
if (!result)
|
||||||
|
return;
|
||||||
|
if (result._isRuntime) {
|
||||||
|
cleanups.add(result.destroy);
|
||||||
|
container.appendChild(result.container);
|
||||||
|
} else if (isArr(result)) {
|
||||||
|
result.forEach(processResult);
|
||||||
|
} else {
|
||||||
|
container.appendChild(result instanceof Node ? result : doc.createTextNode(String(result == null ? "" : result)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
processResult(renderFn({ onCleanup: (fn) => cleanups.add(fn) }));
|
||||||
|
} finally {
|
||||||
|
activeOwner = previousOwner;
|
||||||
|
activeEffect = previousEffect;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
_isRuntime: true,
|
||||||
|
container,
|
||||||
|
destroy: () => {
|
||||||
|
cleanups.forEach((fn) => fn());
|
||||||
|
cleanupNode(container);
|
||||||
|
container.remove();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
var when = (cond, SIP, NOP = null) => {
|
||||||
|
const anchor = doc.createTextNode("");
|
||||||
|
const root = h("div", { style: "display:contents" }, [anchor]);
|
||||||
|
let currentView = null;
|
||||||
|
watch(() => !!(isFunc(cond) ? cond() : cond), (show) => {
|
||||||
|
if (currentView) {
|
||||||
|
currentView.destroy();
|
||||||
|
currentView = null;
|
||||||
|
}
|
||||||
|
const content = show ? SIP : NOP;
|
||||||
|
if (content) {
|
||||||
|
currentView = render(() => isFunc(content) ? content() : content);
|
||||||
|
root.insertBefore(currentView.container, anchor);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
onUnmount(() => currentView?.destroy());
|
||||||
|
return root;
|
||||||
|
};
|
||||||
|
var fx = ({ name, duration = 200, scale, slide, rotate, blur }, child) => {
|
||||||
|
const el = typeof child === "function" ? child() : child;
|
||||||
|
if (!(el instanceof Node))
|
||||||
|
return el;
|
||||||
|
if (name) {
|
||||||
|
el.style.animation = `${name}-in ${duration}ms`;
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
const hasTransform = scale || slide || rotate || blur;
|
||||||
|
const initialTransform = [
|
||||||
|
scale ? "scale(0.95)" : "",
|
||||||
|
slide ? "translateY(-10px)" : "",
|
||||||
|
rotate ? "rotate(-2deg)" : ""
|
||||||
|
].filter(Boolean).join(" ");
|
||||||
|
el.style.transition = `all ${duration}ms ease`;
|
||||||
|
el.style.opacity = "0";
|
||||||
|
if (hasTransform)
|
||||||
|
el.style.transform = initialTransform;
|
||||||
|
if (blur)
|
||||||
|
el.style.filter = "blur(4px)";
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
el.style.opacity = "1";
|
||||||
|
if (hasTransform)
|
||||||
|
el.style.transform = "none";
|
||||||
|
if (blur)
|
||||||
|
el.style.filter = "none";
|
||||||
|
});
|
||||||
|
return el;
|
||||||
|
};
|
||||||
|
var each = (src, itemFn, keyField) => {
|
||||||
|
const anchor = doc.createTextNode("");
|
||||||
|
const root = h("div", { style: "display:contents" }, [anchor]);
|
||||||
|
let cache = new Map;
|
||||||
|
watch(() => (isFunc(src) ? src() : src) || [], (items) => {
|
||||||
|
const nextCache = new Map;
|
||||||
|
const nextOrder = [];
|
||||||
|
const newItems = items || [];
|
||||||
|
for (let i = 0;i < newItems.length; i++) {
|
||||||
|
const item = newItems[i];
|
||||||
|
const key = keyField ? item?.[keyField] ?? i : item?.id ?? i;
|
||||||
|
let view = cache.get(key);
|
||||||
|
if (!view)
|
||||||
|
view = render(() => itemFn(item, i));
|
||||||
|
else
|
||||||
|
cache.delete(key);
|
||||||
|
nextCache.set(key, view);
|
||||||
|
nextOrder.push(view);
|
||||||
|
}
|
||||||
|
cache.forEach((view) => view.destroy());
|
||||||
|
let lastRef = anchor;
|
||||||
|
for (let i = nextOrder.length - 1;i >= 0; i--) {
|
||||||
|
const view = nextOrder[i];
|
||||||
|
const node = view.container;
|
||||||
|
if (node.nextSibling !== lastRef)
|
||||||
|
root.insertBefore(node, lastRef);
|
||||||
|
lastRef = node;
|
||||||
|
}
|
||||||
|
cache = nextCache;
|
||||||
|
});
|
||||||
|
return root;
|
||||||
|
};
|
||||||
|
var router = (routes) => {
|
||||||
|
const getHash = () => window.location.hash.slice(1) || "/";
|
||||||
|
const path = $(getHash());
|
||||||
|
const handler = () => path(getHash());
|
||||||
|
window.addEventListener("hashchange", handler);
|
||||||
|
onUnmount(() => window.removeEventListener("hashchange", handler));
|
||||||
|
const hook = h("div", { class: "router-hook" });
|
||||||
|
let currentView = null;
|
||||||
|
watch([path], () => {
|
||||||
|
const cur = path();
|
||||||
|
const route = routes.find((r) => {
|
||||||
|
const p1 = r.path.split("/").filter(Boolean);
|
||||||
|
const p2 = cur.split("/").filter(Boolean);
|
||||||
|
return p1.length === p2.length && p1.every((p, i) => p[0] === ":" || p === p2[i]);
|
||||||
|
}) || routes.find((r) => r.path === "*");
|
||||||
|
if (route) {
|
||||||
|
currentView?.destroy();
|
||||||
|
const params = {};
|
||||||
|
route.path.split("/").filter(Boolean).forEach((p, i) => {
|
||||||
|
if (p[0] === ":")
|
||||||
|
params[p.slice(1)] = cur.split("/").filter(Boolean)[i];
|
||||||
|
});
|
||||||
|
router.params(params);
|
||||||
|
currentView = render(() => isFunc(route.component) ? route.component(params) : route.component);
|
||||||
|
hook.replaceChildren(currentView.container);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return hook;
|
||||||
|
};
|
||||||
|
router.params = $({});
|
||||||
|
router.to = (p) => window.location.hash = p.replace(/^#?\/?/, "#/");
|
||||||
|
router.back = () => window.history.back();
|
||||||
|
router.path = () => window.location.hash.replace(/^#/, "") || "/";
|
||||||
|
var req = ({ url, method = "GET", headers = {} }) => {
|
||||||
|
const loading = $(false);
|
||||||
|
const error = $(null);
|
||||||
|
const data = $(null);
|
||||||
|
let controller = null;
|
||||||
|
let timeoutId = null;
|
||||||
|
const run = async (body = null) => {
|
||||||
|
controller?.abort();
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
controller = new AbortController;
|
||||||
|
timeoutId = setTimeout(() => controller.abort(), 1e4);
|
||||||
|
loading(true);
|
||||||
|
error(null);
|
||||||
|
try {
|
||||||
|
const isFormData = body instanceof FormData;
|
||||||
|
const res = await fetch(url, {
|
||||||
|
method,
|
||||||
|
headers: isFormData ? headers : { "Content-Type": "application/json", ...headers },
|
||||||
|
body: isFormData ? body : body ? JSON.stringify(body) : undefined,
|
||||||
|
signal: controller.signal
|
||||||
|
});
|
||||||
|
const text = await res.text();
|
||||||
|
const json = text ? JSON.parse(text) : null;
|
||||||
|
if (!res.ok)
|
||||||
|
throw new Error(json?.message || res.statusText);
|
||||||
|
data(json);
|
||||||
|
return json;
|
||||||
|
} catch (e) {
|
||||||
|
if (e.name !== "AbortError")
|
||||||
|
error(e.message);
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
loading(false);
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
controller = null;
|
||||||
|
timeoutId = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const abort = () => controller?.abort();
|
||||||
|
return { run, abort, loading, error, data };
|
||||||
|
};
|
||||||
|
var mount = (comp, target) => {
|
||||||
|
const t = typeof target === "string" ? doc.querySelector(target) : target;
|
||||||
|
if (!t)
|
||||||
|
return;
|
||||||
|
if (MOUNTED_NODES.has(t))
|
||||||
|
MOUNTED_NODES.get(t).destroy();
|
||||||
|
const inst = render(isFunc(comp) ? comp : () => comp);
|
||||||
|
t.replaceChildren(inst.container);
|
||||||
|
MOUNTED_NODES.set(t, inst);
|
||||||
|
return inst;
|
||||||
|
};
|
||||||
|
var SigPro = Object.freeze({ $, $$, watch, h, when, each, fx, router, req, mount, batch });
|
||||||
|
if (typeof window !== "undefined") {
|
||||||
|
Object.assign(window, SigPro);
|
||||||
|
"a abbr article aside audio b blockquote br button canvas caption cite code col colgroup datalist dd del details dfn dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 header hr i iframe img input ins kbd label legend li main mark meter nav object ol optgroup option output p picture pre progress section select slot small source span strong sub summary sup svg table tbody td template textarea tfoot th thead time tr u ul video".split(" ").forEach((tag) => {
|
||||||
|
window[tag] = (props, children) => h(tag, props, children);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
export {
|
||||||
|
when,
|
||||||
|
watch,
|
||||||
|
router,
|
||||||
|
req,
|
||||||
|
mount,
|
||||||
|
h,
|
||||||
|
fx,
|
||||||
|
each,
|
||||||
|
batch,
|
||||||
|
$$,
|
||||||
|
$
|
||||||
|
};
|
||||||
1
dist/sigpro.esm.min.js
vendored
Normal file
1
dist/sigpro.esm.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
645
dist/sigpro.js
vendored
Normal file
645
dist/sigpro.js
vendored
Normal file
@@ -0,0 +1,645 @@
|
|||||||
|
(() => {
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
function __accessProp(key) {
|
||||||
|
return this[key];
|
||||||
|
}
|
||||||
|
var __toCommonJS = (from) => {
|
||||||
|
var entry = (__moduleCache ??= new WeakMap).get(from), desc;
|
||||||
|
if (entry)
|
||||||
|
return entry;
|
||||||
|
entry = __defProp({}, "__esModule", { value: true });
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (var key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(entry, key))
|
||||||
|
__defProp(entry, key, {
|
||||||
|
get: __accessProp.bind(from, key),
|
||||||
|
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
||||||
|
});
|
||||||
|
}
|
||||||
|
__moduleCache.set(from, entry);
|
||||||
|
return entry;
|
||||||
|
};
|
||||||
|
var __moduleCache;
|
||||||
|
var __returnValue = (v) => v;
|
||||||
|
function __exportSetter(name, newValue) {
|
||||||
|
this[name] = __returnValue.bind(null, newValue);
|
||||||
|
}
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, {
|
||||||
|
get: all[name],
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
set: __exportSetter.bind(all, name)
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// index.js
|
||||||
|
var exports_sigpro = {};
|
||||||
|
__export(exports_sigpro, {
|
||||||
|
when: () => when,
|
||||||
|
watch: () => watch,
|
||||||
|
router: () => router,
|
||||||
|
req: () => req,
|
||||||
|
mount: () => mount,
|
||||||
|
h: () => h,
|
||||||
|
fx: () => fx,
|
||||||
|
each: () => each,
|
||||||
|
batch: () => batch,
|
||||||
|
$$: () => $$,
|
||||||
|
$: () => $
|
||||||
|
});
|
||||||
|
|
||||||
|
// sigpro.js
|
||||||
|
var isFunc = (f) => typeof f === "function";
|
||||||
|
var isObj = (o) => o && typeof o === "object";
|
||||||
|
var isArr = Array.isArray;
|
||||||
|
var doc = typeof document !== "undefined" ? document : null;
|
||||||
|
var ensureNode = (n) => n?._isRuntime ? n.container : n instanceof Node ? n : doc.createTextNode(n == null ? "" : String(n));
|
||||||
|
var activeEffect = null;
|
||||||
|
var activeOwner = null;
|
||||||
|
var isFlushing = false;
|
||||||
|
var batchDepth = 0;
|
||||||
|
var effectQueue = new Set;
|
||||||
|
var proxyCache = new WeakMap;
|
||||||
|
var ITER = Symbol("iter");
|
||||||
|
var MOUNTED_NODES = new WeakMap;
|
||||||
|
var dispose = (eff) => {
|
||||||
|
if (!eff || eff._disposed)
|
||||||
|
return;
|
||||||
|
eff._disposed = true;
|
||||||
|
const stack = [eff];
|
||||||
|
while (stack.length) {
|
||||||
|
const e = stack.pop();
|
||||||
|
if (e._cleanups) {
|
||||||
|
e._cleanups.forEach((fn) => fn());
|
||||||
|
e._cleanups.clear();
|
||||||
|
}
|
||||||
|
if (e._children) {
|
||||||
|
e._children.forEach((child) => stack.push(child));
|
||||||
|
e._children.clear();
|
||||||
|
}
|
||||||
|
if (e._deps) {
|
||||||
|
e._deps.forEach((depSet) => depSet.delete(e));
|
||||||
|
e._deps.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var onUnmount = (fn) => {
|
||||||
|
if (activeOwner)
|
||||||
|
(activeOwner._cleanups ||= new Set).add(fn);
|
||||||
|
};
|
||||||
|
var untrack = (fn) => {
|
||||||
|
const p = activeEffect;
|
||||||
|
activeEffect = null;
|
||||||
|
try {
|
||||||
|
return fn();
|
||||||
|
} finally {
|
||||||
|
activeEffect = p;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var createEffect = (fn, isComputed = false) => {
|
||||||
|
const effect = () => {
|
||||||
|
if (effect._disposed)
|
||||||
|
return;
|
||||||
|
if (effect._deps)
|
||||||
|
effect._deps.forEach((s) => s.delete(effect));
|
||||||
|
if (effect._cleanups) {
|
||||||
|
effect._cleanups.forEach((c) => c());
|
||||||
|
effect._cleanups.clear();
|
||||||
|
}
|
||||||
|
const prevEffect = activeEffect;
|
||||||
|
const prevOwner = activeOwner;
|
||||||
|
activeEffect = activeOwner = effect;
|
||||||
|
try {
|
||||||
|
return effect._result = fn();
|
||||||
|
} catch (e) {
|
||||||
|
console.error("[SigPro]", e);
|
||||||
|
} finally {
|
||||||
|
activeEffect = prevEffect;
|
||||||
|
activeOwner = prevOwner;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
effect._deps = effect._cleanups = effect._children = null;
|
||||||
|
effect._disposed = false;
|
||||||
|
effect._isComputed = isComputed;
|
||||||
|
effect._depth = activeEffect ? activeEffect._depth + 1 : 0;
|
||||||
|
effect._mounts = [];
|
||||||
|
effect._parent = activeOwner;
|
||||||
|
if (activeOwner)
|
||||||
|
(activeOwner._children ||= new Set).add(effect);
|
||||||
|
return effect;
|
||||||
|
};
|
||||||
|
var flush = () => {
|
||||||
|
if (isFlushing)
|
||||||
|
return;
|
||||||
|
isFlushing = true;
|
||||||
|
const sorted = Array.from(effectQueue).sort((a, b) => a._depth - b._depth);
|
||||||
|
effectQueue.clear();
|
||||||
|
for (const e of sorted)
|
||||||
|
if (!e._disposed)
|
||||||
|
e();
|
||||||
|
isFlushing = false;
|
||||||
|
};
|
||||||
|
var batch = (fn) => {
|
||||||
|
batchDepth++;
|
||||||
|
try {
|
||||||
|
return fn();
|
||||||
|
} finally {
|
||||||
|
batchDepth--;
|
||||||
|
if (batchDepth === 0 && effectQueue.size > 0 && !isFlushing) {
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var trackUpdate = (subs, trigger = false) => {
|
||||||
|
if (!trigger && activeEffect && !activeEffect._disposed) {
|
||||||
|
subs.add(activeEffect);
|
||||||
|
(activeEffect._deps ||= new Set).add(subs);
|
||||||
|
} else if (trigger && subs.size > 0) {
|
||||||
|
let hasQueue = false;
|
||||||
|
for (const e of subs) {
|
||||||
|
if (e === activeEffect || e._disposed)
|
||||||
|
continue;
|
||||||
|
if (e._isComputed) {
|
||||||
|
e._dirty = true;
|
||||||
|
if (e._subs)
|
||||||
|
trackUpdate(e._subs, true);
|
||||||
|
} else {
|
||||||
|
effectQueue.add(e);
|
||||||
|
hasQueue = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasQueue && !isFlushing && batchDepth === 0)
|
||||||
|
queueMicrotask(flush);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var $ = (val, key = null) => {
|
||||||
|
const subs = new Set;
|
||||||
|
if (isFunc(val)) {
|
||||||
|
let cache;
|
||||||
|
const computed = () => {
|
||||||
|
if (computed._dirty) {
|
||||||
|
const prev = activeEffect;
|
||||||
|
activeEffect = computed;
|
||||||
|
try {
|
||||||
|
const next = val();
|
||||||
|
if (!Object.is(cache, next)) {
|
||||||
|
cache = next;
|
||||||
|
trackUpdate(subs, true);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
activeEffect = prev;
|
||||||
|
}
|
||||||
|
computed._dirty = false;
|
||||||
|
}
|
||||||
|
trackUpdate(subs);
|
||||||
|
return cache;
|
||||||
|
};
|
||||||
|
computed._isComputed = true;
|
||||||
|
computed._subs = subs;
|
||||||
|
computed._dirty = true;
|
||||||
|
computed._deps = null;
|
||||||
|
computed._disposed = false;
|
||||||
|
computed.stop = () => {};
|
||||||
|
if (activeOwner)
|
||||||
|
onUnmount(computed.stop);
|
||||||
|
return computed;
|
||||||
|
}
|
||||||
|
if (key)
|
||||||
|
try {
|
||||||
|
val = JSON.parse(localStorage.getItem(key)) ?? val;
|
||||||
|
} catch (e) {}
|
||||||
|
return (...args) => {
|
||||||
|
if (args.length) {
|
||||||
|
const next = isFunc(args[0]) ? args[0](val) : args[0];
|
||||||
|
if (!Object.is(val, next)) {
|
||||||
|
val = next;
|
||||||
|
if (key)
|
||||||
|
localStorage.setItem(key, JSON.stringify(val));
|
||||||
|
trackUpdate(subs, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trackUpdate(subs);
|
||||||
|
return val;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
var $$ = (target) => {
|
||||||
|
if (!isObj(target))
|
||||||
|
return target;
|
||||||
|
const cached = proxyCache.get(target);
|
||||||
|
if (cached)
|
||||||
|
return cached;
|
||||||
|
const subs = new Map;
|
||||||
|
const getSubs = (key) => {
|
||||||
|
let set = subs.get(key);
|
||||||
|
if (!set)
|
||||||
|
subs.set(key, set = new Set);
|
||||||
|
return set;
|
||||||
|
};
|
||||||
|
const proxy = new Proxy(target, {
|
||||||
|
get(target2, key, receiver) {
|
||||||
|
if (typeof key !== "symbol")
|
||||||
|
trackUpdate(getSubs(key));
|
||||||
|
return $$(Reflect.get(target2, key, receiver));
|
||||||
|
},
|
||||||
|
set(target2, key, value, receiver) {
|
||||||
|
const hadKey = Reflect.has(target2, key);
|
||||||
|
const oldValue = Reflect.get(target2, key, receiver);
|
||||||
|
const result = Reflect.set(target2, key, value, receiver);
|
||||||
|
if (result && !Object.is(oldValue, value)) {
|
||||||
|
trackUpdate(getSubs(key), true);
|
||||||
|
if (!hadKey)
|
||||||
|
trackUpdate(getSubs(ITER), true);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
deleteProperty(target2, key) {
|
||||||
|
const result = Reflect.deleteProperty(target2, key);
|
||||||
|
if (result) {
|
||||||
|
trackUpdate(getSubs(key), true);
|
||||||
|
trackUpdate(getSubs(ITER), true);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
ownKeys(target2) {
|
||||||
|
trackUpdate(getSubs(ITER));
|
||||||
|
return Reflect.ownKeys(target2);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
proxyCache.set(target, proxy);
|
||||||
|
return proxy;
|
||||||
|
};
|
||||||
|
var watch = (sources, cb) => {
|
||||||
|
if (cb === undefined) {
|
||||||
|
const effect2 = createEffect(sources);
|
||||||
|
effect2();
|
||||||
|
return () => dispose(effect2);
|
||||||
|
}
|
||||||
|
const effect = createEffect(() => {
|
||||||
|
const vals = Array.isArray(sources) ? sources.map((s) => s()) : sources();
|
||||||
|
untrack(() => cb(vals));
|
||||||
|
});
|
||||||
|
effect();
|
||||||
|
return () => dispose(effect);
|
||||||
|
};
|
||||||
|
var cleanupNode = (node) => {
|
||||||
|
if (!node)
|
||||||
|
return;
|
||||||
|
if (node._cleanups) {
|
||||||
|
node._cleanups.forEach((fn) => fn());
|
||||||
|
node._cleanups.clear();
|
||||||
|
}
|
||||||
|
if (node._ownerEffect)
|
||||||
|
dispose(node._ownerEffect);
|
||||||
|
if (node.childNodes)
|
||||||
|
node.childNodes.forEach((n) => cleanupNode(n));
|
||||||
|
};
|
||||||
|
var DANGEROUS_PROTOCOL = /^\s*(javascript|data|vbscript):/i;
|
||||||
|
var isDangerousAttr = (key) => key === "src" || key === "href" || key.startsWith("on");
|
||||||
|
var validateAttr = (key, val) => {
|
||||||
|
if (val == null || val === false)
|
||||||
|
return null;
|
||||||
|
if (isDangerousAttr(key)) {
|
||||||
|
const sVal = String(val);
|
||||||
|
if (DANGEROUS_PROTOCOL.test(sVal)) {
|
||||||
|
console.warn(`[SigPro] Bloqueado protocolo peligroso en ${key}`);
|
||||||
|
return "#";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
};
|
||||||
|
var h = (tag, props = {}, children = []) => {
|
||||||
|
if (props instanceof Node || isArr(props) || !isObj(props)) {
|
||||||
|
children = props;
|
||||||
|
props = {};
|
||||||
|
}
|
||||||
|
if (isFunc(tag)) {
|
||||||
|
const effect = createEffect(() => {
|
||||||
|
const result2 = tag(props, {
|
||||||
|
children,
|
||||||
|
emit: (ev, ...args) => props[`on${ev[0].toUpperCase()}${ev.slice(1)}`]?.(...args)
|
||||||
|
});
|
||||||
|
effect._result = result2;
|
||||||
|
return result2;
|
||||||
|
});
|
||||||
|
effect();
|
||||||
|
const result = effect._result;
|
||||||
|
if (result == null)
|
||||||
|
return null;
|
||||||
|
const node = result instanceof Node || isArr(result) && result.every((n) => n instanceof Node) ? result : doc.createTextNode(String(result));
|
||||||
|
const attach = (n) => {
|
||||||
|
if (isObj(n) && !n._isRuntime) {
|
||||||
|
n._mounts = effect._mounts || [];
|
||||||
|
n._cleanups = effect._cleanups || new Set;
|
||||||
|
n._ownerEffect = effect;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
isArr(node) ? node.forEach(attach) : attach(node);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
const isSVG = /^(svg|path|circle|rect|line|poly(line|gon)|g|defs|text(path)?|tspan|use|symbol|image|marker|ellipse)$/i.test(tag);
|
||||||
|
const el = isSVG ? doc.createElementNS("http://www.w3.org/2000/svg", tag) : doc.createElement(tag);
|
||||||
|
el._cleanups = new Set;
|
||||||
|
for (let k in props) {
|
||||||
|
if (!props.hasOwnProperty(k))
|
||||||
|
continue;
|
||||||
|
let v = props[k];
|
||||||
|
if (k === "ref") {
|
||||||
|
isFunc(v) ? v(el) : v.current = el;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (isSVG && k.startsWith("xlink:")) {
|
||||||
|
const ns = "http://www.w3.org/1999/xlink";
|
||||||
|
v == null ? el.removeAttributeNS(ns, k.slice(6)) : el.setAttributeNS(ns, k.slice(6), v);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (k.startsWith("on")) {
|
||||||
|
const ev = k.slice(2).toLowerCase();
|
||||||
|
el.addEventListener(ev, v);
|
||||||
|
const off = () => el.removeEventListener(ev, v);
|
||||||
|
el._cleanups.add(off);
|
||||||
|
onUnmount(off);
|
||||||
|
} else if (isFunc(v)) {
|
||||||
|
const effect = createEffect(() => {
|
||||||
|
const val = validateAttr(k, v());
|
||||||
|
if (k === "class")
|
||||||
|
el.className = val || "";
|
||||||
|
else if (val == null)
|
||||||
|
el.removeAttribute(k);
|
||||||
|
else if (k in el && !isSVG)
|
||||||
|
el[k] = val;
|
||||||
|
else
|
||||||
|
el.setAttribute(k, val === true ? "" : val);
|
||||||
|
});
|
||||||
|
effect();
|
||||||
|
el._cleanups.add(() => dispose(effect));
|
||||||
|
onUnmount(() => dispose(effect));
|
||||||
|
if (/^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName) && (k === "value" || k === "checked")) {
|
||||||
|
const evType = k === "checked" ? "change" : "input";
|
||||||
|
el.addEventListener(evType, (ev) => v(ev.target[k]));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const val = validateAttr(k, v);
|
||||||
|
if (val != null) {
|
||||||
|
if (k in el && !isSVG)
|
||||||
|
el[k] = val;
|
||||||
|
else
|
||||||
|
el.setAttribute(k, val === true ? "" : val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const append = (c) => {
|
||||||
|
if (isArr(c))
|
||||||
|
return c.forEach(append);
|
||||||
|
if (isFunc(c)) {
|
||||||
|
const anchor = doc.createTextNode("");
|
||||||
|
el.appendChild(anchor);
|
||||||
|
let currentNodes = [];
|
||||||
|
const effect = createEffect(() => {
|
||||||
|
const res = c();
|
||||||
|
const next = (isArr(res) ? res : [res]).map(ensureNode);
|
||||||
|
currentNodes.forEach((n) => {
|
||||||
|
if (n._isRuntime)
|
||||||
|
n.destroy();
|
||||||
|
else
|
||||||
|
cleanupNode(n);
|
||||||
|
if (n.parentNode)
|
||||||
|
n.remove();
|
||||||
|
});
|
||||||
|
let ref = anchor;
|
||||||
|
for (let i = next.length - 1;i >= 0; i--) {
|
||||||
|
const node = next[i];
|
||||||
|
if (node.parentNode !== ref.parentNode)
|
||||||
|
ref.parentNode?.insertBefore(node, ref);
|
||||||
|
if (node._mounts)
|
||||||
|
node._mounts.forEach((fn) => fn());
|
||||||
|
ref = node;
|
||||||
|
}
|
||||||
|
currentNodes = next;
|
||||||
|
});
|
||||||
|
effect();
|
||||||
|
el._cleanups.add(() => dispose(effect));
|
||||||
|
onUnmount(() => dispose(effect));
|
||||||
|
} else {
|
||||||
|
const node = ensureNode(c);
|
||||||
|
el.appendChild(node);
|
||||||
|
if (node._mounts)
|
||||||
|
node._mounts.forEach((fn) => fn());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
append(children);
|
||||||
|
return el;
|
||||||
|
};
|
||||||
|
var render = (renderFn) => {
|
||||||
|
const cleanups = new Set;
|
||||||
|
const previousOwner = activeOwner;
|
||||||
|
const previousEffect = activeEffect;
|
||||||
|
const container = doc.createElement("div");
|
||||||
|
container.style.display = "contents";
|
||||||
|
container.setAttribute("role", "presentation");
|
||||||
|
activeOwner = { _cleanups: cleanups };
|
||||||
|
activeEffect = null;
|
||||||
|
const processResult = (result) => {
|
||||||
|
if (!result)
|
||||||
|
return;
|
||||||
|
if (result._isRuntime) {
|
||||||
|
cleanups.add(result.destroy);
|
||||||
|
container.appendChild(result.container);
|
||||||
|
} else if (isArr(result)) {
|
||||||
|
result.forEach(processResult);
|
||||||
|
} else {
|
||||||
|
container.appendChild(result instanceof Node ? result : doc.createTextNode(String(result == null ? "" : result)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
processResult(renderFn({ onCleanup: (fn) => cleanups.add(fn) }));
|
||||||
|
} finally {
|
||||||
|
activeOwner = previousOwner;
|
||||||
|
activeEffect = previousEffect;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
_isRuntime: true,
|
||||||
|
container,
|
||||||
|
destroy: () => {
|
||||||
|
cleanups.forEach((fn) => fn());
|
||||||
|
cleanupNode(container);
|
||||||
|
container.remove();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
var when = (cond, SIP, NOP = null) => {
|
||||||
|
const anchor = doc.createTextNode("");
|
||||||
|
const root = h("div", { style: "display:contents" }, [anchor]);
|
||||||
|
let currentView = null;
|
||||||
|
watch(() => !!(isFunc(cond) ? cond() : cond), (show) => {
|
||||||
|
if (currentView) {
|
||||||
|
currentView.destroy();
|
||||||
|
currentView = null;
|
||||||
|
}
|
||||||
|
const content = show ? SIP : NOP;
|
||||||
|
if (content) {
|
||||||
|
currentView = render(() => isFunc(content) ? content() : content);
|
||||||
|
root.insertBefore(currentView.container, anchor);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
onUnmount(() => currentView?.destroy());
|
||||||
|
return root;
|
||||||
|
};
|
||||||
|
var fx = ({ name, duration = 200, scale, slide, rotate, blur }, child) => {
|
||||||
|
const el = typeof child === "function" ? child() : child;
|
||||||
|
if (!(el instanceof Node))
|
||||||
|
return el;
|
||||||
|
if (name) {
|
||||||
|
el.style.animation = `${name}-in ${duration}ms`;
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
const hasTransform = scale || slide || rotate || blur;
|
||||||
|
const initialTransform = [
|
||||||
|
scale ? "scale(0.95)" : "",
|
||||||
|
slide ? "translateY(-10px)" : "",
|
||||||
|
rotate ? "rotate(-2deg)" : ""
|
||||||
|
].filter(Boolean).join(" ");
|
||||||
|
el.style.transition = `all ${duration}ms ease`;
|
||||||
|
el.style.opacity = "0";
|
||||||
|
if (hasTransform)
|
||||||
|
el.style.transform = initialTransform;
|
||||||
|
if (blur)
|
||||||
|
el.style.filter = "blur(4px)";
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
el.style.opacity = "1";
|
||||||
|
if (hasTransform)
|
||||||
|
el.style.transform = "none";
|
||||||
|
if (blur)
|
||||||
|
el.style.filter = "none";
|
||||||
|
});
|
||||||
|
return el;
|
||||||
|
};
|
||||||
|
var each = (src, itemFn, keyField) => {
|
||||||
|
const anchor = doc.createTextNode("");
|
||||||
|
const root = h("div", { style: "display:contents" }, [anchor]);
|
||||||
|
let cache = new Map;
|
||||||
|
watch(() => (isFunc(src) ? src() : src) || [], (items) => {
|
||||||
|
const nextCache = new Map;
|
||||||
|
const nextOrder = [];
|
||||||
|
const newItems = items || [];
|
||||||
|
for (let i = 0;i < newItems.length; i++) {
|
||||||
|
const item = newItems[i];
|
||||||
|
const key = keyField ? item?.[keyField] ?? i : item?.id ?? i;
|
||||||
|
let view = cache.get(key);
|
||||||
|
if (!view)
|
||||||
|
view = render(() => itemFn(item, i));
|
||||||
|
else
|
||||||
|
cache.delete(key);
|
||||||
|
nextCache.set(key, view);
|
||||||
|
nextOrder.push(view);
|
||||||
|
}
|
||||||
|
cache.forEach((view) => view.destroy());
|
||||||
|
let lastRef = anchor;
|
||||||
|
for (let i = nextOrder.length - 1;i >= 0; i--) {
|
||||||
|
const view = nextOrder[i];
|
||||||
|
const node = view.container;
|
||||||
|
if (node.nextSibling !== lastRef)
|
||||||
|
root.insertBefore(node, lastRef);
|
||||||
|
lastRef = node;
|
||||||
|
}
|
||||||
|
cache = nextCache;
|
||||||
|
});
|
||||||
|
return root;
|
||||||
|
};
|
||||||
|
var router = (routes) => {
|
||||||
|
const getHash = () => window.location.hash.slice(1) || "/";
|
||||||
|
const path = $(getHash());
|
||||||
|
const handler = () => path(getHash());
|
||||||
|
window.addEventListener("hashchange", handler);
|
||||||
|
onUnmount(() => window.removeEventListener("hashchange", handler));
|
||||||
|
const hook = h("div", { class: "router-hook" });
|
||||||
|
let currentView = null;
|
||||||
|
watch([path], () => {
|
||||||
|
const cur = path();
|
||||||
|
const route = routes.find((r) => {
|
||||||
|
const p1 = r.path.split("/").filter(Boolean);
|
||||||
|
const p2 = cur.split("/").filter(Boolean);
|
||||||
|
return p1.length === p2.length && p1.every((p, i) => p[0] === ":" || p === p2[i]);
|
||||||
|
}) || routes.find((r) => r.path === "*");
|
||||||
|
if (route) {
|
||||||
|
currentView?.destroy();
|
||||||
|
const params = {};
|
||||||
|
route.path.split("/").filter(Boolean).forEach((p, i) => {
|
||||||
|
if (p[0] === ":")
|
||||||
|
params[p.slice(1)] = cur.split("/").filter(Boolean)[i];
|
||||||
|
});
|
||||||
|
router.params(params);
|
||||||
|
currentView = render(() => isFunc(route.component) ? route.component(params) : route.component);
|
||||||
|
hook.replaceChildren(currentView.container);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return hook;
|
||||||
|
};
|
||||||
|
router.params = $({});
|
||||||
|
router.to = (p) => window.location.hash = p.replace(/^#?\/?/, "#/");
|
||||||
|
router.back = () => window.history.back();
|
||||||
|
router.path = () => window.location.hash.replace(/^#/, "") || "/";
|
||||||
|
var req = ({ url, method = "GET", headers = {} }) => {
|
||||||
|
const loading = $(false);
|
||||||
|
const error = $(null);
|
||||||
|
const data = $(null);
|
||||||
|
let controller = null;
|
||||||
|
let timeoutId = null;
|
||||||
|
const run = async (body = null) => {
|
||||||
|
controller?.abort();
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
controller = new AbortController;
|
||||||
|
timeoutId = setTimeout(() => controller.abort(), 1e4);
|
||||||
|
loading(true);
|
||||||
|
error(null);
|
||||||
|
try {
|
||||||
|
const isFormData = body instanceof FormData;
|
||||||
|
const res = await fetch(url, {
|
||||||
|
method,
|
||||||
|
headers: isFormData ? headers : { "Content-Type": "application/json", ...headers },
|
||||||
|
body: isFormData ? body : body ? JSON.stringify(body) : undefined,
|
||||||
|
signal: controller.signal
|
||||||
|
});
|
||||||
|
const text = await res.text();
|
||||||
|
const json = text ? JSON.parse(text) : null;
|
||||||
|
if (!res.ok)
|
||||||
|
throw new Error(json?.message || res.statusText);
|
||||||
|
data(json);
|
||||||
|
return json;
|
||||||
|
} catch (e) {
|
||||||
|
if (e.name !== "AbortError")
|
||||||
|
error(e.message);
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
loading(false);
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
controller = null;
|
||||||
|
timeoutId = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const abort = () => controller?.abort();
|
||||||
|
return { run, abort, loading, error, data };
|
||||||
|
};
|
||||||
|
var mount = (comp, target) => {
|
||||||
|
const t = typeof target === "string" ? doc.querySelector(target) : target;
|
||||||
|
if (!t)
|
||||||
|
return;
|
||||||
|
if (MOUNTED_NODES.has(t))
|
||||||
|
MOUNTED_NODES.get(t).destroy();
|
||||||
|
const inst = render(isFunc(comp) ? comp : () => comp);
|
||||||
|
t.replaceChildren(inst.container);
|
||||||
|
MOUNTED_NODES.set(t, inst);
|
||||||
|
return inst;
|
||||||
|
};
|
||||||
|
var SigPro = Object.freeze({ $, $$, watch, h, when, each, fx, router, req, mount, batch });
|
||||||
|
if (typeof window !== "undefined") {
|
||||||
|
Object.assign(window, SigPro);
|
||||||
|
"a abbr article aside audio b blockquote br button canvas caption cite code col colgroup datalist dd del details dfn dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 header hr i iframe img input ins kbd label legend li main mark meter nav object ol optgroup option output p picture pre progress section select slot small source span strong sub summary sup svg table tbody td template textarea tfoot th thead time tr u ul video".split(" ").forEach((tag) => {
|
||||||
|
window[tag] = (props, children) => h(tag, props, children);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})();
|
||||||
1
dist/sigpro.min.js
vendored
Normal file
1
dist/sigpro.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
0
docs/.nojekyll
Normal file
0
docs/.nojekyll
Normal file
@@ -1,22 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en-US" dir="ltr">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
||||||
<title>404 | SigPro</title>
|
|
||||||
<meta name="description" content="Not Found">
|
|
||||||
<meta name="generator" content="VitePress v1.6.4">
|
|
||||||
<link rel="preload stylesheet" href="/sigpro/assets/style.DJRheFKp.css" as="style">
|
|
||||||
<link rel="preload stylesheet" href="/sigpro/vp-icons.css" as="style">
|
|
||||||
|
|
||||||
<script type="module" src="/sigpro/assets/app.DtmzNmNl.js"></script>
|
|
||||||
<link rel="preload" href="/sigpro/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
|
|
||||||
<script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
|
|
||||||
<script id="check-mac-os">document.documentElement.classList.toggle("mac",/Mac|iPhone|iPod|iPad/i.test(navigator.platform));</script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="app"></div>
|
|
||||||
<script>window.__VP_HASH_MAP__=JSON.parse("{\"api_components.md\":\"BlFwj17l\",\"api_effects.md\":\"Br_yStBS\",\"api_fetch.md\":\"DQLBJSoq\",\"api_pages.md\":\"BP19nHXw\",\"api_quick.md\":\"BDS3ttnt\",\"api_routing.md\":\"7SNAZXtp\",\"api_signals.md\":\"CrW68-BA\",\"api_storage.md\":\"COEWBXHk\",\"guide_getting-started.md\":\"BeQpK3vd\",\"guide_why.md\":\"DXchYMN-\",\"index.md\":\"uvMJmU4o\",\"vite_plugin.md\":\"gDWEi8f0\"}");window.__VP_SITE_DATA__=JSON.parse("{\"lang\":\"en-US\",\"dir\":\"ltr\",\"title\":\"SigPro\",\"description\":\"Minimalist Reactive Library\",\"base\":\"/sigpro/\",\"head\":[],\"router\":{\"prefetchLinks\":true},\"appearance\":true,\"themeConfig\":{\"logo\":\"/logo.svg\",\"nav\":[{\"text\":\"Home\",\"link\":\"/\"},{\"text\":\"Guide\",\"link\":\"/guide/getting-started\"},{\"text\":\"Api\",\"link\":\"/api/quick\"}],\"sidebar\":[{\"text\":\"Introduction\",\"items\":[{\"text\":\"What is SigPro?\",\"link\":\"/\"},{\"text\":\"Why\",\"link\":\"/guide/why\"},{\"text\":\"Guide\",\"link\":\"/guide/getting-started\"}]},{\"text\":\"API Reference\",\"items\":[{\"text\":\"Quick Start\",\"link\":\"/api/quick\"},{\"text\":\"Signals\",\"link\":\"/api/signals\"},{\"text\":\"Effects\",\"link\":\"/api/effects\"},{\"text\":\"Storage\",\"link\":\"/api/storage\"},{\"text\":\"Fetch\",\"link\":\"/api/fetch\"},{\"text\":\"Pages\",\"link\":\"/api/pages\"},{\"text\":\"Components\",\"link\":\"/api/components\"},{\"text\":\"Routing\",\"link\":\"/api/routing\"}]},{\"text\":\"Vite Router Plugin\",\"items\":[{\"text\":\"Vite Plugin\",\"link\":\"/vite/plugin\"}]}],\"socialLinks\":[{\"icon\":\"github\",\"link\":\"https://github.com/natxocc/sigpro\"}]},\"locales\":{},\"scrollOffset\":134,\"cleanUrls\":false}");</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
55
docs/README.md
Normal file
55
docs/README.md
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
<div class="w-full -mt-10"><section class="relative py-20 overflow-hidden border-b border-base-200/30 text-center flex flex-col items-center"><div class="relative z-10 max-w-5xl mx-auto px-6 flex flex-col items-center"><div class="flex justify-center mb-10"><img src="logo.svg" alt="SigPro Logo" class="w-48 h-48 md:w-64 md:h-64 object-contain drop-shadow-2xl"></div><h1 class="text-7xl md:text-9xl font-black tracking-tighter mb-4 bg-clip-text text-transparent bg-linear-to-r from-primary via-secondary to-accent !text-center w-full">SigPro</h1><div class="text-2xl md:text-3xl font-bold text-base-content/90 mb-4 !text-center w-full">Atomic Unified Reactive Engine</div><div class="text-xl text-base-content/60 max-w-3xl mx-auto mb-10 leading-relaxed italic text-balance font-light !text-center w-full">"The efficiency of direct DOM manipulation with the elegance of functional reactivity."</div><div class="flex flex-wrap justify-center gap-4 w-full"><a href="#/install" class="btn btn-primary btn-lg shadow-xl shadow-primary/20 group px-10 border-none">Get Started <span class="group-hover:translate-x-1 transition-transform inline-block">→</span></a><button onclick="window.open('https://github.com/natxocc/sigpro')" class="btn btn-outline btn-lg border-base-300 hover:bg-base-300 hover:text-base-content">GitHub</button></div></div><div class="absolute top-0 left-1/2 -translate-x-1/2 w-full h-full -z-0 opacity-10 pointer-events-none"><div class="absolute top-10 left-1/4 w-96 h-96 bg-primary filter blur-3xl rounded-full animate-pulse"></div><div class="absolute bottom-10 right-1/4 w-96 h-96 bg-accent filter blur-3xl rounded-full animate-pulse" style="animation-delay: 2.5s"></div></div></section></div>
|
||||||
|
|
||||||
|
<section class="max-w-6xl mx-auto px-6 py-16"><div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 items-stretch"><div class="card bg-base-200/30 border border-base-300 hover:border-primary/40 transition-all p-1"><div class="card-body p-6"><h3 class="card-title text-xl font-black text-primary italic">FUNCTIONAL</h3><p class="text-sm opacity-70">No strings. No templates. Pure JS function calls for instant DOM mounting.</p></div></div><div class="card bg-base-200/30 border border-base-300 hover:border-secondary/40 transition-all p-1"><div class="card-body p-6"><h3 class="card-title text-xl font-black text-secondary italic">ATOMIC</h3><p class="text-sm opacity-70">Fine‑grained signals update exactly what changes. No V‑DOM diffing overhead.</p></div></div><div class="card bg-base-200/30 border border-base-300 hover:border-accent/40 transition-all p-1"><div class="card-body p-6"><h3 class="card-title text-xl font-black text-accent italic">ULTRA‑THIN</h3><p class="text-sm opacity-70">Sub‑2KB runtime. Infinitely smaller bundle than React, Vue or even Svelte.</p></div></div><div class="card bg-base-200/30 border border-base-300 hover:border-base-content/20 transition-all p-1"><div class="card-body p-6"><h3 class="card-title text-xl font-black italic text-base-content">COMPILER‑FREE</h3><p class="text-sm opacity-70">Standard Vanilla JS. What you write is what the browser executes. Period.</p></div></div></div></section>
|
||||||
|
|
||||||
|
<div class="max-w-6xl mx-auto px-6 py-8"><h2 class="text-4xl font-black mb-6">Functional DOM Construction</h2><p class="text-lg opacity-80 mb-6">SigPro replaces slow "Template Parsing" with <strong>High‑Efficiency Function Calls</strong>. While other frameworks force the browser to parse strings of HTML or execute complex JSX transformations, SigPro uses a direct functional approach.</p>
|
||||||
|
|
||||||
|
<table class="table w-full mb-12">
|
||||||
|
<thead><tr><th>Feature</th><th>Standard HTML / JSX</th><th>SigPro Functional</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>Syntax</td><td><code><div>Hello</div></code></td><td><code>div("Hello")</code> (or <code>h('div', "Hello")</code>)</td></tr>
|
||||||
|
<tr><td>Processing</td><td>Parse → Diff → Patch</td><td>Direct API Call</td></tr>
|
||||||
|
<tr><td>Overhead</td><td>High (V‑DOM / Parser)</td><td><strong>Zero</strong></td></tr>
|
||||||
|
<tr><td>Reactivity</td><td>Component‑wide</td><td><strong>Atomic (Node‑level)</strong></td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h3 class="text-2xl font-bold mt-8 mb-4">Less Code, More Power</h3>
|
||||||
|
<p class="mb-4">By sharing a minuscule runtime, your final application bundle is <strong>infinitely smaller</strong>.</p>
|
||||||
|
<ul class="list-disc pl-6 space-y-2 mb-8">
|
||||||
|
<li><strong>React/Vue:</strong> You ship a heavy orchestrator (~30‑90KB) just to say "Hello World".</li>
|
||||||
|
<li><strong>Solid/Svelte:</strong> You still depend on a compilation step that generates extra boilerplate.</li>
|
||||||
|
<li><strong>SigPro:</strong> You ship <strong>Pure Vanilla JS</strong>. The runtime is so small that it often costs less than a single high‑res icon.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3 class="text-2xl font-bold mt-8 mb-4">Two Ways to Use SigPro (v1.2.19+)</h3>
|
||||||
|
<p class="mb-2"><strong>🎯 Modern ESM (recommended):</strong> Import only the functions you need – zero global pollution.</p>
|
||||||
|
<pre class="bg-base-300/30 p-4 rounded-lg mb-4"><code>import { $, div, button, mount } from 'sigpro';
|
||||||
|
const count = $(0);
|
||||||
|
mount(() => div([ button({ onclick: () => count(count()+1) }, count) ]), '#app');</code></pre>
|
||||||
|
<p class="mb-2"><strong>🌍 Classic Global (IIFE):</strong> Load the script and everything is automatically on <code>window</code> – no imports needed.</p>
|
||||||
|
<pre class="bg-base-300/30 p-4 rounded-lg mb-4"><code><script src="https://cdn.jsdelivr.net/npm/sigpro@1.2.19/dist/sigpro.js"></script>
|
||||||
|
<script>
|
||||||
|
const count = $(0);
|
||||||
|
mount(() => div([ button({ onclick: () => count(count()+1) }, count) ]), '#app');
|
||||||
|
</script></code></pre>
|
||||||
|
<p class="mb-2"><strong>🔧 ESM + Global injection:</strong> If you want the global helpers but still use <code>type="module"</code>, call <code>sigpro()</code>.</p>
|
||||||
|
<pre class="bg-base-300/30 p-4 rounded-lg"><code><script type="module">
|
||||||
|
import { sigpro } from 'https://cdn.jsdelivr.net/npm/sigpro@1.2.19/+esm';
|
||||||
|
sigpro(); // now $, div, button, etc. are global
|
||||||
|
</script></code></pre>
|
||||||
|
|
||||||
|
<h3 class="text-2xl font-bold mt-10 mb-4">Precision Engineering</h3>
|
||||||
|
<h4 class="text-xl font-semibold mt-6 mb-2">1. Functional Efficiency</h4>
|
||||||
|
<p><code>div()</code>, <code>button()</code>, <code>span()</code>… These aren't just wrappers; they are pre‑optimized constructors. When you call <code>div({ class: 'btn' }, "Click")</code>, SigPro creates the element and attaches its reactive listeners in a single, surgical operation.</p>
|
||||||
|
|
||||||
|
<h4 class="text-xl font-semibold mt-6 mb-2">2. The "No‑Bundle" Bundle</h4>
|
||||||
|
<p>Because SigPro is so small, it is the only engine where <strong>the more code you write, the more the efficiency gap grows</strong>. While others grow linearly with components and framework overhead, SigPro stays flat, leveraging the native power of modern browser engines.</p>
|
||||||
|
|
||||||
|
<h4 class="text-xl font-semibold mt-6 mb-2">3. Shared Runtime</h4>
|
||||||
|
<p>All components share the same atomic engine. One signal can update a single character in a paragraph across 100 components without ever re‑evaluating the component functions themselves.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="bg-base-200/50 rounded-3xl p-10 my-16 border border-base-300 shadow-inner max-w-6xl mx-auto"><div class="grid grid-cols-1 lg:grid-cols-3 gap-8 items-center"><div class="lg:col-span-2"><h2 class="text-4xl font-black mb-4 mt-0 tracking-tight italic text-primary">Kill the Bloat.</h2><p class="text-xl opacity-80 leading-relaxed">Stop shipping 100KB of "Framework" for 2KB of business logic. SigPro gives you the tools to build ultra‑fast, modern apps with <strong>True Vanilla Performance</strong>.</p></div></div></div>
|
||||||
|
|
||||||
|
<div class="text-center py-10 opacity-30 font-mono text-xs tracking-widest uppercase">Precision Reactive Engine — NatxoCC</div>
|
||||||
20
docs/_sidebar.md
Normal file
20
docs/_sidebar.md
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
* [**Home**](README.md)
|
||||||
|
|
||||||
|
* **Introduction**
|
||||||
|
* [Installation](install.md)
|
||||||
|
* [Vite Plugin](vite/plugin.md)
|
||||||
|
|
||||||
|
* **API Reference**
|
||||||
|
* [Quick Start](api/quick.md)
|
||||||
|
* [Signals & Proxies](api/signal.md)
|
||||||
|
* [watch](api/watch.md)
|
||||||
|
* [when](api/when.md)
|
||||||
|
* [each](api/each.md)
|
||||||
|
* [router](api/router.md)
|
||||||
|
* [fx](api/fx.md)
|
||||||
|
* [req](api/req.md)
|
||||||
|
* [mount](api/mount.md)
|
||||||
|
* [h](api/h.md)
|
||||||
|
* [Tags](api/tags.md)
|
||||||
|
* [Global Store](api/global.md)
|
||||||
|
* [JSX Style](api/jsx.md)
|
||||||
File diff suppressed because one or more lines are too long
173
docs/api/each.md
Normal file
173
docs/api/each.md
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
# Reactive Lists: `each( )`
|
||||||
|
|
||||||
|
The `each` function is a high‑performance keyed list renderer. It maps a reactive array to DOM nodes and surgically updates only the items that changed (added, removed, or reordered). Unlike a simple `.map()`, `each` reuses DOM nodes and preserves internal state.
|
||||||
|
|
||||||
|
## Function Signature
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
each(
|
||||||
|
source: Signal<any[]> | (() => any[]) | any[],
|
||||||
|
itemFn: (item: any, index: number) => Node | (() => Node),
|
||||||
|
keyField?: string
|
||||||
|
): HTMLElement
|
||||||
|
```
|
||||||
|
|
||||||
|
| Parameter | Type | Required | Description |
|
||||||
|
| :--- | :--- | :--- | :--- |
|
||||||
|
| **`source`** | `Signal`, `() => any[]`, or `any[]` | Yes | The reactive array to iterate over. |
|
||||||
|
| **`itemFn`** | `(item, index) => Node` | Yes | Returns a DOM node (or a function that returns a node) for each item. |
|
||||||
|
| **`keyField`** | `string` | No | Name of the property to use as unique key (e.g., `"id"`). Default: `item?.id ?? index`. |
|
||||||
|
|
||||||
|
**Returns:** A `div` with `style="display: contents"` that contains the live list.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage Patterns
|
||||||
|
|
||||||
|
### 1. Basic Keyed List (Recommended)
|
||||||
|
|
||||||
|
Pass the name of the property that contains the unique identifier (e.g., `"id"`). This allows SigPro to reuse DOM nodes when the list is reordered or filtered.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const users = $([
|
||||||
|
{ id: 1, name: "Alice" },
|
||||||
|
{ id: 2, name: "Bob" }
|
||||||
|
]);
|
||||||
|
|
||||||
|
ul({ class: "list" }, [
|
||||||
|
each(users,
|
||||||
|
(user) => li({ class: "p-2" }, user.name),
|
||||||
|
"id" // ← use property "id" as stable key
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Automatic Key (Simple Lists)
|
||||||
|
|
||||||
|
If you omit the `keyField`, `each` defaults to `item?.id ?? index`. For primitive arrays or objects without an `id`, the index is used.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const tags = $(["Tech", "JS", "Web"]);
|
||||||
|
|
||||||
|
div({ class: "flex gap-1" }, [
|
||||||
|
each(tags, (tag) => span({ class: "badge" }, tag))
|
||||||
|
// key defaults to index (0,1,2) – fine for static order
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Using a Different Property Name
|
||||||
|
|
||||||
|
If your unique identifier is not called `id` (e.g., `_id`, `userId`, `slug`), just pass the property name as the third parameter:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const products = $([
|
||||||
|
{ _id: 101, name: "Laptop" },
|
||||||
|
{ _id: 102, name: "Mouse" }
|
||||||
|
]);
|
||||||
|
|
||||||
|
each(products, (item) => li(item.name), "_id");
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Dynamic Content Using Functions
|
||||||
|
|
||||||
|
If your `itemFn` returns a **function**, that function is re‑executed every time the item’s data changes (but the node is reused).
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const todos = $([
|
||||||
|
{ id: 1, text: "Learn SigPro", done: false }
|
||||||
|
]);
|
||||||
|
|
||||||
|
each(todos,
|
||||||
|
(todo) => div([
|
||||||
|
input({ type: "checkbox", checked: () => todo.done, onInput: e => todo.done = e.target.checked }),
|
||||||
|
span(() => todo.done ? s(todo.text) : todo.text)
|
||||||
|
]),
|
||||||
|
"id"
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Source as a Plain Array or Function
|
||||||
|
|
||||||
|
`source` can be a plain array (non‑reactive) or a function that returns an array – it will still react to changes if signals are read inside the function.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const filter = $("all");
|
||||||
|
|
||||||
|
const filteredTodos = () => {
|
||||||
|
const all = todos();
|
||||||
|
if (filter() === "active") return all.filter(t => !t.done);
|
||||||
|
return all;
|
||||||
|
};
|
||||||
|
|
||||||
|
each(filteredTodos, (todo) => li(todo.text), "id");
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## How It Works (Reconciliation)
|
||||||
|
|
||||||
|
When the `source` changes, `each`:
|
||||||
|
|
||||||
|
1. **Compares keys** between the old and new items using the specified `keyField` (or `item.id` / index).
|
||||||
|
2. **Reuses existing DOM nodes** for keys that stay the same.
|
||||||
|
3. **Moves nodes** if order changed (no recreation).
|
||||||
|
4. **Creates new nodes** for new keys.
|
||||||
|
5. **Destroys nodes** for removed keys – cleans up all effects, event listeners, and child components.
|
||||||
|
|
||||||
|
> This is much more efficient than destroying and rebuilding the whole list on every update.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Performance Tips
|
||||||
|
|
||||||
|
- **Stable keys** – Use a property that never changes (like a database primary key). Avoid `Math.random()` or array `index` for lists that can be reordered.
|
||||||
|
- **State preservation** – If a list item contains an input or local state, using a stable key ensures that state is preserved even when the list is filtered or sorted.
|
||||||
|
- **Lazy item functions** – If an item is expensive to render, wrap it in a function: `() => ExpensiveComponent(item)`. The component is only created when the item actually appears in the DOM.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary Comparison
|
||||||
|
|
||||||
|
| Feature | Standard `Array.map` | SigPro `each` |
|
||||||
|
| :--- | :--- | :--- |
|
||||||
|
| **Re‑renders on change** | Re‑creates entire list | Only adds/removes/moves changed items |
|
||||||
|
| **DOM nodes** | New nodes every time | **Reused via keys** |
|
||||||
|
| **Memory cleanup** | Manual (or leak) | **Automatic** (destroy on removal) |
|
||||||
|
| **Internal state per item** | Lost on every update | **Preserved** (if key stable) |
|
||||||
|
| **Reactivity** | None (manual re‑render) | Built‑in, fine‑grained |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Complete Example
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const items = $([
|
||||||
|
{ id: 1, name: "Apple", price: 1.2 },
|
||||||
|
{ id: 2, name: "Banana", price: 0.8 }
|
||||||
|
]);
|
||||||
|
|
||||||
|
const addItem = () => {
|
||||||
|
const newId = Date.now();
|
||||||
|
items([...items(), { id: newId, name: `Item ${newId}`, price: 1.0 }]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeItem = (id) => {
|
||||||
|
items(items().filter(i => i.id !== id));
|
||||||
|
};
|
||||||
|
|
||||||
|
const App = () =>
|
||||||
|
div([
|
||||||
|
button({ onClick: addItem }, "Add item"),
|
||||||
|
ul(
|
||||||
|
each(items,
|
||||||
|
(item) => li([
|
||||||
|
span(`${item.name} – $${item.price}`),
|
||||||
|
button({ onClick: () => removeItem(item.id) }, "X")
|
||||||
|
]),
|
||||||
|
"id"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
|
||||||
|
mount(App, '#app');
|
||||||
|
```
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
184
docs/api/fx.md
Normal file
184
docs/api/fx.md
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
# Animation Helper: `fx( )`
|
||||||
|
|
||||||
|
The `fx` function applies simple **enter animations** to DOM elements. You can either use a predefined CSS keyframes animation or declare inline transition effects (scale, slide, rotate, blur). It is designed to be used when dynamically creating elements – especially inside `when` or `each` branches.
|
||||||
|
|
||||||
|
## Function Signature
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
fx(
|
||||||
|
options: {
|
||||||
|
name?: string; // CSS keyframes animation name (will append '-in')
|
||||||
|
duration?: number; // Animation duration in ms (default: 200)
|
||||||
|
scale?: boolean; // Start with scale(0.95) → none
|
||||||
|
slide?: boolean; // Start with translateY(-10px) → none
|
||||||
|
rotate?: boolean; // Start with rotate(-2deg) → none
|
||||||
|
blur?: boolean; // Start with blur(4px) → none
|
||||||
|
},
|
||||||
|
child: Node | (() => Node)
|
||||||
|
): Node
|
||||||
|
```
|
||||||
|
|
||||||
|
| Parameter | Type | Required | Description |
|
||||||
|
| :--- | :--- | :--- | :--- |
|
||||||
|
| **`options`** | `object` | Yes | Animation configuration. |
|
||||||
|
| **`options.name`** | `string` | No | Name of a CSS `@keyframes` animation. The actual animation name becomes `${name}-in`. |
|
||||||
|
| **`options.duration`** | `number` | No | Duration in milliseconds (default `200`). |
|
||||||
|
| **`options.scale`** | `boolean` | No | Add a scale transform from `0.95` to `none`. |
|
||||||
|
| **`options.slide`** | `boolean` | No | Add a vertical slide from `translateY(-10px)` to `none`. |
|
||||||
|
| **`options.rotate`** | `boolean` | No | Add a small rotation from `rotate(-2deg)` to `none`. |
|
||||||
|
| **`options.blur`** | `boolean` | No | Add a blur filter from `blur(4px)` to `none`. |
|
||||||
|
| **`child`** | `Node` or `() => Node` | Yes | The element to animate. If a function is passed, it is called to obtain the node. |
|
||||||
|
|
||||||
|
**Returns:** The same DOM node (or the child if it is not a `Node`), after applying the animation setup.
|
||||||
|
|
||||||
|
> **Availability:** `fx` is exported from the SigPro module. In **ESM** you must import it (`import { fx } from 'sigpro'`) or inject all globals via `sigpro()`. In the **IIFE** classic script, it is automatically available on `window`. The examples below assume the function is already in scope.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage Patterns
|
||||||
|
|
||||||
|
### 1. Named CSS Keyframes Animation
|
||||||
|
|
||||||
|
Define a `@keyframes` rule in your CSS, for example:
|
||||||
|
|
||||||
|
```css
|
||||||
|
@keyframes fade-in {
|
||||||
|
from { opacity: 0; }
|
||||||
|
to { opacity: 1; }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then apply it with `fx`:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const MyComponent = () =>
|
||||||
|
fx({ name: "fade", duration: 300 },
|
||||||
|
div("I will fade in")
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
> The animation name used is `${name}-in`. In this example: `fade-in`.
|
||||||
|
|
||||||
|
### 2. Inline Transition (Scale + Opacity)
|
||||||
|
|
||||||
|
No CSS keyframes needed. The element starts with `opacity: 0` and `transform: scale(0.95)`, then transitions to `opacity: 1` and `transform: none`.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
fx({ scale: true, duration: 200 },
|
||||||
|
button({ onClick: () => alert("Hi") }, "Click me")
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Combining Multiple Effects
|
||||||
|
|
||||||
|
You can combine `scale`, `slide`, `rotate`, and `blur` at the same time.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
fx({ scale: true, slide: true, blur: true, duration: 250 },
|
||||||
|
div({ class: "card" }, "Smooth enter")
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Using with `when` (Conditional Rendering)
|
||||||
|
|
||||||
|
Wrap the branch content with `fx` to animate entering elements.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
when(show,
|
||||||
|
() => fx({ slide: true },
|
||||||
|
div("This slides in when visible")
|
||||||
|
)
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Using a Function as Child
|
||||||
|
|
||||||
|
If the element is created inside a function (e.g. to avoid recreation until needed), pass a function that returns the node.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
fx({ scale: true },
|
||||||
|
() => div("Lazy created and then animated")
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## What Happens Under the Hood
|
||||||
|
|
||||||
|
### With `name` (CSS animation)
|
||||||
|
|
||||||
|
- Sets `el.style.animation = `${name}-in ${duration}ms``.
|
||||||
|
- The element animates according to your keyframes.
|
||||||
|
- No further inline style changes are applied.
|
||||||
|
|
||||||
|
### Without `name` (transition effects)
|
||||||
|
|
||||||
|
- Sets `el.style.transition = `all ${duration}ms ease``.
|
||||||
|
- Sets initial `opacity: 0`.
|
||||||
|
- Applies initial transforms (`scale`, `slide`, `rotate`) if selected.
|
||||||
|
- Applies initial `filter: blur(4px)` if `blur: true`.
|
||||||
|
- In the next animation frame (via `requestAnimationFrame`), sets:
|
||||||
|
- `opacity: 1`
|
||||||
|
- `transform: none`
|
||||||
|
- `filter: none`
|
||||||
|
- The element transitions smoothly from the start state to the final state.
|
||||||
|
|
||||||
|
> **Important:** The element must be **in the DOM** when the animation starts. `fx` does **not** automatically mount the node – you must already have appended it or be about to mount it. In practice, when you call `fx` inside a component that is being mounted, the element will be added to the DOM shortly after, and the animation runs correctly.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Complete Example
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const App = () =>
|
||||||
|
div([
|
||||||
|
fx({ name: "fade", duration: 400 },
|
||||||
|
h1("Welcome to SigPro")
|
||||||
|
),
|
||||||
|
fx({ scale: true, slide: true, duration: 250 },
|
||||||
|
button({ onClick: () => alert("Animated!") }, "Animated button")
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
|
||||||
|
mount(App, "#app");
|
||||||
|
```
|
||||||
|
|
||||||
|
With accompanying CSS:
|
||||||
|
|
||||||
|
```css
|
||||||
|
@keyframes fade-in {
|
||||||
|
from { opacity: 0; transform: translateY(10px); }
|
||||||
|
to { opacity: 1; transform: translateY(0); }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- `fx` is **not** required for basic reactivity – it is purely a visual helper for enter animations.
|
||||||
|
- For exit animations (when an element is removed), use CSS transitions on the element itself combined with `when` – or consider adding a wrapper that delays removal. SigPro does not include built‑in exit animations.
|
||||||
|
- The function returns the same node you passed, so you can inline it inside `h` or tag helpers:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
div([
|
||||||
|
fx({ scale: true }, span("Hello"))
|
||||||
|
])
|
||||||
|
```
|
||||||
|
|
||||||
|
- If `child` is not a DOM node (e.g., a string or number), `fx` returns it unchanged – no animation is applied.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
| Option | Effect |
|
||||||
|
| :--- | :--- |
|
||||||
|
| `name` | Uses `@keyframes ${name}-in` CSS animation. |
|
||||||
|
| `duration` | Controls animation/transition length (ms). |
|
||||||
|
| `scale` | Start scale `0.95` → `none`. |
|
||||||
|
| `slide` | Start `translateY(-10px)` → `none`. |
|
||||||
|
| `rotate` | Start `rotate(-2deg)` → `none`. |
|
||||||
|
| `blur` | Start `blur(4px)` → `none`. |
|
||||||
|
|
||||||
|
Combine options to create smooth, modern entrance effects without writing extra CSS.
|
||||||
141
docs/api/global.md
Normal file
141
docs/api/global.md
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
# Global State Management: Atomic & Modular
|
||||||
|
|
||||||
|
SigPro leverages the native power and efficiency of **signals** to create robust global stores with **zero complexity**. While other frameworks force you into heavy libraries and rigid boilerplate (Redux, Pinia, or Svelte stores), SigPro treats “the store” as a simple architectural choice: **defining a signal outside of a component.**
|
||||||
|
|
||||||
|
> **Availability:** `$` (and other core functions) are exported from the SigPro module. In **ESM** you must import them (`import { $ } from 'sigpro'`) or inject all globals via `sigpro()`. In the **IIFE** classic script, `$` is automatically available on `window`. The examples below assume `$` is already in scope (via import or global).
|
||||||
|
|
||||||
|
## Modular Organization (Zero Constraints)
|
||||||
|
|
||||||
|
You are not restricted to a single `store.js`. You can organize your state by **feature**, **domain**, or **page**. Since a SigPro store is just a standard JavaScript module exporting signals, you can name your files whatever you like (`auth.js`, `cart.js`, `settings.js`) to keep your logic clean.
|
||||||
|
|
||||||
|
### 1. File‑Based Stores (`<any-name>.js`)
|
||||||
|
|
||||||
|
Creating a dedicated file allows you to export only what you need. This modularity ensures **tree shaking** works perfectly – you never load state that isn’t imported.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// auth.js
|
||||||
|
import { $ } from 'sigpro';
|
||||||
|
|
||||||
|
// A simple global signal
|
||||||
|
export const user = $({ name: "Guest", loggedIn: false });
|
||||||
|
|
||||||
|
// A persistent global signal (auto‑syncs with localStorage)
|
||||||
|
export const theme = $("light", "app-theme-pref");
|
||||||
|
|
||||||
|
// A computed global signal that reacts to the 'user' signal
|
||||||
|
export const welcomeMessage = $(() => `Welcome back, ${user().name}!`);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Cross‑Component Consumption
|
||||||
|
|
||||||
|
Once exported, these signals act as a **single source of truth**. SigPro ensures that if a signal changes in one file, every component importing it across the entire app updates **atomically** without a full re‑render.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Profile.js
|
||||||
|
import { user } from "./auth.js";
|
||||||
|
|
||||||
|
const Profile = () => div([
|
||||||
|
h2(() => user().name),
|
||||||
|
button({ onclick: () => user({ name: "John Doe", loggedIn: true }) }, "Log In")
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Navbar.js
|
||||||
|
import { welcomeMessage, theme } from "./auth.js";
|
||||||
|
|
||||||
|
const Navbar = () => nav({ class: () => theme() }, [
|
||||||
|
span(() => welcomeMessage())
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Why SigPro Stores Are Superior
|
||||||
|
|
||||||
|
| Feature | SigPro | Redux / Pinia / Svelte |
|
||||||
|
| :-------------------- | :---------------------------- | :------------------------------ |
|
||||||
|
| **Boilerplate** | **0%** (just a variable) | High (actions, reducers, stores)|
|
||||||
|
| **Organization** | **Unlimited** (any filename) | Often strictly “store” files |
|
||||||
|
| **Persistence** | **Native** (just add a key) | Requires middleware / plugins |
|
||||||
|
| **Learning Curve** | **Instant** | Steep / complex |
|
||||||
|
| **Bundle Size** | **0KB** (part of core) | 10KB – 30KB+ |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## The Persistence Advantage
|
||||||
|
|
||||||
|
The magic of SigPro’s `$(value, "key")` is that it works identically for local and global states. By simply adding a second argument, your modular store survives browser refreshes automatically. No manual `localStorage.getItem` or `JSON.parse` logic is ever required.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// This single line creates a global, reactive,
|
||||||
|
// and persistent store for a shopping cart.
|
||||||
|
export const cart = $([], "session-cart");
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary of Scopes
|
||||||
|
|
||||||
|
| Scope | Definition | Behaviour |
|
||||||
|
| :-------------- | :-------------------------------------------------------------- | :-------------------------------------------- |
|
||||||
|
| **Local** | Signal defined **inside** a component | Unique to every component instance |
|
||||||
|
| **Module** | Signal defined **outside** a component (same file) | Shared by all instances within that file |
|
||||||
|
| **Global** | Signal defined in a **separate file** and imported | Shared across the entire application |
|
||||||
|
| **Persistent** | Any Signal defined with a **key** (e.g., `$([], "cart")`) | Shared globally and persisted in `localStorage` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Complete Example – Todo Store
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// store/todos.js
|
||||||
|
import { $ } from 'sigpro';
|
||||||
|
|
||||||
|
export const todos = $([], "todos");
|
||||||
|
export const filter = $("all");
|
||||||
|
|
||||||
|
export const addTodo = (text) => {
|
||||||
|
todos([...todos(), { id: Date.now(), text, done: false }]);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const toggleTodo = (id) => {
|
||||||
|
todos(todos().map(t => t.id === id ? { ...t, done: !t.done } : t));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const filteredTodos = $(() => {
|
||||||
|
const all = todos();
|
||||||
|
if (filter() === "active") return all.filter(t => !t.done);
|
||||||
|
if (filter() === "completed") return all.filter(t => t.done);
|
||||||
|
return all;
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// components/TodoApp.js
|
||||||
|
import { todos, filter, addTodo, toggleTodo, filteredTodos } from "../store/todos.js";
|
||||||
|
|
||||||
|
const TodoApp = () =>
|
||||||
|
div({ class: "todo-app" }, [
|
||||||
|
input({ placeholder: "Add todo...", onKeyDown: (e) => {
|
||||||
|
if (e.key === "Enter" && e.target.value) {
|
||||||
|
addTodo(e.target.value);
|
||||||
|
e.target.value = "";
|
||||||
|
}
|
||||||
|
}}),
|
||||||
|
div({ class: "filters" }, [
|
||||||
|
button({ onClick: () => filter("all") }, "All"),
|
||||||
|
button({ onClick: () => filter("active") }, "Active"),
|
||||||
|
button({ onClick: () => filter("completed") }, "Completed")
|
||||||
|
]),
|
||||||
|
ul(
|
||||||
|
each(filteredTodos,
|
||||||
|
(todo) => li([
|
||||||
|
input({ type: "checkbox", checked: () => todo.done, onInput: () => toggleTodo(todo.id) }),
|
||||||
|
span(() => todo.done ? s(todo.text) : todo.text)
|
||||||
|
]),
|
||||||
|
(todo) => todo.id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
|
||||||
|
mount(TodoApp, "#app");
|
||||||
|
```
|
||||||
161
docs/api/h.md
Normal file
161
docs/api/h.md
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
# Hyperscript Function: `h( )`
|
||||||
|
|
||||||
|
The `h` function is the **core DOM builder** of SigPro. It creates DOM elements from a tag name, props, and children. While the global tag helpers (`div()`, `button()`, etc.) are built on top of `h`, you may need `h` directly for dynamic tag names or when you prefer an explicit function style.
|
||||||
|
|
||||||
|
> **Availability:** `h` and all tag helpers (`div`, `button`, etc.) are exported from the SigPro module. In **ESM** you must import them (`import { h, div, button } from 'sigpro'`) or inject all globals via `sigpro()`. In the **IIFE** classic script, `h` and all tag helpers are automatically available on `window`. The examples below assume the functions are already in scope.
|
||||||
|
|
||||||
|
## Function Signature
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
h(
|
||||||
|
tag: string | Function,
|
||||||
|
props?: object | Node | any[],
|
||||||
|
children?: any
|
||||||
|
): Node
|
||||||
|
```
|
||||||
|
|
||||||
|
| Parameter | Type | Description |
|
||||||
|
| :--- | :--- | :--- |
|
||||||
|
| **`tag`** | `string` or `Function` | HTML tag name (e.g., `"div"`) or a component function. |
|
||||||
|
| **`props`** | `object` | Optional. Attributes, event handlers, refs, etc. If not an object, it becomes `children`. |
|
||||||
|
| **`children`** | `any` | Optional. Text, nodes, arrays, or reactive functions. |
|
||||||
|
|
||||||
|
**Returns:** A DOM node (or an array of nodes when the tag is a component that returns an array).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage Patterns
|
||||||
|
|
||||||
|
### 1. Basic Element Creation
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Simple div with text
|
||||||
|
h('div', {}, 'Hello world');
|
||||||
|
|
||||||
|
// With attributes
|
||||||
|
h('button', { class: 'btn', onclick: () => alert('clicked') }, 'Click me');
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Nested Children
|
||||||
|
|
||||||
|
Children can be a single node, an array, or a function.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
h('div', { class: 'container' }, [
|
||||||
|
h('h1', {}, 'Title'),
|
||||||
|
h('p', {}, 'Paragraph text')
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Reactive Children
|
||||||
|
|
||||||
|
Pass a **function** as a child – it will be re‑evaluated whenever any signal inside changes, and the DOM will be patched surgically.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const count = $(0);
|
||||||
|
|
||||||
|
h('div', {}, [
|
||||||
|
h('p', {}, () => `Count: ${count()}`),
|
||||||
|
h('button', { onclick: () => count(count() + 1) }, '+1')
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Reactive Attributes
|
||||||
|
|
||||||
|
Pass a function as an attribute value to keep it dynamic.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const theme = $('dark');
|
||||||
|
|
||||||
|
h('div', { class: () => `box ${theme()}` }, 'Themed box');
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Two‑Way Binding
|
||||||
|
|
||||||
|
Assign a signal directly to `value` or `checked` on form elements – SigPro automatically syncs both ways.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const name = $('');
|
||||||
|
|
||||||
|
h('input', {
|
||||||
|
type: 'text',
|
||||||
|
value: name, // two-way binding
|
||||||
|
placeholder: 'Your name'
|
||||||
|
});
|
||||||
|
h('p', {}, () => `Hello, ${name()}`);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. Component Functions as `tag`
|
||||||
|
|
||||||
|
You can pass a component function directly to `h`. SigPro will execute it with the provided props and an `emit` helper for custom events.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const Button = (props, { children }) =>
|
||||||
|
h('button', { class: 'btn', onclick: props.onClick }, children);
|
||||||
|
|
||||||
|
const App = () =>
|
||||||
|
h('div', {}, [
|
||||||
|
h(Button, { onClick: () => alert('clicked') }, 'Custom button')
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7. SVG Elements
|
||||||
|
|
||||||
|
Use `h` with SVG tag names – SigPro automatically applies the correct namespace.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
h('svg', { width: 100, height: 100 }, [
|
||||||
|
h('circle', { cx: 50, cy: 50, r: 40, fill: 'red' })
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Special Props
|
||||||
|
|
||||||
|
| Prop | Behaviour |
|
||||||
|
| :--- | :--- |
|
||||||
|
| **`ref`** | `ref: (el) => ...` or `ref: { current: null }` – provides direct access to the DOM node after creation. |
|
||||||
|
| **`onEvent`** | Any prop starting with `on` (e.g., `onClick`, `onInput`) is treated as an event listener. Automatically removed on cleanup. |
|
||||||
|
| **`value` / `checked`** | When a signal is passed, creates two‑way binding for inputs, textareas, and selects. |
|
||||||
|
| **`class`** | You can use `class` (not `className`). Accepts a string or a reactive function. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `h` vs Tag Helpers
|
||||||
|
|
||||||
|
| Feature | `h('div', ...)` | `div(...)` (tag helper) |
|
||||||
|
| :--- | :--- | :--- |
|
||||||
|
| **Dynamic tag names** | ✅ `h(tagName, ...)` | ❌ Must know tag name at write time |
|
||||||
|
| **Explicit style** | More verbose | Cleaner, DSL‑like |
|
||||||
|
| **Availability** | Import or global | Import or global (same) |
|
||||||
|
| **Performance** | Identical | Identical (helpers call `h` internally) |
|
||||||
|
|
||||||
|
> **Recommendation:** Use tag helpers (`div()`, `button()`, etc.) for most cases – they are shorter and more readable. Use `h` directly only when the tag name is dynamic (e.g., `h(props.tag, ...)`). Remember that in ESM you need to import the helpers or call `sigpro()` to make them global.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Complete Example
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { $, h, mount } from 'sigpro';
|
||||||
|
|
||||||
|
const dynamicTag = $('h1');
|
||||||
|
|
||||||
|
const App = () =>
|
||||||
|
h('div', { class: 'demo' }, [
|
||||||
|
h(dynamicTag(), {}, () => `Current tag: ${dynamicTag()}`),
|
||||||
|
h('button', { onclick: () => dynamicTag(dynamicTag() === 'h1' ? 'h2' : 'h1') }, 'Toggle heading size')
|
||||||
|
]);
|
||||||
|
|
||||||
|
mount(App, '#app');
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
- `h` is the low‑level DOM builder used internally by all tag helpers.
|
||||||
|
- It supports reactive attributes, reactive children, two‑way binding, event listeners, and SVG.
|
||||||
|
- Use `h` directly when you need a **dynamic tag name**; otherwise, prefer the convenient tag helpers (import them or inject globally).
|
||||||
|
- Components written with `h` are fully reactive and automatically cleaned up.
|
||||||
309
docs/api/jsx.md
Normal file
309
docs/api/jsx.md
Normal file
@@ -0,0 +1,309 @@
|
|||||||
|
# Hyperscript & Tag Helpers
|
||||||
|
|
||||||
|
SigPro provides two complementary ways to create DOM elements:
|
||||||
|
|
||||||
|
1. **The `h` function** – the low‑level DOM builder.
|
||||||
|
2. **Global Tag Helpers** (e.g., `div()`, `button()`, `span()`) – a convenient DSL built on top of `h`.
|
||||||
|
|
||||||
|
Both are reactive, auto‑cleanup, and support SVG, events, two‑way binding, and dynamic children.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `h( )` – Hyperscript Function
|
||||||
|
|
||||||
|
The `h` function is the **core DOM builder** of SigPro. Use it directly when you need a dynamic tag name or prefer an explicit style.
|
||||||
|
|
||||||
|
### Function Signature
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
h(
|
||||||
|
tag: string | Function,
|
||||||
|
props?: object | Node | any[],
|
||||||
|
children?: any
|
||||||
|
): Node
|
||||||
|
```
|
||||||
|
|
||||||
|
| Parameter | Type | Description |
|
||||||
|
| :--- | :--- | :--- |
|
||||||
|
| **`tag`** | `string` or `Function` | HTML tag name (e.g., `"div"`) or a component function. |
|
||||||
|
| **`props`** | `object` | Optional. Attributes, event handlers, refs, etc. |
|
||||||
|
| **`children`** | `any` | Optional. Text, nodes, arrays, or reactive functions. |
|
||||||
|
|
||||||
|
**Returns:** A DOM node (or array of nodes when the tag is a component that returns an array).
|
||||||
|
|
||||||
|
### Usage Examples
|
||||||
|
|
||||||
|
```js
|
||||||
|
// Basic element
|
||||||
|
h('div', {}, 'Hello world');
|
||||||
|
|
||||||
|
// With attributes and events
|
||||||
|
h('button', { class: 'btn', onclick: () => alert('clicked') }, 'Click me');
|
||||||
|
|
||||||
|
// Nested children
|
||||||
|
h('div', { class: 'container' }, [
|
||||||
|
h('h1', {}, 'Title'),
|
||||||
|
h('p', {}, 'Paragraph')
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Reactive child (function)
|
||||||
|
const count = $(0);
|
||||||
|
h('div', {}, [
|
||||||
|
h('p', {}, () => `Count: ${count()}`),
|
||||||
|
h('button', { onclick: () => count(count() + 1) }, '+1')
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Reactive attribute
|
||||||
|
const theme = $('dark');
|
||||||
|
h('div', { class: () => `box ${theme()}` }, 'Themed box');
|
||||||
|
|
||||||
|
// Two-way binding on input
|
||||||
|
const name = $('');
|
||||||
|
h('input', { type: 'text', value: name, placeholder: 'Your name' });
|
||||||
|
h('p', {}, () => `Hello, ${name()}`);
|
||||||
|
|
||||||
|
// Component as tag
|
||||||
|
const Button = (props, { children }) =>
|
||||||
|
h('button', { class: 'btn', onclick: props.onClick }, children);
|
||||||
|
|
||||||
|
h(Button, { onClick: () => alert('clicked') }, 'Click me');
|
||||||
|
|
||||||
|
// SVG (auto-namespace)
|
||||||
|
h('svg', { width: 100, height: 100 }, [
|
||||||
|
h('circle', { cx: 50, cy: 50, r: 40, fill: 'red' })
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Special Props
|
||||||
|
|
||||||
|
| Prop | Behaviour |
|
||||||
|
| :--- | :--- |
|
||||||
|
| **`ref`** | `ref: (el) => ...` or `ref: { current: null }` – direct DOM node access. |
|
||||||
|
| **`onEvent`** | Any prop starting with `on` (e.g., `onClick`) is an event listener – auto‑removed on cleanup. |
|
||||||
|
| **`value` / `checked`** | When a signal is passed, creates two‑way binding for form elements. |
|
||||||
|
| **`class`** | Use `class` (not `className`). Accepts a string or reactive function. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Global Tag Helpers (Lowercase)
|
||||||
|
|
||||||
|
When you import SigPro (either via `import 'sigpro'` or the CDN), it automatically injects a helper function for **every standard HTML tag** directly onto `window`. These helpers are **lowercase** and work exactly like `h`, but with a cleaner syntax.
|
||||||
|
|
||||||
|
### Available Helpers
|
||||||
|
|
||||||
|
All standard HTML5 tags: `div`, `span`, `p`, `section`, `nav`, `header`, `footer`, `h1`…`h6`, `ul`, `ol`, `li`, `button`, `a`, `input`, `form`, `table`, `svg`, `circle`, etc.
|
||||||
|
|
||||||
|
### Usage Examples
|
||||||
|
|
||||||
|
```js
|
||||||
|
// Instead of h('div', ...)
|
||||||
|
div({ class: 'container' }, 'Content');
|
||||||
|
|
||||||
|
// Children only (skip props)
|
||||||
|
section([
|
||||||
|
h2('Title'),
|
||||||
|
p('Paragraph')
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Reactive attribute
|
||||||
|
const theme = $('light');
|
||||||
|
div({ class: () => `app-${theme()}` }, 'Themed');
|
||||||
|
|
||||||
|
// Two-way binding
|
||||||
|
const search = $('');
|
||||||
|
input({ type: 'text', value: search, placeholder: 'Search...' });
|
||||||
|
p(() => `You typed: ${search()}`);
|
||||||
|
|
||||||
|
// Dynamic children
|
||||||
|
const count = $(0);
|
||||||
|
div([
|
||||||
|
p(() => `Count: ${count()}`),
|
||||||
|
button({ onClick: () => count(count() + 1) }, '+1')
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Complete Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
const App = () =>
|
||||||
|
div({ class: 'app' }, [
|
||||||
|
h1('Welcome'),
|
||||||
|
input({ value: name, placeholder: 'Your name' }),
|
||||||
|
p(() => `Hello, ${name() || 'stranger'}!`),
|
||||||
|
button({ onClick: () => alert('Hi') }, 'Click me')
|
||||||
|
]);
|
||||||
|
|
||||||
|
mount(App, '#app');
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## JSX with SigPro
|
||||||
|
|
||||||
|
SigPro works seamlessly with JSX. You can use JSX as a compile‑time syntax sugar for `h` calls.
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
#### TypeScript
|
||||||
|
|
||||||
|
```json
|
||||||
|
// tsconfig.json
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"jsx": "react",
|
||||||
|
"jsxFactory": "h",
|
||||||
|
"jsxFragmentFactory": "Fragment"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Vite
|
||||||
|
|
||||||
|
```js
|
||||||
|
// vite.config.js
|
||||||
|
import { defineConfig } from 'vite'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
esbuild: {
|
||||||
|
jsxFactory: 'h',
|
||||||
|
jsxFragmentFactory: 'Fragment'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Babel
|
||||||
|
|
||||||
|
```js
|
||||||
|
// babel.config.js
|
||||||
|
export default {
|
||||||
|
plugins: [
|
||||||
|
['@babel/plugin-transform-react-jsx', {
|
||||||
|
pragma: 'h',
|
||||||
|
pragmaFrag: 'Fragment'
|
||||||
|
}]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Note:** You need to import `h` and `Fragment` from SigPro in every JSX file, or make them global.
|
||||||
|
|
||||||
|
### JSX Example
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
// App.jsx
|
||||||
|
import { $, h, Fragment, mount } from 'sigpro';
|
||||||
|
|
||||||
|
const Button = ({ onClick, children }) => (
|
||||||
|
<button class="btn btn-primary" onclick={onClick}>
|
||||||
|
{children}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
|
||||||
|
const App = () => {
|
||||||
|
const count = $(0);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class="container p-8">
|
||||||
|
<h1 class="text-2xl font-bold">SigPro with JSX</h1>
|
||||||
|
|
||||||
|
<Button onClick={() => count(count() + 1)}>
|
||||||
|
Clicks: {() => count()}
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Fragment>
|
||||||
|
<p>Multiple elements</p>
|
||||||
|
<p>Without extra wrapper</p>
|
||||||
|
</Fragment>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
mount(App, '#app');
|
||||||
|
```
|
||||||
|
|
||||||
|
### What Gets Compiled
|
||||||
|
|
||||||
|
Your JSX:
|
||||||
|
```jsx
|
||||||
|
<div class="container">
|
||||||
|
<Button>Click</Button>
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
Compiles to:
|
||||||
|
```js
|
||||||
|
h('div', { class: "container" },
|
||||||
|
h(Button, {}, "Click")
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Without a Build Step (CDN + Tag Helpers)
|
||||||
|
|
||||||
|
If you don’t want to configure a JSX compiler, you can use the global tag helpers directly. They are available after loading SigPro via CDN.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script type="module">
|
||||||
|
import 'https://cdn.jsdelivr.net/npm/sigpro@1.2.18/+esm';
|
||||||
|
// Now $, $$, watch, h, mount, div, button, etc. are global
|
||||||
|
|
||||||
|
const count = $(0);
|
||||||
|
const App = () =>
|
||||||
|
div({ class: 'container' }, [
|
||||||
|
h1(() => `Count: ${count()}`),
|
||||||
|
button({ onClick: () => count(count() + 1) }, 'Increment')
|
||||||
|
]);
|
||||||
|
|
||||||
|
mount(App, '#app');
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Template Literals Alternative (`htm`)
|
||||||
|
|
||||||
|
For a JSX‑like syntax without a build step, you can combine SigPro with [`htm`](https://github.com/developit/htm).
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { $, h, mount } from 'https://cdn.jsdelivr.net/npm/sigpro@1.2.18/+esm';
|
||||||
|
import htm from 'https://esm.sh/htm';
|
||||||
|
|
||||||
|
const html = htm.bind(h); // bind to SigPro's h function
|
||||||
|
|
||||||
|
const App = () => {
|
||||||
|
const count = $(0);
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<div class="container">
|
||||||
|
<h1>SigPro Demo</h1>
|
||||||
|
<button onclick=${() => count(count() + 1)}>
|
||||||
|
Clicks: ${() => count()}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
};
|
||||||
|
|
||||||
|
mount(App, '#app');
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary Comparison
|
||||||
|
|
||||||
|
| Method | Build Step | Syntax | Recommended for |
|
||||||
|
| :--- | :--- | :--- | :--- |
|
||||||
|
| **`h` function** | Optional | `h('div', ...)` | Dynamic tag names, low‑level control |
|
||||||
|
| **Tag Helpers** | Optional | `div(...)` | Most cases – clean, simple, no build step |
|
||||||
|
| **JSX** | Required | `<div>...</div>` | Large projects, teams familiar with React syntax |
|
||||||
|
| **`htm`** | Optional | `` html`<div>...</div>` `` | Buildless but HTML‑like syntax |
|
||||||
|
|
||||||
|
> **Tip:** All approaches are fully reactive, support two‑way binding, events, SVG, and automatic cleanup. Choose the one that fits your workflow.
|
||||||
150
docs/api/mount.md
Normal file
150
docs/api/mount.md
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
# Application Mounter: `mount( )`
|
||||||
|
|
||||||
|
The `mount` function is the entry point of your reactive world. It bridges the gap between your SigPro logic and the browser's real DOM by rendering a component into a target element and managing its full reactive lifecycle.
|
||||||
|
|
||||||
|
## Function Signature
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
mount(component: Function | Node, target: string | HTMLElement): RuntimeObject
|
||||||
|
```
|
||||||
|
|
||||||
|
| Parameter | Type | Required | Description |
|
||||||
|
| :--- | :--- | :--- | :--- |
|
||||||
|
| **`component`** | `Function` or `Node` | Yes | A component function (returns a Node) or a direct DOM node. |
|
||||||
|
| **`target`** | `string` or `HTMLElement` | Yes | CSS selector (e.g., `"#app"`) or DOM element where the app will be mounted. |
|
||||||
|
|
||||||
|
**Returns:** A `Runtime` object with:
|
||||||
|
- `container`: The actual DOM element created by the renderer.
|
||||||
|
- `destroy()`: A method to completely unmount and clean up the application.
|
||||||
|
|
||||||
|
> **Availability:** `mount` is exported from the SigPro module. In **ESM** you must import it (`import { mount } from 'sigpro'`) or inject all globals via `sigpro()`. In the **IIFE** classic script, it is automatically available on `window`. The examples below assume the function is already in scope.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage Patterns
|
||||||
|
|
||||||
|
### 1. Main Application Entry Point
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { mount } from 'sigpro';
|
||||||
|
|
||||||
|
const App = () => div({ class: "app" }, [
|
||||||
|
h1("Hello SigPro"),
|
||||||
|
button("Click me")
|
||||||
|
]);
|
||||||
|
|
||||||
|
mount(App, '#app');
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Reactive Widget (Island Architecture)
|
||||||
|
|
||||||
|
Mount small reactive components into static HTML pages.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const Counter = () => {
|
||||||
|
const count = $(0);
|
||||||
|
return button({ onclick: () => count(count() + 1) }, () => `Clicks: ${count()}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
mount(Counter, '#sidebar-widget');
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Direct Node Mounting
|
||||||
|
|
||||||
|
You can also mount an already existing DOM node.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const myDiv = div("I am already a node");
|
||||||
|
mount(myDiv, '#container');
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## How It Works (Lifecycle & Cleanup)
|
||||||
|
|
||||||
|
When you call `mount`, SigPro performs these steps:
|
||||||
|
|
||||||
|
1. **Duplicate Detection**
|
||||||
|
SigPro keeps a `WeakMap` (`MOUNTED_NODES`) that tracks which DOM target already has a mounted runtime. If you mount a new component to the same target, the previous instance is **automatically destroyed** before the new one is rendered. This prevents memory leaks and “zombie effects”.
|
||||||
|
|
||||||
|
2. **Render Phase**
|
||||||
|
The `render` function creates a **cleanup container** (a `div` with `style="display: contents"`), and executes the component inside a fresh reactive owner. All effects (`watch`), event listeners, and child components created during this render are captured.
|
||||||
|
|
||||||
|
3. **DOM Injection**
|
||||||
|
The target element is cleared using `replaceChildren()`, and the container (which holds the rendered content) is appended.
|
||||||
|
|
||||||
|
4. **Runtime Object**
|
||||||
|
Returns an object `{ _isRuntime: true, container, destroy }`. The `destroy` function recursively disposes all effects, cleans up DOM nodes, and removes the container from the parent.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Manual Unmounting
|
||||||
|
|
||||||
|
You can call `destroy()` at any time to tear down the application. This is essential for imperatively managed UI like **modals**, **toasts**, or **dynamic panels**.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const widget = mount(MyToast, '#toast-container');
|
||||||
|
|
||||||
|
// Later, remove it completely:
|
||||||
|
widget.destroy();
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Automatic Re‑mount on Same Target
|
||||||
|
|
||||||
|
If you call `mount` a second time on the same target, SigPro automatically destroys the previous instance and replaces it with the new one. No manual cleanup required.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
mount(LoginScreen, '#app');
|
||||||
|
// ... later, after login
|
||||||
|
mount(Dashboard, '#app'); // LoginScreen is destroyed automatically
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## What is Automatically Cleaned Up
|
||||||
|
|
||||||
|
When `destroy()` is called (or when a new mount replaces an old one), everything is purged:
|
||||||
|
|
||||||
|
- All `watch` effects
|
||||||
|
- All event listeners added via SigPro (`onClick`, `onInput`, etc.)
|
||||||
|
- All child components created with `when`, `each`, or nested `mount` calls
|
||||||
|
- Any custom cleanups registered with `onUnmount`
|
||||||
|
|
||||||
|
> **You only need manual cleanup** for external resources not managed by SigPro (e.g., `setInterval`, third‑party libraries, WebSocket connections). Use `onUnmount` for that.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Complete Example
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { $, mount, div, h1, button } from 'sigpro';
|
||||||
|
|
||||||
|
const App = () => {
|
||||||
|
const count = $(0);
|
||||||
|
return div({ class: "demo" }, [
|
||||||
|
h1(() => `Count: ${count()}`),
|
||||||
|
button({ onClick: () => count(count() + 1) }, "Increment")
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const runtime = mount(App, '#app');
|
||||||
|
|
||||||
|
// Destroy after 10 seconds
|
||||||
|
setTimeout(() => runtime.destroy(), 10000);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary Cheat Sheet
|
||||||
|
|
||||||
|
| Goal | Code |
|
||||||
|
| :--- | :--- |
|
||||||
|
| Mount to a CSS selector | `mount(App, '#root')` |
|
||||||
|
| Mount to a DOM element | `mount(App, document.getElementById('root'))` |
|
||||||
|
| Mount a static node | `mount(div("Hello"), '#target')` |
|
||||||
|
| Manual destruction | `const app = mount(App, '#app'); app.destroy();` |
|
||||||
|
| Auto‑replace on same target | Just call `mount` again – SigPro handles cleanup. |
|
||||||
|
|
||||||
|
> **Note:** The target must exist in the DOM at the time of mounting.
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
327
docs/api/quick.md
Normal file
327
docs/api/quick.md
Normal file
@@ -0,0 +1,327 @@
|
|||||||
|
# ⚡ SigPro – Complete API Reference
|
||||||
|
|
||||||
|
SigPro is a **Real‑DOM first** reactive micro‑framework. No virtual DOM, no diffing overhead – it updates the DOM directly with surgical precision. Built‑in automatic cleanup prevents memory leaks, and the API is designed to be both tiny and powerful.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { $, $$, watch, h, when, each, fx, router, req, mount, batch } from 'sigpro'
|
||||||
|
// Or, if you prefer the global style in an ESM environment:
|
||||||
|
// import { sigpro } from 'sigpro'; sigpro(); // then $, h, div... become window globals
|
||||||
|
// In a classic IIFE script (<script src="sigpro.js">), everything is available globally automatically.
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔁 Core Reactivity
|
||||||
|
|
||||||
|
### `$(value, localStorageKey?)` – Signal & Computed
|
||||||
|
|
||||||
|
Creates a reactive signal. If a function is passed, it becomes a **computed** signal that caches its result until dependencies change.
|
||||||
|
|
||||||
|
| Usage | Description |
|
||||||
|
|-------|-------------|
|
||||||
|
| `const count = $(0)` | Basic signal, returns a getter/setter: `count()` reads, `count(5)` writes. |
|
||||||
|
| `const double = $( () => count() * 2 )` | Computed signal – updates automatically when `count` changes. |
|
||||||
|
| `const stored = $('hello', 'myKey')` | Persisted signal – reads/writes to `localStorage`. |
|
||||||
|
|
||||||
|
**Example**
|
||||||
|
```javascript
|
||||||
|
const count = $(0)
|
||||||
|
const double = $( () => count() * 2 )
|
||||||
|
|
||||||
|
watch(() => {
|
||||||
|
console.log(`count = ${count()}, double = ${double()}`)
|
||||||
|
}) // logs on every change
|
||||||
|
|
||||||
|
count(5) // triggers log: count=5, double=10
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `$$(object)` – Deep Reactive Proxy
|
||||||
|
|
||||||
|
Makes a plain object (and all nested objects) deeply reactive. Any property access is tracked, any mutation triggers updates.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const state = $$({ user: { name: 'Alice', age: 30 }, items: [1,2,3] })
|
||||||
|
|
||||||
|
watch(() => {
|
||||||
|
console.log(state.user.name) // tracks `user.name`
|
||||||
|
})
|
||||||
|
|
||||||
|
state.user.name = 'Bob' // triggers the effect
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Note**: `$$` caches proxies per original object, so calling `$$` multiple times on the same object returns the same proxy.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `watch(source, callback?)` – Reactive Effect
|
||||||
|
|
||||||
|
Two modes:
|
||||||
|
|
||||||
|
1. **Auto‑track mode** – pass a function: `watch(() => { /* reads signals */ })`
|
||||||
|
Automatically re‑runs whenever any signal read inside changes.
|
||||||
|
|
||||||
|
2. **Explicit mode** – pass an array of signals and a callback:
|
||||||
|
`watch([count, double], () => { ... })`
|
||||||
|
Runs the callback when any of the listed signals change. The callback receives the new values.
|
||||||
|
|
||||||
|
Both modes return a `stop` function that disposes the effect.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// auto mode
|
||||||
|
const stop = watch(() => console.log(count()))
|
||||||
|
|
||||||
|
// explicit mode
|
||||||
|
watch([count, double], ([newCount, newDouble]) => {
|
||||||
|
console.log(newCount, newDouble)
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Important**: Effects are depth‑aware – they run in topological order, parents before children.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧱 Components & DOM (Hyperscript)
|
||||||
|
|
||||||
|
### `h(tag, props, children)` – Create DOM Nodes
|
||||||
|
|
||||||
|
The universal builder. `props` can be omitted. Children can be strings, numbers, nodes, arrays, or **dynamic functions**.
|
||||||
|
|
||||||
|
| Feature | Example |
|
||||||
|
|---------|---------|
|
||||||
|
| Standard attributes | `h('div', { class: 'box', id: 'main' })` |
|
||||||
|
| Events | `onClick: (e) => ...` (automatically cleaned up) |
|
||||||
|
| Reactive attributes | `class: () => count() > 0 ? 'positive' : 'negative'` |
|
||||||
|
| Two‑way binding | `value: mySignal` (works on `input`, `textarea`, `select`) |
|
||||||
|
| Refs | `ref: (el) => ...` or `ref: { current: null }` |
|
||||||
|
| SVG support | tag names like `svg`, `circle`, `path` – sets correct namespace |
|
||||||
|
| Dangerous URL sanitising | `href` / `src` with `javascript:` or `data:` are blocked → `'#'` |
|
||||||
|
|
||||||
|
**Dynamic children** – pass a function as a child, it will be re‑executed and the DOM patched automatically:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
h('div', {}, [
|
||||||
|
() => count() > 0 ? h('span', {}, 'positive') : h('span', {}, 'zero or negative')
|
||||||
|
])
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tag shortcuts
|
||||||
|
|
||||||
|
When using the **ESM module with named imports**, you can import the tag helpers individually:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { div, h1, button } from 'sigpro'
|
||||||
|
|
||||||
|
div({ class: 'container' }, [
|
||||||
|
h1({}, 'Title'),
|
||||||
|
button({ onClick: () => alert('hi') }, 'Click me')
|
||||||
|
])
|
||||||
|
```
|
||||||
|
|
||||||
|
If you prefer the **global style** (all tags and core functions on `window`), either:
|
||||||
|
- Use the classic IIFE script: `<script src="sigpro.js"></script>`
|
||||||
|
- Or in ESM, call `sigpro()` after importing: `import { sigpro } from 'sigpro'; sigpro();`
|
||||||
|
|
||||||
|
After that, you can write `div()`, `span()`, etc. directly, without any import.
|
||||||
|
|
||||||
|
Available tags: `a`, `abbr`, `article`, `aside`, `audio`, `b`, `blockquote`, `br`, `button`, `canvas`, `caption`, `cite`, `code`, `col`, `colgroup`, `datalist`, `dd`, `del`, `details`, `dfn`, `dialog`, `div`, `dl`, `dt`, `em`, `embed`, `fieldset`, `figcaption`, `figure`, `footer`, `form`, `h1`…`h6`, `header`, `hr`, `i`, `iframe`, `img`, `input`, `ins`, `kbd`, `label`, `legend`, `li`, `main`, `mark`, `meter`, `nav`, `object`, `ol`, `optgroup`, `option`, `output`, `p`, `picture`, `pre`, `progress`, `section`, `select`, `slot`, `small`, `source`, `span`, `strong`, `sub`, `summary`, `sup`, `svg`, `table`, `tbody`, `td`, `template`, `textarea`, `tfoot`, `th`, `thead`, `time`, `tr`, `u`, `ul`, `video`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧩 Flow Control Components
|
||||||
|
|
||||||
|
### `when(condition, thenComponent, elseComponent?)`
|
||||||
|
|
||||||
|
Reactive conditional rendering. `condition` can be a boolean, a signal, or any function that returns a boolean. Both branches can be `Node`, `() => Node`, or `null`. Automatically disposes the unmounted branch.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
when(
|
||||||
|
() => user.loggedIn(),
|
||||||
|
() => div({}, 'Welcome back!'),
|
||||||
|
() => button({ onClick: () => login() }, 'Login')
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `each(source, itemRenderer, keyFn)`
|
||||||
|
|
||||||
|
Optimised keyed list rendering. `source` can be an array or a signal/function returning an array. `itemRenderer(item, index)` returns a Node (or a function that returns Nodes). `keyFn(item, index)` returns a unique identifier – **required** for efficient DOM reuse.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const items = $([{ id: 1, text: 'a' }, { id: 2, text: 'b' }])
|
||||||
|
|
||||||
|
each(items,
|
||||||
|
(item) => Li({}, item.text),
|
||||||
|
(item) => item.id
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
When the array changes, elements are added, removed, or reordered with minimal DOM operations.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 💥 Batch
|
||||||
|
|
||||||
|
### `batch(fn)`
|
||||||
|
|
||||||
|
Batch multiple reactive updates into a single flush, improving performance.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
batch(() => {
|
||||||
|
count(1)
|
||||||
|
name('John')
|
||||||
|
// effects run only once after the batch ends
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✨ Animations – `fx(options, child)`
|
||||||
|
|
||||||
|
Applies smooth enter animations (CSS transitions / keyframes). Returns the modified element.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
fx({ name: 'fade', duration: 300 },
|
||||||
|
Div({}, 'Hello')
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Options**
|
||||||
|
- `name` – uses predefined keyframes `${name}-in` (you must define them in your CSS)
|
||||||
|
- `duration` – in ms (default 200)
|
||||||
|
- `scale` – adds `scale(0.95)` → `none`
|
||||||
|
- `slide` – adds `translateY(-10px)` → `none`
|
||||||
|
- `rotate` – adds `rotate(-2deg)` → `none`
|
||||||
|
- `blur` – adds `blur(4px)` → `none`
|
||||||
|
|
||||||
|
If `name` is given, it sets `animation: ${name}-in ${duration}ms`. Otherwise it applies a smooth transition from the initial transform/filter to the final state.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧭 Router – `router(routes)`
|
||||||
|
|
||||||
|
Hash‑based SPA router. Returns a DOM node that renders the current route.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const routes = [
|
||||||
|
{ path: '/', component: () => div({}, 'Home') },
|
||||||
|
{ path: '/user/:id', component: (params) => div({}, `User ${params.id}`) },
|
||||||
|
{ path: '*', component: () => div({}, '404') }
|
||||||
|
]
|
||||||
|
|
||||||
|
const App = () => div({}, [
|
||||||
|
a({ href: '#/' }, 'Home'),
|
||||||
|
a({ href: '#/user/42' }, 'User 42'),
|
||||||
|
router(routes)
|
||||||
|
])
|
||||||
|
```
|
||||||
|
|
||||||
|
**API**
|
||||||
|
|
||||||
|
| Method | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `router.params()` | Returns a reactive signal of current route params (e.g., `{ id: '42' }`). |
|
||||||
|
| `router.to(path)` | Navigate to a new hash (e.g., `router.to('/user/5')`). Prepend `#` automatically. |
|
||||||
|
| `router.back()` | Go back in history. |
|
||||||
|
| `router.path()` | Returns current hash path without `#` (e.g., `/user/42`). |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🌐 HTTP Requests – `req(config)`
|
||||||
|
|
||||||
|
Creates a reactive request controller with built‑in loading/error/data signals and abort support.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const fetchUser = req({ url: '/api/user/1', method: 'GET' })
|
||||||
|
|
||||||
|
// start the request
|
||||||
|
fetchUser.run().catch(console.error)
|
||||||
|
|
||||||
|
// reactively display state
|
||||||
|
watch(() => {
|
||||||
|
if (fetchUser.loading()) console.log('loading...')
|
||||||
|
if (fetchUser.error()) console.error(fetchUser.error())
|
||||||
|
if (fetchUser.data()) console.log(fetchUser.data())
|
||||||
|
})
|
||||||
|
|
||||||
|
// abort if needed
|
||||||
|
fetchUser.abort()
|
||||||
|
```
|
||||||
|
|
||||||
|
**Options**
|
||||||
|
- `url` (required)
|
||||||
|
- `method` (default `'GET'`)
|
||||||
|
- `headers` (object, default `{}`)
|
||||||
|
|
||||||
|
**Return value**
|
||||||
|
- `run(body?)` – initiates the request, returns a promise.
|
||||||
|
- `abort()` – aborts the current request (AbortController).
|
||||||
|
- `loading` – signal (boolean)
|
||||||
|
- `error` – signal (`null` or error message)
|
||||||
|
- `data` – signal (`null` or parsed JSON)
|
||||||
|
|
||||||
|
> **Note**: Automatically sets `Content-Type: application/json` unless `body` is a `FormData`. Timeout after 10 seconds aborts the request.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Mounting – `mount(component, target)`
|
||||||
|
|
||||||
|
Clears the target element and mounts the application. Returns the runtime instance (which has a `.destroy()` method).
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
mount(() => App(), '#app')
|
||||||
|
// or
|
||||||
|
mount(App, document.body)
|
||||||
|
```
|
||||||
|
|
||||||
|
If you mount again on the same target, the previous instance is automatically destroyed.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧹 Global Cleanup & Memory
|
||||||
|
|
||||||
|
SigPro tracks every effect, DOM event listener, and nested component. When a component is unmounted:
|
||||||
|
- All its effects are disposed.
|
||||||
|
- All DOM event listeners are removed.
|
||||||
|
- All `onUnmount` callbacks run.
|
||||||
|
- Child components are recursively destroyed.
|
||||||
|
|
||||||
|
You never need to manually clean up – just write reactive code.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📦 Full Example – Counter with Persistence
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { $, watch, h, mount } from 'sigpro'
|
||||||
|
|
||||||
|
const count = $(0, 'counter') // persists in localStorage
|
||||||
|
|
||||||
|
const App = () =>
|
||||||
|
div({ class: 'counter' }, [
|
||||||
|
h1({}, () => `Count: ${count()}`),
|
||||||
|
button({ onClick: () => count(count() + 1) }, '+'),
|
||||||
|
button({ onClick: () => count(count() - 1) }, '-'),
|
||||||
|
button({ onClick: () => count(0) }, 'Reset')
|
||||||
|
])
|
||||||
|
|
||||||
|
mount(App, '#app')
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 Customising the API (Renaming)
|
||||||
|
|
||||||
|
You can rename everything in one line:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { $ as signal, watch as effect, h as element, mount as render } from 'sigpro'
|
||||||
|
```
|
||||||
|
|
||||||
|
Or assign globally (after calling `sigpro()` or using the classic script):
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
window.myReactive = $
|
||||||
|
```
|
||||||
184
docs/api/req.md
Normal file
184
docs/api/req.md
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
# HTTP Requests: `req( )`
|
||||||
|
|
||||||
|
The `req` function creates a **reactive HTTP request controller**. It returns signals for `loading`, `error`, and `data`, plus a `run` method to execute the request and an `abort` method to cancel it. All signals update automatically as the request progresses.
|
||||||
|
|
||||||
|
## Function Signature
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
req(config: {
|
||||||
|
url: string;
|
||||||
|
method?: string; // default: 'GET'
|
||||||
|
headers?: Record<string, string>;
|
||||||
|
}): {
|
||||||
|
run: (body?: any) => Promise<any>;
|
||||||
|
abort: () => void;
|
||||||
|
loading: Signal<boolean>;
|
||||||
|
error: Signal<string | null>;
|
||||||
|
data: Signal<any | null>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| Parameter | Type | Required | Description |
|
||||||
|
| :--- | :--- | :--- | :--- |
|
||||||
|
| **`url`** | `string` | Yes | The endpoint to call. |
|
||||||
|
| **`method`** | `string` | No | HTTP method (`'GET'`, `'POST'`, etc.). Default `'GET'`. |
|
||||||
|
| **`headers`** | `object` | No | Custom headers (will be merged with defaults). |
|
||||||
|
|
||||||
|
**Returns:** A controller object with reactive signals and methods.
|
||||||
|
|
||||||
|
> **Availability:** `req` is exported from the SigPro module. In **ESM** you must import it (`import { req } from 'sigpro'`) or inject all globals via `sigpro()`. In the **IIFE** classic script, it is automatically available on `window`. The examples below assume the function is already in scope.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage Patterns
|
||||||
|
|
||||||
|
### 1. Basic GET Request
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const users = req({ url: '/api/users' });
|
||||||
|
|
||||||
|
// Start the request
|
||||||
|
users.run().catch(console.error);
|
||||||
|
|
||||||
|
// React to the response
|
||||||
|
watch(() => {
|
||||||
|
if (users.loading()) console.log('Loading...');
|
||||||
|
if (users.error()) console.error(users.error());
|
||||||
|
if (users.data()) console.log('Data:', users.data());
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. POST Request with Body
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const createUser = req({ url: '/api/users', method: 'POST' });
|
||||||
|
|
||||||
|
const handleSubmit = async (formData) => {
|
||||||
|
try {
|
||||||
|
await createUser.run(formData);
|
||||||
|
alert('User created!');
|
||||||
|
} catch (err) {
|
||||||
|
// Error already in createUser.error()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Aborting a Request
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const search = req({ url: '/api/search' });
|
||||||
|
|
||||||
|
// Abort if the user types again quickly
|
||||||
|
let timeout;
|
||||||
|
input({ onInput: (e) => {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
search.abort(); // cancel previous in-flight request
|
||||||
|
timeout = setTimeout(() => search.run({ q: e.target.value }), 300);
|
||||||
|
}});
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Reactive UI with Signals
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const profile = req({ url: '/api/me' });
|
||||||
|
|
||||||
|
const App = () =>
|
||||||
|
div([
|
||||||
|
when(() => profile.loading(),
|
||||||
|
() => div("Loading...")
|
||||||
|
),
|
||||||
|
when(() => profile.error(),
|
||||||
|
() => div("Error: " + profile.error())
|
||||||
|
),
|
||||||
|
when(() => profile.data(),
|
||||||
|
() => div([
|
||||||
|
h2(profile.data().name),
|
||||||
|
p(profile.data().email)
|
||||||
|
])
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
|
||||||
|
profile.run();
|
||||||
|
mount(App, '#app');
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Request Lifecycle
|
||||||
|
|
||||||
|
When you call `run(body?)`:
|
||||||
|
|
||||||
|
1. Any previous request is **aborted** automatically.
|
||||||
|
2. `loading` becomes `true`.
|
||||||
|
3. `error` is cleared.
|
||||||
|
4. A 10‑second timeout is set (auto‑abort).
|
||||||
|
5. The request is sent using `fetch`.
|
||||||
|
6. On success: `data` is set with the parsed JSON, `loading` becomes `false`.
|
||||||
|
7. On error: `error` is set with the message, `data` is cleared, `loading` becomes `false`.
|
||||||
|
|
||||||
|
> **Important:** The response body is parsed as JSON. If the response is not OK or the JSON parsing fails, `error` is set and the promise rejects.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Automatic Headers
|
||||||
|
|
||||||
|
- If `body` is a plain object or array, the request automatically includes `Content-Type: application/json` (unless you override it in `headers`).
|
||||||
|
- If `body` is a `FormData` instance, the `Content-Type` is not set (browser will set it automatically with the correct boundary).
|
||||||
|
- Other headers can be added via the `headers` option.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const upload = req({
|
||||||
|
url: '/upload',
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'X-Custom': 'value' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('file', fileInput.files[0]);
|
||||||
|
upload.run(formData);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
- Network errors, timeouts, and HTTP error statuses (4xx, 5xx) all set `error` and cause the promise to reject.
|
||||||
|
- The `error` signal contains a human‑readable message.
|
||||||
|
- Abort errors (calling `abort()` or timeout) are **silent** – they do not set `error` or reject the promise?
|
||||||
|
Actually, according to the source: if `e.name === 'AbortError'`, it does **not** call `error(e.message)`, but the promise still rejects with the AbortError. You can handle it with `.catch()` if needed.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Complete Example
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const api = req({ url: 'https://jsonplaceholder.typicode.com/posts/1' });
|
||||||
|
|
||||||
|
const App = () =>
|
||||||
|
div({ class: "demo" }, [
|
||||||
|
when(() => api.loading(), () => p("⏳ Loading...")),
|
||||||
|
when(() => api.error(), () => p("❌ " + api.error())),
|
||||||
|
when(() => api.data(), () => div([
|
||||||
|
h2(api.data().title),
|
||||||
|
p(api.data().body)
|
||||||
|
])),
|
||||||
|
button({
|
||||||
|
onClick: () => api.run(),
|
||||||
|
disabled: () => api.loading()
|
||||||
|
}, "Fetch")
|
||||||
|
]);
|
||||||
|
|
||||||
|
mount(App, '#app');
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
| Member | Type | Description |
|
||||||
|
| :--- | :--- | :--- |
|
||||||
|
| `run(body?)` | `(any) => Promise` | Starts the request. Returns a promise. |
|
||||||
|
| `abort()` | `() => void` | Cancels the current request. |
|
||||||
|
| `loading` | `Signal<boolean>` | `true` while request is in flight. |
|
||||||
|
| `error` | `Signal<string\|null>` | Contains an error message, or `null`. |
|
||||||
|
| `data` | `Signal<any\|null>` | Contains the parsed response (JSON), or `null`. |
|
||||||
189
docs/api/router.md
Normal file
189
docs/api/router.md
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
# Routing: `router( )` & Utilities
|
||||||
|
|
||||||
|
SigPro includes a built‑in, lightweight **hash router** to create single‑page applications (SPA). It manages the URL hash, matches components to routes with dynamic segments (`:id`), and automatically cleans up each page when you navigate away.
|
||||||
|
|
||||||
|
## Function Signature
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
router(routes: Route[]): HTMLElement
|
||||||
|
```
|
||||||
|
|
||||||
|
### Route Object
|
||||||
|
|
||||||
|
| Property | Type | Description |
|
||||||
|
| :--- | :--- | :--- |
|
||||||
|
| **`path`** | `string` | The URL fragment pattern (e.g. `"/"`, `"/user/:id"`, or `"*"` for catch‑all). |
|
||||||
|
| **`component`** | `Function` | A function that returns a Node, a string, or a reactive view. Receives `params` object as argument. |
|
||||||
|
|
||||||
|
**Returns:** A `div` element (with class `"router-hook"`) that acts as the router outlet. The router automatically destroys the previous view and mounts the matched component when the hash changes.
|
||||||
|
|
||||||
|
> **Availability:** `router` and its helper methods (`router.to`, `router.back`, `router.path`, `router.params`) are exported from the SigPro module. In **ESM** you must import them (`import { router } from 'sigpro'`) or inject all globals via `sigpro()`. In the **IIFE** classic script, they are automatically available on `window`. The examples below assume the functions are already in scope.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage Patterns
|
||||||
|
|
||||||
|
### 1. Defining Routes
|
||||||
|
|
||||||
|
Place the `router` element where you want the page content to appear. Inside the routes array, define your routes.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const Home = () => h1("Home Page");
|
||||||
|
const UserProfile = (params) => h1(`User ID: ${params.id}`);
|
||||||
|
const NotFound = () => h1("404 – Page not found");
|
||||||
|
|
||||||
|
const App = () =>
|
||||||
|
div({ class: "app-layout" }, [
|
||||||
|
nav([
|
||||||
|
a({ href: "#/" }, "Home"),
|
||||||
|
a({ href: "#/user/42" }, "User 42")
|
||||||
|
]),
|
||||||
|
router([
|
||||||
|
{ path: "/", component: Home },
|
||||||
|
{ path: "/user/:id", component: UserProfile },
|
||||||
|
{ path: "*", component: NotFound }
|
||||||
|
])
|
||||||
|
]);
|
||||||
|
|
||||||
|
mount(App, "#app");
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Dynamic Segments (`:id`)
|
||||||
|
|
||||||
|
When a route contains a colon‑prefixed segment (like `:id`), the router extracts the corresponding value from the current hash and passes it as a property inside the `params` object to the component function.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// If the hash is #/user/42
|
||||||
|
const UserProfile = (params) => {
|
||||||
|
console.log(params.id); // "42"
|
||||||
|
return div(`User ${params.id}`);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Accessing Route Parameters Anywhere
|
||||||
|
|
||||||
|
The router maintains a reactive signal `router.params` that always holds the parameters of the currently matched route. You can read it anywhere in your app.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
watch(() => {
|
||||||
|
const params = router.params();
|
||||||
|
console.log("Current route params:", params);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Navigation Utilities
|
||||||
|
|
||||||
|
SigPro provides several helper functions to control navigation and read the router state.
|
||||||
|
|
||||||
|
### `router.to(path)`
|
||||||
|
|
||||||
|
Navigates to the given path. It automatically formats the hash (e.g. `"/dashboard"` becomes `"#/dashboard"`). You can pass either a full hash string or a path without the `#`.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
button({ onclick: () => router.to("/dashboard") }, "Go to Dashboard")
|
||||||
|
```
|
||||||
|
|
||||||
|
### `router.back()`
|
||||||
|
|
||||||
|
Goes back one step in the browser’s history, just like calling `history.back()`.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
button({ onclick: () => router.back() }, "← Back")
|
||||||
|
```
|
||||||
|
|
||||||
|
### `router.path()`
|
||||||
|
|
||||||
|
Returns the current route path **without the leading `#`**. This is a plain string, not a signal.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
console.log(router.path()); // e.g. "/user/42"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Automatic Cleanup
|
||||||
|
|
||||||
|
Every time you navigate to a new route, the router calls `.destroy()` on the previous view. This recursively disposes of:
|
||||||
|
|
||||||
|
- All `watch` effects created inside that page
|
||||||
|
- All event listeners attached via SigPro’s event binding
|
||||||
|
- Any nested `when`, `each`, or `router` instances
|
||||||
|
|
||||||
|
**No manual cleanup is required** – memory leaks are prevented automatically.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Reactive Route Parameters
|
||||||
|
|
||||||
|
`router.params` is a **reactive signal** (created with `$({})`). You can watch it to react to parameter changes without re‑mounting the whole router outlet.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
watch(() => router.params(), (params) => {
|
||||||
|
console.log("Params changed:", params);
|
||||||
|
// e.g. fetch new data when the :id changes
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Styling the Router Outlet
|
||||||
|
|
||||||
|
The router returns a `div` with the class `"router-hook"`. You can style it just like any other element:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.router-hook {
|
||||||
|
display: block;
|
||||||
|
min-height: 60vh;
|
||||||
|
animation: fadeIn 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeIn {
|
||||||
|
from { opacity: 0; transform: translateY(8px); }
|
||||||
|
to { opacity: 1; transform: translateY(0); }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want the router outlet to have no layout impact, you can set `display: contents` on it.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Complete Example
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { $, router, mount } from "sigpro";
|
||||||
|
|
||||||
|
const Home = () => div("Welcome home");
|
||||||
|
const About = () => div("About us");
|
||||||
|
const User = (params) => div(`User profile: ${params.id}`);
|
||||||
|
|
||||||
|
const App = () =>
|
||||||
|
div([
|
||||||
|
nav([
|
||||||
|
a({ href: "#/" }, "Home"),
|
||||||
|
a({ href: "#/about" }, "About"),
|
||||||
|
a({ href: "#/user/5" }, "User 5")
|
||||||
|
]),
|
||||||
|
router([
|
||||||
|
{ path: "/", component: Home },
|
||||||
|
{ path: "/about", component: About },
|
||||||
|
{ path: "/user/:id", component: User },
|
||||||
|
{ path: "*", component: () => div("404 – Not found") }
|
||||||
|
])
|
||||||
|
]);
|
||||||
|
|
||||||
|
mount(App, "#app");
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
| Function | Description |
|
||||||
|
| :--- | :--- |
|
||||||
|
| `router(routes)` | Creates a router outlet. |
|
||||||
|
| `router.to(path)` | Navigates to a new hash route. |
|
||||||
|
| `router.back()` | Goes back in history. |
|
||||||
|
| `router.path()` | Returns the current path without `#`. |
|
||||||
|
| `router.params()` | Reactive signal of the current route parameters. |
|
||||||
File diff suppressed because one or more lines are too long
390
docs/api/signal.md
Normal file
390
docs/api/signal.md
Normal file
@@ -0,0 +1,390 @@
|
|||||||
|
# The Signal Function: `$( )`
|
||||||
|
|
||||||
|
The `$( )` function is the core constructor of SigPro. It defines how data is stored, computed, and persisted.
|
||||||
|
|
||||||
|
## Function Signature
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
$(initialValue: any, key?: string): Signal
|
||||||
|
$(computation: Function): ComputedSignal
|
||||||
|
```
|
||||||
|
|
||||||
|
| Parameter | Type | Required | Description |
|
||||||
|
| :--- | :--- | :--- | :--- |
|
||||||
|
| **`initialValue`** | `any` | Yes* | The starting value of your signal. |
|
||||||
|
| **`computation`** | `Function` | Yes* | A function that returns a value based on other signals. |
|
||||||
|
| **`key`** | `string` | No | A unique name to persist the signal in `localStorage`. |
|
||||||
|
|
||||||
|
*\*Either an initial value or a computation function must be provided.*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage Patterns
|
||||||
|
|
||||||
|
### 1. Simple State
|
||||||
|
**`$(value)`**
|
||||||
|
Creates a writable signal. It returns a function that acts as both **getter** and **setter**.
|
||||||
|
|
||||||
|
<div id="demo-signal-simple"></div>
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
const count = $(0);
|
||||||
|
const App = () => div({ class: "example" }, [
|
||||||
|
p(() => `Count: ${count()}`),
|
||||||
|
button({ onClick: () => count(count() + 1) }, "+1")
|
||||||
|
]);
|
||||||
|
setTimeout(() => mount(App, '#demo-signal-simple'), 50);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Persistent State
|
||||||
|
**`$(value, key)`**
|
||||||
|
Creates a writable signal that syncs with the browser's storage.
|
||||||
|
|
||||||
|
<div id="demo-signal-persist"></div>
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
const theme = $("light", "theme-persist-demo");
|
||||||
|
const App = () => div([
|
||||||
|
p(() => `Current theme: ${theme()}`),
|
||||||
|
button({ onClick: () => theme(theme() === "light" ? "dark" : "light") }, "Toggle theme")
|
||||||
|
]);
|
||||||
|
setTimeout(() => mount(App, '#demo-signal-persist'), 50);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
*Note: On page load, SigPro will prioritize the value found in `localStorage` over the `initialValue`.*
|
||||||
|
|
||||||
|
### 3. Computed State (Derived)
|
||||||
|
**`$(function)`**
|
||||||
|
Creates a read-only signal that updates automatically when any signal used inside it changes.
|
||||||
|
|
||||||
|
<div id="demo-signal-computed"></div>
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
const price = $(100);
|
||||||
|
const tax = $(0.21);
|
||||||
|
const total = $(() => price() * (1 + tax()));
|
||||||
|
|
||||||
|
const App = () => div([
|
||||||
|
p(() => `Price: €${price()}`),
|
||||||
|
p(() => `Tax rate: ${tax() * 100}%`),
|
||||||
|
p(() => `Total: €${total().toFixed(2)}`),
|
||||||
|
button({ onClick: () => price(price() + 10) }, "+€10"),
|
||||||
|
button({ onClick: () => price(price() - 10) }, "-€10")
|
||||||
|
]);
|
||||||
|
setTimeout(() => mount(App, '#demo-signal-computed'), 50);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Updating with Logic
|
||||||
|
When calling the setter, you can pass an **updater function** to access the current value safely.
|
||||||
|
|
||||||
|
<div id="demo-signal-updater"></div>
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
const list = $(["A", "B"]);
|
||||||
|
const App = () => div([
|
||||||
|
ul(() => list().map(item => li(item))),
|
||||||
|
button({ onClick: () => list(prev => [...prev, "C"]) }, "Add C")
|
||||||
|
]);
|
||||||
|
setTimeout(() => mount(App, '#demo-signal-updater'), 50);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# The Reactive Object: `$$( )`
|
||||||
|
|
||||||
|
The `$$( )` function creates a reactive proxy for complex nested objects. Unlike `$()`, which tracks a single value, `$$()` tracks **every property access** automatically.
|
||||||
|
|
||||||
|
## Function Signature
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
$$<T extends object>(obj: T): T
|
||||||
|
```
|
||||||
|
|
||||||
|
| Parameter | Type | Required | Description |
|
||||||
|
| :--- | :--- | :--- | :--- |
|
||||||
|
| **`obj`** | `object` | Yes | The object to make reactive. Properties are tracked recursively. |
|
||||||
|
|
||||||
|
**Returns:** A reactive proxy that behaves like the original object but triggers updates when any property changes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage Patterns
|
||||||
|
|
||||||
|
### 1. Simple Object
|
||||||
|
|
||||||
|
<div id="demo-dollar-simple"></div>
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
const state = $$({ count: 0, name: "Juan" });
|
||||||
|
watch(() => console.log(`Count is now ${state.count}`));
|
||||||
|
|
||||||
|
const App = () => div([
|
||||||
|
p(() => `Count: ${state.count}, Name: ${state.name}`),
|
||||||
|
button({ onClick: () => state.count++ }, "Increment count"),
|
||||||
|
button({ onClick: () => state.name = state.name === "Juan" ? "Ana" : "Juan" }, "Toggle name")
|
||||||
|
]);
|
||||||
|
setTimeout(() => mount(App, '#demo-dollar-simple'), 50);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Deep Reactivity
|
||||||
|
|
||||||
|
<div id="demo-dollar-deep"></div>
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
const user = $$({
|
||||||
|
profile: {
|
||||||
|
name: "Juan",
|
||||||
|
address: { city: "Madrid", zip: "28001" }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(() => user.profile.address.city, () => console.log("City changed"));
|
||||||
|
|
||||||
|
const App = () => div([
|
||||||
|
p(() => `City: ${user.profile.address.city}`),
|
||||||
|
button({ onClick: () => user.profile.address.city = "Barcelona" }, "Change to Barcelona")
|
||||||
|
]);
|
||||||
|
setTimeout(() => mount(App, '#demo-dollar-deep'), 50);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Arrays
|
||||||
|
|
||||||
|
<div id="demo-dollar-array"></div>
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
const todos = $$([
|
||||||
|
{ id: 1, text: "Learn SigPro", done: false },
|
||||||
|
{ id: 2, text: "Build an app", done: false }
|
||||||
|
]);
|
||||||
|
|
||||||
|
watch(() => todos.length, () => console.log(`You have ${todos.length} todos`));
|
||||||
|
|
||||||
|
const App = () => div([
|
||||||
|
ul(() => todos.map(todo => li(todo.text + (todo.done ? " ✓" : "")))),
|
||||||
|
button({ onClick: () => todos.push({ id: Date.now(), text: "New todo", done: false }) }, "Add todo"),
|
||||||
|
button({ onClick: () => todos[0].done = !todos[0].done }, "Toggle first todo")
|
||||||
|
]);
|
||||||
|
setTimeout(() => mount(App, '#demo-dollar-array'), 50);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Mixed with Signals
|
||||||
|
|
||||||
|
<div id="demo-dollar-mixed"></div>
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
const form = $$({
|
||||||
|
fields: { email: "", password: "" },
|
||||||
|
isValid: $(false)
|
||||||
|
});
|
||||||
|
|
||||||
|
const canSubmit = $(() =>
|
||||||
|
form.fields.email.includes("@") &&
|
||||||
|
form.fields.password.length > 6
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(canSubmit, valid => form.isValid(valid));
|
||||||
|
|
||||||
|
const App = () => div([
|
||||||
|
input({ type: "email", placeholder: "Email", value: () => form.fields.email, onInput: e => form.fields.email = e.target.value }),
|
||||||
|
input({ type: "password", placeholder: "Password", value: () => form.fields.password, onInput: e => form.fields.password = e.target.value }),
|
||||||
|
p(() => `Form valid: ${form.isValid() ? "Yes" : "No"}`)
|
||||||
|
]);
|
||||||
|
setTimeout(() => mount(App, '#demo-dollar-mixed'), 50);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Key Differences: `$()` vs `$$()`
|
||||||
|
|
||||||
|
| Feature | `$()` Signal | `$$()` Reactive |
|
||||||
|
| :--- | :--- | :--- |
|
||||||
|
| **Primitives** | ✅ Works directly | ❌ Needs wrapper object |
|
||||||
|
| **Objects** | Manual tracking | ✅ Automatic deep tracking |
|
||||||
|
| **Nested properties** | ❌ Not reactive | ✅ Fully reactive |
|
||||||
|
| **Arrays** | Requires reassignment | ✅ Methods (push, pop, etc.) work |
|
||||||
|
| **Syntax** | `count()` / `count(5)` | `state.count = 5` |
|
||||||
|
| **LocalStorage** | ✅ Built-in | ❌ (use `$()` for persistence) |
|
||||||
|
| **Performance** | Lighter | Slightly heavier (Proxy) |
|
||||||
|
| **Destructuring** | ✅ Safe | ❌ Breaks reactivity |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## When to Use Each
|
||||||
|
|
||||||
|
### Use `$()` when:
|
||||||
|
|
||||||
|
<div id="demo-use-dollar"></div>
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
const count = $(0);
|
||||||
|
const firstName = $("John");
|
||||||
|
const lastName = $("Doe");
|
||||||
|
const fullName = $(() => `${firstName()} ${lastName()}`);
|
||||||
|
|
||||||
|
const App = () => div([
|
||||||
|
p(() => `Count: ${count()}`),
|
||||||
|
button({ onClick: () => count(count() + 1) }, "Count up"),
|
||||||
|
p(() => `Full name: ${fullName()}`),
|
||||||
|
input({ value: firstName, placeholder: "First name" }),
|
||||||
|
input({ value: lastName, placeholder: "Last name" })
|
||||||
|
]);
|
||||||
|
setTimeout(() => mount(App, '#demo-use-dollar'), 50);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Use `$$()` when:
|
||||||
|
|
||||||
|
<div id="demo-use-dollar-dollar"></div>
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
const form = $$({ email: "", password: "" });
|
||||||
|
const settings = $$({ theme: "dark", notifications: true });
|
||||||
|
|
||||||
|
const App = () => div([
|
||||||
|
input({ placeholder: "Email", onInput: e => form.email = e.target.value }),
|
||||||
|
input({ placeholder: "Password", type: "password", onInput: e => form.password = e.target.value }),
|
||||||
|
p(() => `Email: ${form.email}, Password: ${form.password}`),
|
||||||
|
button({ onClick: () => settings.theme = settings.theme === "dark" ? "light" : "dark" }, "Toggle theme"),
|
||||||
|
p(() => `Current theme: ${settings.theme}`)
|
||||||
|
]);
|
||||||
|
setTimeout(() => mount(App, '#demo-use-dollar-dollar'), 50);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Important Notes
|
||||||
|
|
||||||
|
### ✅ DO:
|
||||||
|
```javascript
|
||||||
|
// Access properties directly
|
||||||
|
state.count = 10;
|
||||||
|
state.user.name = "Ana";
|
||||||
|
todos.push(newItem);
|
||||||
|
|
||||||
|
// Track in effects
|
||||||
|
watch(() => state.count, () => {});
|
||||||
|
watch(() => state.user.name, () => {});
|
||||||
|
```
|
||||||
|
|
||||||
|
### ❌ DON'T:
|
||||||
|
```javascript
|
||||||
|
// Destructuring breaks reactivity
|
||||||
|
const { count, user } = state; // ❌ count and user are not reactive
|
||||||
|
|
||||||
|
// Reassigning the whole object
|
||||||
|
state = { count: 10 }; // ❌ Loses reactivity
|
||||||
|
|
||||||
|
// Using primitive directly
|
||||||
|
const count = $$(0); // ❌ Doesn't work (use $() instead)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Automatic Cleanup
|
||||||
|
|
||||||
|
Like all SigPro reactive primitives, `$$()` integrates with the cleanup system:
|
||||||
|
|
||||||
|
- Effects tracking reactive properties are automatically disposed
|
||||||
|
- No manual cleanup needed
|
||||||
|
- Works with `watch`, `when`, and `each`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Technical Comparison
|
||||||
|
|
||||||
|
| Aspect | `$()` | `$$()` |
|
||||||
|
| :--- | :--- | :--- |
|
||||||
|
| **Implementation** | Closure with Set | Proxy with WeakMap |
|
||||||
|
| **Tracking** | Explicit (function call) | Implicit (property access) |
|
||||||
|
| **Memory** | Minimal | Slightly more (WeakMap cache) |
|
||||||
|
| **Use Case** | Simple state | Complex state |
|
||||||
|
| **Learning Curve** | Low | Low (feels like plain JS) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Complete Example
|
||||||
|
|
||||||
|
<div id="demo-complete"></div>
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
const app = {
|
||||||
|
theme: $("dark", "theme_complete"),
|
||||||
|
sidebarOpen: $(true),
|
||||||
|
user: $$({ name: "", email: "", preferences: { notifications: true, language: "es" } }),
|
||||||
|
isLoggedIn: $(() => !!app.user.name),
|
||||||
|
login(name, email) {
|
||||||
|
app.user.name = name;
|
||||||
|
app.user.email = email;
|
||||||
|
},
|
||||||
|
logout() {
|
||||||
|
app.user.name = "";
|
||||||
|
app.user.email = "";
|
||||||
|
app.user.preferences.notifications = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const LoginForm = () => div([
|
||||||
|
input({ placeholder: "Name", onInput: e => app.user.name = e.target.value }),
|
||||||
|
input({ placeholder: "Email", onInput: e => app.user.email = e.target.value }),
|
||||||
|
button({ onClick: () => app.login(app.user.name, app.user.email) }, "Login")
|
||||||
|
]);
|
||||||
|
|
||||||
|
const UserProfile = () => div([
|
||||||
|
h2(() => `Welcome ${app.user.name}`),
|
||||||
|
p(() => `Email: ${app.user.email}`),
|
||||||
|
p(() => `Notifications: ${app.user.preferences.notifications ? "ON" : "OFF"}`),
|
||||||
|
button({ onClick: () => app.user.preferences.notifications = !app.user.preferences.notifications }, "Toggle Notifications"),
|
||||||
|
button({ onClick: app.logout }, "Logout")
|
||||||
|
]);
|
||||||
|
|
||||||
|
const App = () => div({ class: "complete-example" }, [
|
||||||
|
when(() => app.isLoggedIn(), () => UserProfile(), () => LoginForm())
|
||||||
|
]);
|
||||||
|
|
||||||
|
setTimeout(() => mount(App, '#demo-complete'), 50);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Migration from `$()` to `$$()`
|
||||||
|
|
||||||
|
If you have code using nested signals:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Before - Manual nesting
|
||||||
|
const user = $({
|
||||||
|
name: $(""),
|
||||||
|
email: $("")
|
||||||
|
});
|
||||||
|
user().name("Juan"); // Need to call inner signal
|
||||||
|
|
||||||
|
// After - Automatic nesting
|
||||||
|
const user = $$({
|
||||||
|
name: "",
|
||||||
|
email: ""
|
||||||
|
});
|
||||||
|
user.name = "Juan"; // Direct assignment
|
||||||
|
```
|
||||||
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
244
docs/api/tags.md
Normal file
244
docs/api/tags.md
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
# Global Tag Helpers
|
||||||
|
|
||||||
|
In **SigPro**, you don't need to manually type `h('div', ...)` for every element. To keep your code declarative and readable, the engine provides **helper functions** for all standard HTML5 tags.
|
||||||
|
|
||||||
|
## 1. How it Works
|
||||||
|
|
||||||
|
SigPro iterates through a list of standard HTML tags and creates a wrapper function for each one.
|
||||||
|
- **Under the hood:** `h('button', { onclick: ... }, 'Click')`
|
||||||
|
- **SigPro Style:** `button({ onclick: ... }, 'Click')`
|
||||||
|
|
||||||
|
> **Note:** All tag helpers are **lowercase** (e.g., `div`, `span`, `button`). This keeps the syntax close to raw HTML.
|
||||||
|
|
||||||
|
These helpers can be used in two ways, depending on your environment:
|
||||||
|
|
||||||
|
### Mode A: Classic (IIFE) – Auto‑global
|
||||||
|
When you load the **IIFE bundle** (`sigpro.js`) with a traditional `<script>` tag (no `type="module"`), all tag helpers are automatically injected into the `window` object.
|
||||||
|
```html
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/sigpro@1.2.19/dist/sigpro.js"></script>
|
||||||
|
<script>
|
||||||
|
// div, span, button, ... are already global
|
||||||
|
const App = () => div({ class: "card" }, "Hello");
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Mode B: ESM (Modern) – Explicit or Imported
|
||||||
|
When you import the **ES module** (via `import` or CDN with `type="module"`), nothing is added to `window` by default. You have two options:
|
||||||
|
|
||||||
|
1. **Manual global injection** – import `sigpro` and call it:
|
||||||
|
```javascript
|
||||||
|
import { sigpro } from 'sigpro';
|
||||||
|
sigpro(); // now div, span, button, etc. become global
|
||||||
|
```
|
||||||
|
2. **Named imports** (recommended) – import the helpers you need directly:
|
||||||
|
```javascript
|
||||||
|
import { div, span, button } from 'sigpro';
|
||||||
|
// use them directly
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. The Complete List of Tag Helpers
|
||||||
|
|
||||||
|
All helpers are **lowercase** and follow HTML5 tag names. You can use them globally (after injection) or import them individually.
|
||||||
|
|
||||||
|
| Category | Available functions |
|
||||||
|
| :--- | :--- |
|
||||||
|
| **Structure** | `div`, `span`, `p`, `section`, `nav`, `main`, `header`, `footer`, `article`, `aside` |
|
||||||
|
| **Typography** | `h1`, `h2`, `h3`, `h4`, `h5`, `h6`, `ul`, `ol`, `li`, `dl`, `dt`, `dd`, `strong`, `em`, `code`, `pre`, `small`, `b`, `u`, `mark` |
|
||||||
|
| **Interactive** | `button`, `a`, `label`, `br`, `hr`, `details`, `summary`, `dialog` |
|
||||||
|
| **Forms** | `form`, `input`, `select`, `option`, `textarea`, `fieldset`, `legend` |
|
||||||
|
| **Tables** | `table`, `thead`, `tbody`, `tr`, `th`, `td`, `tfoot`, `caption` |
|
||||||
|
| **Media** | `img`, `canvas`, `video`, `audio`, `svg`, `iframe`, `picture`, `source` |
|
||||||
|
|
||||||
|
Full list includes all standard tags: `a`, `abbr`, `article`, `aside`, `audio`, `b`, `blockquote`, `br`, `button`, `canvas`, `caption`, `cite`, `code`, `col`, `colgroup`, `datalist`, `dd`, `del`, `details`, `dfn`, `dialog`, `div`, `dl`, `dt`, `em`, `embed`, `fieldset`, `figcaption`, `figure`, `footer`, `form`, `h1`…`h6`, `header`, `hr`, `i`, `iframe`, `img`, `input`, `ins`, `kbd`, `label`, `legend`, `li`, `main`, `mark`, `meter`, `nav`, `object`, `ol`, `optgroup`, `option`, `output`, `p`, `picture`, `pre`, `progress`, `section`, `select`, `slot`, `small`, `source`, `span`, `strong`, `sub`, `summary`, `sup`, `svg`, `table`, `tbody`, `td`, `template`, `textarea`, `tfoot`, `th`, `thead`, `time`, `tr`, `u`, `ul`, `video`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Usage Patterns
|
||||||
|
|
||||||
|
### A. Attributes + Children
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
div({ class: 'container', id: 'main' }, [
|
||||||
|
h1("Welcome to SigPro"),
|
||||||
|
p("The zero‑VDOM framework.")
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|
### B. Children Only
|
||||||
|
|
||||||
|
If you don't need attributes, pass the content directly as the first argument.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
section([
|
||||||
|
h2("Clean Syntax"),
|
||||||
|
button("I have no props!")
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Reactive Power
|
||||||
|
|
||||||
|
These helpers are natively wired into SigPro's reactivity system.
|
||||||
|
|
||||||
|
### Reactive Attributes (One‑Way)
|
||||||
|
|
||||||
|
Pass a **function** that returns the value. SigPro creates an internal effect to keep the DOM in sync.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const theme = $("light");
|
||||||
|
|
||||||
|
div({
|
||||||
|
class: () => `app-box ${theme()}`
|
||||||
|
}, "Themeable Box");
|
||||||
|
```
|
||||||
|
|
||||||
|
### Two‑Way Binding (Automatic)
|
||||||
|
|
||||||
|
Assign a **signal** directly to `value` or `checked` on form inputs – SigPro automatically bridges the signal and the input element bidirectionally.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const search = $("");
|
||||||
|
|
||||||
|
input({
|
||||||
|
type: "text",
|
||||||
|
placeholder: "Search...",
|
||||||
|
value: search
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Pro Tip:** To make an input **read‑only** but still reactive, wrap the signal in a function: `value: () => search()` – this prevents backward synchronization.
|
||||||
|
|
||||||
|
### Dynamic Children
|
||||||
|
|
||||||
|
You can pass a **function as a child** – it will be re‑executed whenever any signal inside changes, and the DOM will be patched surgically.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const count = $(0);
|
||||||
|
|
||||||
|
div([
|
||||||
|
p(() => `Count is ${count()}`),
|
||||||
|
button({ onClick: () => count(count() + 1) }, "Increment")
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Custom Components with `h()` or Tag Helpers
|
||||||
|
|
||||||
|
While the tag helpers cover all standard HTML tags, you can create reusable components using them directly.
|
||||||
|
|
||||||
|
### Basic Component
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const UserCard = (props, children) =>
|
||||||
|
div({ class: 'card p-4', 'data-id': props.id }, children);
|
||||||
|
|
||||||
|
UserCard({ id: 123 }, [h3("John Doe"), p("john@example.com")]);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Reactive Component
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const Counter = () => {
|
||||||
|
const count = $(0);
|
||||||
|
return div({ class: 'flex gap-2' }, [
|
||||||
|
button({ onClick: () => count(count() - 1) }, '-'),
|
||||||
|
span(() => count()),
|
||||||
|
button({ onClick: () => count(count() + 1) }, '+')
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Manual Cleanup for External Resources
|
||||||
|
|
||||||
|
Only needed for intervals, sockets, third‑party libraries:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const Timer = () => {
|
||||||
|
const time = $(new Date().toLocaleTimeString());
|
||||||
|
const el = span(() => time());
|
||||||
|
|
||||||
|
const interval = setInterval(() => time(new Date().toLocaleTimeString()), 1000);
|
||||||
|
onUnmount(() => clearInterval(interval));
|
||||||
|
|
||||||
|
return el;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Comparison with `h()`
|
||||||
|
|
||||||
|
| Use case | Recommendation |
|
||||||
|
| :--- | :--- |
|
||||||
|
| Standard tags (`div`, `span`, `button`) | Use tag helpers: `div()`, `span()`, `button()` |
|
||||||
|
| Dynamic tag names (unknown at write time) | Use `h(tagName, props, children)` |
|
||||||
|
| Components returning a single node | Any function that returns a node (using helpers or `h`) |
|
||||||
|
|
||||||
|
> **Auto‑cleanup:** All tag helpers and `h` automatically dispose effects, event listeners, and nested components when removed from the DOM.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Complete Example
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// In a modern ESM environment (recommended)
|
||||||
|
import { div, h1, input, p, button, mount, $ } from 'sigpro';
|
||||||
|
|
||||||
|
const nameSignal = $('');
|
||||||
|
|
||||||
|
const App = () =>
|
||||||
|
div({ class: "app" }, [
|
||||||
|
h1("Welcome"),
|
||||||
|
input({
|
||||||
|
placeholder: "Your name",
|
||||||
|
value: nameSignal
|
||||||
|
}),
|
||||||
|
p(() => `Hello, ${nameSignal() || "stranger"}!`),
|
||||||
|
button({ onClick: () => alert("Clicked") }, "Click me")
|
||||||
|
]);
|
||||||
|
|
||||||
|
mount(App, '#app');
|
||||||
|
```
|
||||||
|
|
||||||
|
Or using the classic script (auto‑global):
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/sigpro@1.2.19/dist/sigpro.js"></script>
|
||||||
|
<script>
|
||||||
|
const nameSignal = $('');
|
||||||
|
const App = () => div({ class: "app" }, [
|
||||||
|
h1("Welcome"),
|
||||||
|
input({ placeholder: "Your name", value: nameSignal }),
|
||||||
|
p(() => `Hello, ${nameSignal() || "stranger"}!`),
|
||||||
|
button({ onClick: () => alert("Clicked") }, "Click me")
|
||||||
|
]);
|
||||||
|
mount(App, '#app');
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Important Notes
|
||||||
|
|
||||||
|
- **Naming:** All tag helpers are **lowercase** – no PascalCase helpers (`Div`, `Button`).
|
||||||
|
- **Global availability:**
|
||||||
|
- **IIFE script** → automatically on `window`.
|
||||||
|
- **ESM module** → not global by default; use `import { div } from 'sigpro'` or call `sigpro()` to inject all globals.
|
||||||
|
- **Custom components:** Use **PascalCase** for your own component functions (e.g., `UserCard`) to visually distinguish them from built‑in tags.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Summary
|
||||||
|
|
||||||
|
| Feature | Description |
|
||||||
|
| :--- | :--- |
|
||||||
|
| **Tag helpers** | Lowercase functions for every HTML element (e.g., `div()`, `button()`). |
|
||||||
|
| **Availability** | Auto‑global in IIFE; in ESM use named imports or `sigpro()`. |
|
||||||
|
| **Reactive attributes** | Pass a function to any attribute to keep it synced. |
|
||||||
|
| **Two‑way binding** | Assign a signal directly to `value` or `checked` on form elements. |
|
||||||
|
| **Dynamic children** | Pass a function as a child for live updating content. |
|
||||||
|
| **Auto‑cleanup** | All effects, events, and children are disposed when the element is removed. |
|
||||||
124
docs/api/watch.md
Normal file
124
docs/api/watch.md
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
# Reactivity Control: `watch( )`
|
||||||
|
|
||||||
|
The `watch` function is the reactive engine of SigPro. It allows you to execute code automatically when signals change. `watch` is **polymorphic**: it can track dependencies automatically or follow an explicit list.
|
||||||
|
|
||||||
|
## Function Signature
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Automatic Mode (Magic Tracking)
|
||||||
|
watch(callback: Function): StopFunction
|
||||||
|
|
||||||
|
// Explicit Mode (Isolated Dependencies)
|
||||||
|
watch(deps: Signal[], callback: (values: any[]) => void): StopFunction
|
||||||
|
```
|
||||||
|
|
||||||
|
| Parameter | Type | Required | Description |
|
||||||
|
| :--- | :--- | :--- | :--- |
|
||||||
|
| **`callback`** (auto mode) | `Function` | Yes | The code to run. Any signal accessed inside becomes a dependency. |
|
||||||
|
| **`deps`** (explicit mode) | `Signal[]` | Yes | An array of signals to watch explicitly. |
|
||||||
|
| **`callback`** (explicit mode) | `Function` | Yes | Runs when any of the `deps` change. Receives an array of their current values. |
|
||||||
|
|
||||||
|
**Returns:** A `StopFunction` that, when called, destroys the watcher and releases memory.
|
||||||
|
|
||||||
|
> **Availability:** `watch` is exported from the SigPro module. In **ESM** you must import it (`import { watch } from 'sigpro'`) or inject all globals via `sigpro()`. In the **IIFE** classic script, it is automatically available on `window`. The examples below assume the function is already in scope.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage Patterns
|
||||||
|
|
||||||
|
### 1. Automatic Mode (Default)
|
||||||
|
Any signal you **touch** inside the callback becomes a dependency. SigPro tracks them behind the scenes.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const count = $(0);
|
||||||
|
|
||||||
|
watch(() => {
|
||||||
|
// Re‑runs every time 'count' changes
|
||||||
|
console.log(`Count is: ${count()}`);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Explicit Mode (Isolated)
|
||||||
|
This mode **isolates** execution. The callback only triggers when the signals in the array change. Any other signal accessed *inside* the callback will **not** trigger a re‑run. This is ideal for routers or performance‑critical components.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const path = $("/home");
|
||||||
|
const user = $("Admin");
|
||||||
|
|
||||||
|
watch([path], ([newPath]) => {
|
||||||
|
// Only triggers when 'path' changes.
|
||||||
|
// Changes to 'user' will NOT trigger this.
|
||||||
|
console.log(`Navigating to ${newPath} as ${user()}`);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
In explicit mode, the callback receives an array of current values corresponding to the `deps` order.
|
||||||
|
|
||||||
|
### 3. Stopping a Watcher
|
||||||
|
Call the returned function to kill the watcher manually.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const stop = watch(() => console.log(count()));
|
||||||
|
// Later...
|
||||||
|
stop(); // Disconnects the watcher completely.
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Automatic Cleanup Inside Effects
|
||||||
|
If your watcher creates timers, event listeners, or nested effects, SigPro tracks them as children and cleans them up automatically before re‑running or when stopped.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
watch(() => {
|
||||||
|
const timer = setInterval(() => console.log("tick"), 1000);
|
||||||
|
// No need to manually clear – SigPro will dispose it when the watcher re‑runs or stops.
|
||||||
|
// (But you can also return a cleanup function if needed)
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Batching & Microtask Queue
|
||||||
|
|
||||||
|
SigPro batches reactive updates. If you modify several signals in the same synchronous block, the watcher will fire **only once**, after the task completes.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const a = $(0);
|
||||||
|
const b = $(0);
|
||||||
|
|
||||||
|
watch(() => console.log(a(), b()));
|
||||||
|
|
||||||
|
// Triggers only ONE log: "1 2"
|
||||||
|
a(1);
|
||||||
|
b(2);
|
||||||
|
```
|
||||||
|
|
||||||
|
This is achieved via `queueMicrotask`, ensuring optimal performance.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Key Points
|
||||||
|
|
||||||
|
- **Function name:** `watch` (lowercase) – exported from SigPro and also available globally (depending on environment).
|
||||||
|
- **Auto mode:** `watch(fn)` – automatically tracks any signals read inside `fn`.
|
||||||
|
- **Explicit mode:** `watch([sig1, sig2], (values) => {...})` – only re‑runs when listed signals change; callback receives an array of their new values.
|
||||||
|
- **Stop function:** returned by both modes; call it to dispose the effect and its children.
|
||||||
|
- **Batching:** multiple signal writes in one event loop tick trigger a single execution (microtask).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Complete Example
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const count = $(0);
|
||||||
|
const step = $(1);
|
||||||
|
|
||||||
|
watch(() => {
|
||||||
|
console.log(`Count changed to ${count()}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
watch([count, step], ([newCount, newStep]) => {
|
||||||
|
console.log(`Count=${newCount}, step=${newStep} (explicit)`);
|
||||||
|
});
|
||||||
|
|
||||||
|
count(5); // logs: auto + explicit
|
||||||
|
step(2); // logs: explicit only (auto does not track step)
|
||||||
|
```
|
||||||
132
docs/api/when.md
Normal file
132
docs/api/when.md
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
# Reactive Branching: `when( )`
|
||||||
|
|
||||||
|
The `when` function is the reactive control flow operator in SigPro. It conditionally renders one of two branches (or nothing) based on a reactive condition. The inactive branch is completely removed from the DOM and its effects are destroyed, saving memory and CPU.
|
||||||
|
|
||||||
|
## Function Signature
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
when(
|
||||||
|
condition: boolean | Signal<boolean> | (() => boolean),
|
||||||
|
thenBranch: Node | (() => Node),
|
||||||
|
elseBranch?: Node | (() => Node) | null
|
||||||
|
): HTMLElement
|
||||||
|
```
|
||||||
|
|
||||||
|
| Parameter | Type | Required | Description |
|
||||||
|
| :--- | :--- | :--- | :--- |
|
||||||
|
| **`condition`** | `boolean` / `Signal` / `() => boolean` | Yes | A value or reactive expression that determines which branch to show. |
|
||||||
|
| **`thenBranch`** | `Node` / `() => Node` | Yes | Content rendered when the condition is **truthy**. |
|
||||||
|
| **`elseBranch`** | `Node` / `() => Node` | No | Content rendered when the condition is **falsy**. Defaults to nothing. |
|
||||||
|
|
||||||
|
**Returns:** A `div` with `style="display:contents"` that acts as an anchor for the dynamic content. This element is part of the DOM and will be replaced/updated automatically.
|
||||||
|
|
||||||
|
> **Availability:** `when` is exported from the SigPro module. In **ESM** you must import it (`import { when } from 'sigpro'`) or inject all globals via `sigpro()`. In the **IIFE** classic script, it is automatically available on `window`. The examples below assume the function is already in scope.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage Patterns
|
||||||
|
|
||||||
|
### 1. Simple Toggle
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const isVisible = $(false);
|
||||||
|
|
||||||
|
div([
|
||||||
|
button({ onclick: () => isVisible(!isVisible()) }, "Toggle"),
|
||||||
|
when(isVisible,
|
||||||
|
p("Now you see me!"),
|
||||||
|
p("Now you don't...")
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. With Functions (Lazy Initialization)
|
||||||
|
|
||||||
|
To avoid creating heavy components until they are actually needed, pass a function that returns the branch.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
when(() => user.isLoggedIn(),
|
||||||
|
() => DashboardComponent(), // Only created when logged in
|
||||||
|
() => LoginForm() // Only created when guest
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Complex Conditions
|
||||||
|
|
||||||
|
`condition` can be any expression that returns a boolean – it can read signals, computed values, or plain booleans.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
when(() => count() > 10 && status() === 'ready',
|
||||||
|
span("Threshold reached!")
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Without an `else` branch
|
||||||
|
|
||||||
|
If no `elseBranch` is provided, nothing is rendered when the condition is falsy.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
when(loading,
|
||||||
|
div({ class: "spinner" }, "Loading...")
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Automatic Cleanup
|
||||||
|
|
||||||
|
`when` automatically manages the lifecycle of each branch:
|
||||||
|
|
||||||
|
- When the condition changes, the current branch is destroyed.
|
||||||
|
- All effects (`watch`), event listeners, and child `when`/`each` inside the destroyed branch are recursively disposed.
|
||||||
|
- The new branch is created and mounted.
|
||||||
|
- Memory leaks are prevented without any manual intervention.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
- **Use functions for expensive branches** – `() => Component()` ensures the component is only created when the branch becomes active.
|
||||||
|
- **Avoid inline complex logic** – keep conditions readable; extract to computed signals if needed.
|
||||||
|
- **No manual cleanup required** – SigPro handles everything.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Technical Comparison
|
||||||
|
|
||||||
|
| Feature | CSS `display: none` | `when` |
|
||||||
|
| :--- | :--- | :--- |
|
||||||
|
| **DOM presence** | Always present | Only active branch exists |
|
||||||
|
| **Event listeners** | Still attached | Removed |
|
||||||
|
| **Effects (`watch`)** | Still running | Destroyed |
|
||||||
|
| **Memory usage** | Higher | Optimised (only one branch alive) |
|
||||||
|
| **Cleanup** | Manual | Automatic |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Complete Example
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const loggedIn = $(false);
|
||||||
|
const username = $("Guest");
|
||||||
|
|
||||||
|
const Profile = () => div([
|
||||||
|
h2(`Welcome, ${username()}`),
|
||||||
|
button({ onclick: () => loggedIn(false) }, "Logout")
|
||||||
|
]);
|
||||||
|
|
||||||
|
const LoginForm = () => div([
|
||||||
|
input({ placeholder: "Name", onInput: e => username(e.target.value) }),
|
||||||
|
button({ onclick: () => loggedIn(true) }, "Login")
|
||||||
|
]);
|
||||||
|
|
||||||
|
const App = () =>
|
||||||
|
div([
|
||||||
|
when(loggedIn,
|
||||||
|
() => Profile(),
|
||||||
|
() => LoginForm()
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
|
||||||
|
mount(App, '#app');
|
||||||
|
```
|
||||||
@@ -1,571 +0,0 @@
|
|||||||
import{_ as i,o as a,c as n,ae as h}from"./chunks/framework.C8AWLET_.js";const F=JSON.parse('{"title":"Components API 🧩","description":"","frontmatter":{},"headers":[],"relativePath":"api/components.md","filePath":"api/components.md"}'),t={name:"api/components.md"};function l(k,s,p,e,E,r){return a(),n("div",null,[...s[0]||(s[0]=[h(`<h1 id="components-api-🧩" tabindex="-1">Components API 🧩 <a class="header-anchor" href="#components-api-🧩" aria-label="Permalink to "Components API 🧩""></a></h1><p>Components in SigPro are native Web Components built on the Custom Elements standard. They provide a way to create reusable, encapsulated pieces of UI with reactive properties and automatic cleanup.</p><h2 id="component-tagname-setupfunction-observedattributes-useshadowdom" tabindex="-1"><code>$.component(tagName, setupFunction, observedAttributes, useShadowDOM)</code> <a class="header-anchor" href="#component-tagname-setupfunction-observedattributes-useshadowdom" aria-label="Permalink to "\`$.component(tagName, setupFunction, observedAttributes, useShadowDOM)\`""></a></h2><p>Creates a custom element with reactive properties and automatic dependency tracking.</p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'my-button'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">props</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">slot</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">emit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> class="btn"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @click=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> emit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'click'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">slot</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}, [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'variant'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Observe the 'variant' attribute</span></span></code></pre></div><h2 id="📋-api-reference" tabindex="-1">📋 API Reference <a class="header-anchor" href="#📋-api-reference" aria-label="Permalink to "📋 API Reference""></a></h2><h3 id="parameters" tabindex="-1">Parameters <a class="header-anchor" href="#parameters" aria-label="Permalink to "Parameters""></a></h3><table tabindex="0"><thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td><code>tagName</code></td><td><code>string</code></td><td>required</td><td>Custom element tag name (must include a hyphen, e.g., <code>my-button</code>)</td></tr><tr><td><code>setupFunction</code></td><td><code>Function</code></td><td>required</td><td>Function that returns the component's template</td></tr><tr><td><code>observedAttributes</code></td><td><code>string[]</code></td><td><code>[]</code></td><td>Attributes to observe for changes (become reactive props)</td></tr><tr><td><code>useShadowDOM</code></td><td><code>boolean</code></td><td><code>false</code></td><td><code>true</code> = Shadow DOM (encapsulated), <code>false</code> = Light DOM (inherits styles)</td></tr></tbody></table><h3 id="setup-function-parameters" tabindex="-1">Setup Function Parameters <a class="header-anchor" href="#setup-function-parameters" aria-label="Permalink to "Setup Function Parameters""></a></h3><p>The setup function receives two arguments:</p><ol><li><strong><code>props</code></strong> - Object containing reactive signals for each observed attribute</li><li><strong><code>context</code></strong> - Object with helper methods and properties</li></ol><h4 id="context-object-properties" tabindex="-1">Context Object Properties <a class="header-anchor" href="#context-object-properties" aria-label="Permalink to "Context Object Properties""></a></h4><table tabindex="0"><thead><tr><th>Property</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>slot(name)</code></td><td><code>Function</code></td><td>Returns array of child nodes for the specified slot</td></tr><tr><td><code>emit(name, detail)</code></td><td><code>Function</code></td><td>Dispatches a custom event</td></tr><tr><td><code>select(selector)</code></td><td><code>Function</code></td><td>Query selector within component's root</td></tr><tr><td><code>selectAll(selector)</code></td><td><code>Function</code></td><td>Query selector all within component's root</td></tr><tr><td><code>host</code></td><td><code>HTMLElement</code></td><td>Reference to the custom element instance</td></tr><tr><td><code>root</code></td><td><code>Node</code></td><td>Component's root (shadow root or element itself)</td></tr><tr><td><code>onUnmount(callback)</code></td><td><code>Function</code></td><td>Register cleanup function</td></tr></tbody></table><h2 id="🏠-light-dom-vs-shadow-dom" tabindex="-1">🏠 Light DOM vs Shadow DOM <a class="header-anchor" href="#🏠-light-dom-vs-shadow-dom" aria-label="Permalink to "🏠 Light DOM vs Shadow DOM""></a></h2><h3 id="light-dom-useshadowdom-false-default" tabindex="-1">Light DOM (<code>useShadowDOM = false</code>) - Default <a class="header-anchor" href="#light-dom-useshadowdom-false-default" aria-label="Permalink to "Light DOM (\`useShadowDOM = false\`) - Default""></a></h3><p>The component <strong>inherits global styles</strong> from the application. Perfect for components that should integrate with your site's design system.</p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Button that uses global Tailwind CSS</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'tw-button'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">props</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">slot</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">emit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> variant</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> props.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">variant</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'primary'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> variants</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> primary: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'bg-blue-500 hover:bg-blue-600 text-white'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> secondary: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'bg-gray-500 hover:bg-gray-600 text-white'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> outline: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'border border-blue-500 text-blue-500 hover:bg-blue-50'</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> class="px-4 py-2 rounded font-semibold transition-colors \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">variants</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">[</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">variant</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">]</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @click=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> emit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'click'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">slot</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}, [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'variant'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]);</span></span></code></pre></div><h3 id="shadow-dom-useshadowdom-true-encapsulated" tabindex="-1">Shadow DOM (<code>useShadowDOM = true</code>) - Encapsulated <a class="header-anchor" href="#shadow-dom-useshadowdom-true-encapsulated" aria-label="Permalink to "Shadow DOM (\`useShadowDOM = true\`) - Encapsulated""></a></h3><p>The component <strong>encapsulates its styles</strong> completely. External styles don't affect it, and its styles don't leak out.</p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Calendar with encapsulated styles</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'ui-calendar'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">props</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <style></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /* These styles won't affect the rest of the page */</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> .calendar {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> font-family: system-ui, sans-serif;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> background: white;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> border-radius: 12px;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> padding: 20px;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> box-shadow: 0 4px 12px rgba(0,0,0,0.1);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> .day {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> aspect-ratio: 1;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> display: flex;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> align-items: center;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> justify-content: center;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> cursor: pointer;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> border-radius: 50%;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> .day.selected {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> background: #2196f3;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> color: white;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </style></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="calendar"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">renderCalendar</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">props</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">date</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">())</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}, [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'date'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">], </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// true = use Shadow DOM</span></span></code></pre></div><h2 id="🎯-basic-examples" tabindex="-1">🎯 Basic Examples <a class="header-anchor" href="#🎯-basic-examples" aria-label="Permalink to "🎯 Basic Examples""></a></h2><h3 id="simple-counter-component" tabindex="-1">Simple Counter Component <a class="header-anchor" href="#simple-counter-component" aria-label="Permalink to "Simple Counter Component""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// counter.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'my-counter'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">props</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> count</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="counter"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>Count: \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">count</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button @click=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> count</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">c</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> c</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> +</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}>+</button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button @click=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> count</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">c</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> c</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> -</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}>-</button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button @click=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> count</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}>Reset</button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><p><strong>Usage:</strong></p><div class="language-html vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"><</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">my-counter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">my-counter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span></code></pre></div><h3 id="component-with-props" tabindex="-1">Component with Props <a class="header-anchor" href="#component-with-props" aria-label="Permalink to "Component with Props""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// greeting.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'my-greeting'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">props</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> props.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'World'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> greeting</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`Hello, \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}!\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="greeting"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h1>\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">greeting</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</h1></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>This is a greeting component.</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}, [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'name'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Observe the 'name' attribute</span></span></code></pre></div><p><strong>Usage:</strong></p><div class="language-html vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"><</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">my-greeting</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"John"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">my-greeting</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"><</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">my-greeting</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"Jane"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">my-greeting</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span></code></pre></div><h3 id="component-with-events" tabindex="-1">Component with Events <a class="header-anchor" href="#component-with-events" aria-label="Permalink to "Component with Events""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// toggle.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'my-toggle'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">props</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">emit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> isOn</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(props.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">initial</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'on'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> toggle</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> isOn</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">isOn</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> emit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'toggle'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { isOn: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">isOn</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> emit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">isOn</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'on'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'off'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> class="toggle \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> isOn</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'active'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''}"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @click=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">toggle</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> isOn</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'ON'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'OFF'}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}, [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'initial'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]);</span></span></code></pre></div><p><strong>Usage:</strong></p><div class="language-html vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"><</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">my-toggle</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> initial</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"off"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> @toggle</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\${(e)</span><span style="--shiki-light:#B31D28;--shiki-light-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">> console.log('Toggled:', e.detail)}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> @on=\${() => console.log('Turned on')}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> @off=\${() => console.log('Turned off')}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">my-toggle</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span></code></pre></div><h2 id="🎨-advanced-examples" tabindex="-1">🎨 Advanced Examples <a class="header-anchor" href="#🎨-advanced-examples" aria-label="Permalink to "🎨 Advanced Examples""></a></h2><h3 id="form-input-component" tabindex="-1">Form Input Component <a class="header-anchor" href="#form-input-component" aria-label="Permalink to "Form Input Component""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// form-input.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'form-input'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">props</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">emit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> value</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(props.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> error</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> touched</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Validation effect</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (props.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">pattern</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">&&</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> touched</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> regex</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> RegExp</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(props.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">pattern</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> isValid</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> regex.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">test</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> error</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(isValid </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> null</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> props.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">errorMessage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'Invalid input'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> emit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'validate'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { isValid, value: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> handleInput</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">e</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(e.target.value);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> emit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'update'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, e.target.value);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> handleBlur</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> touched</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="form-group"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">props</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">label</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <label class="form-label"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">props</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">label</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">props</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">required</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`<span class="required">*</span>\`</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </label></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <input</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> type="\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">props</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">type</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'text'}"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> class="form-control \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> error</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'is-invalid'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''}"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> :value=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">value</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @input=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">handleInput</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @blur=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">handleBlur</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> placeholder="\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">props</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">placeholder</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''}"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ?disabled=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">props</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">disabled</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ?required=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">props</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">required</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> error</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="error-message">\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">error</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">props</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">helpText</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <small class="help-text">\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">props</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">helpText</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</small></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}, [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'label'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'type'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'value'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'placeholder'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'disabled'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'required'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'pattern'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'errorMessage'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'helpText'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]);</span></span></code></pre></div><p><strong>Usage:</strong></p><div class="language-html vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"><</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">form-input</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> label</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"Email"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"email"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> required</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pattern</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> errorMessage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"Please enter a valid email"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> @update</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\${(e)</span><span style="--shiki-light:#B31D28;--shiki-light-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">> formData.email = e.detail}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> @validate=\${(e) => setEmailValid(e.detail.isValid)}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"></</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">form-input</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span></code></pre></div><h3 id="modal-dialog-component" tabindex="-1">Modal/Dialog Component <a class="header-anchor" href="#modal-dialog-component" aria-label="Permalink to "Modal/Dialog Component""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// modal.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'my-modal'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">props</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">slot</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">emit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">onUnmount</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> isOpen</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Handle escape key</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> handleKeydown</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">e</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (e.key </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'Escape'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> &&</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> isOpen</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> close</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">isOpen</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> document.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">addEventListener</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'keydown'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, handleKeydown);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> document.body.style.overflow </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'hidden'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> document.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">removeEventListener</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'keydown'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, handleKeydown);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> document.body.style.overflow </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Cleanup on unmount</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> onUnmount</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> document.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">removeEventListener</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'keydown'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, handleKeydown);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> document.body.style.overflow </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> open</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> isOpen</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> emit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'open'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> close</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> isOpen</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> emit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'close'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Expose methods to parent</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> props.open </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> open;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> props.close </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> close;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <!-- Trigger button --></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> class="modal-trigger"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @click=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">open</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">slot</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'trigger'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'Open Modal'}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <!-- Modal overlay --></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> isOpen</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="modal-overlay" @click=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">close</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="modal-content" @click.stop></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="modal-header"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h3>\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">props</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">title</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'Modal'}</h3></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button class="close-btn" @click=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">close</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}>&times;</button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="modal-body"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">slot</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'body'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="modal-footer"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">slot</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'footer'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button @click=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">close</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}>Close</button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}, [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'title'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">], </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span></code></pre></div><p><strong>Usage:</strong></p><div class="language-html vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"><</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">my-modal</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> title</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"Confirm Delete"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">button</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> slot</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"trigger"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">>Delete Item</</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">button</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> slot</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"body"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">p</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">>Are you sure you want to delete this item?</</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">p</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">p</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"warning"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">>This action cannot be undone.</</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">p</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> slot</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"footer"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">button</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"cancel"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> @click</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\${close}</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">>Cancel</</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">button</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">button</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"delete"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> @click</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\${handleDelete}</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">>Delete</</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">button</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"></</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">my-modal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span></code></pre></div><h3 id="data-table-component" tabindex="-1">Data Table Component <a class="header-anchor" href="#data-table-component" aria-label="Permalink to "Data Table Component""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// data-table.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'data-table'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">props</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">emit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(props.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">data</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> []);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> columns</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(props.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">columns</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> []);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> sortColumn</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> sortDirection</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'asc'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> filterText</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Computed: filtered and sorted data</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> processedData</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> result </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">data</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()];</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Filter</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">filterText</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> search</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> filterText</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">toLowerCase</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> result </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> result.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">filter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">row</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> Object.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">values</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(row).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">some</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">val</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> String</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(val).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">toLowerCase</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">includes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(search)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> )</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> );</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Sort</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">sortColumn</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> col</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> sortColumn</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> direction</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> sortDirection</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'asc'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> -</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> result.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">sort</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">a</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">b</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (a[col] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"><</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> b[col]) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> -</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">direction;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (a[col] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> b[col]) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> direction;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> result;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> handleSort</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">col</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">sortColumn</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> col) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> sortDirection</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">sortDirection</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'asc'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'desc'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'asc'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> sortColumn</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(col);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> sortDirection</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'asc'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> emit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'sort'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { column: col, direction: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">sortDirection</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="data-table"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <!-- Search input --></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="table-toolbar"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <input</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> type="search"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> :value=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">filterText</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> placeholder="Search..."</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> class="search-input"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <span class="record-count"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">processedData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">} of \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">data</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">} records\`}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <!-- Table --></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <table></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <thead></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <tr></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">columns</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">col</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <th </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @click=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> handleSort</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">col</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">field</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> class:sortable=\${</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> class:sorted=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> sortColumn</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> col</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">field</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">col</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">label</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> sortColumn</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> col</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">field</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <span class="sort-icon"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">sortDirection</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'asc'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '↑'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '↓'}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </th></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </tr></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </thead></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <tbody></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> processedData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">row</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <tr @click=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> emit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'row-click'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">, </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">row</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">columns</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">col</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <td>\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">row</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">[</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">col</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">field</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">]</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</td></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </tr></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </tbody></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </table></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <!-- Empty state --></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> processedData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ===</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="empty-state"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> No data found</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}, [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'data'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'columns'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]);</span></span></code></pre></div><p><strong>Usage:</strong></p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> userColumns</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { field: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'id'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, label: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'ID'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { field: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'name'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, label: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Name'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { field: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'email'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, label: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Email'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { field: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'role'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, label: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Role'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">];</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> userData</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { id: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'John Doe'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, email: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'john@example.com'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, role: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Admin'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { id: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Jane Smith'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, email: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'jane@example.com'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, role: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'User'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">];</span></span></code></pre></div><div class="language-html vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"><</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">data-table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> .data</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\${userData}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> .columns</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\${userColumns}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> @row-click</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\${(e)</span><span style="--shiki-light:#B31D28;--shiki-light-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">> console.log('Row clicked:', e.detail)}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"></</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">data-table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span></code></pre></div><h3 id="tabs-component" tabindex="-1">Tabs Component <a class="header-anchor" href="#tabs-component" aria-label="Permalink to "Tabs Component""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// tabs.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'my-tabs'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">props</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">slot</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">emit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> activeTab</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(props.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">active</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Get all tab headers from slots</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> tabs</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> headers</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> slot</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'tab'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> headers.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">node</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">index</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> index,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> title: node.textContent,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> content: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">slot</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`panel-\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">index</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> emit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'change'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { index: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">activeTab</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(), tab: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">tabs</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">activeTab</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()] });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="tabs"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="tab-headers"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">tabs</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">tab</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> class="tab-header \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> activeTab</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> tab</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">index</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'active'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''}"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @click=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> activeTab</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">tab</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">index</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">tab</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">title</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="tab-panels"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">tabs</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">tab</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> class="tab-panel"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> style="display: \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> activeTab</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> tab</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">index</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'block'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'none'}"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">tab</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">content</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}, [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'active'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]);</span></span></code></pre></div><p><strong>Usage:</strong></p><div class="language-html vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"><</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">my-tabs</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> @change</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\${(e)</span><span style="--shiki-light:#B31D28;--shiki-light-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">> console.log('Tab changed:', e.detail)}></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> slot</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"tab"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">>Profile</</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> slot</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"panel-0"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">h3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">>Profile Settings</</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">h3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">form</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">>...</</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">form</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> slot</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"tab"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">>Security</</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> slot</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"panel-1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">h3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">>Security Settings</</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">h3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">form</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">>...</</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">form</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> slot</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"tab"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">>Notifications</</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> slot</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"panel-2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">h3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">>Notification Preferences</</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">h3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">form</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">>...</</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">form</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"></</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">my-tabs</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span></code></pre></div><h3 id="component-with-external-data" tabindex="-1">Component with External Data <a class="header-anchor" href="#component-with-external-data" aria-label="Permalink to "Component with External Data""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// user-profile.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'user-profile'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">props</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">emit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">onUnmount</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> user</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> loading</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> error</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Fetch user data when userId changes</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> userId</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> props.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">userId</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">userId) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> error</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> controller</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> AbortController</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`/api/users/\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">userId</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { signal: controller.signal })</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">res</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> res.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">json</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">())</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> emit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'loaded'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, data);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> })</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">catch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">err</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (err.name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'AbortError'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> error</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(err.message);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> emit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'error'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, err);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> })</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">finally</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Cleanup: abort fetch if component unmounts or userId changes</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> onUnmount</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> controller.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">abort</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="user-profile"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loading</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="spinner">Loading...</div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> error</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="error">Error: \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">error</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> user</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="user-info"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <img src="\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">user</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">avatar</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}" class="avatar" /></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h2>\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">user</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</h2></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">user</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">email</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>Member since: \${</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Date</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">user</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">joined</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">toLocaleDateString</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="no-user">No user selected</div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}, [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'user-id'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]);</span></span></code></pre></div><h2 id="📦-component-libraries" tabindex="-1">📦 Component Libraries <a class="header-anchor" href="#📦-component-libraries" aria-label="Permalink to "📦 Component Libraries""></a></h2><h3 id="building-a-reusable-component-library" tabindex="-1">Building a Reusable Component Library <a class="header-anchor" href="#building-a-reusable-component-library" aria-label="Permalink to "Building a Reusable Component Library""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// components/index.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Button component</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> Button</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'ui-button'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">props</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">slot</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">emit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> variant</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> props.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">variant</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'primary'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> size</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> props.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">size</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'md'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> sizes</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> sm: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'px-2 py-1 text-sm'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> md: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'px-4 py-2'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> lg: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'px-6 py-3 text-lg'</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> variants</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> primary: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'bg-blue-500 hover:bg-blue-600 text-white'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> secondary: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'bg-gray-500 hover:bg-gray-600 text-white'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> danger: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'bg-red-500 hover:bg-red-600 text-white'</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> class="rounded font-semibold transition-colors \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">sizes</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">[</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">size</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">]</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">} \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">variants</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">[</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">variant</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">]</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ?disabled=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">props</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">disabled</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @click=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> emit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'click'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">slot</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}, [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'variant'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'size'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'disabled'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Card component</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> Card</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'ui-card'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">props</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">slot</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="card border rounded-lg shadow-sm overflow-hidden"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">props</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">title</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="card-header bg-gray-50 px-4 py-3 border-b"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h3 class="font-semibold">\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">props</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">title</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</h3></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="card-body p-4"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">slot</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">props</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">footer</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="card-footer bg-gray-50 px-4 py-3 border-t"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">slot</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'footer'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}, [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'title'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Badge component</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> Badge</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'ui-badge'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">props</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">slot</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> type</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> props.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'default'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> types</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> default: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'bg-gray-100 text-gray-800'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> success: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'bg-green-100 text-green-800'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> warning: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'bg-yellow-100 text-yellow-800'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> error: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'bg-red-100 text-red-800'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> info: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'bg-blue-100 text-blue-800'</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <span class="inline-block px-2 py-1 text-xs font-semibold rounded \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">types</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">[</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">type</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">]</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">slot</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}, [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'type'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html };</span></span></code></pre></div><p><strong>Usage:</strong></p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { Button, Card, Badge } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './components/index.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Use components anywhere</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> app</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <Card title="Welcome"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>This is a card component</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div slot="footer"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <Button variant="primary" @click=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">handleClick</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> Save Changes</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </Button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <Badge type="success">New</Badge></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </Card></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span></code></pre></div><h2 id="🎯-decision-guide-light-dom-vs-shadow-dom" tabindex="-1">🎯 Decision Guide: Light DOM vs Shadow DOM <a class="header-anchor" href="#🎯-decision-guide-light-dom-vs-shadow-dom" aria-label="Permalink to "🎯 Decision Guide: Light DOM vs Shadow DOM""></a></h2><table tabindex="0"><thead><tr><th>Use Light DOM (<code>false</code>) when...</th><th>Use Shadow DOM (<code>true</code>) when...</th></tr></thead><tbody><tr><td>Component is part of your main app</td><td>Building a UI library for others</td></tr><tr><td>Using global CSS (Tailwind, Bootstrap)</td><td>Creating embeddable widgets</td></tr><tr><td>Need to inherit theme variables</td><td>Styles must be pixel-perfect everywhere</td></tr><tr><td>Working with existing design system</td><td>Component has complex, specific styles</td></tr><tr><td>Quick prototyping</td><td>Distributing to different projects</td></tr><tr><td>Form elements that should match site</td><td>Need style isolation/encapsulation</td></tr></tbody></table><h2 id="📊-summary" tabindex="-1">📊 Summary <a class="header-anchor" href="#📊-summary" aria-label="Permalink to "📊 Summary""></a></h2><table tabindex="0"><thead><tr><th>Feature</th><th>Description</th></tr></thead><tbody><tr><td><strong>Native Web Components</strong></td><td>Built on Custom Elements standard</td></tr><tr><td><strong>Reactive Props</strong></td><td>Observed attributes become signals</td></tr><tr><td><strong>Two Rendering Modes</strong></td><td>Light DOM (default) or Shadow DOM</td></tr><tr><td><strong>Automatic Cleanup</strong></td><td>Effects and listeners cleaned up on disconnect</td></tr><tr><td><strong>Event System</strong></td><td>Custom events with <code>emit()</code></td></tr><tr><td><strong>Slot Support</strong></td><td>Full slot API for content projection</td></tr><tr><td><strong>Zero Dependencies</strong></td><td>Pure vanilla JavaScript</td></tr></tbody></table><hr><blockquote><p><strong>Pro Tip:</strong> Start with Light DOM components for app-specific UI, and use Shadow DOM when building components that need to work identically across different projects or websites.</p></blockquote>`,64)])])}const g=i(t,[["render",l]]);export{F as __pageData,g as default};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{_ as i,o as a,c as n,ae as h}from"./chunks/framework.C8AWLET_.js";const F=JSON.parse('{"title":"Components API 🧩","description":"","frontmatter":{},"headers":[],"relativePath":"api/components.md","filePath":"api/components.md"}'),t={name:"api/components.md"};function l(k,s,p,e,E,r){return a(),n("div",null,[...s[0]||(s[0]=[h("",64)])])}const g=i(t,[["render",l]]);export{F as __pageData,g as default};
|
|
||||||
@@ -1,763 +0,0 @@
|
|||||||
import{_ as i,o as a,c as n,ae as h}from"./chunks/framework.C8AWLET_.js";const g=JSON.parse('{"title":"Effects API 🔄","description":"","frontmatter":{},"headers":[],"relativePath":"api/effects.md","filePath":"api/effects.md"}'),k={name:"api/effects.md"};function l(t,s,p,e,E,r){return a(),n("div",null,[...s[0]||(s[0]=[h(`<h1 id="effects-api-🔄" tabindex="-1">Effects API 🔄 <a class="header-anchor" href="#effects-api-🔄" aria-label="Permalink to "Effects API 🔄""></a></h1><p>Effects are the bridge between reactive signals and side effects in your application. They automatically track signal dependencies and re-run whenever those signals change, enabling everything from DOM updates to data fetching and localStorage synchronization.</p><h2 id="core-concepts" tabindex="-1">Core Concepts <a class="header-anchor" href="#core-concepts" aria-label="Permalink to "Core Concepts""></a></h2><h3 id="what-is-an-effect" tabindex="-1">What is an Effect? <a class="header-anchor" href="#what-is-an-effect" aria-label="Permalink to "What is an Effect?""></a></h3><p>An effect is a function that:</p><ul><li><strong>Runs immediately</strong> when created</li><li><strong>Tracks all signals</strong> read during its execution</li><li><strong>Re-runs automatically</strong> when any tracked signal changes</li><li><strong>Can return a cleanup function</strong> that runs before the next execution or when the effect is stopped</li></ul><h3 id="how-effects-work" tabindex="-1">How Effects Work <a class="header-anchor" href="#how-effects-work" aria-label="Permalink to "How Effects Work""></a></h3><ol><li>When an effect runs, it sets itself as the <code>activeEffect</code></li><li>Any signal read during execution adds the effect to its subscribers</li><li>When a signal changes, it queues all its subscribers</li><li>Effects are batched and run in the next microtask</li><li>If an effect returns a function, it's stored as a cleanup handler</li></ol><h2 id="effect-effectfn" tabindex="-1"><code>$.effect(effectFn)</code> <a class="header-anchor" href="#effect-effectfn" aria-label="Permalink to "\`$.effect(effectFn)\`""></a></h2><p>Creates a reactive effect that automatically tracks dependencies and re-runs when they change.</p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> count</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`Count is: \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Logs: "Count is: 0"</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Logs: "Count is: 1"</span></span></code></pre></div><h2 id="📋-api-reference" tabindex="-1">📋 API Reference <a class="header-anchor" href="#📋-api-reference" aria-label="Permalink to "📋 API Reference""></a></h2><table tabindex="0"><thead><tr><th>Pattern</th><th>Example</th><th>Description</th></tr></thead><tbody><tr><td>Basic Effect</td><td><code>$.effect(() => console.log(count()))</code></td><td>Run on dependency changes</td></tr><tr><td>With Cleanup</td><td><code>$.effect(() => { timer = setInterval(...); return () => clearInterval(timer) })</code></td><td>Return cleanup function</td></tr><tr><td>Stop Effect</td><td><code>const stop = $.effect(...); stop()</code></td><td>Manually stop an effect</td></tr></tbody></table><h3 id="effect-object-internal" tabindex="-1">Effect Object (Internal) <a class="header-anchor" href="#effect-object-internal" aria-label="Permalink to "Effect Object (Internal)""></a></h3><table tabindex="0"><thead><tr><th>Property/Method</th><th>Description</th></tr></thead><tbody><tr><td><code>dependencies</code></td><td>Set of signal subscriber sets this effect belongs to</td></tr><tr><td><code>cleanupHandlers</code></td><td>Set of cleanup functions to run before next execution</td></tr><tr><td><code>run()</code></td><td>Executes the effect and tracks dependencies</td></tr><tr><td><code>stop()</code></td><td>Stops the effect and runs all cleanup handlers</td></tr></tbody></table><h2 id="🎯-basic-examples" tabindex="-1">🎯 Basic Examples <a class="header-anchor" href="#🎯-basic-examples" aria-label="Permalink to "🎯 Basic Examples""></a></h2><h3 id="console-logging" tabindex="-1">Console Logging <a class="header-anchor" href="#console-logging" aria-label="Permalink to "Console Logging""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'World'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> count</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`Hello \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}! Count is \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Logs: "Hello World! Count is 0"</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'John'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Logs: "Hello John! Count is 0"</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Logs: "Hello John! Count is 5"</span></span></code></pre></div><h3 id="dom-updates" tabindex="-1">DOM Updates <a class="header-anchor" href="#dom-updates" aria-label="Permalink to "DOM Updates""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> count</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> element</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> document.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">getElementById</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'counter'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> element.textContent </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`Count: \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Updates DOM automatically when count changes</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Element text becomes "Count: 10"</span></span></code></pre></div><h3 id="document-title" tabindex="-1">Document Title <a class="header-anchor" href="#document-title" aria-label="Permalink to "Document Title""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> page</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'home'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> unreadCount</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> base</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> page</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'home'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'Home'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'Dashboard'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> unread</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> unreadCount</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">></span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \` (\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">unreadCount</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">})\`</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> document.title </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">base</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">unread</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">} - My App\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">page</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'dashboard'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Title: "Dashboard - My App"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">unreadCount</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Title: "Dashboard (3) - My App"</span></span></code></pre></div><h2 id="🧹-effects-with-cleanup" tabindex="-1">🧹 Effects with Cleanup <a class="header-anchor" href="#🧹-effects-with-cleanup" aria-label="Permalink to "🧹 Effects with Cleanup""></a></h2><p>Cleanup functions are essential for managing resources like intervals, event listeners, and subscriptions.</p><h3 id="basic-cleanup" tabindex="-1">Basic Cleanup <a class="header-anchor" href="#basic-cleanup" aria-label="Permalink to "Basic Cleanup""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> userId</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> id</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> userId</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`Setting up timer for user \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">id</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> timer</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> setInterval</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`Polling user \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">id</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}...\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Cleanup runs before next effect execution</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`Cleaning up timer for user \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">id</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> clearInterval</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(timer);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Sets up timer for user 1</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">userId</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Cleans up timer for user 1</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Sets up timer for user 2</span></span></code></pre></div><h3 id="event-listener-cleanup" tabindex="-1">Event Listener Cleanup <a class="header-anchor" href="#event-listener-cleanup" aria-label="Permalink to "Event Listener Cleanup""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> isListening</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">isListening</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> handleClick</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">e</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Window clicked:'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, e.clientX, e.clientY);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> window.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">addEventListener</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'click'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, handleClick);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Click listener added'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> window.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">removeEventListener</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'click'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, handleClick);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Click listener removed'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">isListening</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Adds listener</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">isListening</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Removes listener</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">isListening</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Adds listener again</span></span></code></pre></div><h3 id="websocket-connection" tabindex="-1">WebSocket Connection <a class="header-anchor" href="#websocket-connection" aria-label="Permalink to "WebSocket Connection""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> room</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'general'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> messages</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([]);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> currentRoom</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> room</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`Connecting to room: \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">currentRoom</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> ws</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> WebSocket</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`wss://chat.example.com/\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">currentRoom</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ws.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">onmessage</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">event</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> messages</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">messages</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(), </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">JSON</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">parse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(event.data)]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ws.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">onerror</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">error</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">error</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'WebSocket error:'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, error);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Cleanup: close connection when room changes</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`Disconnecting from room: \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">currentRoom</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ws.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">close</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">room</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'random'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Closes 'general' connection, opens 'random'</span></span></code></pre></div><h2 id="⏱️-effect-timing-and-batching" tabindex="-1">⏱️ Effect Timing and Batching <a class="header-anchor" href="#⏱️-effect-timing-and-batching" aria-label="Permalink to "⏱️ Effect Timing and Batching""></a></h2><h3 id="microtask-batching" tabindex="-1">Microtask Batching <a class="header-anchor" href="#microtask-batching" aria-label="Permalink to "Microtask Batching""></a></h3><p>Effects are batched using <code>queueMicrotask</code> for optimal performance:</p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> a</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> b</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> c</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Effect ran with:'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">a</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(), </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">b</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(), </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">c</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Logs immediately: "Effect ran with: 1 2 3"</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Multiple updates in same tick - only one effect run!</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">a</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">b</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">20</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">c</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">30</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Only logs once: "Effect ran with: 10 20 30"</span></span></code></pre></div><h3 id="async-effects" tabindex="-1">Async Effects <a class="header-anchor" href="#async-effects" aria-label="Permalink to "Async Effects""></a></h3><p>Effects can be asynchronous, but be careful with dependency tracking:</p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> userId</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> userData</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> id</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> userId</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`Fetching user \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">id</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}...\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Only id() is tracked (synchronous part)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`/api/users/\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">id</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">res</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> res.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">json</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">())</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // This runs later - no dependency tracking here!</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> userData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">userId</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Triggers effect again, cancels previous fetch</span></span></code></pre></div><h3 id="effect-with-abortcontroller" tabindex="-1">Effect with AbortController <a class="header-anchor" href="#effect-with-abortcontroller" aria-label="Permalink to "Effect with AbortController""></a></h3><p>For proper async cleanup with fetch:</p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> userId</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> userData</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> loading</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> id</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> userId</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> controller</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> AbortController</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`/api/users/\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">id</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { signal: controller.signal })</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">res</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> res.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">json</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">())</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> userData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> })</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">catch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">err</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (err.name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'AbortError'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">error</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Fetch error:'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, err);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Cleanup: abort fetch if userId changes before completion</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> controller.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">abort</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h2 id="🎨-advanced-effect-patterns" tabindex="-1">🎨 Advanced Effect Patterns <a class="header-anchor" href="#🎨-advanced-effect-patterns" aria-label="Permalink to "🎨 Advanced Effect Patterns""></a></h2><h3 id="debounced-effects" tabindex="-1">Debounced Effects <a class="header-anchor" href="#debounced-effects" aria-label="Permalink to "Debounced Effects""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> searchTerm</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> results</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> debounceTimeout;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> term</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> searchTerm</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Clear previous timeout</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> clearTimeout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(debounceTimeout);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Don't search if term is too short</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (term.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> <</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> results</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Debounce search</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> debounceTimeout </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> setTimeout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Searching for:'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, term);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`/api/search?q=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">term</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">r</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> r.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">json</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> results</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">300</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Cleanup on effect re-run</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> clearTimeout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(debounceTimeout);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h3 id="throttled-effects" tabindex="-1">Throttled Effects <a class="header-anchor" href="#throttled-effects" aria-label="Permalink to "Throttled Effects""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> scrollPosition</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> lastRun </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> rafId </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> pos</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> scrollPosition</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Throttle with requestAnimationFrame</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (rafId) </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">cancelAnimationFrame</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(rafId);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> rafId </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> requestAnimationFrame</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Scroll position:'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, pos);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> updateScrollUI</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(pos);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> lastRun </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> Date.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">now</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> rafId </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (rafId) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> cancelAnimationFrame</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(rafId);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> rafId </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Even with many updates, effect runs at most once per frame</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">; i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"><</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">; i</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">++</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> scrollPosition</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(i);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><h3 id="conditional-effects" tabindex="-1">Conditional Effects <a class="header-anchor" href="#conditional-effects" aria-label="Permalink to "Conditional Effects""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> isEnabled</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> value</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> threshold</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Effect only runs when isEnabled is true</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">isEnabled</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`Monitoring value: \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">value</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}, threshold: \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">threshold</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> threshold</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> alert</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`Value \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">value</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">} exceeded threshold \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">threshold</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}!\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">isEnabled</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Effect starts monitoring</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">15</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Triggers alert</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">isEnabled</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Effect stops (still runs, but condition prevents logic)</span></span></code></pre></div><h3 id="effect-with-multiple-cleanups" tabindex="-1">Effect with Multiple Cleanups <a class="header-anchor" href="#effect-with-multiple-cleanups" aria-label="Permalink to "Effect with Multiple Cleanups""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> config</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({ theme: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'light'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, notifications: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">theme</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">notifications</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> config</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> cleanups</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [];</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Setup theme</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> document.body.className </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`theme-\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">theme</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> cleanups.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">push</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> document.body.classList.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">remove</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`theme-\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">theme</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Setup notifications</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (notifications) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> handler</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">e</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Notification:'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, e.detail);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> window.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">addEventListener</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'notification'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, handler);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> cleanups.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">push</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> window.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">removeEventListener</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'notification'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, handler);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Return combined cleanup</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> cleanups.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">forEach</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">cleanup</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> cleanup</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h2 id="🎯-effects-in-components" tabindex="-1">🎯 Effects in Components <a class="header-anchor" href="#🎯-effects-in-components" aria-label="Permalink to "🎯 Effects in Components""></a></h2><h3 id="component-lifecycle" tabindex="-1">Component Lifecycle <a class="header-anchor" href="#component-lifecycle" aria-label="Permalink to "Component Lifecycle""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'timer-display'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> seconds</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Effect for timer - automatically cleaned up when component unmounts</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> interval</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> setInterval</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> seconds</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">s</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> s </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> clearInterval</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(interval);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h2>Timer: \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">seconds</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}s</h2></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h3 id="effects-with-props" tabindex="-1">Effects with Props <a class="header-anchor" href="#effects-with-props" aria-label="Permalink to "Effects with Props""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'data-viewer'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">props</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> error</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Effect reacts to prop changes</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> url</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> props.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">url</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">url) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> controller</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> AbortController</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(url, { signal: controller.signal })</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">res</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> res.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">json</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">())</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">catch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">err</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (err.name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'AbortError'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> error</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(err.message);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> controller.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">abort</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">error</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`<div class="error">\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">error</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</div>\`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">data</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`<div>Loading...</div>\`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`<pre>\${</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">JSON</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">stringify</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">data</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(), </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">2</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</pre>\`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> }</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}, [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'url'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]);</span></span></code></pre></div><h2 id="🔧-effect-management" tabindex="-1">🔧 Effect Management <a class="header-anchor" href="#🔧-effect-management" aria-label="Permalink to "🔧 Effect Management""></a></h2><h3 id="stopping-effects" tabindex="-1">Stopping Effects <a class="header-anchor" href="#stopping-effects" aria-label="Permalink to "Stopping Effects""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> count</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Start effect</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> stopEffect</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Count:'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Logs: "Count: 1"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Logs: "Count: 2"</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Stop the effect</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">stopEffect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// No logging - effect is stopped</span></span></code></pre></div><h3 id="conditional-effect-stopping" tabindex="-1">Conditional Effect Stopping <a class="header-anchor" href="#conditional-effect-stopping" aria-label="Permalink to "Conditional Effect Stopping""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> isActive</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> count</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> currentEffect </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">isActive</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Start or restart the monitoring effect</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (currentEffect) </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">currentEffect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> currentEffect </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Monitoring count:'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Stop monitoring</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (currentEffect) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> currentEffect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> currentEffect </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h3 id="nested-effects" tabindex="-1">Nested Effects <a class="header-anchor" href="#nested-effects" aria-label="Permalink to "Nested Effects""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> user</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({ id: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'John'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> settings</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({ theme: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'dark'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'User changed:'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().name);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Nested effect - tracks settings independently</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Settings changed:'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">settings</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().theme);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // When user changes, the nested effect is recreated</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h2 id="🚀-real-world-examples" tabindex="-1">🚀 Real-World Examples <a class="header-anchor" href="#🚀-real-world-examples" aria-label="Permalink to "🚀 Real-World Examples""></a></h2><h3 id="auto-saving-form" tabindex="-1">Auto-saving Form <a class="header-anchor" href="#auto-saving-form" aria-label="Permalink to "Auto-saving Form""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> formData</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> title: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> content: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> tags: []</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> lastSaved</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> saveStatus</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'idle'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 'idle', 'saving', 'saved', 'error'</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> saveTimeout;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> formData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Clear previous timeout</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> clearTimeout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(saveTimeout);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Don't save empty form</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">data.title </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">&&</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> !</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">data.content) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> saveStatus</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'idle'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> saveStatus</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'saving'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Debounce save</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> saveTimeout </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> setTimeout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/api/posts'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> method: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'POST'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> headers: { </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Content-Type'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'application/json'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> body: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">JSON</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">stringify</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> saveStatus</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'saved'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> lastSaved</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Date</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">catch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (error) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> saveStatus</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'error'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">error</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Auto-save failed:'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, error);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> clearTimeout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(saveTimeout);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// UI feedback</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> statusMessage</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> status</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> saveStatus</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> saved</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> lastSaved</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (status </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'saving'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'Saving...'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (status </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'error'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'Save failed'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (status </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'saved'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> &&</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> saved) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`Last saved: \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">saved</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">toLocaleTimeString</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h3 id="real-time-search-with-debounce" tabindex="-1">Real-time Search with Debounce <a class="header-anchor" href="#real-time-search-with-debounce" aria-label="Permalink to "Real-time Search with Debounce""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> searchInput</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> searchResults</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> searchStatus</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'idle'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 'idle', 'searching', 'results', 'no-results', 'error'</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> searchTimeout;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> abortController </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> query</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> searchInput</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">trim</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Clear previous timeout</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> clearTimeout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(searchTimeout);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Cancel previous request</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (abortController) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> abortController.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">abort</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> abortController </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Don't search for short queries</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (query.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> <</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> searchResults</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> searchStatus</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'idle'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> searchStatus</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'searching'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Debounce search</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> searchTimeout </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> setTimeout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> abortController </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> AbortController</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> response</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`/api/search?q=\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">encodeURIComponent</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">query</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> signal: abortController.signal</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> response.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">json</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">abortController.signal.aborted) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> searchResults</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> searchStatus</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'results'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'no-results'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> abortController </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">catch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (error) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (error.name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'AbortError'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">error</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Search failed:'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, error);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> searchStatus</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'error'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">300</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> clearTimeout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(searchTimeout);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (abortController) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> abortController.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">abort</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> abortController </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h3 id="analytics-tracking" tabindex="-1">Analytics Tracking <a class="header-anchor" href="#analytics-tracking" aria-label="Permalink to "Analytics Tracking""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Analytics configuration</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> analyticsEnabled</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> currentPage</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> userProperties</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Track page views</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">analyticsEnabled</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> page</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> currentPage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> properties</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> userProperties</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Track page view:'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, page, properties);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Send to analytics</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> gtag</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'config'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'GA-MEASUREMENT-ID'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> page_path: page,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">properties</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Track user interactions</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> trackEvent</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">eventName</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">properties</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {}) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">analyticsEnabled</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Track event:'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, eventName, properties);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> gtag</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'event'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, eventName, properties);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Usage</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">currentPage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/dashboard'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">userProperties</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({ userId: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">123</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, plan: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'premium'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">trackEvent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'button_click'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { buttonId: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'signup'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span></code></pre></div><h3 id="keyboard-shortcuts" tabindex="-1">Keyboard Shortcuts <a class="header-anchor" href="#keyboard-shortcuts" aria-label="Permalink to "Keyboard Shortcuts""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> shortcuts</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'ctrl+s'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: { handler: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, description: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Save'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'ctrl+z'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: { handler: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, description: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Undo'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'ctrl+shift+z'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: { handler: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, description: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Redo'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'escape'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: { handler: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, description: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Close modal'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> pressedKeys</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> handleKeyDown</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">e</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> key</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> e.key.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">toLowerCase</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> ctrl</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> e.ctrlKey </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'ctrl+'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> shift</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> e.shiftKey </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'shift+'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> alt</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> e.altKey </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'alt+'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> meta</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> e.metaKey </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'meta+'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> combo</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">ctrl</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">shift</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">alt</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">meta</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">key</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">replace</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/</span><span style="--shiki-light:#22863A;--shiki-light-font-weight:bold;--shiki-dark:#85E89D;--shiki-dark-font-weight:bold;">\\+</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">$</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> shortcut</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> shortcuts</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()[combo];</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (shortcut?.handler) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> e.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">preventDefault</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> shortcut.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">handler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> window.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">addEventListener</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'keydown'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, handleKeyDown);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> window.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">removeEventListener</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'keydown'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, handleKeyDown);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Register shortcuts</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">shortcuts</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">shortcuts</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(),</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'ctrl+s'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> handler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> saveDocument</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(),</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> description: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Save document'</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'ctrl+z'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> handler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> undo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(),</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> description: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Undo'</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h3 id="infinite-scroll" tabindex="-1">Infinite Scroll <a class="header-anchor" href="#infinite-scroll" aria-label="Permalink to "Infinite Scroll""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> posts</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> page</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> hasMore</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> loading</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> observer </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Load more posts</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loadMore</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">loading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> !</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">hasMore</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> response</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`/api/posts?page=\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">page</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> newPosts</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> response.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">json</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (newPosts.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ===</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> hasMore</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> posts</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">posts</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(), </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">newPosts]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> page</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">p</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> p </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">finally</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Setup intersection observer for infinite scroll</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> sentinel</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> document.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">getElementById</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'sentinel'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">sentinel) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> observer </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> IntersectionObserver</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">entries</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (entries[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">].isIntersecting </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">&&</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> !</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">loading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">&&</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> hasMore</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loadMore</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { threshold: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0.1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> );</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> observer.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">observe</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(sentinel);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (observer) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> observer.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">disconnect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> observer </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Initial load</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">loadMore</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span></code></pre></div><h2 id="📊-performance-considerations" tabindex="-1">📊 Performance Considerations <a class="header-anchor" href="#📊-performance-considerations" aria-label="Permalink to "📊 Performance Considerations""></a></h2><table tabindex="0"><thead><tr><th>Pattern</th><th>Performance Impact</th><th>Best Practice</th></tr></thead><tbody><tr><td>Multiple signal reads</td><td>O(n) per effect</td><td>Group related signals</td></tr><tr><td>Deep object access</td><td>Minimal</td><td>Use computed signals</td></tr><tr><td>Large arrays</td><td>O(n) for iteration</td><td>Memoize with computed</td></tr><tr><td>Frequent updates</td><td>Batched</td><td>Let batching work</td></tr><tr><td>Heavy computations</td><td>Blocking</td><td>Use Web Workers</td></tr></tbody></table><h2 id="🎯-best-practices" tabindex="-1">🎯 Best Practices <a class="header-anchor" href="#🎯-best-practices" aria-label="Permalink to "🎯 Best Practices""></a></h2><h3 id="_1-keep-effects-focused" tabindex="-1">1. Keep Effects Focused <a class="header-anchor" href="#_1-keep-effects-focused" aria-label="Permalink to "1. Keep Effects Focused""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ❌ Avoid doing too much in one effect</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> updateUI</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// UI update</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> saveToStorage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Storage</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> sendAnalytics</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Analytics</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> validate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Validation</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ✅ Split into focused effects</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> updateUI</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> saveToStorage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> sendAnalytics</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> validate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()));</span></span></code></pre></div><h3 id="_2-always-clean-up" tabindex="-1">2. Always Clean Up <a class="header-anchor" href="#_2-always-clean-up" aria-label="Permalink to "2. Always Clean Up""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ❌ Missing cleanup</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> timer</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> setInterval</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {}, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Memory leak!</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ✅ Proper cleanup</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> timer</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> setInterval</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {}, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> clearInterval</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(timer);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h3 id="_3-avoid-writing-to-signals-in-effects" tabindex="-1">3. Avoid Writing to Signals in Effects <a class="header-anchor" href="#_3-avoid-writing-to-signals-in-effects" aria-label="Permalink to "3. Avoid Writing to Signals in Effects""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> a</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> b</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ❌ Avoid - can cause loops</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> a</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">b</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Writing to a while reading b</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ✅ Use computed signals instead</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> sum</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> a</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> b</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span></code></pre></div><h3 id="_4-use-conditional-logic-carefully" tabindex="-1">4. Use Conditional Logic Carefully <a class="header-anchor" href="#_4-use-conditional-logic-carefully" aria-label="Permalink to "4. Use Conditional Logic Carefully""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ❌ Condition affects dependency tracking</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">condition</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">a</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Only tracks a when condition is true</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ✅ Track all dependencies explicitly</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> cond</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> condition</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Track condition</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (cond) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">a</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Track a</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h3 id="_5-memoize-expensive-computations" tabindex="-1">5. Memoize Expensive Computations <a class="header-anchor" href="#_5-memoize-expensive-computations" aria-label="Permalink to "5. Memoize Expensive Computations""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> items</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([]);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ❌ Expensive computation runs on every effect</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> total</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> items</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">reduce</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">sum</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">i</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> sum </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> i.price, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> updateTotal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(total);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ✅ Memoize with computed signal</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> total</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> items</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">reduce</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">sum</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">i</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> sum </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> i.price, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> updateTotal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">total</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()));</span></span></code></pre></div><h2 id="🔍-debugging-effects" tabindex="-1">🔍 Debugging Effects <a class="header-anchor" href="#🔍-debugging-effects" aria-label="Permalink to "🔍 Debugging Effects""></a></h2><h3 id="logging-effect-runs" tabindex="-1">Logging Effect Runs <a class="header-anchor" href="#logging-effect-runs" aria-label="Permalink to "Logging Effect Runs""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> withLogging</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">effectFn</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`[\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}] Running...\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> start</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> performance.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">now</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> result</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> effectFn</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> duration</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> performance.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">now</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> start;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`[\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}] Completed in \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">duration</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">toFixed</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">2</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}ms\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> result;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Usage</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">withLogging</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Count:'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'count-effect'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span></code></pre></div><h3 id="effect-inspector" tabindex="-1">Effect Inspector <a class="header-anchor" href="#effect-inspector" aria-label="Permalink to "Effect Inspector""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> createEffectInspector</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> effects</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> id </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> trackedEffect</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">fn</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`effect-\${</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">++</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">id</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> info</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> name,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> runs: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> lastRun: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> duration: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> dependencies: </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> wrapped</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> info.runs</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">++</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> info.lastRun </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Date</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> start</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> performance.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">now</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> result</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fn</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> info.duration </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> performance.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">now</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> start;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> result;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> stop</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(wrapped);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> effects.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(stop, info);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> stop;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> getReport</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> report</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {};</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> effects.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">forEach</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">info</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">stop</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> report[info.name] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> runs: info.runs,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> lastRun: info.lastRun,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> avgDuration: info.duration </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> info.runs</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> report;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { trackedEffect, getReport };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Usage</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> inspector</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> createEffectInspector</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">inspector.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">trackedEffect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Count:'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'counter-effect'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span></code></pre></div><h2 id="📊-summary" tabindex="-1">📊 Summary <a class="header-anchor" href="#📊-summary" aria-label="Permalink to "📊 Summary""></a></h2><table tabindex="0"><thead><tr><th>Feature</th><th>Description</th></tr></thead><tbody><tr><td><strong>Automatic Tracking</strong></td><td>Dependencies tracked automatically</td></tr><tr><td><strong>Cleanup Functions</strong></td><td>Return function to clean up resources</td></tr><tr><td><strong>Batch Updates</strong></td><td>Multiple changes batched in microtask</td></tr><tr><td><strong>Manual Stop</strong></td><td>Can stop effects with returned function</td></tr><tr><td><strong>Nested Effects</strong></td><td>Effects can contain other effects</td></tr><tr><td><strong>Auto-cleanup</strong></td><td>Effects in pages/components auto-cleaned</td></tr></tbody></table><hr><blockquote><p><strong>Pro Tip:</strong> Effects are the perfect place for side effects like DOM updates, data fetching, and subscriptions. Keep them focused and always clean up resources!</p></blockquote>`,94)])])}const y=i(k,[["render",l]]);export{g as __pageData,y as default};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{_ as i,o as a,c as n,ae as h}from"./chunks/framework.C8AWLET_.js";const g=JSON.parse('{"title":"Effects API 🔄","description":"","frontmatter":{},"headers":[],"relativePath":"api/effects.md","filePath":"api/effects.md"}'),k={name:"api/effects.md"};function l(t,s,p,e,E,r){return a(),n("div",null,[...s[0]||(s[0]=[h("",94)])])}const y=i(k,[["render",l]]);export{g as __pageData,y as default};
|
|
||||||
@@ -1,849 +0,0 @@
|
|||||||
import{_ as i,o as a,c as n,ae as h}from"./chunks/framework.C8AWLET_.js";const d=JSON.parse('{"title":"Fetch API 🌐","description":"","frontmatter":{},"headers":[],"relativePath":"api/fetch.md","filePath":"api/fetch.md"}'),l={name:"api/fetch.md"};function k(t,s,p,e,E,F){return a(),n("div",null,[...s[0]||(s[0]=[h(`<h1 id="fetch-api-🌐" tabindex="-1">Fetch API 🌐 <a class="header-anchor" href="#fetch-api-🌐" aria-label="Permalink to "Fetch API 🌐""></a></h1><p>SigPro provides a simple, lightweight wrapper around the native Fetch API that integrates seamlessly with signals for loading state management. It's designed for common use cases with sensible defaults.</p><h2 id="core-concepts" tabindex="-1">Core Concepts <a class="header-anchor" href="#core-concepts" aria-label="Permalink to "Core Concepts""></a></h2><h3 id="what-is-fetch" tabindex="-1">What is <code>$.fetch</code>? <a class="header-anchor" href="#what-is-fetch" aria-label="Permalink to "What is \`$.fetch\`?""></a></h3><p>A ultra-simple fetch wrapper that:</p><ul><li><strong>Automatically handles JSON</strong> serialization and parsing</li><li><strong>Integrates with signals</strong> for loading state</li><li><strong>Returns <code>null</code> on error</strong> (no try/catch needed for basic usage)</li><li><strong>Works great with effects</strong> for reactive data fetching</li></ul><h2 id="fetch-url-data-loading" tabindex="-1"><code>$.fetch(url, data, [loading])</code> <a class="header-anchor" href="#fetch-url-data-loading" aria-label="Permalink to "\`$.fetch(url, data, [loading])\`""></a></h2><p>Makes a POST request with JSON data and optional loading signal.</p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> loading</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loadUser</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> user</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/api/user'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { id: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">123</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }, loading);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (user) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'User loaded:'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, user);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><h2 id="📋-api-reference" tabindex="-1">📋 API Reference <a class="header-anchor" href="#📋-api-reference" aria-label="Permalink to "📋 API Reference""></a></h2><h3 id="parameters" tabindex="-1">Parameters <a class="header-anchor" href="#parameters" aria-label="Permalink to "Parameters""></a></h3><table tabindex="0"><thead><tr><th>Parameter</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>url</code></td><td><code>string</code></td><td>Endpoint URL</td></tr><tr><td><code>data</code></td><td><code>Object</code></td><td>Data to send (automatically JSON.stringify'd)</td></tr><tr><td><code>loading</code></td><td><code>Function</code> (optional)</td><td>Signal function to track loading state</td></tr></tbody></table><h3 id="returns" tabindex="-1">Returns <a class="header-anchor" href="#returns" aria-label="Permalink to "Returns""></a></h3><table tabindex="0"><thead><tr><th>Return</th><th>Description</th></tr></thead><tbody><tr><td><code>Promise<Object|null></code></td><td>Parsed JSON response or <code>null</code> on error</td></tr></tbody></table><h2 id="🎯-basic-examples" tabindex="-1">🎯 Basic Examples <a class="header-anchor" href="#🎯-basic-examples" aria-label="Permalink to "🎯 Basic Examples""></a></h2><h3 id="simple-data-fetching" tabindex="-1">Simple Data Fetching <a class="header-anchor" href="#simple-data-fetching" aria-label="Permalink to "Simple Data Fetching""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> userData</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetchUser</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">id</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/api/user'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { id });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (data) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> userData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fetchUser</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">123</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span></code></pre></div><h3 id="with-loading-state" tabindex="-1">With Loading State <a class="header-anchor" href="#with-loading-state" aria-label="Permalink to "With Loading State""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> user</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> loading</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loadUser</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">id</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/api/user'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { id }, loading);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (data) </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// In your template</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loading</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="spinner">Loading...</div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> user</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h2>\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">user</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</h2></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>Email: \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">user</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">email</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>No user found</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span></code></pre></div><h3 id="in-an-effect" tabindex="-1">In an Effect <a class="header-anchor" href="#in-an-effect" aria-label="Permalink to "In an Effect""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> userId</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> user</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> loading</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> id</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> userId</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (id) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`/api/users/\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">id</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, loading).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (data) </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">userId</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Automatically fetches new user</span></span></code></pre></div><h2 id="🚀-advanced-examples" tabindex="-1">🚀 Advanced Examples <a class="header-anchor" href="#🚀-advanced-examples" aria-label="Permalink to "🚀 Advanced Examples""></a></h2><h3 id="user-profile-with-loading-states" tabindex="-1">User Profile with Loading States <a class="header-anchor" href="#user-profile-with-loading-states" aria-label="Permalink to "User Profile with Loading States""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Profile</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> userId</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> user</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> loading</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> error</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetchUser</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">id</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> error</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/api/user'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { id }, loading);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (data) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> error</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Failed to load user'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Fetch when userId changes</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetchUser</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">userId</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="profile"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="user-selector"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button @click=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> userId</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}>User 1</button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button @click=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> userId</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">2</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}>User 2</button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button @click=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> userId</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">3</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}>User 3</button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">loading</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`<div class="spinner">Loading profile...</div>\`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">error</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`<div class="error">\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">error</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</div>\`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">user</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="user-info"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h2>\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">user</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</h2></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>Email: \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">user</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">email</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>Role: \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">user</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">role</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>Joined: \${</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Date</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">user</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">joined</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">toLocaleDateString</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`<p>Select a user</p>\`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> }</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span></code></pre></div><h3 id="todo-list-with-api" tabindex="-1">Todo List with API <a class="header-anchor" href="#todo-list-with-api" aria-label="Permalink to "Todo List with API""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> TodoApp</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> todos</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> loading</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> newTodo</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> filter</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'all'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 'all', 'active', 'completed'</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Load todos</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loadTodos</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/api/todos'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {}, loading);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (data) </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Add todo</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> addTodo</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">newTodo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">trim</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> todo</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/api/todos'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> text: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">newTodo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(),</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> completed: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (todo) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(), todo]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> newTodo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Toggle todo</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> toggleTodo</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">id</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">completed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> updated</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`/api/todos/\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">id</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> completed: </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">completed</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (updated) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">t</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> t.id </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> id </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> updated </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> t</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Delete todo</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> deleteTodo</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">id</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> result</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`/api/todos/\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">id</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}/delete\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {});</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (result) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">filter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">t</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> t.id </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!==</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> id));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Filtered todos</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> filteredTodos</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> currentFilter</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> filter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (currentFilter </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'all'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (currentFilter </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'active'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">filter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">t</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> !</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">t.completed);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">filter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">t</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> t.completed);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Load on mount</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loadTodos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="todo-app"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h1>Todo List</h1></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="add-todo"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <input</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> type="text"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> :value=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">newTodo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @keydown.enter=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">addTodo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> placeholder="Add a new todo..."</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button @click=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">addTodo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}>Add</button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="filters"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> class:active=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> filter</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'all'}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @click=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> filter</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'all'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> All</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> class:active=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> filter</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'active'}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @click=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> filter</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'active'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> Active</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> class:active=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> filter</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'completed'}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @click=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> filter</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'completed'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> Completed</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loading</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="spinner">Loading todos...</div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ) : html\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">ul</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> class</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"todo-list"</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">filteredTodos</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">todo</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <li class="todo-item"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <input</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> type="checkbox"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> :checked=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">todo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">completed</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @change=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> toggleTodo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">todo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">id</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">, </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">todo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">completed</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <span class:completed=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">todo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">completed</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}>\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">todo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">text</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button @click=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> deleteTodo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">todo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">id</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}>🗑️</button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </li></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">ul</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">};</span></span></code></pre></div><h3 id="infinite-scroll-with-pagination" tabindex="-1">Infinite Scroll with Pagination <a class="header-anchor" href="#infinite-scroll-with-pagination" aria-label="Permalink to "Infinite Scroll with Pagination""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> InfiniteScroll</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> posts</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> page</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> loading</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> hasMore</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> error</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loadMore</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">loading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> !</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">hasMore</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/api/posts'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> page: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">page</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(),</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> limit: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }, loading);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (data) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (data.posts.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ===</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> hasMore</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> posts</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">posts</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(), </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">data.posts]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> page</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">p</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> p </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> error</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Failed to load posts'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Intersection Observer for infinite scroll</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> observer</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> IntersectionObserver</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">entries</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (entries[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">].isIntersecting) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loadMore</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { threshold: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0.1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> );</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> sentinel</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> document.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">getElementById</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'sentinel'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (sentinel) observer.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">observe</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(sentinel);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> observer.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">disconnect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Initial load</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loadMore</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="infinite-scroll"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h1>Posts</h1></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="posts"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">posts</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">post</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <article class="post"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h2>\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">post</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">title</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</h2></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">post</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">body</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <small>By \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">post</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">author</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</small></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </article></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div id="sentinel" class="sentinel"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">loading</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`<div class="spinner">Loading more...</div>\`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">error</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`<div class="error">\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">error</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</div>\`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">hasMore</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`<div class="end">No more posts</div>\`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> }</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span></code></pre></div><h3 id="search-with-debounce" tabindex="-1">Search with Debounce <a class="header-anchor" href="#search-with-debounce" aria-label="Permalink to "Search with Debounce""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> SearchComponent</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> query</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> results</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> loading</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> error</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> searchTimeout;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> performSearch</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">searchQuery</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">searchQuery.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">trim</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> results</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/api/search'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> q: searchQuery </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }, loading);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (data) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> results</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> error</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Search failed'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Debounced search</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> searchQuery</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> query</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> clearTimeout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(searchTimeout);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (searchQuery.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> <</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> results</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> searchTimeout </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> setTimeout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> performSearch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(searchQuery);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">300</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> clearTimeout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(searchTimeout);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="search"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="search-box"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <input</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> type="search"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> :value=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">query</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> placeholder="Search..."</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> class="search-input"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loading</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <span class="spinner-small">⌛</span></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ) : ''}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">error</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`<div class="error">\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">error</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</div>\`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">results</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ></span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <ul class="results"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">results</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">item</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <li class="result-item"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h3>\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">item</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">title</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</h3></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">item</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">description</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </li></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </ul></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">query</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> >=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> &&</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> !</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">loading</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`<p class="no-results">No results found</p>\`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> }</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">};</span></span></code></pre></div><h3 id="form-submission" tabindex="-1">Form Submission <a class="header-anchor" href="#form-submission" aria-label="Permalink to "Form Submission""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> ContactForm</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> formData</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> email: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> message: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> submitting</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> submitError</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> submitSuccess</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> handleSubmit</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">e</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> e.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">preventDefault</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> submitError</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> submitSuccess</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> result</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/api/contact'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">formData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(), submitting);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (result) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> submitSuccess</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> formData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({ name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, email: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, message: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> submitError</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Failed to send message. Please try again.'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> updateField</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">field</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> formData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">formData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(),</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [field]: value</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <form class="contact-form" @submit=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">handleSubmit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h2>Contact Us</h2></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="form-group"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <label for="name">Name:</label></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <input</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> type="text"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> id="name"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> :value=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> formData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @input=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> updateField</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'name'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">, </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">target</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">value</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> required</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ?disabled=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">submitting</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="form-group"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <label for="email">Email:</label></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <input</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> type="email"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> id="email"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> :value=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> formData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">email</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @input=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> updateField</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'email'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">, </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">target</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">value</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> required</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ?disabled=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">submitting</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="form-group"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <label for="message">Message:</label></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <textarea</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> id="message"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> :value=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> formData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">message</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @input=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> updateField</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'message'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">, </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">target</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">value</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> required</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> rows="5"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ?disabled=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">submitting</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ></textarea></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">submitting</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`<div class="submitting">Sending...</div>\`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">submitError</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`<div class="error">\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">submitError</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</div>\`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">submitSuccess</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`<div class="success">Message sent successfully!</div>\`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> }</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> type="submit" </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ?disabled=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">submitting</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> Send Message</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </form></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span></code></pre></div><h3 id="real-time-dashboard-with-multiple-endpoints" tabindex="-1">Real-time Dashboard with Multiple Endpoints <a class="header-anchor" href="#real-time-dashboard-with-multiple-endpoints" aria-label="Permalink to "Real-time Dashboard with Multiple Endpoints""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Dashboard</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Multiple data streams</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> metrics</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({});</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> alerts</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> logs</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> loading</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> metrics: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> alerts: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> logs: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> refreshInterval</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">5000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 5 seconds</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetchMetrics</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/api/metrics'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {}, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">loading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().metrics);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (data) </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">metrics</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetchAlerts</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/api/alerts'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {}, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">loading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().alerts);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (data) </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">alerts</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetchLogs</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/api/logs'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> limit: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">50</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">loading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().logs);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (data) </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">logs</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Auto-refresh all data</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetchMetrics</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetchAlerts</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetchLogs</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> interval</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> setInterval</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetchMetrics</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetchAlerts</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">refreshInterval</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> clearInterval</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(interval);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="dashboard"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <header></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h1>System Dashboard</h1></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="refresh-control"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <label></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> Refresh interval:</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <select :value=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">refreshInterval</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">} @change=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> refreshInterval</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">parseInt</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">target</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">value</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">))</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <option value="2000">2 seconds</option></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <option value="5000">5 seconds</option></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <option value="10000">10 seconds</option></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <option value="30000">30 seconds</option></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </select></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </label></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </header></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="dashboard-grid"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <!-- Metrics Panel --></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="panel metrics"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h2>System Metrics</h2></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loading</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">metrics</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="spinner">Loading metrics...</div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ) : html\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> class</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"metrics-grid"</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> class</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"metric"</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">label</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">>CPU</</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">label</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">span</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">>\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">metrics</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">cpu</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ||</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}%</</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">span</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> class</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"metric"</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">label</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">>Memory</</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">label</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">span</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">>\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">metrics</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">memory</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ||</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}%</</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">span</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> class</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"metric"</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">label</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">>Requests</</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">label</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">span</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">>\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">metrics</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">requests</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ||</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}/s</</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">span</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <!-- Alerts Panel --></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="panel alerts"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h2>Active Alerts</h2></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loading</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">alerts</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="spinner">Loading alerts...</div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ) : alerts().length > 0 ? html\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">ul</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">alerts</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">alert</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <li class="alert \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">alert</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">severity</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <strong>\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">alert</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">type</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</strong></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">alert</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">message</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <small>\${</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Date</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">alert</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">timestamp</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">toLocaleTimeString</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</small></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </li></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">ul</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p class="no-data">No active alerts</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <!-- Logs Panel --></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="panel logs"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h2>Recent Logs</h2></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loading</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">logs</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="spinner">Loading logs...</div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ) : html\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">ul</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">logs</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">log</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <li class="log \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">log</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">level</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <span class="timestamp">\${</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Date</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">log</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">timestamp</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">toLocaleTimeString</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <span class="message">\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">log</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">message</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </li></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">ul</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">};</span></span></code></pre></div><h3 id="file-upload" tabindex="-1">File Upload <a class="header-anchor" href="#file-upload" aria-label="Permalink to "File Upload""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> FileUploader</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> files</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> uploading</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> uploadProgress</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({});</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> uploadResults</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([]);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> handleFileSelect</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">e</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> files</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">e.target.files]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> uploadFiles</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">files</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ===</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> uploading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> uploadResults</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> file</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> of</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> files</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> formData</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> FormData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> formData.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">append</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'file'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, file);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Track progress for this file</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> uploadProgress</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">uploadProgress</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(),</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [file.name]: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Custom fetch for FormData</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> response</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/api/upload'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> method: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'POST'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> body: formData</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> result</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> response.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">json</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> uploadResults</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">uploadResults</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(),</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { file: file.name, success: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, result }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">catch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (error) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> uploadResults</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">uploadResults</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(),</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { file: file.name, success: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, error: error.message }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> uploadProgress</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">uploadProgress</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(),</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [file.name]: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">100</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> uploading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="file-uploader"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h2>Upload Files</h2></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <input</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> type="file"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> multiple</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @change=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">handleFileSelect</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ?disabled=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">uploading</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> files</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ></span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="file-list"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h3>Selected Files:</h3></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <ul></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">files</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">file</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <li></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">file</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">} (\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">file</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">size</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> /</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1024</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">toFixed</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">2</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">} KB)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> uploadProgress</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()[</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">file</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <progress value="\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">uploadProgress</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()[</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">file</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">]</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}" max="100"></progress></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ) : ''}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </li></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> </</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">ul</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">button</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#B31D28;--shiki-light-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic;"> @click=\${uploadFiles}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#B31D28;--shiki-light-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic;"> ?disabled=\${uploading}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> uploading</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'Uploading...'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'Upload Files'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">button</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> </</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">div</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \` : ''}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> uploadResults</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ></span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="upload-results"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h3>Upload Results:</h3></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <ul></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">uploadResults</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">result</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <li class="\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">result</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">success</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'success'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'error'}"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">result</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">file</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}: </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">result</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">success</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'Uploaded successfully'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`Failed: \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">result</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">error</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </li></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </ul></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">};</span></span></code></pre></div><h3 id="retry-logic" tabindex="-1">Retry Logic <a class="header-anchor" href="#retry-logic" aria-label="Permalink to "Retry Logic""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Enhanced fetch with retry</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetchWithRetry</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">url</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">data</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">loading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">maxRetries</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> lastError;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> attempt </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">; attempt </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"><=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> maxRetries; attempt</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">++</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (loading) </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">loading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> result</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(url, data);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (result </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> result;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // If we get null but no error, wait and retry</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (attempt </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"><</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> maxRetries) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> Promise</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">resolve</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> setTimeout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(resolve, Math.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">pow</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, attempt) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Exponential backoff</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> );</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">catch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (error) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> lastError </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> error;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">warn</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`Attempt \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">attempt</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">} failed:\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, error);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (attempt </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"><</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> maxRetries) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> Promise</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">resolve</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> setTimeout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(resolve, Math.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">pow</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, attempt) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> );</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">finally</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (attempt </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> maxRetries </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">&&</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> loading) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">error</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'All retry attempts failed:'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, lastError);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Usage</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> loading</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetchWithRetry</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/api/unreliable-endpoint'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {}, loading, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span></code></pre></div><h2 id="🎯-best-practices" tabindex="-1">🎯 Best Practices <a class="header-anchor" href="#🎯-best-practices" aria-label="Permalink to "🎯 Best Practices""></a></h2><h3 id="_1-always-handle-null-responses" tabindex="-1">1. Always Handle Null Responses <a class="header-anchor" href="#_1-always-handle-null-responses" aria-label="Permalink to "1. Always Handle Null Responses""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ❌ Don't assume success</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/api/data'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data.property); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Might throw if data is null</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ✅ Check for null</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/api/data'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (data) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data.property);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">} </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> showError</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Failed to load data'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><h3 id="_2-use-with-effects-for-reactivity" tabindex="-1">2. Use with Effects for Reactivity <a class="header-anchor" href="#_2-use-with-effects-for-reactivity" aria-label="Permalink to "2. Use with Effects for Reactivity""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ❌ Manual fetching</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">button.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">addEventListener</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'click'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/api/data'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> updateUI</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ✅ Reactive fetching</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> trigger</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">trigger</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/api/data'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (data) </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">updateUI</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">trigger</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Triggers fetch</span></span></code></pre></div><h3 id="_3-combine-with-loading-signals" tabindex="-1">3. Combine with Loading Signals <a class="header-anchor" href="#_3-combine-with-loading-signals" aria-label="Permalink to "3. Combine with Loading Signals""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ✅ Always show loading state</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> loading</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> load</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> result</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/api/data'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {}, loading);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (result) </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">data</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(result);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// In template</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loading</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '<Spinner />'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> data</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '<Data />'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '<Empty />'}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span></code></pre></div><h3 id="_4-cancel-in-flight-requests" tabindex="-1">4. Cancel In-flight Requests <a class="header-anchor" href="#_4-cancel-in-flight-requests" aria-label="Permalink to "4. Cancel In-flight Requests""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ✅ Use AbortController with effects</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> controller;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (controller) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> controller.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">abort</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> controller </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> AbortController</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(url, { signal: controller.signal })</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">res</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> res.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">json</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">())</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">controller.signal.aborted) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> updateData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> controller.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">abort</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h2 id="📊-error-handling" tabindex="-1">📊 Error Handling <a class="header-anchor" href="#📊-error-handling" aria-label="Permalink to "📊 Error Handling""></a></h2><h3 id="basic-error-handling" tabindex="-1">Basic Error Handling <a class="header-anchor" href="#basic-error-handling" aria-label="Permalink to "Basic Error Handling""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/api/data'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">data) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Handle error (show message, retry, etc.)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><h3 id="with-error-signal" tabindex="-1">With Error Signal <a class="header-anchor" href="#with-error-signal" aria-label="Permalink to "With Error Signal""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> error</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> loading</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loadData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> error</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> result</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/api/data'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {}, loading);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (result) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> data</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(result);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> error</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Failed to load data'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><hr><blockquote><p><strong>Pro Tip:</strong> Combine <code>$.fetch</code> with <code>$.effect</code> and loading signals for a complete reactive data fetching solution. The loading signal integration makes it trivial to show loading states in your UI.</p></blockquote>`,54)])])}const g=i(l,[["render",k]]);export{d as __pageData,g as default};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{_ as i,o as a,c as n,ae as h}from"./chunks/framework.C8AWLET_.js";const d=JSON.parse('{"title":"Fetch API 🌐","description":"","frontmatter":{},"headers":[],"relativePath":"api/fetch.md","filePath":"api/fetch.md"}'),l={name:"api/fetch.md"};function k(t,s,p,e,E,F){return a(),n("div",null,[...s[0]||(s[0]=[h("",54)])])}const g=i(l,[["render",k]]);export{d as __pageData,g as default};
|
|
||||||
@@ -1,381 +0,0 @@
|
|||||||
import{_ as i,o as a,c as n,ae as h}from"./chunks/framework.C8AWLET_.js";const d=JSON.parse('{"title":"Pages API 📄","description":"","frontmatter":{},"headers":[],"relativePath":"api/pages.md","filePath":"api/pages.md"}'),t={name:"api/pages.md"};function l(k,s,p,e,E,r){return a(),n("div",null,[...s[0]||(s[0]=[h(`<h1 id="pages-api-📄" tabindex="-1">Pages API 📄 <a class="header-anchor" href="#pages-api-📄" aria-label="Permalink to "Pages API 📄""></a></h1><p>Pages in SigPro are special components designed for route-based navigation with <strong>automatic cleanup</strong>. When you navigate away from a page, all signals, effects, and event listeners created within that page are automatically cleaned up - no memory leaks, no manual cleanup needed.</p><h2 id="page-setupfunction" tabindex="-1"><code>$.page(setupFunction)</code> <a class="header-anchor" href="#page-setupfunction" aria-label="Permalink to "\`$.page(setupFunction)\`""></a></h2><p>Creates a page with automatic cleanup of all signals and effects when navigated away.</p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">page</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // All signals and effects created here</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // will be automatically cleaned up on navigation</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> count</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`Count: \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h1>My Page</h1></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>Count: \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">count</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button @click=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> count</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">c</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> c</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> +</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}>+</button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h2 id="📋-api-reference" tabindex="-1">📋 API Reference <a class="header-anchor" href="#📋-api-reference" aria-label="Permalink to "📋 API Reference""></a></h2><table tabindex="0"><thead><tr><th>Parameter</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>setupFunction</code></td><td><code>Function</code></td><td>Function that returns the page content. Receives context object with <code>params</code> and <code>onUnmount</code></td></tr></tbody></table><h3 id="context-object-properties" tabindex="-1">Context Object Properties <a class="header-anchor" href="#context-object-properties" aria-label="Permalink to "Context Object Properties""></a></h3><table tabindex="0"><thead><tr><th>Property</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>params</code></td><td><code>Object</code></td><td>Route parameters passed to the page</td></tr><tr><td><code>onUnmount</code></td><td><code>Function</code></td><td>Register cleanup callbacks (alternative to automatic cleanup)</td></tr></tbody></table><h2 id="🎯-basic-usage" tabindex="-1">🎯 Basic Usage <a class="header-anchor" href="#🎯-basic-usage" aria-label="Permalink to "🎯 Basic Usage""></a></h2><h3 id="simple-page" tabindex="-1">Simple Page <a class="header-anchor" href="#simple-page" aria-label="Permalink to "Simple Page""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// pages/home.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">page</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> title</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Welcome to SigPro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="home-page"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h1>\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">title</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</h1></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>This page will clean itself up when you navigate away.</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h3 id="page-with-route-parameters" tabindex="-1">Page with Route Parameters <a class="header-anchor" href="#page-with-route-parameters" aria-label="Permalink to "Page with Route Parameters""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// pages/user.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">page</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(({ </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Access route parameters</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> userId</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> params.id;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> userData</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> loading</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Auto-cleaned effect</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`/api/users/\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">userId</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, loading)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> userData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loading</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="spinner">Loading...</div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h1>User Profile: \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">userData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()?.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</h1></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>Email: \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">userData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()?.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">email</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h2 id="🧹-automatic-cleanup" tabindex="-1">🧹 Automatic Cleanup <a class="header-anchor" href="#🧹-automatic-cleanup" aria-label="Permalink to "🧹 Automatic Cleanup""></a></h2><p>The magic of <code>$.page</code> is automatic cleanup. Everything created inside the page is tracked and cleaned up:</p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">page</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // ✅ Signals are auto-cleaned</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> count</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> user</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // ✅ Effects are auto-cleaned</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> document.title </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`Count: \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // ✅ Event listeners are auto-cleaned</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> window.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">addEventListener</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'resize'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, handleResize);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // ✅ Intervals and timeouts are auto-cleaned</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> interval</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> setInterval</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> refreshData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">5000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`<div>Page content</div>\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// When navigating away: all signals, effects, listeners, intervals STOP</span></span></code></pre></div><h2 id="📝-manual-cleanup-with-onunmount" tabindex="-1">📝 Manual Cleanup with <code>onUnmount</code> <a class="header-anchor" href="#📝-manual-cleanup-with-onunmount" aria-label="Permalink to "📝 Manual Cleanup with \`onUnmount\`""></a></h2><p>Sometimes you need custom cleanup logic. Use <code>onUnmount</code> for that:</p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">page</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(({ </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">onUnmount</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // WebSocket connection</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> socket</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> WebSocket</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'wss://api.example.com'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> socket.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">onmessage</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">event</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> updateData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">JSON</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">parse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(event.data));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Manual cleanup</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> onUnmount</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> socket.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">close</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'WebSocket closed'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`<div>Real-time updates</div>\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h2 id="🔄-integration-with-router" tabindex="-1">🔄 Integration with Router <a class="header-anchor" href="#🔄-integration-with-router" aria-label="Permalink to "🔄 Integration with Router""></a></h2><p>Pages are designed to work seamlessly with <code>$.router</code>:</p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> HomePage </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './pages/Home.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> UserPage </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './pages/User.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> SettingsPage </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './pages/Settings.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> routes</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: HomePage },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/user/:id'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: UserPage },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/settings'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: SettingsPage },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">];</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Mount router</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">document.body.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">appendChild</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">($.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">router</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(routes));</span></span></code></pre></div><h2 id="💡-practical-examples" tabindex="-1">💡 Practical Examples <a class="header-anchor" href="#💡-practical-examples" aria-label="Permalink to "💡 Practical Examples""></a></h2><h3 id="example-1-data-fetching-page" tabindex="-1">Example 1: Data Fetching Page <a class="header-anchor" href="#example-1-data-fetching-page" aria-label="Permalink to "Example 1: Data Fetching Page""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// pages/posts.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">page</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(({ </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> posts</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> loading</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> error</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/api/posts'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">res</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> res.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">json</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">())</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> posts</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> })</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">catch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">err</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> error</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(err.message);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="posts-page"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h1>Blog Posts</h1></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loading</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="loading">Loading posts...</div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> error</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="error">Error: \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">error</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="posts-grid"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">posts</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">post</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <article class="post-card"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h2>\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">post</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">title</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</h2></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">post</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">excerpt</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <a href="#/post/\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">post</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">id</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}">Read more</a></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </article></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h3 id="example-2-real-time-dashboard" tabindex="-1">Example 2: Real-time Dashboard <a class="header-anchor" href="#example-2-real-time-dashboard" aria-label="Permalink to "Example 2: Real-time Dashboard""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// pages/dashboard.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">page</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(({ </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">onUnmount</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> metrics</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> cpu: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> memory: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> requests: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Auto-refresh data</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> refreshInterval</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> setInterval</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/api/metrics'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (data) </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">metrics</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">5000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Manual cleanup for interval</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> onUnmount</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> clearInterval</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(refreshInterval));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Live clock</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> currentTime</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Date</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> clockInterval</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> setInterval</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> currentTime</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Date</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> onUnmount</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> clearInterval</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(clockInterval));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="dashboard"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h1>System Dashboard</h1></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="time"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> Last updated: \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> currentTime</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">toLocaleTimeString</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="metrics-grid"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="metric-card"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h3>CPU Usage</h3></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p class="metric-value">\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> metrics</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">cpu</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}%</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="metric-card"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h3>Memory Usage</h3></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p class="metric-value">\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> metrics</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">memory</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}%</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="metric-card"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h3>Requests/min</h3></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p class="metric-value">\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> metrics</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">requests</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h3 id="example-3-multi-step-form" tabindex="-1">Example 3: Multi-step Form <a class="header-anchor" href="#example-3-multi-step-form" aria-label="Permalink to "Example 3: Multi-step Form""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// pages/checkout.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">page</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(({ </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">onUnmount</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> step</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> formData</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> email: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> address: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> payment: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Warn user before leaving</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> handleBeforeUnload</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">e</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">step</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"><</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> e.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">preventDefault</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> e.returnValue </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> window.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">addEventListener</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'beforeunload'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, handleBeforeUnload);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> onUnmount</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> window.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">removeEventListener</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'beforeunload'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, handleBeforeUnload);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> nextStep</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> step</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">s</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> Math.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">min</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(s </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> prevStep</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> step</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">s</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> Math.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">max</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(s </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="checkout"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h1>Checkout - Step \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">step</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">} of 3</h1></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> switch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">step</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> case</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">:</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="step"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h2>Email</h2></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <input </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> type="email" </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> :value=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> formData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">email</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @input=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> formData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">({</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">formData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(), email: </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">target</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">value</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">})</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> case</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 2</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">:</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="step"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h2>Address</h2></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <textarea </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> :value=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> formData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">address</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @input=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> formData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">({</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">formData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(), address: </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">target</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">value</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">})</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ></textarea></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> case</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 3</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">:</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="step"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h2>Payment</h2></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <input </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> type="text" </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> placeholder="Card number"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> :value=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> formData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">payment</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @input=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> formData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">({</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">formData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(), payment: </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">target</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">value</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">})</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> }</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="buttons"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> step</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">></span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button @click=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">prevStep</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}>Previous</button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> step</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"><</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button @click=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">nextStep</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}>Next</button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button @click=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">submitOrder</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}>Place Order</button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h3 id="example-4-page-with-tabs" tabindex="-1">Example 4: Page with Tabs <a class="header-anchor" href="#example-4-page-with-tabs" aria-label="Permalink to "Example 4: Page with Tabs""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// pages/profile.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">page</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(({ </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> activeTab</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'overview'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> userData</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Load user data</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`/api/users/\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">params</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">id</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> userData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> tabs</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> overview</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h3>Overview</h3></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>Username: \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">userData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()?.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">username</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>Member since: \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">userData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()?.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">joined</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> posts</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h3>Posts</h3></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">userData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()?.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">posts</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">post</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="post">\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">post</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">title</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> settings</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h3>Settings</h3></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <label></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <input type="checkbox" :checked=\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">userData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()?.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">emailNotifications</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">} /></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> Email notifications</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </label></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="profile-page"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h1>\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> userData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()?.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</h1></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="tabs"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">Object</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">keys</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">tabs</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">tab</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> class:active=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> activeTab</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> tab</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @click=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> activeTab</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">tab</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">tab</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">charAt</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">toUpperCase</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> tab</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">slice</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="tab-content"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> tabs</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">activeTab</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()]()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h2 id="🎯-advanced-patterns" tabindex="-1">🎯 Advanced Patterns <a class="header-anchor" href="#🎯-advanced-patterns" aria-label="Permalink to "🎯 Advanced Patterns""></a></h2><h3 id="page-with-nested-routes" tabindex="-1">Page with Nested Routes <a class="header-anchor" href="#page-with-nested-routes" aria-label="Permalink to "Page with Nested Routes""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// pages/settings/index.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">page</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(({ </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> section</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> params.section </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'general'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> sections</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> general</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'./general.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">m</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> m.default),</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> security</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'./security.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">m</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> m.default),</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> notifications</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'./notifications.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">m</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> m.default)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> currentSection</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> sections[section]().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">comp</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> currentSection</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(comp));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="settings"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <nav></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <a href="#/settings/general">General</a></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <a href="#/settings/security">Security</a></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <a href="#/settings/notifications">Notifications</a></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </nav></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="content"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">currentSection</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h3 id="page-with-authentication" tabindex="-1">Page with Authentication <a class="header-anchor" href="#page-with-authentication" aria-label="Permalink to "Page with Authentication""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// pages/dashboard.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">page</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(({ </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">onUnmount</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> isAuthenticated</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> authCheck</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> token</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> localStorage.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">getItem</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'token'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> isAuthenticated</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">token);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Redirect if not authenticated</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">isAuthenticated</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.router.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">go</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/login'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="dashboard"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h1>Protected Dashboard</h1></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <!-- Protected content --></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h2 id="📊-summary" tabindex="-1">📊 Summary <a class="header-anchor" href="#📊-summary" aria-label="Permalink to "📊 Summary""></a></h2><table tabindex="0"><thead><tr><th>Feature</th><th>Description</th></tr></thead><tbody><tr><td><strong>Automatic Cleanup</strong></td><td>All signals, effects, and resources auto-cleaned on navigation</td></tr><tr><td><strong>Memory Safe</strong></td><td>No memory leaks, even with complex nested effects</td></tr><tr><td><strong>Router Integration</strong></td><td>Designed to work perfectly with <code>$.router</code></td></tr><tr><td><strong>Parameters</strong></td><td>Access route parameters via <code>params</code> object</td></tr><tr><td><strong>Manual Cleanup</strong></td><td><code>onUnmount</code> for custom cleanup needs</td></tr><tr><td><strong>Zero Configuration</strong></td><td>Just wrap your page in <code>$.page()</code> and it works</td></tr></tbody></table><hr><blockquote><p><strong>Pro Tip:</strong> Always wrap route-based views in <code>$.page()</code> to ensure proper cleanup. This prevents memory leaks and ensures your app stays performant even after many navigation changes.</p></blockquote>`,41)])])}const g=i(t,[["render",l]]);export{d as __pageData,g as default};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{_ as i,o as a,c as n,ae as h}from"./chunks/framework.C8AWLET_.js";const d=JSON.parse('{"title":"Pages API 📄","description":"","frontmatter":{},"headers":[],"relativePath":"api/pages.md","filePath":"api/pages.md"}'),t={name:"api/pages.md"};function l(k,s,p,e,E,r){return a(),n("div",null,[...s[0]||(s[0]=[h("",41)])])}const g=i(t,[["render",l]]);export{d as __pageData,g as default};
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
|||||||
import{_ as i,o as a,c as t,ae as n}from"./chunks/framework.C8AWLET_.js";const E=JSON.parse('{"title":"Quick API Reference ⚡","description":"","frontmatter":{},"headers":[],"relativePath":"api/quick.md","filePath":"api/quick.md"}'),h={name:"api/quick.md"};function l(e,s,p,k,d,r){return a(),t("div",null,[...s[0]||(s[0]=[n("",55)])])}const F=i(h,[["render",l]]);export{E as __pageData,F as default};
|
|
||||||
@@ -1,604 +0,0 @@
|
|||||||
import{_ as i,o as a,c as n,ae as h}from"./chunks/framework.C8AWLET_.js";const g=JSON.parse('{"title":"Routing API 🌐","description":"","frontmatter":{},"headers":[],"relativePath":"api/routing.md","filePath":"api/routing.md"}'),t={name:"api/routing.md"};function k(p,s,l,e,E,r){return a(),n("div",null,[...s[0]||(s[0]=[h(`<h1 id="routing-api-🌐" tabindex="-1">Routing API 🌐 <a class="header-anchor" href="#routing-api-🌐" aria-label="Permalink to "Routing API 🌐""></a></h1><p>SigPro includes a simple yet powerful hash-based router designed for Single Page Applications (SPAs). It works everywhere with zero server configuration and integrates seamlessly with <code>$.page</code> for automatic cleanup.</p><h2 id="why-hash-based-routing" tabindex="-1">Why Hash-Based Routing? <a class="header-anchor" href="#why-hash-based-routing" aria-label="Permalink to "Why Hash-Based Routing?""></a></h2><p>Hash routing (<code>#/about</code>) works <strong>everywhere</strong> - no server configuration needed. Perfect for:</p><ul><li>Static sites and SPAs</li><li>GitHub Pages, Netlify, any static hosting</li><li>Local development without a server</li><li>Projects that need to work immediately</li></ul><h2 id="router-routes" tabindex="-1"><code>$.router(routes)</code> <a class="header-anchor" href="#router-routes" aria-label="Permalink to "\`$.router(routes)\`""></a></h2><p>Creates a hash-based router that renders the matching component and handles navigation.</p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> HomePage </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './pages/Home.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> AboutPage </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './pages/About.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> UserPage </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './pages/User.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> routes</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: HomePage },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/about'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: AboutPage },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/user/:id'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: UserPage },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">];</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Mount the router</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">document.body.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">appendChild</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">($.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">router</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(routes));</span></span></code></pre></div><h2 id="📋-api-reference" tabindex="-1">📋 API Reference <a class="header-anchor" href="#📋-api-reference" aria-label="Permalink to "📋 API Reference""></a></h2><h3 id="router-routes-1" tabindex="-1"><code>$.router(routes)</code> <a class="header-anchor" href="#router-routes-1" aria-label="Permalink to "\`$.router(routes)\`""></a></h3><table tabindex="0"><thead><tr><th>Parameter</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>routes</code></td><td><code>Array<Route></code></td><td>Array of route configurations</td></tr></tbody></table><p><strong>Returns:</strong> <code>HTMLDivElement</code> - Container that renders the current page</p><h3 id="router-go-path" tabindex="-1"><code>$.router.go(path)</code> <a class="header-anchor" href="#router-go-path" aria-label="Permalink to "\`$.router.go(path)\`""></a></h3><table tabindex="0"><thead><tr><th>Parameter</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>path</code></td><td><code>string</code></td><td>Route path to navigate to (automatically adds leading slash)</td></tr></tbody></table><h3 id="route-object" tabindex="-1">Route Object <a class="header-anchor" href="#route-object" aria-label="Permalink to "Route Object""></a></h3><table tabindex="0"><thead><tr><th>Property</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>path</code></td><td><code>string</code> or <code>RegExp</code></td><td>Route pattern to match</td></tr><tr><td><code>component</code></td><td><code>Function</code></td><td>Function that returns page content (receives <code>params</code>)</td></tr></tbody></table><h2 id="🎯-route-patterns" tabindex="-1">🎯 Route Patterns <a class="header-anchor" href="#🎯-route-patterns" aria-label="Permalink to "🎯 Route Patterns""></a></h2><h3 id="string-paths-simple-routes" tabindex="-1">String Paths (Simple Routes) <a class="header-anchor" href="#string-paths-simple-routes" aria-label="Permalink to "String Paths (Simple Routes)""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> routes</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Static routes</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: HomePage },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/about'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: AboutPage },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/contact'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: ContactPage },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Routes with parameters</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/user/:id'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: UserPage },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/user/:id/posts'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: UserPostsPage },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/user/:id/posts/:postId'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: PostPage },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/search/:query/page/:num'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: SearchPage },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">];</span></span></code></pre></div><h3 id="regexp-paths-advanced-routing" tabindex="-1">RegExp Paths (Advanced Routing) <a class="header-anchor" href="#regexp-paths-advanced-routing" aria-label="Permalink to "RegExp Paths (Advanced Routing)""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> routes</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Match numeric IDs only</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path:</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">^</span><span style="--shiki-light:#22863A;--shiki-light-font-weight:bold;--shiki-dark:#85E89D;--shiki-dark-font-weight:bold;">\\/</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">users</span><span style="--shiki-light:#22863A;--shiki-light-font-weight:bold;--shiki-dark:#85E89D;--shiki-dark-font-weight:bold;">\\/</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">(?<</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">id</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">></span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">\\d</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">$</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: UserPage },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Match product slugs (letters, numbers, hyphens)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path:</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">^</span><span style="--shiki-light:#22863A;--shiki-light-font-weight:bold;--shiki-dark:#85E89D;--shiki-dark-font-weight:bold;">\\/</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">products</span><span style="--shiki-light:#22863A;--shiki-light-font-weight:bold;--shiki-dark:#85E89D;--shiki-dark-font-weight:bold;">\\/</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">(?<</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">slug</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">></span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">[a-z0-9-]</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">$</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: ProductPage },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Match blog posts by year/month</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path:</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">^</span><span style="--shiki-light:#22863A;--shiki-light-font-weight:bold;--shiki-dark:#85E89D;--shiki-dark-font-weight:bold;">\\/</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">blog</span><span style="--shiki-light:#22863A;--shiki-light-font-weight:bold;--shiki-dark:#85E89D;--shiki-dark-font-weight:bold;">\\/</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">(?<</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">year</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">></span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">\\d</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">{4}</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">)</span><span style="--shiki-light:#22863A;--shiki-light-font-weight:bold;--shiki-dark:#85E89D;--shiki-dark-font-weight:bold;">\\/</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">(?<</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">month</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">></span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">\\d</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">{2}</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">$</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: BlogArchive },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Match optional language prefix</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path:</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">^</span><span style="--shiki-light:#22863A;--shiki-light-font-weight:bold;--shiki-dark:#85E89D;--shiki-dark-font-weight:bold;">\\/</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">(?<</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">lang</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">>en</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">|</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">es</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">|</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">fr)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#22863A;--shiki-light-font-weight:bold;--shiki-dark:#85E89D;--shiki-dark-font-weight:bold;">\\/</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">about</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">$</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: AboutPage },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Match UUID format</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path:</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">^</span><span style="--shiki-light:#22863A;--shiki-light-font-weight:bold;--shiki-dark:#85E89D;--shiki-dark-font-weight:bold;">\\/</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">items</span><span style="--shiki-light:#22863A;--shiki-light-font-weight:bold;--shiki-dark:#85E89D;--shiki-dark-font-weight:bold;">\\/</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">(?<</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">uuid</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">></span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">[0-9a-f]</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">{8}</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">[0-9a-f]</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">{4}</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">[0-9a-f]</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">{4}</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">[0-9a-f]</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">{4}</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">[0-9a-f]</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">{12}</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">$</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> component: ItemPage },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">];</span></span></code></pre></div><h2 id="📦-basic-examples" tabindex="-1">📦 Basic Examples <a class="header-anchor" href="#📦-basic-examples" aria-label="Permalink to "📦 Basic Examples""></a></h2><h3 id="simple-router-setup" tabindex="-1">Simple Router Setup <a class="header-anchor" href="#simple-router-setup" aria-label="Permalink to "Simple Router Setup""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// main.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> Home </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './pages/Home.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> About </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './pages/About.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> Contact </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './pages/Contact.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> routes</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: Home },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/about'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: About },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/contact'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: Contact },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">];</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> router</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">router</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(routes);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Mount to DOM</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">document.body.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">appendChild</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(router);</span></span></code></pre></div><h3 id="page-components-with-parameters" tabindex="-1">Page Components with Parameters <a class="header-anchor" href="#page-components-with-parameters" aria-label="Permalink to "Page Components with Parameters""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// pages/User.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">page</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // /user/42 → params = { id: '42' }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // /user/john/posts/123 → params = { id: 'john', postId: '123' }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> userId</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> params.id;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> userData</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`/api/users/\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">userId</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">res</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> res.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">json</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">())</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> userData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="user-page"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h1>User Profile: \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">userId</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</h1></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> userData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>Name: \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">userData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>Email: \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">userData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">email</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`<p>Loading...</p>\`}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h3 id="navigation" tabindex="-1">Navigation <a class="header-anchor" href="#navigation" aria-label="Permalink to "Navigation""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// In templates</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> NavBar</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <nav></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <a href="#/">Home</a></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <a href="#/about">About</a></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <a href="#/contact">Contact</a></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <a href="#/user/42">Profile</a></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <a href="#/search/js/page/1">Search</a></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <!-- Programmatic navigation --></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button @click=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">router</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">go</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/about'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> Go to About</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button @click=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">router</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">go</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'contact'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> Go to Contact (auto-adds leading slash)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </nav></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span></code></pre></div><h2 id="🚀-advanced-examples" tabindex="-1">🚀 Advanced Examples <a class="header-anchor" href="#🚀-advanced-examples" aria-label="Permalink to "🚀 Advanced Examples""></a></h2><h3 id="complete-application-with-layout" tabindex="-1">Complete Application with Layout <a class="header-anchor" href="#complete-application-with-layout" aria-label="Permalink to "Complete Application with Layout""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// App.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> HomePage </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './pages/Home.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> AboutPage </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './pages/About.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> UserPage </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './pages/User.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> SettingsPage </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './pages/Settings.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> NotFound </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './pages/NotFound.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Layout component with navigation</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Layout</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">content</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="app"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <header class="header"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h1>My SigPro App</h1></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <nav class="nav"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <a href="#/" class:active=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> isActive</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}>Home</a></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <a href="#/about" class:active=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> isActive</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/about'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}>About</a></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <a href="#/user/42" class:active=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> isActive</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/user/42'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}>Profile</a></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <a href="#/settings" class:active=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> isActive</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/settings'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}>Settings</a></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </nav></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </header></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <main class="main"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">content</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </main></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <footer class="footer"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>© 2024 SigPro App</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </footer></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Helper to check active route</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> isActive</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">path</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> current</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> window.location.hash.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">replace</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">^</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">#</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '/'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> current </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> path;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Routes with layout</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> routes</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Layout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">HomePage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(params)) },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/about'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Layout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">AboutPage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(params)) },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/user/:id'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Layout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">UserPage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(params)) },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/settings'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Layout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">SettingsPage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(params)) },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/:path(.*)'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Layout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">NotFound</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(params)) }, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Catch-all</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">];</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Create and mount router</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> router</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">router</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(routes);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">document.body.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">appendChild</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(router);</span></span></code></pre></div><h3 id="nested-routes" tabindex="-1">Nested Routes <a class="header-anchor" href="#nested-routes" aria-label="Permalink to "Nested Routes""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// pages/Settings.js (parent route)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> SettingsGeneral </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './settings/General.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> SettingsSecurity </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './settings/Security.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> SettingsNotifications </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './settings/Notifications.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">page</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> section</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> params.section </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'general'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> sections</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> general: SettingsGeneral,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> security: SettingsSecurity,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> notifications: SettingsNotifications</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> CurrentSection</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> sections[section];</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="settings"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h1>Settings</h1></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="settings-layout"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <nav class="settings-sidebar"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <a href="#/settings/general" class:active=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> section</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'general'}></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> General</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </a></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <a href="#/settings/security" class:active=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> section</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'security'}></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> Security</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </a></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <a href="#/settings/notifications" class:active=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> section</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'notifications'}></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> Notifications</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </a></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </nav></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="settings-content"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">CurrentSection</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">params</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// pages/settings/General.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">page</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h2>General Settings</h2></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <form>...</form></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Main router with nested routes</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> routes</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: HomePage },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/settings/:section?'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: SettingsPage }, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Optional section param</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">];</span></span></code></pre></div><h3 id="protected-routes-authentication" tabindex="-1">Protected Routes (Authentication) <a class="header-anchor" href="#protected-routes-authentication" aria-label="Permalink to "Protected Routes (Authentication)""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// auth.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> isAuthenticated</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> user</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> checkAuth</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> token</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> localStorage.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">getItem</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'token'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (token) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> response</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/api/verify'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (response.ok) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> userData</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> response.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">json</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(userData);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> isAuthenticated</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">catch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (e) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Handle error</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> isAuthenticated</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> requireAuth</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">isAuthenticated</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(params);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Redirect to login</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.router.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">go</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/login'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { isAuthenticated, user };</span></span></code></pre></div><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// pages/Dashboard.js (protected route)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { requireAuth, user } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '../auth.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Dashboard</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">page</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="dashboard"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h1>Welcome, \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> user</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()?.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}!</h1></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>This is your protected dashboard.</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> requireAuth</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(Dashboard);</span></span></code></pre></div><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// main.js with protected routes</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { checkAuth } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './auth.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> HomePage </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './pages/Home.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> LoginPage </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './pages/Login.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> DashboardPage </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './pages/Dashboard.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> AdminPage </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './pages/Admin.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Check auth on startup</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">checkAuth</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> routes</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: HomePage },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/login'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: LoginPage },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/dashboard'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: DashboardPage }, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Protected</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/admin'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: AdminPage }, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Protected</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">];</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">document.body.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">appendChild</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">($.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">router</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(routes));</span></span></code></pre></div><h3 id="route-transitions" tabindex="-1">Route Transitions <a class="header-anchor" href="#route-transitions" aria-label="Permalink to "Route Transitions""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// with-transitions.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> createRouterWithTransitions</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">routes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> transitioning</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> currentView</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> nextView</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> container</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> document.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">createElement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'div'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> container.style.display </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'contents'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> renderWithTransition</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">newView</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">currentView</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> newView) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> transitioning</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> nextView</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(newView);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Fade out</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> container.style.transition </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'opacity 0.2s'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> container.style.opacity </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '0'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> Promise</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">resolve</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> setTimeout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(resolve, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">200</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Update content</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> container.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">replaceChildren</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(newView);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> currentView</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(newView);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Fade in</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> container.style.opacity </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '1'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> Promise</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">resolve</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> setTimeout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(resolve, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">200</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> transitioning</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> container.style.transition </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> router</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">router</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(routes.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">route</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">route,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> view</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> route.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(params);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> renderWithTransition</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(view);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> document.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">createComment</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'router-placeholder'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> })));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> router;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span></code></pre></div><h3 id="breadcrumbs-navigation" tabindex="-1">Breadcrumbs Navigation <a class="header-anchor" href="#breadcrumbs-navigation" aria-label="Permalink to "Breadcrumbs Navigation""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// with-breadcrumbs.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> createBreadcrumbs</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">routes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> breadcrumbs</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> updateBreadcrumbs</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">path</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> parts</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> path.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">split</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">filter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(Boolean);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> crumbs</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [];</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> currentPath </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> parts.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">forEach</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">part</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">index</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> currentPath </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`/\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">part</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Find matching route</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> route</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> routes.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">find</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">r</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (r.path.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">includes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">':'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> pattern</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> r.path.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">replace</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">[</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">^</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">/]</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">g</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, part);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> pattern </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> currentPath;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> r.path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> currentPath;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> crumbs.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">push</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> path: currentPath,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> label: route?.name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> part.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">charAt</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">toUpperCase</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> part.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">slice</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">),</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> isLast: index </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> parts.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> -</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> breadcrumbs</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(crumbs);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Listen to route changes</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> window.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">addEventListener</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'hashchange'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> path</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> window.location.hash.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">replace</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">^</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">#</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '/'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> updateBreadcrumbs</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(path);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Initial update</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> updateBreadcrumbs</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(window.location.hash.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">replace</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">^</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">#</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '/'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> breadcrumbs;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span></code></pre></div><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Usage in layout</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { createBreadcrumbs } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './with-breadcrumbs.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> breadcrumbs</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> createBreadcrumbs</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(routes);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Layout</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">content</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="app"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <nav class="breadcrumbs"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> breadcrumbs</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">crumb</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">crumb</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">isLast</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <a href="#\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">crumb</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">path</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}">\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">crumb</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">label</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</a></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <span class="separator">/</span></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <span class="current">\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">crumb</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">label</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </nav></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <main></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">content</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </main></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span></code></pre></div><h3 id="query-parameters" tabindex="-1">Query Parameters <a class="header-anchor" href="#query-parameters" aria-label="Permalink to "Query Parameters""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// with-query-params.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> getQueryParams</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> hash</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> window.location.hash;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> queryStart</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> hash.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">indexOf</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'?'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (queryStart </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> -</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {};</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> queryString</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> hash.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">slice</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(queryStart </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> params</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> URLSearchParams</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(queryString);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> result</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {};</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">of</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> params) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> result[key] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> value;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> result;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> updateQueryParams</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> hash</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> window.location.hash.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">split</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'?'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">];</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> queryString</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> URLSearchParams</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(params).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">toString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> window.location.hash </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> queryString </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">hash</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}?\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">queryString</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> hash;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span></code></pre></div><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Search page with query params</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { getQueryParams, updateQueryParams } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './with-query-params.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">page</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Get initial query from URL</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> queryParams</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> getQueryParams</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> searchQuery</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(queryParams.q </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> page</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">parseInt</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(queryParams.page) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> results</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Update URL when search changes</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> updateQueryParams</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> q: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">searchQuery</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> undefined</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> page: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">page</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">></span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> page</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> undefined</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Fetch results when search or page changes</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">searchQuery</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`/api/search?q=\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">searchQuery</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}&page=\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">page</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">res</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> res.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">json</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">())</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> results</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="search-page"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h1>Search</h1></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <input</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> type="search"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> :value=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">searchQuery</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> placeholder="Search..."</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @input=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> searchQuery</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">target</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">value</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> page</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Reset to first page on new search</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> }</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="results"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">results</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">item</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="result">\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">item</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">title</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> results</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="pagination"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ?disabled=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> page</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"><=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @click=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> page</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">p</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> p</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> -</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> Previous</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <span>Page \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">page</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ?disabled=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> results</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> <</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 10</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @click=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> page</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">p</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> p</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> +</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> Next</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h3 id="lazy-loading-routes" tabindex="-1">Lazy Loading Routes <a class="header-anchor" href="#lazy-loading-routes" aria-label="Permalink to "Lazy Loading Routes""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// lazy.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> lazy</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">loader</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> component </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">component) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> module</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loader</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> component </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> module</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">.default;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(params);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span></code></pre></div><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// main.js with lazy loading</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { lazy } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './lazy.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> Layout </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './Layout.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> routes</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">lazy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'./pages/Home.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)) },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/about'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">lazy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'./pages/About.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)) },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/dashboard'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">lazy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'./pages/Dashboard.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)) },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/admin'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> component: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">lazy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'./pages/Admin.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)),</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Show loading state</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> loading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`<div class="loading">Loading admin panel...</div>\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">];</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Wrap with layout</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> routesWithLayout</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> routes.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">route</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">route,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Layout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(route.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(params))</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}));</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">document.body.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">appendChild</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">($.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">router</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(routesWithLayout));</span></span></code></pre></div><h3 id="route-guards-middleware" tabindex="-1">Route Guards / Middleware <a class="header-anchor" href="#route-guards-middleware" aria-label="Permalink to "Route Guards / Middleware""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// middleware.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> withGuard</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">guard</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> result</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> guard</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(params);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (result </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(params);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">else</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">typeof</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> result </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'string'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.router.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">go</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(result);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> result; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Custom component (e.g., AccessDenied)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Guards</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> roleGuard</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">requiredRole</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> userRole</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> localStorage.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">getItem</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'userRole'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (userRole </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> requiredRole) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">userRole) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '/login'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> AccessDeniedPage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(params);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> authGuard</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> token</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> localStorage.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">getItem</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'token'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> token </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> true</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '/login'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pendingChangesGuard</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">hasPendingChanges</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">hasPendingChanges</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> ConfirmLeavePage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(params);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span></code></pre></div><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Usage</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { withGuard, authGuard, roleGuard } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './middleware.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> routes</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: HomePage },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/profile'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">withGuard</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(ProfilePage, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">authGuard</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/admin'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> component: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">withGuard</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(AdminPage, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">roleGuard</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'admin'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)) </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">];</span></span></code></pre></div><h2 id="📊-route-matching-priority" tabindex="-1">📊 Route Matching Priority <a class="header-anchor" href="#📊-route-matching-priority" aria-label="Permalink to "📊 Route Matching Priority""></a></h2><p>Routes are matched in the order they are defined. More specific routes should come first:</p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> routes</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // More specific first</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/user/:id/edit'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: EditUserPage },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/user/:id/posts'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: UserPostsPage },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/user/:id'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: UserPage },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Static routes</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/about'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: AboutPage },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/contact'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: ContactPage },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Catch-all last</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/:path(.*)'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: NotFoundPage },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">];</span></span></code></pre></div><h2 id="🎯-complete-example" tabindex="-1">🎯 Complete Example <a class="header-anchor" href="#🎯-complete-example" aria-label="Permalink to "🎯 Complete Example""></a></h2><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// main.js - Complete application</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { lazy } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './utils/lazy.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { withGuard, authGuard } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './utils/middleware.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> Layout </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './components/Layout.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Lazy load pages</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> HomePage</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> lazy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'./pages/Home.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> AboutPage</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> lazy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'./pages/About.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> LoginPage</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> lazy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'./pages/Login.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> DashboardPage</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> lazy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'./pages/Dashboard.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> UserPage</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> lazy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'./pages/User.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> SettingsPage</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> lazy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'./pages/Settings.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> NotFoundPage</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> lazy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'./pages/NotFound.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">));</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Route configuration</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> routes</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: HomePage, name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Home'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/about'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: AboutPage, name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'About'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/login'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: LoginPage, name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Login'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/dashboard'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> component: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">withGuard</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(DashboardPage, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">authGuard</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()),</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Dashboard'</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/user/:id'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> component: UserPage,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'User Profile'</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/settings/:section?'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> component: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">withGuard</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(SettingsPage, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">authGuard</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()),</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Settings'</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/:path(.*)'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: NotFoundPage, name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Not Found'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">];</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Wrap all routes with layout</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> routesWithLayout</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> routes.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">route</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">route,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Layout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(route.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(params))</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}));</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Create and mount router</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> router</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">router</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(routesWithLayout);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">document.body.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">appendChild</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(router);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Navigation helper (available globally)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">window.navigate </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.router.go;</span></span></code></pre></div><h2 id="📊-summary" tabindex="-1">📊 Summary <a class="header-anchor" href="#📊-summary" aria-label="Permalink to "📊 Summary""></a></h2><table tabindex="0"><thead><tr><th>Feature</th><th>Description</th></tr></thead><tbody><tr><td><strong>Hash-based</strong></td><td>Works everywhere, no server config</td></tr><tr><td><strong>Route Parameters</strong></td><td><code>:param</code> syntax for dynamic segments</td></tr><tr><td><strong>RegExp Support</strong></td><td>Advanced pattern matching</td></tr><tr><td><strong>Query Parameters</strong></td><td>Support for <code>?key=value</code> in URLs</td></tr><tr><td><strong>Programmatic Navigation</strong></td><td><code>$.router.go(path)</code></td></tr><tr><td><strong>Auto-cleanup</strong></td><td>Works with <code>$.page</code> for memory management</td></tr><tr><td><strong>Zero Dependencies</strong></td><td>Pure vanilla JavaScript</td></tr><tr><td><strong>Lazy Loading Ready</strong></td><td>Easy code splitting</td></tr></tbody></table><hr><blockquote><p><strong>Pro Tip:</strong> Order matters in route definitions - put more specific routes (with parameters) before static ones, and always include a catch-all route (404) at the end.</p></blockquote>`,60)])])}const F=i(t,[["render",k]]);export{g as __pageData,F as default};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{_ as i,o as a,c as n,ae as h}from"./chunks/framework.C8AWLET_.js";const g=JSON.parse('{"title":"Routing API 🌐","description":"","frontmatter":{},"headers":[],"relativePath":"api/routing.md","filePath":"api/routing.md"}'),t={name:"api/routing.md"};function k(p,s,l,e,E,r){return a(),n("div",null,[...s[0]||(s[0]=[h("",60)])])}const F=i(t,[["render",k]]);export{g as __pageData,F as default};
|
|
||||||
@@ -1,659 +0,0 @@
|
|||||||
import{_ as i,o as a,c as n,ae as h}from"./chunks/framework.C8AWLET_.js";const g=JSON.parse('{"title":"Signals API 📡","description":"","frontmatter":{},"headers":[],"relativePath":"api/signals.md","filePath":"api/signals.md"}'),k={name:"api/signals.md"};function l(t,s,p,e,E,r){return a(),n("div",null,[...s[0]||(s[0]=[h(`<h1 id="signals-api-📡" tabindex="-1">Signals API 📡 <a class="header-anchor" href="#signals-api-📡" aria-label="Permalink to "Signals API 📡""></a></h1><p>Signals are the heart of SigPro's reactivity system. They are reactive values that automatically track dependencies and notify subscribers when they change. This enables fine-grained updates without virtual DOM diffing.</p><h2 id="core-concepts" tabindex="-1">Core Concepts <a class="header-anchor" href="#core-concepts" aria-label="Permalink to "Core Concepts""></a></h2><h3 id="what-is-a-signal" tabindex="-1">What is a Signal? <a class="header-anchor" href="#what-is-a-signal" aria-label="Permalink to "What is a Signal?""></a></h3><p>A signal is a function that holds a value and notifies dependents when that value changes. Signals can be:</p><ul><li><strong>Basic signals</strong> - Hold simple values (numbers, strings, objects)</li><li><strong>Computed signals</strong> - Derive values from other signals</li><li><strong>Persistent signals</strong> - Automatically sync with localStorage/sessionStorage</li></ul><h3 id="how-reactivity-works" tabindex="-1">How Reactivity Works <a class="header-anchor" href="#how-reactivity-works" aria-label="Permalink to "How Reactivity Works""></a></h3><p>SigPro uses automatic dependency tracking:</p><ol><li>When you read a signal inside an effect, the effect becomes a subscriber</li><li>When the signal's value changes, all subscribers are notified</li><li>Updates are batched using microtasks for optimal performance</li><li>Only the exact nodes that depend on changed values are updated</li></ol><h2 id="initialvalue" tabindex="-1"><code>$(initialValue)</code> <a class="header-anchor" href="#initialvalue" aria-label="Permalink to "\`$(initialValue)\`""></a></h2><p>Creates a reactive signal. The behavior changes based on the type of <code>initialValue</code>:</p><ul><li>If <code>initialValue</code> is a <strong>function</strong>, creates a computed signal</li><li>Otherwise, creates a basic signal</li></ul><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Basic signal</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> count</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Computed signal</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> firstName</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'John'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> lastName</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Doe'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> fullName</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">firstName</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">} \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">lastName</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span></code></pre></div><h2 id="📋-api-reference" tabindex="-1">📋 API Reference <a class="header-anchor" href="#📋-api-reference" aria-label="Permalink to "📋 API Reference""></a></h2><h3 id="basic-signals" tabindex="-1">Basic Signals <a class="header-anchor" href="#basic-signals" aria-label="Permalink to "Basic Signals""></a></h3><table tabindex="0"><thead><tr><th>Pattern</th><th>Example</th><th>Description</th></tr></thead><tbody><tr><td>Create</td><td><code>const count = $(0)</code></td><td>Create signal with initial value</td></tr><tr><td>Get</td><td><code>count()</code></td><td>Read current value</td></tr><tr><td>Set</td><td><code>count(5)</code></td><td>Set new value directly</td></tr><tr><td>Update</td><td><code>count(prev => prev + 1)</code></td><td>Update based on previous value</td></tr></tbody></table><h3 id="computed-signals" tabindex="-1">Computed Signals <a class="header-anchor" href="#computed-signals" aria-label="Permalink to "Computed Signals""></a></h3><table tabindex="0"><thead><tr><th>Pattern</th><th>Example</th><th>Description</th></tr></thead><tbody><tr><td>Create</td><td><code>const total = $(() => price() * quantity())</code></td><td>Derive value from other signals</td></tr><tr><td>Get</td><td><code>total()</code></td><td>Read computed value (auto-updates)</td></tr></tbody></table><h3 id="signal-methods" tabindex="-1">Signal Methods <a class="header-anchor" href="#signal-methods" aria-label="Permalink to "Signal Methods""></a></h3><table tabindex="0"><thead><tr><th>Method</th><th>Description</th><th>Example</th></tr></thead><tbody><tr><td><code>signal()</code></td><td>Gets current value</td><td><code>count()</code></td></tr><tr><td><code>signal(newValue)</code></td><td>Sets new value</td><td><code>count(5)</code></td></tr><tr><td><code>signal(prev => new)</code></td><td>Updates using previous value</td><td><code>count(c => c + 1)</code></td></tr></tbody></table><h2 id="🎯-basic-examples" tabindex="-1">🎯 Basic Examples <a class="header-anchor" href="#🎯-basic-examples" aria-label="Permalink to "🎯 Basic Examples""></a></h2><h3 id="counter-signal" tabindex="-1">Counter Signal <a class="header-anchor" href="#counter-signal" aria-label="Permalink to "Counter Signal""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> count</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 0</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 5</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">prev</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> prev </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 6</span></span></code></pre></div><h3 id="object-signal" tabindex="-1">Object Signal <a class="header-anchor" href="#object-signal" aria-label="Permalink to "Object Signal""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> user</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'John'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> age: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">30</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> email: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'john@example.com'</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Read</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().name); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 'John'</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Update (immutable pattern)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(),</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> age: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">31</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Partial update with function</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">prev</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">prev,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> email: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'john.doe@example.com'</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}));</span></span></code></pre></div><h3 id="array-signal" tabindex="-1">Array Signal <a class="header-anchor" href="#array-signal" aria-label="Permalink to "Array Signal""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> todos</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Learn SigPro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Build an app'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Add item</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(), </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Deploy to production'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Remove item</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">filter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">_</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">i</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">));</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Update item</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">todo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">i</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'Master SigPro'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> todo</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">));</span></span></code></pre></div><h2 id="🔄-computed-signals" tabindex="-1">🔄 Computed Signals <a class="header-anchor" href="#🔄-computed-signals" aria-label="Permalink to "🔄 Computed Signals""></a></h2><p>Computed signals automatically update when their dependencies change:</p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> price</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> quantity</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> tax</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0.21</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Computed signals</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> subtotal</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> price</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">*</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> quantity</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> taxAmount</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> subtotal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">*</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> tax</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> total</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> subtotal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> taxAmount</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">total</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 24.2</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">price</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">15</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">total</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 36.3 (automatically updated)</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">quantity</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">total</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 54.45 (automatically updated)</span></span></code></pre></div><h3 id="computed-with-multiple-dependencies" tabindex="-1">Computed with Multiple Dependencies <a class="header-anchor" href="#computed-with-multiple-dependencies" aria-label="Permalink to "Computed with Multiple Dependencies""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> firstName</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'John'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> lastName</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Doe'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> prefix</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Mr.'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> fullName</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Computed signals can contain logic</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">firstName</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">} \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">lastName</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> prefix</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">prefix</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">} \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> name;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fullName</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 'Mr. John Doe'</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">prefix</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fullName</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 'John Doe'</span></span></code></pre></div><h3 id="computed-with-conditional-logic" tabindex="-1">Computed with Conditional Logic <a class="header-anchor" href="#computed-with-conditional-logic" aria-label="Permalink to "Computed with Conditional Logic""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> user</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({ role: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'admin'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, permissions: [] });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> isAdmin</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().role </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'admin'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> hasPermission</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> isAdmin</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().permissions.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">includes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'edit'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">hasPermission</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// true</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({ role: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'user'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, permissions: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'view'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">] });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">hasPermission</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// false (can't edit)</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({ role: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'user'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, permissions: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'view'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'edit'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">] });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">hasPermission</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// true (now has permission)</span></span></code></pre></div><h2 id="🧮-advanced-signal-patterns" tabindex="-1">🧮 Advanced Signal Patterns <a class="header-anchor" href="#🧮-advanced-signal-patterns" aria-label="Permalink to "🧮 Advanced Signal Patterns""></a></h2><h3 id="derived-state-pattern" tabindex="-1">Derived State Pattern <a class="header-anchor" href="#derived-state-pattern" aria-label="Permalink to "Derived State Pattern""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Shopping cart example</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> cart</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { id: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Product 1'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, price: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, quantity: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { id: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Product 2'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, price: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">15</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, quantity: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Derived values</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> itemCount</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> cart</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">reduce</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">sum</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">item</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> sum </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> item.quantity, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> subtotal</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> cart</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">reduce</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">sum</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">item</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> sum </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (item.price </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> item.quantity), </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> tax</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> subtotal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0.21</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> total</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> subtotal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> tax</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Update cart</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">cart</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">cart</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(),</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { id: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Product 3'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, price: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">20</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, quantity: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// All derived values auto-update</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">itemCount</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 4</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">total</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// (10*2 + 15*1 + 20*1) * 1.21 = 78.65</span></span></code></pre></div><h3 id="validation-pattern" tabindex="-1">Validation Pattern <a class="header-anchor" href="#validation-pattern" aria-label="Permalink to "Validation Pattern""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> email</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> password</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> confirmPassword</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Validation signals</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> isEmailValid</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> value</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> email</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">^</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">[</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">^</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">\\s@]</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">@</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">[</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">^</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">\\s@]</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#22863A;--shiki-light-font-weight:bold;--shiki-dark:#85E89D;--shiki-dark-font-weight:bold;">\\.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">[</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">^</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">\\s@]</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+$</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">test</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(value);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> isPasswordValid</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> value</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> password</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> value.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> >=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 8</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> doPasswordsMatch</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> password</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> confirmPassword</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> isFormValid</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> isEmailValid</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">&&</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> isPasswordValid</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">&&</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> doPasswordsMatch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Update form</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">email</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'user@example.com'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">password</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'secure123'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">confirmPassword</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'secure123'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">isFormValid</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// true</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Validation messages</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> emailError</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> email</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">&&</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> !</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">isEmailValid</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'Invalid email format'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span></code></pre></div><h3 id="filtering-and-search-pattern" tabindex="-1">Filtering and Search Pattern <a class="header-anchor" href="#filtering-and-search-pattern" aria-label="Permalink to "Filtering and Search Pattern""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> items</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { id: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Apple'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, category: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'fruit'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { id: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Banana'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, category: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'fruit'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { id: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Carrot'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, category: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'vegetable'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { id: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Date'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, category: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'fruit'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> searchTerm</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> categoryFilter</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'all'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Filtered items (computed)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> filteredItems</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> result </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> items</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Apply search filter</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">searchTerm</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> term</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> searchTerm</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">toLowerCase</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> result </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> result.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">filter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">item</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> item.name.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">toLowerCase</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">includes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(term)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> );</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Apply category filter</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">categoryFilter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'all'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> result </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> result.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">filter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">item</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> item.category </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> categoryFilter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> );</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> result;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Stats</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> fruitCount</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> items</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">filter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">item</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> item.category </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'fruit'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">).</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> vegCount</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> items</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">filter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">item</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> item.category </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'vegetable'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">).</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Update filters</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">searchTerm</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'a'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">filteredItems</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">i</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> i.name)); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ['Apple', 'Banana', 'Carrot', 'Date']</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">categoryFilter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'fruit'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">filteredItems</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">i</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> i.name)); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ['Apple', 'Banana', 'Date']</span></span></code></pre></div><h3 id="pagination-pattern" tabindex="-1">Pagination Pattern <a class="header-anchor" href="#pagination-pattern" aria-label="Permalink to "Pagination Pattern""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> allItems</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">Array</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">keys</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()].</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">i</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`Item \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">i</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> +</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> currentPage</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> itemsPerPage</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Paginated items (computed)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> paginatedItems</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> start</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">currentPage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">*</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> itemsPerPage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> end</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> start </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> itemsPerPage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> allItems</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">slice</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(start, end);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Pagination metadata</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> totalPages</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> Math.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">ceil</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">allItems</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> /</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> itemsPerPage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">())</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> hasNextPage</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> currentPage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"><</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> totalPages</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> hasPrevPage</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> currentPage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">></span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> pageRange</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> current</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> currentPage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> total</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> totalPages</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> delta</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> range </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [];</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> Math.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">max</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, current </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> delta); </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"><=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> Math.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">min</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(total </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, current </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> delta); </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> i</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">++</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> range.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">push</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(i);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (current </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> delta </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">></span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) range </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'...'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">range];</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (current </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> delta </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"><</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> total </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) range </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">range, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'...'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">];</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">range, total];</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Navigation</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> nextPage</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">hasNextPage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">currentPage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">c</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> c </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> prevPage</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">hasPrevPage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">currentPage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">c</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> c </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> goToPage</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">page</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (page </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">>=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> &&</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> page </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"><=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> totalPages</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> currentPage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(page);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span></code></pre></div><h2 id="🔧-advanced-signal-features" tabindex="-1">🔧 Advanced Signal Features <a class="header-anchor" href="#🔧-advanced-signal-features" aria-label="Permalink to "🔧 Advanced Signal Features""></a></h2><h3 id="signal-equality-comparison" tabindex="-1">Signal Equality Comparison <a class="header-anchor" href="#signal-equality-comparison" aria-label="Permalink to "Signal Equality Comparison""></a></h3><p>Signals use <code>Object.is</code> for change detection. Only notify subscribers when values are actually different:</p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> count</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// These won't trigger updates:</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Same value</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">prev</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> prev); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Returns same value</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// These will trigger updates:</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Different value</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">prev</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> prev </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Still 0? Actually returns 0? Wait...</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Be careful with functional updates!</span></span></code></pre></div><h3 id="batch-updates" tabindex="-1">Batch Updates <a class="header-anchor" href="#batch-updates" aria-label="Permalink to "Batch Updates""></a></h3><p>Multiple signal updates are batched into a single microtask:</p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> firstName</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'John'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> lastName</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Doe'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> fullName</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">firstName</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">} \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">lastName</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Full name:'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fullName</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Logs: 'Full name: John Doe'</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Multiple updates in same tick - only one effect run!</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">firstName</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Jane'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">lastName</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Smith'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Only logs once: 'Full name: Jane Smith'</span></span></code></pre></div><h3 id="infinite-loop-protection" tabindex="-1">Infinite Loop Protection <a class="header-anchor" href="#infinite-loop-protection" aria-label="Permalink to "Infinite Loop Protection""></a></h3><p>SigPro includes protection against infinite reactive loops:</p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> a</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> b</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// This would create a loop, but SigPro prevents it</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> a</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">b</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Reading b</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> b</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">a</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Reading a - loop detected!</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Throws: "SigPro: Infinite reactive loop detected."</span></span></code></pre></div><h2 id="📊-performance-characteristics" tabindex="-1">📊 Performance Characteristics <a class="header-anchor" href="#📊-performance-characteristics" aria-label="Permalink to "📊 Performance Characteristics""></a></h2><table tabindex="0"><thead><tr><th>Operation</th><th>Complexity</th><th>Notes</th></tr></thead><tbody><tr><td>Signal read</td><td>O(1)</td><td>Direct value access</td></tr><tr><td>Signal write</td><td>O(n)</td><td>n = number of subscribers</td></tr><tr><td>Computed read</td><td>O(1) or O(m)</td><td>m = computation complexity</td></tr><tr><td>Effect run</td><td>O(s)</td><td>s = number of signal reads</td></tr></tbody></table><h2 id="🎯-best-practices" tabindex="-1">🎯 Best Practices <a class="header-anchor" href="#🎯-best-practices" aria-label="Permalink to "🎯 Best Practices""></a></h2><h3 id="_1-keep-signals-focused" tabindex="-1">1. Keep Signals Focused <a class="header-anchor" href="#_1-keep-signals-focused" aria-label="Permalink to "1. Keep Signals Focused""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ❌ Avoid large monolithic signals</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> state</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> user: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> posts: [],</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> theme: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'light'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> notifications: []</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ✅ Split into focused signals</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> user</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> posts</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> theme</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'light'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> notifications</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([]);</span></span></code></pre></div><h3 id="_2-use-computed-for-derived-state" tabindex="-1">2. Use Computed for Derived State <a class="header-anchor" href="#_2-use-computed-for-derived-state" aria-label="Permalink to "2. Use Computed for Derived State""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ❌ Don't compute in templates/effects</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> total</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> items</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">reduce</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">sum</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">i</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> sum </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> i.price, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> updateUI</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(total);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ✅ Compute with signals</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> total</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> items</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">reduce</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">sum</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">i</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> sum </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> i.price, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> updateUI</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">total</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()));</span></span></code></pre></div><h3 id="_3-immutable-updates" tabindex="-1">3. Immutable Updates <a class="header-anchor" href="#_3-immutable-updates" aria-label="Permalink to "3. Immutable Updates""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ❌ Don't mutate objects/arrays</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> user</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({ name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'John'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'Jane'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Won't trigger updates!</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ✅ Create new objects/arrays</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(), name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Jane'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ❌ Don't mutate arrays</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> todos</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'a'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'b'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">push</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'c'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Won't trigger updates!</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ✅ Create new arrays</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(), </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'c'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]);</span></span></code></pre></div><h3 id="_4-functional-updates-for-dependencies" tabindex="-1">4. Functional Updates for Dependencies <a class="header-anchor" href="#_4-functional-updates-for-dependencies" aria-label="Permalink to "4. Functional Updates for Dependencies""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ❌ Avoid if new value depends on current</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ✅ Use functional update</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">prev</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> prev </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span></code></pre></div><h3 id="_5-clean-up-effects" tabindex="-1">5. Clean Up Effects <a class="header-anchor" href="#_5-clean-up-effects" aria-label="Permalink to "5. Clean Up Effects""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> userId</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Effects auto-clean in pages, but you can stop manually</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> stop</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetchUser</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">userId</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Later, if needed</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">stop</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span></code></pre></div><h2 id="🚀-real-world-examples" tabindex="-1">🚀 Real-World Examples <a class="header-anchor" href="#🚀-real-world-examples" aria-label="Permalink to "🚀 Real-World Examples""></a></h2><h3 id="form-state-management" tabindex="-1">Form State Management <a class="header-anchor" href="#form-state-management" aria-label="Permalink to "Form State Management""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Form state</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> formData</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> username: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> email: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> age: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> newsletter: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Touched fields (for validation UI)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> touched</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> username: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> email: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> age: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Validation rules</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> validations</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> username</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> value.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> >=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> null</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'Username must be at least 3 characters'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> email</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">^</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">[</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">^</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">\\s@]</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">@</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">[</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">^</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">\\s@]</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#22863A;--shiki-light-font-weight:bold;--shiki-dark:#85E89D;--shiki-dark-font-weight:bold;">\\.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">[</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">^</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">\\s@]</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+$</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">test</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(value) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> null</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'Invalid email'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> age</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> !</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">>=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 18</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> &&</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"><=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 120</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> null</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'Age must be 18-120'</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Validation signals</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> errors</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> formData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> result</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {};</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> Object.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">keys</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(validations).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">forEach</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">field</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> error</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> validations[field](data[field]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (error) result[field] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> error;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> result;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> isValid</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> Object.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">keys</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">errors</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()).</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ===</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Field helpers</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fieldProps</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">field</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> value: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">formData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()[field],</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> error: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">touched</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()[field] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> errors</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()[field] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> onChange</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">e</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> value</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> e.target.type </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'checkbox'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> e.target.checked </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> e.target.value;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> formData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">formData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(),</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [field]: value</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> onBlur</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> touched</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">touched</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(),</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [field]: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Form submission</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> submitAttempts</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> isSubmitting</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> handleSubmit</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> submitAttempts</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">s</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> s </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">isValid</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Mark all fields as touched to show errors</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> touched</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(Object.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">keys</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">formData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">reduce</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">acc</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">field</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">acc,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [field]: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }), {}));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> isSubmitting</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> saveForm</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">formData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Reset form on success</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> formData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({ username: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, email: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, age: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, newsletter: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> touched</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({ username: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, email: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, age: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">finally</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> isSubmitting</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span></code></pre></div><h3 id="todo-app-with-filters" tabindex="-1">Todo App with Filters <a class="header-anchor" href="#todo-app-with-filters" aria-label="Permalink to "Todo App with Filters""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// State</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> todos</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { id: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, text: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Learn SigPro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, completed: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { id: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, text: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Build an app'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, completed: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { id: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, text: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Write docs'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, completed: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> filter</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'all'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 'all', 'active', 'completed'</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> newTodoText</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Computed values</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> filteredTodos</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> all</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> switch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">filter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> case</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'active'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">:</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> all.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">filter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">t</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> !</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">t.completed);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> case</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'completed'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">:</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> all.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">filter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">t</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> t.completed);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">:</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> all;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> activeCount</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">filter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">t</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> !</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">t.completed).</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> completedCount</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">filter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">t</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> t.completed).</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> hasCompleted</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> completedCount</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">></span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Actions</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> addTodo</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> text</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> newTodoText</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">trim</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (text) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(),</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> id: Date.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">now</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(),</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> text,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> completed: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> newTodoText</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> toggleTodo</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">id</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">todo</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> todo.id </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> id </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">todo, completed: </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">todo.completed }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> todo</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> deleteTodo</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">id</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">filter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">todo</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> todo.id </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!==</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> id));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> clearCompleted</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">filter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">todo</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> !</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">todo.completed));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> toggleAll</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> allCompleted</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> activeCount</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">todo</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">todo,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> completed: </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">allCompleted</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> })));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span></code></pre></div><h3 id="shopping-cart" tabindex="-1">Shopping Cart <a class="header-anchor" href="#shopping-cart" aria-label="Permalink to "Shopping Cart""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Products catalog</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> products</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { id: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Laptop'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, price: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">999</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, stock: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { id: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Mouse'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, price: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">29</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, stock: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">20</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { id: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Keyboard'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, price: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">79</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, stock: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { id: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Monitor'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, price: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">299</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, stock: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Cart state</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> cart</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({});</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> selectedProduct</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> quantity</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Computed cart values</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> cartItems</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> items</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [];</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> Object.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">entries</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">cart</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">forEach</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(([</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">productId</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">qty</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> product</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> products</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">find</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">p</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> p.id </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> parseInt</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(productId));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (product) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> items.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">push</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">product,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> quantity: qty,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> subtotal: product.price </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> qty</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> items;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> itemCount</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> cartItems</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">reduce</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">sum</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">item</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> sum </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> item.quantity, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> subtotal</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> cartItems</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">reduce</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">sum</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">item</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> sum </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> item.subtotal, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> tax</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> subtotal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0.10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> shipping</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> subtotal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">></span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 100</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> total</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> subtotal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> tax</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> shipping</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> isCartEmpty</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> itemCount</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Cart actions</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> addToCart</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">product</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">qty</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> currentQty</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> cart</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()[product.id] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> newQty</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> currentQty </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> qty;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (newQty </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"><=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> product.stock) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> cart</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">cart</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(),</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [product.id]: newQty</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> updateQuantity</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">productId</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">newQty</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> product</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> products</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">find</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">p</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> p.id </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> productId);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (newQty </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"><=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> product.stock) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (newQty </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"><=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> removeFromCart</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(productId);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> cart</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">cart</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(),</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [productId]: newQty</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> removeFromCart</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">productId</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> newCart</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">cart</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> delete</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> newCart[productId];</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> cart</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(newCart);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> clearCart</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> cart</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Stock management</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> productStock</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">productId</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> product</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> products</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">find</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">p</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> p.id </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> productId);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">product) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> inCart</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> cart</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()[productId] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> product.stock </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> inCart;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> isInStock</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">productId</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">qty</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> productStock</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(productId) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">>=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> qty;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span></code></pre></div><h2 id="📈-debugging-signals" tabindex="-1">📈 Debugging Signals <a class="header-anchor" href="#📈-debugging-signals" aria-label="Permalink to "📈 Debugging Signals""></a></h2><h3 id="logging-signal-changes" tabindex="-1">Logging Signal Changes <a class="header-anchor" href="#logging-signal-changes" aria-label="Permalink to "Logging Signal Changes""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Wrap a signal to log changes</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> withLogging</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">signal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">args</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (args.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> oldValue</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> signal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> result</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> signal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">args);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}:\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, oldValue, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'->'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">signal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> result;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> signal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Usage</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> count</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> withLogging</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">$</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">), </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'count'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Logs: "count: 0 -> 5"</span></span></code></pre></div><h3 id="signal-inspector" tabindex="-1">Signal Inspector <a class="header-anchor" href="#signal-inspector" aria-label="Permalink to "Signal Inspector""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Create an inspectable signal</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> createInspector</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> signals</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> createSignal</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">initialValue</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> signal</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(initialValue);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> signals.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(signal, { name, subscribers: </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Wrap to track subscribers</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> wrapped</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">args</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">args.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> &&</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> activeEffect) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> info</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> signals.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(wrapped);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> info.subscribers.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">add</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(activeEffect);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> signal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">args);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> wrapped;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> getInfo</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> info</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {};</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> signals.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">forEach</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">data</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">signal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> info[data.name] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> subscribers: data.subscribers.size,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> value: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">signal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> info;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { createSignal, getInfo };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Usage</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> inspector</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> createInspector</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> count</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> inspector.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">createSignal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'count'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> doubled</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> inspector.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">createSignal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'doubled'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(inspector.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">getInfo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// { count: { subscribers: 0, value: 0 }, doubled: { subscribers: 0, value: 0 } }</span></span></code></pre></div><h2 id="📊-summary" tabindex="-1">📊 Summary <a class="header-anchor" href="#📊-summary" aria-label="Permalink to "📊 Summary""></a></h2><table tabindex="0"><thead><tr><th>Feature</th><th>Description</th></tr></thead><tbody><tr><td><strong>Basic Signals</strong></td><td>Hold values and notify on change</td></tr><tr><td><strong>Computed Signals</strong></td><td>Auto-updating derived values</td></tr><tr><td><strong>Automatic Tracking</strong></td><td>Dependencies tracked automatically</td></tr><tr><td><strong>Batch Updates</strong></td><td>Multiple updates batched in microtask</td></tr><tr><td><strong>Infinite Loop Protection</strong></td><td>Prevents reactive cycles</td></tr><tr><td><strong>Zero Dependencies</strong></td><td>Pure vanilla JavaScript</td></tr></tbody></table><hr><blockquote><p><strong>Pro Tip:</strong> Signals are the foundation of reactivity in SigPro. Master them, and you've mastered 80% of the library!</p></blockquote>`,82)])])}const y=i(k,[["render",l]]);export{g as __pageData,y as default};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{_ as i,o as a,c as n,ae as h}from"./chunks/framework.C8AWLET_.js";const g=JSON.parse('{"title":"Signals API 📡","description":"","frontmatter":{},"headers":[],"relativePath":"api/signals.md","filePath":"api/signals.md"}'),k={name:"api/signals.md"};function l(t,s,p,e,E,r){return a(),n("div",null,[...s[0]||(s[0]=[h("",82)])])}const y=i(k,[["render",l]]);export{g as __pageData,y as default};
|
|
||||||
@@ -1,796 +0,0 @@
|
|||||||
import{_ as i,o as a,c as n,ae as h}from"./chunks/framework.C8AWLET_.js";const g=JSON.parse('{"title":"Storage API 💾","description":"","frontmatter":{},"headers":[],"relativePath":"api/storage.md","filePath":"api/storage.md"}'),k={name:"api/storage.md"};function l(t,s,p,e,E,r){return a(),n("div",null,[...s[0]||(s[0]=[h(`<h1 id="storage-api-💾" tabindex="-1">Storage API 💾 <a class="header-anchor" href="#storage-api-💾" aria-label="Permalink to "Storage API 💾""></a></h1><p>SigPro provides persistent signals that automatically synchronize with browser storage APIs. This allows you to create reactive state that survives page reloads and browser sessions with zero additional code.</p><h2 id="core-concepts" tabindex="-1">Core Concepts <a class="header-anchor" href="#core-concepts" aria-label="Permalink to "Core Concepts""></a></h2><h3 id="what-is-persistent-storage" tabindex="-1">What is Persistent Storage? <a class="header-anchor" href="#what-is-persistent-storage" aria-label="Permalink to "What is Persistent Storage?""></a></h3><p>Persistent signals are special signals that:</p><ul><li><strong>Initialize from storage</strong> (localStorage/sessionStorage) if a saved value exists</li><li><strong>Auto-save</strong> whenever the signal value changes</li><li><strong>Handle JSON serialization</strong> automatically</li><li><strong>Clean up</strong> when set to <code>null</code> or <code>undefined</code></li></ul><h3 id="storage-types" tabindex="-1">Storage Types <a class="header-anchor" href="#storage-types" aria-label="Permalink to "Storage Types""></a></h3><table tabindex="0"><thead><tr><th>Storage</th><th>Persistence</th><th>Use Case</th></tr></thead><tbody><tr><td><code>localStorage</code></td><td>Forever (until cleared)</td><td>User preferences, themes, saved data</td></tr><tr><td><code>sessionStorage</code></td><td>Until tab/window closes</td><td>Form drafts, temporary state</td></tr></tbody></table><h2 id="storage-key-initialvalue-storage" tabindex="-1"><code>$.storage(key, initialValue, [storage])</code> <a class="header-anchor" href="#storage-key-initialvalue-storage" aria-label="Permalink to "\`$.storage(key, initialValue, [storage])\`""></a></h2><p>Creates a persistent signal that syncs with browser storage.</p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// localStorage (default)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> theme</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">storage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'theme'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'light'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> user</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">storage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'user'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> settings</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">storage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'settings'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { notifications: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// sessionStorage</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> draft</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">storage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'draft'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, sessionStorage);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> formData</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">storage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'form'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {}, sessionStorage);</span></span></code></pre></div><h2 id="📋-api-reference" tabindex="-1">📋 API Reference <a class="header-anchor" href="#📋-api-reference" aria-label="Permalink to "📋 API Reference""></a></h2><h3 id="parameters" tabindex="-1">Parameters <a class="header-anchor" href="#parameters" aria-label="Permalink to "Parameters""></a></h3><table tabindex="0"><thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td><code>key</code></td><td><code>string</code></td><td>required</td><td>Storage key name</td></tr><tr><td><code>initialValue</code></td><td><code>any</code></td><td>required</td><td>Default value if none stored</td></tr><tr><td><code>storage</code></td><td><code>Storage</code></td><td><code>localStorage</code></td><td>Storage type (<code>localStorage</code> or <code>sessionStorage</code>)</td></tr></tbody></table><h3 id="returns" tabindex="-1">Returns <a class="header-anchor" href="#returns" aria-label="Permalink to "Returns""></a></h3><table tabindex="0"><thead><tr><th>Return</th><th>Description</th></tr></thead><tbody><tr><td><code>Function</code></td><td>Signal function (getter/setter) with persistence</td></tr></tbody></table><h2 id="🎯-basic-examples" tabindex="-1">🎯 Basic Examples <a class="header-anchor" href="#🎯-basic-examples" aria-label="Permalink to "🎯 Basic Examples""></a></h2><h3 id="theme-preference" tabindex="-1">Theme Preference <a class="header-anchor" href="#theme-preference" aria-label="Permalink to "Theme Preference""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Persistent theme signal</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> theme</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">storage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'theme'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'light'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Apply theme to document</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> document.body.className </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`theme-\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">theme</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Toggle theme</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> toggleTheme</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> theme</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">t</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> t </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'light'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'dark'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'light'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Template</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>Current theme: \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">theme</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button @click=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">toggleTheme</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> Toggle Theme</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span></code></pre></div><h3 id="user-preferences" tabindex="-1">User Preferences <a class="header-anchor" href="#user-preferences" aria-label="Permalink to "User Preferences""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Complex preferences object</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> preferences</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">storage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'preferences'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> language: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'en'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> fontSize: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'medium'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> notifications: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> compactView: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> sidebarOpen: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Update single preference</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> setPreference</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> preferences</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">preferences</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(),</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [key]: value</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Usage</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">setPreference</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'language'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'es'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">setPreference</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'fontSize'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'large'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">preferences</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().language); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 'es'</span></span></code></pre></div><h3 id="form-draft" tabindex="-1">Form Draft <a class="header-anchor" href="#form-draft" aria-label="Permalink to "Form Draft""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Session-based draft (clears when tab closes)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> draft</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">storage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'contact-form'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> email: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> message: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}, sessionStorage);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Auto-save on input</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> handleInput</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">field</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> draft</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">draft</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(),</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [field]: value</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Clear draft after submit</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> handleSubmit</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> submitForm</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">draft</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> draft</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Clears from storage</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Template</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <form @submit=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">handleSubmit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <input</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> type="text"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> :value=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> draft</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @input=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> handleInput</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'name'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">, </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">target</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">value</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> placeholder="Name"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <input</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> type="email"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> :value=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> draft</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">email</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @input=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> handleInput</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'email'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">, </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">target</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">value</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> placeholder="Email"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <textarea</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> :value=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> draft</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">message</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @input=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> handleInput</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'message'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">, </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">target</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">value</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> placeholder="Message"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ></textarea></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button type="submit">Send</button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </form></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span></code></pre></div><h2 id="🚀-advanced-examples" tabindex="-1">🚀 Advanced Examples <a class="header-anchor" href="#🚀-advanced-examples" aria-label="Permalink to "🚀 Advanced Examples""></a></h2><h3 id="authentication-state" tabindex="-1">Authentication State <a class="header-anchor" href="#authentication-state" aria-label="Permalink to "Authentication State""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Persistent auth state</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> auth</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">storage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'auth'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> token: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> user: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> expiresAt: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Computed helpers</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> isAuthenticated</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">token</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">expiresAt</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> auth</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">token </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> !</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">expiresAt) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Date</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(expiresAt) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">></span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Date</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> user</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> auth</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().user);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Login function</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> login</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">email</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">password</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> response</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/api/login'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> method: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'POST'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> body: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">JSON</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">stringify</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({ email, password })</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (response.ok) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">token</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">expiresIn</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> response.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">json</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> auth</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> token,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> user,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> expiresAt: </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Date</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(Date.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">now</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> expiresIn </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">toISOString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Logout</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> logout</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> auth</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Clear from storage</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Auto-refresh token</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">isAuthenticated</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">expiresAt</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> auth</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> expiresIn</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Date</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(expiresAt) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">-</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Date</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> refreshTime</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> expiresIn </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 60000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 1 minute before expiry</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (refreshTime </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">></span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> timer</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> setTimeout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(refreshToken, refreshTime);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> clearTimeout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(timer);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Navigation guard</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">isAuthenticated</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">&&</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> window.location.pathname </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '/login'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.router.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">go</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/login'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h3 id="multi-tab-synchronization" tabindex="-1">Multi-tab Synchronization <a class="header-anchor" href="#multi-tab-synchronization" aria-label="Permalink to "Multi-tab Synchronization""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Storage key for cross-tab communication</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> STORAGE_KEY</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'app-state'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Create persistent signal</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> appState</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">storage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">STORAGE_KEY</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> count: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> lastUpdated: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Listen for storage events (changes from other tabs)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">window.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">addEventListener</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'storage'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">event</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (event.key </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> STORAGE_KEY</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> &&</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> event.newValue) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Update signal without triggering save loop</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> newValue</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> JSON</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">parse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(event.newValue);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> appState</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(newValue);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">catch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (e) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">error</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Failed to parse storage event:'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, e);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Update state (syncs across all tabs)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> increment</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> appState</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> count: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">appState</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().count </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> lastUpdated: </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Date</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">toISOString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Tab counter</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> tabCount</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Track number of tabs open</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">window.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">addEventListener</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'storage'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">event</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (event.key </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'tab-heartbeat'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> tabCount</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">parseInt</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(event.newValue) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Send heartbeat</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">setInterval</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> localStorage.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">setItem</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'tab-heartbeat'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">tabCount</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span></code></pre></div><h3 id="settings-manager" tabindex="-1">Settings Manager <a class="header-anchor" href="#settings-manager" aria-label="Permalink to "Settings Manager""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Settings schema</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> settingsSchema</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> theme: {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> type: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'select'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> options: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'light'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'dark'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'system'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">],</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> default: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'system'</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> fontSize: {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> type: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'range'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> min: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">12</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> max: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">24</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> default: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">16</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> notifications: {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> type: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'checkbox'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> default: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> language: {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> type: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'select'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> options: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'en'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'es'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'fr'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'de'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">],</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> default: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'en'</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Persistent settings</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> settings</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">storage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'app-settings'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> Object.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">entries</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(settingsSchema).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">reduce</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">acc</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, [</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">config</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">acc,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [key]: config.default</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }), {})</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Settings component</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> SettingsPanel</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="settings-panel"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h2>Settings</h2></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">Object</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">entries</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">settingsSchema</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(([</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">key</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">config</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">]) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> switch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">config</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">type</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> case</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'select'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">:</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="setting"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <label>\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">key</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}:</label></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <select </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> :value=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> settings</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()[</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">key</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">]</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @change=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> updateSetting</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">key</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">, </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">target</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">value</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">config</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">options</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">opt</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <option value="\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">opt</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}" ?selected=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> settings</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()[</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">key</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> opt</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">opt</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </option></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </select></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> case</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'range'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">:</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="setting"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <label>\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">key</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}: \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> settings</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()[</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">key</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">]</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</label></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <input</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> type="range"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> min="\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">config</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">min</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> max="\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">config</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">max</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> :value=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> settings</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()[</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">key</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">]</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @input=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> updateSetting</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">key</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">parseInt</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">target</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">value</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">))</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> case</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'checkbox'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">:</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="setting"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <label></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <input</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> type="checkbox"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> :checked=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> settings</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()[</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">key</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">]</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @change=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> updateSetting</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">key</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">, </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">target</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">checked</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">key</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </label></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> })</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button @click=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">resetDefaults</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}>Reset to Defaults</button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Helper functions</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> updateSetting</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> settings</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">settings</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(),</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [key]: value</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> resetDefaults</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> defaults</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> Object.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">entries</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(settingsSchema).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">reduce</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">acc</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, [</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">config</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">acc,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [key]: config.default</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }), {});</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> settings</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(defaults);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Apply settings globally</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">theme</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">fontSize</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> settings</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Apply theme</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> document.documentElement.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">setAttribute</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'data-theme'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, theme);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Apply font size</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> document.documentElement.style.fontSize </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">fontSize</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}px\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h3 id="shopping-cart-persistence" tabindex="-1">Shopping Cart Persistence <a class="header-anchor" href="#shopping-cart-persistence" aria-label="Permalink to "Shopping Cart Persistence""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Persistent shopping cart</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> cart</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">storage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'shopping-cart'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> items: [],</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> lastUpdated: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Computed values</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> cartItems</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> cart</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().items);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> itemCount</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> cartItems</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">reduce</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">sum</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">item</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> sum </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> item.quantity, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> subtotal</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> cartItems</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">reduce</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">sum</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">item</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> sum </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (item.price </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> item.quantity), </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> tax</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> subtotal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0.1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> total</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> subtotal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> tax</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Cart actions</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> addToCart</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">product</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">quantity</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> existing</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> cartItems</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">findIndex</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">item</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> item.id </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> product.id);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (existing </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">>=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Update quantity</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> newItems</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">cartItems</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()];</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> newItems[existing] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">newItems[existing],</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> quantity: newItems[existing].quantity </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> quantity</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> cart</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> items: newItems,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> lastUpdated: </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Date</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">toISOString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Add new item</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> cart</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> items: [</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">cartItems</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(), { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">product, quantity }],</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> lastUpdated: </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Date</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">toISOString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> removeFromCart</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">productId</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> cart</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> items: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">cartItems</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">filter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">item</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> item.id </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!==</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> productId),</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> lastUpdated: </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Date</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">toISOString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> updateQuantity</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">productId</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">quantity</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (quantity </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"><=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> removeFromCart</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(productId);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> newItems</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> cartItems</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">item</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> item.id </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> productId </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">item, quantity } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> item</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> );</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> cart</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> items: newItems,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> lastUpdated: </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Date</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">toISOString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> clearCart</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> cart</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> items: [],</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> lastUpdated: </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Date</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">toISOString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Cart expiration (7 days)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> CART_EXPIRY_DAYS</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 7</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> lastUpdated</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> cart</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().lastUpdated;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (lastUpdated) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> expiryDate</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Date</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(lastUpdated);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> expiryDate.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">setDate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(expiryDate.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">getDate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> CART_EXPIRY_DAYS</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Date</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> expiryDate) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> clearCart</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Cart display component</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> CartDisplay</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="cart"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h3>Shopping Cart (\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">itemCount</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">} items)</h3></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">cartItems</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">item</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="cart-item"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <span>\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">item</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <span>$\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">item</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">price</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">} x \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">item</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">quantity</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <span>$\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">item</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">price</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> *</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> item</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">quantity</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button @click=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> removeFromCart</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">item</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">id</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}>Remove</button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <input</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> type="number"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> min="1"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> :value=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">item</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">quantity</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @change=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> updateQuantity</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">item</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">id</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">parseInt</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">target</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">value</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">))</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="cart-totals"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>Subtotal: $\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">subtotal</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>Tax (10%): $\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">tax</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p><strong>Total: $\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">total</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</strong></p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> cartItems</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ></span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button @click=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">checkout</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}>Checkout</button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button @click=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">clearCart</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}>Clear Cart</button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>Your cart is empty</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span></code></pre></div><h3 id="recent-searches-history" tabindex="-1">Recent Searches History <a class="header-anchor" href="#recent-searches-history" aria-label="Permalink to "Recent Searches History""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Persistent search history (max 10 items)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> searchHistory</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">storage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'search-history'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, []);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Add search to history</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> addSearch</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">query</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">query.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">trim</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> current</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> searchHistory</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> newHistory</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { query, timestamp: </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Date</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">toISOString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">current.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">filter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">item</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> item.query </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!==</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> query)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ].</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">slice</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Keep only last 10</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> searchHistory</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(newHistory);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Clear history</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> clearHistory</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> searchHistory</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Remove specific item</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> removeFromHistory</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">query</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> searchHistory</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">searchHistory</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">filter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">item</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> item.query </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!==</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> query));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Search component</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> SearchWithHistory</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> searchInput</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> handleSearch</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> query</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> searchInput</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (query) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> addSearch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(query);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> performSearch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(query);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> searchInput</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="search-container"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="search-box"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <input</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> type="search"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> :value=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">searchInput</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @keydown.enter=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">handleSearch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> placeholder="Search..."</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button @click=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">handleSearch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}>Search</button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> searchHistory</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ></span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="search-history"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h4>Recent Searches</h4></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">searchHistory</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">item</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="history-item"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> class="history-query"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @click=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> searchInput</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">item</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">query</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> handleSearch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> }</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 🔍 \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">item</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">query</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <small>\${</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Date</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">item</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">timestamp</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">toLocaleString</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</small></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> class="remove-btn"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @click=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> removeFromHistory</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">item</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">query</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ✕</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button class="clear-btn" @click=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">clearHistory</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> Clear History</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ''}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span></code></pre></div><h3 id="multiple-profiles-accounts" tabindex="-1">Multiple Profiles / Accounts <a class="header-anchor" href="#multiple-profiles-accounts" aria-label="Permalink to "Multiple Profiles / Accounts""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Profile manager</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> profiles</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">storage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'user-profiles'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> current: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'default'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> list: {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> default: {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Default'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> theme: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'light'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> preferences: {}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Switch profile</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> switchProfile</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">profileId</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> profiles</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">profiles</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(),</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> current: profileId</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Create profile</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> createProfile</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> id</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`profile-\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">Date</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">now</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> profiles</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> current: id,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> list: {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">profiles</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().list,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [id]: {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> name,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> theme: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'light'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> preferences: {},</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> createdAt: </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Date</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">toISOString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> id;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Delete profile</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> deleteProfile</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">profileId</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (profileId </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'default'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Can't delete default</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> newList</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">profiles</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().list };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> delete</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> newList[profileId];</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> profiles</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> current: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'default'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> list: newList</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Get current profile data</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> currentProfile</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">current</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">list</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> profiles</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> list[current] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> list.default;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Profile-aware settings</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> profileTheme</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> currentProfile</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().theme);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> profilePreferences</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> currentProfile</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().preferences);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Update profile data</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> updateCurrentProfile</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">updates</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">current</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">list</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> profiles</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> profiles</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> current,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> list: {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">list,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [current]: {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">list[current],</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">updates</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Profile selector component</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> ProfileSelector</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="profile-selector"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <select </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> :value=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> profiles</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">current</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @change=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> switchProfile</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">target</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">value</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">Object</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">entries</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">profiles</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">list</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(([</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">id</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">profile</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">]) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <option value="\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">id</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}">\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">profile</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</option></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </select></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button @click=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> prompt</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Enter profile name:'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> (</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">) </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">createProfile</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> }</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> New Profile</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span></code></pre></div><h2 id="🛡️-error-handling" tabindex="-1">🛡️ Error Handling <a class="header-anchor" href="#🛡️-error-handling" aria-label="Permalink to "🛡️ Error Handling""></a></h2><h3 id="storage-errors" tabindex="-1">Storage Errors <a class="header-anchor" href="#storage-errors" aria-label="Permalink to "Storage Errors""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Safe storage wrapper</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> safeStorage</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">initialValue</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">storage</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> localStorage) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">storage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(key, initialValue, storage);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">catch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (error) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">warn</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`Storage failed for \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">key</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}, using in-memory fallback:\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, error);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(initialValue);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Usage with fallback</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> theme</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> safeStorage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'theme'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'light'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> user</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> safeStorage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'user'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span></code></pre></div><h3 id="quota-exceeded-handling" tabindex="-1">Quota Exceeded Handling <a class="header-anchor" href="#quota-exceeded-handling" aria-label="Permalink to "Quota Exceeded Handling""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> createManagedStorage</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">initialValue</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">maxSize</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1024</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> *</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 100KB limit</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> signal</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">storage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(key, initialValue);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Monitor size</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> size</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> value</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> signal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> json</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> JSON</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">stringify</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(value);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> bytes</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Blob</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([json]).size;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> size</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(bytes);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (bytes </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> maxSize) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">warn</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`Storage for \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">key</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">} exceeded \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">maxSize</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">} bytes\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Could implement cleanup strategy here</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">catch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (e) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">error</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Size check failed:'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, e);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { signal, size };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Usage</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">signal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">largeData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">size</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> createManagedStorage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'app-data'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {}, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">50000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span></code></pre></div><h2 id="📊-storage-limits" tabindex="-1">📊 Storage Limits <a class="header-anchor" href="#📊-storage-limits" aria-label="Permalink to "📊 Storage Limits""></a></h2><table tabindex="0"><thead><tr><th>Storage Type</th><th>Typical Limit</th><th>Notes</th></tr></thead><tbody><tr><td><code>localStorage</code></td><td>5-10MB</td><td>Varies by browser</td></tr><tr><td><code>sessionStorage</code></td><td>5-10MB</td><td>Cleared when tab closes</td></tr><tr><td><code>cookies</code></td><td>4KB</td><td>Not recommended for SigPro</td></tr></tbody></table><h2 id="🎯-best-practices" tabindex="-1">🎯 Best Practices <a class="header-anchor" href="#🎯-best-practices" aria-label="Permalink to "🎯 Best Practices""></a></h2><h3 id="_1-validate-stored-data" tabindex="-1">1. Validate Stored Data <a class="header-anchor" href="#_1-validate-stored-data" aria-label="Permalink to "1. Validate Stored Data""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Schema validation</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> createValidatedStorage</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">schema</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">defaultValue</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">storage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> signal</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">storage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(key, defaultValue, storage);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Wrap to validate on read/write</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> validated</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">args</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (args.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Validate before writing</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> value</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> args[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">];</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">typeof</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'function'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Handle functional updates</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> validated</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">validated</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Basic validation</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> isValid</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> Object.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">keys</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(schema).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">every</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">key</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> validator</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> schema[key];</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> !</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">validator </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> validator</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(value[key]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">isValid) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">warn</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Invalid data, skipping storage write'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> signal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> signal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">args);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> validated;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Usage</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> userSchema</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">v</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> v </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">&&</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> v.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ></span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> age</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">v</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> v </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">>=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 18</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> &&</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> v </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"><=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 120</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> email</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">v</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;">@</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">test</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(v)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> user</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> createValidatedStorage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'user'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, userSchema, {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> age: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">25</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> email: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h3 id="_2-handle-versioning" tabindex="-1">2. Handle Versioning <a class="header-anchor" href="#_2-handle-versioning" aria-label="Permalink to "2. Handle Versioning""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> VERSION</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> createVersionedStorage</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">migrations</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">storage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> raw</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">storage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(key, { version: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">VERSION</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, data: {} }, storage);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> migrate</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">data</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> current </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> data;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> currentVersion</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> current.version </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> v </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> currentVersion; v </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"><</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> VERSION</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">; v</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">++</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> migrator</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> migrations[v];</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (migrator) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> current </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> migrator</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(current);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> current;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Migrate if needed</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> stored</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> raw</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (stored.version </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> VERSION</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> migrated</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> migrate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(stored);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> raw</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(migrated);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> raw;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Usage</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> migrations</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">old</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> version: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> data: {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">old.data,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> preferences: old.preferences </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> })</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> settings</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> createVersionedStorage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'app-settings'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, migrations);</span></span></code></pre></div><h3 id="_3-encrypt-sensitive-data" tabindex="-1">3. Encrypt Sensitive Data <a class="header-anchor" href="#_3-encrypt-sensitive-data" aria-label="Permalink to "3. Encrypt Sensitive Data""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Simple encryption (use proper crypto in production)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> encrypt</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">text</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> btoa</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(text); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Base64 - NOT secure, just example</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> decrypt</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">text</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> atob</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(text);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">catch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> createSecureStorage</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">initialValue</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">storage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> encryptedKey</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`enc_\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">key</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> signal</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">storage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(encryptedKey, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, storage);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> secure</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">args</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (args.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Encrypt before storing</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> value</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> args[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">];</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> encrypted</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> encrypt</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">JSON</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">stringify</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(value));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> signal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(encrypted);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Decrypt when reading</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> encrypted</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> signal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">encrypted) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> initialValue;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> decrypted</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> decrypt</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(encrypted);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> decrypted </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> JSON</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">parse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(decrypted) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> initialValue;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">catch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> initialValue;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> secure;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Usage</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> secureToken</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> createSecureStorage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'auth-token'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">secureToken</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'sensitive-data-123'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Stored encrypted</span></span></code></pre></div><h2 id="📈-performance-considerations" tabindex="-1">📈 Performance Considerations <a class="header-anchor" href="#📈-performance-considerations" aria-label="Permalink to "📈 Performance Considerations""></a></h2><table tabindex="0"><thead><tr><th>Operation</th><th>Cost</th><th>Notes</th></tr></thead><tbody><tr><td>Initial read</td><td>O(1)</td><td>Single storage read</td></tr><tr><td>Write</td><td>O(1) + JSON.stringify</td><td>Auto-save on change</td></tr><tr><td>Large objects</td><td>O(n)</td><td>Stringify/parse overhead</td></tr><tr><td>Multiple keys</td><td>O(k)</td><td>k = number of keys</td></tr></tbody></table><hr><blockquote><p><strong>Pro Tip:</strong> Use <code>sessionStorage</code> for temporary data like form drafts, and <code>localStorage</code> for persistent user preferences. Always validate data when reading from storage to handle corrupted values gracefully.</p></blockquote>`,54)])])}const F=i(k,[["render",l]]);export{g as __pageData,F as default};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{_ as i,o as a,c as n,ae as h}from"./chunks/framework.C8AWLET_.js";const g=JSON.parse('{"title":"Storage API 💾","description":"","frontmatter":{},"headers":[],"relativePath":"api/storage.md","filePath":"api/storage.md"}'),k={name:"api/storage.md"};function l(t,s,p,e,E,r){return a(),n("div",null,[...s[0]||(s[0]=[h("",54)])])}const F=i(k,[["render",l]]);export{g as __pageData,F as default};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{t as p}from"./chunks/theme.yfWKMLQM.js";import{R as s,a0 as i,a1 as u,a2 as c,a3 as l,a4 as f,a5 as d,a6 as m,a7 as h,a8 as g,a9 as A,d as v,u as y,v as C,s as P,aa as b,ab as w,ac as R,ad as E}from"./chunks/framework.C8AWLET_.js";function r(e){if(e.extends){const a=r(e.extends);return{...a,...e,async enhanceApp(t){a.enhanceApp&&await a.enhanceApp(t),e.enhanceApp&&await e.enhanceApp(t)}}}return e}const n=r(p),S=v({name:"VitePressApp",setup(){const{site:e,lang:a,dir:t}=y();return C(()=>{P(()=>{document.documentElement.lang=a.value,document.documentElement.dir=t.value})}),e.value.router.prefetchLinks&&b(),w(),R(),n.setup&&n.setup(),()=>E(n.Layout)}});async function T(){globalThis.__VITEPRESS__=!0;const e=_(),a=D();a.provide(u,e);const t=c(e.route);return a.provide(l,t),a.component("Content",f),a.component("ClientOnly",d),Object.defineProperties(a.config.globalProperties,{$frontmatter:{get(){return t.frontmatter.value}},$params:{get(){return t.page.value.params}}}),n.enhanceApp&&await n.enhanceApp({app:a,router:e,siteData:m}),{app:a,router:e,data:t}}function D(){return A(S)}function _(){let e=s;return h(a=>{let t=g(a),o=null;return t&&(e&&(t=t.replace(/\.js$/,".lean.js")),o=import(t)),s&&(e=!1),o},n.NotFound)}s&&T().then(({app:e,router:a,data:t})=>{a.go().then(()=>{i(a.route,t.site),e.mount("#app")})});export{T as createApp};
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,172 +0,0 @@
|
|||||||
import{_ as i,o as a,c as n,ae as t}from"./chunks/framework.C8AWLET_.js";const E=JSON.parse('{"title":"Getting Started with SigPro 🚀","description":"","frontmatter":{},"headers":[],"relativePath":"guide/getting-started.md","filePath":"guide/getting-started.md"}'),l={name:"guide/getting-started.md"};function h(p,s,e,k,r,d){return a(),n("div",null,[...s[0]||(s[0]=[t(`<h1 id="getting-started-with-sigpro-🚀" tabindex="-1">Getting Started with SigPro 🚀 <a class="header-anchor" href="#getting-started-with-sigpro-🚀" aria-label="Permalink to "Getting Started with SigPro 🚀""></a></h1><p>Welcome to SigPro! This guide will help you get up and running with the library in minutes. SigPro is a minimalist reactive library that embraces the web platform - no compilation, no virtual DOM, just pure JavaScript and intelligent reactivity.</p><h2 id="📦-installation" tabindex="-1">📦 Installation <a class="header-anchor" href="#📦-installation" aria-label="Permalink to "📦 Installation""></a></h2><p>Choose your preferred installation method:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"># Using npm</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">npm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> install</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> sigpro</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"># Using bun</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">bun</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> add</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> sigpro</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"># Or simply copy sigpro.js to your project</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"># (yes, it's that simple!)</span></span></code></pre></div><h2 id="🎯-core-imports" tabindex="-1">🎯 Core Imports <a class="header-anchor" href="#🎯-core-imports" aria-label="Permalink to "🎯 Core Imports""></a></h2><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span></code></pre></div><p>That's it! Just two imports to unlock the entire reactive system:</p><ul><li><strong><code>$</code></strong> - Creates reactive signals (the heart of reactivity)</li><li><strong><code>html</code></strong> - Template literal tag for reactive DOM rendering</li></ul><h2 id="🧠-understanding-the-basics" tabindex="-1">🧠 Understanding the Basics <a class="header-anchor" href="#🧠-understanding-the-basics" aria-label="Permalink to "🧠 Understanding the Basics""></a></h2><h3 id="signals-the-reactive-heart" tabindex="-1">Signals - The Reactive Heart <a class="header-anchor" href="#signals-the-reactive-heart" aria-label="Permalink to "Signals - The Reactive Heart""></a></h3><p>Signals are reactive values that automatically track dependencies and update when changed:</p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Create a signal with initial value</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> count</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Read value (with auto dependency tracking)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 0</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Set new value</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Update using previous value</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">prev</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> prev </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 6</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Create computed signals (auto-updating)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> firstName</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'John'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> lastName</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Doe'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> fullName</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">firstName</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">} \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">lastName</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">fullName</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// "John Doe"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">firstName</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Jane'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// fullName() now returns "Jane Doe"</span></span></code></pre></div><h3 id="effects-automatic-reactions" tabindex="-1">Effects - Automatic Reactions <a class="header-anchor" href="#effects-automatic-reactions" aria-label="Permalink to "Effects - Automatic Reactions""></a></h3><p>Effects automatically run and re-run when their signal dependencies change:</p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> count</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`Count is: \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Logs: "Count is: 0"</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Logs: "Count is: 1"</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Effects can return cleanup functions</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> id</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> timer</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> setInterval</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`Polling with count: \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">id</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Cleanup runs before next effect execution</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> clearInterval</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(timer);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h3 id="rendering-with-html" tabindex="-1">Rendering with <code>html</code> <a class="header-anchor" href="#rendering-with-html" aria-label="Permalink to "Rendering with \`html\`""></a></h3><p>The <code>html</code> tag creates reactive DOM fragments:</p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> count</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> isActive</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> fragment</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="counter"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h2>Count: \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">count</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</h2></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <!-- Event binding --></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button @click=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> count</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">c</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> c</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> +</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> Increment</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <!-- Boolean attributes --></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button ?disabled=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> !</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">isActive</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> Submit</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">document.body.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">appendChild</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(fragment);</span></span></code></pre></div><h2 id="🎨-your-first-reactive-app" tabindex="-1">🎨 Your First Reactive App <a class="header-anchor" href="#🎨-your-first-reactive-app" aria-label="Permalink to "🎨 Your First Reactive App""></a></h2><p>Let's build a simple todo app to see SigPro in action:</p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Create a simple todo app</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> TodoApp</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Reactive state</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> todos</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Learn SigPro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'Build something awesome'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> newTodo</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Computed value</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> todoCount</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Add todo function</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> addTodo</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">newTodo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">trim</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(), </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">newTodo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> newTodo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Remove todo function</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> removeTodo</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">index</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">filter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">_</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">i</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!==</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> index));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Return reactive template</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div style="max-width: 400px; margin: 2rem auto; font-family: system-ui;"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h1>📝 Todo App</h1></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <!-- Input form --></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div style="display: flex; gap: 8px; margin-bottom: 16px;"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <input </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> type="text" </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> :value=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">newTodo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> placeholder="Add a new todo..."</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> style="flex: 1; padding: 8px; border: 1px solid #ddd; border-radius: 4px;"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @keydown.enter=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">addTodo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @click=\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">addTodo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> style="padding: 8px 16px; background: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer;"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> Add</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <!-- Todo count --></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>Total todos: \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">todoCount</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <!-- Todo list --></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <ul style="list-style: none; padding: 0;"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> todos</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">((</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">todo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">index</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <li style="display: flex; justify-content: space-between; align-items: center; padding: 8px; margin: 4px 0; background: #f5f5f5; border-radius: 4px;"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <span>\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">todo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @click=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> removeTodo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">index</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> style="padding: 4px 8px; background: #ff4444; color: white; border: none; border-radius: 4px; cursor: pointer;"</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ✕</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </li></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </ul></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Mount the app</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">document.body.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">appendChild</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">TodoApp</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span></code></pre></div><h2 id="🎯-key-concepts" tabindex="-1">🎯 Key Concepts <a class="header-anchor" href="#🎯-key-concepts" aria-label="Permalink to "🎯 Key Concepts""></a></h2><h3 id="_1-signal-patterns" tabindex="-1">1. <strong>Signal Patterns</strong> <a class="header-anchor" href="#_1-signal-patterns" aria-label="Permalink to "1. **Signal Patterns**""></a></h3><table tabindex="0"><thead><tr><th>Pattern</th><th>Example</th><th>Use Case</th></tr></thead><tbody><tr><td>Basic signal</td><td><code>const count = $(0)</code></td><td>Simple values</td></tr><tr><td>Computed</td><td><code>$( () => first() + last() )</code></td><td>Derived values</td></tr><tr><td>Signal update</td><td><code>count(5)</code></td><td>Direct set</td></tr><tr><td>Functional update</td><td><code>count(prev => prev + 1)</code></td><td>Based on previous</td></tr></tbody></table><h3 id="_2-effect-patterns" tabindex="-1">2. <strong>Effect Patterns</strong> <a class="header-anchor" href="#_2-effect-patterns" aria-label="Permalink to "2. **Effect Patterns**""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Basic effect</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">count</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()));</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Effect with cleanup</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> timer</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> setInterval</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {}, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> clearInterval</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(timer);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Stopping an effect</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> stop</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {});</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">stop</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Effect won't run again</span></span></code></pre></div><h3 id="_3-html-directives" tabindex="-1">3. <strong>HTML Directives</strong> <a class="header-anchor" href="#_3-html-directives" aria-label="Permalink to "3. **HTML Directives**""></a></h3><table tabindex="0"><thead><tr><th>Directive</th><th>Example</th><th>Description</th></tr></thead><tbody><tr><td><code>@event</code></td><td><code>@click=\${handler}</code></td><td>Event listeners</td></tr><tr><td><code>:property</code></td><td><code>:value=\${signal}</code></td><td>Two-way binding</td></tr><tr><td><code>?attribute</code></td><td><code>?disabled=\${signal}</code></td><td>Boolean attributes</td></tr><tr><td><code>.property</code></td><td><code>.scrollTop=\${value}</code></td><td>DOM properties</td></tr></tbody></table><h2 id="💡-pro-tips-for-beginners" tabindex="-1">💡 Pro Tips for Beginners <a class="header-anchor" href="#💡-pro-tips-for-beginners" aria-label="Permalink to "💡 Pro Tips for Beginners""></a></h2><h3 id="_1-start-simple" tabindex="-1">1. <strong>Start Simple</strong> <a class="header-anchor" href="#_1-start-simple" aria-label="Permalink to "1. **Start Simple**""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Begin with basic signals</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'World'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`<h1>Hello, \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}!</h1>\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span></code></pre></div><h3 id="_2-use-computed-signals-for-derived-state" tabindex="-1">2. <strong>Use Computed Signals for Derived State</strong> <a class="header-anchor" href="#_2-use-computed-signals-for-derived-state" aria-label="Permalink to "2. **Use Computed Signals for Derived State**""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ❌ Don't compute in template</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`<p>Total: \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">items</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> *</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> price</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</p>\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ✅ Compute with signals</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> total</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> items</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> *</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> price</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`<p>Total: \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">total</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</p>\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span></code></pre></div><h3 id="_3-leverage-effects-for-side-effects" tabindex="-1">3. <strong>Leverage Effects for Side Effects</strong> <a class="header-anchor" href="#_3-leverage-effects-for-side-effects" aria-label="Permalink to "3. **Leverage Effects for Side Effects**""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Auto-save to localStorage</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> localStorage.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">setItem</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'draft'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">JSON</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">stringify</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">draft</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h2 id="🔧-vs-code-setup" tabindex="-1">🔧 VS Code Setup <a class="header-anchor" href="#🔧-vs-code-setup" aria-label="Permalink to "🔧 VS Code Setup""></a></h2><p>For the best development experience, install these VS Code extensions:</p><ul><li><strong>lit-html</strong> - Adds syntax highlighting for <code>html</code> tagged templates</li><li><strong>Prettier</strong> - Automatically formats your template literals</li></ul><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// With lit-html extension, you get full syntax highlighting!</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div style="color: #ff4444; background: linear-gradient(45deg, blue, green)"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h1>Beautiful highlighted template</h1></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span></code></pre></div><h2 id="📁-project-structure" tabindex="-1">📁 Project Structure <a class="header-anchor" href="#📁-project-structure" aria-label="Permalink to "📁 Project Structure""></a></h2><p>Here's a recommended structure for larger apps:</p><div class="language- vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>my-sigpro-app/</span></span>
|
|
||||||
<span class="line"><span>├── index.html</span></span>
|
|
||||||
<span class="line"><span>├── main.js</span></span>
|
|
||||||
<span class="line"><span>├── components/</span></span>
|
|
||||||
<span class="line"><span>│ ├── Button.js</span></span>
|
|
||||||
<span class="line"><span>│ ├── TodoList.js</span></span>
|
|
||||||
<span class="line"><span>│ └── TodoItem.js</span></span>
|
|
||||||
<span class="line"><span>├── pages/</span></span>
|
|
||||||
<span class="line"><span>│ ├── HomePage.js</span></span>
|
|
||||||
<span class="line"><span>│ └── AboutPage.js</span></span>
|
|
||||||
<span class="line"><span>└── utils/</span></span>
|
|
||||||
<span class="line"><span> └── helpers.js</span></span></code></pre></div><p>Example <code>main.js</code>:</p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> HomePage </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './pages/HomePage.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Mount your app</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">document.body.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">appendChild</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">HomePage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span></code></pre></div><h2 id="🎓-summary" tabindex="-1">🎓 Summary <a class="header-anchor" href="#🎓-summary" aria-label="Permalink to "🎓 Summary""></a></h2><p>You've learned:</p><ul><li>✅ How to install SigPro</li><li>✅ Core concepts: signals, effects, and reactive rendering</li><li>✅ Built a complete todo app</li><li>✅ Key patterns and best practices</li><li>✅ How to structure larger applications</li></ul><p><strong>Remember:</strong> SigPro embraces the web platform. You're writing vanilla JavaScript with superpowers—no compilation, no lock-in, just clean, maintainable code that will work for years to come.</p><blockquote><p>"Stop fighting the platform. Start building with it."</p></blockquote><p>Happy coding! 🎉</p>`,51)])])}const o=i(l,[["render",h]]);export{E as __pageData,o as default};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{_ as i,o as a,c as n,ae as t}from"./chunks/framework.C8AWLET_.js";const E=JSON.parse('{"title":"Getting Started with SigPro 🚀","description":"","frontmatter":{},"headers":[],"relativePath":"guide/getting-started.md","filePath":"guide/getting-started.md"}'),l={name:"guide/getting-started.md"};function h(p,s,e,k,r,d){return a(),n("div",null,[...s[0]||(s[0]=[t("",51)])])}const o=i(l,[["render",h]]);export{E as __pageData,o as default};
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
import{_ as s,o as a,c as i,ae as e}from"./chunks/framework.C8AWLET_.js";const c=JSON.parse('{"title":"Why SigPro? ❓","description":"","frontmatter":{},"headers":[],"relativePath":"guide/why.md","filePath":"guide/why.md"}'),n={name:"guide/why.md"};function r(l,t,o,h,d,p){return a(),i("div",null,[...t[0]||(t[0]=[e(`<h1 id="why-sigpro-❓" tabindex="-1">Why SigPro? ❓ <a class="header-anchor" href="#why-sigpro-❓" aria-label="Permalink to "Why SigPro? ❓""></a></h1><p>After years of building applications with React, Vue, and Svelte—investing countless hours mastering their unique mental models, build tools, and update cycles—I kept circling back to the same realization: no matter how sophisticated the framework, it all eventually compiles down to HTML, CSS, and vanilla JavaScript. The web platform has evolved tremendously, yet many libraries continue to reinvent the wheel, creating parallel universes with their own rules, their own syntaxes, and their own steep learning curves.</p><p><strong>SigPro is my answer to a simple question:</strong> Why fight the platform when we can embrace it?</p><h2 id="🌐-the-web-platform-is-finally-ready" tabindex="-1">🌐 The Web Platform Is Finally Ready <a class="header-anchor" href="#🌐-the-web-platform-is-finally-ready" aria-label="Permalink to "🌐 The Web Platform Is Finally Ready""></a></h2><p>Modern browsers now offer powerful primitives that make true reactivity possible without virtual DOM diffing, without compilers, and without lock-in:</p><table tabindex="0"><thead><tr><th>Browser Primitive</th><th>What It Enables</th></tr></thead><tbody><tr><td><strong>Custom Elements</strong></td><td>Create reusable components with native browser APIs</td></tr><tr><td><strong>Shadow DOM</strong></td><td>Encapsulate styles and markup without preprocessors</td></tr><tr><td><strong>CSS Custom Properties</strong></td><td>Dynamic theming without CSS-in-JS</td></tr><tr><td><strong>Microtask Queues</strong></td><td>Efficient update batching without complex scheduling</td></tr></tbody></table><h2 id="🎯-the-sigpro-philosophy" tabindex="-1">🎯 The SigPro Philosophy <a class="header-anchor" href="#🎯-the-sigpro-philosophy" aria-label="Permalink to "🎯 The SigPro Philosophy""></a></h2><p>SigPro strips away the complexity, delivering a reactive programming model that feels familiar but stays remarkably close to vanilla JS:</p><ul><li><strong>No JSX transformations</strong> - Just template literals</li><li><strong>No template compilers</strong> - The browser parses your HTML</li><li><strong>No proprietary syntax to learn</strong> - Just functions and signals</li><li><strong>No build step required</strong> - Works directly in the browser</li></ul><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Just vanilla JavaScript with signals</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> count</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">document.body.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">appendChild</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>Count: \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">count</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button @click=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> count</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">c</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> c</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> +</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> Increment</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span></code></pre></div><h2 id="📊-comparative" tabindex="-1">📊 Comparative <a class="header-anchor" href="#📊-comparative" aria-label="Permalink to "📊 Comparative""></a></h2><table tabindex="0"><thead><tr><th>Metric</th><th>SigPro</th><th>Solid</th><th>Svelte</th><th>Vue</th><th>React</th></tr></thead><tbody><tr><td><strong>Bundle Size</strong> (gzip)</td><td>🥇 <strong>5.2KB</strong></td><td>🥈 15KB</td><td>🥉 16.6KB</td><td>20.4KB</td><td>43.9KB</td></tr><tr><td><strong>Time to Interactive</strong></td><td>🥇 <strong>0.8s</strong></td><td>🥈 1.3s</td><td>🥉 1.4s</td><td>1.6s</td><td>2.3s</td></tr><tr><td><strong>Initial Render</strong> (ms)</td><td>🥇 <strong>124ms</strong></td><td>🥈 198ms</td><td>🥉 287ms</td><td>298ms</td><td>452ms</td></tr><tr><td><strong>Update Performance</strong> (ms)</td><td>🥇 <strong>4ms</strong></td><td>🥈 5ms</td><td>🥈 5ms</td><td>🥉 7ms</td><td>18ms</td></tr><tr><td><strong>Dependencies</strong></td><td>🥇 <strong>0</strong></td><td>🥇 <strong>0</strong></td><td>🥇 <strong>0</strong></td><td>🥈 2</td><td>🥉 5</td></tr><tr><td><strong>Compilation Required</strong></td><td>🥇 <strong>No</strong></td><td>🥇 <strong>No</strong></td><td>🥈 Yes</td><td>🥇 <strong>No</strong></td><td>🥇 <strong>No</strong></td></tr><tr><td><strong>Browser Native</strong></td><td>🥇 <strong>Yes</strong></td><td>🥈 Partial</td><td>🥉 Partial</td><td>🥉 Partial</td><td>No</td></tr><tr><td><strong>Framework Lock-in</strong></td><td>🥇 <strong>None</strong></td><td>🥈 Medium</td><td>🥉 High</td><td>🥈 Medium</td><td>🥉 High</td></tr><tr><td><strong>Longevity</strong> (standards-based)</td><td>🥇 <strong>10+ years</strong></td><td>🥈 5 years</td><td>🥉 3 years</td><td>🥈 5 years</td><td>🥈 5 years</td></tr></tbody></table><h2 id="🔑-core-principles" tabindex="-1">🔑 Core Principles <a class="header-anchor" href="#🔑-core-principles" aria-label="Permalink to "🔑 Core Principles""></a></h2><p>SigPro is built on four fundamental principles:</p><h3 id="📡-true-reactivity" tabindex="-1">📡 <strong>True Reactivity</strong> <a class="header-anchor" href="#📡-true-reactivity" aria-label="Permalink to "📡 **True Reactivity**""></a></h3><p>Automatic dependency tracking with no manual subscriptions. When a signal changes, only the exact DOM nodes that depend on it update—surgically, efficiently, instantly.</p><h3 id="⚡-surgical-updates" tabindex="-1">⚡ <strong>Surgical Updates</strong> <a class="header-anchor" href="#⚡-surgical-updates" aria-label="Permalink to "⚡ **Surgical Updates**""></a></h3><p>No virtual DOM diffing. No tree reconciliation. Just direct DOM updates where and when needed. The result is predictable performance that scales with your content, not your component count.</p><h3 id="🧩-web-standards" tabindex="-1">🧩 <strong>Web Standards</strong> <a class="header-anchor" href="#🧩-web-standards" aria-label="Permalink to "🧩 **Web Standards**""></a></h3><p>Built on Custom Elements, not a custom rendering engine. Your components are real web components that work in any framework—or none at all.</p><h3 id="🔬-predictable" tabindex="-1">🔬 <strong>Predictable</strong> <a class="header-anchor" href="#🔬-predictable" aria-label="Permalink to "🔬 **Predictable**""></a></h3><p>No magic, just signals and effects. What you see is what you get. The debugging experience is straightforward because there's no framework layer between your code and the browser.</p><h2 id="🎨-the-development-experience" tabindex="-1">🎨 The Development Experience <a class="header-anchor" href="#🎨-the-development-experience" aria-label="Permalink to "🎨 The Development Experience""></a></h2><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// With VS Code + lit-html extension, you get:</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ✅ Syntax highlighting</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ✅ Color previews</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ✅ Auto-formatting</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ✅ IntelliSense</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div style="color: #ff4444; background: linear-gradient(45deg, blue, green)"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h1>Beautiful highlighted template</h1></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span></code></pre></div><h2 id="⏱️-built-for-the-long-term" tabindex="-1">⏱️ Built for the Long Term <a class="header-anchor" href="#⏱️-built-for-the-long-term" aria-label="Permalink to "⏱️ Built for the Long Term""></a></h2><p>What emerged is a library that proves we've reached a turning point: the web is finally mature enough that we don't need to abstract it anymore. We can build reactive, component-based applications using virtually pure JavaScript, leveraging the platform's latest advances instead of working against them.</p><p><strong>The result isn't just smaller bundles or faster rendering—it's code that will still run 10 years from now, in any browser, without maintenance.</strong></p><h2 id="📈-the-verdict" tabindex="-1">📈 The Verdict <a class="header-anchor" href="#📈-the-verdict" aria-label="Permalink to "📈 The Verdict""></a></h2><p>While other frameworks build parallel universes with proprietary syntax and compilation steps, SigPro embraces the web platform. SigPro isn't just another framework—it's a return to fundamentals, showing that the dream of simple, powerful reactivity is now achievable with the tools browsers give us out of the box.</p><blockquote><p><em>"Stop fighting the platform. Start building with it."</em></p></blockquote><h2 id="🚀-ready-to-start" tabindex="-1">🚀 Ready to Start? <a class="header-anchor" href="#🚀-ready-to-start" aria-label="Permalink to "🚀 Ready to Start?""></a></h2><p><a href="/sigpro/guide/getting-started.html">Get Started with SigPro</a> • <a href="https://github.com/natxocc/sigpro" target="_blank" rel="noreferrer">View on GitHub</a> • <a href="https://www.npmjs.com/package/sigpro" target="_blank" rel="noreferrer">npm Package</a></p>`,32)])])}const k=s(n,[["render",r]]);export{c as __pageData,k as default};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{_ as s,o as a,c as i,ae as e}from"./chunks/framework.C8AWLET_.js";const c=JSON.parse('{"title":"Why SigPro? ❓","description":"","frontmatter":{},"headers":[],"relativePath":"guide/why.md","filePath":"guide/why.md"}'),n={name:"guide/why.md"};function r(l,t,o,h,d,p){return a(),i("div",null,[...t[0]||(t[0]=[e("",32)])])}const k=s(n,[["render",r]]);export{c as __pageData,k as default};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{_ as e,o as i,c as a,ae as n}from"./chunks/framework.C8AWLET_.js";const g=JSON.parse(`{"title":"","description":"","frontmatter":{"layout":"home","hero":{"name":"SigPro","text":"Reactivity for the Web Platform","tagline":"A minimalist reactive library for building web interfaces with signals, effects, and native web components. No compilation, no virtual DOM, just pure JavaScript and intelligent reactivity.","image":{"src":"/logo.svg","alt":"SigPro"},"actions":[{"theme":"brand","text":"Get Started","link":"/guide/getting-started"}]},"features":[{"title":"⚡ 3KB gzipped","details":"Minimal footprint with maximum impact. No heavy dependencies, just pure reactivity."},{"title":"🎯 Native Web Components","details":"Built on Custom Elements and Shadow DOM. Leverage the platform, don't fight it."},{"title":"🔄 Signal-based Reactivity","details":"Fine-grained updates without virtual DOM diffing. Just intelligent, automatic reactivity."}]},"headers":[],"relativePath":"index.md","filePath":"index.md"}`),s={name:"index.md"};function o(r,t,l,d,p,c){return i(),a("div",null,[...t[0]||(t[0]=[n('<div class="custom-container"><p class="npm-stats"><img src="https://badge.fury.io/js/sigpro.svg" alt="npm version"><img src="https://img.shields.io/bundlephobia/minzip/sigpro" alt="bundle size"><img src="https://img.shields.io/npm/l/sigpro" alt="license"></p></div><div class="verdict-quote"><p><strong>"Stop fighting the platform. Start building with it."</strong></p></div>',2)])])}const u=e(s,[["render",o]]);export{g as __pageData,u as default};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{_ as e,o as i,c as a,ae as n}from"./chunks/framework.C8AWLET_.js";const g=JSON.parse(`{"title":"","description":"","frontmatter":{"layout":"home","hero":{"name":"SigPro","text":"Reactivity for the Web Platform","tagline":"A minimalist reactive library for building web interfaces with signals, effects, and native web components. No compilation, no virtual DOM, just pure JavaScript and intelligent reactivity.","image":{"src":"/logo.svg","alt":"SigPro"},"actions":[{"theme":"brand","text":"Get Started","link":"/guide/getting-started"}]},"features":[{"title":"⚡ 3KB gzipped","details":"Minimal footprint with maximum impact. No heavy dependencies, just pure reactivity."},{"title":"🎯 Native Web Components","details":"Built on Custom Elements and Shadow DOM. Leverage the platform, don't fight it."},{"title":"🔄 Signal-based Reactivity","details":"Fine-grained updates without virtual DOM diffing. Just intelligent, automatic reactivity."}]},"headers":[],"relativePath":"index.md","filePath":"index.md"}`),s={name:"index.md"};function o(r,t,l,d,p,c){return i(),a("div",null,[...t[0]||(t[0]=[n("",2)])])}const u=e(s,[["render",o]]);export{g as __pageData,u as default};
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
@@ -1,225 +0,0 @@
|
|||||||
import{_ as i,o as a,c as n,ae as t}from"./chunks/framework.C8AWLET_.js";const E=JSON.parse('{"title":"Vite Plugin: Automatic File-based Routing 🚦","description":"","frontmatter":{},"headers":[],"relativePath":"vite/plugin.md","filePath":"vite/plugin.md"}'),l={name:"vite/plugin.md"};function p(h,s,e,k,r,d){return a(),n("div",null,[...s[0]||(s[0]=[t(`<h1 id="vite-plugin-automatic-file-based-routing-🚦" tabindex="-1">Vite Plugin: Automatic File-based Routing 🚦 <a class="header-anchor" href="#vite-plugin-automatic-file-based-routing-🚦" aria-label="Permalink to "Vite Plugin: Automatic File-based Routing 🚦""></a></h1><p>SigPro provides an optional Vite plugin that automatically generates routes based on your file structure. No configuration needed - just create pages and they're instantly available with the correct paths.</p><h2 id="why-use-this-plugin" tabindex="-1">Why Use This Plugin? <a class="header-anchor" href="#why-use-this-plugin" aria-label="Permalink to "Why Use This Plugin?""></a></h2><p>While SigPro's router works perfectly with manually defined routes, this plugin:</p><ul><li><strong>Eliminates boilerplate</strong> - No need to write route configurations</li><li><strong>Enforces conventions</strong> - Consistent URL structure across your app</li><li><strong>Supports dynamic routes</strong> - Use <code>[param]</code> syntax for parameters</li><li><strong>Automatic code-splitting</strong> - Each page becomes a separate chunk</li><li><strong>Type-safe</strong> (with JSDoc) - Routes follow your file structure</li></ul><h2 id="installation" tabindex="-1">Installation <a class="header-anchor" href="#installation" aria-label="Permalink to "Installation""></a></h2><p>The plugin is included with SigPro, but you need to add it to your Vite config:</p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// vite.config.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { defineConfig } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'vite'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { sigproRouter } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> defineConfig</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> plugins: [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">sigproRouter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()]</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h2 id="how-it-works" tabindex="-1">How It Works <a class="header-anchor" href="#how-it-works" aria-label="Permalink to "How It Works""></a></h2><p>The plugin scans your <code>src/pages</code> directory and automatically generates routes based on the file structure:</p><div class="language- vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>src/pages/</span></span>
|
|
||||||
<span class="line"><span>├── index.js → '/'</span></span>
|
|
||||||
<span class="line"><span>├── about.js → '/about'</span></span>
|
|
||||||
<span class="line"><span>├── blog/</span></span>
|
|
||||||
<span class="line"><span>│ ├── index.js → '/blog'</span></span>
|
|
||||||
<span class="line"><span>│ └── [slug].js → '/blog/:slug'</span></span>
|
|
||||||
<span class="line"><span>└── users/</span></span>
|
|
||||||
<span class="line"><span> ├── [id].js → '/users/:id'</span></span>
|
|
||||||
<span class="line"><span> └── [id]/edit.js → '/users/:id/edit'</span></span></code></pre></div><h2 id="usage" tabindex="-1">Usage <a class="header-anchor" href="#usage" aria-label="Permalink to "Usage""></a></h2><h3 id="_1-enable-the-plugin" tabindex="-1">1. Enable the Plugin <a class="header-anchor" href="#_1-enable-the-plugin" aria-label="Permalink to "1. Enable the Plugin""></a></h3><p>Add the plugin to your Vite config as shown above.</p><h3 id="_2-import-the-generated-routes" tabindex="-1">2. Import the Generated Routes <a class="header-anchor" href="#_2-import-the-generated-routes" aria-label="Permalink to "2. Import the Generated Routes""></a></h3><p>Once you have the generated routes, using them with the router is straightforward:</p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// main.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { routes } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'virtual:sigpro-routes'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Simple usage</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> router</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">router</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(routes);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">document.body.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">appendChild</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(router);</span></span></code></pre></div><p>Or directly in your template:</p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// app.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { routes } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'virtual:sigpro-routes'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> App</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="app"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <header></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h1>My Application</h1></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </header></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <main class="p-4 flex flex-col gap-4 mx-auto w-full"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="p-4 bg-base-100 rounded-box shadow-sm"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">router</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">routes</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </main></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">document.body.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">appendChild</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">App</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span></code></pre></div><p>This approach keeps your template clean and lets the router handle all the page rendering automatically.</p><h3 id="_3-create-pages" tabindex="-1">3. Create Pages <a class="header-anchor" href="#_3-create-pages" aria-label="Permalink to "3. Create Pages""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// src/pages/index.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h1>Home Page</h1></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <a href="#/about">About</a></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span></code></pre></div><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// src/pages/users/[id].js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> userId</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> params.id;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h1>User Profile: \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">userId</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</h1></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <a href="#/users/\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">userId</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}/edit">Edit</a></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span></code></pre></div><h2 id="📋-file-to-route-mapping" tabindex="-1">📋 File-to-Route Mapping <a class="header-anchor" href="#📋-file-to-route-mapping" aria-label="Permalink to "📋 File-to-Route Mapping""></a></h2><h3 id="static-routes" tabindex="-1">Static Routes <a class="header-anchor" href="#static-routes" aria-label="Permalink to "Static Routes""></a></h3><table tabindex="0"><thead><tr><th>File Path</th><th>Generated Route</th></tr></thead><tbody><tr><td><code>src/pages/index.js</code></td><td><code>/</code></td></tr><tr><td><code>src/pages/about.js</code></td><td><code>/about</code></td></tr><tr><td><code>src/pages/contact/index.js</code></td><td><code>/contact</code></td></tr><tr><td><code>src/pages/blog/post.js</code></td><td><code>/blog/post</code></td></tr></tbody></table><h3 id="dynamic-routes" tabindex="-1">Dynamic Routes <a class="header-anchor" href="#dynamic-routes" aria-label="Permalink to "Dynamic Routes""></a></h3><table tabindex="0"><thead><tr><th>File Path</th><th>Generated Route</th><th>Example URL</th></tr></thead><tbody><tr><td><code>src/pages/users/[id].js</code></td><td><code>/users/:id</code></td><td><code>/users/42</code></td></tr><tr><td><code>src/pages/blog/[slug].js</code></td><td><code>/blog/:slug</code></td><td><code>/blog/hello-world</code></td></tr><tr><td><code>src/pages/users/[id]/posts/[pid].js</code></td><td><code>/users/:id/posts/:pid</code></td><td><code>/users/42/posts/123</code></td></tr></tbody></table><h3 id="nested-routes" tabindex="-1">Nested Routes <a class="header-anchor" href="#nested-routes" aria-label="Permalink to "Nested Routes""></a></h3><table tabindex="0"><thead><tr><th>File Path</th><th>Generated Route</th><th>Notes</th></tr></thead><tbody><tr><td><code>src/pages/settings/index.js</code></td><td><code>/settings</code></td><td>Index page</td></tr><tr><td><code>src/pages/settings/profile.js</code></td><td><code>/settings/profile</code></td><td>Sub-page</td></tr><tr><td><code>src/pages/settings/security.js</code></td><td><code>/settings/security</code></td><td>Sub-page</td></tr><tr><td><code>src/pages/settings/[section].js</code></td><td><code>/settings/:section</code></td><td>Dynamic section</td></tr></tbody></table><h2 id="🎯-advanced-examples" tabindex="-1">🎯 Advanced Examples <a class="header-anchor" href="#🎯-advanced-examples" aria-label="Permalink to "🎯 Advanced Examples""></a></h2><h3 id="blog-with-posts" tabindex="-1">Blog with Posts <a class="header-anchor" href="#blog-with-posts" aria-label="Permalink to "Blog with Posts""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// src/pages/blog/index.js - Lists all posts</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> posts</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([]);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/api/posts'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">res</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> res.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">json</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">())</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> posts</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h1>Blog</h1></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">posts</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">post</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <article></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h2><a href="#/blog/\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">post</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">slug</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}">\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">post</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">title</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</a></h2></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">post</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">excerpt</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </article></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span></code></pre></div><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// src/pages/blog/[slug].js - Single post</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> post</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> slug</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> params.slug;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`/api/posts/\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">slug</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">res</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> res.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">json</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">())</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> post</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <a href="#/blog">← Back to blog</a></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> post</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <article></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h1>\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">post</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">title</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</h1></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div>\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">post</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">content</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </article></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`<div>Loading...</div>\`}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span></code></pre></div><h3 id="dashboard-with-nested-sections" tabindex="-1">Dashboard with Nested Sections <a class="header-anchor" href="#dashboard-with-nested-sections" aria-label="Permalink to "Dashboard with Nested Sections""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// src/pages/dashboard/index.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="dashboard"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <nav></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <a href="#/dashboard">Overview</a></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <a href="#/dashboard/analytics">Analytics</a></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <a href="#/dashboard/settings">Settings</a></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </nav></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <main></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h1>Dashboard Overview</h1></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <!-- Overview content --></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </main></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span></code></pre></div><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// src/pages/dashboard/analytics.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="dashboard"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <nav></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <a href="#/dashboard">Overview</a></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <a href="#/dashboard/analytics">Analytics</a></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <a href="#/dashboard/settings">Settings</a></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </nav></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <main></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h1>Analytics</h1></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <!-- Analytics content --></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </main></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span></code></pre></div><h3 id="e-commerce-product-routes" tabindex="-1">E-commerce Product Routes <a class="header-anchor" href="#e-commerce-product-routes" aria-label="Permalink to "E-commerce Product Routes""></a></h3><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// src/pages/products/[category]/[id].js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">category</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">id</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> params;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> product</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`/api/products/\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">category</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}/\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">id</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">res</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> res.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">json</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">())</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> product</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(data));</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="product-page"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <nav class="breadcrumbs"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <a href="#/products">Products</a> &gt;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <a href="#/products/\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">category</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}">\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">category</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</a> &gt;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <span>\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">id</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </nav></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> product</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <div class="product"></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <h1>\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">product</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</h1></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p class="price">$\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">product</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">price</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <p>\${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">product</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">().</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">description</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</p></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> <button @click=\${</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> addToCart</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">product</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">())</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> Add to Cart</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </button></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`<div>Loading...</div>\`}</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> </div></span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span></code></pre></div><h2 id="🔧-configuration-options" tabindex="-1">🔧 Configuration Options <a class="header-anchor" href="#🔧-configuration-options" aria-label="Permalink to "🔧 Configuration Options""></a></h2><p>The plugin accepts an optional configuration object:</p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// vite.config.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { defineConfig } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'vite'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { sigproRouter } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro/vite'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> defineConfig</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> plugins: [</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> sigproRouter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> pagesDir: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'src/pages'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Default: 'src/pages'</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> extensions: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'.jsx'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">], </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Default: ['.js', '.jsx']</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> exclude: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'**/_*'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'**/components/**'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">] </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Glob patterns to exclude</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> })</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ]</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h3 id="options" tabindex="-1">Options <a class="header-anchor" href="#options" aria-label="Permalink to "Options""></a></h3><table tabindex="0"><thead><tr><th>Option</th><th>Type</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td><code>pagesDir</code></td><td><code>string</code></td><td><code>'src/pages'</code></td><td>Directory containing your pages</td></tr><tr><td><code>extensions</code></td><td><code>string[]</code></td><td><code>['.js', '.jsx']</code></td><td>File extensions to include</td></tr><tr><td><code>exclude</code></td><td><code>string[]</code></td><td><code>[]</code></td><td>Glob patterns to exclude</td></tr></tbody></table><h2 id="🎯-route-priority" tabindex="-1">🎯 Route Priority <a class="header-anchor" href="#🎯-route-priority" aria-label="Permalink to "🎯 Route Priority""></a></h2><p>The plugin automatically sorts routes to ensure correct matching:</p><ol><li><strong>Static routes</strong> take precedence over dynamic ones</li><li><strong>More specific routes</strong> (deeper paths) come first</li><li><strong>Alphabetical order</strong> for routes at the same level</li></ol><p>Example sorting:</p><div class="language- vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>/users/new (static, specific)</span></span>
|
|
||||||
<span class="line"><span>/users/[id]/edit (dynamic, deeper)</span></span>
|
|
||||||
<span class="line"><span>/users/[id] (dynamic, shallower)</span></span>
|
|
||||||
<span class="line"><span>/users/profile (static, shallower)</span></span></code></pre></div><h2 id="📦-output-example" tabindex="-1">📦 Output Example <a class="header-anchor" href="#📦-output-example" aria-label="Permalink to "📦 Output Example""></a></h2><p>When you import <code>virtual:sigpro-routes</code>, you get:</p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Generated module</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> Page_0 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '/src/pages/index.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> Page_1 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '/src/pages/about.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> Page_2 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '/src/pages/blog/index.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> Page_3 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '/src/pages/blog/[slug].js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> Page_4 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '/src/pages/users/[id].js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> Page_5 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '/src/pages/users/[id]/edit.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> routes</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: Page_0 },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/about'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: Page_1 },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/blog'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: Page_2 },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/blog/:slug'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: Page_3 },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/users/:id'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: Page_4 },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/users/:id/edit'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, component: Page_5 },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">];</span></span></code></pre></div><h2 id="🚀-performance-benefits" tabindex="-1">🚀 Performance Benefits <a class="header-anchor" href="#🚀-performance-benefits" aria-label="Permalink to "🚀 Performance Benefits""></a></h2><ul><li><strong>Automatic code splitting</strong> - Each page becomes a separate chunk</li><li><strong>Lazy loading ready</strong> - Import pages dynamically</li><li><strong>Tree shaking</strong> - Only used routes are included</li></ul><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// With dynamic imports (automatic with Vite)</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> routes</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'./pages/index.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { path: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/about'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'./pages/about.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) },</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // ...</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">];</span></span></code></pre></div><h2 id="💡-pro-tips" tabindex="-1">💡 Pro Tips <a class="header-anchor" href="#💡-pro-tips" aria-label="Permalink to "💡 Pro Tips""></a></h2><h3 id="_1-group-related-pages" tabindex="-1">1. Group Related Pages <a class="header-anchor" href="#_1-group-related-pages" aria-label="Permalink to "1. Group Related Pages""></a></h3><div class="language- vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>src/pages/</span></span>
|
|
||||||
<span class="line"><span>├── dashboard/</span></span>
|
|
||||||
<span class="line"><span>│ ├── index.js</span></span>
|
|
||||||
<span class="line"><span>│ ├── analytics.js</span></span>
|
|
||||||
<span class="line"><span>│ └── settings.js</span></span>
|
|
||||||
<span class="line"><span>└── dashboard.js # ❌ Don't mix with folder</span></span></code></pre></div><h3 id="_2-use-index-files-for-clean-urls" tabindex="-1">2. Use Index Files for Clean URLs <a class="header-anchor" href="#_2-use-index-files-for-clean-urls" aria-label="Permalink to "2. Use Index Files for Clean URLs""></a></h3><div class="language- vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>✅ Good:</span></span>
|
|
||||||
<span class="line"><span>pages/blog/index.js → /blog</span></span>
|
|
||||||
<span class="line"><span>pages/blog/post.js → /blog/post</span></span>
|
|
||||||
<span class="line"><span></span></span>
|
|
||||||
<span class="line"><span>❌ Avoid:</span></span>
|
|
||||||
<span class="line"><span>pages/blog.js → /blog (conflicts with folder)</span></span></code></pre></div><h3 id="_3-private-components" tabindex="-1">3. Private Components <a class="header-anchor" href="#_3-private-components" aria-label="Permalink to "3. Private Components""></a></h3><p>Prefix with underscore to exclude from routing:</p><div class="language- vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>src/pages/</span></span>
|
|
||||||
<span class="line"><span>├── index.js</span></span>
|
|
||||||
<span class="line"><span>├── about.js</span></span>
|
|
||||||
<span class="line"><span>└── _components/ # ❌ Not scanned</span></span>
|
|
||||||
<span class="line"><span> └── Header.js</span></span></code></pre></div><h3 id="_4-layout-components" tabindex="-1">4. Layout Components <a class="header-anchor" href="#_4-layout-components" aria-label="Permalink to "4. Layout Components""></a></h3><p>Create a layout wrapper in your main entry:</p><div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// main.js</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { $, html } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'sigpro'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { routes } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'virtual:sigpro-routes'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Wrap all routes with layout</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> routesWithLayout</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> routes.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">route</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ({</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">route,</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Layout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(route.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(params))</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}));</span></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> router</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> $.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">router</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(routesWithLayout);</span></span>
|
|
||||||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">document.body.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">appendChild</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(router);</span></span></code></pre></div><hr><blockquote><p><strong>Note:</strong> This plugin is completely optional. You can always define routes manually if you prefer. The plugin just saves you from writing boilerplate route configurations.</p></blockquote><blockquote><p><strong>Pro Tip:</strong> The plugin works great with hot module replacement (HMR) - add a new page and it's instantly available in your dev server without restarting!</p></blockquote>`,69)])])}const o=i(l,[["render",p]]);export{E as __pageData,o as default};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{_ as i,o as a,c as n,ae as t}from"./chunks/framework.C8AWLET_.js";const E=JSON.parse('{"title":"Vite Plugin: Automatic File-based Routing 🚦","description":"","frontmatter":{},"headers":[],"relativePath":"vite/plugin.md","filePath":"vite/plugin.md"}'),l={name:"vite/plugin.md"};function p(h,s,e,k,r,d){return a(),n("div",null,[...s[0]||(s[0]=[t("",69)])])}const o=i(l,[["render",p]]);export{E as __pageData,o as default};
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
|||||||
{"api_components.md":"BlFwj17l","api_effects.md":"Br_yStBS","api_fetch.md":"DQLBJSoq","api_pages.md":"BP19nHXw","api_quick.md":"BDS3ttnt","api_routing.md":"7SNAZXtp","api_signals.md":"CrW68-BA","api_storage.md":"COEWBXHk","guide_getting-started.md":"BeQpK3vd","guide_why.md":"DXchYMN-","index.md":"uvMJmU4o","vite_plugin.md":"gDWEi8f0"}
|
|
||||||
File diff suppressed because one or more lines are too long
221
docs/install.md
Normal file
221
docs/install.md
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
# Installation & Setup
|
||||||
|
|
||||||
|
SigPro is designed to be drop-in ready. Whether you are building a complex application with a bundler or a simple reactive widget in a single HTML file, SigPro scales with your needs.
|
||||||
|
|
||||||
|
## 1. Installation
|
||||||
|
|
||||||
|
Choose the method that best fits your workflow:
|
||||||
|
|
||||||
|
<div class="tabs tabs-box w-full mt-8 mb-12">
|
||||||
|
<input type="radio" name="install_method" class="tab border-base-300" aria-label="npm" checked />
|
||||||
|
<div class="tab-content bg-base-100 border-base-300 rounded-box p-6">
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install sigpro
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<input type="radio" name="install_method" class="tab border-base-300" aria-label="pnpm" />
|
||||||
|
<div class="tab-content bg-base-100 border-base-300 rounded-box p-6">
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm add sigpro
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<input type="radio" name="install_method" class="tab border-base-300" aria-label="yarn" />
|
||||||
|
<div class="tab-content bg-base-100 border-base-300 rounded-box p-6">
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn add sigpro
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<input type="radio" name="install_method" class="tab border-base-300" aria-label="bun" />
|
||||||
|
<div class="tab-content bg-base-100 border-base-300 rounded-box p-6">
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bun add sigpro
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<input type="radio" name="install_method" class="tab border-base-300 whitespace-nowrap" aria-label="CDN (ESM)" />
|
||||||
|
<div class="tab-content bg-base-100 border-base-300 rounded-box p-6">
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script type="module">
|
||||||
|
// Import the module – no automatic global injection
|
||||||
|
import { sigpro, $, h, mount } from 'https://cdn.jsdelivr.net/npm/sigpro@1.2.19/+esm';
|
||||||
|
|
||||||
|
// Option A: manually inject all globals (like the classic script)
|
||||||
|
sigpro(); // now $, h, div, watch, etc. are on window
|
||||||
|
|
||||||
|
// Option B: use named imports (no global pollution)
|
||||||
|
const count = $(0);
|
||||||
|
mount(() => h1(() => `Count: ${count()}`), '#app');
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<input type="radio" name="install_method" class="tab border-base-300 whitespace-nowrap" aria-label="CDN (IIFE)" />
|
||||||
|
<div class="tab-content bg-base-100 border-base-300 rounded-box p-6">
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!-- Classic script: auto‑installs everything on window -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/sigpro@1.2.19/dist/sigpro.js"></script>
|
||||||
|
<script>
|
||||||
|
// $, h, div, button, watch, ... are already global
|
||||||
|
const count = $(0);
|
||||||
|
const App = () => div({ class: "card" }, [
|
||||||
|
h1(() => `Count: ${count()}`),
|
||||||
|
button({ onclick: () => count(count() + 1) }, "Increment")
|
||||||
|
]);
|
||||||
|
mount(App, '#app');
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Quick Start Examples
|
||||||
|
|
||||||
|
SigPro uses **lowercase** Tag Helpers (e.g., `div`, `button`) to keep the syntax close to raw HTML, while still being pure JavaScript functions.
|
||||||
|
|
||||||
|
<div class="tabs tabs-box w-full mt-8 mb-12 bg-base-200/50 p-2 rounded-xl border border-base-300">
|
||||||
|
<input type="radio" name="quick_start_tabs" class="tab !rounded-lg" aria-label="Bundlers (ESM)" checked />
|
||||||
|
<div class="tab-content bg-base-100 border-base-300 rounded-lg p-6 mt-2">
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// App.js – Using named imports (recommended)
|
||||||
|
import { $, h1, button, div, mount } from 'sigpro';
|
||||||
|
|
||||||
|
export const App = () => {
|
||||||
|
const count = $(0);
|
||||||
|
return div({ class: "card p-4" }, [
|
||||||
|
h1(() => `Count is: ${count()}`),
|
||||||
|
button(
|
||||||
|
{ class: "btn btn-primary", onclick: () => count(count() + 1) },
|
||||||
|
"Increment"
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
// main.js
|
||||||
|
import { mount } from 'sigpro';
|
||||||
|
import { App } from './App.js';
|
||||||
|
|
||||||
|
mount(App, '#app');
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<input type="radio" name="quick_start_tabs" class="tab !rounded-lg" aria-label="Classic (Direct CDN)" />
|
||||||
|
<div class="tab-content bg-base-100 border-base-300 rounded-lg p-6 mt-2">
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/sigpro@1.2.19/dist/sigpro.js"></script>
|
||||||
|
<script>
|
||||||
|
// Everything is already global – no import needed
|
||||||
|
const name = $('Developer');
|
||||||
|
const App = () => section({ class: "container" }, [
|
||||||
|
h2(() => `Welcome, ${name()}`),
|
||||||
|
input({
|
||||||
|
type: "text",
|
||||||
|
class: "input input-bordered",
|
||||||
|
value: name,
|
||||||
|
placeholder: "Type your name...",
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
mount(App, '#app');
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Global by Design (Two Modes)
|
||||||
|
|
||||||
|
SigPro gives you full control over global pollution.
|
||||||
|
|
||||||
|
### Mode A: Classic (IIFE) – Auto‑injection
|
||||||
|
When you load the **IIFE bundle** (`sigpro.js`) with a traditional `<script>` tag (no `type="module"`), the library automatically injects:
|
||||||
|
- All core functions (`$`, `$$`, `watch`, `h`, `when`, `each`, `fx`, `router`, `req`, `mount`, `batch`) into `window`.
|
||||||
|
- Lowercase tag helpers (`div`, `span`, `button`, etc.) also become global functions.
|
||||||
|
|
||||||
|
✅ Zero configuration – just drop the script and start coding.
|
||||||
|
|
||||||
|
### Mode B: ESM (Modern) – Explicit Injection
|
||||||
|
When you import the **ESM module** (from CDN or via `import`), **nothing** is added to `window` by default. You have two clean options:
|
||||||
|
|
||||||
|
1. **Named imports** (recommended for most apps):
|
||||||
|
```javascript
|
||||||
|
import { $, h, mount } from 'sigpro';
|
||||||
|
```
|
||||||
|
No global pollution, perfect for bundlers and large projects.
|
||||||
|
|
||||||
|
2. **Manual global injection** (similar to classic mode but controlled):
|
||||||
|
```javascript
|
||||||
|
import { sigpro } from 'sigpro';
|
||||||
|
sigpro(); // now $, h, div, button, ... are on window
|
||||||
|
```
|
||||||
|
Useful for quick prototyping or when you prefer the global style.
|
||||||
|
|
||||||
|
### Why two modes?
|
||||||
|
- **Legacy / no‑build**: Use the IIFE script and get everything automatically.
|
||||||
|
- **Modern ESM**: Keep your global namespace clean, leverage tree‑shaking, or inject only when you need it.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Why no build step?
|
||||||
|
|
||||||
|
Because SigPro uses **native ES Modules** and standard JavaScript functions to generate the DOM, you don't actually *need* a compiler like Babel or a transformer for JSX.
|
||||||
|
|
||||||
|
- **Development:** Just save and refresh. Pure JS, no "transpilation" required.
|
||||||
|
- **Performance:** Extremely lightweight. Use any modern bundler (Vite, esbuild) only when you are ready to minify and tree-shake for production.
|
||||||
|
|
||||||
|
## 5. Why SigPro? (The Competitive Edge)
|
||||||
|
|
||||||
|
SigPro stands out by removing the "Build Step" tax and the "Virtual DOM" overhead. It is the closest you can get to writing raw HTML/JS while maintaining modern reactivity.
|
||||||
|
|
||||||
|
| Feature | **SigPro** | **SolidJS** | **Svelte** | **React** | **Vue** |
|
||||||
|
| :----------------- | :--------------- | :----------- | :----------- | :---------- | :---------- |
|
||||||
|
| **Bundle Size** | **~3KB** | ~7KB | ~4KB | ~40KB+ | ~30KB |
|
||||||
|
| **DOM Strategy** | **Direct DOM** | Direct DOM | Compiled DOM | Virtual DOM | Virtual DOM |
|
||||||
|
| **Reactivity** | **Fine-grained** | Fine-grained | Compiled | Re-renders | Proxies |
|
||||||
|
| **Build Step** | **Optional** | Required | Required | Required | Optional |
|
||||||
|
| **Learning Curve** | **Minimal** | Medium | Low | High | Medium |
|
||||||
|
| **Initialization** | **Ultra-Fast** | Very Fast | Fast | Slow | Medium |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Key Advantages
|
||||||
|
|
||||||
|
- **Extreme Performance**: No Virtual DOM reconciliation. SigPro updates the specific node or attribute instantly when a signal changes.
|
||||||
|
- **Fine-Grained Reactivity**: State changes only trigger updates where the data is actually used, not on the entire component.
|
||||||
|
- **Native Web Standards**: Everything is a standard JS function. No custom template syntax to learn.
|
||||||
|
- **Zero Magic**: No hidden compilers. What you write is what runs in the browser.
|
||||||
|
- **Global by Design** (with control): Tag helpers and core functions can be globally available (IIFE) or imported on demand (ESM) – you choose.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Summary
|
||||||
|
|
||||||
|
SigPro isn't just another framework; it's a bridge to the native web. By using standard ES Modules and functional DOM generation, you get the benefits of a modern reactive library with the weight of a utility script.
|
||||||
|
|
||||||
|
**Because, in the end... why fight the web when we can embrace it?**
|
||||||
645
docs/sigpro.js
Normal file
645
docs/sigpro.js
Normal file
@@ -0,0 +1,645 @@
|
|||||||
|
(() => {
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
function __accessProp(key) {
|
||||||
|
return this[key];
|
||||||
|
}
|
||||||
|
var __toCommonJS = (from) => {
|
||||||
|
var entry = (__moduleCache ??= new WeakMap).get(from), desc;
|
||||||
|
if (entry)
|
||||||
|
return entry;
|
||||||
|
entry = __defProp({}, "__esModule", { value: true });
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (var key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(entry, key))
|
||||||
|
__defProp(entry, key, {
|
||||||
|
get: __accessProp.bind(from, key),
|
||||||
|
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
||||||
|
});
|
||||||
|
}
|
||||||
|
__moduleCache.set(from, entry);
|
||||||
|
return entry;
|
||||||
|
};
|
||||||
|
var __moduleCache;
|
||||||
|
var __returnValue = (v) => v;
|
||||||
|
function __exportSetter(name, newValue) {
|
||||||
|
this[name] = __returnValue.bind(null, newValue);
|
||||||
|
}
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, {
|
||||||
|
get: all[name],
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
set: __exportSetter.bind(all, name)
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// index.js
|
||||||
|
var exports_sigpro = {};
|
||||||
|
__export(exports_sigpro, {
|
||||||
|
when: () => when,
|
||||||
|
watch: () => watch,
|
||||||
|
router: () => router,
|
||||||
|
req: () => req,
|
||||||
|
mount: () => mount,
|
||||||
|
h: () => h,
|
||||||
|
fx: () => fx,
|
||||||
|
each: () => each,
|
||||||
|
batch: () => batch,
|
||||||
|
$$: () => $$,
|
||||||
|
$: () => $
|
||||||
|
});
|
||||||
|
|
||||||
|
// sigpro.js
|
||||||
|
var isFunc = (f) => typeof f === "function";
|
||||||
|
var isObj = (o) => o && typeof o === "object";
|
||||||
|
var isArr = Array.isArray;
|
||||||
|
var doc = typeof document !== "undefined" ? document : null;
|
||||||
|
var ensureNode = (n) => n?._isRuntime ? n.container : n instanceof Node ? n : doc.createTextNode(n == null ? "" : String(n));
|
||||||
|
var activeEffect = null;
|
||||||
|
var activeOwner = null;
|
||||||
|
var isFlushing = false;
|
||||||
|
var batchDepth = 0;
|
||||||
|
var effectQueue = new Set;
|
||||||
|
var proxyCache = new WeakMap;
|
||||||
|
var ITER = Symbol("iter");
|
||||||
|
var MOUNTED_NODES = new WeakMap;
|
||||||
|
var dispose = (eff) => {
|
||||||
|
if (!eff || eff._disposed)
|
||||||
|
return;
|
||||||
|
eff._disposed = true;
|
||||||
|
const stack = [eff];
|
||||||
|
while (stack.length) {
|
||||||
|
const e = stack.pop();
|
||||||
|
if (e._cleanups) {
|
||||||
|
e._cleanups.forEach((fn) => fn());
|
||||||
|
e._cleanups.clear();
|
||||||
|
}
|
||||||
|
if (e._children) {
|
||||||
|
e._children.forEach((child) => stack.push(child));
|
||||||
|
e._children.clear();
|
||||||
|
}
|
||||||
|
if (e._deps) {
|
||||||
|
e._deps.forEach((depSet) => depSet.delete(e));
|
||||||
|
e._deps.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var onUnmount = (fn) => {
|
||||||
|
if (activeOwner)
|
||||||
|
(activeOwner._cleanups ||= new Set).add(fn);
|
||||||
|
};
|
||||||
|
var untrack = (fn) => {
|
||||||
|
const p = activeEffect;
|
||||||
|
activeEffect = null;
|
||||||
|
try {
|
||||||
|
return fn();
|
||||||
|
} finally {
|
||||||
|
activeEffect = p;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var createEffect = (fn, isComputed = false) => {
|
||||||
|
const effect = () => {
|
||||||
|
if (effect._disposed)
|
||||||
|
return;
|
||||||
|
if (effect._deps)
|
||||||
|
effect._deps.forEach((s) => s.delete(effect));
|
||||||
|
if (effect._cleanups) {
|
||||||
|
effect._cleanups.forEach((c) => c());
|
||||||
|
effect._cleanups.clear();
|
||||||
|
}
|
||||||
|
const prevEffect = activeEffect;
|
||||||
|
const prevOwner = activeOwner;
|
||||||
|
activeEffect = activeOwner = effect;
|
||||||
|
try {
|
||||||
|
return effect._result = fn();
|
||||||
|
} catch (e) {
|
||||||
|
console.error("[SigPro]", e);
|
||||||
|
} finally {
|
||||||
|
activeEffect = prevEffect;
|
||||||
|
activeOwner = prevOwner;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
effect._deps = effect._cleanups = effect._children = null;
|
||||||
|
effect._disposed = false;
|
||||||
|
effect._isComputed = isComputed;
|
||||||
|
effect._depth = activeEffect ? activeEffect._depth + 1 : 0;
|
||||||
|
effect._mounts = [];
|
||||||
|
effect._parent = activeOwner;
|
||||||
|
if (activeOwner)
|
||||||
|
(activeOwner._children ||= new Set).add(effect);
|
||||||
|
return effect;
|
||||||
|
};
|
||||||
|
var flush = () => {
|
||||||
|
if (isFlushing)
|
||||||
|
return;
|
||||||
|
isFlushing = true;
|
||||||
|
const sorted = Array.from(effectQueue).sort((a, b) => a._depth - b._depth);
|
||||||
|
effectQueue.clear();
|
||||||
|
for (const e of sorted)
|
||||||
|
if (!e._disposed)
|
||||||
|
e();
|
||||||
|
isFlushing = false;
|
||||||
|
};
|
||||||
|
var batch = (fn) => {
|
||||||
|
batchDepth++;
|
||||||
|
try {
|
||||||
|
return fn();
|
||||||
|
} finally {
|
||||||
|
batchDepth--;
|
||||||
|
if (batchDepth === 0 && effectQueue.size > 0 && !isFlushing) {
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var trackUpdate = (subs, trigger = false) => {
|
||||||
|
if (!trigger && activeEffect && !activeEffect._disposed) {
|
||||||
|
subs.add(activeEffect);
|
||||||
|
(activeEffect._deps ||= new Set).add(subs);
|
||||||
|
} else if (trigger && subs.size > 0) {
|
||||||
|
let hasQueue = false;
|
||||||
|
for (const e of subs) {
|
||||||
|
if (e === activeEffect || e._disposed)
|
||||||
|
continue;
|
||||||
|
if (e._isComputed) {
|
||||||
|
e._dirty = true;
|
||||||
|
if (e._subs)
|
||||||
|
trackUpdate(e._subs, true);
|
||||||
|
} else {
|
||||||
|
effectQueue.add(e);
|
||||||
|
hasQueue = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasQueue && !isFlushing && batchDepth === 0)
|
||||||
|
queueMicrotask(flush);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var $ = (val, key = null) => {
|
||||||
|
const subs = new Set;
|
||||||
|
if (isFunc(val)) {
|
||||||
|
let cache;
|
||||||
|
const computed = () => {
|
||||||
|
if (computed._dirty) {
|
||||||
|
const prev = activeEffect;
|
||||||
|
activeEffect = computed;
|
||||||
|
try {
|
||||||
|
const next = val();
|
||||||
|
if (!Object.is(cache, next)) {
|
||||||
|
cache = next;
|
||||||
|
trackUpdate(subs, true);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
activeEffect = prev;
|
||||||
|
}
|
||||||
|
computed._dirty = false;
|
||||||
|
}
|
||||||
|
trackUpdate(subs);
|
||||||
|
return cache;
|
||||||
|
};
|
||||||
|
computed._isComputed = true;
|
||||||
|
computed._subs = subs;
|
||||||
|
computed._dirty = true;
|
||||||
|
computed._deps = null;
|
||||||
|
computed._disposed = false;
|
||||||
|
computed.stop = () => {};
|
||||||
|
if (activeOwner)
|
||||||
|
onUnmount(computed.stop);
|
||||||
|
return computed;
|
||||||
|
}
|
||||||
|
if (key)
|
||||||
|
try {
|
||||||
|
val = JSON.parse(localStorage.getItem(key)) ?? val;
|
||||||
|
} catch (e) {}
|
||||||
|
return (...args) => {
|
||||||
|
if (args.length) {
|
||||||
|
const next = isFunc(args[0]) ? args[0](val) : args[0];
|
||||||
|
if (!Object.is(val, next)) {
|
||||||
|
val = next;
|
||||||
|
if (key)
|
||||||
|
localStorage.setItem(key, JSON.stringify(val));
|
||||||
|
trackUpdate(subs, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trackUpdate(subs);
|
||||||
|
return val;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
var $$ = (target) => {
|
||||||
|
if (!isObj(target))
|
||||||
|
return target;
|
||||||
|
const cached = proxyCache.get(target);
|
||||||
|
if (cached)
|
||||||
|
return cached;
|
||||||
|
const subs = new Map;
|
||||||
|
const getSubs = (key) => {
|
||||||
|
let set = subs.get(key);
|
||||||
|
if (!set)
|
||||||
|
subs.set(key, set = new Set);
|
||||||
|
return set;
|
||||||
|
};
|
||||||
|
const proxy = new Proxy(target, {
|
||||||
|
get(target2, key, receiver) {
|
||||||
|
if (typeof key !== "symbol")
|
||||||
|
trackUpdate(getSubs(key));
|
||||||
|
return $$(Reflect.get(target2, key, receiver));
|
||||||
|
},
|
||||||
|
set(target2, key, value, receiver) {
|
||||||
|
const hadKey = Reflect.has(target2, key);
|
||||||
|
const oldValue = Reflect.get(target2, key, receiver);
|
||||||
|
const result = Reflect.set(target2, key, value, receiver);
|
||||||
|
if (result && !Object.is(oldValue, value)) {
|
||||||
|
trackUpdate(getSubs(key), true);
|
||||||
|
if (!hadKey)
|
||||||
|
trackUpdate(getSubs(ITER), true);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
deleteProperty(target2, key) {
|
||||||
|
const result = Reflect.deleteProperty(target2, key);
|
||||||
|
if (result) {
|
||||||
|
trackUpdate(getSubs(key), true);
|
||||||
|
trackUpdate(getSubs(ITER), true);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
ownKeys(target2) {
|
||||||
|
trackUpdate(getSubs(ITER));
|
||||||
|
return Reflect.ownKeys(target2);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
proxyCache.set(target, proxy);
|
||||||
|
return proxy;
|
||||||
|
};
|
||||||
|
var watch = (sources, cb) => {
|
||||||
|
if (cb === undefined) {
|
||||||
|
const effect2 = createEffect(sources);
|
||||||
|
effect2();
|
||||||
|
return () => dispose(effect2);
|
||||||
|
}
|
||||||
|
const effect = createEffect(() => {
|
||||||
|
const vals = Array.isArray(sources) ? sources.map((s) => s()) : sources();
|
||||||
|
untrack(() => cb(vals));
|
||||||
|
});
|
||||||
|
effect();
|
||||||
|
return () => dispose(effect);
|
||||||
|
};
|
||||||
|
var cleanupNode = (node) => {
|
||||||
|
if (!node)
|
||||||
|
return;
|
||||||
|
if (node._cleanups) {
|
||||||
|
node._cleanups.forEach((fn) => fn());
|
||||||
|
node._cleanups.clear();
|
||||||
|
}
|
||||||
|
if (node._ownerEffect)
|
||||||
|
dispose(node._ownerEffect);
|
||||||
|
if (node.childNodes)
|
||||||
|
node.childNodes.forEach((n) => cleanupNode(n));
|
||||||
|
};
|
||||||
|
var DANGEROUS_PROTOCOL = /^\s*(javascript|data|vbscript):/i;
|
||||||
|
var isDangerousAttr = (key) => key === "src" || key === "href" || key.startsWith("on");
|
||||||
|
var validateAttr = (key, val) => {
|
||||||
|
if (val == null || val === false)
|
||||||
|
return null;
|
||||||
|
if (isDangerousAttr(key)) {
|
||||||
|
const sVal = String(val);
|
||||||
|
if (DANGEROUS_PROTOCOL.test(sVal)) {
|
||||||
|
console.warn(`[SigPro] Bloqueado protocolo peligroso en ${key}`);
|
||||||
|
return "#";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
};
|
||||||
|
var h = (tag, props = {}, children = []) => {
|
||||||
|
if (props instanceof Node || isArr(props) || !isObj(props)) {
|
||||||
|
children = props;
|
||||||
|
props = {};
|
||||||
|
}
|
||||||
|
if (isFunc(tag)) {
|
||||||
|
const effect = createEffect(() => {
|
||||||
|
const result2 = tag(props, {
|
||||||
|
children,
|
||||||
|
emit: (ev, ...args) => props[`on${ev[0].toUpperCase()}${ev.slice(1)}`]?.(...args)
|
||||||
|
});
|
||||||
|
effect._result = result2;
|
||||||
|
return result2;
|
||||||
|
});
|
||||||
|
effect();
|
||||||
|
const result = effect._result;
|
||||||
|
if (result == null)
|
||||||
|
return null;
|
||||||
|
const node = result instanceof Node || isArr(result) && result.every((n) => n instanceof Node) ? result : doc.createTextNode(String(result));
|
||||||
|
const attach = (n) => {
|
||||||
|
if (isObj(n) && !n._isRuntime) {
|
||||||
|
n._mounts = effect._mounts || [];
|
||||||
|
n._cleanups = effect._cleanups || new Set;
|
||||||
|
n._ownerEffect = effect;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
isArr(node) ? node.forEach(attach) : attach(node);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
const isSVG = /^(svg|path|circle|rect|line|poly(line|gon)|g|defs|text(path)?|tspan|use|symbol|image|marker|ellipse)$/i.test(tag);
|
||||||
|
const el = isSVG ? doc.createElementNS("http://www.w3.org/2000/svg", tag) : doc.createElement(tag);
|
||||||
|
el._cleanups = new Set;
|
||||||
|
for (let k in props) {
|
||||||
|
if (!props.hasOwnProperty(k))
|
||||||
|
continue;
|
||||||
|
let v = props[k];
|
||||||
|
if (k === "ref") {
|
||||||
|
isFunc(v) ? v(el) : v.current = el;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (isSVG && k.startsWith("xlink:")) {
|
||||||
|
const ns = "http://www.w3.org/1999/xlink";
|
||||||
|
v == null ? el.removeAttributeNS(ns, k.slice(6)) : el.setAttributeNS(ns, k.slice(6), v);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (k.startsWith("on")) {
|
||||||
|
const ev = k.slice(2).toLowerCase();
|
||||||
|
el.addEventListener(ev, v);
|
||||||
|
const off = () => el.removeEventListener(ev, v);
|
||||||
|
el._cleanups.add(off);
|
||||||
|
onUnmount(off);
|
||||||
|
} else if (isFunc(v)) {
|
||||||
|
const effect = createEffect(() => {
|
||||||
|
const val = validateAttr(k, v());
|
||||||
|
if (k === "class")
|
||||||
|
el.className = val || "";
|
||||||
|
else if (val == null)
|
||||||
|
el.removeAttribute(k);
|
||||||
|
else if (k in el && !isSVG)
|
||||||
|
el[k] = val;
|
||||||
|
else
|
||||||
|
el.setAttribute(k, val === true ? "" : val);
|
||||||
|
});
|
||||||
|
effect();
|
||||||
|
el._cleanups.add(() => dispose(effect));
|
||||||
|
onUnmount(() => dispose(effect));
|
||||||
|
if (/^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName) && (k === "value" || k === "checked")) {
|
||||||
|
const evType = k === "checked" ? "change" : "input";
|
||||||
|
el.addEventListener(evType, (ev) => v(ev.target[k]));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const val = validateAttr(k, v);
|
||||||
|
if (val != null) {
|
||||||
|
if (k in el && !isSVG)
|
||||||
|
el[k] = val;
|
||||||
|
else
|
||||||
|
el.setAttribute(k, val === true ? "" : val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const append = (c) => {
|
||||||
|
if (isArr(c))
|
||||||
|
return c.forEach(append);
|
||||||
|
if (isFunc(c)) {
|
||||||
|
const anchor = doc.createTextNode("");
|
||||||
|
el.appendChild(anchor);
|
||||||
|
let currentNodes = [];
|
||||||
|
const effect = createEffect(() => {
|
||||||
|
const res = c();
|
||||||
|
const next = (isArr(res) ? res : [res]).map(ensureNode);
|
||||||
|
currentNodes.forEach((n) => {
|
||||||
|
if (n._isRuntime)
|
||||||
|
n.destroy();
|
||||||
|
else
|
||||||
|
cleanupNode(n);
|
||||||
|
if (n.parentNode)
|
||||||
|
n.remove();
|
||||||
|
});
|
||||||
|
let ref = anchor;
|
||||||
|
for (let i = next.length - 1;i >= 0; i--) {
|
||||||
|
const node = next[i];
|
||||||
|
if (node.parentNode !== ref.parentNode)
|
||||||
|
ref.parentNode?.insertBefore(node, ref);
|
||||||
|
if (node._mounts)
|
||||||
|
node._mounts.forEach((fn) => fn());
|
||||||
|
ref = node;
|
||||||
|
}
|
||||||
|
currentNodes = next;
|
||||||
|
});
|
||||||
|
effect();
|
||||||
|
el._cleanups.add(() => dispose(effect));
|
||||||
|
onUnmount(() => dispose(effect));
|
||||||
|
} else {
|
||||||
|
const node = ensureNode(c);
|
||||||
|
el.appendChild(node);
|
||||||
|
if (node._mounts)
|
||||||
|
node._mounts.forEach((fn) => fn());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
append(children);
|
||||||
|
return el;
|
||||||
|
};
|
||||||
|
var render = (renderFn) => {
|
||||||
|
const cleanups = new Set;
|
||||||
|
const previousOwner = activeOwner;
|
||||||
|
const previousEffect = activeEffect;
|
||||||
|
const container = doc.createElement("div");
|
||||||
|
container.style.display = "contents";
|
||||||
|
container.setAttribute("role", "presentation");
|
||||||
|
activeOwner = { _cleanups: cleanups };
|
||||||
|
activeEffect = null;
|
||||||
|
const processResult = (result) => {
|
||||||
|
if (!result)
|
||||||
|
return;
|
||||||
|
if (result._isRuntime) {
|
||||||
|
cleanups.add(result.destroy);
|
||||||
|
container.appendChild(result.container);
|
||||||
|
} else if (isArr(result)) {
|
||||||
|
result.forEach(processResult);
|
||||||
|
} else {
|
||||||
|
container.appendChild(result instanceof Node ? result : doc.createTextNode(String(result == null ? "" : result)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
processResult(renderFn({ onCleanup: (fn) => cleanups.add(fn) }));
|
||||||
|
} finally {
|
||||||
|
activeOwner = previousOwner;
|
||||||
|
activeEffect = previousEffect;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
_isRuntime: true,
|
||||||
|
container,
|
||||||
|
destroy: () => {
|
||||||
|
cleanups.forEach((fn) => fn());
|
||||||
|
cleanupNode(container);
|
||||||
|
container.remove();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
var when = (cond, SIP, NOP = null) => {
|
||||||
|
const anchor = doc.createTextNode("");
|
||||||
|
const root = h("div", { style: "display:contents" }, [anchor]);
|
||||||
|
let currentView = null;
|
||||||
|
watch(() => !!(isFunc(cond) ? cond() : cond), (show) => {
|
||||||
|
if (currentView) {
|
||||||
|
currentView.destroy();
|
||||||
|
currentView = null;
|
||||||
|
}
|
||||||
|
const content = show ? SIP : NOP;
|
||||||
|
if (content) {
|
||||||
|
currentView = render(() => isFunc(content) ? content() : content);
|
||||||
|
root.insertBefore(currentView.container, anchor);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
onUnmount(() => currentView?.destroy());
|
||||||
|
return root;
|
||||||
|
};
|
||||||
|
var fx = ({ name, duration = 200, scale, slide, rotate, blur }, child) => {
|
||||||
|
const el = typeof child === "function" ? child() : child;
|
||||||
|
if (!(el instanceof Node))
|
||||||
|
return el;
|
||||||
|
if (name) {
|
||||||
|
el.style.animation = `${name}-in ${duration}ms`;
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
const hasTransform = scale || slide || rotate || blur;
|
||||||
|
const initialTransform = [
|
||||||
|
scale ? "scale(0.95)" : "",
|
||||||
|
slide ? "translateY(-10px)" : "",
|
||||||
|
rotate ? "rotate(-2deg)" : ""
|
||||||
|
].filter(Boolean).join(" ");
|
||||||
|
el.style.transition = `all ${duration}ms ease`;
|
||||||
|
el.style.opacity = "0";
|
||||||
|
if (hasTransform)
|
||||||
|
el.style.transform = initialTransform;
|
||||||
|
if (blur)
|
||||||
|
el.style.filter = "blur(4px)";
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
el.style.opacity = "1";
|
||||||
|
if (hasTransform)
|
||||||
|
el.style.transform = "none";
|
||||||
|
if (blur)
|
||||||
|
el.style.filter = "none";
|
||||||
|
});
|
||||||
|
return el;
|
||||||
|
};
|
||||||
|
var each = (src, itemFn, keyField) => {
|
||||||
|
const anchor = doc.createTextNode("");
|
||||||
|
const root = h("div", { style: "display:contents" }, [anchor]);
|
||||||
|
let cache = new Map;
|
||||||
|
watch(() => (isFunc(src) ? src() : src) || [], (items) => {
|
||||||
|
const nextCache = new Map;
|
||||||
|
const nextOrder = [];
|
||||||
|
const newItems = items || [];
|
||||||
|
for (let i = 0;i < newItems.length; i++) {
|
||||||
|
const item = newItems[i];
|
||||||
|
const key = keyField ? item?.[keyField] ?? i : item?.id ?? i;
|
||||||
|
let view = cache.get(key);
|
||||||
|
if (!view)
|
||||||
|
view = render(() => itemFn(item, i));
|
||||||
|
else
|
||||||
|
cache.delete(key);
|
||||||
|
nextCache.set(key, view);
|
||||||
|
nextOrder.push(view);
|
||||||
|
}
|
||||||
|
cache.forEach((view) => view.destroy());
|
||||||
|
let lastRef = anchor;
|
||||||
|
for (let i = nextOrder.length - 1;i >= 0; i--) {
|
||||||
|
const view = nextOrder[i];
|
||||||
|
const node = view.container;
|
||||||
|
if (node.nextSibling !== lastRef)
|
||||||
|
root.insertBefore(node, lastRef);
|
||||||
|
lastRef = node;
|
||||||
|
}
|
||||||
|
cache = nextCache;
|
||||||
|
});
|
||||||
|
return root;
|
||||||
|
};
|
||||||
|
var router = (routes) => {
|
||||||
|
const getHash = () => window.location.hash.slice(1) || "/";
|
||||||
|
const path = $(getHash());
|
||||||
|
const handler = () => path(getHash());
|
||||||
|
window.addEventListener("hashchange", handler);
|
||||||
|
onUnmount(() => window.removeEventListener("hashchange", handler));
|
||||||
|
const hook = h("div", { class: "router-hook" });
|
||||||
|
let currentView = null;
|
||||||
|
watch([path], () => {
|
||||||
|
const cur = path();
|
||||||
|
const route = routes.find((r) => {
|
||||||
|
const p1 = r.path.split("/").filter(Boolean);
|
||||||
|
const p2 = cur.split("/").filter(Boolean);
|
||||||
|
return p1.length === p2.length && p1.every((p, i) => p[0] === ":" || p === p2[i]);
|
||||||
|
}) || routes.find((r) => r.path === "*");
|
||||||
|
if (route) {
|
||||||
|
currentView?.destroy();
|
||||||
|
const params = {};
|
||||||
|
route.path.split("/").filter(Boolean).forEach((p, i) => {
|
||||||
|
if (p[0] === ":")
|
||||||
|
params[p.slice(1)] = cur.split("/").filter(Boolean)[i];
|
||||||
|
});
|
||||||
|
router.params(params);
|
||||||
|
currentView = render(() => isFunc(route.component) ? route.component(params) : route.component);
|
||||||
|
hook.replaceChildren(currentView.container);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return hook;
|
||||||
|
};
|
||||||
|
router.params = $({});
|
||||||
|
router.to = (p) => window.location.hash = p.replace(/^#?\/?/, "#/");
|
||||||
|
router.back = () => window.history.back();
|
||||||
|
router.path = () => window.location.hash.replace(/^#/, "") || "/";
|
||||||
|
var req = ({ url, method = "GET", headers = {} }) => {
|
||||||
|
const loading = $(false);
|
||||||
|
const error = $(null);
|
||||||
|
const data = $(null);
|
||||||
|
let controller = null;
|
||||||
|
let timeoutId = null;
|
||||||
|
const run = async (body = null) => {
|
||||||
|
controller?.abort();
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
controller = new AbortController;
|
||||||
|
timeoutId = setTimeout(() => controller.abort(), 1e4);
|
||||||
|
loading(true);
|
||||||
|
error(null);
|
||||||
|
try {
|
||||||
|
const isFormData = body instanceof FormData;
|
||||||
|
const res = await fetch(url, {
|
||||||
|
method,
|
||||||
|
headers: isFormData ? headers : { "Content-Type": "application/json", ...headers },
|
||||||
|
body: isFormData ? body : body ? JSON.stringify(body) : undefined,
|
||||||
|
signal: controller.signal
|
||||||
|
});
|
||||||
|
const text = await res.text();
|
||||||
|
const json = text ? JSON.parse(text) : null;
|
||||||
|
if (!res.ok)
|
||||||
|
throw new Error(json?.message || res.statusText);
|
||||||
|
data(json);
|
||||||
|
return json;
|
||||||
|
} catch (e) {
|
||||||
|
if (e.name !== "AbortError")
|
||||||
|
error(e.message);
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
loading(false);
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
controller = null;
|
||||||
|
timeoutId = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const abort = () => controller?.abort();
|
||||||
|
return { run, abort, loading, error, data };
|
||||||
|
};
|
||||||
|
var mount = (comp, target) => {
|
||||||
|
const t = typeof target === "string" ? doc.querySelector(target) : target;
|
||||||
|
if (!t)
|
||||||
|
return;
|
||||||
|
if (MOUNTED_NODES.has(t))
|
||||||
|
MOUNTED_NODES.get(t).destroy();
|
||||||
|
const inst = render(isFunc(comp) ? comp : () => comp);
|
||||||
|
t.replaceChildren(inst.container);
|
||||||
|
MOUNTED_NODES.set(t, inst);
|
||||||
|
return inst;
|
||||||
|
};
|
||||||
|
var SigPro = Object.freeze({ $, $$, watch, h, when, each, fx, router, req, mount, batch });
|
||||||
|
if (typeof window !== "undefined") {
|
||||||
|
Object.assign(window, SigPro);
|
||||||
|
"a abbr article aside audio b blockquote br button canvas caption cite code col colgroup datalist dd del details dfn dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 header hr i iframe img input ins kbd label legend li main mark meter nav object ol optgroup option output p picture pre progress section select slot small source span strong sub summary sup svg table tbody td template textarea tfoot th thead time tr u ul video".split(" ").forEach((tag) => {
|
||||||
|
window[tag] = (props, children) => h(tag, props, children);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})();
|
||||||
File diff suppressed because one or more lines are too long
146
docs/vite/plugin.md
Normal file
146
docs/vite/plugin.md
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
# Vite Plugin: File-based Routing
|
||||||
|
|
||||||
|
The `sigproRouter` plugin for Vite automates route generation by scanning your `pages` directory. It creates a **virtual module** that you can import directly into your code, eliminating the need to maintain a manual routes array.
|
||||||
|
|
||||||
|
## 1. Project Structure
|
||||||
|
|
||||||
|
To use the plugin, organize your files within the `src/pages` directory. The folder hierarchy directly determines your application's URL structure. SigPro uses brackets `[param]` for dynamic segments.
|
||||||
|
|
||||||
|
<div class="mockup-code bg-base-300 text-base-content shadow-xl my-8">
|
||||||
|
<pre><code>my-sigpro-app/
|
||||||
|
├── src/
|
||||||
|
│ ├── pages/
|
||||||
|
│ │ ├── index.js → #/
|
||||||
|
│ │ ├── about.js → #/about
|
||||||
|
│ │ ├── users/
|
||||||
|
│ │ │ └── [id].js → #/users/:id
|
||||||
|
│ │ └── blog/
|
||||||
|
│ │ ├── index.js → #/blog
|
||||||
|
│ │ └── [slug].js → #/blog/:slug
|
||||||
|
│ ├── App.js (Main Layout)
|
||||||
|
│ └── main.js (Entry Point)
|
||||||
|
├── vite.config.js
|
||||||
|
└── package.json</code></pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Setup & Configuration
|
||||||
|
|
||||||
|
Add the plugin to your `vite.config.js`. It works out of the box with zero configuration.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// vite.config.js
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import { sigproRouter } from 'sigpro/vite';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [sigproRouter()]
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Implementation
|
||||||
|
|
||||||
|
Thanks to **SigPro's synchronous initialization**, you no longer need to wrap your mounting logic in `.then()` blocks.
|
||||||
|
|
||||||
|
<div class="tabs tabs-box w-full mt-8 mb-12 bg-base-200/50 p-2 border border-base-300">
|
||||||
|
<input type="radio" name="route_impl" class="tab" aria-label="Option A: Direct in main.js" checked />
|
||||||
|
<div class="tab-content bg-base-100 border-base-300 rounded-lg p-6 mt-2">
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// src/main.js
|
||||||
|
import SigPro from 'sigpro';
|
||||||
|
import { routes } from 'virtual:sigpro-routes';
|
||||||
|
|
||||||
|
// The Core already has Router ready
|
||||||
|
Mount(Router(routes), '#app');
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<input type="radio" name="route_impl" class="tab" aria-label="Option B: Inside App.js (Persistent Layout)" />
|
||||||
|
<div class="tab-content bg-base-100 border-base-300 rounded-lg p-6 mt-2">
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// src/App.js
|
||||||
|
import { routes } from 'virtual:sigpro-routes';
|
||||||
|
|
||||||
|
export default () => div({ class: 'layout' }, [
|
||||||
|
header([
|
||||||
|
h1("SigPro App"),
|
||||||
|
nav([
|
||||||
|
button({ onclick: () => Router.go('/') }, "Home"),
|
||||||
|
button({ onclick: () => Router.go('/blog') }, "Blog")
|
||||||
|
])
|
||||||
|
]),
|
||||||
|
// Only the content inside <main> will be swapped reactively
|
||||||
|
main(Router(routes))
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Route Mapping Reference
|
||||||
|
|
||||||
|
The plugin follows a simple convention to transform your file system into a routing map.
|
||||||
|
|
||||||
|
<div class="overflow-x-auto my-8">
|
||||||
|
<table class="table table-zebra w-full">
|
||||||
|
<thead class="bg-base-200">
|
||||||
|
<tr>
|
||||||
|
<th>File Path</th>
|
||||||
|
<th>Generated Path</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><code>index.js</code></td>
|
||||||
|
<td class="font-mono text-primary font-bold">/</td>
|
||||||
|
<td>The application root.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>about.js</code></td>
|
||||||
|
<td class="font-mono text-primary font-bold">/about</td>
|
||||||
|
<td>A static page.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>[id].js</code></td>
|
||||||
|
<td class="font-mono text-primary font-bold">/:id</td>
|
||||||
|
<td>Dynamic parameter (passed to the component).</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>blog/index.js</code></td>
|
||||||
|
<td class="font-mono text-primary font-bold">/blog</td>
|
||||||
|
<td>Folder index page.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>_utils.js</code></td>
|
||||||
|
<td class="italic opacity-50 text-error">Ignored</td>
|
||||||
|
<td>Files starting with <code>_</code> are excluded from routing.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. How it Works (Vite Virtual Module)
|
||||||
|
|
||||||
|
The plugin generates a virtual module named `virtual:sigpro-routes`. This module exports an array of objects compatible with `Router()`:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Internal representation generated by the plugin
|
||||||
|
export const routes = [
|
||||||
|
{ path: '/', component: () => import('/src/pages/index.js') },
|
||||||
|
{ path: '/users/:id', component: () => import('/src/pages/users/[id].js') },
|
||||||
|
// ...
|
||||||
|
];
|
||||||
|
```
|
||||||
|
|
||||||
|
Because it uses dynamic `import()`, Vite automatically performs **Code Splitting**, meaning each page is its own small JS file that only loads when the user navigates to it.
|
||||||
@@ -1 +0,0 @@
|
|||||||
.vpi-social-github{--icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'%3E%3Cpath fill='black' d='M12 .297c-6.63 0-12 5.373-12 12c0 5.303 3.438 9.8 8.205 11.385c.6.113.82-.258.82-.577c0-.285-.01-1.04-.015-2.04c-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729c1.205.084 1.838 1.236 1.838 1.236c1.07 1.835 2.809 1.305 3.495.998c.108-.776.417-1.305.76-1.605c-2.665-.3-5.466-1.332-5.466-5.93c0-1.31.465-2.38 1.235-3.22c-.135-.303-.54-1.523.105-3.176c0 0 1.005-.322 3.3 1.23c.96-.267 1.98-.399 3-.405c1.02.006 2.04.138 3 .405c2.28-1.552 3.285-1.23 3.285-1.23c.645 1.653.24 2.873.12 3.176c.765.84 1.23 1.91 1.23 3.22c0 4.61-2.805 5.625-5.475 5.92c.42.36.81 1.096.81 2.22c0 1.606-.015 2.896-.015 3.286c0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")}
|
|
||||||
3
index.js
3
index.js
@@ -1,3 +1,2 @@
|
|||||||
// index.js
|
// index.js
|
||||||
export * from './packages/sigpro/sigpro.js';
|
export * from './sigpro.js';
|
||||||
export { default as sigproRouter } from './packages/sigpro/plugin.js';
|
|
||||||
49
package.json
49
package.json
@@ -1,23 +1,52 @@
|
|||||||
{
|
{
|
||||||
"name": "sigpro",
|
"name": "sigpro",
|
||||||
"version": "1.0.14",
|
"version": "1.2.20",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"homepage": "https://natxocc.github.io/sigpro/",
|
"main": "./dist/sigpro.esm.min.js",
|
||||||
|
"module": "./dist/sigpro.esm.min.js",
|
||||||
|
"unpkg": "./dist/sigpro.min.js",
|
||||||
|
"jsdelivr": "./dist/sigpro.min.js",
|
||||||
|
"types": "./sigpro.d.ts",
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"import": "./dist/sigpro.esm.min.js",
|
||||||
|
"script": "./dist/sigpro.js",
|
||||||
|
"types": "./sigpro.d.ts"
|
||||||
|
},
|
||||||
|
"./vite": "./vite/index.js",
|
||||||
|
"./vite/*": "./vite/*.js"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"index.js",
|
||||||
|
"sigpro.js",
|
||||||
|
"dist",
|
||||||
|
"vite",
|
||||||
|
"README.md",
|
||||||
|
"LICENSE"
|
||||||
|
],
|
||||||
|
"homepage": "https://sigpro.natxocc.com/#/",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/natxocc/sigpro.git"
|
"url": "https://git.natxocc.com/natxocc/sigpro"
|
||||||
},
|
},
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/natxocc/sigpro/issues"
|
"url": "https://git.natxocc.com/natxocc/sigpro/issues"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"registry": "https://git.natxocc.com/api/packages/natxocc/npm/"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"docs:dev": "vitepress dev packages/docs",
|
"clean": "rm -rf dist",
|
||||||
"docs:build": "vitepress build packages/docs",
|
"prebuild": "npm run clean",
|
||||||
"docs:preview": "vitepress preview packages/docs"
|
"build:iife": "bun build ./index.js --bundle --outfile=./dist/sigpro.js --format=iife --global-name=SigPro",
|
||||||
},
|
"build:docs": "bun build ./index.js --bundle --outfile=./docs/sigpro.js --format=iife --global-name=SigPro",
|
||||||
"devDependencies": {
|
"build:iife:min": "bun build ./index.js --bundle --outfile=./dist/sigpro.min.js --format=iife --global-name=SigPro --minify",
|
||||||
"vitepress": "^1.6.4"
|
"build:esm": "bun build ./index.js --bundle --outfile=./dist/sigpro.esm.js --format=esm",
|
||||||
|
"build:esm:min": "bun build ./index.js --bundle --outfile=./dist/sigpro.esm.min.js --format=esm --minify",
|
||||||
|
"build": "bun run build:iife && bun run build:iife:min && bun run build:esm && bun run build:esm:min && bun run build:docs",
|
||||||
|
"docs": "bun x serve docs",
|
||||||
|
"prepublishOnly": "npm run build"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"signals",
|
"signals",
|
||||||
|
|||||||
275
packages/docs/.vitepress/cache/deps/@theme_index.js
vendored
275
packages/docs/.vitepress/cache/deps/@theme_index.js
vendored
@@ -1,275 +0,0 @@
|
|||||||
import {
|
|
||||||
useMediaQuery
|
|
||||||
} from "./chunk-RLEUDPPB.js";
|
|
||||||
import {
|
|
||||||
computed,
|
|
||||||
ref,
|
|
||||||
shallowRef,
|
|
||||||
watch
|
|
||||||
} from "./chunk-3S55Y3P7.js";
|
|
||||||
|
|
||||||
// node_modules/vitepress/dist/client/theme-default/index.js
|
|
||||||
import "/config/workspace/sigpro/node_modules/vitepress/dist/client/theme-default/styles/fonts.css";
|
|
||||||
|
|
||||||
// node_modules/vitepress/dist/client/theme-default/without-fonts.js
|
|
||||||
import "/config/workspace/sigpro/node_modules/vitepress/dist/client/theme-default/styles/vars.css";
|
|
||||||
import "/config/workspace/sigpro/node_modules/vitepress/dist/client/theme-default/styles/base.css";
|
|
||||||
import "/config/workspace/sigpro/node_modules/vitepress/dist/client/theme-default/styles/icons.css";
|
|
||||||
import "/config/workspace/sigpro/node_modules/vitepress/dist/client/theme-default/styles/utils.css";
|
|
||||||
import "/config/workspace/sigpro/node_modules/vitepress/dist/client/theme-default/styles/components/custom-block.css";
|
|
||||||
import "/config/workspace/sigpro/node_modules/vitepress/dist/client/theme-default/styles/components/vp-code.css";
|
|
||||||
import "/config/workspace/sigpro/node_modules/vitepress/dist/client/theme-default/styles/components/vp-code-group.css";
|
|
||||||
import "/config/workspace/sigpro/node_modules/vitepress/dist/client/theme-default/styles/components/vp-doc.css";
|
|
||||||
import "/config/workspace/sigpro/node_modules/vitepress/dist/client/theme-default/styles/components/vp-sponsor.css";
|
|
||||||
import VPBadge from "/config/workspace/sigpro/node_modules/vitepress/dist/client/theme-default/components/VPBadge.vue";
|
|
||||||
import Layout from "/config/workspace/sigpro/node_modules/vitepress/dist/client/theme-default/Layout.vue";
|
|
||||||
import { default as default2 } from "/config/workspace/sigpro/node_modules/vitepress/dist/client/theme-default/components/VPBadge.vue";
|
|
||||||
import { default as default3 } from "/config/workspace/sigpro/node_modules/vitepress/dist/client/theme-default/components/VPButton.vue";
|
|
||||||
import { default as default4 } from "/config/workspace/sigpro/node_modules/vitepress/dist/client/theme-default/components/VPDocAsideSponsors.vue";
|
|
||||||
import { default as default5 } from "/config/workspace/sigpro/node_modules/vitepress/dist/client/theme-default/components/VPFeatures.vue";
|
|
||||||
import { default as default6 } from "/config/workspace/sigpro/node_modules/vitepress/dist/client/theme-default/components/VPHomeContent.vue";
|
|
||||||
import { default as default7 } from "/config/workspace/sigpro/node_modules/vitepress/dist/client/theme-default/components/VPHomeFeatures.vue";
|
|
||||||
import { default as default8 } from "/config/workspace/sigpro/node_modules/vitepress/dist/client/theme-default/components/VPHomeHero.vue";
|
|
||||||
import { default as default9 } from "/config/workspace/sigpro/node_modules/vitepress/dist/client/theme-default/components/VPHomeSponsors.vue";
|
|
||||||
import { default as default10 } from "/config/workspace/sigpro/node_modules/vitepress/dist/client/theme-default/components/VPImage.vue";
|
|
||||||
import { default as default11 } from "/config/workspace/sigpro/node_modules/vitepress/dist/client/theme-default/components/VPLink.vue";
|
|
||||||
import { default as default12 } from "/config/workspace/sigpro/node_modules/vitepress/dist/client/theme-default/components/VPNavBarSearch.vue";
|
|
||||||
import { default as default13 } from "/config/workspace/sigpro/node_modules/vitepress/dist/client/theme-default/components/VPSocialLink.vue";
|
|
||||||
import { default as default14 } from "/config/workspace/sigpro/node_modules/vitepress/dist/client/theme-default/components/VPSocialLinks.vue";
|
|
||||||
import { default as default15 } from "/config/workspace/sigpro/node_modules/vitepress/dist/client/theme-default/components/VPSponsors.vue";
|
|
||||||
import { default as default16 } from "/config/workspace/sigpro/node_modules/vitepress/dist/client/theme-default/components/VPTeamMembers.vue";
|
|
||||||
import { default as default17 } from "/config/workspace/sigpro/node_modules/vitepress/dist/client/theme-default/components/VPTeamPage.vue";
|
|
||||||
import { default as default18 } from "/config/workspace/sigpro/node_modules/vitepress/dist/client/theme-default/components/VPTeamPageSection.vue";
|
|
||||||
import { default as default19 } from "/config/workspace/sigpro/node_modules/vitepress/dist/client/theme-default/components/VPTeamPageTitle.vue";
|
|
||||||
|
|
||||||
// node_modules/vitepress/dist/client/theme-default/composables/local-nav.js
|
|
||||||
import { onContentUpdated } from "vitepress";
|
|
||||||
|
|
||||||
// node_modules/vitepress/dist/client/theme-default/composables/outline.js
|
|
||||||
import { getScrollOffset } from "vitepress";
|
|
||||||
|
|
||||||
// node_modules/vitepress/dist/client/theme-default/support/utils.js
|
|
||||||
import { withBase } from "vitepress";
|
|
||||||
|
|
||||||
// node_modules/vitepress/dist/client/theme-default/composables/data.js
|
|
||||||
import { useData as useData$ } from "vitepress";
|
|
||||||
var useData = useData$;
|
|
||||||
|
|
||||||
// node_modules/vitepress/dist/client/theme-default/support/utils.js
|
|
||||||
function ensureStartingSlash(path) {
|
|
||||||
return path.startsWith("/") ? path : `/${path}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// node_modules/vitepress/dist/client/theme-default/support/sidebar.js
|
|
||||||
function getSidebar(_sidebar, path) {
|
|
||||||
if (Array.isArray(_sidebar))
|
|
||||||
return addBase(_sidebar);
|
|
||||||
if (_sidebar == null)
|
|
||||||
return [];
|
|
||||||
path = ensureStartingSlash(path);
|
|
||||||
const dir = Object.keys(_sidebar).sort((a, b) => {
|
|
||||||
return b.split("/").length - a.split("/").length;
|
|
||||||
}).find((dir2) => {
|
|
||||||
return path.startsWith(ensureStartingSlash(dir2));
|
|
||||||
});
|
|
||||||
const sidebar = dir ? _sidebar[dir] : [];
|
|
||||||
return Array.isArray(sidebar) ? addBase(sidebar) : addBase(sidebar.items, sidebar.base);
|
|
||||||
}
|
|
||||||
function getSidebarGroups(sidebar) {
|
|
||||||
const groups = [];
|
|
||||||
let lastGroupIndex = 0;
|
|
||||||
for (const index in sidebar) {
|
|
||||||
const item = sidebar[index];
|
|
||||||
if (item.items) {
|
|
||||||
lastGroupIndex = groups.push(item);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!groups[lastGroupIndex]) {
|
|
||||||
groups.push({ items: [] });
|
|
||||||
}
|
|
||||||
groups[lastGroupIndex].items.push(item);
|
|
||||||
}
|
|
||||||
return groups;
|
|
||||||
}
|
|
||||||
function addBase(items, _base) {
|
|
||||||
return [...items].map((_item) => {
|
|
||||||
const item = { ..._item };
|
|
||||||
const base = item.base || _base;
|
|
||||||
if (base && item.link)
|
|
||||||
item.link = base + item.link;
|
|
||||||
if (item.items)
|
|
||||||
item.items = addBase(item.items, base);
|
|
||||||
return item;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// node_modules/vitepress/dist/client/theme-default/composables/sidebar.js
|
|
||||||
function useSidebar() {
|
|
||||||
const { frontmatter, page, theme: theme2 } = useData();
|
|
||||||
const is960 = useMediaQuery("(min-width: 960px)");
|
|
||||||
const isOpen = ref(false);
|
|
||||||
const _sidebar = computed(() => {
|
|
||||||
const sidebarConfig = theme2.value.sidebar;
|
|
||||||
const relativePath = page.value.relativePath;
|
|
||||||
return sidebarConfig ? getSidebar(sidebarConfig, relativePath) : [];
|
|
||||||
});
|
|
||||||
const sidebar = ref(_sidebar.value);
|
|
||||||
watch(_sidebar, (next, prev) => {
|
|
||||||
if (JSON.stringify(next) !== JSON.stringify(prev))
|
|
||||||
sidebar.value = _sidebar.value;
|
|
||||||
});
|
|
||||||
const hasSidebar = computed(() => {
|
|
||||||
return frontmatter.value.sidebar !== false && sidebar.value.length > 0 && frontmatter.value.layout !== "home";
|
|
||||||
});
|
|
||||||
const leftAside = computed(() => {
|
|
||||||
if (hasAside)
|
|
||||||
return frontmatter.value.aside == null ? theme2.value.aside === "left" : frontmatter.value.aside === "left";
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
const hasAside = computed(() => {
|
|
||||||
if (frontmatter.value.layout === "home")
|
|
||||||
return false;
|
|
||||||
if (frontmatter.value.aside != null)
|
|
||||||
return !!frontmatter.value.aside;
|
|
||||||
return theme2.value.aside !== false;
|
|
||||||
});
|
|
||||||
const isSidebarEnabled = computed(() => hasSidebar.value && is960.value);
|
|
||||||
const sidebarGroups = computed(() => {
|
|
||||||
return hasSidebar.value ? getSidebarGroups(sidebar.value) : [];
|
|
||||||
});
|
|
||||||
function open() {
|
|
||||||
isOpen.value = true;
|
|
||||||
}
|
|
||||||
function close() {
|
|
||||||
isOpen.value = false;
|
|
||||||
}
|
|
||||||
function toggle() {
|
|
||||||
isOpen.value ? close() : open();
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
isOpen,
|
|
||||||
sidebar,
|
|
||||||
sidebarGroups,
|
|
||||||
hasSidebar,
|
|
||||||
hasAside,
|
|
||||||
leftAside,
|
|
||||||
isSidebarEnabled,
|
|
||||||
open,
|
|
||||||
close,
|
|
||||||
toggle
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// node_modules/vitepress/dist/client/theme-default/composables/outline.js
|
|
||||||
var ignoreRE = /\b(?:VPBadge|header-anchor|footnote-ref|ignore-header)\b/;
|
|
||||||
var resolvedHeaders = [];
|
|
||||||
function getHeaders(range) {
|
|
||||||
const headers = [
|
|
||||||
...document.querySelectorAll(".VPDoc :where(h1,h2,h3,h4,h5,h6)")
|
|
||||||
].filter((el) => el.id && el.hasChildNodes()).map((el) => {
|
|
||||||
const level = Number(el.tagName[1]);
|
|
||||||
return {
|
|
||||||
element: el,
|
|
||||||
title: serializeHeader(el),
|
|
||||||
link: "#" + el.id,
|
|
||||||
level
|
|
||||||
};
|
|
||||||
});
|
|
||||||
return resolveHeaders(headers, range);
|
|
||||||
}
|
|
||||||
function serializeHeader(h) {
|
|
||||||
let ret = "";
|
|
||||||
for (const node of h.childNodes) {
|
|
||||||
if (node.nodeType === 1) {
|
|
||||||
if (ignoreRE.test(node.className))
|
|
||||||
continue;
|
|
||||||
ret += node.textContent;
|
|
||||||
} else if (node.nodeType === 3) {
|
|
||||||
ret += node.textContent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret.trim();
|
|
||||||
}
|
|
||||||
function resolveHeaders(headers, range) {
|
|
||||||
if (range === false) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
const levelsRange = (typeof range === "object" && !Array.isArray(range) ? range.level : range) || 2;
|
|
||||||
const [high, low] = typeof levelsRange === "number" ? [levelsRange, levelsRange] : levelsRange === "deep" ? [2, 6] : levelsRange;
|
|
||||||
return buildTree(headers, high, low);
|
|
||||||
}
|
|
||||||
function buildTree(data, min, max) {
|
|
||||||
resolvedHeaders.length = 0;
|
|
||||||
const result = [];
|
|
||||||
const stack = [];
|
|
||||||
data.forEach((item) => {
|
|
||||||
const node = { ...item, children: [] };
|
|
||||||
let parent = stack[stack.length - 1];
|
|
||||||
while (parent && parent.level >= node.level) {
|
|
||||||
stack.pop();
|
|
||||||
parent = stack[stack.length - 1];
|
|
||||||
}
|
|
||||||
if (node.element.classList.contains("ignore-header") || parent && "shouldIgnore" in parent) {
|
|
||||||
stack.push({ level: node.level, shouldIgnore: true });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (node.level > max || node.level < min)
|
|
||||||
return;
|
|
||||||
resolvedHeaders.push({ element: node.element, link: node.link });
|
|
||||||
if (parent)
|
|
||||||
parent.children.push(node);
|
|
||||||
else
|
|
||||||
result.push(node);
|
|
||||||
stack.push(node);
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// node_modules/vitepress/dist/client/theme-default/composables/local-nav.js
|
|
||||||
function useLocalNav() {
|
|
||||||
const { theme: theme2, frontmatter } = useData();
|
|
||||||
const headers = shallowRef([]);
|
|
||||||
const hasLocalNav = computed(() => {
|
|
||||||
return headers.value.length > 0;
|
|
||||||
});
|
|
||||||
onContentUpdated(() => {
|
|
||||||
headers.value = getHeaders(frontmatter.value.outline ?? theme2.value.outline);
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
headers,
|
|
||||||
hasLocalNav
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// node_modules/vitepress/dist/client/theme-default/without-fonts.js
|
|
||||||
var theme = {
|
|
||||||
Layout,
|
|
||||||
enhanceApp: ({ app }) => {
|
|
||||||
app.component("Badge", VPBadge);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var without_fonts_default = theme;
|
|
||||||
export {
|
|
||||||
default2 as VPBadge,
|
|
||||||
default3 as VPButton,
|
|
||||||
default4 as VPDocAsideSponsors,
|
|
||||||
default5 as VPFeatures,
|
|
||||||
default6 as VPHomeContent,
|
|
||||||
default7 as VPHomeFeatures,
|
|
||||||
default8 as VPHomeHero,
|
|
||||||
default9 as VPHomeSponsors,
|
|
||||||
default10 as VPImage,
|
|
||||||
default11 as VPLink,
|
|
||||||
default12 as VPNavBarSearch,
|
|
||||||
default13 as VPSocialLink,
|
|
||||||
default14 as VPSocialLinks,
|
|
||||||
default15 as VPSponsors,
|
|
||||||
default16 as VPTeamMembers,
|
|
||||||
default17 as VPTeamPage,
|
|
||||||
default18 as VPTeamPageSection,
|
|
||||||
default19 as VPTeamPageTitle,
|
|
||||||
without_fonts_default as default,
|
|
||||||
useLocalNav,
|
|
||||||
useSidebar
|
|
||||||
};
|
|
||||||
//# sourceMappingURL=@theme_index.js.map
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,40 +0,0 @@
|
|||||||
{
|
|
||||||
"hash": "33e82b21",
|
|
||||||
"configHash": "c6db372a",
|
|
||||||
"lockfileHash": "e3b0c442",
|
|
||||||
"browserHash": "66861689",
|
|
||||||
"optimized": {
|
|
||||||
"vue": {
|
|
||||||
"src": "../../../../../node_modules/vue/dist/vue.runtime.esm-bundler.js",
|
|
||||||
"file": "vue.js",
|
|
||||||
"fileHash": "415ad31e",
|
|
||||||
"needsInterop": false
|
|
||||||
},
|
|
||||||
"vitepress > @vue/devtools-api": {
|
|
||||||
"src": "../../../../../node_modules/@vue/devtools-api/dist/index.js",
|
|
||||||
"file": "vitepress___@vue_devtools-api.js",
|
|
||||||
"fileHash": "82c7da90",
|
|
||||||
"needsInterop": false
|
|
||||||
},
|
|
||||||
"vitepress > @vueuse/core": {
|
|
||||||
"src": "../../../../../node_modules/@vueuse/core/index.mjs",
|
|
||||||
"file": "vitepress___@vueuse_core.js",
|
|
||||||
"fileHash": "bf2a3493",
|
|
||||||
"needsInterop": false
|
|
||||||
},
|
|
||||||
"@theme/index": {
|
|
||||||
"src": "../../../../../node_modules/vitepress/dist/client/theme-default/index.js",
|
|
||||||
"file": "@theme_index.js",
|
|
||||||
"fileHash": "0d87b191",
|
|
||||||
"needsInterop": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"chunks": {
|
|
||||||
"chunk-RLEUDPPB": {
|
|
||||||
"file": "chunk-RLEUDPPB.js"
|
|
||||||
},
|
|
||||||
"chunk-3S55Y3P7": {
|
|
||||||
"file": "chunk-3S55Y3P7.js"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
12951
packages/docs/.vitepress/cache/deps/chunk-3S55Y3P7.js
vendored
12951
packages/docs/.vitepress/cache/deps/chunk-3S55Y3P7.js
vendored
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
9719
packages/docs/.vitepress/cache/deps/chunk-RLEUDPPB.js
vendored
9719
packages/docs/.vitepress/cache/deps/chunk-RLEUDPPB.js
vendored
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"type": "module"
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -1,583 +0,0 @@
|
|||||||
import {
|
|
||||||
DefaultMagicKeysAliasMap,
|
|
||||||
StorageSerializers,
|
|
||||||
TransitionPresets,
|
|
||||||
assert,
|
|
||||||
breakpointsAntDesign,
|
|
||||||
breakpointsBootstrapV5,
|
|
||||||
breakpointsElement,
|
|
||||||
breakpointsMasterCss,
|
|
||||||
breakpointsPrimeFlex,
|
|
||||||
breakpointsQuasar,
|
|
||||||
breakpointsSematic,
|
|
||||||
breakpointsTailwind,
|
|
||||||
breakpointsVuetify,
|
|
||||||
breakpointsVuetifyV2,
|
|
||||||
breakpointsVuetifyV3,
|
|
||||||
bypassFilter,
|
|
||||||
camelize,
|
|
||||||
clamp,
|
|
||||||
cloneFnJSON,
|
|
||||||
computedAsync,
|
|
||||||
computedEager,
|
|
||||||
computedInject,
|
|
||||||
computedWithControl,
|
|
||||||
containsProp,
|
|
||||||
controlledRef,
|
|
||||||
createEventHook,
|
|
||||||
createFetch,
|
|
||||||
createFilterWrapper,
|
|
||||||
createGlobalState,
|
|
||||||
createInjectionState,
|
|
||||||
createRef,
|
|
||||||
createReusableTemplate,
|
|
||||||
createSharedComposable,
|
|
||||||
createSingletonPromise,
|
|
||||||
createTemplatePromise,
|
|
||||||
createUnrefFn,
|
|
||||||
customStorageEventName,
|
|
||||||
debounceFilter,
|
|
||||||
defaultDocument,
|
|
||||||
defaultLocation,
|
|
||||||
defaultNavigator,
|
|
||||||
defaultWindow,
|
|
||||||
executeTransition,
|
|
||||||
extendRef,
|
|
||||||
formatDate,
|
|
||||||
formatTimeAgo,
|
|
||||||
get,
|
|
||||||
getLifeCycleTarget,
|
|
||||||
getSSRHandler,
|
|
||||||
hasOwn,
|
|
||||||
hyphenate,
|
|
||||||
identity,
|
|
||||||
increaseWithUnit,
|
|
||||||
injectLocal,
|
|
||||||
invoke,
|
|
||||||
isClient,
|
|
||||||
isDef,
|
|
||||||
isDefined,
|
|
||||||
isIOS,
|
|
||||||
isObject,
|
|
||||||
isWorker,
|
|
||||||
makeDestructurable,
|
|
||||||
mapGamepadToXbox360Controller,
|
|
||||||
noop,
|
|
||||||
normalizeDate,
|
|
||||||
notNullish,
|
|
||||||
now,
|
|
||||||
objectEntries,
|
|
||||||
objectOmit,
|
|
||||||
objectPick,
|
|
||||||
onClickOutside,
|
|
||||||
onElementRemoval,
|
|
||||||
onKeyDown,
|
|
||||||
onKeyPressed,
|
|
||||||
onKeyStroke,
|
|
||||||
onKeyUp,
|
|
||||||
onLongPress,
|
|
||||||
onStartTyping,
|
|
||||||
pausableFilter,
|
|
||||||
promiseTimeout,
|
|
||||||
provideLocal,
|
|
||||||
provideSSRWidth,
|
|
||||||
pxValue,
|
|
||||||
rand,
|
|
||||||
reactify,
|
|
||||||
reactifyObject,
|
|
||||||
reactiveComputed,
|
|
||||||
reactiveOmit,
|
|
||||||
reactivePick,
|
|
||||||
refAutoReset,
|
|
||||||
refDebounced,
|
|
||||||
refDefault,
|
|
||||||
refThrottled,
|
|
||||||
refWithControl,
|
|
||||||
resolveRef,
|
|
||||||
resolveUnref,
|
|
||||||
set,
|
|
||||||
setSSRHandler,
|
|
||||||
syncRef,
|
|
||||||
syncRefs,
|
|
||||||
templateRef,
|
|
||||||
throttleFilter,
|
|
||||||
timestamp,
|
|
||||||
toArray,
|
|
||||||
toReactive,
|
|
||||||
toRef,
|
|
||||||
toRefs,
|
|
||||||
toValue,
|
|
||||||
tryOnBeforeMount,
|
|
||||||
tryOnBeforeUnmount,
|
|
||||||
tryOnMounted,
|
|
||||||
tryOnScopeDispose,
|
|
||||||
tryOnUnmounted,
|
|
||||||
unrefElement,
|
|
||||||
until,
|
|
||||||
useActiveElement,
|
|
||||||
useAnimate,
|
|
||||||
useArrayDifference,
|
|
||||||
useArrayEvery,
|
|
||||||
useArrayFilter,
|
|
||||||
useArrayFind,
|
|
||||||
useArrayFindIndex,
|
|
||||||
useArrayFindLast,
|
|
||||||
useArrayIncludes,
|
|
||||||
useArrayJoin,
|
|
||||||
useArrayMap,
|
|
||||||
useArrayReduce,
|
|
||||||
useArraySome,
|
|
||||||
useArrayUnique,
|
|
||||||
useAsyncQueue,
|
|
||||||
useAsyncState,
|
|
||||||
useBase64,
|
|
||||||
useBattery,
|
|
||||||
useBluetooth,
|
|
||||||
useBreakpoints,
|
|
||||||
useBroadcastChannel,
|
|
||||||
useBrowserLocation,
|
|
||||||
useCached,
|
|
||||||
useClipboard,
|
|
||||||
useClipboardItems,
|
|
||||||
useCloned,
|
|
||||||
useColorMode,
|
|
||||||
useConfirmDialog,
|
|
||||||
useCountdown,
|
|
||||||
useCounter,
|
|
||||||
useCssVar,
|
|
||||||
useCurrentElement,
|
|
||||||
useCycleList,
|
|
||||||
useDark,
|
|
||||||
useDateFormat,
|
|
||||||
useDebounceFn,
|
|
||||||
useDebouncedRefHistory,
|
|
||||||
useDeviceMotion,
|
|
||||||
useDeviceOrientation,
|
|
||||||
useDevicePixelRatio,
|
|
||||||
useDevicesList,
|
|
||||||
useDisplayMedia,
|
|
||||||
useDocumentVisibility,
|
|
||||||
useDraggable,
|
|
||||||
useDropZone,
|
|
||||||
useElementBounding,
|
|
||||||
useElementByPoint,
|
|
||||||
useElementHover,
|
|
||||||
useElementSize,
|
|
||||||
useElementVisibility,
|
|
||||||
useEventBus,
|
|
||||||
useEventListener,
|
|
||||||
useEventSource,
|
|
||||||
useEyeDropper,
|
|
||||||
useFavicon,
|
|
||||||
useFetch,
|
|
||||||
useFileDialog,
|
|
||||||
useFileSystemAccess,
|
|
||||||
useFocus,
|
|
||||||
useFocusWithin,
|
|
||||||
useFps,
|
|
||||||
useFullscreen,
|
|
||||||
useGamepad,
|
|
||||||
useGeolocation,
|
|
||||||
useIdle,
|
|
||||||
useImage,
|
|
||||||
useInfiniteScroll,
|
|
||||||
useIntersectionObserver,
|
|
||||||
useInterval,
|
|
||||||
useIntervalFn,
|
|
||||||
useKeyModifier,
|
|
||||||
useLastChanged,
|
|
||||||
useLocalStorage,
|
|
||||||
useMagicKeys,
|
|
||||||
useManualRefHistory,
|
|
||||||
useMediaControls,
|
|
||||||
useMediaQuery,
|
|
||||||
useMemoize,
|
|
||||||
useMemory,
|
|
||||||
useMounted,
|
|
||||||
useMouse,
|
|
||||||
useMouseInElement,
|
|
||||||
useMousePressed,
|
|
||||||
useMutationObserver,
|
|
||||||
useNavigatorLanguage,
|
|
||||||
useNetwork,
|
|
||||||
useNow,
|
|
||||||
useObjectUrl,
|
|
||||||
useOffsetPagination,
|
|
||||||
useOnline,
|
|
||||||
usePageLeave,
|
|
||||||
useParallax,
|
|
||||||
useParentElement,
|
|
||||||
usePerformanceObserver,
|
|
||||||
usePermission,
|
|
||||||
usePointer,
|
|
||||||
usePointerLock,
|
|
||||||
usePointerSwipe,
|
|
||||||
usePreferredColorScheme,
|
|
||||||
usePreferredContrast,
|
|
||||||
usePreferredDark,
|
|
||||||
usePreferredLanguages,
|
|
||||||
usePreferredReducedMotion,
|
|
||||||
usePreferredReducedTransparency,
|
|
||||||
usePrevious,
|
|
||||||
useRafFn,
|
|
||||||
useRefHistory,
|
|
||||||
useResizeObserver,
|
|
||||||
useSSRWidth,
|
|
||||||
useScreenOrientation,
|
|
||||||
useScreenSafeArea,
|
|
||||||
useScriptTag,
|
|
||||||
useScroll,
|
|
||||||
useScrollLock,
|
|
||||||
useSessionStorage,
|
|
||||||
useShare,
|
|
||||||
useSorted,
|
|
||||||
useSpeechRecognition,
|
|
||||||
useSpeechSynthesis,
|
|
||||||
useStepper,
|
|
||||||
useStorage,
|
|
||||||
useStorageAsync,
|
|
||||||
useStyleTag,
|
|
||||||
useSupported,
|
|
||||||
useSwipe,
|
|
||||||
useTemplateRefsList,
|
|
||||||
useTextDirection,
|
|
||||||
useTextSelection,
|
|
||||||
useTextareaAutosize,
|
|
||||||
useThrottleFn,
|
|
||||||
useThrottledRefHistory,
|
|
||||||
useTimeAgo,
|
|
||||||
useTimeout,
|
|
||||||
useTimeoutFn,
|
|
||||||
useTimeoutPoll,
|
|
||||||
useTimestamp,
|
|
||||||
useTitle,
|
|
||||||
useToNumber,
|
|
||||||
useToString,
|
|
||||||
useToggle,
|
|
||||||
useTransition,
|
|
||||||
useUrlSearchParams,
|
|
||||||
useUserMedia,
|
|
||||||
useVModel,
|
|
||||||
useVModels,
|
|
||||||
useVibrate,
|
|
||||||
useVirtualList,
|
|
||||||
useWakeLock,
|
|
||||||
useWebNotification,
|
|
||||||
useWebSocket,
|
|
||||||
useWebWorker,
|
|
||||||
useWebWorkerFn,
|
|
||||||
useWindowFocus,
|
|
||||||
useWindowScroll,
|
|
||||||
useWindowSize,
|
|
||||||
watchArray,
|
|
||||||
watchAtMost,
|
|
||||||
watchDebounced,
|
|
||||||
watchDeep,
|
|
||||||
watchIgnorable,
|
|
||||||
watchImmediate,
|
|
||||||
watchOnce,
|
|
||||||
watchPausable,
|
|
||||||
watchThrottled,
|
|
||||||
watchTriggerable,
|
|
||||||
watchWithFilter,
|
|
||||||
whenever
|
|
||||||
} from "./chunk-RLEUDPPB.js";
|
|
||||||
import "./chunk-3S55Y3P7.js";
|
|
||||||
export {
|
|
||||||
DefaultMagicKeysAliasMap,
|
|
||||||
StorageSerializers,
|
|
||||||
TransitionPresets,
|
|
||||||
assert,
|
|
||||||
computedAsync as asyncComputed,
|
|
||||||
refAutoReset as autoResetRef,
|
|
||||||
breakpointsAntDesign,
|
|
||||||
breakpointsBootstrapV5,
|
|
||||||
breakpointsElement,
|
|
||||||
breakpointsMasterCss,
|
|
||||||
breakpointsPrimeFlex,
|
|
||||||
breakpointsQuasar,
|
|
||||||
breakpointsSematic,
|
|
||||||
breakpointsTailwind,
|
|
||||||
breakpointsVuetify,
|
|
||||||
breakpointsVuetifyV2,
|
|
||||||
breakpointsVuetifyV3,
|
|
||||||
bypassFilter,
|
|
||||||
camelize,
|
|
||||||
clamp,
|
|
||||||
cloneFnJSON,
|
|
||||||
computedAsync,
|
|
||||||
computedEager,
|
|
||||||
computedInject,
|
|
||||||
computedWithControl,
|
|
||||||
containsProp,
|
|
||||||
computedWithControl as controlledComputed,
|
|
||||||
controlledRef,
|
|
||||||
createEventHook,
|
|
||||||
createFetch,
|
|
||||||
createFilterWrapper,
|
|
||||||
createGlobalState,
|
|
||||||
createInjectionState,
|
|
||||||
reactify as createReactiveFn,
|
|
||||||
createRef,
|
|
||||||
createReusableTemplate,
|
|
||||||
createSharedComposable,
|
|
||||||
createSingletonPromise,
|
|
||||||
createTemplatePromise,
|
|
||||||
createUnrefFn,
|
|
||||||
customStorageEventName,
|
|
||||||
debounceFilter,
|
|
||||||
refDebounced as debouncedRef,
|
|
||||||
watchDebounced as debouncedWatch,
|
|
||||||
defaultDocument,
|
|
||||||
defaultLocation,
|
|
||||||
defaultNavigator,
|
|
||||||
defaultWindow,
|
|
||||||
computedEager as eagerComputed,
|
|
||||||
executeTransition,
|
|
||||||
extendRef,
|
|
||||||
formatDate,
|
|
||||||
formatTimeAgo,
|
|
||||||
get,
|
|
||||||
getLifeCycleTarget,
|
|
||||||
getSSRHandler,
|
|
||||||
hasOwn,
|
|
||||||
hyphenate,
|
|
||||||
identity,
|
|
||||||
watchIgnorable as ignorableWatch,
|
|
||||||
increaseWithUnit,
|
|
||||||
injectLocal,
|
|
||||||
invoke,
|
|
||||||
isClient,
|
|
||||||
isDef,
|
|
||||||
isDefined,
|
|
||||||
isIOS,
|
|
||||||
isObject,
|
|
||||||
isWorker,
|
|
||||||
makeDestructurable,
|
|
||||||
mapGamepadToXbox360Controller,
|
|
||||||
noop,
|
|
||||||
normalizeDate,
|
|
||||||
notNullish,
|
|
||||||
now,
|
|
||||||
objectEntries,
|
|
||||||
objectOmit,
|
|
||||||
objectPick,
|
|
||||||
onClickOutside,
|
|
||||||
onElementRemoval,
|
|
||||||
onKeyDown,
|
|
||||||
onKeyPressed,
|
|
||||||
onKeyStroke,
|
|
||||||
onKeyUp,
|
|
||||||
onLongPress,
|
|
||||||
onStartTyping,
|
|
||||||
pausableFilter,
|
|
||||||
watchPausable as pausableWatch,
|
|
||||||
promiseTimeout,
|
|
||||||
provideLocal,
|
|
||||||
provideSSRWidth,
|
|
||||||
pxValue,
|
|
||||||
rand,
|
|
||||||
reactify,
|
|
||||||
reactifyObject,
|
|
||||||
reactiveComputed,
|
|
||||||
reactiveOmit,
|
|
||||||
reactivePick,
|
|
||||||
refAutoReset,
|
|
||||||
refDebounced,
|
|
||||||
refDefault,
|
|
||||||
refThrottled,
|
|
||||||
refWithControl,
|
|
||||||
resolveRef,
|
|
||||||
resolveUnref,
|
|
||||||
set,
|
|
||||||
setSSRHandler,
|
|
||||||
syncRef,
|
|
||||||
syncRefs,
|
|
||||||
templateRef,
|
|
||||||
throttleFilter,
|
|
||||||
refThrottled as throttledRef,
|
|
||||||
watchThrottled as throttledWatch,
|
|
||||||
timestamp,
|
|
||||||
toArray,
|
|
||||||
toReactive,
|
|
||||||
toRef,
|
|
||||||
toRefs,
|
|
||||||
toValue,
|
|
||||||
tryOnBeforeMount,
|
|
||||||
tryOnBeforeUnmount,
|
|
||||||
tryOnMounted,
|
|
||||||
tryOnScopeDispose,
|
|
||||||
tryOnUnmounted,
|
|
||||||
unrefElement,
|
|
||||||
until,
|
|
||||||
useActiveElement,
|
|
||||||
useAnimate,
|
|
||||||
useArrayDifference,
|
|
||||||
useArrayEvery,
|
|
||||||
useArrayFilter,
|
|
||||||
useArrayFind,
|
|
||||||
useArrayFindIndex,
|
|
||||||
useArrayFindLast,
|
|
||||||
useArrayIncludes,
|
|
||||||
useArrayJoin,
|
|
||||||
useArrayMap,
|
|
||||||
useArrayReduce,
|
|
||||||
useArraySome,
|
|
||||||
useArrayUnique,
|
|
||||||
useAsyncQueue,
|
|
||||||
useAsyncState,
|
|
||||||
useBase64,
|
|
||||||
useBattery,
|
|
||||||
useBluetooth,
|
|
||||||
useBreakpoints,
|
|
||||||
useBroadcastChannel,
|
|
||||||
useBrowserLocation,
|
|
||||||
useCached,
|
|
||||||
useClipboard,
|
|
||||||
useClipboardItems,
|
|
||||||
useCloned,
|
|
||||||
useColorMode,
|
|
||||||
useConfirmDialog,
|
|
||||||
useCountdown,
|
|
||||||
useCounter,
|
|
||||||
useCssVar,
|
|
||||||
useCurrentElement,
|
|
||||||
useCycleList,
|
|
||||||
useDark,
|
|
||||||
useDateFormat,
|
|
||||||
refDebounced as useDebounce,
|
|
||||||
useDebounceFn,
|
|
||||||
useDebouncedRefHistory,
|
|
||||||
useDeviceMotion,
|
|
||||||
useDeviceOrientation,
|
|
||||||
useDevicePixelRatio,
|
|
||||||
useDevicesList,
|
|
||||||
useDisplayMedia,
|
|
||||||
useDocumentVisibility,
|
|
||||||
useDraggable,
|
|
||||||
useDropZone,
|
|
||||||
useElementBounding,
|
|
||||||
useElementByPoint,
|
|
||||||
useElementHover,
|
|
||||||
useElementSize,
|
|
||||||
useElementVisibility,
|
|
||||||
useEventBus,
|
|
||||||
useEventListener,
|
|
||||||
useEventSource,
|
|
||||||
useEyeDropper,
|
|
||||||
useFavicon,
|
|
||||||
useFetch,
|
|
||||||
useFileDialog,
|
|
||||||
useFileSystemAccess,
|
|
||||||
useFocus,
|
|
||||||
useFocusWithin,
|
|
||||||
useFps,
|
|
||||||
useFullscreen,
|
|
||||||
useGamepad,
|
|
||||||
useGeolocation,
|
|
||||||
useIdle,
|
|
||||||
useImage,
|
|
||||||
useInfiniteScroll,
|
|
||||||
useIntersectionObserver,
|
|
||||||
useInterval,
|
|
||||||
useIntervalFn,
|
|
||||||
useKeyModifier,
|
|
||||||
useLastChanged,
|
|
||||||
useLocalStorage,
|
|
||||||
useMagicKeys,
|
|
||||||
useManualRefHistory,
|
|
||||||
useMediaControls,
|
|
||||||
useMediaQuery,
|
|
||||||
useMemoize,
|
|
||||||
useMemory,
|
|
||||||
useMounted,
|
|
||||||
useMouse,
|
|
||||||
useMouseInElement,
|
|
||||||
useMousePressed,
|
|
||||||
useMutationObserver,
|
|
||||||
useNavigatorLanguage,
|
|
||||||
useNetwork,
|
|
||||||
useNow,
|
|
||||||
useObjectUrl,
|
|
||||||
useOffsetPagination,
|
|
||||||
useOnline,
|
|
||||||
usePageLeave,
|
|
||||||
useParallax,
|
|
||||||
useParentElement,
|
|
||||||
usePerformanceObserver,
|
|
||||||
usePermission,
|
|
||||||
usePointer,
|
|
||||||
usePointerLock,
|
|
||||||
usePointerSwipe,
|
|
||||||
usePreferredColorScheme,
|
|
||||||
usePreferredContrast,
|
|
||||||
usePreferredDark,
|
|
||||||
usePreferredLanguages,
|
|
||||||
usePreferredReducedMotion,
|
|
||||||
usePreferredReducedTransparency,
|
|
||||||
usePrevious,
|
|
||||||
useRafFn,
|
|
||||||
useRefHistory,
|
|
||||||
useResizeObserver,
|
|
||||||
useSSRWidth,
|
|
||||||
useScreenOrientation,
|
|
||||||
useScreenSafeArea,
|
|
||||||
useScriptTag,
|
|
||||||
useScroll,
|
|
||||||
useScrollLock,
|
|
||||||
useSessionStorage,
|
|
||||||
useShare,
|
|
||||||
useSorted,
|
|
||||||
useSpeechRecognition,
|
|
||||||
useSpeechSynthesis,
|
|
||||||
useStepper,
|
|
||||||
useStorage,
|
|
||||||
useStorageAsync,
|
|
||||||
useStyleTag,
|
|
||||||
useSupported,
|
|
||||||
useSwipe,
|
|
||||||
useTemplateRefsList,
|
|
||||||
useTextDirection,
|
|
||||||
useTextSelection,
|
|
||||||
useTextareaAutosize,
|
|
||||||
refThrottled as useThrottle,
|
|
||||||
useThrottleFn,
|
|
||||||
useThrottledRefHistory,
|
|
||||||
useTimeAgo,
|
|
||||||
useTimeout,
|
|
||||||
useTimeoutFn,
|
|
||||||
useTimeoutPoll,
|
|
||||||
useTimestamp,
|
|
||||||
useTitle,
|
|
||||||
useToNumber,
|
|
||||||
useToString,
|
|
||||||
useToggle,
|
|
||||||
useTransition,
|
|
||||||
useUrlSearchParams,
|
|
||||||
useUserMedia,
|
|
||||||
useVModel,
|
|
||||||
useVModels,
|
|
||||||
useVibrate,
|
|
||||||
useVirtualList,
|
|
||||||
useWakeLock,
|
|
||||||
useWebNotification,
|
|
||||||
useWebSocket,
|
|
||||||
useWebWorker,
|
|
||||||
useWebWorkerFn,
|
|
||||||
useWindowFocus,
|
|
||||||
useWindowScroll,
|
|
||||||
useWindowSize,
|
|
||||||
watchArray,
|
|
||||||
watchAtMost,
|
|
||||||
watchDebounced,
|
|
||||||
watchDeep,
|
|
||||||
watchIgnorable,
|
|
||||||
watchImmediate,
|
|
||||||
watchOnce,
|
|
||||||
watchPausable,
|
|
||||||
watchThrottled,
|
|
||||||
watchTriggerable,
|
|
||||||
watchWithFilter,
|
|
||||||
whenever
|
|
||||||
};
|
|
||||||
//# sourceMappingURL=vitepress___@vueuse_core.js.map
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"version": 3,
|
|
||||||
"sources": [],
|
|
||||||
"sourcesContent": [],
|
|
||||||
"mappings": "",
|
|
||||||
"names": []
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user