import * as React from "react"; export type LogoSize = "xs" | "sm" | "md" | "lg"; export type LogoTone = "primary" | "success"; export type LogoMark = "glyph" | "godx" | "godx-lockup"; export interface LogoProps extends Omit, "children"> { /** * The brand glyph — a short mark (a letter/initials, default `"g"`) or a custom node such as an * inline ``. Keep it to 1–2 glyphs; the box is square and centres its content. * * A STRING is classified by the ink band it occupies (`g` x-height→descender, `GX` cap→baseline, * `神` the full em box) and optically centred for that band — a line box is not a letterform, and * the classes' centres are 0.21em apart. Any other node is left alone. Retune a band, or pin one * mark, with the `--logo-glyph-*-optical-offset` tokens. * * A string is also FITTED to the box: two full-width forms want ~2em against a box sized for * roughly one, so `東京` at `xs` is SET SMALLER rather than wrapping. The mark is always one * line. Retune how much of the box a fitted glyph may take with `--logo-glyph-fit-max-width`. */ glyph?: React.ReactNode; /** * Semantic mark artwork. `"godx"` renders the canonical GoDX identity mark as an inline vector; * `"glyph"` preserves the configurable boxed-glyph treatment. */ mark?: LogoMark; /** * Box size tier (tokenised), applied to EVERY mark. The boxed glyph reads `--logo-size-*` * (default `md` = 1.75rem); `mark="godx"` reads its own `--logo-godx-size-*` scale (default `md` * = 2rem — the identity artwork is a capsule in a square viewBox and needs slightly more box to * read at the same optical weight). */ size?: LogoSize; /** * Semantic fill role. `"success"` provides the canonical green identity mark without changing * the application's primary action colour. */ tone?: LogoTone; /** * Readable product name rendered BESIDE the mark as one lockup. Pass the localized product name * (a string, or a node when the name needs its own markup). */ wordmark?: React.ReactNode; /** * The PRODUCT name that follows the brand, set off by the lockup's own rule — "GoDX | ID", * "GoDX | Console", "GoDX | Admin" (gh#649). Pass the localized product name; it renders after * `wordmark` when both are set. * * It is TEXT, in the lockup's own type scale, not artwork. The kit's flattened "GoDX | ID" file * is a SECOND master (`0 0 1234 242` against this package's `30 30 871.29 182`) with its own * hardcoded ink, its own global `id="title"`/`id="desc"` and a `#C5C8D6` rule; drawing the * suffix would mean one more of those, one more dark variant and one more release per product * name, and no localization at all. The brand's own construction — the G, the arrow, the "GoDX" * logotype — stays untouched inside `mark="godx-lockup"`; a product name is not part of it. * * The rule's colour/width/height and the gap around it are `--logo-divider-*` / * `--logo-product-suffix-*` tokens, so a service retunes them once rather than per page. */ productSuffix?: React.ReactNode; /** * Accessible name for the mark. When set, the logo is exposed to assistive tech as an image with * this name; when omitted the mark is decorative (`aria-hidden`) — the correct default when a * readable wordmark sits beside it. */ label?: string; /** * Mượn thẻ của con làm GỐC của logo thay vì dựng `` — cách để cả cái logo trở thành một * LIÊN KẾT (``, hay `` của router). * * Vì sao cần một prop chứ không phải bọc ngoài: `.ui-logo-lockup` là `display: inline-flex`, nên * bọc nó trong một `` thường (`display: inline`) đặt lockup lên một line box và phần descender * của strut đội thêm vài px vào ô mark — logo bị nhích lên trong thanh trên. Consumer chỉ còn * cách viết `className="flex"` lên thẻ ``, thứ `ui-audit` chặn đúng theo luật * `no-utility-layout` (đo ở godx-chat, 08/09/2026). Với `asChild`, chính thẻ của consumer MANG * `.ui-logo-lockup`, nên không còn phần tử trung gian nào để canh. * * Đúng MỘT con, và ruột của nó bị bỏ qua: nội dung của logo vẫn do `glyph`/`mark`/`wordmark` * quyết định. */ asChild?: boolean; /** Chỉ dùng cùng `asChild`: đúng một phần tử để đi mượn. */ children?: React.ReactNode; } /** * The band the glyph's ink actually occupies, as the (top edge, bottom edge) of the UNION of every * character in the string — `"GX"` is cap→baseline, `"gX"` is cap→descender. */ export type LogoGlyphInk = "cap-baseline" | "cap-descender" | "x-baseline" | "x-descender"; /** * Classify a glyph for optical centring. Pure, no layout read, no measurement — the component is * the only layer that can do this at all, because CSS cannot see which character is in the box. * Returns `undefined` for a non-string glyph (an inline ``, any other node) and for an empty * string: those are not classified and keep the neutral default rather than being guessed at. */ export declare function logoGlyphInk(glyph: React.ReactNode): LogoGlyphInk | undefined; /** * How much INLINE space the glyph string wants, as counts of the four advance classes — the fact * `.ui-logo-glyph`'s fit cap is computed from (gh#377). `fullwidth` is the characters that occupy * a whole em; `wide` is the proportional forms that REACH that em (`M W m`); `space` is the runs * of collapsible white space the paint keeps; `narrow` is everything else. * * The contract is that the FITTED font-size times the PAINTED advance stays inside the box, at * every tier, on every bundled face. Over-stating an advance only sets the mark a little smaller * than it had to be; under-stating it puts the mark outside its own box, which is the defect * these classes exist to remove. */ export interface LogoGlyphAdvance { fullwidth: number; wide: number; narrow: number; space: number; } /** * Count a glyph string's characters by advance class. Pure, no layout read, no measurement — the * component is the only layer that can do this, because CSS cannot see which characters are in the * box. Returns `undefined` for a non-string glyph and for an empty string, exactly like * `logoGlyphInk`: those are not classified and keep the neutral default rather than being guessed * at. Iterates code points, so a surrogate pair (CJK Extension B) counts once. * * WHITE SPACE IS COUNTED, NOT DROPPED. `.ui-logo-glyph` sets `white-space: nowrap`, which stops * the mark wrapping but still PAINTS an interior space — measured 0.198em (system) to 0.333em * (Hiragino Sans) — so a string whose space was dropped from the count was fitted to an advance * narrower than the one that reached the screen (`東 京` spilled 2.63px at `md`). CSS's own * processing is mirrored exactly: leading and trailing runs are trimmed away, and an interior run * of any length collapses to ONE space (both verified in Chromium against the shipped `nowrap`). */ export declare function logoGlyphAdvance(glyph: React.ReactNode): LogoGlyphAdvance | undefined; /** * Logo — the product brand-mark box: a glyph on the primary fill, or (with `wordmark`) the full * mark + wordmark LOCKUP. Size, radius, per-tier font-size, the wordmark's * face/weight/tracking/colour and the mark↔wordmark gap are all tokens. */ export declare const Logo: React.ForwardRefExoticComponent>;