@citizenplane/pimp 13.0.0 → 14.0.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.
Files changed (66) hide show
  1. package/dist/pimp.es.js +4804 -4585
  2. package/dist/pimp.umd.js +44 -44
  3. package/dist/style.css +1 -1
  4. package/package.json +1 -1
  5. package/src/components/CpAccordion.vue +163 -0
  6. package/src/components/CpAccordionGroup.vue +51 -0
  7. package/src/components/CpBadge.vue +2 -2
  8. package/src/components/CpButton.vue +4 -3
  9. package/src/components/CpButtonGroup.vue +30 -2
  10. package/src/components/CpDate.vue +5 -4
  11. package/src/components/CpInput.vue +4 -4
  12. package/src/components/CpItemActions.vue +11 -9
  13. package/src/components/CpMultiselect.vue +3 -3
  14. package/src/components/CpPartnerBadge.vue +3 -2
  15. package/src/components/CpSelect.vue +5 -5
  16. package/src/components/CpTable.vue +2 -2
  17. package/src/components/CpTelInput.vue +4 -4
  18. package/src/components/CpTextarea.vue +3 -3
  19. package/src/components/CpTransitionCounter.vue +77 -0
  20. package/src/components/CpTransitionListItems.vue +41 -0
  21. package/src/components/CpTransitionSize.vue +88 -0
  22. package/src/components/CpTransitionSlide.vue +44 -0
  23. package/src/components/CpTransitionTabContent.vue +70 -0
  24. package/src/components/index.ts +16 -2
  25. package/src/constants/Sizes.ts +1 -11
  26. package/src/constants/index.ts +1 -1
  27. package/src/stories/BaseInputLabel.stories.ts +1 -1
  28. package/src/stories/CpAccordion.stories.ts +282 -0
  29. package/src/stories/CpAccordionGroup.stories.ts +223 -0
  30. package/src/stories/CpAirlineLogo.stories.ts +1 -1
  31. package/src/stories/CpAlert.stories.ts +1 -1
  32. package/src/stories/CpBadge.stories.ts +2 -4
  33. package/src/stories/CpButton.stories.ts +147 -146
  34. package/src/stories/CpCheckbox.stories.ts +1 -1
  35. package/src/stories/CpContextualMenu.stories.ts +1 -1
  36. package/src/stories/CpDate.stories.ts +1 -1
  37. package/src/stories/CpDatepicker.stories.ts +1 -1
  38. package/src/stories/CpDialog.stories.ts +1 -1
  39. package/src/stories/CpHeading.stories.ts +1 -1
  40. package/src/stories/CpIcon.stories.ts +1 -1
  41. package/src/stories/CpInput.stories.ts +2 -4
  42. package/src/stories/CpItemActions.stories.ts +1 -1
  43. package/src/stories/CpLoader.stories.ts +1 -1
  44. package/src/stories/CpMenuItem.stories.ts +1 -1
  45. package/src/stories/CpMultiselect.stories.ts +1 -1
  46. package/src/stories/CpPartnerBadge.stories.ts +3 -3
  47. package/src/stories/CpRadio.stories.ts +1 -1
  48. package/src/stories/CpSelect.stories.ts +4 -6
  49. package/src/stories/CpSelectMenu.stories.ts +1 -1
  50. package/src/stories/CpSelectableButton.stories.ts +4 -6
  51. package/src/stories/CpSwitch.stories.ts +1 -1
  52. package/src/stories/CpTable.stories.ts +1 -1
  53. package/src/stories/CpTableEmptyState.stories.ts +1 -1
  54. package/src/stories/CpTabs.stories.ts +1 -1
  55. package/src/stories/CpTelInput.stories.ts +1 -1
  56. package/src/stories/CpTextarea.stories.ts +1 -1
  57. package/src/stories/CpToast.stories.ts +1 -1
  58. package/src/stories/CpTooltip.stories.ts +1 -1
  59. package/src/stories/CpTransitionCounter.stories.ts +66 -0
  60. package/src/stories/{TransitionExpand.stories.ts → CpTransitionExpand.stories.ts} +11 -11
  61. package/src/stories/CpTransitionListItems.stories.ts +147 -0
  62. package/src/stories/CpTransitionSize.stories.ts +147 -0
  63. package/src/stories/CpTransitionSlide.stories.ts +65 -0
  64. package/src/stories/CpTransitionTabContent.stories.ts +78 -0
  65. package/src/stories/documentationStyles.ts +16 -0
  66. /package/src/components/{TransitionExpand.vue → CpTransitionExpand.vue} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@citizenplane/pimp",
3
- "version": "13.0.0",
3
+ "version": "14.0.0",
4
4
  "scripts": {
5
5
  "dev": "storybook dev -p 8080",
6
6
  "build-storybook": "storybook build --output-dir ./docs",
@@ -0,0 +1,163 @@
1
+ <template>
2
+ <div class="cpAccordion">
3
+ <button
4
+ :id="accordionId"
5
+ :aria-controls="accordionContentId"
6
+ :aria-expanded="isToggled"
7
+ class="cpAccordion__header"
8
+ :class="dynamicClasses"
9
+ cp-item-actions-trigger
10
+ type="button"
11
+ @click="handleClick"
12
+ >
13
+ <div class="cpAccordion__title">
14
+ <cp-icon v-if="displayLeadingIcon" class="cpAccordion__icon" size="16" :type="dynamicIcon" />
15
+ <div class="cpAccordion__leading">
16
+ <span>{{ title }}</span>
17
+ <slot name="leading-slot" />
18
+ </div>
19
+ </div>
20
+ <div class="cpAccordion__trailing">
21
+ <slot name="trailing-slot" />
22
+ <cp-icon v-if="displayActionTrigger" class="cpAccordion__more" size="16" type="more-horizontal" />
23
+ <cp-icon v-if="displayTrailingIcon" class="cpAccordion__icon" size="16" :type="dynamicIcon" />
24
+ </div>
25
+ <cp-item-actions
26
+ v-if="hasActions"
27
+ :actions="resolvedActions"
28
+ class="cpAccordion__actions"
29
+ :quick-options-limit="resolvedQuickOptionsLimit"
30
+ />
31
+ </button>
32
+ <cp-transition-expand>
33
+ <div v-if="isToggled" :id="accordionContentId" :aria-labelledby="accordionId" class="cpAccordion__content">
34
+ <slot />
35
+ </div>
36
+ </cp-transition-expand>
37
+ </div>
38
+ </template>
39
+
40
+ <script setup lang="ts">
41
+ import { computed, ref, useId } from 'vue'
42
+
43
+ import type { MenuItem } from 'primevue/menuitem'
44
+
45
+ export interface CpAccordionBaseProps {
46
+ defaultOpenState?: boolean
47
+ quickOptionsLimit?: number
48
+ title: string
49
+ }
50
+
51
+ /**
52
+ * Leading (default): optional `actions` (`MenuItem[]`).
53
+ * Trailing: `actions` must not be passed (use `iconPosition: 'trailing'` only).
54
+ */
55
+ export type CpAccordionProps =
56
+ | (CpAccordionBaseProps & {
57
+ actions?: MenuItem[]
58
+ hideActionTrigger?: boolean
59
+ iconPosition?: 'leading'
60
+ })
61
+ | (CpAccordionBaseProps & {
62
+ iconPosition: 'trailing'
63
+ })
64
+
65
+ const props = defineProps<CpAccordionProps>()
66
+
67
+ const isToggled = ref(props.defaultOpenState)
68
+
69
+ const accordionId = useId()
70
+
71
+ const accordionContentId = computed(() => `${accordionId}-content`)
72
+
73
+ const resolvedIconPosition = computed(() => props.iconPosition || 'leading')
74
+
75
+ const resolvedQuickOptionsLimit = computed(() => props.quickOptionsLimit || 0)
76
+
77
+ const resolvedActions = computed<MenuItem[]>(() => {
78
+ if (props.iconPosition === 'trailing') return []
79
+ return props.actions || []
80
+ })
81
+
82
+ const resolvedHideActionTrigger = computed(() => {
83
+ if (props.iconPosition === 'trailing') return true
84
+ return props.hideActionTrigger
85
+ })
86
+
87
+ const hasActions = computed(() => resolvedActions.value.length > 0)
88
+ const hasLeadingIcon = computed(() => resolvedIconPosition.value === 'leading')
89
+ const hasTrailingIcon = computed(() => resolvedIconPosition.value === 'trailing')
90
+
91
+ const displayActionTrigger = computed(() => !resolvedHideActionTrigger.value && hasActions.value)
92
+ const displayLeadingIcon = computed(() => hasLeadingIcon.value || hasActions.value)
93
+ const displayTrailingIcon = computed(() => hasTrailingIcon.value && !hasActions.value)
94
+
95
+ const dynamicIcon = computed(() => (isToggled.value ? 'chevron-up' : 'chevron-down'))
96
+
97
+ const dynamicClasses = computed(() => [{ 'cpAccordion--isOpen': isToggled.value }])
98
+
99
+ const handleClick = () => (isToggled.value = !isToggled.value)
100
+ </script>
101
+
102
+ <style lang="scss">
103
+ .cpAccordion {
104
+ display: flex;
105
+ flex-direction: column;
106
+ background-color: var(--cp-background-primary);
107
+ width: 100%;
108
+
109
+ &__header {
110
+ @extend %u-focus-outline;
111
+
112
+ border-radius: var(--cp-radius-none);
113
+ display: flex;
114
+ align-items: center;
115
+ justify-content: space-between;
116
+ padding: var(--cp-spacing-lg);
117
+ gap: var(--cp-spacing-lg);
118
+ cursor: pointer;
119
+
120
+ &:hover {
121
+ background-color: var(--cp-background-primary-hover);
122
+ }
123
+ }
124
+
125
+ &__title {
126
+ display: flex;
127
+ align-items: center;
128
+ gap: var(--cp-spacing-lg);
129
+ font-weight: 500;
130
+ font-size: var(--cp-text-size-sm);
131
+ line-height: var(--cp-line-height-sm);
132
+ }
133
+
134
+ &__icon {
135
+ color: var(--cp-foreground-secondary);
136
+ flex-shrink: 0;
137
+ padding: var(--cp-spacing-xs);
138
+ }
139
+
140
+ &__leading {
141
+ display: flex;
142
+ flex-direction: column;
143
+ }
144
+
145
+ &__trailing {
146
+ display: flex;
147
+ align-items: center;
148
+ gap: var(--cp-spacing-lg);
149
+ position: relative;
150
+ }
151
+
152
+ &__actions {
153
+ background: linear-gradient(270deg, var(--cp-utility-neutral-100) 0%, rgba(242, 246, 250, 0) 100%);
154
+ padding: 0 var(--cp-spacing-md) 0 15%;
155
+ display: flex;
156
+ align-items: center;
157
+ }
158
+
159
+ &__more {
160
+ color: var(--cp-foreground-primary);
161
+ }
162
+ }
163
+ </style>
@@ -0,0 +1,51 @@
1
+ <template>
2
+ <div class="cpAccordionGroup" :class="groupClass">
3
+ <slot />
4
+ </div>
5
+ </template>
6
+
7
+ <script setup lang="ts">
8
+ import { computed } from 'vue'
9
+
10
+ import { capitalizeFirstLetter } from '@/helpers'
11
+
12
+ interface Props {
13
+ variant?: 'minimal' | 'default' | 'primary'
14
+ }
15
+
16
+ const props = withDefaults(defineProps<Props>(), {
17
+ variant: 'minimal',
18
+ })
19
+
20
+ const groupClass = computed(() => {
21
+ return { [`cpAccordionGroup--is${capitalizeFirstLetter(props.variant)}`]: true }
22
+ })
23
+ </script>
24
+
25
+ <style lang="scss">
26
+ .cpAccordionGroup {
27
+ display: flex;
28
+ flex-direction: column;
29
+ width: 100%;
30
+
31
+ &--isDefault {
32
+ .cpAccordion {
33
+ border-bottom: fn.px-to-rem(1) solid var(--cp-border-soft);
34
+ }
35
+
36
+ .cpAccordion:last-child {
37
+ border-bottom: none;
38
+ }
39
+ }
40
+
41
+ &--isPrimary {
42
+ border: fn.px-to-rem(1) solid var(--cp-border-soft);
43
+ border-radius: var(--cp-radius-md);
44
+ overflow: hidden;
45
+
46
+ .cpAccordion:not(:last-child) {
47
+ border-bottom: fn.px-to-rem(1) solid var(--cp-border-soft);
48
+ }
49
+ }
50
+ }
51
+ </style>
@@ -18,7 +18,7 @@
18
18
  <script setup lang="ts">
19
19
  import { computed } from 'vue'
20
20
 
21
- import { Colors, Sizes } from '@/constants'
21
+ import type { Colors, Sizes } from '@/constants'
22
22
  import { capitalizeFirstLetter } from '@/helpers'
23
23
 
24
24
  interface Emits {
@@ -41,7 +41,7 @@ interface Props {
41
41
 
42
42
  const props = withDefaults(defineProps<Props>(), {
43
43
  color: 'gray',
44
- size: Sizes.MD,
44
+ size: 'md',
45
45
  label: '',
46
46
  leadingIcon: '',
47
47
  trailingIcon: '',
@@ -36,10 +36,11 @@ import { Haptics } from '@/constants/Hapitcs'
36
36
 
37
37
  import CpLoader from '@/components/CpLoader.vue'
38
38
 
39
- import { Colors, Sizes } from '@/constants'
39
+ import type { Colors, Sizes } from '@/constants'
40
40
  import { capitalizeFirstLetter } from '@/helpers'
41
41
 
42
42
  type ButtonColor = Extract<Colors, 'neutral' | 'accent' | 'error' | 'warning' | 'success'>
43
+ type ButtonSizes = Extract<Sizes, '2xs' | 'xs' | 'sm' | 'md' | 'lg'>
43
44
 
44
45
  interface Props {
45
46
  appearance?: ButtonAppearances
@@ -48,7 +49,7 @@ interface Props {
48
49
  enableHaptics?: boolean
49
50
  isLoading?: boolean
50
51
  isSquare?: boolean
51
- size?: Exclude<Sizes, Sizes.XXL | Sizes.XXXL | Sizes.XXXXL>
52
+ size?: ButtonSizes
52
53
  tag?: ButtonTags
53
54
  type?: ButtonTypes
54
55
  }
@@ -58,7 +59,7 @@ const props = withDefaults(defineProps<Props>(), {
58
59
  color: 'neutral',
59
60
  tag: 'button',
60
61
  type: 'button',
61
- size: Sizes.MD,
62
+ size: 'md',
62
63
  })
63
64
 
64
65
  const slots = useSlots()
@@ -1,16 +1,44 @@
1
1
  <template>
2
- <div class="cpButtonGroup">
2
+ <div class="cpButtonGroup" :class="dynamicClasses">
3
3
  <slot />
4
4
  </div>
5
5
  </template>
6
6
 
7
+ <script setup lang="ts">
8
+ import { computed } from 'vue'
9
+
10
+ interface Props {
11
+ size?: '2xs' | 'xs' | 'sm' | 'md' | 'lg'
12
+ }
13
+
14
+ const props = withDefaults(defineProps<Props>(), {
15
+ size: 'md',
16
+ })
17
+
18
+ const dynamicClasses = computed(() => `cpButtonGroup--${props.size}`)
19
+ </script>
20
+
7
21
  <style lang="scss">
8
22
  .cpButtonGroup {
9
23
  display: flex;
10
24
  align-items: flex-start;
11
- border-radius: var(--cp-radius-sm);
25
+ border-radius: var(--cp-radius-md);
12
26
  box-shadow: 0 0 0 fn.px-to-rem(1) var(--cp-border-soft);
13
27
 
28
+ &--2xs {
29
+ border-radius: var(--cp-radius-sm-md);
30
+ }
31
+
32
+ &--xs,
33
+ &--sm,
34
+ &--md {
35
+ border-radius: var(--cp-radius-md);
36
+ }
37
+
38
+ &--lg {
39
+ border-radius: var(--cp-radius-md-lg);
40
+ }
41
+
14
42
  > * {
15
43
  position: relative;
16
44
 
@@ -45,9 +45,9 @@
45
45
  :required="required"
46
46
  />
47
47
  </div>
48
- <transition-expand>
48
+ <cp-transition-expand>
49
49
  <div v-if="advancedErrorMessage" class="cpDate__errorMessage">{{ advancedErrorMessage }}</div>
50
- </transition-expand>
50
+ </cp-transition-expand>
51
51
  </div>
52
52
  </template>
53
53
 
@@ -57,7 +57,8 @@ import { ref, computed, watch, useId } from 'vue'
57
57
 
58
58
  import BaseInputLabel from '@/components/BaseInputLabel.vue'
59
59
 
60
- import { HUMAN_MAX_AGE, Sizes } from '@/constants'
60
+ import { HUMAN_MAX_AGE } from '@/constants'
61
+ import type { Sizes } from '@/constants'
61
62
  import { capitalizeFirstLetter } from '@/helpers'
62
63
 
63
64
  interface Emits {
@@ -101,7 +102,7 @@ const props = withDefaults(defineProps<Props>(), {
101
102
  autocompleteBirthday: false,
102
103
  locale: () => navigator.language,
103
104
  inputsOptions: () => ({}),
104
- size: Sizes.MD,
105
+ size: 'md',
105
106
  })
106
107
 
107
108
  const emit = defineEmits<Emits>()
@@ -39,14 +39,14 @@
39
39
  </transition>
40
40
  </div>
41
41
  </div>
42
- <transition-expand mode="out-in">
42
+ <cp-transition-expand mode="out-in">
43
43
  <p v-if="displayErrorMessage" :id="errorMessageId" class="cpInput__error">
44
44
  {{ errorMessage }}
45
45
  </p>
46
46
  <p v-else-if="displayHelp" :id="helpMessageId" class="cpInput__help">
47
47
  {{ help }}
48
48
  </p>
49
- </transition-expand>
49
+ </cp-transition-expand>
50
50
  </div>
51
51
  </template>
52
52
 
@@ -55,7 +55,7 @@ import { ref, useAttrs, useSlots, computed, nextTick, onMounted, useId } from 'v
55
55
 
56
56
  import BaseInputLabel from '@/components/BaseInputLabel.vue'
57
57
 
58
- import { Sizes } from '@/constants'
58
+ import type { Sizes } from '@/constants'
59
59
  import { capitalizeFirstLetter } from '@/helpers'
60
60
 
61
61
  interface Emits {
@@ -83,7 +83,7 @@ const props = withDefaults(defineProps<Props>(), {
83
83
  inputId: null,
84
84
  mask: null,
85
85
  modelValue: '',
86
- size: Sizes.MD,
86
+ size: 'md',
87
87
  tooltip: '',
88
88
  })
89
89
 
@@ -12,8 +12,8 @@
12
12
  <cp-contextual-menu
13
13
  ref="contextualMenu"
14
14
  :items="actions"
15
- @hide="isDropdownOpen = false"
16
- @show="isDropdownOpen = true"
15
+ @hide="handleDropdownState(false)"
16
+ @show="handleDropdownState(true)"
17
17
  />
18
18
  </div>
19
19
  </template>
@@ -42,7 +42,7 @@ const isDropdownOpen = ref(false)
42
42
  const showContextualMenu = (event: MouseEvent) => contextualMenu.value?.show(event)
43
43
 
44
44
  const defaultAction = {
45
- icon: 'more-vertical',
45
+ icon: 'more-horizontal',
46
46
  command: (event: MouseEvent) => showContextualMenu(event),
47
47
  }
48
48
 
@@ -58,12 +58,14 @@ const slicedActions = computed(() => {
58
58
  const firstActions = actionsCopy.slice(0, props.quickOptionsLimit)
59
59
  return [...firstActions, defaultAction]
60
60
  })
61
+
62
+ const handleDropdownState = (state: boolean) => (isDropdownOpen.value = state)
61
63
  </script>
62
64
 
63
65
  <style lang="scss">
64
66
  .cpItemActions {
65
67
  position: absolute;
66
- right: var(--cp-spacing-lg);
68
+ right: 0;
67
69
  top: 50%;
68
70
  transform: translate3d(calc(var(--cp-dimensions-1) * 1.25), -50%, 0);
69
71
  transition:
@@ -78,18 +80,18 @@ const slicedActions = computed(() => {
78
80
  padding: 0;
79
81
 
80
82
  &:first-child .cpMenuItem__button {
81
- border-top-left-radius: var(--cp-radius-sm);
82
- border-bottom-left-radius: var(--cp-radius-sm);
83
+ border-top-left-radius: var(--cp-radius-md);
84
+ border-bottom-left-radius: var(--cp-radius-md);
83
85
  }
84
86
  &:last-child .cpMenuItem__button {
85
- border-top-right-radius: var(--cp-radius-sm);
86
- border-bottom-right-radius: var(--cp-radius-sm);
87
+ border-top-right-radius: var(--cp-radius-md);
88
+ border-bottom-right-radius: var(--cp-radius-md);
87
89
  }
88
90
  }
89
91
 
90
92
  .cpMenuItem__button {
91
93
  border-radius: 0;
92
- padding: var(--cp-spacing-xs) var(--cp-spacing-sm);
94
+ padding: var(--cp-spacing-sm-md);
93
95
  }
94
96
  }
95
97
 
@@ -86,11 +86,11 @@
86
86
  />
87
87
  </template>
88
88
  </auto-complete>
89
- <transition-expand mode="out-in">
89
+ <cp-transition-expand mode="out-in">
90
90
  <p v-if="isInvalid" class="cpMultiselect__error">
91
91
  {{ errorMessage }}
92
92
  </p>
93
- </transition-expand>
93
+ </cp-transition-expand>
94
94
  </div>
95
95
  </template>
96
96
 
@@ -101,7 +101,7 @@ import { ref, computed, onMounted, useSlots, useId } from 'vue'
101
101
 
102
102
  import BaseInputLabel from '@/components/BaseInputLabel.vue'
103
103
  import BaseSelectClearButton from '@/components/BaseSelectClearButton.vue'
104
- import TransitionExpand from '@/components/TransitionExpand.vue'
104
+ import CpTransitionExpand from '@/components/CpTransitionExpand.vue'
105
105
 
106
106
  import { isEmpty } from '@/helpers/object'
107
107
 
@@ -14,7 +14,8 @@ import IconOta from '@/components/icons/IconOta.vue'
14
14
  import IconSupplier from '@/components/icons/IconSupplier.vue'
15
15
  import IconThirdParty from '@/components/icons/IconThirdParty.vue'
16
16
 
17
- import { PartnerTypes, Sizes } from '@/constants'
17
+ import { PartnerTypes } from '@/constants'
18
+ import type { Sizes } from '@/constants'
18
19
 
19
20
  interface Props {
20
21
  size?: Sizes
@@ -22,7 +23,7 @@ interface Props {
22
23
  }
23
24
 
24
25
  const props = withDefaults(defineProps<Props>(), {
25
- size: Sizes.MD,
26
+ size: 'md',
26
27
  type: PartnerTypes.THIRDPARTY,
27
28
  })
28
29
 
@@ -25,14 +25,14 @@
25
25
  <option v-for="(option, index) in options" :key="index" :value="option.value">{{ option.label }}</option>
26
26
  </select>
27
27
  </div>
28
- <transition-expand mode="out-in">
28
+ <cp-transition-expand mode="out-in">
29
29
  <p v-if="displayErrorMessage" :id="errorMessageId" class="cpSelect__error">
30
30
  {{ errorMessage }}
31
31
  </p>
32
32
  <p v-else-if="displayHelp" :id="helpMessageId" class="cpSelect__help">
33
33
  {{ help }}
34
34
  </p>
35
- </transition-expand>
35
+ </cp-transition-expand>
36
36
  </div>
37
37
  </template>
38
38
 
@@ -40,9 +40,9 @@
40
40
  import { computed, useId } from 'vue'
41
41
 
42
42
  import BaseInputLabel from '@/components/BaseInputLabel.vue'
43
- import TransitionExpand from '@/components/TransitionExpand.vue'
43
+ import CpTransitionExpand from '@/components/CpTransitionExpand.vue'
44
44
 
45
- import { Sizes } from '@/constants'
45
+ import type { Sizes } from '@/constants'
46
46
  import { capitalizeFirstLetter } from '@/helpers'
47
47
 
48
48
  interface Emits {
@@ -82,7 +82,7 @@ const props = withDefaults(defineProps<Props>(), {
82
82
  autocomplete: 'on',
83
83
  isInvalid: false,
84
84
  errorMessage: '',
85
- size: Sizes.MD,
85
+ size: 'md',
86
86
  help: '',
87
87
  tooltip: '',
88
88
  })
@@ -809,7 +809,7 @@ defineExpose({ hideContextualMenu, resetPagination, currentRowData })
809
809
 
810
810
  &--isOptions .cpTable__action {
811
811
  display: none;
812
- padding: var(--cp-dimensions-1_5) var(--cp-spacing-md);
812
+ padding: var(--cp-spacing-sm-md) var(--cp-spacing-md);
813
813
  border: none;
814
814
  border-radius: 0;
815
815
  color: var(--cp-foreground-primary);
@@ -1021,7 +1021,7 @@ defineExpose({ hideContextualMenu, resetPagination, currentRowData })
1021
1021
  box-shadow: var(--cp-shadows-3xs);
1022
1022
  border-radius: var(--cp-radius-md-lg);
1023
1023
  border: var(--cp-dimensions-0_25) solid var(--cp-border-soft);
1024
- padding: var(--cp-dimensions-1_5) var(--cp-dimensions-2_5);
1024
+ padding: var(--cp-spacing-sm-md) var(--cp-dimensions-2_5);
1025
1025
  transition: background-color 0.15s;
1026
1026
  background-color: var(--cp-background-primary);
1027
1027
 
@@ -28,14 +28,14 @@
28
28
  </template>
29
29
  </vue-tel-input>
30
30
  </div>
31
- <transition-expand mode="out-in">
31
+ <cp-transition-expand mode="out-in">
32
32
  <p v-if="displayErrorMessage" :id="errorMessageId" class="cpTelInput__error">
33
33
  {{ errorMessage }}
34
34
  </p>
35
35
  <p v-else-if="displayHelp" :id="helpMessageId" class="cpTelInput__help">
36
36
  {{ help }}
37
37
  </p>
38
- </transition-expand>
38
+ </cp-transition-expand>
39
39
  </div>
40
40
  </template>
41
41
 
@@ -44,7 +44,7 @@ import { useAttrs, ref, useId, computed, nextTick } from 'vue'
44
44
 
45
45
  import BaseInputLabel from '@/components/BaseInputLabel.vue'
46
46
 
47
- import { Sizes } from '@/constants'
47
+ import type { Sizes } from '@/constants'
48
48
  import { capitalizeFirstLetter } from '@/helpers'
49
49
 
50
50
  interface Props {
@@ -74,7 +74,7 @@ const props = withDefaults(defineProps<Props>(), {
74
74
  tooltip: '',
75
75
  name: '',
76
76
  hideSearch: false,
77
- size: Sizes.MD,
77
+ size: 'md',
78
78
  })
79
79
 
80
80
  const emit = defineEmits<Emits>()
@@ -19,11 +19,11 @@
19
19
  :required="required"
20
20
  :style="`min-height: ${height}px`"
21
21
  />
22
- <transition-expand>
22
+ <cp-transition-expand>
23
23
  <p v-if="displayErrorMessage" class="cpTextarea__error">
24
24
  {{ errorMessage }}
25
25
  </p>
26
- </transition-expand>
26
+ </cp-transition-expand>
27
27
  </div>
28
28
  </template>
29
29
 
@@ -31,7 +31,7 @@
31
31
  import { ref, computed, useId } from 'vue'
32
32
 
33
33
  import BaseInputLabel from '@/components/BaseInputLabel.vue'
34
- import TransitionExpand from '@/components/TransitionExpand.vue'
34
+ import CpTransitionExpand from '@/components/CpTransitionExpand.vue'
35
35
 
36
36
  import { capitalizeFirstLetter } from '@/helpers'
37
37
 
@@ -0,0 +1,77 @@
1
+ <template>
2
+ <div class="cpTransitionCounter">
3
+ <transition :duration="duration" mode="out-in" :name="formattedTransitionName">
4
+ <span :key="counterNumber">
5
+ <slot />
6
+ </span>
7
+ </transition>
8
+ </div>
9
+ </template>
10
+
11
+ <script setup lang="ts">
12
+ import { ref, computed, watch } from 'vue'
13
+
14
+ interface Props {
15
+ counterNumber?: number
16
+ duration?: number
17
+ }
18
+
19
+ const props = withDefaults(defineProps<Props>(), {
20
+ counterNumber: 0,
21
+ duration: 300,
22
+ })
23
+
24
+ enum Directions {
25
+ UP = 'up',
26
+ DOWN = 'down',
27
+ }
28
+
29
+ const direction = ref<Directions>(Directions.UP)
30
+
31
+ const formattedTransitionName = computed(() => `counter-${direction.value}`)
32
+
33
+ watch(
34
+ () => props.counterNumber,
35
+ (newValue: number, oldValue: number) => {
36
+ direction.value = newValue < oldValue ? Directions.DOWN : Directions.UP
37
+ },
38
+ )
39
+ </script>
40
+
41
+ <style lang="scss">
42
+ .cpTransitionCounter {
43
+ display: inline-flex;
44
+ overflow: hidden;
45
+
46
+ &-up-enter-from {
47
+ transform: translate3d(0, 100%, 0);
48
+ }
49
+
50
+ &-down-enter-from {
51
+ transform: translate3d(0, -100%, 0);
52
+ }
53
+
54
+ &-up-leave-to,
55
+ &-down-leave-to {
56
+ filter: blur(1px);
57
+ opacity: 0;
58
+ }
59
+
60
+ &-up-leave-to {
61
+ transform: translate3d(0, -100%, 0) skewY(-30deg);
62
+ }
63
+
64
+ &-down-leave-to {
65
+ transform: translate3d(0, 100%, 0) skewY(30deg);
66
+ }
67
+
68
+ &-up-enter-active,
69
+ &-down-enter-active,
70
+ &-up-leave-active,
71
+ &-down-leave-active {
72
+ transition:
73
+ transform 200ms ease,
74
+ opacity 200ms ease;
75
+ }
76
+ }
77
+ </style>