diff --git a/packages/core/engine/defaults.ts b/packages/core/engine/defaults.ts index f23bdd0..2b5625a 100644 --- a/packages/core/engine/defaults.ts +++ b/packages/core/engine/defaults.ts @@ -3,6 +3,7 @@ import { UmbraScheme, UmbraSettings } from './types' export const defaultSettings: UmbraSettings = { readability: 10, iterations: 15, + insertion: 10, shades: [5, 5, 5, 5, 15, 10, 10, 25, 30, 25, 25, 25], tints: [5, 10, 10, 10, 15, 15, 25, 15, 15, 15, 15, 25] } diff --git a/packages/core/engine/generator.ts b/packages/core/engine/generator.ts index d26ca8b..0362413 100644 --- a/packages/core/engine/generator.ts +++ b/packages/core/engine/generator.ts @@ -1,8 +1,7 @@ import { colord, Colord } from 'colord' -import { UmbraAdjusted, UmbraInput } from './types' +import { UmbraAdjusted, UmbraInput, Accent } from './types' import { pickContrast, colorMix } from './primitives/color' -import { normalizeRange, nextAccent, getStrings } from './primitives/utils' -import { defaultSettings } from './defaults' +import { insertColorIntoRange, nextAccent, getStrings } from './primitives/utils' interface GetRange { from: Colord @@ -30,40 +29,61 @@ function getRange({ from, to, range }: GetRange) { }) } -function accentRange( - input: UmbraInput, - adjusted: UmbraAdjusted, - passedRange: (number | string)[], +interface RangeProps { + input: UmbraInput + adjusted: UmbraAdjusted + range: (number | string)[] color?: string -) { - const { background, foreground } = adjusted - const settingsRange = background.isDark() ? defaultSettings.shades : defaultSettings.tints - const range = passedRange.length > 0 ? passedRange : settingsRange || [] +} + +function autoPlacedRange({ input, adjusted, range, color }: RangeProps) { + if (!color) return range + const baseRange = getRange({ + from: adjusted.background, + to: adjusted.foreground, + range: rangeValues(adjusted, input.settings) || [] + }) + return insertColorIntoRange({ range, shades: baseRange, color: colord(color) }) +} + +function accentColor(fallback: Colord, accent?: string, range?: (number | string)[]) { + const plainColor2 = accent ? accent : range ? getStrings(range)[0] : undefined + return plainColor2 ? colord(plainColor2) : fallback +} + +function replaceAtIndex(array: (number | string)[], index: number, value: string) { + const newArray = array.slice() + newArray[index] = value + return newArray +} + +function putAccentInRange(adjusted: UmbraAdjusted, accent: Accent | string, input: UmbraInput) { + const isString = typeof accent === 'string' + const color = isString ? accent : accent.color + const insertion = input.settings.insertion - if (!color) return getRange({ from: background, to: foreground, range }) + const fallback = rangeValues(adjusted, input.settings) || [] + const range = isString ? fallback : rangeValues(adjusted, accent) || fallback - const defaultRange = input.settings.shades || [] - const shades = getRange({ from: background, to: foreground, range: defaultRange }) - const normalizedRange = normalizeRange({ range: range, shades, color: colord(color) }) - return getRange({ from: background, to: foreground, range: normalizedRange }) + if (insertion && color) return replaceAtIndex(range, insertion, color) + if (!insertion && color) return autoPlacedRange({ input, adjusted, range, color }) + return range } function accents(input: UmbraInput, adjusted: UmbraAdjusted) { - const defaultShades = rangeValues(adjusted, input.settings) + const { background, foreground } = adjusted return adjusted.accents.map((accent) => { - const plainColor = typeof accent === 'string' ? accent : accent.color - const plainRange = typeof accent === 'string' ? defaultShades : rangeValues(adjusted, accent) - const color = plainColor ? plainColor : plainRange ? getStrings(plainRange)[0] : undefined - const range = plainRange ? plainRange : defaultShades - const name = typeof accent === 'string' ? undefined : accent.name - - const c = color ? colord(color) : undefined - const fallback = c ? c : adjusted.foreground + const isString = typeof accent === 'string' + + const name = isString ? undefined : accent.name + const color = isString ? accent : accent.color + const range = putAccentInRange(adjusted, accent, input) + return { - name: name ? name : `accent`, - background: fallback, - foreground: pickContrast(fallback, adjusted), - range: accentRange(input, adjusted, range, plainColor) + name: name || `accent`, + background: accentColor(adjusted.foreground, color, range), + foreground: pickContrast(background, adjusted), + range: getRange({ from: background, to: foreground, range }) } }) } @@ -74,15 +94,12 @@ interface RangeValues { } function rangeValues(adjusted: UmbraAdjusted, scheme?: RangeValues) { - const { background } = adjusted - const shades = scheme?.shades || [] - const tints = scheme?.tints || shades - return background.isDark() ? shades : tints + return adjusted.background.isDark() ? scheme?.shades : scheme?.tints } function base(input: UmbraInput, adjusted: UmbraAdjusted) { const { background, foreground } = adjusted - const range = rangeValues(adjusted, input.settings) + const range = rangeValues(adjusted, input.settings) || [] return { name: 'base', background, diff --git a/packages/core/engine/primitives/utils.ts b/packages/core/engine/primitives/utils.ts index 1892e37..6262572 100644 --- a/packages/core/engine/primitives/utils.ts +++ b/packages/core/engine/primitives/utils.ts @@ -33,7 +33,7 @@ function getReadable(shade: Colord, color: Colord, index: number) { return { readability, index } } -export function normalizeRange({ range, shades, color }: NewRange) { +export function insertColorIntoRange({ range, shades, color }: NewRange) { const leastReadable = shades .map((shade, index) => getReadable(shade, color, index)) .reduce((a, b) => (a.readability < b.readability ? a : b)) diff --git a/packages/core/engine/types/index.ts b/packages/core/engine/types/index.ts index 930327b..892f466 100644 --- a/packages/core/engine/types/index.ts +++ b/packages/core/engine/types/index.ts @@ -55,6 +55,7 @@ export interface DehydratedAdjusted { export interface UmbraSettings { readability?: number iterations?: number + insertion?: number aliases?: Alias | true shades?: (number | string)[] tints?: (number | string)[] diff --git a/packages/playground/src/App.vue b/packages/playground/src/App.vue index e0a1be7..244e281 100644 --- a/packages/playground/src/App.vue +++ b/packages/playground/src/App.vue @@ -28,30 +28,29 @@ const radixYellow = { const success = { name: 'success', - shades: [25, 25, 25, 25, 25, '#4caf50', 25, 25, 25, 25, 25, 25] + color: '#4caf50' } const royal = { name: 'royal', - shades: [25, 25, 25, 25, 25, '#a94d94', 35, 25, 25, 25, 25, 25] + color: '#4d4da9' } const brown = { name: 'brown', - shades: [25, 25, 25, 25, 25, '#87533e', 25, 25, 25, 25, 25, 25] + color: '#87533e' } const something = { - shades: [10, 15, 25, 35, 35, '#4f0820', 15, 15, 15, 15, 15, 25] + shades: [5, 5, 5, 5, 15, 10, 10, 25, '#e5484d', 25, 25, 25] } const accent = { - shades: [10, 10, 25, 25, 25, 25, 25, 25, '#ff0157', 10, 25, 25] + color: '#ff0157' } const accent2 = { - color: '#ff0157', - shades: [10, 10, 25, 25, 25, 25, 25, 25, 25, 10, 25, 25] + color: '#ff0157' } const accent3 = { @@ -62,6 +61,7 @@ const theme = umbra({ background: '#000000', foreground: '#ffffff', accents: [ + royal, radixRed, radixYellow, radixBlue, @@ -70,7 +70,6 @@ const theme = umbra({ accent3, radixRed, success, - royal, brown, something ]