@citizenplane/pimp 18.8.0 → 18.8.2
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/CpMenu.vue.d.ts +2 -2
- package/dist/components/CpMenu.vue.d.ts.map +1 -1
- package/dist/components/icons/IconDestination.vue.d.ts +3 -0
- package/dist/components/icons/IconDestination.vue.d.ts.map +1 -0
- package/dist/components/icons/IconOrigin.vue.d.ts +3 -0
- package/dist/components/icons/IconOrigin.vue.d.ts.map +1 -0
- package/dist/composables/useIsBreakpoint.d.ts +3 -0
- package/dist/composables/useIsBreakpoint.d.ts.map +1 -0
- package/dist/constants/CpCustomIcons.d.ts +2 -0
- package/dist/constants/CpCustomIcons.d.ts.map +1 -1
- package/dist/pimp.es.js +4025 -3992
- package/dist/pimp.umd.js +51 -51
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/assets/css/easings.css +1 -0
- package/src/assets/css/transitions.css +34 -0
- package/src/assets/main.css +1 -0
- package/src/components/CpMenu.vue +28 -46
- package/src/components/icons/IconDestination.vue +5 -0
- package/src/components/icons/IconOrigin.vue +5 -0
- package/src/composables/useIsBreakpoint.ts +16 -0
- package/src/constants/CpCustomIcons.ts +4 -0
- package/src/stories/CpMenu.stories.ts +6 -3
package/package.json
CHANGED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/* Transitions classes that are globally used */
|
|
2
|
+
|
|
3
|
+
.scale-elastic-enter-active,
|
|
4
|
+
.scale-elastic-leave-active {
|
|
5
|
+
transition:
|
|
6
|
+
scale 200ms var(--cp-easing-elastic),
|
|
7
|
+
opacity 200ms ease;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.scale-elastic-enter-from,
|
|
11
|
+
.scale-elastic-leave-to {
|
|
12
|
+
opacity: 0;
|
|
13
|
+
scale: 0.9;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.drawer-enter-active,
|
|
17
|
+
.drawer-leave-active {
|
|
18
|
+
transition: transform 500ms var(--cp-easing-ease-out-quart);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.drawer-enter-from,
|
|
22
|
+
.drawer-leave-to {
|
|
23
|
+
transform: translate3d(0, 100%, 0);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.fade-enter-active,
|
|
27
|
+
.fade-leave-active {
|
|
28
|
+
transition: opacity 300ms ease;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.fade-enter-from,
|
|
32
|
+
.fade-leave-to {
|
|
33
|
+
opacity: 0;
|
|
34
|
+
}
|
package/src/assets/main.css
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="cpMenu">
|
|
3
|
+
<div v-if="isDrawer" class="cpMenu__drawerOverlay" :class="drawerOverlayDynamicClass" />
|
|
3
4
|
<div
|
|
4
5
|
ref="trigger"
|
|
5
6
|
:aria-controls="menuId"
|
|
@@ -62,25 +63,28 @@
|
|
|
62
63
|
import PrimevueDrawer from 'primevue/drawer'
|
|
63
64
|
import type { MenuItem } from 'primevue/menuitem'
|
|
64
65
|
import PrimevuePopover from 'primevue/popover'
|
|
65
|
-
import { computed, nextTick,
|
|
66
|
+
import { computed, nextTick, ref, useId } from 'vue'
|
|
67
|
+
|
|
68
|
+
import { useIsBreakpoint } from '@/composables/useIsBreakpoint'
|
|
66
69
|
|
|
67
70
|
import CpButton from '@/components/CpButton.vue'
|
|
68
71
|
import CpIcon from '@/components/CpIcon.vue'
|
|
69
72
|
import CpMenuList from '@/components/CpMenuList.vue'
|
|
70
73
|
|
|
74
|
+
import { Breakpoints } from '@/constants/layout'
|
|
71
75
|
import { getKeyboardFocusableElements } from '@/helpers/dom'
|
|
72
76
|
|
|
73
77
|
export interface Props {
|
|
74
78
|
class?: string
|
|
75
79
|
forcePopover?: boolean
|
|
76
|
-
|
|
80
|
+
isFullHeightDrawer?: boolean
|
|
77
81
|
items?: MenuItem[]
|
|
78
82
|
keepOpenOnClick?: boolean
|
|
79
83
|
}
|
|
80
84
|
|
|
81
85
|
const props = withDefaults(defineProps<Props>(), {
|
|
82
86
|
class: undefined,
|
|
83
|
-
|
|
87
|
+
isFullHeightDrawer: false,
|
|
84
88
|
items: undefined,
|
|
85
89
|
keepOpenOnClick: false,
|
|
86
90
|
})
|
|
@@ -90,37 +94,33 @@ const emits = defineEmits<{
|
|
|
90
94
|
show: []
|
|
91
95
|
}>()
|
|
92
96
|
|
|
93
|
-
const MOBILE_BREAKPOINT_PX = 640
|
|
94
|
-
|
|
95
97
|
const trigger = ref<HTMLElement | null>(null)
|
|
96
98
|
const popover = ref<InstanceType<typeof PrimevuePopover>>()
|
|
97
99
|
const closeButton = ref<InstanceType<typeof CpButton> | null>(null)
|
|
98
100
|
const isOpen = ref(false)
|
|
99
101
|
const menuId = useId()
|
|
100
102
|
|
|
101
|
-
const
|
|
102
|
-
const isMobileViewport = ref(mediaQuery.matches)
|
|
103
|
-
const onMediaChange = (event: MediaQueryListEvent) => {
|
|
104
|
-
isMobileViewport.value = event.matches
|
|
105
|
-
}
|
|
106
|
-
mediaQuery.addEventListener('change', onMediaChange)
|
|
107
|
-
onUnmounted(() => mediaQuery.removeEventListener('change', onMediaChange))
|
|
103
|
+
const isMobileViewport = useIsBreakpoint(Breakpoints.TABLET)
|
|
108
104
|
|
|
109
105
|
const isDrawer = computed(() => isMobileViewport.value && !props.forcePopover)
|
|
110
106
|
const hasItems = computed(() => props.items?.length)
|
|
111
107
|
const popupType = computed(() => (hasItems.value ? 'menu' : 'dialog'))
|
|
112
108
|
|
|
113
109
|
const popoverPt = {
|
|
114
|
-
root: { class: ['
|
|
115
|
-
content: { class: '
|
|
110
|
+
root: { class: ['cpMenu__menu', props.class] },
|
|
111
|
+
content: { class: 'cpMenu__menuContent' },
|
|
116
112
|
transition: { name: 'scale-elastic', duration: 100 },
|
|
117
113
|
}
|
|
118
114
|
|
|
115
|
+
const drawerOverlayDynamicClass = computed(() => ({
|
|
116
|
+
'cpMenu__drawerOverlay--isOpen': isOpen.value,
|
|
117
|
+
}))
|
|
118
|
+
|
|
119
119
|
const drawerPt = {
|
|
120
|
-
root: { class: ['cpMenu__drawer', { 'cpMenu__drawer--
|
|
120
|
+
root: { class: ['cpMenu__drawer', { 'cpMenu__drawer--isFullHeight': props.isFullHeightDrawer }] },
|
|
121
121
|
content: { class: 'cpMenu__drawerContent' },
|
|
122
|
-
mask: { class: 'cpMenu__drawerMask' },
|
|
123
122
|
header: { class: 'cpMenu__drawerHeader' },
|
|
123
|
+
transition: { name: 'drawer', duration: 300 },
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
const show = (event: Event) => {
|
|
@@ -171,7 +171,7 @@ defineExpose({ show, hide, toggle })
|
|
|
171
171
|
cursor: pointer;
|
|
172
172
|
}
|
|
173
173
|
|
|
174
|
-
&
|
|
174
|
+
&__menu {
|
|
175
175
|
position: absolute;
|
|
176
176
|
min-width: calc(var(--cp-dimensions-1) * 62.5);
|
|
177
177
|
border-radius: var(--cp-radius-md);
|
|
@@ -182,18 +182,25 @@ defineExpose({ show, hide, toggle })
|
|
|
182
182
|
will-change: opacity, transform;
|
|
183
183
|
}
|
|
184
184
|
|
|
185
|
-
&
|
|
185
|
+
&__menuContent {
|
|
186
186
|
padding: var(--cp-spacing-sm) 0;
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
-
&
|
|
189
|
+
&__drawerOverlay {
|
|
190
190
|
position: fixed;
|
|
191
|
-
z-index:
|
|
191
|
+
z-index: 0;
|
|
192
192
|
display: flex;
|
|
193
193
|
align-items: flex-end;
|
|
194
194
|
justify-content: center;
|
|
195
195
|
background-color: var(--cp-background-overlay);
|
|
196
196
|
inset: 0;
|
|
197
|
+
opacity: 0;
|
|
198
|
+
pointer-events: none;
|
|
199
|
+
transition: opacity 250ms ease;
|
|
200
|
+
|
|
201
|
+
&--isOpen {
|
|
202
|
+
opacity: 1;
|
|
203
|
+
}
|
|
197
204
|
}
|
|
198
205
|
|
|
199
206
|
&__drawer {
|
|
@@ -208,7 +215,7 @@ defineExpose({ show, hide, toggle })
|
|
|
208
215
|
box-shadow: var(--cp-shadows-overlay);
|
|
209
216
|
}
|
|
210
217
|
|
|
211
|
-
&__drawer--
|
|
218
|
+
&__drawer--isFullHeight {
|
|
212
219
|
height: 100%;
|
|
213
220
|
max-height: 100%;
|
|
214
221
|
border-radius: 0;
|
|
@@ -230,29 +237,4 @@ defineExpose({ show, hide, toggle })
|
|
|
230
237
|
padding: var(--cp-spacing-md) var(--cp-spacing-xl);
|
|
231
238
|
}
|
|
232
239
|
}
|
|
233
|
-
|
|
234
|
-
.scale-elastic-enter-active,
|
|
235
|
-
.scale-elastic-leave-active {
|
|
236
|
-
transition:
|
|
237
|
-
scale 200ms var(--cp-easing-elastic),
|
|
238
|
-
opacity 200ms ease;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
.scale-elastic-enter-from,
|
|
242
|
-
.scale-elastic-leave-to {
|
|
243
|
-
opacity: 0;
|
|
244
|
-
scale: 0.9;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
.p-drawer-enter-active,
|
|
248
|
-
.p-drawer-leave-active {
|
|
249
|
-
transition:
|
|
250
|
-
transform 300ms ease,
|
|
251
|
-
opacity 250ms ease;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
.p-drawer-enter-from,
|
|
255
|
-
.p-drawer-leave-to {
|
|
256
|
-
transform: translateY(100%);
|
|
257
|
-
}
|
|
258
240
|
</style>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor">
|
|
3
|
+
<path d="M16 11.9999C16 9.02546 18.1644 6.55652 21.0042 6.08217C21.5489 5.99118 22 6.44763 22 6.99992C22 7.5522 21.5453 7.98709 21.0101 8.12334C19.2798 8.56386 18 10.1324 18 11.9999C18 13.8674 19.2798 15.436 21.0101 15.8765C21.5453 16.0127 22 16.4476 22 16.9999C22 17.5522 21.5489 18.0087 21.0042 17.9177C18.1644 17.4433 16 14.9744 16 11.9999ZM11.5859 12.9999L9.29297 15.2929C8.90244 15.6834 8.90244 16.3164 9.29297 16.7069C9.68349 17.0975 10.3165 17.0975 10.707 16.7069L14.6967 12.7173C14.8838 12.5356 15 12.2813 15 11.9999C15 11.7185 14.8838 11.4642 14.6967 11.2825L10.707 7.29288C10.3165 6.90236 9.68349 6.90236 9.29297 7.29288C8.90244 7.68341 8.90244 8.31642 9.29297 8.70695L11.5859 10.9999H2C1.44772 10.9999 1 11.4476 1 11.9999C1 12.5522 1.44772 12.9999 2 12.9999H11.5859Z"/>
|
|
4
|
+
</svg>
|
|
5
|
+
</template>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor">
|
|
3
|
+
<path d="M2 6.99992C2 6.44763 2.45108 5.99118 2.99581 6.08217C5.83559 6.55653 8 9.02546 8 11.9999C8 14.9744 5.83559 17.4433 2.99581 17.9177C2.45107 18.0087 2 17.5522 2 16.9999C2 16.4476 2.45467 16.0127 2.98988 15.8765C4.72024 15.436 6 13.8674 6 11.9999C6 10.1324 4.72024 8.56386 2.98988 8.12334C2.45467 7.98709 2 7.5522 2 6.99992ZM19.5859 13H10C9.44771 13 9 12.5523 9 12C9 11.4478 9.44771 11 10 11H19.5859L17.293 8.70707C16.9024 8.31655 16.9024 7.68353 17.293 7.29301C17.6835 6.90248 18.3165 6.90248 18.707 7.29301L22.707 11.293C23.0976 11.6835 23.0976 12.3165 22.707 12.7071L18.707 16.7071C18.3165 17.0976 17.6835 17.0976 17.293 16.7071C16.9024 16.3165 16.9024 15.6835 17.293 15.293L19.5859 13Z"/>
|
|
4
|
+
</svg>
|
|
5
|
+
</template>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { useWindowSize } from '@vueuse/core'
|
|
2
|
+
import { computed, onMounted, ref } from 'vue'
|
|
3
|
+
|
|
4
|
+
import { Breakpoints } from '@/constants/layout'
|
|
5
|
+
|
|
6
|
+
export const useIsBreakpoint = (breakpoint: Breakpoints = Breakpoints.MOBILE) => {
|
|
7
|
+
const isMounted = ref(false)
|
|
8
|
+
onMounted(() => (isMounted.value = true))
|
|
9
|
+
|
|
10
|
+
const { width } = useWindowSize()
|
|
11
|
+
|
|
12
|
+
return computed(() => {
|
|
13
|
+
if (!isMounted.value) return false
|
|
14
|
+
return width.value < breakpoint
|
|
15
|
+
})
|
|
16
|
+
}
|
|
@@ -38,6 +38,7 @@ import IconCorrosive from '@/components/icons/IconCorrosive.vue'
|
|
|
38
38
|
import IconDashedCircle from '@/components/icons/IconDashedCircle.vue'
|
|
39
39
|
import IconDedicated from '@/components/icons/IconDedicated.vue'
|
|
40
40
|
import IconDeparture from '@/components/icons/IconDeparture.vue'
|
|
41
|
+
import IconDestination from '@/components/icons/IconDestination.vue'
|
|
41
42
|
import IconDeviceForbidden from '@/components/icons/IconDeviceForbidden.vue'
|
|
42
43
|
import IconDirectFlightAlt from '@/components/icons/IconDirectFlightAlt.vue'
|
|
43
44
|
import IconDistribution from '@/components/icons/IconDistribution.vue'
|
|
@@ -92,6 +93,7 @@ import IconNoSeat from '@/components/icons/IconNoSeat.vue'
|
|
|
92
93
|
import IconNotion from '@/components/icons/IconNotion.vue'
|
|
93
94
|
import IconOffline from '@/components/icons/IconOffline.vue'
|
|
94
95
|
import IconOneWay from '@/components/icons/IconOneWay.vue'
|
|
96
|
+
import IconOrigin from '@/components/icons/IconOrigin.vue'
|
|
95
97
|
import IconOta from '@/components/icons/IconOta.vue'
|
|
96
98
|
import IconOtaFilled from '@/components/icons/IconOtaFilled.vue'
|
|
97
99
|
import IconPaid from '@/components/icons/IconPaid.vue'
|
|
@@ -173,6 +175,7 @@ export const CustomCpIcons = {
|
|
|
173
175
|
dedicated: IconDedicated,
|
|
174
176
|
departure: IconDeparture,
|
|
175
177
|
'direct-flight-alt': IconDirectFlightAlt,
|
|
178
|
+
destination: IconDestination,
|
|
176
179
|
'device-forbidden': IconDeviceForbidden,
|
|
177
180
|
distribution: IconDistribution,
|
|
178
181
|
'distribution-closed': IconDistributionClosed,
|
|
@@ -226,6 +229,7 @@ export const CustomCpIcons = {
|
|
|
226
229
|
notion: IconNotion,
|
|
227
230
|
offline: IconOffline,
|
|
228
231
|
'one-way': IconOneWay,
|
|
232
|
+
origin: IconOrigin,
|
|
229
233
|
ota: IconOta,
|
|
230
234
|
'ota-filled': IconOtaFilled,
|
|
231
235
|
paid: IconPaid,
|
|
@@ -29,7 +29,7 @@ const meta = {
|
|
|
29
29
|
description: 'Disable the bottom-drawer behavior on mobile and keep the popover anchored to the trigger.',
|
|
30
30
|
table: { defaultValue: { summary: 'false' } },
|
|
31
31
|
},
|
|
32
|
-
|
|
32
|
+
isFullHeightDrawer: {
|
|
33
33
|
control: 'boolean',
|
|
34
34
|
description: 'When enabled, the mobile drawer takes the full available height.',
|
|
35
35
|
table: { defaultValue: { summary: 'false' } },
|
|
@@ -132,7 +132,10 @@ export const ForcePopoverOnMobile: Story = {
|
|
|
132
132
|
*/
|
|
133
133
|
export const FullHeightDrawer: Story = {
|
|
134
134
|
args: {
|
|
135
|
-
|
|
135
|
+
isFullHeightDrawer: true,
|
|
136
|
+
},
|
|
137
|
+
globals: {
|
|
138
|
+
viewport: { value: 'mobile1', isRotated: false },
|
|
136
139
|
},
|
|
137
140
|
render: (args) => ({
|
|
138
141
|
components: { CpButton, CpMenu },
|
|
@@ -150,7 +153,7 @@ export const FullHeightDrawer: Story = {
|
|
|
150
153
|
template: `
|
|
151
154
|
<CpMenu v-bind="args" :items="items">
|
|
152
155
|
<template #trigger>
|
|
153
|
-
<CpButton>Open
|
|
156
|
+
<CpButton size="xs" appearance="secondary">Open drawer</CpButton>
|
|
154
157
|
</template>
|
|
155
158
|
</CpMenu>
|
|
156
159
|
`,
|