@globalbrain/sefirot 2.0.0-draft.7 → 2.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 (95) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +6 -6
  3. package/lib/components/SAvatar.vue +17 -17
  4. package/lib/components/SButton.vue +512 -267
  5. package/lib/components/SButtonGroup.vue +149 -0
  6. package/lib/components/SDropdown.vue +26 -150
  7. package/lib/components/SDropdownSection.vue +48 -0
  8. package/lib/components/SDropdownSectionFilter.vue +189 -0
  9. package/lib/components/SDropdownSectionFilterItem.vue +21 -0
  10. package/lib/components/SDropdownSectionFilterItemAvatar.vue +31 -0
  11. package/lib/components/SDropdownSectionFilterItemText.vue +20 -0
  12. package/lib/components/SDropdownSectionMenu.vue +39 -0
  13. package/lib/components/SIcon.vue +13 -0
  14. package/lib/components/SInputBase.vue +31 -31
  15. package/lib/components/SInputCheckbox.vue +1 -1
  16. package/lib/components/SInputCheckboxes.vue +74 -0
  17. package/lib/components/SInputDate.vue +182 -0
  18. package/lib/components/SInputDropdown.vue +158 -157
  19. package/lib/components/SInputDropdownItem.vue +46 -48
  20. package/lib/components/{SInputDropdownItemUserTag.vue → SInputDropdownItemAvatar.vue} +43 -44
  21. package/lib/components/SInputDropdownItemText.vue +79 -16
  22. package/lib/components/SInputFile.vue +55 -60
  23. package/lib/components/SInputHMS.vue +120 -110
  24. package/lib/components/SInputNumber.vue +38 -9
  25. package/lib/components/SInputRadio.vue +39 -36
  26. package/lib/components/SInputRadios.vue +40 -53
  27. package/lib/components/SInputSelect.vue +3 -3
  28. package/lib/components/SInputSwitch.vue +193 -0
  29. package/lib/components/SInputSwitches.vue +88 -0
  30. package/lib/components/SInputText.vue +206 -62
  31. package/lib/components/SInputTextarea.vue +46 -32
  32. package/lib/components/SInputYMD.vue +123 -126
  33. package/lib/components/SMarkdown.vue +52 -0
  34. package/lib/components/SModal.vue +25 -63
  35. package/lib/components/SMount.vue +19 -0
  36. package/lib/components/SSheet.vue +49 -55
  37. package/lib/components/SSheetFooter.vue +1 -1
  38. package/lib/components/SSheetFooterAction.vue +24 -17
  39. package/lib/components/SSheetFooterActions.vue +1 -4
  40. package/lib/components/SSheetForm.vue +15 -0
  41. package/lib/components/SSheetMedium.vue +8 -10
  42. package/lib/components/SSheetTitle.vue +7 -14
  43. package/lib/components/SSnackbar.vue +55 -45
  44. package/lib/components/{SPortalSnackbars.vue → SSnackbars.vue} +17 -20
  45. package/lib/components/SStep.vue +106 -0
  46. package/lib/components/SSteps.vue +59 -0
  47. package/lib/components/STable.vue +241 -0
  48. package/lib/components/STableCell.vue +82 -0
  49. package/lib/components/STableCellAvatar.vue +69 -0
  50. package/lib/components/STableCellAvatars.vue +93 -0
  51. package/lib/components/STableCellDay.vue +40 -0
  52. package/lib/components/STableCellPill.vue +84 -0
  53. package/lib/components/STableCellText.vue +102 -0
  54. package/lib/components/STableColumn.vue +255 -0
  55. package/lib/components/STableFooter.vue +115 -0
  56. package/lib/components/STableHeader.vue +74 -0
  57. package/lib/components/STableItem.vue +38 -0
  58. package/lib/components/STooltip.vue +112 -0
  59. package/lib/composables/Dropdown.ts +40 -99
  60. package/lib/composables/Form.ts +21 -18
  61. package/lib/composables/Grid.ts +117 -0
  62. package/lib/composables/Markdown.ts +138 -0
  63. package/lib/composables/Step.ts +7 -0
  64. package/lib/composables/Table.ts +103 -0
  65. package/lib/composables/Tooltip.ts +91 -0
  66. package/lib/composables/Validation.ts +6 -7
  67. package/lib/composables/markdown/LinkPlugin.ts +45 -0
  68. package/lib/mixins/Sheet.ts +5 -3
  69. package/lib/stores/Snackbars.ts +48 -0
  70. package/lib/{assets/styles → styles}/base.css +0 -0
  71. package/lib/{assets/styles → styles}/bootstrap.css +1 -0
  72. package/lib/{assets/styles → styles}/variables.css +55 -48
  73. package/lib/support/Day.ts +8 -0
  74. package/lib/support/Num.ts +3 -0
  75. package/lib/support/Time.ts +5 -2
  76. package/lib/support/Utils.ts +4 -3
  77. package/lib/types/shims.d.ts +3 -0
  78. package/lib/validation/validators/requiredYmd.ts +1 -1
  79. package/lib/validation/validators/ymd.ts +4 -4
  80. package/package.json +62 -43
  81. package/CHANGELOG.md +0 -41
  82. package/lib/components/SDialog.vue +0 -140
  83. package/lib/components/SDropdownItem.vue +0 -78
  84. package/lib/components/SDropdownItemText.vue +0 -22
  85. package/lib/components/SDropdownItemUser.vue +0 -40
  86. package/lib/components/SInputDropdownItemTextTag.vue +0 -94
  87. package/lib/components/SInputDropdownItemUser.vue +0 -41
  88. package/lib/components/SPortalModals.vue +0 -74
  89. package/lib/composables/Dialog.ts +0 -38
  90. package/lib/composables/Modal.ts +0 -34
  91. package/lib/composables/Snackbar.ts +0 -18
  92. package/lib/store/Sefirot.ts +0 -17
  93. package/lib/store/dialog/index.ts +0 -42
  94. package/lib/store/modal/index.ts +0 -61
  95. package/lib/store/snackbars/index.ts +0 -70
@@ -1,140 +0,0 @@
1
- <template>
2
- <div class="SDialog" :class="{ 'load-only': isLoadOnly }">
3
- <p v-if="title" class="title">{{ title }}</p>
4
- <p v-if="text" class="text">{{ text }}</p>
5
-
6
- <div v-if="isTypeLoading" class="load">
7
- <div class="load-icon">
8
- <SIconPreloader class="load-svg" />
9
- </div>
10
- </div>
11
-
12
- <div v-if="actions.length > 0" class="actions">
13
- <div v-for="(action, index) in actions" :key="index" class="action">
14
- <SButton
15
- size="small"
16
- :type="getActionType(action.type)"
17
- :label="action.label"
18
- @click="action.callback"
19
- />
20
- </div>
21
- </div>
22
- </div>
23
- </template>
24
-
25
- <script setup lang="ts">
26
- import { PropType, computed } from 'vue'
27
- import { Action } from '../store/dialog'
28
- import SIconPreloader from './icons/SIconPreloader.vue'
29
- import SButton from './SButton.vue'
30
-
31
- const props = defineProps({
32
- type: { type: String as PropType<'confirm' | 'loading'>, default: 'confirm' },
33
- title: { type: String, default: null },
34
- text: { type: String, default: null },
35
- actions: { type: Array as PropType<Action[]>, default: () => [] }
36
- })
37
-
38
- const isTypeLoading = computed(() => props.type === 'loading')
39
- const isLoadOnly = computed(() => isTypeLoading.value && !props.title && !props.text)
40
-
41
- function getActionType(value?: 'text' | 'mute'): 'text' | 'mute' {
42
- return value !== 'mute' ? 'text' : 'mute'
43
- }
44
- </script>
45
-
46
- <style lang="postcss" scoped>
47
- .SDialog {
48
- margin: 96px 16px;
49
- border: 1px solid var(--c-divider-light);
50
- border-radius: 8px;
51
- padding: 16px 16px 8px;
52
- max-width: 392px;
53
- background-color: var(--c-bg);
54
- box-shadow: var(--shadow-depth-3);
55
-
56
- @media (min-width: 424px) {
57
- margin: 64px auto;
58
- padding: 24px 24px 16px;
59
- }
60
- }
61
-
62
- .SDialog.load-only {
63
- margin: 128px auto;
64
- padding: 0;
65
- width: 80px;
66
- height: 80px;
67
-
68
- .load {
69
- display: flex;
70
- justify-content: center;
71
- align-items: center;
72
- margin: 0;
73
- padding: 0;
74
- width: 80px;
75
- height: 80px;
76
- }
77
-
78
- .load-svg {
79
- transform: translate(0);
80
- }
81
-
82
- @media (min-width: 424px) {
83
- margin: 128px auto;
84
- }
85
- }
86
-
87
- .title {
88
- line-height: 28px;
89
- font-size: 16px;
90
- font-weight: 500;
91
- }
92
-
93
- .text {
94
- line-height: 20px;
95
- font-size: 14px;
96
- }
97
-
98
- .load {
99
- margin-top: 2px;
100
- transform: translateY(1px);
101
- }
102
-
103
- .load-svg {
104
- width: 48px;
105
- height: 48px;
106
- transform: translate(-10px, 2px);
107
-
108
- @media (min-width: 424px) {
109
- transform: translate(-12px, 6px);
110
- }
111
- }
112
-
113
- .progress {
114
- padding-top: 14px;
115
- padding-bottom: 8px;
116
-
117
- @media (min-width: 424px) {
118
- padding-top: 16px;
119
- padding-bottom: 4px;
120
- }
121
- }
122
-
123
- .actions {
124
- display: flex;
125
- justify-content: flex-end;
126
- flex-wrap: wrap;
127
- margin: 0 -8px;
128
- padding-top: 12px;
129
-
130
- @media (min-width: 424px) {
131
- margin: 0 -10px;
132
- }
133
- }
134
-
135
- .action {
136
- @media (min-width: 424px) {
137
- padding: 0 4px;
138
- }
139
- }
140
- </style>
@@ -1,78 +0,0 @@
1
- <template>
2
- <li class="SDropdownItem" role="button" @click="$emit('click')">
3
- <div v-if="item" class="content">
4
- <component :is="component" :item="item" />
5
- </div>
6
-
7
- <div class="status">
8
- <SIconCheck v-if="isActive" class="status-icon" />
9
- </div>
10
- </li>
11
- </template>
12
-
13
- <script setup lang="ts">
14
- import { ComputedRef, PropType, computed } from 'vue'
15
- import { isArray, isEqual } from '../support/Utils'
16
- import SIconCheck from './icons/SIconCheck.vue'
17
- import SDropdownItemText from './SDropdownItemText.vue'
18
- import SDropdownItemUser from './SDropdownItemUser.vue'
19
-
20
- const props = defineProps({
21
- selected: { type: Object as PropType<ComputedRef<any>>, default: null },
22
- item: { type: Object as PropType<any>, default: null }
23
- })
24
-
25
- defineEmits(['click'])
26
-
27
- const component = computed(() => {
28
- if (props.item.type === 'text') {
29
- return SDropdownItemText
30
- }
31
-
32
- if (props.item.type === 'user') {
33
- return SDropdownItemUser
34
- }
35
-
36
- throw new Error('Invalid item type.')
37
- })
38
-
39
- const isActive = computed(() => {
40
- if (!props.selected) {
41
- return false
42
- }
43
-
44
- const selected = props.selected.value
45
- const value = props.item.value
46
-
47
- return isArray(selected)
48
- ? !!selected.find(s => isEqual(s, value))
49
- : isEqual(selected, value)
50
- })
51
- </script>
52
-
53
- <style lang="postcss" scoped>
54
- @import "@/assets/styles/variables";
55
-
56
- .SDropdownItem {
57
- display: flex;
58
- justify-content: space-between;
59
- padding: 8px 12px 8px 16px;
60
- }
61
-
62
- .status {
63
- display: flex;
64
- justify-content: center;
65
- align-items: center;
66
- margin-left: 8px;
67
- width: 16px;
68
- height: 16px;
69
- }
70
-
71
- .status-icon {
72
- width: 16px;
73
- height: 16px;
74
- transform: translateY(1px);
75
- fill: var(--c-text-1);
76
- transition: fill .25s;
77
- }
78
- </style>
@@ -1,22 +0,0 @@
1
- <template>
2
- <div class="SDropdownItemText">
3
- <p class="text">{{ item.text }}</p>
4
- </div>
5
- </template>
6
-
7
- <script setup lang="ts">
8
- import { PropType } from 'vue'
9
-
10
- defineProps({
11
- item: { type: Object as PropType<any>, required: true }
12
- })
13
- </script>
14
-
15
- <style lang="postcss" scoped>
16
- .text {
17
- margin: 0;
18
- line-height: 16px;
19
- font-size: 12px;
20
- font-weight: 500;
21
- }
22
- </style>
@@ -1,40 +0,0 @@
1
- <template>
2
- <div class="SDropdownItemUser">
3
- <div class="avatar">
4
- <SAvatar size="mini" :avatar="item.avatar" :name="item.name" />
5
- </div>
6
-
7
- <p class="name">{{ item.name }}</p>
8
- </div>
9
- </template>
10
-
11
- <script setup lang="ts">
12
- import { PropType } from 'vue'
13
- import { UserItem } from '../composables/Dropdown'
14
- import SAvatar from './SAvatar.vue'
15
-
16
- defineProps({
17
- item: { type: Object as PropType<UserItem>, required: true }
18
- })
19
- </script>
20
-
21
- <style lang="postcss" scoped>
22
- .SDropdownItemUser {
23
- position: relative;
24
- }
25
-
26
- .avatar {
27
- position: absolute;
28
- top: 0;
29
- left: -4px;
30
- width: 24px;
31
- height: 24px;
32
- }
33
-
34
- .name {
35
- padding-left: 32px;
36
- line-height: 24px;
37
- font-size: 12px;
38
- font-weight: 500;
39
- }
40
- </style>
@@ -1,94 +0,0 @@
1
- <template>
2
- <div class="SInputDropdownItemTextTag" :class="{ disabled }">
3
- <p class="text">{{ item.text }}</p>
4
-
5
- <div v-if="!disabled" class="remove" role="button" @click="$emit('remove')">
6
- <div class="remove-box">
7
- <SIconX class="remove-icon" />
8
- </div>
9
- </div>
10
- </div>
11
- </template>
12
-
13
- <script setup lang="ts">
14
- import { PropType } from 'vue'
15
- import SIconX from './icons/SIconX.vue'
16
-
17
- defineProps({
18
- item: { type: Object as PropType<any>, required: true },
19
- disabled: { type: Boolean, default: false }
20
- })
21
-
22
- defineEmits(['remove'])
23
- </script>
24
-
25
- <style lang="postcss" scoped>
26
- .SInputDropdownItemTextTag {
27
- display: flex;
28
- border-radius: 12px;
29
- padding: 0 0 0 10px;
30
- background-color: var(--c-white-mute);
31
- }
32
-
33
- .dark .SInputDropdownItemTextTag {
34
- background-color: var(--c-black-mute);
35
- }
36
-
37
- .SInputDropdownItemTextTag.disabled {
38
- padding: 0 10px 0;
39
- background-color: var(--c-gray-light-4);
40
-
41
- .text {
42
- color: var(--c-text-2);
43
- }
44
- }
45
-
46
- .dark .SInputDropdownItemTextTag.disabled {
47
- background-color: var(--c-gray-dark-2);
48
- }
49
-
50
- .text {
51
- margin: 0;
52
- line-height: 24px;
53
- font-size: 12px;
54
- font-weight: 500;
55
- white-space: nowrap;
56
- }
57
-
58
- .remove {
59
- display: flex;
60
- justify-content: center;
61
- align-items: center;
62
- margin-left: 2px;
63
- width: 24px;
64
- height: 24px;
65
-
66
- &:hover .remove-box {
67
- color: var(--c-text-1);
68
- background-color: var(--c-gray-light-4)
69
- }
70
- }
71
-
72
- .dark .remove {
73
- &:hover .remove-box {
74
- background-color: var(--c-gray-dark-2)
75
- }
76
- }
77
-
78
- .remove-box {
79
- display: flex;
80
- justify-content: center;
81
- align-items: center;
82
- border-radius: 50%;
83
- width: 20px;
84
- height: 20px;
85
- color: var(--c-text-2);
86
- transition: color .25s, background-color .25s;
87
- }
88
-
89
- .remove-icon {
90
- width: 12px;
91
- height: 12px;
92
- fill: currentColor;
93
- }
94
- </style>
@@ -1,41 +0,0 @@
1
- <template>
2
- <div class="SInputDropdownItemUser" :class="{ disabled }">
3
- <div class="avatar">
4
- <SAvatar size="mini" :avatar="item.avatar" :name="item.name" />
5
- </div>
6
-
7
- <p class="name">{{ item.name }}</p>
8
- </div>
9
- </template>
10
-
11
- <script setup lang="ts">
12
- import { PropType } from 'vue'
13
- import { UserItem } from '../composables/Dropdown'
14
- import SAvatar from './SAvatar.vue'
15
-
16
- defineProps({
17
- item: { type: Object as PropType<UserItem>, required: true },
18
- disabled: { type: Boolean, default: false }
19
- })
20
- </script>
21
-
22
- <style lang="postcss" scoped>
23
- .SInputDropdownItemUser {
24
- position: relative;
25
- }
26
-
27
- .avatar {
28
- position: absolute;
29
- top: 0;
30
- left: 0;
31
- width: 24px;
32
- height: 24px;
33
- }
34
-
35
- .name {
36
- padding-left: 32px;
37
- line-height: 24px;
38
- font-size: 12px;
39
- font-weight: 500;
40
- }
41
- </style>
@@ -1,74 +0,0 @@
1
- <template>
2
- <transition name="fade">
3
- <div v-if="isActive" class="SPortalModals">
4
- <transition-group name="fade" :duration="250" appear>
5
- <SModal
6
- v-for="(item, index) in items"
7
- :key="item.id"
8
- :id="item.id"
9
- :show="index === items.length - 1"
10
- :component="item.component"
11
- :data="item.data"
12
- @close="id => close(id)"
13
- />
14
- </transition-group>
15
- </div>
16
- </transition>
17
- </template>
18
-
19
- <script setup lang="ts">
20
- import { ref, computed, watch } from 'vue'
21
- import { useRoute } from 'vue-router'
22
- import { useStore } from 'vuex'
23
- import SModal from './SModal.vue'
24
-
25
- const route = useRoute()
26
- const store = useStore()
27
-
28
- const items = computed(() => store.state.modal.items)
29
- const hasItem = computed(() => items.value.length > 0)
30
-
31
- const isActive = ref(false)
32
-
33
- let timer: any
34
-
35
- watch(hasItem, (value) => {
36
- clearTimeout(timer)
37
-
38
- value
39
- ? (isActive.value = true)
40
- : (timer = setTimeout(() => { isActive.value = false }, 250))
41
- })
42
-
43
- watch(route, closeAll)
44
-
45
- function close(id?: number) {
46
- store.dispatch('modal/close', id)
47
- }
48
-
49
- function closeAll() {
50
- store.dispatch('modal/closeAll')
51
- }
52
- </script>
53
-
54
- <style scoped lang="postcss">
55
- .SPortalModals {
56
- position: fixed;
57
- top: 0;
58
- right: 0;
59
- bottom: 0;
60
- left: 0;
61
- z-index: var(--z-index-backdrop);
62
- background-color: rgba(0, 0, 0, .8);
63
- }
64
-
65
- .SPortalModals.fade-enter-active,
66
- .SPortalModals.fade-leave-active {
67
- transition: opacity .25s;
68
- }
69
-
70
- .SPortalModals.fade-enter-from,
71
- .SPortalModals.fade-leave-to {
72
- opacity: 0;
73
- }
74
- </style>
@@ -1,38 +0,0 @@
1
- import { useStore } from 'vuex'
2
- import { useModalId } from './Modal'
3
-
4
- export interface Dialog {
5
- open(dialog?: Options): Promise<any>
6
- close(): Promise<any>
7
- }
8
-
9
- export interface Options {
10
- type?: 'confirm' | 'loading'
11
- title?: string
12
- text?: string
13
- actions?: Action[]
14
- }
15
-
16
- export interface Action {
17
- type?: 'primary' | 'mute'
18
- label: string
19
- callback(): void
20
- }
21
-
22
- export function useDialog(): Dialog {
23
- const store = useStore()
24
- const id = useModalId()
25
-
26
- function open(options?: Options) {
27
- return store.dispatch('dialog/open', { ...options, id })
28
- }
29
-
30
- function close() {
31
- return store.dispatch('dialog/close', id)
32
- }
33
-
34
- return {
35
- open,
36
- close
37
- }
38
- }
@@ -1,34 +0,0 @@
1
- import { useStore } from 'vuex'
2
-
3
- export interface Modal {
4
- open(data?: Record<string, any>): Promise<any>
5
- close(): Promise<any>
6
- }
7
-
8
- let modalId = 0
9
-
10
- export function useModal(component: any): Modal {
11
- const store = useStore()
12
- const id = useModalId()
13
-
14
- function open(data: Record<string, any> = {}): Promise<any> {
15
- return store.dispatch('modal/open', {
16
- id,
17
- component,
18
- data
19
- })
20
- }
21
-
22
- function close() {
23
- return store.dispatch('modal/close', id)
24
- }
25
-
26
- return {
27
- open,
28
- close
29
- }
30
- }
31
-
32
- export function useModalId(): number {
33
- return ++modalId
34
- }
@@ -1,18 +0,0 @@
1
- import { useStore } from 'vuex'
2
- import { Snackbar as SnackbarOptions } from '../store/snackbars'
3
-
4
- export interface Snackbar {
5
- push(options: SnackbarOptions): void
6
- }
7
-
8
- export function useSnackbar(): Snackbar {
9
- const store = useStore()
10
-
11
- function push(options: SnackbarOptions): void {
12
- store.dispatch('snackbars/push', options)
13
- }
14
-
15
- return {
16
- push
17
- }
18
- }
@@ -1,17 +0,0 @@
1
- import { Store, Plugin } from 'vuex'
2
- import modal, { State as ModalState } from './modal'
3
- import dialog from './dialog'
4
- import snackbars, { State as SnackbarsState } from './snackbars'
5
-
6
- export interface State {
7
- modal: ModalState
8
- snackbars: SnackbarsState
9
- }
10
-
11
- export function Sefirot<S = any>(): Plugin<S> {
12
- return (store) => {
13
- store.registerModule('modal', modal)
14
- store.registerModule('dialog', dialog)
15
- store.registerModule('snackbars', snackbars)
16
- }
17
- }
@@ -1,42 +0,0 @@
1
- import { ActionTree, ActionContext } from 'vuex'
2
- import SDialog from '../../components/SDialog.vue'
3
-
4
- export interface OpenPayload {
5
- id?: number
6
- type?: 'confirm' | 'loading'
7
- title?: string
8
- text?: string
9
- actions?: Action[]
10
- }
11
-
12
- export interface Action {
13
- type?: 'text' | 'mute'
14
- label: string
15
- callback(): void
16
- }
17
-
18
- export const actions: ActionTree<any, any> = {
19
- open(context: ActionContext<any, any>, payload: OpenPayload): void {
20
- const { id } = payload
21
-
22
- delete payload.id
23
-
24
- context.dispatch('modal/open', {
25
- id,
26
- component: SDialog,
27
- data: payload,
28
- options: {
29
- closable: false
30
- }
31
- }, { root: true })
32
- },
33
-
34
- close(context: ActionContext<any, any>, uid?: number): void {
35
- context.dispatch('modal/close', uid, { root: true })
36
- }
37
- }
38
-
39
- export default {
40
- namespaced: true,
41
- actions
42
- }
@@ -1,61 +0,0 @@
1
- import { shallowReactive, markRaw } from 'vue'
2
- import { ActionTree, ActionContext, MutationTree } from 'vuex'
3
-
4
- export interface State {
5
- items: Item[]
6
- }
7
-
8
- export interface Item {
9
- id?: number
10
- component: any
11
- data?: Record<string, any>
12
- }
13
-
14
- function state(): State {
15
- return {
16
- items: []
17
- }
18
- }
19
-
20
- const actions: ActionTree<State, any> = {
21
- open(context: ActionContext<State, any>, item: Item): void {
22
- context.commit('push', item)
23
- },
24
-
25
- close(context: ActionContext<State, any>, id?: number): void {
26
- id ? context.commit('drop', id) : context.commit('pop')
27
- },
28
-
29
- closeAll(context: ActionContext<State, any>): void {
30
- context.commit('flush')
31
- }
32
- }
33
-
34
- const mutations: MutationTree<State> = {
35
- push(state: State, item: Item): void {
36
- state.items.push({
37
- ...item,
38
- data: shallowReactive(item.data ?? {}),
39
- component: markRaw(item.component)
40
- })
41
- },
42
-
43
- pop(state: State): void {
44
- state.items.pop()
45
- },
46
-
47
- drop(state: State, id: number) {
48
- state.items = state.items.filter(item => item.id !== id)
49
- },
50
-
51
- flush(state: State): void {
52
- state.items = []
53
- }
54
- }
55
-
56
- export default {
57
- namespaced: true,
58
- state,
59
- actions,
60
- mutations
61
- }