@citizenplane/pimp 12.0.2 → 13.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.
- package/dist/pimp.es.js +1296 -1292
- package/dist/pimp.umd.js +38 -38
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/components/CpDialog.vue +19 -1
- package/src/components/CpLoader.vue +42 -19
- package/src/stories/CpDialog.stories.ts +27 -0
- package/src/stories/CpLoader.stories.ts +7 -2
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
class="cpDialog__dialog"
|
|
9
9
|
@keydown.esc.stop.prevent="handleClose"
|
|
10
10
|
>
|
|
11
|
-
<div aria-hidden="true" class="cpDialog__overlay" />
|
|
11
|
+
<div aria-hidden="true" class="cpDialog__overlay" :class="overlayDynamicClass" @click="handleOverlayClick" />
|
|
12
12
|
<main ref="dialogContainer" class="cpDialog__container" :style="dynamicStyle" @keydown.tab="trapFocus">
|
|
13
13
|
<header class="cpDialog__header">
|
|
14
14
|
<div v-if="hasTitleOrSubtitle" class="cpDialog__headerTexts">
|
|
@@ -44,6 +44,7 @@ import { computed, ref, useSlots, onMounted, nextTick, onBeforeUnmount, useId }
|
|
|
44
44
|
import { getKeyboardFocusableElements, handleTrapFocus } from '@/helpers/dom'
|
|
45
45
|
|
|
46
46
|
interface Props {
|
|
47
|
+
isClosableOnClickOutside?: boolean
|
|
47
48
|
maxWidth?: number
|
|
48
49
|
subtitle?: string
|
|
49
50
|
title?: string
|
|
@@ -57,6 +58,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
57
58
|
maxWidth: 600,
|
|
58
59
|
title: '',
|
|
59
60
|
subtitle: '',
|
|
61
|
+
isClosableOnClickOutside: false,
|
|
60
62
|
})
|
|
61
63
|
|
|
62
64
|
const emit = defineEmits<Emits>()
|
|
@@ -74,6 +76,10 @@ const dialogContainer = ref<HTMLElement | null>(null)
|
|
|
74
76
|
|
|
75
77
|
const dynamicStyle = computed(() => ({ maxWidth: `${props.maxWidth}px` }))
|
|
76
78
|
|
|
79
|
+
const overlayDynamicClass = computed(() => ({
|
|
80
|
+
'cpDialog__overlay--isClosableOnClickOutside': props.isClosableOnClickOutside,
|
|
81
|
+
}))
|
|
82
|
+
|
|
77
83
|
const hasTitleSlot = computed(() => !!slots.title)
|
|
78
84
|
const hasTitle = computed(() => !!props.title || hasTitleSlot.value)
|
|
79
85
|
const hasSubtitleSlot = computed(() => !!slots.subtitle)
|
|
@@ -96,6 +102,11 @@ const focusOnFirstFocusableElement = () => {
|
|
|
96
102
|
focusableElements[0].focus()
|
|
97
103
|
}
|
|
98
104
|
|
|
105
|
+
const handleOverlayClick = () => {
|
|
106
|
+
if (!props.isClosableOnClickOutside) return
|
|
107
|
+
handleClose()
|
|
108
|
+
}
|
|
109
|
+
|
|
99
110
|
onMounted(() => {
|
|
100
111
|
openDialog()
|
|
101
112
|
nextTick(() => focusOnFirstFocusableElement())
|
|
@@ -146,11 +157,18 @@ $dialog-breakpoint: 550px;
|
|
|
146
157
|
inset: 0;
|
|
147
158
|
pointer-events: none;
|
|
148
159
|
transition: opacity 250ms ease;
|
|
160
|
+
|
|
161
|
+
&--isClosableOnClickOutside {
|
|
162
|
+
pointer-events: auto;
|
|
163
|
+
z-index: 0;
|
|
164
|
+
cursor: pointer;
|
|
165
|
+
}
|
|
149
166
|
}
|
|
150
167
|
|
|
151
168
|
&__container {
|
|
152
169
|
position: relative;
|
|
153
170
|
display: flex;
|
|
171
|
+
z-index: 2;
|
|
154
172
|
overflow: hidden;
|
|
155
173
|
width: 100%;
|
|
156
174
|
max-height: 100%;
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
class="cpLoader"
|
|
5
5
|
:class="dynamicClasses"
|
|
6
6
|
enable-background="new 0 0 40 40"
|
|
7
|
-
:height="
|
|
7
|
+
:height="40"
|
|
8
8
|
version="1.1"
|
|
9
9
|
viewBox="0 0 40 40"
|
|
10
|
-
:width="
|
|
10
|
+
:width="40"
|
|
11
11
|
x="0px"
|
|
12
12
|
xml:space="preserve"
|
|
13
13
|
xmlns="http://www.w3.org/2000/svg"
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
<animateTransform
|
|
26
26
|
attributeName="transform"
|
|
27
27
|
attributeType="xml"
|
|
28
|
-
dur="
|
|
28
|
+
:dur="formatedDuration"
|
|
29
29
|
from="0 20 20"
|
|
30
30
|
repeatCount="indefinite"
|
|
31
31
|
to="360 20 20"
|
|
@@ -41,23 +41,22 @@ import { computed } from 'vue'
|
|
|
41
41
|
import { Colors } from '@/constants'
|
|
42
42
|
import { capitalizeFirstLetter } from '@/helpers'
|
|
43
43
|
|
|
44
|
+
type LoaderColor = Extract<Colors, 'neutral' | 'accent' | 'error' | 'warning' | 'success'>
|
|
45
|
+
type LoaderSize = '2xs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl'
|
|
46
|
+
|
|
44
47
|
interface Props {
|
|
45
|
-
color?:
|
|
46
|
-
|
|
48
|
+
color?: LoaderColor
|
|
49
|
+
duration?: number
|
|
50
|
+
size?: LoaderSize
|
|
47
51
|
}
|
|
48
52
|
|
|
49
|
-
const props = withDefaults(defineProps<Props>(), { color: 'accent', size:
|
|
53
|
+
const props = withDefaults(defineProps<Props>(), { color: 'accent', duration: 700, size: 'sm' })
|
|
50
54
|
|
|
51
|
-
const
|
|
55
|
+
const formatedDuration = computed(() => `${props.duration}ms`)
|
|
52
56
|
|
|
53
57
|
const dynamicClasses = computed(() => {
|
|
54
|
-
return [`cpLoader--is${
|
|
58
|
+
return [`cpLoader--is${capitalizeFirstLetter(props.color)}`, `cpLoader--${props.size}`]
|
|
55
59
|
})
|
|
56
|
-
|
|
57
|
-
const sizeAttrs = computed(() => ({
|
|
58
|
-
height: props.size,
|
|
59
|
-
width: props.size,
|
|
60
|
-
}))
|
|
61
60
|
</script>
|
|
62
61
|
|
|
63
62
|
<style lang="scss">
|
|
@@ -74,12 +73,36 @@ const sizeAttrs = computed(() => ({
|
|
|
74
73
|
@include cp-loader-themed('Warning', var(--cp-foreground-warning-secondary));
|
|
75
74
|
@include cp-loader-themed('Success', var(--cp-foreground-success-secondary));
|
|
76
75
|
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
&--2xs {
|
|
77
|
+
@include mx.square-sizing(16);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
&--xs {
|
|
81
|
+
@include mx.square-sizing(20);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
&--sm {
|
|
85
|
+
@include mx.square-sizing(24);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
&--md {
|
|
89
|
+
@include mx.square-sizing(32);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
&--lg {
|
|
93
|
+
@include mx.square-sizing(40);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
&--xl {
|
|
97
|
+
@include mx.square-sizing(48);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
&--2xl {
|
|
101
|
+
@include mx.square-sizing(64);
|
|
102
|
+
}
|
|
79
103
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
@include cp-loader-themed('Red', var(--cp-text-error-primary)); // TODO: Should be replace by ERROR
|
|
104
|
+
&--3xl {
|
|
105
|
+
@include mx.square-sizing(96);
|
|
106
|
+
}
|
|
84
107
|
}
|
|
85
108
|
</style>
|
|
@@ -131,3 +131,30 @@ export const TitleSubtitleWithSlots: Story = {
|
|
|
131
131
|
`,
|
|
132
132
|
}),
|
|
133
133
|
}
|
|
134
|
+
|
|
135
|
+
export const ClosableOnClickOutside: Story = {
|
|
136
|
+
args: {
|
|
137
|
+
maxWidth: 600,
|
|
138
|
+
isClosableOnClickOutside: true,
|
|
139
|
+
},
|
|
140
|
+
render: (args) => ({
|
|
141
|
+
setup() {
|
|
142
|
+
const isOpen = ref(false)
|
|
143
|
+
return { args, isOpen }
|
|
144
|
+
},
|
|
145
|
+
template: `
|
|
146
|
+
<CpButton @click="isOpen = true">Open Dialog</CpButton>
|
|
147
|
+
<CpTransitionDialog>
|
|
148
|
+
<CpDialog v-bind="args" v-if="isOpen" @close="isOpen = false">
|
|
149
|
+
<template #title>Header slot</template>
|
|
150
|
+
<template #subtitle>Subtitle</template>
|
|
151
|
+
<p>This is the default slot content. You can put any content here.</p>
|
|
152
|
+
<template #footer>
|
|
153
|
+
<CpButton @click="isOpen = false">Cancel</CpButton>
|
|
154
|
+
This is the footer slot
|
|
155
|
+
</template>
|
|
156
|
+
</CpDialog>
|
|
157
|
+
</CpTransitionDialog>
|
|
158
|
+
`,
|
|
159
|
+
}),
|
|
160
|
+
}
|
|
@@ -7,14 +7,19 @@ const meta = {
|
|
|
7
7
|
component: CpLoader,
|
|
8
8
|
argTypes: {
|
|
9
9
|
size: {
|
|
10
|
-
control: '
|
|
10
|
+
control: 'select',
|
|
11
|
+
options: ['2xs', 'xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl'],
|
|
11
12
|
description: 'Size of the loader in pixels',
|
|
12
13
|
},
|
|
13
14
|
color: {
|
|
14
15
|
control: 'select',
|
|
15
|
-
options: ['neutral', 'accent', 'error', 'warning', 'success'
|
|
16
|
+
options: ['neutral', 'accent', 'error', 'warning', 'success'],
|
|
16
17
|
description: 'The color variant of the loader',
|
|
17
18
|
},
|
|
19
|
+
duration: {
|
|
20
|
+
control: 'number',
|
|
21
|
+
description: 'The duration of the loader in ms (700ms by default)',
|
|
22
|
+
},
|
|
18
23
|
},
|
|
19
24
|
} satisfies Meta<typeof CpLoader>
|
|
20
25
|
|