@globalbrain/sefirot 2.0.0-draft.8 → 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 (97) hide show
  1. package/README.md +6 -6
  2. package/lib/components/SAvatar.vue +17 -17
  3. package/lib/components/SButton.vue +512 -267
  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 +189 -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 +1 -1
  15. package/lib/components/SInputCheckboxes.vue +74 -0
  16. package/lib/components/SInputDate.vue +182 -0
  17. package/lib/components/SInputDropdown.vue +158 -157
  18. package/lib/components/SInputDropdownItem.vue +46 -48
  19. package/lib/components/{SInputDropdownItemUserTag.vue → SInputDropdownItemAvatar.vue} +43 -44
  20. package/lib/components/SInputDropdownItemText.vue +79 -16
  21. package/lib/components/SInputFile.vue +55 -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 +3 -3
  27. package/lib/components/SInputSwitch.vue +193 -0
  28. package/lib/components/SInputSwitches.vue +88 -0
  29. package/lib/components/SInputText.vue +206 -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 +25 -63
  34. package/lib/components/SMount.vue +19 -0
  35. package/lib/components/SSheet.vue +49 -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 +55 -45
  43. package/lib/components/{SPortalSnackbars.vue → SSnackbars.vue} +17 -20
  44. package/lib/components/SStep.vue +106 -0
  45. package/lib/components/SSteps.vue +59 -0
  46. package/lib/components/STable.vue +241 -0
  47. package/lib/components/STableCell.vue +82 -0
  48. package/lib/components/STableCellAvatar.vue +69 -0
  49. package/lib/components/STableCellAvatars.vue +93 -0
  50. package/lib/components/STableCellDay.vue +40 -0
  51. package/lib/components/STableCellPill.vue +84 -0
  52. package/lib/components/STableCellText.vue +102 -0
  53. package/lib/components/STableColumn.vue +255 -0
  54. package/lib/components/STableFooter.vue +115 -0
  55. package/lib/components/STableHeader.vue +74 -0
  56. package/lib/components/STableItem.vue +38 -0
  57. package/lib/components/STooltip.vue +112 -0
  58. package/lib/composables/Dropdown.ts +40 -99
  59. package/lib/composables/Form.ts +21 -18
  60. package/lib/composables/Grid.ts +117 -0
  61. package/lib/composables/Markdown.ts +138 -0
  62. package/lib/composables/Step.ts +7 -0
  63. package/lib/composables/Table.ts +103 -0
  64. package/lib/composables/Tooltip.ts +91 -0
  65. package/lib/composables/Validation.ts +5 -9
  66. package/lib/composables/markdown/LinkPlugin.ts +45 -0
  67. package/lib/mixins/Sheet.ts +5 -3
  68. package/lib/stores/Snackbars.ts +48 -0
  69. package/lib/{assets/styles → styles}/base.css +0 -0
  70. package/lib/{assets/styles → styles}/bootstrap.css +1 -0
  71. package/lib/{assets/styles → styles}/variables.css +55 -48
  72. package/lib/support/Day.ts +8 -0
  73. package/lib/support/Num.ts +3 -0
  74. package/lib/support/Time.ts +5 -2
  75. package/lib/support/Utils.ts +4 -3
  76. package/lib/types/shims.d.ts +3 -0
  77. package/lib/validation/validators/requiredYmd.ts +1 -1
  78. package/lib/validation/validators/ymd.ts +4 -4
  79. package/package.json +57 -37
  80. package/CHANGELOG.md +0 -47
  81. package/lib/.DS_Store +0 -0
  82. package/lib/components/.DS_Store +0 -0
  83. package/lib/components/SDialog.vue +0 -140
  84. package/lib/components/SDropdownItem.vue +0 -78
  85. package/lib/components/SDropdownItemText.vue +0 -22
  86. package/lib/components/SDropdownItemUser.vue +0 -40
  87. package/lib/components/SInputDropdownItemTextTag.vue +0 -94
  88. package/lib/components/SInputDropdownItemUser.vue +0 -41
  89. package/lib/components/SPortalModals.vue +0 -74
  90. package/lib/components/icons/.DS_Store +0 -0
  91. package/lib/composables/Dialog.ts +0 -38
  92. package/lib/composables/Modal.ts +0 -34
  93. package/lib/composables/Snackbar.ts +0 -18
  94. package/lib/store/Sefirot.ts +0 -17
  95. package/lib/store/dialog/index.ts +0 -42
  96. package/lib/store/modal/index.ts +0 -61
  97. 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,84 @@
1
+ <script setup lang="ts">
2
+ import { SnackbarAction, useSnackbars } from '../stores/Snackbars'
3
+ import SButton from './SButton.vue'
4
+ import SIconX from './icons/SIconX.vue'
5
+
6
+ const props = defineProps<{
7
+ id: number
8
+ mode?: 'neutral' | 'info' | 'warning' | 'danger'
9
+ text: string
10
+ actions?: SnackbarAction[]
11
+ }>()
12
+
13
+ const snackbars = useSnackbars()
14
+
15
+ function close() {
16
+ snackbars.pop(props.id)
17
+ }
18
+ </script>
19
+
1
20
  <template>
2
- <div class="SSnackbar">
21
+ <div class="SSnackbar" :class="[mode ?? 'neutral']">
3
22
  <button class="close" @click="close">
4
23
  <SIconX class="close-icon" />
5
24
  </button>
6
25
 
7
- <p class="content">{{ text }}</p>
26
+ <p class="content">
27
+ {{ text }}
28
+ </p>
8
29
 
9
30
  <div v-if="actions" class="actions">
10
31
  <div v-for="(action, index) in actions" :key="index" class="action">
11
32
  <SButton
12
- :type="action.type"
33
+ size="medium"
34
+ type="text"
13
35
  :label="action.label"
14
- inverse
15
- @click="handleCallback(action)"
36
+ @click="action.onClick"
16
37
  />
17
38
  </div>
18
39
  </div>
19
40
  </div>
20
41
  </template>
21
42
 
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>
43
+ <style scoped lang="postcss">
47
44
  .SSnackbar {
48
45
  position: relative;
49
- border: 1px solid transparent;
50
- border-radius: 4px;
46
+ border: 1px solid var(--c-divider-light);
47
+ border-radius: 6px;
51
48
  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
- }
49
+ background-color: var(--c-bg-elv-up);
50
+ box-shadow: var(--shadow-depth-3);
51
+ overflow: hidden;
52
+
53
+ &::before {
54
+ position: absolute;
55
+ top: 0;
56
+ left: 0;
57
+ bottom: 0;
58
+ width: 3px;
59
+ content: "";
60
+ }
56
61
 
57
- .dark .SSnackbar {
58
- border-color: var(--c-divider-light);
62
+ &.neutral::before { background-color: var(--c-gray); }
63
+ &.info::before { background-color: var(--c-info); }
64
+ &.warning::before { background-color: var(--c-warning); }
65
+ &.danger::before { background-color: var(--c-danger); }
59
66
  }
60
67
 
61
68
  .close {
62
69
  position: absolute;
63
- top: 4px;
64
- right: 4px;
70
+ top: 2px;
71
+ right: 0;
65
72
  z-index: 20;
66
73
  display: flex;
67
74
  justify-content: center;
68
75
  align-items: center;
69
76
  width: 48px;
70
- height: 48px;
77
+ height: 45px;
71
78
 
72
79
  &:hover {
73
80
  .close-icon {
74
- fill: var(--c-text-dark-1);
81
+ fill: var(--c-text-1);
75
82
  }
76
83
  }
77
84
  }
@@ -79,26 +86,29 @@ function handleCallback(action: Action) {
79
86
  .close-icon {
80
87
  width: 16px;
81
88
  height: 16px;
82
- fill: var(--c-text-dark-2);
89
+ fill: var(--c-text-3);
83
90
  transition: fill .25s;
84
91
  }
85
92
 
86
93
  .content {
87
94
  position: relative;
88
95
  z-index: 10;
89
- padding: 16px 68px 16px 20px;
96
+ padding: 14px 68px 14px 16px;
97
+ line-height: 20px;
90
98
  font-size: 14px;
99
+ color: var(--c-text-1);
91
100
  }
92
101
 
93
102
  .actions {
94
103
  display: flex;
95
104
  justify-content: flex-end;
105
+ margin-top: -8px;
96
106
  padding: 0 8px 8px;
97
107
  }
98
108
 
99
109
  .action {
100
110
  & + & {
101
- padding-left: 8px;
111
+ padding-left: 4px;
102
112
  }
103
113
  }
104
114
  </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>
@@ -0,0 +1,106 @@
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
+ <SIconCheck v-else-if="status === 'done'" class="icon" />
8
+ <SIconX v-else-if="status === 'failed'" 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 { PropType } from 'vue'
19
+ import { StepStatus, BarMode } from '../composables/Step'
20
+ import SIconCheck from './icons/SIconCheck.vue'
21
+ import SIconX from './icons/SIconX.vue'
22
+
23
+ defineProps({
24
+ status: { type: String as PropType<StepStatus>, required: true },
25
+ barLeft: { type: String as PropType<BarMode | null>, default: null },
26
+ barRight: { type: String as PropType<BarMode | null>, default: null },
27
+ text: { type: String, default: null }
28
+ })
29
+ </script>
30
+
31
+ <style lang="postcss" scoped>
32
+ .SStep.upcoming {
33
+ .point { border-color: var(--c-divider); }
34
+ .text { color: var(--c-text-2); }
35
+ }
36
+
37
+ .SStep.active {
38
+ .point { border-color: var(--c-success); }
39
+ .text { color: var(--c-success); }
40
+ }
41
+
42
+ .SStep.done {
43
+ .point {
44
+ border-color: var(--c-success);
45
+ background-color: var(--c-success);
46
+ }
47
+
48
+ .text { color: var(--c-text-1); }
49
+ }
50
+
51
+ .SStep.failed {
52
+ .point {
53
+ border-color: var(--c-danger);
54
+ background-color: var(--c-danger);
55
+ }
56
+
57
+ .text { color: var(--c-danger); }
58
+ }
59
+
60
+ .indicator {
61
+ display: flex;
62
+ align-items: center;
63
+ width: 100%;
64
+ }
65
+
66
+ .point {
67
+ display: flex;
68
+ justify-content: center;
69
+ align-items: center;
70
+ border: 1px solid transparent;
71
+ border-radius: 50%;
72
+ width: 16px;
73
+ height: 16px;
74
+ }
75
+
76
+ .inner-dot {
77
+ border-radius: 50%;
78
+ width: 6px;
79
+ height: 6px;
80
+ background-color: var(--c-success);
81
+ }
82
+
83
+ .icon {
84
+ width: 10px;
85
+ height: 10px;
86
+ fill: var(--c-white);
87
+ }
88
+
89
+ .bar {
90
+ width: calc(50% - 8px);
91
+ height: 2px;
92
+ }
93
+
94
+ .bar.mute { background-color: var(--c-divider-light); }
95
+ .bar.active { background-color: var(--c-success); }
96
+ .bar.failed { background-color: var(--c-danger); }
97
+
98
+ .text {
99
+ margin: 0;
100
+ padding: 8px 8px 0;
101
+ text-align: center;
102
+ line-height: 16px;
103
+ font-size: 12px;
104
+ font-weight: 500;
105
+ }
106
+ </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>