srcdev-nuxt-forms 6.1.9 → 6.1.11
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.
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="triple-toggle-switch" :data-size="size" :data-theme="theme">
|
|
3
|
+
<div class="triple-toggle-switch-wrapper">
|
|
4
|
+
<div class="selected-option-marker-wrapper">
|
|
5
|
+
<div class="selected-option-marker" :class="[{ show: showMarker }]"></div>
|
|
6
|
+
</div>
|
|
7
|
+
<div class="option-group-wrapper">
|
|
8
|
+
<div v-for="(option, index) in fieldData.data" :key="option.id" class="option-group" ref="optionGroup">
|
|
9
|
+
<Icon v-if="option.icon" :name="option.icon" class="option-icon" ref="optionIcons" />
|
|
10
|
+
<input
|
|
11
|
+
type="radio"
|
|
12
|
+
:id="option.id"
|
|
13
|
+
name="colour-scheme"
|
|
14
|
+
class="option-input"
|
|
15
|
+
v-model="modelValue"
|
|
16
|
+
:value="option.value"
|
|
17
|
+
/>
|
|
18
|
+
<label :for="option.id" class="sr-only">{{ option.label }}</label>
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
</template>
|
|
24
|
+
|
|
25
|
+
<script setup lang="ts">
|
|
26
|
+
import propValidators from "../../forms/c12/prop-validators"
|
|
27
|
+
|
|
28
|
+
const props = defineProps({
|
|
29
|
+
name: {
|
|
30
|
+
type: String,
|
|
31
|
+
defaul: "triple-toggle-switch",
|
|
32
|
+
},
|
|
33
|
+
size: {
|
|
34
|
+
type: String as PropType<string>,
|
|
35
|
+
default: "medium",
|
|
36
|
+
validator(value: string) {
|
|
37
|
+
return propValidators.size.includes(value)
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
theme: {
|
|
41
|
+
type: String as PropType<string>,
|
|
42
|
+
default: "primary",
|
|
43
|
+
validator(value: string) {
|
|
44
|
+
return propValidators.theme.includes(value)
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
stepAnimationDuration: {
|
|
48
|
+
type: Number as PropType<number>,
|
|
49
|
+
default: 100,
|
|
50
|
+
},
|
|
51
|
+
styleClassPassthrough: {
|
|
52
|
+
type: Array as PropType<string[]>,
|
|
53
|
+
default: () => [],
|
|
54
|
+
},
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
const modelValue = defineModel()
|
|
58
|
+
|
|
59
|
+
const fieldData = defineModel("fieldData") as Ref<IFormMultipleOptions>
|
|
60
|
+
|
|
61
|
+
const optionGroupRefs = useTemplateRef<HTMLDivElement>("optionGroup")
|
|
62
|
+
|
|
63
|
+
const iconWidth = ref("0px")
|
|
64
|
+
const showMarker = ref(false)
|
|
65
|
+
|
|
66
|
+
const selectedOptionIndex = computed(() => {
|
|
67
|
+
return fieldData.value.data.findIndex((option) => option.value === modelValue.value)
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
const setupDefaults = () => {
|
|
71
|
+
if (Array.isArray(optionGroupRefs.value) && optionGroupRefs.value[0]) {
|
|
72
|
+
iconWidth.value = optionGroupRefs.value[0].getBoundingClientRect().width + "px"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
onMounted(() => {
|
|
77
|
+
setupDefaults()
|
|
78
|
+
})
|
|
79
|
+
</script>
|
|
80
|
+
|
|
81
|
+
<style lang="css">
|
|
82
|
+
.triple-toggle-switch {
|
|
83
|
+
--_form-border-colour: var(--theme-form-radio-border);
|
|
84
|
+
|
|
85
|
+
--_form-outline-colour: var(--theme-form-radio-outline);
|
|
86
|
+
|
|
87
|
+
--_form-border-radius: calc(
|
|
88
|
+
(var(--_scheme-icon-font-size) / 2) + var(--form-element-border-width) + var(--form-element-outline-width) +
|
|
89
|
+
var(--_form-padding) + var(--_select-scheme-group-padding) + var(--form-element-border-width) +
|
|
90
|
+
var(--form-element-outline-width)
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
--_form-items-gap: 1rem;
|
|
94
|
+
--_form-padding: 0.6rem;
|
|
95
|
+
|
|
96
|
+
--_select-scheme-group-background-color: var(--theme-form-checkbox-bg);
|
|
97
|
+
--_select-scheme-group-background-image: none;
|
|
98
|
+
--_select-scheme-group-padding: 0.5rem;
|
|
99
|
+
--_scheme-icon-font-size: 2rem;
|
|
100
|
+
--_scheme-icon-colour: black;
|
|
101
|
+
|
|
102
|
+
&:has(input[value="auto"]:checked) {
|
|
103
|
+
--_select-scheme-group-background-color: transparent;
|
|
104
|
+
--_select-scheme-group-background-image: radial-gradient(
|
|
105
|
+
circle,
|
|
106
|
+
rgb(66, 180, 58) 0%,
|
|
107
|
+
rgb(17, 199, 0) 27%,
|
|
108
|
+
rgb(8, 117, 3) 100%
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
&:has(input[value="light"]:checked) {
|
|
113
|
+
--_select-scheme-group-background-color: transparent;
|
|
114
|
+
--_select-scheme-group-background-image: radial-gradient(
|
|
115
|
+
circle,
|
|
116
|
+
rgba(180, 58, 91, 1) 0%,
|
|
117
|
+
rgba(253, 29, 29, 1) 27%,
|
|
118
|
+
rgba(252, 176, 69, 1) 100%
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
&:has(input[value="dark"]:checked) {
|
|
123
|
+
--_select-scheme-group-background-color: transparent;
|
|
124
|
+
--_select-scheme-group-background-image: radial-gradient(
|
|
125
|
+
circle,
|
|
126
|
+
rgb(50, 20, 25) 0%,
|
|
127
|
+
rgb(0, 0, 0) 27%,
|
|
128
|
+
rgb(100, 100, 100) 100%
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.triple-toggle-switch-wrapper {
|
|
133
|
+
display: inline-grid;
|
|
134
|
+
grid-template-areas: "select-stack";
|
|
135
|
+
width: fit-content;
|
|
136
|
+
|
|
137
|
+
background-color: var(--theme-input-surface);
|
|
138
|
+
border: var(--form-element-border-width) solid var(--theme-input-border);
|
|
139
|
+
outline: var(--form-element-outline-width) solid var(--theme-input-outline);
|
|
140
|
+
border-radius: var(--_form-border-radius);
|
|
141
|
+
padding: var(--_form-padding);
|
|
142
|
+
|
|
143
|
+
transition: all var(--theme-form-transition-duration) ease-in-out;
|
|
144
|
+
|
|
145
|
+
&:has(input:focus-visible) {
|
|
146
|
+
outline: var(--form-element-outline-width) solid var(--theme-input-outline-hover);
|
|
147
|
+
outline-offset: 0.2rem;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.selected-option-marker-wrapper {
|
|
151
|
+
grid-area: select-stack;
|
|
152
|
+
z-index: 1;
|
|
153
|
+
display: flex;
|
|
154
|
+
align-items: center;
|
|
155
|
+
position: relative;
|
|
156
|
+
|
|
157
|
+
.selected-option-marker {
|
|
158
|
+
aspect-ratio: 1;
|
|
159
|
+
width: v-bind(iconWidth);
|
|
160
|
+
transition: all 400ms ease-in-out;
|
|
161
|
+
background-color: var(--_select-scheme-group-background-color);
|
|
162
|
+
background-image: var(--_select-scheme-group-background-image);
|
|
163
|
+
border: var(--form-element-border-width) solid light-dark(var(--gray-12), var(--gray-0));
|
|
164
|
+
|
|
165
|
+
border-radius: 50%;
|
|
166
|
+
|
|
167
|
+
position: absolute;
|
|
168
|
+
left: calc(
|
|
169
|
+
v-bind(selectedOptionIndex) * v-bind(iconWidth) + (var(--_form-items-gap) * v-bind(selectedOptionIndex))
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
opacity: 1;
|
|
173
|
+
|
|
174
|
+
&.show {
|
|
175
|
+
opacity: 1;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.option-group-wrapper {
|
|
181
|
+
display: grid;
|
|
182
|
+
grid-area: select-stack;
|
|
183
|
+
grid-template-columns: repeat(3, 1fr);
|
|
184
|
+
align-items: center;
|
|
185
|
+
width: fit-content;
|
|
186
|
+
z-index: 2;
|
|
187
|
+
gap: var(--_form-items-gap);
|
|
188
|
+
position: relative;
|
|
189
|
+
|
|
190
|
+
.option-group {
|
|
191
|
+
aspect-ratio: 1;
|
|
192
|
+
display: grid;
|
|
193
|
+
grid-template-areas: "icon-stack";
|
|
194
|
+
place-content: center;
|
|
195
|
+
background: transparent;
|
|
196
|
+
border: var(--form-element-border-width) solid #ffffff50;
|
|
197
|
+
outline: var(--form-element-outline-width) solid transparent;
|
|
198
|
+
border-radius: 50%;
|
|
199
|
+
padding: var(--_select-scheme-group-padding);
|
|
200
|
+
overflow: hidden;
|
|
201
|
+
|
|
202
|
+
transition: all calc(var(--theme-form-transition-duration) / 3);
|
|
203
|
+
|
|
204
|
+
&:has(.option-icon:hover) {
|
|
205
|
+
outline: var(--form-element-outline-width) solid light-dark(var(--gray-12), var(--gray-0));
|
|
206
|
+
}
|
|
207
|
+
&:has(input:focus-visible) {
|
|
208
|
+
outline: var(--form-element-outline-width) solid var(--theme-input-outline-hover);
|
|
209
|
+
outline-offset: 0.2rem;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.option-icon {
|
|
213
|
+
grid-area: icon-stack;
|
|
214
|
+
display: block;
|
|
215
|
+
color: light-dark(var(--gray-12), var(--gray-0));
|
|
216
|
+
font-size: var(--_scheme-icon-font-size);
|
|
217
|
+
|
|
218
|
+
.icon {
|
|
219
|
+
background-color: transparent;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
&:hover {
|
|
223
|
+
cursor: pointer;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.option-input {
|
|
228
|
+
grid-area: icon-stack;
|
|
229
|
+
opacity: 0;
|
|
230
|
+
aspect-ratio: 1;
|
|
231
|
+
width: var(--_scheme-icon-font-size);
|
|
232
|
+
&:hover {
|
|
233
|
+
cursor: pointer;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
&:has(input[value="auto"]:checked) {
|
|
238
|
+
--_scheme-icon-colour: white;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
&:has(input[value="light"]:checked) {
|
|
242
|
+
--_scheme-icon-colour: white;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
&:has(input[value="dark"]:checked) {
|
|
246
|
+
--_scheme-icon-colour: white;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
</style>
|
|
@@ -7,38 +7,17 @@
|
|
|
7
7
|
<div class="select-scheme-group-wrapper">
|
|
8
8
|
<div class="select-scheme-group">
|
|
9
9
|
<LazyIcon name="material-symbols:night-sight-auto-sharp" class="scheme-icon" />
|
|
10
|
-
<input
|
|
11
|
-
type="radio"
|
|
12
|
-
id="auto"
|
|
13
|
-
name="colour-scheme"
|
|
14
|
-
class="scheme-input"
|
|
15
|
-
v-model="currentColourScheme"
|
|
16
|
-
value="auto"
|
|
17
|
-
/>
|
|
10
|
+
<input type="radio" id="auto" name="colour-scheme" class="scheme-input" v-model="colourMode" value="auto" />
|
|
18
11
|
<label for="auto" class="sr-only">{{ labels.auto }}</label>
|
|
19
12
|
</div>
|
|
20
13
|
<div class="select-scheme-group">
|
|
21
14
|
<LazyIcon name="radix-icons:sun" class="scheme-icon" />
|
|
22
|
-
<input
|
|
23
|
-
type="radio"
|
|
24
|
-
id="light"
|
|
25
|
-
name="colour-scheme"
|
|
26
|
-
class="scheme-input"
|
|
27
|
-
v-model="currentColourScheme"
|
|
28
|
-
value="light"
|
|
29
|
-
/>
|
|
15
|
+
<input type="radio" id="light" name="colour-scheme" class="scheme-input" v-model="colourMode" value="light" />
|
|
30
16
|
<label for="light" class="sr-only">{{ labels.light }}</label>
|
|
31
17
|
</div>
|
|
32
18
|
<div class="select-scheme-group">
|
|
33
19
|
<LazyIcon name="radix-icons:moon" class="scheme-icon" />
|
|
34
|
-
<input
|
|
35
|
-
type="radio"
|
|
36
|
-
id="dark"
|
|
37
|
-
name="colour-scheme"
|
|
38
|
-
class="scheme-input"
|
|
39
|
-
v-model="currentColourScheme"
|
|
40
|
-
value="dark"
|
|
41
|
-
/>
|
|
20
|
+
<input type="radio" id="dark" name="colour-scheme" class="scheme-input" v-model="colourMode" value="dark" />
|
|
42
21
|
<label for="dark" class="sr-only">{{ labels.dark }}</label>
|
|
43
22
|
</div>
|
|
44
23
|
</div>
|
|
@@ -88,7 +67,8 @@ const props = defineProps({
|
|
|
88
67
|
|
|
89
68
|
const duration = ref(props.stepAnimationDuration)
|
|
90
69
|
|
|
91
|
-
const
|
|
70
|
+
const colourMode = ref<"light" | "dark" | "auto">("dark")
|
|
71
|
+
const { setColourScheme } = useSettingsStore()
|
|
92
72
|
|
|
93
73
|
const colourSchemeWrapper = ref<HTMLFormElement | null>(null)
|
|
94
74
|
const colourSchemeGroupElements = ref<HTMLDivElement[]>([])
|
|
@@ -96,9 +76,9 @@ const colourSchemeInputElements = ref<HTMLInputElement[]>([])
|
|
|
96
76
|
const showMarker = ref(false)
|
|
97
77
|
|
|
98
78
|
const findIndexOfInputValueFromCurrentColourScheme = () => {
|
|
99
|
-
if (
|
|
100
|
-
if (
|
|
101
|
-
if (
|
|
79
|
+
if (colourMode.value === "auto") return 1
|
|
80
|
+
if (colourMode.value === "light") return 2
|
|
81
|
+
if (colourMode.value === "dark") return 3
|
|
102
82
|
return undefined
|
|
103
83
|
}
|
|
104
84
|
|
|
@@ -165,8 +145,9 @@ onMounted(() => {
|
|
|
165
145
|
}
|
|
166
146
|
})
|
|
167
147
|
|
|
168
|
-
watch(
|
|
169
|
-
|
|
148
|
+
watch(colourMode, (newVal) => {
|
|
149
|
+
console.log("Colour mode changed:", newVal)
|
|
150
|
+
setColourScheme(newVal)
|
|
170
151
|
})
|
|
171
152
|
|
|
172
153
|
watch(currentActiveIndex, () => {
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<ToggleSwitchWithLabelInline
|
|
2
|
+
<ToggleSwitchWithLabelInline
|
|
3
|
+
v-model="colourMode"
|
|
4
|
+
:name
|
|
5
|
+
:label
|
|
6
|
+
labelWeight="normal"
|
|
7
|
+
:size
|
|
8
|
+
trueValue="dark"
|
|
9
|
+
falseValue="light"
|
|
10
|
+
:style-class-passthrough
|
|
11
|
+
>
|
|
3
12
|
<template #iconOn>
|
|
4
13
|
<LazyIcon name="radix-icons:moon" class="icon" />
|
|
5
14
|
</template>
|
|
@@ -10,7 +19,7 @@
|
|
|
10
19
|
</template>
|
|
11
20
|
|
|
12
21
|
<script setup lang="ts">
|
|
13
|
-
import propValidators from
|
|
22
|
+
import propValidators from "../../forms/c12/prop-validators"
|
|
14
23
|
|
|
15
24
|
defineProps({
|
|
16
25
|
name: {
|
|
@@ -23,25 +32,32 @@ defineProps({
|
|
|
23
32
|
},
|
|
24
33
|
labelWeight: {
|
|
25
34
|
type: String as PropType<string>,
|
|
26
|
-
default:
|
|
35
|
+
default: "semi-bold",
|
|
27
36
|
validator(value: string) {
|
|
28
|
-
return propValidators.labelWeight.includes(value)
|
|
37
|
+
return propValidators.labelWeight.includes(value)
|
|
29
38
|
},
|
|
30
39
|
},
|
|
31
40
|
size: {
|
|
32
41
|
type: String as PropType<string>,
|
|
33
|
-
default:
|
|
42
|
+
default: "small",
|
|
34
43
|
validator(value: string) {
|
|
35
|
-
return propValidators.size.includes(value)
|
|
44
|
+
return propValidators.size.includes(value)
|
|
36
45
|
},
|
|
37
46
|
},
|
|
38
47
|
styleClassPassthrough: {
|
|
39
48
|
type: Array as PropType<string[]>,
|
|
40
49
|
default: () => [],
|
|
41
50
|
},
|
|
42
|
-
})
|
|
51
|
+
})
|
|
43
52
|
|
|
44
53
|
// const displayMode = ref<'auto' | 'dark' | 'light'>('auto');
|
|
45
54
|
|
|
46
|
-
const
|
|
55
|
+
const colourMode = ref<"light" | "dark" | "auto">("dark")
|
|
56
|
+
|
|
57
|
+
// const { currentColourScheme, setColourScheme } = useSettingsStore()
|
|
58
|
+
|
|
59
|
+
watch(colourMode, (newVal) => {
|
|
60
|
+
// console.log("Colour mode changed:", newVal)
|
|
61
|
+
// setColourScheme(newVal)
|
|
62
|
+
})
|
|
47
63
|
</script>
|
package/nuxt.config.ts
CHANGED
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
export default defineNuxtConfig({
|
|
4
4
|
devtools: { enabled: true },
|
|
5
5
|
modules: ["@nuxt/eslint", "@nuxt/icon", "@pinia/nuxt", "pinia-plugin-persistedstate/nuxt", "@nuxt/test-utils/module"],
|
|
6
|
+
imports: {
|
|
7
|
+
dirs: ["./stores"],
|
|
8
|
+
},
|
|
6
9
|
alias: {
|
|
7
10
|
"#shared": "./shared",
|
|
8
11
|
},
|
package/package.json
CHANGED