@adaptabletools/adaptable
Version:
Powerful AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements
118 lines (117 loc) • 5.31 kB
JavaScript
import Helper from '../../Utilities/Helpers/Helper';
import { clamp } from '../../Utilities/Extensions/NumberExtensions';
import { shouldRenderStyledColumnOnRow } from '../../Utilities/Helpers/StyledColumns/StyledColumnHelper';
const SVG_NS = 'http://www.w3.org/2000/svg';
const DEFAULT_MAX = 5;
const DEFAULT_SIZE = 14;
const DEFAULT_GAP = 2;
const DEFAULT_ICON = 'Star';
const DEFAULT_FILLED_COLOR = 'var(--ab-color-warn, #f5a623)';
const DEFAULT_EMPTY_COLOR = 'color-mix(in srgb, currentColor 22%, transparent)';
const ICON_PATHS = {
Star: 'M12 2 L14.9 8.6 L22 9.3 L16.7 14.1 L18.2 21 L12 17.4 L5.8 21 L7.3 14.1 L2 9.3 L9.1 8.6 Z',
Heart: 'M12 21 C 12 21 3 14.5 3 8.5 C 3 5.5 5.5 3 8.5 3 C 10.3 3 11.7 4 12 5.2 C 12.3 4 13.7 3 15.5 3 C 18.5 3 21 5.5 21 8.5 C 21 14.5 12 21 12 21 Z',
Circle: 'M12 4 a8 8 0 1 0 0.0001 0 Z',
Thumb: 'M2 11 h4 v10 h-4 z M7 11 l4 -8 c.5 -1 2 -1 2 0 l-1 5 h6 c1 0 2 1 1.7 2 l-2 8 c-.3 1 -1 1.6 -2 1.6 H7 z',
};
const resolveValue = (raw) => {
if (Helper.objectNotExists(raw))
return undefined;
const n = typeof raw === 'number' ? raw : Number(raw);
return isNaN(n) ? undefined : n;
};
const createIconElement = (shape, fill, filledColor, emptyColor, size, uid) => {
const svg = document.createElementNS(SVG_NS, 'svg');
svg.setAttribute('width', String(size));
svg.setAttribute('height', String(size));
svg.setAttribute('viewBox', '0 0 24 24');
svg.setAttribute('aria-hidden', 'true');
const d = ICON_PATHS[shape];
const empty = document.createElementNS(SVG_NS, 'path');
empty.setAttribute('d', d);
empty.setAttribute('fill', emptyColor);
svg.appendChild(empty);
if (fill > 0) {
const clipId = `ab-rating-clip-${uid}`;
const defs = document.createElementNS(SVG_NS, 'defs');
const clipPath = document.createElementNS(SVG_NS, 'clipPath');
clipPath.setAttribute('id', clipId);
const clipRect = document.createElementNS(SVG_NS, 'rect');
clipRect.setAttribute('x', '0');
clipRect.setAttribute('y', '0');
clipRect.setAttribute('width', String(24 * clamp(fill, 0, 1)));
clipRect.setAttribute('height', '24');
clipPath.appendChild(clipRect);
defs.appendChild(clipPath);
svg.appendChild(defs);
const filled = document.createElementNS(SVG_NS, 'path');
filled.setAttribute('d', d);
filled.setAttribute('fill', filledColor);
filled.setAttribute('clip-path', `url(#${clipId})`);
svg.appendChild(filled);
}
return svg;
};
export const getRatingRendererForColumn = (styledColumn, _abColumn, api) => {
if (!styledColumn.RatingStyle) {
return;
}
const ratingStyle = styledColumn.RatingStyle;
return class RatingRenderer {
eGui;
init(params) {
if (!shouldRenderStyledColumnOnRow(styledColumn, params.node, api)) {
this.eGui = document.createElement('div');
if (params.value != undefined) {
this.eGui.append(String(params.value));
}
return;
}
const value = resolveValue(params.value);
if (value == undefined) {
this.eGui = document.createElement('div');
return;
}
const max = ratingStyle.Max ?? DEFAULT_MAX;
const size = ratingStyle.Size ?? DEFAULT_SIZE;
const gap = ratingStyle.Gap ?? DEFAULT_GAP;
const allowHalf = ratingStyle.AllowHalf ?? true;
const icon = ratingStyle.Icon ?? DEFAULT_ICON;
const filledColor = ratingStyle.FilledColor ?? DEFAULT_FILLED_COLOR;
const emptyColor = ratingStyle.EmptyColor ?? DEFAULT_EMPTY_COLOR;
const showValue = ratingStyle.ShowValue ?? false;
const clampedValue = clamp(value, 0, max);
const effectiveValue = allowHalf
? clampedValue
: Math.round(clampedValue);
const uid = `${Math.random().toString(36).slice(2, 8)}`;
this.eGui = document.createElement('div');
this.eGui.className = 'ab-Rating__wrapper';
this.eGui.style.display = 'inline-flex';
this.eGui.style.alignItems = 'center';
this.eGui.style.gap = `${gap}px`;
this.eGui.style.height = '100%';
this.eGui.style.lineHeight = '1';
for (let i = 0; i < max; i++) {
const fill = clamp(effectiveValue - i, 0, 1);
const iconEl = createIconElement(icon, fill, filledColor, emptyColor, size, `${uid}-${i}`);
iconEl.setAttribute('class', 'ab-Rating__icon');
this.eGui.appendChild(iconEl);
}
if (showValue) {
const textEl = document.createElement('span');
textEl.className = 'ab-Rating__text';
textEl.style.marginLeft = '6px';
textEl.style.fontVariantNumeric = 'tabular-nums';
textEl.innerText = params.formatValue?.(value) ?? String(value);
this.eGui.appendChild(textEl);
}
}
getGui() {
return this.eGui;
}
refresh(_params) {
return false;
}
};
};