Skip to content

Commit

Permalink
fix(QB-23021): make ARGB for cell data work
Browse files Browse the repository at this point in the history
  • Loading branch information
Johan Lohmander committed Apr 22, 2024
1 parent 550c6bb commit 2edd033
Show file tree
Hide file tree
Showing 93 changed files with 10,978 additions and 4 deletions.
2 changes: 1 addition & 1 deletion example/TableApp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"lint": "eslint ."
},
"dependencies": {
"@nebula.js/sn-table": "file:../../prebuilt/nebula.js-react-native-sn-table-1.14.121.tgz",
"@nebula.js/sn-table": "file:../../prebuilt/react-native-sn-table",
"@nebula.js/stardust": "2.9.0",
"@qlik/carbon-core": "2.0.4",
"@qlik/react-native-carbon": "2.1.18",
Expand Down
6 changes: 3 additions & 3 deletions example/TableApp/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1179,9 +1179,8 @@
"@jridgewell/resolve-uri" "3.1.0"
"@jridgewell/sourcemap-codec" "1.4.14"

"@nebula.js/sn-table@file:../../prebuilt/nebula.js-react-native-sn-table-1.14.121.tgz":
"@nebula.js/sn-table@file:../../prebuilt/package":
version "1.14.121"
resolved "file:../../prebuilt/nebula.js-react-native-sn-table-1.14.121.tgz#732730d20345059416bfec28fa3a6790b53cbeee"

"@nebula.js/[email protected]":
version "2.9.0"
Expand All @@ -1206,7 +1205,8 @@
integrity sha512-F2ooCVg9Yv99xATZCePA3WdQCNd1jlvxpWb83GzzF/EOmDyvdV6KkX9gm1aC2jiR386bsyZ20akB4kA6Hdo6pA==

"@qlik/react-native-simple-grid@link:../..":
version "1.2.12"
version "0.0.0"
uid ""

"@react-native-async-storage/[email protected]":
version "1.17.6"
Expand Down
Binary file not shown.
217 changes: 217 additions & 0 deletions prebuilt/react-native-sn-table/conditional-colors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
/* eslint-disable prefer-destructuring */
import { TableCell } from './types';

Check failure on line 2 in prebuilt/react-native-sn-table/conditional-colors.ts

View workflow job for this annotation

GitHub Actions / Types Build Validation

'TableCell' is a type and must be imported using a type-only import when 'verbatimModuleSyntax' is enabled.

export type PaletteColor = {
color: string;
icon: string;
index: number;
};

export type Limit = {
value: number;
gradient: boolean;
normal: number;
};

export type Segments = {
limits: Array<Limit>;
paletteColors: Array<PaletteColor>;
};

export type ConditionalColoring = {
segments: Segments;
};

export type Indicator = {
applySegmentColors: boolean;
position: string;
showTextValues: boolean;
};

export type Respresentaton = {
indicator: Indicator;
};

export type Column = {
conditionalColoring: ConditionalColoring;
representation: Respresentaton;
qMin?: number;
qMax?: number;
};

export type LimitBound = {
upperIndex: number;
lowerIndex: number;
};

export type ConditionalColoringMeasureInfo = EngineAPI.INxMeasureInfo & { conditionalColoring?: ConditionalColoring };

Check failure on line 47 in prebuilt/react-native-sn-table/conditional-colors.ts

View workflow job for this annotation

GitHub Actions / Types Build Validation

Cannot find namespace 'EngineAPI'.

function interpolate(a: number, b: number, amount: number) {
return a + (b - a) * amount;
}

export function lerp(a: string, b: string, amount: number) {
if (!a.startsWith('#') || !b.startsWith('#')) {
return 'none';
}
const from = parseInt(a.slice(1, 7), 16);
const to = parseInt(b.slice(1, 7), 16);
const ar = (from & 0xff0000) >> 16;
const ag = (from & 0x00ff00) >> 8;
const ab = from & 0x0000ff;
const br = (to & 0xff0000) >> 16;
const bg = (to & 0x00ff00) >> 8;
const bb = to & 0x0000ff;
const rr = interpolate(ar, br, amount);
const rg = interpolate(ag, bg, amount);
const rb = interpolate(ab, bb, amount);

// 6 because it's a hex
return `#${((rr << 16) + (rg << 8) + (rb | 0)).toString(16).padStart(6, '0').slice(-6)}`;
}

function getAutoMinMax(lmts: Array<Limit>, val: number) {
let limits = lmts.map((l: Limit) => l.value);

let range;
let delta = 0;

limits = limits.sort((a, b) => a - b);
const nanLimits = limits.some((l) => Number.isNaN(+l));

// eslint-disable-next-line no-nested-ternary
const value = !Number.isNaN(+val) ? val : !Number.isNaN(+limits[0]) ? limits[0] : 0.5;

if (limits.length === 0 || nanLimits) {
if (value === 0) {
delta = 0;
} else {
delta = value * 0.5;
}
} else if (limits.length === 1) {
range = limits[0] - value;

if (range === 0 || Number.isNaN(+range)) {
if (value === 0) {
delta = 0.5;
} else {
delta = Math.abs(value * 0.5);
}
} else if (range > 0) {
// limit on right side of value
return {
min: value - Math.abs(value) * 0.5,
max: limits[0] + 2 * range,
};
} else {
return {
min: limits[0] + 2 * range,
max: value + Math.abs(value) * 0.5,
};
}
} else {
// 2 or more limits
range = limits[limits.length - 1] - limits[0];
range = range > 0 ? range : 1;
return {
min: Math.min(value, limits[0]) - range / 2,
max: Math.max(value, limits[limits.length - 1]) + range / 2,
};
}

return {
min: value - delta,
max: value + delta,
};
}

function shouldBlend(segmentInfo: Segments, colorIndex: number) {
if (segmentInfo.limits.length === 0) {
return false;
}

let returnBoolean;

if (colorIndex === 0) {
// first color
returnBoolean = segmentInfo.limits[colorIndex].gradient;
} else if (colorIndex === segmentInfo.limits.length) {
returnBoolean = segmentInfo.limits[colorIndex - 1].gradient;
} else {
returnBoolean = segmentInfo.limits[colorIndex].gradient || segmentInfo.limits[colorIndex - 1].gradient;
}

return returnBoolean;
}

export function getConditionalColor(paletteIndex: number, value: number, column: Column): PaletteColor {
if (!shouldBlend(column.conditionalColoring.segments, paletteIndex)) {
return { ...column.conditionalColoring.segments.paletteColors[paletteIndex], ...column.representation.indicator };
}

const { paletteColors } = column.conditionalColoring.segments;
const { limits } = column.conditionalColoring.segments;
const { min, max } = getAutoMinMax(limits, value);
const segmentLimits = limits.map((l) => {
const limitNormal = max === min ? 0.5 : (l.value - min) / (max - min);
return { ...l, normal: limitNormal };
});
const mag = max - min;
let t = 1.0;
let color = 'none';

const normal = (value - min) / mag;
const lowerLimit = paletteIndex > 0 ? segmentLimits[paletteIndex - 1] : { normal: 0, value: 0, gradient: false };
const upperLimit = segmentLimits[paletteIndex]
? segmentLimits[paletteIndex]
: { normal: 1, value: 0, gradient: false };
const prevColor = paletteColors[paletteIndex - (paletteIndex > 0 ? 1 : 0)];
const nextColor = paletteColors[paletteIndex + (paletteIndex < paletteColors.length - 1 ? 1 : 0)];
const normValueInLimits = (normal - lowerLimit.normal) / (upperLimit.normal - lowerLimit.normal);
if (lowerLimit && lowerLimit.gradient && upperLimit && upperLimit.gradient) {
// triple gradient
if (normal - lowerLimit.value < upperLimit.value - normal) {
// closer to the lower limit
color = prevColor.color;
t = 0.5 - normValueInLimits;
} else {
color = nextColor.color;
t = normValueInLimits - 0.5;
}
} else if (lowerLimit && lowerLimit.gradient) {
color = prevColor.color;
t = 1 - (0.5 + normValueInLimits / 2);
} else if (upperLimit && upperLimit.gradient) {
color = nextColor.color;
t = normValueInLimits / 2;
} else {
t = normal;
}

return {
...column.representation.indicator,
...paletteColors[paletteIndex],
color: lerp(paletteColors[paletteIndex].color, color, t),
};
}

export function getIndicator(column: Column, tableCell: TableCell): PaletteColor | undefined {
if (
column.conditionalColoring &&
tableCell.qNum !== undefined &&
column.conditionalColoring.segments.limits.length > 0
) {
let index = 0;
const cl = column.conditionalColoring.segments.limits.length;

while (index < cl && tableCell.qNum > column.conditionalColoring.segments.limits[index].value) {
index++;
}
const idc = getConditionalColor(index, tableCell.qNum, column);
return idc;
}
if (column.conditionalColoring && tableCell.qNum && column.conditionalColoring.segments.paletteColors.length === 1) {
return { ...column.conditionalColoring.segments.paletteColors[0], ...column.representation.indicator };
}
return undefined;
}
15 changes: 15 additions & 0 deletions prebuilt/react-native-sn-table/data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export default () => ({
targets: [
{
path: '/qHyperCubeDef',
dimensions: {
min: 0,
max: 1000,
},
measures: {
min: 0,
max: 1000,
},
},
],
});
Loading

0 comments on commit 2edd033

Please sign in to comment.