@citizenplane/pimp 7.0.1 → 8.0.1

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 (42) hide show
  1. package/.eslintrc.js +1 -0
  2. package/.lintstagedrc.json +2 -2
  3. package/README.md +18 -6
  4. package/dist/pimp.es.js +10669 -0
  5. package/dist/pimp.umd.js +9 -0
  6. package/dist/style.css +1 -0
  7. package/package-lock.json +2295 -1775
  8. package/package.json +27 -20
  9. package/src/App.vue +0 -1
  10. package/src/README.md +23 -9
  11. package/src/assets/styles/base/_base.scss +2 -15
  12. package/src/assets/styles/helpers/_functions.scss +1 -1
  13. package/src/assets/styles/helpers/_keyframes.scss +25 -0
  14. package/src/assets/styles/lib/_normalize.scss +19 -41
  15. package/src/assets/styles/variables/_colors.scss +16 -16
  16. package/src/assets/styles/variables/_sizing.scss +1 -1
  17. package/src/assets/styles/variables/_spacing.scss +2 -2
  18. package/src/components/atomic-elements/CpBadge.vue +41 -29
  19. package/src/components/buttons/CpButton.vue +1 -1
  20. package/src/components/core/BaseInputLabel/index.vue +0 -1
  21. package/src/components/core/playground-sections/SectionAtomicElements.vue +20 -4
  22. package/src/components/core/playground-sections/SectionDatePickers.vue +26 -1
  23. package/src/components/core/playground-sections/SectionSimpleInputs.vue +6 -1
  24. package/src/components/date-pickers/CpCalendar.vue +49 -2
  25. package/src/components/date-pickers/CpDate.vue +61 -39
  26. package/src/components/date-pickers/CpDatepicker.vue +50 -3
  27. package/src/components/feedback-indicators/CpAlert.vue +4 -4
  28. package/src/components/index.js +15 -0
  29. package/src/components/inputs/CpInput.vue +59 -75
  30. package/src/components/inputs/CpTextarea.vue +19 -2
  31. package/src/components/lists-and-table/CpTable/index.scss +15 -9
  32. package/src/components/selects/CpSelect.vue +21 -2
  33. package/src/components/toggles/CpCheckbox/index.scss +1 -1
  34. package/src/components/toggles/CpRadio/index.scss +2 -2
  35. package/src/components/visual/CpIcon.vue +9 -2
  36. package/src/libs/CoreDatepicker.vue +101 -118
  37. package/vite.config.js +19 -0
  38. package/dist/assets/chevron-down-icon.1e5b69a2.svg +0 -3
  39. package/dist/assets/index.2be314eb.css +0 -1
  40. package/dist/assets/index.e3e1e2b7.js +0 -1
  41. package/dist/assets/vendor.ed632372.js +0 -9
  42. package/dist/index.html +0 -20
@@ -1,6 +1,8 @@
1
1
  <template>
2
- <div class="cpInput" :class="dynamicClasses" :aria-disabled="disabled" @click="focusOnInput">
3
- <base-input-label v-if="label" :for="inputReferenceId"> {{ inputLabelTitle }}</base-input-label>
2
+ <div class="cpInput" :class="dynamicClasses" :aria-disabled="isDisabled" @click="focusOnInput">
3
+ <base-input-label v-if="label" :for="inputIdentifier" class="cpInput__label">
4
+ {{ inputLabelTitle }}
5
+ </base-input-label>
4
6
  <div
5
7
  ref="cpInputContainer"
6
8
  :class="{ 'cpInput__container--hasBeforeIcon': hasBeforeIcon }"
@@ -19,23 +21,21 @@
19
21
  <slot name="input-icon-after" />
20
22
  </div>
21
23
  <input
22
- :id="inputReferenceId"
24
+ :id="inputIdentifier"
23
25
  v-maska="mask"
24
- :disabled="disabled"
25
- :name="name"
26
- :placeholder="placeholder"
27
- :readonly="readonly"
28
- :required="required"
29
- :autocomplete="autocomplete"
30
- :inputmode="inputMode"
31
- :type="type"
32
26
  :value="modelValue"
27
+ v-bind="restAttributes"
33
28
  class="cpInput__inner"
34
29
  @input="handleChange"
35
30
  />
36
31
  </div>
37
32
  <transition-expand>
38
- <base-input-label v-if="isInputInvalid && errorMessage" :is-invalid="isInvalid" :for="inputReferenceId">
33
+ <base-input-label
34
+ v-if="isInputInvalid && errorMessage"
35
+ :is-invalid="isInvalid"
36
+ :for="inputIdentifier"
37
+ class="cpInput__label cpInput__label--isAfter"
38
+ >
39
39
  {{ errorMessage }}
40
40
  </base-input-label>
41
41
  </transition-expand>
@@ -43,27 +43,14 @@
43
43
  </template>
44
44
 
45
45
  <script>
46
+ import { ref } from 'vue'
47
+
46
48
  import { randomString } from '@/helpers'
47
49
 
48
50
  import BaseInputLabel from '@/components/core/BaseInputLabel/index.vue'
49
51
  import CpIcon from '@/components/visual/CpIcon.vue'
50
52
  import TransitionExpand from '@/components/helpers-utilities/TransitionExpand.vue'
51
53
 
52
- const inputTypesList = [
53
- 'text',
54
- 'date',
55
- 'datetime-local',
56
- 'email',
57
- 'month',
58
- 'number',
59
- 'password',
60
- 'search',
61
- 'tel',
62
- 'time',
63
- 'url',
64
- 'week',
65
- ]
66
-
67
54
  export default {
68
55
  name: 'CpInput',
69
56
  components: {
@@ -71,6 +58,7 @@ export default {
71
58
  BaseInputLabel,
72
59
  TransitionExpand,
73
60
  },
61
+ inheritAttrs: false,
74
62
  props: {
75
63
  modelValue: {
76
64
  type: [String, Number, Boolean],
@@ -80,46 +68,10 @@ export default {
80
68
  type: String,
81
69
  default: '',
82
70
  },
83
- placeholder: {
84
- type: String,
85
- default: '',
86
- required: true,
87
- },
88
- required: {
89
- type: Boolean,
90
- default: false,
91
- },
92
71
  inputId: {
93
72
  type: String,
94
- default: '',
95
- },
96
- type: {
97
- type: String,
98
- default: inputTypesList[0],
99
- validator: (value) => {
100
- return inputTypesList.includes(value)
101
- },
102
- },
103
- name: {
104
- type: String,
105
- default: '',
106
- },
107
- readonly: {
108
- type: Boolean,
109
- default: false,
110
- },
111
- disabled: {
112
- type: Boolean,
113
73
  default: null,
114
74
  },
115
- autocomplete: {
116
- type: String,
117
- default: 'on',
118
- },
119
- inputMode: {
120
- type: String,
121
- default: 'text',
122
- },
123
75
  isInvalid: {
124
76
  type: Boolean,
125
77
  default: false,
@@ -146,18 +98,38 @@ export default {
146
98
  },
147
99
  },
148
100
  emits: ['update:modelValue'],
101
+ setup(props, { attrs }) {
102
+ // class is a reserved work, we can't remove 'class' property from attrs
103
+ // eslint-disable-next-line no-unused-vars
104
+ const { ['class']: value, id, ...restAttributes } = attrs
105
+ const inputIdentifier = id === undefined ? ref(randomString()) : id
106
+
107
+ return {
108
+ inputIdentifier,
109
+ restAttributes,
110
+ }
111
+ },
149
112
  data() {
150
113
  return {
151
- inputReferenceId: this.inputId,
152
114
  isDOMElementValid: true,
153
115
  }
154
116
  },
155
117
  computed: {
118
+ isDisabled() {
119
+ return this.checkAttribute('disabled')
120
+ },
121
+ isRequired() {
122
+ return this.checkAttribute('required')
123
+ },
124
+ isReadonly() {
125
+ return this.checkAttribute('readonly')
126
+ },
156
127
  dynamicClasses() {
157
128
  return [
129
+ this.$attrs.class,
158
130
  {
159
131
  'cpInput--isInvalid': this.isInputInvalid,
160
- 'cpInput--isDisabled': this.disabled,
132
+ 'cpInput--isDisabled': this.isDisabled,
161
133
  'cpInput--hasNoBorder': this.removeBorder,
162
134
  'cpInput--isLarge': this.isLarge,
163
135
  },
@@ -171,12 +143,14 @@ export default {
171
143
  }
172
144
  },
173
145
  inputLabelTitle() {
174
- const requiredLabel = this.required && this.label ? '*' : ''
146
+ if (this.label === '') return ''
147
+
148
+ const requiredMark = this.isRequired ? '*' : ''
175
149
 
176
- return `${this.label} ${requiredLabel}`
150
+ return `${this.label} ${requiredMark}`
177
151
  },
178
152
  isValid() {
179
- return this.modelValue && !this.readonly && !this.isInvalid && this.isDOMElementValid
153
+ return this.modelValue && !this.isReadonly && !this.isInvalid && this.isDOMElementValid
180
154
  },
181
155
  isInputInvalid() {
182
156
  return this.isInvalid || !this.isDOMElementValid
@@ -188,15 +162,11 @@ export default {
188
162
  return !!this.$slots['input-icon-after']
189
163
  },
190
164
  DOMElement() {
191
- return this.$refs.cpInputContainer.children.namedItem(this.inputReferenceId)
165
+ return this.$refs.cpInputContainer.children.namedItem(this.inputIdentifier)
192
166
  },
193
167
  },
194
168
  mounted() {
195
- if (!this.inputReferenceId) this.inputReferenceId = randomString()
196
-
197
- this.$nextTick(() => {
198
- this.checkInputValidity()
199
- })
169
+ this.$nextTick(() => this.checkInputValidity())
200
170
  },
201
171
  methods: {
202
172
  handleChange(e) {
@@ -214,6 +184,9 @@ export default {
214
184
  (this.DOMElement.validity && this.DOMElement.validity.valid) ||
215
185
  (this.DOMElement.validity && this.DOMElement.validity.valueMissing)
216
186
  },
187
+ checkAttribute(attribute) {
188
+ return this.$attrs[attribute] === '' || this.$attrs[attribute] === true
189
+ },
217
190
  },
218
191
  }
219
192
  </script>
@@ -229,7 +202,6 @@ export default {
229
202
  position: relative;
230
203
  display: flex;
231
204
  flex-direction: column;
232
- font-size: pxToRem(16);
233
205
 
234
206
  &__container {
235
207
  z-index: 1;
@@ -310,6 +282,18 @@ export default {
310
282
  box-shadow: none;
311
283
  }
312
284
 
285
+ &__label {
286
+ display: block;
287
+
288
+ &:not(#{&}--isAfter) {
289
+ margin-bottom: pxToEm(6);
290
+ }
291
+
292
+ &--isAfter {
293
+ margin-top: pxToEm(6);
294
+ }
295
+ }
296
+
313
297
  $cp-input-icon-size: pxToEm(20);
314
298
 
315
299
  &__icon {
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div class="cpTextarea">
3
- <base-input-label v-if="label" :for="inputReferenceId">
3
+ <base-input-label v-if="label" :for="inputReferenceId" class="cpTextarea__label">
4
4
  {{ inputLabelTitle }}
5
5
  </base-input-label>
6
6
  <textarea
@@ -15,7 +15,12 @@
15
15
  @input="handleChange"
16
16
  />
17
17
  <transition-expand>
18
- <base-input-label v-if="isInvalid" :for="inputReferenceId" is-invalid>
18
+ <base-input-label
19
+ v-if="isInvalid"
20
+ :for="inputReferenceId"
21
+ is-invalid
22
+ class="cpTextarea__label cpTextarea__label--isAfter"
23
+ >
19
24
  {{ errorMessage }}
20
25
  </base-input-label>
21
26
  </transition-expand>
@@ -153,5 +158,17 @@ export default {
153
158
  }
154
159
  }
155
160
  }
161
+
162
+ &__label {
163
+ display: block;
164
+
165
+ &:not(#{&}--isAfter) {
166
+ margin-bottom: pxToEm(6);
167
+ }
168
+
169
+ &--isAfter {
170
+ margin-top: pxToEm(6);
171
+ }
172
+ }
156
173
  }
157
174
  </style>
@@ -1,4 +1,4 @@
1
- @import "src/assets/styles/main";
1
+ @import 'src/assets/styles/main';
2
2
 
3
3
  .cpTable {
4
4
  position: relative;
@@ -34,9 +34,9 @@
34
34
  /* Scrolling Visual Cue */
35
35
  &__container[role='region'][aria-labelledby][tabindex] {
36
36
  background: linear-gradient(to right, $neutral-light 30%, rgba(255, 255, 255, 0)),
37
- linear-gradient(to right, rgba($neutral-light, 0), $neutral-light 70%) 0 100%,
38
- radial-gradient(farthest-side at 0% 50%, rgba($neutral-dark, 0.2), rgba($neutral-dark, 0)),
39
- radial-gradient(farthest-side at 100% 50%, rgba($neutral-dark, 0.2), rgba($neutral-dark, 0)) 0 100%;
37
+ linear-gradient(to right, rgba($neutral-light, 0), $neutral-light 70%) 0 100%,
38
+ radial-gradient(farthest-side at 0% 50%, rgba($neutral-dark, 0.2), rgba($neutral-dark, 0)),
39
+ radial-gradient(farthest-side at 100% 50%, rgba($neutral-dark, 0.2), rgba($neutral-dark, 0)) 0 100%;
40
40
  background-repeat: no-repeat;
41
41
  background-color: $neutral-light;
42
42
  background-size: 40px 100%, 40px 100%, 14px 100%, 14px 100%;
@@ -168,6 +168,11 @@
168
168
  background-color: scale-color($neutral-dark, $lightness: 98%);
169
169
  color: $neutral-dark;
170
170
  }
171
+
172
+ &:focus {
173
+ outline: none !important;
174
+ box-shadow: 0 0 0 pxToEm(3) scale-color($secondary-color, $lightness: 80%);
175
+ }
171
176
  }
172
177
 
173
178
  &--isOptions svg {
@@ -223,11 +228,11 @@
223
228
  left: 0;
224
229
  transform: translateX(-100%);
225
230
  background-image: linear-gradient(
226
- 90deg,
227
- rgba($neutral-dark-3, 0) 0,
228
- rgba($neutral-dark-3, 0.2) 20%,
229
- rgba($neutral-dark-3, 0.5) 60%,
230
- rgba($neutral-dark-3, 0)
231
+ 90deg,
232
+ rgba($neutral-dark-3, 0) 0,
233
+ rgba($neutral-dark-3, 0.2) 20%,
234
+ rgba($neutral-dark-3, 0.5) 60%,
235
+ rgba($neutral-dark-3, 0)
231
236
  );
232
237
  animation: shimmer 2s infinite;
233
238
  }
@@ -289,6 +294,7 @@
289
294
  }
290
295
 
291
296
  &:focus {
297
+ outline: none !important;
292
298
  box-shadow: 0 0 0 pxToEm(3) scale-color($blue, $lightness: 70%);
293
299
  }
294
300
 
@@ -1,6 +1,8 @@
1
1
  <template>
2
2
  <div class="cpSelect" :class="dynamicClasses">
3
- <base-input-label v-if="label" :for="selectReferenceId">{{ selectLabelTitle }}</base-input-label>
3
+ <base-input-label v-if="label" :for="selectReferenceId" class="cpSelect__label">
4
+ {{ selectLabelTitle }}
5
+ </base-input-label>
4
6
  <div class="cpSelect__container">
5
7
  <select
6
8
  :id="selectReferenceId"
@@ -18,7 +20,12 @@
18
20
  </select>
19
21
  </div>
20
22
  <transition-expand>
21
- <base-input-label v-if="isInvalid" :is-invalid="isInvalid" :for="selectReferenceId">
23
+ <base-input-label
24
+ v-if="isInvalid"
25
+ :is-invalid="isInvalid"
26
+ :for="selectReferenceId"
27
+ class="cpSelect__label cpSelect__label--isAfter"
28
+ >
22
29
  {{ errorMessage }}
23
30
  </base-input-label>
24
31
  </transition-expand>
@@ -163,6 +170,18 @@ export default {
163
170
  }
164
171
  }
165
172
 
173
+ &__label {
174
+ display: block;
175
+
176
+ &:not(#{&}--isAfter) {
177
+ margin-bottom: pxToEm(6);
178
+ }
179
+
180
+ &--isAfter {
181
+ margin-top: pxToEm(6);
182
+ }
183
+ }
184
+
166
185
  &--isDisabled {
167
186
  .cpSelect__inner {
168
187
  border-color: $neutral-dark-4 !important;
@@ -1,5 +1,5 @@
1
1
  @use 'sass:math';
2
- @import "src/assets/styles/main";
2
+ @import 'src/assets/styles/main';
3
3
 
4
4
  $cp-checkbox-base-width: pxToEm(20);
5
5
  $cp-checkbox-tick-base-width: pxToEm(14);
@@ -1,5 +1,5 @@
1
1
  @use 'sass:math';
2
- @import "src/assets/styles/main";
2
+ @import 'src/assets/styles/main';
3
3
 
4
4
  $cp-radio-base-width: pxToEm(20);
5
5
 
@@ -85,7 +85,7 @@ $cp-radio-base-width: pxToEm(20);
85
85
  transition: transform 0.1s linear;
86
86
 
87
87
  &:before {
88
- content: "";
88
+ content: '';
89
89
  display: flex;
90
90
  width: 100%;
91
91
  height: 100%;
@@ -1,5 +1,5 @@
1
1
  <script>
2
- import { defineComponent, h } from 'vue'
2
+ import { defineComponent, h, watch } from 'vue'
3
3
  import * as feather from 'feather-icons'
4
4
 
5
5
  export default defineComponent({
@@ -67,7 +67,14 @@ export default defineComponent({
67
67
  },
68
68
  },
69
69
  setup(props, { attrs }) {
70
- const icon = feather.icons[props.type]
70
+ let icon = feather.icons[props.type]
71
+
72
+ watch(
73
+ () => props.type,
74
+ () => {
75
+ icon = feather.icons[props.type]
76
+ },
77
+ )
71
78
 
72
79
  return () =>
73
80
  h(