@kud/ink-ui 0.17.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md CHANGED
@@ -79,6 +79,13 @@ import { colors, spacing } from "@kud/ink-ui"
79
79
  A literal like `color="orange"` or `color="#FF8C00"` is wrong even when it
80
80
  renders identically — it breaks the moment a token moves.
81
81
 
82
+ The one exception is `<Pill color>`, for a surface mirroring an external
83
+ system whose colours ARE its vocabulary — GitHub's merged purple, a CI
84
+ provider's result colours. The test is whether the hue is a **fact about the
85
+ thing being labelled**; a colour picked because it looks right is still a token
86
+ job. The pill inks itself against whatever fill it is given, so a caller reaching
87
+ for this never picks a foreground.
88
+
82
89
  **State is never signalled by colour alone.** Every status carries a shape, a
83
90
  glyph or a weight as well, because a colourblind reader cannot see the hue and
84
91
  a piped terminal has no colour at all. `SelectableRow` marks the active row
package/dist/index.d.ts CHANGED
@@ -19,16 +19,26 @@ type PillVariant = "success" | "error" | "warning" | "info" | "accent" | "muted"
19
19
  type PillProps = {
20
20
  children: string;
21
21
  variant?: PillVariant;
22
+ /**
23
+ * An explicit fill, for a caller that owns a palette of its own — one
24
+ * mirroring an external system whose colours ARE the vocabulary (GitHub's
25
+ * merged purple, a CI provider's result colours). Overrides `variant`.
26
+ *
27
+ * Not a way round the token rule. A colour picked because it looks nice is
28
+ * still wrong here; the test is whether the hue is a fact about the thing
29
+ * being labelled rather than a preference about the label.
30
+ */
31
+ color?: string;
22
32
  };
23
33
  /**
24
- * A filled, rounded label — a category the thing belongs to, not a status it is
25
- * in.
34
+ * A filled, rounded label — a category the thing belongs to, or an event that
35
+ * has just happened to it.
26
36
  *
27
- * Reach for it when the word IS the information (`epic`, `draft`, `blocked`) and
28
- * you want it to read as one object rather than as more prose. For a reference
29
- * the reader is meant to follow — a ticket key, a repo — leave the text dim: a
30
- * fill gives a breadcrumb a weight it has not earned, and once everything is a
31
- * pill none of them is.
37
+ * Reach for it when the word IS the information (`epic`, `draft`, `blocked`,
38
+ * `NEW`) and you want it to read as one object rather than as more prose. For a
39
+ * reference the reader is meant to follow — a ticket key, a repo — leave the
40
+ * text dim: a fill gives a breadcrumb a weight it has not earned, and once
41
+ * everything is a pill none of them is.
32
42
  *
33
43
  * The WORD carries the meaning and the colour only reinforces it, so a pill
34
44
  * survives being read in monochrome, piped, or by someone who cannot separate
@@ -43,7 +53,7 @@ type PillProps = {
43
53
  * `NO_COLOR` is the one case that does fall back to brackets: with the fill
44
54
  * stripped, the caps would be drawing the outline of a pill that is not there.
45
55
  */
46
- declare const Pill: ({ children, variant }: PillProps) => React__default.JSX.Element;
56
+ declare const Pill: ({ children, variant, color }: PillProps) => React__default.JSX.Element;
47
57
  /**
48
58
  * How many columns `<Pill>` occupies for `text` — the label plus its two caps.
49
59
  *
package/dist/index.js CHANGED
@@ -55,8 +55,19 @@ var INK = {
55
55
  accent: "black",
56
56
  muted: "white"
57
57
  };
58
- var Pill = ({ children, variant = "muted" }) => {
59
- const fill = FILL[variant];
58
+ var inkFor = (fill) => {
59
+ const hex = /^#([0-9a-f]{6})$/i.exec(fill)?.[1];
60
+ if (!hex) return "white";
61
+ const channel = (i) => {
62
+ const c = parseInt(hex.slice(i, i + 2), 16) / 255;
63
+ return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
64
+ };
65
+ const luminance = 0.2126 * channel(0) + 0.7152 * channel(2) + 0.0722 * channel(4);
66
+ return (luminance + 0.05) / 0.05 >= 1.05 / (luminance + 0.05) ? "black" : "white";
67
+ };
68
+ var Pill = ({ children, variant = "muted", color }) => {
69
+ const fill = color ?? FILL[variant];
70
+ const ink = color ? inkFor(color) : INK[variant];
60
71
  if (process.env["NO_COLOR"]) return /* @__PURE__ */ jsxs(Text, { color: fill, children: [
61
72
  "[",
62
73
  children,
@@ -64,7 +75,7 @@ var Pill = ({ children, variant = "muted" }) => {
64
75
  ] });
65
76
  return /* @__PURE__ */ jsxs(Text, { children: [
66
77
  /* @__PURE__ */ jsx(Text, { color: fill, children: glyphs.plCapLeft }),
67
- /* @__PURE__ */ jsx(Text, { backgroundColor: fill, color: INK[variant], children }),
78
+ /* @__PURE__ */ jsx(Text, { backgroundColor: fill, color: ink, children }),
68
79
  /* @__PURE__ */ jsx(Text, { color: fill, children: glyphs.plCapRight })
69
80
  ] });
70
81
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kud/ink-ui",
3
- "version": "0.17.0",
3
+ "version": "0.18.0",
4
4
  "description": "React component library for Ink CLIs",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",