@opentui/solid 0.1.13 → 0.1.14
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 +109 -79
- package/jsx-runtime.d.ts +17 -15
- package/package.json +2 -2
- package/src/elements/index.d.ts +21 -45
- package/src/elements/text-node.d.ts +1 -0
- package/src/reconciler.d.ts +3 -4
- package/src/types/elements.d.ts +64 -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
|
@@ -37,7 +37,7 @@ var onResize = (callback) => {
|
|
|
37
37
|
};
|
|
38
38
|
var useTerminalDimensions = () => {
|
|
39
39
|
const renderer = useRenderer();
|
|
40
|
-
const [terminalDimensions, setTerminalDimensions] = createSignal({ width: renderer.
|
|
40
|
+
const [terminalDimensions, setTerminalDimensions] = createSignal({ width: renderer.width, height: renderer.height });
|
|
41
41
|
const callback = (width, height) => {
|
|
42
42
|
setTerminalDimensions({ width, height });
|
|
43
43
|
};
|
|
@@ -93,14 +93,21 @@ var useTimeline = (timeline, initialValue, targetValue, options, startTime = 0)
|
|
|
93
93
|
};
|
|
94
94
|
|
|
95
95
|
// src/elements/index.ts
|
|
96
|
-
var
|
|
97
|
-
ascii_font: ASCIIFontRenderable,
|
|
96
|
+
var baseComponents = {
|
|
98
97
|
box: BoxRenderable,
|
|
98
|
+
text: TextRenderable,
|
|
99
99
|
input: InputRenderable,
|
|
100
100
|
select: SelectRenderable,
|
|
101
|
-
|
|
102
|
-
|
|
101
|
+
ascii_font: ASCIIFontRenderable,
|
|
102
|
+
tab_select: TabSelectRenderable
|
|
103
103
|
};
|
|
104
|
+
var componentCatalogue = { ...baseComponents };
|
|
105
|
+
function extend(objects) {
|
|
106
|
+
Object.assign(componentCatalogue, objects);
|
|
107
|
+
}
|
|
108
|
+
function getComponentCatalogue() {
|
|
109
|
+
return componentCatalogue;
|
|
110
|
+
}
|
|
104
111
|
|
|
105
112
|
// src/reconciler.ts
|
|
106
113
|
import {
|
|
@@ -114,6 +121,7 @@ import {
|
|
|
114
121
|
TabSelectRenderableEvents,
|
|
115
122
|
TextRenderable as TextRenderable3
|
|
116
123
|
} from "@opentui/core";
|
|
124
|
+
import { useContext as useContext2 } from "solid-js";
|
|
117
125
|
import { createRenderer } from "solid-js/universal";
|
|
118
126
|
|
|
119
127
|
// src/elements/text-node.ts
|
|
@@ -140,6 +148,9 @@ var log = (...args) => {
|
|
|
140
148
|
// src/elements/text-node.ts
|
|
141
149
|
var GHOST_NODE_TAG = "text-ghost";
|
|
142
150
|
var ChunkToTextNodeMap = new WeakMap;
|
|
151
|
+
var isTextChunk = (node) => {
|
|
152
|
+
return typeof node === "object" && "__isChunk" in node;
|
|
153
|
+
};
|
|
143
154
|
|
|
144
155
|
class TextNode {
|
|
145
156
|
id;
|
|
@@ -193,6 +204,7 @@ class TextNode {
|
|
|
193
204
|
}
|
|
194
205
|
}
|
|
195
206
|
textParent.content = styledText;
|
|
207
|
+
textParent.visible = styledText.toString() !== "";
|
|
196
208
|
this.parent = parent;
|
|
197
209
|
}
|
|
198
210
|
remove(parent) {
|
|
@@ -251,9 +263,27 @@ class GhostTextRenderable extends TextRenderable2 {
|
|
|
251
263
|
}
|
|
252
264
|
|
|
253
265
|
// src/reconciler.ts
|
|
254
|
-
|
|
266
|
+
var logId = (node) => {
|
|
267
|
+
if (!node)
|
|
268
|
+
return;
|
|
269
|
+
if (isTextChunk(node)) {
|
|
270
|
+
return node.plainText;
|
|
271
|
+
}
|
|
272
|
+
return node.id;
|
|
273
|
+
};
|
|
255
274
|
function _insertNode(parent, node, anchor) {
|
|
256
|
-
log("Inserting node:", node
|
|
275
|
+
log("Inserting node:", logId(node), "into parent:", logId(parent), "with anchor:", logId(anchor), node instanceof TextNode);
|
|
276
|
+
if (node instanceof StyledText) {
|
|
277
|
+
log("Inserting styled text:", node.toString());
|
|
278
|
+
for (const chunk of node.chunks) {
|
|
279
|
+
_insertNode(parent, _createTextNode(chunk), anchor);
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
if (isTextChunk(node)) {
|
|
284
|
+
_insertNode(parent, _createTextNode(node), anchor);
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
257
287
|
if (node instanceof TextNode) {
|
|
258
288
|
return node.insert(parent, anchor);
|
|
259
289
|
}
|
|
@@ -261,6 +291,10 @@ function _insertNode(parent, node, anchor) {
|
|
|
261
291
|
return;
|
|
262
292
|
}
|
|
263
293
|
if (anchor) {
|
|
294
|
+
if (isTextChunk(anchor)) {
|
|
295
|
+
console.warn("Cannot add non text node with text chunk anchor");
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
264
298
|
const anchorIndex = parent.getChildren().findIndex((el) => {
|
|
265
299
|
if (anchor instanceof TextNode) {
|
|
266
300
|
return el.id === anchor.textParent?.id;
|
|
@@ -273,7 +307,20 @@ function _insertNode(parent, node, anchor) {
|
|
|
273
307
|
}
|
|
274
308
|
}
|
|
275
309
|
function _removeNode(parent, node) {
|
|
276
|
-
log("Removing node:", node
|
|
310
|
+
log("Removing node:", logId(node), "from parent:", logId(parent));
|
|
311
|
+
if (isTextChunk(node)) {
|
|
312
|
+
const textNode = TextNode.getTextNodeFromChunk(node);
|
|
313
|
+
if (textNode) {
|
|
314
|
+
_removeNode(parent, textNode);
|
|
315
|
+
}
|
|
316
|
+
} else if (node instanceof StyledText) {
|
|
317
|
+
for (const chunk of node.chunks) {
|
|
318
|
+
const textNode = TextNode.getTextNodeFromChunk(chunk);
|
|
319
|
+
if (!textNode)
|
|
320
|
+
continue;
|
|
321
|
+
_removeNode(parent, textNode);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
277
324
|
if (node instanceof TextNode) {
|
|
278
325
|
return node.remove(parent);
|
|
279
326
|
}
|
|
@@ -282,6 +329,16 @@ function _removeNode(parent, node) {
|
|
|
282
329
|
node.destroyRecursively();
|
|
283
330
|
}
|
|
284
331
|
}
|
|
332
|
+
function _createTextNode(value) {
|
|
333
|
+
log("Creating text node:", value);
|
|
334
|
+
const chunk = value && isTextChunk(value) ? value : {
|
|
335
|
+
__isChunk: true,
|
|
336
|
+
text: new TextEncoder().encode(`${value}`),
|
|
337
|
+
plainText: `${value}`
|
|
338
|
+
};
|
|
339
|
+
const textNode = new TextNode(chunk);
|
|
340
|
+
return textNode;
|
|
341
|
+
}
|
|
285
342
|
var {
|
|
286
343
|
render: _render,
|
|
287
344
|
effect,
|
|
@@ -290,7 +347,7 @@ var {
|
|
|
290
347
|
createElement,
|
|
291
348
|
createTextNode,
|
|
292
349
|
insertNode,
|
|
293
|
-
insert
|
|
350
|
+
insert,
|
|
294
351
|
spread,
|
|
295
352
|
setProp,
|
|
296
353
|
mergeProps,
|
|
@@ -303,24 +360,23 @@ var {
|
|
|
303
360
|
if (!solidRenderer) {
|
|
304
361
|
throw new Error("No renderer found");
|
|
305
362
|
}
|
|
363
|
+
const elements = getComponentCatalogue();
|
|
364
|
+
if (!elements[tagName]) {
|
|
365
|
+
throw new Error(`[Reconciler] Unknown component type: ${tagName}`);
|
|
366
|
+
}
|
|
306
367
|
const element = new elements[tagName](solidRenderer, { id });
|
|
307
368
|
log("Element created with id:", id);
|
|
308
369
|
return element;
|
|
309
370
|
},
|
|
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
|
-
},
|
|
371
|
+
createTextNode: _createTextNode,
|
|
320
372
|
replaceText(textNode, value) {
|
|
321
|
-
log("Replacing text:", value, "in node:", textNode
|
|
373
|
+
log("Replacing text:", value, "in node:", logId(textNode));
|
|
322
374
|
if (textNode instanceof Renderable2)
|
|
323
375
|
return;
|
|
376
|
+
if (isTextChunk(textNode)) {
|
|
377
|
+
console.warn("Cannot replace text on text chunk", logId(textNode));
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
324
380
|
const newChunk = {
|
|
325
381
|
__isChunk: true,
|
|
326
382
|
text: new TextEncoder().encode(value),
|
|
@@ -329,8 +385,8 @@ var {
|
|
|
329
385
|
textNode.replaceText(newChunk);
|
|
330
386
|
},
|
|
331
387
|
setProperty(node, name, value, prev) {
|
|
332
|
-
if (node instanceof TextNode) {
|
|
333
|
-
console.warn("Cannot set property on text node:", node
|
|
388
|
+
if (node instanceof TextNode || isTextChunk(node)) {
|
|
389
|
+
console.warn("Cannot set property on text node:", logId(node));
|
|
334
390
|
return;
|
|
335
391
|
}
|
|
336
392
|
if (name.startsWith("on:")) {
|
|
@@ -427,18 +483,25 @@ var {
|
|
|
427
483
|
},
|
|
428
484
|
insertNode: _insertNode,
|
|
429
485
|
removeNode: _removeNode,
|
|
430
|
-
getParentNode(
|
|
431
|
-
log("Getting parent of node:",
|
|
486
|
+
getParentNode(childNode) {
|
|
487
|
+
log("Getting parent of node:", logId(childNode));
|
|
488
|
+
let node = childNode;
|
|
489
|
+
if (isTextChunk(childNode)) {
|
|
490
|
+
const parentTextNode = TextNode.getTextNodeFromChunk(childNode);
|
|
491
|
+
if (!parentTextNode)
|
|
492
|
+
return;
|
|
493
|
+
node = parentTextNode;
|
|
494
|
+
}
|
|
432
495
|
const parent = node.parent;
|
|
433
496
|
if (!parent) {
|
|
434
|
-
log("No parent found for node:", node
|
|
497
|
+
log("No parent found for node:", logId(node));
|
|
435
498
|
return;
|
|
436
499
|
}
|
|
437
|
-
log("Parent found:", parent
|
|
500
|
+
log("Parent found:", logId(parent), "for node:", logId(node));
|
|
438
501
|
return parent;
|
|
439
502
|
},
|
|
440
503
|
getFirstChild(node) {
|
|
441
|
-
log("Getting first child of node:", node
|
|
504
|
+
log("Getting first child of node:", logId(node));
|
|
442
505
|
if (node instanceof TextRenderable3) {
|
|
443
506
|
const chunk = node.content.chunks[0];
|
|
444
507
|
if (chunk) {
|
|
@@ -447,22 +510,26 @@ var {
|
|
|
447
510
|
return;
|
|
448
511
|
}
|
|
449
512
|
}
|
|
450
|
-
if (node instanceof TextNode) {
|
|
513
|
+
if (node instanceof TextNode || isTextChunk(node)) {
|
|
451
514
|
return;
|
|
452
515
|
}
|
|
453
516
|
const firstChild = node.getChildren()[0];
|
|
454
517
|
if (!firstChild) {
|
|
455
|
-
log("No first child found for node:", node
|
|
518
|
+
log("No first child found for node:", logId(node));
|
|
456
519
|
return;
|
|
457
520
|
}
|
|
458
|
-
log("First child found:", firstChild
|
|
521
|
+
log("First child found:", logId(firstChild), "for node:", logId(node));
|
|
459
522
|
return firstChild;
|
|
460
523
|
},
|
|
461
524
|
getNextSibling(node) {
|
|
462
|
-
log("Getting next sibling of node:", node
|
|
525
|
+
log("Getting next sibling of node:", logId(node));
|
|
526
|
+
if (isTextChunk(node)) {
|
|
527
|
+
console.warn("Cannot get next sibling of text chunk");
|
|
528
|
+
return;
|
|
529
|
+
}
|
|
463
530
|
const parent = node.parent;
|
|
464
531
|
if (!parent) {
|
|
465
|
-
log("No parent found for node:", node
|
|
532
|
+
log("No parent found for node:", logId(node));
|
|
466
533
|
return;
|
|
467
534
|
}
|
|
468
535
|
if (node instanceof TextNode) {
|
|
@@ -470,73 +537,34 @@ var {
|
|
|
470
537
|
const siblings2 = parent.content.chunks;
|
|
471
538
|
const index2 = siblings2.indexOf(node.chunk);
|
|
472
539
|
if (index2 === -1 || index2 === siblings2.length - 1) {
|
|
473
|
-
log("No next sibling found for node:", node
|
|
540
|
+
log("No next sibling found for node:", logId(node));
|
|
474
541
|
return;
|
|
475
542
|
}
|
|
476
543
|
const nextSibling2 = siblings2[index2 + 1];
|
|
477
544
|
if (!nextSibling2) {
|
|
478
|
-
log("Next sibling is null for node:", node
|
|
545
|
+
log("Next sibling is null for node:", logId(node));
|
|
479
546
|
return;
|
|
480
547
|
}
|
|
481
548
|
return TextNode.getTextNodeFromChunk(nextSibling2);
|
|
482
549
|
}
|
|
483
|
-
console.warn("Text parent is not a text node:", node
|
|
550
|
+
console.warn("Text parent is not a text node:", logId(node));
|
|
484
551
|
return;
|
|
485
552
|
}
|
|
486
553
|
const siblings = parent.getChildren();
|
|
487
554
|
const index = siblings.indexOf(node);
|
|
488
555
|
if (index === -1 || index === siblings.length - 1) {
|
|
489
|
-
log("No next sibling found for node:", node
|
|
556
|
+
log("No next sibling found for node:", logId(node));
|
|
490
557
|
return;
|
|
491
558
|
}
|
|
492
559
|
const nextSibling = siblings[index + 1];
|
|
493
560
|
if (!nextSibling) {
|
|
494
|
-
log("Next sibling is null for node:", node
|
|
561
|
+
log("Next sibling is null for node:", logId(node));
|
|
495
562
|
return;
|
|
496
563
|
}
|
|
497
|
-
log("Next sibling found:", nextSibling
|
|
564
|
+
log("Next sibling found:", logId(nextSibling), "for node:", logId(node));
|
|
498
565
|
return nextSibling;
|
|
499
566
|
}
|
|
500
567
|
});
|
|
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
568
|
|
|
541
569
|
// index.ts
|
|
542
570
|
var render = async (node, renderConfig = {}) => {
|
|
@@ -558,7 +586,6 @@ export {
|
|
|
558
586
|
useKeyHandler,
|
|
559
587
|
use,
|
|
560
588
|
spread,
|
|
561
|
-
solidUniversalInsert,
|
|
562
589
|
setProp,
|
|
563
590
|
render,
|
|
564
591
|
onResize,
|
|
@@ -566,12 +593,15 @@ export {
|
|
|
566
593
|
memo,
|
|
567
594
|
insertNode,
|
|
568
595
|
insert,
|
|
569
|
-
|
|
596
|
+
getComponentCatalogue,
|
|
597
|
+
extend,
|
|
570
598
|
effect,
|
|
571
599
|
createTextNode,
|
|
572
600
|
createElement,
|
|
573
601
|
createComponentTimeline,
|
|
574
602
|
createComponent,
|
|
603
|
+
componentCatalogue,
|
|
604
|
+
baseComponents,
|
|
575
605
|
_render,
|
|
576
606
|
RendererContext
|
|
577
607
|
};
|
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.14",
|
|
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.14",
|
|
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/index.d.ts
CHANGED
|
@@ -1,52 +1,28 @@
|
|
|
1
|
-
import type { ASCIIFontOptions, BoxOptions, InputRenderableOptions, Renderable, RenderableOptions, SelectOption, SelectRenderableOptions, StyledText, TabSelectOption, TabSelectRenderableOptions, TextChunk, TextOptions } from "@opentui/core";
|
|
2
1
|
import { ASCIIFontRenderable, BoxRenderable, InputRenderable, SelectRenderable, TabSelectRenderable, TextRenderable } from "@opentui/core";
|
|
3
|
-
import type {
|
|
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
|
-
text: typeof TextRenderable;
|
|
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>;
|
|
48
11
|
};
|
|
49
|
-
|
|
50
|
-
export
|
|
51
|
-
|
|
52
|
-
|
|
12
|
+
type ComponentCatalogue = Record<string, RenderableConstructor>;
|
|
13
|
+
export declare const componentCatalogue: ComponentCatalogue;
|
|
14
|
+
/**
|
|
15
|
+
* Extend the component catalogue with new renderable components
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* // Extend with an object of components
|
|
20
|
+
* extend({
|
|
21
|
+
* consoleButton: ConsoleButtonRenderable,
|
|
22
|
+
* customBox: CustomBoxRenderable
|
|
23
|
+
* })
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare function extend<T extends ComponentCatalogue>(objects: T): void;
|
|
27
|
+
export declare function getComponentCatalogue(): ComponentCatalogue;
|
|
28
|
+
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,64 @@
|
|
|
1
|
+
import type { ASCIIFontOptions, ASCIIFontRenderable, BoxOptions, BoxRenderable, InputRenderable, InputRenderableOptions, Renderable, RenderableOptions, RenderContext, 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
|
+
/** Convert renderable constructor to component props with proper style exclusions */
|
|
49
|
+
export type ExtendedComponentProps<TConstructor extends RenderableConstructor, TOptions = ExtractRenderableOptions<TConstructor>> = TOptions & {
|
|
50
|
+
children?: JSX.Element;
|
|
51
|
+
style?: Partial<Omit<TOptions, GetNonStyledProperties<TConstructor>>>;
|
|
52
|
+
} & ElementProps<ExtractRenderable<TConstructor>>;
|
|
53
|
+
/** Helper type to create JSX element properties from a component catalogue */
|
|
54
|
+
export type ExtendedIntrinsicElements<TComponentCatalogue extends Record<string, RenderableConstructor>> = {
|
|
55
|
+
[TComponentName in keyof TComponentCatalogue]: ExtendedComponentProps<TComponentCatalogue[TComponentName]>;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Global augmentation interface for extended components
|
|
59
|
+
* This will be augmented by user code using module augmentation
|
|
60
|
+
*/
|
|
61
|
+
export interface OpenTUIComponents {
|
|
62
|
+
[componentName: string]: RenderableConstructor;
|
|
63
|
+
}
|
|
64
|
+
export {};
|