@globalbrain/sefirot 2.0.0-draft.8 → 2.1.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 (182) hide show
  1. package/README.md +6 -6
  2. package/lib/components/SAvatar.vue +17 -17
  3. package/lib/components/SButton.vue +520 -276
  4. package/lib/components/SButtonGroup.vue +149 -0
  5. package/lib/components/SDropdown.vue +26 -150
  6. package/lib/components/SDropdownSection.vue +48 -0
  7. package/lib/components/SDropdownSectionFilter.vue +190 -0
  8. package/lib/components/SDropdownSectionFilterItem.vue +21 -0
  9. package/lib/components/SDropdownSectionFilterItemAvatar.vue +31 -0
  10. package/lib/components/SDropdownSectionFilterItemText.vue +20 -0
  11. package/lib/components/SDropdownSectionMenu.vue +39 -0
  12. package/lib/components/SIcon.vue +13 -0
  13. package/lib/components/SInputBase.vue +31 -31
  14. package/lib/components/SInputCheckbox.vue +4 -3
  15. package/lib/components/SInputCheckboxes.vue +74 -0
  16. package/lib/components/SInputDate.vue +182 -0
  17. package/lib/components/SInputDropdown.vue +159 -157
  18. package/lib/components/SInputDropdownItem.vue +46 -48
  19. package/lib/components/SInputDropdownItemAvatar.vue +99 -0
  20. package/lib/components/SInputDropdownItemText.vue +79 -16
  21. package/lib/components/SInputFile.vue +56 -60
  22. package/lib/components/SInputHMS.vue +120 -110
  23. package/lib/components/SInputNumber.vue +38 -9
  24. package/lib/components/SInputRadio.vue +39 -36
  25. package/lib/components/SInputRadios.vue +40 -53
  26. package/lib/components/SInputSelect.vue +7 -6
  27. package/lib/components/SInputSwitch.vue +193 -0
  28. package/lib/components/SInputSwitches.vue +88 -0
  29. package/lib/components/SInputText.vue +207 -62
  30. package/lib/components/SInputTextarea.vue +46 -32
  31. package/lib/components/SInputYMD.vue +123 -126
  32. package/lib/components/SMarkdown.vue +52 -0
  33. package/lib/components/SModal.vue +33 -57
  34. package/lib/components/SMount.vue +19 -0
  35. package/lib/components/SSheet.vue +50 -55
  36. package/lib/components/SSheetFooter.vue +1 -1
  37. package/lib/components/SSheetFooterAction.vue +24 -17
  38. package/lib/components/SSheetFooterActions.vue +1 -4
  39. package/lib/components/SSheetForm.vue +15 -0
  40. package/lib/components/SSheetMedium.vue +8 -10
  41. package/lib/components/SSheetTitle.vue +7 -14
  42. package/lib/components/SSnackbar.vue +58 -47
  43. package/lib/components/{SPortalSnackbars.vue → SSnackbars.vue} +17 -20
  44. package/lib/components/{icons/SIconPreloader.vue → SSpinner.vue} +5 -4
  45. package/lib/components/SStep.vue +107 -0
  46. package/lib/components/SSteps.vue +59 -0
  47. package/lib/components/STable.vue +242 -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 +103 -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 +5 -9
  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 +59 -37
  81. package/CHANGELOG.md +0 -47
  82. package/lib/.DS_Store +0 -0
  83. package/lib/components/.DS_Store +0 -0
  84. package/lib/components/SDialog.vue +0 -140
  85. package/lib/components/SDropdownItem.vue +0 -78
  86. package/lib/components/SDropdownItemText.vue +0 -22
  87. package/lib/components/SDropdownItemUser.vue +0 -40
  88. package/lib/components/SInputDropdownItemTextTag.vue +0 -94
  89. package/lib/components/SInputDropdownItemUser.vue +0 -41
  90. package/lib/components/SInputDropdownItemUserTag.vue +0 -100
  91. package/lib/components/SPortalModals.vue +0 -74
  92. package/lib/components/icons/.DS_Store +0 -0
  93. package/lib/components/icons/SIconActivity.vue +0 -5
  94. package/lib/components/icons/SIconArrowDown.vue +0 -5
  95. package/lib/components/icons/SIconArrowLeft.vue +0 -5
  96. package/lib/components/icons/SIconArrowRight.vue +0 -5
  97. package/lib/components/icons/SIconArrowUp.vue +0 -5
  98. package/lib/components/icons/SIconBarChart.vue +0 -7
  99. package/lib/components/icons/SIconBriefcase.vue +0 -5
  100. package/lib/components/icons/SIconBuilding.vue +0 -5
  101. package/lib/components/icons/SIconCalendar.vue +0 -5
  102. package/lib/components/icons/SIconCheck.vue +0 -5
  103. package/lib/components/icons/SIconCheckCircle.vue +0 -6
  104. package/lib/components/icons/SIconCheckCircleThin.vue +0 -6
  105. package/lib/components/icons/SIconCheckSquare.vue +0 -6
  106. package/lib/components/icons/SIconChevronDown.vue +0 -5
  107. package/lib/components/icons/SIconChevronLeft.vue +0 -5
  108. package/lib/components/icons/SIconChevronRight.vue +0 -5
  109. package/lib/components/icons/SIconChevronUp.vue +0 -5
  110. package/lib/components/icons/SIconClock.vue +0 -6
  111. package/lib/components/icons/SIconCode.vue +0 -6
  112. package/lib/components/icons/SIconDatabase.vue +0 -5
  113. package/lib/components/icons/SIconDollarSign.vue +0 -5
  114. package/lib/components/icons/SIconDownload.vue +0 -6
  115. package/lib/components/icons/SIconDownloadCloud.vue +0 -6
  116. package/lib/components/icons/SIconEdit.vue +0 -6
  117. package/lib/components/icons/SIconEdit2.vue +0 -5
  118. package/lib/components/icons/SIconEdit3.vue +0 -6
  119. package/lib/components/icons/SIconEdit3Off.vue +0 -6
  120. package/lib/components/icons/SIconExternalLink.vue +0 -6
  121. package/lib/components/icons/SIconEye.vue +0 -6
  122. package/lib/components/icons/SIconFile.vue +0 -5
  123. package/lib/components/icons/SIconFilePlus.vue +0 -6
  124. package/lib/components/icons/SIconFileText.vue +0 -8
  125. package/lib/components/icons/SIconFlag.vue +0 -5
  126. package/lib/components/icons/SIconGitBranch.vue +0 -5
  127. package/lib/components/icons/SIconGitCommit.vue +0 -5
  128. package/lib/components/icons/SIconGitPullRequest.vue +0 -6
  129. package/lib/components/icons/SIconGlobe.vue +0 -5
  130. package/lib/components/icons/SIconGrab.vue +0 -10
  131. package/lib/components/icons/SIconGrid.vue +0 -8
  132. package/lib/components/icons/SIconHome.vue +0 -5
  133. package/lib/components/icons/SIconImage.vue +0 -6
  134. package/lib/components/icons/SIconInbox.vue +0 -5
  135. package/lib/components/icons/SIconInfo.vue +0 -7
  136. package/lib/components/icons/SIconLayout.vue +0 -5
  137. package/lib/components/icons/SIconList.vue +0 -10
  138. package/lib/components/icons/SIconLock.vue +0 -5
  139. package/lib/components/icons/SIconLogout.vue +0 -6
  140. package/lib/components/icons/SIconMail.vue +0 -6
  141. package/lib/components/icons/SIconMapPin.vue +0 -6
  142. package/lib/components/icons/SIconMoon.vue +0 -5
  143. package/lib/components/icons/SIconMoreHorizontal.vue +0 -7
  144. package/lib/components/icons/SIconMoreVertical.vue +0 -7
  145. package/lib/components/icons/SIconPauseFill.vue +0 -6
  146. package/lib/components/icons/SIconPlayCircle.vue +0 -6
  147. package/lib/components/icons/SIconPlayFill.vue +0 -5
  148. package/lib/components/icons/SIconPlus.vue +0 -5
  149. package/lib/components/icons/SIconPlusCircle.vue +0 -8
  150. package/lib/components/icons/SIconPlusOff.vue +0 -7
  151. package/lib/components/icons/SIconPreloaderDark.vue +0 -52
  152. package/lib/components/icons/SIconPreloaderLight.vue +0 -52
  153. package/lib/components/icons/SIconProgress.vue +0 -5
  154. package/lib/components/icons/SIconRadio.vue +0 -6
  155. package/lib/components/icons/SIconSave.vue +0 -5
  156. package/lib/components/icons/SIconSearch.vue +0 -5
  157. package/lib/components/icons/SIconSend.vue +0 -5
  158. package/lib/components/icons/SIconSettings.vue +0 -6
  159. package/lib/components/icons/SIconShare2.vue +0 -5
  160. package/lib/components/icons/SIconSkipBackFill.vue +0 -6
  161. package/lib/components/icons/SIconSliders.vue +0 -12
  162. package/lib/components/icons/SIconSun.vue +0 -13
  163. package/lib/components/icons/SIconTelescope.vue +0 -5
  164. package/lib/components/icons/SIconTrash.vue +0 -5
  165. package/lib/components/icons/SIconTrash2.vue +0 -7
  166. package/lib/components/icons/SIconTrash2Off.vue +0 -6
  167. package/lib/components/icons/SIconTrello.vue +0 -7
  168. package/lib/components/icons/SIconUser.vue +0 -6
  169. package/lib/components/icons/SIconUsers.vue +0 -8
  170. package/lib/components/icons/SIconWarning.vue +0 -7
  171. package/lib/components/icons/SIconX.vue +0 -5
  172. package/lib/components/icons/SIconXCircle.vue +0 -6
  173. package/lib/components/icons/SIconXCircleThin.vue +0 -6
  174. package/lib/components/icons/SIconXSquare.vue +0 -6
  175. package/lib/components/icons/SIconZap.vue +0 -5
  176. package/lib/composables/Dialog.ts +0 -38
  177. package/lib/composables/Modal.ts +0 -34
  178. package/lib/composables/Snackbar.ts +0 -18
  179. package/lib/store/Sefirot.ts +0 -17
  180. package/lib/store/dialog/index.ts +0 -42
  181. package/lib/store/modal/index.ts +0 -61
  182. package/lib/store/snackbars/index.ts +0 -70
@@ -1,27 +1,34 @@
1
+ <script setup lang="ts">
2
+ import SButton, { Type, Mode } from './SButton.vue'
3
+
4
+ defineProps<{
5
+ type?: Type
6
+ mode?: Mode
7
+ label: string
8
+ loading?: boolean
9
+ }>()
10
+
11
+ defineEmits<{
12
+ (e: 'click'): void
13
+ }>()
14
+ </script>
15
+
1
16
  <template>
2
17
  <div class="SSheetFooterAction">
3
18
  <SButton
4
- size="small"
5
- :type="type ?? 'primary'"
6
- :mode="mode ?? 'neutral'"
19
+ size="medium"
20
+ :type="type"
21
+ :mode="mode"
7
22
  :label="label"
23
+ :loading="loading"
8
24
  block
9
25
  @click="$emit('click')"
10
26
  />
11
27
  </div>
12
28
  </template>
13
29
 
14
- <script setup lang="ts">
15
- import SButton from './SButton.vue'
16
-
17
- type Type = 'primary' | 'secondary' | 'tertiary' | 'text' | 'mute'
18
- type Mode = 'neutral' | 'info' | 'success' | 'warning' | 'danger'
19
-
20
- defineProps<{
21
- type?: Type
22
- mode?: Mode
23
- label?: string
24
- }>()
25
-
26
- defineEmits(['click'])
27
- </script>
30
+ <style scoped lang="postcss">
31
+ .SSheetFooterAction {
32
+ min-width: 88px;
33
+ }
34
+ </style>
@@ -8,10 +8,7 @@
8
8
  .SSheetFooterActions {
9
9
  display: flex;
10
10
  justify-content: flex-end;
11
+ gap: 12px;
11
12
  padding: 16px 0 15px;
12
13
  }
13
-
14
- .SSheetFooterActions :deep(.SSheetFooterAction + .SSheetFooterAction) {
15
- padding-left: 8px;
16
- }
17
14
  </style>
@@ -0,0 +1,15 @@
1
+ <template>
2
+ <div class="SSheetForm">
3
+ <slot />
4
+ </div>
5
+ </template>
6
+
7
+ <style scoped lang="postcss">
8
+ .SSheetForm {
9
+ padding: 32px;
10
+
11
+ .SSheetTitle + & {
12
+ padding-top: 16px;
13
+ }
14
+ }
15
+ </style>
@@ -4,20 +4,17 @@
4
4
  </div>
5
5
  </template>
6
6
 
7
- <style lang="postcss" scoped>
7
+ <style scoped lang="postcss">
8
8
  .SSheetMedium {
9
- padding: 12px 16px 20px;
9
+ padding: 32px;
10
10
 
11
- @media (min-width: 512px) {
12
- padding: 16px 24px 26px;
11
+ .SSheetTitle + & {
12
+ padding-top: 0;
13
13
  }
14
14
  }
15
15
 
16
16
  .SSheetMedium :deep(p) {
17
- margin: 16px 0;
18
- line-height: 24px;
19
- font-size: 14px;
20
- font-weight: 400;
17
+ margin-bottom: 16px;
21
18
  }
22
19
 
23
20
  .SSheetMedium :deep(p:first-child) {
@@ -49,7 +46,7 @@
49
46
  .SSheetMedium :deep(li) {
50
47
  position: relative;
51
48
  padding-left: 20px;
52
- font-size: 14px;
49
+ font-size: 16px;
53
50
  font-weight: 400;
54
51
  }
55
52
 
@@ -65,10 +62,11 @@
65
62
  }
66
63
 
67
64
  .SSheetMedium :deep(li + li) {
68
- margin-top: 4px;
65
+ margin-top: 8px;
69
66
  }
70
67
 
71
68
  .SSheetMedium :deep(li > ul) {
72
69
  margin: 4px 0 0;
70
+ margin-bottom: 16px;
73
71
  }
74
72
  </style>
@@ -1,20 +1,13 @@
1
1
  <template>
2
- <header class="SSheetTitle">
3
- <h1 class="title">
4
- <slot />
5
- </h1>
6
- </header>
2
+ <div class="SSheetTitle">
3
+ <p class="title"><slot /></p>
4
+ </div>
7
5
  </template>
8
6
 
9
- <style lang="postcss" scoped>
10
- .title {
11
- padding: 20px 48px 0 16px;
12
- line-height: 28px;
7
+ <style scoped lang="postcss">
8
+ .SSheetTitle {
9
+ padding: 32px 32px 16px;
13
10
  font-size: 20px;
14
- font-weight: 500;
15
-
16
- @media (min-width: 512px) {
17
- padding: 24px 64px 0 24px;
18
- }
11
+ font-weight: 600;
19
12
  }
20
13
  </style>
@@ -1,77 +1,85 @@
1
+ <script setup lang="ts">
2
+ import IconX from '@iconify-icons/ph/x'
3
+ import { SnackbarAction, useSnackbars } from '../stores/Snackbars'
4
+ import SButton from './SButton.vue'
5
+ import SIcon from './SIcon.vue'
6
+
7
+ const props = defineProps<{
8
+ id: number
9
+ mode?: 'neutral' | 'info' | 'warning' | 'danger'
10
+ text: string
11
+ actions?: SnackbarAction[]
12
+ }>()
13
+
14
+ const snackbars = useSnackbars()
15
+
16
+ function close() {
17
+ snackbars.pop(props.id)
18
+ }
19
+ </script>
20
+
1
21
  <template>
2
- <div class="SSnackbar">
22
+ <div class="SSnackbar" :class="[mode ?? 'neutral']">
3
23
  <button class="close" @click="close">
4
- <SIconX class="close-icon" />
24
+ <SIcon :icon="IconX" class="close-icon" />
5
25
  </button>
6
26
 
7
- <p class="content">{{ text }}</p>
27
+ <p class="content">
28
+ {{ text }}
29
+ </p>
8
30
 
9
31
  <div v-if="actions" class="actions">
10
32
  <div v-for="(action, index) in actions" :key="index" class="action">
11
33
  <SButton
12
- :type="action.type"
34
+ size="medium"
35
+ type="text"
13
36
  :label="action.label"
14
- inverse
15
- @click="handleCallback(action)"
37
+ @click="action.onClick"
16
38
  />
17
39
  </div>
18
40
  </div>
19
41
  </div>
20
42
  </template>
21
43
 
22
- <script setup lang="ts">
23
- import { PropType } from 'vue'
24
- import { useStore } from 'vuex'
25
- import { Action } from '../store/snackbars'
26
- import SIconX from './icons/SIconX.vue'
27
- import SButton from './SButton.vue'
28
-
29
- const props = defineProps({
30
- id: { type: Number, required: true },
31
- text: { type: String, required: true },
32
- actions: { type: Array as PropType<Action[]>, default: null }
33
- })
34
-
35
- const store = useStore()
36
-
37
- function close() {
38
- store.dispatch('snackbars/pop', props.id)
39
- }
40
-
41
- function handleCallback(action: Action) {
42
- action.callback()
43
- }
44
- </script>
45
-
46
- <style lang="postcss" scoped>
44
+ <style scoped lang="postcss">
47
45
  .SSnackbar {
48
46
  position: relative;
49
- border: 1px solid transparent;
50
- border-radius: 4px;
47
+ border: 1px solid var(--c-divider-light);
48
+ border-radius: 6px;
51
49
  width: 100%;
52
- color: var(--c-text-dark-1);
53
- background-color: rgba(0, 0, 0, .9);
54
- box-shadow: var(--shadow-depth-5);
55
- }
50
+ background-color: var(--c-bg-elv-up);
51
+ box-shadow: var(--shadow-depth-3);
52
+ overflow: hidden;
53
+
54
+ &::before {
55
+ position: absolute;
56
+ top: 0;
57
+ left: 0;
58
+ bottom: 0;
59
+ width: 3px;
60
+ content: "";
61
+ }
56
62
 
57
- .dark .SSnackbar {
58
- border-color: var(--c-divider-light);
63
+ &.neutral::before { background-color: var(--c-gray); }
64
+ &.info::before { background-color: var(--c-info); }
65
+ &.warning::before { background-color: var(--c-warning); }
66
+ &.danger::before { background-color: var(--c-danger); }
59
67
  }
60
68
 
61
69
  .close {
62
70
  position: absolute;
63
- top: 4px;
64
- right: 4px;
71
+ top: 2px;
72
+ right: 0;
65
73
  z-index: 20;
66
74
  display: flex;
67
75
  justify-content: center;
68
76
  align-items: center;
69
77
  width: 48px;
70
- height: 48px;
78
+ height: 45px;
71
79
 
72
80
  &:hover {
73
81
  .close-icon {
74
- fill: var(--c-text-dark-1);
82
+ color: var(--c-text-1);
75
83
  }
76
84
  }
77
85
  }
@@ -79,26 +87,29 @@ function handleCallback(action: Action) {
79
87
  .close-icon {
80
88
  width: 16px;
81
89
  height: 16px;
82
- fill: var(--c-text-dark-2);
83
- transition: fill .25s;
90
+ color: var(--c-text-3);
91
+ transition: color .25s;
84
92
  }
85
93
 
86
94
  .content {
87
95
  position: relative;
88
96
  z-index: 10;
89
- padding: 16px 68px 16px 20px;
97
+ padding: 14px 68px 14px 16px;
98
+ line-height: 20px;
90
99
  font-size: 14px;
100
+ color: var(--c-text-1);
91
101
  }
92
102
 
93
103
  .actions {
94
104
  display: flex;
95
105
  justify-content: flex-end;
106
+ margin-top: -8px;
96
107
  padding: 0 8px 8px;
97
108
  }
98
109
 
99
110
  .action {
100
111
  & + & {
101
- padding-left: 8px;
112
+ padding-left: 4px;
102
113
  }
103
114
  }
104
115
  </style>
@@ -1,10 +1,18 @@
1
+ <script setup lang="ts">
2
+ import { useSnackbars } from '../stores/Snackbars'
3
+ import SSnackbar from './SSnackbar.vue'
4
+
5
+ const snackbars = useSnackbars()
6
+ </script>
7
+
1
8
  <template>
2
9
  <transition name="fade">
3
- <div v-if="hasItem" class="SPortalSnackbars">
10
+ <div v-if="snackbars.items.length" class="SSnackbars">
4
11
  <transition-group name="fade-up">
5
- <div v-for="item in items" :key="item.id" class="item">
12
+ <div v-for="item in snackbars.items" :key="item.id" class="item">
6
13
  <SSnackbar
7
14
  :id="item.id"
15
+ :mode="item.mode"
8
16
  :text="item.text"
9
17
  :actions="item.actions"
10
18
  />
@@ -14,19 +22,8 @@
14
22
  </transition>
15
23
  </template>
16
24
 
17
- <script setup lang="ts">
18
- import { computed } from 'vue'
19
- import { useStore } from 'vuex'
20
- import SSnackbar from './SSnackbar.vue'
21
-
22
- const store = useStore()
23
-
24
- const items = computed(() => store.state.snackbars.items)
25
- const hasItem = computed(() => items.value.length > 0)
26
- </script>
27
-
28
25
  <style lang="postcss" scoped>
29
- .SPortalSnackbars {
26
+ .SSnackbars {
30
27
  position: fixed;
31
28
  bottom: 0;
32
29
  left: 0;
@@ -34,26 +31,26 @@ const hasItem = computed(() => items.value.length > 0)
34
31
  padding: 16px;
35
32
  width: 100%;
36
33
  max-width: 560px;
37
- transition: opacity .25s, transform .25s;
34
+ transition: opacity 0.25s, transform 0.25s;
38
35
 
39
36
  @media (min-width: 768px) {
40
37
  padding: 24px;
41
38
  }
42
39
  }
43
40
 
44
- .SPortalSnackbars.fade-enter-from {
41
+ .SSnackbars.fade-enter-from {
45
42
  opacity: 0;
46
- transform: translateY(48px);
43
+ transform: translateY(24px);
47
44
  }
48
45
 
49
- .SPortalSnackbars.fade-leave-to {
46
+ .SSnackbars.fade-leave-to {
50
47
  opacity: 0;
51
48
  }
52
49
 
53
50
  .item {
54
51
  width: 100%;
55
52
  max-width: 512px;
56
- transition: opacity .25s, transform .25s;
53
+ transition: opacity 0.25s, transform 0.25s;
57
54
 
58
55
  & + & {
59
56
  padding-top: 8px;
@@ -70,6 +67,6 @@ const hasItem = computed(() => items.value.length > 0)
70
67
  }
71
68
 
72
69
  .item.fade-up-enter-from {
73
- transform: translateY(48px);
70
+ transform: translateY(24px);
74
71
  }
75
72
  </style>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid">
2
+ <svg class="SSpinner" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid">
3
3
  <g transform="rotate(0 50 50)">
4
4
  <rect
5
5
  class="bar"
@@ -228,12 +228,13 @@
228
228
  repeatCount="indefinite"
229
229
  />
230
230
  </rect>
231
- </g></svg>
231
+ </g>
232
+ </svg>
232
233
  </template>
233
234
 
234
235
  <style lang="postcss" scoped>
235
236
  .bar {
236
- fill: var(--preloader-color);
237
- transition: fill .5s;
237
+ fill: currentColor;
238
+ transition: fill 0.5s;
238
239
  }
239
240
  </style>
@@ -0,0 +1,107 @@
1
+ <template>
2
+ <div class="SStep" :class="[status]">
3
+ <div class="indicator">
4
+ <div class="bar" :class="[barLeft]" />
5
+ <div class="point">
6
+ <div v-if="status === 'active'" class="inner-dot" />
7
+ <SIcon v-else-if="status === 'done'" :icon="IconCheck" class="icon" />
8
+ <SIcon v-else-if="status === 'failed'" :icon="IconX" class="icon" />
9
+ </div>
10
+ <div class="bar" :class="[barRight]" />
11
+ </div>
12
+
13
+ <p v-if="text" class="text">{{ text }}</p>
14
+ </div>
15
+ </template>
16
+
17
+ <script setup lang="ts">
18
+ import IconCheck from '@iconify-icons/ph/check'
19
+ import IconX from '@iconify-icons/ph/x'
20
+ import { PropType } from 'vue'
21
+ import { StepStatus, BarMode } from '../composables/Step'
22
+ import SIcon from './SIcon.vue'
23
+
24
+ defineProps({
25
+ status: { type: String as PropType<StepStatus>, required: true },
26
+ barLeft: { type: String as PropType<BarMode | null>, default: null },
27
+ barRight: { type: String as PropType<BarMode | null>, default: null },
28
+ text: { type: String, default: null }
29
+ })
30
+ </script>
31
+
32
+ <style lang="postcss" scoped>
33
+ .SStep.upcoming {
34
+ .point { border-color: var(--c-divider); }
35
+ .text { color: var(--c-text-2); }
36
+ }
37
+
38
+ .SStep.active {
39
+ .point { border-color: var(--c-success); }
40
+ .text { color: var(--c-success); }
41
+ }
42
+
43
+ .SStep.done {
44
+ .point {
45
+ border-color: var(--c-success);
46
+ background-color: var(--c-success);
47
+ }
48
+
49
+ .text { color: var(--c-text-1); }
50
+ }
51
+
52
+ .SStep.failed {
53
+ .point {
54
+ border-color: var(--c-danger);
55
+ background-color: var(--c-danger);
56
+ }
57
+
58
+ .text { color: var(--c-danger); }
59
+ }
60
+
61
+ .indicator {
62
+ display: flex;
63
+ align-items: center;
64
+ width: 100%;
65
+ }
66
+
67
+ .point {
68
+ display: flex;
69
+ justify-content: center;
70
+ align-items: center;
71
+ border: 1px solid transparent;
72
+ border-radius: 50%;
73
+ width: 16px;
74
+ height: 16px;
75
+ }
76
+
77
+ .inner-dot {
78
+ border-radius: 50%;
79
+ width: 6px;
80
+ height: 6px;
81
+ background-color: var(--c-success);
82
+ }
83
+
84
+ .icon {
85
+ width: 10px;
86
+ height: 10px;
87
+ color: var(--c-white);
88
+ }
89
+
90
+ .bar {
91
+ width: calc(50% - 8px);
92
+ height: 2px;
93
+ }
94
+
95
+ .bar.mute { background-color: var(--c-divider-light); }
96
+ .bar.active { background-color: var(--c-success); }
97
+ .bar.failed { background-color: var(--c-danger); }
98
+
99
+ .text {
100
+ margin: 0;
101
+ padding: 8px 8px 0;
102
+ text-align: center;
103
+ line-height: 16px;
104
+ font-size: 12px;
105
+ font-weight: 500;
106
+ }
107
+ </style>
@@ -0,0 +1,59 @@
1
+ <template>
2
+ <div class="SSteps">
3
+ <SStep
4
+ v-for="(step, index) in steps"
5
+ :key="index"
6
+ class="item"
7
+ :style="{ width }"
8
+ :bar-left="getBarLeftMode(index)"
9
+ :bar-right="getBarRightMode(index)"
10
+ v-bind="step"
11
+ />
12
+ </div>
13
+ </template>
14
+
15
+ <script setup lang="ts">
16
+ import { computed, PropType } from 'vue'
17
+ import { Step, BarMode } from '../composables/Step'
18
+ import SStep from './SStep.vue'
19
+
20
+ const props = defineProps({
21
+ steps: { type: Array as PropType<Step[]>, required: true }
22
+ })
23
+
24
+ const width = computed(() => {
25
+ return `calc(100% / ${props.steps.length})`
26
+ })
27
+
28
+ function getBarLeftMode(index: number): BarMode | null {
29
+ if (index === 0) {
30
+ return null
31
+ }
32
+
33
+ const current = props.steps[index]
34
+ const prev = props.steps[index - 1]
35
+
36
+ return isActive(prev) && isActive(current) ? 'active' : 'mute'
37
+ }
38
+
39
+ function getBarRightMode(index: number): BarMode | null {
40
+ if (index === props.steps.length - 1) {
41
+ return null
42
+ }
43
+
44
+ const current = props.steps[index]
45
+ const next = props.steps[index + 1]
46
+
47
+ return isActive(current) && isActive(next) ? 'active' : 'mute'
48
+ }
49
+
50
+ function isActive(step: Step): boolean {
51
+ return step.status === 'active' || step.status === 'done'
52
+ }
53
+ </script>
54
+
55
+ <style lang="postcss" scoped>
56
+ .SSteps {
57
+ display: flex;
58
+ }
59
+ </style>