srcdev-nuxt-forms 3.0.0 → 4.0.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 (86) 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-text/InputTextCore.vue +331 -0
  62. package/components/forms/input-text/variants/InputPasswordWithLabel.vue +130 -0
  63. package/components/forms/input-text/variants/InputTextAsNumberWithLabel.vue +187 -0
  64. package/components/forms/input-text/variants/InputTextWithLabel.vue +298 -0
  65. package/components/forms/input-textarea/InputTextareaCore.vue +234 -0
  66. package/components/forms/input-textarea/variants/InputTextareaWithLabel.vue +267 -0
  67. package/components/forms/toggle-switch/ToggleSwitchCore.vue +198 -0
  68. package/components/forms/toggle-switch/ToggleSwitchCoreOld.vue +216 -0
  69. package/components/forms/toggle-switch/variants/ToggleSwitchWithLabel.vue +105 -0
  70. package/components/forms/toggle-switch/variants/ToggleSwitchWithLabelInline.vue +102 -0
  71. package/components/forms/ui/FormField.vue +78 -0
  72. package/components/forms/ui/FormWrapper.vue +35 -0
  73. package/components/utils/colour-scheme-select/ColourSchemeSelect.vue +270 -0
  74. package/components/utils/colour-scheme-select/ColourSchemeSelectOld.vue +225 -0
  75. package/components/utils/dark-mode-switcher/DarkModeSwitcher.vue +47 -0
  76. package/composables/useApiRequest.ts +25 -0
  77. package/composables/useColourScheme.ts +25 -0
  78. package/composables/useErrorMessages.ts +59 -0
  79. package/composables/useFormControl.ts +248 -0
  80. package/composables/useSleep.ts +5 -0
  81. package/composables/useStyleClassPassthrough.ts +30 -0
  82. package/composables/useZodValidation.ts +148 -0
  83. package/nuxt.config.ts +0 -3
  84. package/package.json +1 -1
  85. package/types/types.forms.ts +216 -0
  86. package/types/types.zodFormControl.ts +21 -0
@@ -0,0 +1,274 @@
1
+ <template>
2
+ <div class="input-range-wrapper" :data-form-theme="formTheme">
3
+ <div v-if="hasLeftContent" class="slot left">
4
+ <slot name="left"></slot>
5
+ </div>
6
+
7
+ <div class="input-range-container">
8
+ <slot v-if="hasMarkers" name="markers"></slot>
9
+
10
+ <input
11
+ type="range"
12
+ :id
13
+ :name
14
+ :required
15
+ :min
16
+ :max
17
+ :step
18
+ :list="hasDataList ? name + '-datalist' : ''"
19
+ :class="['input-range-core', `input-range--${size}`, `input-range--${weight}`, styleClassPassthrough, { 'has-markers': hasMarkers }]"
20
+ v-model="modelValue"
21
+ ref="inputRange"
22
+ />
23
+
24
+ <slot v-if="hasDataList" name="datalist"></slot>
25
+ </div>
26
+ <div v-if="hasRightContent" class="slot right">
27
+ <slot name="right"></slot>
28
+ </div>
29
+ </div>
30
+ </template>
31
+
32
+ <script setup lang="ts">
33
+ import propValidators from '../c12/prop-validators';
34
+
35
+ const props = defineProps({
36
+ id: {
37
+ type: String,
38
+ required: true,
39
+ },
40
+ name: {
41
+ type: String,
42
+ required: true,
43
+ },
44
+ min: {
45
+ type: Number,
46
+ required: true,
47
+ },
48
+ max: {
49
+ type: Number,
50
+ required: true,
51
+ },
52
+ step: {
53
+ type: Number,
54
+ default: 1,
55
+ },
56
+ placeholder: {
57
+ type: String,
58
+ default: '',
59
+ },
60
+ required: {
61
+ type: Boolean,
62
+ default: false,
63
+ },
64
+ theme: {
65
+ type: String as PropType<string>,
66
+ default: 'primary',
67
+ validator(value: string) {
68
+ return propValidators.theme.includes(value);
69
+ },
70
+ },
71
+ size: {
72
+ type: String as PropType<string>,
73
+ default: 'medium',
74
+ validator(value: string) {
75
+ return propValidators.size.includes(value);
76
+ },
77
+ },
78
+ weight: {
79
+ type: String as PropType<string>,
80
+ default: 'wght-400',
81
+ validator(value: string) {
82
+ return propValidators.weight.includes(value);
83
+ },
84
+ },
85
+ fieldHasError: {
86
+ type: Boolean,
87
+ default: false,
88
+ },
89
+ styleClassPassthrough: {
90
+ type: Array as PropType<string[]>,
91
+ default: () => [],
92
+ },
93
+ });
94
+
95
+ const slots = useSlots();
96
+ const hasDataList = computed(() => slots.datalist !== undefined);
97
+ const hasMarkers = computed(() => slots.markers !== undefined);
98
+ const hasLeftContent = computed(() => slots.left !== undefined);
99
+ const hasRightContent = computed(() => slots.right !== undefined);
100
+
101
+ const formTheme = computed(() => {
102
+ return props.fieldHasError ? 'error' : props.theme;
103
+ });
104
+
105
+ const modelValue = defineModel<number | readonly number[]>();
106
+
107
+ // @input="changeBackgroundColor"
108
+ const changeBackgroundColor = () => {
109
+ console.log('changeBackgroundColor()');
110
+ const inputRange = ref<HTMLInputElement | null>(null);
111
+ if (inputRange.value !== null) {
112
+ inputRange.value.style.accentColor = 'hsl(' + modelValue.value + ', 100%, 50%)';
113
+ }
114
+ };
115
+ </script>
116
+
117
+ <style lang="css">
118
+ .input-range-wrapper {
119
+ --_gutter: 1.2rem;
120
+ --_border-width: var(--form-element-border-width);
121
+ --_outline-width: var(--form-element-outline-width);
122
+
123
+ --_input-range-height: 2.4rem;
124
+ --_slot-translate-y: calc(var(--_input-range-height) / 4);
125
+
126
+ display: flex;
127
+ align-items: center;
128
+ justify-content: space-between;
129
+ gap: 1rem;
130
+
131
+ .slot {
132
+ align-self: flex-start;
133
+ transform: translateY(-4px);
134
+ }
135
+
136
+ .input-range-container {
137
+ flex-grow: 1;
138
+
139
+ display: grid;
140
+ grid-template-areas: 'element-stack';
141
+
142
+ .input-range-markers {
143
+ grid-area: element-stack;
144
+ display: flex;
145
+ align-items: center;
146
+ justify-content: space-between;
147
+ width: 100%;
148
+ z-index: 2;
149
+
150
+ .marker {
151
+ background-color: black;
152
+ padding: 0.5rem;
153
+ border-radius: 50%;
154
+ overflow: hidden;
155
+ outline: 1px solid gray;
156
+
157
+ &:hover {
158
+ cursor: pointer;
159
+ }
160
+
161
+ .marker-icon {
162
+ font-size: 2rem;
163
+ display: block;
164
+ color: var(--theme-form-range-accent-color);
165
+ }
166
+ }
167
+ }
168
+
169
+ .input-range-core {
170
+ grid-area: element-stack;
171
+
172
+ accent-color: var(--theme-form-range-accent-color);
173
+ height: var(--_input-range-height);
174
+ margin: 0;
175
+ width: 100%;
176
+
177
+ /*
178
+ &:hover {
179
+ cursor: -webkit-grab;
180
+ outline-color: red;
181
+ }
182
+ &:active {
183
+ cursor: -webkit-grabbing;
184
+ outline-color: blue;
185
+ }
186
+ &:focus-visible {
187
+ outline-offset: 0.25rem;
188
+ outline-color: transparent;
189
+ }
190
+ */
191
+
192
+ &::-webkit-slider-thumb {
193
+ /* appearance: none; */
194
+ /* -webkit-appearance: none; */
195
+ accent-color: blue;
196
+ color: blue;
197
+ background-color: 0.1rem solid green;
198
+ outline: 0.1rem solid blue;
199
+ border-radius: 50%;
200
+ }
201
+
202
+ &::-webkit-slider-runnable-track {
203
+ appearance: none;
204
+ -webkit-appearance: none;
205
+ /* background: hsl(10 80% 50% / 0.5); */
206
+ /* box-shadow: 0.1rem 0.1rem 0.1rem #fff, 0rem 0rem 0.1rem #fff; */
207
+ }
208
+
209
+ /* For Chrome, Safari, Opera, and Edge */
210
+ /* &::-webkit-slider-runnable-track {
211
+ background: var(--theme-form-range-accent-color);
212
+ height: var(--_input-range-height);
213
+ } */
214
+
215
+ /* For Firefox */
216
+ /* &::-moz-range-track {
217
+ background: var(--theme-form-range-accent-color);
218
+ height: var(--_input-range-height);
219
+ } */
220
+
221
+ /* Stling the thumb */
222
+ /* &::-webkit-slider-thumb {
223
+ -webkit-appearance: none;
224
+ background: #5cd5eb;
225
+ height: 2rem;
226
+ width: 1rem;
227
+ border-radius: 1rem;
228
+ } */
229
+
230
+ /* For Firefox */
231
+ /* &::-moz-range-thumb {
232
+ background: #5cd5eb;
233
+ height: 2rem;
234
+ width: 1rem;
235
+ border-radius: 1rem;
236
+ border: none;
237
+ } */
238
+
239
+ &:focus-visible {
240
+ box-shadow: var(--form-focus-box-shadow);
241
+ }
242
+
243
+ &.has-markers {
244
+ accent-color: var(--theme-form-range-accent-color);
245
+ height: 2px;
246
+ z-index: 2;
247
+ translate: 0 13px;
248
+
249
+ &::-webkit-slider-thumb {
250
+ /* display: none; */
251
+ opacity: 0;
252
+ &:hover {
253
+ cursor: pointer;
254
+ }
255
+ }
256
+ }
257
+ }
258
+
259
+ .input-range-datalist {
260
+ display: flex;
261
+ flex-direction: column;
262
+ font-family: var(--font-family);
263
+ font-size: 1.4rem;
264
+ font-weight: 500;
265
+ justify-content: space-between;
266
+ writing-mode: vertical-lr;
267
+ width: 100%;
268
+ option {
269
+ padding: 0;
270
+ }
271
+ }
272
+ }
273
+ }
274
+ </style>
@@ -0,0 +1,156 @@
1
+ <template>
2
+ <div class="input-range-with-label" :data-form-theme="formTheme" :class="[elementClasses, { error: fieldHasError }]">
3
+ <label class="input-range-label body-normal-bold" :for="id">{{ label }}</label>
4
+ <template v-if="hasDescription">
5
+ <slot name="description"></slot>
6
+ </template>
7
+
8
+ <InputRangeCore v-model="modelValue" :id :name :min :max :step :theme :required :size :weight :fieldHasError>
9
+ <template v-if="hasDataList" #datalist>
10
+ <slot name="datalist"></slot>
11
+ </template>
12
+ <template v-if="hasLeftContent" #left>
13
+ <InputButtonCore
14
+ type="button"
15
+ @click.stop.prevent="updateRange(-step, Number(modelValue) > min)"
16
+ :readonly="Number(modelValue) === min"
17
+ :is-pending="false"
18
+ buttonText="Step down"
19
+ :theme
20
+ size="x-small"
21
+ >
22
+ <template #iconOnly>
23
+ <slot name="left"></slot>
24
+ </template>
25
+ </InputButtonCore>
26
+ </template>
27
+ <template v-if="hasRightContent" #right>
28
+ <InputButtonCore
29
+ type="button"
30
+ @click.stop.prevent="updateRange(step, Number(modelValue) < max)"
31
+ :readonly="Number(modelValue) === max"
32
+ :is-pending="false"
33
+ buttonText="Step up"
34
+ :theme
35
+ size="x-small"
36
+ >
37
+ <template #iconOnly>
38
+ <slot name="right"></slot>
39
+ </template>
40
+ </InputButtonCore>
41
+ </template>
42
+ </InputRangeCore>
43
+ <InputError :errorMessage :showError="fieldHasError" :id :isDetached="true" :styleClassPassthrough="['mbe-20']" />
44
+ </div>
45
+ </template>
46
+
47
+ <script setup lang="ts">
48
+ import propValidators from '../../c12/prop-validators';
49
+
50
+ const { name, label, required, min, max, step, theme, size, weight, styleClassPassthrough, errorMessage, fieldHasError } = defineProps({
51
+ name: {
52
+ type: String,
53
+ required: true,
54
+ },
55
+ label: {
56
+ type: String,
57
+ required: true,
58
+ },
59
+ min: {
60
+ type: Number,
61
+ required: true,
62
+ },
63
+ max: {
64
+ type: Number,
65
+ required: true,
66
+ },
67
+ step: {
68
+ type: Number,
69
+ default: 1,
70
+ },
71
+ placeholder: {
72
+ type: String,
73
+ default: '',
74
+ },
75
+ errorMessage: {
76
+ type: [Object, String],
77
+ required: true,
78
+ },
79
+ fieldHasError: {
80
+ type: Boolean,
81
+ default: false,
82
+ },
83
+ required: {
84
+ type: Boolean,
85
+ default: false,
86
+ },
87
+ theme: {
88
+ type: String as PropType<string>,
89
+ default: 'primary',
90
+ validator(value: string) {
91
+ return propValidators.theme.includes(value);
92
+ },
93
+ },
94
+ size: {
95
+ type: String as PropType<string>,
96
+ default: 'medium',
97
+ validator(value: string) {
98
+ return propValidators.size.includes(value);
99
+ },
100
+ },
101
+ weight: {
102
+ type: String as PropType<string>,
103
+ default: 'wght-400',
104
+ validator(value: string) {
105
+ return propValidators.weight.includes(value);
106
+ },
107
+ },
108
+ styleClassPassthrough: {
109
+ type: Array as PropType<string[]>,
110
+ default: () => [],
111
+ },
112
+ deepCssClassPassthrough: {
113
+ type: String,
114
+ default: '',
115
+ },
116
+ });
117
+
118
+ const slots = useSlots();
119
+ const hasDescription = computed(() => slots.description !== undefined);
120
+ const hasDataList = computed(() => slots.datalist !== undefined);
121
+ const hasLeftContent = computed(() => slots.left !== undefined);
122
+ const hasRightContent = computed(() => slots.right !== undefined);
123
+ const { elementClasses, updateElementClasses } = useStyleClassPassthrough(styleClassPassthrough);
124
+
125
+ const id = useId();
126
+ const formTheme = computed(() => {
127
+ return fieldHasError ? 'error' : theme;
128
+ });
129
+
130
+ const modelValue = defineModel<number | readonly number[]>();
131
+
132
+ const updateRange = (step: number, withinRangeLimit: boolean) => {
133
+ if (withinRangeLimit) {
134
+ modelValue.value = (Number(modelValue.value) + step) as number;
135
+ }
136
+ };
137
+ </script>
138
+
139
+ <style lang="css">
140
+ .input-range-with-label {
141
+ .input-range-label {
142
+ display: block;
143
+ margin-block: 0.8rem;
144
+
145
+ &:hover {
146
+ cursor: pointer;
147
+ }
148
+ }
149
+
150
+ .label-description {
151
+ font-family: var(--font-family);
152
+ font-size: 1.6rem;
153
+ margin-top: 1.2rem;
154
+ }
155
+ }
156
+ </style>