// Button at the Base subpath, through the same public seam a consumer uses. // // These assertions preserve the observable contract moved out of Application. // Base is now its only implementation and public export. import { readFileSync } from "node:fs"; import { join } from "node:path"; import { createRawSnippet, flushSync, type Snippet } from "svelte"; import { describe, expect, it, vi } from "vitest"; import { APPEARANCE_THEMES, BASE_THEME, COLOR_SCHEMES, } from "../../../packages/theme/src/appearance"; import { appearanceThemeCssPath, colorSchemeCssPath } from "../../../packages/theme/src/paths"; import { cascadeFor, parseStylesheets, resolveProperty, } from "../../../packages/theme/test/support/cascade"; import { BUTTON_INTENTS, BUTTON_SIZES, BUTTON_TONES, BUTTON_VARIANTS, TONES, Button, button, buttonSpinner, } from "./fixtures/button-consumer"; import { classes, classesOf, render, rendered } from "./mount"; function text(content: string): Snippet { return createRawSnippet(() => ({ render: () => `${content}` })); } function click(element: HTMLElement): void { element.click(); flushSync(); } const composition = parseStylesheets([ readFileSync(join(import.meta.dirname, "..", "..", "..", "packages", "tokens", "dist", "tokens.css"), "utf8"), readFileSync(appearanceThemeCssPath(BASE_THEME), "utf8"), ...APPEARANCE_THEMES.map((theme) => readFileSync(appearanceThemeCssPath(theme), "utf8")), ...COLOR_SCHEMES.map((scheme) => readFileSync(colorSchemeCssPath(scheme), "utf8")), ]); function channel(hex: string, offset: number): number { const value = Number.parseInt(hex.slice(offset, offset + 2), 16) / 255; return value <= 0.04045 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4; } function luminance(hex: string): number { return 0.2126 * channel(hex, 1) + 0.7152 * channel(hex, 3) + 0.0722 * channel(hex, 5); } function contrast(left: string, right: string): number { const [lighter, darker] = [luminance(left), luminance(right)].sort((a, b) => b - a); return (lighter + 0.05) / (darker + 0.05); } describe("the Base Button", () => { it("is available through the Base consumer subpath", () => { expect(Button).toBeDefined(); expect(button).toBeTypeOf("function"); expect(buttonSpinner).toBeTypeOf("function"); // Button's meaning is the shared tone vocabulary (ADR 0026); the old // `BUTTON_INTENTS` name stays one release as the same list. expect(BUTTON_TONES).toEqual(TONES); expect(BUTTON_INTENTS).toBe(BUTTON_TONES); }); it("renders a