@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.
- package/.eslintrc.js +1 -0
- package/.lintstagedrc.json +2 -2
- package/README.md +18 -6
- package/dist/pimp.es.js +10669 -0
- package/dist/pimp.umd.js +9 -0
- package/dist/style.css +1 -0
- package/package-lock.json +2295 -1775
- package/package.json +27 -20
- package/src/App.vue +0 -1
- package/src/README.md +23 -9
- package/src/assets/styles/base/_base.scss +2 -15
- package/src/assets/styles/helpers/_functions.scss +1 -1
- package/src/assets/styles/helpers/_keyframes.scss +25 -0
- package/src/assets/styles/lib/_normalize.scss +19 -41
- package/src/assets/styles/variables/_colors.scss +16 -16
- package/src/assets/styles/variables/_sizing.scss +1 -1
- package/src/assets/styles/variables/_spacing.scss +2 -2
- package/src/components/atomic-elements/CpBadge.vue +41 -29
- package/src/components/buttons/CpButton.vue +1 -1
- package/src/components/core/BaseInputLabel/index.vue +0 -1
- package/src/components/core/playground-sections/SectionAtomicElements.vue +20 -4
- package/src/components/core/playground-sections/SectionDatePickers.vue +26 -1
- package/src/components/core/playground-sections/SectionSimpleInputs.vue +6 -1
- package/src/components/date-pickers/CpCalendar.vue +49 -2
- package/src/components/date-pickers/CpDate.vue +61 -39
- package/src/components/date-pickers/CpDatepicker.vue +50 -3
- package/src/components/feedback-indicators/CpAlert.vue +4 -4
- package/src/components/index.js +15 -0
- package/src/components/inputs/CpInput.vue +59 -75
- package/src/components/inputs/CpTextarea.vue +19 -2
- package/src/components/lists-and-table/CpTable/index.scss +15 -9
- package/src/components/selects/CpSelect.vue +21 -2
- package/src/components/toggles/CpCheckbox/index.scss +1 -1
- package/src/components/toggles/CpRadio/index.scss +2 -2
- package/src/components/visual/CpIcon.vue +9 -2
- package/src/libs/CoreDatepicker.vue +101 -118
- package/vite.config.js +19 -0
- package/dist/assets/chevron-down-icon.1e5b69a2.svg +0 -3
- package/dist/assets/index.2be314eb.css +0 -1
- package/dist/assets/index.e3e1e2b7.js +0 -1
- package/dist/assets/vendor.ed632372.js +0 -9
- package/dist/index.html +0 -20
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="cpInput" :class="dynamicClasses" :aria-disabled="
|
|
3
|
-
<base-input-label v-if="label" :for="
|
|
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="
|
|
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
|
|
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.
|
|
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
|
-
|
|
146
|
+
if (this.label === '') return ''
|
|
147
|
+
|
|
148
|
+
const requiredMark = this.isRequired ? '*' : ''
|
|
175
149
|
|
|
176
|
-
return `${this.label} ${
|
|
150
|
+
return `${this.label} ${requiredMark}`
|
|
177
151
|
},
|
|
178
152
|
isValid() {
|
|
179
|
-
return this.modelValue && !this.
|
|
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.
|
|
165
|
+
return this.$refs.cpInputContainer.children.namedItem(this.inputIdentifier)
|
|
192
166
|
},
|
|
193
167
|
},
|
|
194
168
|
mounted() {
|
|
195
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
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"
|
|
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
|
|
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
|
|
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
|
-
|
|
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(
|