@globalbrain/sefirot 2.0.0-draft.3 → 2.0.0-draft.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.
- package/CHANGELOG.md +6 -0
- package/lib/components/SModal.vue +15 -37
- package/lib/components/SPortalModals.vue +2 -3
- package/lib/components/SSheet.vue +71 -13
- package/lib/components/SSheetFooter.vue +5 -1
- package/lib/components/SSheetFooterAction.vue +1 -1
- package/lib/components/SSheetFooterActions.vue +1 -1
- package/lib/components/SSheetMedium.vue +4 -10
- package/lib/components/SSheetTitle.vue +20 -0
- package/lib/composables/Modal.ts +3 -11
- package/lib/mixins/Sheet.ts +2 -4
- package/lib/store/modal/index.ts +0 -5
- package/package.json +1 -1
- package/lib/components/SSheetHeader.vue +0 -60
- package/lib/components/SSheetHeaderTitle.vue +0 -15
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
# [2.0.0-draft.4](https://github.com/globalbrain/sefirot/compare/v2.0.0-draft.3...v2.0.0-draft.4) (2021-12-22)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
* refactor modals ([36d0d1e](https://github.com/globalbrain/sefirot/commit/36d0d1e7747935aff4d909d4023751002875d6c8))
|
|
6
|
+
|
|
1
7
|
# [2.0.0-draft.3](https://github.com/globalbrain/sefirot/compare/v2.0.0-draft.2...v2.0.0-draft.3) (2021-12-17)
|
|
2
8
|
|
|
3
9
|
### Features
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div v-show="show" class="SModal" ref="el"
|
|
3
|
-
<div class="content"
|
|
4
|
-
<component :is="component" v-bind="data" @close="close" />
|
|
2
|
+
<div v-show="show" class="SModal" ref="el">
|
|
3
|
+
<div class="content">
|
|
4
|
+
<component :is="component" v-bind="data ?? {}" @close="close" />
|
|
5
5
|
</div>
|
|
6
6
|
</div>
|
|
7
7
|
</template>
|
|
@@ -10,15 +10,16 @@
|
|
|
10
10
|
import { ref, onMounted, onBeforeUnmount } from 'vue'
|
|
11
11
|
import { disableBodyScroll, enableBodyScroll } from 'body-scroll-lock'
|
|
12
12
|
|
|
13
|
-
const props = defineProps
|
|
14
|
-
id
|
|
15
|
-
component:
|
|
16
|
-
data
|
|
17
|
-
show:
|
|
18
|
-
|
|
19
|
-
})
|
|
13
|
+
const props = defineProps<{
|
|
14
|
+
id?: number
|
|
15
|
+
component: any
|
|
16
|
+
data?: Record<string, any>
|
|
17
|
+
show: boolean
|
|
18
|
+
}>()
|
|
20
19
|
|
|
21
|
-
const emit = defineEmits
|
|
20
|
+
const emit = defineEmits<{
|
|
21
|
+
(e: 'close', id?: number): void
|
|
22
|
+
}>()
|
|
22
23
|
|
|
23
24
|
const el = ref<any>(null)
|
|
24
25
|
|
|
@@ -29,34 +30,16 @@ function close() {
|
|
|
29
30
|
emit('close', props.id)
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
function
|
|
33
|
-
if (props.closable) {
|
|
34
|
-
if (!isDescendant(e.target)) {
|
|
35
|
-
close()
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function isDescendant(el: any): boolean {
|
|
41
|
-
if (el.classList && el.classList.contains('content')) {
|
|
42
|
-
return false
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const parent = document.getElementsByClassName('content')[0]
|
|
46
|
-
|
|
47
|
-
return parent && parent.contains(el)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function lock(): void {
|
|
33
|
+
function lock() {
|
|
51
34
|
disableBodyScroll(el.value!, { reserveScrollBarGap: true })
|
|
52
35
|
}
|
|
53
36
|
|
|
54
|
-
function release()
|
|
37
|
+
function release() {
|
|
55
38
|
enableBodyScroll(el.value!)
|
|
56
39
|
}
|
|
57
40
|
</script>
|
|
58
41
|
|
|
59
|
-
<style lang="postcss"
|
|
42
|
+
<style scoped lang="postcss">
|
|
60
43
|
.SModal {
|
|
61
44
|
position: absolute;
|
|
62
45
|
top: 0;
|
|
@@ -64,13 +47,8 @@ function release(): void {
|
|
|
64
47
|
bottom: 0;
|
|
65
48
|
left: 0;
|
|
66
49
|
height: 100vh;
|
|
67
|
-
padding: 32px 16px 96px;
|
|
68
50
|
overflow: hidden;
|
|
69
51
|
overflow-y: auto;
|
|
70
|
-
|
|
71
|
-
@media (min-width: 768px) {
|
|
72
|
-
padding: 48px 24px 96px;
|
|
73
|
-
}
|
|
74
52
|
}
|
|
75
53
|
|
|
76
54
|
.SModal.fade-enter-active .content,
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
:show="index === items.length - 1"
|
|
10
10
|
:component="item.component"
|
|
11
11
|
:data="item.data"
|
|
12
|
-
:closable="item.options && item.options.closable"
|
|
13
12
|
@close="id => close(id)"
|
|
14
13
|
/>
|
|
15
14
|
</transition-group>
|
|
@@ -43,7 +42,7 @@ watch(hasItem, (value) => {
|
|
|
43
42
|
|
|
44
43
|
watch(route, closeAll)
|
|
45
44
|
|
|
46
|
-
function close(id
|
|
45
|
+
function close(id?: number) {
|
|
47
46
|
store.dispatch('modal/close', id)
|
|
48
47
|
}
|
|
49
48
|
|
|
@@ -52,7 +51,7 @@ function closeAll() {
|
|
|
52
51
|
}
|
|
53
52
|
</script>
|
|
54
53
|
|
|
55
|
-
<style lang="postcss"
|
|
54
|
+
<style scoped lang="postcss">
|
|
56
55
|
.SPortalModals {
|
|
57
56
|
position: fixed;
|
|
58
57
|
top: 0;
|
|
@@ -1,34 +1,92 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
<
|
|
4
|
-
|
|
2
|
+
<div class="SSheet" :class="[size ?? 'medium']" @click="closeIfClosable">
|
|
3
|
+
<article class="box" @click.stop>
|
|
4
|
+
<div v-if="closable !== false" class="close">
|
|
5
|
+
<button class="close-button" @click="$emit('close')">
|
|
6
|
+
<SIconX class="close-icon" />
|
|
7
|
+
</button>
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<slot :close="() => emit('close')" />
|
|
11
|
+
</article>
|
|
12
|
+
</div>
|
|
5
13
|
</template>
|
|
6
14
|
|
|
7
15
|
<script setup lang="ts">
|
|
8
|
-
import
|
|
16
|
+
import SIconX from './icons/SIconX.vue'
|
|
9
17
|
|
|
10
|
-
defineProps<{
|
|
18
|
+
const props = defineProps<{
|
|
11
19
|
size?: 'small' | 'medium' | 'large'
|
|
20
|
+
closable?: boolean
|
|
12
21
|
}>()
|
|
13
22
|
|
|
14
|
-
const
|
|
23
|
+
const emit = defineEmits<{
|
|
24
|
+
(e: 'close'): void
|
|
25
|
+
}>()
|
|
15
26
|
|
|
16
|
-
function
|
|
17
|
-
|
|
27
|
+
function closeIfClosable() {
|
|
28
|
+
if (props.closable !== false) {
|
|
29
|
+
emit('close')
|
|
30
|
+
}
|
|
18
31
|
}
|
|
19
32
|
</script>
|
|
20
33
|
|
|
21
|
-
<style lang="postcss"
|
|
34
|
+
<style scoped lang="postcss">
|
|
22
35
|
.SSheet {
|
|
36
|
+
padding: 16px 16px 96px;
|
|
37
|
+
min-height: 100vh;
|
|
38
|
+
|
|
39
|
+
@media (min-width: 512px) {
|
|
40
|
+
padding: 32px 24px 96px;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@media (min-width: 768px) {
|
|
44
|
+
padding: 48px 32px 128px;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.SSheet.small .box { max-width: 392px; }
|
|
49
|
+
.SSheet.medium .box { max-width: 512px; }
|
|
50
|
+
.SSheet.large .box { max-width: 768px; }
|
|
51
|
+
|
|
52
|
+
.box {
|
|
53
|
+
position: relative;
|
|
23
54
|
margin: 0 auto;
|
|
24
55
|
border: 1px solid var(--c-divider-light);
|
|
25
56
|
border-radius: 8px;
|
|
26
57
|
background-color: var(--c-bg);
|
|
27
58
|
box-shadow: var(--shadow-depth-3);
|
|
28
|
-
overflow: hidden;
|
|
29
59
|
}
|
|
30
60
|
|
|
31
|
-
.
|
|
32
|
-
|
|
33
|
-
|
|
61
|
+
.close {
|
|
62
|
+
position: absolute;
|
|
63
|
+
top: 10px;
|
|
64
|
+
right: 4px;
|
|
65
|
+
z-index: 10;
|
|
66
|
+
|
|
67
|
+
@media (min-width: 512px) {
|
|
68
|
+
top: 14px;
|
|
69
|
+
right: 12px;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.close-button {
|
|
74
|
+
display: flex;
|
|
75
|
+
justify-content: center;
|
|
76
|
+
align-items: center;
|
|
77
|
+
width: 48px;
|
|
78
|
+
height: 48px;
|
|
79
|
+
color: var(--c-text-3);
|
|
80
|
+
transition: color .25s;
|
|
81
|
+
|
|
82
|
+
&:hover {
|
|
83
|
+
color: var(--c-text-1);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.close-icon {
|
|
88
|
+
width: 20px;
|
|
89
|
+
height: 20px;
|
|
90
|
+
fill: currentColor;
|
|
91
|
+
}
|
|
34
92
|
</style>
|
|
@@ -4,9 +4,13 @@
|
|
|
4
4
|
</footer>
|
|
5
5
|
</template>
|
|
6
6
|
|
|
7
|
-
<style lang="postcss"
|
|
7
|
+
<style scoped lang="postcss">
|
|
8
8
|
.SSheetFooter {
|
|
9
9
|
border-top: 1px solid var(--c-divider-light);
|
|
10
10
|
padding: 0 16px;
|
|
11
|
+
|
|
12
|
+
@media (min-width: 512px) {
|
|
13
|
+
padding: 0 24px;
|
|
14
|
+
}
|
|
11
15
|
}
|
|
12
16
|
</style>
|
|
@@ -6,17 +6,11 @@
|
|
|
6
6
|
|
|
7
7
|
<style lang="postcss" scoped>
|
|
8
8
|
.SSheetMedium {
|
|
9
|
-
padding: 16px;
|
|
10
|
-
}
|
|
9
|
+
padding: 12px 16px 20px;
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
font-weight: 500;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
.SSheetMedium :deep(h1 + p) {
|
|
19
|
-
margin-top: 8px;
|
|
11
|
+
@media (min-width: 512px) {
|
|
12
|
+
padding: 16px 24px 26px;
|
|
13
|
+
}
|
|
20
14
|
}
|
|
21
15
|
|
|
22
16
|
.SSheetMedium :deep(p) {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<header class="SSheetTitle">
|
|
3
|
+
<h1 class="title">
|
|
4
|
+
<slot />
|
|
5
|
+
</h1>
|
|
6
|
+
</header>
|
|
7
|
+
</template>
|
|
8
|
+
|
|
9
|
+
<style lang="postcss" scoped>
|
|
10
|
+
.title {
|
|
11
|
+
padding: 20px 48px 0 16px;
|
|
12
|
+
line-height: 28px;
|
|
13
|
+
font-size: 20px;
|
|
14
|
+
font-weight: 500;
|
|
15
|
+
|
|
16
|
+
@media (min-width: 512px) {
|
|
17
|
+
padding: 24px 64px 0 24px;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
</style>
|
package/lib/composables/Modal.ts
CHANGED
|
@@ -1,29 +1,21 @@
|
|
|
1
1
|
import { useStore } from 'vuex'
|
|
2
|
-
import { Options as ModalOptions } from '../store/modal'
|
|
3
2
|
|
|
4
3
|
export interface Modal {
|
|
5
|
-
open(
|
|
4
|
+
open(data?: Record<string, any>): Promise<any>
|
|
6
5
|
close(): Promise<any>
|
|
7
6
|
}
|
|
8
7
|
|
|
9
|
-
export interface OpenOptions {
|
|
10
|
-
id?: number
|
|
11
|
-
component?: any
|
|
12
|
-
data?: Record<string, any>
|
|
13
|
-
options?: ModalOptions
|
|
14
|
-
}
|
|
15
|
-
|
|
16
8
|
let modalId = 0
|
|
17
9
|
|
|
18
10
|
export function useModal(component: any): Modal {
|
|
19
11
|
const store = useStore()
|
|
20
12
|
const id = useModalId()
|
|
21
13
|
|
|
22
|
-
function open(
|
|
14
|
+
function open(data: Record<string, any> = {}): Promise<any> {
|
|
23
15
|
return store.dispatch('modal/open', {
|
|
24
16
|
id,
|
|
25
17
|
component,
|
|
26
|
-
|
|
18
|
+
data
|
|
27
19
|
})
|
|
28
20
|
}
|
|
29
21
|
|
package/lib/mixins/Sheet.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { App } from 'vue'
|
|
2
2
|
import SSheet from '../components/SSheet.vue'
|
|
3
|
-
import
|
|
4
|
-
import SSheetHeaderTitle from '../components/SSheetHeaderTitle.vue'
|
|
3
|
+
import SSheetTitle from '../components/SSheetTitle.vue'
|
|
5
4
|
import SSheetMedium from '../components/SSheetMedium.vue'
|
|
6
5
|
import SSheetFooter from '../components/SSheetFooter.vue'
|
|
7
6
|
import SSheetFooterActions from '../components/SSheetFooterActions.vue'
|
|
@@ -11,8 +10,7 @@ export function mixin(app: App): void {
|
|
|
11
10
|
app.mixin({
|
|
12
11
|
components: {
|
|
13
12
|
SSheet,
|
|
14
|
-
|
|
15
|
-
SSheetHeaderTitle,
|
|
13
|
+
SSheetTitle,
|
|
16
14
|
SSheetMedium,
|
|
17
15
|
SSheetFooter,
|
|
18
16
|
SSheetFooterActions,
|
package/lib/store/modal/index.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<header class="SSheetHeader">
|
|
3
|
-
<slot />
|
|
4
|
-
|
|
5
|
-
<div v-if="closable" class="close">
|
|
6
|
-
<button class="close-button" @click="close">
|
|
7
|
-
<SIconX class="close-icon" />
|
|
8
|
-
</button>
|
|
9
|
-
</div>
|
|
10
|
-
</header>
|
|
11
|
-
</template>
|
|
12
|
-
|
|
13
|
-
<script setup lang="ts">
|
|
14
|
-
import { useStore } from 'vuex'
|
|
15
|
-
import SIconX from './icons/SIconX.vue'
|
|
16
|
-
|
|
17
|
-
defineProps({
|
|
18
|
-
closable: { type: Boolean, default: true }
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
const store = useStore()
|
|
22
|
-
|
|
23
|
-
function close() {
|
|
24
|
-
store.dispatch('modal/close')
|
|
25
|
-
}
|
|
26
|
-
</script>
|
|
27
|
-
|
|
28
|
-
<style lang="postcss" scoped>
|
|
29
|
-
.SSheetHeader {
|
|
30
|
-
display: flex;
|
|
31
|
-
justify-content: space-between;
|
|
32
|
-
border-bottom: 1px solid var(--c-divider-light);
|
|
33
|
-
min-height: 48px;
|
|
34
|
-
background-color: var(--c-bg-soft);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
.close {
|
|
38
|
-
margin: 0 0 0 auto;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
.close-button {
|
|
42
|
-
display: flex;
|
|
43
|
-
justify-content: center;
|
|
44
|
-
align-items: center;
|
|
45
|
-
width: 48px;
|
|
46
|
-
height: 47px;
|
|
47
|
-
color: var(--c-text-3);
|
|
48
|
-
transition: color .25s;
|
|
49
|
-
|
|
50
|
-
&:hover {
|
|
51
|
-
color: var(--c-text-1);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
.close-icon {
|
|
56
|
-
width: 20px;
|
|
57
|
-
height: 20px;
|
|
58
|
-
fill: currentColor;
|
|
59
|
-
}
|
|
60
|
-
</style>
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<h1 class="SSheetHeaderTitle">
|
|
3
|
-
<slot />
|
|
4
|
-
</h1>
|
|
5
|
-
</template>
|
|
6
|
-
|
|
7
|
-
<style lang="postcss" scoped>
|
|
8
|
-
.SSheetHeaderTitle {
|
|
9
|
-
margin: 0;
|
|
10
|
-
padding: 14px 16px 10px;
|
|
11
|
-
line-height: 20px;
|
|
12
|
-
font-size: 14px;
|
|
13
|
-
font-weight: 500;
|
|
14
|
-
}
|
|
15
|
-
</style>
|