@opentui/solid 0.1.86 → 0.1.88
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/index.d.ts +4 -0
- package/index.d.ts +5 -3
- package/index.js +208 -39
- package/jsx-runtime.d.ts +1 -1
- package/package.json +10 -4
- package/scripts/preload.ts +1 -1
- package/scripts/runtime-plugin-support.d.ts +1 -0
- package/scripts/runtime-plugin-support.ts +61 -0
- package/scripts/solid-plugin.d.ts +6 -0
- package/scripts/solid-plugin.ts +72 -41
- package/src/elements/extras.d.ts +1 -1
- package/src/elements/index.d.ts +5 -5
- package/src/plugins/slot.d.ts +25 -0
- package/src/reconciler.d.ts +1 -1
- package/src/time-to-first-draw.d.ts +9 -0
package/dist/index.d.ts
CHANGED
|
@@ -52,7 +52,9 @@ export function getComponentCatalogue(): {
|
|
|
52
52
|
export function extend(objects: any): void;
|
|
53
53
|
export var effect: typeof createRenderEffect;
|
|
54
54
|
export var createTextNode: any;
|
|
55
|
+
export function createSolidSlotRegistry(renderer: any, context: any, options?: {}): import("@opentui/core").SlotRegistry<any, object, any>;
|
|
55
56
|
export function createSlotNode(): SlotRenderable;
|
|
57
|
+
export function createSlot(registry: any, options?: {}): (props: any) => any;
|
|
56
58
|
export var createElement: any;
|
|
57
59
|
export function createDynamic(component: any, props: any): import("solid-js").Accessor<any>;
|
|
58
60
|
declare var createComponent2: typeof createComponent;
|
|
@@ -83,6 +85,7 @@ export function _render(code: any, element: any): undefined;
|
|
|
83
85
|
export class UnderlineSpanRenderable extends TextModifierRenderable {
|
|
84
86
|
constructor(options: any);
|
|
85
87
|
}
|
|
88
|
+
export function TimeToFirstDraw(props: any): any;
|
|
86
89
|
export class TextSlotRenderable extends TextNodeRenderable3 {
|
|
87
90
|
constructor(id: any, parent: any);
|
|
88
91
|
slotParent: any;
|
|
@@ -94,6 +97,7 @@ export class SlotRenderable extends SlotBaseRenderable {
|
|
|
94
97
|
destroyed: boolean;
|
|
95
98
|
getSlotChild(parent: any): any;
|
|
96
99
|
}
|
|
100
|
+
export function Slot(props: any): import("solid-js").Accessor<any>;
|
|
97
101
|
export var RendererContext: import("solid-js").Context<any>;
|
|
98
102
|
export function Portal(props: any): SlotRenderable;
|
|
99
103
|
export class LinkRenderable extends SpanRenderable {
|
package/index.d.ts
CHANGED
|
@@ -11,7 +11,9 @@ export declare const testRender: (node: () => JSX.Element, renderConfig?: TestRe
|
|
|
11
11
|
captureSpans: () => import("@opentui/core").CapturedFrame;
|
|
12
12
|
resize: (width: number, height: number) => void;
|
|
13
13
|
}>;
|
|
14
|
-
export * from "./src/reconciler";
|
|
15
|
-
export * from "./src/elements";
|
|
16
|
-
export * from "./src/
|
|
14
|
+
export * from "./src/reconciler.js";
|
|
15
|
+
export * from "./src/elements/index.js";
|
|
16
|
+
export * from "./src/time-to-first-draw.js";
|
|
17
|
+
export * from "./src/plugins/slot.js";
|
|
18
|
+
export * from "./src/types/elements.js";
|
|
17
19
|
export { type JSX };
|
package/index.js
CHANGED
|
@@ -124,6 +124,7 @@ import {
|
|
|
124
124
|
TextNodeRenderable,
|
|
125
125
|
TextRenderable
|
|
126
126
|
} from "@opentui/core";
|
|
127
|
+
import { decodeHTML } from "entities";
|
|
127
128
|
import { useContext as useContext2 } from "solid-js";
|
|
128
129
|
|
|
129
130
|
// src/renderer/universal.js
|
|
@@ -482,7 +483,7 @@ function _createTextNode(value) {
|
|
|
482
483
|
if (typeof value === "number") {
|
|
483
484
|
value = value.toString();
|
|
484
485
|
}
|
|
485
|
-
return TextNode.fromString(value, { id });
|
|
486
|
+
return TextNode.fromString(decodeHTML(value), { id });
|
|
486
487
|
}
|
|
487
488
|
function createSlotNode() {
|
|
488
489
|
const id = getNextId("slot-node");
|
|
@@ -536,7 +537,7 @@ var {
|
|
|
536
537
|
log("Replacing text:", value, "in node:", logId(textNode));
|
|
537
538
|
if (!(textNode instanceof TextNode))
|
|
538
539
|
return;
|
|
539
|
-
textNode.replace(value, 0);
|
|
540
|
+
textNode.replace(decodeHTML(value), 0);
|
|
540
541
|
},
|
|
541
542
|
setProperty(node, name, value, prev) {
|
|
542
543
|
if (name.startsWith("on:")) {
|
|
@@ -642,9 +643,11 @@ var {
|
|
|
642
643
|
}
|
|
643
644
|
break;
|
|
644
645
|
case "text":
|
|
645
|
-
case "content":
|
|
646
|
-
|
|
646
|
+
case "content": {
|
|
647
|
+
const textValue = typeof value === "string" ? value : Array.isArray(value) ? value.join("") : `${value}`;
|
|
648
|
+
node[name] = decodeHTML(textValue);
|
|
647
649
|
break;
|
|
650
|
+
}
|
|
648
651
|
default:
|
|
649
652
|
node[name] = value;
|
|
650
653
|
}
|
|
@@ -930,60 +933,222 @@ function extend(objects) {
|
|
|
930
933
|
function getComponentCatalogue() {
|
|
931
934
|
return componentCatalogue;
|
|
932
935
|
}
|
|
936
|
+
// src/time-to-first-draw.tsx
|
|
937
|
+
import { TimeToFirstDrawRenderable } from "@opentui/core";
|
|
938
|
+
extend({
|
|
939
|
+
time_to_first_draw: TimeToFirstDrawRenderable
|
|
940
|
+
});
|
|
941
|
+
var TimeToFirstDraw = (props) => {
|
|
942
|
+
return (() => {
|
|
943
|
+
var _el$ = createElement("time_to_first_draw");
|
|
944
|
+
spread(_el$, props, false);
|
|
945
|
+
return _el$;
|
|
946
|
+
})();
|
|
947
|
+
};
|
|
948
|
+
// src/plugins/slot.tsx
|
|
949
|
+
import { createSlotRegistry } from "@opentui/core";
|
|
950
|
+
import { children, createMemo as createMemo3, createSignal as createSignal2, ErrorBoundary, For, onCleanup as onCleanup3, splitProps as splitProps2 } from "solid-js";
|
|
951
|
+
function createSolidSlotRegistry(renderer, context, options = {}) {
|
|
952
|
+
return createSlotRegistry(renderer, "solid:slot-registry", context, options);
|
|
953
|
+
}
|
|
954
|
+
function createSlot(registry, options = {}) {
|
|
955
|
+
return function BoundSlot(props) {
|
|
956
|
+
return createComponent2(Slot, mergeProps3(props, {
|
|
957
|
+
registry,
|
|
958
|
+
get pluginFailurePlaceholder() {
|
|
959
|
+
return options.pluginFailurePlaceholder;
|
|
960
|
+
}
|
|
961
|
+
}));
|
|
962
|
+
};
|
|
963
|
+
}
|
|
964
|
+
function Slot(props) {
|
|
965
|
+
const [local, slotProps] = splitProps2(props, ["registry", "name", "mode", "children", "pluginFailurePlaceholder"]);
|
|
966
|
+
const registry = () => local.registry;
|
|
967
|
+
const pluginFailurePlaceholder = () => local.pluginFailurePlaceholder;
|
|
968
|
+
const [version, setVersion] = createSignal2(0);
|
|
969
|
+
const unsubscribe = registry().subscribe(() => {
|
|
970
|
+
setVersion((current) => current + 1);
|
|
971
|
+
});
|
|
972
|
+
onCleanup3(unsubscribe);
|
|
973
|
+
const entries = createMemo3((previousEntries = []) => {
|
|
974
|
+
version();
|
|
975
|
+
const resolvedEntries = registry().resolveEntries(local.name);
|
|
976
|
+
const previousById = new Map(previousEntries.map((entry) => [entry.id, entry]));
|
|
977
|
+
return resolvedEntries.map((entry) => {
|
|
978
|
+
const previousEntry = previousById.get(entry.id);
|
|
979
|
+
if (previousEntry && previousEntry.renderer === entry.renderer) {
|
|
980
|
+
return previousEntry;
|
|
981
|
+
}
|
|
982
|
+
return entry;
|
|
983
|
+
});
|
|
984
|
+
});
|
|
985
|
+
const entryIds = createMemo3(() => entries().map((entry) => entry.id));
|
|
986
|
+
const entriesById = createMemo3(() => new Map(entries().map((entry) => [entry.id, entry])));
|
|
987
|
+
const fallbackChildren = children(() => local.children);
|
|
988
|
+
const slotName = () => String(local.name);
|
|
989
|
+
const renderPluginFailurePlaceholder = (failure, fallbackValue) => {
|
|
990
|
+
if (!pluginFailurePlaceholder()) {
|
|
991
|
+
return fallbackValue;
|
|
992
|
+
}
|
|
993
|
+
try {
|
|
994
|
+
return pluginFailurePlaceholder()(failure);
|
|
995
|
+
} catch (error) {
|
|
996
|
+
registry().reportPluginError({
|
|
997
|
+
pluginId: failure.pluginId,
|
|
998
|
+
slot: failure.slot ?? slotName(),
|
|
999
|
+
phase: "error_placeholder",
|
|
1000
|
+
source: "solid",
|
|
1001
|
+
error
|
|
1002
|
+
});
|
|
1003
|
+
return fallbackValue;
|
|
1004
|
+
}
|
|
1005
|
+
};
|
|
1006
|
+
const renderEntry = (entry, fallbackOnError) => {
|
|
1007
|
+
const fallbackValue = fallbackOnError ?? null;
|
|
1008
|
+
let initialRender;
|
|
1009
|
+
try {
|
|
1010
|
+
initialRender = entry.renderer(registry().context, slotProps);
|
|
1011
|
+
} catch (error) {
|
|
1012
|
+
const failure = registry().reportPluginError({
|
|
1013
|
+
pluginId: entry.id,
|
|
1014
|
+
slot: slotName(),
|
|
1015
|
+
phase: "render",
|
|
1016
|
+
source: "solid",
|
|
1017
|
+
error
|
|
1018
|
+
});
|
|
1019
|
+
return renderPluginFailurePlaceholder(failure, fallbackValue);
|
|
1020
|
+
}
|
|
1021
|
+
const resolvedInitialRender = children(() => initialRender);
|
|
1022
|
+
const hasInitialOutput = resolvedInitialRender.toArray().some((node) => node !== null && node !== undefined && node !== false);
|
|
1023
|
+
if (!hasInitialOutput) {
|
|
1024
|
+
return fallbackValue;
|
|
1025
|
+
}
|
|
1026
|
+
return createComponent2(ErrorBoundary, {
|
|
1027
|
+
fallback: (error) => {
|
|
1028
|
+
const failure = registry().reportPluginError({
|
|
1029
|
+
pluginId: entry.id,
|
|
1030
|
+
slot: slotName(),
|
|
1031
|
+
phase: "render",
|
|
1032
|
+
source: "solid",
|
|
1033
|
+
error
|
|
1034
|
+
});
|
|
1035
|
+
return renderPluginFailurePlaceholder(failure, fallbackValue);
|
|
1036
|
+
},
|
|
1037
|
+
get children() {
|
|
1038
|
+
return resolvedInitialRender();
|
|
1039
|
+
}
|
|
1040
|
+
});
|
|
1041
|
+
};
|
|
1042
|
+
const AppendEntry = (appendProps) => {
|
|
1043
|
+
const entry = createMemo3(() => entriesById().get(appendProps.entryId));
|
|
1044
|
+
return memo2(() => {
|
|
1045
|
+
const resolvedEntry = entry();
|
|
1046
|
+
if (!resolvedEntry) {
|
|
1047
|
+
return null;
|
|
1048
|
+
}
|
|
1049
|
+
return renderEntry(resolvedEntry);
|
|
1050
|
+
});
|
|
1051
|
+
};
|
|
1052
|
+
const appendView = [memo2(fallbackChildren), createComponent2(For, {
|
|
1053
|
+
get each() {
|
|
1054
|
+
return entryIds();
|
|
1055
|
+
},
|
|
1056
|
+
children: (entryId) => createComponent2(AppendEntry, {
|
|
1057
|
+
entryId
|
|
1058
|
+
})
|
|
1059
|
+
})];
|
|
1060
|
+
return memo2(() => {
|
|
1061
|
+
const resolvedEntries = entries();
|
|
1062
|
+
const mode = local.mode ?? "append";
|
|
1063
|
+
const fallback = fallbackChildren();
|
|
1064
|
+
if (resolvedEntries.length === 0) {
|
|
1065
|
+
return fallback;
|
|
1066
|
+
}
|
|
1067
|
+
if (mode === "single_winner") {
|
|
1068
|
+
const winner = resolvedEntries[0];
|
|
1069
|
+
if (!winner) {
|
|
1070
|
+
return fallback;
|
|
1071
|
+
}
|
|
1072
|
+
return renderEntry(winner, fallback);
|
|
1073
|
+
}
|
|
1074
|
+
if (mode === "replace") {
|
|
1075
|
+
const renderedEntries = resolvedEntries.map((entry) => renderEntry(entry));
|
|
1076
|
+
const hasPluginOutput = renderedEntries.some((entry) => entry !== null && entry !== undefined && entry !== false);
|
|
1077
|
+
if (!hasPluginOutput) {
|
|
1078
|
+
return fallback;
|
|
1079
|
+
}
|
|
1080
|
+
return renderedEntries;
|
|
1081
|
+
}
|
|
1082
|
+
return appendView;
|
|
1083
|
+
});
|
|
1084
|
+
}
|
|
933
1085
|
|
|
934
1086
|
// index.ts
|
|
935
|
-
var
|
|
936
|
-
let isDisposed = false;
|
|
1087
|
+
var mountSolidRoot = (renderer, node) => {
|
|
937
1088
|
let dispose;
|
|
1089
|
+
let disposeRequested = false;
|
|
1090
|
+
let disposed = false;
|
|
1091
|
+
let mounting = true;
|
|
1092
|
+
let destroyRequested = false;
|
|
1093
|
+
const originalDestroy = renderer.destroy.bind(renderer);
|
|
1094
|
+
const runDispose = () => {
|
|
1095
|
+
if (disposed) {
|
|
1096
|
+
return;
|
|
1097
|
+
}
|
|
1098
|
+
if (!dispose) {
|
|
1099
|
+
disposeRequested = true;
|
|
1100
|
+
return;
|
|
1101
|
+
}
|
|
1102
|
+
disposed = true;
|
|
1103
|
+
dispose();
|
|
1104
|
+
};
|
|
1105
|
+
renderer.once("destroy", runDispose);
|
|
1106
|
+
renderer.destroy = () => {
|
|
1107
|
+
if (mounting) {
|
|
1108
|
+
destroyRequested = true;
|
|
1109
|
+
return;
|
|
1110
|
+
}
|
|
1111
|
+
originalDestroy();
|
|
1112
|
+
};
|
|
1113
|
+
try {
|
|
1114
|
+
dispose = _render(() => createComponent2(RendererContext.Provider, {
|
|
1115
|
+
get value() {
|
|
1116
|
+
return renderer;
|
|
1117
|
+
},
|
|
1118
|
+
get children() {
|
|
1119
|
+
return createComponent2(node, {});
|
|
1120
|
+
}
|
|
1121
|
+
}), renderer.root);
|
|
1122
|
+
} finally {
|
|
1123
|
+
mounting = false;
|
|
1124
|
+
renderer.destroy = originalDestroy;
|
|
1125
|
+
}
|
|
1126
|
+
if (disposeRequested) {
|
|
1127
|
+
runDispose();
|
|
1128
|
+
}
|
|
1129
|
+
if (destroyRequested) {
|
|
1130
|
+
originalDestroy();
|
|
1131
|
+
}
|
|
1132
|
+
};
|
|
1133
|
+
var render = async (node, rendererOrConfig = {}) => {
|
|
938
1134
|
const renderer = rendererOrConfig instanceof CliRenderer ? rendererOrConfig : await createCliRenderer({
|
|
939
1135
|
...rendererOrConfig,
|
|
940
1136
|
onDestroy: () => {
|
|
941
|
-
if (!isDisposed) {
|
|
942
|
-
isDisposed = true;
|
|
943
|
-
dispose();
|
|
944
|
-
}
|
|
945
1137
|
rendererOrConfig.onDestroy?.();
|
|
946
1138
|
}
|
|
947
1139
|
});
|
|
948
|
-
if (rendererOrConfig instanceof CliRenderer) {
|
|
949
|
-
renderer.on("destroy", () => {
|
|
950
|
-
if (!isDisposed) {
|
|
951
|
-
isDisposed = true;
|
|
952
|
-
dispose();
|
|
953
|
-
}
|
|
954
|
-
});
|
|
955
|
-
}
|
|
956
1140
|
engine2.attach(renderer);
|
|
957
|
-
|
|
958
|
-
get value() {
|
|
959
|
-
return renderer;
|
|
960
|
-
},
|
|
961
|
-
get children() {
|
|
962
|
-
return createComponent2(node, {});
|
|
963
|
-
}
|
|
964
|
-
}), renderer.root);
|
|
1141
|
+
mountSolidRoot(renderer, node);
|
|
965
1142
|
};
|
|
966
1143
|
var testRender = async (node, renderConfig = {}) => {
|
|
967
|
-
let isDisposed = false;
|
|
968
1144
|
const testSetup = await createTestRenderer({
|
|
969
1145
|
...renderConfig,
|
|
970
1146
|
onDestroy: () => {
|
|
971
|
-
if (!isDisposed) {
|
|
972
|
-
isDisposed = true;
|
|
973
|
-
dispose();
|
|
974
|
-
}
|
|
975
1147
|
renderConfig.onDestroy?.();
|
|
976
1148
|
}
|
|
977
1149
|
});
|
|
978
1150
|
engine2.attach(testSetup.renderer);
|
|
979
|
-
|
|
980
|
-
get value() {
|
|
981
|
-
return testSetup.renderer;
|
|
982
|
-
},
|
|
983
|
-
get children() {
|
|
984
|
-
return createComponent2(node, {});
|
|
985
|
-
}
|
|
986
|
-
}), testSetup.renderer.root);
|
|
1151
|
+
mountSolidRoot(testSetup.renderer, node);
|
|
987
1152
|
return testSetup;
|
|
988
1153
|
};
|
|
989
1154
|
export {
|
|
@@ -1009,7 +1174,9 @@ export {
|
|
|
1009
1174
|
extend,
|
|
1010
1175
|
effect,
|
|
1011
1176
|
createTextNode,
|
|
1177
|
+
createSolidSlotRegistry,
|
|
1012
1178
|
createSlotNode,
|
|
1179
|
+
createSlot,
|
|
1013
1180
|
createElement,
|
|
1014
1181
|
createDynamic,
|
|
1015
1182
|
createComponent2 as createComponent,
|
|
@@ -1017,8 +1184,10 @@ export {
|
|
|
1017
1184
|
baseComponents,
|
|
1018
1185
|
_render,
|
|
1019
1186
|
UnderlineSpanRenderable,
|
|
1187
|
+
TimeToFirstDraw,
|
|
1020
1188
|
TextSlotRenderable,
|
|
1021
1189
|
SlotRenderable,
|
|
1190
|
+
Slot,
|
|
1022
1191
|
RendererContext,
|
|
1023
1192
|
Portal,
|
|
1024
1193
|
LinkRenderable,
|
package/jsx-runtime.d.ts
CHANGED
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.88",
|
|
8
8
|
"description": "SolidJS renderer for OpenTUI",
|
|
9
9
|
"license": "MIT",
|
|
10
10
|
"repository": {
|
|
@@ -25,24 +25,30 @@
|
|
|
25
25
|
"types": "./scripts/solid-plugin.d.ts",
|
|
26
26
|
"import": "./scripts/solid-plugin.ts"
|
|
27
27
|
},
|
|
28
|
+
"./runtime-plugin-support": {
|
|
29
|
+
"types": "./scripts/runtime-plugin-support.d.ts",
|
|
30
|
+
"import": "./scripts/runtime-plugin-support.ts"
|
|
31
|
+
},
|
|
28
32
|
"./jsx-runtime": "./jsx-runtime.d.ts",
|
|
29
33
|
"./jsx-dev-runtime": "./jsx-runtime.d.ts"
|
|
30
34
|
},
|
|
31
35
|
"dependencies": {
|
|
32
36
|
"@babel/core": "7.28.0",
|
|
33
37
|
"@babel/preset-typescript": "7.27.1",
|
|
34
|
-
"@opentui/core": "0.1.
|
|
38
|
+
"@opentui/core": "0.1.88",
|
|
35
39
|
"babel-plugin-module-resolver": "5.0.2",
|
|
36
|
-
"babel-preset-solid": "1.9.
|
|
40
|
+
"babel-preset-solid": "1.9.10",
|
|
41
|
+
"entities": "7.0.1",
|
|
37
42
|
"s-js": "^0.4.9"
|
|
38
43
|
},
|
|
39
44
|
"devDependencies": {
|
|
40
45
|
"@types/babel__core": "7.20.5",
|
|
41
46
|
"@types/bun": "latest",
|
|
42
47
|
"@types/node": "^24.0.0",
|
|
48
|
+
"solid-js": "1.9.11",
|
|
43
49
|
"typescript": "^5"
|
|
44
50
|
},
|
|
45
51
|
"peerDependencies": {
|
|
46
|
-
"solid-js": "1.9.
|
|
52
|
+
"solid-js": "1.9.11"
|
|
47
53
|
}
|
|
48
54
|
}
|
package/scripts/preload.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function ensureRuntimePluginSupport(): boolean;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { plugin as registerBunPlugin } from "bun"
|
|
2
|
+
import * as coreRuntime from "@opentui/core"
|
|
3
|
+
import {
|
|
4
|
+
createRuntimePlugin,
|
|
5
|
+
isCoreRuntimeModuleSpecifier,
|
|
6
|
+
runtimeModuleIdForSpecifier,
|
|
7
|
+
type RuntimeModuleEntry,
|
|
8
|
+
} from "@opentui/core/runtime-plugin"
|
|
9
|
+
import * as solidJsRuntime from "solid-js"
|
|
10
|
+
import * as solidJsStoreRuntime from "solid-js/store"
|
|
11
|
+
import * as solidRuntime from "../index"
|
|
12
|
+
import { createSolidTransformPlugin } from "./solid-plugin"
|
|
13
|
+
|
|
14
|
+
const runtimePluginSupportInstalledKey = "__opentuiSolidRuntimePluginSupportInstalled__"
|
|
15
|
+
|
|
16
|
+
type RuntimePluginSupportState = typeof globalThis & {
|
|
17
|
+
[runtimePluginSupportInstalledKey]?: boolean
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const additionalRuntimeModules: Record<string, RuntimeModuleEntry> = {
|
|
21
|
+
"@opentui/solid": solidRuntime as Record<string, unknown>,
|
|
22
|
+
"solid-js": solidJsRuntime as Record<string, unknown>,
|
|
23
|
+
"solid-js/store": solidJsStoreRuntime as Record<string, unknown>,
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const resolveRuntimeSpecifier = (specifier: string): string | null => {
|
|
27
|
+
if (!isCoreRuntimeModuleSpecifier(specifier) && !additionalRuntimeModules[specifier]) {
|
|
28
|
+
return null
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return runtimeModuleIdForSpecifier(specifier)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function ensureRuntimePluginSupport(): boolean {
|
|
35
|
+
const state = globalThis as RuntimePluginSupportState
|
|
36
|
+
|
|
37
|
+
if (state[runtimePluginSupportInstalledKey]) {
|
|
38
|
+
return false
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
registerBunPlugin(
|
|
42
|
+
createSolidTransformPlugin({
|
|
43
|
+
moduleName: runtimeModuleIdForSpecifier("@opentui/solid"),
|
|
44
|
+
resolvePath(specifier) {
|
|
45
|
+
return resolveRuntimeSpecifier(specifier)
|
|
46
|
+
},
|
|
47
|
+
}),
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
registerBunPlugin(
|
|
51
|
+
createRuntimePlugin({
|
|
52
|
+
core: coreRuntime as Record<string, unknown>,
|
|
53
|
+
additional: additionalRuntimeModules,
|
|
54
|
+
}),
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
state[runtimePluginSupportInstalledKey] = true
|
|
58
|
+
return true
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
ensureRuntimePluginSupport()
|
|
@@ -1,3 +1,9 @@
|
|
|
1
1
|
import { type BunPlugin } from "bun";
|
|
2
|
+
export type ResolveImportPath = (specifier: string) => string | null;
|
|
3
|
+
export interface CreateSolidTransformPluginOptions {
|
|
4
|
+
moduleName?: string;
|
|
5
|
+
resolvePath?: ResolveImportPath;
|
|
6
|
+
}
|
|
7
|
+
export declare function createSolidTransformPlugin(input?: CreateSolidTransformPluginOptions): BunPlugin;
|
|
2
8
|
declare const solidTransformPlugin: BunPlugin;
|
|
3
9
|
export default solidTransformPlugin;
|
package/scripts/solid-plugin.ts
CHANGED
|
@@ -1,53 +1,84 @@
|
|
|
1
1
|
import { transformAsync } from "@babel/core"
|
|
2
|
+
import { readFile } from "node:fs/promises"
|
|
2
3
|
// @ts-expect-error - Types not important.
|
|
3
4
|
import ts from "@babel/preset-typescript"
|
|
4
5
|
// @ts-expect-error - Types not important.
|
|
6
|
+
import moduleResolver from "babel-plugin-module-resolver"
|
|
7
|
+
// @ts-expect-error - Types not important.
|
|
5
8
|
import solid from "babel-preset-solid"
|
|
6
9
|
import { type BunPlugin } from "bun"
|
|
7
10
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
11
|
+
export type ResolveImportPath = (specifier: string) => string | null
|
|
12
|
+
|
|
13
|
+
export interface CreateSolidTransformPluginOptions {
|
|
14
|
+
moduleName?: string
|
|
15
|
+
resolvePath?: ResolveImportPath
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function createSolidTransformPlugin(input: CreateSolidTransformPluginOptions = {}): BunPlugin {
|
|
19
|
+
const moduleName = input.moduleName ?? "@opentui/solid"
|
|
20
|
+
const resolvePath = input.resolvePath
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
name: "bun-plugin-solid",
|
|
24
|
+
setup: (build) => {
|
|
25
|
+
build.onLoad({ filter: /[\/\\]node_modules[\/\\]solid-js[\/\\]dist[\/\\]server\.js$/ }, async (args) => {
|
|
26
|
+
const path = args.path.replace("server.js", "solid.js")
|
|
27
|
+
const file = Bun.file(path)
|
|
28
|
+
const code = await file.text()
|
|
29
|
+
return { contents: code, loader: "js" }
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
build.onLoad(
|
|
33
|
+
{ filter: /[\/\\]node_modules[\/\\]solid-js[\/\\]store[\/\\]dist[\/\\]server\.js$/ },
|
|
34
|
+
async (args) => {
|
|
35
|
+
const path = args.path.replace("server.js", "store.js")
|
|
36
|
+
const file = Bun.file(path)
|
|
37
|
+
const code = await file.text()
|
|
38
|
+
return { contents: code, loader: "js" }
|
|
39
|
+
},
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
build.onLoad({ filter: /\.(js|ts)x$/ }, async (args) => {
|
|
43
|
+
const file = Bun.file(args.path)
|
|
44
|
+
const code = await file.text()
|
|
45
|
+
const plugins = resolvePath
|
|
46
|
+
? [
|
|
47
|
+
[
|
|
48
|
+
moduleResolver,
|
|
49
|
+
{
|
|
50
|
+
resolvePath(specifier: string) {
|
|
51
|
+
return resolvePath(specifier) ?? specifier
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
]
|
|
56
|
+
: []
|
|
57
|
+
|
|
58
|
+
const transforms = await transformAsync(code, {
|
|
59
|
+
filename: args.path,
|
|
60
|
+
plugins,
|
|
61
|
+
presets: [
|
|
62
|
+
[
|
|
63
|
+
solid,
|
|
64
|
+
{
|
|
65
|
+
moduleName,
|
|
66
|
+
generate: "universal",
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
[ts],
|
|
41
70
|
],
|
|
42
|
-
|
|
43
|
-
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
contents: transforms?.code ?? "",
|
|
75
|
+
loader: "js",
|
|
76
|
+
}
|
|
44
77
|
})
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
loader: "js",
|
|
48
|
-
}
|
|
49
|
-
})
|
|
50
|
-
},
|
|
78
|
+
},
|
|
79
|
+
}
|
|
51
80
|
}
|
|
52
81
|
|
|
82
|
+
const solidTransformPlugin = createSolidTransformPlugin()
|
|
83
|
+
|
|
53
84
|
export default solidTransformPlugin
|
package/src/elements/extras.d.ts
CHANGED
package/src/elements/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ASCIIFontRenderable, BoxRenderable, CodeRenderable, DiffRenderable, InputRenderable, LineNumberRenderable, MarkdownRenderable, ScrollBoxRenderable, SelectRenderable, TabSelectRenderable, TextareaRenderable, TextNodeRenderable, TextRenderable, type RenderContext, type TextNodeOptions } from "@opentui/core";
|
|
2
|
-
import type { RenderableConstructor } from "../types/elements";
|
|
3
|
-
export * from "./hooks";
|
|
4
|
-
export * from "./extras";
|
|
5
|
-
export * from "./slot";
|
|
2
|
+
import type { RenderableConstructor } from "../types/elements.js";
|
|
3
|
+
export * from "./hooks.js";
|
|
4
|
+
export * from "./extras.js";
|
|
5
|
+
export * from "./slot.js";
|
|
6
6
|
declare class SpanRenderable extends TextNodeRenderable {
|
|
7
7
|
private readonly _ctx;
|
|
8
8
|
constructor(_ctx: RenderContext | null, options: TextNodeOptions);
|
|
@@ -69,4 +69,4 @@ export declare const componentCatalogue: ComponentCatalogue;
|
|
|
69
69
|
*/
|
|
70
70
|
export declare function extend<T extends ComponentCatalogue>(objects: T): void;
|
|
71
71
|
export declare function getComponentCatalogue(): ComponentCatalogue;
|
|
72
|
-
export type { ExtendedComponentProps, ExtendedIntrinsicElements, RenderableConstructor } from "../types/elements";
|
|
72
|
+
export type { ExtendedComponentProps, ExtendedIntrinsicElements, RenderableConstructor } from "../types/elements.js";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { SlotRegistry, type CliRenderer, type Plugin, type PluginContext, type PluginErrorEvent, type SlotMode, type SlotRegistryOptions } from "@opentui/core";
|
|
2
|
+
import { type JSX } from "solid-js";
|
|
3
|
+
export type { SlotMode };
|
|
4
|
+
type SlotMap = Record<string, object>;
|
|
5
|
+
export type SolidPlugin<TSlots extends SlotMap, TContext extends PluginContext = PluginContext> = Plugin<JSX.Element, TSlots, TContext>;
|
|
6
|
+
export type SolidSlotProps<TSlots extends SlotMap, K extends keyof TSlots, TContext extends PluginContext = PluginContext> = {
|
|
7
|
+
registry: SlotRegistry<JSX.Element, TSlots, TContext>;
|
|
8
|
+
name: K;
|
|
9
|
+
mode?: SlotMode;
|
|
10
|
+
children?: JSX.Element;
|
|
11
|
+
pluginFailurePlaceholder?: (failure: PluginErrorEvent) => JSX.Element;
|
|
12
|
+
} & TSlots[K];
|
|
13
|
+
export type SolidBoundSlotProps<TSlots extends SlotMap, K extends keyof TSlots> = {
|
|
14
|
+
name: K;
|
|
15
|
+
mode?: SlotMode;
|
|
16
|
+
children?: JSX.Element;
|
|
17
|
+
} & TSlots[K];
|
|
18
|
+
export type SolidRegistrySlotComponent<TSlots extends SlotMap, TContext extends PluginContext = PluginContext> = <K extends keyof TSlots>(props: SolidSlotProps<TSlots, K, TContext>) => JSX.Element;
|
|
19
|
+
export type SolidSlotComponent<TSlots extends SlotMap> = <K extends keyof TSlots>(props: SolidBoundSlotProps<TSlots, K>) => JSX.Element;
|
|
20
|
+
export interface SolidSlotOptions {
|
|
21
|
+
pluginFailurePlaceholder?: (failure: PluginErrorEvent) => JSX.Element;
|
|
22
|
+
}
|
|
23
|
+
export declare function createSolidSlotRegistry<TSlots extends SlotMap, TContext extends PluginContext = PluginContext>(renderer: CliRenderer, context: TContext, options?: SlotRegistryOptions): SlotRegistry<JSX.Element, TSlots, TContext>;
|
|
24
|
+
export declare function createSlot<TSlots extends SlotMap, TContext extends PluginContext = PluginContext>(registry: SlotRegistry<JSX.Element, TSlots, TContext>, options?: SolidSlotOptions): SolidSlotComponent<TSlots>;
|
|
25
|
+
export declare function Slot<TSlots extends SlotMap, TContext extends PluginContext = PluginContext, K extends keyof TSlots = keyof TSlots>(props: SolidSlotProps<TSlots, K, TContext>): JSX.Element;
|
package/src/reconciler.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BaseRenderable } from "@opentui/core";
|
|
2
|
-
import { SlotRenderable } from "./elements";
|
|
2
|
+
import { SlotRenderable } from "./elements/index.js";
|
|
3
3
|
export type DomNode = BaseRenderable;
|
|
4
4
|
export declare function createSlotNode(): SlotRenderable;
|
|
5
5
|
export declare const _render: (code: () => BaseRenderable, node: BaseRenderable) => () => void, effect: <T>(fn: (prev?: T) => T, init?: T) => void, memo: <T>(fn: () => T, equal: boolean) => () => T, createComponent: <T>(Comp: (props: T) => BaseRenderable, props: T) => BaseRenderable, createElement: (tag: string) => BaseRenderable, createTextNode: (value: string) => BaseRenderable, insertNode: (parent: BaseRenderable, node: BaseRenderable, anchor?: BaseRenderable | undefined) => void, insert: <T>(parent: any, accessor: T | (() => T), marker?: any | null, initial?: any) => BaseRenderable, spread: <T>(node: any, accessor: (() => T) | T, skipChildren?: boolean) => void, setProp: <T>(node: BaseRenderable, name: string, value: T, prev?: T | undefined) => T, mergeProps: (...sources: unknown[]) => unknown, use: <A, T>(fn: (element: BaseRenderable, arg: A) => T, element: BaseRenderable, arg: A) => T;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { TimeToFirstDrawRenderable } from "@opentui/core";
|
|
2
|
+
import type { ExtendedComponentProps } from "./types/elements";
|
|
3
|
+
declare module "@opentui/solid" {
|
|
4
|
+
interface OpenTUIComponents {
|
|
5
|
+
time_to_first_draw: typeof TimeToFirstDrawRenderable;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
export type TimeToFirstDrawProps = ExtendedComponentProps<typeof TimeToFirstDrawRenderable>;
|
|
9
|
+
export declare const TimeToFirstDraw: (props: TimeToFirstDrawProps) => any;
|