Skip to content

Commit bace973

Browse files
feat: add new classname for legend component (#359)
* feat: add new classname for legend component * fix: 统一命名方式,优化代码逻辑 * fix: 单测报错修改
1 parent 0051da3 commit bace973

File tree

17 files changed

+382
-42
lines changed

17 files changed

+382
-42
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@
118118
},
119119
{
120120
"path": "dist/component.min.js",
121-
"limit": "250 Kb"
121+
"limit": "260 Kb"
122122
}
123123
],
124124
"author": {

src/ui/legend/category.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ export class Category extends Component<CategoryStyleProps> {
2323
private items!: Selection<CategoryItems>;
2424

2525
private renderTitle(container: Selection, width: number, height: number) {
26-
const { showTitle, titleText } = this.attributes;
26+
const { showTitle, titleText, classNamePrefix } = this.attributes;
2727
const style = subStyleProps<TitleStyleProps>(this.attributes, 'title');
2828
const [titleStyle, groupStyle] = splitStyle(style);
2929

3030
this.titleGroup = container.maybeAppendByClassName<Group>(CLASS_NAMES.titleGroup, 'g').styles(groupStyle);
3131

32-
const finalTitleStyle = { width, height, ...titleStyle, text: showTitle ? titleText : '' };
32+
const finalTitleStyle = { width, height, ...titleStyle, text: showTitle ? titleText : '', classNamePrefix };
3333
this.title = this.titleGroup
3434
.maybeAppendByClassName(CLASS_NAMES.title, () => new Title({ style: finalTitleStyle as TitleStyleProps }))
3535
.update(finalTitleStyle) as Selection<Title>;

src/ui/legend/category/item.ts

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ import {
3030
import { Poptip } from '../../poptip';
3131
import type { PoptipStyleProps } from '../../poptip/types';
3232
import type { PoptipRender } from './items';
33+
import { getLegendClassName } from '../utils/classname';
34+
import { CLASSNAME_SUFFIX_MAP } from '../constant';
3335

3436
type ItemMarkerStyle = { size?: number } & PathStyleProps;
3537
type ItemTextStyle = Omit<TextStyleProps, 'text'>;
@@ -53,6 +55,7 @@ export type CategoryItemStyleProps = GroupStyleProps &
5355
poptip?: PoptipStyleProps & PoptipRender;
5456
focus?: boolean;
5557
focusMarkerSize?: number;
58+
classNamePrefix?: string;
5659
};
5760

5861
export type CategoryItemOptions = ComponentOptions<CategoryItemStyleProps>;
@@ -223,19 +226,26 @@ export class CategoryItem extends Component<CategoryItemStyleProps> {
223226
}
224227

225228
private renderMarker(container: Selection) {
226-
const { marker } = this.attributes;
229+
const { marker, classNamePrefix } = this.attributes;
227230
const style = subStyleProps(this.attributes, 'marker');
228231
this.markerGroup = container.maybeAppendByClassName(CLASS_NAMES.markerGroup, 'g').style('zIndex', 0);
229232
ifShow(!!marker, this.markerGroup, () => {
230233
const parent = this.markerGroup.node();
231234
const oldMarker = parent.childNodes?.[0] as DisplayObject | undefined;
235+
const markerClassName = getLegendClassName(CLASS_NAMES.marker.name, CLASSNAME_SUFFIX_MAP.marker, classNamePrefix);
232236
const newMarker =
233-
typeof marker === 'string'
234-
? new Marker({ style: { symbol: marker }, className: CLASS_NAMES.marker.name })
235-
: marker();
237+
typeof marker === 'string' ? new Marker({ style: { symbol: marker }, className: markerClassName }) : marker();
236238

237239
if (!oldMarker) {
238-
if (!(newMarker instanceof Marker)) select(newMarker).attr('className', CLASS_NAMES.marker.name).styles(style);
240+
if (!(newMarker instanceof Marker)) {
241+
const markerClassName = getLegendClassName(
242+
CLASS_NAMES.marker.name,
243+
CLASSNAME_SUFFIX_MAP.marker,
244+
classNamePrefix
245+
);
246+
(newMarker as any).className = markerClassName;
247+
select(newMarker).styles(style);
248+
}
239249
parent.appendChild(newMarker);
240250
} else if (newMarker.nodeName === oldMarker.nodeName) {
241251
if (oldMarker instanceof Marker) oldMarker.update({ ...style, symbol: marker });
@@ -245,7 +255,15 @@ export class CategoryItem extends Component<CategoryItemStyleProps> {
245255
}
246256
} else {
247257
oldMarker.remove();
248-
select(newMarker).attr('className', CLASS_NAMES.marker.name).styles(style);
258+
if (!(newMarker instanceof Marker)) {
259+
const markerClassName = getLegendClassName(
260+
CLASS_NAMES.marker.name,
261+
CLASSNAME_SUFFIX_MAP.marker,
262+
classNamePrefix
263+
);
264+
(newMarker as any).className = markerClassName;
265+
}
266+
select(newMarker).styles(style);
249267
parent.appendChild(newMarker);
250268
}
251269

@@ -258,15 +276,23 @@ export class CategoryItem extends Component<CategoryItemStyleProps> {
258276

259277
private renderLabel(container: Selection) {
260278
const { text: label, ...style } = subStyleProps(this.attributes, 'label');
279+
const { classNamePrefix } = this.attributes;
261280
this.labelGroup = container.maybeAppendByClassName<Group>(CLASS_NAMES.labelGroup, 'g').style('zIndex', 0);
262-
this.labelGroup.maybeAppendByClassName(CLASS_NAMES.label, () => renderExtDo(label)).styles(style);
281+
const labelClassName = getLegendClassName(CLASS_NAMES.label.name, CLASSNAME_SUFFIX_MAP.label, classNamePrefix);
282+
const labelElement = this.labelGroup.maybeAppendByClassName(CLASS_NAMES.label, () => renderExtDo(label));
283+
labelElement.node().setAttribute('class', labelClassName);
284+
labelElement.styles(style);
263285
}
264286

265287
private renderValue(container: Selection) {
266288
const { text: value, ...style } = subStyleProps(this.attributes, 'value');
289+
const { classNamePrefix } = this.attributes;
267290
this.valueGroup = container.maybeAppendByClassName(CLASS_NAMES.valueGroup, 'g').style('zIndex', 0);
268291
ifShow(this.showValue, this.valueGroup, () => {
269-
this.valueGroup.maybeAppendByClassName(CLASS_NAMES.value, () => renderExtDo(value)).styles(style);
292+
const valueClassName = getLegendClassName(CLASS_NAMES.value.name, CLASSNAME_SUFFIX_MAP.value, classNamePrefix);
293+
const valueElement = this.valueGroup.maybeAppendByClassName(CLASS_NAMES.value, () => renderExtDo(value));
294+
valueElement.node().setAttribute('class', valueClassName);
295+
valueElement.styles(style);
270296
});
271297
}
272298

@@ -301,7 +327,7 @@ export class CategoryItem extends Component<CategoryItemStyleProps> {
301327
}
302328

303329
private renderFocus(ctn: Selection) {
304-
const { focus, focusMarkerSize } = this.attributes;
330+
const { focus, focusMarkerSize, classNamePrefix } = this.attributes;
305331
const defaultOptions = {
306332
x: 0,
307333
y: 0,
@@ -316,11 +342,17 @@ export class CategoryItem extends Component<CategoryItemStyleProps> {
316342

317343
this.focusGroup = ctn.maybeAppendByClassName<Group>(CLASS_NAMES.focusGroup, 'g').style('zIndex', 0);
318344
ifShow(focus, this.focusGroup, () => {
345+
const focusClassName = getLegendClassName(
346+
CLASS_NAMES.focus.name,
347+
CLASSNAME_SUFFIX_MAP.focusIcon,
348+
classNamePrefix
349+
);
319350
const marker = new Marker({
320351
style: {
321352
...defaultOptions,
322353
symbol: 'focus',
323354
},
355+
className: focusClassName,
324356
});
325357
const interactiveCircle = new Circle({
326358
style: {
@@ -359,7 +391,18 @@ export class CategoryItem extends Component<CategoryItemStyleProps> {
359391
const { width, height } = this.shape;
360392
const style = subStyleProps(this.attributes, 'background');
361393
this.background = container.maybeAppendByClassName(CLASS_NAMES.backgroundGroup, 'g').style('zIndex', -1);
362-
this.background.maybeAppendByClassName(CLASS_NAMES.background, 'rect').styles({ width, height, ...style });
394+
const backgroundElement = this.background.maybeAppendByClassName(CLASS_NAMES.background, 'rect');
395+
backgroundElement.styles({ width, height, ...style });
396+
397+
const { classNamePrefix = '' } = this.attributes;
398+
if (classNamePrefix) {
399+
const backgroundClassName = getLegendClassName(
400+
CLASS_NAMES.background.name,
401+
CLASSNAME_SUFFIX_MAP.background,
402+
classNamePrefix
403+
);
404+
backgroundElement.node().setAttribute('class', backgroundClassName);
405+
}
363406
}
364407

365408
private adjustLayout() {

src/ui/legend/category/items.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import { ifHorizontal } from '../utils';
2121
import type { CategoryItemStyleProps } from './item';
2222
import { CategoryItem } from './item';
2323
import type { PoptipStyleProps } from '../../poptip/types';
24+
import { getLegendClassName } from '../utils/classname';
25+
import { CLASSNAME_SUFFIX_MAP } from '../constant';
2426

2527
interface CategoryItemsDatum {
2628
[keys: string]: any;
@@ -57,6 +59,7 @@ export type CategoryItemsStyleProps = GroupStyleProps &
5759
poptip?: PoptipStyleProps & PoptipRender;
5860
focus?: boolean;
5961
focusMarkerSize?: number;
62+
classNamePrefix?: string;
6063
};
6164

6265
export type CategoryItemsOptions = ComponentOptions<CategoryItemsStyleProps>;
@@ -131,7 +134,7 @@ export class CategoryItems extends Component<CategoryItemsStyleProps> {
131134
}
132135

133136
private get renderData() {
134-
const { data, layout, poptip, focus, focusMarkerSize } = this.attributes;
137+
const { data, layout, poptip, focus, focusMarkerSize, classNamePrefix } = this.attributes;
135138
const style = subStyleProps<CategoryItemStyleProps>(this.attributes, 'item');
136139

137140
const d = data.map((datum, index) => {
@@ -146,6 +149,7 @@ export class CategoryItems extends Component<CategoryItemsStyleProps> {
146149
poptip,
147150
focus,
148151
focusMarkerSize,
152+
classNamePrefix,
149153
...Object.fromEntries(
150154
Object.entries(style).map(([key, val]) => [key, getCallbackValue(val, [datum, index, data])])
151155
),
@@ -250,17 +254,18 @@ export class CategoryItems extends Component<CategoryItemsStyleProps> {
250254
}
251255

252256
private renderItems(container: Group) {
253-
const { click, mouseenter, mouseleave } = this.attributes;
257+
const { click, mouseenter, mouseleave, classNamePrefix } = this.attributes;
254258
this.flattenPage(container);
255259
const dispatchCustomEvent = this.dispatchCustomEvent.bind(this);
260+
const itemClassName = getLegendClassName(CLASS_NAMES.item.name, CLASSNAME_SUFFIX_MAP.item, classNamePrefix);
256261
select(container)
257262
.selectAll(CLASS_NAMES.item.class)
258263
.data(this.renderData, (d) => d.id)
259264
.join(
260265
(enter) =>
261266
enter
262267
.append(({ style }) => new CategoryItem({ style }))
263-
.attr('className', CLASS_NAMES.item.name)
268+
.attr('className', itemClassName)
264269
.on('click', function () {
265270
click?.(this);
266271
dispatchCustomEvent('itemClick', { item: this });
@@ -311,9 +316,9 @@ export class CategoryItems extends Component<CategoryItemsStyleProps> {
311316
}
312317

313318
private renderNavigator(container: Selection) {
314-
const { orientation } = this.attributes;
319+
const { orientation, classNamePrefix } = this.attributes;
315320
const navStyle = subStyleProps(this.attributes, 'nav');
316-
const style = deepAssign({ orientation }, navStyle);
321+
const style = deepAssign({ orientation, classNamePrefix }, navStyle);
317322
const that = this;
318323
container
319324
.selectAll(CLASS_NAMES.navigator.class)

src/ui/legend/classname-map.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* className suffix mapping for legend elements
3+
* Used to generate prefixed classNames, e.g., classNamePrefix='g2-' generates 'g2-legend-{suffix}'
4+
*
5+
* @example
6+
* import { CLASSNAME_SUFFIX_MAP, getLegendClassName } from './utils';
7+
*
8+
* const titleClassName = getLegendClassName(
9+
* CLASS_NAMES.text.name,
10+
* CLASSNAME_SUFFIX_MAP.title,
11+
* 'g2-'
12+
* );
13+
* // Returns: 'title-text g2-legend-title'
14+
*/
15+
export const CLASSNAME_SUFFIX_MAP = {
16+
// Common elements
17+
title: 'title',
18+
19+
// Category legend elements
20+
item: 'item',
21+
marker: 'marker',
22+
label: 'label',
23+
value: 'value',
24+
focusIcon: 'focus-icon',
25+
background: 'background',
26+
27+
// Continuous legend elements
28+
ribbon: 'ribbon',
29+
track: 'track',
30+
selection: 'selection',
31+
handle: 'handle',
32+
handleMarker: 'handle-marker',
33+
handleLabel: 'handle-label',
34+
indicator: 'indicator',
35+
36+
// Navigator elements (reserved)
37+
prevBtn: 'prev-btn',
38+
nextBtn: 'next-btn',
39+
pageInfo: 'page-info',
40+
} as const;
41+
42+
/**
43+
* className suffix type
44+
*/
45+
export type ClassNameSuffix = keyof typeof CLASSNAME_SUFFIX_MAP;

src/ui/legend/constant.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { classNames, deepAssign, superStyleProps } from '../../util';
22
import { DEFAULT_HANDLE_CFG } from './continuous/handle';
33
import type { LegendBaseStyleProps } from './types';
44

5+
export { CLASSNAME_SUFFIX_MAP, type ClassNameSuffix } from './classname-map';
6+
57
export const LEGEND_BASE_DEFAULT_OPTIONS: Partial<LegendBaseStyleProps> = {
68
showTitle: true,
79
padding: 0,

0 commit comments

Comments
 (0)