Repository navigation
feat: hex color strings for directive color fields - #146
Open
natemoo-re wants to merge 6 commits into
Open
natemoo-re wants to merge 6 commits into
natemoo-re wants to merge 6 commits into
Conversation
… capability Full-screen frames wrap in BSU/ESU when RuntimeCapabilities.syncOutput is true; the flag rides reduce() per frame so a capability flip takes effect on the next rendered frame with no invalidation signal. Zero-diff frames emit zero bytes even when wrapped, and line mode is never wrapped. Renderer-spec 7.9 discharges the deferral recorded in 7.8.
Color fields (open bg, border color/bg, border side color/bg, text
color/bg) accept a hex color string in addition to the packed ARGB
number. Hex grammar: '#' + exactly 3/4/6/8 hex digits, case-insensitive;
3/4-digit forms double each digit; missing alpha defaults to 255.
Conversion happens at the transfer-encoding boundary — hex strings never
appear on the wire; packed values are bit-identical to the equivalent
rgba() result. Invalid hex is invalid directive input: validate()
reports it and the packer MUST throw a TypeError before producing bytes.
Static types stay number | string; directive constructors check string
literals against the grammar at compile time (the TS equivalent of
#${string{3,4,6,8}}), reserving room for full CSS Color 4 syntax later.
Color fields (open bg, border color/bg, border side color/bg, text color/bg) accept '#RGB', '#RGBA', '#RRGGBB', and '#RRGGBBAA' alongside packed ARGB numbers. colorValue() expands strings at the transfer- encoding boundary (RRGGBBAA digit order -> AARRGGBB word layout, 3/4- digit forms double each digit, missing alpha = 255); the wire format and the C renderer are untouched. Directive constructors type-check string literals against the grammar via per-character recursion — a flat template union is unrepresentable (TS2590) at 6/8 digits — while computed strings pass through and are checked normatively by validate() and the packer. Invalid hex throws TypeError before any bytes are produced.
Contributor
Changeset suggestionThe current changeset no longer matches this PR. This review contains a corrected replacement. Why: Changeset should start with an approved active present-tense verb. Changeset package scope does not match the affected packages confidently. Changeset contains unsupported consumer-facing claims. View the proposed changeset---
'@bomb.sh/tty': minor
---
Adds CSS color string support to all directive color fields.
`open({ bg })`, `border.color`, `border.bg`, per-side `color`/`bg`, and `text({ color, bg })` now accept CSS color strings alongside packed ARGB numbers from `rgba()`. Accepted forms: hex (`#f80`, `#ff8800aa`), named colors (`rebeccapurple`, `transparent`), and `rgb()`, `rgba()`, `hsl()`, `hsla()`, `hwb()`, `lab()`, `lch()`, `oklab()`, and `oklch()`. Strings resolve to sRGB at the transfer-encoding boundary; the wire format, snapshots, and renderer are unchanged. Out-of-gamut colors clip per channel.
Invalid strings are caught at every layer: string literals are rejected at compile time by `open()` and `text()`, `validate()` rejects them as invalid field values, and `pack()` throws a `TypeError` before producing any bytes.
#### Migration
The `Color` type is new — color fields that previously accepted only `number` now accept `number | string`. Passing a plain `number` continues to work without any change.
```diff
- open("box", { bg: rgba(255, 136, 0) })
+ open("box", { bg: "#ff8800" }) // string form, or keep the rgba() call
open("box", { bg: rgba(255, 136, 0) }) // unchanged — numbers still work
```
If you pass color values typed as `string` at runtime, `validate()` and `pack()` will reject strings that do not match the CSS color grammar. Ensure any dynamically constructed color strings are valid before passing them to a directive.Review this changeset manually If this draft is correct, react with 🚀 and Cooper will commit it to this branch. |
|
Size Increased — +3.0 KB 132.4 KB unpacked |
commit: |
natemoo-re
marked this pull request as ready for review
October 12, 2026 01:07
# Conflicts: # .changeset/sync-output-capability.md # src/clayterm.c # src/clayterm.h # term-native.ts # term.ts # test/term.test.ts # test/width.test.ts
Widens the §8.5 string form from hex-only to CSS Color 4: hex, named colors and transparent, rgb()/rgba() and hsl()/hsla() (modern and legacy), hwb(), lab(), lch(), oklab(), oklch(). Strings resolve to sRGB at the transfer-encoding boundary; channels clamp to [0, 255] and round, alpha clamps to [0, 1] and scales to 255. Out-of-gamut colors clip per channel with no perceptual gamut mapping. Hex results stay bit-identical to the previous grammar, and the wire format is unchanged. color(), color-mix(), relative color syntax, and device-cmyk() are invalid. System colors and currentcolor are reserved: system colors will map to the themable ANSI 16-color palette, which packed sRGB cannot express, so both are specified separately. Static checking extends to named-color literals and function-name prefixes; function arguments are checked at runtime only.
Color strings now resolve through hueful's parse() + convert() instead
of the hand-rolled hex expander. A new internal color.ts owns
resolveColor(), shared by the packer (colorValue in ops.ts) and
validate(), which swaps its hex regex for a TypeBox "css-color" format
backed by the same resolver, so the two can't drift.
hueful returns unclamped sRGB for wide-gamut spaces, so each channel and
alpha clamps to [0, 1] before scaling to a byte; this is the §8.5
per-channel clip. hueful also parses device-cmyk(), which §8.5 excludes,
so the cmyk space is rejected explicitly. System colors and currentcolor
aren't in hueful's name table and fall out as invalid with no extra code.
Literal checking keeps the per-character hex recursion and adds two
branches: literals containing "(" must lowercase to a supported
function prefix, and anything else must lowercase to a key of hueful's
names export (or "transparent"). hueful becomes a runtime dependency of
the npm package; dnt maps the npm: import into package.json.
| @@ -0,0 +1,14 @@ | |||
| --- | |||
Contributor
There was a problem hiding this comment.
Changeset needs revision.
Changeset should start with an approved active present-tense verb. Changeset package scope does not match the affected packages confidently. Changeset contains unsupported consumer-facing claims.
View the proposed replacement
---
'@bomb.sh/tty': minor
---
Adds CSS color string support to all directive color fields.
`open({ bg })`, `border.color`, `border.bg`, per-side `color`/`bg`, and `text({ color, bg })` now accept CSS color strings alongside packed ARGB numbers from `rgba()`. Accepted forms: hex (`#f80`, `#ff8800aa`), named colors (`rebeccapurple`, `transparent`), and `rgb()`, `rgba()`, `hsl()`, `hsla()`, `hwb()`, `lab()`, `lch()`, `oklab()`, and `oklch()`. Strings resolve to sRGB at the transfer-encoding boundary; the wire format, snapshots, and renderer are unchanged. Out-of-gamut colors clip per channel.
Invalid strings are caught at every layer: string literals are rejected at compile time by `open()` and `text()`, `validate()` rejects them as invalid field values, and `pack()` throws a `TypeError` before producing any bytes.
#### Migration
The `Color` type is new — color fields that previously accepted only `number` now accept `number | string`. Passing a plain `number` continues to work without any change.
```diff
- open("box", { bg: rgba(255, 136, 0) })
+ open("box", { bg: "#ff8800" }) // string form, or keep the rgba() call
open("box", { bg: rgba(255, 136, 0) }) // unchanged — numbers still work
```
If you pass color values typed as `string` at runtime, `validate()` and `pack()` will reject strings that do not match the CSS color grammar. Ensure any dynamically constructed color strings are valid before passing them to a directive.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #139.
Implements support for CSS-styled hex color strings alongside
rgba(). There's no C or wire format change, hex values are expanded to theirrgba()equivalent atpack()time.Supported hex grammar is
#RGBdexpands asd×17(#f80→#ff8800)#RGBA#f80a→#ff8800aa)#RRGGBB#RRGGBBAA