@globalbrain/sefirot 4.15.0 → 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.
@@ -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} ${d.value}`,
46
+ tooltipFormat: (d: KV) => `${d.key}&nbsp;&ndash; ${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 ?? 40,
83
- bottom: props.margins?.bottom ?? (props.xLabel ? 80 : 60),
84
- left: props.margins?.left ?? (props.yLabel ? (vertical ? 80 : 100) : (vertical ? 60 : 80))
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', height + margin.top + margin.bottom)
112
+ .attr('height', clientHeight)
99
113
  .append('g')
100
114
  .attr('transform', `translate(${margin.left},${margin.top})`)
101
115
 
@@ -50,7 +50,7 @@ const props = withDefaults(defineProps<{
50
50
  legendFontSize: '14px',
51
51
 
52
52
  tooltip: true,
53
- tooltipFormat: (d: KV) => `${d.key} ${d.value}`,
53
+ tooltipFormat: (d: KV) => `${d.key}&nbsp;&ndash; ${d.value}`,
54
54
 
55
55
  animate: true,
56
56
  debug: false
@@ -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 { getTextWidth } from '../support/Text'
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'
@@ -231,12 +231,12 @@ const actionsColumnWidth = computed(() => {
231
231
 
232
232
  // has only label
233
233
  if (label && !icon) {
234
- return 1 /* border */ + 12 /* padding */ + getTextWidth(label, font) + 12 /* padding */ + 1 /* border */
234
+ return 1 /* border */ + 12 /* padding */ + getTextSize(label, font).width + 12 /* padding */ + 1 /* border */
235
235
  }
236
236
 
237
237
  // has both icon and label
238
238
  if (icon && label) {
239
- return 1 /* border */ + 8 /* padding */ + 16 /* icon */ + 4 /* padding */ + getTextWidth(label, font) + 10 /* padding */ + 1 /* border */
239
+ return 1 /* border */ + 8 /* padding */ + 16 /* icon */ + 4 /* padding */ + getTextSize(label, font).width + 10 /* padding */ + 1 /* border */
240
240
  }
241
241
 
242
242
  return 0
@@ -2,16 +2,16 @@
2
2
 
3
3
  let _canvas: HTMLCanvasElement
4
4
 
5
- export function getTextWidth(text: string, font: string): number
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 metrics.width
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@globalbrain/sefirot",
3
3
  "type": "module",
4
- "version": "4.15.0",
4
+ "version": "4.16.0",
5
5
  "packageManager": "pnpm@9.15.4",
6
6
  "description": "Vue Components for Global Brain Design System.",
7
7
  "author": "Kia Ishii <ka.ishii@globalbrains.com>",