reset
This commit is contained in:
117
bun.lock
117
bun.lock
@@ -9,14 +9,15 @@
|
|||||||
"name": "dare-client",
|
"name": "dare-client",
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tailwindcss/vite": "^4.2.1",
|
"@tailwindcss/vite": "^4.2.4",
|
||||||
"sigpro": "^1.2.24",
|
"sigpro": "git+http://gitea:3000/natxocc/sigpro",
|
||||||
"sigpro-ui": "^1.2.1",
|
"sigpro-ui": "git+http://gitea:3000/natxocc/sigpro-ui",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@iconify/json": "^2.2.443",
|
"@iconify/json": "^2.2.469",
|
||||||
"@iconify/tailwind4": "^1.2.1",
|
"@iconify/tailwind4": "^1.2.3",
|
||||||
"vite": "^8.0.0",
|
"tailwindcss": "^4.2.4",
|
||||||
|
"vite": "^8.0.10",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"server": {
|
"server": {
|
||||||
@@ -34,15 +35,15 @@
|
|||||||
"packages": {
|
"packages": {
|
||||||
"@antfu/install-pkg": ["@antfu/install-pkg@1.1.0", "", { "dependencies": { "package-manager-detector": "^1.3.0", "tinyexec": "^1.0.1" } }, "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ=="],
|
"@antfu/install-pkg": ["@antfu/install-pkg@1.1.0", "", { "dependencies": { "package-manager-detector": "^1.3.0", "tinyexec": "^1.0.1" } }, "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ=="],
|
||||||
|
|
||||||
"@cyberalien/svg-utils": ["@cyberalien/svg-utils@1.2.9", "", { "dependencies": { "@iconify/types": "^2.0.0" } }, "sha512-bd5I3TQ2k/xqcNB6P6GpFKeid3OgqgGSRz704+XHoGNBAsI7wwYKS6nuxAn26ciUtRjGKovfEy66ryEY9UGUwQ=="],
|
"@cyberalien/svg-utils": ["@cyberalien/svg-utils@1.2.15", "", { "dependencies": { "@iconify/types": "^2.0.0" } }, "sha512-ZbKU6npzW5PNocdoLVJYfKzaP+c/RpT6JUkoaKrW1DOcw6lyXub8XtcNpI3xok6FnyNjS6ZbsrrtjTnS9yeZAQ=="],
|
||||||
|
|
||||||
"@emnapi/core": ["@emnapi/core@1.9.2", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA=="],
|
"@emnapi/core": ["@emnapi/core@1.10.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw=="],
|
||||||
|
|
||||||
"@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="],
|
"@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="],
|
||||||
|
|
||||||
"@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w=="],
|
"@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w=="],
|
||||||
|
|
||||||
"@iconify/json": ["@iconify/json@2.2.463", "", { "dependencies": { "@iconify/types": "*", "pathe": "^2.0.3" } }, "sha512-VZ0n+99OWe9677b04KPF0NajDbFEyWNxMalXZA/4j8HrqyVvY+N1XN/EIER4ceQlKQJ501w9UxLJZjZ5mga0xA=="],
|
"@iconify/json": ["@iconify/json@2.2.469", "", { "dependencies": { "@iconify/types": "*", "pathe": "^2.0.3" } }, "sha512-ARAC23HXrR1QpoR/z+tjGqI3kWgkYsYKJwezWLc8m47dvGpuvZTmQYXSIJVpnHGtUPKylC3jqWb0udXfoDLWeg=="],
|
||||||
|
|
||||||
"@iconify/tailwind4": ["@iconify/tailwind4@1.2.3", "", { "dependencies": { "@iconify/tools": "^5.0.5", "@iconify/types": "^2.0.0", "@iconify/utils": "^3.1.0" }, "peerDependencies": { "tailwindcss": ">= 4.0.0" } }, "sha512-z8SKiMHRASJKF/IY//87MF88lcB7ulxh8vlhQXXLWsBkNtOh6ese9R41MyGpQeqXdRvQVt+/fX2glQtHFjQ+MA=="],
|
"@iconify/tailwind4": ["@iconify/tailwind4@1.2.3", "", { "dependencies": { "@iconify/tools": "^5.0.5", "@iconify/types": "^2.0.0", "@iconify/utils": "^3.1.0" }, "peerDependencies": { "tailwindcss": ">= 4.0.0" } }, "sha512-z8SKiMHRASJKF/IY//87MF88lcB7ulxh8vlhQXXLWsBkNtOh6ese9R41MyGpQeqXdRvQVt+/fX2glQtHFjQ+MA=="],
|
||||||
|
|
||||||
@@ -50,7 +51,7 @@
|
|||||||
|
|
||||||
"@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="],
|
"@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="],
|
||||||
|
|
||||||
"@iconify/utils": ["@iconify/utils@3.1.0", "", { "dependencies": { "@antfu/install-pkg": "^1.1.0", "@iconify/types": "^2.0.0", "mlly": "^1.8.0" } }, "sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw=="],
|
"@iconify/utils": ["@iconify/utils@3.1.1", "", { "dependencies": { "@antfu/install-pkg": "^1.1.0", "@iconify/types": "^2.0.0", "mlly": "^1.8.2" } }, "sha512-MwzoDtw9rO1x+qfgLTV/IVXsHDBqeYZoMIQC8SfxfYSlaSUG+oWiAcoiB1yajAda6mqblm4/1/w2E8tRu7a7Tw=="],
|
||||||
|
|
||||||
"@img/colour": ["@img/colour@1.1.0", "", {}, "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ=="],
|
"@img/colour": ["@img/colour@1.1.0", "", {}, "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ=="],
|
||||||
|
|
||||||
@@ -116,69 +117,69 @@
|
|||||||
|
|
||||||
"@nodable/entities": ["@nodable/entities@2.1.0", "", {}, "sha512-nyT7T3nbMyBI/lvr6L5TyWbFJAI9FTgVRakNoBqCD+PmID8DzFrrNdLLtHMwMszOtqZa8PAOV24ZqDnQrhQINA=="],
|
"@nodable/entities": ["@nodable/entities@2.1.0", "", {}, "sha512-nyT7T3nbMyBI/lvr6L5TyWbFJAI9FTgVRakNoBqCD+PmID8DzFrrNdLLtHMwMszOtqZa8PAOV24ZqDnQrhQINA=="],
|
||||||
|
|
||||||
"@oxc-project/types": ["@oxc-project/types@0.124.0", "", {}, "sha512-VBFWMTBvHxS11Z5Lvlr3IWgrwhMTXV+Md+EQF0Xf60+wAdsGFTBx7X7K/hP4pi8N7dcm1RvcHwDxZ16Qx8keUg=="],
|
"@oxc-project/types": ["@oxc-project/types@0.127.0", "", {}, "sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ=="],
|
||||||
|
|
||||||
"@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-rc.15", "", { "os": "android", "cpu": "arm64" }, "sha512-YYe6aWruPZDtHNpwu7+qAHEMbQ/yRl6atqb/AhznLTnD3UY99Q1jE7ihLSahNWkF4EqRPVC4SiR4O0UkLK02tA=="],
|
"@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-rc.17", "", { "os": "android", "cpu": "arm64" }, "sha512-s70pVGhw4zqGeFnXWvAzJDlvxhlRollagdCCKRgOsgUOH3N1l0LIxf83AtGzmb5SiVM4Hjl5HyarMRfdfj3DaQ=="],
|
||||||
|
|
||||||
"@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-rc.15", "", { "os": "darwin", "cpu": "arm64" }, "sha512-oArR/ig8wNTPYsXL+Mzhs0oxhxfuHRfG7Ikw7jXsw8mYOtk71W0OkF2VEVh699pdmzjPQsTjlD1JIOoHkLP1Fg=="],
|
"@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-rc.17", "", { "os": "darwin", "cpu": "arm64" }, "sha512-4ksWc9n0mhlZpZ9PMZgTGjeOPRu8MB1Z3Tz0Mo02eWfWCHMW1zN82Qz/pL/rC+yQa+8ZnutMF0JjJe7PjwasYw=="],
|
||||||
|
|
||||||
"@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-rc.15", "", { "os": "darwin", "cpu": "x64" }, "sha512-YzeVqOqjPYvUbJSWJ4EDL8ahbmsIXQpgL3JVipmN+MX0XnXMeWomLN3Fb+nwCmP/jfyqte5I3XRSm7OfQrbyxw=="],
|
"@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-rc.17", "", { "os": "darwin", "cpu": "x64" }, "sha512-SUSDOI6WwUVNcWxd02QEBjLdY1VPHvlEkw6T/8nYG322iYWCTxRb1vzk4E+mWWYehTp7ERibq54LSJGjmouOsw=="],
|
||||||
|
|
||||||
"@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-rc.15", "", { "os": "freebsd", "cpu": "x64" }, "sha512-9Erhx956jeQ0nNTyif1+QWAXDRD38ZNjr//bSHrt6wDwB+QkAfl2q6Mn1k6OBPerznjRmbM10lgRb1Pli4xZPw=="],
|
"@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-rc.17", "", { "os": "freebsd", "cpu": "x64" }, "sha512-hwnz3nw9dbJ05EDO/PvcjaaewqqDy7Y1rn1UO81l8iIK1GjenME75dl16ajbvSSMfv66WXSRCYKIqfgq2KCfxw=="],
|
||||||
|
|
||||||
"@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.15", "", { "os": "linux", "cpu": "arm" }, "sha512-cVwk0w8QbZJGTnP/AHQBs5yNwmpgGYStL88t4UIaqcvYJWBfS0s3oqVLZPwsPU6M0zlW4GqjP0Zq5MnAGwFeGA=="],
|
"@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.17", "", { "os": "linux", "cpu": "arm" }, "sha512-IS+W7epTcwANmFSQFrS1SivEXHtl1JtuQA9wlxrZTcNi6mx+FDOYrakGevvvTwgj2JvWiK8B29/qD9BELZPyXQ=="],
|
||||||
|
|
||||||
"@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-rc.15", "", { "os": "linux", "cpu": "arm64" }, "sha512-eBZ/u8iAK9SoHGanqe/jrPnY0JvBN6iXbVOsbO38mbz+ZJsaobExAm1Iu+rxa4S1l2FjG0qEZn4Rc6X8n+9M+w=="],
|
"@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-rc.17", "", { "os": "linux", "cpu": "arm64" }, "sha512-e6usGaHKW5BMNZOymS1UcEYGowQMWcgZ71Z17Sl/h2+ZziNJ1a9n3Zvcz6LdRyIW5572wBCTH/Z+bKuZouGk9Q=="],
|
||||||
|
|
||||||
"@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-rc.15", "", { "os": "linux", "cpu": "arm64" }, "sha512-ZvRYMGrAklV9PEkgt4LQM6MjQX2P58HPAuecwYObY2DhS2t35R0I810bKi0wmaYORt6m/2Sm+Z+nFgb0WhXNcQ=="],
|
"@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-rc.17", "", { "os": "linux", "cpu": "arm64" }, "sha512-b/CgbwAJpmrRLp02RPfhbudf5tZnN9nsPWK82znefso832etkem8H7FSZwxrOI9djcdTP7U6YfNhbRnh7djErg=="],
|
||||||
|
|
||||||
"@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.15", "", { "os": "linux", "cpu": "ppc64" }, "sha512-VDpgGBzgfg5hLg+uBpCLoFG5kVvEyafmfxGUV0UHLcL5irxAK7PKNeC2MwClgk6ZAiNhmo9FLhRYgvMmedLtnQ=="],
|
"@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.17", "", { "os": "linux", "cpu": "ppc64" }, "sha512-4EII1iNGRUN5WwGbF/kOh/EIkoDN9HsupgLQoXfY+D1oyJm7/F4t5PYU5n8SWZgG0FEwakyM8pGgwcBYruGTlA=="],
|
||||||
|
|
||||||
"@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.0.0-rc.15", "", { "os": "linux", "cpu": "s390x" }, "sha512-y1uXY3qQWCzcPgRJATPSOUP4tCemh4uBdY7e3EZbVwCJTY3gLJWnQABgeUetvED+bt1FQ01OeZwvhLS2bpNrAQ=="],
|
"@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.0.0-rc.17", "", { "os": "linux", "cpu": "s390x" }, "sha512-AH8oq3XqQo4IibpVXvPeLDI5pzkpYn0WiZAfT05kFzoJ6tQNzwRdDYQ45M8I/gslbodRZwW8uxLhbSBbkv96rA=="],
|
||||||
|
|
||||||
"@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-rc.15", "", { "os": "linux", "cpu": "x64" }, "sha512-023bTPBod7J3Y/4fzAN6QtpkSABR0rigtrwaP+qSEabUh5zf6ELr9Nc7GujaROuPY3uwdSIXWrvhn1KxOvurWA=="],
|
"@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-rc.17", "", { "os": "linux", "cpu": "x64" }, "sha512-cLnjV3xfo7KslbU41Z7z8BH/E1y5mzUYzAqih1d1MDaIGZRCMqTijqLv76/P7fyHuvUcfGsIpqCdddbxLLK9rA=="],
|
||||||
|
|
||||||
"@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-rc.15", "", { "os": "linux", "cpu": "x64" }, "sha512-witB2O0/hU4CgfOOKUoeFgQ4GktPi1eEbAhaLAIpgD6+ZnhcPkUtPsoKKHRzmOoWPZue46IThdSgdo4XneOLYw=="],
|
"@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-rc.17", "", { "os": "linux", "cpu": "x64" }, "sha512-0phclDw1spsL7dUB37sIARuis2tAgomCJXAHZlpt8PXZ4Ba0dRP1e+66lsRqrfhISeN9bEGNjQs+T/Fbd7oYGw=="],
|
||||||
|
|
||||||
"@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-rc.15", "", { "os": "none", "cpu": "arm64" }, "sha512-UCL68NJ0Ud5zRipXZE9dF5PmirzJE4E4BCIOOssEnM7wLDsxjc6Qb0sGDxTNRTP53I6MZpygyCpY8Aa8sPfKPg=="],
|
"@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-rc.17", "", { "os": "none", "cpu": "arm64" }, "sha512-0ag/hEgXOwgw4t8QyQvUCxvEg+V0KBcA6YuOx9g0r02MprutRF5dyljgm3EmR02O292UX7UeS6HzWHAl6KgyhA=="],
|
||||||
|
|
||||||
"@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-rc.15", "", { "dependencies": { "@emnapi/core": "1.9.2", "@emnapi/runtime": "1.9.2", "@napi-rs/wasm-runtime": "^1.1.3" }, "cpu": "none" }, "sha512-ApLruZq/ig+nhaE7OJm4lDjayUnOHVUa77zGeqnqZ9pn0ovdVbbNPerVibLXDmWeUZXjIYIT8V3xkT58Rm9u5Q=="],
|
"@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-rc.17", "", { "dependencies": { "@emnapi/core": "1.10.0", "@emnapi/runtime": "1.10.0", "@napi-rs/wasm-runtime": "^1.1.4" }, "cpu": "none" }, "sha512-LEXei6vo0E5wTGwpkJ4KoT3OZJRnglwldt5ziLzOlc6qqb55z4tWNq2A+PFqCJuvWWdP53CVhG1Z9NtToDPJrA=="],
|
||||||
|
|
||||||
"@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-rc.15", "", { "os": "win32", "cpu": "arm64" }, "sha512-KmoUoU7HnN+Si5YWJigfTws1jz1bKBYDQKdbLspz0UaqjjFkddHsqorgiW1mxcAj88lYUE6NC/zJNwT+SloqtA=="],
|
"@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-rc.17", "", { "os": "win32", "cpu": "arm64" }, "sha512-gUmyzBl3SPMa6hrqFUth9sVfcLBlYsbMzBx5PlexMroZStgzGqlZ26pYG89rBb45Mnia+oil6YAIFeEWGWhoZA=="],
|
||||||
|
|
||||||
"@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-rc.15", "", { "os": "win32", "cpu": "x64" }, "sha512-3P2A8L+x75qavWLe/Dll3EYBJLQmtkJN8rfh+U/eR3MqMgL/h98PhYI+JFfXuDPgPeCB7iZAKiqii5vqOvnA0g=="],
|
"@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-rc.17", "", { "os": "win32", "cpu": "x64" }, "sha512-3hkiolcUAvPB9FLb3UZdfjVVNWherN1f/skkGWJP/fgSQhYUZpSIRr0/I8ZK9TkF3F7kxvJAk0+IcKvPHk9qQg=="],
|
||||||
|
|
||||||
"@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.15", "", {}, "sha512-UromN0peaE53IaBRe9W7CjrZgXl90fqGpK+mIZbA3qSTeYqg3pqpROBdIPvOG3F5ereDHNwoHBI2e50n1BDr1g=="],
|
"@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.17", "", {}, "sha512-n8iosDOt6Ig1UhJ2AYqoIhHWh/isz0xpicHTzpKBeotdVsTEcxsSA/i3EVM7gQAj0rU27OLAxCjzlj15IWY7bg=="],
|
||||||
|
|
||||||
"@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/node": ["@tailwindcss/node@4.2.4", "", { "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.4" } }, "sha512-Ai7+yQPxz3ddrDQzFfBKdHEVBg0w3Zl83jnjuwxnZOsnH9pGn93QHQtpU0p/8rYWxvbFZHneni6p1BSLK4DkGA=="],
|
||||||
|
|
||||||
"@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": ["@tailwindcss/oxide@4.2.4", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.2.4", "@tailwindcss/oxide-darwin-arm64": "4.2.4", "@tailwindcss/oxide-darwin-x64": "4.2.4", "@tailwindcss/oxide-freebsd-x64": "4.2.4", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.4", "@tailwindcss/oxide-linux-arm64-gnu": "4.2.4", "@tailwindcss/oxide-linux-arm64-musl": "4.2.4", "@tailwindcss/oxide-linux-x64-gnu": "4.2.4", "@tailwindcss/oxide-linux-x64-musl": "4.2.4", "@tailwindcss/oxide-wasm32-wasi": "4.2.4", "@tailwindcss/oxide-win32-arm64-msvc": "4.2.4", "@tailwindcss/oxide-win32-x64-msvc": "4.2.4" } }, "sha512-9El/iI069DKDSXwTvB9J4BwdO5JhRrOweGaK25taBAvBXyXqJAX+Jqdvs8r8gKpsI/1m0LeJLyQYTf/WLrBT1Q=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.2.2", "", { "os": "android", "cpu": "arm64" }, "sha512-dXGR1n+P3B6748jZO/SvHZq7qBOqqzQ+yFrXpoOWWALWndF9MoSKAT3Q0fYgAzYzGhxNYOoysRvYlpixRBBoDg=="],
|
"@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.2.4", "", { "os": "android", "cpu": "arm64" }, "sha512-e7MOr1SAn9U8KlZzPi1ZXGZHeC5anY36qjNwmZv9pOJ8E4Q6jmD1vyEHkQFmNOIN7twGPEMXRHmitN4zCMN03g=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.2.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-iq9Qjr6knfMpZHj55/37ouZeykwbDqF21gPFtfnhCCKGDcPI/21FKC9XdMO/XyBM7qKORx6UIhGgg6jLl7BZlg=="],
|
"@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.2.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-tSC/Kbqpz/5/o/C2sG7QvOxAKqyd10bq+ypZNf+9Fi2TvbVbv1zNpcEptcsU7DPROaSbVgUXmrzKhurFvo5eDg=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.2.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-BlR+2c3nzc8f2G639LpL89YY4bdcIdUmiOOkv2GQv4/4M0vJlpXEa0JXNHhCHU7VWOKWT/CjqHdTP8aUuDJkuw=="],
|
"@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.2.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-yPyUXn3yO/ufR6+Kzv0t4fCg2qNr90jxXc5QqBpjlPNd0NqyDXcmQb/6weunH/MEDXW5dhyEi+agTDiqa3WsGg=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.2.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-YUqUgrGMSu2CDO82hzlQ5qSb5xmx3RUrke/QgnoEx7KvmRJHQuZHZmZTLSuuHwFf0DJPybFMXMYf+WJdxHy/nQ=="],
|
"@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.2.4", "", { "os": "freebsd", "cpu": "x64" }, "sha512-BoMIB4vMQtZsXdGLVc2z+P9DbETkiopogfWZKbWwM8b/1Vinbs4YcUwo+kM/KeLkX3Ygrf4/PsRndKaYhS8Eiw=="],
|
||||||
|
|
||||||
"@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-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.2.4", "", { "os": "linux", "cpu": "arm" }, "sha512-7pIHBLTHYRAlS7V22JNuTh33yLH4VElwKtB3bwchK/UaKUPpQ0lPQiOWcbm4V3WP2I6fNIJ23vABIvoy2izdwA=="],
|
||||||
|
|
||||||
"@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-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-+E4wxJ0ZGOzSH325reXTWB48l42i93kQqMvDyz5gqfRzRZ7faNhnmvlV4EPGJU3QJM/3Ab5jhJ5pCRUsKn6OQw=="],
|
||||||
|
|
||||||
"@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-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-bBADEGAbo4ASnppIziaQJelekCxdMaxisrk+fB7Thit72IBnALp9K6ffA2G4ruj90G9XRS2VQ6q2bCKbfFV82g=="],
|
||||||
|
|
||||||
"@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-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-7Mx25E4WTfnht0TVRTyC00j3i0M+EeFe7wguMDTlX4mRxafznw0CA8WJkFjWYH5BlgELd1kSjuU2JiPnNZbJDA=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.2.2", "", { "os": "linux", "cpu": "x64" }, "sha512-XW3t3qwbIwiSyRCggeO2zxe3KWaEbM0/kW9e8+0XpBgyKU4ATYzcVSMKteZJ1iukJ3HgHBjbg9P5YPRCVUxlnQ=="],
|
"@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-2wwJRF7nyhOR0hhHoChc04xngV3iS+akccHTGtz965FwF0up4b2lOdo6kI1EbDaEXKgvcrFBYcYQQ/rrnWFVfA=="],
|
||||||
|
|
||||||
"@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-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.2.4", "", { "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-FQsqApeor8Fo6gUEklzmaa9994orJZZDBAlQpK2Mq+DslRKFJeD6AjHpBQ0kZFQohVr8o85PPh8eOy86VlSCmw=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.2.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-qPmaQM4iKu5mxpsrWZMOZRgZv1tOZpUm+zdhhQP0VhJfyGGO3aUKdbh3gDZc/dPLQwW4eSqWGrrcWNBZWUWaXQ=="],
|
"@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.2.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-L9BXqxC4ToVgwMFqj3pmZRqyHEztulpUJzCxUtLjobMCzTPsGt1Fa9enKbOpY2iIyVtaHNeNvAK8ERP/64sqGQ=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.2.2", "", { "os": "win32", "cpu": "x64" }, "sha512-1T/37VvI7WyH66b+vqHj/cLwnCxt7Qt3WFu5Q8hk65aOvlwAhs7rAp1VkulBJw/N4tMirXjVnylTR72uI0HGcA=="],
|
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.2.4", "", { "os": "win32", "cpu": "x64" }, "sha512-ESlKG0EpVJQwRjXDDa9rLvhEAh0mhP1sF7sap9dNZT0yyl9SAG6T7gdP09EH0vIv0UNTlo6jPWyujD6559fZvw=="],
|
||||||
|
|
||||||
"@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=="],
|
"@tailwindcss/vite": ["@tailwindcss/vite@4.2.4", "", { "dependencies": { "@tailwindcss/node": "4.2.4", "@tailwindcss/oxide": "4.2.4", "tailwindcss": "4.2.4" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7 || ^8" } }, "sha512-pCvohwOCspk3ZFn6eJzrrX3g4n2JY73H6MmYC87XfGPyTty4YsCjYTMArRZm/zOI8dIt3+EcrLHAFPe5A4bgtw=="],
|
||||||
|
|
||||||
"@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
"@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
||||||
|
|
||||||
@@ -218,13 +219,13 @@
|
|||||||
|
|
||||||
"domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="],
|
"domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="],
|
||||||
|
|
||||||
"enhanced-resolve": ["enhanced-resolve@5.20.1", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.0" } }, "sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA=="],
|
"enhanced-resolve": ["enhanced-resolve@5.21.0", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.3" } }, "sha512-otxSQPw4lkOZWkHpB3zaEQs6gWYEsmX4xQF68ElXC/TWvGxGMSGOvoNbaLXm6/cS/fSfHtsEdw90y20PCd+sCA=="],
|
||||||
|
|
||||||
"entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
|
"entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
|
||||||
|
|
||||||
"fast-xml-builder": ["fast-xml-builder@1.1.5", "", { "dependencies": { "path-expression-matcher": "^1.1.3" } }, "sha512-4TJn/8FKLeslLAH3dnohXqE3QSoxkhvaMzepOIZytwJXZO69Bfz0HBdDHzOTOon6G59Zrk6VQ2bEiv1t61rfkA=="],
|
"fast-xml-builder": ["fast-xml-builder@1.1.5", "", { "dependencies": { "path-expression-matcher": "^1.1.3" } }, "sha512-4TJn/8FKLeslLAH3dnohXqE3QSoxkhvaMzepOIZytwJXZO69Bfz0HBdDHzOTOon6G59Zrk6VQ2bEiv1t61rfkA=="],
|
||||||
|
|
||||||
"fast-xml-parser": ["fast-xml-parser@5.7.0", "", { "dependencies": { "@nodable/entities": "^2.1.0", "fast-xml-builder": "^1.1.5", "path-expression-matcher": "^1.5.0", "strnum": "^2.2.3" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-MTcrUoRQ1GSQ9iG3QJzBGquYYYeA7piZaJoIWbPFGbRn6Jj6z7xgoAyi4DrZX4y2ZIQQBF59gc/zmvvejjgoFQ=="],
|
"fast-xml-parser": ["fast-xml-parser@5.7.2", "", { "dependencies": { "@nodable/entities": "^2.1.0", "fast-xml-builder": "^1.1.5", "path-expression-matcher": "^1.5.0", "strnum": "^2.2.3" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-P7oW7tLbYnhOLQk/Gv7cZgzgMPP/XN03K02/Jy6Y/NHzyIAIpxuZIM/YqAkfiXFPxA2CTm7NtCijK9EDu09u2w=="],
|
||||||
|
|
||||||
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
|
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
|
||||||
|
|
||||||
@@ -234,7 +235,7 @@
|
|||||||
|
|
||||||
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
||||||
|
|
||||||
"hono": ["hono@4.12.14", "", {}, "sha512-am5zfg3yu6sqn5yjKBNqhnTX7Cv+m00ox+7jbaKkrLMRJ4rAdldd1xPd/JzbBWspqaQv6RSTrgFN95EsfhC+7w=="],
|
"hono": ["hono@4.12.16", "", {}, "sha512-jN0ZewiNAWSe5khM3EyCmBb250+b40wWbwNILNfEvq84VREWwOIkuUsFONk/3i3nqkz7Oe1PcpM2mwQEK2L9Kg=="],
|
||||||
|
|
||||||
"iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="],
|
"iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="],
|
||||||
|
|
||||||
@@ -276,9 +277,9 @@
|
|||||||
|
|
||||||
"modern-tar": ["modern-tar@0.7.6", "", {}, "sha512-sweCIVXzx1aIGTCdzcMlSZt1h8k5Tmk08VNAuRk3IU28XamGiOH5ypi11g6De2CH7PhYqSSnGy2A/EFhbWnVKg=="],
|
"modern-tar": ["modern-tar@0.7.6", "", {}, "sha512-sweCIVXzx1aIGTCdzcMlSZt1h8k5Tmk08VNAuRk3IU28XamGiOH5ypi11g6De2CH7PhYqSSnGy2A/EFhbWnVKg=="],
|
||||||
|
|
||||||
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
"nanoid": ["nanoid@3.3.12", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ=="],
|
||||||
|
|
||||||
"nodemailer": ["nodemailer@8.0.5", "", {}, "sha512-0PF8Yb1yZuQfQbq+5/pZJrtF6WQcjTd5/S4JOHs9PGFxuTqoB/icwuB44pOdURHJbRKX1PPoJZtY7R4VUoCC8w=="],
|
"nodemailer": ["nodemailer@8.0.7", "", {}, "sha512-pkjE4mkBzQjdJT4/UmlKl3pX0rC9fZmjh7c6C9o7lv66Ac6w9WCnzPzhbPNxwZAzlF4mdq4CSWB5+FbK6FWCow=="],
|
||||||
|
|
||||||
"nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="],
|
"nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="],
|
||||||
|
|
||||||
@@ -294,9 +295,9 @@
|
|||||||
|
|
||||||
"pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="],
|
"pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="],
|
||||||
|
|
||||||
"postcss": ["postcss@8.5.10", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ=="],
|
"postcss": ["postcss@8.5.13", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-qif0+jGGZoLWdHey3UFHHWP0H7Gbmsk8T5VEqyYFbWqPr1XqvLGBbk/sl8V5exGmcYJklJOhOQq1pV9IcsiFag=="],
|
||||||
|
|
||||||
"rolldown": ["rolldown@1.0.0-rc.15", "", { "dependencies": { "@oxc-project/types": "=0.124.0", "@rolldown/pluginutils": "1.0.0-rc.15" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.15", "@rolldown/binding-darwin-arm64": "1.0.0-rc.15", "@rolldown/binding-darwin-x64": "1.0.0-rc.15", "@rolldown/binding-freebsd-x64": "1.0.0-rc.15", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.15", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.15", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.15", "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.15", "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.15", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.15", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.15", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.15", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.15", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.15", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.15" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-Ff31guA5zT6WjnGp0SXw76X6hzGRk/OQq2hE+1lcDe+lJdHSgnSX6nK3erbONHyCbpSj9a9E+uX/OvytZoWp2g=="],
|
"rolldown": ["rolldown@1.0.0-rc.17", "", { "dependencies": { "@oxc-project/types": "=0.127.0", "@rolldown/pluginutils": "1.0.0-rc.17" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.17", "@rolldown/binding-darwin-arm64": "1.0.0-rc.17", "@rolldown/binding-darwin-x64": "1.0.0-rc.17", "@rolldown/binding-freebsd-x64": "1.0.0-rc.17", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.17", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.17", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.17", "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.17", "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.17", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.17", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.17", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.17", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.17", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.17", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.17" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-ZrT53oAKrtA4+YtBWPQbtPOxIbVDbxT0orcYERKd63VJTF13zPcgXTvD4843L8pcsI7M6MErt8QtON6lrB9tyA=="],
|
||||||
|
|
||||||
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
|
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
|
||||||
|
|
||||||
@@ -306,9 +307,9 @@
|
|||||||
|
|
||||||
"sharp": ["sharp@0.34.5", "", { "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.2", "semver": "^7.7.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.5", "@img/sharp-darwin-x64": "0.34.5", "@img/sharp-libvips-darwin-arm64": "1.2.4", "@img/sharp-libvips-darwin-x64": "1.2.4", "@img/sharp-libvips-linux-arm": "1.2.4", "@img/sharp-libvips-linux-arm64": "1.2.4", "@img/sharp-libvips-linux-ppc64": "1.2.4", "@img/sharp-libvips-linux-riscv64": "1.2.4", "@img/sharp-libvips-linux-s390x": "1.2.4", "@img/sharp-libvips-linux-x64": "1.2.4", "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", "@img/sharp-libvips-linuxmusl-x64": "1.2.4", "@img/sharp-linux-arm": "0.34.5", "@img/sharp-linux-arm64": "0.34.5", "@img/sharp-linux-ppc64": "0.34.5", "@img/sharp-linux-riscv64": "0.34.5", "@img/sharp-linux-s390x": "0.34.5", "@img/sharp-linux-x64": "0.34.5", "@img/sharp-linuxmusl-arm64": "0.34.5", "@img/sharp-linuxmusl-x64": "0.34.5", "@img/sharp-wasm32": "0.34.5", "@img/sharp-win32-arm64": "0.34.5", "@img/sharp-win32-ia32": "0.34.5", "@img/sharp-win32-x64": "0.34.5" } }, "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg=="],
|
"sharp": ["sharp@0.34.5", "", { "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.2", "semver": "^7.7.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.5", "@img/sharp-darwin-x64": "0.34.5", "@img/sharp-libvips-darwin-arm64": "1.2.4", "@img/sharp-libvips-darwin-x64": "1.2.4", "@img/sharp-libvips-linux-arm": "1.2.4", "@img/sharp-libvips-linux-arm64": "1.2.4", "@img/sharp-libvips-linux-ppc64": "1.2.4", "@img/sharp-libvips-linux-riscv64": "1.2.4", "@img/sharp-libvips-linux-s390x": "1.2.4", "@img/sharp-libvips-linux-x64": "1.2.4", "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", "@img/sharp-libvips-linuxmusl-x64": "1.2.4", "@img/sharp-linux-arm": "0.34.5", "@img/sharp-linux-arm64": "0.34.5", "@img/sharp-linux-ppc64": "0.34.5", "@img/sharp-linux-riscv64": "0.34.5", "@img/sharp-linux-s390x": "0.34.5", "@img/sharp-linux-x64": "0.34.5", "@img/sharp-linuxmusl-arm64": "0.34.5", "@img/sharp-linuxmusl-x64": "0.34.5", "@img/sharp-wasm32": "0.34.5", "@img/sharp-win32-arm64": "0.34.5", "@img/sharp-win32-ia32": "0.34.5", "@img/sharp-win32-x64": "0.34.5" } }, "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg=="],
|
||||||
|
|
||||||
"sigpro": ["sigpro@1.2.24", "", {}, "sha512-0EtkWBzkUX1+GzHiCxthHOSOFatgxkNuogpdP4yEO/aSDCiNLt6NiVTU84dBUQ0tQM7erdsGdqHk9Hp/mzwX/w=="],
|
"sigpro": ["sigpro@git+http://gitea:3000/natxocc/sigpro#ab0e6e06974308b28cc54229cf0301ab81d7c132", {}, "ab0e6e06974308b28cc54229cf0301ab81d7c132"],
|
||||||
|
|
||||||
"sigpro-ui": ["sigpro-ui@1.2.1", "", {}, "sha512-mtUfLHhP/T1msiVG0T1YxR+4L4N+zB9nazPrY9Ypw1d97YhP7QW6T1gPp/TbhLnFOdIgIkNGz04J5gpbkdtQaA=="],
|
"sigpro-ui": ["sigpro-ui@git+http://gitea:3000/natxocc/sigpro-ui#2832e1df1e66e3f7d8ba02342729e8d534b9b1a1", {}, "2832e1df1e66e3f7d8ba02342729e8d534b9b1a1"],
|
||||||
|
|
||||||
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
||||||
|
|
||||||
@@ -316,25 +317,23 @@
|
|||||||
|
|
||||||
"svgo": ["svgo@4.0.1", "", { "dependencies": { "commander": "^11.1.0", "css-select": "^5.1.0", "css-tree": "^3.0.1", "css-what": "^6.1.0", "csso": "^5.0.5", "picocolors": "^1.1.1", "sax": "^1.5.0" }, "bin": "./bin/svgo.js" }, "sha512-XDpWUOPC6FEibaLzjfe0ucaV0YrOjYotGJO1WpF0Zd+n6ZGEQUsSugaoLq9QkEZtAfQIxT42UChcssDVPP3+/w=="],
|
"svgo": ["svgo@4.0.1", "", { "dependencies": { "commander": "^11.1.0", "css-select": "^5.1.0", "css-tree": "^3.0.1", "css-what": "^6.1.0", "csso": "^5.0.5", "picocolors": "^1.1.1", "sax": "^1.5.0" }, "bin": "./bin/svgo.js" }, "sha512-XDpWUOPC6FEibaLzjfe0ucaV0YrOjYotGJO1WpF0Zd+n6ZGEQUsSugaoLq9QkEZtAfQIxT42UChcssDVPP3+/w=="],
|
||||||
|
|
||||||
"tailwindcss": ["tailwindcss@4.2.2", "", {}, "sha512-KWBIxs1Xb6NoLdMVqhbhgwZf2PGBpPEiwOqgI4pFIYbNTfBXiKYyWoTsXgBQ9WFg/OlhnvHaY+AEpW7wSmFo2Q=="],
|
"tailwindcss": ["tailwindcss@4.2.4", "", {}, "sha512-HhKppgO81FQof5m6TEnuBWCZGgfRAWbaeOaGT00KOy/Pf/j6oUihdvBpA7ltCeAvZpFhW3j0PTclkxsd4IXYDA=="],
|
||||||
|
|
||||||
"tapable": ["tapable@2.3.2", "", {}, "sha512-1MOpMXuhGzGL5TTCZFItxCc0AARf1EZFQkGqMm7ERKj8+Hgr5oLvJOVFcC+lRmR8hCe2S3jC4T5D7Vg/d7/fhA=="],
|
"tapable": ["tapable@2.3.3", "", {}, "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A=="],
|
||||||
|
|
||||||
"tinyexec": ["tinyexec@1.1.1", "", {}, "sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg=="],
|
"tinyexec": ["tinyexec@1.1.2", "", {}, "sha512-dAqSqE/RabpBKI8+h26GfLq6Vb3JVXs30XYQjdMjaj/c2tS8IYYMbIzP599KtRj7c57/wYApb3QjgRgXmrCukA=="],
|
||||||
|
|
||||||
"tinyglobby": ["tinyglobby@0.2.16", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg=="],
|
"tinyglobby": ["tinyglobby@0.2.16", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg=="],
|
||||||
|
|
||||||
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||||
|
|
||||||
"ufo": ["ufo@1.6.3", "", {}, "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q=="],
|
"ufo": ["ufo@1.6.4", "", {}, "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA=="],
|
||||||
|
|
||||||
"undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="],
|
"undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="],
|
||||||
|
|
||||||
"vite": ["vite@8.0.8", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.8", "rolldown": "1.0.0-rc.15", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.0", "esbuild": "^0.27.0 || ^0.28.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-dbU7/iLVa8KZALJyLOBOQ88nOXtNG8vxKuOT4I2mD+Ya70KPceF4IAmDsmU0h1Qsn5bPrvsY9HJstCRh3hG6Uw=="],
|
"vite": ["vite@8.0.10", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.10", "rolldown": "1.0.0-rc.17", "tinyglobby": "^0.2.16" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.0", "esbuild": "^0.27.0 || ^0.28.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-rZuUu9j6J5uotLDs+cAA4O5H4K1SfPliUlQwqa6YEwSrWDZzP4rhm00oJR5snMewjxF5V/K3D4kctsUTsIU9Mw=="],
|
||||||
|
|
||||||
"@rolldown/binding-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.9.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw=="],
|
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.10.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" }, "bundled": true }, "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.9.2", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" }, "bundled": true }, "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="],
|
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="],
|
||||||
|
|
||||||
|
|||||||
286
client/App.js
Normal file
286
client/App.js
Normal file
@@ -0,0 +1,286 @@
|
|||||||
|
// App.js
|
||||||
|
import { $, watch, h, when } from "./sigpro.js";
|
||||||
|
import {
|
||||||
|
Navbar,
|
||||||
|
Drawer,
|
||||||
|
DrawerToggle,
|
||||||
|
DrawerContent,
|
||||||
|
DrawerSide,
|
||||||
|
DrawerOverlay,
|
||||||
|
Menu,
|
||||||
|
Tabs,
|
||||||
|
Swap,
|
||||||
|
SwapToggle,
|
||||||
|
SwapOn,
|
||||||
|
SwapOff,
|
||||||
|
Icon,
|
||||||
|
Avatar,
|
||||||
|
Dropdown,
|
||||||
|
DropdownButton,
|
||||||
|
DropdownContent,
|
||||||
|
Modal,
|
||||||
|
Fieldset,
|
||||||
|
Input,
|
||||||
|
Button
|
||||||
|
} from "./sigpro-ui.js";
|
||||||
|
import './sigpro-ui.css';
|
||||||
|
|
||||||
|
export const App = () => {
|
||||||
|
// Tema oscuro/claro
|
||||||
|
const isDark = $(localStorage.getItem("theme") === "dark"
|
||||||
|
|| (!localStorage.getItem("theme") && window.matchMedia("(prefers-color-scheme: dark)").matches));
|
||||||
|
|
||||||
|
// Sincronizar el tema con el atributo data-theme del HTML
|
||||||
|
watch(isDark, (dark) => {
|
||||||
|
const theme = dark ? "dark" : "light";
|
||||||
|
document.documentElement.setAttribute("data-theme", theme);
|
||||||
|
localStorage.setItem("theme", theme);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Activar tema inicial
|
||||||
|
document.documentElement.setAttribute("data-theme", isDark() ? "dark" : "light");
|
||||||
|
|
||||||
|
// Estado de login persistente
|
||||||
|
const logged = $(false, "logged");
|
||||||
|
|
||||||
|
// Estado para buscador
|
||||||
|
const searchQuery = $("");
|
||||||
|
|
||||||
|
// Estado para modal de login
|
||||||
|
const showLoginModal = $(false);
|
||||||
|
const loginForm = {
|
||||||
|
username: $(""),
|
||||||
|
password: $("")
|
||||||
|
};
|
||||||
|
|
||||||
|
// Pestañas: la primera (Escritorio) no es cerrable
|
||||||
|
const tabs = $([
|
||||||
|
{
|
||||||
|
label: "Escritorio",
|
||||||
|
content: () => `¡Bienvenido al escritorio!`,
|
||||||
|
closable: false
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
const activeTab = $(0);
|
||||||
|
const openDrawer = $(false);
|
||||||
|
|
||||||
|
// Elementos del menú en el drawer
|
||||||
|
const menuItems = [
|
||||||
|
{
|
||||||
|
label: "Clientes",
|
||||||
|
children: [
|
||||||
|
{ label: "Buscar Cliente", onclick: () => openTab("Clientes") },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Recibos",
|
||||||
|
children: [
|
||||||
|
{ label: "Buscar Recibo" },
|
||||||
|
{ label: "Pendientes" },
|
||||||
|
{ label: "Extornos" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Polizas",
|
||||||
|
children: [
|
||||||
|
{ label: "Buscar Póliza", onclick: () => openTab("Polizas") },
|
||||||
|
{ label: "Nueva producción", onclick: () => openTab("Polizas") },
|
||||||
|
{ label: "Anulaciones", onclick: () => openTab("Polizas") },
|
||||||
|
{ label: "Renovación Cartera", onclick: () => openTab("Polizas") }
|
||||||
|
]
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Comercial",
|
||||||
|
children: [
|
||||||
|
{ label: "Oportunidades" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Siniestros",
|
||||||
|
children: [
|
||||||
|
{ label: "Nuevo Siniestro" },
|
||||||
|
{ label: "Buscar Siniestro" },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Soporte",
|
||||||
|
children: [
|
||||||
|
{ label: "Tickets" },
|
||||||
|
{ label: "Reportes" },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// Referencia al contenedor de pestañas para manejar el foco
|
||||||
|
let tabsContainerRef = null;
|
||||||
|
let drawerToggleRef = null;
|
||||||
|
|
||||||
|
// Abre o crea una pestaña, cierra el drawer
|
||||||
|
const openTab = (label) => {
|
||||||
|
const currentTabs = tabs();
|
||||||
|
|
||||||
|
if (currentTabs.length >= 15) return;
|
||||||
|
|
||||||
|
const newTab = {
|
||||||
|
label,
|
||||||
|
content: () => `¡Bienvenido al escritorio!`,
|
||||||
|
closable: true
|
||||||
|
};
|
||||||
|
tabs([...currentTabs, newTab]);
|
||||||
|
activeTab(tabs().length - 1);
|
||||||
|
|
||||||
|
closeDrawer();
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeDrawer = () => {
|
||||||
|
openDrawer(false);
|
||||||
|
if (drawerToggleRef) drawerToggleRef.checked = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Manejo del login
|
||||||
|
const handleLogin = () => {
|
||||||
|
logged(true);
|
||||||
|
showLoginModal(false);
|
||||||
|
loginForm.username("");
|
||||||
|
loginForm.password("");
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleLogout = () => {
|
||||||
|
logged(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return [
|
||||||
|
Drawer({}, [
|
||||||
|
// Control oculto del drawer
|
||||||
|
DrawerToggle({
|
||||||
|
id: "app-drawer",
|
||||||
|
ref: (el) => drawerToggleRef = el,
|
||||||
|
checked: openDrawer,
|
||||||
|
onchange: (e) => openDrawer(e.target.checked)
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Contenido principal
|
||||||
|
DrawerContent({}, [
|
||||||
|
Navbar({ class: "bg-base-100 shadow-lg align-center" }, [
|
||||||
|
// Botón hamburguesa
|
||||||
|
div({ class: "flex-none" }, [
|
||||||
|
label({ for: "app-drawer", class: "btn btn-ghost btn-square" }, [
|
||||||
|
Icon({}, "icon-[lucide--menu]")
|
||||||
|
])
|
||||||
|
]),
|
||||||
|
|
||||||
|
// Buscador
|
||||||
|
div({ class: "flex-1 max-w-md mx-4" }, [
|
||||||
|
Input({
|
||||||
|
type: "search",
|
||||||
|
placeholder: "Buscar...",
|
||||||
|
value: searchQuery,
|
||||||
|
left: span({ class: "icon-[lucide--search]" }),
|
||||||
|
oninput: (e) => console.log(e.target.value)
|
||||||
|
})
|
||||||
|
]),
|
||||||
|
|
||||||
|
// Espaciador central
|
||||||
|
div({ class: "flex-1" }, []),
|
||||||
|
|
||||||
|
// Swap para tema claro/oscuro
|
||||||
|
Swap({ class: "text-xl" }, [
|
||||||
|
SwapToggle({ value: isDark, class: "swap-rotate" }),
|
||||||
|
SwapOn({}, span({ class: "icon-[lucide--moon]" })),
|
||||||
|
SwapOff({}, span({ class: "icon-[lucide--sun]" })),
|
||||||
|
]),
|
||||||
|
|
||||||
|
// Avatar con dropdown o botón de login
|
||||||
|
when(logged,
|
||||||
|
() => Dropdown({ class: "flex-none ml-2 dropdown-bottom dropdown-end" }, [
|
||||||
|
DropdownButton({ class: "btn-circle btn btn-ghost", tabindex: "0", role: "button" }, [
|
||||||
|
div({ class: "w-10 rounded-full flex items-center justify-center" }, [
|
||||||
|
Icon({}, "icon-[lucide--user] text-xl")
|
||||||
|
])
|
||||||
|
]),
|
||||||
|
DropdownContent(
|
||||||
|
{ class: "menu bg-base-100 rounded-box w-52 p-2 shadow" },
|
||||||
|
[
|
||||||
|
Menu({
|
||||||
|
class: "bg-base-100 max-w-xs w-full",
|
||||||
|
items: [
|
||||||
|
{ label: "Mis mensajes", onclick: () => hide() },
|
||||||
|
{ label: "Delete", onclick: () => hide() },
|
||||||
|
{ label: "Cerrar Sesión", onclick: handleLogout },
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
() => Button({
|
||||||
|
class: "flex-none ml-2 btn btn-ghost btn-circle relative",
|
||||||
|
onclick: () => showLoginModal(true)
|
||||||
|
}, [
|
||||||
|
Icon({}, "icon-[lucide--user] text-xl"),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
]),
|
||||||
|
// Área principal con las pestañas
|
||||||
|
div({
|
||||||
|
class: "p-4",
|
||||||
|
ref: (el) => tabsContainerRef = el
|
||||||
|
}, [
|
||||||
|
Tabs({
|
||||||
|
class: 'tabs-box',
|
||||||
|
items: tabs,
|
||||||
|
activeIndex: activeTab
|
||||||
|
})
|
||||||
|
])
|
||||||
|
]),
|
||||||
|
|
||||||
|
// Lateral del drawer
|
||||||
|
DrawerSide({ class: "z-50" }, [
|
||||||
|
DrawerOverlay({ for: "app-drawer" }),
|
||||||
|
div({
|
||||||
|
class: "menu bg-base-200 text-base-content min-h-full w-80 p-4"
|
||||||
|
}, [
|
||||||
|
h2({ class: "text-lg font-bold mb-4" }, ["Menú"]),
|
||||||
|
Menu({ items: menuItems, class: "bg-base-200 max-w-xs w-full" })
|
||||||
|
])
|
||||||
|
])
|
||||||
|
]),
|
||||||
|
|
||||||
|
// Modal de login
|
||||||
|
Modal({
|
||||||
|
open: showLoginModal,
|
||||||
|
actions: [
|
||||||
|
Button({
|
||||||
|
class: "btn btn-ghost",
|
||||||
|
onclick: () => showLoginModal(false)
|
||||||
|
}, "Cancelar"),
|
||||||
|
Button({
|
||||||
|
class: "btn btn-primary",
|
||||||
|
onclick: handleLogin
|
||||||
|
}, "Entrar")
|
||||||
|
]
|
||||||
|
}, [
|
||||||
|
Fieldset({ label: "Iniciar sesión", class: "bg-base-200 border-base-300 rounded-box border gap-3 p-4", }, [
|
||||||
|
Input({
|
||||||
|
class: "w-full",
|
||||||
|
type: "text",
|
||||||
|
label: "Usuario",
|
||||||
|
float: true,
|
||||||
|
placeholder: "Nombre de usuario",
|
||||||
|
value: loginForm.username
|
||||||
|
})
|
||||||
|
,
|
||||||
|
|
||||||
|
Input({
|
||||||
|
class: "w-full",
|
||||||
|
type: "password",
|
||||||
|
label: "Contraseña",
|
||||||
|
float: true,
|
||||||
|
placeholder: "Contraseña",
|
||||||
|
value: loginForm.password
|
||||||
|
})
|
||||||
|
])
|
||||||
|
|
||||||
|
])
|
||||||
|
];
|
||||||
|
};
|
||||||
15
client/app.css
Normal file
15
client/app.css
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
@import "tailwindcss";
|
||||||
|
@plugin "@iconify/tailwind4";
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Plus Jakarta Sans";
|
||||||
|
src: url("/jakarta.woff2") format("woff2");
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
font-size: 14px;
|
||||||
|
/* font-family: "Plus Jakarta Sans", ui-sans-serif, system-ui, sans-serif; */
|
||||||
|
}
|
||||||
4
client/main.js
Normal file
4
client/main.js
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import { mount } from './sigpro.js';
|
||||||
|
import './app.css';
|
||||||
|
import { App } from './App.js';
|
||||||
|
mount(App, '#app');
|
||||||
@@ -3,20 +3,21 @@
|
|||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"del": "bun pm cache rm && rm -f bun.lockb $$ rm -f bun.lock && rm node_modules/.vite/deps -r",
|
||||||
"kill": "pkill -9 bun && pkill -9 node || true",
|
"kill": "pkill -9 bun && pkill -9 node || true",
|
||||||
"del": "rm node_modules/.vite/deps -r",
|
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tailwindcss/vite": "^4.2.1",
|
"@tailwindcss/vite": "^4.2.4",
|
||||||
"sigpro": "^1.2.24",
|
"sigpro": "git+http://gitea:3000/natxocc/sigpro",
|
||||||
"sigpro-ui": "^1.2.1"
|
"sigpro-ui": "git+http://gitea:3000/natxocc/sigpro-ui"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@iconify/json": "^2.2.443",
|
"@iconify/json": "^2.2.469",
|
||||||
"@iconify/tailwind4": "^1.2.1",
|
"@iconify/tailwind4": "^1.2.3",
|
||||||
"vite": "^8.0.0"
|
"tailwindcss": "^4.2.4",
|
||||||
|
"vite": "^8.0.10"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,247 +0,0 @@
|
|||||||
// App.js
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Vistas de la aplicación (pueden ir en archivos separados luego)
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { Navbar, Swap, Menu, Checkbox, Input, Button, Autocomplete, Datepicker, Colorpicker, Fileinput, Toast } from "sigpro-ui";
|
|
||||||
|
|
||||||
const toggle = $(false);
|
|
||||||
// const consoleToggle = $(()=>console.log(toggle()))
|
|
||||||
const Home = () => {
|
|
||||||
const valor = $("jjj");
|
|
||||||
const miCheck = $(false); // Creamos la señal
|
|
||||||
return Div({ class: "gap-3 flex flex-col" }, [
|
|
||||||
H1("Dashboard Principal"),
|
|
||||||
Button({ tooltip: "tooltip", badge: "22" }, "Hola"),
|
|
||||||
Input({
|
|
||||||
label: "Correo Electrónico",
|
|
||||||
type: "email",
|
|
||||||
placeholder: "ejemplo@correo.com",
|
|
||||||
value: valor, // Binding automático
|
|
||||||
}),
|
|
||||||
Span({ class: "gap-4 text-4xl" }, () => valor()),
|
|
||||||
P("Bienvenido a la interfaz reactiva de SigPro. Aquí puedes ver el estado global."),
|
|
||||||
Checkbox({ tooltip: "Tooltip", toggle: toggle, value: miCheck, label: "Checkbox" }),
|
|
||||||
miCheck,
|
|
||||||
toggle,
|
|
||||||
Button(
|
|
||||||
{
|
|
||||||
class: "btn-primary",
|
|
||||||
onclick: () => {
|
|
||||||
Toast("Cambio de toggle");
|
|
||||||
toggle(!toggle());
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"Lanzar Toast",
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
};
|
|
||||||
|
|
||||||
const Profile = (params) => {
|
|
||||||
const miFecha = $();
|
|
||||||
const miRango = $();
|
|
||||||
const selectedFruit = $("Apple");
|
|
||||||
const fruits = ["Apple", "Banana", "Cherry", "Dragonfruit", "Elderberry"];
|
|
||||||
const colorFondo = $("#ef4444");
|
|
||||||
const misArchivos = $([]);
|
|
||||||
|
|
||||||
const textoInput = $(() => {
|
|
||||||
const f = miFecha;
|
|
||||||
if (!f.start) return "";
|
|
||||||
return f.end ? `${f.start} - ${f.end}` : `${f.start}...`;
|
|
||||||
});
|
|
||||||
|
|
||||||
return Div({ class: "p-4 space-y-4" }, [
|
|
||||||
H2({ class: "text-xl font-bold" }, `Perfil: ${params.id}`),
|
|
||||||
Autocomplete({
|
|
||||||
label: "Selecciona una fruta",
|
|
||||||
value: selectedFruit,
|
|
||||||
options: fruits,
|
|
||||||
onSelect: (val) => console.log("Seleccionado:", val),
|
|
||||||
}),
|
|
||||||
Datepicker({ value: miFecha, label: "Fecha", placeholder: textoInput, hour: true }),
|
|
||||||
Datepicker({ value: miRango, label: "Fecha", placeholder: textoInput, range: true, hour: true }),
|
|
||||||
Colorpicker({ show: true, label: "Color del tema", value: colorFondo }),
|
|
||||||
Input({ type: "number", label: "Number" }),
|
|
||||||
Input({ type: "email", label: "Email" }),
|
|
||||||
Input({ label: "Text" }),
|
|
||||||
Input({ type: "date", label: "Date" }),
|
|
||||||
Input({ type: "password", label: "Password" }),
|
|
||||||
$html("p", {}, () => `Has elegido: ${selectedFruit()}`),
|
|
||||||
Fileinput({
|
|
||||||
tooltip: "Formatos: PDF, JPG",
|
|
||||||
max: 5,
|
|
||||||
// Cada vez que la lista cambia, se dispara esto
|
|
||||||
onSelect: async (files) => {
|
|
||||||
if (files.length === 0) return;
|
|
||||||
|
|
||||||
console.log("Subiendo archivos automáticamente...", files);
|
|
||||||
|
|
||||||
const formData = new FormData();
|
|
||||||
files.forEach((file) => formData.append("files[]", file));
|
|
||||||
|
|
||||||
// await fetch('/api/upload', { method: 'POST', body: formData });
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
Div({ class: "pt-4" }, [
|
|
||||||
Button(
|
|
||||||
{
|
|
||||||
class: "btn-sm btn-outline",
|
|
||||||
onclick: () => $router.to("/"),
|
|
||||||
},
|
|
||||||
"Volver",
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
]);
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* Componente Principal
|
|
||||||
*/
|
|
||||||
export const App = () => {
|
|
||||||
// Estado local de la App (ejemplo: tema o usuario)
|
|
||||||
const isDark = $(false, "sigpro-theme");
|
|
||||||
|
|
||||||
// Efecto para cambiar el tema en el HTML
|
|
||||||
$watch(() => {
|
|
||||||
document.documentElement.setAttribute("data-theme", isDark() ? "dark" : "light");
|
|
||||||
});
|
|
||||||
|
|
||||||
const menuItems = [
|
|
||||||
{ label: "Inicio", onclick: () => $router.to("/") },
|
|
||||||
{ label: "Mi Perfil", onclick: () => $router.to("/profile/42") },
|
|
||||||
{ label: "Tareas TODO", onclick: () => $router.to("/todo") }, // <-- Nueva opción
|
|
||||||
{ label: "Ajustes", onclick: () => Toast("Ajustes no disponibles", "alert-error") },
|
|
||||||
];
|
|
||||||
|
|
||||||
return Div({ class: "min-h-screen flex flex-col" }, [
|
|
||||||
Navbar({ class: "sticky top-0 z-50 bg-base-100/80 backdrop-blur border-b border-base-300" }, [
|
|
||||||
Div({ class: "flex-1" }, [
|
|
||||||
A(
|
|
||||||
{
|
|
||||||
class: "btn btn-ghost text-xl font-black tracking-tighter",
|
|
||||||
onclick: () => $router.to("/"),
|
|
||||||
},
|
|
||||||
"SIGPRO",
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
Button({ disabled: true }, "Disabled"),
|
|
||||||
|
|
||||||
Div({ class: "flex items-center gap-2" }, [
|
|
||||||
Swap({
|
|
||||||
class: "swap-rotate",
|
|
||||||
value: isDark,
|
|
||||||
on: "🌙",
|
|
||||||
off: "☀️",
|
|
||||||
}),
|
|
||||||
Button({ class: "btn-circle btn-ghost", icon: "👤" }),
|
|
||||||
]),
|
|
||||||
]),
|
|
||||||
|
|
||||||
// --- LAYOUT PRINCIPAL ---
|
|
||||||
Div({ class: "flex flex-1" }, [
|
|
||||||
// Sidebar Lateral
|
|
||||||
Aside({ class: "w-64 bg-base-200 p-4 hidden md:block" }, [Menu({ items: menuItems, class: "bg-transparent" })]),
|
|
||||||
|
|
||||||
// Contenido Dinámico (Router)
|
|
||||||
Main({ class: "flex-1 p-6 bg-base-100" }, [
|
|
||||||
$router([
|
|
||||||
{ path: "/", component: Home },
|
|
||||||
{ path: "/profile/:id", component: Profile },
|
|
||||||
{ path: "/todo", component: TodoPage },
|
|
||||||
{
|
|
||||||
path: "*",
|
|
||||||
component: () =>
|
|
||||||
Div({ class: "text-center py-20" }, [H1({ class: "text-9xl font-bold opacity-20" }, "404"), P("La página que buscas no existe.")]),
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
]),
|
|
||||||
]),
|
|
||||||
|
|
||||||
// --- FOOTER ---
|
|
||||||
Footer({ class: "footer footer-center p-4 bg-base-300 text-base-content text-xs" }, [P("© 2026 - Built with SigPro Engine")]),
|
|
||||||
]);
|
|
||||||
};
|
|
||||||
|
|
||||||
const TodoPage = () => {
|
|
||||||
const newTask = $("");
|
|
||||||
// Persistencia automática en localStorage gracias a tu Core
|
|
||||||
const tasks = $([], "sigpro-todo-list");
|
|
||||||
|
|
||||||
const addTask = () => {
|
|
||||||
const val = newTask().trim();
|
|
||||||
if (!val) return Toast("Escribe algo...", "alert-warning");
|
|
||||||
|
|
||||||
tasks([...tasks(), { id: crypto.randomUUID(), text: val, done: false }]);
|
|
||||||
newTask(""); // Limpia el input
|
|
||||||
};
|
|
||||||
|
|
||||||
const removeTask = (id) => {
|
|
||||||
tasks(tasks().filter((t) => t.id !== id));
|
|
||||||
};
|
|
||||||
|
|
||||||
const toggleTask = (id) => {
|
|
||||||
tasks(tasks().map((t) => (t.id === id ? { ...t, done: !t.done } : t)));
|
|
||||||
};
|
|
||||||
|
|
||||||
// Señal computada para el contador
|
|
||||||
const pendingCount = $(() => tasks().filter((t) => !t.done).length);
|
|
||||||
const misDatos = $([{ id: 1 }]);
|
|
||||||
return Div({ class: "max-w-md mx-auto space-y-6" }, [
|
|
||||||
H1({ class: "text-3xl font-black italic" }, "TODO LIST"),
|
|
||||||
|
|
||||||
// Input Group
|
|
||||||
Div({ class: "join w-full" }, [
|
|
||||||
Input({
|
|
||||||
class: "join-item w-full",
|
|
||||||
placeholder: "Nueva tarea...",
|
|
||||||
value: newTask,
|
|
||||||
onkeydown: (e) => e.key === "Enter" && addTask(),
|
|
||||||
}),
|
|
||||||
Button({ class: "btn-primary join-item", onclick: addTask }, "Añadir"),
|
|
||||||
]),
|
|
||||||
|
|
||||||
// Stats
|
|
||||||
Div({ class: "flex justify-between items-center opacity-70 text-sm" }, [
|
|
||||||
Span(() => `Total: ${tasks().length}`),
|
|
||||||
Span({ class: "badge badge-secondary" }, () => `${pendingCount()} pendientes`),
|
|
||||||
]),
|
|
||||||
|
|
||||||
// Lista Reactiva (Aquí evaluamos tu append con sweep)
|
|
||||||
Ul({ class: "menu bg-base-200 rounded-box w-full p-2" }, () =>
|
|
||||||
tasks().length === 0
|
|
||||||
? Li({ class: "p-4 text-center opacity-50" }, "No hay tareas pendientes")
|
|
||||||
: tasks().map((task) =>
|
|
||||||
Li({ class: "flex flex-row items-center gap-2 p-2 border-b border-base-300 last:border-0" }, [
|
|
||||||
Checkbox({
|
|
||||||
class: "checkbox-sm",
|
|
||||||
value: () => task.done,
|
|
||||||
onclick: () => toggleTask(task.id),
|
|
||||||
}),
|
|
||||||
Span(
|
|
||||||
{
|
|
||||||
class: `flex-1 ${task.done ? "line-through opacity-40" : ""}`,
|
|
||||||
onclick: () => toggleTask(task.id),
|
|
||||||
},
|
|
||||||
task.text,
|
|
||||||
),
|
|
||||||
Button(
|
|
||||||
{
|
|
||||||
class: "btn-ghost btn-xs text-error",
|
|
||||||
onclick: () => removeTask(task.id),
|
|
||||||
},
|
|
||||||
"✕",
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
Button(
|
|
||||||
{
|
|
||||||
class: "btn-link btn-xs text-error p-0",
|
|
||||||
onclick: () => tasks([]),
|
|
||||||
},
|
|
||||||
"Limpiar todo",
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
};
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
@import "tailwindcss";
|
|
||||||
@plugin "@iconify/tailwind4";
|
|
||||||
@plugin "daisyui" {
|
|
||||||
themes:
|
|
||||||
light --default,
|
|
||||||
dark --prefersdark;
|
|
||||||
include:
|
|
||||||
alert, avatar, badge, button, card, checkbox, collapse, drawer, dropdown, fab, fieldset, loading, indicator, input, kbd, label, list, menu, modal,
|
|
||||||
navbar, radio, range, select, skeleton, tab, textarea, toast, toggle, tooltip, validator, rating, mask, swap;
|
|
||||||
}
|
|
||||||
|
|
||||||
@font-face {
|
|
||||||
font-family: "Plus Jakarta Sans";
|
|
||||||
src: url("/jakarta.woff2") format("woff2");
|
|
||||||
font-weight: normal;
|
|
||||||
font-style: normal;
|
|
||||||
font-display: swap;
|
|
||||||
}
|
|
||||||
|
|
||||||
:root {
|
|
||||||
font-size: 14px;
|
|
||||||
/* font-family: "Plus Jakarta Sans", ui-sans-serif, system-ui, sans-serif; */
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-ghost {
|
|
||||||
border-color: transparent !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.floating-label > span {
|
|
||||||
font-size: 1.2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
@utility input {
|
|
||||||
@apply transition-all duration-300 ease-in-out outline-none shrink appearance-none items-center;
|
|
||||||
&:hover {
|
|
||||||
background-color: var(--color-base-300);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
import {$mount} from 'sigpro';
|
|
||||||
import { App } from './App.js';
|
|
||||||
import './app.css';
|
|
||||||
$mount(App, '#app');
|
|
||||||
6103
client/sigpro-ui.css
Normal file
6103
client/sigpro-ui.css
Normal file
File diff suppressed because it is too large
Load Diff
534
client/sigpro-ui.js
Normal file
534
client/sigpro-ui.js
Normal file
@@ -0,0 +1,534 @@
|
|||||||
|
import { $, watch, h, mount, when, each, isFunc } from "./sigpro.js"
|
||||||
|
export const val = val => typeof val === "function" ? val() : val;
|
||||||
|
export const getBy = (item, field = 'label') => (item && typeof item === 'object') ? item[field] : item;
|
||||||
|
export const cls = (...classes) => classes.filter(Boolean).join(' ').trim();
|
||||||
|
export const filterBy = (items, query, field = 'label') => {
|
||||||
|
const q = String(val(query) || '').toLowerCase();
|
||||||
|
const list = (val(items) || []).map(i => typeof i === 'object' ? i : { label: i, value: i });
|
||||||
|
return !q ? list : list.filter(item => String(item[field] || '').toLowerCase().includes(q));
|
||||||
|
};
|
||||||
|
export const rand = (r) => `${r}-${Math.random().toString(36).slice(2, 9)}`
|
||||||
|
export const hide = () => document.activeElement?.blur()
|
||||||
|
const currentLocale = $("en");
|
||||||
|
export const lang = {
|
||||||
|
es: { uploadFiles: "Arrastrar y soltar o click para seleccionar..." },
|
||||||
|
en: { uploadFiles: "Drag and drop or click to select" }
|
||||||
|
};
|
||||||
|
export const setLocale = (locale) => { if (lang[locale]) currentLocale(locale) }
|
||||||
|
export const t = t => () => lang[currentLocale()][t] || t;
|
||||||
|
const c1 = (tag, cls) => (p) => h(tag, { ...p, class: `${cls} ${p?.class || ''}`.trim() })
|
||||||
|
const c2 = (tag, cls) => (p, c) => h(tag, { ...p, class: `${cls} ${p?.class || ''}`.trim() }, c)
|
||||||
|
const ct = (tag, cls, type) => (p) => h(tag, { type, ...p, class: `${cls} ${p?.class || ''}`.trim() })
|
||||||
|
export const Alert = c2("div", "alert")
|
||||||
|
export const Avatar = (p, c) => h("div", { class: "avatar" }, h('div', { class: p.class }, c))
|
||||||
|
export const AvatarGroup = c2("div", "avatar-group -space-x-6")
|
||||||
|
export const Badge = c2("span", "badge")
|
||||||
|
export const Breadcrumbs = c2("div", "breadcrumbs")
|
||||||
|
export const Button = c2("button", "btn")
|
||||||
|
export const Card = c2("div", "card")
|
||||||
|
export const CardTitle = c2("div", "card-title")
|
||||||
|
export const CardBody = c2("div", "card-body")
|
||||||
|
export const CardActions = c2("div", "card-actions")
|
||||||
|
export const Carousel = c2("div", "carousel")
|
||||||
|
export const CarouselItem = c2("div", "carousel-item")
|
||||||
|
export const Chat = c2("div", "chat")
|
||||||
|
export const ChatBubble = c2("div", "chat-bubble")
|
||||||
|
export const ChatFooter = c2("div", "chat-footer")
|
||||||
|
export const ChatHeader = c2("div", "chat-header")
|
||||||
|
export const ChatImage = (p, c) => h("div", { ...p, class: cls("chat-image avatar", p.class) }, h("div", { class: "w-10 rounded-full" }, typeof c === "string" ? h("img", { src: c, alt: "avatar" }) : c))
|
||||||
|
export const Checkbox = ct("input", "checkbox", "checkbox")
|
||||||
|
export const Drawer = c2("div", "drawer")
|
||||||
|
export const DrawerToggle = (p) => input({ ...p, type: 'checkbox', class: 'drawer-toggle', checked: () => val(p.checked), onchange: (e) => isFunc(p.checked) && p.checked(e.target.checked) })
|
||||||
|
export const DrawerContent = c2("div", "drawer-content")
|
||||||
|
export const DrawerSide = c2("div", "drawer-side")
|
||||||
|
export const DrawerOverlay = (p) => label({ ...p, for: p.for, class: cls('drawer-overlay', p.class) })
|
||||||
|
export const Divider = c1("div", "divider")
|
||||||
|
export const Dropdown = c2("div", "dropdown")
|
||||||
|
export const DropdownButton = (p, c) => (h('div', { ...p, tabindex: '0', role: 'button', class: cls('btn', p.class) }, c))
|
||||||
|
export const DropdownContent = (p, c) => (h('div', { ...p, tabindex: '0', class: cls('dropdown-content', p.class) }, c))
|
||||||
|
export const Fab = (p, c) => h("div", { class: "fab" }, [h('div', { tabindex: "0", role: "button", class: cls('btn', p.class) }, Icon({},p.icon)), c])
|
||||||
|
export const Fieldset = (p, c) => h("fieldset", { class: cls("fieldset", p.class) }, [h("legend", { class: "fieldset-legend" }, p.label), c])
|
||||||
|
export const Icon = (p, c) => h("span", { ...p, class: cls(c, p.class) })
|
||||||
|
export const Indicator = (p, c) => h("div", { ...p, class: cls("indicator", p.class) }, [p.value && h("span", { class: cls("indicator-item badge", p.class) }, p.value), c])
|
||||||
|
export const Kbd = c2("kbd", "kbd")
|
||||||
|
export const List = c2("ul", "list")
|
||||||
|
export const ListRows = (p) => () => (val(p.items) || []).map((item, idx) => h('li', { class: cls('list-row', p.class, item?.class) }, typeof p.render === 'function' ? p.render(item, idx) : item))
|
||||||
|
export const Loading = c2("span", "loading loading-spinner")
|
||||||
|
export const Navbar = c2("div", "navbar")
|
||||||
|
export const Progress = c1("progress", "progress")
|
||||||
|
export const Radial = (p, c) => h("div", { class: cls("radial-progress", p.class), style: `--value:${val(p.value) ?? 0};`, role: "progressbar", "aria-valuenow": p.value }, c)
|
||||||
|
export const Radio = ct("input", "radio", "radio")
|
||||||
|
export const Range = ct("input", "range", "range")
|
||||||
|
export const Rating = c2("div", "rating")
|
||||||
|
export const RatingItems = (p) => [...Array(p.count)].map((_, i) => h('input', { class: cls('mask', p.class), name: p.name, type: 'radio', checked: () => val(p.value) === i, onchange: () => isFunc(p.value) ? p.value(i) : p.onchange?.(i) }))
|
||||||
|
export const Skeleton = c1("div", "skeleton")
|
||||||
|
export const SkeletonText = c1("span", "skeleton skeleton-text")
|
||||||
|
export const Stack = c2("div", "stack")
|
||||||
|
export const Stats = c2("div", "stats shadow")
|
||||||
|
export const Steps = c2("ul", "steps")
|
||||||
|
export const Step = (p, c) => h("li", { ...p, class: cls("step", p.class), "data-content": p.dataContent }, c)
|
||||||
|
export const Swap = c2("label", "swap")
|
||||||
|
export const SwapToggle = (p) => h('input', { type: 'checkbox', checked: () => val(p.value), onchange: (e) => isFunc(p.value) && p.value(e.target.checked), class: p.class })
|
||||||
|
export const SwapOn = c2("div", "swap-on")
|
||||||
|
export const SwapOff = c2("div", "swap-off")
|
||||||
|
export const Table = c2("table", "table")
|
||||||
|
export const Textarea = c1("textarea", "textarea")
|
||||||
|
export const Textrotate = (p, c) => h('span', { ...p, class: cls('text-rotate', p.class) }, h('span', {}, c))
|
||||||
|
export const Timeline = c2("ul", "timeline")
|
||||||
|
export const Toggle = ct("input", "toggle", "checkbox")
|
||||||
|
export const Tooltip = (p, c) => h("div", { ...p, class: cls("tooltip", p.class), "data-tip": p.tip }, c)
|
||||||
|
export const Accordion = (p) => {
|
||||||
|
const name = p.name || rand('acc')
|
||||||
|
return each(p.items, (it) => {
|
||||||
|
return h('div', { class: cls('collapse', p.class) }, [
|
||||||
|
h('input', { type: 'radio', name, checked: it.open || undefined }),
|
||||||
|
it.title ? h('div', { class: cls("collapse-title", `${it.classTitle ?? ' font-semibold'}`) }, it.title) : null,
|
||||||
|
it.content ? h('div', { class: cls("collapse-content text-sm", `${it.classContent ?? ' font-semibold'}`) }, it.content) : null,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
export const Autocomplete = ({ items, value, onselect, placeholder = '...', ...props }) => {
|
||||||
|
const query = $(val(value) || '')
|
||||||
|
const filtered = $(() => filterBy(items, query()))
|
||||||
|
const pick = (item) => {
|
||||||
|
const display = getBy(item)
|
||||||
|
const actual = typeof item === 'string' ? item : item.value
|
||||||
|
query(display)
|
||||||
|
if (isFunc(value)) value(actual)
|
||||||
|
onselect?.(item)
|
||||||
|
hide()
|
||||||
|
}
|
||||||
|
return Dropdown({ class: 'w-80' }, [
|
||||||
|
h('div', { tabindex: '0', role: 'button', class: 'w-full' }, Input({ ...props, placeholder, value: query, left: Icon({},'icon-[lucide--search]') })),
|
||||||
|
DropdownContent({ class: 'p-2 bg-base-100 rounded-box shadow-xl w-full max-h-60 overflow-y-auto border border-base-300 z-50' },
|
||||||
|
h('ul', { class: 'menu flex-col flex-nowrap w-full p-0' }, [
|
||||||
|
each(filtered, (item) => h('li', {}, [h('a', { onmousedown: (e) => e.preventDefault(), onclick: () => pick(item) }, getBy(item))]), 'value'),
|
||||||
|
() => filtered().length === 0 ? h('li', { class: 'p-4 opacity-50 text-center' }, 'Sin resultados') : null
|
||||||
|
])
|
||||||
|
)
|
||||||
|
])
|
||||||
|
};
|
||||||
|
export const Calendar = (p) => {
|
||||||
|
const internalDate = $(new Date())
|
||||||
|
const hoverDate = $(null)
|
||||||
|
const startHour = $(0)
|
||||||
|
const endHour = $(0)
|
||||||
|
const now = new Date()
|
||||||
|
const todayStr = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`
|
||||||
|
const fmt = d => `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
|
||||||
|
const rangeMode = () => val(p.range) === true
|
||||||
|
const current = () => val(p.value)
|
||||||
|
const selectDate = (date) => {
|
||||||
|
const s = fmt(date)
|
||||||
|
const v = current()
|
||||||
|
if (rangeMode()) {
|
||||||
|
if (!v?.start || (v.start && v.end)) {
|
||||||
|
p.onChange?.({ start: s, end: null, ...(p.hour && { startHour: startHour() }) })
|
||||||
|
} else {
|
||||||
|
const start = v.start
|
||||||
|
const nv = s < start ? { start: s, end: start } : { start, end: s }
|
||||||
|
if (p.hour) { nv.startHour = v.startHour ?? startHour(); nv.endHour = endHour() }
|
||||||
|
p.onChange?.(nv)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p.onChange?.(p.hour ? `${s}T${String(startHour()).padStart(2, '0')}:00:00` : s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const move = (m) => { const d = internalDate(); internalDate(new Date(d.getFullYear(), d.getMonth() + m, 1)) }
|
||||||
|
const moveYear = (y) => { const d = internalDate(); internalDate(new Date(d.getFullYear() + y, d.getMonth(), 1)) }
|
||||||
|
const HourSlider = ({ value: hVal, onChange: onH }) => h('div', { class: 'flex-1' }, [
|
||||||
|
h('div', { class: 'flex gap-2 items-center' }, [
|
||||||
|
h('input', { type: 'range', min: 0, max: 23, value: hVal, class: 'range range-xs flex-1', oninput: e => onH(+e.target.value) }),
|
||||||
|
h('span', { class: 'text-sm font-mono min-w-[48px] text-center' }, () => String(val(hVal)).padStart(2, '0') + ':00')
|
||||||
|
])
|
||||||
|
])
|
||||||
|
return h('div', {
|
||||||
|
class: cls('p-4 bg-base-100 border border-base-300 shadow-2xl rounded-box w-80 select-none', p.class)
|
||||||
|
}, [
|
||||||
|
h('div', { class: 'flex justify-between items-center mb-4 gap-1' }, [
|
||||||
|
h('div', { class: 'flex gap-0.5' }, [
|
||||||
|
h('button', { type: 'button', class: 'btn btn-ghost btn-xs px-1', onclick: () => moveYear(-1) }, h('span', { class: 'icon-[lucide--chevrons-left]' })),
|
||||||
|
h('button', { type: 'button', class: 'btn btn-ghost btn-xs px-1', onclick: () => move(-1) }, h('span', { class: 'icon-[lucide--chevron-left]' }))
|
||||||
|
]),
|
||||||
|
h('span', { class: 'font-bold uppercase flex-1 text-center' }, () => internalDate().toLocaleString('es-ES', { month: 'short', year: 'numeric' })),
|
||||||
|
h('div', { class: 'flex gap-0.5' }, [
|
||||||
|
h('button', { type: 'button', class: 'btn btn-ghost btn-xs px-1', onclick: () => move(1) }, h('span', { class: 'icon-[lucide--chevron-right]' })),
|
||||||
|
h('button', { type: 'button', class: 'btn btn-ghost btn-xs px-1', onclick: () => moveYear(1) }, h('span', { class: 'icon-[lucide--chevrons-right]' }))
|
||||||
|
])
|
||||||
|
]),
|
||||||
|
h('div', { class: 'grid grid-cols-7 gap-1', onmouseleave: () => hoverDate(null) }, [
|
||||||
|
...['L', 'M', 'X', 'J', 'V', 'S', 'D'].map(d => h('div', { class: 'text-[10px] opacity-40 font-bold text-center' }, d)),
|
||||||
|
() => {
|
||||||
|
const d = internalDate(), y = d.getFullYear(), m = d.getMonth()
|
||||||
|
const firstDay = new Date(y, m, 1).getDay()
|
||||||
|
const offset = firstDay === 0 ? 6 : firstDay - 1
|
||||||
|
const dim = new Date(y, m + 1, 0).getDate()
|
||||||
|
const cells = []
|
||||||
|
for (let i = 0; i < offset; i++) cells.push(h('div'))
|
||||||
|
for (let i = 1; i <= dim; i++) {
|
||||||
|
const date = new Date(y, m, i), ds = fmt(date)
|
||||||
|
cells.push(h('button', {
|
||||||
|
type: 'button',
|
||||||
|
class: () => {
|
||||||
|
const v = current(), h = hoverDate()
|
||||||
|
const isStart = typeof v === 'string' ? v.split('T')[0] === ds : v?.start === ds
|
||||||
|
const isEnd = v?.end === ds
|
||||||
|
let inRange = false
|
||||||
|
if (rangeMode() && v?.start) {
|
||||||
|
const start = v.start
|
||||||
|
if (!v.end && h) inRange = (ds > start && ds <= h) || (ds < start && ds >= h)
|
||||||
|
else if (v.end) inRange = ds > start && ds < v.end
|
||||||
|
}
|
||||||
|
const base = 'btn btn-xs p-0 aspect-square min-h-0 h-auto font-normal relative'
|
||||||
|
const st = isStart || isEnd ? 'btn-primary z-10' : inRange ? 'bg-primary/20 border-none rounded-none' : 'btn-ghost'
|
||||||
|
const today = ds === todayStr ? 'ring-1 ring-primary ring-inset font-black text-primary' : ''
|
||||||
|
return cls(base, st, today)
|
||||||
|
},
|
||||||
|
onmouseenter: () => rangeMode() && hoverDate(ds),
|
||||||
|
onclick: () => selectDate(date)
|
||||||
|
}, i.toString()))
|
||||||
|
}
|
||||||
|
return cells
|
||||||
|
}
|
||||||
|
]),
|
||||||
|
p.hour ? h('div', { class: 'mt-3 pt-2 border-t border-base-300' },
|
||||||
|
rangeMode()
|
||||||
|
? h('div', { class: 'flex gap-4' }, [HourSlider({ value: startHour, onChange: h => startHour(h) }), HourSlider({ value: endHour, onChange: h => endHour(h) })])
|
||||||
|
: HourSlider({ value: startHour, onChange: h => startHour(h) })
|
||||||
|
) : null
|
||||||
|
])
|
||||||
|
};
|
||||||
|
export const Colorpicker = (p) => {
|
||||||
|
const current = () => val(p.value) || '#000000'
|
||||||
|
return Dropdown({}, [
|
||||||
|
DropdownButton({ class: 'btn' }, [
|
||||||
|
h('div', { class: 'size-5 rounded-sm', style: () => `background-color: ${current()}` }),
|
||||||
|
p.label && h('span', {}, p.label)
|
||||||
|
]),
|
||||||
|
DropdownContent({ class: 'p-0' },
|
||||||
|
ColorPalette({ value: p.value, onchange: (c) => { isFunc(p.value) ? p.value(c) : p.onchange?.(c) } })
|
||||||
|
)
|
||||||
|
])
|
||||||
|
};
|
||||||
|
export const ColorPalette = (p) => {
|
||||||
|
const current = () => val(p.value) || '#000000'
|
||||||
|
const palette = [
|
||||||
|
'#000', '#1A1A1A', '#333', '#4D4D4D', '#666', '#808080', '#B3B3B3', '#FFF',
|
||||||
|
'#450a0a', '#7f1d1d', '#991b1b', '#b91c1c', '#dc2626', '#ef4444', '#f87171', '#fca5a5',
|
||||||
|
'#431407', '#7c2d12', '#9a3412', '#c2410c', '#ea580c', '#f97316', '#fb923c', '#ffedd5',
|
||||||
|
'#713f12', '#a16207', '#ca8a04', '#eab308', '#facc15', '#fde047', '#fef08a', '#fff9c4',
|
||||||
|
'#064e3b', '#065f46', '#059669', '#10b981', '#34d399', '#4ade80', '#84cc16', '#d9f99d',
|
||||||
|
'#082f49', '#075985', '#0284c7', '#0ea5e9', '#38bdf8', '#7dd3fc', '#22d3ee', '#cffafe',
|
||||||
|
'#1e1b4b', '#312e81', '#4338ca', '#4f46e5', '#6366f1', '#818cf8', '#a5b4fc', '#e0e7ff',
|
||||||
|
'#2e1065', '#4c1d95', '#6d28d9', '#7c3aed', '#8b5cf6', '#a855f7', '#d946ef', '#fae8ff'
|
||||||
|
]
|
||||||
|
const pick = (c) => {
|
||||||
|
isFunc(p.value) ? p.value(c) : p.onchange?.(c)
|
||||||
|
hide()
|
||||||
|
}
|
||||||
|
|
||||||
|
return h('div', {
|
||||||
|
class: cls('p-3 bg-base-100 rounded-box shadow w-64', p.class)
|
||||||
|
}, h('div', { class: 'grid grid-cols-8 gap-1' },
|
||||||
|
palette.map(c => h('button', {
|
||||||
|
type: 'button',
|
||||||
|
style: `background-color: ${c}`,
|
||||||
|
class: () => {
|
||||||
|
const act = current().toLowerCase() === c.toLowerCase()
|
||||||
|
return `size-6 rounded-sm cursor-pointer transition-all hover:scale-125 hover:z-10 active:scale-95 outline-none border border-black/5 p-0 min-h-0 ${act ? 'ring-2 ring-offset-1 ring-primary z-10 scale-110' : ''}`
|
||||||
|
},
|
||||||
|
onclick: () => { pick(c) }
|
||||||
|
}))
|
||||||
|
))
|
||||||
|
};
|
||||||
|
export const Datepicker = (p) => {
|
||||||
|
const displayValue = $("")
|
||||||
|
const rangeMode = () => val(p.range) === true
|
||||||
|
|
||||||
|
watch(() => {
|
||||||
|
const v = val(p.value)
|
||||||
|
if (!v) return displayValue("")
|
||||||
|
let text = ""
|
||||||
|
if (typeof v === "string") {
|
||||||
|
text = p.hour && v.includes("T") ? v.replace("T", " ") : v
|
||||||
|
} else if (v.start && v.end) {
|
||||||
|
const startStr = p.hour && v.startHour != null ? `${v.start} ${String(v.startHour).padStart(2, "0")}:00` : v.start
|
||||||
|
const endStr = p.hour && v.endHour != null ? `${v.end} ${String(v.endHour).padStart(2, "0")}:00` : v.end
|
||||||
|
text = `${startStr} - ${endStr}`
|
||||||
|
} else if (v.start) {
|
||||||
|
const startStr = p.hour && v.startHour != null ? `${v.start} ${String(v.startHour).padStart(2, "0")}:00` : v.start
|
||||||
|
text = `${startStr}...`
|
||||||
|
}
|
||||||
|
displayValue(text)
|
||||||
|
})
|
||||||
|
|
||||||
|
const handleChange = (val) => {
|
||||||
|
if (isFunc(p.value)) p.value(val)
|
||||||
|
else p.onChange?.(val)
|
||||||
|
if (!rangeMode() || val?.end != null) hide()
|
||||||
|
}
|
||||||
|
|
||||||
|
return Dropdown({ class: cls('w-full', p.class) }, [
|
||||||
|
h('label', {
|
||||||
|
tabindex: '0',
|
||||||
|
role: 'button',
|
||||||
|
class: 'input input-bordered flex items-center gap-2 cursor-pointer'
|
||||||
|
}, [
|
||||||
|
h('span', { class: 'icon-[lucide--calendar] shrink-0' }),
|
||||||
|
h('span', {
|
||||||
|
class: () => `grow text-left truncate ${!displayValue() ? 'opacity-50' : ''}`,
|
||||||
|
}, () => displayValue() || p.placeholder || (rangeMode() ? 'Seleccionar rango...' : 'Seleccionar fecha...')),
|
||||||
|
() => displayValue() ? h('button', {
|
||||||
|
type: 'button',
|
||||||
|
class: 'btn btn-ghost btn-xs btn-circle -mr-2',
|
||||||
|
onmousedown: (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
if (isFunc(p.value)) p.value(null)
|
||||||
|
else p.onChange?.(null)
|
||||||
|
displayValue("") // Forzar limpieza visual inmediata
|
||||||
|
}
|
||||||
|
}, h('span', { class: 'icon-[lucide--x] opacity-50' })) : null
|
||||||
|
]),
|
||||||
|
DropdownContent({ class: 'p-0' },
|
||||||
|
Calendar({ value: p.value, range: rangeMode(), hour: p.hour, onChange: handleChange })
|
||||||
|
)
|
||||||
|
])
|
||||||
|
};
|
||||||
|
export const Fileinput = (p) => {
|
||||||
|
const files = $([])
|
||||||
|
const drag = $(false)
|
||||||
|
const error = $(null)
|
||||||
|
const maxBytes = (p.max || 2) * 1024 * 1024
|
||||||
|
const process = (fileList) => {
|
||||||
|
const arr = Array.from(fileList)
|
||||||
|
error(null)
|
||||||
|
if (arr.some(f => f.size > maxBytes)) {
|
||||||
|
error(`Máx ${p.max || 2}MB`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const updated = [...files(), ...arr]
|
||||||
|
files(updated)
|
||||||
|
if (isFunc(p.onselect)) p.onselect(updated)
|
||||||
|
else if (isFunc(p.value)) p.value(updated)
|
||||||
|
}
|
||||||
|
const remove = (idx) => {
|
||||||
|
const updated = files().filter((_, i) => i !== idx)
|
||||||
|
files(updated)
|
||||||
|
if (isFunc(p.onselect)) p.onselect(updated)
|
||||||
|
else if (isFunc(p.value)) p.value(updated)
|
||||||
|
}
|
||||||
|
return h('div', { class: cls('fieldset w-full p-0', p.class) }, [
|
||||||
|
h('label', {
|
||||||
|
class: () => `relative flex items-center justify-between w-full h-12 px-4 border-2 border-dashed rounded-lg cursor-pointer transition-all duration-200 ${drag() ? 'border-primary bg-primary/10' : 'border-base-content/20 bg-base-100 hover:bg-base-200'}`,
|
||||||
|
ondragover: (e) => { e.preventDefault(); drag(true) },
|
||||||
|
ondragleave: () => drag(false),
|
||||||
|
ondrop: (e) => { e.preventDefault(); drag(false); process(e.dataTransfer.files) }
|
||||||
|
}, [
|
||||||
|
h('div', { class: 'flex items-center gap-3 w-full' }, [
|
||||||
|
h('span', { class: 'icon-[lucide--upload]' }),
|
||||||
|
h('span', { class: 'text-sm opacity-70 truncate grow text-left' }, t("uploadFiles")),
|
||||||
|
h('span', { class: 'text-[10px] opacity-40 shrink-0' }, `Máx ${p.max || 2}MB`)
|
||||||
|
]),
|
||||||
|
h('input', {
|
||||||
|
type: 'file',
|
||||||
|
multiple: true,
|
||||||
|
accept: p.accept || '*',
|
||||||
|
class: 'hidden',
|
||||||
|
onchange: (e) => process(e.target.files)
|
||||||
|
})
|
||||||
|
]),
|
||||||
|
() => error() && h('span', { class: 'text-[10px] text-error mt-1 px-1 font-medium' }, error()),
|
||||||
|
when(() => files().length > 0, () =>
|
||||||
|
h('ul', { class: 'mt-2 space-y-1' },
|
||||||
|
each(files, (file, idx) =>
|
||||||
|
h('li', { class: 'flex items-center justify-between p-1.5 pl-3 text-xs bg-base-200/50 rounded-md border border-base-300' }, [
|
||||||
|
h('div', { class: 'flex items-center gap-2 truncate' }, [
|
||||||
|
h('span', { class: 'opacity-50' }, '📄'),
|
||||||
|
h('span', { class: 'truncate font-medium max-w-[200px]' }, file.name),
|
||||||
|
h('span', { class: 'text-[9px] opacity-40' }, `(${(file.size / 1024).toFixed(0)} KB)`)
|
||||||
|
]),
|
||||||
|
h('button', {
|
||||||
|
type: 'button',
|
||||||
|
class: 'btn btn-ghost btn-xs btn-circle',
|
||||||
|
onclick: (e) => { e.preventDefault(); remove(idx) }
|
||||||
|
}, h('span', { class: 'icon-[lucide--x]' }))
|
||||||
|
])
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
])
|
||||||
|
};
|
||||||
|
export const Input = (p) => {
|
||||||
|
const { label, icon, float, placeholder, value, left, right, rule, hint, content, ...rest } = p;
|
||||||
|
const showPassword = $(false);
|
||||||
|
const isPassword = p.type === 'password';
|
||||||
|
const pattern = rule ?? null;
|
||||||
|
const inputType = () => isPassword ? (val(showPassword) ? 'text' : 'password') : (p.type || 'search');
|
||||||
|
return h("label", { class: float ? 'floating-label' : '' }, [
|
||||||
|
float ? h("span", {}, label) : null,
|
||||||
|
h("label", { pattern: pattern, class: () => cls('input validator', p.class) },
|
||||||
|
[
|
||||||
|
label && !float ? h('span', { class: 'label' }, label) : null,
|
||||||
|
left ?? null,
|
||||||
|
h('input', { ...rest, type: inputType, class: 'grow', pattern: pattern, placeholder: placeholder || label || ' ', value: value }),
|
||||||
|
right ?? null,
|
||||||
|
isPassword ? Swap({ class: 'ml-2' }, [
|
||||||
|
SwapToggle({ value: showPassword, class: "swap-rotate" }),
|
||||||
|
SwapOn({}, Icon({},'icon-[lucide--eye]')),
|
||||||
|
SwapOff({}, Icon({},'icon-[lucide--eye-off]')),
|
||||||
|
]) : null
|
||||||
|
]),
|
||||||
|
hint ? h('div', { class: "validator-hint" }, hint) : null,
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
export const Menu = (p) => {
|
||||||
|
if (p.children !== undefined) return h('ul', { class: cls('menu', p.class), ...p }, p.children)
|
||||||
|
const { items } = p
|
||||||
|
const render = (item) => item.children
|
||||||
|
? h('li', {}, h('details', { open: item.open || undefined }, [
|
||||||
|
h('summary', {}, getBy(item)),
|
||||||
|
h('ul', {}, each(() => val(item.children) || [], render))
|
||||||
|
]))
|
||||||
|
: h('li', {}, h('a', {
|
||||||
|
href: item.href,
|
||||||
|
onclick: item.onclick ? (e) => { if (!item.href) e.preventDefault(); item.onclick(e) } : null
|
||||||
|
}, getBy(item)))
|
||||||
|
return h('ul', { class: cls('menu', p.class) },
|
||||||
|
each(() => val(items) || [], render)
|
||||||
|
)
|
||||||
|
};
|
||||||
|
export const Modal = (p, c) => {
|
||||||
|
let dialogRef = null;
|
||||||
|
watch(() => { const isOpen = val(p.open); if (!dialogRef) return; isOpen ? dialogRef.showModal() : dialogRef.close(); });
|
||||||
|
const close = () => isFunc(p.open) && p.open(false);
|
||||||
|
return h("dialog", { ...p, ref: el => dialogRef = el, class: cls('modal', p.class), onclose: close, oncancel: close }, [
|
||||||
|
h("div", { class: "modal-box" }, [
|
||||||
|
p.title && h("h3", { class: "text-lg font-bold" }, p.title),
|
||||||
|
c,
|
||||||
|
h("div", { class: "modal-action" }, [
|
||||||
|
p.actions || Button({ class: 'btn', onclick: close }, 'Cerrar')
|
||||||
|
])
|
||||||
|
]),
|
||||||
|
h("form", { method: "dialog", class: "modal-backdrop" }, [
|
||||||
|
h("button", {}, "close")
|
||||||
|
])
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
export const Select = (p, c) => {
|
||||||
|
if (c !== undefined) return h('select', { class: cls('select', p.class), ...p }, c)
|
||||||
|
const { label, float, placeholder, placeholderDisabled = true, value, left, right, hint, items, keyFn, ...rest } = p
|
||||||
|
const opts = () => {
|
||||||
|
const raw = val(items) || []
|
||||||
|
const ph = placeholder ? [{ disabled: placeholderDisabled, label: placeholder, value: '' }] : []
|
||||||
|
return [...ph, ...raw]
|
||||||
|
}
|
||||||
|
return h('label', { class: float ? 'floating-label' : '' }, [
|
||||||
|
float ? h('span', {}, label) : null,
|
||||||
|
h('label', { class: cls('select', rest.class) }, [
|
||||||
|
(!float && label) ? h('span', { class: 'label' }, label) : null,
|
||||||
|
left ?? null,
|
||||||
|
h('select', {
|
||||||
|
value: () => val(value),
|
||||||
|
onchange: (e) => isFunc(value) ? value(e.target.value) : rest.onchange?.(e)
|
||||||
|
},
|
||||||
|
each(opts, (item) => {
|
||||||
|
const val = getBy(item, item.value !== undefined ? 'value' : undefined)
|
||||||
|
const lab = getBy(item, 'label')
|
||||||
|
return h('option', { value: val, disabled: item.disabled || undefined }, lab)
|
||||||
|
})
|
||||||
|
),
|
||||||
|
right ?? null
|
||||||
|
]),
|
||||||
|
hint ? h('div', { class: 'validator-hint' }, hint) : null
|
||||||
|
])
|
||||||
|
};
|
||||||
|
export const Stat = (p) => h('div', { ...p, class: cls('stat', p.class) }, [
|
||||||
|
p.title ? h('div', { class: 'stat-title' }, p.title) : null,
|
||||||
|
p.value ? h('div', { class: 'stat-value' }, p.value) : null,
|
||||||
|
p.desc ? h('div', { class: 'stat-desc' }, p.desc) : null
|
||||||
|
]);
|
||||||
|
export const TableItems = ({ items, columns = [], header = true }) => {
|
||||||
|
const head = header !== false && columns.some(c => c.label) ? h('thead', {}, h('tr', {}, columns.map(c => h('th', { class: c.class }, c.label)))) : null
|
||||||
|
const body = h('tbody', {}, () => {
|
||||||
|
const list = val(items) || []
|
||||||
|
return list.map((it, idx) => h('tr', {}, columns.map(c => { const v = c.render ? c.render(it, idx) : it[c.key]; return h('td', { class: c.class }, v) })))
|
||||||
|
})
|
||||||
|
return [head, body].filter(Boolean)
|
||||||
|
};
|
||||||
|
export const Tabs = (p, c) => {
|
||||||
|
if (!p.items) {
|
||||||
|
const { class: className, ...rest } = p
|
||||||
|
return h('div', { ...rest, class: cls('tabs', className) }, c)
|
||||||
|
}
|
||||||
|
const { items, activeIndex, onClose, class: className, ...rest } = p
|
||||||
|
const get = x => (isFunc(x) ? x() : x)
|
||||||
|
const closeH = onClose || (isFunc(items) ? (idx, item) => {
|
||||||
|
const arr = val(items)
|
||||||
|
const newArr = arr.filter((_, i) => i !== idx)
|
||||||
|
items(newArr)
|
||||||
|
if (activeIndex() >= newArr.length) activeIndex(Math.max(0, newArr.length - 1))
|
||||||
|
} : null)
|
||||||
|
return h('div', { ...rest, class: cls('tabs', className) }, () => {
|
||||||
|
const list = val(items) || []
|
||||||
|
return list.flatMap((it, idx) => {
|
||||||
|
const isActive = () => activeIndex() === idx
|
||||||
|
const button = h('button', {
|
||||||
|
class: () => `tab ${isActive() ? 'tab-active' : ''} ${it.class || ''}`,
|
||||||
|
onclick: (e) => { e.preventDefault(); activeIndex(idx); it.onclick?.(e) }
|
||||||
|
}, [
|
||||||
|
getBy(it),
|
||||||
|
it.closable ? h('span', {
|
||||||
|
class: 'ml-1 inline-flex items-center justify-center w-4 h-4 rounded-full hover:bg-base-300 text-base-content/60 hover:text-base-content cursor-pointer',
|
||||||
|
onclick: (e) => { e.stopPropagation(); closeH?.(idx, it) }
|
||||||
|
}, h('span', { class: 'icon-[lucide--x] w-3 h-3' })) : null
|
||||||
|
])
|
||||||
|
const contentDiv = h('div', {
|
||||||
|
class: 'tab-content bg-base-100 border-base-300 p-6',
|
||||||
|
style: () => `display: ${isActive() ? 'block' : 'none'};`
|
||||||
|
}, isFunc(it.content) ? it.content() : it.content)
|
||||||
|
return [button, contentDiv]
|
||||||
|
})
|
||||||
|
})
|
||||||
|
};
|
||||||
|
export const Toast = (message, type = "alert-success", duration = 3500) => {
|
||||||
|
let container = document.getElementById("sigpro-toast-container");
|
||||||
|
if (!container) {
|
||||||
|
container = h("div", { id: "sigpro-toast-container", class: "fixed top-0 right-0 z-[9999] p-4 flex flex-col items-end gap-2 pointer-events-none" });
|
||||||
|
document.body.appendChild(container);
|
||||||
|
}
|
||||||
|
const host = h("div", { style: "display: contents" });
|
||||||
|
container.appendChild(host);
|
||||||
|
let closeFn, timer, enterTimer;
|
||||||
|
const ToastComponent = () => {
|
||||||
|
const visible = $(false);
|
||||||
|
const leaving = $(false);
|
||||||
|
closeFn = () => {
|
||||||
|
if (leaving()) return;
|
||||||
|
clearTimeout(timer);
|
||||||
|
clearTimeout(enterTimer);
|
||||||
|
leaving(true);
|
||||||
|
setTimeout(() => { instance.destroy(); host.remove(); if (!container.hasChildNodes()) container.remove(); }, 300);
|
||||||
|
};
|
||||||
|
enterTimer = setTimeout(() => visible(true), 0);
|
||||||
|
const content = typeof message === 'function' ? val(message) : message;
|
||||||
|
const msgNode = typeof content === 'string' ? h("span", {}, content) : content;
|
||||||
|
return h("div", {
|
||||||
|
class: () => {
|
||||||
|
const base = `alert alert-soft ${type} shadow-lg transition-all duration-300 inline-flex w-auto whitespace-nowrap pointer-events-auto`;
|
||||||
|
if (leaving()) return `${base} translate-x-full opacity-0`;
|
||||||
|
if (visible()) return `${base} translate-x-0 opacity-100`;
|
||||||
|
return `${base} translate-x-10 opacity-0`;
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
msgNode,
|
||||||
|
h("button", {
|
||||||
|
class: "btn btn-xs btn-circle btn-ghost",
|
||||||
|
onclick: closeFn
|
||||||
|
}, h("span", { class: "icon-[lucide--x]" }))
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
const instance = mount(ToastComponent, host);
|
||||||
|
if (duration > 0) timer = setTimeout(closeFn, duration);
|
||||||
|
return closeFn;
|
||||||
|
};
|
||||||
433
client/sigpro.js
Normal file
433
client/sigpro.js
Normal file
@@ -0,0 +1,433 @@
|
|||||||
|
const isFunc = f => typeof f === "function"
|
||||||
|
const isObj = o => o && typeof o === "object"
|
||||||
|
const isArr = Array.isArray
|
||||||
|
const doc = typeof document !== "undefined" ? document : null
|
||||||
|
const ensureNode = n => n?._isRuntime ? n.container : (n instanceof Node ? n : doc.createTextNode(n == null ? "" : String(n)))
|
||||||
|
|
||||||
|
let activeEffect = null
|
||||||
|
let activeOwner = null
|
||||||
|
let isFlushing = false
|
||||||
|
let batchDepth = 0
|
||||||
|
const effectQueue = new Set()
|
||||||
|
const MOUNTED_NODES = new WeakMap()
|
||||||
|
|
||||||
|
const SVG_NS = "http://www.w3.org/2000/svg"
|
||||||
|
const XLINK_NS = "http://www.w3.org/1999/xlink"
|
||||||
|
const SVG_TAGS = new Set("svg,path,circle,rect,line,polyline,polygon,g,defs,text,textPath,tspan,use,symbol,image,marker,ellipse".split(","))
|
||||||
|
|
||||||
|
const 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const onUnmount = fn => {
|
||||||
|
if (activeOwner) (activeOwner._cleanups ||= new Set()).add(fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
const untrack = fn => {
|
||||||
|
const p = activeEffect
|
||||||
|
activeEffect = null
|
||||||
|
try { return fn() } finally { activeEffect = p }
|
||||||
|
}
|
||||||
|
|
||||||
|
const 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
|
||||||
|
}
|
||||||
|
|
||||||
|
const 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
|
||||||
|
}
|
||||||
|
|
||||||
|
const batch = fn => {
|
||||||
|
batchDepth++
|
||||||
|
try {
|
||||||
|
return fn()
|
||||||
|
} finally {
|
||||||
|
batchDepth--
|
||||||
|
if (batchDepth === 0 && effectQueue.size > 0 && !isFlushing) flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const $ = (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
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const watch = (sources, cb) => {
|
||||||
|
if (cb === undefined) {
|
||||||
|
const effect = createEffect(sources)
|
||||||
|
effect()
|
||||||
|
return () => dispose(effect)
|
||||||
|
}
|
||||||
|
const effect = createEffect(() => {
|
||||||
|
const vals = isArr(sources) ? sources.map(s => s()) : sources()
|
||||||
|
untrack(() => cb(vals))
|
||||||
|
})
|
||||||
|
effect()
|
||||||
|
return () => dispose(effect)
|
||||||
|
}
|
||||||
|
|
||||||
|
const 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 DANGEROUS_URI_ATTRS = new Set(["src", "href", "formaction", "action", "background", "code", "archive"]);
|
||||||
|
var isDangerousAttr = (key) => DANGEROUS_URI_ATTRS.has(key) || key.startsWith("on");
|
||||||
|
|
||||||
|
const validateAttr = (key, val) => {
|
||||||
|
if (val == null || val === false) return null
|
||||||
|
if (isDangerousAttr(key)) {
|
||||||
|
const sVal = String(val)
|
||||||
|
if (DANGEROUS_PROTOCOL.test(sVal)) return '#'
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
const h = (tag, props = {}, children = []) => {
|
||||||
|
if (props instanceof Node || isArr(props) || !isObj(props)) {
|
||||||
|
children = props
|
||||||
|
props = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isFunc(tag)) {
|
||||||
|
const effect = createEffect(() => {
|
||||||
|
const result = tag(props, {
|
||||||
|
children,
|
||||||
|
emit: (ev, ...args) => props[`on${ev[0].toUpperCase()}${ev.slice(1)}`]?.(...args)
|
||||||
|
})
|
||||||
|
effect._result = result
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
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_TAGS.has(tag)
|
||||||
|
const el = isSVG ? doc.createElementNS(SVG_NS, tag) : doc.createElement(tag)
|
||||||
|
el._cleanups = new Set()
|
||||||
|
|
||||||
|
for (const k of Object.keys(props)) {
|
||||||
|
let v = props[k]
|
||||||
|
if (k === "ref") {
|
||||||
|
isFunc(v) ? v(el) : (v.current = el)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (isSVG && k.startsWith("xlink:")) {
|
||||||
|
const cleanVal = validateAttr(k.slice(6), v)
|
||||||
|
cleanVal == null
|
||||||
|
? el.removeAttributeNS(XLINK_NS, k.slice(6))
|
||||||
|
: el.setAttributeNS(XLINK_NS, k.slice(6), cleanVal)
|
||||||
|
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 === "style" && typeof val === "string") el.setAttribute("style", val)
|
||||||
|
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 === "style" && typeof val === "string") el.setAttribute("style", val)
|
||||||
|
else 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
|
||||||
|
}
|
||||||
|
|
||||||
|
const 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const 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
|
||||||
|
}
|
||||||
|
|
||||||
|
const 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
|
||||||
|
}
|
||||||
|
|
||||||
|
const Fragment = (props) => props.children;
|
||||||
|
|
||||||
|
const 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
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof window !== "undefined") {
|
||||||
|
"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 { $, watch, batch, h, Fragment, render, mount, when, each, onUnmount, isArr, isFunc, isObj }
|
||||||
@@ -134,5 +134,5 @@ export const actions = {
|
|||||||
: null
|
: null
|
||||||
});
|
});
|
||||||
return { totalProcesado: total };
|
return { totalProcesado: total };
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
Reference in New Issue
Block a user