// Data schema and channel helpers. (function (root) { const chartUtils = root.chartUtils; const schema = chartUtils.schema; schema.normalizeUnit = unit => { if (unit == null) return ""; const text = String(unit).trim(); const lower = text.toLowerCase(); return ["", "none", "null", "nan", "undefined", "n/a", "na"].includes(lower) ? "" : text; }; schema.columns = jsonData => { const columns = jsonData && jsonData.data && jsonData.data.columns; return Array.isArray(columns) ? columns : []; }; const buildChannel = (column, role, index, fallbackKey) => { const key = column && column.name != null ? column.name : fallbackKey; const rawLabel = column ? (column.label || column.display_name || column.name || fallbackKey || "") : (fallbackKey || ""); const unit = schema.normalizeUnit(column && column.unit); const description = column && column.description ? column.description : rawLabel; const displayName = column && column.display_name ? column.display_name : rawLabel; return { role: column && column.role != null ? column.role : role, index: index == null ? -1 : index, key: key || "", type: column && column.data_type ? column.data_type : "", unit, rawLabel, description, displayName, label: unit ? `${rawLabel} (${unit})` : rawLabel, raw: column || null, }; }; schema.channel = (jsonData, role, options = {}) => { const columns = schema.columns(jsonData); let index = columns.findIndex(column => column.role === role); if (index < 0 && options.fallbackIndex != null) { index = options.fallbackIndex; } const column = index >= 0 ? columns[index] : null; const fallbackKey = Object.prototype.hasOwnProperty.call(options, "fallbackKey") ? options.fallbackKey : role; return buildChannel(column, role, index, fallbackKey); }; schema.channelByKey = (jsonData, key, options = {}) => { const columns = schema.columns(jsonData); let index = columns.findIndex(column => column.name === key); if (index < 0 && options.fallbackIndex != null) { index = options.fallbackIndex; } const column = index >= 0 ? columns[index] : null; const fallbackKey = Object.prototype.hasOwnProperty.call(options, "fallbackKey") ? options.fallbackKey : key; return buildChannel(column, options.role || (column && column.role) || "", index, fallbackKey); }; schema.column = (columns, index, options = {}) => { const list = Array.isArray(columns) ? columns : []; const column = index >= 0 ? list[index] : null; return buildChannel(column, options.role || (column && column.role) || "", index, options.fallbackKey); }; schema.columnField = (columns, index, fallbackKey = "", options = {}) => ( schema.column(columns, index, { ...options, fallbackKey }).key ); schema.field = (jsonData, index, fallbackKey = "", options = {}) => ( schema.columnField(schema.columns(jsonData), index, fallbackKey, options) ); schema.channels = (jsonData, spec) => { const result = {}; Object.keys(spec || {}).forEach(role => { result[role] = schema.channel(jsonData, role, spec[role]); }); return result; }; })(globalThis);