diff --git a/package-lock.json b/package-lock.json index 6d123375..c84dd653 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,8 +8,7 @@ "license": "MIT", "dependencies": { "hazardous": "^0.3.0", - "node-api-dotnet": "^0.9.18", - "vue-sonner": "^2.0.9" + "node-api-dotnet": "^0.9.18" }, "devDependencies": { "@electron/rebuild": "^4.0.2", @@ -28,6 +27,7 @@ "@tanstack/vue-virtual": "^3.13.18", "@types/jest": "^30.0.0", "@types/node": "^25.0.6", + "@vee-validate/zod": "^4.15.1", "@vitejs/plugin-vue": "^6.0.3", "@vitejs/plugin-vue-jsx": "^5.1.3", "@vueuse/core": "^14.1.0", @@ -61,6 +61,7 @@ "tailwind-merge": "^3.4.0", "tailwindcss": "^4.1.18", "tw-animate-css": "^1.4.0", + "vee-validate": "^4.15.1", "vite": "^7.3.1", "vue": "^3.5.26", "vue-i18n": "^11.2.8", @@ -68,8 +69,10 @@ "vue-marquee-text-component": "^2.0.1", "vue-router": "^4.6.4", "vue-showdown": "^4.2.0", + "vue-sonner": "^2.0.9", "worker-timers": "^8.0.28", - "yargs": "^18.0.0" + "yargs": "^18.0.0", + "zod": "^4.3.5" } }, "node_modules/@babel/code-frame": { @@ -103,6 +106,7 @@ "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -1260,7 +1264,6 @@ "dev": true, "license": "BSD-2-Clause", "optional": true, - "peer": true, "dependencies": { "cross-dirname": "^0.1.0", "debug": "^4.3.4", @@ -1282,7 +1285,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -1299,7 +1301,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "universalify": "^2.0.0" }, @@ -1314,7 +1315,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "engines": { "node": ">= 10.0.0" } @@ -5300,6 +5300,7 @@ "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/lodash": "*" } @@ -5690,6 +5691,33 @@ "win32" ] }, + "node_modules/@vee-validate/zod": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@vee-validate/zod/-/zod-4.15.1.tgz", + "integrity": "sha512-329Z4TDBE5Vx0FdbA8S4eR9iGCFFUNGbxjpQ20ff5b5wGueScjocUIx9JHPa79LTG06RnlUR4XogQsjN4tecKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^4.8.3", + "vee-validate": "4.15.1" + }, + "peerDependencies": { + "zod": "^3.24.0" + } + }, + "node_modules/@vee-validate/zod/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@vitejs/plugin-vue": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.3.tgz", @@ -6017,6 +6045,7 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -6050,6 +6079,7 @@ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -6814,6 +6844,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -7762,8 +7793,7 @@ "integrity": "sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==", "dev": true, "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/cross-env": { "version": "10.1.0", @@ -8064,6 +8094,7 @@ "integrity": "sha512-ce4Ogns4VMeisIuCSK0C62umG0lFy012jd8LMZ6w/veHUeX4fqfDrGe+HTWALAEwK6JwKP+dhPvizhArSOsFbg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "app-builder-lib": "26.4.0", "builder-util": "26.3.4", @@ -8468,7 +8499,6 @@ "dev": true, "hasInstallScript": true, "license": "MIT", - "peer": true, "dependencies": { "@electron/asar": "^3.2.1", "debug": "^4.1.1", @@ -8489,7 +8519,6 @@ "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", @@ -8647,7 +8676,8 @@ "resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.6.0.tgz", "integrity": "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/embla-carousel-reactive-utils": { "version": "8.6.0", @@ -8693,17 +8723,6 @@ "dev": true, "license": "MIT" }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, "node_modules/end-of-stream": { "version": "1.4.5", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", @@ -8832,6 +8851,7 @@ "dev": true, "hasInstallScript": true, "license": "MIT", + "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -8911,6 +8931,7 @@ "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -8971,6 +8992,7 @@ "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, "license": "MIT", + "peer": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -13440,14 +13462,16 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/lodash-es": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/lodash-unified": { "version": "1.0.3", @@ -14673,6 +14697,7 @@ "integrity": "sha512-l7pqLUFTI/+ESXn6k3nu30ZIzW5E2WZF/LaHJEpoq6ElcLD+wduZoB2kBN19du6K/4FDpPMazY2wJr+IndBtQw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vue/devtools-api": "^7.7.7" }, @@ -14843,7 +14868,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "commander": "^9.4.0" }, @@ -14861,7 +14885,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "engines": { "node": "^12.20.0 || >=14" } @@ -14882,6 +14905,7 @@ "integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==", "dev": true, "license": "MIT", + "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -15325,7 +15349,6 @@ "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "glob": "^7.1.3" }, @@ -15340,7 +15363,6 @@ "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -15362,7 +15384,6 @@ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -17200,7 +17221,6 @@ "integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "mkdirp": "^0.5.1", "rimraf": "~2.6.2" @@ -17264,7 +17284,6 @@ "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "minimist": "^1.2.6" }, @@ -17383,6 +17402,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -17892,6 +17912,33 @@ "dev": true, "license": "MIT" }, + "node_modules/vee-validate": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/vee-validate/-/vee-validate-4.15.1.tgz", + "integrity": "sha512-DkFsiTwEKau8VIxyZBGdO6tOudD+QoUBPuHj3e6QFqmbfCRj1ArmYWue9lEp6jLSWBIw4XPlDLjFIZNLdRAMSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^7.5.2", + "type-fest": "^4.8.3" + }, + "peerDependencies": { + "vue": "^3.4.26" + } + }, + "node_modules/vee-validate/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/verror": { "version": "1.10.1", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", @@ -17914,6 +17961,7 @@ "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", @@ -18007,6 +18055,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -18020,6 +18069,7 @@ "integrity": "sha512-SJ/NTccVyAoNUJmkM9KUqPcYlY+u8OVL1X5EW9RIs3ch5H2uERxyyIUI4MRxVCSOiEcupX9xNGde1tL9ZKpimA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vue/compiler-dom": "3.5.26", "@vue/compiler-sfc": "3.5.26", @@ -18216,6 +18266,7 @@ "version": "2.0.9", "resolved": "https://registry.npmjs.org/vue-sonner/-/vue-sonner-2.0.9.tgz", "integrity": "sha512-i6BokNlNDL93fpzNxN/LZSn6D6MzlO+i3qXt6iVZne3x1k7R46d5HlFB4P8tYydhgqOrRbIZEsnRd3kG7qGXyw==", + "dev": true, "license": "MIT", "peerDependencies": { "@nuxt/kit": "^4.0.3", @@ -18633,6 +18684,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/zod": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.5.tgz", + "integrity": "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==", + "dev": true, + "license": "MIT", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, "node_modules/zrender": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/zrender/-/zrender-6.0.0.tgz", diff --git a/package.json b/package.json index 7229f20e..8c3b5ce3 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "@tanstack/vue-virtual": "^3.13.18", "@types/jest": "^30.0.0", "@types/node": "^25.0.6", + "@vee-validate/zod": "^4.15.1", "@vitejs/plugin-vue": "^6.0.3", "@vitejs/plugin-vue-jsx": "^5.1.3", "@vueuse/core": "^14.1.0", @@ -81,6 +82,7 @@ "tailwind-merge": "^3.4.0", "tailwindcss": "^4.1.18", "tw-animate-css": "^1.4.0", + "vee-validate": "^4.15.1", "vite": "^7.3.1", "vue": "^3.5.26", "vue-i18n": "^11.2.8", @@ -88,8 +90,10 @@ "vue-marquee-text-component": "^2.0.1", "vue-router": "^4.6.4", "vue-showdown": "^4.2.0", + "vue-sonner": "^2.0.9", "worker-timers": "^8.0.28", - "yargs": "^18.0.0" + "yargs": "^18.0.0", + "zod": "^4.3.5" }, "build": { "appId": "app.vrcx", @@ -176,7 +180,6 @@ }, "dependencies": { "hazardous": "^0.3.0", - "node-api-dotnet": "^0.9.18", - "vue-sonner": "^2.0.9" + "node-api-dotnet": "^0.9.18" } } diff --git a/src/components/dialogs/GroupDialog/GroupDialog.vue b/src/components/dialogs/GroupDialog/GroupDialog.vue index c886caa0..b0673829 100644 --- a/src/components/dialogs/GroupDialog/GroupDialog.vue +++ b/src/components/dialogs/GroupDialog/GroupDialog.vue @@ -145,7 +145,7 @@ side="top" :content="t('dialog.group.actions.unrepresent_tooltip')"> @@ -185,10 +183,9 @@ @@ -201,10 +198,9 @@ side="top" :content="t('dialog.group.actions.request_join_tooltip')"> @@ -214,12 +210,7 @@ side="top" :content="t('dialog.group.actions.invite_required_tooltip')"> - @@ -229,10 +220,9 @@ side="top" :content="t('dialog.group.actions.join_group_tooltip')"> @@ -245,8 +235,7 @@ :variant=" groupDialog.ref.membershipStatus === 'userblocked' ? 'destructive' : 'outline' " - size="icon-lg" - style="margin-left: 5px"> + size="icon-lg"> diff --git a/src/components/dialogs/GroupDialog/GroupPostEditDialog.vue b/src/components/dialogs/GroupDialog/GroupPostEditDialog.vue index e05da586..abafa503 100644 --- a/src/components/dialogs/GroupDialog/GroupPostEditDialog.vue +++ b/src/components/dialogs/GroupDialog/GroupPostEditDialog.vue @@ -5,88 +5,105 @@ width="650px" append-to-body>
-

- - - - - - - - - - - - -
- - -
-
- - -
-
-
- - - - - + + +
+ + diff --git a/src/components/ui/field/FieldContent.vue b/src/components/ui/field/FieldContent.vue new file mode 100644 index 00000000..29c786a3 --- /dev/null +++ b/src/components/ui/field/FieldContent.vue @@ -0,0 +1,15 @@ + + + diff --git a/src/components/ui/field/FieldDescription.vue b/src/components/ui/field/FieldDescription.vue new file mode 100644 index 00000000..276822f2 --- /dev/null +++ b/src/components/ui/field/FieldDescription.vue @@ -0,0 +1,22 @@ + + + diff --git a/src/components/ui/field/FieldError.vue b/src/components/ui/field/FieldError.vue new file mode 100644 index 00000000..5967b5c5 --- /dev/null +++ b/src/components/ui/field/FieldError.vue @@ -0,0 +1,48 @@ + + + diff --git a/src/components/ui/field/FieldGroup.vue b/src/components/ui/field/FieldGroup.vue new file mode 100644 index 00000000..90f96281 --- /dev/null +++ b/src/components/ui/field/FieldGroup.vue @@ -0,0 +1,20 @@ + + + diff --git a/src/components/ui/field/FieldLabel.vue b/src/components/ui/field/FieldLabel.vue new file mode 100644 index 00000000..dfe78c8b --- /dev/null +++ b/src/components/ui/field/FieldLabel.vue @@ -0,0 +1,23 @@ + + + diff --git a/src/components/ui/field/FieldLegend.vue b/src/components/ui/field/FieldLegend.vue new file mode 100644 index 00000000..0153b329 --- /dev/null +++ b/src/components/ui/field/FieldLegend.vue @@ -0,0 +1,17 @@ + + + diff --git a/src/components/ui/field/FieldSeparator.vue b/src/components/ui/field/FieldSeparator.vue new file mode 100644 index 00000000..aca99626 --- /dev/null +++ b/src/components/ui/field/FieldSeparator.vue @@ -0,0 +1,23 @@ + + + diff --git a/src/components/ui/field/FieldSet.vue b/src/components/ui/field/FieldSet.vue new file mode 100644 index 00000000..93e3095d --- /dev/null +++ b/src/components/ui/field/FieldSet.vue @@ -0,0 +1,21 @@ + + + diff --git a/src/components/ui/field/FieldTitle.vue b/src/components/ui/field/FieldTitle.vue new file mode 100644 index 00000000..d66eea21 --- /dev/null +++ b/src/components/ui/field/FieldTitle.vue @@ -0,0 +1,20 @@ + + + diff --git a/src/components/ui/field/index.js b/src/components/ui/field/index.js new file mode 100644 index 00000000..f69aab3d --- /dev/null +++ b/src/components/ui/field/index.js @@ -0,0 +1,36 @@ +import { cva } from 'class-variance-authority'; + +export const fieldVariants = cva( + 'group/field flex w-full gap-3 data-[invalid=true]:text-destructive', + { + variants: { + orientation: { + vertical: ['flex-col [&>*]:w-full [&>.sr-only]:w-auto'], + horizontal: [ + 'flex-row items-center', + '[&>[data-slot=field-label]]:flex-auto', + 'has-[>[data-slot=field-content]]:items-start has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px' + ], + responsive: [ + 'flex-col [&>*]:w-full [&>.sr-only]:w-auto @md/field-group:flex-row @md/field-group:items-center @md/field-group:[&>*]:w-auto', + '@md/field-group:[&>[data-slot=field-label]]:flex-auto', + '@md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px' + ] + } + }, + defaultVariants: { + orientation: 'vertical' + } + } +); + +export { default as Field } from './Field.vue'; +export { default as FieldContent } from './FieldContent.vue'; +export { default as FieldDescription } from './FieldDescription.vue'; +export { default as FieldError } from './FieldError.vue'; +export { default as FieldGroup } from './FieldGroup.vue'; +export { default as FieldLabel } from './FieldLabel.vue'; +export { default as FieldLegend } from './FieldLegend.vue'; +export { default as FieldSeparator } from './FieldSeparator.vue'; +export { default as FieldSet } from './FieldSet.vue'; +export { default as FieldTitle } from './FieldTitle.vue'; diff --git a/src/components/ui/form/FormControl.vue b/src/components/ui/form/FormControl.vue new file mode 100644 index 00000000..28dc1b26 --- /dev/null +++ b/src/components/ui/form/FormControl.vue @@ -0,0 +1,17 @@ + + + diff --git a/src/components/ui/form/FormDescription.vue b/src/components/ui/form/FormDescription.vue new file mode 100644 index 00000000..d5503ab4 --- /dev/null +++ b/src/components/ui/form/FormDescription.vue @@ -0,0 +1,17 @@ + + + diff --git a/src/components/ui/form/FormItem.vue b/src/components/ui/form/FormItem.vue new file mode 100644 index 00000000..04ff8812 --- /dev/null +++ b/src/components/ui/form/FormItem.vue @@ -0,0 +1,20 @@ + + + diff --git a/src/components/ui/form/FormLabel.vue b/src/components/ui/form/FormLabel.vue new file mode 100644 index 00000000..3256d7d7 --- /dev/null +++ b/src/components/ui/form/FormLabel.vue @@ -0,0 +1,25 @@ + + + diff --git a/src/components/ui/form/FormMessage.vue b/src/components/ui/form/FormMessage.vue new file mode 100644 index 00000000..49e72a84 --- /dev/null +++ b/src/components/ui/form/FormMessage.vue @@ -0,0 +1,22 @@ + + + diff --git a/src/components/ui/form/index.js b/src/components/ui/form/index.js new file mode 100644 index 00000000..5818a579 --- /dev/null +++ b/src/components/ui/form/index.js @@ -0,0 +1,11 @@ +export { default as FormControl } from './FormControl.vue'; +export { default as FormDescription } from './FormDescription.vue'; +export { default as FormItem } from './FormItem.vue'; +export { default as FormLabel } from './FormLabel.vue'; +export { default as FormMessage } from './FormMessage.vue'; +export { FORM_ITEM_INJECTION_KEY } from './injectionKeys'; +export { + Form, + Field as FormField, + FieldArray as FormFieldArray +} from 'vee-validate'; diff --git a/src/components/ui/form/injectionKeys.js b/src/components/ui/form/injectionKeys.js new file mode 100644 index 00000000..533eabd5 --- /dev/null +++ b/src/components/ui/form/injectionKeys.js @@ -0,0 +1 @@ +export const FORM_ITEM_INJECTION_KEY = Symbol(); diff --git a/src/components/ui/form/useFormField.js b/src/components/ui/form/useFormField.js new file mode 100644 index 00000000..670d0197 --- /dev/null +++ b/src/components/ui/form/useFormField.js @@ -0,0 +1,31 @@ +import { computed, inject } from 'vue'; +import { FieldContextKey } from 'vee-validate'; + +import { FORM_ITEM_INJECTION_KEY } from './injectionKeys'; + +export function useFormField() { + const fieldContext = inject(FieldContextKey); + const fieldItemContext = inject(FORM_ITEM_INJECTION_KEY); + + if (!fieldContext) + throw new Error('useFormField should be used within '); + + const { name, errorMessage: error, meta } = fieldContext; + const id = fieldItemContext; + + const fieldState = { + valid: computed(() => meta.valid), + isDirty: computed(() => meta.dirty), + isTouched: computed(() => meta.touched), + error + }; + + return { + id, + name, + formItemId: `${id}-form-item`, + formDescriptionId: `${id}-form-item-description`, + formMessageId: `${id}-form-item-message`, + ...fieldState + }; +} diff --git a/src/components/ui/input-group/InputGroupButton.vue b/src/components/ui/input-group/InputGroupButton.vue index e07b1f1d..aca37671 100644 --- a/src/components/ui/input-group/InputGroupButton.vue +++ b/src/components/ui/input-group/InputGroupButton.vue @@ -13,6 +13,7 @@