@globalbrain/sefirot 4.14.2 → 4.16.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/SButton.vue +2 -2
- package/lib/components/SChartBar.vue +22 -8
- package/lib/components/SChartPie.vue +1 -1
- package/lib/components/SControlActionBarButton.vue +1 -1
- package/lib/components/SControlActionBarClose.vue +1 -1
- package/lib/components/SControlActionBarCollapse.vue +1 -1
- package/lib/components/SControlButton.vue +1 -1
- package/lib/components/SControlInputSearch.vue +4 -4
- package/lib/components/SControlPagination.vue +2 -2
- package/lib/components/SDropdownSectionDateRangeDateFromTo.vue +1 -1
- package/lib/components/SDropdownSectionDateRangeYear.vue +1 -1
- package/lib/components/SDropdownSectionDateRangeYearHalf.vue +1 -1
- package/lib/components/SDropdownSectionDateRangeYearQuarter.vue +1 -1
- package/lib/components/SErrorBoundary.vue +1 -1
- package/lib/components/SInputAddon.vue +1 -1
- package/lib/components/SInputCheckbox.vue +2 -2
- package/lib/components/SInputCheckboxes.vue +2 -2
- package/lib/components/SInputDate.vue +1 -1
- package/lib/components/SInputFile.vue +2 -2
- package/lib/components/SInputFileUploadItem.vue +1 -1
- package/lib/components/SInputHMS.vue +2 -2
- package/lib/components/SInputImage.vue +2 -2
- package/lib/components/SInputRadio.vue +2 -2
- package/lib/components/SInputRadios.vue +2 -2
- package/lib/components/SInputSegments.vue +2 -2
- package/lib/components/SInputSegmentsOption.vue +1 -1
- package/lib/components/SInputSelect.vue +2 -2
- package/lib/components/SInputSwitch.vue +2 -2
- package/lib/components/SInputSwitches.vue +1 -1
- package/lib/components/SInputYMD.vue +2 -2
- package/lib/components/SMarkdown.vue +1 -1
- package/lib/components/SModal.vue +1 -1
- package/lib/components/SPagination.vue +2 -2
- package/lib/components/SPill.vue +1 -1
- package/lib/components/STable.vue +49 -5
- package/lib/components/STableColumn.vue +1 -1
- package/lib/composables/Table.ts +1 -0
- package/lib/support/Text.ts +5 -5
- package/package.json +1 -1
|
@@ -3,6 +3,7 @@ import { useElementSize } from '@vueuse/core'
|
|
|
3
3
|
import * as d3 from 'd3'
|
|
4
4
|
import { useTemplateRef, watch } from 'vue'
|
|
5
5
|
import { type ChartColor, type KV, type Margins, c, scheme } from '../support/Chart'
|
|
6
|
+
import { getTextSize } from '../support/Text'
|
|
6
7
|
|
|
7
8
|
const props = withDefaults(defineProps<{
|
|
8
9
|
// State
|
|
@@ -42,7 +43,7 @@ const props = withDefaults(defineProps<{
|
|
|
42
43
|
tickFontSize: '14px',
|
|
43
44
|
|
|
44
45
|
tooltip: true,
|
|
45
|
-
tooltipFormat: (d: KV) => `${d.key}
|
|
46
|
+
tooltipFormat: (d: KV) => `${d.key} – ${d.value}`,
|
|
46
47
|
|
|
47
48
|
animate: true,
|
|
48
49
|
debug: false
|
|
@@ -67,6 +68,7 @@ function renderChart({
|
|
|
67
68
|
|
|
68
69
|
// Create color scale
|
|
69
70
|
const color = scheme(props.data, props.colors)
|
|
71
|
+
const font = getComputedStyle(chartRef.value).fontFamily
|
|
70
72
|
|
|
71
73
|
// Clear any existing SVG
|
|
72
74
|
d3
|
|
@@ -77,25 +79,37 @@ function renderChart({
|
|
|
77
79
|
// Set dimensions and margins
|
|
78
80
|
const vertical = props.type === 'vertical'
|
|
79
81
|
|
|
82
|
+
const maxKeyLength = props.data.reduce((a, b) => Math.max(a, b.key.length), Number.NEGATIVE_INFINITY)
|
|
83
|
+
const maxValueLength = props.data.reduce((a, b) => Math.max(a, b.value.toLocaleString().length), Number.NEGATIVE_INFINITY)
|
|
84
|
+
|
|
85
|
+
const maxVerticalTickWidthInCh = vertical ? maxValueLength : maxKeyLength
|
|
86
|
+
const maxVerticalTickWidthInPx = getTextSize('0'.repeat(maxVerticalTickWidthInCh), `400 ${props.tickFontSize} ${font}`).width
|
|
87
|
+
const verticalLabelWidthInPx = props.yLabel ? getTextSize(props.yLabel, `400 ${props.yLabelFontSize} ${font}`).height : 0
|
|
88
|
+
const gapBetweenVerticalLabelAndTicks = props.yLabel ? 20 : 0
|
|
89
|
+
|
|
90
|
+
const maxHorizontalTickHeightInPx = getTextSize('0', `400 ${props.tickFontSize} ${font}`).height // wrapping isn't supported
|
|
91
|
+
const horizontalLabelHeightInPx = props.xLabel ? getTextSize(props.xLabel, `400 ${props.xLabelFontSize} ${font}`).height : 0
|
|
92
|
+
const gapBetweenHorizontalLabelAndTicks = props.xLabel ? 20 : 0
|
|
93
|
+
|
|
94
|
+
const xLabelOffset = props.xLabelOffset ?? horizontalLabelHeightInPx + 9 + maxHorizontalTickHeightInPx + gapBetweenHorizontalLabelAndTicks
|
|
95
|
+
const yLabelOffset = props.yLabelOffset ?? 9 + maxVerticalTickWidthInPx + gapBetweenVerticalLabelAndTicks
|
|
96
|
+
|
|
80
97
|
const margin = {
|
|
81
98
|
top: props.margins?.top ?? 30,
|
|
82
|
-
right: props.margins?.right ??
|
|
83
|
-
bottom: props.margins?.bottom ?? (props.xLabel ?
|
|
84
|
-
left: props.margins?.left ?? (
|
|
99
|
+
right: props.margins?.right ?? 30,
|
|
100
|
+
bottom: props.margins?.bottom ?? (30 + horizontalLabelHeightInPx + xLabelOffset - (props.xLabel ? 9 : 0)),
|
|
101
|
+
left: props.margins?.left ?? (30 + verticalLabelWidthInPx + yLabelOffset)
|
|
85
102
|
}
|
|
86
103
|
|
|
87
104
|
const width = clientWidth - margin.left - margin.right
|
|
88
105
|
const height = clientHeight - margin.top - margin.bottom
|
|
89
106
|
|
|
90
|
-
const xLabelOffset = props.xLabelOffset ?? 46
|
|
91
|
-
const yLabelOffset = props.yLabelOffset ?? (vertical ? 40 : 56)
|
|
92
|
-
|
|
93
107
|
// Create SVG
|
|
94
108
|
const svg = d3
|
|
95
109
|
.select(chartRef.value)
|
|
96
110
|
.append('svg')
|
|
97
111
|
.attr('width', '100%')
|
|
98
|
-
.attr('height',
|
|
112
|
+
.attr('height', clientHeight)
|
|
99
113
|
.append('g')
|
|
100
114
|
.attr('transform', `translate(${margin.left},${margin.top})`)
|
|
101
115
|
|
|
@@ -19,10 +19,10 @@ const props = defineProps<{
|
|
|
19
19
|
}>()
|
|
20
20
|
|
|
21
21
|
defineEmits<{
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
'update:model-value': [value: string | null]
|
|
23
|
+
'input': [value: string | null]
|
|
24
|
+
'blur': [value: string | null]
|
|
25
|
+
'enter': [value: string | null]
|
|
26
26
|
}>()
|
|
27
27
|
|
|
28
28
|
const { t } = useTrans({
|
|
@@ -29,8 +29,8 @@ const props = withDefaults(defineProps<{
|
|
|
29
29
|
})
|
|
30
30
|
|
|
31
31
|
const emit = defineEmits<{
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
'update:model-value': [value: boolean]
|
|
33
|
+
'change': [value: boolean]
|
|
34
34
|
}>()
|
|
35
35
|
|
|
36
36
|
const classes = computed(() => [
|
|
@@ -37,8 +37,8 @@ const props = withDefaults(defineProps<{
|
|
|
37
37
|
})
|
|
38
38
|
|
|
39
39
|
const emit = defineEmits<{
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
'update:model-value': [value: Value[]]
|
|
41
|
+
'change': [value: Value[]]
|
|
42
42
|
}>()
|
|
43
43
|
|
|
44
44
|
const _value = computed(() => {
|
|
@@ -26,8 +26,8 @@ const props = defineProps<{
|
|
|
26
26
|
}>()
|
|
27
27
|
|
|
28
28
|
const emit = defineEmits<{
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
'update:model-value': [file: File | File[] | null]
|
|
30
|
+
'change': [file: File | File[] | null]
|
|
31
31
|
}>()
|
|
32
32
|
|
|
33
33
|
const _value = computed(() => {
|
|
@@ -41,8 +41,8 @@ const props = defineProps<{
|
|
|
41
41
|
}>()
|
|
42
42
|
|
|
43
43
|
const emit = defineEmits<{
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
'update:model-value': [value: Value]
|
|
45
|
+
'change': [value: Value]
|
|
46
46
|
}>()
|
|
47
47
|
|
|
48
48
|
const _value = computed(() => {
|
|
@@ -42,8 +42,8 @@ const props = withDefaults(defineProps<{
|
|
|
42
42
|
})
|
|
43
43
|
|
|
44
44
|
const emit = defineEmits<{
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
'update:model-value': [file: File | null]
|
|
46
|
+
'change': [file: File | null]
|
|
47
47
|
}>()
|
|
48
48
|
|
|
49
49
|
const fileInput = ref<HTMLInputElement | null>(null)
|
|
@@ -24,8 +24,8 @@ const props = defineProps<{
|
|
|
24
24
|
}>()
|
|
25
25
|
|
|
26
26
|
const emit = defineEmits<{
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
'update:model-value': [value: boolean]
|
|
28
|
+
'change': [value: boolean]
|
|
29
29
|
}>()
|
|
30
30
|
|
|
31
31
|
const classes = computed(() => [
|
|
@@ -47,8 +47,8 @@ const props = withDefaults(defineProps<{
|
|
|
47
47
|
})
|
|
48
48
|
|
|
49
49
|
const emit = defineEmits<{
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
'update:model-value': [value: ValueType | NullValue]
|
|
51
|
+
'change': [value: ValueType | NullValue]
|
|
52
52
|
}>()
|
|
53
53
|
|
|
54
54
|
const _value = computed(() => {
|
|
@@ -38,8 +38,8 @@ const props = withDefaults(defineProps<{
|
|
|
38
38
|
})
|
|
39
39
|
|
|
40
40
|
const emit = defineEmits<{
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
'update:model-value': [value: Value]
|
|
42
|
+
'change': [value: Value]
|
|
43
43
|
}>()
|
|
44
44
|
|
|
45
45
|
const _value = computed(() => {
|
|
@@ -30,8 +30,8 @@ const props = withDefaults(defineProps<{
|
|
|
30
30
|
})
|
|
31
31
|
|
|
32
32
|
const emit = defineEmits<{
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
'update:model-value': [value: boolean]
|
|
34
|
+
'change': [value: boolean]
|
|
35
35
|
}>()
|
|
36
36
|
|
|
37
37
|
const _value = computed(() => {
|
|
@@ -42,8 +42,8 @@ const props = defineProps<{
|
|
|
42
42
|
}>()
|
|
43
43
|
|
|
44
44
|
const emit = defineEmits<{
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
'update:model-value': [value: Value]
|
|
46
|
+
'change': [value: Value]
|
|
47
47
|
}>()
|
|
48
48
|
|
|
49
49
|
const _value = computed(() => {
|
package/lib/components/SPill.vue
CHANGED
|
@@ -5,7 +5,7 @@ import xor from 'lodash-es/xor'
|
|
|
5
5
|
import { computed, nextTick, reactive, ref, shallowRef, toValue, unref, watch } from 'vue'
|
|
6
6
|
import { type Table } from '../composables/Table'
|
|
7
7
|
import { smartComputed } from '../support/Reactivity'
|
|
8
|
-
import {
|
|
8
|
+
import { getTextSize } from '../support/Text'
|
|
9
9
|
import SInputCheckbox from './SInputCheckbox.vue'
|
|
10
10
|
import SInputRadio from './SInputRadio.vue'
|
|
11
11
|
import SSpinner from './SSpinner.vue'
|
|
@@ -184,6 +184,21 @@ watch(() => unref(props.options.records), () => {
|
|
|
184
184
|
isSyncingBody = false
|
|
185
185
|
}, { flush: 'post' })
|
|
186
186
|
|
|
187
|
+
const frozenColumns = smartComputed(() => {
|
|
188
|
+
const columns = unref(props.options.columns)
|
|
189
|
+
const keys = Object.keys(columns).filter((key) => columns[key].freeze)
|
|
190
|
+
if (selected.value !== undefined && keys.length) {
|
|
191
|
+
keys.unshift('__select')
|
|
192
|
+
}
|
|
193
|
+
return keys.filter((key) => ordersToShow.value.includes(key))
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
const frozenColWidths = smartComputed(() => {
|
|
197
|
+
// eslint-disable-next-line no-void
|
|
198
|
+
void blockWidth.value
|
|
199
|
+
return frozenColumns.value.map((key) => getColWidth(key))
|
|
200
|
+
})
|
|
201
|
+
|
|
187
202
|
useResizeObserver(block, ([entry]) => {
|
|
188
203
|
blockWidth.value = entry.contentRect.width
|
|
189
204
|
})
|
|
@@ -216,12 +231,12 @@ const actionsColumnWidth = computed(() => {
|
|
|
216
231
|
|
|
217
232
|
// has only label
|
|
218
233
|
if (label && !icon) {
|
|
219
|
-
return 1 /* border */ + 12 /* padding */ +
|
|
234
|
+
return 1 /* border */ + 12 /* padding */ + getTextSize(label, font).width + 12 /* padding */ + 1 /* border */
|
|
220
235
|
}
|
|
221
236
|
|
|
222
237
|
// has both icon and label
|
|
223
238
|
if (icon && label) {
|
|
224
|
-
return 1 /* border */ + 8 /* padding */ + 16 /* icon */ + 4 /* padding */ +
|
|
239
|
+
return 1 /* border */ + 8 /* padding */ + 16 /* icon */ + 4 /* padding */ + getTextSize(label, font).width + 10 /* padding */ + 1 /* border */
|
|
225
240
|
}
|
|
226
241
|
|
|
227
242
|
return 0
|
|
@@ -337,6 +352,34 @@ function addSelected(item: any) {
|
|
|
337
352
|
function removeSelected(item: any) {
|
|
338
353
|
updateSelected((selected.value as any[]).filter((i) => i !== item))
|
|
339
354
|
}
|
|
355
|
+
|
|
356
|
+
function getColWidth(key: string) {
|
|
357
|
+
if (key === '__select') {
|
|
358
|
+
return '48px + var(--table-padding-left, 0)'
|
|
359
|
+
}
|
|
360
|
+
const adjustedWidth = colWidths[key]
|
|
361
|
+
if (adjustedWidth && adjustedWidth !== 'auto') {
|
|
362
|
+
return adjustedWidth
|
|
363
|
+
}
|
|
364
|
+
const el = row.value?.children?.[ordersToShow.value.indexOf(key)]
|
|
365
|
+
if (!el) {
|
|
366
|
+
return '0px'
|
|
367
|
+
}
|
|
368
|
+
return `${el.getBoundingClientRect().width}px`
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
function getStyles(key: string) {
|
|
372
|
+
const length = frozenColumns.value.length
|
|
373
|
+
if (length === 0) { return }
|
|
374
|
+
const i = frozenColumns.value.indexOf(key)
|
|
375
|
+
if (i < 0) { return }
|
|
376
|
+
const widthSum = frozenColWidths.value.slice(0, i).join(' + ')
|
|
377
|
+
return {
|
|
378
|
+
'--table-col-position': 'sticky',
|
|
379
|
+
'--table-col-z-index': length - i, // left to right decreasing
|
|
380
|
+
'--table-col-left': widthSum ? `calc(${widthSum})` : '0px'
|
|
381
|
+
}
|
|
382
|
+
}
|
|
340
383
|
</script>
|
|
341
384
|
|
|
342
385
|
<template>
|
|
@@ -361,6 +404,7 @@ function removeSelected(item: any) {
|
|
|
361
404
|
:key="key"
|
|
362
405
|
:name="key"
|
|
363
406
|
:class-name="unref(options.columns)[key]?.className"
|
|
407
|
+
:style="getStyles(key)"
|
|
364
408
|
:width="colWidths[key]"
|
|
365
409
|
>
|
|
366
410
|
<STableColumn
|
|
@@ -419,6 +463,7 @@ function removeSelected(item: any) {
|
|
|
419
463
|
:key="key"
|
|
420
464
|
:name="key"
|
|
421
465
|
:class-name="unref(options.columns)[key]?.className"
|
|
466
|
+
:style="getStyles(key)"
|
|
422
467
|
:width="colWidths[key]"
|
|
423
468
|
>
|
|
424
469
|
<STableCell
|
|
@@ -586,8 +631,7 @@ function removeSelected(item: any) {
|
|
|
586
631
|
}
|
|
587
632
|
|
|
588
633
|
.STable .col-__select {
|
|
589
|
-
--table-padding-left
|
|
590
|
-
--table-col-width: 48px;
|
|
634
|
+
--table-col-width: calc(48px + var(--table-padding-left, 0));
|
|
591
635
|
|
|
592
636
|
:deep(.input) {
|
|
593
637
|
align-items: center;
|
package/lib/composables/Table.ts
CHANGED
package/lib/support/Text.ts
CHANGED
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
let _canvas: HTMLCanvasElement
|
|
4
4
|
|
|
5
|
-
export function
|
|
6
|
-
export function getTextWidth(text: string, el: HTMLElement): number
|
|
7
|
-
|
|
8
|
-
export function getTextWidth(text: string, fontOrEl: string | HTMLElement): number {
|
|
5
|
+
export function getTextSize(text: string, fontOrEl: string | HTMLElement) {
|
|
9
6
|
const canvas = _canvas || (_canvas = document.createElement('canvas'))
|
|
10
7
|
const context = canvas.getContext('2d')!
|
|
11
8
|
context.font = typeof fontOrEl === 'string' ? fontOrEl : getCanvasFont(fontOrEl)
|
|
12
9
|
const metrics = context.measureText(text)
|
|
13
10
|
|
|
14
|
-
return
|
|
11
|
+
return {
|
|
12
|
+
width: metrics.width,
|
|
13
|
+
height: metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent
|
|
14
|
+
}
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
function getCanvasFont(el: HTMLElement) {
|
package/package.json
CHANGED