@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
@@ -0,0 +1,242 @@
1
+ <script setup lang="ts">
2
+ import { reactive, ref, computed, watch, toRefs } from 'vue'
3
+ import { Table } from '../composables/Table'
4
+ import SSpinner from './SSpinner.vue'
5
+ import STableCell from './STableCell.vue'
6
+ import STableColumn from './STableColumn.vue'
7
+ import STableFooter from './STableFooter.vue'
8
+ import STableHeader from './STableHeader.vue'
9
+ import STableItem from './STableItem.vue'
10
+
11
+ const props = defineProps<{
12
+ options: Table
13
+ }>()
14
+
15
+ const {
16
+ orders,
17
+ columns,
18
+ records,
19
+ total,
20
+ page,
21
+ perPage,
22
+ reset,
23
+ borderless,
24
+ loading,
25
+ onPrev,
26
+ onNext,
27
+ onReset,
28
+ } = toRefs(props.options)
29
+
30
+ const head = ref<HTMLElement | null>(null)
31
+ const body = ref<HTMLElement | null>(null)
32
+
33
+ let headLock = false
34
+ let bodyLock = false
35
+
36
+ const colWidths = reactive<Record<string, string>>({})
37
+
38
+ const showHeader = computed(() => {
39
+ return total?.value !== undefined
40
+ })
41
+
42
+ const showFooter = computed(() => {
43
+ return !loading?.value && page?.value && total?.value
44
+ })
45
+
46
+ watch(() => records?.value, () => {
47
+ headLock = true
48
+ bodyLock = true
49
+ }, { flush: 'pre' })
50
+
51
+ watch(() => records?.value, () => {
52
+ syncScroll(head.value, body.value)
53
+ headLock = false
54
+ bodyLock = false
55
+ }, { flush: 'post' })
56
+
57
+ function syncHeadScroll() {
58
+ bodyLock || syncScroll(head.value, body.value)
59
+ }
60
+
61
+ function syncBodyScroll() {
62
+ headLock || syncScroll(body.value, head.value)
63
+ }
64
+
65
+ function syncScroll(from: HTMLElement | null, to: HTMLElement | null) {
66
+ if (from && to) {
67
+ to.scrollLeft = from.scrollLeft
68
+ }
69
+ }
70
+
71
+ function lockHead(value: boolean) {
72
+ headLock = value
73
+ }
74
+
75
+ function lockBody(value: boolean) {
76
+ bodyLock = value
77
+ }
78
+
79
+ function updateColWidth(key: string, value: string) {
80
+ colWidths[key] = value
81
+ }
82
+ </script>
83
+
84
+ <template>
85
+ <div class="STable" :class="{ borderless }" ref="el">
86
+ <div class="box">
87
+ <STableHeader
88
+ v-if="showHeader"
89
+ :total="total"
90
+ :reset="reset"
91
+ :borderless="borderless"
92
+ :on-reset="onReset"
93
+ />
94
+
95
+ <div class="table" role="grid">
96
+ <div
97
+ class="container head"
98
+ ref="head"
99
+ @mouseenter="lockHead(true)"
100
+ @mouseleave="lockHead(false)"
101
+ @scroll="syncHeadScroll"
102
+ >
103
+ <div class="block">
104
+ <div class="row">
105
+ <STableItem v-for="key in orders" :key="key" :name="key" :width="colWidths[key]">
106
+ <STableColumn
107
+ :name="key"
108
+ :label="columns[key].label"
109
+ :dropdown="columns[key].dropdown"
110
+ @resize="(value) => updateColWidth(key, value)"
111
+ />
112
+ </STableItem>
113
+ </div>
114
+ </div>
115
+ </div>
116
+
117
+ <div
118
+ v-if="!loading && records && records.length"
119
+ class="container body"
120
+ ref="body"
121
+ @mouseenter="lockBody(true)"
122
+ @mouseleave="lockBody(false)"
123
+ @scroll="syncBodyScroll"
124
+ >
125
+ <div class="block">
126
+ <div v-for="(record, rIndex) in records" :key="rIndex" class="row">
127
+ <STableItem v-for="key in orders" :key="key" :name="key" :width="colWidths[key]">
128
+ <STableCell
129
+ :name="key"
130
+ :cell="columns[key].cell"
131
+ :value="record[key]"
132
+ :record="record"
133
+ :records="records"
134
+ />
135
+ </STableItem>
136
+ </div>
137
+ </div>
138
+ </div>
139
+ </div>
140
+
141
+ <div v-if="!loading && records && !records.length" class="missing">
142
+ <p class="missing-text">
143
+ No results matched your search.
144
+ </p>
145
+ </div>
146
+
147
+ <div v-if="loading" class="loading">
148
+ <div class="loading-icon">
149
+ <SSpinner class="loading-svg" />
150
+ </div>
151
+ </div>
152
+
153
+ <STableFooter
154
+ v-if="showFooter"
155
+ :total="total"
156
+ :page="page"
157
+ :per-page="perPage"
158
+ :borderless="borderless"
159
+ :on-prev="onPrev"
160
+ :on-next="onNext"
161
+ />
162
+ </div>
163
+ </div>
164
+ </template>
165
+
166
+ <style scoped lang="postcss">
167
+ .box {
168
+ position: relative;
169
+ border: 1px solid var(--c-divider-light);
170
+ border-radius: 6px;
171
+ width: 100%;
172
+
173
+ .STable.borderless & {
174
+ border-right: 0;
175
+ border-left: 0;
176
+ border-radius: 0;
177
+ }
178
+ }
179
+
180
+ .table {
181
+ position: relative;
182
+ min-width: 100%;
183
+ white-space: nowrap;
184
+ }
185
+
186
+ .container {
187
+ position: static;
188
+ width: 100%;
189
+ min-width: 100%;
190
+ overflow-x: auto;
191
+
192
+ &.head {
193
+ position: var(--table-head-position, static);
194
+ top: var(--table-head-top, auto);
195
+ z-index: 20;
196
+ background-color: var(--bg-elv);
197
+
198
+ &::-webkit-scrollbar {
199
+ display: none;
200
+ }
201
+ }
202
+ }
203
+
204
+ .block {
205
+ display: inline-block;
206
+ min-width: 100%;
207
+ }
208
+
209
+ .row {
210
+ display: flex;
211
+ border-bottom: 1px solid var(--c-divider-light);
212
+ }
213
+
214
+ .missing {
215
+ border-radius: 0 0 6px 6px;
216
+ padding: 48px 32px;
217
+ text-align: center;
218
+ background-color: var(--c-bg-elv-up);
219
+ line-height: 24px;
220
+ font-size: 14px;
221
+ font-weight: 500;
222
+ color: var(--c-text-3);
223
+ }
224
+
225
+ .loading {
226
+ border-radius: 0 0 6px 6px;
227
+ padding: 64px 32px;
228
+ background-color: var(--c-bg-elv-up);
229
+ }
230
+
231
+ .loading-icon {
232
+ margin: 0 auto;
233
+ width: 48px;
234
+ height: 48px;
235
+ }
236
+
237
+ .loading-svg {
238
+ width: 48px;
239
+ height: 48px;
240
+ color: var(--c-text-1);
241
+ }
242
+ </style>
@@ -0,0 +1,82 @@
1
+ <script setup lang="ts">
2
+ import { TableCell } from '../composables/Table'
3
+ import STableCellAvatar from './STableCellAvatar.vue'
4
+ import STableCellAvatars from './STableCellAvatars.vue'
5
+ import STableCellDay from './STableCellDay.vue'
6
+ import STableCellPill from './STableCellPill.vue'
7
+ import STableCellText from './STableCellText.vue'
8
+
9
+ defineProps<{
10
+ name: string
11
+ cell?: TableCell
12
+ value: any
13
+ record: any
14
+ records: Record<string, any>
15
+ }>()
16
+ </script>
17
+
18
+ <template>
19
+ <div class="STableCell" :class="[`col-${name}`]">
20
+ <STableCellText
21
+ v-if="!cell || cell.type === 'text'"
22
+ :value="value"
23
+ :record="record"
24
+ :icon="cell?.icon"
25
+ :getter="cell?.value"
26
+ :link="cell?.link"
27
+ :color="cell?.color"
28
+ :icon-color="cell?.iconColor"
29
+ />
30
+ <STableCellDay
31
+ v-else-if="cell.type === 'day'"
32
+ :value="value"
33
+ :record="record"
34
+ :format="cell.format"
35
+ :color="cell.color"
36
+ />
37
+ <STableCellPill
38
+ v-else-if="cell.type === 'pill'"
39
+ :value="value"
40
+ :record="record"
41
+ :getter="cell.value"
42
+ :color="cell.color"
43
+ />
44
+ <STableCellAvatar
45
+ v-else-if="cell.type === 'avatar'"
46
+ :value="value"
47
+ :record="record"
48
+ :image="cell.image"
49
+ :name="cell.name"
50
+ :link="cell.link"
51
+ :color="cell.color"
52
+ />
53
+ <STableCellAvatars
54
+ v-else-if="cell.type === 'avatars'"
55
+ :value="value"
56
+ :record="record"
57
+ :avatars="cell.avatars"
58
+ :color="cell.color"
59
+ />
60
+ </div>
61
+ </template>
62
+
63
+ <style scoped lang="postcss">
64
+ .STableCell {
65
+ background-color: var(--c-bg-elv-up);
66
+ transition: background-color 0.1s;
67
+ overflow: hidden;
68
+
69
+ .row:hover & {
70
+ background-color: var(--c-bg-elv);
71
+ }
72
+
73
+ .STableItem:first-child & {
74
+ padding-left: var(--table-padding-left);
75
+ }
76
+
77
+ .STableItem:last-child & {
78
+ border-right: 0;
79
+ padding-right: var(--table-padding-right);
80
+ }
81
+ }
82
+ </style>
@@ -0,0 +1,69 @@
1
+ <script setup lang="ts">
2
+ import { computed } from 'vue'
3
+ import SAvatar from './SAvatar.vue'
4
+ import SLink from './SLink.vue'
5
+
6
+ const props = defineProps<{
7
+ value?: any
8
+ record?: any
9
+ image?(value: any, record: any): string | undefined
10
+ name?(value: any, record: any): string
11
+ link?(value: any, record: any): string
12
+ color?: 'neutral' | 'soft' | 'mute'
13
+ }>()
14
+
15
+ const _image = computed(() => props.image?.(props.value, props.record))
16
+ const _name = computed(() => props.name?.(props.value, props.record))
17
+ </script>
18
+
19
+ <template>
20
+ <div class="STableCellAvatar" :class="[{ link}, color]">
21
+ <SLink class="container" :href="link?.(value, record)">
22
+ <div v-if="_image" class="avatar">
23
+ <SAvatar size="mini" :avatar="_image" :name="_name" />
24
+ </div>
25
+ <span v-if="_name" class="name">{{ _name }}</span>
26
+ </SLink>
27
+ </div>
28
+ </template>
29
+
30
+ <style scoped lang="postcss">
31
+ .STableCellAvatar {
32
+ min-height: 40px;
33
+ }
34
+
35
+ .container {
36
+ display: flex;
37
+ padding: 8px 16px;
38
+ }
39
+
40
+ .avatar {
41
+ flex-shrink: 0;
42
+ }
43
+
44
+ .name {
45
+ display: inline-block;
46
+ margin-left: 12px;
47
+ line-height: 24px;
48
+ font-size: 12px;
49
+ font-weight: 500;
50
+ white-space: nowrap;
51
+ overflow: hidden;
52
+ text-overflow: ellipsis;
53
+ transition: color 0.25s;
54
+
55
+ .STableCellAvatar.soft & { color: var(--c-text-2); }
56
+ .STableCellAvatar.mute & { color: var(--c-text-3); }
57
+
58
+ .STableCellAvatar.neutral.link & { color: var(--c-tex-1); }
59
+ .STableCellAvatar.soft.link & { color: var(--c-text-2); }
60
+ .STableCellAvatar.mute.link & { color: var(--c-text-3); }
61
+
62
+ .STableCellAvatar.link & { color: var(--c-info); }
63
+ .STableCellAvatar.link:hover & { color: var(--c-info-dark); }
64
+
65
+ .STableCellAvatar.neutral.link:hover & { color: var(--c-info); }
66
+ .STableCellAvatar.soft.link:hover & { color: var(--c-info); }
67
+ .STableCellAvatar.mute.link:hover & { color: var(--c-info); }
68
+ }
69
+ </style>
@@ -0,0 +1,93 @@
1
+ <script setup lang="ts">
2
+ import { computed } from 'vue'
3
+ import type { TableCellAvatarsOption } from '../composables/Table'
4
+ import SAvatar from './SAvatar.vue'
5
+
6
+ const props = defineProps<{
7
+ value?: any
8
+ record?: any
9
+ avatars(value: any, record: any): TableCellAvatarsOption[]
10
+ color?: 'neutral' | 'soft' | 'mute'
11
+ }>()
12
+
13
+ const _avatars = computed(() => {
14
+ return props.avatars(props.value, props.record)
15
+ })
16
+
17
+ const displayAvatars = computed(() => {
18
+ return _avatars.value.slice(0, 3)
19
+ })
20
+
21
+ const names = computed(() => {
22
+ if (_avatars.value.length === 0) {
23
+ return null
24
+ }
25
+
26
+ if (_avatars.value.length === 1) {
27
+ return _avatars.value[0].name
28
+ }
29
+
30
+ if (_avatars.value.length === 2) {
31
+ return `${_avatars.value[0].name} and ${_avatars.value[1].name}`
32
+ }
33
+
34
+ return `${_avatars.value[0].name} +${_avatars.value.length - 1}`
35
+ })
36
+ </script>
37
+
38
+ <template>
39
+ <div class="STableCellAvatars" :class="[color]">
40
+ <div class="container">
41
+ <div class="avatars">
42
+ <div v-for="(avatar, index) in displayAvatars" :key="index" class="avatar">
43
+ <div class="avatar-box">
44
+ <SAvatar size="mini" :avatar="avatar.image" :name="avatar.name" />
45
+ </div>
46
+ </div>
47
+ </div>
48
+ <div class="names">
49
+ {{ names }}
50
+ </div>
51
+ </div>
52
+ </div>
53
+ </template>
54
+
55
+ <style scoped lang="postcss">
56
+ .STableCellAvatars {
57
+ min-height: 40px;
58
+ }
59
+
60
+ .container {
61
+ display: flex;
62
+ gap: 16px;
63
+ padding: 6px 16px 6px 12px;
64
+ }
65
+
66
+ .avatars {
67
+ display: flex;
68
+ }
69
+
70
+ .avatar {
71
+ position: relative;
72
+ width: 20px;
73
+
74
+ &:nth-child(1) { z-index: 30; }
75
+ &:nth-child(2) { z-index: 20; }
76
+ &:nth-child(3) { z-index: 10; }
77
+ }
78
+
79
+ .avatar-box {
80
+ border: 2px solid var(--c-bg-elv-up);
81
+ border-radius: 50%;
82
+ width: 28px;
83
+ }
84
+
85
+ .names {
86
+ line-height: 28px;
87
+ font-size: 12px;
88
+ font-weight: 500;
89
+
90
+ .STableCellAvatars.soft & { color: var(--c-text-2); }
91
+ .STableCellAvatars.mute & { color: var(--c-text-3); }
92
+ }
93
+ </style>
@@ -0,0 +1,40 @@
1
+ <script setup lang="ts">
2
+ import type { Day } from '../support/Day'
3
+
4
+ defineProps<{
5
+ value?: Day | null
6
+ record: any
7
+ format?: string
8
+ color?: 'neutral' | 'soft' | 'mute'
9
+ }>()
10
+ </script>
11
+
12
+ <template>
13
+ <div class="STableCellDay" :class="[color ?? 'neutral']">
14
+ <div v-if="value" class="value">
15
+ {{ value.format(format ?? 'YYYY / MM / DD HH:mm:ss') }}
16
+ </div>
17
+ </div>
18
+ </template>
19
+
20
+ <style scoped lang="postcss">
21
+ .STableCellDay {
22
+ padding: 8px 16px;
23
+ min-height: 40px;
24
+ }
25
+
26
+ .value {
27
+ line-height: 24px;
28
+ font-family: var(--font-family-number);
29
+ font-size: 12px;
30
+ font-weight: 500;
31
+ white-space: nowrap;
32
+ overflow: hidden;
33
+ text-overflow: ellipsis;
34
+ transition: color 0.25s;
35
+
36
+ .STableCellDay.neutral & { color: var(--c-text-1); }
37
+ .STableCellDay.soft & { color: var(--c-text-2); }
38
+ .STableCellDay.mute & { color: var(--c-text-3); }
39
+ }
40
+ </style>
@@ -0,0 +1,84 @@
1
+ <script setup lang="ts">
2
+ import { computed } from 'vue'
3
+ import type { TableCellPillColor } from '../composables/Table'
4
+
5
+ const props = defineProps<{
6
+ value?: any
7
+ record: any
8
+ getter?: string | ((value: any) => string)
9
+ color?: TableCellPillColor | ((value: any) => TableCellPillColor)
10
+ }>()
11
+
12
+ const _value = computed(() => {
13
+ if (props.getter === undefined) {
14
+ return props.value
15
+ }
16
+
17
+ return typeof props.getter === 'string'
18
+ ? props.getter
19
+ : props.getter(props.value)
20
+ })
21
+
22
+ const _color = computed(() => {
23
+ if (props.color === undefined) {
24
+ return null
25
+ }
26
+
27
+ return typeof props.color === 'string'
28
+ ? props.color
29
+ : props.color(props.value)
30
+ })
31
+ </script>
32
+
33
+ <template>
34
+ <div class="STableCellPill" :class="[_color ?? 'mute']">
35
+ <div class="value">{{ _value }}</div>
36
+ </div>
37
+ </template>
38
+
39
+ <style scoped lang="postcss">
40
+ .STableCellPill {
41
+ padding: 9px 16px 10px;
42
+ min-height: 40px;
43
+ }
44
+
45
+ .value {
46
+ display: inline-block;
47
+ border: 1px solid transparent;
48
+ border-radius: 14px;
49
+ padding: 0 8px;
50
+ line-height: 18px;
51
+ font-size: 12px;
52
+ font-weight: 500;
53
+
54
+ .STableCellPill.info & {
55
+ border-color: var(--c-info);
56
+ color: var(--c-info);
57
+ background-color: var(--c-info-bg);
58
+ }
59
+
60
+ .STableCellPill.success & {
61
+ border-color: var(--c-success);
62
+ color: var(--c-success);
63
+ background-color: var(--c-success-bg);
64
+ }
65
+
66
+ .STableCellPill.warning & {
67
+ border-color: var(--c-warning);
68
+ color: var(--c-warning);
69
+ background-color: var(--c-warning-bg);
70
+ }
71
+
72
+ .STableCellPill.danger & {
73
+ border-color: var(--c-danger);
74
+ color: var(--c-danger);
75
+ background-color: var(--c-danger-bg);
76
+ }
77
+
78
+ .STableCellPill.mute & {
79
+ border-color: var(--c-divider);
80
+ color: var(--c-text-2);
81
+ background-color: var(--c-bg-elv);
82
+ }
83
+ }
84
+ </style>
@@ -0,0 +1,103 @@
1
+ <script setup lang="ts">
2
+ import { computed } from 'vue'
3
+ import SIcon from './SIcon.vue'
4
+ import SLink from './SLink.vue'
5
+
6
+ const props = defineProps<{
7
+ value?: any
8
+ record: any
9
+ icon?: any
10
+ getter?: string | ((value: any) => string)
11
+ color?: 'neutral' | 'soft' | 'mute'
12
+ iconColor?: 'neutral' | 'soft' | 'mute'
13
+ link?(value: any, record: any): string
14
+ }>()
15
+
16
+ const _value = computed(() => {
17
+ if (props.getter === undefined) {
18
+ return props.value
19
+ }
20
+
21
+ return typeof props.getter === 'string'
22
+ ? props.getter
23
+ : props.getter(props.value)
24
+ })
25
+ </script>
26
+
27
+ <template>
28
+ <div class="STableCellText" :class="[{ link }, color ?? 'neutral']">
29
+ <SLink v-if="_value" class="container" :href="link?.(value, record)">
30
+ <div v-if="icon" class="icon" :class="[iconColor ?? color ?? 'neutral']">
31
+ <SIcon :icon="icon" class="svg" />
32
+ </div>
33
+ <div class="text" :class="[color ?? 'neutral']">
34
+ {{ _value }}
35
+ </div>
36
+ </SLink>
37
+ </div>
38
+ </template>
39
+
40
+ <style scoped lang="postcss">
41
+ .STableCellText {
42
+ padding: 8px 16px;
43
+ min-height: 40px;
44
+ }
45
+
46
+ .container {
47
+ display: flex;
48
+ gap: 4px;
49
+ }
50
+
51
+ .text {
52
+ line-height: 24px;
53
+ font-size: 12px;
54
+ font-weight: 500;
55
+ white-space: nowrap;
56
+ overflow: hidden;
57
+ text-overflow: ellipsis;
58
+ transition: color 0.25s;
59
+
60
+ &.neutral { color: var(--c-text-1); }
61
+ &.soft { color: var(--c-text-2); }
62
+ &.mute { color: var(--c-text-3); }
63
+
64
+ .STableCellText.link & { color: var(--c-info); }
65
+ .STableCellText.link:hover & { color: var(--c-info-dark); }
66
+
67
+ .STableCellText.link &.neutral { color: var(--c-text-1); }
68
+ .STableCellText.link:hover &.neutral { color: var(--c-info); }
69
+ .STableCellText.link &.soft { color: var(--c-text-2); }
70
+ .STableCellText.link:hover &.soft { color: var(--c-info); }
71
+ .STableCellText.link &.mute { color: var(--c-text-3); }
72
+ .STableCellText.link:hover &.mute { color: var(--c-info); }
73
+ }
74
+
75
+ .icon {
76
+ display: flex;
77
+ justify-content: center;
78
+ align-items: center;
79
+ width: 24px;
80
+ height: 24px;
81
+ transition: color 0.25s;
82
+
83
+ &.neutral { color: var(--c-text-1); }
84
+ &.soft { color: var(--c-text-2); }
85
+ &.mute { color: var(--c-text-3); }
86
+
87
+ .STableCellText.link & { color: var(--c-info); }
88
+ .STableCellText.link:hover & { color: var(--c-info-dark); }
89
+
90
+ .STableCellText.link &.neutral { color: var(--c-text-1); }
91
+ .STableCellText.link:hover &.neutral { color: var(--c-info); }
92
+ .STableCellText.link &.soft { color: var(--c-text-2); }
93
+ .STableCellText.link:hover &.soft { color: var(--c-info); }
94
+ .STableCellText.link &.mute { color: var(--c-text-3); }
95
+ .STableCellText.link:hover &.mute { color: var(--c-info); }
96
+ }
97
+
98
+ .svg {
99
+ width: 18px;
100
+ height: 18px;
101
+ fill: currentColor;
102
+ }
103
+ </style>