srcdev-nuxt-forms 3.0.0 → 4.1.0

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 (87) hide show
  1. package/assets/styles/ally/_utils.css +20 -0
  2. package/assets/styles/ally/_variables.css +8 -0
  3. package/assets/styles/ally/index.css +2 -0
  4. package/assets/styles/forms/index.css +2 -0
  5. package/assets/styles/forms/themes/_error.css +85 -0
  6. package/assets/styles/forms/themes/_ghost.css +85 -0
  7. package/assets/styles/forms/themes/_input-action-underlined.css +20 -0
  8. package/assets/styles/forms/themes/_input-action.css +20 -0
  9. package/assets/styles/forms/themes/_primary.css +92 -0
  10. package/assets/styles/forms/themes/_secondary.css +85 -0
  11. package/assets/styles/forms/themes/_success.css +85 -0
  12. package/assets/styles/forms/themes/_tertiary.css +85 -0
  13. package/assets/styles/forms/themes/_warning.css +85 -0
  14. package/assets/styles/forms/themes/index.css +9 -0
  15. package/assets/styles/forms/variables/_sizes.css +71 -0
  16. package/assets/styles/forms/variables/_theme.css +11 -0
  17. package/assets/styles/forms/variables/index.css +2 -0
  18. package/assets/styles/main.css +5 -0
  19. package/assets/styles/typography/index.css +2 -0
  20. package/assets/styles/typography/utils/_font-classes.css +190 -0
  21. package/assets/styles/typography/utils/_weights.css +69 -0
  22. package/assets/styles/typography/utils/index.css +2 -0
  23. package/assets/styles/typography/variables/_colors.css +14 -0
  24. package/assets/styles/typography/variables/_reponsive-font-size.css +10 -0
  25. package/assets/styles/typography/variables/index.css +2 -0
  26. package/assets/styles/utils/_margin-helpers.css +334 -0
  27. package/assets/styles/utils/_padding-helpers.css +308 -0
  28. package/assets/styles/utils/_page.css +49 -0
  29. package/assets/styles/utils/index.css +3 -0
  30. package/assets/styles/variables/colors/_blue.css +15 -0
  31. package/assets/styles/variables/colors/_gray.css +16 -0
  32. package/assets/styles/variables/colors/_green.css +15 -0
  33. package/assets/styles/variables/colors/_orange.css +15 -0
  34. package/assets/styles/variables/colors/_red.css +15 -0
  35. package/assets/styles/variables/colors/_yellow.css +15 -0
  36. package/assets/styles/variables/colors/colors.css +6 -0
  37. package/assets/styles/variables/index.css +1 -0
  38. package/components/forms/c12/prop-validators/index.ts +38 -0
  39. package/components/forms/c12/utils.ts +14 -0
  40. package/components/forms/form-errors/InputError.vue +172 -0
  41. package/components/forms/form-errors/tests/InputError.spec.ts +67 -0
  42. package/components/forms/input-button/InputButtonCore.vue +191 -0
  43. package/components/forms/input-button/variants/InputButtonConfirm.vue +66 -0
  44. package/components/forms/input-button/variants/InputButtonSubmit.vue +62 -0
  45. package/components/forms/input-checkbox/MultipleCheckboxes.vue +203 -0
  46. package/components/forms/input-checkbox/SingleCheckbox.vue +169 -0
  47. package/components/forms/input-checkbox/tests/MultipleCheckboxes.spec.ts +98 -0
  48. package/components/forms/input-checkbox/tests/data/tags.json +67 -0
  49. package/components/forms/input-checkbox-radio/InputCheckboxRadioButton.vue +214 -0
  50. package/components/forms/input-checkbox-radio/InputCheckboxRadioCore.vue +191 -0
  51. package/components/forms/input-checkbox-radio/InputCheckboxRadioWithLabel.vue +111 -0
  52. package/components/forms/input-number/InputNumberCore.vue +203 -0
  53. package/components/forms/input-number/variants/InputNumberDefault.vue +154 -0
  54. package/components/forms/input-radio/MultipleRadiobuttons.vue +201 -0
  55. package/components/forms/input-radio/tests/MultipleRadioButtons.spec.ts +89 -0
  56. package/components/forms/input-radio/tests/data/tags.json +67 -0
  57. package/components/forms/input-range/InputRangeCore.vue +274 -0
  58. package/components/forms/input-range/variants/InputRangeDefault.vue +156 -0
  59. package/components/forms/input-range-fancy/InputRangeFancyCore.vue +450 -0
  60. package/components/forms/input-range-fancy/InputRangeFancyWithLabel.vue +124 -0
  61. package/components/forms/input-select/InputSelect.vue +289 -0
  62. package/components/forms/input-text/InputTextCore.vue +331 -0
  63. package/components/forms/input-text/variants/InputPasswordWithLabel.vue +130 -0
  64. package/components/forms/input-text/variants/InputTextAsNumberWithLabel.vue +187 -0
  65. package/components/forms/input-text/variants/InputTextWithLabel.vue +298 -0
  66. package/components/forms/input-textarea/InputTextareaCore.vue +234 -0
  67. package/components/forms/input-textarea/variants/InputTextareaWithLabel.vue +267 -0
  68. package/components/forms/toggle-switch/ToggleSwitchCore.vue +198 -0
  69. package/components/forms/toggle-switch/ToggleSwitchCoreOld.vue +216 -0
  70. package/components/forms/toggle-switch/variants/ToggleSwitchWithLabel.vue +105 -0
  71. package/components/forms/toggle-switch/variants/ToggleSwitchWithLabelInline.vue +102 -0
  72. package/components/forms/ui/FormField.vue +78 -0
  73. package/components/forms/ui/FormWrapper.vue +35 -0
  74. package/components/utils/colour-scheme-select/ColourSchemeSelect.vue +270 -0
  75. package/components/utils/colour-scheme-select/ColourSchemeSelectOld.vue +225 -0
  76. package/components/utils/dark-mode-switcher/DarkModeSwitcher.vue +47 -0
  77. package/composables/useApiRequest.ts +25 -0
  78. package/composables/useColourScheme.ts +25 -0
  79. package/composables/useErrorMessages.ts +59 -0
  80. package/composables/useFormControl.ts +248 -0
  81. package/composables/useSleep.ts +5 -0
  82. package/composables/useStyleClassPassthrough.ts +30 -0
  83. package/composables/useZodValidation.ts +148 -0
  84. package/nuxt.config.ts +0 -3
  85. package/package.json +1 -1
  86. package/types/types.forms.ts +217 -0
  87. package/types/types.zodFormControl.ts +21 -0
@@ -0,0 +1,270 @@
1
+ <template>
2
+ <div class="colour-scheme-select" :data-size="size" :data-form-theme="theme">
3
+ <p>Color Scheme select</p>
4
+
5
+ <form class="colour-scheme-select-form mbe-20" ref="colourSchemeWrapper">
6
+ <div class="select-scheme-marker-wrapper">
7
+ <div class="select-scheme-marker" :class="[{ show: showMarker }]"></div>
8
+ </div>
9
+ <div class="select-scheme-group-wrapper">
10
+ <div class="select-scheme-group">
11
+ <LazyIcon name="material-symbols:night-sight-auto-sharp" class="scheme-icon" />
12
+ <input type="radio" id="auto" name="colour-scheme" class="scheme-input" v-model="currentColourScheme" value="auto" />
13
+ <label for="auto" class="sr-only">Auto</label>
14
+ </div>
15
+ <div class="select-scheme-group">
16
+ <LazyIcon name="radix-icons:sun" class="scheme-icon" />
17
+ <input type="radio" id="light" name="colour-scheme" class="scheme-input" v-model="currentColourScheme" value="light" />
18
+ <label for="light" class="sr-only">Light</label>
19
+ </div>
20
+ <div class="select-scheme-group">
21
+ <LazyIcon name="radix-icons:moon" class="scheme-icon" />
22
+ <input type="radio" id="dark" name="colour-scheme" class="scheme-input" v-model="currentColourScheme" value="dark" />
23
+ <label for="dark" class="sr-only">Dark</label>
24
+ </div>
25
+ </div>
26
+ </form>
27
+ </div>
28
+ </template>
29
+
30
+ <script setup lang="ts">
31
+ import propValidators from '../../forms/c12/prop-validators';
32
+
33
+ const props = defineProps({
34
+ name: {
35
+ type: String,
36
+ defaul: 'colour-scheme-select',
37
+ },
38
+ size: {
39
+ type: String as PropType<string>,
40
+ default: 'medium',
41
+ validator(value: string) {
42
+ return propValidators.size.includes(value);
43
+ },
44
+ },
45
+ theme: {
46
+ type: String as PropType<string>,
47
+ default: 'primary',
48
+ validator(value: string) {
49
+ return propValidators.theme.includes(value);
50
+ },
51
+ },
52
+ stepAnimationDuration: {
53
+ type: Number as PropType<number>,
54
+ default: 100,
55
+ },
56
+ styleClassPassthrough: {
57
+ type: Array as PropType<string[]>,
58
+ default: () => [],
59
+ },
60
+ });
61
+
62
+ const duration = ref(props.stepAnimationDuration);
63
+
64
+ const { currentColourScheme } = useColourScheme();
65
+
66
+ const colourSchemeWrapper = ref<HTMLFormElement | null>(null);
67
+ const colourSchemeGroupElements = ref<HTMLDivElement[]>([]);
68
+ const colourSchemeInputElements = ref<HTMLInputElement[]>([]);
69
+ const showMarker = ref(false);
70
+
71
+ const findIndexOfInputValueFromCurrentColourScheme = () => {
72
+ if (currentColourScheme.value === 'auto') return 1;
73
+ if (currentColourScheme.value === 'light') return 2;
74
+ if (currentColourScheme.value === 'dark') return 3;
75
+ return undefined;
76
+ };
77
+
78
+ const findIndexOfCheckedInput = () => {
79
+ return colourSchemeInputElements.value.findIndex((input) => input.checked);
80
+ };
81
+
82
+ const currentActiveIndex = ref(findIndexOfCheckedInput());
83
+
84
+ const setColourSchemeAttr = async () => {
85
+ const index = findIndexOfInputValueFromCurrentColourScheme() ?? 0;
86
+
87
+ await nextTick();
88
+ currentActiveIndex.value = findIndexOfCheckedInput();
89
+
90
+ const wrapperLeftPosition = colourSchemeWrapper.value?.getBoundingClientRect().left ?? 0;
91
+ const parentLeftPosition = colourSchemeWrapper.value?.parentElement?.getBoundingClientRect().left ?? 0;
92
+ const relativeLeftPosition = wrapperLeftPosition - parentLeftPosition;
93
+
94
+ colourSchemeWrapper.value?.style.setProperty('--_select-scheme-marker-step-animation-duration', colourSchemeGroupElements.value?.length * duration.value + 'ms');
95
+
96
+ colourSchemeWrapper.value?.style.setProperty('--_select-scheme-marker-position', index !== undefined ? index.toString() : '0');
97
+ colourSchemeWrapper.value?.style.setProperty('--_select-scheme-marker-left-offset', colourSchemeGroupElements.value?.[index - 1]?.offsetLeft - relativeLeftPosition + 'px');
98
+ colourSchemeWrapper.value?.style.setProperty('--_select-scheme-marker-width', colourSchemeGroupElements.value?.[index - 1]?.getBoundingClientRect().width + 'px');
99
+ };
100
+
101
+ const handleInputActiveClass = () => {
102
+ colourSchemeInputElements.value.forEach((element) => {
103
+ element.classList.remove('active');
104
+ });
105
+
106
+ setTimeout(() => {
107
+ colourSchemeInputElements.value?.[currentActiveIndex.value].classList.add('active');
108
+ }, duration.value);
109
+ };
110
+
111
+ onMounted(() => {
112
+ colourSchemeGroupElements.value = Array.from(colourSchemeWrapper.value?.querySelectorAll('.select-scheme-group') || []) as HTMLInputElement[];
113
+ colourSchemeInputElements.value = Array.from(colourSchemeWrapper.value?.querySelectorAll('.scheme-input') || []) as HTMLInputElement[];
114
+
115
+ if (colourSchemeWrapper.value !== null) {
116
+ setColourSchemeAttr();
117
+ setTimeout(() => {
118
+ showMarker.value = true;
119
+ handleInputActiveClass();
120
+ }, duration.value);
121
+ }
122
+ });
123
+
124
+ watch(currentColourScheme, () => {
125
+ setColourSchemeAttr();
126
+ });
127
+
128
+ watch(currentActiveIndex, () => {
129
+ handleInputActiveClass();
130
+ });
131
+ </script>
132
+
133
+ <style lang="css">
134
+ .colour-scheme-select {
135
+ --_form-background-color: var(--theme-form-checkbox-bg);
136
+ --_form-border-width: 0.1rem;
137
+ --_form-border-colour: var(--theme-form-radio-border);
138
+ --_form-outline-width: 0.1rem;
139
+
140
+ --_form-outline-colour: var(--theme-form-radio-outline);
141
+
142
+ --_form-border-radius: calc(
143
+ (var(--_scheme-icon-font-size) / 2) + var(--_form-border-width) + var(--_form-outline-width) + var(--_form-padding) + var(--_select-scheme-group-padding) + var(--_select-scheme-group-border-width) +
144
+ var(--_select-scheme-group-outline-width)
145
+ );
146
+
147
+ --_form-items-gap: 1rem;
148
+ --_form-padding: 0.6rem;
149
+
150
+ --_select-scheme-group-background-color: var(--theme-form-checkbox-bg);
151
+ --_select-scheme-group-padding: 0.5rem;
152
+ --_select-scheme-group-border-width: 0.2rem;
153
+ --_select-scheme-group-border-colour: transparent;
154
+ --_select-scheme-group-outline-width: 0.2rem;
155
+ --_select-scheme-group-outline-colour: transparent;
156
+ --_select-scheme-group-width: calc(
157
+ var(--_scheme-icon-font-size) + (var(--_select-scheme-group-padding) * 2) + (var(--_select-scheme-group-border-width) * 2) + (var(--_select-scheme-group-outline-width) * 2)
158
+ );
159
+
160
+ --_scheme-icon-font-size: 2rem;
161
+ --_scheme-icon-colour: black;
162
+
163
+ .colour-scheme-select-form {
164
+ display: inline-grid;
165
+ grid-template-areas: 'select-stack';
166
+ width: fit-content;
167
+
168
+ background-color: var(--_form-background-color);
169
+ border: var(--_form-border-width) solid var(--_form-border-colour);
170
+ outline: var(--_form-outline-width) solid var(--_form-outline-colour);
171
+ border-radius: var(--_form-border-radius);
172
+ padding: var(--_form-padding);
173
+
174
+ .select-scheme-marker-wrapper {
175
+ grid-area: select-stack;
176
+ z-index: 1;
177
+ display: flex;
178
+ align-items: center;
179
+ position: relative;
180
+
181
+ .select-scheme-marker {
182
+ aspect-ratio: 1;
183
+ width: var(--_select-scheme-group-width);
184
+ transition: all var(--_select-scheme-marker-step-animation-duration) ease-in-out;
185
+ background-color: var(--theme-form-radio-border);
186
+ border-radius: 50%;
187
+
188
+ position: absolute;
189
+ left: calc(var(--_select-scheme-marker-left-offset) - var(--_select-scheme-group-border-width));
190
+
191
+ opacity: 0;
192
+
193
+ &.show {
194
+ opacity: 1;
195
+ }
196
+ }
197
+ }
198
+
199
+ .select-scheme-group-wrapper {
200
+ display: grid;
201
+ grid-area: select-stack;
202
+ grid-template-columns: repeat(3, 1fr);
203
+ align-items: center;
204
+ width: fit-content;
205
+ z-index: 2;
206
+ gap: var(--_form-items-gap);
207
+ position: relative;
208
+
209
+ .select-scheme-group {
210
+ aspect-ratio: 1;
211
+ display: grid;
212
+ grid-template-areas: 'icon-stack';
213
+ place-content: center;
214
+ background: var(--_select-scheme-group-background-color);
215
+ border: var(--_select-scheme-group-border-width) solid var(--_select-scheme-group-border-colour);
216
+ outline: var(--_select-scheme-group-outline-width) solid var(--_select-scheme-group-outline-colour);
217
+ border-radius: 50%;
218
+ padding: var(--_select-scheme-group-padding);
219
+
220
+ transition: background calc(var(--_select-scheme-marker-step-animation-duration) / 3);
221
+
222
+ .scheme-icon {
223
+ grid-area: icon-stack;
224
+ display: block;
225
+ color: var(--_scheme-icon-colour);
226
+ font-size: var(--_scheme-icon-font-size);
227
+
228
+ &:hover {
229
+ cursor: pointer;
230
+ }
231
+ }
232
+
233
+ .scheme-input {
234
+ grid-area: icon-stack;
235
+ opacity: 0;
236
+
237
+ &:hover {
238
+ cursor: pointer;
239
+ }
240
+ }
241
+
242
+ &:has(input[value='auto']) {
243
+ &:has(.active) {
244
+ --_select-scheme-group-background-color: green;
245
+ --_scheme-icon-colour: white;
246
+ }
247
+ }
248
+
249
+ &:has(input[value='light']) {
250
+ &:has(.active) {
251
+ /* background: rgb(180, 58, 91);
252
+ background: linear-gradient(90deg, rgba(180, 58, 91, 1) 0%, rgba(253, 29, 29, 1) 50%, rgba(252, 176, 69, 1) 100%); */
253
+ --_select-scheme-group-background-color: radial-gradient(circle, rgba(180, 58, 91, 1) 0%, rgba(253, 29, 29, 1) 27%, rgba(252, 176, 69, 1) 100%);
254
+ /* --_select-scheme-group-background-color: radial-gradient(circle, rgba(63, 94, 251, 1) 70%, rgba(63, 94, 251, 0.5550814075630253) 90%, rgba(255, 255, 255, 0.42622986694677867) 100%); */
255
+
256
+ --_scheme-icon-colour: white;
257
+ }
258
+ }
259
+
260
+ &:has(input[value='dark']) {
261
+ &:has(.active) {
262
+ --_select-scheme-group-background-color: black;
263
+ --_scheme-icon-colour: white;
264
+ }
265
+ }
266
+ }
267
+ }
268
+ }
269
+ }
270
+ </style>
@@ -0,0 +1,225 @@
1
+ <template>
2
+ <div class="colour-scheme-select" :data-size="size" :data-form-theme="theme">
3
+ <p>Color Scheme select</p>
4
+
5
+ <form class="colour-scheme-select-form mbe-20">
6
+ <div class="input-range-markers">
7
+ <div class="marker">
8
+ <LazyIcon name="material-symbols:night-sight-auto-sharp" class="marker-icon" />
9
+ </div>
10
+ <div class="marker">
11
+ <LazyIcon name="radix-icons:sun" class="marker-icon" />
12
+ </div>
13
+ <div class="marker" v>
14
+ <LazyIcon name="radix-icons:moon" class="marker-icon" />
15
+ </div>
16
+ </div>
17
+
18
+ <div class="scheme-marker-wrapper">
19
+ <div class="scheme-marker-indicator"></div>
20
+ </div>
21
+
22
+ <div class="form-elements">
23
+ <div class="form-input">
24
+ <input type="radio" id="auto" name="colour-scheme" v-model="colourScheme" value="auto" />
25
+ <label for="auto" class="sr-only">Auto</label>
26
+ </div>
27
+ <div class="form-input">
28
+ <input type="radio" id="light" name="colour-scheme" v-model="colourScheme" value="light" />
29
+ <label for="light" class="sr-only">Light</label>
30
+ </div>
31
+ <div class="form-input">
32
+ <input type="radio" id="dark" name="colour-scheme" v-model="colourScheme" value="dark" />
33
+ <label for="dark" class="sr-only">Dark</label>
34
+ </div>
35
+ </div>
36
+ </form>
37
+ </div>
38
+ </template>
39
+
40
+ <script setup lang="ts">
41
+ import propValidators from '../../forms/c12/prop-validators';
42
+
43
+ defineProps({
44
+ name: {
45
+ type: String,
46
+ defaul: useId(),
47
+ },
48
+ size: {
49
+ type: String as PropType<string>,
50
+ default: 'medium',
51
+ validator(value: string) {
52
+ return propValidators.size.includes(value);
53
+ },
54
+ },
55
+ theme: {
56
+ type: String as PropType<string>,
57
+ default: 'primary',
58
+ validator(value: string) {
59
+ return propValidators.theme.includes(value);
60
+ },
61
+ },
62
+ styleClassPassthrough: {
63
+ type: Array as PropType<string[]>,
64
+ default: () => [],
65
+ },
66
+ });
67
+
68
+ const colourScheme = ref<'auto' | 'dark' | 'light'>('auto');
69
+
70
+ useColourScheme(colourScheme);
71
+ </script>
72
+
73
+ <style lang="css">
74
+ .colour-scheme-select {
75
+ --_outline-width: 0.1rem;
76
+ --_border-width: 0.1rem;
77
+ --_border-radius: 50%;
78
+ --_background-color: var(--theme-form-checkbox-bg);
79
+ --_box-shadow: none;
80
+
81
+ --_icon-size: var(--form-input-checkbox-radio-button-size);
82
+
83
+ --_background-color: var(--theme-form-radio-bg);
84
+ --_border-color: var(--theme-form-radio-border);
85
+ --_border-radius: 50%;
86
+ --_outline-color: var(--theme-form-radio-outline);
87
+
88
+ --_form-padding: 0.5rem;
89
+ --_form-input-outline-width: 0.2rem;
90
+
91
+ --_scheme-marker-position: start;
92
+
93
+ .colour-scheme-select-form {
94
+ display: grid;
95
+ grid-template-areas: 'element-stack';
96
+ align-items: center;
97
+
98
+ background-color: var(--theme-form-radio-bg);
99
+ border: var(--_border-width) solid var(--_border-color);
100
+
101
+ border-radius: calc((var(--_icon-size) / 2) + var(--_form-padding) + var(--_border-width) + var(--_outline-width) + var(--_form-input-outline-width));
102
+
103
+ outline: var(--_outline-width) solid var(--_outline-color);
104
+ box-shadow: var(--_box-shadow);
105
+
106
+ /* height: calc(var(--_icon-size) + 4px); */
107
+ width: calc((var(--_icon-size) * 3) + (var(--_form-padding) * 17));
108
+
109
+ transition: all 0.2s ease-in-out;
110
+
111
+ .input-range-markers {
112
+ grid-area: element-stack;
113
+ display: flex;
114
+ align-items: center;
115
+ justify-content: space-between;
116
+ width: 100%;
117
+ padding: var(--_form-padding);
118
+
119
+ .marker {
120
+ background-color: black;
121
+ padding: var(--_form-padding);
122
+ border-radius: 50%;
123
+ overflow: hidden;
124
+ /* outline: 1px solid gray; */
125
+
126
+ &:hover {
127
+ cursor: pointer;
128
+ }
129
+
130
+ .marker-icon {
131
+ /* font-size: 2rem; */
132
+ display: block;
133
+ color: white;
134
+ height: var(--_icon-size);
135
+ width: var(--_icon-size);
136
+ }
137
+ }
138
+ }
139
+
140
+ .scheme-marker-wrapper {
141
+ grid-area: element-stack;
142
+ display: grid;
143
+ gap: 1rem;
144
+
145
+ grid-template-columns: repeat(3, 1fr);
146
+ /* transition: grid-template-columns 0.2s; */
147
+ /* text-align: var(--_scheme-marker-position); */
148
+ padding: var(--_form-padding);
149
+ /* z-index: 9; */
150
+
151
+ .scheme-marker-indicator {
152
+ grid-column: 3;
153
+ aspect-ratio: 1;
154
+ background-color: var(--theme-form-radio-bg);
155
+ background-color: red;
156
+ border-radius: 50%;
157
+ height: calc(var(--_icon-size) + var(--_form-padding));
158
+ /* width: calc(var(--_icon-size) + var(--_form-padding)); */
159
+ padding: var(--_form-padding);
160
+ transition: grid-columns 0.2s;
161
+ }
162
+ }
163
+
164
+ .form-elements {
165
+ grid-area: element-stack;
166
+ display: flex;
167
+ align-items: center;
168
+ justify-content: space-between;
169
+ gap: 1rem;
170
+ padding: var(--_form-padding);
171
+
172
+ .form-input {
173
+ border-radius: 50%;
174
+ display: flex;
175
+ place-content: center;
176
+ padding: var(--_form-padding);
177
+ outline: var(--_form-input-outline-width) solid gray;
178
+ opacity: 0.75;
179
+
180
+ &:has(input[value='auto']) {
181
+ background-color: green;
182
+
183
+ &:has(input[value='auto']:checked) {
184
+ --_scheme-marker-position: start;
185
+ outline: var(--_form-input-outline-width) solid var(--_border-color);
186
+ opacity: 1;
187
+ }
188
+ }
189
+
190
+ &:has(input[value='light']) {
191
+ background-color: orange;
192
+
193
+ &:has(input[value='light']:checked) {
194
+ --_scheme-marker-position: center;
195
+ outline: var(--_form-input-outline-width) solid var(--_border-color);
196
+ opacity: 1;
197
+ }
198
+ }
199
+
200
+ &:has(input[value='dark']) {
201
+ background-color: black;
202
+
203
+ &:has(input[value='dark']:checked) {
204
+ --_scheme-marker-position: end;
205
+ outline: var(--_form-input-outline-width) solid var(--_border-color);
206
+ opacity: 1;
207
+ }
208
+ }
209
+
210
+ input[type='radio'] {
211
+ opacity: 0;
212
+ height: var(--_icon-size);
213
+ width: var(--_icon-size);
214
+ margin: 0;
215
+ padding: 0;
216
+
217
+ &:hover {
218
+ cursor: pointer;
219
+ }
220
+ }
221
+ }
222
+ }
223
+ }
224
+ }
225
+ </style>
@@ -0,0 +1,47 @@
1
+ <template>
2
+ <ToggleSwitchWithLabelInline v-model="currentColourScheme" :name :label labelWeight="normal" :size trueValue="dark" falseValue="light" :style-class-passthrough>
3
+ <template #iconOn>
4
+ <LazyIcon name="radix-icons:moon" class="icon" />
5
+ </template>
6
+ <template #iconOff>
7
+ <LazyIcon name="radix-icons:sun" class="icon" />
8
+ </template>
9
+ </ToggleSwitchWithLabelInline>
10
+ </template>
11
+
12
+ <script setup lang="ts">
13
+ import propValidators from '../../forms/c12/prop-validators';
14
+
15
+ defineProps({
16
+ name: {
17
+ type: String,
18
+ required: true,
19
+ },
20
+ label: {
21
+ type: String,
22
+ required: true,
23
+ },
24
+ labelWeight: {
25
+ type: String as PropType<string>,
26
+ default: 'semi-bold',
27
+ validator(value: string) {
28
+ return propValidators.labelWeight.includes(value);
29
+ },
30
+ },
31
+ size: {
32
+ type: String as PropType<string>,
33
+ default: 'small',
34
+ validator(value: string) {
35
+ return propValidators.size.includes(value);
36
+ },
37
+ },
38
+ styleClassPassthrough: {
39
+ type: Array as PropType<string[]>,
40
+ default: () => [],
41
+ },
42
+ });
43
+
44
+ // const displayMode = ref<'auto' | 'dark' | 'light'>('auto');
45
+
46
+ const { currentColourScheme } = useColourScheme();
47
+ </script>
@@ -0,0 +1,25 @@
1
+ class CustomError extends Error {
2
+ // name = "CustomError";
3
+ override name = 'CustomError';
4
+ extraProp = 'Error: test';
5
+ }
6
+
7
+ async function useApiRequest<T, E extends new (message?: string) => Error>(promise: Promise<T>, errorsToCatch?: E[]): Promise<[undefined, T] | [InstanceType<E>]> {
8
+ return promise
9
+ .then((data) => {
10
+ return [undefined, data] as [undefined, T];
11
+ })
12
+ .catch((error) => {
13
+ if (errorsToCatch == undefined) {
14
+ return [error];
15
+ }
16
+
17
+ if (errorsToCatch.some((errorType) => error instanceof errorType)) {
18
+ return [error];
19
+ }
20
+
21
+ throw error;
22
+ });
23
+ }
24
+
25
+ export default useApiRequest;
@@ -0,0 +1,25 @@
1
+ export const useColourScheme = () => {
2
+ const currentColourScheme = ref<'auto' | 'dark' | 'light' | null>(null);
3
+
4
+ const returnSavedColourPreferenceFromLocalStorage = () => {
5
+ if (import.meta.client) {
6
+ return localStorage.getItem('colourScheme') as 'auto' | 'dark' | 'light' | null;
7
+ }
8
+ };
9
+
10
+ onMounted(() => {
11
+ currentColourScheme.value = returnSavedColourPreferenceFromLocalStorage() || 'auto';
12
+ });
13
+
14
+ watch(currentColourScheme, (newVal) => {
15
+ if (import.meta.client && newVal !== null) {
16
+ localStorage.setItem('colourScheme', newVal);
17
+ document.documentElement.dataset.colorScheme = newVal;
18
+ currentColourScheme.value = newVal;
19
+ }
20
+ });
21
+
22
+ return {
23
+ currentColourScheme,
24
+ };
25
+ };
@@ -0,0 +1,59 @@
1
+ import type { IFormData } from '@/types/types.forms';
2
+
3
+ export function useErrorMessage(name: string, formData: Ref<IFormData>) {
4
+ const defaultError = ref('');
5
+ const errorMessages = ref(formData.value.errorMessages);
6
+
7
+ const hasCustomError = () => {
8
+ return errorMessages.value[name] !== undefined && errorMessages.value[name].useCustomError;
9
+ };
10
+
11
+ const errorMessage = computed(() => {
12
+ console.log(`errorMessage()`);
13
+ if (hasCustomError()) {
14
+ console.log(`errorMessage() | IF`);
15
+ return errorMessages.value[name].message;
16
+ } else {
17
+ return defaultError.value;
18
+ }
19
+ });
20
+
21
+ const setDefaultError = (newDefaultError: string) => {
22
+ defaultError.value = newDefaultError;
23
+ };
24
+
25
+ const fieldHasError = computed(() => {
26
+ // console.log(`fieldHasError() | name(${name})`);
27
+ nextTick();
28
+ if (formData.value.submitDisabled) {
29
+ console.log(`fieldHasError() | name(${name}) | IF`);
30
+ if (hasCustomError()) {
31
+ console.log(`fieldHasError() | name(${name}) | IF | IF`);
32
+
33
+ return true;
34
+ } else if (Object.keys(formData.value.validityState).length > 0 && formData.value.validityState[name] !== undefined) {
35
+ console.log(`fieldHasError() | name(${name}) | IF | ELSE IF`);
36
+
37
+ return !formData.value.validityState[name];
38
+ }
39
+ console.log(`fieldHasError() | name(${name}) | IF | ELSE`);
40
+
41
+ return false;
42
+ }
43
+ });
44
+
45
+ const removeCustomError = (valid: boolean = false) => {
46
+ console.log(`useErrorMessage | removeCustomError | name(${name}) | valid(${valid})`);
47
+ // formData.value.validityState[name] = valid;
48
+ // await nextTick();
49
+ // delete formData.value.errorMessages[name];
50
+ };
51
+
52
+ return {
53
+ hasCustomError,
54
+ errorMessage,
55
+ setDefaultError,
56
+ fieldHasError,
57
+ removeCustomError,
58
+ };
59
+ }