srcdev-nuxt-forms 2.4.23 → 2.4.24

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.
@@ -42,6 +42,8 @@
42
42
  --theme-form-toggle-bg-off: light-dark(var(--gray-1), var(--gray-4));
43
43
  --theme-form-toggle-bg-on: light-dark(var(--gray-1), var(--gray-6));
44
44
 
45
+ --theme-form-toggle-border-color: light-dark(var(--blue-12), var(--blue-1));
46
+ --theme-form-toggle-border-width: 0.2rem;
45
47
  --theme-form-toggle-border: var(--form-element-border-width) solid light-dark(var(--blue-12), var(--blue-1));
46
48
 
47
49
  --theme-form-toggle-outline: var(--form-element-outline-width) solid light-dark(var(--blue-1), var(--blue-1));
@@ -1,15 +1,19 @@
1
1
  <template>
2
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 />
3
+ <div @click="toggleSwitchValue" class="toggle-switch-wrapper" :class="[{ round }, { 'use-default-icons': useDefaultIcons }]" :for="inputId">
4
+ <input type="checkbox" v-model="modelValue" :true-value :false-value :aria-invalid="fieldHasError" :id="inputId" :aria-describedby="`${id}-description`" :name :required :checked="isChecked" />
5
5
  <div class="symbol-wrapper" :class="[{ round }]">
6
6
  <div class="symbol" :class="[{ round }]">
7
- <div v-if="hasIconOnSlot" class="symbol-icon icon-on">
8
- <slot name="iconOn"></slot>
7
+ <div class="symbol-icon icon-on">
8
+ <slot name="iconOn">
9
+ <Icon name="material-symbols:circle-outline" class="icon" />
10
+ </slot>
9
11
  </div>
10
12
 
11
- <div v-if="hasIconOffSlot" class="symbol-icon icon-off">
12
- <slot name="iconOff"></slot>
13
+ <div class="symbol-icon icon-off">
14
+ <slot name="iconOff">
15
+ <Icon name="material-symbols:circle-outline" class="icon" />
16
+ </slot>
13
17
  </div>
14
18
  </div>
15
19
  </div>
@@ -76,6 +80,7 @@ const props = defineProps({
76
80
  const slots = useSlots();
77
81
  const hasIconOnSlot = computed(() => slots.iconOn !== undefined);
78
82
  const hasIconOffSlot = computed(() => slots.iconOff !== undefined);
83
+ const useDefaultIcons = computed(() => !hasIconOnSlot.value && !hasIconOffSlot.value);
79
84
 
80
85
  const formTheme = computed(() => {
81
86
  return props.fieldHasError ? 'error' : props.theme;
@@ -86,131 +91,108 @@ const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough)
86
91
 
87
92
  const inputId = computed(() => `toggle-sitch-${props.id}`);
88
93
 
94
+ const isChecked = computed(() => {
95
+ return modelValue.value === props.trueValue;
96
+ });
97
+
89
98
  const toggleSwitchValue = () => {
90
99
  modelValue.value = modelValue.value === props.trueValue ? props.falseValue : props.trueValue;
100
+ console.log(`toggleSwitchValue(${modelValue.value})`);
91
101
  };
92
102
  </script>
93
103
 
94
104
  <style lang="css">
95
105
  .toggle-switch-core {
96
- --_transition-duration: 0.4s;
97
-
98
106
  .toggle-switch-label {
99
107
  display: block;
100
108
  }
101
109
 
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));
110
+ .toggle-switch-wrapper {
111
+ --theme-form-toggle-border-color: var(--blue-12);
112
+ --theme-form-toggle-border-width: 0.1rem;
113
+ --theme-form-toggle-outline-color: var(--gray-2);
114
+ --theme-form-toggle-outline-width: 0.1rem;
115
+
116
+ --_transition-duration: 0.4s;
117
+ --_switch-padding: 0.2rem;
118
+ --_icon-color: inherit;
119
+ --_icon-on-opacity: 0;
120
+ --_icon-off-opacity: 1;
121
+ --_icon-font-size: 2.4rem;
122
+ --_symbol-size: 3.4rem;
123
+ --_symbol-background-color: var(--blue-12);
124
+ --_symbol-outline-color: transparent;
125
+ --_symbol-outline-width: 1px;
126
+ --_symbol-margin-inline-start: 0;
127
+ --_symbol-checked-offset: calc(var(--_symbol-size) * 0.75);
128
+
129
+ &.use-default-icons {
130
+ --_icon-color: transparent;
131
+ }
132
+
133
+ display: flex;
134
+ flex-direction: column;
107
135
 
108
136
  input {
109
- opacity: 0;
110
- width: 0;
111
137
  height: 0;
138
+ width: 0;
139
+ visibility: hidden;
112
140
  }
113
- input:checked {
141
+
142
+ &:has(input:checked) {
114
143
  --_icon-on-opacity: 1;
115
144
  --_icon-off-opacity: 0;
145
+ --_symbol-margin-inline-start: var(--_symbol-checked-offset);
116
146
  }
117
147
 
118
148
  .symbol-wrapper {
119
- position: absolute;
120
- cursor: pointer;
121
- top: 0;
122
- left: 0;
123
- right: 0;
124
- bottom: 0;
125
- overflow: clip;
149
+ /* background: blue; */
150
+ border: var(--theme-form-toggle-border-width) solid var(--theme-form-toggle-border-color);
151
+ outline: var(--theme-form-toggle-outline-width) solid var(--theme-form-toggle-outline-color);
152
+ border-radius: calc(var(--_symbol-size) + calc(var(--theme-form-toggle-border-width) * 2) + calc(var(--_switch-padding) * 2));
153
+ display: inline-flex;
154
+ align-items: center;
155
+ justify-content: start;
156
+ width: calc(var(--_symbol-size) + var(--_symbol-checked-offset) + calc(var(--theme-form-toggle-border-width) * 2) + calc(var(--_switch-padding) * 2));
157
+ padding: var(--_switch-padding);
126
158
 
127
159
  .symbol {
128
- display: grid;
129
- grid-template-areas: 'icon-stack';
130
- overflow: clip;
131
- position: absolute;
160
+ display: inline-grid;
161
+ grid-template-areas: 'icon';
162
+ place-content: center;
132
163
 
133
- .symbol-icon {
134
- grid-area: icon-stack;
135
- display: flex;
136
- align-items: center;
137
- justify-content: center;
138
- }
139
- }
140
- }
141
- }
142
- }
164
+ aspect-ratio: 1/1;
165
+ /* width: var(--_symbol-size); */
166
+ padding: calc(calc(var(--_symbol-size) - var(--_icon-font-size)) / 2);
143
167
 
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
- }
168
+ outline: var(--_symbol-outline-width) solid var(--_symbol-outline-color);
169
+ border-radius: 50%;
170
+ margin-inline-start: var(--_symbol-margin-inline-start);
152
171
 
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;
172
+ background-color: var(--_symbol-background-color);
158
173
 
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
- }
174
+ overflow: clip;
175
+
176
+ transition: margin var(--_transition-duration);
173
177
 
174
178
  .symbol-icon {
175
- transition: var(--_transition-duration);
179
+ display: grid;
180
+ grid-area: icon;
181
+ place-content: center;
182
+
183
+ color: var(--_icon-color);
184
+ font-size: var(--_icon-font-size);
185
+ transition: opacity var(--_transition-duration);
176
186
 
177
187
  &.icon-on {
178
- color: var(--theme-form-toggle-icon-stroke-colour-on);
179
- opacity: 0;
188
+ opacity: var(--_icon-on-opacity);
180
189
  }
181
190
  &.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);
191
+ opacity: var(--_icon-off-opacity);
190
192
  }
191
193
  }
192
194
  }
193
195
  }
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
196
  }
215
197
  }
216
198
  </style>
@@ -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>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "srcdev-nuxt-forms",
3
3
  "type": "module",
4
- "version": "2.4.23",
4
+ "version": "2.4.24",
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",