UNPKG

@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
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; } }; };