diff --git a/src/UITable/elements/Toast.ts b/src/UITable/elements/Toast.ts index c51fa83..968abba 100644 --- a/src/UITable/elements/Toast.ts +++ b/src/UITable/elements/Toast.ts @@ -1,5 +1,6 @@ import { getColor, getDynamicColor } from '../../colors'; import { isNumber } from '../../common'; +import { getGrid, Grid } from '../grid'; import Div, { NonCascadingDiv } from './Div'; import Gradient from './Gradient'; import HSpace from './HSpace'; @@ -9,6 +10,17 @@ import presetStyles, { FlavorKey } from './presetStyles'; import Span from './Span'; import { TapProps } from './types'; +type ToastGrid = Grid< + 'metadata' | 'metadataIcon' | 'leftIcon' | 'leftIconSpacing' +>; + +const toastGrid: ToastGrid = getGrid({ + metadata: '15%', + metadataIcon: '8%', + leftIcon: '10%', + leftIconSpacing: '3%', +}); + export type ToastProps = { title: string; icon: IconOrSFKey; @@ -16,6 +28,7 @@ export type ToastProps = { metadata?: number | string; showCloseIcon?: boolean; description?: string; + grid?: ToastGrid; } & TapProps; /** Flavors that shouldn't be used for the left icon's accent color, as they @@ -29,6 +42,7 @@ export default ({ flavor = 'secondary', metadata, description, + grid = toastGrid, ...tapProps }: ToastProps) => { const accentColor = presetStyles().flavors[flavor].bgColor; @@ -38,19 +52,20 @@ export default ({ const mainRowRightIcons = Span( [ (metadata || isNumber(metadata)) && - P(String(metadata), { align: 'center', width: '15%' }), - showCloseIcon && Icon('x_in_circle', { width: '8%' }), + P(String(metadata), { align: 'center', width: grid.metadata }), + showCloseIcon && Icon('x_in_circle', { width: grid.metadataIcon }), ], { font: () => Font.footnote(), align: 'center', isFaded: true } ); const mainRow = Div([ Icon(icon, { - width: '10%', + width: grid.leftIcon, ...(!BANNED_ICON_COLOR_FLAVORS.includes(flavor) && { color: accentColor, }), }), + HSpace(grid.leftIconSpacing), P(title), mainRowRightIcons, ]); diff --git a/src/UITable/grid.ts b/src/UITable/grid.ts new file mode 100644 index 0000000..fac8fb8 --- /dev/null +++ b/src/UITable/grid.ts @@ -0,0 +1,61 @@ +import { sum } from '../array'; +import { objectFromEntries } from '../common'; +import { isIn } from '../flow'; +import { objectEntries } from '../object'; +import { Percent } from './Row'; +import { parsePercent } from './elements'; + +type GridKey = string | number | symbol; + +export type Grid = Record & GridHelpers; + +// + +const sumPcts = (...percents: Percent[]): Percent => + `${sum(percents.map(pct => parsePercent(pct)))}%`; + +const gridToNumbers = ( + gridWithoutHelpers: Record +): Record => + objectFromEntries( + objectEntries(gridWithoutHelpers).map(([key, pct]) => [ + key, + parsePercent(pct), + ]) + ); + +const calculatePcts = ( + calc: (gridNumbers: Record) => number, + gridWithoutHelpers: Record +): Percent => { + const calcNumber = calc(gridToNumbers(gridWithoutHelpers)); + return `${calcNumber}%`; +}; + +type GridHelpers = { + sum: (...keys: Key[]) => Percent; + calc: (calcFn: (keyNumValues: Record) => number) => Percent; + extend: ( + extendedGrid: Record + ) => Record & GridHelpers; +}; + +// + +export const getGrid = >( + grid: T +): T & GridHelpers => { + const gridHelpers: GridHelpers = { + sum: (...keys: (keyof T)[]) => sumPcts(...keys.map(key => grid[key])), + calc: calcFn => calculatePcts(calcFn, grid), + extend: extendedGrid => getGrid({ ...grid, ...extendedGrid }), + }; + + const reservedKeys = Object.keys(gridHelpers); + const gridKeys = Object.keys(grid); + if (reservedKeys.some(reservedKey => isIn(reservedKey, gridKeys))) { + throw new Error('Using reserved keys in grid'); + } + + return { ...grid, ...gridHelpers }; +}; diff --git a/src/UITable/index.ts b/src/UITable/index.ts index 018def0..8d82742 100644 --- a/src/UITable/index.ts +++ b/src/UITable/index.ts @@ -86,3 +86,4 @@ export { } from './elements'; export { default as getTable } from './getTable'; export * from './types'; +export * from './grid';