@textui/core 0.7.0 → 0.8.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.
@@ -1,12 +1,39 @@
1
1
  import type { Color } from './cells.js';
2
2
  import type { EdgeSpec } from './geometry.js';
3
3
  /**
4
- * Semantic theme tokens. A component names a role, never a colour - which is
5
- * what lets one catalog render the same under a light theme, a dark theme and
6
- * a 16-colour ssh session.
4
+ * Semantic theme tokens, split by the channel each one is written in.
5
+ *
6
+ * A component names a role, never a colour - which is what lets one catalog
7
+ * render the same under a light theme, a dark theme and a 16-colour ssh
8
+ * session. The role is not enough on its own, though: a token also has to be
9
+ * somewhere it can actually be drawn. `canvas` is a fill, `onAccent` is
10
+ * writing, `borderStrong` is a rule - and one union for all three is what let
11
+ * `fg: 'canvas'` and `border: 'onAccent'` compile, to be found by somebody
12
+ * looking at a frame.
13
+ *
14
+ * So each token is listed under the channels it may appear in, and `Style`
15
+ * takes the matching one. A token may appear in more than one - the tones are
16
+ * both a fill and a colour of their own - and a literal colour is the shared
17
+ * escape out of all three.
18
+ *
19
+ * A token missing from a list is a token that channel cannot use. Adding one
20
+ * is a decision about where it reads, not a convenience.
7
21
  */
8
- export type ColorToken = 'canvas' | 'surface' | 'surfaceAlt' | 'overlay' | 'border' | 'borderStrong' | 'borderSubtle' | 'text' | 'muted' | 'subtle' | 'inverted' | 'accent' | 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info' | 'onDefault' | 'onMuted' | 'onAccent' | 'onPrimary' | 'onSecondary' | 'onSuccess' | 'onWarning' | 'onDanger' | 'onInfo' | 'hover' | 'active' | 'selected' | 'focus' | 'disabled' | 'scrim' | 'cursor' | 'shadow' | 'divider';
9
- /** Anywhere a colour is accepted, a semantic token is accepted too. */
22
+ /** Colours a cell's foreground may be. */
23
+ export type FgColorToken = 'accent' | 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info' | 'hover' | 'active' | 'selected' | 'focus' | 'disabled' | 'text' | 'muted' | 'subtle' | 'inverted' | 'borderSubtle' | 'cursor' | 'onDefault' | 'onMuted' | 'onAccent' | 'onPrimary' | 'onSecondary' | 'onSuccess' | 'onWarning' | 'onDanger' | 'onInfo' | 'onSelected' | 'onActive';
24
+ /** Colours a cell's background may be. */
25
+ export type BgColorToken = 'canvas' | 'surface' | 'surfaceAlt' | 'overlay' | 'hover' | 'active' | 'selected' | 'focus' | 'disabled' | 'accent' | 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info' | 'scrim' | 'cursor' | 'shadow';
26
+ /** Colours a rule may be. */
27
+ export type BorderColorToken = 'border' | 'borderStrong' | 'borderSubtle' | 'divider' | 'accent' | 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info' | 'hover' | 'focus' | 'muted' | 'subtle';
28
+ /** Every token, for the places that take a colour without saying which. */
29
+ export type ColorToken = FgColorToken | BgColorToken | BorderColorToken;
30
+ /** A foreground: an `FgColorToken`, or a literal colour. */
31
+ export type FgColor = FgColorToken | Color;
32
+ /** A background: a `BgColorToken`, or a literal colour. */
33
+ export type BgColor = BgColorToken | Color;
34
+ /** A rule: a `BorderColorToken`, or a literal colour. */
35
+ export type BorderColor = BorderColorToken | Color;
36
+ /** Anywhere a colour is accepted, any token and any literal are accepted too. */
10
37
  export type StyleColor = ColorToken | Color;
11
38
  export type Dimension = number | `${number}%` | 'auto';
12
39
  export type BorderStyle = 'none' | 'single' | 'double' | 'round' | 'bold' | 'dashed' | 'ascii' | 'thick' | 'half';
@@ -62,14 +89,14 @@ export type BorderSides = {
62
89
  };
63
90
  /** A colour per edge. Unnamed edges fall back to the border's `color`. */
64
91
  export type BorderColors = {
65
- top?: StyleColor;
66
- right?: StyleColor;
67
- bottom?: StyleColor;
68
- left?: StyleColor;
92
+ top?: BorderColor;
93
+ right?: BorderColor;
94
+ bottom?: BorderColor;
95
+ left?: BorderColor;
69
96
  };
70
97
  export type BorderSpec = BorderStyle | {
71
98
  style?: BorderStyle;
72
- color?: StyleColor;
99
+ color?: BorderColor;
73
100
  /**
74
101
  * Per-edge colour, over `color`. A corner belongs to the edge that runs
75
102
  * through it - the top rule owns both top corners - because a cell holds
@@ -111,7 +138,7 @@ export interface Style {
111
138
  * but stays legible, rather than being replaced by a rectangle of nothing.
112
139
  * `true` uses the theme's `scrim` token; a number sets the strength.
113
140
  */
114
- scrim?: boolean | StyleColor;
141
+ scrim?: boolean | BgColor;
115
142
  scrimStrength?: number;
116
143
  display?: 'flex' | 'none';
117
144
  direction?: 'row' | 'column';
@@ -160,8 +187,8 @@ export interface Style {
160
187
  overflowX?: Overflow;
161
188
  /** Overrides `overflow` downwards. The usual scroll container. */
162
189
  overflowY?: Overflow;
163
- fg?: StyleColor;
164
- bg?: StyleColor;
190
+ fg?: FgColor;
191
+ bg?: BgColor;
165
192
  bold?: boolean;
166
193
  dim?: boolean;
167
194
  italic?: boolean;
@@ -175,15 +202,27 @@ export interface Style {
175
202
  /** Character painted into empty cells of this box. */
176
203
  fill?: string;
177
204
  }
178
- /** Styles selected by interaction state. Merged over the base in this order. */
205
+ /**
206
+ * Styles selected by interaction state. Merged over the base in this order.
207
+ *
208
+ * `selected` is "this is the current one"; `focus` is "and the keyboard is
209
+ * here", so a row that has both wears `focus` and a row that has only the
210
+ * first wears the dimmer `selected`. They are separate names because they
211
+ * were the same word once - `active` meant both the unfocused selection here
212
+ * and the pressed state in `InteractionState` - and a token that meant two
213
+ * things could be filled with either and looked wrong half the time.
214
+ */
179
215
  export interface StatefulStyle {
180
216
  base?: Style;
181
217
  focus?: Style;
182
218
  hover?: Style;
219
+ /** Pressed. Never a selection. */
183
220
  active?: Style;
184
221
  selected?: Style;
185
222
  disabled?: Style;
186
223
  }
224
+ /** The states, in the order the last one wins. The shared vocabulary. */
225
+ export type StateName = 'selected' | 'hover' | 'active' | 'focus' | 'disabled';
187
226
  export type StyleInput = Style | StatefulStyle | (Style | StatefulStyle | undefined | false)[];
188
227
  /** Global semantic variants, available to every component that opts in. */
189
228
  export type SemanticVariant = 'default' | 'primary' | 'secondary' | 'accent' | 'success' | 'warning' | 'danger' | 'info' | 'muted';
@@ -1 +1 @@
1
- {"version":3,"file":"style.d.ts","sourceRoot":"","sources":["../../src/types/style.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"style.d.ts","sourceRoot":"","sources":["../../src/types/style.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C;;;;;;;;;;;;;;;;;;GAkBG;AAEH,0CAA0C;AAC1C,MAAM,MAAM,YAAY,GAEpB,QAAQ,GAAG,SAAS,GAAG,WAAW,GAClC,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,GAGzC,OAAO,GAAG,QAAQ,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,GACtD,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,GAExC,cAAc,GAId,QAAQ,GACR,WAAW,GAAG,SAAS,GACvB,UAAU,GAAG,WAAW,GAAG,aAAa,GACxC,WAAW,GAAG,WAAW,GAAG,UAAU,GAAG,QAAQ,GACjD,YAAY,GAAG,UAAU,CAAC;AAE9B,0CAA0C;AAC1C,MAAM,MAAM,YAAY,GACpB,QAAQ,GAAG,SAAS,GAAG,YAAY,GAAG,SAAS,GAC/C,OAAO,GAAG,QAAQ,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,GACtD,QAAQ,GAAG,SAAS,GAAG,WAAW,GAClC,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,GAEzC,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAElC,6BAA6B;AAC7B,MAAM,MAAM,gBAAgB,GACxB,QAAQ,GAAG,cAAc,GAAG,cAAc,GAAG,SAAS,GACtD,QAAQ,GAAG,SAAS,GAAG,WAAW,GAClC,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,GACzC,OAAO,GAAG,OAAO,GAKjB,OAAO,GAAG,QAAQ,CAAC;AAEvB,2EAA2E;AAC3E,MAAM,MAAM,UAAU,GAAG,YAAY,GAAG,YAAY,GAAG,gBAAgB,CAAC;AAExE,4DAA4D;AAC5D,MAAM,MAAM,OAAO,GAAG,YAAY,GAAG,KAAK,CAAC;AAC3C,2DAA2D;AAC3D,MAAM,MAAM,OAAO,GAAG,YAAY,GAAG,KAAK,CAAC;AAC3C,yDAAyD;AACzD,MAAM,MAAM,WAAW,GAAG,gBAAgB,GAAG,KAAK,CAAC;AAEnD,iFAAiF;AACjF,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,KAAK,CAAC;AAE5C,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,GAAG,MAAM,GAAG,GAAG,MAAM,CAAC;AAEvD,MAAM,MAAM,WAAW,GACnB,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAC/C,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,CAAC;AAE1C,oEAAoE;AACpE,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,YAAY,GACpB,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;AAEhE,mDAAmD;AACnD,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,WAAW,GAAG,KAAK,CAAC;AAExD;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,KAAK,CAAC;AAE1C,MAAM,MAAM,WAAW,GAAG;IACxB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,0EAA0E;AAC1E,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,CAAC,EAAE,WAAW,CAAC;IAClB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,IAAI,CAAC,EAAE,WAAW,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,UAAU,GAClB,WAAW,GACX;IACE,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB;;;;OAIG;IACH,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAC7B;;;;OAIG;IACH,GAAG,CAAC,EAAE,OAAO,CAAC;CACf,CAAC;AAEN,MAAM,MAAM,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,SAAS,GAAG,UAAU,CAAC;AACxE,MAAM,MAAM,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;AACnF,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC;AACpE,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,UAAU,CAAC;AAC/C,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;AACzC;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,QAAQ,GAChB,MAAM,GAAG,MAAM,GAAG,MAAM,GACxB,UAAU,GAAG,gBAAgB,GAAG,iBAAiB,GAAG,cAAc,CAAC;AAGvE,MAAM,WAAW,KAAK;IACpB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IAGvB,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC;IAC7B,6EAA6E;IAC7E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gEAAgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,OAAO,CAAC,EAAE,QAAQ,CAAC;IACnB,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,SAAS,CAAC,EAAE,KAAK,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,2EAA2E;IAC3E,SAAS,CAAC,EAAE,QAAQ,CAAC;IACrB,kEAAkE;IAClE,SAAS,CAAC,EAAE,QAAQ,CAAC;IAGrB,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,UAAU,CAAC;IAGpB,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IACxC,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,KAAK,CAAC;IACb,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,kCAAkC;IAClC,MAAM,CAAC,EAAE,KAAK,CAAC;IACf,QAAQ,CAAC,EAAE,KAAK,CAAC;IACjB,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB;AAED,yEAAyE;AACzE,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC;AAE/E,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,aAAa,GAAG,CAAC,KAAK,GAAG,aAAa,GAAG,SAAS,GAAG,KAAK,CAAC,EAAE,CAAC;AAE/F,2EAA2E;AAC3E,MAAM,MAAM,eAAe,GACvB,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAC9C,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAExD,uDAAuD;AACvD,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AAEpE,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC"}
@@ -71,6 +71,16 @@ export interface ThemeDefinition {
71
71
  id: string;
72
72
  name: string;
73
73
  appearance: 'light' | 'dark';
74
+ /**
75
+ * Whether this theme has any colour to give.
76
+ *
77
+ * A theme's palette is its own business, but a component can state a literal
78
+ * colour - an ink, a chart, a hand-picked hex - and that used to come through
79
+ * untouched, so `mono` painted a rainbow the moment a banner asked for one.
80
+ * Stated, every colour resolves to the terminal's own: tokens and literals
81
+ * alike, which is what a theme that says it has no colour has to mean.
82
+ */
83
+ monochrome?: boolean;
74
84
  /** Extend another registered theme; only the differences need stating. */
75
85
  extends?: string;
76
86
  colors: Partial<Record<ColorToken, Color>>;
@@ -99,7 +109,16 @@ export interface ThemeDefinition {
99
109
  */
100
110
  tableRules?: TableRules;
101
111
  density?: Density;
102
- /** Per-component style overrides, keyed by component name then variant. */
112
+ /**
113
+ * Per-component style overrides, keyed by component name then variant or
114
+ * state.
115
+ *
116
+ * A composite component has to name which of its boxes this is - a list row
117
+ * is a `box` node, and `List` is what a theme author knows it by - so the
118
+ * name is stated at the node with `styleAs` and the map is keyed by it.
119
+ * `base` is the component at rest; the rest are the variants it supports and
120
+ * the five states in `StateName`.
121
+ */
103
122
  components?: Record<string, Record<string, Style>>;
104
123
  /**
105
124
  * Colours for syntax scopes. Every scope has a default drawn from the
@@ -113,6 +132,8 @@ export interface ResolvedTheme {
113
132
  id: string;
114
133
  name: string;
115
134
  appearance: 'light' | 'dark';
135
+ /** Whether every colour this theme gives back is the terminal's own. */
136
+ monochrome: boolean;
116
137
  colors: Record<ColorToken, Color>;
117
138
  spacing: ThemeSpacing;
118
139
  glyphs: ThemeGlyphs;
@@ -124,11 +145,24 @@ export interface ResolvedTheme {
124
145
  components: Record<string, Record<string, Style>>;
125
146
  /** Every syntax scope, resolved to a colour. */
126
147
  syntax: Record<SyntaxScope, Color>;
127
- /** Resolve a token (or pass a literal colour through). */
148
+ /** Resolve a token (or pass a literal colour through, unless monochrome). */
128
149
  color(token: string): Color;
129
150
  borderChars(style?: BorderStyle): BorderChars;
130
151
  dividerChars(style?: DividerStyle): DividerChars;
131
- /** Component style for a name + variant list, merged in order. */
152
+ /**
153
+ * Component style for a name and a list of names to merge over it, in the
154
+ * order given - later names win.
155
+ *
156
+ * The names are the component's `variant`, `tone` and `size` followed by the
157
+ * interaction states that are true: `selected`, `hover`, `active` (pressed),
158
+ * `focus` and `disabled`. So `components.List.selected` is the fill on the
159
+ * current row, and `components.List.focused` is the brighter one on the
160
+ * current row while the list has the keyboard.
161
+ *
162
+ * The order is the same one `flattenStyleInput` merges a `style` prop in, so
163
+ * a state stated at the node and the same state stated by the theme resolve
164
+ * to one answer rather than to whichever happened to be asked second.
165
+ */
132
166
  styleFor(component: string, variants?: string[]): Style;
133
167
  }
134
168
  export interface ThemeRegistry {
@@ -1 +1 @@
1
- {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/types/theme.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/types/theme.ts"],"names":[],"mappings":"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"}
@@ -45,6 +45,15 @@ export declare function sliceColumns(text: string, start: number, width: number)
45
45
  */
46
46
  export declare function expandTabs(text: string, tabWidth?: number): string;
47
47
  export type TruncateSide = 'end' | 'start' | 'middle';
48
+ /**
49
+ * Fit into `width` cells, marking the cut whether or not there was one.
50
+ *
51
+ * `truncate` marks only what it had to cut, which is right for a string that
52
+ * has to fit a cell. A paragraph stopped by the box rather than by its own
53
+ * length is the other case: its last visible row may fit exactly and still not
54
+ * be the end of the text, and it has to say so.
55
+ */
56
+ export declare function markCut(text: string, width: number, ellipsis?: string): string;
48
57
  /** Fit into `width` cells, marking the cut with `ellipsis`. */
49
58
  export declare function truncate(text: string, width: number, ellipsis?: string, side?: TruncateSide): string;
50
59
  /** Pad to exactly `width` cells. Over-long input is returned unchanged. */
@@ -1 +1 @@
1
- {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/util/text.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAelD;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAM7C;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAShD;AA8ED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAsBrD;AAsBD,2CAA2C;AAC3C,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAgBhD;AAED,+EAA+E;AAC/E,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAYhE;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAgC/E;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,SAAI,GAAG,MAAM,CAuB7D;AAED,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEtD,+DAA+D;AAC/D,wBAAgB,QAAQ,CACtB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,QAAQ,SAAM,EACd,IAAI,GAAE,YAAoB,GACzB,MAAM,CAkCR;AAED,2EAA2E;AAC3E,wBAAgB,KAAK,CACnB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,KAAK,GAAE,MAAM,GAAG,QAAQ,GAAG,OAAgB,EAC3C,IAAI,SAAM,GACT,MAAM,CAQR;AAED,kEAAkE;AAClE,wBAAgB,KAAK,CACnB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,KAAK,GAAE,MAAM,GAAG,QAAQ,GAAG,OAAgB,EAC3C,QAAQ,SAAM,GACb,MAAM,CAER;AAED,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAEhD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,YAAY,GAAG,SAAS,CAOnF;AAED,iFAAiF;AACjF,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAE/D;AAED,4EAA4E;AAC5E,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,QAAiB,GAAG,MAAM,EAAE,CAuDvF;AAOD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9C;AAgBD;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG7C;AAED,0EAA0E;AAC1E,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAIjE"}
1
+ {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/util/text.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAelD;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAM7C;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAShD;AA8ED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAsBrD;AAsBD,2CAA2C;AAC3C,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAgBhD;AAED,+EAA+E;AAC/E,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAYhE;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAgC/E;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,SAAI,GAAG,MAAM,CAuB7D;AAED,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEtD;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,SAAM,GAAG,MAAM,CAK3E;AAED,+DAA+D;AAC/D,wBAAgB,QAAQ,CACtB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,QAAQ,SAAM,EACd,IAAI,GAAE,YAAoB,GACzB,MAAM,CAkCR;AAED,2EAA2E;AAC3E,wBAAgB,KAAK,CACnB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,KAAK,GAAE,MAAM,GAAG,QAAQ,GAAG,OAAgB,EAC3C,IAAI,SAAM,GACT,MAAM,CAQR;AAED,kEAAkE;AAClE,wBAAgB,KAAK,CACnB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,KAAK,GAAE,MAAM,GAAG,QAAQ,GAAG,OAAgB,EAC3C,QAAQ,SAAM,GACb,MAAM,CAER;AAED,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAEhD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,YAAY,GAAG,SAAS,CAOnF;AAED,iFAAiF;AACjF,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAE/D;AAED,4EAA4E;AAC5E,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,QAAiB,GAAG,MAAM,EAAE,CAuDvF;AAOD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9C;AAgBD;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG7C;AAED,0EAA0E;AAC1E,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAIjE"}
package/dist/util/text.js CHANGED
@@ -280,6 +280,22 @@ export function expandTabs(text, tabWidth = 4) {
280
280
  })
281
281
  .join('\n');
282
282
  }
283
+ /**
284
+ * Fit into `width` cells, marking the cut whether or not there was one.
285
+ *
286
+ * `truncate` marks only what it had to cut, which is right for a string that
287
+ * has to fit a cell. A paragraph stopped by the box rather than by its own
288
+ * length is the other case: its last visible row may fit exactly and still not
289
+ * be the end of the text, and it has to say so.
290
+ */
291
+ export function markCut(text, width, ellipsis = '…') {
292
+ if (width <= 0)
293
+ return '';
294
+ const ew = stringWidth(ellipsis);
295
+ if (width <= ew)
296
+ return sliceByWidth(ellipsis, width);
297
+ return sliceByWidth(text, width - ew).trimEnd() + ellipsis;
298
+ }
283
299
  /** Fit into `width` cells, marking the cut with `ellipsis`. */
284
300
  export function truncate(text, width, ellipsis = '…', side = 'end') {
285
301
  const total = stringWidth(text);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@textui/core",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Graph-mounted terminal UI runtime - store, registries, renderer, host primitives",
5
5
  "keywords": [
6
6
  "terminal",
package/src/app/app.ts CHANGED
@@ -752,8 +752,15 @@ export class App implements TextUIApp {
752
752
  private stateOf(instance: Instance): InteractionState {
753
753
  const id = typeof instance.props.id === 'string' ? instance.props.id : instance.id;
754
754
  const focusedId = this.focus.focused();
755
+ // A node may state its own focus, and a row has to: the list holds the
756
+ // keyboard, the row is where it lands. Left to the id comparison every
757
+ // row in every list reads as unfocused, so "the current row" and "the
758
+ // current row you can type at" would be the same fill.
759
+ const stated = instance.props.focused;
755
760
  return {
756
- focused: focusedId === id || focusedId === `${instance.id}:focus`,
761
+ focused: typeof stated === 'boolean'
762
+ ? stated
763
+ : focusedId === id || focusedId === `${instance.id}:focus`,
757
764
  hovered: this.hovered === id || this.hoveredChain.has(instance),
758
765
  active: false,
759
766
  selected: instance.props.selected === true,
package/src/core/i18n.ts CHANGED
@@ -94,10 +94,10 @@ export class I18nRegistry implements I18n {
94
94
  return new Intl.ListFormat(this.locale, options).format(items);
95
95
  }
96
96
 
97
- plural(count: number, forms: Record<string, string>): string {
97
+ plural(count: number, forms: Record<string, string>, values?: Record<string, unknown>): string {
98
98
  const rule = new Intl.PluralRules(this.locale).select(count);
99
99
  const template = forms[rule] ?? forms.other ?? '';
100
- return interpolate(template, { count });
100
+ return interpolate(template, { ...values, count });
101
101
  }
102
102
 
103
103
  onChange(fn: (locale: LocaleId) => void): Disposable {
@@ -24,6 +24,31 @@ export interface BaseProps extends Style {
24
24
  disabled?: boolean;
25
25
  selected?: boolean;
26
26
 
27
+ /**
28
+ * The states this node is in, for `style` overlays and for a theme.
29
+ *
30
+ * `focused` is a tri-state on purpose. Left out, the runtime asks the focus
31
+ * manager - which is right for a control and wrong for a row: a list row does
32
+ * not hold the keyboard, the list does. A row that has to be told so, or the
33
+ * distinction between "this is the current row" and "this is the current row
34
+ * and you can type at it" cannot be drawn at all.
35
+ */
36
+ focused?: boolean;
37
+
38
+ /**
39
+ * Which of the component's boxes a theme styles.
40
+ *
41
+ * A composite component draws plain `box` nodes, so without this its entry
42
+ * in a theme's `components` map is a key nothing reads - a list row is a
43
+ * `box`, and `components.List.selected` is what a theme author would reach
44
+ * for. The name has to be stated by the component that owns the box, which
45
+ * is the only place that knows what the row is part of.
46
+ *
47
+ * Omitted, the node is styled under its own host name, so `components.box`
48
+ * and a `variant` keep working exactly as they did.
49
+ */
50
+ styleAs?: string;
51
+
27
52
  /** Participates in tab order. Implied by an interactive role. */
28
53
  focusable?: boolean;
29
54
  /** The focus scope this node belongs to. */
@@ -12,7 +12,7 @@ import type { Buffer } from '../render/buffer.js';
12
12
  import { COLOR_DEFAULT, mix, packColor, type PackedColor } from '../render/color.js';
13
13
  import { rectIntersect } from '../types/geometry.js';
14
14
  import {
15
- graphemes, graphemeWidth, isAscii, sanitize, stringWidth, truncate,
15
+ graphemes, graphemeWidth, isAscii, markCut, sanitize, stringWidth, truncate,
16
16
  truncateSideOf, wrapModeOf, wrapText,
17
17
  } from '../util/text.js';
18
18
  import {
@@ -751,7 +751,16 @@ function paintText(
751
751
 
752
752
  for (let i = 0; i < raw.length && i < area.height; i++) {
753
753
  let line = raw[i] as string;
754
- if (stringWidth(line) > area.width) {
754
+ // The last line the box has room for is cut when the text goes on past
755
+ // it, exactly as a line too wide for the box is. Without this a wrapped
756
+ // paragraph with more to say stopped mid-sentence and read as the whole
757
+ // of it, which is the failure `truncate` exists to prevent sideways.
758
+ const stopped = i === area.height - 1 && raw.length > area.height;
759
+ if (stopped) {
760
+ // The last row it has room for, with more to say: always marked, since
761
+ // the row itself may fit to the cell.
762
+ line = truncateSide === false ? line : markCut(line, area.width, ellipsis);
763
+ } else if (stringWidth(line) > area.width) {
755
764
  line = truncateSide === false
756
765
  ? line
757
766
  : truncate(line, area.width, ellipsis, truncateSide ?? 'end');
@@ -1,4 +1,4 @@
1
- import type { Style, StatefulStyle, StyleInput, BorderSpec, BorderStyle, StyleColor } from '../types/style.js';
1
+ import type { Style, StatefulStyle, StyleInput, BorderSpec, BorderColor, BorderStyle, StyleColor, StateName } from '../types/style.js';
2
2
  import type { ResolvedTheme } from '../types/theme.js';
3
3
  import type { Edges } from '../types/geometry.js';
4
4
  import type { Color } from '../types/cells.js';
@@ -31,6 +31,7 @@ export const STYLE_KEYS = new Set<string>([
31
31
  export interface InteractionState {
32
32
  focused: boolean;
33
33
  hovered: boolean;
34
+ /** Pressed. Not a selection - that is `selected`. */
34
35
  active: boolean;
35
36
  selected: boolean;
36
37
  disabled: boolean;
@@ -40,6 +41,37 @@ export const NO_INTERACTION: InteractionState = {
40
41
  focused: false, hovered: false, active: false, selected: false, disabled: false,
41
42
  };
42
43
 
44
+ /**
45
+ * The states, least to most specific - the order the last one wins.
46
+ *
47
+ * `flattenStyleInput` merges a `style` prop in this order and so does a
48
+ * theme's per-component map, which is the only way the two can be made to
49
+ * agree: a theme states `focus` over `selected` and gets the same answer
50
+ * whether the state came from the node or from the theme. `hovered` is the
51
+ * state; `hover` is the name it wears, which is why this is the one place
52
+ * that has to know the difference.
53
+ */
54
+ const STATE_ORDER: readonly (keyof InteractionState)[] = [
55
+ 'selected', 'hovered', 'active', 'focused', 'disabled',
56
+ ];
57
+
58
+ const STATE_VARIANT: Record<keyof InteractionState, StateName> = {
59
+ selected: 'selected',
60
+ hovered: 'hover',
61
+ active: 'active',
62
+ focused: 'focus',
63
+ disabled: 'disabled',
64
+ };
65
+
66
+ /** The names of the states that are true, in the order the last one wins. */
67
+ export function stateVariants(state: InteractionState): StateName[] {
68
+ const out: StateName[] = [];
69
+ for (const key of STATE_ORDER) {
70
+ if (state[key]) out.push(STATE_VARIANT[key]);
71
+ }
72
+ return out;
73
+ }
74
+
43
75
  function isStateful(value: Style | StatefulStyle): value is StatefulStyle {
44
76
  return (
45
77
  'base' in value || 'focus' in value || 'hover' in value ||
@@ -68,6 +100,7 @@ export function flattenStyleInput(input: StyleInput | undefined, state: Interact
68
100
 
69
101
  // Order matters: selected loses to active, active loses to focus, and
70
102
  // disabled wins over everything - a disabled control is not focusable.
103
+ // The same order `stateVariants` gives a theme, so the two cannot disagree.
71
104
  return mergeStyles(
72
105
  input.base,
73
106
  state.selected ? input.selected : undefined,
@@ -94,13 +127,37 @@ export function resolveStyle(
94
127
  defaultStyle: Style | undefined,
95
128
  state: InteractionState,
96
129
  ): Style {
97
- const variants: string[] = [];
98
- if (typeof props.variant === 'string') variants.push(props.variant);
99
- if (typeof props.tone === 'string') variants.push(props.tone);
100
- if (typeof props.size === 'string') variants.push(props.size);
130
+ const qualifiers: string[] = [];
131
+ if (typeof props.variant === 'string') qualifiers.push(props.variant);
132
+ if (typeof props.tone === 'string') qualifiers.push(props.tone);
133
+ if (typeof props.size === 'string') qualifiers.push(props.size);
134
+ const variants: string[] = [...qualifiers];
135
+
136
+ // The states join last, so a theme's entry for one of them wins over the
137
+ // same name used as a variant - `List.focused` is the fill on the row the
138
+ // keyboard is on, and a `focused` variant means nothing else.
139
+ //
140
+ // Each state is also offered qualified by each of the props-driven names,
141
+ // immediately after the flat one, for the case the flat name cannot say:
142
+ // whether a state paints at all is sometimes a property of a variant rather
143
+ // than of the state. A solid tab is filled and an underline one is not, and
144
+ // `Tabs.selected` has to mean the pair for both while `Tabs.solid.selected`
145
+ // is the one that adds the fill. The qualified name merges last and the
146
+ // order between the states is unchanged, so `disabled` still wins over
147
+ // everything and `focus` still wins over `selected`.
148
+ for (const name of stateVariants(state)) {
149
+ variants.push(name);
150
+ for (const qualifier of qualifiers) variants.push(`${qualifier}.${name}`);
151
+ }
152
+
153
+ // `styleAs` is how a component says which of its boxes a theme styles. A
154
+ // list draws its rows as plain `box` nodes, so without it `components.List`
155
+ // would be a key nothing ever reads - which is what every `components` entry
156
+ // written for a composite component was until this.
157
+ const owner = typeof props.styleAs === 'string' ? props.styleAs : component;
101
158
 
102
159
  return mergeStyles(
103
- theme.styleFor(component, variants),
160
+ theme.styleFor(owner, variants),
104
161
  defaultStyle,
105
162
  styleFromProps(props),
106
163
  flattenStyleInput(props.style as StyleInput | undefined, state),
@@ -109,7 +166,13 @@ export function resolveStyle(
109
166
 
110
167
  // ------------------------------------------------------------------ colour
111
168
 
112
- /** A token name, a literal colour, or nothing. */
169
+ /**
170
+ * A token name, a literal colour, or nothing.
171
+ *
172
+ * Takes the whole union because it is the one place a colour is turned into
173
+ * a cell value: the narrowing happened at the field that named it, which is
174
+ * where the mistake is made and where the error belongs.
175
+ */
113
176
  export function resolveColor(
114
177
  value: StyleColor | undefined,
115
178
  theme: ResolvedTheme,
@@ -119,6 +182,7 @@ export function resolveColor(
119
182
  return theme.color(value as string);
120
183
  }
121
184
 
185
+ /** Pack a colour for a cell, at the caller's own channel. */
122
186
  export function packStyleColor(
123
187
  value: StyleColor | undefined,
124
188
  theme: ResolvedTheme,
@@ -144,9 +208,9 @@ export function attrsFromStyle(style: Style): number {
144
208
  export interface ResolvedBorder {
145
209
  style: BorderStyle;
146
210
  chars: BorderChars;
147
- color: StyleColor | undefined;
211
+ color: BorderColor | undefined;
148
212
  /** Per-edge overrides. Undefined here means "use `color`". */
149
- colors: { top?: StyleColor; right?: StyleColor; bottom?: StyleColor; left?: StyleColor };
213
+ colors: { top?: BorderColor; right?: BorderColor; bottom?: BorderColor; left?: BorderColor };
150
214
  dim: boolean;
151
215
  sides: { top: boolean; right: boolean; bottom: boolean; left: boolean };
152
216
  edges: Edges;