diff --git a/bun.lock b/bun.lock index 8103590..5ee9a83 100644 --- a/bun.lock +++ b/bun.lock @@ -9,6 +9,7 @@ }, "devDependencies": { "@tailwindcss/vite": "^4.2.2", + "vite": "^8.0.0", "vitepress": "^1.6.4", }, }, @@ -64,6 +65,12 @@ "@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=="], @@ -124,6 +131,44 @@ "@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=="], @@ -220,6 +265,8 @@ "@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=="], @@ -306,6 +353,8 @@ "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=="], @@ -376,6 +425,8 @@ "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=="], @@ -390,6 +441,8 @@ "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=="], @@ -412,8 +465,12 @@ "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=="], @@ -428,7 +485,7 @@ "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@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=="], + "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=="], @@ -447,5 +504,7 @@ "@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=="], } } diff --git a/docs/404.html b/docs/404.html index 63191a8..c4bdb55 100644 --- a/docs/404.html +++ b/docs/404.html @@ -16,7 +16,7 @@
- + \ No newline at end of file diff --git a/docs/api/components.html b/docs/api/components.html index 446834f..8387cd0 100644 --- a/docs/api/components.html +++ b/docs/api/components.html @@ -18,7 +18,7 @@ -
Skip to content

Components API 🧩

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.

$.component(tagName, setupFunction, observedAttributes, useShadowDOM)

Creates a custom element with reactive properties and automatic dependency tracking.

javascript
import { $, html } from 'sigpro';
+    
Skip to content

Components API 🧩

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.

$.component(tagName, setupFunction, observedAttributes, useShadowDOM)

Creates a custom element with reactive properties and automatic dependency tracking.

javascript
import { $, html } from 'sigpro';
 
 $.component('my-button', (props, { slot, emit }) => {
   return html`
@@ -589,7 +589,7 @@
     </Card>
   </div>
 `;

🎯 Decision Guide: Light DOM vs Shadow DOM

Use Light DOM (false) when...Use Shadow DOM (true) when...
Component is part of your main appBuilding a UI library for others
Using global CSS (Tailwind, Bootstrap)Creating embeddable widgets
Need to inherit theme variablesStyles must be pixel-perfect everywhere
Working with existing design systemComponent has complex, specific styles
Quick prototypingDistributing to different projects
Form elements that should match siteNeed style isolation/encapsulation

📊 Summary

FeatureDescription
Native Web ComponentsBuilt on Custom Elements standard
Reactive PropsObserved attributes become signals
Two Rendering ModesLight DOM (default) or Shadow DOM
Automatic CleanupEffects and listeners cleaned up on disconnect
Event SystemCustom events with emit()
Slot SupportFull slot API for content projection
Zero DependenciesPure vanilla JavaScript

Pro Tip: 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.

- + \ No newline at end of file diff --git a/docs/api/effects.html b/docs/api/effects.html index d9c3dfc..123ae0c 100644 --- a/docs/api/effects.html +++ b/docs/api/effects.html @@ -18,7 +18,7 @@ -
Skip to content

Effects API 🔄

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.

Core Concepts

What is an Effect?

An effect is a function that:

  • Runs immediately when created
  • Tracks all signals read during its execution
  • Re-runs automatically when any tracked signal changes
  • Can return a cleanup function that runs before the next execution or when the effect is stopped

How Effects Work

  1. When an effect runs, it sets itself as the activeEffect
  2. Any signal read during execution adds the effect to its subscribers
  3. When a signal changes, it queues all its subscribers
  4. Effects are batched and run in the next microtask
  5. If an effect returns a function, it's stored as a cleanup handler

$.effect(effectFn)

Creates a reactive effect that automatically tracks dependencies and re-runs when they change.

javascript
import { $ } from 'sigpro';
+    
Skip to content

Effects API 🔄

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.

Core Concepts

What is an Effect?

An effect is a function that:

  • Runs immediately when created
  • Tracks all signals read during its execution
  • Re-runs automatically when any tracked signal changes
  • Can return a cleanup function that runs before the next execution or when the effect is stopped

How Effects Work

  1. When an effect runs, it sets itself as the activeEffect
  2. Any signal read during execution adds the effect to its subscribers
  3. When a signal changes, it queues all its subscribers
  4. Effects are batched and run in the next microtask
  5. If an effect returns a function, it's stored as a cleanup handler

$.effect(effectFn)

Creates a reactive effect that automatically tracks dependencies and re-runs when they change.

javascript
import { $ } from 'sigpro';
 
 const count = $(0);
 
@@ -781,7 +781,7 @@
 inspector.trackedEffect(() => {
   console.log('Count:', count());
 }, 'counter-effect');

📊 Summary

FeatureDescription
Automatic TrackingDependencies tracked automatically
Cleanup FunctionsReturn function to clean up resources
Batch UpdatesMultiple changes batched in microtask
Manual StopCan stop effects with returned function
Nested EffectsEffects can contain other effects
Auto-cleanupEffects in pages/components auto-cleaned

Pro Tip: Effects are the perfect place for side effects like DOM updates, data fetching, and subscriptions. Keep them focused and always clean up resources!

- + \ No newline at end of file diff --git a/docs/api/fetch.html b/docs/api/fetch.html index 0fc61bd..082619d 100644 --- a/docs/api/fetch.html +++ b/docs/api/fetch.html @@ -18,7 +18,7 @@ -
Skip to content

Fetch API 🌐

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.

Core Concepts

What is $.fetch?

A ultra-simple fetch wrapper that:

  • Automatically handles JSON serialization and parsing
  • Integrates with signals for loading state
  • Returns null on error (no try/catch needed for basic usage)
  • Works great with effects for reactive data fetching

$.fetch(url, data, [loading])

Makes a POST request with JSON data and optional loading signal.

javascript
import { $ } from 'sigpro';
+    
Skip to content

Fetch API 🌐

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.

Core Concepts

What is $.fetch?

A ultra-simple fetch wrapper that:

  • Automatically handles JSON serialization and parsing
  • Integrates with signals for loading state
  • Returns null on error (no try/catch needed for basic usage)
  • Works great with effects for reactive data fetching

$.fetch(url, data, [loading])

Makes a POST request with JSON data and optional loading signal.

javascript
import { $ } from 'sigpro';
 
 const loading = $(false);
 
@@ -867,7 +867,7 @@
     error('Failed to load data');
   }
 }

Pro Tip: Combine $.fetch with $.effect and loading signals for a complete reactive data fetching solution. The loading signal integration makes it trivial to show loading states in your UI.

- + \ No newline at end of file diff --git a/docs/api/pages.html b/docs/api/pages.html index 0d01f88..1bf0f1e 100644 --- a/docs/api/pages.html +++ b/docs/api/pages.html @@ -18,7 +18,7 @@ -
Skip to content

Pages API 📄

Pages in SigPro are special components designed for route-based navigation with automatic cleanup. 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.

$.page(setupFunction)

Creates a page with automatic cleanup of all signals and effects when navigated away.

javascript
import { $, html } from 'sigpro';
+    
Skip to content

Pages API 📄

Pages in SigPro are special components designed for route-based navigation with automatic cleanup. 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.

$.page(setupFunction)

Creates a page with automatic cleanup of all signals and effects when navigated away.

javascript
import { $, html } from 'sigpro';
 
 export default $.page(() => {
   // All signals and effects created here
@@ -399,7 +399,7 @@
     </div>
   `;
 });

📊 Summary

FeatureDescription
Automatic CleanupAll signals, effects, and resources auto-cleaned on navigation
Memory SafeNo memory leaks, even with complex nested effects
Router IntegrationDesigned to work perfectly with $.router
ParametersAccess route parameters via params object
Manual CleanuponUnmount for custom cleanup needs
Zero ConfigurationJust wrap your page in $.page() and it works

Pro Tip: Always wrap route-based views in $.page() to ensure proper cleanup. This prevents memory leaks and ensures your app stays performant even after many navigation changes.

- + \ No newline at end of file diff --git a/docs/api/quick.html b/docs/api/quick.html index 5813651..05e2a79 100644 --- a/docs/api/quick.html +++ b/docs/api/quick.html @@ -18,7 +18,7 @@ -
Skip to content

Quick API Reference ⚡

A comprehensive reference for all SigPro APIs. Everything you need to build reactive web applications with signals and web components.

📋 API Functions Reference

FunctionDescriptionExample
$(initialValue)Creates a reactive signal (getter/setter)const count = $(0)
$(computedFn)Creates a computed signalconst full = $(() => first() + last())
$.effect(fn)Runs effect when dependencies change$.effect(() => console.log(count()))
$.page(setupFn)Creates a page with automatic cleanup$.page(() => html
Page
)
$.component(tagName, setupFn, attrs, useShadow)Creates reactive Web Component$.component('my-menu', setup, ['items'])
$.router(routes)Creates a hash-based router$.router([{path:'/', component:Home}])
$.router.go(path)Navigates to a route$.router.go('/user/42')
$.fetch(url, data, loadingSignal)Fetch wrapper with loading stateconst data = await $.fetch('/api', data, loading)
$.storage(key, initialValue, storageType)Persistent signal (local/sessionStorage)const theme = $.storage('theme', 'light')
html`...`Template literal for reactive HTMLhtml`<div>${count}</div>`

Signal Methods

MethodDescriptionExample
signal()Gets current valuecount()
signal(newValue)Sets new valuecount(5)
signal(prev => new)Updates using previous valuecount(c => c + 1)

Component Context Properties

PropertyDescriptionExample
propsReactive component propertiesprops.title()
slot(name)Accesses slot contentslot() or slot('footer')
emit(event, data)Dispatches custom eventemit('update', value)
onUnmount(cb)Registers cleanup callbackonUnmount(() => clearInterval(timer))

Page Context Properties

PropertyDescriptionExample
paramsRoute parametersparams.id, params.slug
onUnmount(cb)Registers cleanup callbackonUnmount(() => clearInterval(timer))

HTML Directives

DirectiveDescriptionExample
@eventEvent listener@click=${handler}
:propertyTwo-way binding:value=${signal}
?attributeBoolean attribute?disabled=${signal}
.propertyDOM property binding.scrollTop=${value}
class:nameConditional classclass:active=${isActive}

📡 Signals - $(initialValue)

Creates a reactive value that notifies dependents when changed.

PatternExampleDescription
Basic Signalconst count = $(0)Create signal with initial value
Gettercount()Read current value
Settercount(5)Set new value directly
Updatercount(prev => prev + 1)Update based on previous value
Computedconst full = $(() => first() + last())Auto-updating derived signal

Examples

javascript
// Basic signal
+    
Skip to content

Quick API Reference ⚡

A comprehensive reference for all SigPro APIs. Everything you need to build reactive web applications with signals and web components.

📋 API Functions Reference

FunctionDescriptionExample
$(initialValue)Creates a reactive signal (getter/setter)const count = $(0)
$(computedFn)Creates a computed signalconst full = $(() => first() + last())
$.effect(fn)Runs effect when dependencies change$.effect(() => console.log(count()))
$.page(setupFn)Creates a page with automatic cleanup$.page(() => html
Page
)
$.component(tagName, setupFn, attrs, useShadow)Creates reactive Web Component$.component('my-menu', setup, ['items'])
$.router(routes)Creates a hash-based router$.router([{path:'/', component:Home}])
$.router.go(path)Navigates to a route$.router.go('/user/42')
$.fetch(url, data, loadingSignal)Fetch wrapper with loading stateconst data = await $.fetch('/api', data, loading)
$.storage(key, initialValue, storageType)Persistent signal (local/sessionStorage)const theme = $.storage('theme', 'light')
html`...`Template literal for reactive HTMLhtml`<div>${count}</div>`

Signal Methods

MethodDescriptionExample
signal()Gets current valuecount()
signal(newValue)Sets new valuecount(5)
signal(prev => new)Updates using previous valuecount(c => c + 1)

Component Context Properties

PropertyDescriptionExample
propsReactive component propertiesprops.title()
slot(name)Accesses slot contentslot() or slot('footer')
emit(event, data)Dispatches custom eventemit('update', value)
onUnmount(cb)Registers cleanup callbackonUnmount(() => clearInterval(timer))

Page Context Properties

PropertyDescriptionExample
paramsRoute parametersparams.id, params.slug
onUnmount(cb)Registers cleanup callbackonUnmount(() => clearInterval(timer))

HTML Directives

DirectiveDescriptionExample
@eventEvent listener@click=${handler}
:propertyTwo-way binding:value=${signal}
?attributeBoolean attribute?disabled=${signal}
.propertyDOM property binding.scrollTop=${value}
class:nameConditional classclass:active=${isActive}

📡 Signals - $(initialValue)

Creates a reactive value that notifies dependents when changed.

PatternExampleDescription
Basic Signalconst count = $(0)Create signal with initial value
Gettercount()Read current value
Settercount(5)Set new value directly
Updatercount(prev => prev + 1)Update based on previous value
Computedconst full = $(() => first() + last())Auto-updating derived signal

Examples

javascript
// Basic signal
 const count = $(0);
 console.log(count()); // 0
 count(5);
@@ -211,7 +211,7 @@
     </div>
   `;
 }, ['user-id']); // Observe userId attribute
- + \ No newline at end of file diff --git a/docs/api/routing.html b/docs/api/routing.html index 4e56eba..7344730 100644 --- a/docs/api/routing.html +++ b/docs/api/routing.html @@ -18,7 +18,7 @@ -
Skip to content

Routing API 🌐

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 $.page for automatic cleanup.

Why Hash-Based Routing?

Hash routing (#/about) works everywhere - no server configuration needed. Perfect for:

  • Static sites and SPAs
  • GitHub Pages, Netlify, any static hosting
  • Local development without a server
  • Projects that need to work immediately

$.router(routes)

Creates a hash-based router that renders the matching component and handles navigation.

javascript
import { $, html } from 'sigpro';
+    
Skip to content

Routing API 🌐

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 $.page for automatic cleanup.

Why Hash-Based Routing?

Hash routing (#/about) works everywhere - no server configuration needed. Perfect for:

  • Static sites and SPAs
  • GitHub Pages, Netlify, any static hosting
  • Local development without a server
  • Projects that need to work immediately

$.router(routes)

Creates a hash-based router that renders the matching component and handles navigation.

javascript
import { $, html } from 'sigpro';
 import HomePage from './pages/Home.js';
 import AboutPage from './pages/About.js';
 import UserPage from './pages/User.js';
@@ -622,7 +622,7 @@
 
 // Navigation helper (available globally)
 window.navigate = $.router.go;

📊 Summary

FeatureDescription
Hash-basedWorks everywhere, no server config
Route Parameters:param syntax for dynamic segments
RegExp SupportAdvanced pattern matching
Query ParametersSupport for ?key=value in URLs
Programmatic Navigation$.router.go(path)
Auto-cleanupWorks with $.page for memory management
Zero DependenciesPure vanilla JavaScript
Lazy Loading ReadyEasy code splitting

Pro Tip: 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.

- + \ No newline at end of file diff --git a/docs/api/signals.html b/docs/api/signals.html index 15a7021..ba4bb95 100644 --- a/docs/api/signals.html +++ b/docs/api/signals.html @@ -18,7 +18,7 @@ -
Skip to content

Signals API 📡

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.

Core Concepts

What is a Signal?

A signal is a function that holds a value and notifies dependents when that value changes. Signals can be:

  • Basic signals - Hold simple values (numbers, strings, objects)
  • Computed signals - Derive values from other signals
  • Persistent signals - Automatically sync with localStorage/sessionStorage

How Reactivity Works

SigPro uses automatic dependency tracking:

  1. When you read a signal inside an effect, the effect becomes a subscriber
  2. When the signal's value changes, all subscribers are notified
  3. Updates are batched using microtasks for optimal performance
  4. Only the exact nodes that depend on changed values are updated

$(initialValue)

Creates a reactive signal. The behavior changes based on the type of initialValue:

  • If initialValue is a function, creates a computed signal
  • Otherwise, creates a basic signal
javascript
import { $ } from 'sigpro';
+    
Skip to content

Signals API 📡

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.

Core Concepts

What is a Signal?

A signal is a function that holds a value and notifies dependents when that value changes. Signals can be:

  • Basic signals - Hold simple values (numbers, strings, objects)
  • Computed signals - Derive values from other signals
  • Persistent signals - Automatically sync with localStorage/sessionStorage

How Reactivity Works

SigPro uses automatic dependency tracking:

  1. When you read a signal inside an effect, the effect becomes a subscriber
  2. When the signal's value changes, all subscribers are notified
  3. Updates are batched using microtasks for optimal performance
  4. Only the exact nodes that depend on changed values are updated

$(initialValue)

Creates a reactive signal. The behavior changes based on the type of initialValue:

  • If initialValue is a function, creates a computed signal
  • Otherwise, creates a basic signal
javascript
import { $ } from 'sigpro';
 
 // Basic signal
 const count = $(0);
@@ -677,7 +677,7 @@
 
 console.log(inspector.getInfo());
 // { count: { subscribers: 0, value: 0 }, doubled: { subscribers: 0, value: 0 } }

📊 Summary

FeatureDescription
Basic SignalsHold values and notify on change
Computed SignalsAuto-updating derived values
Automatic TrackingDependencies tracked automatically
Batch UpdatesMultiple updates batched in microtask
Infinite Loop ProtectionPrevents reactive cycles
Zero DependenciesPure vanilla JavaScript

Pro Tip: Signals are the foundation of reactivity in SigPro. Master them, and you've mastered 80% of the library!

- + \ No newline at end of file diff --git a/docs/api/storage.html b/docs/api/storage.html index f2652a3..642b0d9 100644 --- a/docs/api/storage.html +++ b/docs/api/storage.html @@ -18,7 +18,7 @@ -
Skip to content

Storage API 💾

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.

Core Concepts

What is Persistent Storage?

Persistent signals are special signals that:

  • Initialize from storage (localStorage/sessionStorage) if a saved value exists
  • Auto-save whenever the signal value changes
  • Handle JSON serialization automatically
  • Clean up when set to null or undefined

Storage Types

StoragePersistenceUse Case
localStorageForever (until cleared)User preferences, themes, saved data
sessionStorageUntil tab/window closesForm drafts, temporary state

$.storage(key, initialValue, [storage])

Creates a persistent signal that syncs with browser storage.

javascript
import { $ } from 'sigpro';
+    
Skip to content

Storage API 💾

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.

Core Concepts

What is Persistent Storage?

Persistent signals are special signals that:

  • Initialize from storage (localStorage/sessionStorage) if a saved value exists
  • Auto-save whenever the signal value changes
  • Handle JSON serialization automatically
  • Clean up when set to null or undefined

Storage Types

StoragePersistenceUse Case
localStorageForever (until cleared)User preferences, themes, saved data
sessionStorageUntil tab/window closesForm drafts, temporary state

$.storage(key, initialValue, [storage])

Creates a persistent signal that syncs with browser storage.

javascript
import { $ } from 'sigpro';
 
 // localStorage (default)
 const theme = $.storage('theme', 'light');
@@ -814,7 +814,7 @@
 // Usage
 const secureToken = createSecureStorage('auth-token', null);
 secureToken('sensitive-data-123'); // Stored encrypted

📈 Performance Considerations

OperationCostNotes
Initial readO(1)Single storage read
WriteO(1) + JSON.stringifyAuto-save on change
Large objectsO(n)Stringify/parse overhead
Multiple keysO(k)k = number of keys

Pro Tip: Use sessionStorage for temporary data like form drafts, and localStorage for persistent user preferences. Always validate data when reading from storage to handle corrupted values gracefully.

- + \ No newline at end of file diff --git a/docs/guide/getting-started.html b/docs/guide/getting-started.html index 09d4964..9c00301 100644 --- a/docs/guide/getting-started.html +++ b/docs/guide/getting-started.html @@ -18,7 +18,7 @@ -
Skip to content

Getting Started with SigPro 🚀

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.

📦 Installation

Choose your preferred installation method:

bash
# Using npm
+    
Skip to content

Getting Started with SigPro 🚀

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.

📦 Installation

Choose your preferred installation method:

bash
# Using npm
 npm install sigpro
 
 # Using bun
@@ -190,7 +190,7 @@
 
 // Mount your app
 document.body.appendChild(HomePage());

🎓 Summary

You've learned:

  • ✅ How to install SigPro
  • ✅ Core concepts: signals, effects, and reactive rendering
  • ✅ Built a complete todo app
  • ✅ Key patterns and best practices
  • ✅ How to structure larger applications

Remember: 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.

"Stop fighting the platform. Start building with it."

Happy coding! 🎉

- + \ No newline at end of file diff --git a/docs/guide/why.html b/docs/guide/why.html index 194d874..270a53f 100644 --- a/docs/guide/why.html +++ b/docs/guide/why.html @@ -18,7 +18,7 @@ -
Skip to content

Why SigPro? ❓

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.

SigPro is my answer to a simple question: Why fight the platform when we can embrace it?

🌐 The Web Platform Is Finally Ready

Modern browsers now offer powerful primitives that make true reactivity possible without virtual DOM diffing, without compilers, and without lock-in:

Browser PrimitiveWhat It Enables
Custom ElementsCreate reusable components with native browser APIs
Shadow DOMEncapsulate styles and markup without preprocessors
CSS Custom PropertiesDynamic theming without CSS-in-JS
Microtask QueuesEfficient update batching without complex scheduling

🎯 The SigPro Philosophy

SigPro strips away the complexity, delivering a reactive programming model that feels familiar but stays remarkably close to vanilla JS:

  • No JSX transformations - Just template literals
  • No template compilers - The browser parses your HTML
  • No proprietary syntax to learn - Just functions and signals
  • No build step required - Works directly in the browser
javascript
// Just vanilla JavaScript with signals
+    
Skip to content

Why SigPro? ❓

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.

SigPro is my answer to a simple question: Why fight the platform when we can embrace it?

🌐 The Web Platform Is Finally Ready

Modern browsers now offer powerful primitives that make true reactivity possible without virtual DOM diffing, without compilers, and without lock-in:

Browser PrimitiveWhat It Enables
Custom ElementsCreate reusable components with native browser APIs
Shadow DOMEncapsulate styles and markup without preprocessors
CSS Custom PropertiesDynamic theming without CSS-in-JS
Microtask QueuesEfficient update batching without complex scheduling

🎯 The SigPro Philosophy

SigPro strips away the complexity, delivering a reactive programming model that feels familiar but stays remarkably close to vanilla JS:

  • No JSX transformations - Just template literals
  • No template compilers - The browser parses your HTML
  • No proprietary syntax to learn - Just functions and signals
  • No build step required - Works directly in the browser
javascript
// Just vanilla JavaScript with signals
 import { $, html } from 'sigpro';
 
 const count = $(0);
@@ -41,7 +41,7 @@
     <h1>Beautiful highlighted template</h1>
   </div>
 `

⏱️ Built for the Long Term

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.

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.

📈 The Verdict

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.

"Stop fighting the platform. Start building with it."

🚀 Ready to Start?

Get Started with SigProView on GitHubnpm Package

- + \ No newline at end of file diff --git a/docs/index.html b/docs/index.html index c68ceb0..bbf917d 100644 --- a/docs/index.html +++ b/docs/index.html @@ -18,8 +18,8 @@ -
Skip to content

SigProReactivity for the Web Platform

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.

SigPro

npm versionbundle sizelicense

"Stop fighting the platform. Start building with it."

- +
Skip to content

SigProReactivity for the Web Platform

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.

SigPro

npm versionbundle sizelicense

"Stop fighting the platform. Start building with it."

+ \ No newline at end of file diff --git a/docs/public/logo.svg b/docs/logo.svg similarity index 100% rename from docs/public/logo.svg rename to docs/logo.svg diff --git a/docs/ui/intro.html b/docs/ui/intro.html index d68cc71..767aafe 100644 --- a/docs/ui/intro.html +++ b/docs/ui/intro.html @@ -18,8 +18,8 @@ -
Skip to content

SigPro UI

SigPro UI is a collection of high-performance Web Components built on top of the SigPro reactive library and styled with DaisyUI.

Why SigPro UI?

Designed to streamline modern web development, SigPro UI combines the lightweight reactivity of SigPro with the beautiful, accessible design system of DaisyUI.

  • Native Web Components: Use them in any framework or plain HTML.
  • Reactive by Design: Powered by SigPro signals ($) for seamless state management.
  • Utility-First Styling: Leveraging Tailwind CSS and DaisyUI for a polished look without the bloat.
  • Developer Experience: Focus on building features, not reinventing UI patterns.

Getting Started

SigPro UI allows you to build modular, reactive interfaces with minimal overhead, making web development faster, cleaner, and more efficient.

- +
Skip to content

SigPro UI

SigPro UI is a collection of high-performance Web Components built on top of the SigPro reactive library and styled with DaisyUI.

Why SigPro UI?

Designed to streamline modern web development, SigPro UI combines the lightweight reactivity of SigPro with the beautiful, accessible design system of DaisyUI.

  • Native Web Components: Use them in any framework or plain HTML.
  • Reactive by Design: Powered by SigPro signals ($) for seamless state management.
  • Utility-First Styling: Leveraging Tailwind CSS and DaisyUI for a polished look without the bloat.
  • Developer Experience: Focus on building features, not reinventing UI patterns.

Getting Started

SigPro UI allows you to build modular, reactive interfaces with minimal overhead, making web development faster, cleaner, and more efficient.

+ \ No newline at end of file diff --git a/docs/vite/plugin.html b/docs/vite/plugin.html index 3dbf3cb..ab94f17 100644 --- a/docs/vite/plugin.html +++ b/docs/vite/plugin.html @@ -18,7 +18,7 @@ -
Skip to content

Vite Plugin: Automatic File-based Routing 🚦

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.

Why Use This Plugin?

While SigPro's router works perfectly with manually defined routes, this plugin:

  • Eliminates boilerplate - No need to write route configurations
  • Enforces conventions - Consistent URL structure across your app
  • Supports dynamic routes - Use [param] syntax for parameters
  • Automatic code-splitting - Each page becomes a separate chunk
  • Type-safe (with JSDoc) - Routes follow your file structure

Installation

The plugin is included with SigPro, but you need to add it to your Vite config:

javascript
// vite.config.js
+    
Skip to content

Vite Plugin: Automatic File-based Routing 🚦

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.

Why Use This Plugin?

While SigPro's router works perfectly with manually defined routes, this plugin:

  • Eliminates boilerplate - No need to write route configurations
  • Enforces conventions - Consistent URL structure across your app
  • Supports dynamic routes - Use [param] syntax for parameters
  • Automatic code-splitting - Each page becomes a separate chunk
  • Type-safe (with JSDoc) - Routes follow your file structure

Installation

The plugin is included with SigPro, but you need to add it to your Vite config:

javascript
// vite.config.js
 import { defineConfig } from 'vite';
 import { sigproRouter } from 'sigpro';
 
@@ -243,7 +243,7 @@
 
 const router = $.router(routesWithLayout);
 document.body.appendChild(router);

Note: This plugin is completely optional. You can always define routes manually if you prefer. The plugin just saves you from writing boilerplate route configurations.

Pro Tip: The plugin works great with hot module replacement (HMR) - add a new page and it's instantly available in your dev server without restarting!

- + \ No newline at end of file diff --git a/index.js b/index.js index dbf3dea..04596c1 100644 --- a/index.js +++ b/index.js @@ -1,18 +1,4 @@ // index.js - -// 1. Re-export all named core logic (signals, effects, html, etc.) -export * from './sigpro.js'; - -// 2. Import and re-export the Vite Router Plugin -// This allows users to import { sigproRouter } directly from the package -import sigproRouter from './sigpro-router-plugin.js'; -export { sigproRouter }; - -// 3. Re-export UI components -// Users can import components like: import { Button, Input, Card } from 'sigpro'; -export * from './UI/index.js'; - -// 4. Default export for the global namespace (optional) -// Combines core logic, router plugin, and UI components into a single object -import * as sigpro from './sigpro.js'; -export default { ...sigpro, sigproRouter }; +export * from './packages/sigpro/sigpro.min.js'; +export { default as sigproRouter } from './packages/sigpro/plugin.min.js'; +export * from './packages/sigproui/index.js'; \ No newline at end of file diff --git a/package.json b/package.json index f46b9a4..e899827 100644 --- a/package.json +++ b/package.json @@ -12,12 +12,15 @@ "url": "https://github.com/natxocc/sigpro/issues" }, "scripts": { - "docs:dev": "vitepress dev docs/src", - "docs:build": "vitepress build docs/src", - "docs:preview": "vitepress preview docs/src" + "docs:dev": "vitepress dev packages/docs", + "docs:build": "vitepress build packages/docs", + "docs:preview": "vitepress preview packages/docs", + "ui:dev": "vite packages/sigproui", + "ui:build": "vite build packages/sigproui" }, "devDependencies": { "@tailwindcss/vite": "^4.2.2", + "vite": "^8.0.0", "vitepress": "^1.6.4" }, "keywords": [ diff --git a/docs/src/.vitepress/cache/deps/@theme_index.js b/packages/docs/.vitepress/cache/deps/@theme_index.js similarity index 100% rename from docs/src/.vitepress/cache/deps/@theme_index.js rename to packages/docs/.vitepress/cache/deps/@theme_index.js diff --git a/docs/src/.vitepress/cache/deps/@theme_index.js.map b/packages/docs/.vitepress/cache/deps/@theme_index.js.map similarity index 100% rename from docs/src/.vitepress/cache/deps/@theme_index.js.map rename to packages/docs/.vitepress/cache/deps/@theme_index.js.map diff --git a/docs/src/.vitepress/cache/deps/_metadata.json b/packages/docs/.vitepress/cache/deps/_metadata.json similarity index 82% rename from docs/src/.vitepress/cache/deps/_metadata.json rename to packages/docs/.vitepress/cache/deps/_metadata.json index 6a43e24..93e3b3e 100644 --- a/docs/src/.vitepress/cache/deps/_metadata.json +++ b/packages/docs/.vitepress/cache/deps/_metadata.json @@ -1,31 +1,31 @@ { - "hash": "d9f33c5d", - "configHash": "ed6d9386", + "hash": "33e82b21", + "configHash": "c6db372a", "lockfileHash": "e3b0c442", - "browserHash": "07432c9f", + "browserHash": "66861689", "optimized": { "vue": { "src": "../../../../../node_modules/vue/dist/vue.runtime.esm-bundler.js", "file": "vue.js", - "fileHash": "1994a58f", + "fileHash": "415ad31e", "needsInterop": false }, "vitepress > @vue/devtools-api": { "src": "../../../../../node_modules/@vue/devtools-api/dist/index.js", "file": "vitepress___@vue_devtools-api.js", - "fileHash": "b25fcac2", + "fileHash": "82c7da90", "needsInterop": false }, "vitepress > @vueuse/core": { "src": "../../../../../node_modules/@vueuse/core/index.mjs", "file": "vitepress___@vueuse_core.js", - "fileHash": "59cc8e6b", + "fileHash": "bf2a3493", "needsInterop": false }, "@theme/index": { "src": "../../../../../node_modules/vitepress/dist/client/theme-default/index.js", "file": "@theme_index.js", - "fileHash": "ae58cdf7", + "fileHash": "0d87b191", "needsInterop": false } }, diff --git a/docs/src/.vitepress/cache/deps/chunk-3S55Y3P7.js b/packages/docs/.vitepress/cache/deps/chunk-3S55Y3P7.js similarity index 100% rename from docs/src/.vitepress/cache/deps/chunk-3S55Y3P7.js rename to packages/docs/.vitepress/cache/deps/chunk-3S55Y3P7.js diff --git a/docs/src/.vitepress/cache/deps/chunk-3S55Y3P7.js.map b/packages/docs/.vitepress/cache/deps/chunk-3S55Y3P7.js.map similarity index 100% rename from docs/src/.vitepress/cache/deps/chunk-3S55Y3P7.js.map rename to packages/docs/.vitepress/cache/deps/chunk-3S55Y3P7.js.map diff --git a/docs/src/.vitepress/cache/deps/chunk-RLEUDPPB.js b/packages/docs/.vitepress/cache/deps/chunk-RLEUDPPB.js similarity index 100% rename from docs/src/.vitepress/cache/deps/chunk-RLEUDPPB.js rename to packages/docs/.vitepress/cache/deps/chunk-RLEUDPPB.js diff --git a/docs/src/.vitepress/cache/deps/chunk-RLEUDPPB.js.map b/packages/docs/.vitepress/cache/deps/chunk-RLEUDPPB.js.map similarity index 100% rename from docs/src/.vitepress/cache/deps/chunk-RLEUDPPB.js.map rename to packages/docs/.vitepress/cache/deps/chunk-RLEUDPPB.js.map diff --git a/docs/src/.vitepress/cache/deps/package.json b/packages/docs/.vitepress/cache/deps/package.json similarity index 100% rename from docs/src/.vitepress/cache/deps/package.json rename to packages/docs/.vitepress/cache/deps/package.json diff --git a/docs/src/.vitepress/cache/deps/vitepress___@vue_devtools-api.js b/packages/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js similarity index 100% rename from docs/src/.vitepress/cache/deps/vitepress___@vue_devtools-api.js rename to packages/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js diff --git a/docs/src/.vitepress/cache/deps/vitepress___@vue_devtools-api.js.map b/packages/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js.map similarity index 100% rename from docs/src/.vitepress/cache/deps/vitepress___@vue_devtools-api.js.map rename to packages/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js.map diff --git a/docs/src/.vitepress/cache/deps/vitepress___@vueuse_core.js b/packages/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js similarity index 100% rename from docs/src/.vitepress/cache/deps/vitepress___@vueuse_core.js rename to packages/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js diff --git a/docs/src/.vitepress/cache/deps/vitepress___@vueuse_core.js.map b/packages/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js.map similarity index 100% rename from docs/src/.vitepress/cache/deps/vitepress___@vueuse_core.js.map rename to packages/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js.map diff --git a/docs/src/.vitepress/cache/deps/vue.js b/packages/docs/.vitepress/cache/deps/vue.js similarity index 100% rename from docs/src/.vitepress/cache/deps/vue.js rename to packages/docs/.vitepress/cache/deps/vue.js diff --git a/docs/src/.vitepress/cache/deps/vue.js.map b/packages/docs/.vitepress/cache/deps/vue.js.map similarity index 100% rename from docs/src/.vitepress/cache/deps/vue.js.map rename to packages/docs/.vitepress/cache/deps/vue.js.map diff --git a/docs/src/.vitepress/config.js b/packages/docs/.vitepress/config.js similarity index 76% rename from docs/src/.vitepress/config.js rename to packages/docs/.vitepress/config.js index 7029c16..bb36cfd 100644 --- a/docs/src/.vitepress/config.js +++ b/packages/docs/.vitepress/config.js @@ -5,29 +5,21 @@ const isDev = process.env.NODE_ENV === 'development' export default defineConfig({ title: "SigPro", description: "Minimalist Reactive Library", - base: isDev ? '/absproxy/5173/sigpro/' : '/sigpro/', + outDir: '../../docs', + base: isDev ? '/absproxy/5174/sigpro/' : '/sigpro/', - // CONFIGURACIÓN DE NIVEL SUPERIOR (Prioridad VitePress) - server: { - host: '0.0.0.0', // Forzamos escucha total - port: 5173, - // @ts-ignore - VitePress a veces no reconoce el tipo pero lo pasa a Vite - allowedHosts: ['code.natxocc.com', '.natxocc.com'], - strictPort: true - }, - // CONFIGURACIÓN DE VITE (Motor interno) vite: { + outDir: '../../docs', + base: isDev ? '/absproxy/5174/sigpro/' : '/sigpro/', server: { - allowedHosts: true, // Permitir todo en el motor interno - hmr: { - host: 'code.natxocc.com', - protocol: 'wss' - } + allowedHosts: true, + port: 5174, } }, themeConfig: { + logo: '/logo.svg', nav: [ { text: 'Home', link: '/' }, { text: 'Guide', link: '/guide/getting-started' }, diff --git a/docs/src/api/components.md b/packages/docs/api/components.md similarity index 100% rename from docs/src/api/components.md rename to packages/docs/api/components.md diff --git a/docs/src/api/effects.md b/packages/docs/api/effects.md similarity index 100% rename from docs/src/api/effects.md rename to packages/docs/api/effects.md diff --git a/docs/src/api/fetch.md b/packages/docs/api/fetch.md similarity index 100% rename from docs/src/api/fetch.md rename to packages/docs/api/fetch.md diff --git a/docs/src/api/pages.md b/packages/docs/api/pages.md similarity index 100% rename from docs/src/api/pages.md rename to packages/docs/api/pages.md diff --git a/docs/src/api/quick.md b/packages/docs/api/quick.md similarity index 100% rename from docs/src/api/quick.md rename to packages/docs/api/quick.md diff --git a/docs/src/api/routing.md b/packages/docs/api/routing.md similarity index 100% rename from docs/src/api/routing.md rename to packages/docs/api/routing.md diff --git a/docs/src/api/signals.md b/packages/docs/api/signals.md similarity index 100% rename from docs/src/api/signals.md rename to packages/docs/api/signals.md diff --git a/docs/src/api/storage.md b/packages/docs/api/storage.md similarity index 100% rename from docs/src/api/storage.md rename to packages/docs/api/storage.md diff --git a/docs/src/guide/getting-started.md b/packages/docs/guide/getting-started.md similarity index 100% rename from docs/src/guide/getting-started.md rename to packages/docs/guide/getting-started.md diff --git a/docs/src/guide/why.md b/packages/docs/guide/why.md similarity index 100% rename from docs/src/guide/why.md rename to packages/docs/guide/why.md diff --git a/docs/src/index.md b/packages/docs/index.md similarity index 100% rename from docs/src/index.md rename to packages/docs/index.md diff --git a/docs/src/logo.svg b/packages/docs/logo.svg similarity index 100% rename from docs/src/logo.svg rename to packages/docs/logo.svg diff --git a/packages/docs/public/logo.svg b/packages/docs/public/logo.svg new file mode 100644 index 0000000..ac6432e --- /dev/null +++ b/packages/docs/public/logo.svg @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/src/ui/intro.md b/packages/docs/ui/intro.md similarity index 100% rename from docs/src/ui/intro.md rename to packages/docs/ui/intro.md diff --git a/docs/src/vite/plugin.md b/packages/docs/vite/plugin.md similarity index 100% rename from docs/src/vite/plugin.md rename to packages/docs/vite/plugin.md diff --git a/sigpro/sigpro-router-plugin.js b/packages/sigpro/plugin.js similarity index 100% rename from sigpro/sigpro-router-plugin.js rename to packages/sigpro/plugin.js diff --git a/packages/sigpro/plugin.min.js b/packages/sigpro/plugin.min.js new file mode 100644 index 0000000..325a121 --- /dev/null +++ b/packages/sigpro/plugin.min.js @@ -0,0 +1 @@ +import fs from"fs";import path from"path";export default function sigproRouter(){const e="virtual:sigpro-routes",r="\0"+e;function t(e){let r=[];if(!fs.existsSync(e))return r;return fs.readdirSync(e).forEach((n=>{const s=path.resolve(e,n),o=fs.statSync(s);o&&o.isDirectory()?r=r.concat(t(s)):(n.endsWith(".js")||n.endsWith(".jsx"))&&r.push(s)})),r}return{name:"sigpro-router",resolveId(t){if(t===e)return r},load(e){if(e===r){const e=path.resolve(process.cwd(),"src/pages");let r=t(e);r=r.sort(((r,t)=>{const n=path.relative(e,r).replace(/\\/g,"/"),s=path.relative(e,t).replace(/\\/g,"/"),o=n.includes("[")||n.includes(":");return o!==(s.includes("[")||s.includes(":"))?o?1:-1:s.length-n.length}));let n="",s="export const routes = [\n";return r.forEach(((r,t)=>{const o=r.replace(/\\/g,"/"),c=`Page_${t}`;let a=function(e){let r=e.replace(/\\/g,"/").replace(/\.jsx?$/,"");return"index"===r?"/":(r.endsWith("/index")&&(r=r.slice(0,-6)),r=r.replace(/\[([^\]]+)\]/g,":$1"),("/"+r.toLowerCase()).replace(/\/+/g,"/").replace(/\/$/,"")||"/")}(path.relative(e,r).replace(/\\/g,"/"));a.includes(":");n+=`import ${c} from '${o}';\n`,s+=` { path: '${a}', component: ${c} },\n`})),s+="];",`${n}\n${s}`}}}} \ No newline at end of file diff --git a/sigpro/sigpro.js b/packages/sigpro/sigpro.js similarity index 100% rename from sigpro/sigpro.js rename to packages/sigpro/sigpro.js diff --git a/packages/sigpro/sigpro.min.js b/packages/sigpro/sigpro.min.js new file mode 100644 index 0000000..7f4e5d4 --- /dev/null +++ b/packages/sigpro/sigpro.min.js @@ -0,0 +1 @@ +let activeEffect=null;const effectQueue=new Set;let isFlushScheduled=!1,flushCount=0;const flushEffectQueue=()=>{if(isFlushScheduled=!1,flushCount++,flushCount>100)throw effectQueue.clear(),flushCount=0,new Error("SigPro: Infinite reactive loop detected.");try{const e=Array.from(effectQueue);effectQueue.clear();for(const t of e)t.run()}catch(e){console.error("SigPro Flush Error:",e)}finally{setTimeout(()=>{flushCount=0},0)}},$=e=>{const t=new Set;let n;if("function"==typeof e){let s,o=!0;const c={dependencies:new Set,markDirty:()=>{o||(o=!0,t.forEach(e=>{e.markDirty&&e.markDirty(),effectQueue.add(e)}),!isFlushScheduled&&effectQueue.size&&(isFlushScheduled=!0,queueMicrotask(flushEffectQueue)))},run:()=>{c.dependencies.forEach(e=>e.delete(c)),c.dependencies.clear();const t=activeEffect;activeEffect=c;try{s=e()}finally{activeEffect=t,o=!1}}};n=()=>(activeEffect&&(t.add(activeEffect),activeEffect.dependencies.add(t)),o&&c.run(),s)}else n=(...n)=>{if(n.length){const s="function"==typeof n[0]?n[0](e):n[0];Object.is(e,s)||(e=s,t.forEach(e=>{e.markDirty&&e.markDirty(),effectQueue.add(e)}),!isFlushScheduled&&effectQueue.size&&(isFlushScheduled=!0,queueMicrotask(flushEffectQueue)))}return activeEffect&&(t.add(activeEffect),activeEffect.dependencies.add(t)),e};return n};let currentPageCleanups=null;const $e=e=>{const t={dependencies:new Set,cleanupHandlers:new Set,run(){this.cleanupHandlers.forEach(e=>e()),this.cleanupHandlers.clear(),this.dependencies.forEach(e=>e.delete(this)),this.dependencies.clear();const t=activeEffect;activeEffect=this;try{const t=e();"function"==typeof t&&this.cleanupHandlers.add(t)}finally{activeEffect=t}},stop(){this.cleanupHandlers.forEach(e=>e()),this.dependencies.forEach(e=>e.delete(this))}};return currentPageCleanups&¤tPageCleanups.push(()=>t.stop()),activeEffect&&activeEffect.cleanupHandlers.add(()=>t.stop()),t.run(),()=>t.stop()},$s=(e,t,n=localStorage)=>{let s;try{const o=n.getItem(e);s=null!==o?JSON.parse(o):t}catch(o){console.warn(`Error reading ${e} from storage:`,o),s=t,n.removeItem(e)}const o=$(s);return $e(()=>{try{const t=o();null==t?n.removeItem(e):n.setItem(e,JSON.stringify(t))}catch(t){console.warn(`Error saving ${e} to storage:`,t)}}),o},html=(e,...t)=>{const n=html._templateCache??(html._templateCache=new WeakMap);let s=n.get(e);if(!s){const t=document.createElement("template");t.innerHTML=e.join("{{part}}");const o=[],c=document.createTreeWalker(t.content,133),r=e=>{const n=[];for(;e&&e!==t.content;){let t=0;for(let n=e.previousSibling;n;n=n.previousSibling)t++;n.push(t),e=e.parentNode}return n.reverse()};let i;for(;i=c.nextNode();){let e=!1;const t={type:i.nodeType,path:r(i),parts:[]};if(1===i.nodeType)for(let n=0;n{return{node:(t=o,n=e.path,n.reduce((e,t)=>e?.childNodes?.[t],t)),info:e};var t,n}).forEach(({node:e,info:n})=>{if(e)if(1===n.type)n.parts.forEach(n=>{const s=t[c++],o=n.name,r=o[0];if("@"===r){const[t,...n]=o.slice(1).split("."),c=o=>{if(n.includes("prevent")&&o.preventDefault(),n.includes("stop")&&o.stopPropagation(),!n.includes("self")||o.target===e){if(n.some(e=>e.startsWith("debounce"))){const t=n.find(e=>e.startsWith("debounce"))?.split(":")[1]||300;return clearTimeout(e._debounceTimer),void(e._debounceTimer=setTimeout(()=>s(o),t))}n.includes("once")&&e.removeEventListener(t,c),s(o)}};e.addEventListener(t,c,{passive:n.includes("passive"),capture:n.includes("capture")})}else if(":"===r){const t=o.slice(1),n="checkbox"===e.type||"radio"===e.type?"change":"input";"function"==typeof s?$e(()=>{const n=s();e[t]!==n&&(e[t]=n)}):e[t]=s,e.addEventListener(n,()=>{const t="change"===n?e.checked:e.value;"function"==typeof s&&s(t)})}else if("?"===r){const t=o.slice(1);"function"==typeof s?$e(()=>{const n=s();e.toggleAttribute(t,!!n)}):e.toggleAttribute(t,!!s)}else if("."===r){const t=o.slice(1);"function"==typeof s?$e(()=>{const n=s();e[t]=n,null!=n&&"object"!=typeof n&&"boolean"!=typeof n&&e.setAttribute(t,n)}):(e[t]=s,null!=s&&"object"!=typeof s&&"boolean"!=typeof s&&e.setAttribute(t,s))}else"function"==typeof s?$e(()=>e.setAttribute(o,s())):e.setAttribute(o,s)});else if(3===n.type){const n=e.textContent.split("{{part}}").length-1;((e,t)=>{const n=e.textContent.split("{{part}}"),s=e.parentNode;let o=0;n.forEach((c,r)=>{if(c&&s.insertBefore(document.createTextNode(c),e),r{const e=l();e!==f&&(f=e,i(e))})}else i(l);function i(e){if("object"==typeof e||Array.isArray(e)){for(;a.nextSibling!==u;)s.removeChild(a.nextSibling);const t=Array.isArray(e)?e:[e],n=document.createDocumentFragment();t.forEach(e=>{if(null==e||!1===e)return;const t=e instanceof Node?e:document.createTextNode(e);n.appendChild(t)}),s.insertBefore(n,u)}else{const t=a.nextSibling,n=String(e??"");if(t!==u&&3===t?.nodeType)t.textContent=n;else{for(;a.nextSibling!==u;)s.removeChild(a.nextSibling);s.insertBefore(document.createTextNode(n),u)}}}}}),e.remove()})(e,t.slice(c,c+n)),c+=n}}),o},$p=e=>{const t="page-"+Math.random().toString(36).substring(2,9);return customElements.define(t,class extends HTMLElement{connectedCallback(){this.style.display="contents",this._cleanups=[],currentPageCleanups=this._cleanups;try{const t=e({params:JSON.parse(this.getAttribute("params")||"{}"),onUnmount:e=>this._cleanups.push(e)});this.appendChild(t instanceof Node?t:document.createTextNode(String(t)))}finally{currentPageCleanups=null}}disconnectedCallback(){this._cleanups.forEach(e=>e()),this._cleanups=[],this.innerHTML=""}}),(e={})=>{const n=document.createElement(t);return n.setAttribute("params",JSON.stringify(e)),n}},$c=(e,t,n=[],s=!1)=>{customElements.get(e)||customElements.define(e,class extends HTMLElement{static get observedAttributes(){return n}constructor(){super(),this._propertySignals={},this.cleanupFunctions=[],this._root=s?this.attachShadow({mode:"open"}):this,n.forEach(e=>this._propertySignals[e]=$(void 0))}connectedCallback(){const e=[...this.childNodes];this._root.innerHTML="",n.forEach(e=>{const t=this.hasOwnProperty(e)?this[e]:this.getAttribute(e);Object.defineProperty(this,e,{get:()=>this._propertySignals[e](),set:t=>{const n="false"!==t&&(""===t&&"value"!==e||t);this._propertySignals[e](n)},configurable:!0}),null!=t&&(this[e]=t)});const s={select:e=>this._root.querySelector(e),selectAll:e=>this._root.querySelectorAll(e),slot:t=>e.filter(e=>{const n=1===e.nodeType?e.getAttribute("slot"):null;return t?n===t:!n}),emit:(e,t)=>this.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0,composed:!0})),host:this,root:this._root,onUnmount:e=>this.cleanupFunctions.push(e)},o=t(this._propertySignals,s);o instanceof Node&&this._root.appendChild(o)}attributeChangedCallback(e,t,n){this[e]!==n&&(this[e]=n)}disconnectedCallback(){this.cleanupFunctions.forEach(e=>e()),this.cleanupFunctions=[]}})},$f=async(e,t,n)=>{n&&n(!0);try{const n=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}),s=await n.text();try{return JSON.parse(s)}catch(e){return console.warn("Invalid JSON response"),null}}catch(e){return null}finally{n&&n(!1)}},$r=e=>{const t=document.createElement("div");t.style.display="contents";const n=(e,t)=>{if(!t.includes(":"))return t===e?{}:null;const n=t.split("/"),s=e.split("/");if(n.length!==s.length)return null;const o={};for(let e=0;e{const s=window.location.hash.replace(/^#/,"")||"/";let o=null,c={};for(const t of e){const e=n(s,t.path);if(null!==e){o=t,c=e;break}}const r=o?o.component(c):Object.assign(document.createElement("h1"),{textContent:"404"});t.replaceChildren(r instanceof Node?r:document.createTextNode(String(r??"")))};return window.addEventListener("hashchange",s),s(),t};$r.go=e=>{const t=e.startsWith("/")?e:`/${e}`;window.location.hash!==`#${t}`&&(window.location.hash=t)},$.effect=$e,$.page=$p,$.component=$c,$.fetch=$f,$.router=$r,$.storage=$s,"undefined"!=typeof window&&(window.$=$);export{$,html}; \ No newline at end of file diff --git a/packages/sigproui/app.js b/packages/sigproui/app.js new file mode 100644 index 0000000..52a9964 --- /dev/null +++ b/packages/sigproui/app.js @@ -0,0 +1,244 @@ +/** + * UI Demo/Test - Para probar componentes localmente sin hacer release + * + * Ejecutar: + * 1. Crear un archivo index.html que importe este archivo + * 2. O usar con Vite: bun add -d vite && bun vite UI/app.js + * + * Alternativamente, simplemente copiar las partes que necesitas a tu proyecto + */ +import { $, html, effect } from "../../index.js"; +import { Button, Input, Card, Drawer, Menu, Dropdown, Fab, Dialog, Loading } from "./index.js"; + +// Importar la función helper de loading +import { loading } from "./components/Loading.js"; + +// Estado para la demo +const state = { + inputValue: $(""), + checkboxValue: $(false), + radioValue: $("option1"), + rangeValue: $(50), + showDialog: $(false), + openDrawer: $(false), +}; + +// Menú de navegación +const menuItems = [ + { label: "Home", icon: "icon-[lucide--home]", href: "#/home" }, + { label: "About", icon: "icon-[lucide--info]", href: "#/about" }, + { + label: "Components", + icon: "icon-[lucide--box]", + open: false, + sub: [ + { label: "Button", href: "#/button" }, + { label: "Input", href: "#/input" }, + { label: "Card", href: "#/card" }, + { label: "Forms", href: "#/forms" }, + ] + }, +]; + +// Demo page principal +export default function App() { + effect(() => { + console.log("Input value:", state.inputValue()); + }); + + return html` +
+ + + + + + +
+ + +
+

Buttons

+
+ console.log("Primary clicked")}>Primary + Secondary + Accent + Ghost + Link + Loading + Disabled + With Badge + With Tooltip +
+
+ + +
+

Input

+
+ state.inputValue(v)} + placeholder="Enter username" + > + + + + +
+

Current input value: "${state.inputValue()}"

+
+ + +
+

Card

+ + Card Title +

This is a basic card with some content.

+
+ Accept + Cancel +
+
+ + + Card with Image +

Beautiful flower image

+
+ Buy Now +
+
+
+ + +
+

Form Controls

+
+ + state.checkboxValue(v)} + > +

Checkbox value: ${() => state.checkboxValue() ? "checked" : "unchecked"}

+ +
+ state.radioValue() === "option1"} + .value=${"option1"} + label="Option 1" + @change=${(v) => state.radioValue(v)} + > + state.radioValue() === "option2"} + .value=${"option2"} + label="Option 2" + @change=${(v) => state.radioValue(v)} + > + state.radioValue() === "option3"} + .value=${"option3"} + label="Option 3" + @change=${(v) => state.radioValue(v)} + > +
+

Radio value: "${state.radioValue()}"

+ +
+ state.rangeValue(Number(v))} + > +

Range value: ${state.rangeValue()}

+
+ +
+
+ + +
+

Loading

+
+ loading(true, "Loading...")}> + Show Loading + + loading(false)}> + Hide Loading + +
+
+ + +
+

Dialog

+ state.showDialog(true)}>Open Dialog + + state.showDialog(false)}> + Confirm Action +

Are you sure you want to proceed?

+
+ state.showDialog(false)}>Cancel + { console.log("Confirmed!"); state.showDialog(false); }}>Confirm +
+
+
+ + +
+

Dropdown

+ + Open Dropdown +
  • Item 1
  • +
  • Item 2
  • +
  • Item 3
  • +
    +
    + + +
    +

    FAB (Floating Action Button)

    + +
    + +
    +
    + `; +} + +// Mount the app +if (typeof document !== "undefined") { + const root = document.getElementById("app"); + if (root) { + root.appendChild(App()); + } +} diff --git a/UI/components/Button.js b/packages/sigproui/components/Button.js similarity index 100% rename from UI/components/Button.js rename to packages/sigproui/components/Button.js diff --git a/UI/components/Card.js b/packages/sigproui/components/Card.js similarity index 100% rename from UI/components/Card.js rename to packages/sigproui/components/Card.js diff --git a/UI/components/Checkbox.js b/packages/sigproui/components/Checkbox.js similarity index 100% rename from UI/components/Checkbox.js rename to packages/sigproui/components/Checkbox.js diff --git a/UI/components/ColorPicker.js b/packages/sigproui/components/ColorPicker.js similarity index 100% rename from UI/components/ColorPicker.js rename to packages/sigproui/components/ColorPicker.js diff --git a/UI/components/DatePicker.js b/packages/sigproui/components/DatePicker.js similarity index 100% rename from UI/components/DatePicker.js rename to packages/sigproui/components/DatePicker.js diff --git a/UI/components/Dialog.js b/packages/sigproui/components/Dialog.js similarity index 100% rename from UI/components/Dialog.js rename to packages/sigproui/components/Dialog.js diff --git a/UI/components/Drawer.js b/packages/sigproui/components/Drawer.js similarity index 100% rename from UI/components/Drawer.js rename to packages/sigproui/components/Drawer.js diff --git a/UI/components/Dropdown.js b/packages/sigproui/components/Dropdown.js similarity index 100% rename from UI/components/Dropdown.js rename to packages/sigproui/components/Dropdown.js diff --git a/UI/components/Fab.js b/packages/sigproui/components/Fab.js similarity index 100% rename from UI/components/Fab.js rename to packages/sigproui/components/Fab.js diff --git a/UI/components/Input.js b/packages/sigproui/components/Input.js similarity index 100% rename from UI/components/Input.js rename to packages/sigproui/components/Input.js diff --git a/UI/components/Loading.js b/packages/sigproui/components/Loading.js similarity index 100% rename from UI/components/Loading.js rename to packages/sigproui/components/Loading.js diff --git a/UI/components/Menu.js b/packages/sigproui/components/Menu.js similarity index 100% rename from UI/components/Menu.js rename to packages/sigproui/components/Menu.js diff --git a/UI/components/Radio.js b/packages/sigproui/components/Radio.js similarity index 100% rename from UI/components/Radio.js rename to packages/sigproui/components/Radio.js diff --git a/UI/components/Range.js b/packages/sigproui/components/Range.js similarity index 100% rename from UI/components/Range.js rename to packages/sigproui/components/Range.js diff --git a/UI/components/Rating.js b/packages/sigproui/components/Rating.js similarity index 100% rename from UI/components/Rating.js rename to packages/sigproui/components/Rating.js diff --git a/UI/components/Tab.js b/packages/sigproui/components/Tab.js similarity index 100% rename from UI/components/Tab.js rename to packages/sigproui/components/Tab.js diff --git a/UI/components/Toast.js b/packages/sigproui/components/Toast.js similarity index 100% rename from UI/components/Toast.js rename to packages/sigproui/components/Toast.js diff --git a/packages/sigproui/index.html b/packages/sigproui/index.html new file mode 100644 index 0000000..01aaa4d --- /dev/null +++ b/packages/sigproui/index.html @@ -0,0 +1,25 @@ + + + + + + SigProUI Test + + + + + +
    + + + + diff --git a/UI/index.js b/packages/sigproui/index.js similarity index 99% rename from UI/index.js rename to packages/sigproui/index.js index 9208b50..a3231d4 100644 --- a/UI/index.js +++ b/packages/sigproui/index.js @@ -19,6 +19,7 @@ import "./components/Rating.js"; import "./components/Tab.js"; import "./components/Toast.js"; + export { default as Button } from "./components/Button.js"; export { default as Card } from "./components/Card.js"; export { default as Checkbox } from "./components/Checkbox.js"; diff --git a/UI/sigproui.css b/packages/sigproui/sigproui.css similarity index 62% rename from UI/sigproui.css rename to packages/sigproui/sigproui.css index 9f0f527..67afa05 100644 --- a/UI/sigproui.css +++ b/packages/sigproui/sigproui.css @@ -3,6 +3,12 @@ * Requiere Tailwind CSS y DaisyUI */ +/* Tailwind + DaisyUI */ +@import "tailwindcss"; +@plugin "daisyui" { + themes: light --default, dark; +} + /* Utilidades personalizadas de SigProUI */ .btn-ghost { border-color: transparent !important; @@ -78,6 +84,21 @@ height: 1rem; } +.loading.loading-sm { + width: 1rem; + height: 1rem; +} + +.loading.loading-md { + width: 1.5rem; + height: 1.5rem; +} + +.loading.loading-lg { + width: 2.5rem; + height: 2.5rem; +} + .hidden { display: none; } @@ -90,3 +111,36 @@ transform: rotate(360deg); } } + +/* Loading spinner variants */ +.loading-spinner { + border-right-color: transparent; +} + +.loading-dots::after { + content: ""; + animation: dots 1s infinite; +} + +@keyframes dots { + 0%, 20% { content: "."; } + 40% { content: ".."; } + 60%, 100% { content: "..."; } +} + +.loading-ring { + border-bottom-color: transparent; +} + +.loading-facebook::after { + content: ""; + animation: facebook 1.5s infinite; +} + +@keyframes facebook { + 0% { transform: scale(0, 0.035); } + 25% { transform: scale(0.035, 0.035); } + 50% { transform: scale(0.035, 1); } + 75% { transform: scale(1, 1); } + 100% { transform: scale(1, 0.035); } +} diff --git a/sigpro-router-plugin.js b/sigpro-router-plugin.js deleted file mode 100644 index fbdd32b..0000000 --- a/sigpro-router-plugin.js +++ /dev/null @@ -1 +0,0 @@ -import fs from"fs";import path from"path";export default function sigproRouter(){const e="virtual:sigpro-routes",t="\0"+e;function r(e){let t=[];if(!fs.existsSync(e))return t;return fs.readdirSync(e).forEach((n=>{const o=path.resolve(e,n),s=fs.statSync(o);s&&s.isDirectory()?t=t.concat(r(o)):(n.endsWith(".js")||n.endsWith(".jsx"))&&t.push(o)})),t}return{name:"sigpro-router",resolveId(r){if(r===e)return t},load(e){if(e===t){const e=path.resolve(process.cwd(),"src/pages");let t=r(e);t=t.sort(((t,r)=>{const n=path.relative(e,t).replace(/\\/g,"/"),o=path.relative(e,r).replace(/\\/g,"/"),s=n.includes("[")||n.includes(":");return s!==(o.includes("[")||o.includes(":"))?s?1:-1:o.length-n.length}));let n="",o="export const routes = [\n";return console.log("\n🚀 [SigPro Router] Routes generated:"),t.forEach(((t,r)=>{const s=t.replace(/\\/g,"/"),c=path.relative(e,t).replace(/\\/g,"/"),l=`Page_${r}`;let a=function(e){let t=e.replace(/\\/g,"/").replace(/\.jsx?$/,"");return"index"===t?"/":(t.endsWith("/index")&&(t=t.slice(0,-6)),t=t.replace(/\[([^\]]+)\]/g,":$1"),("/"+t.toLowerCase()).replace(/\/+/g,"/").replace(/\/$/,"")||"/")}(c);const i=a.includes(":");n+=`import ${l} from '${s}';\n`,console.log(` ${i?"🔗":"📄"} ${a.padEnd(30)} -> ${c}`),o+=` { path: '${a}', component: ${l} },\n`})),o+="];",`${n}\n${o}`}}}} \ No newline at end of file diff --git a/sigpro.js b/sigpro.js deleted file mode 100644 index 9c1af3c..0000000 --- a/sigpro.js +++ /dev/null @@ -1 +0,0 @@ -let activeEffect=null;const effectQueue=new Set;let isFlushScheduled=!1,flushCount=0;const flushEffectQueue=()=>{if(isFlushScheduled=!1,flushCount++,flushCount>100)throw effectQueue.clear(),flushCount=0,new Error("SigPro: Infinite reactive loop detected.");try{const e=Array.from(effectQueue);effectQueue.clear();for(const t of e)t.run()}catch(e){console.error("SigPro Flush Error:",e)}finally{setTimeout((()=>{flushCount=0}),0)}},$=e=>{const t=new Set;let n;if("function"==typeof e){let s,o=!0;const c={dependencies:new Set,markDirty:()=>{o||(o=!0,t.forEach((e=>{e.markDirty&&e.markDirty(),effectQueue.add(e)})),!isFlushScheduled&&effectQueue.size&&(isFlushScheduled=!0,queueMicrotask(flushEffectQueue)))},run:()=>{c.dependencies.forEach((e=>e.delete(c))),c.dependencies.clear();const t=activeEffect;activeEffect=c;try{s=e()}finally{activeEffect=t,o=!1}}};n=()=>(activeEffect&&(t.add(activeEffect),activeEffect.dependencies.add(t)),o&&c.run(),s)}else n=(...n)=>{if(n.length){const s="function"==typeof n[0]?n[0](e):n[0];Object.is(e,s)||(e=s,t.forEach((e=>{e.markDirty&&e.markDirty(),effectQueue.add(e)})),!isFlushScheduled&&effectQueue.size&&(isFlushScheduled=!0,queueMicrotask(flushEffectQueue)))}return activeEffect&&(t.add(activeEffect),activeEffect.dependencies.add(t)),e};return n};let currentPageCleanups=null;const $e=e=>{const t={dependencies:new Set,cleanupHandlers:new Set,run(){this.cleanupHandlers.forEach((e=>e())),this.cleanupHandlers.clear(),this.dependencies.forEach((e=>e.delete(this))),this.dependencies.clear();const t=activeEffect;activeEffect=this;try{const t=e();"function"==typeof t&&this.cleanupHandlers.add(t)}finally{activeEffect=t}},stop(){this.cleanupHandlers.forEach((e=>e())),this.dependencies.forEach((e=>e.delete(this)))}};return currentPageCleanups&¤tPageCleanups.push((()=>t.stop())),activeEffect&&activeEffect.cleanupHandlers.add((()=>t.stop())),t.run(),()=>t.stop()},$s=(e,t,n=localStorage)=>{let s;try{const o=n.getItem(e);s=null!==o?JSON.parse(o):t}catch(o){console.warn(`Error reading ${e} from storage:`,o),s=t,n.removeItem(e)}const o=$(s);return $e((()=>{try{const t=o();null==t?n.removeItem(e):n.setItem(e,JSON.stringify(t))}catch(t){console.warn(`Error saving ${e} to storage:`,t)}})),o},html=(e,...t)=>{const n=html._templateCache??(html._templateCache=new WeakMap);let s=n.get(e);if(!s){const t=document.createElement("template");t.innerHTML=e.join("{{part}}");const o=[],c=document.createTreeWalker(t.content,133),r=e=>{const n=[];for(;e&&e!==t.content;){let t=0;for(let n=e.previousSibling;n;n=n.previousSibling)t++;n.push(t),e=e.parentNode}return n.reverse()};let i;for(;i=c.nextNode();){let e=!1;const t={type:i.nodeType,path:r(i),parts:[]};if(1===i.nodeType)for(let n=0;n{return{node:(t=o,n=e.path,n.reduce(((e,t)=>e?.childNodes?.[t]),t)),info:e};var t,n})).forEach((({node:e,info:n})=>{if(e)if(1===n.type)n.parts.forEach((n=>{const s=t[c++],o=n.name,r=o[0];if("@"===r){const[t,...n]=o.slice(1).split("."),c=o=>{if(n.includes("prevent")&&o.preventDefault(),n.includes("stop")&&o.stopPropagation(),!n.includes("self")||o.target===e){if(n.some((e=>e.startsWith("debounce")))){const t=n.find((e=>e.startsWith("debounce")))?.split(":")[1]||300;return clearTimeout(e._debounceTimer),void(e._debounceTimer=setTimeout((()=>s(o)),t))}n.includes("once")&&e.removeEventListener(t,c),s(o)}};e.addEventListener(t,c,{passive:n.includes("passive"),capture:n.includes("capture")})}else if(":"===r){const t=o.slice(1),n="checkbox"===e.type||"radio"===e.type?"change":"input";"function"==typeof s?$e((()=>{const n=s();e[t]!==n&&(e[t]=n)})):e[t]=s,e.addEventListener(n,(()=>{const t="change"===n?e.checked:e.value;"function"==typeof s&&s(t)}))}else if("?"===r){const t=o.slice(1);"function"==typeof s?$e((()=>{const n=s();e.toggleAttribute(t,!!n)})):e.toggleAttribute(t,!!s)}else if("."===r){const t=o.slice(1);"function"==typeof s?$e((()=>{const n=s();e[t]=n,null!=n&&"object"!=typeof n&&"boolean"!=typeof n&&e.setAttribute(t,n)})):(e[t]=s,null!=s&&"object"!=typeof s&&"boolean"!=typeof s&&e.setAttribute(t,s))}else"function"==typeof s?$e((()=>e.setAttribute(o,s()))):e.setAttribute(o,s)}));else if(3===n.type){const n=e.textContent.split("{{part}}").length-1;((e,t)=>{const n=e.textContent.split("{{part}}"),s=e.parentNode;let o=0;n.forEach(((c,r)=>{if(c&&s.insertBefore(document.createTextNode(c),e),r{const e=l();e!==f&&(f=e,i(e))}))}else i(l);function i(e){if("object"==typeof e||Array.isArray(e)){for(;a.nextSibling!==u;)s.removeChild(a.nextSibling);const t=Array.isArray(e)?e:[e],n=document.createDocumentFragment();t.forEach((e=>{if(null==e||!1===e)return;const t=e instanceof Node?e:document.createTextNode(e);n.appendChild(t)})),s.insertBefore(n,u)}else{const t=a.nextSibling,n=String(e??"");if(t!==u&&3===t?.nodeType)t.textContent=n;else{for(;a.nextSibling!==u;)s.removeChild(a.nextSibling);s.insertBefore(document.createTextNode(n),u)}}}}})),e.remove()})(e,t.slice(c,c+n)),c+=n}})),o},$p=e=>{const t="page-"+Math.random().toString(36).substring(2,9);return customElements.define(t,class extends HTMLElement{connectedCallback(){this.style.display="contents",this._cleanups=[],currentPageCleanups=this._cleanups;try{const t=e({params:JSON.parse(this.getAttribute("params")||"{}"),onUnmount:e=>this._cleanups.push(e)});this.appendChild(t instanceof Node?t:document.createTextNode(String(t)))}finally{currentPageCleanups=null}}disconnectedCallback(){this._cleanups.forEach((e=>e())),this._cleanups=[],this.innerHTML=""}}),(e={})=>{const n=document.createElement(t);return n.setAttribute("params",JSON.stringify(e)),n}},$c=(e,t,n=[],s=!1)=>{customElements.get(e)||customElements.define(e,class extends HTMLElement{static get observedAttributes(){return n}constructor(){super(),this._propertySignals={},this.cleanupFunctions=[],this._root=s?this.attachShadow({mode:"open"}):this,n.forEach((e=>this._propertySignals[e]=$(void 0)))}connectedCallback(){const e=[...this.childNodes];this._root.innerHTML="",n.forEach((e=>{const t=this.hasOwnProperty(e)?this[e]:this.getAttribute(e);Object.defineProperty(this,e,{get:()=>this._propertySignals[e](),set:t=>{const n="false"!==t&&(""===t&&"value"!==e||t);this._propertySignals[e](n)},configurable:!0}),null!=t&&(this[e]=t)}));const s={select:e=>this._root.querySelector(e),selectAll:e=>this._root.querySelectorAll(e),slot:t=>e.filter((e=>{const n=1===e.nodeType?e.getAttribute("slot"):null;return t?n===t:!n})),emit:(e,t)=>this.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0,composed:!0})),host:this,root:this._root,onUnmount:e=>this.cleanupFunctions.push(e)},o=t(this._propertySignals,s);o instanceof Node&&this._root.appendChild(o)}attributeChangedCallback(e,t,n){this[e]!==n&&(this[e]=n)}disconnectedCallback(){this.cleanupFunctions.forEach((e=>e())),this.cleanupFunctions=[]}})},$f=async(e,t,n)=>{n&&n(!0);try{const n=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}),s=await n.text();try{return JSON.parse(s)}catch(e){return console.warn("Invalid JSON response"),null}}catch(e){return null}finally{n&&n(!1)}},$r=e=>{const t=document.createElement("div");t.style.display="contents";const n=(e,t)=>{if(!t.includes(":"))return t===e?{}:null;const n=t.split("/"),s=e.split("/");if(n.length!==s.length)return null;const o={};for(let e=0;e{const s=window.location.hash.replace(/^#/,"")||"/";let o=null,c={};for(const t of e){const e=n(s,t.path);if(null!==e){o=t,c=e;break}}const r=o?o.component(c):Object.assign(document.createElement("h1"),{textContent:"404"});t.replaceChildren(r instanceof Node?r:document.createTextNode(String(r??"")))};return window.addEventListener("hashchange",s),s(),t};$r.go=e=>{const t=e.startsWith("/")?e:`/${e}`;window.location.hash!==`#${t}`&&(window.location.hash=t)},$.effect=$e,$.page=$p,$.component=$c,$.fetch=$f,$.router=$r,$.storage=$s,"undefined"!=typeof window&&(window.$=$);export{$,html}; diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 0000000..c231a91 --- /dev/null +++ b/vite.config.js @@ -0,0 +1,24 @@ +import { defineConfig } from 'vite'; +import tailwindcss from '@tailwindcss/vite'; +const isDev = process.env.NODE_ENV === 'development'; + +export default defineConfig({ + base: isDev ? '/absproxy/5175/' : '/', + plugins: [ + tailwindcss(), + ], + root: 'UI', + build: { + outDir: '../dist', + }, + resolve: { + alias: { + 'sigpro': './sigpro.js', + }, + }, + server: { + port: 5175, + open: true, + allowedHosts: true, + }, +});