@citizenplane/pimp 18.12.2 → 18.12.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 (35) hide show
  1. package/README.md +8 -0
  2. package/biome.json +10 -0
  3. package/dist/components/CpMultiselect.vue.d.ts.map +1 -1
  4. package/dist/components/CpTabs.vue.d.ts.map +1 -1
  5. package/dist/components/CpTransitionCounter.vue.d.ts.map +1 -1
  6. package/dist/components/CpTransitionExpand.vue.d.ts.map +1 -1
  7. package/dist/components/CpTransitionSize.vue.d.ts.map +1 -1
  8. package/dist/components/CpTransitionTabContent.vue.d.ts.map +1 -1
  9. package/dist/components/icons/IconBank.vue.d.ts +3 -0
  10. package/dist/components/icons/IconBank.vue.d.ts.map +1 -0
  11. package/dist/components/index.d.ts +2 -1
  12. package/dist/components/index.d.ts.map +1 -1
  13. package/dist/composables/useReducedMotion.d.ts +2 -0
  14. package/dist/composables/useReducedMotion.d.ts.map +1 -0
  15. package/dist/constants/CpCustomIcons.d.ts +1 -0
  16. package/dist/constants/CpCustomIcons.d.ts.map +1 -1
  17. package/dist/constants/index.d.ts +1 -0
  18. package/dist/constants/index.d.ts.map +1 -1
  19. package/dist/pimp.es.js +3293 -3263
  20. package/dist/pimp.umd.js +30 -30
  21. package/dist/style.css +1 -1
  22. package/package.json +1 -1
  23. package/src/assets/css/reduced-motion.css +73 -0
  24. package/src/assets/main.css +1 -0
  25. package/src/components/CpMultiselect.vue +1 -0
  26. package/src/components/CpTabs.vue +4 -1
  27. package/src/components/CpTransitionCounter.vue +6 -1
  28. package/src/components/CpTransitionExpand.vue +16 -0
  29. package/src/components/CpTransitionSize.vue +23 -8
  30. package/src/components/CpTransitionTabContent.vue +8 -1
  31. package/src/components/icons/IconBank.vue +5 -0
  32. package/src/components/index.ts +2 -0
  33. package/src/composables/useReducedMotion.ts +13 -0
  34. package/src/constants/CpCustomIcons.ts +2 -0
  35. package/src/constants/index.ts +2 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@citizenplane/pimp",
3
- "version": "18.12.2",
3
+ "version": "18.12.4",
4
4
  "scripts": {
5
5
  "dev": "storybook dev -p 8081",
6
6
  "build-storybook": "storybook build --output-dir ./docs",
@@ -0,0 +1,73 @@
1
+ @media (prefers-reduced-motion: reduce) {
2
+ *,
3
+ *::before,
4
+ *::after {
5
+ scroll-behavior: auto !important;
6
+ transition-delay: 0ms !important;
7
+ transition-duration: 1ms !important;
8
+ }
9
+
10
+ [class$="-enter-from"],
11
+ [class*="-enter-from "],
12
+ [class$="-leave-to"],
13
+ [class*="-leave-to "] {
14
+ transform: none !important;
15
+ }
16
+
17
+ :where([class$="-enter-from"], [class*="-enter-from "], [class$="-leave-to"], [class*="-leave-to "]) {
18
+ rotate: none !important;
19
+ scale: 1 !important;
20
+ translate: none !important;
21
+ }
22
+
23
+ [class$="-enter-active"],
24
+ [class*="-enter-active "],
25
+ [class$="-leave-active"],
26
+ [class*="-leave-active "] {
27
+ transition: opacity 120ms linear !important;
28
+ }
29
+
30
+ .dialog-enter-from dialog main,
31
+ .dialog-leave-to dialog main {
32
+ transform: none !important;
33
+ }
34
+
35
+ .cpDialog__container,
36
+ .cpDialog__overlay,
37
+ .cpMenu__menuContent,
38
+ .cpTable__overlay,
39
+ .v-popper__wrapper {
40
+ transition: opacity 120ms linear !important;
41
+ }
42
+
43
+ .v-popper__popper--hidden .v-popper__wrapper {
44
+ scale: 1 !important;
45
+ }
46
+
47
+ .drawer-enter-from,
48
+ .drawer-leave-to {
49
+ opacity: 0 !important;
50
+ }
51
+
52
+ .counter-up-enter-active,
53
+ .counter-up-leave-active,
54
+ .counter-down-enter-active,
55
+ .counter-down-leave-active,
56
+ .expand-enter-active,
57
+ .expand-leave-active {
58
+ transition: none !important;
59
+ }
60
+
61
+ .counter-up-leave-to,
62
+ .counter-down-leave-to {
63
+ filter: none !important;
64
+ }
65
+
66
+ :not([data-motion="essential"], [data-motion="essential"] *),
67
+ :not([data-motion="essential"], [data-motion="essential"] *)::before,
68
+ :not([data-motion="essential"], [data-motion="essential"] *)::after {
69
+ animation-delay: 0ms !important;
70
+ animation-duration: 1ms !important;
71
+ animation-iteration-count: 1 !important;
72
+ }
73
+ }
@@ -6,3 +6,4 @@
6
6
  @import "./css/easings.css";
7
7
  @import "./css/transitions.css";
8
8
  @import "./css/tokens.css";
9
+ @import "./css/reduced-motion.css";
@@ -347,6 +347,7 @@ onMounted(() => overrideAlignOverlay())
347
347
  justify-content: space-between;
348
348
  padding: var(--cp-spacing-md);
349
349
  border-radius: var(--cp-radius-md);
350
+ background-color: var(--cp-background-primary);
350
351
  box-shadow:
351
352
  var(--cp-shadows-3xs-inset),
352
353
  0 0 0 var(--cp-dimensions-0_25) var(--cp-border-soft);
@@ -30,6 +30,8 @@
30
30
  <script setup lang="ts">
31
31
  import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
32
32
 
33
+ import { useReducedMotion } from '@/composables/useReducedMotion'
34
+
33
35
  import CpText from '@/components/CpText.vue'
34
36
 
35
37
  import { capitalizeFirstLetter } from '@/helpers'
@@ -64,6 +66,7 @@ const cpTabsElement = ref<HTMLElement | null>(null)
64
66
  const activeUnderline = ref<HTMLElement | null>(null)
65
67
  const activeTabIndex = ref<number | null>(props.defaultActiveIndex)
66
68
  const suppressUnderlineTransition = ref(false)
69
+ const prefersReducedMotion = useReducedMotion()
67
70
 
68
71
  const textSize = computed(() => {
69
72
  switch (props.size) {
@@ -204,7 +207,7 @@ const scrollToActiveElement = (behavior: ScrollBehavior = 'smooth') => {
204
207
  const activeTabElement = getActiveTabElement()
205
208
  if (!activeTabElement) return
206
209
 
207
- return activeTabElement.scrollIntoView({ block: 'nearest', behavior })
210
+ return activeTabElement.scrollIntoView({ block: 'nearest', behavior: prefersReducedMotion.value ? 'instant' : behavior })
208
211
  }
209
212
 
210
213
  onBeforeUnmount(() => window.removeEventListener('resize', setUnderlineStyle))
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div class="cpTransitionCounter">
3
- <transition :duration="duration" mode="out-in" :name="formattedTransitionName">
3
+ <transition :duration="resolvedDuration" mode="out-in" :name="formattedTransitionName">
4
4
  <span :key="counterNumber">
5
5
  <slot />
6
6
  </span>
@@ -11,6 +11,8 @@
11
11
  <script setup lang="ts">
12
12
  import { computed, ref, watch } from 'vue'
13
13
 
14
+ import { useReducedMotion } from '@/composables/useReducedMotion'
15
+
14
16
  interface Props {
15
17
  counterNumber?: number
16
18
  duration?: number
@@ -30,6 +32,9 @@ const direction = ref<Directions>(Directions.UP)
30
32
 
31
33
  const formattedTransitionName = computed(() => `counter-${direction.value}`)
32
34
 
35
+ const prefersReducedMotion = useReducedMotion()
36
+ const resolvedDuration = computed(() => (prefersReducedMotion.value ? 0 : props.duration))
37
+
33
38
  watch(
34
39
  () => props.counterNumber,
35
40
  (newValue: number, oldValue: number) => {
@@ -5,6 +5,10 @@
5
5
  </template>
6
6
 
7
7
  <script setup lang="ts">
8
+ import { useReducedMotion } from '@/composables/useReducedMotion'
9
+
10
+ const prefersReducedMotion = useReducedMotion()
11
+
8
12
  const afterEnter = (element: Element) => {
9
13
  const el = element as HTMLElement
10
14
  el.style.height = `auto`
@@ -12,6 +16,12 @@ const afterEnter = (element: Element) => {
12
16
 
13
17
  const enter = (element: Element) => {
14
18
  const el = element as HTMLElement
19
+
20
+ if (prefersReducedMotion.value) {
21
+ el.style.height = 'auto'
22
+ return
23
+ }
24
+
15
25
  const { width } = getComputedStyle(el)
16
26
 
17
27
  el.style.width = width
@@ -37,6 +47,12 @@ const enter = (element: Element) => {
37
47
 
38
48
  const leave = (element: Element): void => {
39
49
  const el = element as HTMLElement
50
+
51
+ if (prefersReducedMotion.value) {
52
+ el.style.height = '0'
53
+ return
54
+ }
55
+
40
56
  const { height } = getComputedStyle(el)
41
57
 
42
58
  el.style.height = height
@@ -5,7 +5,9 @@
5
5
  </template>
6
6
 
7
7
  <script setup lang="ts">
8
- import { computed, nextTick, onBeforeUnmount, onMounted, ref, useId } from 'vue'
8
+ import { computed, nextTick, onBeforeUnmount, onMounted, ref, useId, watch } from 'vue'
9
+
10
+ import { useReducedMotion } from '@/composables/useReducedMotion'
9
11
 
10
12
  interface Props {
11
13
  type?: 'width' | 'height'
@@ -13,6 +15,8 @@ interface Props {
13
15
 
14
16
  const props = withDefaults(defineProps<Props>(), { type: 'width' })
15
17
 
18
+ const prefersReducedMotion = useReducedMotion()
19
+
16
20
  const slotWrapper = ref()
17
21
  const slotContent = computed<HTMLElement | null>(() => slotWrapper.value?.children[0])
18
22
 
@@ -52,22 +56,33 @@ const updateWrapperSize = async () => {
52
56
 
53
57
  const observer = ref<MutationObserver>()
54
58
 
55
- const initObserver = () => {
59
+ const startObserving = () => {
60
+ if (!slotContent.value || observer.value) return
61
+
56
62
  observer.value = new MutationObserver(updateWrapperSize)
57
63
  observer.value.observe(slotContent.value as HTMLElement, { childList: true, subtree: false })
58
64
 
59
65
  updateWrapperSize()
60
66
  }
61
67
 
68
+ const stopObserving = () => {
69
+ observer.value?.disconnect()
70
+ observer.value = undefined
71
+
72
+ if (!slotWrapper.value) return
73
+
74
+ slotWrapper.value.style.width = ''
75
+ slotWrapper.value.style.height = ''
76
+ slotWrapper.value.style.minHeight = ''
77
+ }
78
+
79
+ watch(prefersReducedMotion, (isReduced) => (isReduced ? stopObserving() : startObserving()))
80
+
62
81
  onMounted(() => {
63
- if (slotContent.value) {
64
- initObserver()
65
- }
82
+ if (!prefersReducedMotion.value) startObserving()
66
83
  })
67
84
 
68
- onBeforeUnmount(() => {
69
- if (observer.value) observer.value.disconnect()
70
- })
85
+ onBeforeUnmount(() => observer.value?.disconnect())
71
86
  </script>
72
87
 
73
88
  <style lang="scss">
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <transition :duration="duration" mode="out-in" :name="formattedTransitionName" @after-enter="emit('onAfterEnter')">
2
+ <transition :duration="resolvedDuration" mode="out-in" :name="formattedTransitionName" @after-enter="emit('onAfterEnter')">
3
3
  <slot />
4
4
  </transition>
5
5
  </template>
@@ -7,6 +7,10 @@
7
7
  <script setup lang="ts">
8
8
  import { computed } from 'vue'
9
9
 
10
+ import { useReducedMotion } from '@/composables/useReducedMotion'
11
+
12
+ import { REDUCED_MOTION_FADE_MS } from '@/constants'
13
+
10
14
  type Direction = 'forward' | 'backward'
11
15
 
12
16
  type EmitType = {
@@ -26,6 +30,9 @@ const props = withDefaults(defineProps<Props>(), {
26
30
  const emit = defineEmits<EmitType>()
27
31
 
28
32
  const formattedTransitionName = computed(() => `tab-content-${props.direction}`)
33
+
34
+ const prefersReducedMotion = useReducedMotion()
35
+ const resolvedDuration = computed(() => (prefersReducedMotion.value ? REDUCED_MOTION_FADE_MS : props.duration))
29
36
  </script>
30
37
 
31
38
  <style lang="scss">
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <svg xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" width="24" height="24" viewBox="0 0 24 24" fill="currentColor">
3
+ <path d="M11.3389 2.36384C11.6929 2.05223 12.2131 2.0327 12.5879 2.30525L12.6602 2.36384L21.4629 10.1119L20.8027 10.8609V10.8629L21.4629 10.1119C21.7752 10.3867 21.885 10.8262 21.7383 11.2154C21.5914 11.6046 21.2187 11.8627 20.8027 11.8629H20.208V19.6871H20.8027C21.3548 19.6873 21.8026 20.135 21.8027 20.6871C21.8027 21.2392 21.3548 21.6869 20.8027 21.6871H3.19727C2.64509 21.687 2.19731 21.2393 2.19727 20.6871C2.19736 20.1349 2.64512 19.6872 3.19727 19.6871H4.0127V11.8629H3.19727C2.78126 11.8628 2.40861 11.6046 2.26172 11.2154C2.11501 10.8263 2.22413 10.3867 2.53613 10.1119L11.3389 2.36384ZM6.0127 19.6871H8.74414V11.8629H6.0127V19.6871ZM10.7441 19.6871H13.4766V11.8629H10.7441V19.6871ZM15.4766 19.6871H18.208V11.8629H15.4766V19.6871ZM5.84668 9.86286H18.1533L11.999 4.44685L5.84668 9.86286Z" />
4
+ </svg>
5
+ </template>
@@ -13,6 +13,7 @@ import type { App, Plugin } from 'vue'
13
13
  import { BindOnceDirective } from 'vue-bind-once'
14
14
  import VueTelInput from 'vue-tel-input'
15
15
 
16
+ import { useReducedMotion } from '../composables/useReducedMotion'
16
17
  import ClickOutside from '../directives/ClickOutside'
17
18
  import CpCoreDatepicker from '../libs/CoreDatepicker.vue'
18
19
  import CpAccordion from './CpAccordion.vue'
@@ -265,6 +266,7 @@ export {
265
266
  IconSupplier,
266
267
  IconThirdParty,
267
268
  IconTooltip,
269
+ useReducedMotion,
268
270
  }
269
271
 
270
272
  export default Pimp
@@ -0,0 +1,13 @@
1
+ import { usePreferredReducedMotion } from '@vueuse/core'
2
+ import { computed, getCurrentInstance, onMounted, ref } from 'vue'
3
+
4
+ export const useReducedMotion = () => {
5
+ const preference = usePreferredReducedMotion()
6
+
7
+ const isMounted = ref(!getCurrentInstance())
8
+ if (!isMounted.value) {
9
+ onMounted(() => (isMounted.value = true))
10
+ }
11
+
12
+ return computed(() => isMounted.value && preference.value === 'reduce')
13
+ }
@@ -18,6 +18,7 @@ import IconBaggageCheckedNone from '@/components/icons/IconBaggageCheckedNone.vu
18
18
  import IconBaggagePersonalNone from '@/components/icons/IconBaggagePersonalNone.vue'
19
19
  import IconBaggageSet from '@/components/icons/IconBaggageSet.vue'
20
20
  import IconBaggageSetPlus from '@/components/icons/IconBaggageSetPlus.vue'
21
+ import IconBank from '@/components/icons/IconBank.vue'
21
22
  import IconBomb from '@/components/icons/IconBomb.vue'
22
23
  import IconBottle from '@/components/icons/IconBottle.vue'
23
24
  import IconBroadcast from '@/components/icons/IconBroadcast.vue'
@@ -155,6 +156,7 @@ export const CustomCpIcons = {
155
156
  'baggage-set': IconBaggageSet,
156
157
  'baggage-battery': IconBaggageBattery,
157
158
  'baggage-set-plus': IconBaggageSetPlus,
159
+ bank: IconBank,
158
160
  'car-battery': IconCarBattery,
159
161
  bomb: IconBomb,
160
162
  bottle: IconBottle,
@@ -8,3 +8,5 @@ export { Intent } from './Intent'
8
8
  export { Position } from './Position'
9
9
 
10
10
  export const HUMAN_MAX_AGE = 120
11
+
12
+ export const REDUCED_MOTION_FADE_MS = 120