@globalbrain/sefirot 4.30.1 → 4.32.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/client.d.ts +5 -0
- package/config/nuxt.d.ts +1 -0
- package/config/nuxt.js +8 -5
- package/config/vite.js +4 -13
- package/lib/components/SActionList.vue +2 -2
- package/lib/components/SActionMenu.vue +43 -7
- package/lib/components/SAvatar.vue +1 -1
- package/lib/components/SAvatarStack.vue +12 -12
- package/lib/components/SButton.vue +5 -7
- package/lib/components/SCard.vue +2 -2
- package/lib/components/SChartBar.vue +37 -12
- package/lib/components/SChartPie.vue +13 -7
- package/lib/components/SControlActionBarCollapse.vue +2 -4
- package/lib/components/SControlInputSearch.vue +7 -2
- package/lib/components/SDataListItem.vue +1 -3
- package/lib/components/SDescAvatar.vue +1 -1
- package/lib/components/SDescDay.vue +2 -2
- package/lib/components/SDescFile.vue +2 -4
- package/lib/components/SDescItem.vue +2 -1
- package/lib/components/SDescLabel.vue +1 -1
- package/lib/components/SDescLink.vue +2 -7
- package/lib/components/SDescPill.vue +2 -4
- package/lib/components/SDescText.vue +3 -3
- package/lib/components/SDropdown.vue +1 -1
- package/lib/components/SDropdownSectionFilter.vue +11 -11
- package/lib/components/SFragment.vue +1 -1
- package/lib/components/SInputAddon.vue +13 -11
- package/lib/components/SInputBase.vue +11 -11
- package/lib/components/SInputCheckbox.vue +6 -3
- package/lib/components/SInputCheckboxes.vue +7 -3
- package/lib/components/SInputDate.vue +3 -5
- package/lib/components/SInputDropdown.vue +26 -28
- package/lib/components/SInputDropdownItem.vue +21 -11
- package/lib/components/SInputFile.vue +9 -6
- package/lib/components/SInputFileUpload.vue +9 -11
- package/lib/components/SInputFileUploadItem.vue +8 -4
- package/lib/components/SInputHMS.vue +3 -1
- package/lib/components/SInputImage.vue +4 -2
- package/lib/components/SInputNumber.vue +9 -10
- package/lib/components/SInputRadio.vue +3 -2
- package/lib/components/SInputRadios.vue +6 -5
- package/lib/components/SInputSegments.vue +5 -7
- package/lib/components/SInputSegmentsOption.vue +1 -2
- package/lib/components/SInputSelect.vue +6 -4
- package/lib/components/SInputSwitch.vue +4 -1
- package/lib/components/SInputSwitches.vue +5 -3
- package/lib/components/SInputText.vue +16 -16
- package/lib/components/SInputTextarea.vue +7 -3
- package/lib/components/SInputYMD.vue +3 -1
- package/lib/components/SLink.vue +2 -2
- package/lib/components/SLocalNav.vue +1 -1
- package/lib/components/SLocalNavActions.vue +1 -1
- package/lib/components/SLocalNavMenu.vue +2 -2
- package/lib/components/SLoginPagePasswordDialog.vue +2 -2
- package/lib/components/SM.vue +1 -1
- package/lib/components/SMFade.vue +1 -1
- package/lib/components/SMarkdown.vue +3 -2
- package/lib/components/SModal.vue +2 -2
- package/lib/components/SSnackbar.vue +2 -2
- package/lib/components/SSteps.vue +6 -6
- package/lib/components/STable.vue +70 -27
- package/lib/components/STableCell.vue +14 -17
- package/lib/components/STableCellAvatars.vue +1 -1
- package/lib/components/STableCellDay.vue +12 -5
- package/lib/components/STableCellNumber.vue +2 -3
- package/lib/components/STableCellPath.vue +2 -2
- package/lib/components/STableCellText.vue +2 -3
- package/lib/components/STableColumn.vue +38 -16
- package/lib/components/STableFooter.vue +10 -2
- package/lib/components/STableHeader.vue +0 -1
- package/lib/components/STableHeaderMenu.vue +4 -4
- package/lib/components/STableHeaderMenuItem.vue +1 -1
- package/lib/components/STooltip.vue +3 -3
- package/lib/composables/Api.ts +1 -1
- package/lib/composables/App.ts +13 -11
- package/lib/composables/Dropdown.ts +10 -1
- package/lib/composables/Error.ts +37 -37
- package/lib/composables/Grid.ts +1 -4
- package/lib/composables/Image.ts +2 -3
- package/lib/composables/Lang.ts +8 -16
- package/lib/composables/Markdown.ts +1 -1
- package/lib/composables/Table.ts +0 -2
- package/lib/composables/Theme.ts +1 -13
- package/lib/composables/Utils.ts +11 -4
- package/lib/composables/Validation.ts +1 -4
- package/lib/http/Http.ts +23 -17
- package/lib/styles/variables-deprecated.css +0 -1
- package/lib/styles/variables.css +16 -16
- package/lib/support/Chart.ts +0 -1
- package/lib/support/DateRange.ts +1 -1
- package/lib/support/Day.ts +12 -65
- package/lib/support/File.ts +7 -16
- package/lib/support/Utils.ts +7 -40
- package/lib/validation/Rule.ts +6 -21
- package/lib/validation/rules/decimal.ts +3 -3
- package/lib/validation/rules/email.ts +1 -1
- package/lib/validation/rules/index.ts +1 -1
- package/lib/validation/rules/negativeInteger.ts +1 -1
- package/lib/validation/rules/positiveInteger.ts +1 -1
- package/lib/validation/rules/requiredHms.ts +2 -2
- package/lib/validation/rules/requiredIf.ts +1 -4
- package/lib/validation/rules/requiredYmd.ts +2 -2
- package/lib/validation/rules/slackChannelName.ts +4 -1
- package/lib/validation/rules/zeroOrNegativeInteger.ts +1 -1
- package/lib/validation/rules/zeroOrPositiveInteger.ts +1 -1
- package/lib/validation/validators/after.ts +1 -5
- package/lib/validation/validators/afterOrEqual.ts +1 -5
- package/lib/validation/validators/before.ts +1 -4
- package/lib/validation/validators/beforeOrEqual.ts +1 -5
- package/lib/validation/validators/decimal.ts +7 -9
- package/lib/validation/validators/email.ts +4 -8
- package/lib/validation/validators/fileExtension.ts +7 -15
- package/lib/validation/validators/hms.ts +26 -15
- package/lib/validation/validators/index.ts +0 -2
- package/lib/validation/validators/maxFileSize.ts +3 -13
- package/lib/validation/validators/maxLength.ts +1 -7
- package/lib/validation/validators/maxTotalFileSize.ts +3 -26
- package/lib/validation/validators/maxValue.ts +2 -6
- package/lib/validation/validators/minLength.ts +1 -7
- package/lib/validation/validators/minValue.ts +2 -6
- package/lib/validation/validators/month.ts +1 -7
- package/lib/validation/validators/negativeInteger.ts +1 -7
- package/lib/validation/validators/positiveInteger.ts +1 -7
- package/lib/validation/validators/required.ts +5 -28
- package/lib/validation/validators/requiredHmsIf.ts +11 -13
- package/lib/validation/validators/requiredIf.ts +5 -11
- package/lib/validation/validators/requiredYmdIf.ts +11 -13
- package/lib/validation/validators/slackChannelName.ts +11 -11
- package/lib/validation/validators/url.ts +7 -5
- package/lib/validation/validators/ymd.ts +36 -30
- package/package.json +44 -42
- package/lib/composables/Http.ts +0 -18
- package/lib/validation/validators/requiredHms.ts +0 -9
- package/lib/validation/validators/requiredYmd.ts +0 -9
package/client.d.ts
CHANGED
|
@@ -7,3 +7,8 @@ declare module 'v-calendar' {
|
|
|
7
7
|
export * from 'v-calendar/dist/types/src/index.d.ts'
|
|
8
8
|
export { default } from 'v-calendar/dist/types/src/index.d.ts'
|
|
9
9
|
}
|
|
10
|
+
|
|
11
|
+
interface NumberConstructor {
|
|
12
|
+
isFinite(value: unknown): value is number
|
|
13
|
+
isInteger(value: unknown): value is number
|
|
14
|
+
}
|
package/config/nuxt.d.ts
CHANGED
package/config/nuxt.js
CHANGED
|
@@ -5,25 +5,28 @@ import icons from 'unplugin-icons/nuxt'
|
|
|
5
5
|
import { mergeConfig } from 'vite'
|
|
6
6
|
import { baseConfig as baseViteConfig } from './vite.js'
|
|
7
7
|
|
|
8
|
-
delete baseViteConfig.plugins
|
|
9
|
-
delete baseViteConfig.resolve?.alias
|
|
10
|
-
|
|
11
8
|
export const baseConfig = {
|
|
12
9
|
alias: { sefirot: fileURLToPath(new URL('../lib', import.meta.url)) },
|
|
13
10
|
app: { teleportId: 'sefirot-modals' },
|
|
14
11
|
modules: [
|
|
15
12
|
/**
|
|
13
|
+
* @this {any}
|
|
16
14
|
* @param {any} _
|
|
17
15
|
* @param {any} nuxt
|
|
18
16
|
*/
|
|
19
17
|
function (_, nuxt) {
|
|
20
|
-
// eslint-disable-next-line @typescript-eslint/no-invalid-this
|
|
21
18
|
return icons.bind(this, { scale: 1 }, nuxt)()
|
|
22
19
|
}
|
|
23
20
|
],
|
|
24
21
|
postcss: { plugins: { 'postcss-nested': {} } },
|
|
25
22
|
telemetry: false,
|
|
26
|
-
vite:
|
|
23
|
+
vite: {
|
|
24
|
+
...baseViteConfig,
|
|
25
|
+
resolve: { ...baseViteConfig.resolve, alias: {} },
|
|
26
|
+
plugins: baseViteConfig.plugins?.filter(
|
|
27
|
+
(plugin) => plugin && 'name' in plugin && plugin.name !== 'unplugin-icons'
|
|
28
|
+
)
|
|
29
|
+
}
|
|
27
30
|
}
|
|
28
31
|
|
|
29
32
|
export function defineConfig(config = {}) {
|
package/config/vite.js
CHANGED
|
@@ -1,16 +1,5 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* Adapted from
|
|
5
|
-
* @see https://github.com/unplugin/unplugin-icons/blob/67fd9b7791dc1754cb8dc46b854b22c8bb4cf380/src/core/compilers/vue3.ts
|
|
6
|
-
* @see https://github.com/unplugin/unplugin-icons/blob/639ec9691e022e52c641d0f96f585dbf04dab095/src/core/svgId.ts
|
|
7
|
-
*
|
|
8
|
-
* Original licenses:
|
|
9
|
-
*
|
|
10
|
-
* Copyright (c) 2020 Anthony Fu <https://github.com/antfu>
|
|
11
|
-
* @license MIT
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
3
|
import { fileURLToPath } from 'node:url'
|
|
15
4
|
import MagicString from 'magic-string'
|
|
16
5
|
import icons from 'unplugin-icons/vite'
|
|
@@ -48,6 +37,7 @@ export const baseConfig = {
|
|
|
48
37
|
|
|
49
38
|
// list the client-side direct dependencies/peerDependencies which get bundled
|
|
50
39
|
dedupe: [
|
|
40
|
+
'@popperjs/core',
|
|
51
41
|
'@sentry/browser',
|
|
52
42
|
'@sentry/vue',
|
|
53
43
|
'@tanstack/vue-virtual',
|
|
@@ -84,9 +74,10 @@ export const baseConfig = {
|
|
|
84
74
|
'dayjs/plugin/relativeTime',
|
|
85
75
|
'dayjs/plugin/timezone',
|
|
86
76
|
'dayjs/plugin/utc',
|
|
77
|
+
'file-saver',
|
|
78
|
+
'isomorphic-dompurify',
|
|
87
79
|
'markdown-it > argparse',
|
|
88
|
-
'markdown-it > entities'
|
|
89
|
-
'file-saver'
|
|
80
|
+
'markdown-it > entities'
|
|
90
81
|
],
|
|
91
82
|
exclude: [
|
|
92
83
|
'markdown-it'
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { type Component, ref } from 'vue'
|
|
2
|
+
import { type Component, ref, useTemplateRef } from 'vue'
|
|
3
3
|
import { type DropdownSection, useManualDropdownPosition } from '../composables/Dropdown'
|
|
4
4
|
import { useFlyout } from '../composables/Flyout'
|
|
5
5
|
import SButton, { type Mode, type Size, type Tooltip, type Type } from './SButton.vue'
|
|
@@ -29,21 +29,52 @@ const props = withDefaults(defineProps<{
|
|
|
29
29
|
dropdownAlign: 'left'
|
|
30
30
|
})
|
|
31
31
|
|
|
32
|
-
const
|
|
32
|
+
const containerRef = useTemplateRef('container')
|
|
33
|
+
const dropdownRef = useTemplateRef('dropdown')
|
|
33
34
|
|
|
34
|
-
const { isOpen, toggle } = useFlyout(
|
|
35
|
-
const { position, update:
|
|
35
|
+
const { isOpen, toggle } = useFlyout(containerRef)
|
|
36
|
+
const { position: verticalPlacement, update: updateVerticalPlacement } =
|
|
37
|
+
useManualDropdownPosition(containerRef)
|
|
38
|
+
|
|
39
|
+
const actualAlign = ref(props.dropdownAlign)
|
|
40
|
+
|
|
41
|
+
function calculateOptimalAlign(dropdownElement: HTMLElement): 'left' | 'right' {
|
|
42
|
+
// Temporarily show the dropdown to measure it (similar to tooltip approach)
|
|
43
|
+
const originalDisplay = dropdownElement.style.display
|
|
44
|
+
dropdownElement.style.display = 'block'
|
|
45
|
+
const dropdownRect = dropdownElement.getBoundingClientRect()
|
|
46
|
+
dropdownElement.style.display = originalDisplay
|
|
47
|
+
|
|
48
|
+
const dropdownWidth = dropdownRect.width
|
|
49
|
+
|
|
50
|
+
const viewportWidth = window.innerWidth
|
|
51
|
+
const containerRect = containerRef.value!.getBoundingClientRect()
|
|
52
|
+
|
|
53
|
+
const spaceOnRight = viewportWidth - containerRect.left
|
|
54
|
+
const spaceOnLeft = containerRect.right
|
|
55
|
+
|
|
56
|
+
if (props.dropdownAlign === 'left') {
|
|
57
|
+
return spaceOnRight >= dropdownWidth ? 'left' : 'right'
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return spaceOnLeft >= dropdownWidth ? 'right' : 'left'
|
|
61
|
+
}
|
|
36
62
|
|
|
37
63
|
async function onOpen() {
|
|
38
64
|
if (!props.disabled) {
|
|
39
|
-
|
|
65
|
+
updateVerticalPlacement()
|
|
66
|
+
|
|
67
|
+
if (dropdownRef.value) {
|
|
68
|
+
actualAlign.value = calculateOptimalAlign(dropdownRef.value)
|
|
69
|
+
}
|
|
70
|
+
|
|
40
71
|
toggle()
|
|
41
72
|
}
|
|
42
73
|
}
|
|
43
74
|
</script>
|
|
44
75
|
|
|
45
76
|
<template>
|
|
46
|
-
<div class="SActionMenu" :class="[{ block },
|
|
77
|
+
<div ref="container" class="SActionMenu" :class="[{ block }, actualAlign]">
|
|
47
78
|
<div class="button">
|
|
48
79
|
<SButton
|
|
49
80
|
:tag
|
|
@@ -64,7 +95,12 @@ async function onOpen() {
|
|
|
64
95
|
@click="onOpen"
|
|
65
96
|
/>
|
|
66
97
|
</div>
|
|
67
|
-
<div
|
|
98
|
+
<div
|
|
99
|
+
ref="dropdown"
|
|
100
|
+
class="dropdown"
|
|
101
|
+
:class="verticalPlacement"
|
|
102
|
+
:style="{ display: isOpen ? 'block' : 'none' }"
|
|
103
|
+
>
|
|
68
104
|
<SDropdown :sections="options" />
|
|
69
105
|
</div>
|
|
70
106
|
</div>
|
|
@@ -28,7 +28,7 @@ const classes = computed(() => [
|
|
|
28
28
|
const initial = computed(() => props.name?.charAt(0).toUpperCase())
|
|
29
29
|
|
|
30
30
|
const tooltipPosition = computed(() => {
|
|
31
|
-
return
|
|
31
|
+
return props.tooltip && typeof props.tooltip === 'object'
|
|
32
32
|
? props.tooltip.position || 'top'
|
|
33
33
|
: 'top'
|
|
34
34
|
})
|
|
@@ -27,8 +27,8 @@ const count = computed(() => {
|
|
|
27
27
|
<template>
|
|
28
28
|
<div class="SAvatarStack" :class="size">
|
|
29
29
|
<SAvatar
|
|
30
|
-
v-for="(avatar,
|
|
31
|
-
:key="
|
|
30
|
+
v-for="(avatar, i) in avatars"
|
|
31
|
+
:key="i"
|
|
32
32
|
:size
|
|
33
33
|
:avatar="avatar.image"
|
|
34
34
|
:name="avatar.name"
|
|
@@ -49,11 +49,11 @@ const count = computed(() => {
|
|
|
49
49
|
overflow: hidden;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
&.mini > :deep(*):not(:last-child) { margin-right: -6px }
|
|
53
|
-
&.small > :deep(*):not(:last-child) { margin-right: -8px }
|
|
54
|
-
&.medium > :deep(*):not(:last-child) { margin-right: -8px }
|
|
55
|
-
&.large > :deep(*):not(:last-child) { margin-right: -12px }
|
|
56
|
-
&.jumbo > :deep(*):not(:last-child) { margin-right: -16px }
|
|
52
|
+
&.mini > :deep(*):not(:last-child) { margin-right: -6px; }
|
|
53
|
+
&.small > :deep(*):not(:last-child) { margin-right: -8px; }
|
|
54
|
+
&.medium > :deep(*):not(:last-child) { margin-right: -8px; }
|
|
55
|
+
&.large > :deep(*):not(:last-child) { margin-right: -12px; }
|
|
56
|
+
&.jumbo > :deep(*):not(:last-child) { margin-right: -16px; }
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
.more {
|
|
@@ -69,10 +69,10 @@ const count = computed(() => {
|
|
|
69
69
|
z-index: 1;
|
|
70
70
|
height: 100%;
|
|
71
71
|
|
|
72
|
-
.mini & { font-size: 10px }
|
|
73
|
-
.small & { font-size: 10px }
|
|
74
|
-
.medium & { font-size: 12px }
|
|
75
|
-
.large & { font-size: 12px }
|
|
76
|
-
.jumbo & { font-size: 14px }
|
|
72
|
+
.mini & { font-size: 10px; }
|
|
73
|
+
.small & { font-size: 10px; }
|
|
74
|
+
.medium & { font-size: 12px; }
|
|
75
|
+
.large & { font-size: 12px; }
|
|
76
|
+
.jumbo & { font-size: 14px; }
|
|
77
77
|
}
|
|
78
78
|
</style>
|
|
@@ -82,9 +82,7 @@ const classes = computed(() => [
|
|
|
82
82
|
])
|
|
83
83
|
|
|
84
84
|
const computedTag = computed(() => {
|
|
85
|
-
return props.tag
|
|
86
|
-
? props.tag
|
|
87
|
-
: props.href ? SLink : 'button'
|
|
85
|
+
return props.tag ? props.tag : props.href ? SLink : 'button'
|
|
88
86
|
})
|
|
89
87
|
|
|
90
88
|
const slots = useSlots()
|
|
@@ -96,7 +94,7 @@ const hasTooltip = computed(() => {
|
|
|
96
94
|
)
|
|
97
95
|
})
|
|
98
96
|
|
|
99
|
-
function
|
|
97
|
+
function onClick(): void {
|
|
100
98
|
if (!props.loading) {
|
|
101
99
|
props.disabled ? emit('disabled-click') : emit('click')
|
|
102
100
|
}
|
|
@@ -109,8 +107,8 @@ function handleClick(): void {
|
|
|
109
107
|
:tag="typeof tooltip === 'object' ? tooltip.tag : undefined"
|
|
110
108
|
:text="typeof tooltip === 'object' ? unref(tooltip.text) : tooltip"
|
|
111
109
|
:position="typeof tooltip === 'object' ? tooltip.position : undefined"
|
|
112
|
-
:display="typeof tooltip === 'object' ? tooltip.display ?? 'inline-block' : 'inline-block'"
|
|
113
|
-
:trigger="typeof tooltip === 'object' ? tooltip.trigger ?? 'both' : 'both'"
|
|
110
|
+
:display="typeof tooltip === 'object' ? (tooltip.display ?? 'inline-block') : 'inline-block'"
|
|
111
|
+
:trigger="typeof tooltip === 'object' ? (tooltip.trigger ?? 'both') : 'both'"
|
|
114
112
|
:timeout="typeof tooltip === 'object' ? tooltip.timeout : undefined"
|
|
115
113
|
:tabindex="-1"
|
|
116
114
|
>
|
|
@@ -121,7 +119,7 @@ function handleClick(): void {
|
|
|
121
119
|
:class="classes"
|
|
122
120
|
:href
|
|
123
121
|
role="button"
|
|
124
|
-
@click="
|
|
122
|
+
@click="onClick"
|
|
125
123
|
>
|
|
126
124
|
<span class="content">
|
|
127
125
|
<span v-if="_leadIcon" class="icon" :class="iconMode">
|
package/lib/components/SCard.vue
CHANGED
|
@@ -10,13 +10,13 @@ const props = defineProps<{
|
|
|
10
10
|
mode?: Mode
|
|
11
11
|
}>()
|
|
12
12
|
|
|
13
|
+
const { isCollapsed } = provideCardState()
|
|
14
|
+
|
|
13
15
|
const classes = computed(() => [
|
|
14
16
|
props.size,
|
|
15
17
|
props.mode ?? 'neutral',
|
|
16
18
|
{ collapsed: isCollapsed.value }
|
|
17
19
|
])
|
|
18
|
-
|
|
19
|
-
const { isCollapsed } = provideCardState()
|
|
20
20
|
</script>
|
|
21
21
|
|
|
22
22
|
<template>
|
|
@@ -83,26 +83,51 @@ function renderChart({
|
|
|
83
83
|
// Set dimensions and margins
|
|
84
84
|
const vertical = props.type === 'vertical'
|
|
85
85
|
|
|
86
|
-
const maxKeyLength = props.data.reduce(
|
|
87
|
-
|
|
86
|
+
const maxKeyLength = props.data.reduce(
|
|
87
|
+
(a, b) => Math.max(a, b.key.length),
|
|
88
|
+
Number.NEGATIVE_INFINITY
|
|
89
|
+
)
|
|
90
|
+
const maxValueLength = props.data.reduce(
|
|
91
|
+
(a, b) => Math.max(a, b.value.toLocaleString().length),
|
|
92
|
+
Number.NEGATIVE_INFINITY
|
|
93
|
+
)
|
|
88
94
|
|
|
89
95
|
const maxVerticalTickWidthInCh = vertical ? maxValueLength : maxKeyLength
|
|
90
|
-
const maxVerticalTickWidthInPx = getTextSize(
|
|
91
|
-
|
|
96
|
+
const maxVerticalTickWidthInPx = getTextSize(
|
|
97
|
+
'0'.repeat(maxVerticalTickWidthInCh),
|
|
98
|
+
`400 ${props.tickFontSize} ${font}`
|
|
99
|
+
).width
|
|
100
|
+
const verticalLabelWidthInPx = props.yLabel
|
|
101
|
+
? getTextSize(props.yLabel, `400 ${props.yLabelFontSize} ${font}`).height
|
|
102
|
+
: 0
|
|
92
103
|
const gapBetweenVerticalLabelAndTicks = props.yLabel ? props.yLabelTickGap : 0
|
|
93
104
|
|
|
94
|
-
const maxHorizontalTickHeightInPx = getTextSize(
|
|
95
|
-
|
|
105
|
+
const maxHorizontalTickHeightInPx = getTextSize(
|
|
106
|
+
'0',
|
|
107
|
+
`400 ${props.tickFontSize} ${font}`
|
|
108
|
+
).height // wrapping isn't supported
|
|
109
|
+
const horizontalLabelHeightInPx = props.xLabel
|
|
110
|
+
? getTextSize(props.xLabel, `400 ${props.xLabelFontSize} ${font}`).height
|
|
111
|
+
: 0
|
|
96
112
|
const gapBetweenHorizontalLabelAndTicks = props.xLabel ? props.xLabelTickGap : 0
|
|
97
113
|
|
|
98
|
-
const xLabelOffset = props.xLabelOffset
|
|
99
|
-
|
|
114
|
+
const xLabelOffset = props.xLabelOffset
|
|
115
|
+
?? horizontalLabelHeightInPx + 9 + maxHorizontalTickHeightInPx + gapBetweenHorizontalLabelAndTicks
|
|
116
|
+
const yLabelOffset = props.yLabelOffset
|
|
117
|
+
?? 9 + maxVerticalTickWidthInPx + gapBetweenVerticalLabelAndTicks
|
|
100
118
|
|
|
101
119
|
const margin = {
|
|
102
120
|
top: props.margins?.top ?? 30,
|
|
103
121
|
right: props.margins?.right ?? 30,
|
|
104
|
-
bottom:
|
|
105
|
-
|
|
122
|
+
bottom:
|
|
123
|
+
(props.margins?.bottom ?? 30)
|
|
124
|
+
+ horizontalLabelHeightInPx
|
|
125
|
+
+ xLabelOffset
|
|
126
|
+
- (props.xLabel ? 9 : 0),
|
|
127
|
+
left:
|
|
128
|
+
(props.margins?.left ?? 30)
|
|
129
|
+
+ verticalLabelWidthInPx
|
|
130
|
+
+ yLabelOffset
|
|
106
131
|
}
|
|
107
132
|
|
|
108
133
|
const width = clientWidth - margin.left - margin.right
|
|
@@ -224,8 +249,8 @@ function renderChart({
|
|
|
224
249
|
.append('g')
|
|
225
250
|
.attr('transform', (d) =>
|
|
226
251
|
vertical
|
|
227
|
-
? `translate(${
|
|
228
|
-
: `translate(0,${
|
|
252
|
+
? `translate(${paddedScale(d.key)! - groupOffset},0)`
|
|
253
|
+
: `translate(0,${paddedScale(d.key)! - groupOffset})`
|
|
229
254
|
)
|
|
230
255
|
|
|
231
256
|
// Each group gets a transparent rect covering the full band (using paddedScale.step())
|
|
@@ -180,12 +180,18 @@ function renderChart({
|
|
|
180
180
|
// Calculate radius and center the chart
|
|
181
181
|
const r_k = props.half ? 0.25 : 0.5
|
|
182
182
|
const radius = Math.min(height_2, (width - legendWidth) / (2 + (props.legend ? r_k : 0)))
|
|
183
|
-
const innerRadius = props.innerRadius?.(radius)
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
183
|
+
const innerRadius = props.innerRadius?.(radius)
|
|
184
|
+
?? (props.type === 'pie' ? 6 : Math.max(radius / 1.5, radius - 50))
|
|
185
|
+
|
|
186
|
+
legendGroup?.attr(
|
|
187
|
+
'transform',
|
|
188
|
+
`translate(${radius * (1 + r_k)},${-(props.half ? height_2 : 0) / 2 - legendHeight / 2})`
|
|
189
|
+
)
|
|
190
|
+
svg.attr(
|
|
191
|
+
'transform',
|
|
192
|
+
`translate(${margin.left + width_2 - (props.legend ? radius * r_k + legendWidth : 0) / 2}`
|
|
193
|
+
+ `,${margin.top + height_2})`
|
|
194
|
+
)
|
|
189
195
|
|
|
190
196
|
// Create arc generator
|
|
191
197
|
const arc = d3
|
|
@@ -275,7 +281,7 @@ function renderChart({
|
|
|
275
281
|
})
|
|
276
282
|
.attr('dy', '0.35em')
|
|
277
283
|
.attr('fill', c.text2)
|
|
278
|
-
.attr('text-anchor', (d) => leftOrRight(d) === 1 ? 'start' : 'end')
|
|
284
|
+
.attr('text-anchor', (d) => (leftOrRight(d) === 1 ? 'start' : 'end'))
|
|
279
285
|
.style('font-size', props.labelFontSize)
|
|
280
286
|
.html((d) => props.labelFormat(d.data))
|
|
281
287
|
|
|
@@ -21,14 +21,12 @@ setCollapse(props.collapsed)
|
|
|
21
21
|
const el = shallowRef<HTMLElement | null>(null)
|
|
22
22
|
|
|
23
23
|
const icon = computed(() => {
|
|
24
|
-
return isCollapsed.value
|
|
25
|
-
? IconArrowsOutLineVertical
|
|
26
|
-
: IconArrowsInLineVertical
|
|
24
|
+
return isCollapsed.value ? IconArrowsOutLineVertical : IconArrowsInLineVertical
|
|
27
25
|
})
|
|
28
26
|
</script>
|
|
29
27
|
|
|
30
28
|
<template>
|
|
31
|
-
<div
|
|
29
|
+
<div ref="el" class="SControlActionBarCollapse">
|
|
32
30
|
<SControlActionBarButton
|
|
33
31
|
:as
|
|
34
32
|
:icon
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import IconMagnifyingGlass from '~icons/ph/magnifying-glass-bold'
|
|
3
|
-
import { computed } from 'vue'
|
|
3
|
+
import { type Component, computed } from 'vue'
|
|
4
4
|
import { useControlSize } from '../composables/Control'
|
|
5
5
|
import { useTrans } from '../composables/Lang'
|
|
6
6
|
import { type Validatable } from '../composables/Validation'
|
|
@@ -8,7 +8,7 @@ import SInputText, { type Align, type TextColor } from './SInputText.vue'
|
|
|
8
8
|
|
|
9
9
|
const props = defineProps<{
|
|
10
10
|
placeholder?: string
|
|
11
|
-
unitAfter?:
|
|
11
|
+
unitAfter?: Component | string
|
|
12
12
|
textColor?: TextColor | ((value: string | null) => TextColor)
|
|
13
13
|
align?: Align
|
|
14
14
|
disabled?: boolean
|
|
@@ -52,7 +52,12 @@ const _value = computed(() => {
|
|
|
52
52
|
type="search"
|
|
53
53
|
:placeholder="placeholder ?? t.placeholder"
|
|
54
54
|
:unit-before="IconMagnifyingGlass"
|
|
55
|
+
:unit-after
|
|
56
|
+
:text-color
|
|
57
|
+
:align
|
|
58
|
+
:disabled
|
|
55
59
|
:model-value="_value"
|
|
60
|
+
:display-value
|
|
56
61
|
:validation
|
|
57
62
|
hide-error
|
|
58
63
|
@update:model-value="$emit('update:model-value', $event)"
|
|
@@ -26,7 +26,7 @@ const _avatar = computed(() => {
|
|
|
26
26
|
|
|
27
27
|
<template>
|
|
28
28
|
<div v-if="_avatar?.length" class="SDescAvatar" :class="[dir]">
|
|
29
|
-
<div v-for="a, i in _avatar" :key="i" class="value">
|
|
29
|
+
<div v-for="(a, i) in _avatar" :key="i" class="value">
|
|
30
30
|
<SAvatar
|
|
31
31
|
size="nano"
|
|
32
32
|
:avatar="a.avatar"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed } from 'vue'
|
|
3
3
|
import { useSlotValue } from '../composables/Utils'
|
|
4
|
-
import { type Day } from '../support/Day'
|
|
4
|
+
import { type Day, day } from '../support/Day'
|
|
5
5
|
import SDescEmpty from './SDescEmpty.vue'
|
|
6
6
|
|
|
7
7
|
const props = defineProps<{
|
|
@@ -17,7 +17,7 @@ const _value = computed(() => {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
if (props.value) {
|
|
20
|
-
return props.value.format(props.format ?? 'YYYY-MM-DD HH:mm:ss')
|
|
20
|
+
return day(props.value).format(props.format ?? 'YYYY-MM-DD HH:mm:ss')
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
return null
|
|
@@ -15,16 +15,14 @@ const props = defineProps<{
|
|
|
15
15
|
}>()
|
|
16
16
|
|
|
17
17
|
const items = computed(() => {
|
|
18
|
-
return props.item
|
|
19
|
-
? Array.isArray(props.item) ? props.item : [props.item]
|
|
20
|
-
: null
|
|
18
|
+
return props.item ? (Array.isArray(props.item) ? props.item : [props.item]) : null
|
|
21
19
|
})
|
|
22
20
|
</script>
|
|
23
21
|
|
|
24
22
|
<template>
|
|
25
23
|
<div v-if="items && items.length" class="SDescFile">
|
|
26
24
|
<div class="value">
|
|
27
|
-
<div v-for="item,
|
|
25
|
+
<div v-for="(item, i) in items" :key="i" class="item">
|
|
28
26
|
<div class="data">
|
|
29
27
|
<div class="icon"><IconFileText class="icon-svg" /></div>
|
|
30
28
|
<div class="name">{{ item.name }}</div>
|
|
@@ -44,7 +44,7 @@ function isActionButton(action: Action): action is ActionButton {
|
|
|
44
44
|
<template v-else>{{ value }}</template>
|
|
45
45
|
</div>
|
|
46
46
|
<div v-if="actions?.length" class="actions">
|
|
47
|
-
<template v-for="action,
|
|
47
|
+
<template v-for="(action, i) in actions" :key="i">
|
|
48
48
|
<SButton
|
|
49
49
|
v-if="isActionButton(action)"
|
|
50
50
|
type="text"
|
|
@@ -12,13 +12,8 @@ const props = defineProps<{
|
|
|
12
12
|
const slotValue = useSlotValue()
|
|
13
13
|
|
|
14
14
|
const link = computed(() => {
|
|
15
|
-
if (props.href) {
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
return slotValue.value
|
|
20
|
-
? slotValue.value
|
|
21
|
-
: props.value
|
|
15
|
+
if (props.href) { return props.href }
|
|
16
|
+
return slotValue.value ? slotValue.value : props.value
|
|
22
17
|
})
|
|
23
18
|
</script>
|
|
24
19
|
|
|
@@ -13,16 +13,14 @@ const props = defineProps<{
|
|
|
13
13
|
}>()
|
|
14
14
|
|
|
15
15
|
const pills = computed(() => {
|
|
16
|
-
return props.pill
|
|
17
|
-
? Array.isArray(props.pill) ? props.pill : [props.pill]
|
|
18
|
-
: null
|
|
16
|
+
return props.pill ? (Array.isArray(props.pill) ? props.pill : [props.pill]) : null
|
|
19
17
|
})
|
|
20
18
|
</script>
|
|
21
19
|
|
|
22
20
|
<template>
|
|
23
21
|
<div v-if="pills && pills.length" class="SDescPill">
|
|
24
22
|
<div class="value">
|
|
25
|
-
<div v-for="pill,
|
|
23
|
+
<div v-for="(pill, i) in pills" :key="i" class="pill">
|
|
26
24
|
<SPill tag="div" size="mini" :mode="pill.mode" :label="pill.label" />
|
|
27
25
|
</div>
|
|
28
26
|
</div>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { useLinkifyIt } from 'sefirot/composables/Markdown'
|
|
3
2
|
import { computed } from 'vue'
|
|
3
|
+
import { useLinkifyIt } from '../composables/Markdown'
|
|
4
4
|
import { useHasSlotContent } from '../composables/Utils'
|
|
5
5
|
import SDescEmpty from './SDescEmpty.vue'
|
|
6
6
|
|
|
@@ -32,10 +32,10 @@ const _value = computed(() => {
|
|
|
32
32
|
|
|
33
33
|
<template>
|
|
34
34
|
<div v-if="hasSlot || _value" class="SDescText" :class="classes">
|
|
35
|
-
<div
|
|
35
|
+
<div v-if="hasSlot" class="value">
|
|
36
36
|
<slot />
|
|
37
37
|
</div>
|
|
38
|
-
<div class="value" v-
|
|
38
|
+
<div v-else class="value" v-html="_value" />
|
|
39
39
|
</div>
|
|
40
40
|
<SDescEmpty v-else />
|
|
41
41
|
</template>
|
|
@@ -10,7 +10,7 @@ defineProps<{
|
|
|
10
10
|
<template>
|
|
11
11
|
<div class="SDropdown">
|
|
12
12
|
<div class="container">
|
|
13
|
-
<div v-for="(section,
|
|
13
|
+
<div v-for="(section, i) in sections" :key="i" class="section">
|
|
14
14
|
<SDropdownSection :section />
|
|
15
15
|
</div>
|
|
16
16
|
</div>
|
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
import IconCheck from '~icons/ph/check'
|
|
3
3
|
import Fuse from 'fuse.js'
|
|
4
4
|
import { type MaybeRef, computed, onMounted, ref, unref } from 'vue'
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
type DropdownSectionFilterOption,
|
|
7
|
+
type DropdownSectionFilterSelectedValue
|
|
8
|
+
} from '../composables/Dropdown'
|
|
6
9
|
import { useTrans } from '../composables/Lang'
|
|
7
10
|
import SDropdownSectionFilterItem from './SDropdownSectionFilterItem.vue'
|
|
8
11
|
|
|
@@ -36,7 +39,7 @@ const fuse = computed(() => {
|
|
|
36
39
|
})
|
|
37
40
|
|
|
38
41
|
const filteredOptions = computed(() => {
|
|
39
|
-
return
|
|
42
|
+
return !props.search || !query.value
|
|
40
43
|
? unref(enabledOptions)
|
|
41
44
|
: fuse.value.search(query.value).map((r) => r.item)
|
|
42
45
|
})
|
|
@@ -47,10 +50,7 @@ onMounted(() => {
|
|
|
47
50
|
|
|
48
51
|
function isActive(value: any) {
|
|
49
52
|
const selected = unref(props.selected)
|
|
50
|
-
|
|
51
|
-
return Array.isArray(selected)
|
|
52
|
-
? selected.includes(value)
|
|
53
|
-
: selected === value
|
|
53
|
+
return Array.isArray(selected) ? selected.includes(value) : selected === value
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
function focusPrev(event: any) {
|
|
@@ -61,16 +61,16 @@ function focusNext(event: any) {
|
|
|
61
61
|
event.target.parentNode.nextElementSibling?.firstElementChild?.focus()
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
function
|
|
65
|
-
option.onClick
|
|
66
|
-
props.onClick
|
|
64
|
+
function onClick(option: DropdownSectionFilterOption, value: any) {
|
|
65
|
+
option.onClick?.(value)
|
|
66
|
+
props.onClick?.(value)
|
|
67
67
|
}
|
|
68
68
|
</script>
|
|
69
69
|
|
|
70
70
|
<template>
|
|
71
71
|
<div class="SDropdownSectionFilter">
|
|
72
72
|
<div v-if="search" class="search">
|
|
73
|
-
<input
|
|
73
|
+
<input ref="input" v-model="query" class="input" :placeholder="t.i_ph">
|
|
74
74
|
</div>
|
|
75
75
|
|
|
76
76
|
<ul v-if="filteredOptions.length" class="list">
|
|
@@ -81,7 +81,7 @@ function handleClick(option: DropdownSectionFilterOption, value: any) {
|
|
|
81
81
|
tabindex="0"
|
|
82
82
|
@keyup.up.prevent="focusPrev"
|
|
83
83
|
@keyup.down.prevent="focusNext"
|
|
84
|
-
@click="
|
|
84
|
+
@click="onClick(option, option.value)"
|
|
85
85
|
>
|
|
86
86
|
<span v-if="Array.isArray(unref(selected))" class="checkbox">
|
|
87
87
|
<span class="checkbox-box">
|