srcdev-nuxt-forms 6.0.1 → 6.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.
- package/README.md +45 -5
- package/app/assets/styles/extends-layer/srcdev-forms/components/_form-fieldset.css +1 -1
- package/app/assets/styles/extends-layer/srcdev-forms/components/_input-button.css +1 -1
- package/app/assets/styles/extends-layer/srcdev-forms/components/_input-checkbox-radio-core.css +1 -1
- package/app/assets/styles/extends-layer/srcdev-forms/components/_input-checkbox-radio-options-button.css +1 -1
- package/app/assets/styles/extends-layer/srcdev-forms/components/_input-error.css +1 -1
- package/app/assets/styles/extends-layer/srcdev-forms/components/_input-label.css +1 -1
- package/app/assets/styles/extends-layer/srcdev-forms/components/_input-select.css +1 -1
- package/app/assets/styles/extends-layer/srcdev-forms/components/_input-text.css +1 -1
- package/app/assets/styles/extends-layer/srcdev-forms/components/_input-textarea.css +1 -1
- package/app/assets/styles/setup/_head.css +1 -1
- package/app/assets/styles/setup/typography/vars/_reponsive-font-sizes.css +10 -10
- package/app/assets/styles/setup/typography/vars/index.css +0 -1
- package/app/components/forms/input-text/InputTextCore.vue +56 -50
- package/nuxt.config.ts +11 -11
- package/package.json +2 -2
- package/app/assets/styles/setup/typography/vars/_colors.css +0 -14
- package/app/assets/styles/setup/variables/index.css +0 -1
package/README.md
CHANGED
|
@@ -83,18 +83,58 @@ Styles exist for multiple themes/variants, primary, secondary, tertiary, error e
|
|
|
83
83
|
|
|
84
84
|
Colour scheme can be updated by modifying the css colour variables
|
|
85
85
|
|
|
86
|
-
##
|
|
86
|
+
## Styles Architecture
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
The `/app/assets/styles` folder contains the CSS architecture for this Nuxt layer, organized into two main directories:
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
### `/app/assets/styles/setup/`
|
|
91
|
+
|
|
92
|
+
This directory contains the foundational styles that will be mirrored in any app that extends this layer. It includes:
|
|
93
|
+
|
|
94
|
+
- **`index.css`** - Main setup file that imports all setup modules
|
|
95
|
+
- **`_head.css`** - Head-level styles and document setup
|
|
96
|
+
- **`a11y/`** - Accessibility utilities and variables
|
|
97
|
+
- **`theming/`** - Theme definitions, color schemes, and theme variants
|
|
98
|
+
- **`typography/`** - Typography setup, font definitions, and text utility classes
|
|
99
|
+
- **`utility-classes/`** - General utility classes including fluid spacing and animations
|
|
100
|
+
|
|
101
|
+
These styles form the base layer and will be automatically available in any app that extends this layer.
|
|
102
|
+
|
|
103
|
+
### `/app/assets/styles/extends-layer/srcdev-forms/`
|
|
104
|
+
|
|
105
|
+
This directory contains override styles specifically for apps that extend this layer. It includes:
|
|
106
|
+
|
|
107
|
+
- **`index.css`** - Main override file
|
|
108
|
+
- **`components/`** - Component-specific overrides
|
|
109
|
+
- **`setup/`** - Setup overrides for extended apps
|
|
110
|
+
|
|
111
|
+
This folder structure will also be present in the extending app's assets directory, allowing for easy customization and theming.
|
|
112
|
+
|
|
113
|
+
### Layer Override Namespace
|
|
114
|
+
|
|
115
|
+
To enable proper CSS override functionality, the extending app must include the `srcdev-forms-extended` class namespace:
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
// nuxt.config.ts in the extending app
|
|
119
|
+
export default defineNuxtConfig({
|
|
120
|
+
extends: 'srcdev-nuxt-forms',
|
|
91
121
|
app: {
|
|
92
122
|
head: {
|
|
93
123
|
htmlAttrs: {
|
|
94
|
-
class: '
|
|
124
|
+
class: 'srcdev-forms-extended',
|
|
95
125
|
},
|
|
96
126
|
},
|
|
97
127
|
},
|
|
128
|
+
});
|
|
98
129
|
```
|
|
99
130
|
|
|
100
|
-
|
|
131
|
+
**Important:** All override CSS files in the extending app's `~/assets/styles/extends-layer/srcdev-forms/` directory must use the `.srcdev-forms-extended` class as a namespace prefix to ensure proper specificity and override behavior.
|
|
132
|
+
|
|
133
|
+
Example override structure in the extending app:
|
|
134
|
+
|
|
135
|
+
```css
|
|
136
|
+
/* ~/assets/styles/extends-layer/srcdev-forms/components/button.css */
|
|
137
|
+
.srcdev-forms-extended .btn-primary {
|
|
138
|
+
/* Your custom button styles */
|
|
139
|
+
}
|
|
140
|
+
```
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
:root {
|
|
2
|
-
--step-10: clamp(4.0311rem, 3.36rem + 3.3555vw, 5.9605rem);
|
|
3
|
-
--step-9: clamp(3.3592rem, 2.8691rem + 2.4507vw, 4.7684rem);
|
|
4
|
-
--step-8: clamp(2.7994rem, 2.4462rem + 1.7658vw, 3.8147rem);
|
|
5
|
-
--step-7: clamp(2.3328rem, 2.0827rem + 1.2504vw, 3.0518rem);
|
|
6
|
-
--step-6: clamp(1.944rem, 1.771rem + 0.8651vw, 2.4414rem);
|
|
7
|
-
--step-5: clamp(1.62rem, 1.5041rem + 0.5793vw, 1.9531rem);
|
|
8
|
-
--step-4: clamp(1.35rem, 1.2761rem + 0.3696vw, 1.5625rem);
|
|
9
|
-
--step-3: clamp(1.125rem, 1.0815rem + 0.2174vw, 1.25rem);
|
|
10
|
-
--step-2: clamp(0.9375rem, 0.9158rem + 0.1087vw, 1rem);
|
|
11
|
-
--step-1: clamp(0.7813rem, 0.7747rem + 0.0326vw, 0.8rem);
|
|
2
|
+
--step-10: clamp(4.0311rem, 3.36rem + 3.3555vw, 5.9605rem);
|
|
3
|
+
--step-9: clamp(3.3592rem, 2.8691rem + 2.4507vw, 4.7684rem);
|
|
4
|
+
--step-8: clamp(2.7994rem, 2.4462rem + 1.7658vw, 3.8147rem);
|
|
5
|
+
--step-7: clamp(2.3328rem, 2.0827rem + 1.2504vw, 3.0518rem);
|
|
6
|
+
--step-6: clamp(1.944rem, 1.771rem + 0.8651vw, 2.4414rem);
|
|
7
|
+
--step-5: clamp(1.62rem, 1.5041rem + 0.5793vw, 1.9531rem);
|
|
8
|
+
--step-4: clamp(1.35rem, 1.2761rem + 0.3696vw, 1.5625rem);
|
|
9
|
+
--step-3: clamp(1.125rem, 1.0815rem + 0.2174vw, 1.25rem);
|
|
10
|
+
--step-2: clamp(0.9375rem, 0.9158rem + 0.1087vw, 1rem);
|
|
11
|
+
--step-1: clamp(0.7813rem, 0.7747rem + 0.0326vw, 0.8rem);
|
|
12
12
|
}
|
|
@@ -4,7 +4,14 @@
|
|
|
4
4
|
:data-theme="formTheme"
|
|
5
5
|
:data-size="size"
|
|
6
6
|
:data-inputmode="inputmode"
|
|
7
|
-
:class="[
|
|
7
|
+
:class="[
|
|
8
|
+
inputVariant,
|
|
9
|
+
{ dirty: isDirty },
|
|
10
|
+
{ active: isActive },
|
|
11
|
+
{ error: fieldHasError },
|
|
12
|
+
{ 'has-left-slot': hasLeftSlot },
|
|
13
|
+
{ 'has-right-slot': hasRightSlot },
|
|
14
|
+
]"
|
|
8
15
|
>
|
|
9
16
|
<span v-if="hasLeftSlot" class="slot left-slot">
|
|
10
17
|
<slot name="left"></slot>
|
|
@@ -35,22 +42,21 @@
|
|
|
35
42
|
</template>
|
|
36
43
|
|
|
37
44
|
<script setup lang="ts">
|
|
38
|
-
import propValidators from
|
|
45
|
+
import propValidators from "../c12/prop-validators"
|
|
39
46
|
|
|
40
47
|
const props = defineProps({
|
|
41
48
|
type: {
|
|
42
|
-
type: String as PropType<
|
|
43
|
-
|
|
44
|
-
default: 'text',
|
|
49
|
+
type: String as PropType<"text" | "email" | "password" | "number" | "tel" | "url">,
|
|
50
|
+
default: "text",
|
|
45
51
|
validator(value: string) {
|
|
46
|
-
return propValidators.inputTypesText.includes(value)
|
|
52
|
+
return propValidators.inputTypesText.includes(value)
|
|
47
53
|
},
|
|
48
54
|
},
|
|
49
55
|
inputmode: {
|
|
50
|
-
type: String as PropType<
|
|
51
|
-
default:
|
|
56
|
+
type: String as PropType<"text" | "email" | "tel" | "url" | "search" | "numeric" | "none" | "decimal">,
|
|
57
|
+
default: "text",
|
|
52
58
|
validator(value: string) {
|
|
53
|
-
return propValidators.inputMode.includes(value)
|
|
59
|
+
return propValidators.inputMode.includes(value)
|
|
54
60
|
},
|
|
55
61
|
},
|
|
56
62
|
maxlength: {
|
|
@@ -71,7 +77,7 @@ const props = defineProps({
|
|
|
71
77
|
},
|
|
72
78
|
placeholder: {
|
|
73
79
|
type: String,
|
|
74
|
-
default:
|
|
80
|
+
default: "",
|
|
75
81
|
},
|
|
76
82
|
fieldHasError: {
|
|
77
83
|
type: Boolean,
|
|
@@ -83,9 +89,9 @@ const props = defineProps({
|
|
|
83
89
|
},
|
|
84
90
|
theme: {
|
|
85
91
|
type: String as PropType<string>,
|
|
86
|
-
default:
|
|
92
|
+
default: "primary",
|
|
87
93
|
validator(value: string) {
|
|
88
|
-
return propValidators.theme.includes(value)
|
|
94
|
+
return propValidators.theme.includes(value)
|
|
89
95
|
},
|
|
90
96
|
},
|
|
91
97
|
ariaDescribedby: {
|
|
@@ -94,66 +100,66 @@ const props = defineProps({
|
|
|
94
100
|
},
|
|
95
101
|
size: {
|
|
96
102
|
type: String as PropType<string>,
|
|
97
|
-
default:
|
|
103
|
+
default: "default",
|
|
98
104
|
validator(value: string) {
|
|
99
|
-
return propValidators.size.includes(value)
|
|
105
|
+
return propValidators.size.includes(value)
|
|
100
106
|
},
|
|
101
107
|
},
|
|
102
108
|
inputVariant: {
|
|
103
109
|
type: String as PropType<string>,
|
|
104
|
-
default:
|
|
110
|
+
default: "normal",
|
|
105
111
|
validator(value: string) {
|
|
106
|
-
return propValidators.inputVariant.includes(value)
|
|
112
|
+
return propValidators.inputVariant.includes(value)
|
|
107
113
|
},
|
|
108
114
|
},
|
|
109
|
-
})
|
|
115
|
+
})
|
|
110
116
|
|
|
111
|
-
const slots = useSlots()
|
|
112
|
-
const hasLeftSlot = computed(() => slots.left !== undefined)
|
|
113
|
-
const hasRightSlot = computed(() => slots.right !== undefined)
|
|
117
|
+
const slots = useSlots()
|
|
118
|
+
const hasLeftSlot = computed(() => slots.left !== undefined)
|
|
119
|
+
const hasRightSlot = computed(() => slots.right !== undefined)
|
|
114
120
|
|
|
115
121
|
const formTheme = computed(() => {
|
|
116
|
-
return props.fieldHasError ?
|
|
117
|
-
})
|
|
122
|
+
return props.fieldHasError ? "error" : props.theme
|
|
123
|
+
})
|
|
118
124
|
|
|
119
|
-
const modelValue = defineModel()
|
|
120
|
-
const isDirty = defineModel(
|
|
121
|
-
const isActive = defineModel(
|
|
125
|
+
const modelValue = defineModel()
|
|
126
|
+
const isDirty = defineModel("isDirty")
|
|
127
|
+
const isActive = defineModel("isActive")
|
|
122
128
|
|
|
123
129
|
const inputPattern = computed(() => {
|
|
124
|
-
return props.inputmode ===
|
|
125
|
-
})
|
|
130
|
+
return props.inputmode === "numeric" ? "[0-9]+" : undefined
|
|
131
|
+
})
|
|
126
132
|
|
|
127
133
|
const updateFocus = (isFocused: boolean) => {
|
|
128
|
-
isActive.value = isFocused
|
|
129
|
-
}
|
|
134
|
+
isActive.value = isFocused
|
|
135
|
+
}
|
|
130
136
|
|
|
131
|
-
const inputField = ref<HTMLInputElement | null>(null)
|
|
137
|
+
const inputField = ref<HTMLInputElement | null>(null)
|
|
132
138
|
|
|
133
|
-
const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough)
|
|
139
|
+
const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough)
|
|
134
140
|
|
|
135
141
|
// TODO: Move this to a utility function to allow removeEventListener on unmounted
|
|
136
142
|
// Leaving like this could lead to memory leaks
|
|
137
143
|
const validateInput = () => {
|
|
138
144
|
if (inputField.value !== null) {
|
|
139
|
-
inputField.value.addEventListener(
|
|
140
|
-
let beforeValue = modelValue.value
|
|
145
|
+
inputField.value.addEventListener("beforeinput", (event: any) => {
|
|
146
|
+
let beforeValue = modelValue.value
|
|
141
147
|
event.target.addEventListener(
|
|
142
|
-
|
|
148
|
+
"input",
|
|
143
149
|
() => {
|
|
144
150
|
if (inputField.value !== null && inputField.value.validity.patternMismatch) {
|
|
145
|
-
inputField.value.value = beforeValue as string
|
|
151
|
+
inputField.value.value = beforeValue as string
|
|
146
152
|
}
|
|
147
153
|
},
|
|
148
154
|
{ once: true }
|
|
149
|
-
)
|
|
150
|
-
})
|
|
155
|
+
)
|
|
156
|
+
})
|
|
151
157
|
}
|
|
152
|
-
}
|
|
158
|
+
}
|
|
153
159
|
|
|
154
160
|
onMounted(() => {
|
|
155
|
-
if (props.inputmode ===
|
|
156
|
-
})
|
|
161
|
+
if (props.inputmode === "numeric") validateInput()
|
|
162
|
+
})
|
|
157
163
|
</script>
|
|
158
164
|
|
|
159
165
|
<style lang="css">
|
|
@@ -197,13 +203,13 @@ onMounted(() => {
|
|
|
197
203
|
place-items: center;
|
|
198
204
|
background-clip: padding-box;
|
|
199
205
|
|
|
200
|
-
&.left-slot:not([data-theme=
|
|
206
|
+
&.left-slot:not([data-theme="input-action"]) {
|
|
201
207
|
.icon {
|
|
202
208
|
width: 2.2rem;
|
|
203
209
|
height: 2.2rem;
|
|
204
210
|
}
|
|
205
211
|
|
|
206
|
-
[data-theme=
|
|
212
|
+
[data-theme="input-action"] {
|
|
207
213
|
width: initial;
|
|
208
214
|
height: initial;
|
|
209
215
|
padding: 0.5rem;
|
|
@@ -214,13 +220,13 @@ onMounted(() => {
|
|
|
214
220
|
}
|
|
215
221
|
}
|
|
216
222
|
}
|
|
217
|
-
&.right-slot:not([data-theme=
|
|
223
|
+
&.right-slot:not([data-theme="input-action"]) {
|
|
218
224
|
.icon {
|
|
219
225
|
width: 2.2rem;
|
|
220
226
|
height: 2.2rem;
|
|
221
227
|
}
|
|
222
228
|
|
|
223
|
-
[data-theme=
|
|
229
|
+
[data-theme="input-action"] {
|
|
224
230
|
width: initial;
|
|
225
231
|
height: initial;
|
|
226
232
|
padding: 0.5rem;
|
|
@@ -233,12 +239,12 @@ onMounted(() => {
|
|
|
233
239
|
}
|
|
234
240
|
}
|
|
235
241
|
|
|
236
|
-
&[data-inputmode=
|
|
242
|
+
&[data-inputmode="numeric"] {
|
|
237
243
|
padding-block: 0rem;
|
|
238
244
|
padding-inline: 0.75rem;
|
|
239
245
|
|
|
240
246
|
.slot {
|
|
241
|
-
[data-theme=
|
|
247
|
+
[data-theme="input-action"] {
|
|
242
248
|
width: initial;
|
|
243
249
|
height: initial;
|
|
244
250
|
padding: 0.5rem;
|
|
@@ -281,13 +287,13 @@ onMounted(() => {
|
|
|
281
287
|
place-items: center;
|
|
282
288
|
background-clip: padding-box;
|
|
283
289
|
|
|
284
|
-
&.left-slot:not([data-theme=
|
|
290
|
+
&.left-slot:not([data-theme="input-action-underlined"]) {
|
|
285
291
|
.icon {
|
|
286
292
|
width: 2.2rem;
|
|
287
293
|
height: 2.2rem;
|
|
288
294
|
}
|
|
289
295
|
|
|
290
|
-
[data-theme=
|
|
296
|
+
[data-theme="input-action-underlined"] {
|
|
291
297
|
width: initial;
|
|
292
298
|
height: initial;
|
|
293
299
|
padding: 0.5rem;
|
|
@@ -298,13 +304,13 @@ onMounted(() => {
|
|
|
298
304
|
}
|
|
299
305
|
}
|
|
300
306
|
}
|
|
301
|
-
&.right-slot:not([data-theme=
|
|
307
|
+
&.right-slot:not([data-theme="input-action-underlined"]) {
|
|
302
308
|
.icon {
|
|
303
309
|
width: 2.2rem;
|
|
304
310
|
height: 2.2rem;
|
|
305
311
|
}
|
|
306
312
|
|
|
307
|
-
[data-theme=
|
|
313
|
+
[data-theme="input-action-underlined"] {
|
|
308
314
|
width: initial;
|
|
309
315
|
height: initial;
|
|
310
316
|
padding: 0.5rem;
|
package/nuxt.config.ts
CHANGED
|
@@ -2,39 +2,39 @@
|
|
|
2
2
|
|
|
3
3
|
export default defineNuxtConfig({
|
|
4
4
|
devtools: { enabled: true },
|
|
5
|
-
css: [
|
|
6
|
-
modules: [
|
|
5
|
+
css: ["modern-normalize", "./app/assets/styles/main.css"],
|
|
6
|
+
modules: ["@nuxt/eslint", "@nuxt/icon", "@nuxt/test-utils/module"],
|
|
7
7
|
alias: {
|
|
8
|
-
|
|
8
|
+
"#shared": "./shared",
|
|
9
9
|
},
|
|
10
10
|
typescript: {
|
|
11
11
|
tsConfig: {
|
|
12
12
|
compilerOptions: {
|
|
13
|
-
types: [
|
|
13
|
+
types: ["vitest/globals"], // TypeScript support for globals
|
|
14
14
|
},
|
|
15
15
|
},
|
|
16
16
|
},
|
|
17
17
|
app: {
|
|
18
18
|
head: {
|
|
19
19
|
htmlAttrs: {
|
|
20
|
-
lang:
|
|
21
|
-
|
|
20
|
+
lang: "en",
|
|
21
|
+
"data-color-scheme": "auto",
|
|
22
22
|
},
|
|
23
|
-
titleTemplate:
|
|
24
|
-
meta: [{ charset:
|
|
23
|
+
titleTemplate: "%s - Website name",
|
|
24
|
+
meta: [{ charset: "utf-8" }, { name: "viewport", content: "width=device-width, initial-scale=1" }],
|
|
25
25
|
},
|
|
26
26
|
},
|
|
27
27
|
components: [
|
|
28
28
|
{
|
|
29
|
-
path:
|
|
29
|
+
path: "./components",
|
|
30
30
|
pathPrefix: false,
|
|
31
31
|
},
|
|
32
32
|
],
|
|
33
33
|
vue: {
|
|
34
34
|
runtimeCompiler: true,
|
|
35
35
|
},
|
|
36
|
-
compatibilityDate:
|
|
36
|
+
compatibilityDate: "2024-12-01",
|
|
37
37
|
future: {
|
|
38
38
|
compatibilityVersion: 4,
|
|
39
39
|
},
|
|
40
|
-
})
|
|
40
|
+
})
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "srcdev-nuxt-forms",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "6.0
|
|
4
|
+
"version": "6.1.0",
|
|
5
5
|
"main": "nuxt.config.ts",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"clean": "rm -rf .nuxt && rm -rf .output && rm -rf .playground/.nuxt && rm -rf .playground/.output",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"@iconify-json/carbon": "1.2.10",
|
|
27
27
|
"@iconify-json/material-symbols": "1.2.29",
|
|
28
28
|
"@iconify-json/material-symbols-light": "1.2.29",
|
|
29
|
-
"@nuxt/eslint
|
|
29
|
+
"@nuxt/eslint": "1.8.0",
|
|
30
30
|
"@nuxt/icon": "1.15.0",
|
|
31
31
|
"@nuxt/test-utils": "3.19.2",
|
|
32
32
|
"@vue/test-utils": "2.4.6",
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
:root {
|
|
2
|
-
--theme-link-default: light-dark(var(--blue-12), var(--blue-4));
|
|
3
|
-
|
|
4
|
-
--page-bg: light-dark(var(--gray-0), var(--gray-9));
|
|
5
|
-
|
|
6
|
-
--surface-subtle: light-dark(var(--gray-1), var(--gray-8));
|
|
7
|
-
|
|
8
|
-
--grayscale-text-title: light-dark(var(--gray-12), var(--gray-2));
|
|
9
|
-
--grayscale-text-body: light-dark(var(--gray-12), var(--gray-3));
|
|
10
|
-
--grayscale-text-subtitle: light-dark(var(--gray-12), var(--gray-2));
|
|
11
|
-
--grayscale-text-caption: light-dark(var(--gray-12), var(--gray-2));
|
|
12
|
-
--grayscale-text-negative: light-dark(var(--gray-12), var(--gray-2));
|
|
13
|
-
--grayscale-text-disabled: light-dark(var(--gray-12), var(--gray-2));
|
|
14
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
@import './colors';
|