@globalbrain/sefirot 2.47.4 → 2.49.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/lib/components/SInputSegments.vue +132 -0
- package/lib/components/SInputSegmentsOption.vue +150 -0
- package/lib/components/STableCell.vue +7 -0
- package/lib/components/STableCellActions.vue +38 -0
- package/lib/components/STableCellAvatars.vue +1 -1
- package/lib/components/STableHeader.vue +2 -2
- package/lib/components/STableHeaderActionItem.vue +2 -2
- package/lib/components/STableHeaderActions.vue +2 -2
- package/lib/composables/Table.ts +25 -14
- package/package.json +1 -1
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
<script setup lang="ts" generic="T extends string | number | boolean">
|
|
2
|
+
import { type IconifyIcon } from '@iconify/vue/dist/offline'
|
|
3
|
+
import { computed } from 'vue'
|
|
4
|
+
import { type Validatable } from '../composables/Validation'
|
|
5
|
+
import SInputBase from './SInputBase.vue'
|
|
6
|
+
import SInputSegmentsOption, { type Mode } from './SInputSegmentsOption.vue'
|
|
7
|
+
|
|
8
|
+
export type Size = 'mini' | 'small' | 'medium'
|
|
9
|
+
export type Color = 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
|
|
10
|
+
|
|
11
|
+
export interface Option<T extends string | number | boolean> {
|
|
12
|
+
label: string
|
|
13
|
+
value: T
|
|
14
|
+
mode?: Mode
|
|
15
|
+
disabled?: boolean
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const props = defineProps<{
|
|
19
|
+
size?: Size
|
|
20
|
+
name?: string
|
|
21
|
+
label?: string
|
|
22
|
+
info?: string
|
|
23
|
+
note?: string
|
|
24
|
+
help?: string
|
|
25
|
+
checkIcon?: IconifyIcon
|
|
26
|
+
checkText?: string
|
|
27
|
+
checkColor?: Color
|
|
28
|
+
options: Option<T>[]
|
|
29
|
+
block?: boolean
|
|
30
|
+
disabled?: boolean
|
|
31
|
+
value?: T
|
|
32
|
+
modelValue?: T
|
|
33
|
+
validation?: Validatable
|
|
34
|
+
hideError?: boolean
|
|
35
|
+
}>()
|
|
36
|
+
|
|
37
|
+
const emit = defineEmits<{
|
|
38
|
+
(e: 'update:model-value', value: T): void
|
|
39
|
+
(e: 'change', value: T): void
|
|
40
|
+
}>()
|
|
41
|
+
|
|
42
|
+
const _value = computed(() => {
|
|
43
|
+
const v = props.modelValue !== undefined
|
|
44
|
+
? props.modelValue
|
|
45
|
+
: props.value
|
|
46
|
+
|
|
47
|
+
if (v === undefined) {
|
|
48
|
+
throw new Error('[sefirot] SInputSegments: `value` or `modelValue` is required.')
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return v
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
function onSelect(value: T) {
|
|
55
|
+
emit('update:model-value', value)
|
|
56
|
+
emit('change', value)
|
|
57
|
+
}
|
|
58
|
+
</script>
|
|
59
|
+
|
|
60
|
+
<template>
|
|
61
|
+
<SInputBase
|
|
62
|
+
class="SInputSegments"
|
|
63
|
+
:class="[size ?? 'small', { block }]"
|
|
64
|
+
:label="label"
|
|
65
|
+
:note="note"
|
|
66
|
+
:info="info"
|
|
67
|
+
:help="help"
|
|
68
|
+
:check-icon="checkIcon"
|
|
69
|
+
:check-text="checkText"
|
|
70
|
+
:check-color="checkColor"
|
|
71
|
+
:hide-error="hideError"
|
|
72
|
+
:validation="validation"
|
|
73
|
+
>
|
|
74
|
+
<div class="box">
|
|
75
|
+
<SInputSegmentsOption
|
|
76
|
+
v-for="option, index in options"
|
|
77
|
+
:key="index"
|
|
78
|
+
:size="size ?? 'small'"
|
|
79
|
+
:label="option.label"
|
|
80
|
+
:value="option.value"
|
|
81
|
+
:mode="option.mode ?? 'neutral'"
|
|
82
|
+
:active="_value === option.value"
|
|
83
|
+
:disabled="disabled ? true : option.disabled ?? false"
|
|
84
|
+
@click="onSelect(option.value)"
|
|
85
|
+
/>
|
|
86
|
+
</div>
|
|
87
|
+
<template v-if="$slots.info" #info><slot name="info" /></template>
|
|
88
|
+
</SInputBase>
|
|
89
|
+
</template>
|
|
90
|
+
|
|
91
|
+
<style scoped lang="postcss">
|
|
92
|
+
.SInputSegments.mini {
|
|
93
|
+
.box {
|
|
94
|
+
padding: 2px;
|
|
95
|
+
height: 32px;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.SInputSegments.small {
|
|
100
|
+
.box {
|
|
101
|
+
padding: 4px;
|
|
102
|
+
height: 40px;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.SInputSegments.medium {
|
|
107
|
+
.box {
|
|
108
|
+
padding: 4px;
|
|
109
|
+
height: 48px;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.SInputSegments.block {
|
|
114
|
+
.box {
|
|
115
|
+
display: flex;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.SInputSegments.has-error {
|
|
120
|
+
.box {
|
|
121
|
+
border-color: var(--input-error-border-color);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.box {
|
|
126
|
+
display: inline-flex;
|
|
127
|
+
border: 1px solid var(--input-border-color);
|
|
128
|
+
border-radius: 6px;
|
|
129
|
+
background-color: var(--input-bg-color);
|
|
130
|
+
transition: border-color 0.25s;
|
|
131
|
+
}
|
|
132
|
+
</style>
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
<script setup lang="ts" generic="T extends string | number | boolean">
|
|
2
|
+
export type Size = 'mini' | 'small' | 'medium'
|
|
3
|
+
export type Mode = 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
|
|
4
|
+
|
|
5
|
+
const props = defineProps<{
|
|
6
|
+
size: Size
|
|
7
|
+
label: string
|
|
8
|
+
value: T
|
|
9
|
+
mode: Mode
|
|
10
|
+
active: boolean
|
|
11
|
+
disabled: boolean
|
|
12
|
+
}>()
|
|
13
|
+
|
|
14
|
+
const emit = defineEmits<{
|
|
15
|
+
(e: 'click'): void
|
|
16
|
+
}>()
|
|
17
|
+
|
|
18
|
+
function onClick() {
|
|
19
|
+
if (!props.disabled) {
|
|
20
|
+
emit('click')
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<template>
|
|
26
|
+
<button
|
|
27
|
+
class="SInputSegmentsOption"
|
|
28
|
+
:class="[size, mode, { active }, { disabled }]"
|
|
29
|
+
@click="onClick"
|
|
30
|
+
>
|
|
31
|
+
<span class="label">
|
|
32
|
+
{{ label }}
|
|
33
|
+
</span>
|
|
34
|
+
</button>
|
|
35
|
+
</template>
|
|
36
|
+
|
|
37
|
+
<style scoped lang="postcss">
|
|
38
|
+
.SInputSegmentsOption {
|
|
39
|
+
position: relative;
|
|
40
|
+
display: block;
|
|
41
|
+
flex-grow: 1;
|
|
42
|
+
justify-content: center;
|
|
43
|
+
align-items: center;
|
|
44
|
+
border: 1px solid transparent;
|
|
45
|
+
border-radius: 3px;
|
|
46
|
+
width: 100%;
|
|
47
|
+
height: 100%;
|
|
48
|
+
text-align: center;
|
|
49
|
+
font-size: 14px;
|
|
50
|
+
color: var(--c-text-2);
|
|
51
|
+
white-space: nowrap;
|
|
52
|
+
transition: border-color 0.25s, color 0.25s, background-color 0.25s;
|
|
53
|
+
|
|
54
|
+
&:hover {
|
|
55
|
+
color: var(--c-text-1);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
&.disabled {
|
|
59
|
+
color: var(--c-text-3);
|
|
60
|
+
cursor: not-allowed;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.SInputSegmentsOption + &::before {
|
|
64
|
+
position: absolute;
|
|
65
|
+
left: -1px;
|
|
66
|
+
display: block;
|
|
67
|
+
width: 1px;
|
|
68
|
+
height: 16px;
|
|
69
|
+
border-radius: 4px;
|
|
70
|
+
background-color: var(--c-divider-2);
|
|
71
|
+
content: "";
|
|
72
|
+
transition: opacity 0.25s;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.SInputSegmentsOption.active + &::before,
|
|
76
|
+
&.active::before {
|
|
77
|
+
opacity: 0;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.SInputSegmentsOption.mini {
|
|
82
|
+
.SInputSegmentsOption + &::before {
|
|
83
|
+
top: 4px;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.label {
|
|
87
|
+
padding: 0 12px;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.SInputSegmentsOption.small {
|
|
92
|
+
.SInputSegmentsOption + &::before {
|
|
93
|
+
top: 7px;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.label {
|
|
97
|
+
padding: 0 12px;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.SInputSegmentsOption.medium {
|
|
102
|
+
.SInputSegmentsOption + &::before {
|
|
103
|
+
top: 10px;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.label {
|
|
107
|
+
padding: 0 16px;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.SInputSegmentsOption.neutral.active {
|
|
112
|
+
border-color: var(--button-fill-mute-border-color);
|
|
113
|
+
color: var(--button-fill-mute-text-color);
|
|
114
|
+
background-color: var(--button-fill-mute-bg-color);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.SInputSegmentsOption.mute.active {
|
|
118
|
+
border-color: var(--button-fill-mute-border-color);
|
|
119
|
+
color: var(--c-text-2);
|
|
120
|
+
background-color: var(--button-fill-mute-bg-color);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.SInputSegmentsOption.info.active {
|
|
124
|
+
border-color: var(--button-fill-info-border-color);
|
|
125
|
+
color: var(--button-fill-info-text-color);
|
|
126
|
+
background-color: var(--button-fill-info-bg-color);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.SInputSegmentsOption.success.active {
|
|
130
|
+
border-color: var(--button-fill-success-border-color);
|
|
131
|
+
color: var(--button-fill-success-text-color);
|
|
132
|
+
background-color: var(--button-fill-success-bg-color);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.SInputSegmentsOption.warning.active {
|
|
136
|
+
border-color: var(--button-fill-warning-border-color);
|
|
137
|
+
color: var(--button-fill-warning-text-color);
|
|
138
|
+
background-color: var(--button-fill-warning-bg-color);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.SInputSegmentsOption.danger.active {
|
|
142
|
+
border-color: var(--button-fill-danger-border-color);
|
|
143
|
+
color: var(--button-fill-danger-text-color);
|
|
144
|
+
background-color: var(--button-fill-danger-bg-color);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.label {
|
|
148
|
+
display: inline-block;
|
|
149
|
+
}
|
|
150
|
+
</style>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed } from 'vue'
|
|
3
3
|
import { type TableCell } from '../composables/Table'
|
|
4
|
+
import STableCellActions from './STableCellActions.vue'
|
|
4
5
|
import STableCellAvatar from './STableCellAvatar.vue'
|
|
5
6
|
import STableCellAvatars from './STableCellAvatars.vue'
|
|
6
7
|
import STableCellCustom from './STableCellCustom.vue'
|
|
@@ -99,6 +100,12 @@ const computedCell = computed<TableCell | undefined>(() =>
|
|
|
99
100
|
:avatars="computedCell.avatars"
|
|
100
101
|
:color="computedCell.color"
|
|
101
102
|
/>
|
|
103
|
+
<STableCellActions
|
|
104
|
+
v-else-if="computedCell.type === 'actions'"
|
|
105
|
+
:value="value"
|
|
106
|
+
:record="record"
|
|
107
|
+
:actions="computedCell.actions"
|
|
108
|
+
/>
|
|
102
109
|
<STableCellCustom
|
|
103
110
|
v-else-if="computedCell.type === 'custom'"
|
|
104
111
|
>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { type TableCellAction } from '../composables/Table'
|
|
3
|
+
import SButton from './SButton.vue'
|
|
4
|
+
|
|
5
|
+
defineProps<{
|
|
6
|
+
value: any
|
|
7
|
+
record: any
|
|
8
|
+
actions: TableCellAction[]
|
|
9
|
+
}>()
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<template>
|
|
13
|
+
<div class="STableCellActions">
|
|
14
|
+
<SButton
|
|
15
|
+
v-for="(action, i) in actions"
|
|
16
|
+
:key="i"
|
|
17
|
+
size="mini"
|
|
18
|
+
type="text"
|
|
19
|
+
:mode="action.mode ?? 'mute'"
|
|
20
|
+
:icon="action.icon"
|
|
21
|
+
:icon-mode="action.iconMode"
|
|
22
|
+
:label="action.label"
|
|
23
|
+
:label-mode="action.labelMode"
|
|
24
|
+
@click="action.onClick(value, record)"
|
|
25
|
+
/>
|
|
26
|
+
</div>
|
|
27
|
+
</template>
|
|
28
|
+
|
|
29
|
+
<style scoped lang="postcss">
|
|
30
|
+
.STableCellActions {
|
|
31
|
+
min-height: 40px;
|
|
32
|
+
display: flex;
|
|
33
|
+
align-items: center;
|
|
34
|
+
justify-content: center;
|
|
35
|
+
flex-wrap: nowrap;
|
|
36
|
+
flex-direction: row;
|
|
37
|
+
}
|
|
38
|
+
</style>
|
|
@@ -33,7 +33,7 @@ const names = computed(() => {
|
|
|
33
33
|
return `${_avatars.value[0].name}, ${_avatars.value[1].name}`
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
return `${_avatars.value[0].name}, ${_avatars.value[1].name} +${_avatars.value.length -
|
|
36
|
+
return `${_avatars.value[0].name}, ${_avatars.value[1].name} +${_avatars.value.length - 2}`
|
|
37
37
|
})
|
|
38
38
|
</script>
|
|
39
39
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed } from 'vue'
|
|
3
|
-
import { type
|
|
3
|
+
import { type TableHeaderAction, type TableMenu } from '../composables/Table'
|
|
4
4
|
import { format } from '../support/Num'
|
|
5
5
|
import { isNullish } from '../support/Utils'
|
|
6
6
|
import STableHeaderActions from './STableHeaderActions.vue'
|
|
@@ -10,7 +10,7 @@ const props = defineProps<{
|
|
|
10
10
|
total?: number | null
|
|
11
11
|
reset?: boolean
|
|
12
12
|
menu?: TableMenu[] | TableMenu[][]
|
|
13
|
-
actions?:
|
|
13
|
+
actions?: TableHeaderAction[]
|
|
14
14
|
borderless?: boolean
|
|
15
15
|
onReset?(): void
|
|
16
16
|
selected?: unknown[]
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { type
|
|
2
|
+
import { type TableHeaderAction } from '../composables/Table'
|
|
3
3
|
import SButton from './SButton.vue'
|
|
4
4
|
|
|
5
|
-
withDefaults(defineProps<
|
|
5
|
+
withDefaults(defineProps<TableHeaderAction>(), {
|
|
6
6
|
show: true,
|
|
7
7
|
mode: 'mute',
|
|
8
8
|
labelMode: 'neutral'
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { type
|
|
2
|
+
import { type TableHeaderAction } from '../composables/Table'
|
|
3
3
|
import STableHeaderActionItem from './STableHeaderActionItem.vue'
|
|
4
4
|
|
|
5
|
-
defineProps<{ actions:
|
|
5
|
+
defineProps<{ actions: TableHeaderAction[] }>()
|
|
6
6
|
</script>
|
|
7
7
|
|
|
8
8
|
<template>
|
package/lib/composables/Table.ts
CHANGED
|
@@ -10,7 +10,7 @@ export interface Table<
|
|
|
10
10
|
orders: MaybeRef<O[]>
|
|
11
11
|
columns: MaybeRef<TableColumns<O, R, SR>>
|
|
12
12
|
menu?: MaybeRef<TableMenu[] | TableMenu[][]>
|
|
13
|
-
actions?: MaybeRef<
|
|
13
|
+
actions?: MaybeRef<TableHeaderAction[]>
|
|
14
14
|
records?: MaybeRef<R[] | null | undefined>
|
|
15
15
|
header?: MaybeRef<boolean | undefined>
|
|
16
16
|
footer?: MaybeRef<boolean | undefined>
|
|
@@ -64,6 +64,7 @@ export type TableCell =
|
|
|
64
64
|
| TableCellCustom
|
|
65
65
|
| TableCellEmpty
|
|
66
66
|
| TableCellComponent
|
|
67
|
+
| TableCellActions
|
|
67
68
|
|
|
68
69
|
export type TableCellType =
|
|
69
70
|
| 'text'
|
|
@@ -77,6 +78,9 @@ export type TableCellType =
|
|
|
77
78
|
| 'custom'
|
|
78
79
|
| 'empty'
|
|
79
80
|
| 'component'
|
|
81
|
+
| 'actions'
|
|
82
|
+
|
|
83
|
+
export type ColorModes = 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'danger'
|
|
80
84
|
|
|
81
85
|
export interface TableCellBase {
|
|
82
86
|
type: TableCellType
|
|
@@ -105,14 +109,7 @@ export interface TableCellNumber extends TableCellBase {
|
|
|
105
109
|
onClick?(value: any, record: any): void
|
|
106
110
|
}
|
|
107
111
|
|
|
108
|
-
export type TableCellValueColor =
|
|
109
|
-
| 'neutral'
|
|
110
|
-
| 'soft'
|
|
111
|
-
| 'mute'
|
|
112
|
-
| 'info'
|
|
113
|
-
| 'success'
|
|
114
|
-
| 'warning'
|
|
115
|
-
| 'danger'
|
|
112
|
+
export type TableCellValueColor = ColorModes | 'soft'
|
|
116
113
|
|
|
117
114
|
export interface TableCellDay extends TableCellBase {
|
|
118
115
|
type: 'day'
|
|
@@ -128,7 +125,7 @@ export interface TableCellPill extends TableCellBase {
|
|
|
128
125
|
color?: TableCellPillColor | ((value: any, record: any) => TableCellPillColor)
|
|
129
126
|
}
|
|
130
127
|
|
|
131
|
-
export type TableCellPillColor =
|
|
128
|
+
export type TableCellPillColor = ColorModes
|
|
132
129
|
|
|
133
130
|
export interface TableCellPills extends TableCellBase {
|
|
134
131
|
type: 'pills'
|
|
@@ -177,7 +174,21 @@ export interface TableCellComponent extends TableCellBase {
|
|
|
177
174
|
export interface TableCellState extends TableCellBase {
|
|
178
175
|
type: 'state'
|
|
179
176
|
label: string
|
|
180
|
-
mode?:
|
|
177
|
+
mode?: ColorModes
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export interface TableCellActions extends TableCellBase {
|
|
181
|
+
type: 'actions'
|
|
182
|
+
actions: TableCellAction[]
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export interface TableCellAction {
|
|
186
|
+
mode?: ColorModes
|
|
187
|
+
icon?: any
|
|
188
|
+
iconMode?: ColorModes
|
|
189
|
+
label?: string
|
|
190
|
+
labelMode?: ColorModes
|
|
191
|
+
onClick(value: any, record: any): void
|
|
181
192
|
}
|
|
182
193
|
|
|
183
194
|
export interface TableMenu {
|
|
@@ -186,11 +197,11 @@ export interface TableMenu {
|
|
|
186
197
|
dropdown: DropdownSection[]
|
|
187
198
|
}
|
|
188
199
|
|
|
189
|
-
export interface
|
|
200
|
+
export interface TableHeaderAction {
|
|
190
201
|
show?: boolean
|
|
191
|
-
mode?:
|
|
202
|
+
mode?: ColorModes
|
|
192
203
|
label: string
|
|
193
|
-
labelMode?:
|
|
204
|
+
labelMode?: ColorModes
|
|
194
205
|
onClick(): void
|
|
195
206
|
}
|
|
196
207
|
|