create-nexgen 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. package/package.json +26 -0
  2. package/src/index.js +108 -0
  3. package/template/.dockerignore +14 -0
  4. package/template/.env +58 -0
  5. package/template/.env.example +59 -0
  6. package/template/.prettierignore +5 -0
  7. package/template/.prettierrc +8 -0
  8. package/template/README.md +447 -0
  9. package/template/drizzle.config.ts +29 -0
  10. package/template/eslint.config.js +52 -0
  11. package/template/gitignore-stub +24 -0
  12. package/template/package.json +96 -0
  13. package/template/public/assets/AuthLayout-CbswhpjJ.js +1 -0
  14. package/template/public/assets/Button-_7aQ7gHL.js +1 -0
  15. package/template/public/assets/Input-CLNJXmKc.css +1 -0
  16. package/template/public/assets/Input-z8GI8Aqo.js +1 -0
  17. package/template/public/assets/InputPasswordToggle-BxlzVGp3.js +1 -0
  18. package/template/public/assets/InputPasswordToggle-C77FI9Eg.css +1 -0
  19. package/template/public/assets/Layout-DotR1sQC.js +1 -0
  20. package/template/public/assets/Refresh-BdqsPPBC.js +1 -0
  21. package/template/public/assets/admin-ui-CU34rLdN.js +1 -0
  22. package/template/public/assets/bootstrap-icons-BeopsB42.woff +0 -0
  23. package/template/public/assets/bootstrap-icons-mSm7cUeB.woff2 +0 -0
  24. package/template/public/assets/dashboard-CwybEyLc.js +1 -0
  25. package/template/public/assets/dashboard-Dc4d-Pi7.css +1 -0
  26. package/template/public/assets/forgetPassword-CKEJaXsq.js +1 -0
  27. package/template/public/assets/index-Bleyx5dm.js +64 -0
  28. package/template/public/assets/index-DUw8E6Yg.css +1 -0
  29. package/template/public/assets/login-DC7PTlQF.js +1 -0
  30. package/template/public/assets/realtime-test-BPQdrFym.css +1 -0
  31. package/template/public/assets/realtime-test-tQZ0rBEJ.js +1 -0
  32. package/template/public/assets/register-3O7Qs28C.js +1 -0
  33. package/template/public/assets/resetPassword-A5AzMWKs.js +1 -0
  34. package/template/public/assets/verifyEmail-DDBEQHOv.js +1 -0
  35. package/template/public/index.html +17 -0
  36. package/template/src/database/migrations/mysql/0000_init.sql +73 -0
  37. package/template/src/database/migrations/mysql/meta/0000_snapshot.json +484 -0
  38. package/template/src/database/migrations/mysql/meta/_journal.json +13 -0
  39. package/template/src/database/schema.ts +4 -0
  40. package/template/src/env.ts +107 -0
  41. package/template/src/framework/cache/cache.ts +81 -0
  42. package/template/src/framework/database/connection.ts +168 -0
  43. package/template/src/framework/database/optional-db-drivers.d.ts +9 -0
  44. package/template/src/framework/database/paginate.ts +200 -0
  45. package/template/src/framework/database/schema.ts +26 -0
  46. package/template/src/framework/database/seed.ts +33 -0
  47. package/template/src/framework/events/dispatcher.ts +57 -0
  48. package/template/src/framework/facade.ts +27 -0
  49. package/template/src/framework/http/app.ts +61 -0
  50. package/template/src/framework/http/cors.ts +19 -0
  51. package/template/src/framework/http/logger.ts +85 -0
  52. package/template/src/framework/http/openapi.ts +34 -0
  53. package/template/src/framework/http/ratelimiter.ts +13 -0
  54. package/template/src/framework/http/router.ts +76 -0
  55. package/template/src/framework/http/static.ts +33 -0
  56. package/template/src/framework/http/validation.ts +24 -0
  57. package/template/src/framework/kernel.ts +40 -0
  58. package/template/src/framework/maker-cli/src/index.mjs +51 -0
  59. package/template/src/framework/maker-cli/src/levels/level-1/env-db.mjs +57 -0
  60. package/template/src/framework/maker-cli/src/levels/level-1/file-ops.mjs +30 -0
  61. package/template/src/framework/maker-cli/src/levels/level-1/flags.mjs +16 -0
  62. package/template/src/framework/maker-cli/src/levels/level-1/help.mjs +24 -0
  63. package/template/src/framework/maker-cli/src/levels/level-1/naming.mjs +13 -0
  64. package/template/src/framework/maker-cli/src/levels/level-1/process.mjs +47 -0
  65. package/template/src/framework/maker-cli/src/levels/level-2/db/core.mjs +299 -0
  66. package/template/src/framework/maker-cli/src/levels/level-2/db/index.mjs +177 -0
  67. package/template/src/framework/maker-cli/src/levels/level-2/deploy/core.mjs +635 -0
  68. package/template/src/framework/maker-cli/src/levels/level-2/deploy/index.mjs +145 -0
  69. package/template/src/framework/maker-cli/src/levels/level-2/module/core.mjs +707 -0
  70. package/template/src/framework/maker-cli/src/levels/level-2/module/index.mjs +116 -0
  71. package/template/src/framework/maker-cli/src/levels/level-2/runtime/build-frontend.mjs +16 -0
  72. package/template/src/framework/maker-cli/src/levels/level-2/runtime/core.mjs +311 -0
  73. package/template/src/framework/maker-cli/src/levels/level-2/runtime/index.mjs +71 -0
  74. package/template/src/framework/maker-cli/stubs/controller/openapi.ts.stub +55 -0
  75. package/template/src/framework/maker-cli/stubs/controller/openapi.with-model.ts.stub +56 -0
  76. package/template/src/framework/maker-cli/stubs/controller/plain.ts.stub +57 -0
  77. package/template/src/framework/maker-cli/stubs/controller/schema.plain.ts.stub +13 -0
  78. package/template/src/framework/maker-cli/stubs/controller/schema.ts.stub +32 -0
  79. package/template/src/framework/maker-cli/stubs/deploy/Dockerfile.bun.stub +49 -0
  80. package/template/src/framework/maker-cli/stubs/deploy/Dockerfile.pnpm.stub +53 -0
  81. package/template/src/framework/maker-cli/stubs/deploy/Dockerfile.stub +49 -0
  82. package/template/src/framework/maker-cli/stubs/deploy/Dockerfile.yarn.stub +53 -0
  83. package/template/src/framework/maker-cli/stubs/deploy/README.stub +55 -0
  84. package/template/src/framework/maker-cli/stubs/deploy/compose/mysql.server.stub +29 -0
  85. package/template/src/framework/maker-cli/stubs/deploy/compose/postgres.server.stub +29 -0
  86. package/template/src/framework/maker-cli/stubs/deploy/compose/sqlite.stub +29 -0
  87. package/template/src/framework/maker-cli/stubs/deploy/env/mysql.server.stub +73 -0
  88. package/template/src/framework/maker-cli/stubs/deploy/env/postgres.server.stub +73 -0
  89. package/template/src/framework/maker-cli/stubs/deploy/env/sqlite.stub +72 -0
  90. package/template/src/framework/maker-cli/stubs/deploy/scripts/auto-migrate.sh.stub +15 -0
  91. package/template/src/framework/maker-cli/stubs/deploy/server/README.stub +77 -0
  92. package/template/src/framework/maker-cli/stubs/deploy/server/compose/noredis.stub +118 -0
  93. package/template/src/framework/maker-cli/stubs/deploy/server/compose/redis.dev.stub +131 -0
  94. package/template/src/framework/maker-cli/stubs/deploy/server/compose/redis.stub +129 -0
  95. package/template/src/framework/maker-cli/stubs/deploy/server/env/local.example.stub +10 -0
  96. package/template/src/framework/maker-cli/stubs/deploy/server/env/noredis.stub +24 -0
  97. package/template/src/framework/maker-cli/stubs/deploy/server/env/redis.stub +24 -0
  98. package/template/src/framework/maker-cli/stubs/deploy/server/nginx-vhost/README.stub +15 -0
  99. package/template/src/framework/maker-cli/stubs/deploy/server/nginx-vhost/app.example.com.stub +12 -0
  100. package/template/src/framework/maker-cli/stubs/deploy/server/pgadmin/servers.stub +13 -0
  101. package/template/src/framework/maker-cli/stubs/deploy/server/redis/redis.conf.stub +6 -0
  102. package/template/src/framework/maker-cli/stubs/deploy/supervisor/noredis.stub +53 -0
  103. package/template/src/framework/maker-cli/stubs/deploy/supervisor/redis.stub +69 -0
  104. package/template/src/framework/maker-cli/stubs/deploy/workflow/local.json.stub +24 -0
  105. package/template/src/framework/maker-cli/stubs/deploy/workflow/remote.json.stub +20 -0
  106. package/template/src/framework/maker-cli/stubs/example/console.ts.stub +33 -0
  107. package/template/src/framework/maker-cli/stubs/example/controller.ts.stub +503 -0
  108. package/template/src/framework/maker-cli/stubs/example/job.ts.stub +74 -0
  109. package/template/src/framework/maker-cli/stubs/example/route.api.ts.stub +206 -0
  110. package/template/src/framework/maker-cli/stubs/example/schema.ts.stub +41 -0
  111. package/template/src/framework/maker-cli/stubs/job/name.ts.stub +24 -0
  112. package/template/src/framework/maker-cli/stubs/model/name.mysql.ts.stub +8 -0
  113. package/template/src/framework/maker-cli/stubs/model/name.postgresql.ts.stub +8 -0
  114. package/template/src/framework/maker-cli/stubs/model/name.sqlite.ts.stub +8 -0
  115. package/template/src/framework/maker-cli/stubs/notification/NotificationBell.vue.stub +218 -0
  116. package/template/src/framework/maker-cli/stubs/notification/controller.ts.stub +85 -0
  117. package/template/src/framework/maker-cli/stubs/notification/index.vue.stub +211 -0
  118. package/template/src/framework/maker-cli/stubs/notification/job.ts.stub +12 -0
  119. package/template/src/framework/maker-cli/stubs/notification/route.api.ts.stub +49 -0
  120. package/template/src/framework/maker-cli/stubs/notification/schema.ts.stub +25 -0
  121. package/template/src/framework/maker-cli/stubs/route/api.ts.stub +79 -0
  122. package/template/src/framework/maker-cli/stubs/route/plain.ts.stub +10 -0
  123. package/template/src/framework/maker-cli/stubs/schedule/name.ts.stub +35 -0
  124. package/template/src/framework/maker-cli/stubs/seeder/name.ts.stub +17 -0
  125. package/template/src/framework/modules/discover.ts +54 -0
  126. package/template/src/framework/modules/routes.ts +26 -0
  127. package/template/src/framework/notification/index.ts +109 -0
  128. package/template/src/framework/queue/clear.ts +20 -0
  129. package/template/src/framework/queue/queue.ts +213 -0
  130. package/template/src/framework/queue/ui.ts +104 -0
  131. package/template/src/framework/queue/worker.ts +33 -0
  132. package/template/src/framework/realtime/broadcast.ts +27 -0
  133. package/template/src/framework/realtime/index.ts +1 -0
  134. package/template/src/framework/realtime/socket-cookie.ts +65 -0
  135. package/template/src/framework/realtime/socket.ts +132 -0
  136. package/template/src/framework/realtime/types.ts +6 -0
  137. package/template/src/framework/realtime/ui.ts +16 -0
  138. package/template/src/framework/redis/client.ts +126 -0
  139. package/template/src/framework/scheduler/lock.ts +124 -0
  140. package/template/src/framework/scheduler/run.ts +26 -0
  141. package/template/src/framework/scheduler/scheduler.ts +82 -0
  142. package/template/src/framework/server.ts +147 -0
  143. package/template/src/framework/session/session.ts +116 -0
  144. package/template/src/framework/storage/storage.ts +743 -0
  145. package/template/src/framework/support/cookie.ts +78 -0
  146. package/template/src/framework/support/jwt.ts +45 -0
  147. package/template/src/framework/support/lifecycle.ts +35 -0
  148. package/template/src/framework/support/logger.ts +102 -0
  149. package/template/src/framework/support/mail.ts +43 -0
  150. package/template/src/framework/support/password.ts +23 -0
  151. package/template/src/framework/support/url.ts +25 -0
  152. package/template/src/middlewares/auth-middleware.ts +98 -0
  153. package/template/src/middlewares/role-middleware.ts +24 -0
  154. package/template/src/modules/auth/controllers/auth.controller.ts +445 -0
  155. package/template/src/modules/auth/controllers/auth.helpers.ts +110 -0
  156. package/template/src/modules/auth/controllers/auth.schema.ts +102 -0
  157. package/template/src/modules/auth/controllers/role.controller.ts +25 -0
  158. package/template/src/modules/auth/database/models/notifications.ts +22 -0
  159. package/template/src/modules/auth/database/models/role.ts +14 -0
  160. package/template/src/modules/auth/database/models/user.ts +46 -0
  161. package/template/src/modules/auth/database/seeders/role.ts +19 -0
  162. package/template/src/modules/auth/database/seeders/user.ts +33 -0
  163. package/template/src/modules/auth/jobs/forgetpass.ts +18 -0
  164. package/template/src/modules/auth/jobs/registeruser.ts +31 -0
  165. package/template/src/modules/auth/jobs/verifyemail.ts +18 -0
  166. package/template/src/modules/auth/routes/api.ts +151 -0
  167. package/template/src/modules/auth/routes/role.ts +39 -0
  168. package/template/src/modules/welcome/controllers/welcome.controller.ts +14 -0
  169. package/template/src/modules/welcome/controllers/welcome.schema.ts +6 -0
  170. package/template/src/modules/welcome/database/models/welcome.ts +6 -0
  171. package/template/src/modules/welcome/routes/api.ts +20 -0
  172. package/template/src/resources/index.html +16 -0
  173. package/template/src/resources/src/App.vue +5 -0
  174. package/template/src/resources/src/assets/css/styles.css +14934 -0
  175. package/template/src/resources/src/assets/css/styles.css.map +1 -0
  176. package/template/src/resources/src/assets/images/favicon/favicon.ico +0 -0
  177. package/template/src/resources/src/assets/images/favicon/favicon1.ico +0 -0
  178. package/template/src/resources/src/assets/images/logo-1.png +0 -0
  179. package/template/src/resources/src/assets/images/logo-dark-sm.png +0 -0
  180. package/template/src/resources/src/assets/images/logo-dark.png +0 -0
  181. package/template/src/resources/src/assets/images/logo-dark1.png +0 -0
  182. package/template/src/resources/src/assets/images/logo-sm.png +0 -0
  183. package/template/src/resources/src/assets/images/logo1.png +0 -0
  184. package/template/src/resources/src/assets/images/logo2.png +0 -0
  185. package/template/src/resources/src/assets/scss/custom.css +217 -0
  186. package/template/src/resources/src/assets/scss/custom.css.map +1 -0
  187. package/template/src/resources/src/assets/scss/custom.scss +1100 -0
  188. package/template/src/resources/src/components/Button.vue +35 -0
  189. package/template/src/resources/src/components/Checkbox.vue +29 -0
  190. package/template/src/resources/src/components/FloatButton.vue +36 -0
  191. package/template/src/resources/src/components/Href.vue +32 -0
  192. package/template/src/resources/src/components/Input.vue +227 -0
  193. package/template/src/resources/src/components/InputGroup.vue +153 -0
  194. package/template/src/resources/src/components/InputPasswordToggle.vue +226 -0
  195. package/template/src/resources/src/components/Modal.vue +102 -0
  196. package/template/src/resources/src/components/Pagebar.vue +28 -0
  197. package/template/src/resources/src/components/Refresh.vue +26 -0
  198. package/template/src/resources/src/components/Select.vue +390 -0
  199. package/template/src/resources/src/components/Spinner.vue +42 -0
  200. package/template/src/resources/src/components/Switch.vue +65 -0
  201. package/template/src/resources/src/components/TextArea.vue +121 -0
  202. package/template/src/resources/src/components/Toast.vue +56 -0
  203. package/template/src/resources/src/components/datatable/DataTableSkeleton.vue +99 -0
  204. package/template/src/resources/src/components/datatable/Pagination.vue +161 -0
  205. package/template/src/resources/src/components/datatable/SelectOpption.vue +54 -0
  206. package/template/src/resources/src/components/datatable/index.vue +237 -0
  207. package/template/src/resources/src/composables/useAuth.ts +52 -0
  208. package/template/src/resources/src/composables/useBrowserDetect.ts +5 -0
  209. package/template/src/resources/src/composables/useDialog.ts +5 -0
  210. package/template/src/resources/src/composables/useGum.ts +3 -0
  211. package/template/src/resources/src/composables/usePulse.ts +5 -0
  212. package/template/src/resources/src/env.d.ts +20 -0
  213. package/template/src/resources/src/helpers/nformatter.ts +10 -0
  214. package/template/src/resources/src/helpers/utils.ts +68 -0
  215. package/template/src/resources/src/layouts/AuthLayout.vue +20 -0
  216. package/template/src/resources/src/layouts/Layout/Footer.vue +23 -0
  217. package/template/src/resources/src/layouts/Layout/Header.vue +90 -0
  218. package/template/src/resources/src/layouts/Layout/Sidebar.vue +137 -0
  219. package/template/src/resources/src/layouts/Layout/index.vue +76 -0
  220. package/template/src/resources/src/main.ts +27 -0
  221. package/template/src/resources/src/pages/auth/forgetPassword.vue +76 -0
  222. package/template/src/resources/src/pages/auth/login.vue +93 -0
  223. package/template/src/resources/src/pages/auth/register.vue +130 -0
  224. package/template/src/resources/src/pages/auth/resetPassword.vue +119 -0
  225. package/template/src/resources/src/pages/auth/verifyEmail.vue +60 -0
  226. package/template/src/resources/src/pages/dashboard/index.vue +76 -0
  227. package/template/src/resources/src/plugins/axios.ts +33 -0
  228. package/template/src/resources/src/plugins/browserDetect.ts +55 -0
  229. package/template/src/resources/src/plugins/dialog.ts +167 -0
  230. package/template/src/resources/src/plugins/gum.ts +343 -0
  231. package/template/src/resources/src/plugins/pulse.ts +141 -0
  232. package/template/src/resources/src/plugins/routeProgress.ts +87 -0
  233. package/template/src/resources/src/router/index.ts +85 -0
  234. package/template/src/resources/src/stores/admin-ui.ts +148 -0
  235. package/template/src/resources/src/stores/auth.ts +151 -0
  236. package/template/src/resources/tsconfig.json +19 -0
  237. package/template/src/resources/vite.config.ts +43 -0
  238. package/template/src/storage/logs/app.log +20179 -0
  239. package/template/src/storage/logs/fatal.log +727 -0
  240. package/template/tsconfig.json +20 -0
@@ -0,0 +1,35 @@
1
+ <template>
2
+ <button
3
+ class="d-flex justify-content-center align-items-center custom-btn shadow-none"
4
+ :type="props.type"
5
+ v-bind="$attrs">
6
+ <slot v-if="hasDefaultSlot"></slot>
7
+ <template v-else>
8
+ <span v-if="props.label" class="text-capitalize" :class="{ 'me-1': props.icon }">{{
9
+ props.label
10
+ }}</span>
11
+ <span v-if="props.icon"><i :class="props.icon"></i></span>
12
+ </template>
13
+ </button>
14
+ </template>
15
+
16
+ <script setup lang="ts">
17
+ import { computed, useSlots } from "vue";
18
+
19
+ interface ButtonProps {
20
+ label?: string;
21
+ icon?: string;
22
+ type?: "button" | "submit" | "reset";
23
+ }
24
+
25
+ defineOptions({ name: "Button", inheritAttrs: false });
26
+
27
+ const slots = useSlots();
28
+ const props = withDefaults(defineProps<ButtonProps>(), {
29
+ type: "button"
30
+ });
31
+
32
+ const hasDefaultSlot = computed(() => Boolean(slots.default?.().length));
33
+ </script>
34
+
35
+ <style lang="scss" scoped></style>
@@ -0,0 +1,29 @@
1
+ <template>
2
+ <div class="form-check mb-0" :class="props.topclass">
3
+ <input
4
+ :id="props.id"
5
+ v-model="model"
6
+ class="form-check-input shadow-none border-secondary"
7
+ type="checkbox"
8
+ v-bind="$attrs" />
9
+ <label v-if="props.label" class="form-check-label" :for="props.id">{{ props.label }}</label>
10
+ </div>
11
+ </template>
12
+
13
+ <script setup lang="ts">
14
+ defineOptions({ name: "Checkbox", inheritAttrs: false });
15
+
16
+ interface CheckboxProps {
17
+ id?: string;
18
+ label?: string;
19
+ topclass?: string;
20
+ }
21
+
22
+ const props = defineProps<CheckboxProps>();
23
+
24
+ type CheckboxModel = boolean | Array<string | number>;
25
+
26
+ const model = defineModel<CheckboxModel>({ default: false });
27
+ </script>
28
+
29
+ <style lang="scss" scoped></style>
@@ -0,0 +1,36 @@
1
+ <template>
2
+ <div
3
+ class="float-button position-fixed text-center removeprintarea"
4
+ :style="floatStyle"
5
+ v-bind="$attrs">
6
+ <slot></slot>
7
+ </div>
8
+ </template>
9
+
10
+ <script setup lang="ts">
11
+ import { computed } from "vue";
12
+
13
+ interface FloatButtonProps {
14
+ top?: string;
15
+ right?: string;
16
+ zIndex?: number;
17
+ }
18
+
19
+ const props = withDefaults(defineProps<FloatButtonProps>(), {
20
+ top: "200px",
21
+ right: "0",
22
+ zIndex: 100
23
+ });
24
+
25
+ const floatStyle = computed(() => ({
26
+ top: props.top,
27
+ right: props.right,
28
+ zIndex: props.zIndex
29
+ }));
30
+ </script>
31
+
32
+ <style lang="scss" scoped>
33
+ .float-button {
34
+ border-radius: 0 5px 5px 5px;
35
+ }
36
+ </style>
@@ -0,0 +1,32 @@
1
+ <template>
2
+ <a :href="String(props.to)" class="d-flex align-items-center" v-bind="$attrs">
3
+ <slot v-if="hasDefaultSlot"></slot>
4
+ <template v-else>
5
+ <span v-if="props.label" class="text-capitalize" :class="{ 'me-1': props.icon }">{{
6
+ props.label
7
+ }}</span>
8
+ <span v-if="props.icon"><i :class="props.icon"></i></span>
9
+ </template>
10
+ </a>
11
+ </template>
12
+
13
+ <script setup lang="ts">
14
+ import { computed, useSlots } from "vue";
15
+
16
+ interface HrefProps {
17
+ label?: string;
18
+ icon?: string;
19
+ to?: string | number;
20
+ }
21
+
22
+ defineOptions({ name: "Href", inheritAttrs: false });
23
+
24
+ const slots = useSlots();
25
+ const props = withDefaults(defineProps<HrefProps>(), {
26
+ to: "#"
27
+ });
28
+
29
+ const hasDefaultSlot = computed(() => Boolean(slots.default?.().length));
30
+ </script>
31
+
32
+ <style lang="scss" scoped></style>
@@ -0,0 +1,227 @@
1
+ <template>
2
+ <div :class="topclass">
3
+ <div class="position-relative">
4
+ <label
5
+ :for="inputId"
6
+ class="d-flex align-items-center mb-1"
7
+ :class="{ 'd-none': !inputLabel }">
8
+ <div class="position-relative">
9
+ <span class="text-capitalize" v-html="inputLabel"></span>
10
+ <span
11
+ class="position-absolute text-danger rounded-circle bg-danger must"
12
+ :class="{ 'd-none': !props.must }"></span>
13
+ </div>
14
+ <div
15
+ class="text-end ms-auto text-primary fw-semibold"
16
+ :class="{ 'd-none': !props.hood }"
17
+ style="font-size: 12px; margin-top: 0.15rem"
18
+ v-html="hoodHtml"></div>
19
+ </label>
20
+ <input
21
+ class="form-control"
22
+ :value="props.modelValue"
23
+ :maxlength="maxLengthAttr"
24
+ :readonly="props.readonly"
25
+ v-bind="$attrs"
26
+ :autocomplete="inputAutocomplete"
27
+ @input="updateModel" />
28
+ <div
29
+ class="position-absolute bottom-0 end-0 pe-1 text-secondary max"
30
+ :class="{ 'd-none': !max }">
31
+ {{ maxCounter }}
32
+ </div>
33
+ </div>
34
+ <div
35
+ :id="`${inputId}Help`"
36
+ class="form-text mt-1 text-danger"
37
+ :class="{ 'd-none': !props.err }">
38
+ {{ props.err }}
39
+ </div>
40
+ </div>
41
+ </template>
42
+
43
+ <script setup lang="ts">
44
+ import { computed, onMounted, nextTick, useAttrs } from "vue";
45
+ import useBrowserDetect from "../composables/useBrowserDetect";
46
+
47
+ defineOptions({ name: "Input", inheritAttrs: false });
48
+ const { isFirefox } = useBrowserDetect();
49
+
50
+ const $attrs = useAttrs();
51
+ type InputCategory =
52
+ | "number"
53
+ | "decimal"
54
+ | "+decimal-"
55
+ | "mobile"
56
+ | "tax-period"
57
+ | "bin"
58
+ | "challan-number"
59
+ | string;
60
+
61
+ interface InputProps {
62
+ focus?: boolean;
63
+ must?: boolean;
64
+ err?: string | boolean;
65
+ modelValue?: string | number;
66
+ category?: InputCategory;
67
+ hood?: string | boolean | number;
68
+ readonly?: boolean;
69
+ }
70
+
71
+ const props = withDefaults(defineProps<InputProps>(), {
72
+ err: false,
73
+ modelValue: ""
74
+ });
75
+
76
+ const topclass = computed(() => ($attrs.topclass as string | undefined) || "mb-2");
77
+ const inputId = computed(() => ($attrs.id as string | undefined) || "");
78
+ const inputLabel = computed(() => ($attrs.label as string | undefined) || "");
79
+ const inputType = computed(() => ($attrs.type as string | undefined) || "text");
80
+
81
+ const max = computed<number | null>(() => {
82
+ const raw = $attrs.maxlength as string | number | undefined;
83
+ return raw != null ? Number(raw) : null;
84
+ });
85
+
86
+ const inputAutocomplete = computed(() => {
87
+ const attrAutocomplete = $attrs.autocomplete as string | undefined;
88
+ if (attrAutocomplete) {
89
+ return attrAutocomplete;
90
+ }
91
+ return ["number", "decimal"].includes(props.category ?? "") ? "off" : "on";
92
+ });
93
+
94
+ const maxLengthAttr = computed<number | undefined>(() => max.value ?? undefined);
95
+
96
+ const hoodHtml = computed(() =>
97
+ props.hood === false || props.hood == null ? "" : String(props.hood)
98
+ );
99
+
100
+ const maxCounter = computed(() => {
101
+ if (max.value == null) {
102
+ return "";
103
+ }
104
+
105
+ if (!isFirefox && inputType.value === "month") {
106
+ return "";
107
+ }
108
+
109
+ return max.value - String(props.modelValue).length;
110
+ });
111
+
112
+ const emit = defineEmits<{
113
+ (event: "update:modelValue", value: string | number): void;
114
+ }>();
115
+ const updateModel = (e: Event) => {
116
+ const target = e.target as HTMLInputElement;
117
+
118
+ if (props.category === "number") {
119
+ emit("update:modelValue", (target.value = target.value.replace(/[^\d]/gi, "")));
120
+ } else if (props.category === "decimal") {
121
+ let val = target.value;
122
+
123
+ // Remove everything except digits, decimal point, and minus sign
124
+ val = val.replace(/[^0-9.]/g, "");
125
+
126
+ // Allow only one decimal point
127
+ const parts = val.split(".");
128
+ if (parts.length > 2) {
129
+ val = parts[0] + "." + parts.slice(1).join("");
130
+ }
131
+
132
+ emit("update:modelValue", (target.value = val));
133
+ } else if (props.category === "+decimal-") {
134
+ let val = target.value;
135
+
136
+ // Remove everything except digits, decimal point, and minus sign
137
+ val = val.replace(/[^0-9.-]/g, ""); // if need minus sign
138
+
139
+ // Move minus sign to the front if it exists anywhere
140
+ const isNegative = val.includes("-");
141
+ val = val.replace(/-/g, ""); // remove all minus signs
142
+ if (isNegative) {
143
+ val = "-" + val;
144
+ }
145
+
146
+ // Allow only one decimal point
147
+ const parts = val.split(".");
148
+ if (parts.length > 2) {
149
+ val = parts[0] + "." + parts.slice(1).join("");
150
+ }
151
+
152
+ emit("update:modelValue", (target.value = val));
153
+ } else if (props.category === "mobile") {
154
+ let digits = target.value.replace(/[^\d]/g, ""); // only digits
155
+ let val = digits;
156
+ if (target.value.includes("+")) {
157
+ val = "+" + digits;
158
+ }
159
+ emit("update:modelValue", (target.value = val));
160
+ } else if (props.category === "tax-period") {
161
+ let val = target.value.replace(/[^\d-]/g, ""); // Only numbers and hyphen
162
+ val = val.replace(/-/g, ""); // Remove all hyphens
163
+ val = val.slice(0, 6); // Only 6 digits (YYYYMM)
164
+
165
+ if (val.length > 4) {
166
+ let year = val.slice(0, 4);
167
+ let month = val.slice(4, 6);
168
+
169
+ // Only correct if both month digits entered
170
+ if (month.length === 2) {
171
+ let m = parseInt(month, 10);
172
+ // Clamp month between 1 and 12
173
+ if (m < 1) m = 1;
174
+ if (m > 12) m = 12;
175
+ // Always pad to 2 digits
176
+ month = m.toString().padStart(2, "0");
177
+ }
178
+
179
+ val = year + "-" + month;
180
+ }
181
+
182
+ emit("update:modelValue", (target.value = val));
183
+ } else if (props.category === "bin") {
184
+ let digits = target.value.replace(/[^\d]/g, "");
185
+ digits = digits.slice(0, 14);
186
+ let formatted = digits;
187
+ if (digits.length > 9) {
188
+ formatted = digits.slice(0, 9) + "-" + digits.slice(9, 14);
189
+ }
190
+ emit("update:modelValue", (target.value = formatted));
191
+ } else if (props.category === "challan-number") {
192
+ let digits = target.value.replace(/[^\d]/g, "");
193
+ digits = digits.slice(0, 16);
194
+ let formatted = digits;
195
+ if (digits.length > 4) {
196
+ formatted = digits.slice(0, 4) + "-" + digits.slice(4, 16);
197
+ }
198
+ emit("update:modelValue", (target.value = formatted));
199
+ } else {
200
+ emit("update:modelValue", target.value);
201
+ }
202
+ };
203
+
204
+ onMounted(() => {
205
+ if (!props.focus || !inputId.value) {
206
+ return;
207
+ }
208
+
209
+ nextTick(() => {
210
+ const input = document.querySelector(`#${inputId.value}`) as HTMLInputElement | null;
211
+ input?.focus();
212
+ });
213
+ });
214
+ </script>
215
+
216
+ <style lang="scss" scoped>
217
+ .must {
218
+ width: 4px;
219
+ height: 4px;
220
+ margin-left: 2px;
221
+ margin-top: 5px;
222
+ }
223
+
224
+ .max {
225
+ font-size: 0.6rem;
226
+ }
227
+ </style>
@@ -0,0 +1,153 @@
1
+ <template>
2
+ <div :class="topclass">
3
+ <div class="position-relative">
4
+ <label
5
+ :for="inputId"
6
+ class="text-capitalize d-flex align-items-center mb-1"
7
+ :class="{ 'd-none': !inputLabel }">
8
+ <div class="position-relative">
9
+ <span class="text-capitalize" v-html="inputLabel"></span>
10
+ <span
11
+ class="position-absolute text-danger rounded-circle bg-danger must"
12
+ :class="{ 'd-none': !props.must }"></span>
13
+ </div>
14
+ <div
15
+ :class="hoodClass"
16
+ style="font-size: 12px; margin-top: 0.15rem"
17
+ v-html="hoodHtml"></div>
18
+ </label>
19
+ <div class="input-group">
20
+ <div class="position-relative" :style="props.half ? 'width: 50%;' : 'width: 35%;'">
21
+ <input
22
+ :id="inputId"
23
+ type="text"
24
+ class="form-control flex-grow-0 px-1 text-center rounded-0 rounded-start"
25
+ :maxlength="maxLengthAttr"
26
+ :value="props.modelValue"
27
+ v-bind="$attrs"
28
+ @input="updateModel" />
29
+ <div
30
+ class="position-absolute bottom-0 end-0 pe-1 text-secondary max"
31
+ :class="{ 'd-none': !max }">
32
+ {{ maxCounter }}
33
+ </div>
34
+ </div>
35
+ <input
36
+ type="text"
37
+ class="form-control text-center border-start second-input"
38
+ :style="props.half ? 'width: 50%;' : 'width: 62%;'"
39
+ :placeholder="placeholder1"
40
+ :value="props.calcdata"
41
+ readonly />
42
+ </div>
43
+ </div>
44
+ <div :id="`${inputId}Help`" class="form-text text-danger" :class="{ 'd-none': !props.err }">
45
+ {{ props.err }}
46
+ </div>
47
+ </div>
48
+ </template>
49
+
50
+ <script setup lang="ts">
51
+ import { computed, nextTick, onMounted, useAttrs } from "vue";
52
+
53
+ defineOptions({ name: "InputGroup", inheritAttrs: false });
54
+
55
+ type InputGroupCategory = "number" | "decimal" | "mobile" | string;
56
+
57
+ interface InputGroupProps {
58
+ focus?: boolean;
59
+ must?: boolean;
60
+ half?: boolean;
61
+ err?: string | boolean;
62
+ modelValue?: string | number;
63
+ category?: InputGroupCategory;
64
+ calcdata?: string | number;
65
+ hood?: string | number | boolean;
66
+ }
67
+
68
+ const $attrs = useAttrs();
69
+ const props = withDefaults(defineProps<InputGroupProps>(), {
70
+ err: false,
71
+ modelValue: "",
72
+ calcdata: ""
73
+ });
74
+
75
+ const topclass = computed(() => ($attrs.topclass as string | undefined) || "mb-3");
76
+ const inputId = computed(() => ($attrs.id as string | undefined) || "");
77
+ const inputLabel = computed(() => ($attrs.label as string | undefined) || "");
78
+ const placeholder1 = computed(() => ($attrs.placeholder1 as string | undefined) || "");
79
+
80
+ const max = computed<number | null>(() => {
81
+ const raw = $attrs.maxlength as string | number | undefined;
82
+ return raw != null ? Number(raw) : null;
83
+ });
84
+
85
+ const maxLengthAttr = computed<number | undefined>(() => max.value ?? undefined);
86
+ const maxCounter = computed(() =>
87
+ max.value == null ? "" : max.value - String(props.modelValue).length
88
+ );
89
+
90
+ const hoodHtml = computed(() =>
91
+ props.hood === false || props.hood == null ? "" : String(props.hood)
92
+ );
93
+ const hoodClass = computed(() => [
94
+ "text-uppercase w-50 text-end text-primary fw-semibold",
95
+ props.half ? "w-50" : "w-100",
96
+ !props.hood && "d-none"
97
+ ]);
98
+
99
+ const emit = defineEmits<{
100
+ (event: "update:modelValue", value: string | number): void;
101
+ }>();
102
+
103
+ const updateModel = (e: Event) => {
104
+ const target = e.target as HTMLInputElement;
105
+
106
+ if (props.category === "number") {
107
+ emit("update:modelValue", (target.value = target.value.replace(/[^\d]/gi, "")));
108
+ } else if (props.category === "decimal") {
109
+ let val = target.value;
110
+ val = val.replace(/[^0-9.]/g, "");
111
+
112
+ const parts = val.split(".");
113
+ if (parts.length > 2) {
114
+ val = parts[0] + "." + parts.slice(1).join("");
115
+ }
116
+
117
+ emit("update:modelValue", (target.value = val));
118
+ } else if (props.category === "mobile") {
119
+ const digits = target.value.replace(/[^\d]/g, "");
120
+ let val = digits;
121
+ if (target.value.includes("+")) {
122
+ val = "+" + digits;
123
+ }
124
+ emit("update:modelValue", (target.value = val));
125
+ } else {
126
+ emit("update:modelValue", target.value);
127
+ }
128
+ };
129
+
130
+ onMounted(() => {
131
+ if (!props.focus || !inputId.value) {
132
+ return;
133
+ }
134
+
135
+ nextTick(() => {
136
+ const input = document.querySelector(`#${inputId.value}`) as HTMLInputElement | null;
137
+ input?.focus();
138
+ });
139
+ });
140
+ </script>
141
+
142
+ <style lang="scss" scoped>
143
+ .must {
144
+ width: 4px;
145
+ height: 4px;
146
+ margin-left: 2px;
147
+ margin-top: 5px;
148
+ }
149
+
150
+ .max {
151
+ font-size: 0.6rem;
152
+ }
153
+ </style>