srcdev-nuxt-forms 0.1.0 → 1.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 (87) hide show
  1. package/LICENSE +21 -0
  2. package/assets/styles/brand/_brand.css +150 -0
  3. package/assets/styles/brand/_brand_dark.css +152 -0
  4. package/assets/styles/brand/_palette_dark.css +148 -0
  5. package/assets/styles/brand/_palette_light.css +148 -0
  6. package/assets/styles/brand/_typography.css +176 -0
  7. package/assets/styles/brand/index.css +1 -0
  8. package/assets/styles/forms/index.css +1 -1
  9. package/assets/styles/forms/themes/_default.css +3 -0
  10. package/assets/styles/forms/themes/_error.css +45 -11
  11. package/assets/styles/forms/themes/_ghost.css +42 -10
  12. package/assets/styles/forms/themes/_primary.css +42 -10
  13. package/assets/styles/forms/themes/_secondary.css +42 -10
  14. package/assets/styles/forms/themes/_success.css +42 -11
  15. package/assets/styles/forms/themes/_tertiary.css +42 -10
  16. package/assets/styles/forms/themes/_warning.css +42 -10
  17. package/assets/styles/forms/themes/index.css +1 -0
  18. package/assets/styles/forms/variables/_palette.css +104 -0
  19. package/assets/styles/forms/variables/_theme.css +12 -18
  20. package/assets/styles/forms/variables/index.css +2 -0
  21. package/assets/styles/main.css +2 -0
  22. package/assets/styles/scaffolding/_margin-helpers.css +308 -0
  23. package/assets/styles/scaffolding/_padding-helpers.css +308 -0
  24. package/assets/styles/scaffolding/_page.css +23 -0
  25. package/assets/styles/scaffolding/index.css +3 -0
  26. package/assets/styles/variables/colors/_blue.css +2 -2
  27. package/assets/styles/variables/colors/_gray.css +2 -1
  28. package/assets/styles/variables/colors/_green.css +2 -2
  29. package/assets/styles/variables/colors/_orange.css +2 -2
  30. package/assets/styles/variables/colors/_red.css +2 -2
  31. package/assets/styles/variables/colors/_yellow.css +1 -1
  32. package/components/forms/c12/prop-validators/index.ts +8 -20
  33. package/components/forms/c12/utils.ts +14 -0
  34. package/components/forms/c12/validation-patterns/en.json +12 -0
  35. package/components/forms/form-errors/InputError.vue +177 -0
  36. package/components/forms/input-button/InputButtonCore.vue +33 -109
  37. package/components/forms/input-button/variants/InputButtonConfirm.vue +1 -1
  38. package/components/forms/input-button/variants/InputButtonSubmit.vue +1 -1
  39. package/components/forms/input-checkbox/InputCheckboxCore.vue +263 -0
  40. package/components/forms/input-checkbox/InputCheckboxWithLabel.vue +116 -0
  41. package/components/forms/input-checkbox/variants/MultipleCheckboxes.vue +167 -0
  42. package/components/forms/input-checkbox/variants/SingleCheckbox.vue +172 -0
  43. package/components/forms/input-number/InputNumberCore.vue +184 -0
  44. package/components/forms/input-number/variants/InputNumberDefault.vue +155 -0
  45. package/components/forms/input-radio/InputRadiobuttonCore.vue +212 -0
  46. package/components/forms/input-radio/InputRadiobuttonWithLabel.vue +103 -0
  47. package/components/forms/input-radio/variants/MultipleRadiobuttons.vue +166 -0
  48. package/components/forms/input-range/InputRangeCore.vue +153 -0
  49. package/components/forms/input-range/variants/InputRangeDefault.vue +159 -0
  50. package/components/forms/input-text/InputTextCore.vue +149 -87
  51. package/components/forms/input-text/variants/material/InputPasswordWithLabel.vue +99 -0
  52. package/components/forms/input-text/variants/material/InputTextAsNumberWithLabel.vue +142 -0
  53. package/components/forms/input-text/variants/material/InputTextWithLabel.vue +125 -0
  54. package/components/forms/input-textarea/InputTextareaCore.vue +161 -0
  55. package/components/forms/input-textarea/variants/InputTextareaWithLabel.vue +106 -0
  56. package/components/scaffolding/footer/NavFooter.vue +62 -0
  57. package/components/ui/content-grid/ContentGrid.vue +85 -0
  58. package/composables/useApiRequest.ts +25 -0
  59. package/composables/useErrorMessages.ts +17 -5
  60. package/composables/useFormControl.ts +149 -37
  61. package/composables/useSleep.ts +2 -2
  62. package/composables/useStyleClassPassthrough.ts +30 -0
  63. package/composables/useZodValidation.ts +120 -0
  64. package/layouts/default.vue +26 -16
  65. package/nuxt.config.ts +22 -0
  66. package/package.json +13 -8
  67. package/pages/forms/examples/buttons/index.vue +14 -13
  68. package/pages/forms/examples/material/cssbattle.vue +60 -0
  69. package/pages/forms/examples/material/text-fields.vue +551 -93
  70. package/pages/index.vue +2 -2
  71. package/pages/limit-text.vue +43 -0
  72. package/pages/typography.vue +83 -0
  73. package/server/api/places/list.get.ts +23 -0
  74. package/server/api/textFields.post.ts +37 -0
  75. package/server/api/utils/index.get.ts +20 -0
  76. package/server/data/places/cities.json +43 -0
  77. package/server/data/places/countries.json +55 -0
  78. package/server/data/utils/title.json +49 -0
  79. package/types/types.forms.ts +135 -3
  80. package/types/types.places.ts +8 -0
  81. package/types/types.zodFormControl.ts +21 -0
  82. package/components/forms/input-text/variants/material/InputEmailMaterial.vue +0 -72
  83. package/components/forms/input-text/variants/material/InputPasswordMaterial.vue +0 -88
  84. package/components/forms/input-text/variants/material/InputTextMaterial.vue +0 -75
  85. package/components/forms/input-text/variants/material/InputTextMaterialCore.vue +0 -258
  86. package/composables/useUpdateStyleClassPassthrough.ts +0 -29
  87. package/pages/forms/examples/material/text-fields-compact.vue +0 -136
@@ -1,11 +1,12 @@
1
1
  <template>
2
2
  <button
3
- :type="type"
3
+ :type
4
4
  :readonly
5
5
  :aria-disabled="readonly"
6
6
  :data-test-id="dataTestId"
7
- class="btn"
8
- :class="[`btn-${type}`, `theme-${theme}`, size, effectClass, styleClassPassthrough, { 'icon-only': isIconOnly }]"
7
+ :data-btn-theme="theme"
8
+ class="input-button-core btn"
9
+ :class="[`btn-${type}`, size, effectClass, styleClassPassthrough, { 'icon-only': isIconOnly }]"
9
10
  >
10
11
  <span v-if="useEffect && effect == 'fancy'" class="fancy"></span>
11
12
  <template v-if="hasLeftContent && !isIconOnly">
@@ -54,9 +55,9 @@ const props = defineProps({
54
55
  },
55
56
  type: {
56
57
  type: String as PropType<'submit' | 'button' | 'reset'>,
57
- default: 'submit',
58
+ default: 'button',
58
59
  validator(value: string) {
59
- return ['button', 'cancel', 'reset', 'submit'].includes(value);
60
+ return propValidators.inputTypesButton.includes(value);
60
61
  },
61
62
  },
62
63
  buttonText: {
@@ -111,16 +112,16 @@ const isIconOnly = computed(() => slots.iconOnly !== undefined);
111
112
  .btn {
112
113
  --_padding-block: var(--theme-form-button-padding-block-normal);
113
114
  --_padding-inline: var(--theme-form-button-padding-inline-normal);
114
- --_border-radius: 4px;
115
115
  --_icon-gap: var(--theme-form-button-icon-gap-normal);
116
+ --_border-width: var(--input-border-width-default);
117
+ --_outline-width: var(--input-outline-width-thin);
116
118
 
117
119
  align-items: center;
118
120
  display: flex;
119
121
  gap: var(--_icon-gap);
120
122
  justify-content: center;
121
123
  border: none;
122
- border-radius: var(--_border-radius);
123
-
124
+ border-radius: var(--input-border-radius);
124
125
  font-family: var(--font-family);
125
126
 
126
127
  padding-inline: var(--_padding-inline);
@@ -128,11 +129,33 @@ const isIconOnly = computed(() => slots.iconOnly !== undefined);
128
129
 
129
130
  transition: all 0.2s ease-in-out;
130
131
 
131
- &:hover,
132
- &:focus-visible {
132
+ background-color: var(--theme-btn-bg);
133
+ border: var(--_border-width) solid var(--theme-btn-border);
134
+ color: var(--theme-btn-text);
135
+ outline: 1px solid var(--theme-btn-outline);
136
+
137
+ /*
138
+ * States
139
+ **/
140
+ &:hover {
141
+ --theme-btn-bg: var(--theme-btn-bg-hover);
142
+ --theme-btn-border: var(--theme-btn-border-hover);
143
+ --theme-btn-text: var(--theme-btn-text-hover);
144
+ --theme-btn-outline: var(--theme-btn-outline-hover);
145
+ }
146
+
147
+ &:hover {
133
148
  cursor: pointer;
134
149
  }
135
150
 
151
+ &:focus-visible {
152
+ --theme-btn-bg: var(--theme-btn-bg-focus);
153
+ --theme-btn-border: var(--theme-btn-border-focus);
154
+ --theme-btn-text: var(--theme-btn-text-focus);
155
+ --theme-btn-outline: var(--theme-btn-outline-focus);
156
+ box-shadow: var(--theme-form-focus-box-shadow);
157
+ }
158
+
136
159
  &[readonly] {
137
160
  opacity: 0.5;
138
161
  &:hover,
@@ -264,104 +287,5 @@ const isIconOnly = computed(() => slots.iconOnly !== undefined);
264
287
  }
265
288
  }
266
289
  }
267
-
268
- --_border-width: var(--input-border-width-default);
269
-
270
- /*
271
- * Initial theme (primary)
272
- **/
273
- --_theme-form-border: var(--theme-form-primary-border);
274
- --_theme-form-border-hover: var(--theme-form-primary-border-hover);
275
- --_theme-form-outline: var(--theme-form-primary-outline);
276
- --_theme-form-outline-hover: var(--theme-form-primary-outline-hover);
277
- --_theme-form-bg: var(--theme-form-primary-bg);
278
- --_theme-form-bg-hover: var(--theme-form-primary-bg-hover);
279
- --_theme-form-color: var(--theme-form-primary-color);
280
- --_theme-form-color-hover: var(--theme-form-primary-color-hover);
281
-
282
- background-color: var(--_theme-form-bg);
283
- border: var(--_border-width) solid var(--_theme-form-border);
284
- color: var(--_theme-form-color);
285
- outline: 1px solid var(--_theme-form-outline);
286
-
287
- /*
288
- * Themes (alternate)
289
- **/
290
- &.theme-secondary {
291
- --_theme-form-border: var(--theme-form-secondary-border);
292
- --_theme-form-border-hover: var(--theme-form-secondary-border-hover);
293
- --_theme-form-outline: var(--theme-form-secondary-outline);
294
- --_theme-form-outline-hover: var(--theme-form-secondary-outline-hover);
295
- --_theme-form-bg: var(--theme-form-secondary-bg);
296
- --_theme-form-bg-hover: var(--theme-form-secondary-bg-hover);
297
- --_theme-form-color: var(--theme-form-secondary-color);
298
- --_theme-form-color-hover: var(--theme-form-secondary-color-hover);
299
- }
300
-
301
- &.theme-tertiary {
302
- --_theme-form-border: var(--theme-form-tertiary-border);
303
- --_theme-form-border-hover: var(--theme-form-tertiary-border-hover);
304
- --_theme-form-outline: var(--theme-form-tertiary-outline);
305
- --_theme-form-outline-hover: var(--theme-form-tertiary-outline-hover);
306
- --_theme-form-bg: var(--theme-form-tertiary-bg);
307
- --_theme-form-bg-hover: var(--theme-form-tertiary-bg-hover);
308
- --_theme-form-color: var(--theme-form-tertiary-color);
309
- --_theme-form-color-hover: var(--theme-form-tertiary-color-hover);
310
- }
311
-
312
- &.theme-warning {
313
- --_theme-form-border: var(--theme-form-warning-border);
314
- --_theme-form-border-hover: var(--theme-form-warning-border-hover);
315
- --_theme-form-outline: var(--theme-form-warning-outline);
316
- --_theme-form-outline-hover: var(--theme-form-warning-outline-hover);
317
- --_theme-form-bg: var(--theme-form-warning-bg);
318
- --_theme-form-bg-hover: var(--theme-form-warning-bg-hover);
319
- --_theme-form-color: var(--theme-form-warning-color);
320
- --_theme-form-color-hover: var(--theme-form-warning-color-hover);
321
- }
322
-
323
- &.theme-error {
324
- --_theme-form-border: var(--theme-form-error-border);
325
- --_theme-form-border-hover: var(--theme-form-error-border-hover);
326
- --_theme-form-outline: var(--theme-form-error-outline);
327
- --_theme-form-outline-hover: var(--theme-form-error-outline-hover);
328
- --_theme-form-bg: var(--theme-form-error-bg);
329
- --_theme-form-bg-hover: var(--theme-form-error-bg-hover);
330
- --_theme-form-color: var(--theme-form-error-color);
331
- --_theme-form-color-hover: var(--theme-form-error-color-hover);
332
- }
333
-
334
- &.theme-success {
335
- --_theme-form-border: var(--theme-form-success-border);
336
- --_theme-form-border-hover: var(--theme-form-success-border-hover);
337
- --_theme-form-outline: var(--theme-form-success-outline);
338
- --_theme-form-outline-hover: var(--theme-form-success-outline-hover);
339
- --_theme-form-bg: var(--theme-form-success-bg);
340
- --_theme-form-bg-hover: var(--theme-form-success-bg-hover);
341
- --_theme-form-color: var(--theme-form-success-color);
342
- --_theme-form-color-hover: var(--theme-form-success-color-hover);
343
- }
344
-
345
- &.theme-ghost {
346
- --_theme-form-border: var(--theme-form-ghost-border);
347
- --_theme-form-border-hover: var(--theme-form-ghost-border-hover);
348
- --_theme-form-outline: var(--theme-form-ghost-outline);
349
- --_theme-form-outline-hover: var(--theme-form-ghost-outline-hover);
350
- --_theme-form-bg: var(--theme-form-ghost-bg);
351
- --_theme-form-bg-hover: var(--theme-form-ghost-bg-hover);
352
- --_theme-form-color: var(--theme-form-ghost-color);
353
- --_theme-form-color-hover: var(--theme-form-ghost-color-hover);
354
- }
355
-
356
- /*
357
- * States
358
- **/
359
- &:hover,
360
- &:focus-visible {
361
- --_theme-form-color: var(--_theme-form-color-hover);
362
- --_theme-form-bg: var(--_theme-form-bg-hover);
363
- --_theme-form-border: var(--_theme-form-border-hover);
364
- --_theme-form-outline: var(--_theme-form-outline-hover);
365
- }
366
290
  }
367
291
  </style>
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <InputButtonCore
3
- type="submit"
3
+ type="button"
4
4
  :use-effect="useEffect"
5
5
  :isPending="isPending"
6
6
  :readonly
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <InputButtonCore
3
- type="submit"
3
+ type="button"
4
4
  :use-effect="useEffect"
5
5
  :isPending="isPending"
6
6
  :readonly
@@ -0,0 +1,263 @@
1
+ <template>
2
+ <div class="input-checkbox-wrapper" :data-form-theme="formTheme" :class="[size, checkboxAppearance, { error: fieldHasError }]">
3
+ <input
4
+ type="checkbox"
5
+ :true-value="trueValue"
6
+ :false-value="falseValue"
7
+ :id
8
+ :name
9
+ :required="required && !multipleOptions"
10
+ :value="trueValue"
11
+ :class="['input-checkbox-core', size, checkboxAppearance, { error: fieldHasError }]"
12
+ v-model="modelValue"
13
+ ref="inputField"
14
+ />
15
+ <div v-if="checkboxAppearance === 'with-decorator'" :class="['input-checkbox-decorator', size, checkboxStyle]">
16
+ <Icon name="material-symbols:check" class="icon-check" :class="[{ checked: isChecked }]" />
17
+ <div v-if="checkboxStyle === 'check' || checkboxStyle === 'cross'" :class="[checkboxStyle, { checked: isChecked }]"></div>
18
+ </div>
19
+ </div>
20
+ </template>
21
+
22
+ <script setup lang="ts">
23
+ import propValidators from '../c12/prop-validators';
24
+ const { id, name, required, trueValue, falseValue, multipleOptions, theme, styleClassPassthrough, size, checkboxAppearance, checkboxStyle, fieldHasError } = defineProps({
25
+ id: {
26
+ type: String,
27
+ required: true,
28
+ },
29
+ name: {
30
+ type: String,
31
+ required: true,
32
+ },
33
+ required: {
34
+ type: Boolean,
35
+ value: false,
36
+ },
37
+ trueValue: {
38
+ type: [String, Number, Boolean],
39
+ default: true,
40
+ },
41
+ falseValue: {
42
+ type: [String, Number, Boolean],
43
+ default: false,
44
+ },
45
+ multipleOptions: {
46
+ type: Boolean,
47
+ default: false,
48
+ },
49
+ theme: {
50
+ type: String as PropType<string>,
51
+ default: 'primary',
52
+ validator(value: string) {
53
+ return propValidators.theme.includes(value);
54
+ },
55
+ },
56
+ size: {
57
+ type: String as PropType<string>,
58
+ default: 'medium',
59
+ validator(value: string) {
60
+ return propValidators.size.includes(value);
61
+ },
62
+ },
63
+ checkboxAppearance: {
64
+ type: String as PropType<string>,
65
+ default: null,
66
+ validator(value: string) {
67
+ return propValidators.checkboxAppearance.includes(value);
68
+ },
69
+ },
70
+ checkboxStyle: {
71
+ type: String as PropType<string>,
72
+ default: 'check',
73
+ validator(value: string) {
74
+ return propValidators.checkboxStyle.includes(value);
75
+ },
76
+ },
77
+ fieldHasError: {
78
+ type: Boolean,
79
+ default: false,
80
+ },
81
+ styleClassPassthrough: {
82
+ type: Array as PropType<string[]>,
83
+ default: () => [],
84
+ },
85
+ });
86
+
87
+ const { elementClasses, updateElementClasses } = useStyleClassPassthrough(styleClassPassthrough);
88
+
89
+ const formTheme = computed(() => {
90
+ return fieldHasError ? 'error' : theme;
91
+ });
92
+
93
+ const modelValue = defineModel<any>();
94
+
95
+ const inputField = ref<HTMLInputElement | null>(null);
96
+
97
+ const isArray = Array.isArray(modelValue.value);
98
+
99
+ const isChecked = computed(() => {
100
+ if (isArray) {
101
+ return modelValue.value.indexOf(trueValue) > -1;
102
+ } else {
103
+ return modelValue.value === trueValue;
104
+ }
105
+ });
106
+ </script>
107
+
108
+ <style scoped lang="css">
109
+ .input-checkbox-wrapper {
110
+ --_checkbox-size: initial;
111
+ --_checkbox-border-radius: 4px;
112
+ --_outline-width: var(--input-outline-width-thin);
113
+ --_border-width: var(--input-border-width-thin); /* --input-border-width-default / 2px */
114
+
115
+ display: grid;
116
+ grid-template-areas: 'element-stack';
117
+
118
+ &.with-decorator {
119
+ border-radius: var(--_checkbox-border-radius);
120
+ border: var(--_border-width) solid var(--theme-form-input-border);
121
+ height: var(--_checkbox-size);
122
+ width: var(--_checkbox-size);
123
+
124
+ &:has(.input-checkbox-core:focus-visible) {
125
+ border: var(--_border-width) solid var(--theme-form-input-border-focus);
126
+ outline: var(--_outline-width) solid hsl(from var(--theme-form-input-outline-focus) h s 50%);
127
+ box-shadow: var(--theme-form-focus-box-shadow);
128
+ }
129
+ }
130
+
131
+ /* Sizes */
132
+ &.x-small {
133
+ --_checkbox-size: 20px;
134
+ }
135
+ &.small {
136
+ --_checkbox-size: 24px;
137
+ }
138
+ &.normal {
139
+ --_checkbox-size: 30px;
140
+ }
141
+ &.medium {
142
+ --_checkbox-size: 40px;
143
+ }
144
+ &.large {
145
+ --_checkbox-size: 44px;
146
+ }
147
+
148
+ .input-checkbox-decorator {
149
+ display: grid;
150
+ grid-area: element-stack;
151
+ background-color: var(--theme-form-checkbox-bg);
152
+
153
+ height: var(--_checkbox-size);
154
+ width: var(--_checkbox-size);
155
+ place-content: center;
156
+ position: relative;
157
+ z-index: -1;
158
+
159
+ :not(&.check),
160
+ :not(&.cross) {
161
+ .icon-check {
162
+ display: none;
163
+ }
164
+ }
165
+
166
+ .check {
167
+ grid-area: stack;
168
+ width: calc(var(--_checkbox-size) * 0.2);
169
+ height: calc(var(--_checkbox-size) * 0.45);
170
+ border-bottom: 3px solid var(--theme-form-checkbox-symbol);
171
+ border-right: 3px solid var(--theme-form-checkbox-symbol);
172
+ transform: rotate(45deg) translate(-1px, -1px);
173
+ opacity: 0;
174
+ transition: opacity 0.2s ease-in-out;
175
+
176
+ &.checked {
177
+ opacity: 1;
178
+ }
179
+ }
180
+
181
+ .cross {
182
+ grid-area: stack;
183
+ width: calc(var(--_checkbox-size) * 0.65);
184
+ height: 3px;
185
+ background-color: var(--theme-form-checkbox-symbol);
186
+ transform: rotate(45deg);
187
+ opacity: 0;
188
+ transition: opacity 0.2s ease-in-out;
189
+
190
+ &.checked {
191
+ opacity: 1;
192
+
193
+ &::after {
194
+ opacity: 1;
195
+ }
196
+ }
197
+
198
+ &::after {
199
+ content: '';
200
+ grid-area: stack;
201
+ display: block;
202
+ width: calc(var(--_checkbox-size) * 0.65);
203
+ height: 3px;
204
+ background-color: var(--theme-form-checkbox-symbol);
205
+ transform: rotate(-90deg);
206
+ opacity: 0;
207
+ transition: opacity 0.2s ease-in-out;
208
+ }
209
+ }
210
+
211
+ .icon-check {
212
+ grid-area: stack;
213
+ display: block;
214
+ height: var(--_checkbox-size);
215
+ width: var(--_checkbox-size);
216
+ transform: translate(-3px, 0px);
217
+ zoom: 0.75;
218
+ margin: 0;
219
+ opacity: 0;
220
+ padding: 0;
221
+ transition: opacity 0.2s ease-in-out;
222
+
223
+ &.checked {
224
+ opacity: 1;
225
+ }
226
+ }
227
+ }
228
+
229
+ .input-checkbox-core {
230
+ grid-area: element-stack;
231
+ border: var(--_border-width) solid var(--theme-form-input-border);
232
+ height: var(--_checkbox-size);
233
+ width: var(--_checkbox-size);
234
+
235
+ transition: all 0.2s ease-in-out;
236
+
237
+ &.with-decorator {
238
+ appearance: none;
239
+ margin: 0;
240
+ overflow: hidden;
241
+ opacity: 0;
242
+ }
243
+
244
+ &:hover {
245
+ cursor: pointer;
246
+ }
247
+
248
+ &:focus-visible {
249
+ border: var(--_border-width) solid var(--theme-form-input-border);
250
+ outline: var(--_outline-width) solid hsl(from var(--theme-form-input-outline-focus) h s 50%);
251
+ box-shadow: var(--theme-form-focus-box-shadow);
252
+ }
253
+
254
+ &:checked::after {
255
+ /* content: '✔'; */
256
+ display: grid;
257
+ font-family: var(--font-family);
258
+ place-content: center;
259
+ font-size: calc(var(--_checkbox-size) * 0.75);
260
+ }
261
+ }
262
+ }
263
+ </style>
@@ -0,0 +1,116 @@
1
+ <template>
2
+ <div class="input-checkbox-with-label" :class="[elementClasses, optionsLayout, { error: fieldHasError }]">
3
+ <InputCheckboxCore :id :name :required v-model="modelValue" :size :trueValue :falseValue :checkboxAppearance :checkboxStyle :fieldHasError :theme />
4
+ <label v-if="hasLabelContent" class="input-checkbox-label body-normal" :for="id">
5
+ <slot name="labelContent"></slot>
6
+ </label>
7
+ <label v-else class="input-checkbox-label body-normal-semibold" :for="id">{{ label }}</label>
8
+ </div>
9
+ </template>
10
+
11
+ <script setup lang="ts">
12
+ import propValidators from '../c12/prop-validators';
13
+
14
+ const { id, name, label, required, fieldHasError, trueValue, falseValue, size, checkboxAppearance, checkboxStyle, optionsLayout, styleClassPassthrough, theme } = defineProps({
15
+ id: {
16
+ type: String,
17
+ required: true,
18
+ },
19
+ name: {
20
+ type: String,
21
+ required: true,
22
+ },
23
+ label: {
24
+ type: String,
25
+ required: true,
26
+ },
27
+ required: {
28
+ type: Boolean,
29
+ default: false,
30
+ },
31
+ fieldHasError: {
32
+ type: Boolean,
33
+ default: false,
34
+ },
35
+ trueValue: {
36
+ type: [String, Number, Boolean],
37
+ default: true,
38
+ },
39
+ falseValue: {
40
+ type: [String, Number, Boolean],
41
+ default: false,
42
+ },
43
+ size: {
44
+ type: String as PropType<string>,
45
+ default: 'medium',
46
+ validator(value: string) {
47
+ return propValidators.size.includes(value);
48
+ },
49
+ },
50
+ checkboxAppearance: {
51
+ type: String as PropType<string>,
52
+ default: null,
53
+ validator(value: string) {
54
+ return propValidators.checkboxAppearance.includes(value);
55
+ },
56
+ },
57
+ checkboxStyle: {
58
+ type: String as PropType<string>,
59
+ default: 'check',
60
+ validator(value: string) {
61
+ return propValidators.checkboxStyle.includes(value);
62
+ },
63
+ },
64
+ optionsLayout: {
65
+ type: String as PropType<string>,
66
+ default: 'equal-widths',
67
+ validator(value: string) {
68
+ return propValidators.optionsLayout.includes(value);
69
+ },
70
+ },
71
+ styleClassPassthrough: {
72
+ type: Array as PropType<string[]>,
73
+ default: () => [],
74
+ },
75
+ theme: {
76
+ type: String as PropType<string>,
77
+ default: 'primary',
78
+ validator(value: string) {
79
+ return propValidators.theme.includes(value);
80
+ },
81
+ },
82
+ });
83
+
84
+ const slots = useSlots();
85
+ const hasLabelContent = computed(() => slots.labelContent !== undefined);
86
+ const { elementClasses, updateElementClasses } = useStyleClassPassthrough(styleClassPassthrough);
87
+
88
+ const modelValue = defineModel();
89
+ </script>
90
+
91
+ <style lang="css">
92
+ .input-checkbox-with-label {
93
+ --_white-space: wrap;
94
+
95
+ display: flex;
96
+ align-items: center;
97
+
98
+ &.inline {
99
+ --_white-space: nowrap;
100
+ }
101
+
102
+ .input-checkbox-label {
103
+ display: flex;
104
+ width: 100%;
105
+ height: 100%;
106
+ align-items: center;
107
+ margin-block: 8px;
108
+ padding-inline: 8px;
109
+ white-space: var(--_white-space);
110
+
111
+ &:hover {
112
+ cursor: pointer;
113
+ }
114
+ }
115
+ }
116
+ </style>