"use strict"; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.LegendCategory = void 0; const gui_1 = require("@antv/gui"); const util_1 = require("@antv/util"); const d3_format_1 = require("d3-format"); const marker_1 = require("../utils/marker"); const utils_1 = require("./utils"); function inferLayout(position, gridRow, gridCol) { const [gridRowLimit, gridColLimit] = [gridRow || 100, gridCol || 100]; switch (position) { case 'top': case 'bottom': case 'top-left': case 'top-right': case 'bottom-left': case 'bottom-right': return [1, gridColLimit]; case 'left': case 'right': return [gridRowLimit, 1]; default: return [gridRow, gridCol]; } } function createShape(shape, library, coordinate, theme, style = {}) { var _a, _b; const marker = ((_b = (_a = library[`shape.${shape}`]) === null || _a === void 0 ? void 0 : _a.props) === null || _b === void 0 ? void 0 : _b.defaultMarker) || (0, util_1.last)(shape.split('.')); return () => (0, marker_1.useMarker)(marker, style)(0, 0, 6); } function inferShape(scales, markState) { const shapeScale = (0, utils_1.scaleOf)(scales, 'shape'); const colorScale = (0, utils_1.scaleOf)(scales, 'color'); // infer the main shape if multiple marks are used const shapes = []; for (const [mark, state] of markState) { const namespace = mark.type; const domain = (colorScale === null || colorScale === void 0 ? void 0 : colorScale.getOptions().domain.length) > 0 ? colorScale === null || colorScale === void 0 ? void 0 : colorScale.getOptions().domain : state.data; const shape = domain.map((d, i) => { var _a; if (shapeScale) return shapeScale.map(d || 'point'); return ((_a = mark === null || mark === void 0 ? void 0 : mark.style) === null || _a === void 0 ? void 0 : _a.shape) || state.defaultShape || 'point'; }); if (typeof namespace === 'string') shapes.push([namespace, shape]); } if (shapes.length === 0) return ['point', ['point']]; if (shapes.length === 1) return shapes[0]; if (!shapeScale) return shapes[0]; // Evaluate the maximum likelihood of shape const { range } = shapeScale.getOptions(); return shapes .map(([namespace, shape]) => { let sum = 0; for (let i = 0; i < shapes.length; i++) { const targetShape = range[i % range.length]; if (shape[i] === targetShape) sum++; } return [sum / shape.length, [namespace, shape]]; }) .sort((a, b) => b[0] - a[0])[0][1]; } function inferItemMarker(options, { scales, library, coordinate, theme, markState }) { const shapeScale = (0, utils_1.scaleOf)(scales, 'shape'); const [namespace, shapes] = inferShape(scales, markState); const { itemMarker } = options; if (shapeScale && !itemMarker) { return (d, i) => createShape(`${namespace}.${shapes[i]}`, library, coordinate, theme, { color: d.color, }); } if (typeof itemMarker === 'function') return itemMarker; return (d, i) => createShape(itemMarker || `${namespace}.${shapes[i]}`, library, coordinate, theme, { color: d.color, }); } function inferItemMarkerOpacity(scales) { const scale = (0, utils_1.scaleOf)(scales, 'opacity'); if (scale) { const { range } = scale.getOptions(); return (d, i) => range[i]; } return undefined; } function inferItemMarkerSize(scales) { const scale = (0, utils_1.scaleOf)(scales, 'size'); // only support constant size scale. // size in category legend means the marker radius. if (scale) return scale.map(NaN) * 2; return 8; } function inferCategoryStyle(options, context) { const { labelFormatter = (d) => `${d}` } = options; const { scales } = context; const baseStyle = { itemMarker: inferItemMarker(options, context), itemMarkerSize: inferItemMarkerSize(scales), itemMarkerOpacity: inferItemMarkerOpacity(scales), }; const finalLabelFormatter = typeof labelFormatter === 'string' ? (0, d3_format_1.format)(labelFormatter) : labelFormatter; // here must exists a color scale const colorScale = (0, utils_1.scaleOf)(scales, 'color'); const domain = (0, utils_1.domainOf)(scales); return Object.assign(Object.assign({}, baseStyle), { data: domain.map((d) => ({ id: d, label: finalLabelFormatter(d), color: colorScale.map(d), })) }); } function inferLegendShape(value, options, component) { const { position } = options; if (position === 'center') { const { bbox } = value; // to be comfirm: if position is center, we should use the width and height of user definition. const { width, height } = bbox; return { width, height }; } const { width, height } = (0, utils_1.inferComponentShape)(value, options, component); return { width, height }; } /** * Guide Component for ordinal color scale. */ const LegendCategory = (options) => { const { labelFormatter, layout, order, orientation, position, size, title } = options, style = __rest(options, ["labelFormatter", "layout", "order", "orientation", "position", "size", "title"]); const { gridCol, gridRow } = style; return (context) => { var _a, _b, _c; const { value, theme } = context; const { bbox } = value; const { width, height } = inferLegendShape(value, options, exports.LegendCategory); const finalLayout = (0, utils_1.inferComponentLayout)(position, (_c = (_b = (_a = value.scales) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.guide) === null || _c === void 0 ? void 0 : _c.layout); const [finalGridRow, finalGridCol] = inferLayout(position, gridRow, gridCol); const legendStyle = Object.assign({ orientation: ['right', 'left', 'center'].includes(position) ? 'vertical' : 'horizontal', width, height, gridCol: gridCol !== null && gridCol !== void 0 ? gridCol : finalGridCol, gridRow: gridRow !== null && gridRow !== void 0 ? gridRow : finalGridRow, rowPadding: 0, colPadding: 8, titleText: (0, utils_1.titleContent)(title) }, inferCategoryStyle(options, context)); const { legend: legendTheme = {} } = theme; const categoryStyle = (0, utils_1.adaptor)(Object.assign({}, legendTheme, legendStyle, style)); const layoutWrapper = new utils_1.LegendCategoryLayout({ style: Object.assign(Object.assign({ x: bbox.x, y: bbox.y, width: bbox.width, height: bbox.height }, finalLayout), { // @ts-ignore subOptions: categoryStyle }), }); layoutWrapper.appendChild(new gui_1.Category({ className: 'legend-category', style: categoryStyle, })); return layoutWrapper; }; }; exports.LegendCategory = LegendCategory; exports.LegendCategory.props = { defaultPosition: 'top', defaultOrder: 1, defaultSize: 40, }; //# sourceMappingURL=legendCategory.js.map