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,216 @@
1
+ <template>
2
+ <div class="toggle-switch-core" :class="elementClasses" :data-size="size" :data-form-theme="formTheme">
3
+ <div @click="toggleSwitchValue" class="toggle-switch-input" :class="[{ round }]" :for="inputId">
4
+ <input type="checkbox" v-model="modelValue" :true-value :false-value :aria-invalid="fieldHasError" :id="inputId" :aria-describedby="`${id}-description`" :name :required />
5
+ <div class="symbol-wrapper" :class="[{ round }]">
6
+ <div class="symbol" :class="[{ round }]">
7
+ <div v-if="hasIconOnSlot" class="symbol-icon icon-on">
8
+ <slot name="iconOn"></slot>
9
+ </div>
10
+
11
+ <div v-if="hasIconOffSlot" class="symbol-icon icon-off">
12
+ <slot name="iconOff"></slot>
13
+ </div>
14
+ </div>
15
+ </div>
16
+ </div>
17
+ </div>
18
+ </template>
19
+
20
+ <script setup lang="ts">
21
+ import propValidators from '../c12/prop-validators';
22
+
23
+ const props = defineProps({
24
+ id: {
25
+ type: String,
26
+ required: true,
27
+ },
28
+ name: {
29
+ type: String,
30
+ required: true,
31
+ },
32
+ required: {
33
+ type: Boolean,
34
+ default: false,
35
+ },
36
+ fieldHasError: {
37
+ type: Boolean,
38
+ default: false,
39
+ },
40
+ trueValue: {
41
+ type: [String, Number, Boolean],
42
+ default: true,
43
+ },
44
+ falseValue: {
45
+ type: [String, Number, Boolean],
46
+ default: false,
47
+ },
48
+ styleClassPassthrough: {
49
+ type: Array as PropType<string[]>,
50
+ default: () => [],
51
+ },
52
+ theme: {
53
+ type: String as PropType<string>,
54
+ default: 'primary',
55
+ validator(value: string) {
56
+ return propValidators.theme.includes(value);
57
+ },
58
+ },
59
+ round: {
60
+ type: Boolean,
61
+ default: true,
62
+ },
63
+ size: {
64
+ type: String as PropType<string>,
65
+ default: 'normal',
66
+ validator(value: string) {
67
+ return propValidators.size.includes(value);
68
+ },
69
+ },
70
+ ariaDescribedby: {
71
+ type: String,
72
+ default: null,
73
+ },
74
+ });
75
+
76
+ const slots = useSlots();
77
+ const hasIconOnSlot = computed(() => slots.iconOn !== undefined);
78
+ const hasIconOffSlot = computed(() => slots.iconOff !== undefined);
79
+
80
+ const formTheme = computed(() => {
81
+ return props.fieldHasError ? 'error' : props.theme;
82
+ });
83
+
84
+ const modelValue = defineModel();
85
+ const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
86
+
87
+ const inputId = computed(() => `toggle-sitch-${props.id}`);
88
+
89
+ const toggleSwitchValue = () => {
90
+ modelValue.value = modelValue.value === props.trueValue ? props.falseValue : props.trueValue;
91
+ };
92
+ </script>
93
+
94
+ <style lang="css">
95
+ .toggle-switch-core {
96
+ --_transition-duration: 0.4s;
97
+
98
+ .toggle-switch-label {
99
+ display: block;
100
+ }
101
+
102
+ .toggle-switch-input {
103
+ position: relative;
104
+ display: inline-block;
105
+ height: calc(var(--form-toggle-symbol-size) + calc(var(--form-element-border-width) * 2) + calc(var(--form-element-outline-width) * 2));
106
+ width: calc(var(--form-toggle-symbol-size) * 2 - calc(var(--form-element-border-width) * 2) + calc(var(--form-element-outline-width) * 2) + var(--form-toggle-switch-width-adjustment));
107
+
108
+ input {
109
+ opacity: 0;
110
+ width: 0;
111
+ height: 0;
112
+ }
113
+ input:checked {
114
+ --_icon-on-opacity: 1;
115
+ --_icon-off-opacity: 0;
116
+ }
117
+
118
+ .symbol-wrapper {
119
+ position: absolute;
120
+ cursor: pointer;
121
+ top: 0;
122
+ left: 0;
123
+ right: 0;
124
+ bottom: 0;
125
+ overflow: clip;
126
+
127
+ .symbol {
128
+ display: grid;
129
+ grid-template-areas: 'icon-stack';
130
+ overflow: clip;
131
+ position: absolute;
132
+
133
+ .symbol-icon {
134
+ grid-area: icon-stack;
135
+ display: flex;
136
+ align-items: center;
137
+ justify-content: center;
138
+ }
139
+ }
140
+ }
141
+ }
142
+ }
143
+
144
+ /*
145
+ * ToggleSwitch configurable
146
+ **/
147
+ .toggle-switch-core {
148
+ .toggle-switch-input {
149
+ &.round {
150
+ border-radius: calc(var(--form-toggle-symbol-size) + calc(var(--form-element-border-width) * 2));
151
+ }
152
+
153
+ .symbol-wrapper {
154
+ border: var(--theme-form-toggle-border);
155
+ background-color: var(--theme-form-toggle-bg-off);
156
+ outline: var(--theme-form-toggle-outline);
157
+ transition: 0.4s;
158
+
159
+ &.round {
160
+ border-radius: var(--form-toggle-symbol-size);
161
+ }
162
+ .symbol {
163
+ height: calc(var(--form-toggle-symbol-size) - 0.6rem);
164
+ width: calc(var(--form-toggle-symbol-size) - 0.6rem);
165
+ left: 0.4rem;
166
+ bottom: 0.4rem;
167
+ background-color: var(--theme-form-toggle-symbol-off);
168
+ transition: var(--_transition-duration);
169
+
170
+ &.round {
171
+ border-radius: 50%;
172
+ }
173
+
174
+ .symbol-icon {
175
+ transition: var(--_transition-duration);
176
+
177
+ &.icon-on {
178
+ color: var(--theme-form-toggle-icon-stroke-colour-on);
179
+ opacity: 0;
180
+ }
181
+ &.icon-off {
182
+ color: var(--theme-form-toggle-icon-stroke-colour-off);
183
+ opacity: 1;
184
+ }
185
+
186
+ .icon {
187
+ --_icon-size: var(--form-icon-size);
188
+ height: var(--_icon-size);
189
+ width: var(--_icon-size);
190
+ }
191
+ }
192
+ }
193
+ }
194
+
195
+ input:focus-visible + .symbol-wrapper {
196
+ box-shadow: var(--box-shadow-on);
197
+ outline: var(--form-element-outline-width) solid hsl(from var(--theme-form-input-outline-focus) h s 90%);
198
+ }
199
+
200
+ input:checked + .symbol-wrapper .symbol {
201
+ --_on-position: calc(var(--form-toggle-symbol-size) * 0.8);
202
+ background-color: var(--theme-form-toggle-symbol-on);
203
+ transform: translateX(var(--_on-position));
204
+
205
+ .symbol-icon {
206
+ &.icon-on {
207
+ opacity: 1;
208
+ }
209
+ &.icon-off {
210
+ opacity: 0;
211
+ }
212
+ }
213
+ }
214
+ }
215
+ }
216
+ </style>
@@ -0,0 +1,105 @@
1
+ <template>
2
+ <div class="toggle-switch-with-label" :class="[elementClasses]" :data-form-theme="formTheme">
3
+ <label class="toggle-switch-label input-text-label body-normal-bold" :for="`toggle-sitch-${id}`">{{ label }}</label>
4
+ <div v-if="hasDescriptionSlot" :id="`${id}-description`">
5
+ <slot name="description"></slot>
6
+ </div>
7
+ <ToggleSwitchCore v-model="modelValue" :id :name :required :field-has-error :true-value :false-value :theme :round :size :ariaDescribedby>
8
+ <template v-if="hasIconOnSlot" #iconOn>
9
+ <slot name="iconOn"></slot>
10
+ </template>
11
+
12
+ <template v-if="hasIconOffSlot" #iconOff>
13
+ <slot name="iconOff"></slot>
14
+ </template>
15
+ </ToggleSwitchCore>
16
+ <InputError :errorMessage :showError="fieldHasError" :id="errorId" :isDetached="true" />
17
+ </div>
18
+ </template>
19
+
20
+ <script setup lang="ts">
21
+ import propValidators from '../../c12/prop-validators';
22
+
23
+ const props = defineProps({
24
+ name: {
25
+ type: String,
26
+ required: true,
27
+ },
28
+ label: {
29
+ type: String,
30
+ required: true,
31
+ },
32
+ required: {
33
+ type: Boolean,
34
+ default: false,
35
+ },
36
+ errorMessage: {
37
+ type: [Object, String],
38
+ default: '',
39
+ required: false,
40
+ },
41
+ fieldHasError: {
42
+ type: Boolean,
43
+ default: false,
44
+ },
45
+ trueValue: {
46
+ type: [String, Number, Boolean],
47
+ default: true,
48
+ },
49
+ falseValue: {
50
+ type: [String, Number, Boolean],
51
+ default: false,
52
+ },
53
+ styleClassPassthrough: {
54
+ type: Array as PropType<string[]>,
55
+ default: () => [],
56
+ },
57
+ theme: {
58
+ type: String as PropType<string>,
59
+ default: 'primary',
60
+ validator(value: string) {
61
+ return propValidators.theme.includes(value);
62
+ },
63
+ },
64
+ round: {
65
+ type: Boolean,
66
+ default: true,
67
+ },
68
+ size: {
69
+ type: String as PropType<string>,
70
+ default: 'normal',
71
+ validator(value: string) {
72
+ return propValidators.size.includes(value);
73
+ },
74
+ },
75
+ });
76
+
77
+ const slots = useSlots();
78
+ const hasDescriptionSlot = computed(() => slots.description !== undefined);
79
+ const hasIconOnSlot = computed(() => slots.iconOn !== undefined);
80
+ const hasIconOffSlot = computed(() => slots.iconOff !== undefined);
81
+
82
+ const formTheme = computed(() => {
83
+ return props.fieldHasError ? 'error' : props.theme;
84
+ });
85
+
86
+ const id = useId();
87
+ const errorId = `${id}-error-message`;
88
+ const ariaDescribedby = computed(() => {
89
+ const ariaDescribedbyId = hasDescriptionSlot.value ? `${id}-description` : undefined;
90
+ return props.fieldHasError ? errorId : ariaDescribedbyId;
91
+ });
92
+
93
+ const modelValue = defineModel();
94
+ const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
95
+ </script>
96
+
97
+ <style lang="css">
98
+ .toggle-switch-with-label {
99
+ --_transition-duration: 0.4s;
100
+
101
+ .toggle-switch-label {
102
+ display: block;
103
+ }
104
+ }
105
+ </style>
@@ -0,0 +1,102 @@
1
+ <template>
2
+ <div class="toggle-switch-with-label-inline" :class="[elementClasses]" :data-form-theme="theme">
3
+ <label class="toggle-switch-label input-text-label" :class="labelWeightClass" :for="`toggle-sitch-${id}`">{{ label }}</label>
4
+ <ToggleSwitchCore v-model="modelValue" :id :name :true-value :false-value :theme :round :size>
5
+ <template v-if="hasIconOnSlot" #iconOn>
6
+ <slot name="iconOn"></slot>
7
+ </template>
8
+
9
+ <template v-if="hasIconOffSlot" #iconOff>
10
+ <slot name="iconOff"></slot>
11
+ </template>
12
+ </ToggleSwitchCore>
13
+ </div>
14
+ </template>
15
+
16
+ <script setup lang="ts">
17
+ import propValidators from '../../c12/prop-validators';
18
+
19
+ const props = defineProps({
20
+ name: {
21
+ type: String,
22
+ required: true,
23
+ },
24
+ label: {
25
+ type: String,
26
+ required: true,
27
+ },
28
+ labelWeight: {
29
+ type: String as PropType<string>,
30
+ default: 'semi-bold',
31
+ validator(value: string) {
32
+ return propValidators.labelWeight.includes(value);
33
+ },
34
+ },
35
+ trueValue: {
36
+ type: [String, Number, Boolean],
37
+ default: true,
38
+ },
39
+ falseValue: {
40
+ type: [String, Number, Boolean],
41
+ default: false,
42
+ },
43
+ styleClassPassthrough: {
44
+ type: Array as PropType<string[]>,
45
+ default: () => [],
46
+ },
47
+ theme: {
48
+ type: String as PropType<string>,
49
+ default: 'primary',
50
+ validator(value: string) {
51
+ return propValidators.theme.includes(value);
52
+ },
53
+ },
54
+ round: {
55
+ type: Boolean,
56
+ default: true,
57
+ },
58
+ size: {
59
+ type: String as PropType<string>,
60
+ default: 'normal',
61
+ validator(value: string) {
62
+ return propValidators.size.includes(value);
63
+ },
64
+ },
65
+ });
66
+
67
+ const slots = useSlots();
68
+ const hasIconOnSlot = computed(() => slots.iconOn !== undefined);
69
+ const hasIconOffSlot = computed(() => slots.iconOff !== undefined);
70
+
71
+ const id = useId();
72
+
73
+ const labelWeightClass = computed(() => {
74
+ switch (props.labelWeight) {
75
+ case 'bold':
76
+ return 'body-normal-bold';
77
+ case 'semi-bold':
78
+ return 'body-normal-semibold';
79
+ case 'normal':
80
+ return 'body-normal';
81
+ default:
82
+ return 'body-normal-semibold';
83
+ }
84
+ });
85
+
86
+ const modelValue = defineModel();
87
+ const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
88
+ </script>
89
+
90
+ <style lang="css">
91
+ .toggle-switch-with-label-inline {
92
+ --_transition-duration: 0.4s;
93
+ display: flex;
94
+ align-items: center;
95
+ gap: 12px;
96
+
97
+ .toggle-switch-label {
98
+ display: block;
99
+ white-space: nowrap;
100
+ }
101
+ }
102
+ </style>
@@ -0,0 +1,78 @@
1
+ <template>
2
+ <div class="form-field" :class="[width, styleClassPassthrough, { 'has-gutter': hasGutter }, { error: fieldHasError }]">
3
+ <div class="form-field-inner">
4
+ <slot name="default"></slot>
5
+ </div>
6
+ </div>
7
+ </template>
8
+
9
+ <script setup lang="ts">
10
+ defineProps({
11
+ width: {
12
+ type: String as PropType<string>,
13
+ default: 'narrow',
14
+ validator: (val: string) => ['narrow', 'medium', 'wide'].includes(val),
15
+ },
16
+ fieldHasError: {
17
+ type: Boolean as PropType<boolean>,
18
+ default: false,
19
+ },
20
+ hasGutter: {
21
+ type: Boolean as PropType<boolean>,
22
+ default: true,
23
+ },
24
+ styleClassPassthrough: {
25
+ type: String,
26
+ default: '',
27
+ },
28
+ });
29
+ </script>
30
+
31
+ <style lang="css">
32
+ .form-field {
33
+ --_gutter-width: 0rem;
34
+ --_max-width: 400px;
35
+ --_background-color: transparent;
36
+ --_border-radius: 0.4rem;
37
+
38
+ background-color: var(--_background-color);
39
+ border-radius: var(--_border-radius);
40
+ margin-inline: auto;
41
+ margin-block: 1lh;
42
+
43
+ width: min(100% - calc(2 * var(--_gutter-width)), var(--_max-width));
44
+ outline: 0rem solid var(--gray-5);
45
+
46
+ &.error {
47
+ background-color: var(--theme-error-surface);
48
+ }
49
+
50
+ &:has(.underline) {
51
+ --_background-color: var(--theme-form-input-bg-underlined);
52
+ }
53
+
54
+ .form-field-inner {
55
+ background-color: var(--_background-color);
56
+ border-radius: var(--_border-radius);
57
+ margin-inline-start: 0rem;
58
+ padding-inline-start: 0rem;
59
+ outline: 0 solid var(--gray-5);
60
+ }
61
+
62
+ &.has-gutter {
63
+ --_gutter-width: 1.6rem;
64
+ }
65
+
66
+ &.narrow {
67
+ max-width: 400px;
68
+ }
69
+
70
+ &.medium {
71
+ --_max-width: 800px;
72
+ }
73
+
74
+ &.wide {
75
+ --_max-width: 1200px;
76
+ }
77
+ }
78
+ </style>
@@ -0,0 +1,35 @@
1
+ <template>
2
+ <div class="form-wrapper" :class="width">
3
+ <slot name="default"></slot>
4
+ </div>
5
+ </template>
6
+
7
+ <script setup lang="ts">
8
+ defineProps({
9
+ width: {
10
+ type: String as PropType<string>,
11
+ default: 'narrow',
12
+ validator: (val: string) => ['narrow', 'medium', 'wide'].includes(val),
13
+ },
14
+ });
15
+ </script>
16
+
17
+ <style lang="css">
18
+ .form-wrapper {
19
+ outline: 0rem solid var(--gray-12);
20
+ padding-bottom: 2rem;
21
+ margin-trim: block;
22
+
23
+ &.narrow {
24
+ max-width: 400px;
25
+ }
26
+
27
+ &.medium {
28
+ max-width: 800px;
29
+ }
30
+
31
+ &.wide {
32
+ max-width: 1200px;
33
+ }
34
+ }
35
+ </style>