{"version":3,"sources":["../src/index.ts","../src/assets.ts"],"names":[],"mappings":"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","file":"assets.mjs","sourcesContent":["/**\n * The orangecheck mark: an isometric check on a 16×8 grid, three faces.\n *\n * Framework-free and dependency-free: SVG strings for any page, a data URI\n * for CSS and images, and the geometry for a renderer that draws its own.\n * The React component is in `@orangecheck/mark/react`.\n */\n\n/** The three faces as SVG points in the 16×8 box. */\nexport const MARK_POINTS = {\n    top: '0,3 2,2 6,4 14,0 16,1 6,6',\n    left: '0,3 6,6 6,8 0,5',\n    right: '6,6 16,1 16,3 6,8',\n} as const;\n\nexport const MARK_VIEWBOX = '0 0 16 8';\n\n/** The faces as drawn. For dark grounds only: the top face is about 1.3:1 on white. */\nexport const MARK_FACES = { top: '#FED8AB', left: '#FB933C', right: '#EA580B' } as const;\n\n/**\n * One colour, three weights: the check at full strength, the sides as depth.\n * Chosen for the widest smallest step between neighbouring faces and the\n * ground across light, dark and mid-tone (amber, brown) buttons.\n */\nexport const MARK_MONO_OPACITY = { top: 1, left: 0.6, right: 0.3 } as const;\n\n/** The tile: the faces on an ink square with rounded corners, 24×24. Reads on any ground. */\nexport const MARK_TILE = {\n    viewBox: '0 0 24 24',\n    radius: 6.25,\n    fill: '#0A0A0A',\n    transform: 'translate(4.25 8.1) scale(0.97)',\n} as const;\n\n/** Smallest width the bare mark may be drawn at, in CSS pixels (the tile: the same, square). */\nexport const MARK_MIN_PX = 16;\n\n/** `mono`: the host's text colour. `brand`: as drawn, on dark grounds. `tile`: the faces on their own ink tile. */\nexport type MarkVariant = 'mono' | 'brand' | 'tile';\n\nexport interface MarkSvgOptions {\n    variant?: MarkVariant;\n    /** An accessible name. Without one the mark is decoration, hidden from assistive technology. */\n    title?: string;\n    /** Width as a CSS length, `1.75em` by default (the tile `1.25em`); the height follows. Overridable from CSS. */\n    width?: string;\n    /** Mono only: every face at full strength, one flat shape. For forced colours and anything that cannot shade. */\n    flat?: boolean;\n    /** The mono colour. Default `currentColor`; a data URI needs a real colour, since an image inherits none. */\n    color?: string;\n    /** Added to the `<svg>` element. */\n    className?: string;\n}\n\nconst ORDER = ['left', 'right', 'top'] as const;\n\nfunction escape(s: string): string {\n    return s.replace(/[&<>\"']/g, (c) => `&#${c.charCodeAt(0)};`);\n}\n\n/** A face's opacity in mono: stepped, or full for a flat mark. */\nfunction opacity(face: (typeof ORDER)[number], flat: boolean): number {\n    return flat ? 1 : MARK_MONO_OPACITY[face];\n}\n\nfunction faces(variant: MarkVariant, color: string, flat = false): string {\n    return ORDER.map((face) =>\n        variant === 'mono'\n            ? `<polygon points=\"${MARK_POINTS[face]}\" fill=\"${escape(color)}\"${opacity(face, flat) === 1 ? '' : ` fill-opacity=\"${opacity(face, flat)}\"`}/>`\n            : `<polygon points=\"${MARK_POINTS[face]}\" fill=\"${MARK_FACES[face]}\"/>`\n    ).join('');\n}\n\n/** The height that keeps a CSS length's aspect for the variant: half for the mark, equal for the tile. */\nfunction heightFor(variant: MarkVariant, width: string): string {\n    if (variant === 'tile') return width;\n    const m = /^(-?[\\d.]+)([a-z%]*)$/i.exec(width.trim());\n    return m ? `${Number(m[1]) / 2}${m[2]}` : 'auto';\n}\n\n/**\n * The mark as an SVG string. Sized in em by default, so it follows the\n * font size of the text beside it; a stylesheet can still set its size,\n * since width and height are attributes, not inline styles (no CSP needed).\n */\nexport function markSvg(options: MarkSvgOptions = {}): string {\n    const variant = options.variant ?? 'mono';\n    if (variant !== 'mono' && variant !== 'brand' && variant !== 'tile') throw new TypeError(`markSvg: unknown variant ${String(variant)}`);\n    const width = options.width ?? (variant === 'tile' ? '1.25em' : '1.75em');\n    const color = options.color ?? 'currentColor';\n    const label = options.title ? `<title>${escape(options.title)}</title>` : '';\n    const a11y = options.title ? 'role=\"img\"' : 'aria-hidden=\"true\" focusable=\"false\"';\n    const cls = options.className ? ` class=\"${escape(options.className)}\"` : '';\n    const size = `width=\"${escape(width)}\" height=\"${escape(heightFor(variant, width))}\"`;\n    if (variant === 'tile') {\n        return (\n            `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"${MARK_TILE.viewBox}\" ${size} ${a11y} data-oc-mark=\"tile\"${cls}>${label}` +\n            `<rect width=\"24\" height=\"24\" rx=\"${MARK_TILE.radius}\" fill=\"${MARK_TILE.fill}\"/>` +\n            `<g transform=\"${MARK_TILE.transform}\">${faces('brand', color)}</g></svg>`\n        );\n    }\n    return `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"${MARK_VIEWBOX}\" ${size} ${a11y} data-oc-mark=\"${variant}\"${cls}>${label}${faces(variant, color, options.flat)}</svg>`;\n}\n\n/** The mark as a `data:image/svg+xml` URI, for CSS backgrounds and `<img>`. Mono needs an explicit `color`. */\nexport function markDataUri(options: MarkSvgOptions = {}): string {\n    if ((options.variant ?? 'mono') === 'mono' && (!options.color || options.color === 'currentColor')) {\n        throw new TypeError('markDataUri: a mono mark in an image needs a colour; an image inherits none');\n    }\n    return `data:image/svg+xml,${encodeURIComponent(markSvg({ ...options, width: options.width ?? '16' }))}`;\n}\n\nconst SVG_NS = 'http://www.w3.org/2000/svg';\n\n/**\n * The mark as an `<svg>` element, built node by node: no HTML parsing, so\n * it works under Trusted Types and any Content-Security-Policy. Same\n * drawing and attributes as markSvg.\n */\nexport function markElement(doc: Document, options: Omit<MarkSvgOptions, 'className'> & { className?: string } = {}): SVGSVGElement {\n    const variant = options.variant ?? 'mono';\n    if (variant !== 'mono' && variant !== 'brand' && variant !== 'tile') throw new TypeError(`markElement: unknown variant ${String(variant)}`);\n    const width = options.width ?? (variant === 'tile' ? '1.25em' : '1.75em');\n    const color = options.color ?? 'currentColor';\n    const el = <K extends keyof SVGElementTagNameMap>(tag: K, attrs: Record<string, string>) => {\n        const node = doc.createElementNS(SVG_NS, tag);\n        for (const [k, v] of Object.entries(attrs)) node.setAttribute(k, v);\n        return node;\n    };\n    const svg = el('svg', {\n        viewBox: variant === 'tile' ? MARK_TILE.viewBox : MARK_VIEWBOX,\n        width,\n        height: heightFor(variant, width),\n        'data-oc-mark': variant,\n    });\n    if (options.className) svg.setAttribute('class', options.className);\n    if (options.title) {\n        svg.setAttribute('role', 'img');\n        const title = el('title', {});\n        title.textContent = options.title;\n        svg.append(title);\n    } else {\n        svg.setAttribute('aria-hidden', 'true');\n        svg.setAttribute('focusable', 'false');\n    }\n    const parent = variant === 'tile' ? el('g', { transform: MARK_TILE.transform }) : svg;\n    if (variant === 'tile') svg.append(el('rect', { width: '24', height: '24', rx: String(MARK_TILE.radius), fill: MARK_TILE.fill }), parent);\n    for (const face of ORDER) {\n        const attrs: Record<string, string> = { points: MARK_POINTS[face] };\n        if (variant === 'mono') {\n            attrs.fill = color;\n            if (opacity(face, !!options.flat) !== 1) attrs['fill-opacity'] = String(opacity(face, !!options.flat));\n        } else attrs.fill = MARK_FACES[face];\n        parent.append(el('polygon', attrs));\n    }\n    return svg;\n}\n","import { MARK_FACES, MARK_POINTS, MARK_TILE, markSvg, type MarkVariant } from './index';\n\n/** PNG widths written to assets/png, in px. The bare mark is half as tall; the tile is square. */\nexport const PNG_WIDTHS = [16, 24, 32, 40, 48, 64, 80, 96, 128, 256] as const;\n\nconst FILES: Array<{ name: string; variant: MarkVariant; color?: string }> = [\n    { name: 'orangecheck-mark-brand', variant: 'brand' },\n    { name: 'orangecheck-mark-tile', variant: 'tile' },\n    { name: 'orangecheck-mark-mono', variant: 'mono' },\n    { name: 'orangecheck-mark-mono-black', variant: 'mono', color: '#0A0A0A' },\n    { name: 'orangecheck-mark-mono-white', variant: 'mono', color: '#FFFFFF' },\n];\n\n/** The standalone SVG files: px-sized, named, one per variant and colour. */\nexport function assetSvgs() {\n    return FILES.map(({ name, variant, color }) => {\n        const square = variant === 'tile';\n        const svgAt = (w: number, h: number) =>\n            markSvg({ variant, color, title: 'orangecheck', width: String(w) }).replace(/height=\"[^\"]*\"/, `height=\"${h}\"`);\n        return { name, square, svg: `${svgAt(64, square ? 64 : 32)}\\n`, svgAt };\n    });\n}\n\n/** The tile with square corners: an app icon the platform rounds itself (iOS home screen). */\nexport function squareTileSvg(size: number): string {\n    const face = (f: keyof typeof MARK_POINTS) => `<polygon points=\"${MARK_POINTS[f]}\" fill=\"${MARK_FACES[f]}\"/>`;\n    return (\n        `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"${MARK_TILE.viewBox}\" width=\"${size}\" height=\"${size}\">` +\n        `<rect width=\"24\" height=\"24\" fill=\"${MARK_TILE.fill}\"/>` +\n        `<g transform=\"${MARK_TILE.transform}\">${face('left')}${face('right')}${face('top')}</g></svg>`\n    );\n}\n\n/**\n * assets/favicon: a site's icon set, drawn from the tile, under the names\n * family sites already link. favicon.ico holds the 16, 32 and 48 px PNGs.\n */\nexport const FAVICON_PNGS: ReadonlyArray<{ file: string; size: number; square?: true }> = [\n    { file: 'favicon-16x16.png', size: 16 },\n    { file: 'favicon-32x32.png', size: 32 },\n    { file: 'favicon-48x48.png', size: 48 },\n    { file: 'apple-touch-icon.png', size: 180, square: true },\n    { file: 'android-chrome-192x192.png', size: 192 },\n    { file: 'android-chrome-512x512.png', size: 512 },\n];\nexport const FAVICON_ICO_SIZES = [16, 32, 48] as const;\n\n/** favicon.svg: the tile, sized for a tab. */\nexport function faviconSvg(): string {\n    return `${markSvg({ variant: 'tile', width: '32' }).replace(/height=\"[^\"]*\"/, 'height=\"32\"')}\\n`;\n}\n\n/** An .ico holding PNG images (every browser and Windows since Vista read these). */\nexport function icoFromPngs(images: ReadonlyArray<{ size: number; png: Uint8Array }>): Uint8Array {\n    const header = 6 + 16 * images.length;\n    const total = header + images.reduce((n, i) => n + i.png.length, 0);\n    const out = new Uint8Array(total);\n    const view = new DataView(out.buffer);\n    view.setUint16(2, 1, true); // type: icon\n    view.setUint16(4, images.length, true);\n    let offset = header;\n    images.forEach(({ size, png }, i) => {\n        const at = 6 + 16 * i;\n        view.setUint8(at, size >= 256 ? 0 : size);\n        view.setUint8(at + 1, size >= 256 ? 0 : size);\n        view.setUint16(at + 4, 1, true); // colour planes\n        view.setUint16(at + 6, 32, true); // bits per pixel\n        view.setUint32(at + 8, png.length, true);\n        view.setUint32(at + 12, offset, true);\n        out.set(png, offset);\n        offset += png.length;\n    });\n    return out;\n}\n"]}