@citizenplane/pimp 18.16.3 → 18.17.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/dist/components/CpQuantityCounter.vue.d.ts +24 -0
- package/dist/components/CpQuantityCounter.vue.d.ts.map +1 -0
- package/dist/components/index.d.ts +2 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/pimp.es.js +715 -658
- package/dist/pimp.umd.js +19 -19
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/components/CpQuantityCounter.vue +106 -0
- package/src/components/index.ts +3 -0
- package/src/stories/CpQuantityCounter.stories.ts +63 -0
package/package.json
CHANGED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="cpQuantityCounter">
|
|
3
|
+
<button
|
|
4
|
+
:aria-label="decreaseLabel"
|
|
5
|
+
class="cpQuantityCounter__button"
|
|
6
|
+
:disabled="isDecrementDisabled"
|
|
7
|
+
type="button"
|
|
8
|
+
@click="decrement"
|
|
9
|
+
>
|
|
10
|
+
<cp-icon size="16" type="minus" />
|
|
11
|
+
</button>
|
|
12
|
+
<cp-transition-counter v-if="!disableAnimation" class="cpQuantityCounter__count" :counter-number="modelValue">
|
|
13
|
+
<span>{{ modelValue }}</span>
|
|
14
|
+
</cp-transition-counter>
|
|
15
|
+
<span v-else class="cpQuantityCounter__count">{{ modelValue }}</span>
|
|
16
|
+
<button
|
|
17
|
+
:aria-label="increaseLabel"
|
|
18
|
+
class="cpQuantityCounter__button cpQuantityCounter__button--isAccent"
|
|
19
|
+
:disabled="isIncrementDisabled"
|
|
20
|
+
type="button"
|
|
21
|
+
@click="increment"
|
|
22
|
+
>
|
|
23
|
+
<cp-icon size="16" type="plus" />
|
|
24
|
+
</button>
|
|
25
|
+
</div>
|
|
26
|
+
</template>
|
|
27
|
+
|
|
28
|
+
<script setup lang="ts">
|
|
29
|
+
import { computed } from 'vue'
|
|
30
|
+
|
|
31
|
+
import CpIcon from '@/components/CpIcon.vue'
|
|
32
|
+
import CpTransitionCounter from '@/components/CpTransitionCounter.vue'
|
|
33
|
+
|
|
34
|
+
interface Props {
|
|
35
|
+
decreaseLabel: string
|
|
36
|
+
disableAnimation?: boolean
|
|
37
|
+
increaseLabel: string
|
|
38
|
+
max?: number | null
|
|
39
|
+
min?: number
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const props = withDefaults(defineProps<Props>(), { disableAnimation: false, max: null, min: 0 })
|
|
43
|
+
|
|
44
|
+
const modelValue = defineModel<number>({ required: true })
|
|
45
|
+
|
|
46
|
+
const isDecrementDisabled = computed(() => modelValue.value <= props.min)
|
|
47
|
+
const isIncrementDisabled = computed(() => props.max !== null && modelValue.value >= props.max)
|
|
48
|
+
|
|
49
|
+
const decrement = () => {
|
|
50
|
+
if (isDecrementDisabled.value) return
|
|
51
|
+
modelValue.value -= 1
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const increment = () => {
|
|
55
|
+
if (isIncrementDisabled.value) return
|
|
56
|
+
modelValue.value += 1
|
|
57
|
+
}
|
|
58
|
+
</script>
|
|
59
|
+
|
|
60
|
+
<style lang="scss">
|
|
61
|
+
.cpQuantityCounter {
|
|
62
|
+
display: flex;
|
|
63
|
+
align-items: center;
|
|
64
|
+
padding: var(--cp-spacing-xs);
|
|
65
|
+
border-radius: var(--cp-radius-md-lg);
|
|
66
|
+
background: var(--cp-background-accent-primary);
|
|
67
|
+
gap: var(--cp-spacing-sm);
|
|
68
|
+
|
|
69
|
+
&__button {
|
|
70
|
+
display: flex;
|
|
71
|
+
align-items: center;
|
|
72
|
+
justify-content: center;
|
|
73
|
+
padding: var(--cp-spacing-sm-md);
|
|
74
|
+
border: fn.px-to-rem(1) solid var(--cp-border-soft);
|
|
75
|
+
border-radius: var(--cp-radius-md);
|
|
76
|
+
background: var(--cp-background-primary);
|
|
77
|
+
box-shadow: var(--cp-shadows-3xs);
|
|
78
|
+
color: var(--cp-text-primary);
|
|
79
|
+
|
|
80
|
+
@include mx.square-sizing(28);
|
|
81
|
+
@extend %u-focus-outline;
|
|
82
|
+
|
|
83
|
+
&:disabled {
|
|
84
|
+
border-color: transparent;
|
|
85
|
+
background: var(--cp-background-secondary);
|
|
86
|
+
box-shadow: none;
|
|
87
|
+
color: var(--cp-text-disabled);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
&--isAccent {
|
|
91
|
+
color: var(--cp-text-accent-primary);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
&__count {
|
|
96
|
+
display: flex;
|
|
97
|
+
width: fn.px-to-rem(24);
|
|
98
|
+
justify-content: center;
|
|
99
|
+
color: var(--cp-text-primary);
|
|
100
|
+
font-size: var(--cp-text-size-sm);
|
|
101
|
+
font-weight: 500;
|
|
102
|
+
line-height: var(--cp-text-sm-line-height);
|
|
103
|
+
text-align: center;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
</style>
|
package/src/components/index.ts
CHANGED
|
@@ -40,6 +40,7 @@ import CpMenu from './CpMenu.vue'
|
|
|
40
40
|
import CpMenuItem from './CpMenuItem.vue'
|
|
41
41
|
import CpMenuList from './CpMenuList.vue'
|
|
42
42
|
import CpMultiselect from './CpMultiselect.vue'
|
|
43
|
+
import CpQuantityCounter from './CpQuantityCounter.vue'
|
|
43
44
|
import CpRadio from './CpRadio.vue'
|
|
44
45
|
import CpRadioGroup from './CpRadioGroup.vue'
|
|
45
46
|
import CpRadioNew from './CpRadioNew.vue'
|
|
@@ -120,6 +121,7 @@ const Components = {
|
|
|
120
121
|
CpSelect,
|
|
121
122
|
CpSelectMenu,
|
|
122
123
|
CpMultiselect,
|
|
124
|
+
CpQuantityCounter,
|
|
123
125
|
CpCheckbox,
|
|
124
126
|
CpRadio,
|
|
125
127
|
CpRadioGroup,
|
|
@@ -244,6 +246,7 @@ export {
|
|
|
244
246
|
CpMenuItem,
|
|
245
247
|
CpMenuList,
|
|
246
248
|
CpMultiselect,
|
|
249
|
+
CpQuantityCounter,
|
|
247
250
|
CpRadio,
|
|
248
251
|
CpRadioGroup,
|
|
249
252
|
CpRadioNew,
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
|
|
4
|
+
import CpQuantityCounter from '@/components/CpQuantityCounter.vue'
|
|
5
|
+
|
|
6
|
+
const meta = {
|
|
7
|
+
title: 'Atoms/CpQuantityCounter',
|
|
8
|
+
component: CpQuantityCounter,
|
|
9
|
+
argTypes: {
|
|
10
|
+
decreaseLabel: {
|
|
11
|
+
control: 'text',
|
|
12
|
+
description: 'Aria-label for the decrease button',
|
|
13
|
+
},
|
|
14
|
+
disableAnimation: {
|
|
15
|
+
control: 'boolean',
|
|
16
|
+
description: 'Whether to render the count as a plain span instead of animating it',
|
|
17
|
+
},
|
|
18
|
+
increaseLabel: {
|
|
19
|
+
control: 'text',
|
|
20
|
+
description: 'Aria-label for the increase button',
|
|
21
|
+
},
|
|
22
|
+
max: {
|
|
23
|
+
control: 'number',
|
|
24
|
+
description: 'Maximum allowed value',
|
|
25
|
+
},
|
|
26
|
+
min: {
|
|
27
|
+
control: 'number',
|
|
28
|
+
description: 'Minimum allowed value',
|
|
29
|
+
},
|
|
30
|
+
modelValue: {
|
|
31
|
+
control: 'number',
|
|
32
|
+
description: 'The counter value',
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
} satisfies Meta<typeof CpQuantityCounter>
|
|
36
|
+
|
|
37
|
+
export default meta
|
|
38
|
+
type Story = StoryObj<typeof meta>
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Default counter. Use the controls to experiment with each prop in isolation.
|
|
42
|
+
*/
|
|
43
|
+
export const Default: Story = {
|
|
44
|
+
args: {
|
|
45
|
+
modelValue: 1,
|
|
46
|
+
min: 0,
|
|
47
|
+
max: 5,
|
|
48
|
+
decreaseLabel: 'Decrease',
|
|
49
|
+
increaseLabel: 'Increase',
|
|
50
|
+
},
|
|
51
|
+
render: (args) => ({
|
|
52
|
+
components: { CpQuantityCounter },
|
|
53
|
+
setup() {
|
|
54
|
+
const value = ref(1)
|
|
55
|
+
return { args, value }
|
|
56
|
+
},
|
|
57
|
+
template: `
|
|
58
|
+
<div style="padding: 20px;">
|
|
59
|
+
<CpQuantityCounter v-bind="args" v-model="value" />
|
|
60
|
+
</div>
|
|
61
|
+
`,
|
|
62
|
+
}),
|
|
63
|
+
}
|