@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.
- package/dist/app/app.d.ts.map +1 -1
- package/dist/app/app.js +8 -1
- package/dist/core/i18n.d.ts +1 -1
- package/dist/core/i18n.d.ts.map +1 -1
- package/dist/core/i18n.js +2 -2
- package/dist/jsx/intrinsics.d.ts +23 -0
- package/dist/jsx/intrinsics.d.ts.map +1 -1
- package/dist/runtime/paint.js +12 -2
- package/dist/runtime/style.d.ts +17 -7
- package/dist/runtime/style.d.ts.map +1 -1
- package/dist/runtime/style.js +66 -6
- package/dist/themes/builtin.d.ts +0 -9
- package/dist/themes/builtin.d.ts.map +1 -1
- package/dist/themes/builtin.js +101 -4
- package/dist/themes/registry.d.ts.map +1 -1
- package/dist/themes/registry.js +26 -0
- package/dist/types/i18n.d.ts +9 -1
- package/dist/types/i18n.d.ts.map +1 -1
- package/dist/types/style.d.ts +53 -14
- package/dist/types/style.d.ts.map +1 -1
- package/dist/types/theme.d.ts +37 -3
- package/dist/types/theme.d.ts.map +1 -1
- package/dist/util/text.d.ts +9 -0
- package/dist/util/text.d.ts.map +1 -1
- package/dist/util/text.js +16 -0
- package/package.json +1 -1
- package/src/app/app.ts +8 -1
- package/src/core/i18n.ts +2 -2
- package/src/jsx/intrinsics.ts +25 -0
- package/src/runtime/paint.ts +11 -2
- package/src/runtime/style.ts +73 -9
- package/src/themes/builtin.ts +105 -4
- package/src/themes/registry.ts +23 -0
- package/src/types/i18n.ts +9 -1
- package/src/types/style.ts +85 -18
- package/src/types/theme.ts +37 -3
- package/src/util/text.ts +15 -0
package/dist/types/style.d.ts
CHANGED
|
@@ -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
|
|
5
|
-
*
|
|
6
|
-
* a
|
|
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
|
-
|
|
9
|
-
|
|
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?:
|
|
66
|
-
right?:
|
|
67
|
-
bottom?:
|
|
68
|
-
left?:
|
|
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?:
|
|
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 |
|
|
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?:
|
|
164
|
-
bg?:
|
|
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
|
-
/**
|
|
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":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C
|
|
1
|
+
{"version":3,"file":"style.d.ts","sourceRoot":"","sources":["../../src/types/style.ts"],"names":[],"mappings":"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"}
|
package/dist/types/theme.d.ts
CHANGED
|
@@ -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
|
-
/**
|
|
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
|
-
/**
|
|
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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"}
|
package/dist/util/text.d.ts
CHANGED
|
@@ -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. */
|
package/dist/util/text.d.ts.map
CHANGED
|
@@ -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
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:
|
|
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 {
|
package/src/jsx/intrinsics.ts
CHANGED
|
@@ -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. */
|
package/src/runtime/paint.ts
CHANGED
|
@@ -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
|
-
|
|
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');
|
package/src/runtime/style.ts
CHANGED
|
@@ -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
|
|
98
|
-
if (typeof props.variant === 'string')
|
|
99
|
-
if (typeof props.tone === 'string')
|
|
100
|
-
if (typeof props.size === 'string')
|
|
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(
|
|
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
|
-
/**
|
|
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:
|
|
211
|
+
color: BorderColor | undefined;
|
|
148
212
|
/** Per-edge overrides. Undefined here means "use `color`". */
|
|
149
|
-
colors: { top?:
|
|
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;
|