@opentui/solid 0.1.13 → 0.1.15
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/index.d.ts +1 -0
- package/index.js +113 -79
- package/jsx-runtime.d.ts +17 -15
- package/package.json +2 -2
- package/src/elements/hooks.d.ts +4 -0
- package/src/elements/index.d.ts +23 -46
- package/src/elements/text-node.d.ts +1 -0
- package/src/reconciler.d.ts +3 -4
- package/src/types/elements.d.ts +67 -0
package/index.d.ts
CHANGED
|
@@ -3,4 +3,5 @@ import type { JSX } from "./jsx-runtime";
|
|
|
3
3
|
export declare const render: (node: () => JSX.Element, renderConfig?: CliRendererConfig) => Promise<void>;
|
|
4
4
|
export * from "./src/reconciler";
|
|
5
5
|
export * from "./src/elements";
|
|
6
|
+
export * from "./src/types/elements";
|
|
6
7
|
export { type JSX };
|
package/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
ASCIIFontRenderable,
|
|
8
8
|
BoxRenderable,
|
|
9
9
|
InputRenderable,
|
|
10
|
+
ScrollBoxRenderable,
|
|
10
11
|
SelectRenderable,
|
|
11
12
|
TabSelectRenderable,
|
|
12
13
|
TextRenderable
|
|
@@ -37,14 +38,14 @@ var onResize = (callback) => {
|
|
|
37
38
|
};
|
|
38
39
|
var useTerminalDimensions = () => {
|
|
39
40
|
const renderer = useRenderer();
|
|
40
|
-
const [terminalDimensions, setTerminalDimensions] = createSignal({ width: renderer.
|
|
41
|
+
const [terminalDimensions, setTerminalDimensions] = createSignal({ width: renderer.width, height: renderer.height });
|
|
41
42
|
const callback = (width, height) => {
|
|
42
43
|
setTerminalDimensions({ width, height });
|
|
43
44
|
};
|
|
44
45
|
onResize(callback);
|
|
45
46
|
return terminalDimensions;
|
|
46
47
|
};
|
|
47
|
-
var
|
|
48
|
+
var useKeyboard = (callback) => {
|
|
48
49
|
const keyHandler = getKeyHandler();
|
|
49
50
|
onMount(() => {
|
|
50
51
|
keyHandler.on("keypress", callback);
|
|
@@ -53,6 +54,7 @@ var useKeyHandler = (callback) => {
|
|
|
53
54
|
keyHandler.off("keypress", callback);
|
|
54
55
|
});
|
|
55
56
|
};
|
|
57
|
+
var useKeyHandler = useKeyboard;
|
|
56
58
|
var useSelectionHandler = (callback) => {
|
|
57
59
|
const renderer = useRenderer();
|
|
58
60
|
onMount(() => {
|
|
@@ -93,14 +95,22 @@ var useTimeline = (timeline, initialValue, targetValue, options, startTime = 0)
|
|
|
93
95
|
};
|
|
94
96
|
|
|
95
97
|
// src/elements/index.ts
|
|
96
|
-
var
|
|
97
|
-
ascii_font: ASCIIFontRenderable,
|
|
98
|
+
var baseComponents = {
|
|
98
99
|
box: BoxRenderable,
|
|
100
|
+
text: TextRenderable,
|
|
99
101
|
input: InputRenderable,
|
|
100
102
|
select: SelectRenderable,
|
|
103
|
+
ascii_font: ASCIIFontRenderable,
|
|
101
104
|
tab_select: TabSelectRenderable,
|
|
102
|
-
|
|
105
|
+
scrollbox: ScrollBoxRenderable
|
|
103
106
|
};
|
|
107
|
+
var componentCatalogue = { ...baseComponents };
|
|
108
|
+
function extend(objects) {
|
|
109
|
+
Object.assign(componentCatalogue, objects);
|
|
110
|
+
}
|
|
111
|
+
function getComponentCatalogue() {
|
|
112
|
+
return componentCatalogue;
|
|
113
|
+
}
|
|
104
114
|
|
|
105
115
|
// src/reconciler.ts
|
|
106
116
|
import {
|
|
@@ -114,6 +124,7 @@ import {
|
|
|
114
124
|
TabSelectRenderableEvents,
|
|
115
125
|
TextRenderable as TextRenderable3
|
|
116
126
|
} from "@opentui/core";
|
|
127
|
+
import { useContext as useContext2 } from "solid-js";
|
|
117
128
|
import { createRenderer } from "solid-js/universal";
|
|
118
129
|
|
|
119
130
|
// src/elements/text-node.ts
|
|
@@ -140,6 +151,9 @@ var log = (...args) => {
|
|
|
140
151
|
// src/elements/text-node.ts
|
|
141
152
|
var GHOST_NODE_TAG = "text-ghost";
|
|
142
153
|
var ChunkToTextNodeMap = new WeakMap;
|
|
154
|
+
var isTextChunk = (node) => {
|
|
155
|
+
return typeof node === "object" && "__isChunk" in node;
|
|
156
|
+
};
|
|
143
157
|
|
|
144
158
|
class TextNode {
|
|
145
159
|
id;
|
|
@@ -193,6 +207,7 @@ class TextNode {
|
|
|
193
207
|
}
|
|
194
208
|
}
|
|
195
209
|
textParent.content = styledText;
|
|
210
|
+
textParent.visible = styledText.toString() !== "";
|
|
196
211
|
this.parent = parent;
|
|
197
212
|
}
|
|
198
213
|
remove(parent) {
|
|
@@ -251,9 +266,27 @@ class GhostTextRenderable extends TextRenderable2 {
|
|
|
251
266
|
}
|
|
252
267
|
|
|
253
268
|
// src/reconciler.ts
|
|
254
|
-
|
|
269
|
+
var logId = (node) => {
|
|
270
|
+
if (!node)
|
|
271
|
+
return;
|
|
272
|
+
if (isTextChunk(node)) {
|
|
273
|
+
return node.plainText;
|
|
274
|
+
}
|
|
275
|
+
return node.id;
|
|
276
|
+
};
|
|
255
277
|
function _insertNode(parent, node, anchor) {
|
|
256
|
-
log("Inserting node:", node
|
|
278
|
+
log("Inserting node:", logId(node), "into parent:", logId(parent), "with anchor:", logId(anchor), node instanceof TextNode);
|
|
279
|
+
if (node instanceof StyledText) {
|
|
280
|
+
log("Inserting styled text:", node.toString());
|
|
281
|
+
for (const chunk of node.chunks) {
|
|
282
|
+
_insertNode(parent, _createTextNode(chunk), anchor);
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
if (isTextChunk(node)) {
|
|
287
|
+
_insertNode(parent, _createTextNode(node), anchor);
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
257
290
|
if (node instanceof TextNode) {
|
|
258
291
|
return node.insert(parent, anchor);
|
|
259
292
|
}
|
|
@@ -261,6 +294,10 @@ function _insertNode(parent, node, anchor) {
|
|
|
261
294
|
return;
|
|
262
295
|
}
|
|
263
296
|
if (anchor) {
|
|
297
|
+
if (isTextChunk(anchor)) {
|
|
298
|
+
console.warn("Cannot add non text node with text chunk anchor");
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
264
301
|
const anchorIndex = parent.getChildren().findIndex((el) => {
|
|
265
302
|
if (anchor instanceof TextNode) {
|
|
266
303
|
return el.id === anchor.textParent?.id;
|
|
@@ -273,7 +310,20 @@ function _insertNode(parent, node, anchor) {
|
|
|
273
310
|
}
|
|
274
311
|
}
|
|
275
312
|
function _removeNode(parent, node) {
|
|
276
|
-
log("Removing node:", node
|
|
313
|
+
log("Removing node:", logId(node), "from parent:", logId(parent));
|
|
314
|
+
if (isTextChunk(node)) {
|
|
315
|
+
const textNode = TextNode.getTextNodeFromChunk(node);
|
|
316
|
+
if (textNode) {
|
|
317
|
+
_removeNode(parent, textNode);
|
|
318
|
+
}
|
|
319
|
+
} else if (node instanceof StyledText) {
|
|
320
|
+
for (const chunk of node.chunks) {
|
|
321
|
+
const textNode = TextNode.getTextNodeFromChunk(chunk);
|
|
322
|
+
if (!textNode)
|
|
323
|
+
continue;
|
|
324
|
+
_removeNode(parent, textNode);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
277
327
|
if (node instanceof TextNode) {
|
|
278
328
|
return node.remove(parent);
|
|
279
329
|
}
|
|
@@ -282,6 +332,16 @@ function _removeNode(parent, node) {
|
|
|
282
332
|
node.destroyRecursively();
|
|
283
333
|
}
|
|
284
334
|
}
|
|
335
|
+
function _createTextNode(value) {
|
|
336
|
+
log("Creating text node:", value);
|
|
337
|
+
const chunk = value && isTextChunk(value) ? value : {
|
|
338
|
+
__isChunk: true,
|
|
339
|
+
text: new TextEncoder().encode(`${value}`),
|
|
340
|
+
plainText: `${value}`
|
|
341
|
+
};
|
|
342
|
+
const textNode = new TextNode(chunk);
|
|
343
|
+
return textNode;
|
|
344
|
+
}
|
|
285
345
|
var {
|
|
286
346
|
render: _render,
|
|
287
347
|
effect,
|
|
@@ -290,7 +350,7 @@ var {
|
|
|
290
350
|
createElement,
|
|
291
351
|
createTextNode,
|
|
292
352
|
insertNode,
|
|
293
|
-
insert
|
|
353
|
+
insert,
|
|
294
354
|
spread,
|
|
295
355
|
setProp,
|
|
296
356
|
mergeProps,
|
|
@@ -303,24 +363,23 @@ var {
|
|
|
303
363
|
if (!solidRenderer) {
|
|
304
364
|
throw new Error("No renderer found");
|
|
305
365
|
}
|
|
366
|
+
const elements = getComponentCatalogue();
|
|
367
|
+
if (!elements[tagName]) {
|
|
368
|
+
throw new Error(`[Reconciler] Unknown component type: ${tagName}`);
|
|
369
|
+
}
|
|
306
370
|
const element = new elements[tagName](solidRenderer, { id });
|
|
307
371
|
log("Element created with id:", id);
|
|
308
372
|
return element;
|
|
309
373
|
},
|
|
310
|
-
createTextNode
|
|
311
|
-
log("Creating text node:", value);
|
|
312
|
-
const chunk = typeof value === "object" && "__isChunk" in value ? value : {
|
|
313
|
-
__isChunk: true,
|
|
314
|
-
text: new TextEncoder().encode(`${value}`),
|
|
315
|
-
plainText: `${value}`
|
|
316
|
-
};
|
|
317
|
-
const textNode = new TextNode(chunk);
|
|
318
|
-
return textNode;
|
|
319
|
-
},
|
|
374
|
+
createTextNode: _createTextNode,
|
|
320
375
|
replaceText(textNode, value) {
|
|
321
|
-
log("Replacing text:", value, "in node:", textNode
|
|
376
|
+
log("Replacing text:", value, "in node:", logId(textNode));
|
|
322
377
|
if (textNode instanceof Renderable2)
|
|
323
378
|
return;
|
|
379
|
+
if (isTextChunk(textNode)) {
|
|
380
|
+
console.warn("Cannot replace text on text chunk", logId(textNode));
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
324
383
|
const newChunk = {
|
|
325
384
|
__isChunk: true,
|
|
326
385
|
text: new TextEncoder().encode(value),
|
|
@@ -329,8 +388,8 @@ var {
|
|
|
329
388
|
textNode.replaceText(newChunk);
|
|
330
389
|
},
|
|
331
390
|
setProperty(node, name, value, prev) {
|
|
332
|
-
if (node instanceof TextNode) {
|
|
333
|
-
console.warn("Cannot set property on text node:", node
|
|
391
|
+
if (node instanceof TextNode || isTextChunk(node)) {
|
|
392
|
+
console.warn("Cannot set property on text node:", logId(node));
|
|
334
393
|
return;
|
|
335
394
|
}
|
|
336
395
|
if (name.startsWith("on:")) {
|
|
@@ -427,18 +486,25 @@ var {
|
|
|
427
486
|
},
|
|
428
487
|
insertNode: _insertNode,
|
|
429
488
|
removeNode: _removeNode,
|
|
430
|
-
getParentNode(
|
|
431
|
-
log("Getting parent of node:",
|
|
489
|
+
getParentNode(childNode) {
|
|
490
|
+
log("Getting parent of node:", logId(childNode));
|
|
491
|
+
let node = childNode;
|
|
492
|
+
if (isTextChunk(childNode)) {
|
|
493
|
+
const parentTextNode = TextNode.getTextNodeFromChunk(childNode);
|
|
494
|
+
if (!parentTextNode)
|
|
495
|
+
return;
|
|
496
|
+
node = parentTextNode;
|
|
497
|
+
}
|
|
432
498
|
const parent = node.parent;
|
|
433
499
|
if (!parent) {
|
|
434
|
-
log("No parent found for node:", node
|
|
500
|
+
log("No parent found for node:", logId(node));
|
|
435
501
|
return;
|
|
436
502
|
}
|
|
437
|
-
log("Parent found:", parent
|
|
503
|
+
log("Parent found:", logId(parent), "for node:", logId(node));
|
|
438
504
|
return parent;
|
|
439
505
|
},
|
|
440
506
|
getFirstChild(node) {
|
|
441
|
-
log("Getting first child of node:", node
|
|
507
|
+
log("Getting first child of node:", logId(node));
|
|
442
508
|
if (node instanceof TextRenderable3) {
|
|
443
509
|
const chunk = node.content.chunks[0];
|
|
444
510
|
if (chunk) {
|
|
@@ -447,22 +513,26 @@ var {
|
|
|
447
513
|
return;
|
|
448
514
|
}
|
|
449
515
|
}
|
|
450
|
-
if (node instanceof TextNode) {
|
|
516
|
+
if (node instanceof TextNode || isTextChunk(node)) {
|
|
451
517
|
return;
|
|
452
518
|
}
|
|
453
519
|
const firstChild = node.getChildren()[0];
|
|
454
520
|
if (!firstChild) {
|
|
455
|
-
log("No first child found for node:", node
|
|
521
|
+
log("No first child found for node:", logId(node));
|
|
456
522
|
return;
|
|
457
523
|
}
|
|
458
|
-
log("First child found:", firstChild
|
|
524
|
+
log("First child found:", logId(firstChild), "for node:", logId(node));
|
|
459
525
|
return firstChild;
|
|
460
526
|
},
|
|
461
527
|
getNextSibling(node) {
|
|
462
|
-
log("Getting next sibling of node:", node
|
|
528
|
+
log("Getting next sibling of node:", logId(node));
|
|
529
|
+
if (isTextChunk(node)) {
|
|
530
|
+
console.warn("Cannot get next sibling of text chunk");
|
|
531
|
+
return;
|
|
532
|
+
}
|
|
463
533
|
const parent = node.parent;
|
|
464
534
|
if (!parent) {
|
|
465
|
-
log("No parent found for node:", node
|
|
535
|
+
log("No parent found for node:", logId(node));
|
|
466
536
|
return;
|
|
467
537
|
}
|
|
468
538
|
if (node instanceof TextNode) {
|
|
@@ -470,73 +540,34 @@ var {
|
|
|
470
540
|
const siblings2 = parent.content.chunks;
|
|
471
541
|
const index2 = siblings2.indexOf(node.chunk);
|
|
472
542
|
if (index2 === -1 || index2 === siblings2.length - 1) {
|
|
473
|
-
log("No next sibling found for node:", node
|
|
543
|
+
log("No next sibling found for node:", logId(node));
|
|
474
544
|
return;
|
|
475
545
|
}
|
|
476
546
|
const nextSibling2 = siblings2[index2 + 1];
|
|
477
547
|
if (!nextSibling2) {
|
|
478
|
-
log("Next sibling is null for node:", node
|
|
548
|
+
log("Next sibling is null for node:", logId(node));
|
|
479
549
|
return;
|
|
480
550
|
}
|
|
481
551
|
return TextNode.getTextNodeFromChunk(nextSibling2);
|
|
482
552
|
}
|
|
483
|
-
console.warn("Text parent is not a text node:", node
|
|
553
|
+
console.warn("Text parent is not a text node:", logId(node));
|
|
484
554
|
return;
|
|
485
555
|
}
|
|
486
556
|
const siblings = parent.getChildren();
|
|
487
557
|
const index = siblings.indexOf(node);
|
|
488
558
|
if (index === -1 || index === siblings.length - 1) {
|
|
489
|
-
log("No next sibling found for node:", node
|
|
559
|
+
log("No next sibling found for node:", logId(node));
|
|
490
560
|
return;
|
|
491
561
|
}
|
|
492
562
|
const nextSibling = siblings[index + 1];
|
|
493
563
|
if (!nextSibling) {
|
|
494
|
-
log("Next sibling is null for node:", node
|
|
564
|
+
log("Next sibling is null for node:", logId(node));
|
|
495
565
|
return;
|
|
496
566
|
}
|
|
497
|
-
log("Next sibling found:", nextSibling
|
|
567
|
+
log("Next sibling found:", logId(nextSibling), "for node:", logId(node));
|
|
498
568
|
return nextSibling;
|
|
499
569
|
}
|
|
500
570
|
});
|
|
501
|
-
var insertStyledText = (parent, value, current, marker) => {
|
|
502
|
-
while (typeof current === "function")
|
|
503
|
-
current = current();
|
|
504
|
-
if (value === current)
|
|
505
|
-
return current;
|
|
506
|
-
if (current) {
|
|
507
|
-
if (typeof current === "object" && "__isChunk" in current) {
|
|
508
|
-
const node = TextNode.getTextNodeFromChunk(current);
|
|
509
|
-
if (node) {
|
|
510
|
-
_removeNode(parent, node);
|
|
511
|
-
}
|
|
512
|
-
} else if (current instanceof StyledText) {
|
|
513
|
-
for (const chunk of current.chunks) {
|
|
514
|
-
const chunkNode = TextNode.getTextNodeFromChunk(chunk);
|
|
515
|
-
if (!chunkNode)
|
|
516
|
-
continue;
|
|
517
|
-
_removeNode(parent, chunkNode);
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
if (value instanceof StyledText) {
|
|
522
|
-
log("Inserting styled text:", value.toString());
|
|
523
|
-
for (const chunk of value.chunks) {
|
|
524
|
-
insertNode(parent, createTextNode(chunk), marker);
|
|
525
|
-
}
|
|
526
|
-
return value;
|
|
527
|
-
} else if (value && typeof value === "object" && "__isChunk" in value) {
|
|
528
|
-
insertNode(parent, createTextNode(value), marker);
|
|
529
|
-
return value;
|
|
530
|
-
}
|
|
531
|
-
return solidUniversalInsert(parent, value, marker, current);
|
|
532
|
-
};
|
|
533
|
-
var insert = (parent, accessor, marker, initial) => {
|
|
534
|
-
if (marker !== undefined && !initial)
|
|
535
|
-
initial = [];
|
|
536
|
-
if (typeof accessor !== "function")
|
|
537
|
-
return insertStyledText(parent, accessor, initial, marker);
|
|
538
|
-
effect((current) => insertStyledText(parent, accessor(), current, marker), initial);
|
|
539
|
-
};
|
|
540
571
|
|
|
541
572
|
// index.ts
|
|
542
573
|
var render = async (node, renderConfig = {}) => {
|
|
@@ -555,10 +586,10 @@ export {
|
|
|
555
586
|
useTerminalDimensions,
|
|
556
587
|
useSelectionHandler,
|
|
557
588
|
useRenderer,
|
|
589
|
+
useKeyboard,
|
|
558
590
|
useKeyHandler,
|
|
559
591
|
use,
|
|
560
592
|
spread,
|
|
561
|
-
solidUniversalInsert,
|
|
562
593
|
setProp,
|
|
563
594
|
render,
|
|
564
595
|
onResize,
|
|
@@ -566,12 +597,15 @@ export {
|
|
|
566
597
|
memo,
|
|
567
598
|
insertNode,
|
|
568
599
|
insert,
|
|
569
|
-
|
|
600
|
+
getComponentCatalogue,
|
|
601
|
+
extend,
|
|
570
602
|
effect,
|
|
571
603
|
createTextNode,
|
|
572
604
|
createElement,
|
|
573
605
|
createComponentTimeline,
|
|
574
606
|
createComponent,
|
|
607
|
+
componentCatalogue,
|
|
608
|
+
baseComponents,
|
|
575
609
|
_render,
|
|
576
610
|
RendererContext
|
|
577
611
|
};
|
package/jsx-runtime.d.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { Renderable } from "@opentui/core"
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
import type {
|
|
3
|
+
AsciiFontProps,
|
|
4
|
+
BoxProps,
|
|
5
|
+
ExtendedIntrinsicElements,
|
|
6
|
+
InputProps,
|
|
7
|
+
OpenTUIComponents,
|
|
8
|
+
SelectProps,
|
|
9
|
+
TabSelectProps,
|
|
10
|
+
TextProps,
|
|
11
|
+
} from "./src/types/elements"
|
|
10
12
|
|
|
11
13
|
declare namespace JSX {
|
|
12
14
|
// Replace Node with Renderable
|
|
@@ -14,13 +16,13 @@ declare namespace JSX {
|
|
|
14
16
|
|
|
15
17
|
interface ArrayElement extends Array<Element> {}
|
|
16
18
|
|
|
17
|
-
interface IntrinsicElements {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
input:
|
|
21
|
-
select:
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
interface IntrinsicElements extends ExtendedIntrinsicElements<OpenTUIComponents> {
|
|
20
|
+
box: BoxProps
|
|
21
|
+
text: TextProps
|
|
22
|
+
input: InputProps
|
|
23
|
+
select: SelectProps
|
|
24
|
+
ascii_font: AsciiFontProps
|
|
25
|
+
tab_select: TabSelectProps
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
interface ElementChildrenAttribute {
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"types": "index.d.ts",
|
|
6
6
|
"type": "module",
|
|
7
|
-
"version": "0.1.
|
|
7
|
+
"version": "0.1.15",
|
|
8
8
|
"description": "SolidJS renderer for OpenTUI",
|
|
9
9
|
"license": "MIT",
|
|
10
10
|
"repository": {
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"./jsx-dev-runtime": "./jsx-runtime.d.ts"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@opentui/core": "0.1.
|
|
28
|
+
"@opentui/core": "0.1.15",
|
|
29
29
|
"babel-plugin-module-resolver": "5.0.2",
|
|
30
30
|
"@babel/core": "7.28.0",
|
|
31
31
|
"@babel/preset-typescript": "7.27.1",
|
package/src/elements/hooks.d.ts
CHANGED
|
@@ -6,6 +6,10 @@ export declare const useTerminalDimensions: () => import("solid-js").Accessor<{
|
|
|
6
6
|
width: number;
|
|
7
7
|
height: number;
|
|
8
8
|
}>;
|
|
9
|
+
export declare const useKeyboard: (callback: (key: ParsedKey) => void) => void;
|
|
10
|
+
/**
|
|
11
|
+
* @deprecated renamed to useKeyboard
|
|
12
|
+
*/
|
|
9
13
|
export declare const useKeyHandler: (callback: (key: ParsedKey) => void) => void;
|
|
10
14
|
export declare const useSelectionHandler: (callback: (selection: Selection) => void) => void;
|
|
11
15
|
export declare const createComponentTimeline: (options?: TimelineOptions) => Timeline;
|
package/src/elements/index.d.ts
CHANGED
|
@@ -1,52 +1,29 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import type { JSX, Ref } from "solid-js";
|
|
1
|
+
import { ASCIIFontRenderable, BoxRenderable, InputRenderable, ScrollBoxRenderable, SelectRenderable, TabSelectRenderable, TextRenderable } from "@opentui/core";
|
|
2
|
+
import type { RenderableConstructor } from "../types/elements";
|
|
4
3
|
export * from "./hooks";
|
|
5
|
-
export declare const
|
|
6
|
-
ascii_font: typeof ASCIIFontRenderable;
|
|
4
|
+
export declare const baseComponents: {
|
|
7
5
|
box: typeof BoxRenderable;
|
|
6
|
+
text: typeof TextRenderable;
|
|
8
7
|
input: typeof InputRenderable;
|
|
9
8
|
select: typeof SelectRenderable;
|
|
9
|
+
ascii_font: typeof ASCIIFontRenderable;
|
|
10
10
|
tab_select: typeof TabSelectRenderable;
|
|
11
|
-
|
|
12
|
-
};
|
|
13
|
-
export type Element = keyof typeof elements;
|
|
14
|
-
type RenderableNonStyleKeys = "buffered";
|
|
15
|
-
type ElementProps<T extends RenderableOptions<K>, K extends Renderable = Renderable, NonStyleKeys extends keyof T = RenderableNonStyleKeys> = {
|
|
16
|
-
style?: Omit<T, NonStyleKeys | RenderableNonStyleKeys>;
|
|
17
|
-
ref?: Ref<K>;
|
|
18
|
-
} & T;
|
|
19
|
-
type ContainerProps = {
|
|
20
|
-
children?: JSX.Element;
|
|
21
|
-
};
|
|
22
|
-
export type BoxElementProps = ElementProps<BoxOptions, BoxRenderable, "title"> & ContainerProps;
|
|
23
|
-
export type BoxStyle = BoxElementProps["style"];
|
|
24
|
-
export type InputElementProps = ElementProps<InputRenderableOptions, InputRenderable, "value" | "maxLength" | "placeholder"> & {
|
|
25
|
-
onInput?: (value: string) => void;
|
|
26
|
-
onSubmit?: (value: string) => void;
|
|
27
|
-
onChange?: (value: string) => void;
|
|
28
|
-
focused?: boolean;
|
|
29
|
-
};
|
|
30
|
-
export type InputStyle = InputElementProps["style"];
|
|
31
|
-
type TabSelectEventCallback = (index: number, option: TabSelectOption) => void;
|
|
32
|
-
export type TabSelectElementProps = ElementProps<TabSelectRenderableOptions, TabSelectRenderable, "options" | "showScrollArrows" | "showDescription" | "wrapSelection"> & {
|
|
33
|
-
onSelect?: TabSelectEventCallback;
|
|
34
|
-
onChange?: TabSelectEventCallback;
|
|
35
|
-
focused?: boolean;
|
|
36
|
-
};
|
|
37
|
-
export type TabSelectStyle = TabSelectElementProps["style"];
|
|
38
|
-
type SelectEventCallback = (index: number, option: SelectOption) => void;
|
|
39
|
-
export type SelectElementProps = ElementProps<SelectRenderableOptions, SelectRenderable, "options" | "showScrollIndicator" | "wrapSelection" | "fastScrollStep"> & {
|
|
40
|
-
onSelect?: SelectEventCallback;
|
|
41
|
-
onChange?: SelectEventCallback;
|
|
42
|
-
focused?: boolean;
|
|
43
|
-
};
|
|
44
|
-
export type SelectStyle = SelectElementProps["style"];
|
|
45
|
-
type TextChildTypes = (string & {}) | number | boolean | null | undefined;
|
|
46
|
-
type TextProps = {
|
|
47
|
-
children: TextChildTypes | StyledText | TextChunk | Array<TextChildTypes | TextChunk>;
|
|
11
|
+
scrollbox: typeof ScrollBoxRenderable;
|
|
48
12
|
};
|
|
49
|
-
|
|
50
|
-
export
|
|
51
|
-
|
|
52
|
-
|
|
13
|
+
type ComponentCatalogue = Record<string, RenderableConstructor>;
|
|
14
|
+
export declare const componentCatalogue: ComponentCatalogue;
|
|
15
|
+
/**
|
|
16
|
+
* Extend the component catalogue with new renderable components
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```tsx
|
|
20
|
+
* // Extend with an object of components
|
|
21
|
+
* extend({
|
|
22
|
+
* consoleButton: ConsoleButtonRenderable,
|
|
23
|
+
* customBox: CustomBoxRenderable
|
|
24
|
+
* })
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare function extend<T extends ComponentCatalogue>(objects: T): void;
|
|
28
|
+
export declare function getComponentCatalogue(): ComponentCatalogue;
|
|
29
|
+
export type { ExtendedComponentProps, ExtendedIntrinsicElements, RenderableConstructor } from "../types/elements";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Renderable, TextRenderable, type RenderContext, type TextChunk, type TextOptions } from "@opentui/core";
|
|
2
2
|
import { type DomNode } from "../reconciler";
|
|
3
|
+
export declare const isTextChunk: (node: any) => node is TextChunk;
|
|
3
4
|
/**
|
|
4
5
|
* Represents a text node in the SolidJS reconciler.
|
|
5
6
|
*/
|
package/src/reconciler.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { Renderable } from "@opentui/core";
|
|
1
|
+
import { Renderable, type TextChunk } from "@opentui/core";
|
|
2
2
|
import { TextNode } from "./elements/text-node";
|
|
3
|
-
export type DomNode = Renderable | TextNode;
|
|
4
|
-
export declare const _render: (code: () => DomNode, node: DomNode) => () => void, effect: <T>(fn: (prev?: T) => T, init?: T) => void, memo: <T>(fn: () => T, equal: boolean) => () => T, createComponent: <T>(Comp: (props: T) => DomNode, props: T) => DomNode, createElement: (tag: string) => DomNode, createTextNode: (value: string) => DomNode, insertNode: (parent: DomNode, node: DomNode, anchor?: DomNode | undefined) => void,
|
|
5
|
-
export declare const insert: typeof solidUniversalInsert;
|
|
3
|
+
export type DomNode = Renderable | TextNode | TextChunk;
|
|
4
|
+
export declare const _render: (code: () => DomNode, node: DomNode) => () => void, effect: <T>(fn: (prev?: T) => T, init?: T) => void, memo: <T>(fn: () => T, equal: boolean) => () => T, createComponent: <T>(Comp: (props: T) => DomNode, props: T) => DomNode, createElement: (tag: string) => DomNode, createTextNode: (value: string) => DomNode, insertNode: (parent: DomNode, node: DomNode, anchor?: DomNode | undefined) => void, insert: <T>(parent: any, accessor: T | (() => T), marker?: any | null, initial?: any) => DomNode, spread: <T>(node: any, accessor: (() => T) | T, skipChildren?: boolean) => void, setProp: <T>(node: DomNode, name: string, value: T, prev?: T | undefined) => T, mergeProps: (...sources: unknown[]) => unknown, use: <A, T>(fn: (element: DomNode, arg: A) => T, element: DomNode, arg: A) => T;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { ASCIIFontOptions, ASCIIFontRenderable, BoxOptions, BoxRenderable, InputRenderable, InputRenderableOptions, Renderable, RenderableOptions, RenderContext, ScrollBoxOptions, ScrollBoxRenderable, SelectOption, SelectRenderable, SelectRenderableOptions, StyledText, TabSelectOption, TabSelectRenderable, TabSelectRenderableOptions, TextChunk, TextOptions, TextRenderable } from "@opentui/core";
|
|
2
|
+
import type { JSX, Ref } from "solid-js";
|
|
3
|
+
/** Properties that should not be included in the style prop */
|
|
4
|
+
export type NonStyledProps = "id" | "buffered" | "live" | "enableLayout" | "selectable" | "renderAfter" | "renderBefore" | `on${string}`;
|
|
5
|
+
/** Solid-specific props for all components */
|
|
6
|
+
export type ElementProps<TRenderable = unknown> = {
|
|
7
|
+
ref?: Ref<TRenderable>;
|
|
8
|
+
};
|
|
9
|
+
/** Base type for any renderable constructor */
|
|
10
|
+
export type RenderableConstructor<TRenderable extends Renderable = Renderable> = new (ctx: RenderContext, options: any) => TRenderable;
|
|
11
|
+
/** Extract the options type from a renderable constructor */
|
|
12
|
+
type ExtractRenderableOptions<TConstructor> = TConstructor extends new (ctx: RenderContext, options: infer TOptions) => any ? TOptions : never;
|
|
13
|
+
/** Extract the renderable type from a constructor */
|
|
14
|
+
type ExtractRenderable<TConstructor> = TConstructor extends new (ctx: RenderContext, options: any) => infer TRenderable ? TRenderable : never;
|
|
15
|
+
/** Determine which properties should be excluded from styling for different renderable types */
|
|
16
|
+
export type GetNonStyledProperties<TConstructor> = TConstructor extends RenderableConstructor<TextRenderable> ? NonStyledProps | "content" : TConstructor extends RenderableConstructor<BoxRenderable> ? NonStyledProps | "title" : TConstructor extends RenderableConstructor<ASCIIFontRenderable> ? NonStyledProps | "text" | "selectable" : TConstructor extends RenderableConstructor<InputRenderable> ? NonStyledProps | "placeholder" | "value" : NonStyledProps;
|
|
17
|
+
/** Base props for container components that accept children */
|
|
18
|
+
type ContainerProps<TOptions> = TOptions & {
|
|
19
|
+
children?: JSX.Element;
|
|
20
|
+
};
|
|
21
|
+
/** Smart component props that automatically determine excluded properties */
|
|
22
|
+
type ComponentProps<TOptions extends RenderableOptions<TRenderable>, TRenderable extends Renderable> = TOptions & {
|
|
23
|
+
style?: Partial<Omit<TOptions, GetNonStyledProperties<RenderableConstructor<TRenderable>>>>;
|
|
24
|
+
} & ElementProps<TRenderable>;
|
|
25
|
+
/** Valid text content types for Text component children */
|
|
26
|
+
type TextChildren = (string & {}) | number | boolean | null | undefined;
|
|
27
|
+
export type TextProps = ComponentProps<TextOptions, TextRenderable> & {
|
|
28
|
+
children?: TextChildren | StyledText | TextChunk | Array<TextChildren | StyledText | TextChunk>;
|
|
29
|
+
};
|
|
30
|
+
export type BoxProps = ComponentProps<ContainerProps<BoxOptions>, BoxRenderable>;
|
|
31
|
+
export type InputProps = ComponentProps<InputRenderableOptions, InputRenderable> & {
|
|
32
|
+
focused?: boolean;
|
|
33
|
+
onInput?: (value: string) => void;
|
|
34
|
+
onChange?: (value: string) => void;
|
|
35
|
+
onSubmit?: (value: string) => void;
|
|
36
|
+
};
|
|
37
|
+
export type SelectProps = ComponentProps<SelectRenderableOptions, SelectRenderable> & {
|
|
38
|
+
focused?: boolean;
|
|
39
|
+
onChange?: (index: number, option: SelectOption | null) => void;
|
|
40
|
+
onSelect?: (index: number, option: SelectOption | null) => void;
|
|
41
|
+
};
|
|
42
|
+
export type AsciiFontProps = ComponentProps<ASCIIFontOptions, ASCIIFontRenderable>;
|
|
43
|
+
export type TabSelectProps = ComponentProps<TabSelectRenderableOptions, TabSelectRenderable> & {
|
|
44
|
+
focused?: boolean;
|
|
45
|
+
onChange?: (index: number, option: TabSelectOption | null) => void;
|
|
46
|
+
onSelect?: (index: number, option: TabSelectOption | null) => void;
|
|
47
|
+
};
|
|
48
|
+
export type ScrollBoxProps = ComponentProps<ContainerProps<ScrollBoxOptions>, ScrollBoxRenderable> & {
|
|
49
|
+
focused?: boolean;
|
|
50
|
+
};
|
|
51
|
+
/** Convert renderable constructor to component props with proper style exclusions */
|
|
52
|
+
export type ExtendedComponentProps<TConstructor extends RenderableConstructor, TOptions = ExtractRenderableOptions<TConstructor>> = TOptions & {
|
|
53
|
+
children?: JSX.Element;
|
|
54
|
+
style?: Partial<Omit<TOptions, GetNonStyledProperties<TConstructor>>>;
|
|
55
|
+
} & ElementProps<ExtractRenderable<TConstructor>>;
|
|
56
|
+
/** Helper type to create JSX element properties from a component catalogue */
|
|
57
|
+
export type ExtendedIntrinsicElements<TComponentCatalogue extends Record<string, RenderableConstructor>> = {
|
|
58
|
+
[TComponentName in keyof TComponentCatalogue]: ExtendedComponentProps<TComponentCatalogue[TComponentName]>;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Global augmentation interface for extended components
|
|
62
|
+
* This will be augmented by user code using module augmentation
|
|
63
|
+
*/
|
|
64
|
+
export interface OpenTUIComponents {
|
|
65
|
+
[componentName: string]: RenderableConstructor;
|
|
66
|
+
}
|
|
67
|
+
export {};
|