|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function normalizeScreens(screens, root = true) { |
|
if (Array.isArray(screens)) { |
|
return screens.map((screen) => { |
|
if (root && Array.isArray(screen)) { |
|
throw new Error('The tuple syntax is not supported for `screens`.') |
|
} |
|
|
|
if (typeof screen === 'string') { |
|
return { name: screen.toString(), not: false, values: [{ min: screen, max: undefined }] } |
|
} |
|
|
|
let [name, options] = screen |
|
name = name.toString() |
|
|
|
if (typeof options === 'string') { |
|
return { name, not: false, values: [{ min: options, max: undefined }] } |
|
} |
|
|
|
if (Array.isArray(options)) { |
|
return { name, not: false, values: options.map((option) => resolveValue(option)) } |
|
} |
|
|
|
return { name, not: false, values: [resolveValue(options)] } |
|
}) |
|
} |
|
|
|
return normalizeScreens(Object.entries(screens ?? {}), false) |
|
} |
|
|
|
|
|
|
|
|
|
|
|
export function isScreenSortable(screen) { |
|
if (screen.values.length !== 1) { |
|
return { result: false, reason: 'multiple-values' } |
|
} else if (screen.values[0].raw !== undefined) { |
|
return { result: false, reason: 'raw-values' } |
|
} else if (screen.values[0].min !== undefined && screen.values[0].max !== undefined) { |
|
return { result: false, reason: 'min-and-max' } |
|
} |
|
|
|
return { result: true, reason: null } |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function compareScreens(type, a, z) { |
|
let aScreen = toScreen(a, type) |
|
let zScreen = toScreen(z, type) |
|
|
|
let aSorting = isScreenSortable(aScreen) |
|
let bSorting = isScreenSortable(zScreen) |
|
|
|
|
|
if (aSorting.reason === 'multiple-values' || bSorting.reason === 'multiple-values') { |
|
throw new Error( |
|
'Attempted to sort a screen with multiple values. This should never happen. Please open a bug report.' |
|
) |
|
} else if (aSorting.reason === 'raw-values' || bSorting.reason === 'raw-values') { |
|
throw new Error( |
|
'Attempted to sort a screen with raw values. This should never happen. Please open a bug report.' |
|
) |
|
} else if (aSorting.reason === 'min-and-max' || bSorting.reason === 'min-and-max') { |
|
throw new Error( |
|
'Attempted to sort a screen with both min and max values. This should never happen. Please open a bug report.' |
|
) |
|
} |
|
|
|
|
|
let { min: aMin, max: aMax } = aScreen.values[0] |
|
let { min: zMin, max: zMax } = zScreen.values[0] |
|
|
|
|
|
if (a.not) [aMin, aMax] = [aMax, aMin] |
|
if (z.not) [zMin, zMax] = [zMax, zMin] |
|
|
|
aMin = aMin === undefined ? aMin : parseFloat(aMin) |
|
aMax = aMax === undefined ? aMax : parseFloat(aMax) |
|
zMin = zMin === undefined ? zMin : parseFloat(zMin) |
|
zMax = zMax === undefined ? zMax : parseFloat(zMax) |
|
|
|
let [aValue, zValue] = type === 'min' ? [aMin, zMin] : [zMax, aMax] |
|
|
|
return aValue - zValue |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function toScreen(value, type) { |
|
if (typeof value === 'object') { |
|
return value |
|
} |
|
|
|
return { |
|
name: 'arbitrary-screen', |
|
values: [{ [type]: value }], |
|
} |
|
} |
|
|
|
function resolveValue({ 'min-width': _minWidth, min = _minWidth, max, raw } = {}) { |
|
return { min, max, raw } |
|
} |
|
|