@globalbrain/sefirot 2.42.0 → 2.44.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/SDesc.vue +17 -3
- package/lib/components/SDescDay.vue +5 -11
- package/lib/components/SDescEmpty.vue +0 -5
- package/lib/components/SDescItem.vue +23 -0
- package/lib/components/SDescLink.vue +8 -16
- package/lib/components/SDescNumber.vue +5 -9
- package/lib/components/SDescPill.vue +0 -5
- package/lib/components/SDescState.vue +0 -5
- package/lib/components/SDescText.vue +9 -7
- package/lib/components/SInputCheckbox.vue +30 -4
- package/lib/components/SInputCheckboxes.vue +3 -0
- package/lib/components/SInputRadio.vue +31 -5
- package/lib/components/SInputRadios.vue +3 -0
- package/lib/components/SInputYMD.vue +3 -0
- package/lib/composables/Utils.ts +30 -1
- package/package.json +1 -1
package/lib/components/SDesc.vue
CHANGED
|
@@ -1,14 +1,28 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { provide } from 'vue'
|
|
2
3
|
import SGrid from './SGrid.vue'
|
|
3
4
|
|
|
4
|
-
defineProps<{
|
|
5
|
+
const props = withDefaults(defineProps<{
|
|
5
6
|
cols?: string | number
|
|
6
7
|
gap?: string | number
|
|
7
|
-
|
|
8
|
+
dir?: 'column' | 'row'
|
|
9
|
+
labelWidth?: string | number
|
|
10
|
+
divider?: boolean
|
|
11
|
+
}>(), {
|
|
12
|
+
dir: 'column',
|
|
13
|
+
divider: true
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
provide('sefirot-desc-label-wdith', () => props.labelWidth)
|
|
8
17
|
</script>
|
|
9
18
|
|
|
10
19
|
<template>
|
|
11
|
-
<SGrid
|
|
20
|
+
<SGrid
|
|
21
|
+
class="SDesc"
|
|
22
|
+
:class="[dir, { divider }]"
|
|
23
|
+
:cols="cols"
|
|
24
|
+
:gap="gap"
|
|
25
|
+
>
|
|
12
26
|
<slot />
|
|
13
27
|
</SGrid>
|
|
14
28
|
</template>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
import { useSlotValue } from '../composables/Utils'
|
|
3
4
|
import { type Day } from '../support/Day'
|
|
4
5
|
import SDescEmpty from './SDescEmpty.vue'
|
|
5
6
|
|
|
@@ -8,13 +9,11 @@ const props = defineProps<{
|
|
|
8
9
|
format?: string
|
|
9
10
|
}>()
|
|
10
11
|
|
|
11
|
-
const
|
|
12
|
+
const slotValue = useSlotValue()
|
|
12
13
|
|
|
13
14
|
const _value = computed(() => {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
if (typeof slotValue === 'string') {
|
|
17
|
-
return slotValue
|
|
15
|
+
if (slotValue.value) {
|
|
16
|
+
return slotValue.value
|
|
18
17
|
}
|
|
19
18
|
|
|
20
19
|
if (props.value) {
|
|
@@ -35,11 +34,6 @@ const _value = computed(() => {
|
|
|
35
34
|
</template>
|
|
36
35
|
|
|
37
36
|
<style scoped lang="postcss">
|
|
38
|
-
.SDescDay {
|
|
39
|
-
border-bottom: 1px dashed var(--c-divider-1);
|
|
40
|
-
padding-bottom: 7px;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
37
|
.value {
|
|
44
38
|
line-height: 24px;
|
|
45
39
|
font-size: 14px;
|
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { computed, inject } from 'vue'
|
|
2
3
|
import SGridItem from './SGridItem.vue'
|
|
3
4
|
|
|
4
5
|
defineProps<{
|
|
5
6
|
span?: string | number
|
|
6
7
|
}>()
|
|
8
|
+
|
|
9
|
+
const labelWidthProp = inject<() => string | number | undefined>('sefirot-desc-label-wdith')
|
|
10
|
+
|
|
11
|
+
const labelWidth = computed(() => {
|
|
12
|
+
const w = labelWidthProp?.()
|
|
13
|
+
return w ? `${w}px` : '1fr'
|
|
14
|
+
})
|
|
7
15
|
</script>
|
|
8
16
|
|
|
9
17
|
<template>
|
|
@@ -11,3 +19,18 @@ defineProps<{
|
|
|
11
19
|
<slot />
|
|
12
20
|
</SGridItem>
|
|
13
21
|
</template>
|
|
22
|
+
|
|
23
|
+
<style scoped lang="postcss">
|
|
24
|
+
.SDescItem {
|
|
25
|
+
display: grid;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.SDesc.row > .SDescItem {
|
|
29
|
+
grid-template-columns: var(--desc-label-width, v-bind(labelWidth)) 1fr;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.SDesc.divider > .SDescItem {
|
|
33
|
+
border-bottom: 1px dashed var(--c-divider-1);
|
|
34
|
+
padding-bottom: 7px;
|
|
35
|
+
}
|
|
36
|
+
</style>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
import { useSlotValue } from '../composables/Utils'
|
|
3
4
|
import SDescEmpty from './SDescEmpty.vue'
|
|
4
5
|
import SLink from './SLink.vue'
|
|
5
6
|
|
|
@@ -8,27 +9,23 @@ const props = defineProps<{
|
|
|
8
9
|
href?: string
|
|
9
10
|
}>()
|
|
10
11
|
|
|
11
|
-
const
|
|
12
|
+
const slotValue = useSlotValue()
|
|
12
13
|
|
|
13
14
|
const link = computed(() => {
|
|
14
15
|
if (props.href) {
|
|
15
16
|
return props.href
|
|
16
17
|
}
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
return slotValue
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
return props.value
|
|
19
|
+
return slotValue.value
|
|
20
|
+
? slotValue.value
|
|
21
|
+
: props.value
|
|
25
22
|
})
|
|
26
23
|
</script>
|
|
27
24
|
|
|
28
25
|
<template>
|
|
29
|
-
<div v-if="
|
|
26
|
+
<div v-if="slotValue || value" class="SDescLink">
|
|
30
27
|
<SLink class="value" :href="link">
|
|
31
|
-
<slot v-if="
|
|
28
|
+
<slot v-if="slotValue" />
|
|
32
29
|
<template v-else>{{ value }}</template>
|
|
33
30
|
</SLink>
|
|
34
31
|
</div>
|
|
@@ -36,11 +33,6 @@ const link = computed(() => {
|
|
|
36
33
|
</template>
|
|
37
34
|
|
|
38
35
|
<style scoped lang="postcss">
|
|
39
|
-
.SDescLink {
|
|
40
|
-
border-bottom: 1px dashed var(--c-divider-1);
|
|
41
|
-
padding-bottom: 7px;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
36
|
.value {
|
|
45
37
|
display: block;
|
|
46
38
|
line-height: 24px;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
import { useSlotValue } from '../composables/Utils'
|
|
3
4
|
import { format } from '../support/Num'
|
|
4
5
|
import SDescEmpty from './SDescEmpty.vue'
|
|
5
6
|
|
|
@@ -8,12 +9,12 @@ const props = defineProps<{
|
|
|
8
9
|
separator?: boolean
|
|
9
10
|
}>()
|
|
10
11
|
|
|
11
|
-
const
|
|
12
|
+
const slotValue = useSlotValue()
|
|
12
13
|
|
|
13
14
|
const _value = computed(() => {
|
|
14
|
-
const
|
|
15
|
+
const sv = slotValue.value
|
|
15
16
|
|
|
16
|
-
const v =
|
|
17
|
+
const v = sv ? Number(sv) : props.value
|
|
17
18
|
|
|
18
19
|
if (v == null) {
|
|
19
20
|
return null
|
|
@@ -33,11 +34,6 @@ const _value = computed(() => {
|
|
|
33
34
|
</template>
|
|
34
35
|
|
|
35
36
|
<style scoped lang="postcss">
|
|
36
|
-
.SDescNumber {
|
|
37
|
-
border-bottom: 1px dashed var(--c-divider-1);
|
|
38
|
-
padding-bottom: 7px;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
37
|
.value {
|
|
42
38
|
line-height: 24px;
|
|
43
39
|
font-size: 14px;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed } from 'vue'
|
|
3
|
+
import { useHasSlotContent } from '../composables/Utils'
|
|
3
4
|
import SDescEmpty from './SDescEmpty.vue'
|
|
4
5
|
|
|
5
6
|
const props = defineProps<{
|
|
@@ -13,13 +14,15 @@ const classes = computed(() => [
|
|
|
13
14
|
{ 'pre-wrap': props.preWrap }
|
|
14
15
|
])
|
|
15
16
|
|
|
17
|
+
const hasSlot = useHasSlotContent()
|
|
18
|
+
|
|
16
19
|
const lineClamp = computed(() => props.lineClamp ?? 'none')
|
|
17
20
|
</script>
|
|
18
21
|
|
|
19
22
|
<template>
|
|
20
|
-
<div v-if="
|
|
23
|
+
<div v-if="hasSlot || value" class="SDescText" :class="classes">
|
|
21
24
|
<div class="value">
|
|
22
|
-
<slot v-if="
|
|
25
|
+
<slot v-if="hasSlot" />
|
|
23
26
|
<template v-else>{{ value }}</template>
|
|
24
27
|
</div>
|
|
25
28
|
</div>
|
|
@@ -27,11 +30,6 @@ const lineClamp = computed(() => props.lineClamp ?? 'none')
|
|
|
27
30
|
</template>
|
|
28
31
|
|
|
29
32
|
<style scoped lang="postcss">
|
|
30
|
-
.SDescText {
|
|
31
|
-
border-bottom: 1px dashed var(--c-divider-1);
|
|
32
|
-
padding-bottom: 7px;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
33
|
.value {
|
|
36
34
|
line-height: 24px;
|
|
37
35
|
font-size: 14px;
|
|
@@ -50,6 +48,10 @@ const lineClamp = computed(() => props.lineClamp ?? 'none')
|
|
|
50
48
|
}
|
|
51
49
|
}
|
|
52
50
|
|
|
51
|
+
.value :deep(p + p) {
|
|
52
|
+
margin-top: 12px;
|
|
53
|
+
}
|
|
54
|
+
|
|
53
55
|
.value :deep(a) {
|
|
54
56
|
color: var(--c-info-text);
|
|
55
57
|
transition: color 0.25s;
|
|
@@ -19,6 +19,7 @@ const props = withDefaults(defineProps<{
|
|
|
19
19
|
checkText?: string
|
|
20
20
|
checkColor?: Color
|
|
21
21
|
text?: string
|
|
22
|
+
disabled?: boolean
|
|
22
23
|
value?: boolean
|
|
23
24
|
modelValue?: boolean
|
|
24
25
|
validation?: Validatable
|
|
@@ -33,6 +34,11 @@ const emit = defineEmits<{
|
|
|
33
34
|
(e: 'change', value: boolean): void
|
|
34
35
|
}>()
|
|
35
36
|
|
|
37
|
+
const classes = computed(() => [
|
|
38
|
+
props.size ?? 'small',
|
|
39
|
+
{ disabled: props.disabled }
|
|
40
|
+
])
|
|
41
|
+
|
|
36
42
|
const _value = computed(() => {
|
|
37
43
|
return props.modelValue !== undefined
|
|
38
44
|
? props.modelValue
|
|
@@ -40,15 +46,17 @@ const _value = computed(() => {
|
|
|
40
46
|
})
|
|
41
47
|
|
|
42
48
|
function onClick() {
|
|
43
|
-
|
|
44
|
-
|
|
49
|
+
if (!props.disabled) {
|
|
50
|
+
emit('update:model-value', !_value.value)
|
|
51
|
+
emit('change', !_value.value)
|
|
52
|
+
}
|
|
45
53
|
}
|
|
46
54
|
</script>
|
|
47
55
|
|
|
48
56
|
<template>
|
|
49
57
|
<SInputBase
|
|
50
58
|
class="SInputCheckbox"
|
|
51
|
-
:class="
|
|
59
|
+
:class="classes"
|
|
52
60
|
:label="label"
|
|
53
61
|
:note="note"
|
|
54
62
|
:info="info"
|
|
@@ -59,7 +67,13 @@ function onClick() {
|
|
|
59
67
|
:validation="validation"
|
|
60
68
|
>
|
|
61
69
|
<div class="container">
|
|
62
|
-
<div
|
|
70
|
+
<div
|
|
71
|
+
class="input"
|
|
72
|
+
:class="{ on: _value }"
|
|
73
|
+
role="button"
|
|
74
|
+
@click="onClick"
|
|
75
|
+
:aria-disabled="disabled"
|
|
76
|
+
>
|
|
63
77
|
<div class="box">
|
|
64
78
|
<div class="check">
|
|
65
79
|
<SIcon :icon="IconCheck" class="check-icon" />
|
|
@@ -139,4 +153,16 @@ function onClick() {
|
|
|
139
153
|
font-size: 14px;
|
|
140
154
|
font-weight: 400;
|
|
141
155
|
}
|
|
156
|
+
|
|
157
|
+
.SInputCheckbox.disabled {
|
|
158
|
+
.box {
|
|
159
|
+
border-color: var(--input-disabled-border-color);
|
|
160
|
+
background-color: var(--input-disabled-bg-color);
|
|
161
|
+
|
|
162
|
+
&:hover { border-color: var(--input-disabled-border-color); }
|
|
163
|
+
&:focus:not(:focus-visible) { border-color: var(--input-disabled-border-color); }
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.input { cursor: not-allowed; }
|
|
167
|
+
}
|
|
142
168
|
</style>
|
|
@@ -13,6 +13,7 @@ export type Value = string | number | boolean
|
|
|
13
13
|
export interface Option {
|
|
14
14
|
label: string
|
|
15
15
|
value: Value
|
|
16
|
+
disabled?: boolean
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
const props = withDefaults(defineProps<{
|
|
@@ -27,6 +28,7 @@ const props = withDefaults(defineProps<{
|
|
|
27
28
|
checkColor?: Color
|
|
28
29
|
options: Option[]
|
|
29
30
|
nullable?: boolean
|
|
31
|
+
disabled?: boolean
|
|
30
32
|
value?: Value[]
|
|
31
33
|
modelValue?: Value[]
|
|
32
34
|
validation?: Validatable
|
|
@@ -82,6 +84,7 @@ function handleChange(value: Value): void {
|
|
|
82
84
|
<div v-for="option in options" :key="String(option.value)" class="col">
|
|
83
85
|
<SInputCheckbox
|
|
84
86
|
:text="option.label"
|
|
87
|
+
:disabled="option.disabled ?? disabled"
|
|
85
88
|
:model-value="isChecked(option.value)"
|
|
86
89
|
@update:model-value="handleChange(option.value)"
|
|
87
90
|
/>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { type IconifyIcon } from '@iconify/vue/dist/offline'
|
|
3
|
-
import { type DefineComponent } from 'vue'
|
|
3
|
+
import { type DefineComponent, computed } from 'vue'
|
|
4
4
|
import { type Validatable } from '../composables/Validation'
|
|
5
5
|
import SInputBase from './SInputBase.vue'
|
|
6
6
|
|
|
@@ -18,6 +18,7 @@ const props = defineProps<{
|
|
|
18
18
|
checkText?: string
|
|
19
19
|
checkColor?: Color
|
|
20
20
|
text: string
|
|
21
|
+
disabled?: boolean
|
|
21
22
|
modelValue: boolean
|
|
22
23
|
validation?: Validatable
|
|
23
24
|
hideError?: boolean
|
|
@@ -28,16 +29,23 @@ const emit = defineEmits<{
|
|
|
28
29
|
(e: 'change', value: boolean): void
|
|
29
30
|
}>()
|
|
30
31
|
|
|
32
|
+
const classes = computed(() => [
|
|
33
|
+
props.size ?? 'small',
|
|
34
|
+
{ disabled: props.disabled }
|
|
35
|
+
])
|
|
36
|
+
|
|
31
37
|
function onClick() {
|
|
32
|
-
|
|
33
|
-
|
|
38
|
+
if (!props.disabled) {
|
|
39
|
+
emit('update:model-value', !props.modelValue)
|
|
40
|
+
emit('change', !props.modelValue)
|
|
41
|
+
}
|
|
34
42
|
}
|
|
35
43
|
</script>
|
|
36
44
|
|
|
37
45
|
<template>
|
|
38
46
|
<SInputBase
|
|
39
47
|
class="SInputRadio"
|
|
40
|
-
:class="
|
|
48
|
+
:class="classes"
|
|
41
49
|
:label="label"
|
|
42
50
|
:note="note"
|
|
43
51
|
:info="info"
|
|
@@ -49,7 +57,13 @@ function onClick() {
|
|
|
49
57
|
:hide-error="hideError"
|
|
50
58
|
>
|
|
51
59
|
<div class="container">
|
|
52
|
-
<div
|
|
60
|
+
<div
|
|
61
|
+
class="input"
|
|
62
|
+
:class="{ on: props.modelValue }"
|
|
63
|
+
role="button"
|
|
64
|
+
@click="onClick"
|
|
65
|
+
:aria-disabled="disabled"
|
|
66
|
+
>
|
|
53
67
|
<div class="box">
|
|
54
68
|
<div class="check" />
|
|
55
69
|
</div>
|
|
@@ -125,4 +139,16 @@ function onClick() {
|
|
|
125
139
|
font-size: 14px;
|
|
126
140
|
font-weight: 400;
|
|
127
141
|
}
|
|
142
|
+
|
|
143
|
+
.SInputRadio.disabled {
|
|
144
|
+
.box {
|
|
145
|
+
border-color: var(--input-disabled-border-color);
|
|
146
|
+
background-color: var(--input-disabled-bg-color);
|
|
147
|
+
|
|
148
|
+
&:hover { border-color: var(--input-disabled-border-color); }
|
|
149
|
+
&:focus:not(:focus-visible) { border-color: var(--input-disabled-border-color); }
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.input { cursor: not-allowed; }
|
|
153
|
+
}
|
|
128
154
|
</style>
|
|
@@ -12,6 +12,7 @@ export type Color = 'neutral' | 'mute' | 'info' | 'success' | 'warning' | 'dange
|
|
|
12
12
|
export interface Option {
|
|
13
13
|
label: string
|
|
14
14
|
value: string | number | boolean
|
|
15
|
+
disabled?: boolean
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
const props = withDefaults(defineProps<{
|
|
@@ -26,6 +27,7 @@ const props = withDefaults(defineProps<{
|
|
|
26
27
|
checkColor?: Color
|
|
27
28
|
options: Option[]
|
|
28
29
|
nullable?: boolean
|
|
30
|
+
disabled?: boolean
|
|
29
31
|
value?: string | number | boolean | null
|
|
30
32
|
modelValue?: string | number | boolean | null
|
|
31
33
|
validation?: Validatable
|
|
@@ -92,6 +94,7 @@ function onChange(value: string | number | boolean) {
|
|
|
92
94
|
<div v-for="(option, index) in options" :key="index" class="col">
|
|
93
95
|
<SInputRadio
|
|
94
96
|
:text="option.label"
|
|
97
|
+
:disabled="option.disabled ?? disabled"
|
|
95
98
|
:model-value="isChecked(option.value)"
|
|
96
99
|
@update:model-value="onUpdate(option.value)"
|
|
97
100
|
@change="onChange(option.value)"
|
|
@@ -277,6 +277,9 @@ function createRequiredTouched(): boolean[] {
|
|
|
277
277
|
.container {
|
|
278
278
|
background-color: var(--input-disabled-bg-color);
|
|
279
279
|
}
|
|
280
|
+
|
|
281
|
+
.container:hover { border-color: var(--input-border-color); }
|
|
282
|
+
.container.focus { border-color: var(--input-border-color); }
|
|
280
283
|
}
|
|
281
284
|
|
|
282
285
|
.SInputYMD.has-error {
|
package/lib/composables/Utils.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type MaybeRefOrGetter, resolveUnref } from '@vueuse/core'
|
|
2
|
-
import { type ComputedRef, computed } from 'vue'
|
|
2
|
+
import { type ComputedRef, computed, useSlots } from 'vue'
|
|
3
|
+
import { isArray, isString } from '../support/Utils'
|
|
3
4
|
|
|
4
5
|
export type WhenCondition<T> = MaybeRefOrGetter<T>
|
|
5
6
|
|
|
@@ -33,3 +34,31 @@ export function computedArray<T = any>(fn: (arr: T[]) => void): ComputedRef<T[]>
|
|
|
33
34
|
return arr
|
|
34
35
|
})
|
|
35
36
|
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Checks whether the slot has a non empty value.
|
|
40
|
+
*/
|
|
41
|
+
export function useHasSlotContent(name = 'default'): ComputedRef<boolean> {
|
|
42
|
+
const slots = useSlots()
|
|
43
|
+
|
|
44
|
+
return computed(() => {
|
|
45
|
+
return !!slots[name]?.().some((s) => {
|
|
46
|
+
return isArray(s.children) ? true : !!(s.children as string).trim()
|
|
47
|
+
})
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Get the slot value. If the slot contains child nodes, it will get ignored
|
|
53
|
+
* and treated as if it was empty. This composable is useful to get the plain
|
|
54
|
+
* text out of the slot content.
|
|
55
|
+
*/
|
|
56
|
+
export function useSlotValue(name = 'default'): ComputedRef<string | null> {
|
|
57
|
+
const slots = useSlots()
|
|
58
|
+
|
|
59
|
+
return computed(() => {
|
|
60
|
+
const c = slots[name]?.()[0]?.children
|
|
61
|
+
const v = isString(c) ? c.trim() : null
|
|
62
|
+
return v !== '' ? v : null
|
|
63
|
+
})
|
|
64
|
+
}
|