@citizenplane/pimp 6.4.0 → 7.0.4

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 (70) hide show
  1. package/.eslintrc.js +3 -6
  2. package/.lintstagedrc.json +4 -0
  3. package/dist/favicon.ico +0 -0
  4. package/dist/pimp.es.js +10617 -0
  5. package/dist/pimp.umd.js +9 -35597
  6. package/dist/style.css +1 -0
  7. package/jest.config.js +11 -11
  8. package/package-lock.json +7966 -13664
  9. package/package.json +37 -41
  10. package/src/App.vue +12 -17
  11. package/src/assets/styles/base/_base.scss +3 -16
  12. package/src/assets/styles/helpers/_keyframes.scss +26 -29
  13. package/src/components/buttons/CpButton.vue +10 -6
  14. package/src/components/core/BaseInputLabel/index.vue +2 -2
  15. package/src/components/core/playground-sections/SectionAtomicElements.vue +1 -1
  16. package/src/components/core/playground-sections/SectionButtons.vue +14 -11
  17. package/src/components/core/playground-sections/SectionDatePickers.vue +31 -17
  18. package/src/components/core/playground-sections/SectionFeedbackIndicators.vue +1 -1
  19. package/src/components/core/playground-sections/SectionInputs.vue +3 -3
  20. package/src/components/core/playground-sections/SectionListsAndTables.vue +2 -2
  21. package/src/components/core/playground-sections/SectionSelectMenus.vue +13 -13
  22. package/src/components/core/playground-sections/SectionSelects.vue +1 -1
  23. package/src/components/core/playground-sections/SectionSimpleInputs.vue +20 -18
  24. package/src/components/core/playground-sections/SectionToasters.vue +1 -1
  25. package/src/components/core/playground-sections/SectionToggles.vue +23 -36
  26. package/src/components/core/playground-sections/SectionTypography.vue +1 -1
  27. package/src/components/date-pickers/CpCalendar.vue +60 -14
  28. package/src/components/date-pickers/CpDate.vue +11 -13
  29. package/src/components/date-pickers/CpDatepicker.vue +55 -8
  30. package/src/components/feedback-indicators/CpAlert.vue +5 -15
  31. package/src/components/feedback-indicators/CpToaster.vue +299 -86
  32. package/src/components/helpers-utilities/TransitionExpand.vue +52 -58
  33. package/src/components/index.js +38 -73
  34. package/src/components/inputs/CpInput.vue +20 -55
  35. package/src/components/inputs/CpTextarea.vue +8 -9
  36. package/src/components/lists-and-table/CpTable/CpTableEmptyState/index.vue +1 -6
  37. package/src/components/lists-and-table/CpTable/index.scss +16 -9
  38. package/src/components/lists-and-table/CpTable/index.vue +6 -5
  39. package/src/components/selects/CpSelect.vue +10 -11
  40. package/src/components/selects/CpSelectMenu/index.vue +13 -23
  41. package/src/components/toggles/CpCheckbox/index.scss +8 -5
  42. package/src/components/toggles/CpCheckbox/index.vue +3 -7
  43. package/src/components/toggles/CpRadio/index.scss +14 -11
  44. package/src/components/toggles/CpRadio/index.vue +34 -47
  45. package/src/components/toggles/CpSwitch/index.vue +18 -17
  46. package/src/components/typography/CpHeading/index.vue +2 -2
  47. package/src/components/visual/CpIcon.vue +156 -0
  48. package/src/directives/ClickOutside.js +13 -0
  49. package/src/directives/ResizeSelect.js +1 -1
  50. package/src/libs/CoreDatepicker.vue +127 -133
  51. package/src/main.js +16 -10
  52. package/src/plugins/toaster.js +69 -0
  53. package/src/utils/constants/src/Intent.js +4 -4
  54. package/vite.config.js +45 -0
  55. package/dist/demo.html +0 -10
  56. package/dist/img/chevron-down-icon.dd31db33.svg +0 -3
  57. package/dist/pimp.common.js +0 -35587
  58. package/dist/pimp.common.js.map +0 -1
  59. package/dist/pimp.css +0 -1
  60. package/dist/pimp.umd.js.map +0 -1
  61. package/dist/pimp.umd.min.js +0 -2
  62. package/dist/pimp.umd.min.js.map +0 -1
  63. package/public/index.html +0 -17
  64. package/src/components/core/playground-sections/SectionMultiSelects.vue +0 -57
  65. package/src/components/selects/CpMultiselect.vue +0 -211
  66. package/src/helpers/multiselectMixin.js +0 -765
  67. package/src/helpers/pointerMixin.js +0 -135
  68. package/src/libs/CoreMultiSelect.vue +0 -618
  69. package/src/libs/CoreToaster.vue +0 -269
  70. package/vue.config.js +0 -20
@@ -2,17 +2,21 @@
2
2
  <div v-click-outside="closeDropdown" class="cpSelectMenu">
3
3
  <button class="cpSelectMenu__button" type="button" @click="toggleDropdown">
4
4
  <span class="cpSelectMenu__label">{{ selectedValue.label }}</span>
5
- <chevron-down-icon :class="{ 'cpSelectMenu__icon--isOpened': isDropdownOpen }" class="cpSelectMenu__icon" />
5
+ <cp-icon
6
+ type="chevron-down"
7
+ :class="{ 'cpSelectMenu__icon--isOpened': isDropdownOpen }"
8
+ class="cpSelectMenu__icon"
9
+ />
6
10
  </button>
7
11
  <transition @enter="enter">
8
12
  <div v-if="isDropdownOpen" ref="dropdownRef" class="cpSelectMenu__dropdown dropdown">
9
13
  <p v-if="dropdownTitle" class="dropdown__title">
10
14
  {{ dropdownTitle }}
11
- <button type="button" @click="closeDropdown"><x-icon /></button>
15
+ <button type="button" @click="closeDropdown"><cp-icon type="x" /></button>
12
16
  </p>
13
17
  <div class="dropdown__list">
14
18
  <label v-if="hasFilter" class="dropdown__filterBar">
15
- <search-icon />
19
+ <cp-icon type="search" />
16
20
  <input
17
21
  ref="dropdownFilterRef"
18
22
  type="text"
@@ -30,7 +34,7 @@
30
34
  :type="inputType"
31
35
  @change="onChange({ value, label })"
32
36
  />
33
- <check-icon v-if="isSelectedValue(value)" class="dropdown__icon" />
37
+ <cp-icon v-if="isSelectedValue(value)" type="check" class="dropdown__icon" />
34
38
  {{ label }}
35
39
  </label>
36
40
  </li>
@@ -44,19 +48,8 @@
44
48
 
45
49
  <script>
46
50
  import anime from 'animejs'
47
- import vClickOutside from 'v-click-outside'
48
- import { ChevronDownIcon, CheckIcon, XIcon, SearchIcon } from 'vue-feather-icons'
49
51
 
50
52
  export default {
51
- components: {
52
- ChevronDownIcon,
53
- CheckIcon,
54
- XIcon,
55
- SearchIcon,
56
- },
57
- directives: {
58
- clickOutside: vClickOutside.directive,
59
- },
60
53
  props: {
61
54
  values: {
62
55
  type: Array,
@@ -99,6 +92,7 @@ export default {
99
92
  required: false,
100
93
  },
101
94
  },
95
+ emits: ['update:selectedValue', 'on-close', 'on-filter-change'],
102
96
  data() {
103
97
  return {
104
98
  isDropdownOpen: false,
@@ -136,7 +130,7 @@ export default {
136
130
  this.$emit('on-close')
137
131
  },
138
132
  onChange(value) {
139
- value.value !== this.selectedValue.value && this.$emit('input', value)
133
+ value.value !== this.selectedValue.value && this.$emit('update:selectedValue', value)
140
134
  this.closeOnSelect && this.closeDropdown()
141
135
  },
142
136
  updateFilterValue(event) {
@@ -226,10 +220,6 @@ export default {
226
220
  white-space: normal;
227
221
  font-weight: 600;
228
222
  color: $neutral-dark;
229
-
230
- svg {
231
- stroke: $neutral-dark;
232
- }
233
223
  }
234
224
 
235
225
  &__filterBar {
@@ -250,9 +240,9 @@ export default {
250
240
  }
251
241
  }
252
242
 
253
- & > svg {
243
+ i {
254
244
  margin-right: pxToEm(8);
255
- stroke: $neutral-dark;
245
+ color: $neutral-dark;
256
246
  flex-shrink: 0;
257
247
  }
258
248
  }
@@ -297,7 +287,7 @@ export default {
297
287
  left: pxToEm(8);
298
288
  top: 50%;
299
289
  transform: translateY(-50%);
300
- stroke: $secondary-color;
290
+ color: $secondary-color;
301
291
  }
302
292
 
303
293
  &__emptyState {
@@ -49,7 +49,7 @@ $cp-checkbox-tick-base-width: pxToEm(14);
49
49
  cursor: pointer;
50
50
  transition: background-color 0.1s ease-out, transform 0.1s linear;
51
51
 
52
- & + svg {
52
+ & + i {
53
53
  position: absolute;
54
54
  z-index: 2;
55
55
  top: 50%;
@@ -57,13 +57,16 @@ $cp-checkbox-tick-base-width: pxToEm(14);
57
57
  transform: translateY(-50%);
58
58
  width: $cp-checkbox-tick-base-width;
59
59
  height: $cp-checkbox-tick-base-width;
60
- stroke: $neutral-light;
61
- stroke-width: 3;
60
+ color: $neutral-light;
62
61
  opacity: 0;
63
62
  transition: opacity 0.2s linear 0.1s;
64
63
  }
65
64
 
66
- &:checked + svg {
65
+ & + i svg {
66
+ stroke-width: 3;
67
+ }
68
+
69
+ &:checked + i {
67
70
  visibility: visible;
68
71
  opacity: 1;
69
72
  }
@@ -102,7 +105,7 @@ $cp-checkbox-tick-base-width: pxToEm(14);
102
105
  grid-row: 1;
103
106
  }
104
107
 
105
- input + svg {
108
+ input + i {
106
109
  left: auto;
107
110
  right: calc(#{math.div($cp-checkbox-base-width, 2)} - #{math.div($cp-checkbox-tick-base-width, 2)});
108
111
  }
@@ -10,7 +10,7 @@
10
10
  :autofocus="autofocus"
11
11
  @change="onChange(checkboxValue)"
12
12
  />
13
- <check-icon />
13
+ <cp-icon type="check" />
14
14
  <span class="cpCheckbox__label" :class="{ 'cpCheckbox__label--isCapitalized': capitalizeLabel }">
15
15
  {{ checkboxLabel }}
16
16
  </span>
@@ -18,15 +18,10 @@
18
18
  </template>
19
19
 
20
20
  <script>
21
- import { CheckIcon } from 'vue-feather-icons'
22
-
23
21
  import { capitalizeFirstLetter, randomString } from '@/helpers'
24
22
  import { ToggleColors } from '@/constants'
25
23
 
26
24
  export default {
27
- components: {
28
- CheckIcon,
29
- },
30
25
  props: {
31
26
  value: {
32
27
  type: [Array, Boolean],
@@ -73,6 +68,7 @@ export default {
73
68
  default: false,
74
69
  },
75
70
  },
71
+ emits: ['update:value'],
76
72
  data() {
77
73
  return {
78
74
  checkedProxy: false,
@@ -106,7 +102,7 @@ export default {
106
102
  },
107
103
  methods: {
108
104
  onChange() {
109
- this.$emit('input', this.checkedProxy)
105
+ this.$emit('update:value', this.checkedProxy)
110
106
  },
111
107
  },
112
108
  }
@@ -2,7 +2,6 @@
2
2
  @import "src/assets/styles/main";
3
3
 
4
4
  $cp-radio-base-width: pxToEm(20);
5
- $cp-radio-tick-base-width: pxToEm(8);
6
5
 
7
6
  @mixin cp-radio-style($color, $className) {
8
7
  &--is#{$className}#{&}--isActive {
@@ -40,16 +39,24 @@ $cp-radio-tick-base-width: pxToEm(8);
40
39
  grid-template-columns: min-content 1fr;
41
40
  grid-gap: $space-md;
42
41
  align-items: center;
43
- cursor: pointer;
42
+
43
+ &:not(#{&}--isDisabled),
44
+ &:not(#{&}--isDisabled) * {
45
+ cursor: pointer;
46
+ }
44
47
 
45
48
  @include cp-radio-style($secondary-color, 'Blue');
46
49
  @include cp-radio-style($primary-color, 'Purple');
47
50
 
48
51
  &--isDisabled {
49
52
  background-color: $neutral-light-1;
50
- cursor: not-allowed;
51
53
  color: $neutral-dark-1;
52
54
 
55
+ &,
56
+ * {
57
+ cursor: not-allowed;
58
+ }
59
+
53
60
  &:hover,
54
61
  &:focus {
55
62
  box-shadow: none;
@@ -72,24 +79,20 @@ $cp-radio-tick-base-width: pxToEm(8);
72
79
  appearance: none;
73
80
  border: pxToRem(1) solid $neutral-dark-4;
74
81
  border-radius: 100%;
82
+ padding: 25%;
75
83
  width: $cp-radio-base-width;
76
84
  height: $cp-radio-base-width;
77
- flex-shrink: 0;
78
- display: grid;
79
- place-items: center;
80
- cursor: pointer;
81
85
  transition: transform 0.1s linear;
82
86
 
83
87
  &:before {
84
88
  content: "";
85
- display: block;
86
- width: $cp-radio-tick-base-width;
87
- height: $cp-radio-tick-base-width;
89
+ display: flex;
90
+ width: 100%;
91
+ height: 100%;
88
92
  border-radius: 100%;
89
93
  background-color: $neutral-light;
90
94
  transition: transform 0.15s linear;
91
95
  transform: scale(0);
92
- transform-origin: center;
93
96
  }
94
97
 
95
98
  &:active:not(:disabled) {
@@ -1,19 +1,25 @@
1
1
  <template>
2
- <label :class="computedClasses" class="cpRadio" :for="radioUniqueId">
2
+ <label
3
+ v-for="({ label, value, description, additionalData, disabled }, index) in options"
4
+ :key="getRadioId(index)"
5
+ :class="computedClasses({ value, disabled })"
6
+ class="cpRadio"
7
+ :for="getRadioId(index)"
8
+ >
3
9
  <input
4
- :id="radioUniqueId"
5
- :checked="isSelected"
6
- :value="radioValue"
7
- :disabled="isDisabled"
10
+ :id="getRadioId(index)"
11
+ :checked="isActive(value)"
12
+ :value="value"
13
+ :disabled="disabled"
8
14
  type="radio"
9
15
  :autofocus="autofocus"
10
16
  :name="groupName"
11
- @change="onChange(radioValue)"
17
+ @input="onChange(value)"
12
18
  />
13
19
  <span class="cpRadio__content">
14
20
  <span class="cpRadio__information">
15
- <span class="cpRadio__label">{{ radioLabel }}</span>
16
- <span v-if="radioDescription" class="cpRadio__description">{{ radioDescription }}</span>
21
+ <span class="cpRadio__label">{{ label }}</span>
22
+ <span v-if="description" class="cpRadio__description">{{ description }}</span>
17
23
  </span>
18
24
  <span v-if="additionalData" class="cpRadio__additionalData">{{ additionalData }}</span>
19
25
  </span>
@@ -26,36 +32,15 @@ import { ToggleColors } from '@/constants'
26
32
 
27
33
  export default {
28
34
  props: {
29
- radioValue: {
35
+ modelValue: {
30
36
  type: String,
31
37
  default: '',
32
38
  required: true,
33
39
  },
34
- radioLabel: {
35
- type: String,
36
- default: '',
40
+ options: {
41
+ type: Array,
37
42
  required: true,
38
43
  },
39
- radioDescription: {
40
- type: String,
41
- default: '',
42
- required: false,
43
- },
44
- additionalData: {
45
- type: String,
46
- default: '',
47
- required: false,
48
- },
49
- isSelected: {
50
- type: Boolean,
51
- default: false,
52
- required: false,
53
- },
54
- isDisabled: {
55
- type: Boolean,
56
- default: false,
57
- required: false,
58
- },
59
44
  groupName: {
60
45
  type: String,
61
46
  default: '',
@@ -73,31 +58,33 @@ export default {
73
58
  default: false,
74
59
  },
75
60
  },
61
+ emits: ['update:modelValue'],
76
62
  data() {
77
63
  return {
78
64
  radioUniqueId: '',
79
65
  }
80
66
  },
81
- computed: {
82
- capitalizedColor() {
83
- return capitalizeFirstLetter(this.color)
84
- },
85
- computedClasses() {
86
- return [
87
- {
88
- 'cpRadio--isActive': this.isSelected,
89
- 'cpRadio--isDisabled': this.isDisabled,
90
- },
91
- `cpRadio--is${this.capitalizedColor}`,
92
- ]
93
- },
94
- },
95
67
  mounted() {
96
68
  this.radioUniqueId = randomString()
97
69
  },
98
70
  methods: {
99
71
  onChange(value) {
100
- this.$emit('input', value)
72
+ this.$emit('update:modelValue', value)
73
+ },
74
+ getRadioId(index) {
75
+ return `${this.radioUniqueId}${index}`
76
+ },
77
+ isActive(value) {
78
+ return value === this.modelValue
79
+ },
80
+ computedClasses({ value, disabled }) {
81
+ return [
82
+ {
83
+ 'cpRadio--isActive': this.isActive(value),
84
+ 'cpRadio--isDisabled': disabled,
85
+ },
86
+ `cpRadio--is${capitalizeFirstLetter(this.color)}`,
87
+ ]
101
88
  },
102
89
  },
103
90
  }
@@ -4,15 +4,15 @@
4
4
  <input
5
5
  :id="switchUniqueId"
6
6
  :disabled="disabled"
7
- :checked="value"
8
- :value="value"
7
+ :checked="modelValue"
8
+ :value="modelValue"
9
9
  type="checkbox"
10
10
  :name="groupName"
11
11
  :autofocus="autofocus"
12
- @change="handleClick(value)"
12
+ @change="handleClick(modelValue)"
13
13
  />
14
14
  <span class="cpSwitch__icon">
15
- <check-icon />
15
+ <cp-icon type="check" />
16
16
  </span>
17
17
  <span class="cpSwitch__knobContainer">
18
18
  <span class="cpSwitch__knob" />
@@ -23,17 +23,12 @@
23
23
  </template>
24
24
 
25
25
  <script>
26
- import { CheckIcon } from 'vue-feather-icons'
27
-
28
26
  import { capitalizeFirstLetter, randomString } from '@/helpers'
29
27
  import { ToggleColors } from '@/constants'
30
28
 
31
29
  export default {
32
- components: {
33
- CheckIcon,
34
- },
35
30
  props: {
36
- value: {
31
+ modelValue: {
37
32
  type: Boolean,
38
33
  default: null,
39
34
  },
@@ -67,6 +62,7 @@ export default {
67
62
  default: false,
68
63
  },
69
64
  },
65
+ emits: ['update:modelValue'],
70
66
  data() {
71
67
  return {
72
68
  switchUniqueId: '',
@@ -80,7 +76,7 @@ export default {
80
76
  return [
81
77
  {
82
78
  'cpSwitch--hasLabel': this.label,
83
- 'cpSwitch--isActive': this.value,
79
+ 'cpSwitch--isActive': this.modelValue,
84
80
  'cpSwitch--isDisabled': this.disabled,
85
81
  'cpSwitch--isReversed': this.reverseLabel,
86
82
  },
@@ -93,7 +89,7 @@ export default {
93
89
  },
94
90
  methods: {
95
91
  handleClick(value) {
96
- this.$emit('input', !value)
92
+ this.$emit('update:modelValue', !value)
97
93
  },
98
94
  },
99
95
  }
@@ -170,7 +166,8 @@ export default {
170
166
 
171
167
  &--isActive .cpSwitch {
172
168
  &__icon {
173
- transform: translateY(-50%) scale(1);
169
+ transform: translateY(-50%);
170
+ opacity: 1;
174
171
  }
175
172
 
176
173
  &__knobContainer {
@@ -210,18 +207,22 @@ export default {
210
207
  position: absolute;
211
208
  left: 0;
212
209
  top: 50%;
213
- transform: translateY(-50%) scale(0);
210
+ transform: translateY(-50%);
211
+ opacity: 0;
214
212
  padding-left: pxToRem(4);
215
213
  display: flex;
216
214
  align-items: center;
217
215
  justify-content: center;
218
- transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.175) 0.08s;
216
+ transition: opacity 0.12s ease-in;
219
217
  width: $cp-switch-base-height;
220
218
  height: $cp-switch-base-height;
221
219
 
222
- & > svg {
220
+ i {
223
221
  width: 80%;
224
- height: auto;
222
+ }
223
+
224
+ svg {
225
+ width: 100%;
225
226
  stroke-width: 3;
226
227
  color: $neutral-light;
227
228
  }
@@ -1,7 +1,7 @@
1
1
  <template>
2
- <div :is="headingLevel" :class="`cpHeading--${size}`" class="cpHeading">
2
+ <component :is="$props.headingLevel" v-bind="$attrs" :class="`cpHeading--${size}`" class="cpHeading">
3
3
  <slot />
4
- </div>
4
+ </component>
5
5
  </template>
6
6
 
7
7
  <script>
@@ -0,0 +1,156 @@
1
+ <script>
2
+ import { defineComponent, h, watch } from 'vue'
3
+ import * as feather from 'feather-icons'
4
+
5
+ export default defineComponent({
6
+ name: 'CpIcon',
7
+ props: {
8
+ animation: {
9
+ type: String,
10
+ default: undefined,
11
+ },
12
+
13
+ animationSpeed: {
14
+ type: String,
15
+ default: undefined,
16
+ },
17
+
18
+ fill: {
19
+ type: String,
20
+ default: 'none',
21
+ },
22
+
23
+ size: {
24
+ type: [Number, String],
25
+ default: 24,
26
+ },
27
+
28
+ stroke: {
29
+ type: String,
30
+ default: 'currentColor',
31
+ },
32
+
33
+ strokeLinecap: {
34
+ type: String,
35
+ default: 'round',
36
+ },
37
+
38
+ strokeLinejoin: {
39
+ type: String,
40
+ default: 'round',
41
+ },
42
+
43
+ strokeWidth: {
44
+ type: [Number, String],
45
+ default: 2,
46
+ },
47
+
48
+ tag: {
49
+ type: String,
50
+ default: 'i',
51
+ },
52
+
53
+ type: {
54
+ type: String,
55
+ default: 'feather',
56
+ validator(type) {
57
+ if (!feather) {
58
+ throw new Error('The Feather icons is required.')
59
+ }
60
+
61
+ if (!feather.icons[type]) {
62
+ throw new Error(`"${type}" is not an available icon type.`)
63
+ }
64
+
65
+ return true
66
+ },
67
+ },
68
+ },
69
+ setup(props, { attrs }) {
70
+ let icon = feather.icons[props.type]
71
+
72
+ watch(
73
+ () => props.type,
74
+ () => {
75
+ icon = feather.icons[props.type]
76
+ },
77
+ )
78
+
79
+ return () =>
80
+ h(
81
+ props.tag,
82
+
83
+ {
84
+ ...attrs,
85
+ 'data-name': props.type,
86
+ 'data-tags': icon.tags,
87
+ 'data-type': props.type,
88
+ class: {
89
+ featherIcon: true,
90
+ [`cpIcon--${props.type}`]: props.type,
91
+ [`cpIcon--${props.animation}`]: props.animation,
92
+ [`cpIcon--${props.animationSpeed}`]: props.animationSpeed,
93
+ },
94
+ },
95
+
96
+ [
97
+ h(
98
+ 'svg',
99
+
100
+ {
101
+ ...icon.attrs,
102
+ fill: props.fill,
103
+ height: props.size,
104
+ stroke: props.stroke,
105
+ 'stroke-linecap': props.strokeLinecap,
106
+ 'stroke-linejoin': props.strokeLinejoin,
107
+ 'stroke-width': props.strokeWidth,
108
+ width: props.size,
109
+ class: [icon.attrs.class, 'cpIcon__content'],
110
+ innerHTML: icon.contents,
111
+ },
112
+ ),
113
+ ],
114
+ )
115
+ },
116
+ })
117
+ </script>
118
+
119
+ <style lang="scss">
120
+ @keyframes cpIcon--spin {
121
+ from {
122
+ transform: rotate(0);
123
+ }
124
+
125
+ to {
126
+ transform: rotate(360deg);
127
+ }
128
+ }
129
+
130
+ .cpIcon {
131
+ display: inline-block;
132
+ overflow: hidden;
133
+
134
+ &--spin {
135
+ animation: cpIcon--spin 2s linear infinite;
136
+ }
137
+
138
+ &--pulse {
139
+ animation: cpIcon--spin 2s infinite steps(8);
140
+ }
141
+
142
+ &--slow {
143
+ animation-duration: 3s;
144
+ }
145
+
146
+ &--fast {
147
+ animation-duration: 1s;
148
+ }
149
+
150
+ &__content {
151
+ display: block;
152
+ height: inherit;
153
+ width: inherit;
154
+ }
155
+ }
156
+ </style>
@@ -0,0 +1,13 @@
1
+ export default {
2
+ beforeMount(el, binding) {
3
+ el.clickOutsideEvent = function (event) {
4
+ if (!(el === event.target || el.contains(event.target))) {
5
+ binding.value(event, el)
6
+ }
7
+ }
8
+ document.body.addEventListener('click', el.clickOutsideEvent)
9
+ },
10
+ unmounted(el) {
11
+ document.body.removeEventListener('click', el.clickOutsideEvent)
12
+ },
13
+ }
@@ -3,7 +3,7 @@ export default {
3
3
  inserted: resizeSelect,
4
4
  }
5
5
 
6
- function resizeSelect(el, binding, vnode) {
6
+ function resizeSelect(el) {
7
7
  const select = document.createElement('select')
8
8
  select.className = el.className
9
9
  const option = document.createElement('option')