From 75a4de93a114b0e0acd80f7ad5a23e4969d2c0dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matheus=20Sim=C3=B5es?= Date: Fri, 17 Apr 2026 10:13:20 -0300 Subject: [PATCH 01/13] feat: :sparkles: ajuste de elemento fantasma na sidebar --- package-lock.json | 270 ++++++++++++++++------------------ src/components/AppSidebar.tsx | 14 +- 2 files changed, 131 insertions(+), 153 deletions(-) diff --git a/package-lock.json b/package-lock.json index de0bc63..4f804fb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -363,9 +363,9 @@ } }, "node_modules/@chenglou/pretext": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/@chenglou/pretext/-/pretext-0.0.3.tgz", - "integrity": "sha512-RQmqMqUAPRCyv4R3LlRi/ao6KbNWYclqLA+V1HS7sWgyUUbjn3JmmlfXZSY/BjM4rbmIaMSyIVisYocYGYftiQ==", + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/@chenglou/pretext/-/pretext-0.0.5.tgz", + "integrity": "sha512-A8GZN10REdFGsyuiUgLV8jjPDDFMg5GmgxGWV0I3igxBOnzj+jgz2VMmVD7g+SFyoctfeqHFxbNatKSzVRWtRg==", "license": "MIT", "optional": true }, @@ -513,7 +513,6 @@ "version": "1.9.2", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz", "integrity": "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -525,7 +524,6 @@ "version": "1.9.2", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz", "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -536,7 +534,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -859,10 +856,9 @@ } }, "node_modules/@napi-rs/wasm-runtime": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.2.tgz", - "integrity": "sha512-sNXv5oLJ7ob93xkZ1XnxisYhGYXfaG9f65/ZgYuAu3qt7b3NadcOEhLvx28hv31PgX8SZJRYrAIPQilQmFpLVw==", - "dev": true, + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", + "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", "license": "MIT", "optional": true, "dependencies": { @@ -878,10 +874,10 @@ } }, "node_modules/@oxc-project/types": { - "version": "0.122.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.122.0.tgz", - "integrity": "sha512-oLAl5kBpV4w69UtFZ9xqcmTi+GENWOcPF7FCrczTiBbmC0ibXxCwyvZGbO39rCVEuLGAZM84DH0pUIyyv/YJzA==", - "dev": true, + "version": "0.124.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.124.0.tgz", + "integrity": "sha512-VBFWMTBvHxS11Z5Lvlr3IWgrwhMTXV+Md+EQF0Xf60+wAdsGFTBx7X7K/hP4pi8N7dcm1RvcHwDxZ16Qx8keUg==", + "devOptional": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/Boshen" @@ -2622,13 +2618,12 @@ "license": "MIT" }, "node_modules/@rolldown/binding-android-arm64": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.12.tgz", - "integrity": "sha512-pv1y2Fv0JybcykuiiD3qBOBdz6RteYojRFY1d+b95WVuzx211CRh+ytI/+9iVyWQ6koTh5dawe4S/yRfOFjgaA==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.15.tgz", + "integrity": "sha512-YYe6aWruPZDtHNpwu7+qAHEMbQ/yRl6atqb/AhznLTnD3UY99Q1jE7ihLSahNWkF4EqRPVC4SiR4O0UkLK02tA==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2639,13 +2634,12 @@ } }, "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.12.tgz", - "integrity": "sha512-cFYr6zTG/3PXXF3pUO+umXxt1wkRK/0AYT8lDwuqvRC+LuKYWSAQAQZjCWDQpAH172ZV6ieYrNnFzVVcnSflAg==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.15.tgz", + "integrity": "sha512-oArR/ig8wNTPYsXL+Mzhs0oxhxfuHRfG7Ikw7jXsw8mYOtk71W0OkF2VEVh699pdmzjPQsTjlD1JIOoHkLP1Fg==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2656,13 +2650,12 @@ } }, "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.12.tgz", - "integrity": "sha512-ZCsYknnHzeXYps0lGBz8JrF37GpE9bFVefrlmDrAQhOEi4IOIlcoU1+FwHEtyXGx2VkYAvhu7dyBf75EJQffBw==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.15.tgz", + "integrity": "sha512-YzeVqOqjPYvUbJSWJ4EDL8ahbmsIXQpgL3JVipmN+MX0XnXMeWomLN3Fb+nwCmP/jfyqte5I3XRSm7OfQrbyxw==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2673,13 +2666,12 @@ } }, "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.12.tgz", - "integrity": "sha512-dMLeprcVsyJsKolRXyoTH3NL6qtsT0Y2xeuEA8WQJquWFXkEC4bcu1rLZZSnZRMtAqwtrF/Ib9Ddtpa/Gkge9Q==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.15.tgz", + "integrity": "sha512-9Erhx956jeQ0nNTyif1+QWAXDRD38ZNjr//bSHrt6wDwB+QkAfl2q6Mn1k6OBPerznjRmbM10lgRb1Pli4xZPw==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2690,13 +2682,12 @@ } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.12.tgz", - "integrity": "sha512-YqWjAgGC/9M1lz3GR1r1rP79nMgo3mQiiA+Hfo+pvKFK1fAJ1bCi0ZQVh8noOqNacuY1qIcfyVfP6HoyBRZ85Q==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.15.tgz", + "integrity": "sha512-cVwk0w8QbZJGTnP/AHQBs5yNwmpgGYStL88t4UIaqcvYJWBfS0s3oqVLZPwsPU6M0zlW4GqjP0Zq5MnAGwFeGA==", "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2707,13 +2698,12 @@ } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.12.tgz", - "integrity": "sha512-/I5AS4cIroLpslsmzXfwbe5OmWvSsrFuEw3mwvbQ1kDxJ822hFHIx+vsN/TAzNVyepI/j/GSzrtCIwQPeKCLIg==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.15.tgz", + "integrity": "sha512-eBZ/u8iAK9SoHGanqe/jrPnY0JvBN6iXbVOsbO38mbz+ZJsaobExAm1Iu+rxa4S1l2FjG0qEZn4Rc6X8n+9M+w==", "cpu": [ "arm64" ], - "dev": true, "libc": [ "glibc" ], @@ -2727,13 +2717,12 @@ } }, "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.12.tgz", - "integrity": "sha512-V6/wZztnBqlx5hJQqNWwFdxIKN0m38p8Jas+VoSfgH54HSj9tKTt1dZvG6JRHcjh6D7TvrJPWFGaY9UBVOaWPw==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.15.tgz", + "integrity": "sha512-ZvRYMGrAklV9PEkgt4LQM6MjQX2P58HPAuecwYObY2DhS2t35R0I810bKi0wmaYORt6m/2Sm+Z+nFgb0WhXNcQ==", "cpu": [ "arm64" ], - "dev": true, "libc": [ "musl" ], @@ -2747,13 +2736,12 @@ } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.12.tgz", - "integrity": "sha512-AP3E9BpcUYliZCxa3w5Kwj9OtEVDYK6sVoUzy4vTOJsjPOgdaJZKFmN4oOlX0Wp0RPV2ETfmIra9x1xuayFB7g==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.15.tgz", + "integrity": "sha512-VDpgGBzgfg5hLg+uBpCLoFG5kVvEyafmfxGUV0UHLcL5irxAK7PKNeC2MwClgk6ZAiNhmo9FLhRYgvMmedLtnQ==", "cpu": [ "ppc64" ], - "dev": true, "libc": [ "glibc" ], @@ -2767,13 +2755,12 @@ } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.12.tgz", - "integrity": "sha512-nWwpvUSPkoFmZo0kQazZYOrT7J5DGOJ/+QHHzjvNlooDZED8oH82Yg67HvehPPLAg5fUff7TfWFHQS8IV1n3og==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.15.tgz", + "integrity": "sha512-y1uXY3qQWCzcPgRJATPSOUP4tCemh4uBdY7e3EZbVwCJTY3gLJWnQABgeUetvED+bt1FQ01OeZwvhLS2bpNrAQ==", "cpu": [ "s390x" ], - "dev": true, "libc": [ "glibc" ], @@ -2787,13 +2774,12 @@ } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.12.tgz", - "integrity": "sha512-RNrafz5bcwRy+O9e6P8Z/OCAJW/A+qtBczIqVYwTs14pf4iV1/+eKEjdOUta93q2TsT/FI0XYDP3TCky38LMAg==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.15.tgz", + "integrity": "sha512-023bTPBod7J3Y/4fzAN6QtpkSABR0rigtrwaP+qSEabUh5zf6ELr9Nc7GujaROuPY3uwdSIXWrvhn1KxOvurWA==", "cpu": [ "x64" ], - "dev": true, "libc": [ "glibc" ], @@ -2807,13 +2793,12 @@ } }, "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.12.tgz", - "integrity": "sha512-Jpw/0iwoKWx3LJ2rc1yjFrj+T7iHZn2JDg1Yny1ma0luviFS4mhAIcd1LFNxK3EYu3DHWCps0ydXQ5i/rrJ2ig==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.15.tgz", + "integrity": "sha512-witB2O0/hU4CgfOOKUoeFgQ4GktPi1eEbAhaLAIpgD6+ZnhcPkUtPsoKKHRzmOoWPZue46IThdSgdo4XneOLYw==", "cpu": [ "x64" ], - "dev": true, "libc": [ "musl" ], @@ -2827,13 +2812,12 @@ } }, "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.12.tgz", - "integrity": "sha512-vRugONE4yMfVn0+7lUKdKvN4D5YusEiPilaoO2sgUWpCvrncvWgPMzK00ZFFJuiPgLwgFNP5eSiUlv2tfc+lpA==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.15.tgz", + "integrity": "sha512-UCL68NJ0Ud5zRipXZE9dF5PmirzJE4E4BCIOOssEnM7wLDsxjc6Qb0sGDxTNRTP53I6MZpygyCpY8Aa8sPfKPg==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2844,30 +2828,46 @@ } }, "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.12.tgz", - "integrity": "sha512-ykGiLr/6kkiHc0XnBfmFJuCjr5ZYKKofkx+chJWDjitX+KsJuAmrzWhwyOMSHzPhzOHOy7u9HlFoa5MoAOJ/Zg==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.15.tgz", + "integrity": "sha512-ApLruZq/ig+nhaE7OJm4lDjayUnOHVUa77zGeqnqZ9pn0ovdVbbNPerVibLXDmWeUZXjIYIT8V3xkT58Rm9u5Q==", "cpu": [ "wasm32" ], - "dev": true, "license": "MIT", "optional": true, "dependencies": { - "@napi-rs/wasm-runtime": "^1.1.1" + "@emnapi/core": "1.9.2", + "@emnapi/runtime": "1.9.2", + "@napi-rs/wasm-runtime": "^1.1.3" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.12.tgz", - "integrity": "sha512-5eOND4duWkwx1AzCxadcOrNeighiLwMInEADT0YM7xeEOOFcovWZCq8dadXgcRHSf3Ulh1kFo/qvzoFiCLOL1Q==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.15.tgz", + "integrity": "sha512-KmoUoU7HnN+Si5YWJigfTws1jz1bKBYDQKdbLspz0UaqjjFkddHsqorgiW1mxcAj88lYUE6NC/zJNwT+SloqtA==", "cpu": [ "arm64" ], - "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.15.tgz", + "integrity": "sha512-3P2A8L+x75qavWLe/Dll3EYBJLQmtkJN8rfh+U/eR3MqMgL/h98PhYI+JFfXuDPgPeCB7iZAKiqii5vqOvnA0g==", + "cpu": [ + "x64" + ], "license": "MIT", "optional": true, "os": [ @@ -3355,7 +3355,6 @@ "version": "0.10.1", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -4011,9 +4010,9 @@ } }, "node_modules/boneyard-js": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/boneyard-js/-/boneyard-js-1.6.7.tgz", - "integrity": "sha512-ClzI7uF4cAaSBQOtwChjNQhIzOUIWofYBBN8Q0bY/b7+i3Ik6o/ykd0SZp4XaRMt7z9BDwE7Ir/U6IxDV9cGqw==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/boneyard-js/-/boneyard-js-1.7.7.tgz", + "integrity": "sha512-/xWx9Okv73pfdFLHS8oQw4SkPBDJN1OxDSIb3bMY2LI/t50a5qHkJNLm6/GeFpaahTSVJQKG7p6kgisheDsGFg==", "license": "MIT", "dependencies": { "playwright": "^1.58.2" @@ -4022,19 +4021,24 @@ "boneyard-js": "bin/cli.js" }, "optionalDependencies": { - "@chenglou/pretext": "^0.0.3" + "@chenglou/pretext": "^0.0.5" }, "peerDependencies": { "@angular/core": ">=14", + "preact": ">=10", "react": ">=18", "react-native": ">=0.71", "svelte": ">=5.29", + "vite": ">=5", "vue": ">=3" }, "peerDependenciesMeta": { "@angular/core": { "optional": true }, + "preact": { + "optional": true + }, "react": { "optional": true }, @@ -4044,6 +4048,9 @@ "svelte": { "optional": true }, + "vite": { + "optional": true + }, "vue": { "optional": true } @@ -4310,7 +4317,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "dev": true, + "devOptional": true, "license": "Apache-2.0", "engines": { "node": ">=8" @@ -4623,7 +4630,7 @@ "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=12.0.0" @@ -4692,7 +4699,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -4892,7 +4898,7 @@ "version": "2.6.1", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", - "dev": true, + "devOptional": true, "license": "MIT", "bin": { "jiti": "lib/jiti-cli.mjs" @@ -5044,7 +5050,7 @@ "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", - "dev": true, + "devOptional": true, "license": "MPL-2.0", "dependencies": { "detect-libc": "^2.0.3" @@ -5077,7 +5083,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -5098,7 +5103,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -5119,7 +5123,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -5140,7 +5143,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -5161,7 +5163,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -5182,7 +5183,6 @@ "cpu": [ "arm64" ], - "dev": true, "libc": [ "glibc" ], @@ -5206,7 +5206,6 @@ "cpu": [ "arm64" ], - "dev": true, "libc": [ "musl" ], @@ -5230,7 +5229,6 @@ "cpu": [ "x64" ], - "dev": true, "libc": [ "glibc" ], @@ -5254,7 +5252,6 @@ "cpu": [ "x64" ], - "dev": true, "libc": [ "musl" ], @@ -5278,7 +5275,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -5299,7 +5295,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -5417,7 +5412,7 @@ "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, + "devOptional": true, "funding": [ { "type": "github", @@ -5564,14 +5559,14 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, + "devOptional": true, "license": "ISC" }, "node_modules/picomatch": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=12" @@ -5628,7 +5623,7 @@ "version": "8.5.8", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", - "dev": true, + "devOptional": true, "funding": [ { "type": "opencollective", @@ -5977,14 +5972,14 @@ } }, "node_modules/rolldown": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.12.tgz", - "integrity": "sha512-yP4USLIMYrwpPHEFB5JGH1uxhcslv6/hL0OyvTuY+3qlOSJvZ7ntYnoWpehBxufkgN0cvXxppuTu5hHa/zPh+A==", - "dev": true, + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.15.tgz", + "integrity": "sha512-Ff31guA5zT6WjnGp0SXw76X6hzGRk/OQq2hE+1lcDe+lJdHSgnSX6nK3erbONHyCbpSj9a9E+uX/OvytZoWp2g==", + "devOptional": true, "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.122.0", - "@rolldown/pluginutils": "1.0.0-rc.12" + "@oxc-project/types": "=0.124.0", + "@rolldown/pluginutils": "1.0.0-rc.15" }, "bin": { "rolldown": "bin/cli.mjs" @@ -5993,45 +5988,28 @@ "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.0.0-rc.12", - "@rolldown/binding-darwin-arm64": "1.0.0-rc.12", - "@rolldown/binding-darwin-x64": "1.0.0-rc.12", - "@rolldown/binding-freebsd-x64": "1.0.0-rc.12", - "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.12", - "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.12", - "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.12", - "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.12", - "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.12", - "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.12", - "@rolldown/binding-linux-x64-musl": "1.0.0-rc.12", - "@rolldown/binding-openharmony-arm64": "1.0.0-rc.12", - "@rolldown/binding-wasm32-wasi": "1.0.0-rc.12", - "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.12", - "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.12" - } - }, - "node_modules/rolldown/node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.12.tgz", - "integrity": "sha512-PyqoipaswDLAZtot351MLhrlrh6lcZPo2LSYE+VDxbVk24LVKAGOuE4hb8xZQmrPAuEtTZW8E6D2zc5EUZX4Lw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" + "@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" } }, "node_modules/rolldown/node_modules/@rolldown/pluginutils": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.12.tgz", - "integrity": "sha512-HHMwmarRKvoFsJorqYlFeFRzXZqCt2ETQlEDOb9aqssrnVBB1/+xgTGtuTrIk5vzLNX1MjMtTf7W9z3tsSbrxw==", - "dev": true, + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.15.tgz", + "integrity": "sha512-UromN0peaE53IaBRe9W7CjrZgXl90fqGpK+mIZbA3qSTeYqg3pqpROBdIPvOG3F5ereDHNwoHBI2e50n1BDr1g==", + "devOptional": true, "license": "MIT" }, "node_modules/saxes": { @@ -6107,7 +6085,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, + "devOptional": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -6225,7 +6203,7 @@ "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "fdir": "^6.5.0", @@ -6487,16 +6465,16 @@ } }, "node_modules/vite": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.3.tgz", - "integrity": "sha512-B9ifbFudT1TFhfltfaIPgjo9Z3mDynBTJSUYxTjOQruf/zHH+ezCQKcoqO+h7a9Pw9Nm/OtlXAiGT1axBgwqrQ==", - "dev": true, + "version": "8.0.8", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.8.tgz", + "integrity": "sha512-dbU7/iLVa8KZALJyLOBOQ88nOXtNG8vxKuOT4I2mD+Ya70KPceF4IAmDsmU0h1Qsn5bPrvsY9HJstCRh3hG6Uw==", + "devOptional": true, "license": "MIT", "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.8", - "rolldown": "1.0.0-rc.12", + "rolldown": "1.0.0-rc.15", "tinyglobby": "^0.2.15" }, "bin": { @@ -6514,7 +6492,7 @@ "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.0", - "esbuild": "^0.27.0", + "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", diff --git a/src/components/AppSidebar.tsx b/src/components/AppSidebar.tsx index 5fc9556..d668194 100644 --- a/src/components/AppSidebar.tsx +++ b/src/components/AppSidebar.tsx @@ -70,16 +70,14 @@ interface AppSidebarProps { const NAV_ITEMS: NavItem[] = [ { label: "Início", Icon: Home, view: "home" }, - { label: "Demandas", Icon: ListChecks, view: "demandas", requiresClient: true }, - { - label: "Calendário", - Icon: CalendarDays, + label: "Demandas", + Icon: ListChecks, requiresClient: true, children: [ + { view: "demandas", label: "Todas Demandas" }, { view: "calendar", label: "Calendário" }, { view: "timeline", label: "Linha do Tempo" }, - { view: "list", label: "Lista" }, ], }, @@ -301,11 +299,13 @@ export function AppSidebar({ - {isAdmin && ( + {/* {isAdmin && ( <> - )} + )} */} + + {availableClients.map((client) => ( Date: Fri, 17 Apr 2026 10:32:01 -0300 Subject: [PATCH 02/13] =?UTF-8?q?feat:=20:sparkles:=20adicionada=20view=20?= =?UTF-8?q?de=20transi=C3=A7=C3=A3o=20entre=20cliients?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/architecture.md | 39 +++- src/App.tsx | 29 ++- src/components/ClientTransitionOverlay.tsx | 259 +++++++++++++++++++++ 3 files changed, 318 insertions(+), 9 deletions(-) create mode 100644 src/components/ClientTransitionOverlay.tsx diff --git a/docs/architecture.md b/docs/architecture.md index dc3257e..3646a14 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -7,10 +7,11 @@ src/ ├── App.tsx # Root: providers, roteamento, inicialização do cliente ├── main.tsx # Entry point ├── components/ -│ ├── TaskModal.tsx # Modal criar/editar demanda -│ ├── AppHeader.tsx # Header: logo, hamburger mobile, NotificationBell, theme toggle (desktop) -│ ├── AppSidebar.tsx # Sidebar de navegação; theme toggle no footer mobile -│ └── ui/ # Design system (Button, Input, Label, Badge) +│ ├── TaskModal.tsx # Modal criar/editar demanda +│ ├── AppHeader.tsx # Header: logo, hamburger mobile, NotificationBell, theme toggle (desktop) +│ ├── AppSidebar.tsx # Sidebar de navegação; theme toggle no footer mobile +│ ├── ClientTransitionOverlay.tsx # Overlay animado exibido ao trocar de cliente +│ └── ui/ # Design system (Button, Input, Label, Badge) ├── views/ │ ├── home/ # HomeView — saudação, SearchLauncher, QuickAccess │ ├── dashboard/ # DashboardView → Calendar/Timeline @@ -155,14 +156,40 @@ Relê o perfil do usuário atual (member + clients) sem reiniciar o ciclo de aut ## Troca de Cliente +A troca de cliente exibe um overlay de transição animado antes de efetivar a mudança: + ``` handleSelectClient(newId) - → invalidate() ← limpa tasks/members imediatamente (sem vazamento) - → setClient(newId) ← persiste no localStorage + → setTransitionClient({ id, name }) ← exibe ClientTransitionOverlay (~3s) + ↓ onComplete (após fade-out) + → setClient(newId) ← persiste no localStorage → setView("home") + → toast cinza "Trocado para " (sonner, 3s) → useEffect dispara fetchData(newId) ``` +### `ClientTransitionOverlay` (`src/components/ClientTransitionOverlay.tsx`) + +Overlay fullscreen (`z-[9999]`) exibido ao trocar de cliente. Duração total ~3.8s. + +**Camadas visuais (profundidade):** +- Gradiente radial fixo no fundo (`--muted`) simulando luminosidade de céu — não anima +- 8 nuvens SVG com posição, escala e opacidade fixas no `style`; cada nuvem anima **apenas `translateX`** via keyframe único gerado dinamicamente por valor de `dx` (`ct-cloud-8`, `ct-cloud-10`, etc.) — isso evita que o `scale` do style seja sobrescrito e mantém o drift orgânico e independente +- Linha de horizonte + pista SVG posicionadas em `bottom: 24-26%`, criando perspectiva de chão + +**Avião lateral (`PlaneSide`) + rastro:** +- SVG de vista lateral: fuselagem em perspectiva, asa principal, cauda vertical e horizontal, janelas +- Percorre da esquerda para a direita em arco de decolagem (`ct-takeoff`): táxi → inclinação suave → saída diagonal em ~25° +- Rastro de condensação duplo com gradiente linear atrás do avião + +**Conteúdo central (sem card):** +- Label "DESTINO" em uppercase + tracking largo +- Nome do cliente em `text-5xl` bold, fonte Syne +- Separador decorativo `✦` +- Mensagens rotativas com fade + `translateY(3px)` suave (350ms): `🛂 Verificando passaporte` → `🎫 Confirmando embarque` → `🛫 Decolando agora` → `✈️ Em rota de cruzeiro` + +Ao fechar, dispara `onComplete` → efetiva a troca no store e exibe toast de confirmação. + ## `ClientOption` (tipo em `src/contexts/AuthContext.ts`) ```ts diff --git a/src/App.tsx b/src/App.tsx index e32cded..0f269be 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -29,6 +29,7 @@ import type { Notification } from "./types/notification"; import type { ViewType } from "@/store/useUIStore"; import { canAccessView, resolveAccessRole } from "@/lib/accessControl"; import { ConfirmModal, TooltipProvider } from "@/components/ui"; +import { ClientTransitionOverlay } from "@/components/ClientTransitionOverlay"; export default function App() { const { session, user, signIn, signOut, authError, loading: authLoading, isAdmin, member, clients, refreshProfile } = useAuthContext(); @@ -128,10 +129,25 @@ export default function App() { const [pendingDeleteTaskId, setPendingDeleteTaskId] = useState(null) const [closeTaskModalOnDelete, setCloseTaskModalOnDelete] = useState(false) + const [transitionClient, setTransitionClient] = useState<{ id: string | null | undefined; name: string } | null>(null) + const handleSelectClient = useCallback((clientId: string | null | undefined) => { - setClient(clientId); - setView("home"); - }, [setClient, setView]); + const targetClient = clients.find((c) => c.id === clientId) + if (!targetClient || clientId === effectiveClientId) return + setTransitionClient({ id: clientId, name: targetClient.name }) + }, [clients, effectiveClientId]) + + const handleTransitionComplete = useCallback(() => { + if (!transitionClient) return + setClient(transitionClient.id) + setView("home") + toast('Visualização alterada', { + description: `Trocado para ${transitionClient.name}`, + style: { background: 'var(--muted)', color: 'var(--foreground)', border: '1px solid var(--border)' }, + duration: 3000, + }) + setTransitionClient(null) + }, [transitionClient, setClient, setView]) const handleViewChange = useCallback((newView: ViewType) => { setMobileSidebarOpen(false); @@ -332,6 +348,13 @@ export default function App() { /> )} + {transitionClient && ( + + )} + {pendingDeleteTaskId && ( void +} + +const MESSAGES = [ + '🛂 Verificando passaporte', + '🎫 Confirmando embarque', + '🛫 Decolando agora', + '✈️ Em rota de cruzeiro', +] + +const TOTAL_MS = 3800 +const MSG_INTERVAL = TOTAL_MS / MESSAGES.length + +// Nuvens +const CLOUDS = [ + { x: 6, y: 12, s: 1.0, o: 0.06, d: 22, dx: 10 }, + { x: 70, y: 8, s: 0.7, o: 0.04, d: 28, dx: 8 }, + { x: 35, y: 20, s: 1.3, o: 0.05, d: 18, dx: 14 }, + { x: 82, y: 32, s: 0.85,o: 0.04, d: 24, dx: 9 }, + { x: 15, y: 48, s: 1.1, o: 0.05, d: 20, dx: 12 }, + { x: 58, y: 58, s: 0.65,o: 0.03, d: 30, dx: 7 }, + { x: 3, y: 68, s: 0.9, o: 0.05, d: 26, dx: 11 }, + { x: 88, y: 65, s: 1.2, o: 0.04, d: 16, dx: 13 }, +] + +function PlaneSide({ size = 56 }: { size?: number }) { + return ( + + {/* O avião agora é desenhado RETO. A rotação acontece na keyframe do CSS */} + + {/* ELEMENTOS DE FUNDO */} + + + + + {/* ELEMENTOS PRINCIPAIS */} + + + + + + + + + + + ) +} + +function Cloud({ x, y, s, o, d, dx }: typeof CLOUDS[0]) { + const delay = -(d * 0.4) + return ( +
+ + + + + + +
+ ) +} + +export function ClientTransitionOverlay({ clientName, onComplete }: ClientTransitionOverlayProps) { + const [messageIndex, setMessageIndex] = useState(0) + const [msgOut, setMsgOut] = useState(false) + const [visible, setVisible] = useState(false) + const onCompleteRef = useRef(onComplete) + onCompleteRef.current = onComplete + + useEffect(() => { + const showTimer = setTimeout(() => setVisible(true), 20) + + let current = 0 + const msgInterval = setInterval(() => { + setMsgOut(true) + setTimeout(() => { + current = (current + 1) % MESSAGES.length + setMessageIndex(current) + setMsgOut(false) + }, 350) + }, MSG_INTERVAL) + + const fadeOutTimer = setTimeout(() => { + setVisible(false) + setTimeout(() => onCompleteRef.current(), 500) + }, TOTAL_MS) + + return () => { + clearTimeout(showTimer) + clearInterval(msgInterval) + clearTimeout(fadeOutTimer) + } + }, []) + + const uniqueDx = [...new Set(CLOUDS.map((c) => Math.round(c.dx)))] + + return ( +
+ {/* Gradiente de céu */} +
+ + {/* Nuvens */} + {CLOUDS.map((c, i) => ( + + ))} + + {/* Linha de horizonte */} +
+ + {/* Pista animada (Ilusão de velocidade) */} +
+ + + + + {Array.from({ length: 14 }).map((_, i) => ( + + ))} + + +
+ + {/* Avião lateral + rastro (Animado via GPU usando Translate3D) */} +
+ {/* Rastro */} +
+ + + + + + + + + + +
+ + +
+ + {/* Conteúdo central */} +
+

+ Destino +

+ +

+ {clientName} +

+ +
+
+ ✦ +
+
+ +

+ {MESSAGES[messageIndex]} +

+
+ + +
+ ) +} \ No newline at end of file From ff8c610d3c0d3274268f47b97625c96b0d2b7c8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matheus=20Sim=C3=B5es?= Date: Fri, 17 Apr 2026 10:52:48 -0300 Subject: [PATCH 03/13] =?UTF-8?q?feat:=20:sparkles:=20ajustado=20anima?= =?UTF-8?q?=C3=A7=C3=A3o=20pra=20fazer=20o=20fetch=20durante=20a=20anima?= =?UTF-8?q?=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/architecture.md | 13 +- src/App.tsx | 11 +- src/components/ClientTransitionOverlay.tsx | 434 +++++++++++++-------- 3 files changed, 284 insertions(+), 174 deletions(-) diff --git a/docs/architecture.md b/docs/architecture.md index 3646a14..e45e027 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -160,14 +160,17 @@ A troca de cliente exibe um overlay de transição animado antes de efetivar a m ``` handleSelectClient(newId) - → setTransitionClient({ id, name }) ← exibe ClientTransitionOverlay (~3s) - ↓ onComplete (após fade-out) - → setClient(newId) ← persiste no localStorage - → setView("home") + → setClient(newId) ← persiste no localStorage (imediato) + → setView("home") ← imediato + → setTransitionClient({ id, name }) ← exibe ClientTransitionOverlay (~3.2s) + → useEffect dispara fetchData(newId) ← inicia em background durante o overlay + ↓ onComplete (após fade-out do overlay) → toast cinza "Trocado para " (sonner, 3s) - → useEffect dispara fetchData(newId) + → setTransitionClient(null) ``` +> A store e o fetch são disparados **imediatamente** ao clicar, antes do overlay fechar. Quando a animação termina, os dados já chegaram ou estão a caminho — sem espera visível após a transição. + ### `ClientTransitionOverlay` (`src/components/ClientTransitionOverlay.tsx`) Overlay fullscreen (`z-[9999]`) exibido ao trocar de cliente. Duração total ~3.8s. diff --git a/src/App.tsx b/src/App.tsx index 0f269be..fc4dfeb 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -134,20 +134,23 @@ export default function App() { const handleSelectClient = useCallback((clientId: string | null | undefined) => { const targetClient = clients.find((c) => c.id === clientId) if (!targetClient || clientId === effectiveClientId) return + // Exibe o overlay primeiro; após o fade-in (~650ms) dispara a troca para o fetch ocorrer em background setTransitionClient({ id: clientId, name: targetClient.name }) - }, [clients, effectiveClientId]) + setTimeout(() => { + setClient(clientId) + setView("home") + }, 650) + }, [clients, effectiveClientId, setClient, setView]) const handleTransitionComplete = useCallback(() => { if (!transitionClient) return - setClient(transitionClient.id) - setView("home") toast('Visualização alterada', { description: `Trocado para ${transitionClient.name}`, style: { background: 'var(--muted)', color: 'var(--foreground)', border: '1px solid var(--border)' }, duration: 3000, }) setTransitionClient(null) - }, [transitionClient, setClient, setView]) + }, [transitionClient]) const handleViewChange = useCallback((newView: ViewType) => { setMobileSidebarOpen(false); diff --git a/src/components/ClientTransitionOverlay.tsx b/src/components/ClientTransitionOverlay.tsx index bb63edb..d2d5f46 100644 --- a/src/components/ClientTransitionOverlay.tsx +++ b/src/components/ClientTransitionOverlay.tsx @@ -1,107 +1,113 @@ -import { useEffect, useRef, useState } from 'react' +import React, { useEffect, useRef, useState } from 'react' +// --- TIPO DAS PROPS --- interface ClientTransitionOverlayProps { clientName: string onComplete: () => void } const MESSAGES = [ - '🛂 Verificando passaporte', + '🛂 Verificando credenciais', '🎫 Confirmando embarque', - '🛫 Decolando agora', - '✈️ Em rota de cruzeiro', + '🛫 Autorização de torre', + '✈️ Em rota de cruzeiro', ] -const TOTAL_MS = 3800 +const TOTAL_MS = 3200 // Transição mais rápida (reduzida de 4600ms para 3200ms) const MSG_INTERVAL = TOTAL_MS / MESSAGES.length -// Nuvens +// Nuvens com posições e velocidades otimizadas para fluir da direita para a esquerda const CLOUDS = [ - { x: 6, y: 12, s: 1.0, o: 0.06, d: 22, dx: 10 }, - { x: 70, y: 8, s: 0.7, o: 0.04, d: 28, dx: 8 }, - { x: 35, y: 20, s: 1.3, o: 0.05, d: 18, dx: 14 }, - { x: 82, y: 32, s: 0.85,o: 0.04, d: 24, dx: 9 }, - { x: 15, y: 48, s: 1.1, o: 0.05, d: 20, dx: 12 }, - { x: 58, y: 58, s: 0.65,o: 0.03, d: 30, dx: 7 }, - { x: 3, y: 68, s: 0.9, o: 0.05, d: 26, dx: 11 }, - { x: 88, y: 65, s: 1.2, o: 0.04, d: 16, dx: 13 }, + { top: 5, size: 200, opacity: 0.45, duration: 45, delay: -10 }, + { top: 15, size: 300, opacity: 0.35, duration: 35, delay: -5 }, + { top: 30, size: 250, opacity: 0.25, duration: 50, delay: -20 }, + { top: 45, size: 400, opacity: 0.3, duration: 40, delay: -15 }, + { top: 10, size: 150, opacity: 0.5, duration: 25, delay: -2 }, + { top: 60, size: 350, opacity: 0.2, duration: 60, delay: -30 }, ] -function PlaneSide({ size = 56 }: { size?: number }) { +// --- COMPONENTES AUXILIARES --- + +function NoiseOverlay() { return ( - - {/* O avião agora é desenhado RETO. A rotação acontece na keyframe do CSS */} - - {/* ELEMENTOS DE FUNDO */} - - - - - {/* ELEMENTOS PRINCIPAIS */} - - - - - - - - - - +
+ + + + + + +
) } -function Cloud({ x, y, s, o, d, dx }: typeof CLOUDS[0]) { - const delay = -(d * 0.4) +function Cloud({ top, size, opacity, duration, delay }: typeof CLOUDS[0]) { return (
- - - - - - + /> + ) +} + +function PlaneIcon() { + return ( + + + {/* Fuselagem */} + + {/* Asa Principal */} + + + {/* Asa Traseira */} + + + {/* Cockpit Window */} + + + + ) +} + +function Barcode() { + const bars = React.useMemo(() => { + return Array.from({ length: 32 }).map(() => ({ + width: Math.random() > 0.6 ? '3px' : '1.5px', + height: `${40 + Math.random() * 60}%`, + })) + }, []) + + return ( +
+ {bars.map((bar, i) => ( +
+ ))}
) } +// --- COMPONENTE PRINCIPAL --- + export function ClientTransitionOverlay({ clientName, onComplete }: ClientTransitionOverlayProps) { const [messageIndex, setMessageIndex] = useState(0) const [msgOut, setMsgOut] = useState(false) const [visible, setVisible] = useState(false) + const onCompleteRef = useRef(onComplete) onCompleteRef.current = onComplete useEffect(() => { - const showTimer = setTimeout(() => setVisible(true), 20) + // Pequeno delay para garantir que a animação de entrada seja vista + const showTimer = setTimeout(() => setVisible(true), 50) let current = 0 const msgInterval = setInterval(() => { @@ -110,12 +116,12 @@ export function ClientTransitionOverlay({ clientName, onComplete }: ClientTransi current = (current + 1) % MESSAGES.length setMessageIndex(current) setMsgOut(false) - }, 350) + }, 300) // Fade out do texto mais rápido }, MSG_INTERVAL) const fadeOutTimer = setTimeout(() => { setVisible(false) - setTimeout(() => onCompleteRef.current(), 500) + setTimeout(() => onCompleteRef.current(), 600) // Fade global mais ágil }, TOTAL_MS) return () => { @@ -125,135 +131,233 @@ export function ClientTransitionOverlay({ clientName, onComplete }: ClientTransi } }, []) - const uniqueDx = [...new Set(CLOUDS.map((c) => Math.round(c.dx)))] - return (
- {/* Gradiente de céu */} + + + {/* CÉU GRADIENTE SUAVE - Adaptável ao tema via pseudo-elemento / var CSS local */}
- {/* Nuvens */} + {/* NUVENS ATMOSFÉRICAS */} {CLOUDS.map((c, i) => ( ))} - {/* Linha de horizonte */} -
+ {/* CHÃO / PISTA - Adaptável */} +
+ {/* Linha Central da Pista Animada */} +
+
+ {Array.from({ length: 30 }).map((_, i) => ( +
+ ))} +
+
+
- {/* Pista animada (Ilusão de velocidade) */} + {/* AVIÃO ANIMADO - Movimento contínuo e mais rápido */}
- - - - - {Array.from({ length: 14 }).map((_, i) => ( - - ))} - - +
- {/* Avião lateral + rastro (Animado via GPU usando Translate3D) */} + {/* TICKET DE EMBARQUE PREMIUM - Tema Adaptável */}
- {/* Rastro */} -
- - - - - - - - - - -
+ {/* Topo do Ticket */} +
+
+ {/* Símbolo decorativo */} + + + + +
- -
+
+ + Boarding Pass + + + Priority + +
- {/* Conteúdo central */} -
-

- Destino -

- -

- {clientName} -

+

+ Passenger +

+

+ {clientName} +

+ +
+
+

Flight

+

NX-012

+
+
+

Gate

+

A-42

+
+
+
-
-
- ✦ -
+ {/* Linha Picotada */} +
+
+
+
-

- {MESSAGES[messageIndex]} -

+ {/* Canhoto Inferior */} +
+

+ {MESSAGES[messageIndex]} +

+ +
+ +

+ 0010110 0110001 +

+
+
+ {/* --- ESTILOS INJETADOS (KEYFRAMES) --- */}
) +} + +// === COMPONENTE APP DE DEMONSTRAÇÃO (Apenas para o Preview) === +export default function App() { + const [showOverlay, setShowOverlay] = useState(false) + const [isDarkMode, setIsDarkMode] = useState(false) + + // Injeta a classe dark no HTML para o Tailwind aplicar os estilos adaptáveis + useEffect(() => { + if (isDarkMode) { + document.documentElement.classList.add('dark') + } else { + document.documentElement.classList.remove('dark') + } + }, [isDarkMode]) + + return ( +
+
+ +
+ +
+

Dashboard Principal

+

+ Clique no botão abaixo para ver a transição 100% fluida e adaptável. +

+ +
+ + {showOverlay && ( + setShowOverlay(false)} + /> + )} +
+ ) } \ No newline at end of file From 50e9dbefe1bbe30995edf90e84f2d959e70c59ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matheus=20Sim=C3=B5es?= Date: Fri, 17 Apr 2026 12:02:24 -0300 Subject: [PATCH 04/13] =?UTF-8?q?feat:=20:sparkles:=20ajustado=20view=20e?= =?UTF-8?q?=20envio=20de=20notifica=C3=A7=C3=B5es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/settings.local.json | 3 +- docs/hooks/notifications.md | 16 + docs/views/admin.md | 22 + package-lock.json | 1374 ++++++++++++++++- package.json | 2 + src/components/ClientTransitionOverlay.tsx | 265 ++-- src/components/NotificationBell.tsx | 36 +- src/lib/notifications.ts | 20 + .../admin/components/NotificationsPanel.tsx | 490 +++--- 9 files changed, 1772 insertions(+), 456 deletions(-) diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 2cd7175..e1ddaa6 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -37,7 +37,8 @@ "Bash(mv components/DemandasFilters.tsx components/TasksFilters.tsx)", "Bash(npx --yes tsc --noEmit --project \"c:/Users/dinam/Documents/Projetos/run-way/tsconfig.json\")", "Bash(npm show:*)", - "Bash(ls c:/Users/dinam/Documents/Projetos/run-way/node_modules/boneyard-js/react*)" + "Bash(ls c:/Users/dinam/Documents/Projetos/run-way/node_modules/boneyard-js/react*)", + "Bash(npm list *)" ] }, "hooks": { diff --git a/docs/hooks/notifications.md b/docs/hooks/notifications.md index 33aee8f..6bea740 100644 --- a/docs/hooks/notifications.md +++ b/docs/hooks/notifications.md @@ -100,6 +100,22 @@ Componente de sino com dropdown. Recebe notificações já carregadas via props - **Todas** — todas as notificações do usuário - **Cliente atual** — filtra por `client_id === selectedClientId` +--- + +# createNotificationForAll + +```ts +createNotificationForAll(clientIds: string[], title: string, message: string, type?: string): Promise +``` + +Insere um broadcast (`user_id = null`) para cada `clientId` em uma única operação `insert` em lote. Usado pelo `NotificationsPanel` na opção de destino **Todos**. + +--- + +## Formatação da mensagem + +O campo `message` suporta **Markdown** — negrito, itálico, quebras de linha etc. Renderizado via `react-markdown` com classes `prose-xs` do Tailwind. + ## Audiência Cada item exibe ícone e label indicando o destinatário: diff --git a/docs/views/admin.md b/docs/views/admin.md index 6ad8106..f8eb682 100644 --- a/docs/views/admin.md +++ b/docs/views/admin.md @@ -107,6 +107,28 @@ No tab **Membros**, os filtros disponíveis são: **Todos / Ativos / Sem acesso - **Sem acesso** filtra members ativos sem `auth_user_id` - **Desativados** filtra members com `is_active === false` +## NotificationsPanel + +Aba de envio e histórico de notificações manuais. + +### Destinos + +| Opção | Comportamento | +|---|---| +| **Usuário** | Notificação direta a um membro ativo (`user_id` preenchido, `manual`) | +| **Cliente** | Broadcast para todos os membros de um cliente (`user_id = null`, `client_id`) | +| **Todos** | Broadcast para todos os clientes cadastrados — chama `createNotificationForAll` | + +### Editor de mensagem + +O campo **Mensagem** tem tabs **Editar / Preview**: +- **Editar** — textarea mono; suporta Markdown (`**negrito**`, `_itálico_`, quebras de linha) +- **Preview** — renderiza via `react-markdown` antes do envio + +### Histórico + +Scroll independente, contido em `100vh`. Mensagens renderizadas como Markdown via `react-markdown`. + ## Impersonation Admin pode visualizar a aplicação como um cliente específico via `impersonatedClientId` (estado no `AuthContext`). Um banner amarelo aparece na AdminView quando ativo, com botão para sair da visão. diff --git a/package-lock.json b/package-lock.json index 4f804fb..a12aec1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,8 @@ "radix-ui": "^1.4.3", "react": "^19.2.4", "react-dom": "^19.2.4", + "react-markdown": "^10.1.0", + "remark-breaks": "^4.0.0", "sonner": "^2.0.7", "tailwind-merge": "^3.5.0", "vaul": "^1.1.2", @@ -3380,6 +3382,15 @@ "assertion-error": "^2.0.1" } }, + "node_modules/@types/debug": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", + "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, "node_modules/@types/deep-eql": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", @@ -3391,9 +3402,26 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, "license": "MIT" }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -3401,6 +3429,21 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" + }, "node_modules/@types/node": { "version": "24.12.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.2.tgz", @@ -3414,7 +3457,6 @@ "version": "19.2.14", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", - "devOptional": true, "license": "MIT", "dependencies": { "csstype": "^3.2.2" @@ -3430,6 +3472,12 @@ "@types/react": "^19.2.0" } }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, "node_modules/@types/ws": { "version": "8.18.1", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", @@ -3734,6 +3782,12 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "license": "ISC" + }, "node_modules/@vitejs/plugin-react": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.1.tgz", @@ -3979,6 +4033,16 @@ "node": ">=12" } }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -4132,6 +4196,16 @@ ], "license": "CC-BY-4.0" }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/chai": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", @@ -4159,6 +4233,46 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/class-variance-authority": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", @@ -4200,6 +4314,16 @@ "dev": true, "license": "MIT" }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -4254,7 +4378,6 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "devOptional": true, "license": "MIT" }, "node_modules/data-urls": { @@ -4275,7 +4398,6 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -4296,6 +4418,19 @@ "dev": true, "license": "MIT" }, + "node_modules/decode-named-character-reference": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz", + "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==", + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -4307,7 +4442,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -4329,6 +4463,19 @@ "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", "license": "MIT" }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/dom-accessibility-api": { "version": "0.5.16", "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", @@ -4575,6 +4722,16 @@ "node": ">=4.0" } }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/estree-walker": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", @@ -4605,6 +4762,12 @@ "node": ">=12.0.0" } }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -4771,6 +4934,46 @@ "node": ">=8" } }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", + "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hermes-estree": { "version": "0.25.1", "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", @@ -4801,6 +5004,16 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, + "node_modules/html-url-attributes": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz", + "integrity": "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/iceberg-js": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/iceberg-js/-/iceberg-js-0.8.1.tgz", @@ -4857,6 +5070,46 @@ "node": ">=8" } }, + "node_modules/inline-style-parser": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", + "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", + "license": "MIT" + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -4880,6 +5133,28 @@ "node": ">=0.10.0" } }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", @@ -5331,6 +5606,16 @@ "dev": true, "license": "MIT" }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -5371,92 +5656,728 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, - "node_modules/mdn-data": { - "version": "2.27.1", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", - "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", - "dev": true, - "license": "CC0-1.0" + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", + "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "escape-string-regexp": "^5.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true, + "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", "license": "MIT", "engines": { - "node": ">=4" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" + "node_modules/mdast-util-from-markdown": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz", + "integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" }, - "engines": { - "node": "*" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "devOptional": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", + "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "license": "MIT" - }, - "node_modules/node-releases": { - "version": "2.0.37", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.37.tgz", - "integrity": "sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==", - "dev": true, - "license": "MIT" - }, - "node_modules/obug": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", - "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", - "dev": true, - "funding": [ - "https://github.com/sponsors/sxzz", - "https://opencollective.com/debug" - ], - "license": "MIT" + "node_modules/mdast-util-mdx-jsx": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", + "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-newline-to-break": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-newline-to-break/-/mdast-util-newline-to-break-2.0.0.tgz", + "integrity": "sha512-MbgeFca0hLYIEx/2zGsszCSEJJ1JSCdiY5xQxRcLDDGa8EPvlLPupJ4DSajbMPAnC0je8jfb9TiUATnxxrHUog==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-find-and-replace": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdn-data": { + "version": "2.27.1", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", + "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "devOptional": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.37", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.37.tgz", + "integrity": "sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==", + "dev": true, + "license": "MIT" + }, + "node_modules/obug": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT" + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, "license": "MIT", "dependencies": { "deep-is": "^0.1.3", @@ -5515,6 +6436,31 @@ "node": ">=6" } }, + "node_modules/parse-entities": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" + }, "node_modules/parse5": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz", @@ -5688,6 +6634,16 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/property-information": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -5868,6 +6824,33 @@ "license": "MIT", "peer": true }, + "node_modules/react-markdown": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-10.1.0.tgz", + "integrity": "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "html-url-attributes": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "unified": "^11.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=18", + "react": ">=18" + } + }, "node_modules/react-remove-scroll": { "version": "2.7.2", "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz", @@ -5951,6 +6934,54 @@ "node": ">=8" } }, + "node_modules/remark-breaks": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-breaks/-/remark-breaks-4.0.0.tgz", + "integrity": "sha512-IjEjJOkH4FuJvHZVIW0QCDWxcG96kCq7An/KVH2NfJe6rKZU2AsHeB3OEjPNRxi4QC34Xdx7I2KGYn6IpT7gxQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-newline-to-break": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", + "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -6091,6 +7122,16 @@ "node": ">=0.10.0" } }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/stackback": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", @@ -6105,6 +7146,20 @@ "dev": true, "license": "MIT" }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/strip-indent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", @@ -6131,6 +7186,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/style-to-js": { + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz", + "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==", + "license": "MIT", + "dependencies": { + "style-to-object": "1.0.14" + } + }, + "node_modules/style-to-object": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz", + "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==", + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.2.7" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -6272,6 +7345,26 @@ "node": ">=20" } }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/ts-api-utils": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", @@ -6358,6 +7451,93 @@ "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", "license": "MIT" }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/update-browserslist-db": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", @@ -6464,6 +7644,34 @@ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc" } }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/vite": { "version": "8.0.8", "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.8.tgz", @@ -6832,6 +8040,16 @@ "optional": true } } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } } } } diff --git a/package.json b/package.json index 71c49b1..5a8872f 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,8 @@ "radix-ui": "^1.4.3", "react": "^19.2.4", "react-dom": "^19.2.4", + "react-markdown": "^10.1.0", + "remark-breaks": "^4.0.0", "sonner": "^2.0.7", "tailwind-merge": "^3.5.0", "vaul": "^1.1.2", diff --git a/src/components/ClientTransitionOverlay.tsx b/src/components/ClientTransitionOverlay.tsx index d2d5f46..73fb5c6 100644 --- a/src/components/ClientTransitionOverlay.tsx +++ b/src/components/ClientTransitionOverlay.tsx @@ -1,20 +1,20 @@ -import React, { useEffect, useRef, useState } from 'react' +import { useEffect, useRef, useState } from "react"; // --- TIPO DAS PROPS --- interface ClientTransitionOverlayProps { - clientName: string - onComplete: () => void + clientName: string; + onComplete: () => void; } const MESSAGES = [ - '🛂 Verificando credenciais', - '🎫 Confirmando embarque', - '🛫 Autorização de torre', - '✈️ Em rota de cruzeiro', -] + "🛂 Verificando credenciais", + "🎫 Confirmando embarque", + "🛫 Autorização de torre", + "✈️ Em rota de cruzeiro", +]; -const TOTAL_MS = 3200 // Transição mais rápida (reduzida de 4600ms para 3200ms) -const MSG_INTERVAL = TOTAL_MS / MESSAGES.length +const TOTAL_MS = 3200; // Transição mais rápida (reduzida de 4600ms para 3200ms) +const MSG_INTERVAL = TOTAL_MS / MESSAGES.length; // Nuvens com posições e velocidades otimizadas para fluir da direita para a esquerda const CLOUDS = [ @@ -24,24 +24,33 @@ const CLOUDS = [ { top: 45, size: 400, opacity: 0.3, duration: 40, delay: -15 }, { top: 10, size: 150, opacity: 0.5, duration: 25, delay: -2 }, { top: 60, size: 350, opacity: 0.2, duration: 60, delay: -30 }, -] +]; // --- COMPONENTES AUXILIARES --- function NoiseOverlay() { return (
- + - +
- ) + ); } -function Cloud({ top, size, opacity, duration, delay }: typeof CLOUDS[0]) { +function Cloud({ top, size, opacity, duration, delay }: (typeof CLOUDS)[0]) { return (
- ) + ); } function PlaneIcon() { return ( - - + + {/* Fuselagem */} - + {/* Asa Principal */} - - + + {/* Asa Traseira */} - - + + {/* Cockpit Window */} - + - ) + ); } +const BARCODE_BARS = Array.from({ length: 32 }).map((_, i) => { + // deterministic pseudo-random based on index to avoid impure render + const seed = Math.sin(i * 9301 + 49297) * 233280; + const r1 = seed - Math.floor(seed); + const seed2 = Math.sin(i * 4321 + 12345) * 233280; + const r2 = seed2 - Math.floor(seed2); + return { + width: r1 > 0.6 ? "3px" : "1.5px", + height: `${40 + r2 * 60}%`, + }; +}); + function Barcode() { - const bars = React.useMemo(() => { - return Array.from({ length: 32 }).map(() => ({ - width: Math.random() > 0.6 ? '3px' : '1.5px', - height: `${40 + Math.random() * 60}%`, - })) - }, []) + const bars = BARCODE_BARS; return (
@@ -92,51 +137,56 @@ function Barcode() {
))}
- ) + ); } // --- COMPONENTE PRINCIPAL --- -export function ClientTransitionOverlay({ clientName, onComplete }: ClientTransitionOverlayProps) { - const [messageIndex, setMessageIndex] = useState(0) - const [msgOut, setMsgOut] = useState(false) - const [visible, setVisible] = useState(false) - - const onCompleteRef = useRef(onComplete) - onCompleteRef.current = onComplete +export function ClientTransitionOverlay({ + clientName, + onComplete, +}: ClientTransitionOverlayProps) { + const [messageIndex, setMessageIndex] = useState(0); + const [msgOut, setMsgOut] = useState(false); + const [visible, setVisible] = useState(false); + + const onCompleteRef = useRef(onComplete); + useEffect(() => { + onCompleteRef.current = onComplete; + }); useEffect(() => { // Pequeno delay para garantir que a animação de entrada seja vista - const showTimer = setTimeout(() => setVisible(true), 50) + const showTimer = setTimeout(() => setVisible(true), 50); - let current = 0 + let current = 0; const msgInterval = setInterval(() => { - setMsgOut(true) + setMsgOut(true); setTimeout(() => { - current = (current + 1) % MESSAGES.length - setMessageIndex(current) - setMsgOut(false) - }, 300) // Fade out do texto mais rápido - }, MSG_INTERVAL) + current = (current + 1) % MESSAGES.length; + setMessageIndex(current); + setMsgOut(false); + }, 300); // Fade out do texto mais rápido + }, MSG_INTERVAL); const fadeOutTimer = setTimeout(() => { - setVisible(false) - setTimeout(() => onCompleteRef.current(), 600) // Fade global mais ágil - }, TOTAL_MS) + setVisible(false); + setTimeout(() => onCompleteRef.current(), 600); // Fade global mais ágil + }, TOTAL_MS); return () => { - clearTimeout(showTimer) - clearInterval(msgInterval) - clearTimeout(fadeOutTimer) - } - }, []) + clearTimeout(showTimer); + clearInterval(msgInterval); + clearTimeout(fadeOutTimer); + }; + }, []); return (
@@ -145,7 +195,8 @@ export function ClientTransitionOverlay({ clientName, onComplete }: ClientTransi
@@ -159,9 +210,12 @@ export function ClientTransitionOverlay({ clientName, onComplete }: ClientTransi {/* Linha Central da Pista Animada */}
- {Array.from({ length: 30 }).map((_, i) => ( -
- ))} + {Array.from({ length: 30 }).map((_, i) => ( +
+ ))}
@@ -170,10 +224,10 @@ export function ClientTransitionOverlay({ clientName, onComplete }: ClientTransi
@@ -184,19 +238,31 @@ export function ClientTransitionOverlay({ clientName, onComplete }: ClientTransi className="ct-ticket relative z-20 w-[360px] max-w-[90vw] bg-white dark:bg-zinc-900 text-zinc-900 dark:text-zinc-100 shadow-[0_20px_60px_-15px_rgba(0,0,0,0.2)] dark:shadow-[0_20px_60px_-15px_rgba(0,0,0,0.8)] border border-zinc-200 dark:border-zinc-800 -translate-y-8 flex flex-col" style={{ animation: visible - ? 'ct-card-enter 0.8s cubic-bezier(0.16, 1, 0.3, 1) forwards, ct-float 4s ease-in-out 0.8s infinite alternate' - : 'none', + ? "ct-card-enter 0.8s cubic-bezier(0.16, 1, 0.3, 1) forwards, ct-float 4s ease-in-out 0.8s infinite alternate" + : "none", opacity: 0, }} > {/* Topo do Ticket */}
- {/* Símbolo decorativo */} - - - - + {/* Símbolo decorativo */} + + + +
@@ -214,16 +280,24 @@ export function ClientTransitionOverlay({ clientName, onComplete }: ClientTransi

{clientName}

- +
-
-

Flight

-

NX-012

-
-
-

Gate

-

A-42

-
+
+

+ Flight +

+

+ NX-012 +

+
+
+

+ Gate +

+

+ A-42 +

+
@@ -240,8 +314,9 @@ export function ClientTransitionOverlay({ clientName, onComplete }: ClientTransi className="text-xs font-semibold tracking-wide text-zinc-600 dark:text-zinc-400 text-center uppercase" style={{ opacity: msgOut ? 0 : 1, - transform: msgOut ? 'translateY(-4px)' : 'translateY(0)', - transition: 'opacity 0.3s ease, transform 0.3s cubic-bezier(0.2, 0, 0.2, 1)', + transform: msgOut ? "translateY(-4px)" : "translateY(0)", + transition: + "opacity 0.3s ease, transform 0.3s cubic-bezier(0.2, 0, 0.2, 1)", }} > {MESSAGES[messageIndex]} @@ -311,31 +386,31 @@ export function ClientTransitionOverlay({ clientName, onComplete }: ClientTransi } `}
- ) + ); } // === COMPONENTE APP DE DEMONSTRAÇÃO (Apenas para o Preview) === export default function App() { - const [showOverlay, setShowOverlay] = useState(false) - const [isDarkMode, setIsDarkMode] = useState(false) + const [showOverlay, setShowOverlay] = useState(false); + const [isDarkMode, setIsDarkMode] = useState(false); // Injeta a classe dark no HTML para o Tailwind aplicar os estilos adaptáveis useEffect(() => { if (isDarkMode) { - document.documentElement.classList.add('dark') + document.documentElement.classList.add("dark"); } else { - document.documentElement.classList.remove('dark') + document.documentElement.classList.remove("dark"); } - }, [isDarkMode]) + }, [isDarkMode]); return (
-
@@ -359,5 +434,5 @@ export default function App() { /> )}
- ) -} \ No newline at end of file + ); +} diff --git a/src/components/NotificationBell.tsx b/src/components/NotificationBell.tsx index eaeba2d..7f1dd15 100644 --- a/src/components/NotificationBell.tsx +++ b/src/components/NotificationBell.tsx @@ -1,5 +1,7 @@ import { useState, useRef, useEffect, useMemo, useCallback } from 'react' -import { Bell, CheckCheck, User, Users } from 'lucide-react' +import ReactMarkdown from 'react-markdown' +import remarkBreaks from 'remark-breaks' +import { Bell, CheckCheck, UserCheck, UserX, ShieldCheck, ShieldOff, Megaphone, MessageSquare, ClipboardList } from 'lucide-react' import { DropdownMenu, DropdownMenuTrigger, @@ -74,6 +76,19 @@ function groupNotificationsByDate(notifications: Notification[]): Map + case 'step_unassigned': return + case 'role_changed': return + case 'client_access_granted': return + case 'client_access_revoked': return + case 'admin_broadcast': return + case 'manual': return + default: return + } +} + function playNotificationSound() { const audio = new Audio('/notification.mp3') audio.volume = 0.3 @@ -106,13 +121,8 @@ function NotificationItem({ notification.read ? 'hover:bg-muted/40' : 'bg-primary/5 hover:bg-primary/10' }`} > - {/* Ícone de audiência */} -
- {isPersonal ? : } +
+ {getNotificationTypeIcon(notification.type)}
@@ -125,9 +135,9 @@ function NotificationItem({
-

- {notification.message} -

+
+ {notification.message} +
Marcar como lidas @@ -294,6 +304,7 @@ export function NotificationBell({
{GROUP_LABELS[groupKey]}
+
{items.map((notification) => ( ))} +
) })} diff --git a/src/lib/notifications.ts b/src/lib/notifications.ts index a36b994..8e8f885 100644 --- a/src/lib/notifications.ts +++ b/src/lib/notifications.ts @@ -118,6 +118,26 @@ export async function createNotificationForClient( if (error) throw error } +export async function createNotificationForAll( + clientIds: string[], + title: string, + message: string, + type: string = 'admin_broadcast' +) { + if (!supabaseAdmin) throw new Error('Admin não configurado') + + const rows = clientIds.map((clientId) => ({ + client_id: clientId, + user_id: null, + title, + message, + type, + })) + + const { error } = await supabaseAdmin.from('notifications').insert(rows) + if (error) throw error +} + export function resolveNotificationRoute(notification: Notification): string | null { if (!notification.metadata) return null diff --git a/src/views/admin/components/NotificationsPanel.tsx b/src/views/admin/components/NotificationsPanel.tsx index 72315b6..2fe6a5d 100644 --- a/src/views/admin/components/NotificationsPanel.tsx +++ b/src/views/admin/components/NotificationsPanel.tsx @@ -1,9 +1,11 @@ import { useState, useCallback, useEffect, useMemo } from 'react' -import { Send, Users, Building2, Clock, AlertTriangle, RefreshCw, Eye, EyeOff } from 'lucide-react' +import { Send, Users, Building2, Globe, Clock, AlertTriangle, RefreshCw, Eye, EyeOff, UserCheck, UserX, ShieldCheck, ShieldOff, Megaphone, ClipboardList, MessageSquare } from 'lucide-react' +import ReactMarkdown from 'react-markdown' +import remarkBreaks from 'remark-breaks' import { Button, Input, Label } from '@/components/ui' import { toast } from 'sonner' import { supabaseAdmin } from '@/lib/supabase' -import { createNotification, createNotificationForClient, fetchAllNotifications, markAsRead as markAsReadApi } from '@/lib/notifications' +import { createNotification, createNotificationForClient, createNotificationForAll, fetchAllNotifications, markAsRead as markAsReadApi } from '@/lib/notifications' import type { Member } from '@/hooks/useSupabase' import type { Client } from '@/types/db' import type { Notification } from '@/types/notification' @@ -13,20 +15,27 @@ interface NotificationsPanelProps { users: Member[] } -type TargetType = 'user' | 'client' +type TargetType = 'user' | 'client' | 'all' function formatDate(dateString: string): string { try { - const date = new Date(dateString) - return date.toLocaleString('pt-BR', { - day: '2-digit', - month: '2-digit', - year: 'numeric', - hour: '2-digit', - minute: '2-digit', + return new Date(dateString).toLocaleString('pt-BR', { + day: '2-digit', month: '2-digit', year: 'numeric', + hour: '2-digit', minute: '2-digit', }) - } catch { - return '' + } catch { return '' } +} + +function getNotificationTypeIcon(type: string): React.ReactNode { + switch (type) { + case 'step_assigned': return + case 'step_unassigned': return + case 'role_changed': return + case 'client_access_granted': return + case 'client_access_revoked': return + case 'admin_broadcast': return + case 'manual': return + default: return } } @@ -43,82 +52,42 @@ function getNotificationTypeLabel(type: string): string { return labels[type] || type } -function isToday(dateString: string): boolean { - const date = new Date(dateString) - const today = new Date() - return date.toDateString() === today.toDateString() -} - -function isYesterday(dateString: string): boolean { - const date = new Date(dateString) - const yesterday = new Date() - yesterday.setDate(yesterday.getDate() - 1) - return date.toDateString() === yesterday.toDateString() -} - -function isLast7Days(dateString: string): boolean { - const date = new Date(dateString) - const today = new Date() - const diffDays = Math.floor((today.getTime() - date.getTime()) / (1000 * 60 * 60 * 24)) - return diffDays >= 1 && diffDays <= 7 +function isToday(d: string) { return new Date(d).toDateString() === new Date().toDateString() } +function isYesterday(d: string) { + const y = new Date(); y.setDate(y.getDate() - 1) + return new Date(d).toDateString() === y.toDateString() } - -interface GroupedNotifications { - today: Notification[] - yesterday: Notification[] - last7Days: Notification[] - older: Notification[] +function isLast7Days(d: string) { + const diff = Math.floor((Date.now() - new Date(d).getTime()) / 86400000) + return diff >= 1 && diff <= 7 } -function groupNotifications(notifications: Notification[]): GroupedNotifications { - const grouped: GroupedNotifications = { - today: [], - yesterday: [], - last7Days: [], - older: [], - } - - for (const notif of notifications) { - if (isToday(notif.created_at)) { - grouped.today.push(notif) - } else if (isYesterday(notif.created_at)) { - grouped.yesterday.push(notif) - } else if (isLast7Days(notif.created_at)) { - grouped.last7Days.push(notif) - } else { - grouped.older.push(notif) - } +function groupNotifications(notifications: Notification[]) { + const g = { today: [] as Notification[], yesterday: [] as Notification[], last7Days: [] as Notification[], older: [] as Notification[] } + for (const n of notifications) { + if (isToday(n.created_at)) g.today.push(n) + else if (isYesterday(n.created_at)) g.yesterday.push(n) + else if (isLast7Days(n.created_at)) g.last7Days.push(n) + else g.older.push(n) } - - return grouped + return g } -function NotificationList({ - notifications, - onMarkAsRead, - onToggleRead, -}: { +function NotificationList({ notifications, onMarkAsRead, onToggleRead }: { notifications: Notification[] onMarkAsRead: (id: string) => void onToggleRead?: (id: string) => void }) { if (notifications.length === 0) return null - return (
{notifications.map((notif) => ( -
+
+
{getNotificationTypeIcon(notif.type)}
- {!notif.read && ( - - )} - - {notif.title} - + {!notif.read && } + {notif.title} {getNotificationTypeLabel(notif.type)} @@ -128,26 +97,18 @@ function NotificationList({ )}
-

{notif.message}

- - {formatDate(notif.created_at)} - +
+ {notif.message} +
+ {formatDate(notif.created_at)}
{!notif.read ? ( - ) : onToggleRead ? ( - ) : null} @@ -162,9 +123,10 @@ export function NotificationsPanel({ clients, users }: NotificationsPanelProps) const [title, setTitle] = useState('') const [message, setMessage] = useState('') const [targetType, setTargetType] = useState('user') - const [selectedUserId, setSelectedUserId] = useState('') - const [selectedClientId, setSelectedClientId] = useState('') + const [selectedUserId, setSelectedUserId] = useState('') + const [selectedClientId, setSelectedClientId] = useState('') const [sending, setSending] = useState(false) + const [messageTab, setMessageTab] = useState<'edit' | 'preview'>('edit') const [history, setHistory] = useState([]) const [loadingHistory, setLoadingHistory] = useState(true) @@ -175,8 +137,7 @@ export function NotificationsPanel({ clients, users }: NotificationsPanelProps) setLoadingHistory(true) setError(null) try { - const data = await fetchAllNotifications() - setHistory(data) + setHistory(await fetchAllNotifications()) } catch (e) { setError(e instanceof Error ? e.message : 'Erro ao carregar') } finally { @@ -184,35 +145,30 @@ export function NotificationsPanel({ clients, users }: NotificationsPanelProps) } }, []) - useEffect(() => { - loadHistory() - }, [loadHistory]) + useEffect(() => { loadHistory() }, [loadHistory]) const grouped = useMemo(() => groupNotifications(history), [history]) const handleSend = async () => { - if (!title.trim() || !message.trim()) { - toast.error('Preencha o título e a mensagem') - return - } - - if (!supabaseAdmin) { - toast.error('Admin não configurado') - return - } + if (!title.trim() || !message.trim()) { toast.error('Preencha o título e a mensagem'); return } + if (!supabaseAdmin) { toast.error('Admin não configurado'); return } setSending(true) - try { if (targetType === 'user' && selectedUserId) { await createNotification(title, message, selectedUserId, undefined, 'manual') } else if (targetType === 'client' && selectedClientId) { await createNotificationForClient(selectedClientId, title, message) + } else if (targetType === 'all') { + await createNotificationForAll(clients.map((c) => c.id), title, message) + } else { + toast.error('Selecione um destino'); setSending(false); return } toast.success('Notificação enviada') setTitle('') setMessage('') + setMessageTab('edit') await loadHistory() } catch { toast.error('Erro ao enviar notificação') @@ -225,142 +181,155 @@ export function NotificationsPanel({ clients, users }: NotificationsPanelProps) try { await markAsReadApi(id) setHistory((prev) => prev.map((n) => (n.id === id ? { ...n, read: true } : n))) - } catch { - toast.error('Erro ao marcar como lida') - } + } catch { toast.error('Erro ao marcar como lida') } } const handleToggleRead = async (id: string) => { - const notification = history.find((n) => n.id === id) - if (!notification) return - try { await markAsReadApi(id) - setHistory((prev) => - prev.map((n) => (n.id === id ? { ...n, read: !n.read } : n)) - ) - } catch { - toast.error('Erro ao atualizar') - } + setHistory((prev) => prev.map((n) => (n.id === id ? { ...n, read: !n.read } : n))) + } catch { toast.error('Erro ao atualizar') } } const activeUsers = users.filter((u) => u.is_active !== false) - const hasNotifications = history.length > 0 + const targets: { key: TargetType; label: string; icon: React.ReactNode; description: string }[] = [ + { key: 'user', label: 'Usuário', icon: , description: 'Um membro específico' }, + { key: 'client', label: 'Cliente', icon: , description: 'Todos de um cliente' }, + { key: 'all', label: 'Todos', icon: , description: `${clients.length} clientes` }, + ] return ( -
-
+
+ {/* Formulário */} +
- -

Enviar Notificação

+ +

Enviar Notificação

-
-
- -
- + {/* Destino */} +
+ +
+ {targets.map((t) => ( -
+ ))}
+
- {targetType === 'user' && ( -
- - -
- )} - - {targetType === 'client' && ( -
- - -
- )} - + {/* Seletor condicional */} + {targetType === 'user' && (
- - setTitle(e.target.value)} - placeholder="Ex: Atualização importante" - /> + +
+ )} + {targetType === 'client' && (
+ + +
+ )} + + {targetType === 'all' && ( +
+ Será enviado como broadcast para todos os {clients.length} clientes cadastrados. +
+ )} + + {/* Título */} +
+ + setTitle(e.target.value)} placeholder="Ex: Atualização importante" /> +
+ + {/* Mensagem com tabs */} +
+
+
+ + +
+
+ {messageTab === 'edit' ? (