import type { VNode } from 'preact'; /** * Something that can be embedded as the inner content of an SVG element: * - string: raw SVG markup (used by the .gg resolver) * - VNode: a Preact virtual DOM node built via h() * - number: coerced to string * - null / undefined / false: nothing rendered * * Arrays of the above are accepted too (flattened by the renderer). */ export type SvgFragment = string | number | VNode | null | undefined | false | SvgFragment[]; /** One inclusive frame range `[min, max]`. `max` may be `Infinity`. */ export type FrameRange = readonly [min: number, max: number]; /** * A frame selector — a single frame, or a list where each item is * either a single frame number or an inclusive `[min, max]` range. */ export type FrameSpec = number | ReadonlyArray; /** * Canonical, *internal* grid coordinate — 0-based after normalization. * `{col: 0, row: 0}` corresponds to the user-facing "A1" cell. * * Do not construct GridPos directly in user code; write one of the * user-facing input forms (`GridPosInput`) and let the normalizer * convert it. `col` / `row` are kept as plain numbers so layout math * stays index-friendly. */ export interface GridPos { /** 0-based column index (0 .. columns-1) */ col: number; /** 0-based row index (0 .. rows-1) */ row: number; } /** * User-facing input for a coordinate. Accepts: * - A1 string `"A1"` / `"aa100"` — case-insensitive; preferred * - tuple `[1, 1]` — 1-based (col, row) * - named object `{ col: 1, row: 1 }` — 1-based * * A1 = column 1, row 1 = top-left. All forms are normalized to the * internal 0-based `GridPos` before any rendering runs. */ export type GridPosInput = { col: number; row: number; } | readonly [col: number, row: number] | string; /** * A rectangular region spanning multiple grid cells. * Uses top-left (inclusive) and bottom-right (inclusive) corners. */ export interface GridSpan { from: GridPosInput; to: GridPosInput; } export interface DiagramTheme { /** Default color for node rings and their icons via currentColor. */ primary: string; /** Default color for connectors. */ secondary: string; /** Accent color for highlights; referenced by name from element color fields. */ accent: string; /** Default color for note text. */ text: string; /** * SVG canvas background. Undefined or 'transparent' → no background * rect is drawn (the SVG renders with a transparent backdrop). */ bg?: string; /** Reserved for muted/secondary text (no default). */ muted?: string; } /** * A color value. Either a CSS color literal ('#e8792f', 'red', 'rgb(...)') * or one of the theme keyword names below — in which case it resolves to * the corresponding DiagramTheme field at render time. */ export type ThemeColorKey = 'primary' | 'secondary' | 'accent' | 'text' | 'muted' | 'bg'; export type BadgePosition = 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left'; export interface NodeBadge { /** React element drawn inside a 24×24 viewBox */ icon: SvgFragment; /** Corner where the badge sits (default: 'top-right') */ position?: BadgePosition; /** Badge diameter as fraction of node diameter (default: 0.3) */ size?: number; /** Override color (cascades via `currentColor`; takes effect when iconTheme = 'theme') */ color?: string; /** * Color treatment (default: 'native'): * - 'native' — the badge's own fill/stroke colors are preserved * - 'theme' — the badge adopts `color` (or the node color) via currentColor */ iconTheme?: 'theme' | 'native'; } export interface NodeDef { id: string; /** * Frames this node belongs to. When omitted the node is part of * every frame; when set, the node only materialises on render calls * whose `frame` matches. Declarations with the same id across * multiple frame-tagged entries are merged (later declaration wins * per field) — useful for "same icon, different label at frame N". */ frames?: FrameSpec; /** * Grid position (column, row) — 0-based. * * When omitted, the position is auto-assigned by walking nodes in * declaration order: col increments along row 0. If `columns` is * specified at the diagram level, auto-positions wrap into the next * row when col reaches `columns`. * * Explicit positions are taken as-is and don't disturb the auto * counter — explicit and auto-positioned nodes can coexist. */ pos?: GridPosInput; /** * The icon asset rendered inside the node's clipping circle/rect. * Accepts a Preact VNode (`h('svg', …)`), a raw SVG string, or — in * the .gg pipeline's pre-resolution stage — the string identifier * (`'tabler/user'`, `'./foo.svg'`, a bare name) that the resolver * later inlines into an SVG fragment. */ src?: SvgFragment; /** * Short text rendered inside the node circle in place of an icon. * When set, the icon (`src`) is suppressed. Multi-line strings split * on `\n`. The text auto-sizes to the largest font that fits both * - height ≤ icon height (`iconSize`) * - bounding box inscribed in the node circle * so the typical use is digits/short labels like `"1"`, `"2"`, `"OK"`. */ text?: string; /** Label shown as a semi-transparent badge overlapping the top of the icon */ label?: SvgFragment; /** * Pin the label direction to one of the 8 placement slots, * bypassing the direction axis of the auto-search. The leader-length * axis is still walked (tier 1 → 2 → 3) unless `leaderLength` is * also set. Accepts the same kebab-case names the placer uses * internally: * 'top-right' | 'bottom-right' | 'bottom-left' | 'top-left' | * 'top-center' | 'bottom-center' | * 'left-center' | 'right-center'. * * In `.gg` source set this via the CSS-style attribute: * `style="label-direction: top-right"`. */ labelDirection?: 'top-right' | 'bottom-right' | 'bottom-left' | 'top-left' | 'top-center' | 'bottom-center' | 'left-center' | 'right-center'; /** * Pin the leader-line length tier (1 = tight, 2 = medium, 3 = long), * bypassing the length axis of the auto-search. Independent of * `labelDirection` — set neither for full auto-search, set one to * filter that axis, or both to fix the placement to a single slot. * If the pinned combination collides with something else, the label * still renders there but the result carries `error: true` and a * `label-collision` diagnostic. * * In `.gg` source: `style="leader-length: 2"`. */ leaderLength?: 1 | 2 | 3; /** Node diameter as absolute fraction of cell size (0–1). Overrides sizeScale when set. */ size?: number; /** Node size multiplier on the default fraction (default: 1). Ignored when `size` is set. */ sizeScale?: number; /** Override color for this node */ color?: string; /** Label font-size multiplier relative to the theme base (default: 1) */ labelScale?: number; /** * How the icon picks its colors: * - 'theme' (default): propagates the node color to the icon via * `currentColor`, so monochrome icons adopt the node's color. * - 'native': leaves the icon's own fill/stroke attributes intact. * Use this for multicolor logos / branded assets. */ iconTheme?: 'theme' | 'native'; /** * How the icon's bounds are clipped: * - 'square' (default): the icon's 24×24 viewport (same as the * node's bounding square) — anything outside is cropped. * - 'circle': clipped to a circle inscribed in the square; useful * for avatar-style raster images so they become round. * - 'none': no clipping; the icon can extend beyond its bounds. * Rarely needed for vector icons; useful for decorative raster * overlays. */ clip?: 'square' | 'circle' | 'none'; /** * Optional badges placed at the node's corners. Accepts: * - a preset name ('check' / 'star' / 'alert' / 'info' / …) * - a preset reference `{ preset, position?, size? }` * - a full NodeBadge for explicit control * * Multiple badges at the same `position` render in declaration order * (earlier = bottom). Presets that need this (e.g. a white disc under * a tabler filled icon) use that stacking internally. */ badges?: import('./badges.js').BadgeSpec[]; /** * Marks the icon as failed to resolve (e.g. a string identifier that * couldn't be looked up in the icon registry). When true and errors * are not suppressed, the icon is hidden and the node ring renders * in the error color so the missing reference is visually obvious. */ iconError?: boolean; } export type ArrowEnd = 'none' | 'start' | 'end' | 'both'; /** * Connector waypoint (canonical, *internal* form — 0-based after * normalization). Unlike GridPos, waypoints allow fractional * coordinates — `{col: 0.5, row: 1}` threads between cell centres. */ export interface WayPoint { col: number; row: number; } /** * User-facing input form for a waypoint. Matches GridPosInput shape but * allows fractional numbers. A1 strings are not accepted here (they * denote whole cells); use a tuple or object for mid-cell routing. * * { col: 1.5, row: 1 } // between columns A and B on row 1 * [1.5, 1] // same, tuple form */ export type WayPointInput = { col: number; row: number; } | readonly [col: number, row: number]; export interface ConnectorDef { /** Optional id used to reference this connector (e.g. from a Note) */ id?: string; /** Frames this connector belongs to. See `NodeDef.frames`. */ frames?: FrameSpec; /** Source node id */ from: string; /** Target node id */ to: string; /** Arrow style (default: 'end') */ arrow?: ArrowEnd; /** Line thickness in px (default: 2) */ strokeWidth?: number; /** Override color */ color?: string; /** Dash pattern (e.g. '6 3') — omit for solid line */ dash?: string; /** Label placed at the midpoint of the connector */ label?: SvgFragment; /** Intermediate waypoints the line passes through */ waypoints?: WayPointInput[]; /** How far from node center to pull back arrow tips (0–1, default: 0.6) */ nodeMargin?: number; /** Label font-size multiplier relative to the theme base (default: 1) */ labelScale?: number; } export interface RegionDef { /** Frames this region belongs to. See `NodeDef.frames`. */ frames?: FrameSpec; /** Grid cells to fill — can be multiple spans for L-shapes etc. */ spans: GridSpan[]; /** Background color (with alpha for semi-transparency) */ color: string; /** Optional label for the region */ label?: SvgFragment; /** Border radius in px (default: auto) */ borderRadius?: number; /** Label font-size multiplier relative to the theme base (default: 1) */ labelScale?: number; } export interface NoteDef { /** Frames this note belongs to. See `NodeDef.frames`. */ frames?: FrameSpec; /** Grid position — the note consumes this single cell */ pos: GridPosInput; /** Text content. `\n` makes an explicit line break; long lines wrap within the cell width. */ text: string; /** Ids of nodes or connectors to draw unconditional leader lines to */ targets?: string[]; /** Background color (default: #ffffff) */ bg?: string; /** Border and text color (default: theme.text) */ color?: string; /** Font-size multiplier relative to the theme base (default: 1) */ labelScale?: number; } /** * Frame-scoped settings override (the .gg `doc [N] { … }` form). When * `resolveFrame(def, frame)` runs, each override whose `frames` * includes the current frame is deep-merged into the base settings * on top of the frames-less `doc { … }` block. */ export interface FrameDocOverride { frames: FrameSpec; settings: Omit; } export interface DiagramDef { /** Pixel size of one grid cell in the internal SVG coordinate space (default: 256) */ cellSize?: number; /** Padding inside the SVG in px (default: scaled from cellSize) */ padding?: number; /** Number of columns. Default: inferred from the largest node `pos.col` (+1). */ columns?: number; /** Number of rows. Default: inferred from the largest node `pos.row` (+1). */ rows?: number; /** Color theme */ theme?: DiagramTheme; /** Background regions (rendered first, behind everything) */ regions?: RegionDef[]; /** Nodes */ nodes: NodeDef[]; /** Connectors between nodes */ connectors?: ConnectorDef[]; /** Annotation notes with leader lines */ notes?: NoteDef[]; /** * Frame-scoped settings overrides. Populated by the parser from * `doc [N] { … }` statements (or supplied directly in the TS API) * and collapsed into the base settings by `resolveFrame`. */ frameOverrides?: FrameDocOverride[]; } /** NodeDef after coordinate normalization + auto-position fill. */ export interface NormalizedNodeDef extends Omit { pos: GridPos; } /** ConnectorDef after waypoint normalization. */ export interface NormalizedConnectorDef extends Omit { waypoints?: WayPoint[]; } /** NoteDef after position normalization. */ export interface NormalizedNoteDef extends Omit { pos: GridPos; } /** A canonical grid span — both endpoints in 0-based object form. */ export interface NormalizedGridSpan { from: GridPos; to: GridPos; } /** RegionDef with every span endpoint normalized. */ export interface NormalizedRegionDef extends Omit { spans: NormalizedGridSpan[]; } /** DiagramDef with every element normalized. */ export interface NormalizedDiagramDef extends Omit { nodes: NormalizedNodeDef[]; connectors?: NormalizedConnectorDef[]; notes?: NormalizedNoteDef[]; regions?: NormalizedRegionDef[]; } //# sourceMappingURL=types.d.ts.map