NAME
====

Selkie::BorderStyle - Box-drawing glyph sets and title alignment for framed widgets

SYNOPSIS
========

```raku
use Selkie::BorderStyle;
use Selkie::Widget::Border;

# Pick a stock glyph set by kind.
my $panel = Selkie::Widget::Border.new(
    title        => 'Characters',
    border-style => BorderRounded,
    title-align  => TitleCenter,
);

# Or hand it a bespoke glyph table.
my $dashed = Selkie::BorderStyle::BorderGlyphs.new(
    top-left     => '.', top-right    => '.',
    bottom-left  => "'", bottom-right => "'",
    horizontal   => '-', vertical     => ':',
);
$panel.set-border-glyphs($dashed);
```

DESCRIPTION
===========

Two enums and a value class, shared by every widget that paints a frame.

`BorderKind` names the five stock glyph sets; `BorderGlyphs` is the six-glyph table one of those names resolves to (or that you build yourself); `TitleAlign` says where a title sits along its edge.

The glyph tables, in `top-left top-right bottom-left bottom-right horizontal vertical` order:

    BorderSingle    ┌ ┐ └ ┘ ─ │      ┌────────┐
    BorderRounded   ╭ ╮ ╰ ╯ ─ │      │ single │
    BorderDouble    ╔ ╗ ╚ ╝ ═ ║      └────────┘
    BorderHeavy     ┏ ┓ ┗ ┛ ━ ┃
    BorderAscii     + + + + - |      ╭────────╮
                                     │rounded │
                                     ╰────────╯

No automatic downgrade
----------------------

Selkie never inspects the locale, `TERM`, or the terminal's reported capabilities to swap a Unicode glyph set for an ASCII one. Auto-downgrade would make rendering — and therefore snapshot tests — depend on the environment the process happens to run in, which is exactly the class of bug snapshot tests exist to catch.

`BorderAscii` is the escape hatch. If your app must run somewhere the box-drawing block isn't available, decide that yourself (a config flag, a `--ascii` switch, a `%*ENV` probe you own) and pass `BorderAscii`:

```raku
my $kind = %*ENV<MYAPP_ASCII> ?? BorderAscii !! BorderRounded;
Selkie::Widget::Border.new(:title('Log'), border-style => $kind);
```

Custom glyph tables
-------------------

Every glyph is a `Str`, not a codepoint, so multi-codepoint clusters work. Keep each one a single *column* wide though — the frame painter assumes one cell per glyph, and a double-width glyph (CJK, most emoji) will push the frame out of alignment. Emitting a run of `cols - 2` horizontals is a single `putstr`, so a wide horizontal glyph overflows the right corner rather than being clipped.

EXAMPLES
========

Resolving a kind to its table
-----------------------------

```raku
my $g = Selkie::BorderStyle::BorderGlyphs.for(BorderDouble);
say $g.top-left;      # ╔
say $g.horizontal;    # ═

# Resolution is cached — the same kind always returns the same object.
say BorderGlyphs.for(BorderDouble) === BorderGlyphs.for(BorderDouble);  # True
```

Deriving a table from a stock one
---------------------------------

`BorderGlyphs` is immutable; `clone` is the way to vary one glyph.

```raku
my $studded = BorderGlyphs.for(BorderSingle).clone(
    top-left => '◤', top-right => '◥',
);
```

Aligning titles
---------------

```raku
$panel.set-title-align(TitleCenter);
$panel.set-bottom-title('↑/↓ scroll  q quit');
$panel.set-bottom-title-align(TitleRight);
```

SEE ALSO
========

  * [Selkie::Widget::Border](Selkie--Widget--Border.md) — the widget that consumes all of this

  * [Selkie::Theme](Selkie--Theme.md) — `border` / `border-focused` slots pick the frame's *colours*; the glyph set is orthogonal



The five stock box-drawing glyph sets. `BorderSingle` is the default everywhere and the only one that was available before Selkie 0.11. `BorderRounded` is the same weight with arc corners. `BorderDouble` and `BorderHeavy` read as emphasis. `BorderAscii` uses nothing outside 7-bit ASCII and is the manual escape hatch for terminals or fonts without the box-drawing block — Selkie never selects it for you (see the module Pod).



Where a title sits along the edge it's drawn on. `TitleLeft` is the historical (and default) placement: two columns in from the left corner. `TitleCenter` centres the decorated title across the full width. `TitleRight` ends it two columns short of the right corner. All three are clamped so the corner glyphs are never overwritten.

class Selkie::BorderStyle::BorderGlyphs
---------------------------------------

The six glyphs it takes to paint a box: four corners, one horizontal, one vertical. Build one with `.for(BorderKind)` for a stock set, `.new` for a bespoke table, or `.clone` off a stock set to vary a glyph or two. Instances are immutable value objects and safe to share between widgets.

### has Str:D $.top-left

Top-left corner glyph, e.g. `┌`.

### has Str:D $.top-right

Top-right corner glyph, e.g. `┐`.

### has Str:D $.bottom-left

Bottom-left corner glyph, e.g. `└`.

### has Str:D $.bottom-right

Bottom-right corner glyph, e.g. `┘`.

### has Str:D $.horizontal

Glyph tiled along the top and bottom edges, e.g. `─`.

### has Str:D $.vertical

Glyph drawn down the left and right edges, e.g. `│`.

### method single

```raku
method single() returns Selkie::BorderStyle::BorderGlyphs:D
```

The `┌┐└┘─│` set. Selkie's default, and byte-identical to what `Border` painted before glyph sets existed.

### method rounded

```raku
method rounded() returns Selkie::BorderStyle::BorderGlyphs:D
```

The `╭╮╰╯─│` set — single-weight edges, arc corners.

### method double

```raku
method double() returns Selkie::BorderStyle::BorderGlyphs:D
```

The `╔╗╚╝═║` set — double-ruled edges.

### method heavy

```raku
method heavy() returns Selkie::BorderStyle::BorderGlyphs:D
```

The `┏┓┗┛━┃` set — heavy-weight edges.

### method ascii

```raku
method ascii() returns Selkie::BorderStyle::BorderGlyphs:D
```

The `+ + + + - |` set — 7-bit ASCII only.

### method for

```raku
method for(
    BorderKind:D $kind
) returns Selkie::BorderStyle::BorderGlyphs:D
```

Resolve a `BorderKind` to its glyph table. Cached: the same kind always yields the very same object, so callers can compare with `===` and render loops don't allocate.

