89 lines
2.8 KiB
TypeScript
89 lines
2.8 KiB
TypeScript
import { lowerToCanonical, type CanonicalClauseDescriptor } from 'imhotep-dsl'
|
|
import type { FluentRelation } from 'imhotep-dsl'
|
|
import type { ImhotepUi } from './public.js'
|
|
|
|
export interface PresetResult {
|
|
assertions: FluentRelation[]
|
|
clauses: CanonicalClauseDescriptor[]
|
|
}
|
|
|
|
function toPresetResult(assertions: FluentRelation[]): PresetResult {
|
|
const clauses: CanonicalClauseDescriptor[] = []
|
|
for (const assertion of assertions) {
|
|
clauses.push(...lowerToCanonical(assertion.toAst()))
|
|
}
|
|
return { assertions, clauses }
|
|
}
|
|
|
|
export function touchTarget(
|
|
ui: ImhotepUi,
|
|
selector: string,
|
|
options: { minSize?: number } = {},
|
|
): PresetResult {
|
|
const minSize = options.minSize ?? 44
|
|
const assertions = [
|
|
ui.expect(selector).to.be.atLeast(minSize, 'width'),
|
|
ui.expect(selector).to.be.atLeast(minSize, 'height'),
|
|
]
|
|
return toPresetResult(assertions)
|
|
}
|
|
|
|
export function toolbarAlignment(
|
|
ui: ImhotepUi,
|
|
selectors: string[],
|
|
options: { minGap?: number; axis?: 'centerY' | 'centerX' } = {},
|
|
): PresetResult {
|
|
const minGap = options.minGap ?? 8
|
|
const axis = options.axis ?? 'centerY'
|
|
const assertions: FluentRelation[] = []
|
|
for (let i = 0; i < selectors.length - 1; i++) {
|
|
assertions.push(ui.expect(selectors[i]).to.be.leftOf(selectors[i + 1], { minGap }))
|
|
assertions.push(ui.expect(selectors[i]).to.be.alignedWith(selectors[i + 1], { axis }))
|
|
}
|
|
return toPresetResult(assertions)
|
|
}
|
|
|
|
export function cardSpacing(
|
|
ui: ImhotepUi,
|
|
cardSelector: string,
|
|
nextCardSelector: string,
|
|
options: { minGap?: number } = {},
|
|
): PresetResult {
|
|
const minGap = options.minGap ?? 16
|
|
const assertions = [
|
|
ui.expect(cardSelector).to.be.leftOf(nextCardSelector, { minGap }),
|
|
ui.expect(cardSelector).to.be.alignedWith(nextCardSelector, { axis: 'top' }),
|
|
]
|
|
return toPresetResult(assertions)
|
|
}
|
|
|
|
export function formLabelAlignment(
|
|
ui: ImhotepUi,
|
|
labelSelector: string,
|
|
inputSelector: string,
|
|
options: { labelAbove?: boolean; maxGap?: number } = {},
|
|
): PresetResult {
|
|
const labelAbove = options.labelAbove ?? true
|
|
const maxGap = options.maxGap ?? 16
|
|
const assertions: FluentRelation[] = []
|
|
if (labelAbove) {
|
|
assertions.push(ui.expect(labelSelector).to.be.above(inputSelector, { maxGap }))
|
|
assertions.push(ui.expect(labelSelector).to.be.alignedWith(inputSelector, { axis: 'left' }))
|
|
} else {
|
|
assertions.push(ui.expect(labelSelector).to.be.leftOf(inputSelector, { maxGap }))
|
|
assertions.push(ui.expect(labelSelector).to.be.alignedWith(inputSelector, { axis: 'centerY' }))
|
|
}
|
|
return toPresetResult(assertions)
|
|
}
|
|
|
|
export function modalContainment(
|
|
ui: ImhotepUi,
|
|
modalSelector: string,
|
|
): PresetResult {
|
|
const assertions = [
|
|
ui.expect(modalSelector).to.be.inside('body'),
|
|
ui.expect(modalSelector).to.be.centeredWithin('body'),
|
|
]
|
|
return toPresetResult(assertions)
|
|
}
|