create-nexwire 4.2.4 → 4.2.5

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 (35) hide show
  1. package/express/.vscode/extensions.json +6 -0
  2. package/express/.vscode/settings.json +37 -26
  3. package/express/biome.json +99 -66
  4. package/express/package.json +30 -28
  5. package/express/src/database/schema.ts +2 -2
  6. package/express/src/resources/src/components/Checkbox.vue +32 -29
  7. package/express/src/resources/src/components/Input.vue +243 -223
  8. package/express/src/resources/src/components/InputGroup.vue +147 -145
  9. package/express/src/resources/src/components/InputPasswordToggle.vue +229 -213
  10. package/express/src/resources/src/components/Modal.vue +71 -55
  11. package/express/src/resources/src/components/Refresh.vue +19 -0
  12. package/express/src/resources/src/helpers/assets.ts +51 -0
  13. package/express/src/resources/src/main.ts +3 -1
  14. package/express/src/resources/src/plugins/gum.ts +1 -1
  15. package/express/src/resources/src/stores/auth.ts +184 -164
  16. package/express/src/resources/vite.config.ts +9 -2
  17. package/express/src/storage/database/nexwire.sqlite +0 -0
  18. package/hono/.vscode/extensions.json +6 -0
  19. package/hono/.vscode/settings.json +37 -26
  20. package/hono/biome.json +25 -2
  21. package/hono/package.json +24 -22
  22. package/hono/src/database/schema.ts +2 -2
  23. package/hono/src/resources/src/components/Checkbox.vue +32 -29
  24. package/hono/src/resources/src/components/Input.vue +243 -234
  25. package/hono/src/resources/src/components/InputGroup.vue +147 -149
  26. package/hono/src/resources/src/components/InputPasswordToggle.vue +229 -222
  27. package/hono/src/resources/src/components/Modal.vue +71 -55
  28. package/hono/src/resources/src/components/Refresh.vue +19 -0
  29. package/hono/src/resources/src/helpers/assets.ts +51 -0
  30. package/hono/src/resources/src/main.ts +3 -1
  31. package/hono/src/resources/src/plugins/gum.ts +1 -1
  32. package/hono/src/resources/src/stores/auth.ts +184 -164
  33. package/hono/src/resources/vite.config.ts +9 -2
  34. package/hono/src/storage/database/nexwire.sqlite +0 -0
  35. package/package.json +1 -1
@@ -1,149 +1,147 @@
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
- ref="inputRef"
23
- :id="inputId"
24
- type="text"
25
- class="form-control flex-grow-0 px-1 text-center rounded-0 rounded-start"
26
- :maxlength="maxLengthAttr"
27
- :value="props.modelValue"
28
- v-bind="$attrs"
29
- @input="updateModel" />
30
- <div
31
- class="position-absolute bottom-0 end-0 pe-1 text-secondary max"
32
- :class="{ 'd-none': !max }">
33
- {{ maxCounter }}
34
- </div>
35
- </div>
36
- <input
37
- type="text"
38
- class="form-control text-center border-start second-input"
39
- :style="props.half ? 'width: 50%;' : 'width: 62%;'"
40
- :placeholder="placeholder1"
41
- :value="props.calcdata"
42
- readonly />
43
- </div>
44
- </div>
45
- <div :id="`${inputId}Help`" class="form-text text-danger" :class="{ 'd-none': !props.err }">
46
- {{ props.err }}
47
- </div>
48
- </div>
49
- </template>
50
-
51
- <script setup lang="ts">
52
- import { computed, nextTick, onMounted, ref, useAttrs } from "vue";
53
-
54
- defineOptions({ name: "InputGroup", inheritAttrs: false });
55
-
56
- type InputGroupCategory = "number" | "decimal" | "mobile" | string;
57
-
58
- interface InputGroupProps {
59
- focus?: boolean;
60
- must?: boolean;
61
- half?: boolean;
62
- err?: string | boolean;
63
- modelValue?: string | number;
64
- category?: InputGroupCategory;
65
- calcdata?: string | number;
66
- hood?: string | number | boolean;
67
- }
68
-
69
- const $attrs = useAttrs();
70
- const inputRef = ref<HTMLInputElement | null>(null);
71
- const props = withDefaults(defineProps<InputGroupProps>(), {
72
- err: false,
73
- modelValue: "",
74
- calcdata: ""
75
- });
76
-
77
- const topclass = computed(() => ($attrs.topclass as string | undefined) || "mb-3");
78
- const inputId = computed(() => ($attrs.id as string | undefined) || "");
79
- const inputLabel = computed(() => ($attrs.label as string | undefined) || "");
80
- const placeholder1 = computed(() => ($attrs.placeholder1 as string | undefined) || "");
81
-
82
- const max = computed<number | null>(() => {
83
- const raw = $attrs.maxlength as string | number | undefined;
84
- return raw != null ? Number(raw) : null;
85
- });
86
-
87
- const maxLengthAttr = computed<number | undefined>(() => max.value ?? undefined);
88
- const maxCounter = computed(() =>
89
- max.value == null ? "" : max.value - String(props.modelValue).length
90
- );
91
-
92
- const hoodHtml = computed(() =>
93
- props.hood === false || props.hood == null ? "" : String(props.hood)
94
- );
95
- const hoodClass = computed(() => [
96
- "text-uppercase w-50 text-end text-primary fw-semibold",
97
- props.half ? "w-50" : "w-100",
98
- !props.hood && "d-none"
99
- ]);
100
-
101
- const emit = defineEmits<(event: "update:modelValue", value: string | number) => void>();
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
- const shouldFocus = props.focus !== false && props.focus !== undefined;
132
- if (!shouldFocus) return;
133
-
134
- nextTick(() => inputRef.value?.focus());
135
- });
136
- </script>
137
-
138
- <style lang="scss" scoped>
139
- .must {
140
- width: 4px;
141
- height: 4px;
142
- margin-left: 2px;
143
- margin-top: 5px;
144
- }
145
-
146
- .max {
147
- font-size: 0.6rem;
148
- }
149
- </style>
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
+ ref="inputRef"
23
+ :id="inputId"
24
+ type="text"
25
+ class="form-control flex-grow-0 px-1 text-center rounded-0 rounded-start"
26
+ :maxlength="maxLengthAttr"
27
+ :value="props.modelValue"
28
+ v-bind="$attrs"
29
+ @input="updateModel" />
30
+ <div
31
+ class="position-absolute bottom-0 end-0 pe-1 text-secondary max"
32
+ :class="{ 'd-none': !max }">
33
+ {{ maxCounter }}
34
+ </div>
35
+ </div>
36
+ <input
37
+ type="text"
38
+ class="form-control text-center border-start second-input"
39
+ :style="props.half ? 'width: 50%;' : 'width: 62%;'"
40
+ :placeholder="placeholder1"
41
+ :value="props.calcdata"
42
+ readonly />
43
+ </div>
44
+ </div>
45
+ <div :id="`${inputId}Help`" class="form-text text-danger" :class="{ 'd-none': !props.err }">
46
+ {{ props.err }}
47
+ </div>
48
+ </div>
49
+ </template>
50
+
51
+ <script setup lang="ts">
52
+ import { computed, nextTick, onMounted, ref, useAttrs } from "vue";
53
+
54
+ defineOptions({ name: "InputGroup", inheritAttrs: false });
55
+
56
+ type InputGroupCategory = "number" | "decimal" | "mobile" | string;
57
+
58
+ interface InputGroupProps {
59
+ focus?: boolean;
60
+ must?: boolean;
61
+ half?: boolean;
62
+ err?: string | boolean;
63
+ modelValue?: string | number;
64
+ category?: InputGroupCategory;
65
+ calcdata?: string | number;
66
+ hood?: string | number | boolean;
67
+ }
68
+
69
+ const $attrs = useAttrs();
70
+ const inputRef = ref<HTMLInputElement | null>(null);
71
+ const props = withDefaults(defineProps<InputGroupProps>(), {
72
+ err: false,
73
+ modelValue: "",
74
+ calcdata: ""
75
+ });
76
+
77
+ const topclass = computed(() => ($attrs.topclass as string | undefined) || "mb-3");
78
+ const inputId = computed(() => ($attrs.id as string | undefined) || "");
79
+ const inputLabel = computed(() => ($attrs.label as string | undefined) || "");
80
+ const placeholder1 = computed(() => ($attrs.placeholder1 as string | undefined) || "");
81
+
82
+ const max = computed<number | null>(() => {
83
+ const raw = $attrs.maxlength as string | number | undefined;
84
+ return raw != null ? Number(raw) : null;
85
+ });
86
+
87
+ const maxLengthAttr = computed<number | undefined>(() => max.value ?? undefined);
88
+ const maxCounter = computed(() => (max.value == null ? "" : max.value - String(props.modelValue).length));
89
+
90
+ const hoodHtml = computed(() => (props.hood === false || props.hood == null ? "" : String(props.hood)));
91
+ const hoodClass = computed(() => [
92
+ "text-uppercase w-50 text-end text-primary fw-semibold",
93
+ props.half ? "w-50" : "w-100",
94
+ !props.hood && "d-none"
95
+ ]);
96
+
97
+ const emit = defineEmits<(event: "update:modelValue", value: string | number) => void>();
98
+
99
+ const updateModel = (e: Event) => {
100
+ const target = e.target as HTMLInputElement;
101
+
102
+ if (props.category === "number") {
103
+ emit("update:modelValue", (target.value = target.value.replace(/[^\d]/gi, "")));
104
+ } else if (props.category === "decimal") {
105
+ let val = target.value;
106
+ val = val.replace(/[^0-9.]/g, "");
107
+
108
+ const parts = val.split(".");
109
+ if (parts.length > 2) {
110
+ val = `${parts[0]}.${parts.slice(1).join("")}`;
111
+ }
112
+
113
+ emit("update:modelValue", (target.value = val));
114
+ } else if (props.category === "mobile") {
115
+ const digits = target.value.replace(/[^\d]/g, "");
116
+ let val = digits;
117
+ if (target.value.includes("+")) {
118
+ val = `+${digits}`;
119
+ }
120
+ emit("update:modelValue", (target.value = val));
121
+ } else {
122
+ emit("update:modelValue", target.value);
123
+ }
124
+ };
125
+
126
+ onMounted(async () => {
127
+ const shouldFocus = props.focus !== false && props.focus !== undefined;
128
+ if (!shouldFocus) return;
129
+
130
+ await nextTick();
131
+ // preventScroll: focusing inside a modal must not scroll the modal/page
132
+ inputRef.value?.focus({ preventScroll: true });
133
+ });
134
+ </script>
135
+
136
+ <style lang="scss" scoped>
137
+ .must {
138
+ width: 4px;
139
+ height: 4px;
140
+ margin-left: 2px;
141
+ margin-top: 5px;
142
+ }
143
+
144
+ .max {
145
+ font-size: 0.6rem;
146
+ }
147
+ </style>