@globalbrain/sefirot 3.49.0 → 4.0.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.
- package/config/nuxt.d.ts +4 -0
- package/config/nuxt.js +31 -0
- package/config/vite.d.ts +8 -0
- package/config/vite.js +69 -0
- package/lib/components/SActionList.vue +0 -1
- package/lib/components/SActionListItem.vue +3 -11
- package/lib/components/SAlert.vue +8 -13
- package/lib/components/SButton.vue +9 -10
- package/lib/components/SCardBlock.vue +0 -6
- package/lib/components/SControlActionBarClose.vue +1 -1
- package/lib/components/SControlActionBarCollapse.vue +2 -2
- package/lib/components/SControlInputSearch.vue +2 -2
- package/lib/components/SDescAvatar.vue +1 -2
- package/lib/components/SDescFile.vue +4 -6
- package/lib/components/SDescPill.vue +1 -2
- package/lib/components/SDescText.vue +1 -1
- package/lib/components/SDropdownSectionDateRange.vue +2 -2
- package/lib/components/SDropdownSectionDateRangeDateFromTo.vue +2 -2
- package/lib/components/SDropdownSectionDateRangeYear.vue +2 -2
- package/lib/components/SDropdownSectionDateRangeYearHalf.vue +2 -2
- package/lib/components/SDropdownSectionDateRangeYearQuarter.vue +2 -2
- package/lib/components/SDropdownSectionFilter.vue +4 -6
- package/lib/components/SIndicator.vue +10 -16
- package/lib/components/SInputAddon.vue +6 -8
- package/lib/components/SInputBase.vue +6 -8
- package/lib/components/SInputCheckbox.vue +7 -11
- package/lib/components/SInputCheckboxes.vue +3 -4
- package/lib/components/SInputDate.vue +3 -4
- package/lib/components/SInputDropdown.vue +10 -13
- package/lib/components/SInputDropdownItemAvatar.vue +2 -3
- package/lib/components/SInputDropdownItemText.vue +2 -3
- package/lib/components/SInputFile.vue +3 -4
- package/lib/components/SInputHMS.vue +4 -5
- package/lib/components/SInputImage.vue +5 -7
- package/lib/components/SInputNumber.vue +10 -11
- package/lib/components/SInputRadio.vue +3 -4
- package/lib/components/SInputRadios.vue +3 -4
- package/lib/components/SInputSegments.vue +3 -4
- package/lib/components/SInputSelect.vue +7 -9
- package/lib/components/SInputSwitch.vue +3 -4
- package/lib/components/SInputSwitches.vue +3 -4
- package/lib/components/SInputText.vue +7 -9
- package/lib/components/SInputTextarea.vue +3 -4
- package/lib/components/SInputYMD.vue +4 -5
- package/lib/components/SLink.vue +1 -1
- package/lib/components/SLocalNavMenu.vue +3 -4
- package/lib/components/SLoginPage.vue +79 -22
- package/lib/components/SLoginPagePasswordDialog.vue +95 -0
- package/lib/components/SPagination.vue +2 -2
- package/lib/components/SPill.vue +1 -5
- package/lib/components/SSnackbar.vue +2 -3
- package/lib/components/SStep.vue +4 -5
- package/lib/components/STable.vue +1 -2
- package/lib/components/STableCell.vue +5 -13
- package/lib/components/STableCellAvatar.vue +10 -27
- package/lib/components/STableCellAvatars.vue +6 -19
- package/lib/components/STableCellDay.vue +4 -11
- package/lib/components/STableCellNumber.vue +8 -9
- package/lib/components/STableCellPill.vue +5 -33
- package/lib/components/STableCellPills.vue +4 -14
- package/lib/components/STableCellState.vue +3 -3
- package/lib/components/STableCellText.vue +22 -50
- package/lib/components/STableColumn.vue +4 -6
- package/lib/components/STableFooter.vue +4 -5
- package/lib/components/STableHeader.vue +2 -19
- package/lib/components/STableHeaderMenu.vue +1 -2
- package/lib/components/STableHeaderMenuItem.vue +2 -3
- package/lib/components/STableItem.vue +1 -1
- package/lib/composables/Data.ts +8 -102
- package/lib/composables/Error.ts +3 -3
- package/lib/composables/Table.ts +17 -22
- package/lib/composables/Utils.ts +2 -2
- package/lib/composables/Validation.ts +76 -14
- package/lib/http/Http.ts +27 -10
- package/lib/mixins/Card.ts +0 -27
- package/lib/mixins/Fundamental.ts +0 -3
- package/lib/support/Day.ts +5 -5
- package/lib/support/Utils.ts +35 -14
- package/lib/validation/validators/maxLength.ts +2 -2
- package/lib/validation/validators/maxValue.ts +2 -2
- package/lib/validation/validators/minLength.ts +2 -2
- package/lib/validation/validators/minValue.ts +2 -2
- package/lib/validation/validators/required.ts +4 -4
- package/package.json +40 -40
- package/lib/components/SCardFooter.vue +0 -22
- package/lib/components/SCardFooterAction.vue +0 -31
- package/lib/components/SCardFooterActions.vue +0 -18
- package/lib/components/SCardHeader.vue +0 -15
- package/lib/components/SCardHeaderAction.vue +0 -28
- package/lib/components/SCardHeaderActionClose.vue +0 -27
- package/lib/components/SCardHeaderActionCollapse.vue +0 -47
- package/lib/components/SCardHeaderActions.vue +0 -13
- package/lib/components/SCardHeaderTitle.vue +0 -29
- package/lib/components/SIcon.vue +0 -13
- package/lib/components/SSheet.vue +0 -87
- package/lib/components/SSheetFooter.vue +0 -16
- package/lib/components/SSheetFooterAction.vue +0 -34
- package/lib/components/SSheetFooterActions.vue +0 -14
- package/lib/components/SSheetForm.vue +0 -15
- package/lib/components/SSheetMedium.vue +0 -72
- package/lib/components/SSheetTitle.vue +0 -13
- package/lib/components/STableHeaderActions.vue +0 -20
- package/lib/composables/D.ts +0 -21
- package/lib/composables/Form.ts +0 -109
- package/lib/composables/V.ts +0 -97
- package/lib/mixins/Sheet.ts +0 -30
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
2
|
+
import { computed, ref } from 'vue'
|
|
3
|
+
import { usePower } from '../composables/Power'
|
|
4
4
|
import SButton from './SButton.vue'
|
|
5
5
|
import SLink from './SLink.vue'
|
|
6
|
+
import SLoginPagePasswordDialog from './SLoginPagePasswordDialog.vue'
|
|
7
|
+
import SModal from './SModal.vue'
|
|
6
8
|
import SIconGbLogoWhite from './icon/SIconGbLogoWhite.vue'
|
|
9
|
+
import IconLockKey from '~icons/ph/lock-key-fill'
|
|
10
|
+
import IconGoogle from '~icons/ri/google-fill'
|
|
7
11
|
|
|
8
12
|
export interface CoverTitle {
|
|
9
13
|
text: string
|
|
@@ -15,11 +19,20 @@ export interface CoverPhotographer {
|
|
|
15
19
|
link: string
|
|
16
20
|
}
|
|
17
21
|
|
|
18
|
-
export
|
|
22
|
+
export type Action = ActionPassword | ActionSocial
|
|
23
|
+
|
|
24
|
+
export interface ActionPassword {
|
|
25
|
+
type: 'password'
|
|
26
|
+
onSubmit(email: string, password: string): Promise<boolean>
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface ActionSocial {
|
|
19
30
|
type: 'google'
|
|
20
|
-
onClick
|
|
31
|
+
onClick(): Promise<void>
|
|
21
32
|
}
|
|
22
33
|
|
|
34
|
+
export type ActionType = 'password' | 'google'
|
|
35
|
+
|
|
23
36
|
const props = defineProps<{
|
|
24
37
|
cover: string
|
|
25
38
|
coverTitle: CoverTitle
|
|
@@ -27,23 +40,51 @@ const props = defineProps<{
|
|
|
27
40
|
actions: Action[]
|
|
28
41
|
}>()
|
|
29
42
|
|
|
43
|
+
const passwordDialog = usePower()
|
|
44
|
+
|
|
45
|
+
const selectedPasswordAction = ref<ActionPassword | null>(null)
|
|
46
|
+
const actionInProgress = ref(false)
|
|
47
|
+
const actionError = ref(false)
|
|
48
|
+
|
|
30
49
|
const coverBgImageStyle = computed(() => `url(${props.cover})`)
|
|
31
50
|
|
|
32
|
-
function getActionLabel(type:
|
|
51
|
+
function getActionLabel(type: ActionType) {
|
|
33
52
|
switch (type) {
|
|
53
|
+
case 'password':
|
|
54
|
+
return 'Sign in via Password'
|
|
34
55
|
case 'google':
|
|
35
56
|
return 'Sign in via Google'
|
|
36
|
-
default:
|
|
37
|
-
throw new Error('[sefirot] Invalid action type')
|
|
38
57
|
}
|
|
39
58
|
}
|
|
40
59
|
|
|
41
|
-
function getIconComponent(type:
|
|
60
|
+
function getIconComponent(type: ActionType) {
|
|
42
61
|
switch (type) {
|
|
62
|
+
case 'password':
|
|
63
|
+
return IconLockKey
|
|
43
64
|
case 'google':
|
|
44
65
|
return IconGoogle
|
|
45
|
-
|
|
46
|
-
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function onAction(action: Action) {
|
|
70
|
+
switch (action.type) {
|
|
71
|
+
case 'password':
|
|
72
|
+
selectedPasswordAction.value = action
|
|
73
|
+
return passwordDialog.on()
|
|
74
|
+
case 'google':
|
|
75
|
+
return action.onClick()
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async function onSubmit(email: string, password: string) {
|
|
80
|
+
actionInProgress.value = true
|
|
81
|
+
|
|
82
|
+
actionError.value = !(await selectedPasswordAction.value!.onSubmit(email, password))
|
|
83
|
+
|
|
84
|
+
actionInProgress.value = false
|
|
85
|
+
|
|
86
|
+
if (!actionError.value) {
|
|
87
|
+
passwordDialog.off()
|
|
47
88
|
}
|
|
48
89
|
}
|
|
49
90
|
</script>
|
|
@@ -74,20 +115,30 @@ function getIconComponent(type: Action['type']) {
|
|
|
74
115
|
<p class="form-lead">This is a very closed login form meant for specific audiences only. If you can’t login, well, you know who to ask.</p>
|
|
75
116
|
</div>
|
|
76
117
|
|
|
77
|
-
<div class="form-actions">
|
|
78
|
-
<
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
118
|
+
<div class="form-actions" :class="{ multi: actions.length > 1 }">
|
|
119
|
+
<div v-for="action in actions" :key="action.type" class="form-action">
|
|
120
|
+
<SButton
|
|
121
|
+
size="large"
|
|
122
|
+
mode="white"
|
|
123
|
+
block
|
|
124
|
+
rounded
|
|
125
|
+
:label="getActionLabel(action.type)"
|
|
126
|
+
:icon="getIconComponent(action.type)"
|
|
127
|
+
@click="onAction(action)"
|
|
128
|
+
/>
|
|
129
|
+
</div>
|
|
88
130
|
</div>
|
|
89
131
|
</div>
|
|
90
132
|
</div>
|
|
133
|
+
|
|
134
|
+
<SModal :open="passwordDialog.state.value" @close="passwordDialog.off">
|
|
135
|
+
<SLoginPagePasswordDialog
|
|
136
|
+
:loading="actionInProgress"
|
|
137
|
+
:error="actionError"
|
|
138
|
+
@cancel="passwordDialog.off"
|
|
139
|
+
@submit="onSubmit"
|
|
140
|
+
/>
|
|
141
|
+
</SModal>
|
|
91
142
|
</div>
|
|
92
143
|
</template>
|
|
93
144
|
|
|
@@ -196,9 +247,15 @@ function getIconComponent(type: Action['type']) {
|
|
|
196
247
|
display: flex;
|
|
197
248
|
flex-direction: column;
|
|
198
249
|
align-items: center;
|
|
199
|
-
gap:
|
|
250
|
+
gap: 16px;
|
|
200
251
|
padding-top: 24px;
|
|
201
252
|
text-align: center;
|
|
202
253
|
margin: 0 auto;
|
|
203
254
|
}
|
|
255
|
+
|
|
256
|
+
.form-actions.multi .form-action {
|
|
257
|
+
display: block;
|
|
258
|
+
width: 100%;
|
|
259
|
+
max-width: 256px;
|
|
260
|
+
}
|
|
204
261
|
</style>
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { useData } from '../composables/Data'
|
|
3
|
+
import { useValidation } from '../composables/Validation'
|
|
4
|
+
import { email, maxLength, required } from '../validation/rules'
|
|
5
|
+
import SAlert from './SAlert.vue'
|
|
6
|
+
import SCard from './SCard.vue'
|
|
7
|
+
import SCardBlock from './SCardBlock.vue'
|
|
8
|
+
import SContent from './SContent.vue'
|
|
9
|
+
import SControl from './SControl.vue'
|
|
10
|
+
import SControlButton from './SControlButton.vue'
|
|
11
|
+
import SControlRight from './SControlRight.vue'
|
|
12
|
+
import SDoc from './SDoc.vue'
|
|
13
|
+
import SInputText from './SInputText.vue'
|
|
14
|
+
|
|
15
|
+
defineProps<{
|
|
16
|
+
loading: boolean
|
|
17
|
+
error: boolean
|
|
18
|
+
}>()
|
|
19
|
+
|
|
20
|
+
const emit = defineEmits<{
|
|
21
|
+
cancel: []
|
|
22
|
+
submit: [email: string, password: string]
|
|
23
|
+
}>()
|
|
24
|
+
|
|
25
|
+
const { data } = useData({
|
|
26
|
+
email: null as string | null,
|
|
27
|
+
password: null as string | null
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
const { validation, validateAndNotify } = useValidation(data, {
|
|
31
|
+
email: {
|
|
32
|
+
required: required(),
|
|
33
|
+
maxLength: maxLength(255),
|
|
34
|
+
email: email()
|
|
35
|
+
},
|
|
36
|
+
password: {
|
|
37
|
+
required: required(),
|
|
38
|
+
maxLength: maxLength(255)
|
|
39
|
+
}
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
async function onSubmit() {
|
|
43
|
+
if (await validateAndNotify()) {
|
|
44
|
+
emit('submit', data.value.email!, data.value.password!)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
</script>
|
|
48
|
+
|
|
49
|
+
<template>
|
|
50
|
+
<SCard size="small">
|
|
51
|
+
<SCardBlock class="s-p-24">
|
|
52
|
+
<SDoc>
|
|
53
|
+
<SContent>
|
|
54
|
+
<h2>Sign in to account</h2>
|
|
55
|
+
</SContent>
|
|
56
|
+
<SAlert v-if="error" mode="danger">
|
|
57
|
+
<p>Invalid email or password.</p>
|
|
58
|
+
</SAlert>
|
|
59
|
+
<SInputText
|
|
60
|
+
name="email"
|
|
61
|
+
type="email"
|
|
62
|
+
label="Email"
|
|
63
|
+
placeholder="john.doe@example.com"
|
|
64
|
+
v-model="data.email"
|
|
65
|
+
:validation="validation.email"
|
|
66
|
+
/>
|
|
67
|
+
<SInputText
|
|
68
|
+
name="password"
|
|
69
|
+
type="password"
|
|
70
|
+
label="Password"
|
|
71
|
+
placeholder="Password"
|
|
72
|
+
v-model="data.password"
|
|
73
|
+
:validation="validation.password"
|
|
74
|
+
/>
|
|
75
|
+
</SDoc>
|
|
76
|
+
</SCardBlock>
|
|
77
|
+
<SCardBlock size="xlarge" class="s-px-24">
|
|
78
|
+
<SControl>
|
|
79
|
+
<SControlRight>
|
|
80
|
+
<SControlButton
|
|
81
|
+
label="Cancel"
|
|
82
|
+
:disabled="loading"
|
|
83
|
+
@click="$emit('cancel')"
|
|
84
|
+
/>
|
|
85
|
+
<SControlButton
|
|
86
|
+
mode="info"
|
|
87
|
+
label="Sign in"
|
|
88
|
+
:loading="loading"
|
|
89
|
+
@click="onSubmit"
|
|
90
|
+
/>
|
|
91
|
+
</SControlRight>
|
|
92
|
+
</SControl>
|
|
93
|
+
</SCardBlock>
|
|
94
|
+
</SCard>
|
|
95
|
+
</template>
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import IconCaretLeft from '@iconify-icons/ph/caret-left-bold'
|
|
3
|
-
import IconCaretRight from '@iconify-icons/ph/caret-right-bold'
|
|
4
2
|
import { computed } from 'vue'
|
|
5
3
|
import { useTrans } from '../composables/Lang'
|
|
6
4
|
import { format } from '../support/Num'
|
|
7
5
|
import SButton from './SButton.vue'
|
|
6
|
+
import IconCaretLeft from '~icons/ph/caret-left-bold'
|
|
7
|
+
import IconCaretRight from '~icons/ph/caret-right-bold'
|
|
8
8
|
|
|
9
9
|
export type Size = 'mini' | 'small' | 'medium'
|
|
10
10
|
export type Align = 'left' | 'center' | 'right'
|
package/lib/components/SPill.vue
CHANGED
|
@@ -12,9 +12,6 @@ const props = defineProps<{
|
|
|
12
12
|
mode?: Mode
|
|
13
13
|
label?: string
|
|
14
14
|
clickable?: boolean
|
|
15
|
-
|
|
16
|
-
// @deprecated Use `as` instead.
|
|
17
|
-
tag?: string
|
|
18
15
|
}>()
|
|
19
16
|
|
|
20
17
|
const emit = defineEmits<{
|
|
@@ -29,8 +26,7 @@ const classes = computed(() => [
|
|
|
29
26
|
])
|
|
30
27
|
|
|
31
28
|
const computedTag = computed(() => {
|
|
32
|
-
|
|
33
|
-
return as || (props.clickable ? 'button' : 'span')
|
|
29
|
+
return props.as || (props.clickable ? 'button' : 'span')
|
|
34
30
|
})
|
|
35
31
|
|
|
36
32
|
function onClick() {
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import IconX from '@iconify-icons/ph/x'
|
|
3
2
|
import { type SnackbarAction, useSnackbars } from '../stores/Snackbars'
|
|
4
3
|
import SButton from './SButton.vue'
|
|
5
|
-
import
|
|
4
|
+
import IconX from '~icons/ph/x'
|
|
6
5
|
|
|
7
6
|
const props = defineProps<{
|
|
8
7
|
id: number
|
|
@@ -21,7 +20,7 @@ function close() {
|
|
|
21
20
|
<template>
|
|
22
21
|
<div class="SSnackbar" :class="[mode ?? 'neutral']">
|
|
23
22
|
<button class="close" @click="close">
|
|
24
|
-
<
|
|
23
|
+
<IconX class="close-icon" />
|
|
25
24
|
</button>
|
|
26
25
|
|
|
27
26
|
<p class="content">
|
package/lib/components/SStep.vue
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import IconCheck from '@iconify-icons/ph/check'
|
|
3
|
-
import IconX from '@iconify-icons/ph/x'
|
|
4
2
|
import { type PropType } from 'vue'
|
|
5
3
|
import { type BarMode, type StepStatus } from '../composables/Step'
|
|
6
|
-
import
|
|
4
|
+
import IconCheck from '~icons/ph/check'
|
|
5
|
+
import IconX from '~icons/ph/x'
|
|
7
6
|
|
|
8
7
|
defineProps({
|
|
9
8
|
status: { type: String as PropType<StepStatus>, required: true },
|
|
@@ -19,8 +18,8 @@ defineProps({
|
|
|
19
18
|
<div class="bar" :class="[barLeft]" />
|
|
20
19
|
<div class="point">
|
|
21
20
|
<div v-if="status === 'active'" class="inner-dot" />
|
|
22
|
-
<
|
|
23
|
-
<
|
|
21
|
+
<IconCheck v-else-if="status === 'done'" class="icon" />
|
|
22
|
+
<IconX v-else-if="status === 'failed'" class="icon" />
|
|
24
23
|
</div>
|
|
25
24
|
<div class="bar" :class="[barRight]" />
|
|
26
25
|
</div>
|
|
@@ -98,7 +98,7 @@ const showFooter = computed(() => {
|
|
|
98
98
|
return footer
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
return (
|
|
101
|
+
return !!(
|
|
102
102
|
unref(props.options.page)
|
|
103
103
|
&& unref(props.options.perPage)
|
|
104
104
|
&& unref(props.options.total)
|
|
@@ -363,7 +363,6 @@ function updateSelected(selected: any) {
|
|
|
363
363
|
:total="unref(options.total)"
|
|
364
364
|
:reset="unref(options.reset)"
|
|
365
365
|
:menu="unref(options.menu)"
|
|
366
|
-
:actions="unref(options.actions)"
|
|
367
366
|
:borderless="unref(options.borderless)"
|
|
368
367
|
:on-reset="options.onReset"
|
|
369
368
|
:selected="Array.isArray(selected) ? selected : undefined"
|
|
@@ -37,7 +37,7 @@ const computedCell = computed<TableCell | undefined>(() =>
|
|
|
37
37
|
:record="record"
|
|
38
38
|
:align="computedCell?.align"
|
|
39
39
|
:icon="computedCell?.icon"
|
|
40
|
-
:
|
|
40
|
+
:text="computedCell?.value"
|
|
41
41
|
:link="computedCell?.link"
|
|
42
42
|
:color="computedCell?.color"
|
|
43
43
|
:icon-color="computedCell?.iconColor"
|
|
@@ -49,7 +49,7 @@ const computedCell = computed<TableCell | undefined>(() =>
|
|
|
49
49
|
:record="record"
|
|
50
50
|
:align="computedCell.align"
|
|
51
51
|
:icon="computedCell.icon"
|
|
52
|
-
:
|
|
52
|
+
:number="computedCell.value"
|
|
53
53
|
:separator="computedCell.separator"
|
|
54
54
|
:link="computedCell.link"
|
|
55
55
|
:color="computedCell.color"
|
|
@@ -58,29 +58,23 @@ const computedCell = computed<TableCell | undefined>(() =>
|
|
|
58
58
|
/>
|
|
59
59
|
<STableCellDay
|
|
60
60
|
v-else-if="computedCell.type === 'day'"
|
|
61
|
-
:value="value"
|
|
62
|
-
:record="record"
|
|
63
61
|
:align="computedCell.align"
|
|
64
|
-
:
|
|
62
|
+
:day="computedCell.value"
|
|
65
63
|
:format="computedCell.format"
|
|
66
64
|
:color="computedCell.color"
|
|
67
65
|
/>
|
|
68
66
|
<STableCellPill
|
|
69
67
|
v-else-if="computedCell.type === 'pill'"
|
|
70
|
-
:
|
|
71
|
-
:record="record"
|
|
72
|
-
:getter="computedCell.value"
|
|
68
|
+
:pill="computedCell.value"
|
|
73
69
|
:color="computedCell.color"
|
|
74
70
|
/>
|
|
75
71
|
<STableCellPills
|
|
76
72
|
v-else-if="computedCell.type === 'pills'"
|
|
77
|
-
:value="value"
|
|
78
|
-
:record="record"
|
|
79
73
|
:pills="computedCell.pills"
|
|
80
74
|
/>
|
|
81
75
|
<STableCellState
|
|
82
76
|
v-else-if="computedCell.type === 'state'"
|
|
83
|
-
:
|
|
77
|
+
:state="computedCell.label"
|
|
84
78
|
:mode="computedCell.mode"
|
|
85
79
|
/>
|
|
86
80
|
<STableCellAvatar
|
|
@@ -95,8 +89,6 @@ const computedCell = computed<TableCell | undefined>(() =>
|
|
|
95
89
|
/>
|
|
96
90
|
<STableCellAvatars
|
|
97
91
|
v-else-if="computedCell.type === 'avatars'"
|
|
98
|
-
:value="value"
|
|
99
|
-
:record="record"
|
|
100
92
|
:avatars="computedCell.avatars"
|
|
101
93
|
:color="computedCell.color"
|
|
102
94
|
:avatar-count="computedCell.avatarCount"
|
|
@@ -1,48 +1,31 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed } from 'vue'
|
|
3
2
|
import SAvatar from './SAvatar.vue'
|
|
4
3
|
import SLink from './SLink.vue'
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
defineProps<{
|
|
7
6
|
value?: any
|
|
8
7
|
record?: any
|
|
9
|
-
image?: string | null
|
|
10
|
-
name?: string | null
|
|
11
|
-
link?: string | null
|
|
8
|
+
image?: string | null
|
|
9
|
+
name?: string | null
|
|
10
|
+
link?: string | null
|
|
12
11
|
color?: 'neutral' | 'soft' | 'mute'
|
|
13
12
|
onClick?(value: any, record: any): void
|
|
14
13
|
}>()
|
|
15
|
-
|
|
16
|
-
const _image = computed(() => resolve(props.image))
|
|
17
|
-
const _name = computed(() => resolve(props.name))
|
|
18
|
-
const _link = computed(() => resolve(props.link))
|
|
19
|
-
|
|
20
|
-
function resolve(
|
|
21
|
-
value?: string | null | ((value: any, record: any) => string | null | undefined)
|
|
22
|
-
) {
|
|
23
|
-
if (value == null || value === '') {
|
|
24
|
-
return null
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return typeof value === 'function'
|
|
28
|
-
? value(props.value, props.record)
|
|
29
|
-
: value
|
|
30
|
-
}
|
|
31
14
|
</script>
|
|
32
15
|
|
|
33
16
|
<template>
|
|
34
|
-
<div class="STableCellAvatar" :class="[{ link: link || onClick }, color]">
|
|
17
|
+
<div class="STableCellAvatar" :class="[{ link: !!(link || onClick) }, color]">
|
|
35
18
|
<SLink
|
|
36
19
|
class="container"
|
|
37
|
-
:href="
|
|
20
|
+
:href="link || undefined"
|
|
38
21
|
:role="onClick ? 'button' : null"
|
|
39
22
|
@click="() => onClick?.(value, record)"
|
|
40
23
|
>
|
|
41
|
-
<div v-if="
|
|
42
|
-
<SAvatar size="mini" :avatar="
|
|
24
|
+
<div v-if="image || name" class="avatar">
|
|
25
|
+
<SAvatar size="mini" :avatar="image" :name="name" />
|
|
43
26
|
</div>
|
|
44
|
-
<span v-if="
|
|
45
|
-
{{
|
|
27
|
+
<span v-if="name" class="name">
|
|
28
|
+
{{ name }}
|
|
46
29
|
</span>
|
|
47
30
|
</SLink>
|
|
48
31
|
</div>
|
|
@@ -5,9 +5,7 @@ import { type Position } from '../composables/Tooltip'
|
|
|
5
5
|
import SAvatar from './SAvatar.vue'
|
|
6
6
|
|
|
7
7
|
const props = withDefaults(defineProps<{
|
|
8
|
-
|
|
9
|
-
record?: any
|
|
10
|
-
avatars: TableCellAvatarsOption[] | ((value: any, record: any) => TableCellAvatarsOption[])
|
|
8
|
+
avatars: TableCellAvatarsOption[]
|
|
11
9
|
color?: 'neutral' | 'soft' | 'mute'
|
|
12
10
|
avatarCount?: number
|
|
13
11
|
nameCount?: number
|
|
@@ -17,22 +15,16 @@ const props = withDefaults(defineProps<{
|
|
|
17
15
|
nameCount: 2
|
|
18
16
|
})
|
|
19
17
|
|
|
20
|
-
const _avatars = computed(() => {
|
|
21
|
-
return typeof props.avatars === 'function'
|
|
22
|
-
? props.avatars(props.value, props.record)
|
|
23
|
-
: props.avatars
|
|
24
|
-
})
|
|
25
|
-
|
|
26
18
|
const avatarDiff = computed(() => {
|
|
27
|
-
return
|
|
19
|
+
return props.avatars.length - props.avatarCount
|
|
28
20
|
})
|
|
29
21
|
|
|
30
22
|
const displayAvatars = computed(() => {
|
|
31
|
-
return
|
|
23
|
+
return props.avatars.slice(0, props.avatarCount)
|
|
32
24
|
})
|
|
33
25
|
|
|
34
26
|
const nameDiff = computed(() => {
|
|
35
|
-
return
|
|
27
|
+
return props.avatars.length - props.nameCount
|
|
36
28
|
})
|
|
37
29
|
|
|
38
30
|
const displayNames = computed(() => {
|
|
@@ -41,8 +33,7 @@ const displayNames = computed(() => {
|
|
|
41
33
|
return null
|
|
42
34
|
}
|
|
43
35
|
|
|
44
|
-
const slicedAvatars =
|
|
45
|
-
|
|
36
|
+
const slicedAvatars = props.avatars.slice(0, props.nameCount)
|
|
46
37
|
const names = slicedAvatars.map((avatar) => avatar.name).join(', ')
|
|
47
38
|
|
|
48
39
|
if (nameDiff.value > 0) {
|
|
@@ -57,11 +48,7 @@ const displayNames = computed(() => {
|
|
|
57
48
|
<div class="STableCellAvatars" :class="[color]">
|
|
58
49
|
<div class="container">
|
|
59
50
|
<div v-if="displayAvatars.length" class="avatars">
|
|
60
|
-
<div
|
|
61
|
-
v-for="(avatar, index) in displayAvatars"
|
|
62
|
-
:key="index"
|
|
63
|
-
class="avatar"
|
|
64
|
-
>
|
|
51
|
+
<div v-for="(avatar, index) in displayAvatars" :key="index" class="avatar">
|
|
65
52
|
<div class="avatar-box">
|
|
66
53
|
<SAvatar size="mini" :avatar="avatar.image" :name="avatar.name" :tooltip="tooltip" />
|
|
67
54
|
</div>
|
|
@@ -1,25 +1,18 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed } from 'vue'
|
|
3
2
|
import { type Day } from '../support/Day'
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
record?: any
|
|
4
|
+
defineProps<{
|
|
5
|
+
day?: Day | null
|
|
8
6
|
align?: 'left' | 'center' | 'right'
|
|
9
|
-
getter?: Day | null
|
|
10
7
|
format?: string
|
|
11
8
|
color?: 'neutral' | 'soft' | 'mute'
|
|
12
9
|
}>()
|
|
13
|
-
|
|
14
|
-
const _value = computed(() => {
|
|
15
|
-
return props.getter ? props.getter : props.value
|
|
16
|
-
})
|
|
17
10
|
</script>
|
|
18
11
|
|
|
19
12
|
<template>
|
|
20
13
|
<div class="STableCellDay" :class="[align ?? 'left', color ?? 'neutral']">
|
|
21
|
-
<div v-if="
|
|
22
|
-
{{
|
|
14
|
+
<div v-if="day" class="value">
|
|
15
|
+
{{ day.format(format ?? 'YYYY-MM-DD HH:mm:ss') }}
|
|
23
16
|
</div>
|
|
24
17
|
</div>
|
|
25
18
|
</template>
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed } from 'vue'
|
|
2
|
+
import { type Component, computed } from 'vue'
|
|
3
3
|
import { type TableCellValueColor } from '../composables/Table'
|
|
4
4
|
import { format } from '../support/Num'
|
|
5
|
-
import SIcon from './SIcon.vue'
|
|
6
5
|
import SLink from './SLink.vue'
|
|
7
6
|
|
|
8
7
|
const props = defineProps<{
|
|
9
8
|
value?: any
|
|
10
9
|
record?: any
|
|
11
10
|
align?: 'left' | 'center' | 'right'
|
|
12
|
-
icon?:
|
|
13
|
-
|
|
11
|
+
icon?: Component
|
|
12
|
+
number?: number | null
|
|
14
13
|
separator?: boolean
|
|
15
14
|
color?: TableCellValueColor
|
|
16
15
|
iconColor?: TableCellValueColor
|
|
@@ -18,14 +17,14 @@ const props = defineProps<{
|
|
|
18
17
|
onClick?(value: any, record: any): void
|
|
19
18
|
}>()
|
|
20
19
|
|
|
21
|
-
const _value = computed(() => props.
|
|
20
|
+
const _value = computed(() => props.number ?? props.value)
|
|
22
21
|
const _color = computed(() => props.color ?? 'neutral')
|
|
23
22
|
const _iconColor = computed(() => props.iconColor ?? _color.value)
|
|
24
23
|
|
|
25
24
|
const classes = computed(() => [
|
|
26
25
|
props.align ?? 'left',
|
|
27
26
|
_color,
|
|
28
|
-
{ link: props.link || props.onClick }
|
|
27
|
+
{ link: !!(props.link || props.onClick) }
|
|
29
28
|
])
|
|
30
29
|
</script>
|
|
31
30
|
|
|
@@ -38,10 +37,10 @@ const classes = computed(() => [
|
|
|
38
37
|
:role="onClick ? 'button' : null"
|
|
39
38
|
@click="() => onClick?.(value, record)"
|
|
40
39
|
>
|
|
41
|
-
<div v-if="icon" class="icon" :class="
|
|
42
|
-
<
|
|
40
|
+
<div v-if="icon" class="icon" :class="_iconColor">
|
|
41
|
+
<component :is="icon" class="svg" />
|
|
43
42
|
</div>
|
|
44
|
-
<div class="value" :class="
|
|
43
|
+
<div class="value" :class="_color">
|
|
45
44
|
{{ separator ? format(_value) : _value }}
|
|
46
45
|
</div>
|
|
47
46
|
</SLink>
|
|
@@ -1,43 +1,15 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed } from 'vue'
|
|
3
2
|
import SPill, { type Mode } from './SPill.vue'
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
getter?: string | ((value: any, record: any) => string)
|
|
9
|
-
color?: Mode | ((value: any, record: any) => Mode)
|
|
4
|
+
defineProps<{
|
|
5
|
+
pill?: string
|
|
6
|
+
color?: Mode
|
|
10
7
|
}>()
|
|
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, props.record)
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
const _color = computed(() => {
|
|
23
|
-
if (props.color === undefined) {
|
|
24
|
-
return props.color
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return typeof props.color === 'string'
|
|
28
|
-
? props.color
|
|
29
|
-
: props.color(props.value, props.record)
|
|
30
|
-
})
|
|
31
8
|
</script>
|
|
32
9
|
|
|
33
10
|
<template>
|
|
34
|
-
<div class="STableCellPill" :class="[
|
|
35
|
-
<SPill
|
|
36
|
-
v-if="_value"
|
|
37
|
-
size="mini"
|
|
38
|
-
:mode="_color"
|
|
39
|
-
:label="_value"
|
|
40
|
-
/>
|
|
11
|
+
<div class="STableCellPill" :class="[color || 'neutral']">
|
|
12
|
+
<SPill v-if="pill" size="mini" :mode="color" :label="pill" />
|
|
41
13
|
</div>
|
|
42
14
|
</template>
|
|
43
15
|
|