From 204a6f4038810c4256aa2f432ee5efc0b3c4d43e Mon Sep 17 00:00:00 2001 From: TheoForger Date: Wed, 2 Apr 2025 16:42:34 -0400 Subject: [PATCH 01/13] Update dependencies # Conflicts: # package-lock.json # package.json --- package-lock.json | 1473 +++++++++++++++++++++++++++++++-------------- package.json | 4 +- 2 files changed, 1007 insertions(+), 470 deletions(-) diff --git a/package-lock.json b/package-lock.json index d232126d..32935a65 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,10 +11,9 @@ "@authenio/samlify-node-xmllint": "^2.0.0", "@aws-sdk/client-route-53": "^3.777.0", "@chakra-ui/icons": "^2.2.6", - "@chakra-ui/react": "^2.10.7", + "@chakra-ui/react": "^3.15.0", "@emotion/react": "^11.14.0", "@emotion/server": "^11.11.0", - "@emotion/styled": "^11.14.0", "@prisma/client": "^6.5.0", "@remix-run/express": "2.16.4", "@remix-run/node": "2.16.4", @@ -29,7 +28,6 @@ "dayjs": "^1.11.13", "docker-secret": "^2.0.6", "express": "^4.21.2", - "framer-motion": "^12.6.3", "helmet": "^8.1.0", "http-graceful-shutdown": "^3.1.14", "ioredis": "^5.6.0", @@ -105,6 +103,72 @@ "node": ">=6.0.0" } }, + "node_modules/@ark-ui/react": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@ark-ui/react/-/react-5.4.0.tgz", + "integrity": "sha512-TatFGOb6zKx4a363jg3McQY+2/wEcUZgTHZTomueFMR+JgqHR98aAFnCPvi2L5UF+326qXEWHxHIPlQLwFUb1A==", + "license": "MIT", + "dependencies": { + "@internationalized/date": "3.7.0", + "@zag-js/accordion": "1.7.0", + "@zag-js/anatomy": "1.7.0", + "@zag-js/auto-resize": "1.7.0", + "@zag-js/avatar": "1.7.0", + "@zag-js/carousel": "1.7.0", + "@zag-js/checkbox": "1.7.0", + "@zag-js/clipboard": "1.7.0", + "@zag-js/collapsible": "1.7.0", + "@zag-js/collection": "1.7.0", + "@zag-js/color-picker": "1.7.0", + "@zag-js/color-utils": "1.7.0", + "@zag-js/combobox": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/date-picker": "1.7.0", + "@zag-js/date-utils": "1.7.0", + "@zag-js/dialog": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/editable": "1.7.0", + "@zag-js/file-upload": "1.7.0", + "@zag-js/file-utils": "1.7.0", + "@zag-js/focus-trap": "1.7.0", + "@zag-js/highlight-word": "1.7.0", + "@zag-js/hover-card": "1.7.0", + "@zag-js/i18n-utils": "1.7.0", + "@zag-js/menu": "1.7.0", + "@zag-js/number-input": "1.7.0", + "@zag-js/pagination": "1.7.0", + "@zag-js/pin-input": "1.7.0", + "@zag-js/popover": "1.7.0", + "@zag-js/presence": "1.7.0", + "@zag-js/progress": "1.7.0", + "@zag-js/qr-code": "1.7.0", + "@zag-js/radio-group": "1.7.0", + "@zag-js/rating-group": "1.7.0", + "@zag-js/react": "1.7.0", + "@zag-js/select": "1.7.0", + "@zag-js/signature-pad": "1.7.0", + "@zag-js/slider": "1.7.0", + "@zag-js/splitter": "1.7.0", + "@zag-js/steps": "1.7.0", + "@zag-js/switch": "1.7.0", + "@zag-js/tabs": "1.7.0", + "@zag-js/tags-input": "1.7.0", + "@zag-js/time-picker": "1.7.0", + "@zag-js/timer": "1.7.0", + "@zag-js/toast": "1.7.0", + "@zag-js/toggle": "1.7.0", + "@zag-js/toggle-group": "1.7.0", + "@zag-js/tooltip": "1.7.0", + "@zag-js/tour": "1.7.0", + "@zag-js/tree-view": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, "node_modules/@authenio/samlify-node-xmllint": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@authenio/samlify-node-xmllint/-/samlify-node-xmllint-2.0.0.tgz", @@ -2540,27 +2604,6 @@ "node": ">=6.9.0" } }, - "node_modules/@chakra-ui/anatomy": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/@chakra-ui/anatomy/-/anatomy-2.3.6.tgz", - "integrity": "sha512-TjmjyQouIZzha/l8JxdBZN1pKZTj7sLpJ0YkFnQFyqHcbfWggW9jKWzY1E0VBnhtFz/xF3KC6UAVuZVSJx+y0g==", - "license": "MIT" - }, - "node_modules/@chakra-ui/hooks": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/@chakra-ui/hooks/-/hooks-2.4.4.tgz", - "integrity": "sha512-+gMwLIkabtddIL/GICU7JmnYtvfONP+fNiTfdYLV9/I1eyCz8igKgLmFJOGM6F+BpUev6hh+/+DX5ezGQ9VTbQ==", - "license": "MIT", - "dependencies": { - "@chakra-ui/utils": "2.2.4", - "@zag-js/element-size": "0.31.1", - "copy-to-clipboard": "3.3.3", - "framesync": "6.1.2" - }, - "peerDependencies": { - "react": ">=18" - } - }, "node_modules/@chakra-ui/icons": { "version": "2.2.6", "resolved": "https://registry.npmjs.org/@chakra-ui/icons/-/icons-2.2.6.tgz", @@ -2572,81 +2615,26 @@ } }, "node_modules/@chakra-ui/react": { - "version": "2.10.7", - "resolved": "https://registry.npmjs.org/@chakra-ui/react/-/react-2.10.7.tgz", - "integrity": "sha512-GX1dCmnvrxxyZEofDX9GMAtRakZJKnUqFM9k8qhaycPaeyfkiTNNTjhPNX917hgVx1yhC3kcJOs5IeC7yW56/g==", - "license": "MIT", - "dependencies": { - "@chakra-ui/hooks": "2.4.4", - "@chakra-ui/styled-system": "2.12.2", - "@chakra-ui/theme": "3.4.8", - "@chakra-ui/utils": "2.2.4", - "@popperjs/core": "^2.11.8", - "@zag-js/focus-visible": "^0.31.1", - "aria-hidden": "^1.2.3", - "react-fast-compare": "3.2.2", - "react-focus-lock": "^2.9.6", - "react-remove-scroll": "^2.5.7" + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/@chakra-ui/react/-/react-3.15.0.tgz", + "integrity": "sha512-U7mR9ru5Vhpat57nP04lenVDtaMzPKfKedhBDkesk5VUbzr5euWygjspa/tTO37ew7t7Q/pyUovXAizoWEzZ1g==", + "license": "MIT", + "dependencies": { + "@ark-ui/react": "5.4.0", + "@emotion/is-prop-valid": "1.3.1", + "@emotion/serialize": "1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "1.2.0", + "@emotion/utils": "1.4.2", + "@pandacss/is-valid-prop": "0.41.0", + "csstype": "3.1.3", + "fast-safe-stringify": "2.1.1" }, "peerDependencies": { "@emotion/react": ">=11", - "@emotion/styled": ">=11", - "framer-motion": ">=4.0.0", "react": ">=18", "react-dom": ">=18" } }, - "node_modules/@chakra-ui/styled-system": { - "version": "2.12.2", - "resolved": "https://registry.npmjs.org/@chakra-ui/styled-system/-/styled-system-2.12.2.tgz", - "integrity": "sha512-BlQ7i3+GYC0S0c72B+paa0sYo+QeNSMfz6fwQRFsc8A5Aax9i9lSdRL+vwJVC+k6r/0HWfRwk016R2RD2ihEwQ==", - "license": "MIT", - "dependencies": { - "@chakra-ui/utils": "2.2.4", - "csstype": "^3.1.2" - } - }, - "node_modules/@chakra-ui/theme": { - "version": "3.4.8", - "resolved": "https://registry.npmjs.org/@chakra-ui/theme/-/theme-3.4.8.tgz", - "integrity": "sha512-ZLMP2Gek38ZTIlj+sMZLsd1TW27yVdmUKMfBmjsr1psAeOa5bDBLKDszICjhEqk7gAbiWB7jr1/HzBXid4kduQ==", - "license": "MIT", - "dependencies": { - "@chakra-ui/anatomy": "2.3.6", - "@chakra-ui/theme-tools": "2.2.8", - "@chakra-ui/utils": "2.2.4" - }, - "peerDependencies": { - "@chakra-ui/styled-system": ">=2.8.0" - } - }, - "node_modules/@chakra-ui/theme-tools": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/@chakra-ui/theme-tools/-/theme-tools-2.2.8.tgz", - "integrity": "sha512-X2i2qgkG+k3DQfh/adn3zzM4Ty8QrGobVPjMl9rMrEYq3ac+pur6KVdVHy/SwwoPvB6S4i84uq7y35+KbJan9g==", - "license": "MIT", - "dependencies": { - "@chakra-ui/anatomy": "2.3.6", - "@chakra-ui/utils": "2.2.4", - "color2k": "^2.0.2" - }, - "peerDependencies": { - "@chakra-ui/styled-system": ">=2.0.0" - } - }, - "node_modules/@chakra-ui/utils": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@chakra-ui/utils/-/utils-2.2.4.tgz", - "integrity": "sha512-nRpR9SnX7aLcJx7lKu8kgQWxdJso1oR/78HcBI+mzidvWdTykbTGdm5Q2R7S0PVH1IFBzBTgi6TiAjHvu96auA==", - "license": "MIT", - "dependencies": { - "@types/lodash.mergewith": "4.6.9", - "lodash.mergewith": "4.6.2" - }, - "peerDependencies": { - "react": ">=16.8.0" - } - }, "node_modules/@colors/colors": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", @@ -2817,29 +2805,6 @@ "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==", "license": "MIT" }, - "node_modules/@emotion/styled": { - "version": "11.14.0", - "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.0.tgz", - "integrity": "sha512-XxfOnXFffatap2IyCeJyNov3kiDQWoR08gPUQxvbL7fxKryGBKUZUkG6Hz48DZwVrJSVh9sJboyV1Ds4OW6SgA==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.18.3", - "@emotion/babel-plugin": "^11.13.5", - "@emotion/is-prop-valid": "^1.3.0", - "@emotion/serialize": "^1.3.3", - "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", - "@emotion/utils": "^1.4.2" - }, - "peerDependencies": { - "@emotion/react": "^11.0.0-rc.0", - "react": ">=16.8.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, "node_modules/@emotion/unitless": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz", @@ -3448,6 +3413,31 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@floating-ui/core": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.9.tgz", + "integrity": "sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.9" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.13", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.13.tgz", + "integrity": "sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.9" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz", + "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==", + "license": "MIT" + }, "node_modules/@hapi/hoek": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", @@ -3531,6 +3521,24 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@internationalized/date": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.7.0.tgz", + "integrity": "sha512-VJ5WS3fcVx0bejE/YHfbDKR/yawZgKqn/if+oEeLqNwBtPzVB06olkfcnojTmEMX+gTpH+FlQ69SHNitJ8/erQ==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@internationalized/number": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.6.0.tgz", + "integrity": "sha512-PtrRcJVy7nw++wn4W2OuePQQfTqDzfusSuY1QTtui4wa7r+rGVtR75pO8CyKvHvzyQYi3Q1uO5sY0AsB4e65Bw==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, "node_modules/@ioredis/commands": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", @@ -4051,6 +4059,11 @@ "win32" ] }, + "node_modules/@pandacss/is-valid-prop": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@pandacss/is-valid-prop/-/is-valid-prop-0.41.0.tgz", + "integrity": "sha512-BE6h6CsJk14ugIRrsazJtN3fcg+KDFRat1Bs93YFKH6jd4DOb1yUyVvC70jKqPVvg70zEcV8acZ7VdcU5TLu+w==" + }, "node_modules/@peculiar/asn1-cms": { "version": "2.3.15", "resolved": "https://registry.npmjs.org/@peculiar/asn1-cms/-/asn1-cms-2.3.15.tgz", @@ -4223,16 +4236,6 @@ "node": ">=18" } }, - "node_modules/@popperjs/core": { - "version": "2.11.8", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", - "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" - } - }, "node_modules/@prisma/client": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.5.0.tgz", @@ -5678,6 +5681,15 @@ "node": ">=18.0.0" } }, + "node_modules/@swc/helpers": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", + "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, "node_modules/@tybys/wasm-util": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", @@ -5934,21 +5946,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/lodash": { - "version": "4.17.16", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.16.tgz", - "integrity": "sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==", - "license": "MIT" - }, - "node_modules/@types/lodash.mergewith": { - "version": "4.6.9", - "resolved": "https://registry.npmjs.org/@types/lodash.mergewith/-/lodash.mergewith-4.6.9.tgz", - "integrity": "sha512-fgkoCAOF47K7sxrQ7Mlud2TH023itugZs2bUg8h/KzT+BnZNrR2jAOmaokbLunHNnobXVWOezAeNn/lZqwxkcw==", - "license": "MIT", - "dependencies": { - "@types/lodash": "*" - } - }, "node_modules/@types/mdast": { "version": "3.0.15", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", @@ -7151,98 +7148,867 @@ "integrity": "sha512-KHBC7z61OJeaMGnF3wqNZj+GGNXOyypZviiKpQeiHirG5Ib1ImwcLBH70rbMSkKfSmUNBsdf2PwaEJtKvgmkNw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@vitest/snapshot": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.34.6.tgz", + "integrity": "sha512-B3OZqYn6k4VaN011D+ve+AA4whM4QkcwcrwaKwAbyyvS/NB1hCWjFIBQxAQQSQir9/RtyAAGuq+4RJmbn2dH4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "magic-string": "^0.30.1", + "pathe": "^1.1.1", + "pretty-format": "^29.5.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.6.tgz", + "integrity": "sha512-xaCvneSaeBw/cz8ySmF7ZwGvL0lBjfvqc1LpQ/vcdHEvpLn3Ff1vAvjw+CoGn0802l++5L/pxb7whwcWAw+DUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^2.1.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.6.tgz", + "integrity": "sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "diff-sequences": "^29.4.3", + "loupe": "^2.3.6", + "pretty-format": "^29.5.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@web3-storage/multipart-parser": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@web3-storage/multipart-parser/-/multipart-parser-1.0.0.tgz", + "integrity": "sha512-BEO6al7BYqcnfX15W2cnGR+Q566ACXAT9UQykORCWW80lmkpWsnEob6zJS1ZVBKsSJC8+7vJkHwlp+lXG1UCdw==", + "license": "(Apache-2.0 AND MIT)" + }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", + "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@xobotyi/scrollbar-width": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz", + "integrity": "sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==", + "license": "MIT" + }, + "node_modules/@zag-js/accordion": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/accordion/-/accordion-1.7.0.tgz", + "integrity": "sha512-LNJOjLTW2KwrToXBrXIbNIAiISA94n0AdWp14H8RrskdokywmEGiC0GgWTGEJ7DNA6TGP6Ae5o9rJ4fHSmCsDQ==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/anatomy": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/anatomy/-/anatomy-1.7.0.tgz", + "integrity": "sha512-fkRgH6vPCwykmRdV38uAJeTtJc8tayAnURfoovHAtB9bK0goagPbpdcYTNyGn8msul0h+KBloOtnw4obvX0nPw==", + "license": "MIT" + }, + "node_modules/@zag-js/aria-hidden": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/aria-hidden/-/aria-hidden-1.7.0.tgz", + "integrity": "sha512-YNbACFZoqw/1JymxCZXtuAFdeYZm7sK3E0jv3bPbqytPj7TziLa1dRDWDdx8cPcu0B4n4WrBMBSCGUjj/nWDCA==", + "license": "MIT" + }, + "node_modules/@zag-js/auto-resize": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/auto-resize/-/auto-resize-1.7.0.tgz", + "integrity": "sha512-ifWflzZc1fNJ+XUZaYpB220AiAr4l3Eczq8ELwj/ugg7T/10Wo0FkxTCVmCZfIiCMoqHuh/2oTX3PCTIwg6uxg==", + "license": "MIT", + "dependencies": { + "@zag-js/dom-query": "1.7.0" + } + }, + "node_modules/@zag-js/avatar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/avatar/-/avatar-1.7.0.tgz", + "integrity": "sha512-vzMCMpYIM2BIvPvK34VaRMUsUSpg3jwoxCzA31k+QrCmjm3ti8pLoT4waE01XHiaQwNPcTFbMWUi/nIQQKG14A==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/carousel": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/carousel/-/carousel-1.7.0.tgz", + "integrity": "sha512-bSbo00J7/4EhXKluQnCmH3dg+GjsI1dcogMNtY3Qe/hTUJI9F8ygXHWzkbEqe2iY8JkBucRm+IVdlAOGAjVARQ==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/scroll-snap": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/checkbox": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/checkbox/-/checkbox-1.7.0.tgz", + "integrity": "sha512-zhisqMrgKZNHyb5n4xN5JYdPU8P+duPJfy18SiHRMghi7rJrfnQZ/Ec+uEih1cGhu85juco5k9ud/AiT7bD6MA==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/focus-visible": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/clipboard": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/clipboard/-/clipboard-1.7.0.tgz", + "integrity": "sha512-rPLoIE7zKBRiHwAzSu/hT21ICMP7TmSWZGvCPV0hjtAE/sFAf/rsEwcx2DT3uBhUtoFQR7tqNRn4CnIGWkr2Fg==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/collapsible": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/collapsible/-/collapsible-1.7.0.tgz", + "integrity": "sha512-W6+3tAC/ilU/ffCLhdJ2bMMTuZSgHnCaLMQemUUS4kMLKUyEdXTqxKzaTEqcBQfHotsYLQUfrK57hoiAKE/UgA==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/collection": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/collection/-/collection-1.7.0.tgz", + "integrity": "sha512-gH7I03ag2niEhCVgNpXBYybnIROGXmAkX+5e1rYQ60mOh2oQnK+5k9k3DRkca5rAKbu4uT6JjYFwnY9sA/NZfA==", + "license": "MIT", + "dependencies": { + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/color-picker": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/color-picker/-/color-picker-1.7.0.tgz", + "integrity": "sha512-t439DB6EUrcj4f+MsLOIpttr3hsP4j3OgznJwSlwWt7Wsyhu9uX7cyevA56w4L4nt7lD1AP7305eN6AnILakjg==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/color-utils": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dismissable": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/popper": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/color-utils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/color-utils/-/color-utils-1.7.0.tgz", + "integrity": "sha512-OvBr4v0x7/Hkts4NFychApkSoV0kDuLhRdcjm1DcHbX5DBGlptnDqGZaswbs5KMYXXH23HDgnBRWmnvmfmGDkg==", + "license": "MIT", + "dependencies": { + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/combobox": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/combobox/-/combobox-1.7.0.tgz", + "integrity": "sha512-kaMvGoBZwiFC9KaUbHXNFkneg7grZmJlteVxk6kJXYd7JGDHhhYsFznPNIC0apvBCIEqwyBGVB/lCjK+BseZtw==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/aria-hidden": "1.7.0", + "@zag-js/collection": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dismissable": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/popper": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/core": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/core/-/core-1.7.0.tgz", + "integrity": "sha512-FyK1POPqgBp7DBpUIwvmBQH16+L52NaTaQJzg8iTI9mI/4m3AxZ5aN+8a8qzwGIkVI6rlDcrBkmuOcHDVIOEGA==", + "license": "MIT", + "dependencies": { + "@zag-js/dom-query": "1.7.0", + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/date-picker": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/date-picker/-/date-picker-1.7.0.tgz", + "integrity": "sha512-64UEmdN74I4aOPS1+7zNSl0VHzUIVLDfgXw0QZ24miMM+SYVcZ1+KSVI4yeS4SETwGpdm9YkvN4z3guCtwcS+w==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/date-utils": "1.7.0", + "@zag-js/dismissable": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/live-region": "1.7.0", + "@zag-js/popper": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + }, + "peerDependencies": { + "@internationalized/date": ">=3.0.0" + } + }, + "node_modules/@zag-js/date-utils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/date-utils/-/date-utils-1.7.0.tgz", + "integrity": "sha512-zZHFx3ZuIHB38qTQzG9/frj9nFLE3JUwMkiueIVdPEgaRl7Tx5VZ3NcDKXQn9ebmXi/Zk9YOAUBr7aGXBBOAcA==", + "license": "MIT", + "peerDependencies": { + "@internationalized/date": ">=3.0.0" + } + }, + "node_modules/@zag-js/dialog": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/dialog/-/dialog-1.7.0.tgz", + "integrity": "sha512-gx/CtKsPg/Y+2d+HtP3tjEdl7KM+x6lUDttjDDBn9rvXFs2REW69AlcJtRzs6B22CxDPmxssGPr1oi3zaU1AUA==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/aria-hidden": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dismissable": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/focus-trap": "1.7.0", + "@zag-js/remove-scroll": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/dismissable": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/dismissable/-/dismissable-1.7.0.tgz", + "integrity": "sha512-o6S++e7iaBmizIgsvLt5RwY7gn2OQGeG2etet+oaUAMtNhi/1+uGG+rTZgOMj/MGg9BYpPld5tXfk/RrlShh9Q==", + "license": "MIT", + "dependencies": { + "@zag-js/dom-query": "1.7.0", + "@zag-js/interact-outside": "1.7.0", + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/dom-query": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.7.0.tgz", + "integrity": "sha512-cj+mKB7Sj7mqAepHMsbV4bGvDJfUYCt4d4ruYw0dVpDa1Z9N38TtztTznfrm9kuqOYcJkgE0q3Rn/kPLi8rK8g==", + "license": "MIT", + "dependencies": { + "@zag-js/types": "1.7.0" + } + }, + "node_modules/@zag-js/editable": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/editable/-/editable-1.7.0.tgz", + "integrity": "sha512-tNRDr95B+mFLk6Z8Fh0+BiDiCWsUt1iR0pIjFy88Y4YjGYd8Q71yNt1SLNKTD3DZnDGmlbRUB/4CaP+jso4aYQ==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/interact-outside": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/element-rect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/element-rect/-/element-rect-1.7.0.tgz", + "integrity": "sha512-j0h1+DASUI5urwBCELdjfk4oekLQ0D2v3a1wQJopGh+ITRVAC1gE1YFx3O+vnP2HwqANxG4+RQHwoQBM2bMBCQ==", + "license": "MIT" + }, + "node_modules/@zag-js/element-size": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/element-size/-/element-size-1.7.0.tgz", + "integrity": "sha512-Nq+HxG64Ts1QvaJPeDuy8zo/RqcbE95RPNVuHBwuxK3sbXOt7umgIrxQMp8uH+1xeJlp7F8/ydKOPyKOTtgiJg==", + "license": "MIT" + }, + "node_modules/@zag-js/file-upload": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/file-upload/-/file-upload-1.7.0.tgz", + "integrity": "sha512-6yJhUDLYsqbd0YBO70PzMDNVJJv8OdC0ZWrf51GMUSugGfSpvQZNDfpAW5Zkzqd4B5nkJDw5KiTSR5NYQlO7VA==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/file-utils": "1.7.0", + "@zag-js/i18n-utils": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/file-utils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/file-utils/-/file-utils-1.7.0.tgz", + "integrity": "sha512-Wb1VoI7UquG1ckJPMFPnmgLg351NI55SXjsEq+CrqgKQCo0httYFLPlkOpp4AbGsoUFZxXRxEXDEVzq5kpPFzQ==", + "license": "MIT", + "dependencies": { + "@zag-js/i18n-utils": "1.7.0" + } + }, + "node_modules/@zag-js/focus-trap": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/focus-trap/-/focus-trap-1.7.0.tgz", + "integrity": "sha512-JHMZAfiL1aoxMAQGolx+iDMgqOMy067yffaLr1tMX55NGZPfEyXEjgxmPXRPf728/7IOShLkWLX17yacmW/w/Q==", + "license": "MIT", + "dependencies": { + "@zag-js/dom-query": "1.7.0" + } + }, + "node_modules/@zag-js/focus-visible": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/focus-visible/-/focus-visible-1.7.0.tgz", + "integrity": "sha512-ycrO6VetctoA7aaw83rnp3erDmQe2Zsyobzp4fzpMbOBTNWzMklt4Kz54xa1ntkia8CpSWVfoauORLlaZoDiAw==", + "license": "MIT", + "dependencies": { + "@zag-js/dom-query": "1.7.0" + } + }, + "node_modules/@zag-js/highlight-word": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/highlight-word/-/highlight-word-1.7.0.tgz", + "integrity": "sha512-dRw9GbMTh+CKKA4dH6n2TEmaayH2cB5Otnaawm+o+q3gkioVij8V/owWFbMZrszW6ajJX/TTdsVJ5IBdPvKhKg==", + "license": "MIT" + }, + "node_modules/@zag-js/hover-card": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/hover-card/-/hover-card-1.7.0.tgz", + "integrity": "sha512-MqrLet1qaJfc2MEvHUWGLQ1OxgTz73gAD7oWXxnxks2Q/BXow2jU3+fVdseg3G63bmUbHXSdOkyGNo0mpHCV3Q==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dismissable": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/popper": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/i18n-utils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/i18n-utils/-/i18n-utils-1.7.0.tgz", + "integrity": "sha512-CcDXxfobG2LlOU1m3xPzV5pXpCe0tSE9u+drtKMz7F/HOZkR3V0rpCCi/zKySPNa3uLC7G8efz1fGQXiOVKONw==", + "license": "MIT", + "dependencies": { + "@zag-js/dom-query": "1.7.0" + } + }, + "node_modules/@zag-js/interact-outside": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/interact-outside/-/interact-outside-1.7.0.tgz", + "integrity": "sha512-tmsVQmcH2N2X2mG2/8/+WRIo9WbRVvLe1OZa3lzFYV4Mu5i+tNK1CHMESpoAd/RdjJ6AyTR2zYiH05WZe76gMw==", + "license": "MIT", + "dependencies": { + "@zag-js/dom-query": "1.7.0", + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/live-region": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/live-region/-/live-region-1.7.0.tgz", + "integrity": "sha512-u2bYIAnBIY+GZqfPqxn2ZylOqE2blUVW7Yc2Z4Ey05K4JXSH2gKR3xPmJCS9/u8tcFKQz5L4KQ/98ntgBG2fGQ==", + "license": "MIT" + }, + "node_modules/@zag-js/menu": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/menu/-/menu-1.7.0.tgz", + "integrity": "sha512-F2XbPC0cWrmj7nLrs1/is2osaPYX9blhEiZuEcGSrWG00w6xWyPb7bFpccW2nbq87JEc58xzW1pnTzPnaAnwSQ==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dismissable": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/popper": "1.7.0", + "@zag-js/rect-utils": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/number-input": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/number-input/-/number-input-1.7.0.tgz", + "integrity": "sha512-zmStn38lscmSsX/P6hZQzan35nEstVmEGC6M3m5G+bzDRC+IR3h19yr1Ma+xXDkT1Vi21GaV0+rytf9WsYJg6Q==", + "license": "MIT", + "dependencies": { + "@internationalized/number": "3.6.0", + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/pagination": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/pagination/-/pagination-1.7.0.tgz", + "integrity": "sha512-gIbJe1fIYlQCpXqWssET9CCmMWLvcz8OCCw7W3ASeLYRvUW3IzhkMAht5pEsvJEZ9tIWaab5fZ7OLqcgCTgVQw==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/pin-input": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/pin-input/-/pin-input-1.7.0.tgz", + "integrity": "sha512-iQfUNfbtq28zPzFjmzDs7otRbFr+kC6luQM33wALZpmmVBNXb7yi9W6R14V6NJI3to6cAaHzRzn3ixxfQJEB3w==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/popover": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/popover/-/popover-1.7.0.tgz", + "integrity": "sha512-Nf9grOVBWlnwQL+AR6X2hAy5bTNQng9xG2Cfo4E8rD2G/CJLKtUGCHHkG8xeQ969HT4urbOrgrZ5UpAhkpNlmw==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/aria-hidden": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dismissable": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/focus-trap": "1.7.0", + "@zag-js/popper": "1.7.0", + "@zag-js/remove-scroll": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/popper": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/popper/-/popper-1.7.0.tgz", + "integrity": "sha512-1Tr9ZBS2VPeZ/zeAR5uEBYLkWn4VcycbaDDkvWxa44fi6LxknDf064cP+ql9AfUp/eUGD2hN9OSEhyxB/JXjKQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "1.6.13", + "@zag-js/dom-query": "1.7.0", + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/presence": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/presence/-/presence-1.7.0.tgz", + "integrity": "sha512-00YcVn3J0zwQ/DSEnbtbCx6UMokHXTiMF+CjNryPaaAOlLk/5s4ogEdrdguFvWxQ6zszQ3UxBh3H9pim+k7jVQ==", + "license": "MIT", + "dependencies": { + "@zag-js/core": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/types": "1.7.0" + } + }, + "node_modules/@zag-js/progress": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/progress/-/progress-1.7.0.tgz", + "integrity": "sha512-dfjPtUGRZW0pURBalm55ACoN083EJ90cDT1RRRF72JhqlRJu/vSXngjSUFtYuG1WADGS3D7F5XIFMo+PAGynFg==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/qr-code": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/qr-code/-/qr-code-1.7.0.tgz", + "integrity": "sha512-fg/hI2Py6D4E2cvh2BJ4PunYyyivkkRga76K9VDvq+hq1OezB6SzchLjFkIXn6431VK+xrU1HqcSR67KAn8IWA==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0", + "proxy-memoize": "3.0.1", + "uqr": "0.1.2" + } + }, + "node_modules/@zag-js/radio-group": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/radio-group/-/radio-group-1.7.0.tgz", + "integrity": "sha512-9NlI5fTh8ZVX5nXm7nU/ZheQLZpHwrHZeKRjomVQQALEWuMZ5YJtVXZaUT5xsCRTk+LEQVSaKp10+aD/5cIMlA==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/element-rect": "1.7.0", + "@zag-js/focus-visible": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/rating-group": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/rating-group/-/rating-group-1.7.0.tgz", + "integrity": "sha512-jDr8M+2fXTxB9l8qm8ktA362eM6Xt6FzIz0dKlV1JsYr5KamhsZ70Y8MPB6i3b45FGdDdj02a2aaWGLRUaRnrw==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/react": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/react/-/react-1.7.0.tgz", + "integrity": "sha512-phr7WMVJcwfOkiLwtobGWkdzVGdZmVQYvF7w8awloW0j1+YF2OdMYDZK8RauHwmg+sEVmqtGeZPr40hZNnKhVQ==", + "license": "MIT", + "dependencies": { + "@zag-js/core": "1.7.0", + "@zag-js/store": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/@zag-js/rect-utils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/rect-utils/-/rect-utils-1.7.0.tgz", + "integrity": "sha512-VvpqanvSrD/a5Gf5VHCM9yhkaBFWWsYTRNNQBtguNDrOh/tFvQBFAwes/BxvT+4fG4xbBL/fbSZIyhZ77Q7L2w==", + "license": "MIT" + }, + "node_modules/@zag-js/remove-scroll": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/remove-scroll/-/remove-scroll-1.7.0.tgz", + "integrity": "sha512-sjuBT/iHUZKoDaIdEa5fn0Ii6qjPbp/xO5g/2n2gI3RhRPjcc9jmrTxuvjKftB+ZoBy4GO8MbeaPKdQLIreufg==", + "license": "MIT", + "dependencies": { + "@zag-js/dom-query": "1.7.0" + } + }, + "node_modules/@zag-js/scroll-snap": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/scroll-snap/-/scroll-snap-1.7.0.tgz", + "integrity": "sha512-dvRmgdnT0AR2g0RtjgVXGJG6Si4gd+os56u1x3VKzAzlMZWYiFd0iyoKFCr/SCBEEMN/Y3ppkQoZjWOlnpah2g==", + "license": "MIT", + "dependencies": { + "@zag-js/dom-query": "1.7.0" + } + }, + "node_modules/@zag-js/select": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/select/-/select-1.7.0.tgz", + "integrity": "sha512-DmKIfoJFO42NgZOspEww5i6j71OqHgUCCodxR0zCmMoISxi1VYYKdjjeeSqivUYoH2mk9+z+lAJF+qdCo45Mzg==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/collection": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dismissable": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/popper": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/signature-pad": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/signature-pad/-/signature-pad-1.7.0.tgz", + "integrity": "sha512-m81iwLl0TKsFPRnPLadVIM53q6b7NJJ6fgRH8Z+TImarorV4QcA0IXr2wcj1MLlIa4CPNiXoQrmOnOdIOFHvWA==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0", + "perfect-freehand": "^1.2.2" + } + }, + "node_modules/@zag-js/slider": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/slider/-/slider-1.7.0.tgz", + "integrity": "sha512-0h9ejtOWa4XjxApcCFyGt7By22kd6gG4PdUZgXiKlPCQFgYrxWXZqMlwH6ZtyD4VYUuRPJ05CezDU5KlmZD/3A==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/element-size": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/splitter": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/splitter/-/splitter-1.7.0.tgz", + "integrity": "sha512-iJiKgRqIp/gbzjTajLIjpoc8dVBhjrTGauwVFj2yfKlkM30lgBRBHPtnrtsVox2A5ZyTikuj2ZtMCFXJAL8BDA==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/steps": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/steps/-/steps-1.7.0.tgz", + "integrity": "sha512-niYlKAy4j7yariPVbPJwBgzWhEsE82d7JIxD4yQW1nyyM6+xAgZrJaTG6WY1ogiBLCDj5kZw1rJv1uBBF6I5EA==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/store": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/store/-/store-1.7.0.tgz", + "integrity": "sha512-3n+AGo3Y3d1+SkEjY/6QPcDU5kfGu4DEA9qMxJgnnOlYT07SEWByMQD2uoEji9M9psHcVvxm86OnF3Y6UuTsuA==", + "license": "MIT", + "dependencies": { + "proxy-compare": "3.0.1" + } + }, + "node_modules/@zag-js/switch": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/switch/-/switch-1.7.0.tgz", + "integrity": "sha512-sz3whYMAD949fJ5v9DegU43SrpUNKhoPOum4LOpoSrh364ePfm7ShsTIgJnqPrdMknr+17ljLx54tXPS1SsMTw==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/focus-visible": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/tabs": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/tabs/-/tabs-1.7.0.tgz", + "integrity": "sha512-bAMp7Vhyis5j3BSKs4m0OwsbchRLLzFf6Yaf54CNraAUdKRwLQckznrajQLPI5F+BrHkGzMXvj/lt9jlGiKDcw==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/element-rect": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + } + }, + "node_modules/@zag-js/tags-input": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/tags-input/-/tags-input-1.7.0.tgz", + "integrity": "sha512-ME/KwP1yrPHX0bP0EqkHI30IQgrE2cAkREoRluM5ScpG3Uiug98x6+zts0YS9j1OB3pyTl0d4alECBruxN8cPA==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/auto-resize": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/interact-outside": "1.7.0", + "@zag-js/live-region": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" } }, - "node_modules/@vitest/snapshot": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.34.6.tgz", - "integrity": "sha512-B3OZqYn6k4VaN011D+ve+AA4whM4QkcwcrwaKwAbyyvS/NB1hCWjFIBQxAQQSQir9/RtyAAGuq+4RJmbn2dH4w==", - "dev": true, + "node_modules/@zag-js/time-picker": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/time-picker/-/time-picker-1.7.0.tgz", + "integrity": "sha512-oeJ/2cHUD/iNF9LVWeFZ0ZrUDpMcSjb1lScqmrDdSuBpt9Hv5NLwjKFVeCtcE7VP3ijgN1VHY5FJzqQyynK9tw==", "license": "MIT", "dependencies": { - "magic-string": "^0.30.1", - "pathe": "^1.1.1", - "pretty-format": "^29.5.0" + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dismissable": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/popper": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" }, - "funding": { - "url": "https://opencollective.com/vitest" + "peerDependencies": { + "@internationalized/date": ">=3.0.0" } }, - "node_modules/@vitest/spy": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.6.tgz", - "integrity": "sha512-xaCvneSaeBw/cz8ySmF7ZwGvL0lBjfvqc1LpQ/vcdHEvpLn3Ff1vAvjw+CoGn0802l++5L/pxb7whwcWAw+DUQ==", - "dev": true, + "node_modules/@zag-js/timer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/timer/-/timer-1.7.0.tgz", + "integrity": "sha512-IpFkbuyBPJl/1idCchljtpZ0PirJWHLpvoFrEnyXQ7clyIeeLuYjyMMfwG+BVWZ7BeYby9A+b0+UNksvoJLtvQ==", "license": "MIT", "dependencies": { - "tinyspy": "^2.1.1" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" } }, - "node_modules/@vitest/utils": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.6.tgz", - "integrity": "sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==", - "dev": true, + "node_modules/@zag-js/toast": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/toast/-/toast-1.7.0.tgz", + "integrity": "sha512-tvEO1vpC9QZ0oYJOKay2dvcq5lAPn4MT7ahnALs89iVjhWyguXAs5kzoq/Devlbuhi+bUY1YxvtrMDJjYVFhaA==", "license": "MIT", "dependencies": { - "diff-sequences": "^29.4.3", - "loupe": "^2.3.6", - "pretty-format": "^29.5.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dismissable": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" } }, - "node_modules/@web3-storage/multipart-parser": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@web3-storage/multipart-parser/-/multipart-parser-1.0.0.tgz", - "integrity": "sha512-BEO6al7BYqcnfX15W2cnGR+Q566ACXAT9UQykORCWW80lmkpWsnEob6zJS1ZVBKsSJC8+7vJkHwlp+lXG1UCdw==", - "license": "(Apache-2.0 AND MIT)" + "node_modules/@zag-js/toggle": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/toggle/-/toggle-1.7.0.tgz", + "integrity": "sha512-94TEthfGXjNmPcIiaOlwwEm73SSI2rRVn6FPviatzQU/OcDaaiAxuvGMIkW7Ov4+1sniAElGP24LTnyz0QuQpg==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + } }, - "node_modules/@xmldom/xmldom": { - "version": "0.8.10", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", - "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", + "node_modules/@zag-js/toggle-group": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/toggle-group/-/toggle-group-1.7.0.tgz", + "integrity": "sha512-qf8S66MUSw95S65BFH+PUtPs6GCLd39MWHJqzvZSXS+UWCLNXQlK8ayrNYh6CQgtgNeyljMqc2pFGWmp+M987w==", "license": "MIT", - "engines": { - "node": ">=10.0.0" + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" } }, - "node_modules/@xobotyi/scrollbar-width": { - "version": "1.9.5", - "resolved": "https://registry.npmjs.org/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz", - "integrity": "sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==", - "license": "MIT" + "node_modules/@zag-js/tooltip": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/tooltip/-/tooltip-1.7.0.tgz", + "integrity": "sha512-ehZOewcxYZL4+ND5QMeDlQQrckssMTzxcReRCOVFXrRZb5X1jX6+ale9MSG+cJYMpQUqT2J5VtzMJH+GNj/jfw==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/focus-visible": "1.7.0", + "@zag-js/popper": "1.7.0", + "@zag-js/store": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + } }, - "node_modules/@zag-js/dom-query": { - "version": "0.31.1", - "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-0.31.1.tgz", - "integrity": "sha512-oiuohEXAXhBxpzzNm9k2VHGEOLC1SXlXSbRPcfBZ9so5NRQUA++zCE7cyQJqGLTZR0t3itFLlZqDbYEXRrefwg==", - "license": "MIT" + "node_modules/@zag-js/tour": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/tour/-/tour-1.7.0.tgz", + "integrity": "sha512-P8wYE0OpW1GtopvQ7ELdF2SuTMI64iBSr4UYGRCt2WkbrjP0vkFp35iUEbFmE44cRKIF8jGU6gznSPCGnGjz9A==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dismissable": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/focus-trap": "1.7.0", + "@zag-js/interact-outside": "1.7.0", + "@zag-js/popper": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + } }, - "node_modules/@zag-js/element-size": { - "version": "0.31.1", - "resolved": "https://registry.npmjs.org/@zag-js/element-size/-/element-size-0.31.1.tgz", - "integrity": "sha512-4T3yvn5NqqAjhlP326Fv+w9RqMIBbNN9H72g5q2ohwzhSgSfZzrKtjL4rs9axY/cw9UfMfXjRjEE98e5CMq7WQ==", - "license": "MIT" + "node_modules/@zag-js/tree-view": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/tree-view/-/tree-view-1.7.0.tgz", + "integrity": "sha512-ULjbcLG3PqYV5BKNW8Z9Ikh+67GblYhEscgfBN4X3BLv9KOG6J0Gp4JQkxkWBTeRpUCTnoBgZ1ZbeOFgNJbcfQ==", + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.7.0", + "@zag-js/collection": "1.7.0", + "@zag-js/core": "1.7.0", + "@zag-js/dom-query": "1.7.0", + "@zag-js/types": "1.7.0", + "@zag-js/utils": "1.7.0" + } }, - "node_modules/@zag-js/focus-visible": { - "version": "0.31.1", - "resolved": "https://registry.npmjs.org/@zag-js/focus-visible/-/focus-visible-0.31.1.tgz", - "integrity": "sha512-dbLksz7FEwyFoANbpIlNnd3bVm0clQSUsnP8yUVQucStZPsuWjCrhL2jlAbGNrTrahX96ntUMXHb/sM68TibFg==", + "node_modules/@zag-js/types": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/types/-/types-1.7.0.tgz", + "integrity": "sha512-rmPonVc8EBOGIEJYjzWIBQ6LJwUMc3LnipRREECO+n7LNlUQUliCOFbHw1UOGP+4ZkCKmxjGFR3jLtjY8aN4gQ==", "license": "MIT", "dependencies": { - "@zag-js/dom-query": "0.31.1" + "csstype": "3.1.3" } }, + "node_modules/@zag-js/utils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@zag-js/utils/-/utils-1.7.0.tgz", + "integrity": "sha512-yIxvH5V27a1WuLgCxHX7qpdtFo8vTJaZLafBpSNfVYG4B8FaxTE+P7JAcpmAzs3UyXura/WfAY2eVWWVBpk9ZA==", + "license": "MIT" + }, "node_modules/@zxing/text-encoding": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz", @@ -7438,18 +8204,6 @@ "dev": true, "license": "Python-2.0" }, - "node_modules/aria-hidden": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz", - "integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==", - "license": "MIT", - "dependencies": { - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/aria-query": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", @@ -8655,12 +9409,6 @@ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "license": "MIT" }, - "node_modules/color2k": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/color2k/-/color2k-2.0.3.tgz", - "integrity": "sha512-zW190nQTIoXcGCaU08DvVNFTmQhUpnJfVuAKfWqUQkflXKpaDdpaYoM0iluLS9lgJNHyBF58KKA2FBEwkD7wog==", - "license": "MIT" - }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", @@ -9257,12 +10005,6 @@ "node": ">=8" } }, - "node_modules/detect-node-es": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", - "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", - "license": "MIT" - }, "node_modules/diff": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", @@ -10612,6 +11354,12 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "license": "MIT" + }, "node_modules/fast-shallow-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fast-shallow-equal/-/fast-shallow-equal-1.0.0.tgz", @@ -10807,18 +11555,6 @@ "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==", "license": "MIT" }, - "node_modules/focus-lock": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/focus-lock/-/focus-lock-1.3.6.tgz", - "integrity": "sha512-Ik/6OCk9RQQ0T5Xw+hKNLWrjSMtv51dD4GRmJjbD5a58TIEpI5a5iXagKVl3Z5UuyslMCA8Xwnu76jQob62Yhg==", - "license": "MIT", - "dependencies": { - "tslib": "^2.0.3" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/follow-redirects": { "version": "1.15.9", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", @@ -10917,48 +11653,6 @@ "node": ">= 0.6" } }, - "node_modules/framer-motion": { - "version": "12.6.3", - "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.6.3.tgz", - "integrity": "sha512-2hsqknz23aloK85bzMc9nSR2/JP+fValQ459ZTVElFQ0xgwR2YqNjYSuDZdFBPOwVCt4Q9jgyTt6hg6sVOALzw==", - "license": "MIT", - "dependencies": { - "motion-dom": "^12.6.3", - "motion-utils": "^12.6.3", - "tslib": "^2.4.0" - }, - "peerDependencies": { - "@emotion/is-prop-valid": "*", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@emotion/is-prop-valid": { - "optional": true - }, - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, - "node_modules/framesync": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/framesync/-/framesync-6.1.2.tgz", - "integrity": "sha512-jBTqhX6KaQVDyus8muwZbBeGGP0XgujBRbQ7gM7BRdS3CadCZIHiawyzYLnafYcvZIh5j8WE7cxZKFn7dXhu9g==", - "license": "MIT", - "dependencies": { - "tslib": "2.4.0" - } - }, - "node_modules/framesync/node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", - "license": "0BSD" - }, "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -11136,15 +11830,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-nonce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", - "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", @@ -13235,12 +13920,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lodash.mergewith": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", - "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", - "license": "MIT" - }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -14719,21 +15398,6 @@ "dev": true, "license": "MIT" }, - "node_modules/motion-dom": { - "version": "12.6.3", - "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.6.3.tgz", - "integrity": "sha512-gRY08RjcnzgFYLemUZ1lo/e9RkBxR+6d4BRvoeZDSeArG4XQXERSPapKl3LNQRu22Sndjf1h+iavgY0O4NrYqA==", - "license": "MIT", - "dependencies": { - "motion-utils": "^12.6.3" - } - }, - "node_modules/motion-utils": { - "version": "12.6.3", - "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.6.3.tgz", - "integrity": "sha512-R/b3Ia2VxtTNZ4LTEO5pKYau1OUNHOuUfxuP0WFCTDYdHkeTBR9UtxR1cc8mDmKr8PEhmmfnTKGz3rSMjNRoRg==", - "license": "MIT" - }, "node_modules/mri": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", @@ -15804,6 +16468,12 @@ "dev": true, "license": "MIT" }, + "node_modules/perfect-freehand": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/perfect-freehand/-/perfect-freehand-1.2.2.tgz", + "integrity": "sha512-eh31l019WICQ03pkF3FSzHxB8n07ItqIQ++G5UV8JX0zVOXzgTGCqnRR0jJ2h9U8/2uW4W4mtGJELt9kEV0CFQ==", + "license": "MIT" + }, "node_modules/periscopic": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz", @@ -16283,6 +16953,7 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, "license": "MIT", "dependencies": { "loose-envify": "^1.4.0", @@ -16314,12 +16985,27 @@ "node": ">= 0.10" } }, + "node_modules/proxy-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-3.0.1.tgz", + "integrity": "sha512-V9plBAt3qjMlS1+nC8771KNf6oJ12gExvaxnNzN/9yVRLdTv/lc+oJlnSzrdYDAvBfTStPCoiaCOTmTs0adv7Q==", + "license": "MIT" + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "license": "MIT" }, + "node_modules/proxy-memoize": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/proxy-memoize/-/proxy-memoize-3.0.1.tgz", + "integrity": "sha512-VDdG/VYtOgdGkWJx7y0o7p+zArSf2383Isci8C+BP3YXgMYDoPd3cCBjw0JdWb6YBb9sFiOPbAADDVTPJnh+9g==", + "license": "MIT", + "dependencies": { + "proxy-compare": "^3.0.0" + } + }, "node_modules/ps-tree": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", @@ -16476,18 +17162,6 @@ "node": ">=0.10.0" } }, - "node_modules/react-clientside-effect": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/react-clientside-effect/-/react-clientside-effect-1.2.7.tgz", - "integrity": "sha512-gce9m0Pk/xYYMEojRI9bgvqQAkl6hm7ozQvqWPyQx+kULiatdHgkNM1QG4DQRx5N9BAzWSCJmt9mMV8/KsdgVg==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.12.13" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" - } - }, "node_modules/react-dom": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", @@ -16501,35 +17175,6 @@ "react": "^18.3.1" } }, - "node_modules/react-fast-compare": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", - "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==", - "license": "MIT" - }, - "node_modules/react-focus-lock": { - "version": "2.13.6", - "resolved": "https://registry.npmjs.org/react-focus-lock/-/react-focus-lock-2.13.6.tgz", - "integrity": "sha512-ehylFFWyYtBKXjAO9+3v8d0i+cnc1trGS0vlTGhzFW1vbFXVUTmR8s2tt/ZQG8x5hElg6rhENlLG1H3EZK0Llg==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.0.0", - "focus-lock": "^1.3.6", - "prop-types": "^15.6.2", - "react-clientside-effect": "^1.2.7", - "use-callback-ref": "^1.3.3", - "use-sidecar": "^1.1.3" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, "node_modules/react-icons": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz", @@ -16555,53 +17200,6 @@ "node": ">=0.10.0" } }, - "node_modules/react-remove-scroll": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.3.tgz", - "integrity": "sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ==", - "license": "MIT", - "dependencies": { - "react-remove-scroll-bar": "^2.3.7", - "react-style-singleton": "^2.2.3", - "tslib": "^2.1.0", - "use-callback-ref": "^1.3.3", - "use-sidecar": "^1.1.3" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/react-remove-scroll-bar": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", - "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", - "license": "MIT", - "dependencies": { - "react-style-singleton": "^2.2.2", - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, "node_modules/react-router": { "version": "6.30.0", "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.0.tgz", @@ -16634,28 +17232,6 @@ "react-dom": ">=16.8" } }, - "node_modules/react-style-singleton": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", - "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", - "license": "MIT", - "dependencies": { - "get-nonce": "^1.0.0", - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, "node_modules/react-universal-interface": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/react-universal-interface/-/react-universal-interface-0.6.2.tgz", @@ -19322,6 +19898,12 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/uqr": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/uqr/-/uqr-0.1.2.tgz", + "integrity": "sha512-MJu7ypHq6QasgF5YRTjqscSzQp/W11zoUk6kvmlH+fmWEs63Y0Eib13hYFwAzagRJcVY8WVnlV+eBDUGMJ5IbA==", + "license": "MIT" + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -19332,49 +19914,6 @@ "punycode": "^2.1.0" } }, - "node_modules/use-callback-ref": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", - "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", - "license": "MIT", - "dependencies": { - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/use-sidecar": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", - "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", - "license": "MIT", - "dependencies": { - "detect-node-es": "^1.1.0", - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, "node_modules/util": { "version": "0.12.5", "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", diff --git a/package.json b/package.json index 0d66a9f5..2d2041de 100644 --- a/package.json +++ b/package.json @@ -35,10 +35,9 @@ "@authenio/samlify-node-xmllint": "^2.0.0", "@aws-sdk/client-route-53": "^3.777.0", "@chakra-ui/icons": "^2.2.6", - "@chakra-ui/react": "^2.10.7", + "@chakra-ui/react": "^3.15.0", "@emotion/react": "^11.14.0", "@emotion/server": "^11.11.0", - "@emotion/styled": "^11.14.0", "@prisma/client": "^6.5.0", "@remix-run/express": "2.16.4", "@remix-run/node": "2.16.4", @@ -53,7 +52,6 @@ "dayjs": "^1.11.13", "docker-secret": "^2.0.6", "express": "^4.21.2", - "framer-motion": "^12.6.3", "helmet": "^8.1.0", "http-graceful-shutdown": "^3.1.14", "ioredis": "^5.6.0", From 61941f7de32610341ec9b9e1d3e7a44a7e48c6a8 Mon Sep 17 00:00:00 2001 From: TheoForger Date: Tue, 1 Apr 2025 18:59:10 -0400 Subject: [PATCH 02/13] Add recommended chakra-ui snippet --- app/components/ui/color-mode.tsx | 102 +++++++++++++++++++++++++++++++ app/components/ui/provider.tsx | 12 ++++ app/components/ui/toaster.tsx | 39 ++++++++++++ app/components/ui/tooltip.tsx | 44 +++++++++++++ 4 files changed, 197 insertions(+) create mode 100644 app/components/ui/color-mode.tsx create mode 100644 app/components/ui/provider.tsx create mode 100644 app/components/ui/toaster.tsx create mode 100644 app/components/ui/tooltip.tsx diff --git a/app/components/ui/color-mode.tsx b/app/components/ui/color-mode.tsx new file mode 100644 index 00000000..2f0b95d0 --- /dev/null +++ b/app/components/ui/color-mode.tsx @@ -0,0 +1,102 @@ +'use client'; + +import type { IconButtonProps, SpanProps } from '@chakra-ui/react'; +import { ClientOnly, IconButton, Skeleton, Span } from '@chakra-ui/react'; +import { ThemeProvider, useTheme } from 'next-themes'; +import type { ThemeProviderProps } from 'next-themes'; +import * as React from 'react'; +import { LuMoon, LuSun } from 'react-icons/lu'; + +export interface ColorModeProviderProps extends ThemeProviderProps {} + +export function ColorModeProvider(props: ColorModeProviderProps) { + return ; +} + +export type ColorMode = 'light' | 'dark'; + +export interface UseColorModeReturn { + colorMode: ColorMode; + setColorMode: (colorMode: ColorMode) => void; + toggleColorMode: () => void; +} + +export function useColorMode(): UseColorModeReturn { + const { resolvedTheme, setTheme } = useTheme(); + const toggleColorMode = () => { + setTheme(resolvedTheme === 'dark' ? 'light' : 'dark'); + }; + return { + colorMode: resolvedTheme as ColorMode, + setColorMode: setTheme, + toggleColorMode, + }; +} + +export function useColorModeValue(light: T, dark: T) { + const { colorMode } = useColorMode(); + return colorMode === 'dark' ? dark : light; +} + +export function ColorModeIcon() { + const { colorMode } = useColorMode(); + return colorMode === 'dark' ? : ; +} + +interface ColorModeButtonProps extends Omit {} + +export const ColorModeButton = React.forwardRef( + function ColorModeButton(props, ref) { + const { toggleColorMode } = useColorMode(); + return ( + }> + + + + + ); + } +); + +export const LightMode = React.forwardRef( + function LightMode(props, ref) { + return ( + + ); + } +); + +export const DarkMode = React.forwardRef(function DarkMode(props, ref) { + return ( + + ); +}); diff --git a/app/components/ui/provider.tsx b/app/components/ui/provider.tsx new file mode 100644 index 00000000..1ca22df5 --- /dev/null +++ b/app/components/ui/provider.tsx @@ -0,0 +1,12 @@ +'use client'; + +import { ChakraProvider, defaultSystem } from '@chakra-ui/react'; +import { ColorModeProvider, type ColorModeProviderProps } from './color-mode'; + +export function Provider(props: ColorModeProviderProps) { + return ( + + + + ); +} diff --git a/app/components/ui/toaster.tsx b/app/components/ui/toaster.tsx new file mode 100644 index 00000000..6a49fd72 --- /dev/null +++ b/app/components/ui/toaster.tsx @@ -0,0 +1,39 @@ +'use client'; + +import { + Toaster as ChakraToaster, + Portal, + Spinner, + Stack, + Toast, + createToaster, +} from '@chakra-ui/react'; + +export const toaster = createToaster({ + placement: 'bottom-end', + pauseOnPageIdle: true, +}); + +export const Toaster = () => { + return ( + + + {(toast) => ( + + {toast.type === 'loading' ? ( + + ) : ( + + )} + + {toast.title && {toast.title}} + {toast.description && {toast.description}} + + {toast.action && {toast.action.label}} + {toast.meta?.closable && } + + )} + + + ); +}; diff --git a/app/components/ui/tooltip.tsx b/app/components/ui/tooltip.tsx new file mode 100644 index 00000000..9f3b8ba1 --- /dev/null +++ b/app/components/ui/tooltip.tsx @@ -0,0 +1,44 @@ +import { Tooltip as ChakraTooltip, Portal } from '@chakra-ui/react'; +import * as React from 'react'; + +export interface TooltipProps extends ChakraTooltip.RootProps { + showArrow?: boolean; + portalled?: boolean; + portalRef?: React.RefObject; + content: React.ReactNode; + contentProps?: ChakraTooltip.ContentProps; + disabled?: boolean; +} + +export const Tooltip = React.forwardRef(function Tooltip(props, ref) { + const { + showArrow, + children, + disabled, + portalled = true, + content, + contentProps, + portalRef, + ...rest + } = props; + + if (disabled) return children; + + return ( + + {children} + + + + {showArrow && ( + + + + )} + {content} + + + + + ); +}); From b058997987c020b4c5408a5c66a6c70640f064d9 Mon Sep 17 00:00:00 2001 From: TheoForger Date: Wed, 2 Apr 2025 14:35:30 -0400 Subject: [PATCH 03/13] Migrate theme --- app/root.tsx | 6 +++--- app/theme/breakpoints.ts | 12 ++++++------ app/theme/colors.ts | 40 ++++++++++++++++++++-------------------- app/theme/index.ts | 36 +++++++++++++++++++++++++----------- app/theme/styles.ts | 14 ++++++-------- 5 files changed, 60 insertions(+), 48 deletions(-) diff --git a/app/root.tsx b/app/root.tsx index c0ebb204..bfa2e024 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -1,4 +1,4 @@ -import { ChakraProvider } from '@chakra-ui/react'; +import { Provider } from '~/components/ui/provider'; import { json } from '@remix-run/node'; import { Links, @@ -79,9 +79,9 @@ function Document({ children }: { children: React.ReactNode }) { export default function App() { return ( - + - + ); } diff --git a/app/theme/breakpoints.ts b/app/theme/breakpoints.ts index 292f84fa..587ef8c1 100644 --- a/app/theme/breakpoints.ts +++ b/app/theme/breakpoints.ts @@ -1,10 +1,10 @@ const breakpoints = { - 'xs': '20em', - 'sm': '30em', - 'md': '48em', - 'lg': '62em', - 'xl': '80em', - '2xl': '96em', + 'xs': { value: '20em' }, + 'sm': { value: '30em' }, + 'md': { value: '48em' }, + 'lg': { value: '62em' }, + 'xl': { value: '80em' }, + '2xl': { value: '96em' }, }; export default breakpoints; diff --git a/app/theme/colors.ts b/app/theme/colors.ts index d28019f2..6564b3c3 100644 --- a/app/theme/colors.ts +++ b/app/theme/colors.ts @@ -1,27 +1,27 @@ const colors = { brand: { - 50: '#ffe4e3', - 100: '#feb7b6', - 200: '#f78988', - 300: '#f25a59', - 400: '#ed2c2b', - 500: '#d41312', - 600: '#a60c0d', - 700: '#770608', - 800: '#4a0203', - 900: '#200000', + 50: { value: '#ffe4e3' }, + 100: { value: '#feb7b6' }, + 200: { value: '#f78988' }, + 300: { value: '#f25a59' }, + 400: { value: '#ed2c2b' }, + 500: { value: '#d41312' }, + 600: { value: '#a60c0d' }, + 700: { value: '#770608' }, + 800: { value: '#4a0203' }, + 900: { value: '#200000' }, }, brand_gray: { - 50: '#f9f9f9', - 100: '#ededed', - 200: '#e1e1e1', - 300: '#d3d3d3', - 400: '#c4c4c4', - 500: '#b3b3b3', - 600: '#a0a0a0', - 700: '#898989', - 800: '#6c6c6c', - 900: '#3f3f3f', + 50: { value: '#f9f9f9' }, + 100: { value: '#ededed' }, + 200: { value: '#e1e1e1' }, + 300: { value: '#d3d3d3' }, + 400: { value: '#c4c4c4' }, + 500: { value: '#b3b3b3' }, + 600: { value: '#a0a0a0' }, + 700: { value: '#898989' }, + 800: { value: '#6c6c6c' }, + 900: { value: '#3f3f3f' }, }, }; diff --git a/app/theme/index.ts b/app/theme/index.ts index 5001b5e0..270d8bdb 100644 --- a/app/theme/index.ts +++ b/app/theme/index.ts @@ -1,23 +1,37 @@ -import { defineStyleConfig, extendTheme, withDefaultColorScheme } from '@chakra-ui/react'; +import { createSystem, defaultConfig, defineRecipe } from '@chakra-ui/react'; import colors from './colors'; import breakpoints from './breakpoints'; import styles from './styles'; -const theme = extendTheme( - { - styles, - colors, - breakpoints, - components: { - Link: defineStyleConfig({ - baseStyle: { +const theme = createSystem(defaultConfig, { + theme: { + recipes: { + Link: defineRecipe({ + base: { color: 'brand.500', textDecor: 'underline', }, }), }, + tokens: { + colors, + breakpoints, + }, + semanticTokens: { + colors: { + brand: { + solid: { value: '{colors.brand.500}' }, + contrast: { value: '{colors.brand.100}' }, + fg: { value: '{colors.brand.700}' }, + muted: { value: '{colors.brand.100}' }, + subtle: { value: '{colors.brand.200}' }, + emphasized: { value: '{colors.brand.300}' }, + focusRing: { value: '{colors.brand.500}' }, + }, + }, + }, }, - withDefaultColorScheme({ colorScheme: 'brand' }) -); + globalCss: styles, +}); export default theme; diff --git a/app/theme/styles.ts b/app/theme/styles.ts index 71ce2a2d..ef4bdf6c 100644 --- a/app/theme/styles.ts +++ b/app/theme/styles.ts @@ -1,13 +1,11 @@ // We want html and body to occupy the full window height for vertical centering const styles = { - global: { - html: { - height: '100%', - }, - body: { - height: '100%', - minHeight: '100%', - }, + html: { + height: '100%', + }, + body: { + height: '100%', + minHeight: '100%', }, }; From 1261f6fcb0ae9e58e4e8da6cc3413331b81dff1f Mon Sep 17 00:00:00 2001 From: TheoForger Date: Wed, 2 Apr 2025 19:29:35 -0400 Subject: [PATCH 04/13] Migrate components --- app/components/admin/admin-metric-card.tsx | 13 +- app/components/admin/users-table.tsx | 164 +++++------ .../certificate/certificate-available.tsx | 83 +++--- .../certificate/certificate-display.tsx | 75 +++-- .../certificate/certificate-request.tsx | 30 +- app/components/certificate/description.tsx | 48 ++-- app/components/certificate/panels/aws.tsx | 61 ++-- app/components/certificate/panels/general.tsx | 59 ++-- app/components/certificate/panels/nginx.tsx | 36 +-- app/components/certificate/panels/node.tsx | 51 ++-- .../dns-record-delete-alert-dialog.tsx | 37 ++- app/components/dns-record-table-row.tsx | 123 ++++---- app/components/dns-record/dns-record-name.tsx | 5 +- app/components/dns-record/form-field.tsx | 12 +- app/components/dns-record/form.tsx | 64 +++-- app/components/dns-records-table.tsx | 102 ++++--- app/components/footer.tsx | 39 ++- app/components/header.tsx | 150 +++++----- app/components/instructions/faq-accordion.tsx | 23 +- .../landing-page/landing-page-card.tsx | 42 ++- app/routes/_auth.admin._index.tsx | 29 +- app/routes/_auth.certificate.information.tsx | 173 ++++++------ app/routes/_auth.dns-records.$dnsRecordId.tsx | 4 +- app/routes/_auth.dns-records._index.tsx | 38 +-- app/routes/_auth.dns-records.instructions.tsx | 265 +++++++++--------- app/routes/_auth.dns-records.new.tsx | 4 +- tsconfig.json | 8 +- 27 files changed, 853 insertions(+), 885 deletions(-) diff --git a/app/components/admin/admin-metric-card.tsx b/app/components/admin/admin-metric-card.tsx index 338281ed..0a83dda4 100644 --- a/app/components/admin/admin-metric-card.tsx +++ b/app/components/admin/admin-metric-card.tsx @@ -1,5 +1,6 @@ import { InfoIcon } from '@chakra-ui/icons'; -import { CardBody, Card, Text, Flex, Tooltip } from '@chakra-ui/react'; +import { Card, Text, Flex } from '@chakra-ui/react'; +import { Tooltip } from '~/components/ui/tooltip'; import type { IconType } from 'react-icons'; interface AdminMetricCardProps { @@ -16,8 +17,8 @@ export default function AdminMetricCard({ tooltipText, }: AdminMetricCardProps) { return ( - - + + - + - - + + ); } diff --git a/app/components/admin/users-table.tsx b/app/components/admin/users-table.tsx index d247a499..e147e569 100644 --- a/app/components/admin/users-table.tsx +++ b/app/components/admin/users-table.tsx @@ -1,22 +1,8 @@ -import { - Table, - Tr, - Th, - Thead, - Tbody, - TableContainer, - Td, - Card, - IconButton, - Tooltip, - Flex, - HStack, - Spinner, - Text, -} from '@chakra-ui/react'; +import { Table, Card, IconButton, Flex, HStack, Spinner, Text } from '@chakra-ui/react'; import { DeleteIcon } from '@chakra-ui/icons'; import { FaTheaterMasks } from 'react-icons/fa'; import { Form, useNavigation } from '@remix-run/react'; +import { Tooltip } from '~/components/ui/tooltip'; import type { UserWithMetrics } from '~/routes/_auth.admin._index'; import { MIN_USERS_SEARCH_TEXT } from '~/routes/_auth.admin._index'; @@ -41,83 +27,79 @@ export default function UsersTable({ users, searchText }: UsersTableProps) { const shouldShowUsers = !(isLoading || shouldShowInstruction || shouldShowNoUsersMessage); return ( - - - - - - - - - - - - - {!shouldShowUsers && ( - - - - )} + + + + + Email + Name + DNS Records + Certificate status + + + + + {!shouldShowUsers && ( + + + + {isLoading && } + {shouldShowInstruction && !isLoading && ( + Please enter at least 3 characters to search + )} + {shouldShowNoUsersMessage && !isLoading && No users found} + + + + )} - {shouldShowUsers && - users.map((user) => { - return ( - - - - - - - - ); - })} - -
EmailNameDNS RecordsCertificate status -
- - {isLoading && } - {shouldShowInstruction && !isLoading && ( - Please enter at least 3 characters to search - )} - {shouldShowNoUsersMessage && !isLoading && No users found} - -
{user.email}{user.displayName}{user.dnsRecordCount} - - - - -
- - - } - variant="ghost" - isDisabled={user.username === username} - /> - -
+ {shouldShowUsers && + users.map((user) => { + return ( + + {user.email} + {user.displayName} + {user.dnsRecordCount} + + + + + +
- - } - variant="ghost" - isDisabled={user.username === username} - type="submit" - /> - - - + + + + +
-
-
-
-
+ +
+ + + + + + + +
+ + + + ); + })} + + + ); } diff --git a/app/components/certificate/certificate-available.tsx b/app/components/certificate/certificate-available.tsx index 9c8f0887..c2fa627c 100644 --- a/app/components/certificate/certificate-available.tsx +++ b/app/components/certificate/certificate-available.tsx @@ -1,13 +1,4 @@ -import { - Heading, - Tab, - TabList, - Tabs, - TabPanels, - Text, - OrderedList, - ListItem, -} from '@chakra-ui/react'; +import { Heading, Tabs, Text, List } from '@chakra-ui/react'; import { useMemo } from 'react'; import dayjs from 'dayjs'; @@ -57,57 +48,55 @@ export default function CertificateAvailable({ will require you to use them in various combinations. These parts include: - - + + Public Certificate: public (not secret) certificate that verifies domain ownership - - + + Private Key: private code (do not share!) used to encrypt/decrypt data - - + + Intermediate Certificate Chain: set of one or more certificates that link your certificate back to a Certificate Authority, establishing a trust relationship - - + + Full Chain: your Public Certificate combined with the Intermediate Certificate Chain - - + + You can select from the list of pre-defined services below to help guide you, or see a General view for all of the certificate's parts. - - - General - Node.js - AWS - NGINX - + + + General + Node.js + AWS + NGINX + - - - - - - - + + + + + ); } diff --git a/app/components/certificate/certificate-display.tsx b/app/components/certificate/certificate-display.tsx index beb764f5..18c488a0 100644 --- a/app/components/certificate/certificate-display.tsx +++ b/app/components/certificate/certificate-display.tsx @@ -5,17 +5,13 @@ import { HStack, Text, Heading, - Tooltip, IconButton, Accordion, - AccordionItem, - AccordionButton, - AccordionIcon, - AccordionPanel, - useToast, useClipboard, } from '@chakra-ui/react'; import { DownloadIcon, CopyIcon } from '@chakra-ui/icons'; +import { Tooltip } from '~/components/ui/tooltip'; +import { toaster } from '~/components/ui/toaster'; import { Link } from '@remix-run/react'; interface CertificateDisplayProps { @@ -31,18 +27,17 @@ export default function CertificateDisplay({ value, downloadPart, }: CertificateDisplayProps) { - const toast = useToast(); - const { onCopy, hasCopied } = useClipboard(value); + const clipboard = useClipboard({ value }); useEffect(() => { - if (hasCopied) { - toast({ + if (clipboard.copied) { + toaster.create({ title: `${title} was copied to the clipboard`, - position: 'bottom-right', - status: 'success', + // Todo! + // status: 'success', }); } - }, [title, toast, hasCopied]); + }, [title, clipboard.copied]); return ( {title} - + } - onClick={onCopy} - /> + onClick={clipboard.copy} + > + + - + - toast({ - title: `${title} is Downloaded`, - position: 'bottom-right', - status: 'success', - }) - } - /> - } - /> + > + + toaster.create({ + title: `${title} is Downloaded`, + // Todo! + // status: 'success', + }) + } + /> + {description} - - - + + + Show/Hide - - - + + + - - - + + + ); } diff --git a/app/components/certificate/certificate-request.tsx b/app/components/certificate/certificate-request.tsx index eaa1da1d..89d1aa8a 100644 --- a/app/components/certificate/certificate-request.tsx +++ b/app/components/certificate/certificate-request.tsx @@ -1,13 +1,4 @@ -import { - Flex, - Heading, - Text, - Button, - Alert, - AlertIcon, - AlertTitle, - AlertDescription, -} from '@chakra-ui/react'; +import { Flex, Heading, Text, Button, Alert } from '@chakra-ui/react'; import { Form } from '@remix-run/react'; import { useState } from 'react'; @@ -53,23 +44,18 @@ export default function CertificateRequestView({ domain, isFailed }: Certificate
setIsDisabled(true)}> -
{isFailed && ( - - - Request Unsuccessful: - + + + Request Unsuccessful: + Unfortunately, your previous request was not successful. - - + + )} ); diff --git a/app/components/certificate/description.tsx b/app/components/certificate/description.tsx index 7a6c2b56..216227a1 100644 --- a/app/components/certificate/description.tsx +++ b/app/components/certificate/description.tsx @@ -1,17 +1,7 @@ import { RepeatIcon, DeleteIcon } from '@chakra-ui/icons'; import { Form, Link as RemixLink } from '@remix-run/react'; -import { - Flex, - Text, - Button, - Stat, - StatLabel, - StatNumber, - Wrap, - WrapItem, - Link, - useToast, -} from '@chakra-ui/react'; +import { Flex, Text, Button, Stat, Wrap, WrapItem, Link } from '@chakra-ui/react'; +import { toaster } from '~/components/ui/toaster'; interface DescriptionSectionProps { certRequested: boolean; @@ -30,7 +20,6 @@ export default function DescriptionSection({ isRenewable, link, }: DescriptionSectionProps) { - const toast = useToast(); return ( @@ -38,8 +27,8 @@ export default function DescriptionSection({ {link && ( <>  To learn more, refer to our  - - information page + + information page . @@ -47,19 +36,19 @@ export default function DescriptionSection({ {certRequested && !!validFromFormatted && !!validToFormatted && ( - - Created On - {validFromFormatted} - - - Expires On - {validToFormatted} - + + Created On + {validFromFormatted} + + + Expires On + {validToFormatted} +
-
@@ -67,17 +56,16 @@ export default function DescriptionSection({
diff --git a/app/components/certificate/panels/aws.tsx b/app/components/certificate/panels/aws.tsx index 7f7e9d4d..ee6b0968 100644 --- a/app/components/certificate/panels/aws.tsx +++ b/app/components/certificate/panels/aws.tsx @@ -1,4 +1,4 @@ -import { Divider, TabPanel, Text, Link } from '@chakra-ui/react'; +import { Tabs, Text, Link, Box } from '@chakra-ui/react'; import CertificateDisplay from '../certificate-display'; interface AwsPanelProps { @@ -9,46 +9,55 @@ interface AwsPanelProps { export default function AwsPanel({ certificate, privateKey, chain }: AwsPanelProps) { return ( - + You can{' '} import your certificate {' '} into{' '} - + AWS Certificate Manager {' '} and use it with{' '} - + many AWS services . - - - - - - + + + + + + ); } diff --git a/app/components/certificate/panels/general.tsx b/app/components/certificate/panels/general.tsx index d8e107bc..ed52ac5b 100644 --- a/app/components/certificate/panels/general.tsx +++ b/app/components/certificate/panels/general.tsx @@ -1,4 +1,4 @@ -import { Divider, TabPanel } from '@chakra-ui/react'; +import { Box, Tabs } from '@chakra-ui/react'; import CertificateDisplay from '../certificate-display'; interface GeneralPanelProps { @@ -15,34 +15,33 @@ export default function GeneralPanel({ fullChain, }: GeneralPanelProps) { return ( - - - - - - - - - + + + + + + + + ); } diff --git a/app/components/certificate/panels/nginx.tsx b/app/components/certificate/panels/nginx.tsx index e74c0727..9b955659 100644 --- a/app/components/certificate/panels/nginx.tsx +++ b/app/components/certificate/panels/nginx.tsx @@ -1,4 +1,4 @@ -import { Divider, TabPanel, Text, Link } from '@chakra-ui/react'; +import { Tabs, Text, Link, Box } from '@chakra-ui/react'; import CertificateDisplay from '../certificate-display'; interface NginxPanelProps { @@ -8,31 +8,33 @@ interface NginxPanelProps { export default function NginxPanel({ fullChain, privateKey }: NginxPanelProps) { return ( - + You can use your certificate with{' '} NGINX to create a secure HTTPS server . - - - - + + + + + ); } diff --git a/app/components/certificate/panels/node.tsx b/app/components/certificate/panels/node.tsx index bb988023..de5a1930 100644 --- a/app/components/certificate/panels/node.tsx +++ b/app/components/certificate/panels/node.tsx @@ -1,4 +1,4 @@ -import { Divider, TabPanel, Text, Link } from '@chakra-ui/react'; +import { Tabs, Text, Link, Box } from '@chakra-ui/react'; import CertificateDisplay from '../certificate-display'; interface NodePanelProps { @@ -9,38 +9,41 @@ interface NodePanelProps { export default function NodePanel({ certificate, privateKey, chain }: NodePanelProps) { return ( - + You can use your certificate with{' '} Node.js to create a secure HTTPS server . - - - - - - + + + + + + + + ); } diff --git a/app/components/dns-record-delete-alert-dialog.tsx b/app/components/dns-record-delete-alert-dialog.tsx index 5adfcb05..919ae617 100644 --- a/app/components/dns-record-delete-alert-dialog.tsx +++ b/app/components/dns-record-delete-alert-dialog.tsx @@ -1,13 +1,5 @@ import { useRef } from 'react'; -import { - AlertDialog, - Button, - AlertDialogOverlay, - AlertDialogContent, - AlertDialogFooter, - AlertDialogHeader, - AlertDialogBody, -} from '@chakra-ui/react'; +import { Dialog, Button } from '@chakra-ui/react'; import { Form } from '@remix-run/react'; import type { DnsRecord } from '@prisma/client'; @@ -27,14 +19,19 @@ export default function DnsRecordDeleteAlertDialog({ const cancelRef = useRef(null); return ( - - - - + cancelRef.current} + > + + + Delete DNS Record - - Are you sure? You can't undo this action afterwards. - + + Are you sure? You can't undo this action afterwards. + @@ -45,9 +42,9 @@ export default function DnsRecordDeleteAlertDialog({ Delete - - - - + + + + ); } diff --git a/app/components/dns-record-table-row.tsx b/app/components/dns-record-table-row.tsx index acb66287..5d208deb 100644 --- a/app/components/dns-record-table-row.tsx +++ b/app/components/dns-record-table-row.tsx @@ -1,20 +1,19 @@ import { - Tr, + Table, Text, - Td, IconButton, Flex, - Tooltip, HStack, Link, ButtonGroup, useClipboard, - useToast, - Hide, VStack, Show, + useBreakpointValue, } from '@chakra-ui/react'; import { EditIcon, DeleteIcon, RepeatIcon, CopyIcon, InfoOutlineIcon } from '@chakra-ui/icons'; +import { Tooltip } from '~/components/ui/tooltip'; +import { toaster } from '~/components/ui/toaster'; import { Form, useNavigate } from '@remix-run/react'; import DnsRecordName from './dns-record/dns-record-name'; @@ -34,37 +33,38 @@ export default function DnsRecordsTableRow({ onCopied, }: DnsRecordsTableRowProps) { const { baseDomain } = useEffectiveUser(); - const { onCopy } = useClipboard(`${dnsRecord.subdomain}.${baseDomain}`); + const clipboard = useClipboard({ value: `${dnsRecord.subdomain}.${baseDomain}` }); const navigate = useNavigate(); - const toast = useToast(); const handleOnCopy = () => { - onCopy(); + clipboard.copy(); onCopied(); }; + const isBelowSm = useBreakpointValue({ base: true, sm: false }); + return ( - - + + - + Type: {' '} {dnsRecord.type} - + Value: {' '} - + {dnsRecord.value} @@ -79,104 +79,106 @@ export default function DnsRecordsTableRow({ - + } aria-label="Lookup DNS record" variant="ghost" ml={{ xs: '0', sm: '2' }} - /> + > + + - - } - aria-label="Refresh DNS record" - variant="ghost" - onClick={handleOnCopy} - /> + + + + - +
- + } aria-label="Refresh DNS record" variant="ghost" type="submit" onClick={() => - toast({ + toaster.create({ title: `DNS Record "${dnsRecord.subdomain}" has been successfully renewed`, - position: 'bottom-right', - status: 'success', + // Todo! + // status: 'success', }) } - /> + > + + - + navigate(dnsRecord.id.toString())} - icon={} aria-label="Edit DNS record" variant="ghost" - /> + > + + - + onDelete(dnsRecord)} - icon={} aria-label="Delete DNS record" variant="ghost" type="submit" - /> + > + +
- - - {dnsRecord.type} - - - +
+ + {dnsRecord.type} + + + {dnsRecord.value} - - + + {dnsRecord.expiresAt.toLocaleDateString('en-US')}
- + } aria-label="Refresh DNS record" variant="ghost" type="submit" onClick={() => - toast({ + toaster.create({ title: `DNS Record "${dnsRecord.subdomain}" has been successfully renewed`, - position: 'bottom-right', - status: 'success', + // Todo! + // status: 'success', }) } - /> + > + +
- - +
+ - + navigate(dnsRecord.id.toString())} icon={} @@ -185,19 +187,20 @@ export default function DnsRecordsTableRow({ mr="1" /> - + onDelete(dnsRecord)} - icon={} aria-label="Delete DNS record" variant="ghost" type="submit" - /> + > + + - - - + +
+
); } diff --git a/app/components/dns-record/dns-record-name.tsx b/app/components/dns-record/dns-record-name.tsx index 378b7516..096df3f9 100644 --- a/app/components/dns-record/dns-record-name.tsx +++ b/app/components/dns-record/dns-record-name.tsx @@ -1,4 +1,5 @@ -import { Flex, Text, Tooltip } from '@chakra-ui/react'; +import { Flex, Text } from '@chakra-ui/react'; +import { Tooltip } from '~/components/ui/tooltip'; import type { DnsRecord } from '@prisma/client'; @@ -42,7 +43,7 @@ const DnsRecordName = ({ dnsRecord, baseDomain }: DnsRecordNameProps) => {
); - return tooltip ? {children} : <>{children}; + return tooltip ? {children} : <>{children}; }; export default DnsRecordName; diff --git a/app/components/dns-record/form-field.tsx b/app/components/dns-record/form-field.tsx index 3849412a..e8f106e8 100644 --- a/app/components/dns-record/form-field.tsx +++ b/app/components/dns-record/form-field.tsx @@ -1,4 +1,4 @@ -import { FormControl, FormErrorMessage, FormHelperText, FormLabel, HStack } from '@chakra-ui/react'; +import { HStack, Field } from '@chakra-ui/react'; interface FormFieldProps { label: string; @@ -16,11 +16,11 @@ export default function FormField({ children, }: FormFieldProps) { return ( - - {label} + + {label} {children} - {helpText && {helpText}} - {error} - + {helpText && {helpText}} + {error} + ); } diff --git a/app/components/dns-record/form.tsx b/app/components/dns-record/form.tsx index 1205cada..b4e6fff1 100644 --- a/app/components/dns-record/form.tsx +++ b/app/components/dns-record/form.tsx @@ -1,13 +1,5 @@ -import { AddIcon, EditIcon } from '@chakra-ui/icons'; -import { - Button, - Input, - InputGroup, - InputRightAddon, - Select, - Textarea, - VStack, -} from '@chakra-ui/react'; +import { AddIcon, createListCollection, EditIcon } from '@chakra-ui/icons'; +import { Button, Input, InputGroup, Portal, Select, Textarea, VStack } from '@chakra-ui/react'; import { Form } from '@remix-run/react'; import type { DnsRecord } from '@prisma/client'; import { useEffectiveUser } from '~/utils'; @@ -29,18 +21,27 @@ export default function DnsRecordForm({ dnsRecord, mode, errors }: dnsRecordForm const submitButtonText = useMemo(() => (mode === 'CREATE' ? 'Create' : 'Update'), [mode]); const SubmitButtonIcon = useMemo(() => (mode === 'CREATE' ? AddIcon : EditIcon), [mode]); + const recordTypes = createListCollection({ + items: [ + { label: 'A Record (IPv4 Address)', value: 'A' }, + { label: 'AAAA Record (IPv6 Address)', value: 'AAAA' }, + { label: 'CNAME Record (Domain Name)', value: 'CNAME' }, + { label: 'MX Record (Mail Server)', value: 'MX' }, + { label: 'TXT Record (Text Value)', value: 'TXT' }, + ], + }); + return (
- + - + - {`.${user.baseDomain}`} @@ -50,13 +51,32 @@ export default function DnsRecordForm({ dnsRecord, mode, errors }: dnsRecordForm helpText="DNS Record Type (IPv4, IPv6, Domain Name, Mail Server, Text) indicates what Value will be" error={errors?.fieldErrors.type?.join(' ')} > - + + + Choose DNS Record Type + + + + + + + + + + + + + + {recordTypes.items.map((type) => ( + + {type.label} + + + ))} + + + + {dnsRecord && } - ); diff --git a/app/components/dns-records-table.tsx b/app/components/dns-records-table.tsx index 553e0f2d..74147bcb 100644 --- a/app/components/dns-records-table.tsx +++ b/app/components/dns-records-table.tsx @@ -1,19 +1,14 @@ import { useState } from 'react'; import { Table, - Tr, - Th, - Thead, - Tbody, - TableContainer, - Td, Flex, Card, - useToast, useDisclosure, Spinner, - Hide, + Show, + useBreakpointValue, } from '@chakra-ui/react'; +import { toaster } from '~/components/ui/toaster'; import { useNavigation } from '@remix-run/react'; import DnsRecordDeleteAlertDialog from './dns-record-delete-alert-dialog'; @@ -26,20 +21,21 @@ interface DnsRecordsTableProps { } export default function DnsRecordsTable({ dnsRecords }: DnsRecordsTableProps) { - const toast = useToast(); const navigation = useNavigation(); const { - isOpen: isDeleteAlertDialogOpen, + open: isDeleteAlertDialogOpen, onOpen: onDeleteAlertDialogOpen, onClose: onDeleteAlertDialogClose, } = useDisclosure(); const [dnsRecordToDelete, setDnsRecordToDelete] = useState(); + const isBelowSm = useBreakpointValue({ base: true, sm: false }); + function onCopied() { - toast({ + toaster.create({ title: 'DNS Record was copied to clipboard', - position: 'bottom-right', - status: 'success', + // Todo! + // status: 'success', }); } @@ -60,47 +56,47 @@ export default function DnsRecordsTable({ dnsRecords }: DnsRecordsTableProps) { return ( <> - - - - - - - - - - - - - - {dnsRecords.map((dnsRecord) => { - const isLoading = - navigation.state === 'submitting' && - Number(navigation.formData?.get('id')) === dnsRecord.id; + + + + + + DNS Record + + + Type + Value + Expiration date + + + + + + {dnsRecords.map((dnsRecord) => { + const isLoading = + navigation.state === 'submitting' && + Number(navigation.formData?.get('id')) === dnsRecord.id; - return isLoading ? ( - - - - ) : ( - - ); - })} - -
DNS RecordTypeValueExpiration date - -
- - - -
-
-
+ return isLoading ? ( + + + + + + + + ) : ( + + ); + })} + + + - - - GitHub - - - Acceptable Use Policy - - + + + + + GitHub + + + Acceptable Use Policy + + + + + © {new Date().getFullYear()} Seneca Polytechnic. All rights reserved. diff --git a/app/components/header.tsx b/app/components/header.tsx index ca550c4c..6ce15ad4 100644 --- a/app/components/header.tsx +++ b/app/components/header.tsx @@ -5,13 +5,11 @@ import { Flex, HStack, Menu, - MenuButton, - MenuList, - MenuItem, IconButton, - Show, - Hide, Button, + Portal, + useBreakpointValue, + Show, } from '@chakra-ui/react'; import { TriangleUpIcon, LockIcon, HamburgerIcon } from '@chakra-ui/icons'; import { Form, Link, useFetcher } from '@remix-run/react'; @@ -25,6 +23,8 @@ export default function Header() { const user = useEffectiveUser(); const originalUser = useUser(); + const isBelowLg = useBreakpointValue({ base: true, lg: false }); + const fetcher = useFetcher(); return ( - + @@ -56,40 +56,45 @@ export default function Header() { - - + + - - } - size="auto" - style={{ backgroundColor: 'transparent' }} - /> - - - - - - DNS Records - - - - - - - - Certificate - - - - - + + + + + + + + + + + + + DNS Records + + + + + + + + Certificate + + + + + + + - @@ -98,46 +103,63 @@ export default function Header() { - - + + + + + + + + {user.username !== originalUser.username && ( + + + + + + + )} + fetcher.submit({}, { method: 'post', action: '/logout' })} + > - Stop Impersonating + Sign Out - - - )} - fetcher.submit({}, { method: 'post', action: '/logout' })}> - - Sign Out - - - - + + + + + ); diff --git a/app/components/instructions/faq-accordion.tsx b/app/components/instructions/faq-accordion.tsx index 0ad0f1ae..7092b3b9 100644 --- a/app/components/instructions/faq-accordion.tsx +++ b/app/components/instructions/faq-accordion.tsx @@ -1,11 +1,4 @@ -import { - AccordionItem, - AccordionButton, - Box, - AccordionPanel, - AccordionIcon, - Text, -} from '@chakra-ui/react'; +import { Accordion, Box, Text } from '@chakra-ui/react'; interface FaqAccordionProps { title: string; @@ -14,14 +7,16 @@ interface FaqAccordionProps { export default function FaqAccordion({ title, children }: FaqAccordionProps) { return ( - - + + {title} - - - {children} - + + + + {children} + + ); } diff --git a/app/components/landing-page/landing-page-card.tsx b/app/components/landing-page/landing-page-card.tsx index 4d137d2b..51e381dc 100644 --- a/app/components/landing-page/landing-page-card.tsx +++ b/app/components/landing-page/landing-page-card.tsx @@ -1,14 +1,4 @@ -import { - Button, - Card, - CardBody, - CardFooter, - CardHeader, - Flex, - Heading, - Link, - Text, -} from '@chakra-ui/react'; +import { Button, Card, Flex, Heading, Link, Text } from '@chakra-ui/react'; import { Link as RemixLink } from '@remix-run/react'; interface LandingPageCardProps { @@ -27,33 +17,35 @@ export default function LandingPageCard({ instructionsPath, }: LandingPageCardProps) { return ( - - + + {cardName} - - + + {cardDescription} {instructionsPath && ( To learn more, refer to our{' '} - - {instructionsPath === '/certificate/information' - ? 'information page' - : 'instructions page'} + + + {instructionsPath === '/certificate/information' + ? 'information page' + : 'instructions page'} + . )} - - - - - + + ); } diff --git a/app/routes/_auth.admin._index.tsx b/app/routes/_auth.admin._index.tsx index 689c1f72..09a7bd77 100644 --- a/app/routes/_auth.admin._index.tsx +++ b/app/routes/_auth.admin._index.tsx @@ -1,13 +1,5 @@ -import { - Flex, - FormControl, - FormHelperText, - Heading, - Input, - InputGroup, - InputLeftAddon, - useToast, -} from '@chakra-ui/react'; +import { Flex, Field, Heading, Input, InputGroup } from '@chakra-ui/react'; +import { toaster } from '~/components/ui/toaster'; import type { Certificate, User } from '@prisma/client'; import { useSubmit } from '@remix-run/react'; import { useCallback, useEffect, useState } from 'react'; @@ -128,8 +120,6 @@ export default function AdminRoute() { const { userCount, dnsRecordCount, certificateCount } = useTypedLoaderData(); const actionResult = useTypedActionData<{ users?: UserWithMetrics[]; isUserDeleted?: boolean }>(); - const toast = useToast(); - const [searchText, setSearchText] = useState(''); const reloadUsers = useCallback(() => { @@ -144,10 +134,10 @@ export default function AdminRoute() { useEffect(() => { if (actionResult?.isUserDeleted) { - toast({ + toaster.create({ title: 'User was deleted', - position: 'bottom-right', - status: 'success', + // Todo! + // status: 'success' }); reloadUsers(); } @@ -187,9 +177,8 @@ export default function AdminRoute() { Users - - - {} + + } width={{ sm: '100%', md: 300 }}> setSearchText(event.currentTarget.value)} /> - Please enter at least 3 characters to search. - + Please enter at least 3 characters to search. + diff --git a/app/routes/_auth.certificate.information.tsx b/app/routes/_auth.certificate.information.tsx index 2b024b58..96365265 100644 --- a/app/routes/_auth.certificate.information.tsx +++ b/app/routes/_auth.certificate.information.tsx @@ -1,18 +1,4 @@ -import { - Heading, - Text, - Link, - Box, - Tabs, - TabList, - Tab, - TabPanels, - TabPanel, - Accordion, - Flex, - ListItem, - OrderedList, -} from '@chakra-ui/react'; +import { Heading, Text, Link, Box, Tabs, Accordion, Flex, List } from '@chakra-ui/react'; import { Link as RemixLink } from '@remix-run/react'; import { LockIcon } from '@chakra-ui/icons'; @@ -67,20 +53,23 @@ export default function CertificateInstructionsRoute() { How to Request a Certificate - - - Go to the  - - Certificate Page - - - - Click the Request a Certificate button - - - You will be greeted with a loading page, and will receive an email once your certificate - has been issued or fails to be issued. - + + + + Go to the  + + Certificate Page + + + + Click the Request a Certificate button + + + You will be greeted with a loading page, and will receive an email once your + certificate has been issued or fails to be issued. + + + You can check if your DNS Records have a valid certificate by using an  @@ -88,7 +77,7 @@ export default function CertificateInstructionsRoute() { . - + Types of Certificates @@ -99,65 +88,63 @@ export default function CertificateInstructionsRoute() { requires the same ones: - - - Public Certificate - Private Key - Intermediate Chain - Full Chain - - - - - A digital document that proves the identity of an entity, such as a user or - organization, and establishes a secure connection between their web browser and a - website or server. It uses a pair of encryption keys, one public and one private, - and is issued by a trusted third party called a certification authority. For more - information  - - click here - - . - - - - - Used to decrypt data that has been encrypted with the corresponding public key, and - to digitally sign documents or messages. For more information  - - click here - - - - - - A set of certificates that are used to verify the authenticity of an SSL/TLS - certificate. They serve as a bridge between the SSL/TLS certificate and the root - Certificate Authority (CA) to establish a chain of trust, ensuring that the SSL/TLS - certificate is valid and secure. For more information  - - click here - - - - - A file that combines an SSL certificate (Public Certificate) with its intermediate - certificates, creating a trust connection between a server and a client. In simpler - terms, it makes sure online communication is secure and trustworthy. - - - + + + Public Certificate + Private Key + Intermediate Chain + Full Chain + + + + A digital document that proves the identity of an entity, such as a user or + organization, and establishes a secure connection between their web browser and a + website or server. It uses a pair of encryption keys, one public and one private, and + is issued by a trusted third party called a certification authority. For more + information  + + click here + + . + + + + + Used to decrypt data that has been encrypted with the corresponding public key, and to + digitally sign documents or messages. For more information  + + click here + + + + + + A set of certificates that are used to verify the authenticity of an SSL/TLS + certificate. They serve as a bridge between the SSL/TLS certificate and the root + Certificate Authority (CA) to establish a chain of trust, ensuring that the SSL/TLS + certificate is valid and secure. For more information  + + click here + + + + + A file that combines an SSL certificate (Public Certificate) with its intermediate + certificates, creating a trust connection between a server and a client. In simpler + terms, it makes sure online communication is secure and trustworthy. + + - + FAQ @@ -175,12 +162,12 @@ export default function CertificateInstructionsRoute() { The certificate that has been issued covers all  - - DNS Records + + DNS Records  that you have in the  - - DNS records table + + DNS records table @@ -202,7 +189,7 @@ export default function CertificateInstructionsRoute() { will be activated, allowing you to request a new certificate to maintain your online security. - + ); diff --git a/app/routes/_auth.dns-records.$dnsRecordId.tsx b/app/routes/_auth.dns-records.$dnsRecordId.tsx index e6f0dff5..1f1c8d81 100644 --- a/app/routes/_auth.dns-records.$dnsRecordId.tsx +++ b/app/routes/_auth.dns-records.$dnsRecordId.tsx @@ -105,8 +105,8 @@ export default function DnsRecordRoute() { Choose a subdomain Name. This will be used to build your domain.
(i.e. [subdomain].[username].mystudentproject.ca).
Then enter a Type and Value that will be mapped with your domain. For more info refer to our{' '} - - instructions page. + + instructions page. diff --git a/app/routes/_auth.dns-records._index.tsx b/app/routes/_auth.dns-records._index.tsx index a51094a0..d614866a 100644 --- a/app/routes/_auth.dns-records._index.tsx +++ b/app/routes/_auth.dns-records._index.tsx @@ -5,11 +5,9 @@ import { Flex, Heading, Stat, - StatLabel, - StatNumber, Text, Link, - Hide, + useBreakpointValue, Show, } from '@chakra-ui/react'; import { Link as RemixLink, isRouteErrorResponse, useRouteError } from '@remix-run/react'; @@ -118,6 +116,8 @@ export function ErrorBoundary() { export default function DnsRecordsIndexRoute() { const data = useTypedLoaderData(); + const isBelowSm = useBreakpointValue({ base: true, sm: false }); + return ( @@ -129,8 +129,8 @@ export default function DnsRecordsIndexRoute() { into effect as your new domain needs to be spread in DNS servers around the globe. The expiration date is initially set to 6 months after the creation date and you can renew the DNS record using the renew button next to the expiry date. For more info refer to our{' '} - - instructions page. + + instructions page. {data.dnsRecords.length ? ( @@ -142,19 +142,23 @@ export default function DnsRecordsIndexRoute() { px={4} py={2} > - - Total User DNS Records - + + Total User DNS Records + {data.userDnsRecordCount} / {data.userDnsRecordLimit} - - + + - - + + + + + - - - @@ -162,7 +166,9 @@ export default function DnsRecordsIndexRoute() { ) : (
- +
)} diff --git a/app/routes/_auth.dns-records.instructions.tsx b/app/routes/_auth.dns-records.instructions.tsx index 1972e0a8..ac3a5989 100644 --- a/app/routes/_auth.dns-records.instructions.tsx +++ b/app/routes/_auth.dns-records.instructions.tsx @@ -4,16 +4,12 @@ import { Text, Grid, VStack, - ListItem, - OrderedList, Link as ChakraLink, Accordion, Tabs, - TabList, - Tab, - TabPanels, - TabPanel, Flex, + List, + Box, } from '@chakra-ui/react'; import { Link } from '@remix-run/react'; import FaqAccordion from '~/components/instructions/faq-accordion'; @@ -41,154 +37,154 @@ export default function CertificateInstructionsRoute() { DNS Record Types - - - + + + A Record - - + + AAAA Record - - + + CNAME Record - - + + MX Record - - + + TXT Record - - + + - - - - - Purpose:{' '} - - Maps a domain name to an IPv4 address. + + + + Purpose:{' '} - - - Example:{' '} - - Your project's domain name is "my-project.user.mystudentproject.ca" and its IPv4 - address is "192.168.0.1". Create an A record to associate these two. + Maps a domain name to an IPv4 address. + + + + Example:{' '} - - - - - Purpose:{' '} - - Maps a domain name to an IPv6 address. + Your project's domain name is "my-project.user.mystudentproject.ca" and its IPv4 + address is "192.168.0.1". Create an A record to associate these two. + + + + + + Purpose:{' '} - - - Example:{' '} - - Your project's domain name is "my-ipv6-project.user.mystudentproject.ca" and its - IPv6 address is "2001:0db8:85a3:0000:0000:8a2e:0370:7334". Create an AAAA record - to associate these two. + Maps a domain name to an IPv6 address. + + + + Example:{' '} - - - - - Purpose:{' '} - - Maps a domain name to another domain name. + Your project's domain name is "my-ipv6-project.user.mystudentproject.ca" and its + IPv6 address is "2001:0db8:85a3:0000:0000:8a2e:0370:7334". Create an AAAA record to + associate these two. + + + + + + Purpose:{' '} - - - Example:{' '} - - Your project's domain name is "my-project.user.mystudentproject.ca", and you also - have a custom domain called "my-custom-domain.com". Create a CNAME record to map - "my-custom-domain.com" to "my-project.user.mystudentproject.ca". + Maps a domain name to another domain name. + + + + Example:{' '} - - - Note:{' '} - - When creating a CNAME record, remember to only include the domain name in the - value field. Including other parts of a URL, such as "https://" or a trailing "/", - can cause the CNAME record to fail to resolve correctly. + Your project's domain name is "my-project.user.mystudentproject.ca", and you also + have a custom domain called "my-custom-domain.com". Create a CNAME record to map + "my-custom-domain.com" to "my-project.user.mystudentproject.ca". + + + + Note:{' '} - - - - - Purpose:{' '} - - Directs email to a mail server. + When creating a CNAME record, remember to only include the domain name in the value + field. Including other parts of a URL, such as "https://" or a trailing "/", can + cause the CNAME record to fail to resolve correctly. + + + + + + Purpose:{' '} - - - Example:{' '} - - Your project's domain name is "my-project.user.mystudentproject.ca", and you have - a mail server running at "mail.my-mail-server.com". You wish people to contact you - at "@my-project.user.mystudentproject.ca". Create an MX record that maps - "my-project.user.mystudentproject.ca" to "mail.my-mail-server.com". + Directs email to a mail server. + + + + Example:{' '} - - - Note:{' '} - - An MX record has to point to an A or AAAA record, while pointing to a CNAME is - forbidden. In the example above, "mail.my-mail-server.com" has to be an A or AAAA - record. + Your project's domain name is "my-project.user.mystudentproject.ca", and you have a + mail server running at "mail.my-mail-server.com". You wish people to contact you at + "@my-project.user.mystudentproject.ca". Create an MX record that maps + "my-project.user.mystudentproject.ca" to "mail.my-mail-server.com". + + + + Note:{' '} - - - - - Purpose:{' '} - - Allows the domain owner to add arbitrary text to the DNS record, often used for - verification purposes. + An MX record has to point to an A or AAAA record, while pointing to a CNAME is + forbidden. In the example above, "mail.my-mail-server.com" has to be an A or AAAA + record. + + + + + + Purpose:{' '} - - - Example:{' '} - - You need to verify your domain ownership for a third-party service. They provide a - unique code "12345abcde". Create a TXT record with the value "12345abcde" for your - domain. + Allows the domain owner to add arbitrary text to the DNS record, often used for + verification purposes. + + + + Example:{' '} - - - + You need to verify your domain ownership for a third-party service. They provide a + unique code "12345abcde". Create a TXT record with the value "12345abcde" for your + domain. + + +
How to Create the first DNS Record? - - - Go to the{' '} - - - DNS records page. - - - - - Hit the "Create your first DNS Record!" button: On the DNS records page, click the - "Create your first DNS Record!" button to open the DNS record creation form. - - - Put appropriate values in fields: Fill in the required information for the selected - record type. (Refer to the previous section to learn about DNS record types and their - corresponding values.) Some fields are optional and they are used mainly for data - collection purposes, feel free to leave them blank. - - - Hit the "Create" button: After entering the required information, click the "Create" - button to generate your DNS record. - - + + + + Go to the{' '} + + + DNS records page. + + + + + Hit the "Create your first DNS Record!" button: On the DNS records page, click the + "Create your first DNS Record!" button to open the DNS record creation form. + + + Put appropriate values in fields: Fill in the required information for the selected + record type. (Refer to the previous section to learn about DNS record types and + their corresponding values.) Some fields are optional and they are used mainly for + data collection purposes, feel free to leave them blank. + + + Hit the "Create" button: After entering the required information, click the "Create" + button to generate your DNS record. + + + Remember to test your project's web address to ensure it is accessible and functioning correctly. Note that it may take some time for DNS changes to propagate. @@ -197,7 +193,8 @@ export default function CertificateInstructionsRoute() { For more information on DNS Records refer{' '} here. @@ -208,7 +205,7 @@ export default function CertificateInstructionsRoute() { FAQ - + DNS propagation time can vary depending on factors such as the specific DNS servers @@ -239,7 +236,7 @@ export default function CertificateInstructionsRoute() { for all students - + diff --git a/app/routes/_auth.dns-records.new.tsx b/app/routes/_auth.dns-records.new.tsx index 53c3f733..31654cee 100644 --- a/app/routes/_auth.dns-records.new.tsx +++ b/app/routes/_auth.dns-records.new.tsx @@ -57,8 +57,8 @@ export default function NewDnsRecordRoute() { Choose a subdomain Name. This will be used to build your domain.
(i.e. [subdomain].[username].mystudentproject.ca).
Then enter a Type and Value that will be mapped with your domain. For more info refer to our{' '} - - instructions page. + + instructions page. diff --git a/tsconfig.json b/tsconfig.json index 5c40b6a1..28b40367 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,16 +2,16 @@ "exclude": ["./test/e2e", "./playwright.config.ts"], "include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"], "compilerOptions": { - "lib": ["DOM", "DOM.Iterable", "ES2019"], + "lib": ["DOM", "DOM.Iterable", "ESNext"], "types": ["vitest/globals"], "isolatedModules": true, "esModuleInterop": true, "jsx": "react-jsx", "jsxImportSource": "react", - "module": "CommonJS", - "moduleResolution": "node", + "module": "ESNext", + "moduleResolution": "Bundler", "resolveJsonModule": true, - "target": "ES2019", + "target": "ESNext", "strict": true, "allowJs": true, "forceConsistentCasingInFileNames": true, From 2ba2e0bbc11de62e1da9c671ec7d8bfb2fff8192 Mon Sep 17 00:00:00 2001 From: TheoForger Date: Wed, 2 Apr 2025 20:25:39 -0400 Subject: [PATCH 05/13] Drop color mode --- app/components/ui/provider.tsx | 12 ------------ app/root.tsx | 6 +++--- 2 files changed, 3 insertions(+), 15 deletions(-) delete mode 100644 app/components/ui/provider.tsx diff --git a/app/components/ui/provider.tsx b/app/components/ui/provider.tsx deleted file mode 100644 index 1ca22df5..00000000 --- a/app/components/ui/provider.tsx +++ /dev/null @@ -1,12 +0,0 @@ -'use client'; - -import { ChakraProvider, defaultSystem } from '@chakra-ui/react'; -import { ColorModeProvider, type ColorModeProviderProps } from './color-mode'; - -export function Provider(props: ColorModeProviderProps) { - return ( - - - - ); -} diff --git a/app/root.tsx b/app/root.tsx index bfa2e024..81b345af 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -1,4 +1,3 @@ -import { Provider } from '~/components/ui/provider'; import { json } from '@remix-run/node'; import { Links, @@ -20,6 +19,7 @@ import type { ActionFunctionArgs, MetaFunction, } from '@remix-run/node'; +import { ChakraProvider } from '@chakra-ui/react'; export const meta: MetaFunction = () => [ { charset: 'utf-8' }, @@ -79,9 +79,9 @@ function Document({ children }: { children: React.ReactNode }) { export default function App() { return ( - + - + ); } From 5f9c120d4626c97018cf172111a685b83ee3b970 Mon Sep 17 00:00:00 2001 From: TheoForger Date: Wed, 2 Apr 2025 20:26:25 -0400 Subject: [PATCH 06/13] Drop `chakra-ui/icons` in favor of 'react-icons' --- app/components/admin/admin-metric-card.tsx | 8 +- app/components/admin/users-table.tsx | 7 +- .../certificate/certificate-display.tsx | 13 ++- app/components/certificate/description.tsx | 6 +- app/components/dns-record-table-row.tsx | 40 +++++-- app/components/dns-record/form.tsx | 21 +++- app/components/header.tsx | 21 ++-- app/components/ui/color-mode.tsx | 102 ------------------ app/routes/_auth.certificate.information.tsx | 14 +-- app/routes/_auth.dns-records._index.tsx | 18 +++- app/routes/_auth.dns-records.instructions.tsx | 17 +-- app/routes/login.tsx | 7 +- package-lock.json | 11 -- package.json | 1 - 14 files changed, 116 insertions(+), 170 deletions(-) delete mode 100644 app/components/ui/color-mode.tsx diff --git a/app/components/admin/admin-metric-card.tsx b/app/components/admin/admin-metric-card.tsx index 0a83dda4..bc770161 100644 --- a/app/components/admin/admin-metric-card.tsx +++ b/app/components/admin/admin-metric-card.tsx @@ -1,6 +1,6 @@ -import { InfoIcon } from '@chakra-ui/icons'; -import { Card, Text, Flex } from '@chakra-ui/react'; +import { Card, Text, Flex, Icon } from '@chakra-ui/react'; import { Tooltip } from '~/components/ui/tooltip'; +import { FaCircleInfo } from 'react-icons/fa6'; import type { IconType } from 'react-icons'; interface AdminMetricCardProps { @@ -41,7 +41,9 @@ export default function AdminMetricCard({ - + + + diff --git a/app/components/admin/users-table.tsx b/app/components/admin/users-table.tsx index e147e569..55bf6948 100644 --- a/app/components/admin/users-table.tsx +++ b/app/components/admin/users-table.tsx @@ -1,6 +1,5 @@ import { Table, Card, IconButton, Flex, HStack, Spinner, Text } from '@chakra-ui/react'; -import { DeleteIcon } from '@chakra-ui/icons'; -import { FaTheaterMasks } from 'react-icons/fa'; +import { FaRegTrashCan, FaMasksTheater } from 'react-icons/fa6'; import { Form, useNavigation } from '@remix-run/react'; import { Tooltip } from '~/components/ui/tooltip'; @@ -75,7 +74,7 @@ export default function UsersTable({ users, searchText }: UsersTableProps) { variant="ghost" disabled={user.username === username} > - + @@ -87,7 +86,7 @@ export default function UsersTable({ users, searchText }: UsersTableProps) { disabled={user.username === username} type="submit" > - + diff --git a/app/components/certificate/certificate-display.tsx b/app/components/certificate/certificate-display.tsx index 18c488a0..fe74c76e 100644 --- a/app/components/certificate/certificate-display.tsx +++ b/app/components/certificate/certificate-display.tsx @@ -8,8 +8,9 @@ import { IconButton, Accordion, useClipboard, + Icon, } from '@chakra-ui/react'; -import { DownloadIcon, CopyIcon } from '@chakra-ui/icons'; +import { FaDownload, FaCopy } from 'react-icons/fa6'; import { Tooltip } from '~/components/ui/tooltip'; import { toaster } from '~/components/ui/toaster'; import { Link } from '@remix-run/react'; @@ -63,7 +64,9 @@ export default function CertificateDisplay({ aria-label={`Copy ${title}`} onClick={clipboard.copy} > - + + + @@ -78,7 +81,7 @@ export default function CertificateDisplay({ }} aria-label={`Download ${title}`} > - toaster.create({ @@ -87,7 +90,9 @@ export default function CertificateDisplay({ // status: 'success', }) } - /> + > + + diff --git a/app/components/certificate/description.tsx b/app/components/certificate/description.tsx index 216227a1..3049db9b 100644 --- a/app/components/certificate/description.tsx +++ b/app/components/certificate/description.tsx @@ -1,4 +1,4 @@ -import { RepeatIcon, DeleteIcon } from '@chakra-ui/icons'; +import { FaRepeat, FaRegTrashCan } from 'react-icons/fa6'; import { Form, Link as RemixLink } from '@remix-run/react'; import { Flex, Text, Button, Stat, Wrap, WrapItem, Link } from '@chakra-ui/react'; import { toaster } from '~/components/ui/toaster'; @@ -48,7 +48,7 @@ export default function DescriptionSection({
@@ -65,7 +65,7 @@ export default function DescriptionSection({ }) } > - Delete + Delete
diff --git a/app/components/dns-record-table-row.tsx b/app/components/dns-record-table-row.tsx index 5d208deb..1227e4c0 100644 --- a/app/components/dns-record-table-row.tsx +++ b/app/components/dns-record-table-row.tsx @@ -10,8 +10,11 @@ import { VStack, Show, useBreakpointValue, + Icon, } from '@chakra-ui/react'; -import { EditIcon, DeleteIcon, RepeatIcon, CopyIcon, InfoOutlineIcon } from '@chakra-ui/icons'; +import { FaPenToSquare, FaRegTrashCan, FaRepeat, FaCopy } from 'react-icons/fa6'; +import { IoIosInformationCircleOutline } from 'react-icons/io'; + import { Tooltip } from '~/components/ui/tooltip'; import { toaster } from '~/components/ui/toaster'; @@ -88,13 +91,17 @@ export default function DnsRecordsTableRow({ variant="ghost" ml={{ xs: '0', sm: '2' }} > - + + + - + + + @@ -114,7 +121,9 @@ export default function DnsRecordsTableRow({ }) } > - + + + @@ -124,7 +133,9 @@ export default function DnsRecordsTableRow({ aria-label="Edit DNS record" variant="ghost" > - + + + @@ -134,7 +145,9 @@ export default function DnsRecordsTableRow({ variant="ghost" type="submit" > - + + + @@ -169,7 +182,9 @@ export default function DnsRecordsTableRow({ }) } > - + + + @@ -181,11 +196,14 @@ export default function DnsRecordsTableRow({ navigate(dnsRecord.id.toString())} - icon={} aria-label="Edit DNS record" variant="ghost" mr="1" - /> + > + + + + - + + + diff --git a/app/components/dns-record/form.tsx b/app/components/dns-record/form.tsx index b4e6fff1..dd95852d 100644 --- a/app/components/dns-record/form.tsx +++ b/app/components/dns-record/form.tsx @@ -1,5 +1,15 @@ -import { AddIcon, createListCollection, EditIcon } from '@chakra-ui/icons'; -import { Button, Input, InputGroup, Portal, Select, Textarea, VStack } from '@chakra-ui/react'; +import { FaPlus, FaPenToSquare } from 'react-icons/fa6'; +import { + Button, + Input, + InputGroup, + Portal, + Select, + Textarea, + VStack, + createListCollection, + Icon, +} from '@chakra-ui/react'; import { Form } from '@remix-run/react'; import type { DnsRecord } from '@prisma/client'; import { useEffectiveUser } from '~/utils'; @@ -19,7 +29,7 @@ export default function DnsRecordForm({ dnsRecord, mode, errors }: dnsRecordForm const user = useEffectiveUser(); const submitButtonText = useMemo(() => (mode === 'CREATE' ? 'Create' : 'Update'), [mode]); - const SubmitButtonIcon = useMemo(() => (mode === 'CREATE' ? AddIcon : EditIcon), [mode]); + const SubmitButtonIcon = useMemo(() => (mode === 'CREATE' ? FaPlus : FaPenToSquare), [mode]); const recordTypes = createListCollection({ items: [ @@ -110,7 +120,10 @@ export default function DnsRecordForm({ dnsRecord, mode, errors }: dnsRecordForm {dnsRecord && } ); diff --git a/app/components/header.tsx b/app/components/header.tsx index 6ce15ad4..70c39811 100644 --- a/app/components/header.tsx +++ b/app/components/header.tsx @@ -10,8 +10,9 @@ import { Portal, useBreakpointValue, Show, + Icon, } from '@chakra-ui/react'; -import { TriangleUpIcon, LockIcon, HamburgerIcon } from '@chakra-ui/icons'; +import { FaCaretUp, FaLock, FaBars } from 'react-icons/fa6'; import { Form, Link, useFetcher } from '@remix-run/react'; import { useEffectiveUser, useUser } from '~/utils'; @@ -42,15 +43,15 @@ export default function Header() { - - + + DNS Records - - + + Certificate @@ -66,7 +67,7 @@ export default function Header() { aria-label="Account Menu" style={{ backgroundColor: 'transparent' }} > - + @@ -75,16 +76,16 @@ export default function Header() { - - + + DNS Records - - + + Certificate diff --git a/app/components/ui/color-mode.tsx b/app/components/ui/color-mode.tsx deleted file mode 100644 index 2f0b95d0..00000000 --- a/app/components/ui/color-mode.tsx +++ /dev/null @@ -1,102 +0,0 @@ -'use client'; - -import type { IconButtonProps, SpanProps } from '@chakra-ui/react'; -import { ClientOnly, IconButton, Skeleton, Span } from '@chakra-ui/react'; -import { ThemeProvider, useTheme } from 'next-themes'; -import type { ThemeProviderProps } from 'next-themes'; -import * as React from 'react'; -import { LuMoon, LuSun } from 'react-icons/lu'; - -export interface ColorModeProviderProps extends ThemeProviderProps {} - -export function ColorModeProvider(props: ColorModeProviderProps) { - return ; -} - -export type ColorMode = 'light' | 'dark'; - -export interface UseColorModeReturn { - colorMode: ColorMode; - setColorMode: (colorMode: ColorMode) => void; - toggleColorMode: () => void; -} - -export function useColorMode(): UseColorModeReturn { - const { resolvedTheme, setTheme } = useTheme(); - const toggleColorMode = () => { - setTheme(resolvedTheme === 'dark' ? 'light' : 'dark'); - }; - return { - colorMode: resolvedTheme as ColorMode, - setColorMode: setTheme, - toggleColorMode, - }; -} - -export function useColorModeValue(light: T, dark: T) { - const { colorMode } = useColorMode(); - return colorMode === 'dark' ? dark : light; -} - -export function ColorModeIcon() { - const { colorMode } = useColorMode(); - return colorMode === 'dark' ? : ; -} - -interface ColorModeButtonProps extends Omit {} - -export const ColorModeButton = React.forwardRef( - function ColorModeButton(props, ref) { - const { toggleColorMode } = useColorMode(); - return ( - }> - - - - - ); - } -); - -export const LightMode = React.forwardRef( - function LightMode(props, ref) { - return ( - - ); - } -); - -export const DarkMode = React.forwardRef(function DarkMode(props, ref) { - return ( - - ); -}); diff --git a/app/routes/_auth.certificate.information.tsx b/app/routes/_auth.certificate.information.tsx index 96365265..01dbfacc 100644 --- a/app/routes/_auth.certificate.information.tsx +++ b/app/routes/_auth.certificate.information.tsx @@ -1,6 +1,6 @@ -import { Heading, Text, Link, Box, Tabs, Accordion, Flex, List } from '@chakra-ui/react'; +import { Heading, Text, Link, Box, Tabs, Accordion, Flex, List, Icon } from '@chakra-ui/react'; import { Link as RemixLink } from '@remix-run/react'; -import { LockIcon } from '@chakra-ui/icons'; +import { FaLock } from 'react-icons/fa6'; import FaqAccordion from '~/components/instructions/faq-accordion'; @@ -16,10 +16,12 @@ export default function CertificateInstructionsRoute() { When browsing the internet, you may have noticed a padlock ( - ) symbol next to the website's URL. This padlock - indicates whether the website has a valid SSL/TLS certificate or not. These certificates - are used to secure websites, encrypting and decrypting data exchanged between clients and - servers. + + + + ) symbol next to the website's URL. This padlock indicates whether the website has a valid + SSL/TLS certificate or not. These certificates are used to secure websites, encrypting and + decrypting data exchanged between clients and servers. An SSL/TLS Certificate is like a digital lock that keeps information exchanged between diff --git a/app/routes/_auth.dns-records._index.tsx b/app/routes/_auth.dns-records._index.tsx index d614866a..52a25a66 100644 --- a/app/routes/_auth.dns-records._index.tsx +++ b/app/routes/_auth.dns-records._index.tsx @@ -1,4 +1,4 @@ -import { AddIcon } from '@chakra-ui/icons'; +import { FaPlus } from 'react-icons/fa6'; import { Button, Center, @@ -9,6 +9,7 @@ import { Link, useBreakpointValue, Show, + Icon, } from '@chakra-ui/react'; import { Link as RemixLink, isRouteErrorResponse, useRouteError } from '@remix-run/react'; import { typedjson, useTypedLoaderData } from 'remix-typedjson'; @@ -151,12 +152,18 @@ export default function DnsRecordsIndexRoute() { @@ -167,7 +174,10 @@ export default function DnsRecordsIndexRoute() {
diff --git a/app/routes/_auth.dns-records.instructions.tsx b/app/routes/_auth.dns-records.instructions.tsx index ac3a5989..f76bbc66 100644 --- a/app/routes/_auth.dns-records.instructions.tsx +++ b/app/routes/_auth.dns-records.instructions.tsx @@ -1,4 +1,4 @@ -import { InfoOutlineIcon } from '@chakra-ui/icons'; +import { IoIosInformationCircleOutline } from 'react-icons/io'; import { Heading, Text, @@ -10,6 +10,7 @@ import { Flex, List, Box, + Icon, } from '@chakra-ui/react'; import { Link } from '@remix-run/react'; import FaqAccordion from '~/components/instructions/faq-accordion'; @@ -215,11 +216,15 @@ export default function CertificateInstructionsRoute() {
To help you monitor the propagation status of your DNS records, we provide an - information icon next to each record. - Clicking on this icon will take you to a DNS record propagation map, where you can - track the progress of your DNS changes in real-time. This map shows you which DNS - servers around the world have updated their cache with your new record information, - allowing you to gauge when your changes will become accessible globally. + information icon{' '} + + + {' '} + next to each record. Clicking on this icon will take you to a DNS record propagation + map, where you can track the progress of your DNS changes in real-time. This map + shows you which DNS servers around the world have updated their cache with your new + record information, allowing you to gauge when your changes will become accessible + globally. diff --git a/app/routes/login.tsx b/app/routes/login.tsx index 7c3f4c2e..0dd51181 100644 --- a/app/routes/login.tsx +++ b/app/routes/login.tsx @@ -8,8 +8,9 @@ import { GridItem, VStack, Flex, + Icon, } from '@chakra-ui/react'; -import { LockIcon } from '@chakra-ui/icons'; +import { FaLock } from 'react-icons/fa6'; import type { ActionFunctionArgs } from '@remix-run/node'; import { redirect } from '@remix-run/node'; import { Form } from '@remix-run/react'; @@ -50,7 +51,9 @@ export default function Login() { - + + +
diff --git a/package-lock.json b/package-lock.json index 32935a65..09b53183 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,6 @@ "dependencies": { "@authenio/samlify-node-xmllint": "^2.0.0", "@aws-sdk/client-route-53": "^3.777.0", - "@chakra-ui/icons": "^2.2.6", "@chakra-ui/react": "^3.15.0", "@emotion/react": "^11.14.0", "@emotion/server": "^11.11.0", @@ -2604,16 +2603,6 @@ "node": ">=6.9.0" } }, - "node_modules/@chakra-ui/icons": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/@chakra-ui/icons/-/icons-2.2.6.tgz", - "integrity": "sha512-WhNdb4hWMOhSGtgknV6INILg/sZDHFRJVwNRwO5B2JO4bPr+/9NPEf8jZuvcx5xMFi00qAC4qIvbMoN4ID0XDQ==", - "license": "MIT", - "peerDependencies": { - "@chakra-ui/react": ">=2.0.0", - "react": ">=18" - } - }, "node_modules/@chakra-ui/react": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/@chakra-ui/react/-/react-3.15.0.tgz", diff --git a/package.json b/package.json index 2d2041de..5b965211 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,6 @@ "dependencies": { "@authenio/samlify-node-xmllint": "^2.0.0", "@aws-sdk/client-route-53": "^3.777.0", - "@chakra-ui/icons": "^2.2.6", "@chakra-ui/react": "^3.15.0", "@emotion/react": "^11.14.0", "@emotion/server": "^11.11.0", From 883c2dabdb12fe5c68d53b3e1741d79873a816e4 Mon Sep 17 00:00:00 2001 From: TheoForger Date: Fri, 4 Apr 2025 17:31:34 -0400 Subject: [PATCH 07/13] Fix css and toast --- .../certificate/certificate-display.tsx | 149 ++++----- app/components/certificate/description.tsx | 106 ++++--- app/components/certificate/panels/aws.tsx | 2 +- app/components/certificate/panels/general.tsx | 2 +- app/components/certificate/panels/nginx.tsx | 2 +- app/components/certificate/panels/node.tsx | 2 +- app/components/dns-record-table-row.tsx | 297 +++++++++--------- app/components/dns-record/form.tsx | 2 +- app/components/dns-records-table.tsx | 8 +- app/components/footer.tsx | 62 ++-- app/routes/_auth.admin._index.tsx | 6 +- app/routes/_auth.dns-records.instructions.tsx | 2 +- app/theme/index.ts | 14 +- app/theme/styles.ts | 1 + 14 files changed, 334 insertions(+), 321 deletions(-) diff --git a/app/components/certificate/certificate-display.tsx b/app/components/certificate/certificate-display.tsx index fe74c76e..858be0e8 100644 --- a/app/components/certificate/certificate-display.tsx +++ b/app/components/certificate/certificate-display.tsx @@ -12,7 +12,7 @@ import { } from '@chakra-ui/react'; import { FaDownload, FaCopy } from 'react-icons/fa6'; import { Tooltip } from '~/components/ui/tooltip'; -import { toaster } from '~/components/ui/toaster'; +import { Toaster, toaster } from '~/components/ui/toaster'; import { Link } from '@remix-run/react'; interface CertificateDisplayProps { @@ -34,93 +34,94 @@ export default function CertificateDisplay({ if (clipboard.copied) { toaster.create({ title: `${title} was copied to the clipboard`, - // Todo! - // status: 'success', + type: 'success', }); } }, [title, clipboard.copied]); return ( - - - - {title} - - - - - - - - - - + <> + + + + + {title} + + - - toaster.create({ - title: `${title} is Downloaded`, - // Todo! - // status: 'success', - }) - } - > - + + - - - - {description} - - - - - Show/Hide - - - - - - + + + - {value} - - - - - - + + toaster.create({ + title: `${title} is Downloaded`, + type: 'success', + }) + } + > + + + + + + + {description} + + + + + Show/Hide + + + + + + + {value} + + + + + + + ); } diff --git a/app/components/certificate/description.tsx b/app/components/certificate/description.tsx index 3049db9b..b9182386 100644 --- a/app/components/certificate/description.tsx +++ b/app/components/certificate/description.tsx @@ -1,7 +1,7 @@ import { FaRepeat, FaRegTrashCan } from 'react-icons/fa6'; import { Form, Link as RemixLink } from '@remix-run/react'; import { Flex, Text, Button, Stat, Wrap, WrapItem, Link } from '@chakra-ui/react'; -import { toaster } from '~/components/ui/toaster'; +import { Toaster, toaster } from '~/components/ui/toaster'; interface DescriptionSectionProps { certRequested: boolean; @@ -21,57 +21,59 @@ export default function DescriptionSection({ link, }: DescriptionSectionProps) { return ( - - - {description} - {link && ( - <> -  To learn more, refer to our  - - information page - - . - + <> + + + + {description} + {link && ( + <> +  To learn more, refer to our  + + information page + + . + + )} + + {certRequested && !!validFromFormatted && !!validToFormatted && ( + + + Created On + {validFromFormatted} + + + Expires On + {validToFormatted} + + + + + + +
+ + +
+
+
+
)} -
- {certRequested && !!validFromFormatted && !!validToFormatted && ( - - - Created On - {validFromFormatted} - - - Expires On - {validToFormatted} - - - -
- -
-
- - -
-
-
-
- )} -
+
+ ); } diff --git a/app/components/certificate/panels/aws.tsx b/app/components/certificate/panels/aws.tsx index ee6b0968..c20f9f86 100644 --- a/app/components/certificate/panels/aws.tsx +++ b/app/components/certificate/panels/aws.tsx @@ -38,7 +38,7 @@ export default function AwsPanel({ certificate, privateKey, chain }: AwsPanelPro . - + - + - + - + - - - - - - - Type: - {' '} - {dnsRecord.type} - - - + <> + + + + + + + - Value: + Type: {' '} - - {dnsRecord.value} + {dnsRecord.type} + + + + + Value: + {' '} + + {dnsRecord.value} + + + + + Expiration Date: + {' '} + {dnsRecord.expiresAt.toLocaleDateString('en-US')} - - - - Expiration Date: - {' '} - {dnsRecord.expiresAt.toLocaleDateString('en-US')} - - - - - - + + + + + + + + + + + + + - + - - - - - - - + +
+ + + + + toaster.create({ + title: `DNS Record "${dnsRecord.subdomain}" has been successfully renewed`, + type: 'success', + }) + } + > + + + + + +
+ + navigate(dnsRecord.id.toString())} + aria-label="Edit DNS record" + variant="ghost" + > + + + + + + + onDelete(dnsRecord)} + aria-label="Delete DNS record" + variant="ghost" + type="submit" + > + + + + + +
+
+
+
+ + {dnsRecord.type} + + + + {dnsRecord.value} + - -
+ + + + {dnsRecord.expiresAt.toLocaleDateString('en-US')} + @@ -116,8 +178,7 @@ export default function DnsRecordsTableRow({ onClick={() => toaster.create({ title: `DNS Record "${dnsRecord.subdomain}" has been successfully renewed`, - // Todo! - // status: 'success', + type: 'success', }) } > @@ -127,100 +188,40 @@ export default function DnsRecordsTableRow({ - - navigate(dnsRecord.id.toString())} - aria-label="Edit DNS record" - variant="ghost" - > - - - - - - - onDelete(dnsRecord)} - aria-label="Delete DNS record" - variant="ghost" - type="submit" - > - - - - - -
- -
- - - {dnsRecord.type} - - - - {dnsRecord.value} - - - - - - {dnsRecord.expiresAt.toLocaleDateString('en-US')} -
- - - - - toaster.create({ - title: `DNS Record "${dnsRecord.subdomain}" has been successfully renewed`, - // Todo! - // status: 'success', - }) - } - > - - - - - -
-
-
- - - - - navigate(dnsRecord.id.toString())} - aria-label="Edit DNS record" - variant="ghost" - mr="1" - > - - - - - - - onDelete(dnsRecord)} - aria-label="Delete DNS record" - variant="ghost" - type="submit" - > - - - - - - - - -
- +
+ + + + + + navigate(dnsRecord.id.toString())} + aria-label="Edit DNS record" + variant="ghost" + mr="1" + > + + + + + + + onDelete(dnsRecord)} + aria-label="Delete DNS record" + variant="ghost" + type="submit" + > + + + + + + + + + + + ); } diff --git a/app/components/dns-record/form.tsx b/app/components/dns-record/form.tsx index dd95852d..fc04fbd8 100644 --- a/app/components/dns-record/form.tsx +++ b/app/components/dns-record/form.tsx @@ -61,7 +61,7 @@ export default function DnsRecordForm({ dnsRecord, mode, errors }: dnsRecordForm helpText="DNS Record Type (IPv4, IPv6, Domain Name, Mail Server, Text) indicates what Value will be" error={errors?.fieldErrors.type?.join(' ')} > - + Choose DNS Record Type diff --git a/app/components/dns-records-table.tsx b/app/components/dns-records-table.tsx index 74147bcb..977ebf9e 100644 --- a/app/components/dns-records-table.tsx +++ b/app/components/dns-records-table.tsx @@ -8,7 +8,7 @@ import { Show, useBreakpointValue, } from '@chakra-ui/react'; -import { toaster } from '~/components/ui/toaster'; +import { Toaster, toaster } from '~/components/ui/toaster'; import { useNavigation } from '@remix-run/react'; import DnsRecordDeleteAlertDialog from './dns-record-delete-alert-dialog'; @@ -34,8 +34,7 @@ export default function DnsRecordsTable({ dnsRecords }: DnsRecordsTableProps) { function onCopied() { toaster.create({ title: 'DNS Record was copied to clipboard', - // Todo! - // status: 'success', + type: 'success', }); } @@ -56,7 +55,8 @@ export default function DnsRecordsTable({ dnsRecords }: DnsRecordsTableProps) { return ( <> - + + diff --git a/app/components/footer.tsx b/app/components/footer.tsx index c79557b7..6788b7b1 100644 --- a/app/components/footer.tsx +++ b/app/components/footer.tsx @@ -3,38 +3,38 @@ import { Box, Container, Stack, HStack, Text, Link } from '@chakra-ui/react'; export default function Footer() { return ( - - - - - - GitHub - - - Acceptable Use Policy - - - - + + + + + + + GitHub + + + Acceptable Use Policy + + + + - © {new Date().getFullYear()} Seneca Polytechnic. All rights reserved. + © {new Date().getFullYear()} Seneca Polytechnic. All rights reserved. + ); diff --git a/app/routes/_auth.admin._index.tsx b/app/routes/_auth.admin._index.tsx index 09a7bd77..4d7e463b 100644 --- a/app/routes/_auth.admin._index.tsx +++ b/app/routes/_auth.admin._index.tsx @@ -1,5 +1,5 @@ import { Flex, Field, Heading, Input, InputGroup } from '@chakra-ui/react'; -import { toaster } from '~/components/ui/toaster'; +import { Toaster, toaster } from '~/components/ui/toaster'; import type { Certificate, User } from '@prisma/client'; import { useSubmit } from '@remix-run/react'; import { useCallback, useEffect, useState } from 'react'; @@ -136,8 +136,7 @@ export default function AdminRoute() { if (actionResult?.isUserDeleted) { toaster.create({ title: 'User was deleted', - // Todo! - // status: 'success' + type: 'success', }); reloadUsers(); } @@ -150,6 +149,7 @@ export default function AdminRoute() { return ( <> + Admin Dashboard diff --git a/app/routes/_auth.dns-records.instructions.tsx b/app/routes/_auth.dns-records.instructions.tsx index f76bbc66..179dc16d 100644 --- a/app/routes/_auth.dns-records.instructions.tsx +++ b/app/routes/_auth.dns-records.instructions.tsx @@ -217,7 +217,7 @@ export default function CertificateInstructionsRoute() { To help you monitor the propagation status of your DNS records, we provide an information icon{' '} - + {' '} next to each record. Clicking on this icon will take you to a DNS record propagation diff --git a/app/theme/index.ts b/app/theme/index.ts index 270d8bdb..6c38b720 100644 --- a/app/theme/index.ts +++ b/app/theme/index.ts @@ -6,9 +6,8 @@ import styles from './styles'; const theme = createSystem(defaultConfig, { theme: { recipes: { - Link: defineRecipe({ + link: defineRecipe({ base: { - color: 'brand.500', textDecor: 'underline', }, }), @@ -21,13 +20,22 @@ const theme = createSystem(defaultConfig, { colors: { brand: { solid: { value: '{colors.brand.500}' }, - contrast: { value: '{colors.brand.100}' }, + contrast: { value: 'white' }, fg: { value: '{colors.brand.700}' }, muted: { value: '{colors.brand.100}' }, subtle: { value: '{colors.brand.200}' }, emphasized: { value: '{colors.brand.300}' }, focusRing: { value: '{colors.brand.500}' }, }, + brand_gray: { + solid: { value: '{colors.brand_gray.500}' }, + contrast: { value: 'colors.brand_gray.100' }, + fg: { value: '{colors.brand_gray.700}' }, + muted: { value: '{colors.brand_gray.100}' }, + subtle: { value: '{colors.brand_gray.200}' }, + emphasized: { value: '{colors.brand_gray.300}' }, + focusRing: { value: '{colors.brand_gray.500}' }, + }, }, }, }, diff --git a/app/theme/styles.ts b/app/theme/styles.ts index ef4bdf6c..abd2e657 100644 --- a/app/theme/styles.ts +++ b/app/theme/styles.ts @@ -2,6 +2,7 @@ const styles = { html: { height: '100%', + colorPalette: 'brand', }, body: { height: '100%', From b981a6713b4cdccc0aa747e2686c50d0e858ba43 Mon Sep 17 00:00:00 2001 From: TheoForger Date: Fri, 4 Apr 2025 18:09:06 -0400 Subject: [PATCH 08/13] Fix footer and link colors --- app/components/dns-records-table.tsx | 2 +- app/components/footer.tsx | 32 +++++++++---------- app/routes/_auth.dns-records.instructions.tsx | 16 ++++------ 3 files changed, 22 insertions(+), 28 deletions(-) diff --git a/app/components/dns-records-table.tsx b/app/components/dns-records-table.tsx index 977ebf9e..e13f2b45 100644 --- a/app/components/dns-records-table.tsx +++ b/app/components/dns-records-table.tsx @@ -56,7 +56,7 @@ export default function DnsRecordsTable({ dnsRecords }: DnsRecordsTableProps) { return ( <> - + diff --git a/app/components/footer.tsx b/app/components/footer.tsx index 6788b7b1..538dd425 100644 --- a/app/components/footer.tsx +++ b/app/components/footer.tsx @@ -12,24 +12,22 @@ export default function Footer() { direction={{ base: 'column', md: 'row' }} fontSize={{ base: 'xs', sm: 'sm', md: 'md' }} > - + - - - GitHub - - - Acceptable Use Policy - - + + GitHub + + + Acceptable Use Policy + diff --git a/app/routes/_auth.dns-records.instructions.tsx b/app/routes/_auth.dns-records.instructions.tsx index 179dc16d..99e1da7c 100644 --- a/app/routes/_auth.dns-records.instructions.tsx +++ b/app/routes/_auth.dns-records.instructions.tsx @@ -164,11 +164,9 @@ export default function CertificateInstructionsRoute() { Go to the{' '} - - - DNS records page. - - + + DNS records page. + Hit the "Create your first DNS Record!" button: On the DNS records page, click the @@ -232,11 +230,9 @@ export default function CertificateInstructionsRoute() { Yes, there is a limitation on the number of DNS records you can create. Each user is allowed to create up to certain number DNS records for their projects. You could see your current limit at{' '} - - - DNS records page. - - + + DNS records page. + This limit helps manage resources efficiently and ensures fair usage of the platform for all students From 1b4e8c4da0524203301c85e761fd4d7aba20b6f3 Mon Sep 17 00:00:00 2001 From: TheoForger Date: Fri, 25 Apr 2025 18:45:05 -0400 Subject: [PATCH 09/13] Fix linter warnings --- app/components/dns-record/form.tsx | 6 +++++- app/components/header.tsx | 1 - 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/components/dns-record/form.tsx b/app/components/dns-record/form.tsx index fc04fbd8..d8290238 100644 --- a/app/components/dns-record/form.tsx +++ b/app/components/dns-record/form.tsx @@ -61,7 +61,11 @@ export default function DnsRecordForm({ dnsRecord, mode, errors }: dnsRecordForm helpText="DNS Record Type (IPv4, IPv6, Domain Name, Mail Server, Text) indicates what Value will be" error={errors?.fieldErrors.type?.join(' ')} > - + Choose DNS Record Type diff --git a/app/components/header.tsx b/app/components/header.tsx index 70c39811..6350c32d 100644 --- a/app/components/header.tsx +++ b/app/components/header.tsx @@ -10,7 +10,6 @@ import { Portal, useBreakpointValue, Show, - Icon, } from '@chakra-ui/react'; import { FaCaretUp, FaLock, FaBars } from 'react-icons/fa6'; import { Form, Link, useFetcher } from '@remix-run/react'; From b59328c6c7d1b15fbbe0bf156c8ad84953d0e512 Mon Sep 17 00:00:00 2001 From: TheoForger Date: Fri, 25 Apr 2025 19:05:37 -0400 Subject: [PATCH 10/13] Fix duplicate toasts --- .../certificate/certificate-display.tsx | 145 +++++---- app/components/certificate/description.tsx | 38 +-- app/components/dns-record-table-row.tsx | 293 +++++++++--------- app/components/dns-records-table.tsx | 3 +- app/routes/_auth.dns-records._index.tsx | 127 ++++---- 5 files changed, 302 insertions(+), 304 deletions(-) diff --git a/app/components/certificate/certificate-display.tsx b/app/components/certificate/certificate-display.tsx index 858be0e8..39caf7ce 100644 --- a/app/components/certificate/certificate-display.tsx +++ b/app/components/certificate/certificate-display.tsx @@ -12,7 +12,7 @@ import { } from '@chakra-ui/react'; import { FaDownload, FaCopy } from 'react-icons/fa6'; import { Tooltip } from '~/components/ui/tooltip'; -import { Toaster, toaster } from '~/components/ui/toaster'; +import { toaster } from '~/components/ui/toaster'; import { Link } from '@remix-run/react'; interface CertificateDisplayProps { @@ -40,88 +40,85 @@ export default function CertificateDisplay({ }, [title, clipboard.copied]); return ( - <> - - - - - {title} - - + + + + {title} + + + + + + + + + + - - + + toaster.create({ + title: `${title} is Downloaded`, + type: 'success', + }) + } + > + - - - - + + + {description} + + + + + Show/Hide + + + + + + - - toaster.create({ - title: `${title} is Downloaded`, - type: 'success', - }) - } - > - - - - - - - {description} - - - - - Show/Hide - - - - - - - {value} - - - - - - - + {value} + +
+ + + +
); } diff --git a/app/components/certificate/description.tsx b/app/components/certificate/description.tsx index b9182386..9ced4715 100644 --- a/app/components/certificate/description.tsx +++ b/app/components/certificate/description.tsx @@ -21,22 +21,22 @@ export default function DescriptionSection({ link, }: DescriptionSectionProps) { return ( - <> - - - - {description} - {link && ( - <> -  To learn more, refer to our  - - information page - - . - - )} - - {certRequested && !!validFromFormatted && !!validToFormatted && ( + + + {description} + {link && ( + <> +  To learn more, refer to our  + + information page + + . + + )} + + {certRequested && !!validFromFormatted && !!validToFormatted && ( + <> + Created On @@ -72,8 +72,8 @@ export default function DescriptionSection({ - )} - - + + )} + ); } diff --git a/app/components/dns-record-table-row.tsx b/app/components/dns-record-table-row.tsx index 3e234983..597a18a2 100644 --- a/app/components/dns-record-table-row.tsx +++ b/app/components/dns-record-table-row.tsx @@ -16,7 +16,7 @@ import { FaPenToSquare, FaRegTrashCan, FaRepeat, FaCopy } from 'react-icons/fa6' import { IoIosInformationCircleOutline } from 'react-icons/io'; import { Tooltip } from '~/components/ui/tooltip'; -import { Toaster, toaster } from '~/components/ui/toaster'; +import { toaster } from '~/components/ui/toaster'; import { Form, useNavigate } from '@remix-run/react'; import DnsRecordName from './dns-record/dns-record-name'; @@ -47,127 +47,65 @@ export default function DnsRecordsTableRow({ const isBelowSm = useBreakpointValue({ base: true, sm: false }); return ( - <> - - - - - - - + + + + + + + + Type: + {' '} + {dnsRecord.type} + + + - Type: + Value: {' '} - {dnsRecord.type} - - - - - Value: - {' '} - - {dnsRecord.value} - + + {dnsRecord.value} - - - - Expiration Date: - {' '} - {dnsRecord.expiresAt.toLocaleDateString('en-US')} - - - - - - - - - - - - - + + + + Expiration Date: + {' '} + {dnsRecord.expiresAt.toLocaleDateString('en-US')} + + + + + + - + - -
- - - - - toaster.create({ - title: `DNS Record "${dnsRecord.subdomain}" has been successfully renewed`, - type: 'success', - }) - } - > - - - - - -
- - navigate(dnsRecord.id.toString())} - aria-label="Edit DNS record" - variant="ghost" - > - - - - - - - onDelete(dnsRecord)} - aria-label="Delete DNS record" - variant="ghost" - type="submit" - > - - - - - -
-
-
-
- - {dnsRecord.type} - - - - {dnsRecord.value} - + + + + + + + - - - - {dnsRecord.expiresAt.toLocaleDateString('en-US')} -
+ + @@ -188,40 +126,99 @@ export default function DnsRecordsTableRow({ -
-
- - - - - navigate(dnsRecord.id.toString())} - aria-label="Edit DNS record" - variant="ghost" - mr="1" - > - - - - - - - onDelete(dnsRecord)} - aria-label="Delete DNS record" - variant="ghost" - type="submit" - > - - - - - - - - -
-
- + + navigate(dnsRecord.id.toString())} + aria-label="Edit DNS record" + variant="ghost" + > + + + + + + + onDelete(dnsRecord)} + aria-label="Delete DNS record" + variant="ghost" + type="submit" + > + + + + + + + + + + + {dnsRecord.type} + + + + {dnsRecord.value} + + + + + + {dnsRecord.expiresAt.toLocaleDateString('en-US')} +
+ + + + + toaster.create({ + title: `DNS Record "${dnsRecord.subdomain}" has been successfully renewed`, + type: 'success', + }) + } + > + + + + + +
+
+
+ + + + + navigate(dnsRecord.id.toString())} + aria-label="Edit DNS record" + variant="ghost" + mr="1" + > + + + + + + + onDelete(dnsRecord)} + aria-label="Delete DNS record" + variant="ghost" + type="submit" + > + + + + + + + + +
+ ); } diff --git a/app/components/dns-records-table.tsx b/app/components/dns-records-table.tsx index e13f2b45..58bc7158 100644 --- a/app/components/dns-records-table.tsx +++ b/app/components/dns-records-table.tsx @@ -8,7 +8,7 @@ import { Show, useBreakpointValue, } from '@chakra-ui/react'; -import { Toaster, toaster } from '~/components/ui/toaster'; +import { toaster } from '~/components/ui/toaster'; import { useNavigation } from '@remix-run/react'; import DnsRecordDeleteAlertDialog from './dns-record-delete-alert-dialog'; @@ -55,7 +55,6 @@ export default function DnsRecordsTable({ dnsRecords }: DnsRecordsTableProps) { return ( <> - diff --git a/app/routes/_auth.dns-records._index.tsx b/app/routes/_auth.dns-records._index.tsx index 52a25a66..d7788078 100644 --- a/app/routes/_auth.dns-records._index.tsx +++ b/app/routes/_auth.dns-records._index.tsx @@ -31,6 +31,7 @@ import type { LoaderFunctionArgs, ActionFunctionArgs } from '@remix-run/node'; import SeenErrorLayout from '~/components/errors/seen-error-layout'; import UnseenErrorLayout from '~/components/errors/unseen-error-layout'; import { getErrorMessageFromStatusCode } from '~/utils'; +import { Toaster } from '~/components/ui/toaster'; export type DnsRecordActionIntent = 'renew-dns-record' | 'delete-dns-record'; @@ -120,68 +121,72 @@ export default function DnsRecordsIndexRoute() { const isBelowSm = useBreakpointValue({ base: true, sm: false }); return ( - - - DNS Records - - - This table shows all of the DNS records that you have created. Once you create a new record, - you will immediately see that new record in the table. However, it will take some time to go - into effect as your new domain needs to be spread in DNS servers around the globe. The - expiration date is initially set to 6 months after the creation date and you can renew the - DNS record using the renew button next to the expiry date. For more info refer to our{' '} - - instructions page. - - - {data.dnsRecords.length ? ( - <> - - - Total User DNS Records - - {data.userDnsRecordCount} / {data.userDnsRecordLimit} - - + <> + + + + DNS Records + + + This table shows all of the DNS records that you have created. Once you create a new + record, you will immediately see that new record in the table. However, it will take some + time to go into effect as your new domain needs to be spread in DNS servers around the + globe. The expiration date is initially set to 6 months after the creation date and you + can renew the DNS record using the renew button next to the expiry date. For more info + refer to our{' '} + + instructions page. + + + {data.dnsRecords.length ? ( + <> + + + Total User DNS Records + + {data.userDnsRecordCount} / {data.userDnsRecordLimit} + + + + + + + + + + + + + + ) : ( +
- - - - - - + - - - - ) : ( -
- - - -
- )} - +
+ )} +
+ ); } From 65a882b690983764cd653ee0797ae91c6db8a57d Mon Sep 17 00:00:00 2001 From: TheoForger Date: Fri, 25 Apr 2025 19:13:46 -0400 Subject: [PATCH 11/13] Fix "Stop Impersonating" button --- app/components/header.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/components/header.tsx b/app/components/header.tsx index 6350c32d..726a8a0b 100644 --- a/app/components/header.tsx +++ b/app/components/header.tsx @@ -141,7 +141,7 @@ export default function Header() { value="revert-to-original-user" > @@ -152,7 +152,7 @@ export default function Header() { value="sign-out" onClick={() => fetcher.submit({}, { method: 'post', action: '/logout' })} > - + Sign Out From cfd02f5b32e998437bc37753f1fbc31c9d25bd4e Mon Sep 17 00:00:00 2001 From: TheoForger Date: Fri, 25 Apr 2025 19:27:24 -0400 Subject: [PATCH 12/13] Fix link color --- app/theme/index.ts | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/app/theme/index.ts b/app/theme/index.ts index 6c38b720..2802e377 100644 --- a/app/theme/index.ts +++ b/app/theme/index.ts @@ -21,21 +21,12 @@ const theme = createSystem(defaultConfig, { brand: { solid: { value: '{colors.brand.500}' }, contrast: { value: 'white' }, - fg: { value: '{colors.brand.700}' }, + fg: { value: '{colors.brand.500}' }, muted: { value: '{colors.brand.100}' }, subtle: { value: '{colors.brand.200}' }, emphasized: { value: '{colors.brand.300}' }, focusRing: { value: '{colors.brand.500}' }, }, - brand_gray: { - solid: { value: '{colors.brand_gray.500}' }, - contrast: { value: 'colors.brand_gray.100' }, - fg: { value: '{colors.brand_gray.700}' }, - muted: { value: '{colors.brand_gray.100}' }, - subtle: { value: '{colors.brand_gray.200}' }, - emphasized: { value: '{colors.brand_gray.300}' }, - focusRing: { value: '{colors.brand_gray.500}' }, - }, }, }, }, From 99dfff536cb57cb6d5a2fbd3510fc52dc1a896a9 Mon Sep 17 00:00:00 2001 From: TheoForger Date: Fri, 25 Apr 2025 19:39:59 -0400 Subject: [PATCH 13/13] Fix user table theme --- app/components/admin/users-table.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/components/admin/users-table.tsx b/app/components/admin/users-table.tsx index 55bf6948..770a3b13 100644 --- a/app/components/admin/users-table.tsx +++ b/app/components/admin/users-table.tsx @@ -26,7 +26,7 @@ export default function UsersTable({ users, searchText }: UsersTableProps) { const shouldShowUsers = !(isLoading || shouldShowInstruction || shouldShowNoUsersMessage); return ( - +