Skip to content

Commit

Permalink
Border colors (plotly#424)
Browse files Browse the repository at this point in the history
  • Loading branch information
Marc-Andre-Rivet committed May 10, 2019
1 parent b6ee3db commit 04f023e
Show file tree
Hide file tree
Showing 35 changed files with 2,323 additions and 419 deletions.
20 changes: 20 additions & 0 deletions packages/dash-table/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,26 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- `derived_viewport_selected_row_ids` mirrors `derived_viewport_selected_rows`
- `derived_virtual_selected_row_ids` mirrors `derived_virtual_selected_rows`

[#424](https://github.com/plotly/dash-table/pull/424)
- Customizable cell borders through `style_**` props
- cell borders now no longer use `box-shadow` and use `border` instead
- Supports CSS shorthands:
border, border_bottom, border_left, border_right, border_top
- style_** props will ignore the following CSS rules:
border_bottom_color, border_bottom_left_radius, border_bottom_right_radius, border_bottom_style, border_bottom_width, border_collapse, border_color, border_corner_shape, border_image_source, border_image_width, border_left_color, border_left_style, border_left_width, border_right_color, border_right_style, border_right_width, border_spacing, border_style, border_top_color, border_top_left_radius, border_top_right_radius, border_top_style, border_top_width, border_width
- Styles priority:
1. Props priority in decreasing order
style_data_conditional
style_data
style_filter_conditional
style_filter
style_header_conditional
style_header
style_cell_conditional
style_cell
2. Within each props, higher index rules win over lower index rules
3. Previously applied styles of equal priority win over later ones (applied top to bottom, left to right)

### Changed
[#397](https://github.com/plotly/dash-table/pull/397)
- Rename `filtering_settings` to `filter`
Expand Down
15 changes: 14 additions & 1 deletion packages/dash-table/src/core/environment/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import { DebugLevel, LogLevel } from 'core/Logger';
import CookieStorage from 'core/storage/Cookie';
import { DebugLevel, LogLevel } from 'core/Logger';

import { Edge } from 'dash-table/derived/edges/type';

const DASH_DEBUG = 'dash_debug';
const DASH_LOG = 'dash_log';

const DEFAULT_EDGE: Edge = '1px solid #d3d3d3';
const ACTIVE_EDGE: Edge = '1px solid var(--accent)';

interface ISearchParams {
get: (key: string) => string | null;
}
Expand Down Expand Up @@ -33,4 +38,12 @@ export default class Environment {
(LogLevel as any)[log] || LogLevel.ERROR :
LogLevel.ERROR;
}

public static get defaultEdge(): Edge {
return DEFAULT_EDGE;
}

public static get activeEdge(): Edge {
return ACTIVE_EDGE;
}
}
11 changes: 10 additions & 1 deletion packages/dash-table/src/core/math/arrayZipMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,16 @@ import * as R from 'ramda';

type Array<T> = T[];

export function arrayMap<T1, T2, TR>(
export function arrayMap<T1, TR>(
a1: Array<T1>,
cb: (d1: T1, i: number) => TR
) {
const mapArray = R.addIndex<T1, TR>(R.map);

return mapArray((iValue, i) => cb(iValue, i), a1);
}

export function arrayMap2<T1, T2, TR>(
a1: Array<T1>,
a2: Array<T2>,
cb: (d1: T1, d2: T2, i: number) => TR
Expand Down
75 changes: 57 additions & 18 deletions packages/dash-table/src/core/math/matrixZipMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,70 +2,109 @@ import * as R from 'ramda';

type Matrix<T> = T[][];

export function matrixMap<T1, T2, TR>(
export function matrixMap<T1, TR>(
m1: Matrix<T1>,
m2: Matrix<T2>,
cb: (d1: T1, d2: T2, i: number, j: number) => TR
cb: (d1: T1, i: number, j: number) => TR
) {
const mapMatrix = R.addIndex<T1[], TR[]>(R.map);
const mapRow = R.addIndex<T1, TR>(R.map);

return mapMatrix((iRow, i) =>
mapRow(
(ijValue, j) => cb(ijValue, m2[i][j], i, j),
(ijValue, j) => cb(ijValue, i, j),
iRow
), m1
);
}

export function matrixMap2<T1, T2, TR>(
m1: Matrix<T1>,
m2: Matrix<T2> | undefined,
cb: (d1: T1, d2: T2 | undefined, i: number, j: number) => TR
) {
const mapMatrix = R.addIndex<T1[], TR[]>(R.map);
const mapRow = R.addIndex<T1, TR>(R.map);

return mapMatrix((iRow, i) =>
mapRow(
(ijValue, j) => cb(
ijValue,
m2 ? m2[i][j] : undefined,
i,
j
),
iRow
), m1
);
}

export function matrixMap3<T1, T2, T3, TR>(
m1: Matrix<T1>,
m2: Matrix<T2>,
m3: Matrix<T3>,
cb: (d1: T1, d2: T2, d3: T3, i: number, j: number) => TR
m2: Matrix<T2> | undefined,
m3: Matrix<T3> | undefined,
cb: (d1: T1, d2: T2 | undefined, d3: T3 | undefined, i: number, j: number) => TR
) {
const mapMatrix = R.addIndex<T1[], TR[]>(R.map);
const mapRow = R.addIndex<T1, TR>(R.map);

return mapMatrix((iRow, i) =>
mapRow(
(ijValue, j) => cb(ijValue, m2[i][j], m3[i][j], i, j),
(ijValue, j) => cb(
ijValue,
m2 ? m2[i][j] : undefined,
m3 ? m3[i][j] : undefined,
i,
j
),
iRow
), m1
);
}

export function matrixMap4<T1, T2, T3, T4, TR>(
m1: Matrix<T1>,
m2: Matrix<T2>,
m3: Matrix<T3>,
m4: Matrix<T4>,
cb: (d1: T1, d2: T2, d3: T3, d4: T4, i: number, j: number) => TR
m2: Matrix<T2> | undefined,
m3: Matrix<T3> | undefined,
m4: Matrix<T4> | undefined,
cb: (d1: T1, d2: T2 | undefined, d3: T3 | undefined, d4: T4 | undefined, i: number, j: number) => TR
) {
const mapMatrix = R.addIndex<T1[], TR[]>(R.map);
const mapRow = R.addIndex<T1, TR>(R.map);

return mapMatrix((iRow, i) =>
mapRow(
(ijValue, j) => cb(ijValue, m2[i][j], m3[i][j], m4[i][j], i, j),
(ijValue, j) => cb(
ijValue,
m2 ? m2[i][j] : undefined,
m3 ? m3[i][j] : undefined,
m4 ? m4[i][j] : undefined,
i,
j
),
iRow
), m1
);
}

export function matrixMapN<TR>(
cb: (i: number, j: number, ...args: any[]) => TR,
...matrices: (any[][])[]
m1: Matrix<any>,
...matrices: (any[][] | undefined)[]
) {
const m1 = matrices.slice(0, 1);
const ms = matrices.slice(1);

const mapMatrix = R.addIndex<any[], TR[]>(R.map);
const mapRow = R.addIndex<any, TR>(R.map);

return mapMatrix((iRow, i) =>
mapRow(
(ijValue, j) => cb(i, j, [ijValue, ...ms.map(m => m[i][j])]),
(ijValue, j) => cb(
i,
j,
[
ijValue,
m1[i][j],
...matrices.map(m => m ? m[i][j] : undefined)
]
),
iRow
), m1
);
Expand Down
8 changes: 8 additions & 0 deletions packages/dash-table/src/core/type/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,10 @@
export type OptionalMap<T, TR extends keyof T, M> = {
[tr in TR]?: M
};
export type RequiredPluck<T, R extends keyof T> = { [r in R]: T[r] };
export type OptionalPluck<T, R extends keyof T> = { [r in R]?: T[r] };

export type RequiredProp<T, R extends keyof T> = T[R];
export type OptionalProp<T, R extends keyof T> = T[R] | undefined;

export type PropOf<T, R extends keyof T> = R;
76 changes: 52 additions & 24 deletions packages/dash-table/src/dash-table/components/CellFactory.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import * as R from 'ramda';
import React from 'react';

import { matrixMap2, matrixMap3 } from 'core/math/matrixZipMap';
import { arrayMap2 } from 'core/math/arrayZipMap';

import { ICellFactoryProps } from 'dash-table/components/Table/props';
import derivedCellWrappers from 'dash-table/derived/cell/wrappers';
import derivedCellContents from 'dash-table/derived/cell/contents';
import derivedCellOperations from 'dash-table/derived/cell/operations';
import derivedCellStyles from 'dash-table/derived/cell/wrapperStyles';
import derivedCellStyles, { derivedDataOpStyles } from 'dash-table/derived/cell/wrapperStyles';
import derivedDropdowns from 'dash-table/derived/cell/dropdowns';
import { derivedRelevantCellStyles } from 'dash-table/derived/style';

import { matrixMap3 } from 'core/math/matrixZipMap';
import { arrayMap } from 'core/math/arrayZipMap';
import { IEdgesMatrices } from 'dash-table/derived/edges/type';

export default class CellFactory {

Expand All @@ -23,11 +25,12 @@ export default class CellFactory {
private readonly cellDropdowns = derivedDropdowns(),
private readonly cellOperations = derivedCellOperations(),
private readonly cellStyles = derivedCellStyles(),
private readonly dataOpStyles = derivedDataOpStyles(),
private readonly cellWrappers = derivedCellWrappers(propsFn),
private readonly relevantStyles = derivedRelevantCellStyles()
) { }

public createCells() {
public createCells(dataEdges: IEdgesMatrices | undefined, dataOpEdges: IEdgesMatrices | undefined) {
const {
active_cell,
columns,
Expand All @@ -49,30 +52,27 @@ export default class CellFactory {
virtualized
} = this.props;

const operations = this.cellOperations(
data,
virtualized.data,
virtualized.indices,
row_selectable,
row_deletable,
selected_rows,
setProps
);

const relevantStyles = this.relevantStyles(
style_cell,
style_data,
style_cell_conditional,
style_data_conditional
);

const wrapperStyles = this.cellStyles(
const cellStyles = this.cellStyles(
columns,
relevantStyles,
virtualized.data,
virtualized.offset
);

const dataOpStyles = this.dataOpStyles(
(row_selectable ? 1 : 0) + (row_deletable ? 1 : 0),
relevantStyles,
virtualized.data,
virtualized.offset
);

const dropdowns = this.cellDropdowns(
columns,
virtualized.data,
Expand All @@ -82,15 +82,25 @@ export default class CellFactory {
dropdown_properties
);

const wrappers = this.cellWrappers(
const operations = this.cellOperations(
data,
virtualized.data,
virtualized.indices,
row_selectable,
row_deletable,
selected_rows,
setProps
);

const cellWrappers = this.cellWrappers(
active_cell,
columns,
virtualized.data,
virtualized.offset,
selected_cells
);

const contents = this.cellContents(
const cellContents = this.cellContents(
active_cell,
columns,
virtualized.data,
Expand All @@ -100,15 +110,33 @@ export default class CellFactory {
dropdowns
);

const ops = matrixMap2(
operations,
dataOpStyles,
(o, s, i, j) => React.cloneElement(o, {
style: R.mergeAll([
dataOpEdges && dataOpEdges.getStyle(i, j),
s,
o.props.style
])
})
);

const cells = matrixMap3(
wrappers,
wrapperStyles,
contents,
(w, s, c) => React.cloneElement(w, { children: [c], style: s })
cellWrappers,
cellStyles,
cellContents,
(w, s, c, i, j) => React.cloneElement(w, {
children: [c],
style: R.mergeAll([
s,
dataEdges && dataEdges.getStyle(i, j)
])
})
);

return arrayMap(
operations,
return arrayMap2(
ops,
cells,
(o, c) => Array.prototype.concat(o, c)
);
Expand Down
Loading

0 comments on commit 04f023e

Please sign in to comment.