frappe-ui 1.0.0-rc.2 → 1.0.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/package.json +2 -3
- package/readme.md +1 -1
- package/src/charts/FunnelChart.vue +6 -5
- package/src/charts/axisChartCommon.ts +3 -0
- package/src/charts/axisChartOptions.ts +11 -15
- package/src/charts/axisFormat.ts +21 -1
- package/src/charts/core/useAxisChart.ts +3 -8
- package/src/charts/types.ts +6 -6
- package/vitepress/components/SiteActions.vue +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "frappe-ui",
|
|
3
|
-
"version": "1.0.0
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "A set of components and utilities for rapid UI development",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=20.19.0"
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"test": "vitest --run",
|
|
51
51
|
"test:coverage": "vitest --run --coverage",
|
|
52
52
|
"test:cypress": "cypress run --component",
|
|
53
|
-
"test:cypress:coverage": "cross-env COVERAGE=true cypress run --component",
|
|
53
|
+
"test:cypress:coverage": "cross-env COVERAGE=true cypress run --component && nyc report",
|
|
54
54
|
"coverage": "yarn test:coverage && yarn test:cypress:coverage && yarn coverage:merge",
|
|
55
55
|
"coverage:merge": "tsx .github/scripts/merge-coverage.ts",
|
|
56
56
|
"type-check": "vue-tsc --noEmit -p tsconfig.app.json && vue-tsc --noEmit -p tsconfig.node.json",
|
|
@@ -310,7 +310,6 @@
|
|
|
310
310
|
"@codemirror/lang-xml": "^6.1.0",
|
|
311
311
|
"@codemirror/lang-yaml": "^6.1.3",
|
|
312
312
|
"@codemirror/lint": "^6.0.0",
|
|
313
|
-
"@cypress/code-coverage": "^3.13.10",
|
|
314
313
|
"@shikijs/transformers": "^3.15.0",
|
|
315
314
|
"@vitejs/plugin-vue": "^6.0.7",
|
|
316
315
|
"@vitest/coverage-v8": "^3.2.4",
|
package/readme.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
# Frappe UI
|
|
6
6
|
|
|
7
|
-
**
|
|
7
|
+
**The all-in-one toolkit for modern frontends. High-quality components, app recipes and AI-ready docs.**
|
|
8
8
|
|
|
9
9
|
<a href="https://www.npmjs.com/package/frappe-ui"><img alt="npm version" src="https://img.shields.io/npm/v/frappe-ui.svg?style=flat" /></a>
|
|
10
10
|
<a href="https://www.npmjs.com/package/frappe-ui"><img alt="npm downloads" src="https://img.shields.io/npm/dm/frappe-ui.svg?style=flat" /></a>
|
|
@@ -121,10 +121,9 @@
|
|
|
121
121
|
:dir="dir"
|
|
122
122
|
>
|
|
123
123
|
<template #default="slotProps">
|
|
124
|
+
<!-- The value item carries the stage's name, so a header would print
|
|
125
|
+
it twice. -->
|
|
124
126
|
<slot name="tooltip" v-bind="slotProps">
|
|
125
|
-
<div class="mb-2 text-p-sm text-ink-gray-5">
|
|
126
|
-
{{ slotProps.label }}
|
|
127
|
-
</div>
|
|
128
127
|
<div class="flex flex-col gap-1.5 text-p-sm">
|
|
129
128
|
<div
|
|
130
129
|
v-for="item in slotProps.items.filter(
|
|
@@ -170,7 +169,7 @@
|
|
|
170
169
|
|
|
171
170
|
<script setup lang="ts">
|
|
172
171
|
import { computed, reactive, ref } from 'vue'
|
|
173
|
-
import {
|
|
172
|
+
import { formatPercent, formatValue } from './format'
|
|
174
173
|
import { buildFunnelStages, funnelShapes } from './funnelGeometry'
|
|
175
174
|
import { useTooltipDismiss } from './core/useTooltipDismiss'
|
|
176
175
|
import { paletteColors, useChartTokens } from './tokens'
|
|
@@ -290,7 +289,9 @@ function readStage(stage: FunnelStage) {
|
|
|
290
289
|
tooltip.items = [
|
|
291
290
|
{
|
|
292
291
|
name: String(stage.index),
|
|
293
|
-
|
|
292
|
+
// `value` is a row key, often one the caller named when reshaping its
|
|
293
|
+
// rows, so it says nothing to the reader.
|
|
294
|
+
label: stage.label,
|
|
294
295
|
color: colors.value[stage.index],
|
|
295
296
|
value: stage.value,
|
|
296
297
|
formattedValue: formatMeasure(stage.value),
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
} from './format'
|
|
13
13
|
import { CHART_FONT_FAMILY } from './measureText'
|
|
14
14
|
import { paletteColors, type ChartTokens } from './tokens'
|
|
15
|
+
import type { AxisChartFormatters } from './seriesData'
|
|
15
16
|
import { mergeDeep } from './utils'
|
|
16
17
|
import type {
|
|
17
18
|
AxisChartBaseConfig,
|
|
@@ -29,6 +30,8 @@ export type AxisChartOptionContext = {
|
|
|
29
30
|
hiddenSeries?: string[]
|
|
30
31
|
/** Plot width in pixels, once measured. Unset leaves pixel sizes to echarts. */
|
|
31
32
|
width?: number
|
|
33
|
+
/** What a data label prints in when its series has no `format` of its own. */
|
|
34
|
+
format?: AxisChartFormatters
|
|
32
35
|
}
|
|
33
36
|
|
|
34
37
|
export const AXIS_LABEL_FONT_SIZE = 11
|
|
@@ -18,12 +18,14 @@ import {
|
|
|
18
18
|
MARK_Z,
|
|
19
19
|
type AxisChartOptionContext,
|
|
20
20
|
} from './axisChartCommon'
|
|
21
|
+
import { seriesFormatter } from './axisFormat'
|
|
21
22
|
import { buildReferenceLineSeries } from './referenceLines'
|
|
22
23
|
import { mergeDeep } from './utils'
|
|
23
24
|
import type {
|
|
24
25
|
AxisChartConfig,
|
|
25
26
|
AxisChartSeriesConfig,
|
|
26
27
|
ChartMark,
|
|
28
|
+
ChartValueFormatter,
|
|
27
29
|
ChartYAxisConfig,
|
|
28
30
|
} from './types'
|
|
29
31
|
|
|
@@ -73,6 +75,8 @@ type SeriesContext = {
|
|
|
73
75
|
carriesTip: (entry: PlottedSeries, rowIndex: number, value: number) => boolean
|
|
74
76
|
/** Whether this area stacks onto another, i.e. reads as a band. */
|
|
75
77
|
banded: boolean
|
|
78
|
+
/** Prints this series' values: its own format, or its axis'. */
|
|
79
|
+
format?: ChartValueFormatter
|
|
76
80
|
/**
|
|
77
81
|
* This series' share of its stack, row by row, on a normalized chart. Set
|
|
78
82
|
* means the plot draws the share and prints it as a percentage; unset means
|
|
@@ -95,7 +99,7 @@ export type StackShares = Map<string, (number | null)[]>
|
|
|
95
99
|
*/
|
|
96
100
|
export function buildAxisChartOption(
|
|
97
101
|
config: AxisChartConfig,
|
|
98
|
-
{ tokens, hiddenSeries = [], width }: AxisChartOptionContext,
|
|
102
|
+
{ tokens, hiddenSeries = [], width, format = {} }: AxisChartOptionContext,
|
|
99
103
|
): EChartsCoreOption {
|
|
100
104
|
const isRTL = config.dir === 'rtl'
|
|
101
105
|
const horizontal = Boolean(config.horizontal)
|
|
@@ -163,6 +167,7 @@ export function buildAxisChartOption(
|
|
|
163
167
|
isRTL,
|
|
164
168
|
color: colors[entry.series.name],
|
|
165
169
|
yAxisIndex: valueAxisIndex(entry.series, hasSecondary),
|
|
170
|
+
format: seriesFormatter(entry.series, format, horizontal),
|
|
166
171
|
xValue,
|
|
167
172
|
carriesTip,
|
|
168
173
|
banded: isBanded(entry, plotted),
|
|
@@ -477,11 +482,7 @@ function buildBarSeries(entry: PlottedSeries, ctx: SeriesContext) {
|
|
|
477
482
|
: tokens.dataLabel,
|
|
478
483
|
fontSize: DATA_LABEL_FONT_SIZE,
|
|
479
484
|
formatter: (params: any) =>
|
|
480
|
-
plottedLabel(
|
|
481
|
-
horizontal ? params.value?.[0] : params.value?.[1],
|
|
482
|
-
series,
|
|
483
|
-
Boolean(ctx.share),
|
|
484
|
-
),
|
|
485
|
+
plottedLabel(horizontal ? params.value?.[0] : params.value?.[1], ctx),
|
|
485
486
|
},
|
|
486
487
|
labelLayout: { hideOverlap: true },
|
|
487
488
|
}
|
|
@@ -532,8 +533,7 @@ function buildLineSeries(
|
|
|
532
533
|
position: 'top',
|
|
533
534
|
color: tokens.dataLabel,
|
|
534
535
|
fontSize: DATA_LABEL_FONT_SIZE,
|
|
535
|
-
formatter: (params: any) =>
|
|
536
|
-
plottedLabel(params.value?.[1], series, Boolean(ctx.share)),
|
|
536
|
+
formatter: (params: any) => plottedLabel(params.value?.[1], ctx),
|
|
537
537
|
},
|
|
538
538
|
labelLayout: { hideOverlap: true },
|
|
539
539
|
}
|
|
@@ -550,14 +550,10 @@ function buildLineSeries(
|
|
|
550
550
|
* What a data label prints. A normalized series plots a share, so printing it
|
|
551
551
|
* as a number would read as a count of something.
|
|
552
552
|
*/
|
|
553
|
-
function plottedLabel(
|
|
554
|
-
value: any,
|
|
555
|
-
series: AxisChartSeriesConfig,
|
|
556
|
-
normalized: boolean,
|
|
557
|
-
) {
|
|
553
|
+
function plottedLabel(value: any, ctx: SeriesContext) {
|
|
558
554
|
if (value === null || value === undefined || isNaN(value)) return ''
|
|
559
|
-
if (
|
|
560
|
-
return
|
|
555
|
+
if (ctx.share) return formatPercent(value)
|
|
556
|
+
return ctx.format ? ctx.format(value) : formatValue(value, 1, true)
|
|
561
557
|
}
|
|
562
558
|
|
|
563
559
|
/**
|
package/src/charts/axisFormat.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { AxisChartFormatters } from './seriesData'
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
AxisChartBaseConfig,
|
|
4
|
+
AxisChartSeriesConfig,
|
|
5
|
+
ChartValueFormatter,
|
|
6
|
+
EchartOptionsOverride,
|
|
7
|
+
} from './types'
|
|
3
8
|
import { mergeDeep } from './utils'
|
|
4
9
|
|
|
5
10
|
/**
|
|
@@ -48,3 +53,18 @@ function withFormatter(
|
|
|
48
53
|
echartOptions,
|
|
49
54
|
)
|
|
50
55
|
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* How a series prints its values. Without its own format, a series reads in the
|
|
59
|
+
* units of the axis it is actually drawn against, so `y2` series never fall back
|
|
60
|
+
* to the primary formatter — except on a horizontal chart, which has no second
|
|
61
|
+
* axis to put them on.
|
|
62
|
+
*/
|
|
63
|
+
export function seriesFormatter(
|
|
64
|
+
series: AxisChartSeriesConfig,
|
|
65
|
+
format: AxisChartFormatters,
|
|
66
|
+
horizontal: boolean,
|
|
67
|
+
): ChartValueFormatter | undefined {
|
|
68
|
+
const secondary = series.axis === 'y2' && !horizontal
|
|
69
|
+
return series.format ?? (secondary ? format.y2 : format.y)
|
|
70
|
+
}
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
resolveXAxis,
|
|
12
12
|
toNumber,
|
|
13
13
|
} from '../axisChartCommon'
|
|
14
|
-
import { applyAxisFormatters } from '../axisFormat'
|
|
14
|
+
import { applyAxisFormatters, seriesFormatter } from '../axisFormat'
|
|
15
15
|
import { pruneHiddenSeries, toggleHiddenSeries } from '../hiddenSeries'
|
|
16
16
|
import { buildTooltipItems } from '../tooltipItems'
|
|
17
17
|
import {
|
|
@@ -136,6 +136,7 @@ export function useAxisChart<C extends AxisChartConfig>(
|
|
|
136
136
|
tokens: tokens.value,
|
|
137
137
|
hiddenSeries: hiddenSeries.value,
|
|
138
138
|
width: plotWidth.value,
|
|
139
|
+
format: format.value,
|
|
139
140
|
},
|
|
140
141
|
),
|
|
141
142
|
error: null as string | null,
|
|
@@ -172,14 +173,8 @@ export function useAxisChart<C extends AxisChartConfig>(
|
|
|
172
173
|
})),
|
|
173
174
|
)
|
|
174
175
|
|
|
175
|
-
// Without its own format, a series reads in the units of the axis it is
|
|
176
|
-
// actually drawn against, so `y2` series never fall back to the primary
|
|
177
|
-
// formatter — except on a horizontal chart, which has no second axis to put
|
|
178
|
-
// them on.
|
|
179
176
|
function formatSeriesValue(series: AxisChartSeriesConfig, value: number) {
|
|
180
|
-
const
|
|
181
|
-
const formatter =
|
|
182
|
-
series.format ?? (secondary ? format.value.y2 : format.value.y)
|
|
177
|
+
const formatter = seriesFormatter(series, format.value, horizontal.value)
|
|
183
178
|
return formatter ? formatter(value) : formatValue(value)
|
|
184
179
|
}
|
|
185
180
|
|
package/src/charts/types.ts
CHANGED
|
@@ -88,9 +88,9 @@ export type AxisChartSeriesConfig = {
|
|
|
88
88
|
axis?: 'y' | 'y2'
|
|
89
89
|
/**
|
|
90
90
|
* Prints this series' values in the tooltip and its data labels, for a series
|
|
91
|
-
* whose unit differs from the others on its axis. Without one,
|
|
92
|
-
*
|
|
93
|
-
*
|
|
91
|
+
* whose unit differs from the others on its axis. Without one, both use its
|
|
92
|
+
* axis' `format`. A label on a normalized stack prints the series' share
|
|
93
|
+
* either way.
|
|
94
94
|
*/
|
|
95
95
|
format?: ChartValueFormatter
|
|
96
96
|
showDataLabels?: boolean
|
|
@@ -734,9 +734,9 @@ export type SeriesStyle = {
|
|
|
734
734
|
type?: ChartMark
|
|
735
735
|
/**
|
|
736
736
|
* Prints this series' values in the tooltip and its data labels, for a series
|
|
737
|
-
* whose unit differs from the others on its axis. Without one,
|
|
738
|
-
*
|
|
739
|
-
*
|
|
737
|
+
* whose unit differs from the others on its axis. Without one, both use its
|
|
738
|
+
* axis' `format`. A label on a normalized stack prints the series' share
|
|
739
|
+
* either way.
|
|
740
740
|
*/
|
|
741
741
|
format?: ChartValueFormatter
|
|
742
742
|
/** Prints this series' value beside each of its marks. */
|