@flyingrobots/bijou-tui 2.1.0 → 3.1.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/README.md +64 -21
- package/dist/animate.d.ts +0 -2
- package/dist/animate.d.ts.map +1 -1
- package/dist/animate.js +17 -26
- package/dist/animate.js.map +1 -1
- package/dist/app-frame-actions.d.ts +1 -5
- package/dist/app-frame-actions.d.ts.map +1 -1
- package/dist/app-frame-actions.js +21 -17
- package/dist/app-frame-actions.js.map +1 -1
- package/dist/app-frame-render.d.ts +2 -0
- package/dist/app-frame-render.d.ts.map +1 -1
- package/dist/app-frame-render.js +55 -8
- package/dist/app-frame-render.js.map +1 -1
- package/dist/app-frame-types.d.ts +9 -0
- package/dist/app-frame-types.d.ts.map +1 -1
- package/dist/app-frame-types.js +4 -4
- package/dist/app-frame-types.js.map +1 -1
- package/dist/app-frame.d.ts +39 -2
- package/dist/app-frame.d.ts.map +1 -1
- package/dist/app-frame.js +195 -31
- package/dist/app-frame.js.map +1 -1
- package/dist/canvas.d.ts +37 -25
- package/dist/canvas.d.ts.map +1 -1
- package/dist/canvas.js +116 -30
- package/dist/canvas.js.map +1 -1
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +12 -4
- package/dist/commands.js.map +1 -1
- package/dist/css/install.d.ts +4 -0
- package/dist/css/install.d.ts.map +1 -0
- package/dist/css/install.js +24 -0
- package/dist/css/install.js.map +1 -0
- package/dist/css/parser.d.ts +14 -0
- package/dist/css/parser.d.ts.map +1 -0
- package/dist/css/parser.js +92 -0
- package/dist/css/parser.js.map +1 -0
- package/dist/css/resolver.d.ts +36 -0
- package/dist/css/resolver.d.ts.map +1 -0
- package/dist/css/resolver.js +130 -0
- package/dist/css/resolver.js.map +1 -0
- package/dist/css/text-style.d.ts +17 -0
- package/dist/css/text-style.d.ts.map +1 -0
- package/dist/css/text-style.js +59 -0
- package/dist/css/text-style.js.map +1 -0
- package/dist/css/types.d.ts +27 -0
- package/dist/css/types.d.ts.map +1 -0
- package/dist/css/types.js +5 -0
- package/dist/css/types.js.map +1 -0
- package/dist/driver.d.ts +14 -7
- package/dist/driver.d.ts.map +1 -1
- package/dist/driver.js +38 -17
- package/dist/driver.js.map +1 -1
- package/dist/eventbus.d.ts +42 -3
- package/dist/eventbus.d.ts.map +1 -1
- package/dist/eventbus.js +127 -3
- package/dist/eventbus.js.map +1 -1
- package/dist/focus-area.d.ts +4 -0
- package/dist/focus-area.d.ts.map +1 -1
- package/dist/focus-area.js +11 -1
- package/dist/focus-area.js.map +1 -1
- package/dist/index.d.ts +13 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/layout-v3.d.ts +10 -0
- package/dist/layout-v3.d.ts.map +1 -0
- package/dist/layout-v3.js +35 -0
- package/dist/layout-v3.js.map +1 -0
- package/dist/motion/motion.d.ts +14 -0
- package/dist/motion/motion.d.ts.map +1 -0
- package/dist/motion/motion.js +31 -0
- package/dist/motion/motion.js.map +1 -0
- package/dist/motion/reconciler.d.ts +15 -0
- package/dist/motion/reconciler.d.ts.map +1 -0
- package/dist/motion/reconciler.js +109 -0
- package/dist/motion/reconciler.js.map +1 -0
- package/dist/motion/types.d.ts +52 -0
- package/dist/motion/types.d.ts.map +1 -0
- package/dist/motion/types.js +2 -0
- package/dist/motion/types.js.map +1 -0
- package/dist/notification.d.ts +73 -0
- package/dist/notification.d.ts.map +1 -0
- package/dist/notification.js +693 -0
- package/dist/notification.js.map +1 -0
- package/dist/overlay.d.ts +3 -1
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js.map +1 -1
- package/dist/pipeline/middleware/css.d.ts +20 -0
- package/dist/pipeline/middleware/css.d.ts.map +1 -0
- package/dist/pipeline/middleware/css.js +41 -0
- package/dist/pipeline/middleware/css.js.map +1 -0
- package/dist/pipeline/middleware/grayscale.d.ts +9 -0
- package/dist/pipeline/middleware/grayscale.d.ts.map +1 -0
- package/dist/pipeline/middleware/grayscale.js +39 -0
- package/dist/pipeline/middleware/grayscale.js.map +1 -0
- package/dist/pipeline/middleware/motion.d.ts +6 -0
- package/dist/pipeline/middleware/motion.d.ts.map +1 -0
- package/dist/pipeline/middleware/motion.js +19 -0
- package/dist/pipeline/middleware/motion.js.map +1 -0
- package/dist/pipeline/middleware/paint.d.ts +6 -0
- package/dist/pipeline/middleware/paint.d.ts.map +1 -0
- package/dist/pipeline/middleware/paint.js +21 -0
- package/dist/pipeline/middleware/paint.js.map +1 -0
- package/dist/pipeline/pipeline.d.ts +56 -0
- package/dist/pipeline/pipeline.d.ts.map +1 -0
- package/dist/pipeline/pipeline.js +45 -0
- package/dist/pipeline/pipeline.js.map +1 -0
- package/dist/runtime.d.ts +1 -1
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +180 -18
- package/dist/runtime.js.map +1 -1
- package/dist/screen.d.ts +12 -1
- package/dist/screen.d.ts.map +1 -1
- package/dist/screen.js +14 -1
- package/dist/screen.js.map +1 -1
- package/dist/subapp/mount.d.ts +67 -0
- package/dist/subapp/mount.d.ts.map +1 -0
- package/dist/subapp/mount.js +60 -0
- package/dist/subapp/mount.js.map +1 -0
- package/dist/types.d.ts +75 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -1
- package/dist/view-output.d.ts +15 -0
- package/dist/view-output.d.ts.map +1 -0
- package/dist/view-output.js +53 -0
- package/dist/view-output.js.map +1 -0
- package/package.json +3 -3
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves the final styles for a component based on a CSS sheet and terminal dimensions.
|
|
3
|
+
*
|
|
4
|
+
* @param identity - The component's identity (type, id, classes).
|
|
5
|
+
* @param sheet - The parsed BCSS sheet.
|
|
6
|
+
* @param terminal - Current terminal dimensions for media query matching.
|
|
7
|
+
* @param graph - The TokenGraph for resolving var() references.
|
|
8
|
+
* @param mode - The theme mode (light/dark).
|
|
9
|
+
* @returns A record of computed style properties.
|
|
10
|
+
*/
|
|
11
|
+
export function resolveStyles(identity, sheet, terminal, graph, mode = 'dark') {
|
|
12
|
+
const matchedRules = [];
|
|
13
|
+
// 1. Collect rules from main sheet
|
|
14
|
+
for (const rule of sheet.rules) {
|
|
15
|
+
const specificity = getMatchSpecificity(identity, rule.selectors);
|
|
16
|
+
if (specificity > 0) {
|
|
17
|
+
matchedRules.push({ rule, specificity });
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
// 2. Collect rules from active media queries
|
|
21
|
+
for (const mq of sheet.mediaQueries) {
|
|
22
|
+
if (matchesMediaQuery(mq.condition, terminal)) {
|
|
23
|
+
for (const rule of mq.rules) {
|
|
24
|
+
const specificity = getMatchSpecificity(identity, rule.selectors);
|
|
25
|
+
if (specificity > 0) {
|
|
26
|
+
// Media query rules have slightly higher base priority in CSS
|
|
27
|
+
matchedRules.push({ rule, specificity: specificity + 0.1 });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
// 3. Sort by specificity (and then order of appearance)
|
|
33
|
+
matchedRules.sort((a, b) => a.specificity - b.specificity);
|
|
34
|
+
// 4. Merge declarations into final object
|
|
35
|
+
const finalStyles = {};
|
|
36
|
+
for (const { rule } of matchedRules) {
|
|
37
|
+
for (const decl of rule.declarations) {
|
|
38
|
+
// !important handling
|
|
39
|
+
if (decl.important || !isImportant(finalStyles, decl.property)) {
|
|
40
|
+
finalStyles[decl.property] = resolveValue(decl.value, graph, mode);
|
|
41
|
+
if (decl.important) {
|
|
42
|
+
finalStyles[`__important_${decl.property}`] = 'true';
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return finalStyles;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Resolve a CSS value, handling var(token.path) references via the TokenGraph.
|
|
51
|
+
*/
|
|
52
|
+
function resolveValue(value, graph, mode = 'dark') {
|
|
53
|
+
if (!graph)
|
|
54
|
+
return value;
|
|
55
|
+
// Simple regex for var(path.to.token)
|
|
56
|
+
const varRegex = /var\(([^)]+)\)/g;
|
|
57
|
+
return value.replace(varRegex, (_, path) => {
|
|
58
|
+
try {
|
|
59
|
+
// Try to get as full token first, then fallback to color
|
|
60
|
+
const resolved = graph.get(path.trim(), mode);
|
|
61
|
+
return resolved.hex;
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return 'inherit'; // Fallback for unresolved vars
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
function isImportant(styles, property) {
|
|
69
|
+
return styles[`__important_${property}`] === 'true';
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Calculate match specificity for a component identity against a set of selectors.
|
|
73
|
+
* Returns 0 if no match, otherwise a positive number representing specificity.
|
|
74
|
+
*/
|
|
75
|
+
function getMatchSpecificity(identity, selectors) {
|
|
76
|
+
let maxSpecificity = 0;
|
|
77
|
+
for (const selector of selectors) {
|
|
78
|
+
let match = true;
|
|
79
|
+
let specificity = 0;
|
|
80
|
+
// Type match
|
|
81
|
+
if (selector.type && selector.type !== '*') {
|
|
82
|
+
if (identity.type !== selector.type)
|
|
83
|
+
match = false;
|
|
84
|
+
specificity += 1;
|
|
85
|
+
}
|
|
86
|
+
// ID match
|
|
87
|
+
if (selector.id) {
|
|
88
|
+
if (identity.id !== selector.id)
|
|
89
|
+
match = false;
|
|
90
|
+
specificity += 100;
|
|
91
|
+
}
|
|
92
|
+
// Class match (all classes in selector must be present on component)
|
|
93
|
+
if (selector.classes.length > 0) {
|
|
94
|
+
for (const cls of selector.classes) {
|
|
95
|
+
if (!identity.classes?.includes(cls)) {
|
|
96
|
+
match = false;
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
specificity += selector.classes.length * 10;
|
|
101
|
+
}
|
|
102
|
+
if (match) {
|
|
103
|
+
maxSpecificity = Math.max(maxSpecificity, specificity);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return maxSpecificity;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Evaluate a basic media query condition like "(width < 80)" or "(height >= 24)".
|
|
110
|
+
*/
|
|
111
|
+
export function matchesMediaQuery(condition, terminal) {
|
|
112
|
+
// Simple regex for (property op value)
|
|
113
|
+
const regex = /\((width|height)\s*(<|>|<=|>=|==|!=)\s*(\d+)\)/;
|
|
114
|
+
const match = condition.match(regex);
|
|
115
|
+
if (!match)
|
|
116
|
+
return false;
|
|
117
|
+
const property = match[1] === 'width' ? terminal.width : terminal.height;
|
|
118
|
+
const op = match[2];
|
|
119
|
+
const value = parseInt(match[3], 10);
|
|
120
|
+
switch (op) {
|
|
121
|
+
case '<': return property < value;
|
|
122
|
+
case '>': return property > value;
|
|
123
|
+
case '<=': return property <= value;
|
|
124
|
+
case '>=': return property >= value;
|
|
125
|
+
case '==': return property === value;
|
|
126
|
+
case '!=': return property !== value;
|
|
127
|
+
default: return false;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/css/resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { BijouContext } from '@flyingrobots/bijou';
|
|
2
|
+
export interface StyledTextToken {
|
|
3
|
+
hex?: string;
|
|
4
|
+
bg?: string;
|
|
5
|
+
modifiers?: string[];
|
|
6
|
+
}
|
|
7
|
+
export interface BCSSIdentity {
|
|
8
|
+
type: string;
|
|
9
|
+
id?: string;
|
|
10
|
+
classes?: string[];
|
|
11
|
+
}
|
|
12
|
+
type BCSSStyles = Record<string, string>;
|
|
13
|
+
export declare function mergeBCSSModifiers(base: readonly string[] | undefined, styles: BCSSStyles): string[] | undefined;
|
|
14
|
+
export declare function resolveBCSSTextToken(ctx: BijouContext, identity: BCSSIdentity, base?: StyledTextToken): StyledTextToken;
|
|
15
|
+
export declare function styleTextWithBCSS(text: string, ctx: BijouContext | undefined, identity: BCSSIdentity, base?: StyledTextToken): string;
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=text-style.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-style.d.ts","sourceRoot":"","sources":["../../src/css/text-style.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEzC,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EACnC,MAAM,EAAE,UAAU,GACjB,MAAM,EAAE,GAAG,SAAS,CAoCtB;AAED,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,YAAY,EACjB,QAAQ,EAAE,YAAY,EACtB,IAAI,GAAE,eAAoB,GACzB,eAAe,CAOjB;AAED,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,YAAY,GAAG,SAAS,EAC7B,QAAQ,EAAE,YAAY,EACtB,IAAI,GAAE,eAAoB,GACzB,MAAM,CAcR"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export function mergeBCSSModifiers(base, styles) {
|
|
2
|
+
const modifiers = new Set(base ?? []);
|
|
3
|
+
const fontWeight = styles['font-weight']?.trim().toLowerCase();
|
|
4
|
+
if (fontWeight === 'bold' || fontWeight === '700' || fontWeight === '800' || fontWeight === '900') {
|
|
5
|
+
modifiers.add('bold');
|
|
6
|
+
}
|
|
7
|
+
else if (fontWeight === 'normal' || fontWeight === '400') {
|
|
8
|
+
modifiers.delete('bold');
|
|
9
|
+
}
|
|
10
|
+
const fontStyle = styles['font-style']?.trim().toLowerCase();
|
|
11
|
+
if (fontStyle === 'italic') {
|
|
12
|
+
modifiers.add('italic');
|
|
13
|
+
}
|
|
14
|
+
else if (fontStyle === 'normal') {
|
|
15
|
+
modifiers.delete('italic');
|
|
16
|
+
}
|
|
17
|
+
const decoration = styles['text-decoration']?.trim().toLowerCase();
|
|
18
|
+
if (decoration === 'none') {
|
|
19
|
+
modifiers.delete('underline');
|
|
20
|
+
modifiers.delete('curly-underline');
|
|
21
|
+
modifiers.delete('dotted-underline');
|
|
22
|
+
modifiers.delete('dashed-underline');
|
|
23
|
+
modifiers.delete('strikethrough');
|
|
24
|
+
modifiers.delete('strike');
|
|
25
|
+
}
|
|
26
|
+
else if (decoration) {
|
|
27
|
+
if (decoration.includes('underline')) {
|
|
28
|
+
modifiers.add('underline');
|
|
29
|
+
}
|
|
30
|
+
if (decoration.includes('line-through')) {
|
|
31
|
+
modifiers.add('strikethrough');
|
|
32
|
+
modifiers.delete('strike');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return modifiers.size > 0 ? Array.from(modifiers) : undefined;
|
|
36
|
+
}
|
|
37
|
+
export function resolveBCSSTextToken(ctx, identity, base = {}) {
|
|
38
|
+
const styles = ctx.resolveBCSS(identity);
|
|
39
|
+
return {
|
|
40
|
+
hex: styles['color'] ?? base.hex,
|
|
41
|
+
bg: styles['background'] ?? base.bg,
|
|
42
|
+
modifiers: mergeBCSSModifiers(base.modifiers, styles),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export function styleTextWithBCSS(text, ctx, identity, base = {}) {
|
|
46
|
+
if (!ctx)
|
|
47
|
+
return text;
|
|
48
|
+
const styles = ctx.resolveBCSS(identity);
|
|
49
|
+
const token = {
|
|
50
|
+
hex: styles['color'] ?? base.hex,
|
|
51
|
+
bg: styles['background'] ?? base.bg,
|
|
52
|
+
modifiers: mergeBCSSModifiers(base.modifiers, styles),
|
|
53
|
+
};
|
|
54
|
+
if (token.hex == null && token.bg == null && (token.modifiers == null || token.modifiers.length === 0)) {
|
|
55
|
+
return text;
|
|
56
|
+
}
|
|
57
|
+
return ctx.style.styled(token, text);
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=text-style.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-style.js","sourceRoot":"","sources":["../../src/css/text-style.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AST types for Bijou CSS (BCSS).
|
|
3
|
+
*/
|
|
4
|
+
export interface BCSSDeclaration {
|
|
5
|
+
property: string;
|
|
6
|
+
value: string;
|
|
7
|
+
important: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface BCSSSelector {
|
|
10
|
+
type?: string;
|
|
11
|
+
id?: string;
|
|
12
|
+
classes: string[];
|
|
13
|
+
raw: string;
|
|
14
|
+
}
|
|
15
|
+
export interface BCSSRule {
|
|
16
|
+
selectors: BCSSSelector[];
|
|
17
|
+
declarations: BCSSDeclaration[];
|
|
18
|
+
}
|
|
19
|
+
export interface BCSSMediaQuery {
|
|
20
|
+
condition: string;
|
|
21
|
+
rules: BCSSRule[];
|
|
22
|
+
}
|
|
23
|
+
export interface BCSSSheet {
|
|
24
|
+
rules: BCSSRule[];
|
|
25
|
+
mediaQueries: BCSSMediaQuery[];
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/css/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,QAAQ;IACvB,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,YAAY,EAAE,eAAe,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,YAAY,EAAE,cAAc,EAAE,CAAC;CAChC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/css/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
package/dist/driver.d.ts
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* ```
|
|
17
17
|
*/
|
|
18
18
|
import type { App, RunOptions } from './types.js';
|
|
19
|
+
import { type Surface } from '@flyingrobots/bijou';
|
|
19
20
|
/** A single step in a scripted interaction sequence. */
|
|
20
21
|
export type ScriptStep<M = never> = {
|
|
21
22
|
/** Key to send (raw terminal key string, e.g., 'a', '\x1b[A', '\x03'). */
|
|
@@ -30,6 +31,13 @@ export type ScriptStep<M = never> = {
|
|
|
30
31
|
};
|
|
31
32
|
/** Milliseconds to wait before sending this step. Default: 0. */
|
|
32
33
|
delay?: number;
|
|
34
|
+
} | {
|
|
35
|
+
/** Pulse event to emit. */
|
|
36
|
+
pulse: {
|
|
37
|
+
dt: number;
|
|
38
|
+
};
|
|
39
|
+
/** Milliseconds to wait before sending this step. Default: 0. */
|
|
40
|
+
delay?: number;
|
|
33
41
|
} | {
|
|
34
42
|
/** Custom message to emit directly onto the bus. */
|
|
35
43
|
msg: M;
|
|
@@ -39,7 +47,9 @@ export type ScriptStep<M = never> = {
|
|
|
39
47
|
/** Options for {@link runScript}, extending the base {@link RunOptions}. */
|
|
40
48
|
export interface RunScriptOptions extends RunOptions {
|
|
41
49
|
/** Capture each rendered frame. */
|
|
42
|
-
onFrame?: (frame:
|
|
50
|
+
onFrame?: (frame: Surface, index: number) => void;
|
|
51
|
+
/** Pulse frequency used to drive animation commands. Set to `false` to disable. */
|
|
52
|
+
pulseFps?: number | false;
|
|
43
53
|
}
|
|
44
54
|
/**
|
|
45
55
|
* Result returned by {@link runScript} after all steps have been processed.
|
|
@@ -50,7 +60,7 @@ export interface RunScriptResult<Model> {
|
|
|
50
60
|
/** Final model state after all steps. */
|
|
51
61
|
model: Model;
|
|
52
62
|
/** All rendered frames in order. */
|
|
53
|
-
frames:
|
|
63
|
+
frames: Surface[];
|
|
54
64
|
/** Total elapsed time in milliseconds. */
|
|
55
65
|
elapsed: number;
|
|
56
66
|
}
|
|
@@ -65,11 +75,8 @@ export interface RunScriptResult<Model> {
|
|
|
65
75
|
* - A command returns QUIT
|
|
66
76
|
* - All script steps are exhausted (auto-quits)
|
|
67
77
|
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
* Commands that use `setTimeout`, real I/O, or other macrotask-based async
|
|
71
|
-
* may not have completed before the next key is dispatched. Use `delay`
|
|
72
|
-
* on subsequent steps to allow time for macrotask-based commands.
|
|
78
|
+
* Between steps the driver waits for the event bus to go idle, so command
|
|
79
|
+
* chains settle deterministically without relying on microtask-only yields.
|
|
73
80
|
*
|
|
74
81
|
* @template Model - The application model type.
|
|
75
82
|
* @template M - The message (action) type for the TEA update cycle.
|
package/dist/driver.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../src/driver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,UAAU,EAAa,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../src/driver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,UAAU,EAAa,MAAM,YAAY,CAAC;AAI7D,OAAO,EAAE,KAAK,OAAO,EAAuB,MAAM,qBAAqB,CAAC;AAQxE,wDAAwD;AACxD,MAAM,MAAM,UAAU,CAAC,CAAC,GAAG,KAAK,IAC5B;IACA,0EAA0E;IAC1E,GAAG,EAAE,MAAM,CAAC;IACZ,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GACC;IACA,4BAA4B;IAC5B,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1C,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GACC;IACA,2BAA2B;IAC3B,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IACtB,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GACC;IACA,oDAAoD;IACpD,GAAG,EAAE,CAAC,CAAC;IACP,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEJ,4EAA4E;AAC5E,MAAM,WAAW,gBAAiB,SAAQ,UAAU;IAClD,mCAAmC;IACnC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,mFAAmF;IACnF,QAAQ,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;CAC3B;AAED;;;;GAIG;AACH,MAAM,WAAW,eAAe,CAAC,KAAK;IACpC,yCAAyC;IACzC,KAAK,EAAE,KAAK,CAAC;IACb,oCAAoC;IACpC,MAAM,EAAE,OAAO,EAAE,CAAC;IAClB,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,CAAC,EACtC,GAAG,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,EAClB,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,EACtB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CA2GjC"}
|
package/dist/driver.js
CHANGED
|
@@ -15,8 +15,12 @@
|
|
|
15
15
|
* console.log(result.frames); // all rendered frames
|
|
16
16
|
* ```
|
|
17
17
|
*/
|
|
18
|
+
import { isResizeMsg } from './types.js';
|
|
18
19
|
import { createEventBus } from './eventbus.js';
|
|
19
20
|
import { parseKey } from './keys.js';
|
|
21
|
+
import { resolveClock, sleep } from '@flyingrobots/bijou';
|
|
22
|
+
import { installBCSSResolver } from './css/install.js';
|
|
23
|
+
import { normalizeViewOutput } from './view-output.js';
|
|
20
24
|
// ---------------------------------------------------------------------------
|
|
21
25
|
// Implementation
|
|
22
26
|
// ---------------------------------------------------------------------------
|
|
@@ -31,11 +35,8 @@ import { parseKey } from './keys.js';
|
|
|
31
35
|
* - A command returns QUIT
|
|
32
36
|
* - All script steps are exhausted (auto-quits)
|
|
33
37
|
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* Commands that use `setTimeout`, real I/O, or other macrotask-based async
|
|
37
|
-
* may not have completed before the next key is dispatched. Use `delay`
|
|
38
|
-
* on subsequent steps to allow time for macrotask-based commands.
|
|
38
|
+
* Between steps the driver waits for the event bus to go idle, so command
|
|
39
|
+
* chains settle deterministically without relying on microtask-only yields.
|
|
39
40
|
*
|
|
40
41
|
* @template Model - The application model type.
|
|
41
42
|
* @template M - The message (action) type for the TEA update cycle.
|
|
@@ -45,12 +46,25 @@ import { parseKey } from './keys.js';
|
|
|
45
46
|
* @returns The final model, all rendered frames, and elapsed time.
|
|
46
47
|
*/
|
|
47
48
|
export async function runScript(app, steps, options) {
|
|
48
|
-
const
|
|
49
|
+
const clock = resolveClock(options?.ctx);
|
|
50
|
+
const start = clock.now();
|
|
49
51
|
const frames = [];
|
|
50
|
-
const bus = createEventBus();
|
|
52
|
+
const bus = createEventBus({ clock });
|
|
53
|
+
const ctx = options?.ctx;
|
|
54
|
+
if (ctx != null) {
|
|
55
|
+
installBCSSResolver(ctx, options?.css);
|
|
56
|
+
}
|
|
51
57
|
const [initModel, initCmds] = app.init();
|
|
52
58
|
let model = initModel;
|
|
53
59
|
let running = true;
|
|
60
|
+
let currentSize = {
|
|
61
|
+
width: Math.max(0, Math.floor(ctx?.runtime.columns || 80)),
|
|
62
|
+
height: Math.max(0, Math.floor(ctx?.runtime.rows || 24)),
|
|
63
|
+
};
|
|
64
|
+
// Start heartbeat for animations when enabled.
|
|
65
|
+
if (options?.pulseFps !== false) {
|
|
66
|
+
bus.startPulse(options?.pulseFps ?? ctx?.runtime.refreshRate ?? 60);
|
|
67
|
+
}
|
|
54
68
|
/** Stop the scripted driver event loop. */
|
|
55
69
|
function shutdown() {
|
|
56
70
|
running = false;
|
|
@@ -61,7 +75,13 @@ export async function runScript(app, steps, options) {
|
|
|
61
75
|
return;
|
|
62
76
|
const [newModel, cmds] = app.update(msg, model);
|
|
63
77
|
model = newModel;
|
|
64
|
-
|
|
78
|
+
if (isResizeMsg(msg)) {
|
|
79
|
+
currentSize = {
|
|
80
|
+
width: Math.max(0, msg.columns),
|
|
81
|
+
height: Math.max(0, msg.rows),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
const frame = normalizeViewOutput(app.view(model), currentSize).surface;
|
|
65
85
|
frames.push(frame);
|
|
66
86
|
options?.onFrame?.(frame, frames.length - 1);
|
|
67
87
|
for (const cmd of cmds) {
|
|
@@ -70,21 +90,20 @@ export async function runScript(app, steps, options) {
|
|
|
70
90
|
});
|
|
71
91
|
try {
|
|
72
92
|
// Capture initial frame
|
|
73
|
-
const initFrame = app.view(model);
|
|
93
|
+
const initFrame = normalizeViewOutput(app.view(model), currentSize).surface;
|
|
74
94
|
frames.push(initFrame);
|
|
75
95
|
options?.onFrame?.(initFrame, 0);
|
|
76
96
|
// Run init commands
|
|
77
97
|
for (const cmd of initCmds) {
|
|
78
98
|
bus.runCmd(cmd);
|
|
79
99
|
}
|
|
80
|
-
|
|
81
|
-
await new Promise((r) => queueMicrotask(r));
|
|
100
|
+
await bus.drain();
|
|
82
101
|
// Feed script steps
|
|
83
102
|
for (const step of steps) {
|
|
84
103
|
if (!running)
|
|
85
104
|
break;
|
|
86
105
|
if (step.delay && step.delay > 0) {
|
|
87
|
-
await
|
|
106
|
+
await sleep(clock, step.delay);
|
|
88
107
|
}
|
|
89
108
|
if (!running)
|
|
90
109
|
break;
|
|
@@ -92,6 +111,9 @@ export async function runScript(app, steps, options) {
|
|
|
92
111
|
const keyMsg = parseKey(step.key);
|
|
93
112
|
bus.emit(keyMsg);
|
|
94
113
|
}
|
|
114
|
+
else if ('pulse' in step) {
|
|
115
|
+
bus.emit({ type: 'pulse', dt: step.pulse.dt });
|
|
116
|
+
}
|
|
95
117
|
else if ('resize' in step) {
|
|
96
118
|
const resizeMsg = {
|
|
97
119
|
type: 'resize',
|
|
@@ -107,19 +129,18 @@ export async function runScript(app, steps, options) {
|
|
|
107
129
|
const _exhaustive = step;
|
|
108
130
|
throw new Error(`runScript: unhandled script step variant: ${JSON.stringify(_exhaustive)}`);
|
|
109
131
|
}
|
|
110
|
-
|
|
111
|
-
await new Promise((r) => queueMicrotask(r));
|
|
132
|
+
await bus.drain();
|
|
112
133
|
}
|
|
113
|
-
|
|
114
|
-
await new Promise((r) => queueMicrotask(r));
|
|
134
|
+
await bus.drain();
|
|
115
135
|
}
|
|
116
136
|
finally {
|
|
137
|
+
bus.stopPulse();
|
|
117
138
|
bus.dispose();
|
|
118
139
|
}
|
|
119
140
|
return {
|
|
120
141
|
model,
|
|
121
142
|
frames,
|
|
122
|
-
elapsed:
|
|
143
|
+
elapsed: clock.now() - start,
|
|
123
144
|
};
|
|
124
145
|
}
|
|
125
146
|
//# sourceMappingURL=driver.js.map
|
package/dist/driver.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"driver.js","sourceRoot":"","sources":["../src/driver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"driver.js","sourceRoot":"","sources":["../src/driver.ts"],"names":[],"mappings":"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"}
|
package/dist/eventbus.d.ts
CHANGED
|
@@ -25,14 +25,24 @@
|
|
|
25
25
|
* ```
|
|
26
26
|
*/
|
|
27
27
|
import type { IOPort } from '@flyingrobots/bijou';
|
|
28
|
-
import
|
|
28
|
+
import { type ClockPort } from '@flyingrobots/bijou';
|
|
29
|
+
import type { Cmd, KeyMsg, MouseMsg, PulseMsg, ResizeMsg } from './types.js';
|
|
29
30
|
/**
|
|
30
31
|
* Union of all message types the bus can carry — built-in key, resize,
|
|
31
|
-
* mouse messages plus any app-defined custom message type.
|
|
32
|
+
* mouse, and pulse messages plus any app-defined custom message type.
|
|
32
33
|
*
|
|
33
34
|
* @template M - Application-defined custom message type.
|
|
34
35
|
*/
|
|
35
|
-
export type BusMsg<M> = KeyMsg | ResizeMsg | MouseMsg | M;
|
|
36
|
+
export type BusMsg<M> = KeyMsg | ResizeMsg | MouseMsg | PulseMsg | M;
|
|
37
|
+
/**
|
|
38
|
+
* Middleware function for intercepting and modifying messages.
|
|
39
|
+
*
|
|
40
|
+
* Call `next(msg)` to continue the message chain. Omitting the call
|
|
41
|
+
* halts message propagation.
|
|
42
|
+
*
|
|
43
|
+
* @template M - Application-defined custom message type.
|
|
44
|
+
*/
|
|
45
|
+
export type Middleware<M> = (msg: BusMsg<M>, next: (msg: BusMsg<M>) => void) => void;
|
|
36
46
|
/**
|
|
37
47
|
* Centralized event bus that unifies all input sources into a single
|
|
38
48
|
* typed event stream for TEA applications.
|
|
@@ -87,6 +97,33 @@ export interface EventBus<M> {
|
|
|
87
97
|
* @returns A disposable that removes this quit handler.
|
|
88
98
|
*/
|
|
89
99
|
onQuit(handler: () => void): Disposable;
|
|
100
|
+
/**
|
|
101
|
+
* Start the system animation heartbeat at the specified frequency.
|
|
102
|
+
* Emits `PulseMsg` to all subscribers.
|
|
103
|
+
*
|
|
104
|
+
* @param fps - Frames per second. Default: 60.
|
|
105
|
+
*/
|
|
106
|
+
startPulse(fps?: number): void;
|
|
107
|
+
/** Stop the system animation heartbeat. */
|
|
108
|
+
stopPulse(): void;
|
|
109
|
+
/**
|
|
110
|
+
* Register a listener for the system heartbeat pulse.
|
|
111
|
+
*
|
|
112
|
+
* @param handler - Callback invoked every pulse with the time delta.
|
|
113
|
+
* @returns A disposable that removes this pulse listener.
|
|
114
|
+
*/
|
|
115
|
+
onPulse(handler: (dt: number) => void): Disposable;
|
|
116
|
+
/**
|
|
117
|
+
* Register a middleware function to intercept or modify messages.
|
|
118
|
+
*
|
|
119
|
+
* Middleware are executed in the order they are registered.
|
|
120
|
+
*
|
|
121
|
+
* @param middleware - The middleware function.
|
|
122
|
+
* @returns A disposable that removes this middleware.
|
|
123
|
+
*/
|
|
124
|
+
use(middleware: Middleware<M>): Disposable;
|
|
125
|
+
/** Resolve once all in-flight commands have settled. */
|
|
126
|
+
drain(): Promise<void>;
|
|
90
127
|
/** Disconnect all sources and remove all subscribers. */
|
|
91
128
|
dispose(): void;
|
|
92
129
|
}
|
|
@@ -96,6 +133,8 @@ export interface CreateEventBusOptions {
|
|
|
96
133
|
onCommandRejected?: (error: unknown) => void;
|
|
97
134
|
/** Called to surface error messages (replaces direct `console.error` usage). */
|
|
98
135
|
onError?: (message: string, error: unknown) => void;
|
|
136
|
+
/** Clock/scheduler override for deterministic command and pulse timing. */
|
|
137
|
+
clock?: ClockPort;
|
|
99
138
|
}
|
|
100
139
|
/** Handle for unsubscribing or disconnecting a resource. */
|
|
101
140
|
interface Disposable {
|
package/dist/eventbus.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eventbus.d.ts","sourceRoot":"","sources":["../src/eventbus.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"eventbus.d.ts","sourceRoot":"","sources":["../src/eventbus.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAA8B,KAAK,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACjF,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAQ7E;;;;;GAKG;AACH,MAAM,MAAM,MAAM,CAAC,CAAC,IAAI,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,CAAC,CAAC;AAErE;;;;;;;GAOG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,KAAK,IAAI,CAAC;AAErF;;;;;GAKG;AACH,MAAM,WAAW,QAAQ,CAAC,CAAC;IACzB;;;;;;OAMG;IACH,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,UAAU,CAAC;IAElD;;;;OAIG;IACH,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAE3B;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,UAAU,CAAC;IAEjE;;;;;;;;;;OAUG;IACH,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAE1B;;;;;;;OAOG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,IAAI,GAAG,UAAU,CAAC;IAExC;;;;;OAKG;IACH,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE/B,2CAA2C;IAC3C,SAAS,IAAI,IAAI,CAAC;IAElB;;;;;OAKG;IACH,OAAO,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,GAAG,UAAU,CAAC;IAEnD;;;;;;;OAOG;IACH,GAAG,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC;IAE3C,wDAAwD;IACxD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvB,yDAAyD;IACzD,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,qDAAqD;AACrD,MAAM,WAAW,qBAAqB;IACpC,6CAA6C;IAC7C,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7C,gFAAgF;IAChF,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACpD,2EAA2E;IAC3E,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAED,4DAA4D;AAC5D,UAAU,UAAU;IAClB,0DAA0D;IAC1D,OAAO,IAAI,IAAI,CAAC;CACjB;AAMD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,UAAU,CAAC,EAAE,qBAAqB,GAAG,QAAQ,CAAC,CAAC,CAAC,CAkQjF"}
|