wave-ui 1.58.0 → 1.60.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/package.json CHANGED
@@ -1,31 +1,35 @@
1
1
  {
2
2
  "name": "wave-ui",
3
- "version": "1.58.0",
3
+ "version": "1.60.0",
4
4
  "description": "An emerging UI framework for Vue.js (2 & 3) with only the bright side. :sunny:",
5
5
  "author": "Antoni Andre <antoniandre.web@gmail.com>",
6
- "license": "MIT",
6
+ "homepage": "https://antoniandre.github.io/wave-ui",
7
7
  "repository": "https://github.com/antoniandre/wave-ui",
8
+ "license": "MIT",
8
9
  "funding": "https://github.com/sponsors/antoniandre",
9
- "main": "./dist/wave-ui.umd.js",
10
+ "main": "./dist/wave-ui.es.js",
10
11
  "unpkg": "dist/wave-ui.umd.js",
11
12
  "jsdelivr": "dist/wave-ui.umd.js",
12
13
  "module": "./dist/wave-ui.es.js",
14
+ "files": [
15
+ "dist",
16
+ "src/wave-ui"
17
+ ],
13
18
  "exports": {
14
- "./dist/wave-ui.css": "./dist/wave-ui.css",
15
- "./dist/wave-ui.cjs.js": "./dist/wave-ui.cjs.js",
16
- "./src/wave-ui": "./src/wave-ui/index.js",
17
- "./src/wave-ui/scss/_variables.scss": "./src/wave-ui/scss/_variables.scss",
18
19
  ".": {
19
20
  "import": "./dist/wave-ui.es.js",
20
21
  "require": "./dist/wave-ui.umd.js"
21
22
  },
22
23
  "./package.json": "./package.json",
23
24
  "./dist/*": "./dist/*",
25
+ "./src/wave-ui": "./src/wave-ui/index.js",
24
26
  "./src/wave-ui/*": "./src/wave-ui/*"
25
27
  },
26
- "files": [
27
- "dist",
28
- "src/wave-ui"
28
+ "type": "module",
29
+ "sideEffects": [
30
+ "*.css",
31
+ "*.scss",
32
+ "*.vue"
29
33
  ],
30
34
  "keywords": [
31
35
  "wave ui",
@@ -43,19 +47,15 @@
43
47
  "serve": "vite preview --base /wave-ui/",
44
48
  "lint": "vite lint"
45
49
  },
46
- "sideEffects": [
47
- "*.css",
48
- "*.scss",
49
- "*.vue"
50
- ],
51
50
  "devDependencies": {
52
- "@babel/core": "^7.19.0",
53
- "@babel/eslint-parser": "^7.18.9",
51
+ "@babel/core": "^7.20.2",
52
+ "@babel/eslint-parser": "^7.19.1",
54
53
  "@babel/plugin-proposal-class-properties": "^7.18.6",
54
+ "@mdi/font": "^6.9.96",
55
55
  "@vitejs/plugin-vue": "^1.10.2",
56
- "autoprefixer": "^10.4.8",
56
+ "autoprefixer": "^10.4.13",
57
57
  "axios": "^0.21.4",
58
- "core-js": "^3.25.0",
58
+ "core-js": "^3.26.1",
59
59
  "eslint": "^7.32.0",
60
60
  "eslint-config-standard": "^16.0.3",
61
61
  "eslint-plugin-import": "^2.26.0",
@@ -64,25 +64,22 @@
64
64
  "eslint-plugin-vue": "^7.20.0",
65
65
  "font-awesome": "^4.7.0",
66
66
  "ghspa": "^1.0.0",
67
- "gsap": "^3.11.1",
67
+ "gsap": "^3.11.3",
68
68
  "ionicons": "^4.6.3",
69
69
  "material-design-icons": "^3.0.1",
70
- "postcss": "^8.4.16",
70
+ "postcss": "^8.4.19",
71
+ "pug": "^3.0.2",
71
72
  "rollup-plugin-delete": "^2.0.0",
72
- "sass": "^1.54.8",
73
+ "sass": "^1.56.1",
73
74
  "simple-syntax-highlighter": "^1.5.1",
74
75
  "splitpanes": "^2.4.1",
75
76
  "vite": "^2.9.15",
76
- "vite-plugin-pug": "^0.3.1",
77
77
  "vite-plugin-vue2": "^1.9.3",
78
- "vue": "^2.7.10",
78
+ "vue": "^2.7.14",
79
79
  "vue-router": "^3.6.5",
80
80
  "vue-svg-loader": "^0.16.0",
81
- "vue-template-compiler": "^2.7.10",
82
- "vueperslides": "^2.15.3",
81
+ "vue-template-compiler": "^2.7.14",
82
+ "vueperslides": "^2.16.0",
83
83
  "vuex": "^3.6.2"
84
- },
85
- "dependencies": {
86
- "@mdi/font": "^6.9.96"
87
84
  }
88
85
  }
@@ -4,7 +4,7 @@ export { default as WAlert } from './w-alert.vue'
4
4
  export { default as WApp } from './w-app.vue'
5
5
  export { default as WBadge } from './w-badge.vue'
6
6
  export { default as WBreadcrumbs } from './w-breadcrumbs.vue'
7
- export { default as WButton } from './w-button.vue'
7
+ export { default as WButton } from './w-button/index.vue'
8
8
  export { default as WCard } from './w-card.vue'
9
9
  export { default as WCheckbox } from './w-checkbox.vue'
10
10
  export { default as WCheckboxes } from './w-checkboxes.vue'
@@ -15,12 +15,13 @@
15
15
  w-button.w-accordion__expand-icon(
16
16
  v-if="expandIcon && !expandIconRight"
17
17
  :icon="(item._expanded && collapseIcon) || expandIcon"
18
+ :icon-props="expandIconProps"
18
19
  :disabled="item._disabled || null"
19
20
  :tabindex="-1"
20
21
  text
21
22
  @keypress.stop
22
23
  @click.stop="!item._disabled && toggleItem(item, $event)"
23
- :class="{ 'w-accordion__expand-icon--expanded': item._expanded }")
24
+ :class="{ 'w-accordion__expand-icon--expanded': item._expanded, 'w-accordion__expand-icon--rotate90': expandIconRotate90 }")
24
25
  //- Title.
25
26
  slot(
26
27
  v-if="$scopedSlots[`item-title.${item.id || i + 1}`]"
@@ -36,7 +37,7 @@
36
37
  text
37
38
  @keypress.stop
38
39
  @click.stop="!item._disabled && toggleItem(item, $event)"
39
- :class="{ 'w-accordion__expand-icon--expanded': item._expanded }")
40
+ :class="{ 'w-accordion__expand-icon--expanded': item._expanded, 'w-accordion__expand-icon--rotate90': expandIconRotate90 }")
40
41
  //- Content.
41
42
  w-transition-expand(
42
43
  y
@@ -77,6 +78,8 @@ export default {
77
78
  contentClass: { type: String },
78
79
  expandIcon: { type: [String, Boolean], default: 'wi-triangle-down' },
79
80
  expandIconRight: { type: Boolean },
81
+ expandIconRotate90: { type: Boolean },
82
+ expandIconProps: { type: Object, default: () => ({}) },
80
83
  expandSingle: { type: Boolean },
81
84
  collapseIcon: { type: String },
82
85
  shadow: { type: Boolean },
@@ -174,8 +177,9 @@ export default {
174
177
  margin-right: $base-increment;
175
178
 
176
179
  .w-accordion--rotate-icon & {@include default-transition;}
180
+ &--rotate90 {transform: rotate(-90deg);}
177
181
  &--expanded {transform: rotate(-180deg);}
178
- .w-accordion--icon-right &--expanded {transform: rotate(180deg);}
182
+ &--expanded.w-accordion__expand-icon--rotate90 {transform: rotate(0deg);}
179
183
 
180
184
  .w-icon:before {font-size: 1.1em;}
181
185
  }
@@ -112,8 +112,8 @@ export default {
112
112
  &--inline {position: static;}
113
113
 
114
114
  &--round {
115
- width: round(1.1 * divide($base-font-size, 2)) * 2;
116
- padding: 0 (round(1.1 * divide($base-font-size, 4)) * 2);
115
+ aspect-ratio: 1;
116
+ padding: 0;
117
117
  }
118
118
 
119
119
  // Sizes.
@@ -184,11 +184,11 @@ export default {
184
184
  }
185
185
  &--shadow {box-shadow: $box-shadow;}
186
186
 
187
- &--dot.w-badge {min-width: 0;padding: 0;}
188
- &--dot.size--xs {width: round(1.35 * $base-increment);height: round(1.35 * $base-increment);}
189
- &--dot.size--sm {width: round(1.7 * $base-increment);height: round(1.7 * $base-increment);}
190
- &--dot.size--md {width: round(2.2 * $base-increment);height: round(2.2 * $base-increment);}
191
- &--dot.size--lg {width: round(2.75 * $base-increment);height: round(2.75 * $base-increment);}
192
- &--dot.size--xl {width: 3 * $base-increment;height: 3 * $base-increment;}
187
+ &--dot.w-badge {min-width: 0;padding: 0;aspect-ratio: 1;}
188
+ &--dot.size--xs {height: round(1.35 * $base-increment);}
189
+ &--dot.size--sm {height: round(1.7 * $base-increment);}
190
+ &--dot.size--md {height: round(2.2 * $base-increment);}
191
+ &--dot.size--lg {height: round(2.75 * $base-increment);}
192
+ &--dot.size--xl {height: 3 * $base-increment;}
193
193
  }
194
194
  </style>
@@ -6,7 +6,6 @@ component.w-button(
6
6
  :class="classes"
7
7
  :disabled="!!disabled || null"
8
8
  v-on="listeners"
9
- v-bind="$attrs"
10
9
  :style="styles")
11
10
  w-icon(v-if="icon" v-bind="iconProps || {}") {{ icon }}
12
11
  slot(v-else)
@@ -24,8 +23,6 @@ component.w-button(
24
23
 
25
24
  <script>
26
25
  export default {
27
- name: 'w-button',
28
-
29
26
  props: {
30
27
  color: { type: String },
31
28
  bgColor: { type: String },
@@ -199,6 +196,7 @@ $spinner-size: 40;
199
196
  padding-right: 3 * $base-increment;
200
197
  }
201
198
  &--icon {
199
+ aspect-ratio: 1;
202
200
  border-radius: 99em;
203
201
  padding: 0;
204
202
  }
@@ -227,11 +225,8 @@ $spinner-size: 40;
227
225
  &.size--xl {padding-left: 3 * $base-increment;padding-right: 3 * $base-increment;}
228
226
  &--round.size--xs {padding-left: round(1.5 * $base-increment);padding-right: round(1.5 * $base-increment);}
229
227
  &--round.size--xl {padding-left: round(4.5 * $base-increment);padding-right: round(4.5 * $base-increment);}
230
- &--icon.size--xs {width: round(1.25 * divide($base-font-size, 2)) * 2;padding-left: 0;padding-right: 0;}
231
- &--icon.size--sm {width: round(1.55 * divide($base-font-size, 2)) * 2;}
232
- &--icon.size--md {width: round(1.85 * divide($base-font-size, 2)) * 2;}
233
- &--icon.size--lg {width: round(2.2 * divide($base-font-size, 2)) * 2;}
234
- &--icon.size--xl {width: round(2.5 * divide($base-font-size, 2)) * 2;padding-left: 0;padding-right: 0;}
228
+ &--icon.size--xs {padding-left: 0;padding-right: 0;}
229
+ &--icon.size--xl {padding-left: 0;padding-right: 0;}
235
230
 
236
231
  // Overlay to mark the focus, hover and active state.
237
232
  &:before {
@@ -0,0 +1,68 @@
1
+ <template lang="pug">
2
+ component(v-if="tooltip" is="w-tooltip" v-bind="tooltipProps || {}")
3
+ template(#activator="{ on }")
4
+ button-partial(v-bind="buttonProps" v-on="{ ...$listeners, ...on }")
5
+ slot
6
+ div(v-html="tooltip")
7
+ button-partial(v-else v-bind="buttonProps" v-on="$listeners")
8
+ slot
9
+ </template>
10
+
11
+ <script>
12
+ import ButtonPartial from './button.vue'
13
+
14
+ export default {
15
+ name: 'w-button',
16
+ inheritAttrs: false, // The attrs are only bound to the button-partial, not the root.
17
+
18
+ props: {
19
+ color: { type: String },
20
+ bgColor: { type: String },
21
+ dark: { type: Boolean },
22
+ outline: { type: Boolean },
23
+ text: { type: Boolean },
24
+ round: { type: Boolean },
25
+ shadow: { type: Boolean },
26
+ tile: { type: Boolean },
27
+ tooltip: { type: String },
28
+ tooltipProps: { type: Object, default: () => ({}) },
29
+ route: { type: [String, Object] }, // Creates a link.
30
+ // Force use of `a` instead of router-link.
31
+ // Router link does not go to a url starting with `#` with history mode.
32
+ forceLink: { type: Boolean },
33
+ type: { type: String, default: 'button' },
34
+ disabled: { type: Boolean },
35
+ loading: { type: Boolean },
36
+ // If an icon is passed, no text will display.
37
+ icon: { type: String, default: null },
38
+ iconProps: { type: Object, default: () => ({}) },
39
+ // Positions.
40
+ absolute: { type: Boolean },
41
+ fixed: { type: Boolean },
42
+ top: { type: Boolean },
43
+ bottom: { type: Boolean },
44
+ left: { type: Boolean },
45
+ right: { type: Boolean },
46
+ zIndex: { type: [Number, String] },
47
+ // Sizes.
48
+ width: { type: [Number, String] },
49
+ height: { type: [Number, String] },
50
+ xs: { type: Boolean },
51
+ sm: { type: Boolean },
52
+ md: { type: Boolean },
53
+ lg: { type: Boolean },
54
+ xl: { type: Boolean }
55
+ },
56
+
57
+ components: { ButtonPartial },
58
+
59
+ emits: [],
60
+
61
+ computed: {
62
+ buttonProps () {
63
+ const { tooltip, tooltipProps, ...props } = this.$props
64
+ return { ...props, ...this.$attrs }
65
+ }
66
+ }
67
+ }
68
+ </script>
@@ -23,19 +23,29 @@ component(
23
23
  role="checkbox")
24
24
  template(v-if="hasLabel && labelOnLeft")
25
25
  label.w-checkbox__label.w-form-el-shakable.pr2(
26
- v-if="$slots.default || label"
26
+ v-if="$slots.default"
27
27
  :for="`w-checkbox--${_uid}`"
28
28
  :class="labelClasses")
29
29
  slot {{ label }}
30
+ label.w-checkbox__label.w-form-el-shakable.pr2(
31
+ v-else-if="label"
32
+ :for="`w-checkbox--${_uid}`"
33
+ :class="labelClasses"
34
+ v-html="label")
30
35
  .w-checkbox__input(@click="$refs.input.focus();$refs.input.click()" :class="this.color")
31
- svg(width="11px" height="9px" viewbox="0 0 12 9")
36
+ svg(viewBox="-0.5 0 12 10")
32
37
  polyline(points="1 5 4 8 10 2")
33
38
  template(v-if="hasLabel && !labelOnLeft")
34
39
  label.w-checkbox__label.w-form-el-shakable.pl2(
35
- v-if="$slots.default || label"
40
+ v-if="$slots.default"
36
41
  :for="`w-checkbox--${_uid}`"
37
42
  :class="labelClasses")
38
43
  slot {{ label }}
44
+ label.w-checkbox__label.w-form-el-shakable.pl2(
45
+ v-else-if="label"
46
+ :for="`w-checkbox--${_uid}`"
47
+ :class="labelClasses"
48
+ v-html="label")
39
49
  </template>
40
50
 
41
51
  <script>
@@ -149,7 +159,7 @@ $inactive-color: #666;
149
159
  &__input {
150
160
  position: relative;
151
161
  width: $small-form-el-size;
152
- height: $small-form-el-size;
162
+ aspect-ratio: 1;
153
163
  display: flex;
154
164
  flex: 0 0 auto; // Prevent stretching width or height.
155
165
  align-items: center;
@@ -160,8 +170,8 @@ $inactive-color: #666;
160
170
 
161
171
  // The checkmark - visible when checked.
162
172
  &__input svg {
163
- width: auto;
164
- height: auto;
173
+ width: 70%;
174
+ aspect-ratio: 1;
165
175
  fill: none;
166
176
  stroke-width: 2;
167
177
  stroke: white;
@@ -172,7 +182,6 @@ $inactive-color: #666;
172
182
  transition: $transition-duration ease-out;
173
183
  opacity: 0;
174
184
  position: relative;
175
- top: -0.5px; // For browser zoom levels.
176
185
  z-index: 1;
177
186
 
178
187
  :checked ~ & {
@@ -187,7 +196,7 @@ $inactive-color: #666;
187
196
  content: '';
188
197
  position: absolute;
189
198
  width: 100%;
190
- height: 100%;
199
+ aspect-ratio: 1;
191
200
  border: $outline-width solid $inactive-color;
192
201
  border-radius: $border-radius;
193
202
  transition: $transition-duration ease-in-out;
@@ -218,7 +227,7 @@ $inactive-color: #666;
218
227
  content: "";
219
228
  position: absolute;
220
229
  width: inherit;
221
- height: inherit;
230
+ aspect-ratio: 1;
222
231
  background-color: currentColor;
223
232
  border-radius: 100%;
224
233
  transform: scale(0);
@@ -20,8 +20,8 @@ component(
20
20
  :readonly="isReadonly || null"
21
21
  :class="{ mt1: !inline && i }")
22
22
  slot(
23
- v-if="$slots[`item.${i + 1}`] || $slots.item"
24
- :name="$slots[`item.${i + 1}`] ? `item.${i + 1}` : 'item'"
23
+ v-if="$scopedSlots[`item.${i + 1}`] || $scopedSlots.item"
24
+ :name="$scopedSlots[`item.${i + 1}`] ? `item.${i + 1}` : 'item'"
25
25
  :item="getOriginalItem(item)"
26
26
  :checked="!!item._isChecked"
27
27
  :index="i + 1")
@@ -12,11 +12,14 @@
12
12
  v-if="cancel !== false"
13
13
  v-bind="cancelButtonProps"
14
14
  :bg-color="(cancelButton || {}).bgColor || 'error'"
15
+ @keyup.escape="!persistent && onCancel()"
15
16
  @click="onCancel")
16
17
  slot(name="cancel") {{ cancelButton.label }}
17
18
  w-button(
18
19
  v-bind="confirmButtonProps"
19
20
  :bg-color="(confirmButton || {}).bgColor || 'success'"
21
+ v-focus
22
+ @keyup.escape="!persistent && onCancel()"
20
23
  @click="onConfirm")
21
24
  slot(name="confirm") {{ confirmButton.label }}
22
25
  </template>
@@ -45,7 +48,11 @@ export default {
45
48
  inline: { type: Boolean }, // The layout inside the menu.
46
49
 
47
50
  // W-menu props.
48
- menu: { type: Object }, // Allow passing down an object of props to the w-menu component.
51
+ // Allow passing down an object of props to the w-menu component.
52
+ menu: { type: Object, default: () => ({}) },
53
+ // Allow passing down an object of props to the w-tooltip component.
54
+ // If a string is given, that will be the label of the tooltip.
55
+ tooltip: { type: [Boolean, Object, String] },
49
56
  // All the menu props shorthands, as long as they don't conflict with the button props.
50
57
  noArrow: { type: Boolean }, // Adds a directional triangle to the edge of the menu, like a tooltip.
51
58
  top: { type: Boolean },
@@ -104,11 +111,20 @@ export default {
104
111
  ...this.menu
105
112
  }
106
113
  },
114
+ tooltipObject () {
115
+ let tooltip = { label: typeof this.tooltip === 'string' ? this.tooltip : '' }
116
+ if (typeof this.tooltip === 'object') tooltip = Object.assign({}, tooltip, this.tooltip)
117
+ return tooltip
118
+ },
107
119
  buttonProps () {
120
+ const { label, ...tooltipProps } = this.tooltipObject
121
+
108
122
  return {
109
123
  bgColor: this.bgColor,
110
124
  color: this.color,
111
125
  icon: this.icon,
126
+ tooltip: label,
127
+ tooltipProps,
112
128
  ...this.mainButton
113
129
  }
114
130
  }
@@ -7,7 +7,7 @@ div(:class="classes")
7
7
  w-transition-expand(y)
8
8
  template(v-if="Validation.message")
9
9
  .w-form-el__error(
10
- v-if="$slots['error-message']"
10
+ v-if="$scopedSlots['error-message']"
11
11
  :class="formProps.validationColor")
12
12
  slot(name="error-message" :message="Validation.message")
13
13
  .w-form-el__error.error(
@@ -111,6 +111,7 @@ export default {
111
111
  line-height: 1;
112
112
  font-size: 1.2em;
113
113
  width: 1em;
114
+ // The aspect ratio will not work if the content is the content overflows.
114
115
  height: 1em;
115
116
 
116
117
  &.size--xs {font-size: round(0.85 * $base-font-size);}
@@ -175,6 +175,8 @@ export default {
175
175
  .w-image-wrap {
176
176
  position: relative;
177
177
  display: inline-flex;
178
+ flex-grow: 0;
179
+ flex-shrink: 0;
178
180
  width: 4em;
179
181
 
180
182
  &--has-ratio {width: 100%;}
@@ -177,8 +177,8 @@ export default {
177
177
  attrs () {
178
178
  // Keep the `class` attribute bound to the wrapper and not the input.
179
179
  // eslint-disable-next-line no-unused-vars
180
- const { class: classes, ...attrs } = this.$attrs
181
- return attrs
180
+ const { class: classes, ...htmlAttrs } = this.$attrs
181
+ return htmlAttrs
182
182
  },
183
183
 
184
184
  listeners () {
@@ -377,6 +377,8 @@ $inactive-color: #777;
377
377
  span.fade-leave-to {position: absolute;}
378
378
  }
379
379
 
380
+ &--loading {cursor: wait;}
381
+
380
382
  // Input field wrapper.
381
383
  // ------------------------------------------------------
382
384
  &__input-wrap {
@@ -60,6 +60,7 @@ import DetachableMixin from '../mixins/detachable'
60
60
  export default {
61
61
  name: 'w-menu',
62
62
  mixins: [DetachableMixin],
63
+ inheritAttrs: false, // The attrs are only bound to the button-partial, not the root.
63
64
 
64
65
  props: {
65
66
  value: {}, // Show or hide.
@@ -20,6 +20,7 @@ export default {
20
20
  value: {},
21
21
  opacity: { type: [Number, String, Boolean] },
22
22
  bgColor: { type: String },
23
+ absolute: { type: Boolean },
23
24
  zIndex: { type: [Number, String, Boolean] },
24
25
  persistent: { type: Boolean },
25
26
  persistentNoAnimation: { type: Boolean }
@@ -46,7 +47,8 @@ export default {
46
47
  },
47
48
  classes () {
48
49
  return {
49
- 'w-overlay--persistent-animate': this.persistentAnimate
50
+ 'w-overlay--persistent-animate': this.persistentAnimate,
51
+ 'w-overlay--absolute': this.absolute
50
52
  }
51
53
  },
52
54
  styles () {
@@ -111,6 +113,7 @@ export default {
111
113
  justify-content: center;
112
114
  background-color: rgba(0, 0, 0, 0.3);
113
115
 
116
+ &--absolute {position: absolute;}
114
117
  &--persistent-animate {animation: 0.15s w-overlay-pop cubic-bezier(0.6, -0.28, 0.74, 0.05);}
115
118
  &--no-pointer-event {pointer-events: none;}
116
119
  }
@@ -7,8 +7,8 @@
7
7
  :style="`width: ${progressValue}%`")
8
8
 
9
9
  //- Circular progress.
10
- template(v-else)
11
- svg(:viewBox="`${circleCenter / 2} ${circleCenter / 2} ${circleCenter} ${circleCenter}`")
10
+ svg(v-else :viewBox="`${circleCenter / 2} ${circleCenter / 2} ${circleCenter} ${circleCenter}`")
11
+ //- Background first, in SVG there is no z-index.
12
12
  circle.bg(
13
13
  v-if="bgColor || this.progressValue > -1"
14
14
  :class="bgColor"
@@ -18,30 +18,21 @@
18
18
  fill="transparent"
19
19
  :stroke-dasharray="circleCircumference"
20
20
  :stroke-width="stroke")
21
- svg.w-progress__progress(
22
- :viewBox="`${circleCenter / 2} ${circleCenter / 2} ${circleCenter} ${circleCenter}`"
23
- :style="`stroke-dashoffset: ${(1 - (progressValue / 100)) * circleCircumference}`")
24
- circle(
21
+ circle.w-progress__progress(
25
22
  :cx="circleCenter"
26
23
  :cy="circleCenter"
27
24
  :r="circleRadius"
28
25
  fill="transparent"
29
26
  :stroke-width="stroke"
30
27
  :stroke-linecap="roundCap && 'round'"
31
- :stroke-dasharray="circleCircumference")
28
+ :stroke-dasharray="circleCircumference"
29
+ :style="`stroke-dashoffset: ${(1 - (progressValue / 100)) * circleCircumference}`")
32
30
 
33
31
  .w-progress__label(v-if="label || $slots.default" :class="labelColor || false")
34
32
  slot {{ Math.round(progressValue) }}{{ circle ? '' : '%' }}
35
33
  </template>
36
34
 
37
35
  <script>
38
- /**
39
- * This component (circular) is hacked to work on Edge as it does not support transform on svg elements.
40
- * https://caniuse.com/#feat=mdn-css_properties_transform-origin_support_in_svg
41
- * It is meant to be 2 circles in 1 svg, with animation on the circle, now instead, there are 2 svgs,
42
- * and the animation is on the second svg itself.
43
- */
44
-
45
36
  // For circular progress.
46
37
  const circleSize = 40
47
38
  const circleRadius = circleSize / 2
@@ -256,7 +247,7 @@ $circle-size: 40;
256
247
  &--circular {
257
248
  display: inline-flex;
258
249
  width: 3em;
259
- height: auto;
250
+ aspect-ratio: 1;
260
251
  font-size: $base-font-size;
261
252
 
262
253
  svg {display: block;width: 100%;}
@@ -264,19 +255,10 @@ $circle-size: 40;
264
255
  &.w-progress--default-bg circle.bg {stroke: rgba(0, 0, 0, 0.1);}
265
256
 
266
257
  .w-progress__progress {
267
- position: absolute;
268
- top: 0;
269
- left: 0;
270
- right: 0;
271
- bottom: 0;
272
-
273
- circle {
274
- stroke: currentColor;
275
- stroke-dashoffset: inherit;
276
- will-change: stroke-dashoffset;
277
- }
258
+ transform-origin: 100% 100%;
278
259
  transform: rotate(-90deg);
279
- will-change: transform;
260
+ stroke: currentColor;
261
+ will-change: stroke-dashoffset;
280
262
  @include default-transition;
281
263
  }
282
264
  &.w-progress--round-cap .w-progress__progress {stroke-linecap: round;}
@@ -21,19 +21,29 @@ component(
21
21
  role="radio")
22
22
  template(v-if="hasLabel && labelOnLeft")
23
23
  label.w-radio__label.w-form-el-shakable.pr2(
24
- v-if="$slots.default || label"
24
+ v-if="$slots.default"
25
25
  :for="`w-radio--${_uid}`"
26
26
  :class="labelClasses")
27
27
  slot {{ label }}
28
+ label.w-radio__label.w-form-el-shakable.pr2(
29
+ v-else-if="label"
30
+ :for="`w-radio--${_uid}`"
31
+ :class="labelClasses"
32
+ v-html="label")
28
33
  .w-radio__input(
29
34
  @click="$refs.input.focus();$refs.input.click()"
30
35
  :class="this.color")
31
36
  template(v-if="hasLabel && !labelOnLeft")
32
37
  label.w-radio__label.w-form-el-shakable.pl2(
33
- v-if="$slots.default || label"
38
+ v-if="$slots.default"
34
39
  :for="`w-radio--${_uid}`"
35
40
  :class="labelClasses")
36
41
  slot {{ label }}
42
+ label.w-radio__label.w-form-el-shakable.pl2(
43
+ v-else-if="label"
44
+ :for="`w-radio--${_uid}`"
45
+ :class="labelClasses"
46
+ v-html="label")
37
47
  </template>
38
48
 
39
49
  <script>
@@ -154,7 +164,7 @@ $inactive-color: #666;
154
164
  position: relative;
155
165
  border-radius: 100%;
156
166
  width: $small-form-el-size;
157
- height: $small-form-el-size;
167
+ aspect-ratio: 1;
158
168
  display: flex;
159
169
  flex: 0 0 auto; // Prevent stretching width or height.
160
170
  align-items: center;
@@ -198,7 +208,7 @@ $inactive-color: #666;
198
208
  content: "";
199
209
  position: absolute;
200
210
  width: inherit;
201
- height: inherit;
211
+ aspect-ratio: 1;
202
212
  background-color: currentColor;
203
213
  border-radius: 100%;
204
214
  transform: scale(0);
@@ -20,8 +20,8 @@ component(
20
20
  :readonly="isReadonly || null"
21
21
  :class="{ mt1: !inline && i }")
22
22
  slot(
23
- v-if="$slots[`item.${i + 1}`] || $slots.item"
24
- :name="$slots[`item.${i + 1}`] ? `item.${i + 1}` : 'item'"
23
+ v-if="$scopedSlots[`item.${i + 1}`] || $scopedSlots.item"
24
+ :name="$scopedSlots[`item.${i + 1}`] ? `item.${i + 1}` : 'item'"
25
25
  :item="getOriginalItem(item)"
26
26
  :index="i + 1"
27
27
  :checked="item.value === value")