@spirobel/mininext 0.7.6 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -18
- package/dist/backend/html.d.ts +46 -0
- package/dist/backend/html.js +233 -0
- package/dist/backend/miniresolve.d.ts +8 -0
- package/dist/backend/miniresolve.js +60 -0
- package/dist/frontend/minidom.d.ts +8 -0
- package/dist/frontend/minidom.js +29 -0
- package/dist/frontend/minirender.d.ts +10 -0
- package/dist/frontend/minirender.js +136 -0
- package/dist/frontend/miniresolve.d.ts +9 -0
- package/dist/frontend/miniresolve.js +143 -0
- package/dist/frontend/minirouter.d.ts +18 -0
- package/dist/frontend/minirouter.js +107 -0
- package/dist/minicache.d.ts +26 -0
- package/dist/minicache.js +44 -0
- package/dist/mininext.d.ts +41 -22
- package/dist/mininext.js +127 -229
- package/package.json +2 -2
- package/dist/html.d.ts +0 -73
- package/dist/html.js +0 -288
- package/dist/url.d.ts +0 -282
- package/dist/url.js +0 -533
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { getCacheEntry, getResolvedMiniHtmlStringThrows, } from "../minicache";
|
|
2
|
+
import { resolveMiniValue, } from "../mininext";
|
|
3
|
+
import { isInside, render } from "./minirender";
|
|
4
|
+
export function resolveMiniHtmlString(stringLiterals, unresolvedValues, mini, slots) {
|
|
5
|
+
const resolvedValues = [];
|
|
6
|
+
let index = 0;
|
|
7
|
+
for (const unresolvedValue of unresolvedValues) {
|
|
8
|
+
const slotId = slots[index];
|
|
9
|
+
if (!slotId)
|
|
10
|
+
throw new Error(`Could not find slot id for ${unresolvedValue}`);
|
|
11
|
+
resolvedValues.push(resolveMiniValue(unresolvedValue, mini, slotId));
|
|
12
|
+
index++;
|
|
13
|
+
}
|
|
14
|
+
return {
|
|
15
|
+
slots,
|
|
16
|
+
stringLiterals,
|
|
17
|
+
values: resolvedValues,
|
|
18
|
+
render: (target, cacheAndCursor) => {
|
|
19
|
+
if (!cacheAndCursor)
|
|
20
|
+
cacheAndCursor = mini.cacheAndCursor; //and cache here
|
|
21
|
+
return render(target, cacheAndCursor);
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export function resolveValuesForCache(unresolvedValues, cac, slots = null) {
|
|
26
|
+
if (!slots)
|
|
27
|
+
slots = unresolvedValues.map(() => crypto.randomUUID());
|
|
28
|
+
const values = unresolvedValues.map((value, index) => {
|
|
29
|
+
const childId = slots[index];
|
|
30
|
+
if (!childId)
|
|
31
|
+
throw new Error("Could not find slot id for value");
|
|
32
|
+
// CASE: primitive
|
|
33
|
+
if (typeof value === "string" || typeof value === "number") {
|
|
34
|
+
const cacheEntry = cac.cache.get(childId);
|
|
35
|
+
if (cacheEntry) {
|
|
36
|
+
if (cacheEntry.value === value)
|
|
37
|
+
return value;
|
|
38
|
+
cacheEntry.value = value;
|
|
39
|
+
cacheEntry.dirty = true;
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
cac.cache.set(childId, { value, dirty: true });
|
|
43
|
+
return value;
|
|
44
|
+
}
|
|
45
|
+
// CASE: child mini htmlstring or component
|
|
46
|
+
return { childId };
|
|
47
|
+
});
|
|
48
|
+
return { slots, values };
|
|
49
|
+
}
|
|
50
|
+
export function resolve(stringLiterals, unresolvedValues, mini) {
|
|
51
|
+
// CASE our cache entry does not exist yet
|
|
52
|
+
const cac = mini.cacheAndCursor;
|
|
53
|
+
const cacheEntry = getCacheEntry(cac);
|
|
54
|
+
if (!cacheEntry) {
|
|
55
|
+
const { slots, values } = resolveValuesForCache(unresolvedValues, cac);
|
|
56
|
+
cac.cache.set(cac.cursor, {
|
|
57
|
+
value: { stringLiterals, values, slots, state: null },
|
|
58
|
+
dirty: true,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
else if (cacheEntry && typeof cacheEntry.value !== "object") {
|
|
62
|
+
const { slots, values } = resolveValuesForCache(unresolvedValues, cac);
|
|
63
|
+
cacheEntry.dirty = true;
|
|
64
|
+
cacheEntry.value = {
|
|
65
|
+
stringLiterals,
|
|
66
|
+
values,
|
|
67
|
+
slots,
|
|
68
|
+
state: null,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
const cacheValue = getResolvedMiniHtmlStringThrows(cac);
|
|
73
|
+
const htmlUnchanged = arraysEqual(stringLiterals, cacheValue.stringLiterals || []);
|
|
74
|
+
const styleOrTagContentChanged = parametricHtmlChanges(stringLiterals, cacheValue.values, unresolvedValues);
|
|
75
|
+
const { slots, values } = resolveValuesForCache(unresolvedValues, cac, htmlUnchanged
|
|
76
|
+
? cacheValue.slots
|
|
77
|
+
: unresolvedValues.map(() => crypto.randomUUID()));
|
|
78
|
+
if (!htmlUnchanged || styleOrTagContentChanged) {
|
|
79
|
+
//recursively delete all children
|
|
80
|
+
deleteAllChildren(cac);
|
|
81
|
+
cacheValue.stringLiterals = stringLiterals;
|
|
82
|
+
cacheValue.slots = slots;
|
|
83
|
+
cacheEntry.dirty = true;
|
|
84
|
+
}
|
|
85
|
+
cacheValue.values = values;
|
|
86
|
+
}
|
|
87
|
+
// at this point we know the cache entry exists
|
|
88
|
+
const cacheValue = getResolvedMiniHtmlStringThrows(cac);
|
|
89
|
+
const slots = cacheValue.slots;
|
|
90
|
+
// we also know slots exist
|
|
91
|
+
if (!slots)
|
|
92
|
+
throw new Error("slots not found");
|
|
93
|
+
return resolveMiniHtmlString(stringLiterals, unresolvedValues, mini, slots);
|
|
94
|
+
}
|
|
95
|
+
function deleteAllChildren(cac, last = true) {
|
|
96
|
+
const cacheEntry = getCacheEntry(cac);
|
|
97
|
+
if (!cacheEntry)
|
|
98
|
+
return;
|
|
99
|
+
if (typeof cacheEntry.value !== "object") {
|
|
100
|
+
cac.cache.delete(cac.cursor); // leaf primitive value
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const cacheValue = getResolvedMiniHtmlStringThrows(cac);
|
|
104
|
+
if (!cacheValue.slots) {
|
|
105
|
+
// when attaching state we have a placeholder cache entry with slots null
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
for (const child of cacheValue.slots) {
|
|
109
|
+
deleteAllChildren({ ...cac, cursor: child }, false); // delete all children
|
|
110
|
+
}
|
|
111
|
+
if (last)
|
|
112
|
+
return; // dont delete the node that called this
|
|
113
|
+
cac.cache.delete(cac.cursor); // delete intermediate nodes
|
|
114
|
+
}
|
|
115
|
+
function arraysEqual(arr1, arr2) {
|
|
116
|
+
if (arr1.length !== arr2.length)
|
|
117
|
+
return false;
|
|
118
|
+
return arr1.every((str, index) => str === arr2[index]);
|
|
119
|
+
}
|
|
120
|
+
export function parametricHtmlChanges(stringLiterals, cached_values, values) {
|
|
121
|
+
const inside = {
|
|
122
|
+
element: false,
|
|
123
|
+
singleQuotes: false,
|
|
124
|
+
doubleQuotes: false,
|
|
125
|
+
lastElement: "",
|
|
126
|
+
};
|
|
127
|
+
let index = 0;
|
|
128
|
+
for (const literal of stringLiterals) {
|
|
129
|
+
isInside(literal, inside);
|
|
130
|
+
if (inside.element || inside.lastElement.trim().endsWith("<style")) {
|
|
131
|
+
const oldValue = cached_values ? cached_values[index] : undefined;
|
|
132
|
+
const newValue = values[index];
|
|
133
|
+
if (oldValue !== newValue)
|
|
134
|
+
return true;
|
|
135
|
+
if (typeof oldValue === "undefined")
|
|
136
|
+
return true;
|
|
137
|
+
if (typeof newValue === "undefined")
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
index++;
|
|
141
|
+
}
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Mini, MiniHtmlString } from "../mininext";
|
|
2
|
+
export type ExtractRouteParam<Path extends string> = Path extends `:${infer Param}/${infer Rest}` ? Param | ExtractRouteParam<Rest> : Path extends `:${infer Param}` ? Param : Path extends `${infer Prefix}/*` ? ExtractRouteParam<Prefix> | "*" : Path extends `${infer _Prefix}/${infer Rest}` ? ExtractRouteParam<Rest> : never;
|
|
3
|
+
export type Params<Path extends string> = {
|
|
4
|
+
[Param in ExtractRouteParam<Path>]: string;
|
|
5
|
+
};
|
|
6
|
+
export type Handler<Path extends string = string> = (params: Params<Path>, mini: Mini) => MiniHtmlString;
|
|
7
|
+
export type RoutePaths<RoutesObj> = {
|
|
8
|
+
[K in keyof RoutesObj]: K extends string ? K extends `/${string}` | "/*" ? K : never : never;
|
|
9
|
+
}[keyof RoutesObj];
|
|
10
|
+
export type TypedRouter<TRoutes extends Record<string, any>> = {
|
|
11
|
+
component: (mini: Mini) => MiniHtmlString;
|
|
12
|
+
navigate(path: string): void;
|
|
13
|
+
navigate<Path extends RoutePaths<TRoutes>>(path: Path, params: Params<Path>): void;
|
|
14
|
+
link(path: string): string;
|
|
15
|
+
link<Path extends RoutePaths<TRoutes>>(path: Path, params: Params<Path>): string;
|
|
16
|
+
getCurrentPath(): string;
|
|
17
|
+
};
|
|
18
|
+
export declare function createRouter<const TRoutes extends Record<string, Handler<any>>>(routes: TRoutes): TypedRouter<TRoutes>;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
export function createRouter(routes) {
|
|
2
|
+
let currentPath = "";
|
|
3
|
+
function matchRoute(path) {
|
|
4
|
+
const routeKeys = Object.keys(routes);
|
|
5
|
+
// Exact matches first
|
|
6
|
+
for (const key of routeKeys) {
|
|
7
|
+
const template = String(key);
|
|
8
|
+
const match = pathMatch(template, path);
|
|
9
|
+
if (match) {
|
|
10
|
+
return {
|
|
11
|
+
handler: routes[key],
|
|
12
|
+
params: match.params,
|
|
13
|
+
routeKey: template,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
// Wildcard routes ending with /*
|
|
18
|
+
for (const key of routeKeys) {
|
|
19
|
+
const template = String(key);
|
|
20
|
+
if (template.endsWith("/*")) {
|
|
21
|
+
const prefix = template.slice(0, -2);
|
|
22
|
+
const match = pathMatch(prefix, path, true);
|
|
23
|
+
if (match) {
|
|
24
|
+
const params = match.params;
|
|
25
|
+
params["*"] = match.rest ?? "";
|
|
26
|
+
return { handler: routes[key], params, routeKey: template };
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
function pathMatch(template, path, isPrefix = false) {
|
|
33
|
+
const templateParts = template.split("/").filter(Boolean);
|
|
34
|
+
const pathParts = path.split("/").filter(Boolean);
|
|
35
|
+
if (!isPrefix && templateParts.length !== pathParts.length)
|
|
36
|
+
return null;
|
|
37
|
+
if (pathParts.length < templateParts.length)
|
|
38
|
+
return null;
|
|
39
|
+
const params = {};
|
|
40
|
+
for (let i = 0; i < templateParts.length; i++) {
|
|
41
|
+
const part = templateParts[i];
|
|
42
|
+
if (part.startsWith(":")) {
|
|
43
|
+
params[part.slice(1)] = pathParts[i];
|
|
44
|
+
}
|
|
45
|
+
else if (part !== pathParts[i]) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
let rest = "";
|
|
50
|
+
if (isPrefix && pathParts.length > templateParts.length) {
|
|
51
|
+
rest = "/" + pathParts.slice(templateParts.length).join("/");
|
|
52
|
+
}
|
|
53
|
+
return { params, rest };
|
|
54
|
+
}
|
|
55
|
+
function buildPath(template, params) {
|
|
56
|
+
let base = template;
|
|
57
|
+
let append = "";
|
|
58
|
+
if (template.endsWith("/*")) {
|
|
59
|
+
base = template.slice(0, -2);
|
|
60
|
+
const wildcardValue = params["*"];
|
|
61
|
+
if (wildcardValue !== undefined) {
|
|
62
|
+
append = wildcardValue.startsWith("/")
|
|
63
|
+
? wildcardValue
|
|
64
|
+
: "/" + wildcardValue;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return (base.replace(/:(\w+)/g, (_, param) => {
|
|
68
|
+
const value = params[param];
|
|
69
|
+
if (value === undefined) {
|
|
70
|
+
throw new Error(`Missing param: ${param}`);
|
|
71
|
+
}
|
|
72
|
+
return value;
|
|
73
|
+
}) + append);
|
|
74
|
+
}
|
|
75
|
+
function link(pathOrTemplate, params) {
|
|
76
|
+
let finalPath;
|
|
77
|
+
if (params && typeof pathOrTemplate === "string") {
|
|
78
|
+
finalPath = buildPath(pathOrTemplate, params);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
finalPath = pathOrTemplate;
|
|
82
|
+
}
|
|
83
|
+
const result = finalPath.startsWith("/") ? finalPath : "/" + finalPath;
|
|
84
|
+
return result.startsWith("#") ? result : "#" + result;
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
component(mini) {
|
|
88
|
+
const path = window.location.hash;
|
|
89
|
+
const cleanPath = path === "#" || path === "" ? "/" : path.slice(1);
|
|
90
|
+
currentPath = cleanPath;
|
|
91
|
+
const match = matchRoute(cleanPath);
|
|
92
|
+
if (match) {
|
|
93
|
+
const handler = match.handler;
|
|
94
|
+
const params = match.params;
|
|
95
|
+
return handler(params, mini);
|
|
96
|
+
}
|
|
97
|
+
throw new Error("no url matched");
|
|
98
|
+
},
|
|
99
|
+
navigate: function (pathOrTemplate, params) {
|
|
100
|
+
window.location.hash = link(pathOrTemplate, params);
|
|
101
|
+
},
|
|
102
|
+
link,
|
|
103
|
+
getCurrentPath() {
|
|
104
|
+
return currentPath;
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { PrimitiveValue, StateObject, StringArray } from "./mininext";
|
|
2
|
+
export declare function getCacheEntry(cacheAndCursor: CacheAndCursor): CacheObject | undefined;
|
|
3
|
+
export declare function getCacheEntryThrows(cacheAndCursor: CacheAndCursor): CacheObject;
|
|
4
|
+
export declare function getResolvedMiniHtmlStringThrows(cacheAndCursor: CacheAndCursor): ResolvedMiniCacheHtmlString;
|
|
5
|
+
export declare function state<T>(name: string, value: T, cacheAndCursor: CacheAndCursor, global?: boolean): StateObject<T>;
|
|
6
|
+
export type CacheValue = PrimitiveValue | ResolvedMiniCacheHtmlString;
|
|
7
|
+
export type CacheObject = {
|
|
8
|
+
el?: HTMLElement;
|
|
9
|
+
value: CacheValue;
|
|
10
|
+
dirty: boolean;
|
|
11
|
+
};
|
|
12
|
+
export type MiniCache = Map<string, CacheObject>;
|
|
13
|
+
export type CacheAndCursor = {
|
|
14
|
+
cache: MiniCache;
|
|
15
|
+
cursor: string;
|
|
16
|
+
};
|
|
17
|
+
export type ResolvedMiniCacheHtmlString = {
|
|
18
|
+
stringLiterals: StringArray | null;
|
|
19
|
+
values: ResolvedMiniCacheValue[] | null;
|
|
20
|
+
slots: string[] | null;
|
|
21
|
+
state: StateObject[] | null;
|
|
22
|
+
};
|
|
23
|
+
export type ResolvedMiniCacheValue = PrimitiveValue | ResolvedMiniChildHtmlString;
|
|
24
|
+
export type ResolvedMiniChildHtmlString = {
|
|
25
|
+
childId: string;
|
|
26
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export function getCacheEntry(cacheAndCursor) {
|
|
2
|
+
return cacheAndCursor.cache.get(cacheAndCursor.cursor);
|
|
3
|
+
}
|
|
4
|
+
export function getCacheEntryThrows(cacheAndCursor) {
|
|
5
|
+
const entry = getCacheEntry(cacheAndCursor);
|
|
6
|
+
if (!entry)
|
|
7
|
+
throw new Error(`Could not find cache entry for cursor ${cacheAndCursor.cursor}`);
|
|
8
|
+
return entry;
|
|
9
|
+
}
|
|
10
|
+
export function getResolvedMiniHtmlStringThrows(cacheAndCursor) {
|
|
11
|
+
const cacheEntry = getCacheEntryThrows(cacheAndCursor);
|
|
12
|
+
if (typeof cacheEntry.value !== "object")
|
|
13
|
+
throw new Error(`the result is a primitive value, we expected a ResolvedMiniCacheHtmlString. ${JSON.stringify(cacheEntry)}`);
|
|
14
|
+
return cacheEntry.value;
|
|
15
|
+
}
|
|
16
|
+
export function state(name, value, cacheAndCursor, global) {
|
|
17
|
+
const localCac = { ...cacheAndCursor };
|
|
18
|
+
if (global)
|
|
19
|
+
localCac.cursor = "global";
|
|
20
|
+
let cacheEntry = getCacheEntry(localCac);
|
|
21
|
+
if (!cacheEntry) {
|
|
22
|
+
cacheAndCursor.cache.set(localCac.cursor, {
|
|
23
|
+
value: {
|
|
24
|
+
stringLiterals: null,
|
|
25
|
+
values: null,
|
|
26
|
+
slots: null,
|
|
27
|
+
state: [],
|
|
28
|
+
},
|
|
29
|
+
dirty: true,
|
|
30
|
+
});
|
|
31
|
+
cacheEntry = getCacheEntryThrows(localCac);
|
|
32
|
+
}
|
|
33
|
+
const cacheValue = getResolvedMiniHtmlStringThrows(localCac);
|
|
34
|
+
if (!cacheValue.state)
|
|
35
|
+
cacheValue.state = [];
|
|
36
|
+
const stateObjects = cacheValue.state;
|
|
37
|
+
const stateObject = stateObjects.find((stateObject) => stateObject.name === name);
|
|
38
|
+
if (stateObject)
|
|
39
|
+
return stateObject; //CASE: state already exists
|
|
40
|
+
const newStateObject = { value, name };
|
|
41
|
+
stateObjects.push(newStateObject);
|
|
42
|
+
cacheEntry.dirty = true; // we want to dirty the cache in any case, not just if cache entry did not exist yet
|
|
43
|
+
return newStateObject;
|
|
44
|
+
}
|
package/dist/mininext.d.ts
CHANGED
|
@@ -1,22 +1,41 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
1
|
+
import { type CacheAndCursor } from "./minicache";
|
|
2
|
+
import { type Skeleton } from "./backend/html";
|
|
3
|
+
export { renderRoot } from "./frontend/minidom";
|
|
4
|
+
export { createRouter, type Params } from "./frontend/minirouter";
|
|
5
|
+
export declare const isBackend: boolean;
|
|
6
|
+
export type PrimitiveValue = string | number | null;
|
|
7
|
+
export type MiniHtmlString = {
|
|
8
|
+
stringLiterals: TemplateStringsArray;
|
|
9
|
+
values: MiniValue[];
|
|
10
|
+
resolve(mini?: Mini): ResolvedMiniHtmlString;
|
|
11
|
+
build(mini?: Mini, root?: string, config?: Bun.BuildConfig): Promise<Skeleton>;
|
|
12
|
+
renderBackend(mini?: Mini): string;
|
|
13
|
+
};
|
|
14
|
+
export type MiniComponent = (mini: Mini) => MiniHtmlString;
|
|
15
|
+
export type MiniValue = PrimitiveValue | MiniComponent | MiniHtmlString;
|
|
16
|
+
export type StateObject<T = unknown> = {
|
|
17
|
+
value: T;
|
|
18
|
+
name: string;
|
|
19
|
+
};
|
|
20
|
+
export type Mini = {
|
|
21
|
+
html: typeof html;
|
|
22
|
+
state: <T>(name: string, value: T, global?: boolean) => StateObject<T>;
|
|
23
|
+
cacheAndCursor: CacheAndCursor;
|
|
24
|
+
flatten(htmlStringArray: MiniHtmlString[], flattenRootFn?: (htmlstrings: MiniHtmlString) => MiniHtmlString): MiniHtmlString;
|
|
25
|
+
fill(...args: MiniValue[]): Blob;
|
|
26
|
+
};
|
|
27
|
+
export declare function html(stringLiterals: TemplateStringsArray, ...values: MiniValue[]): MiniHtmlString;
|
|
28
|
+
export declare function constructMiniHtmlString(stringLiterals: TemplateStringsArray, values: MiniValue[]): MiniHtmlString;
|
|
29
|
+
export declare function makeNewMini(cac: CacheAndCursor): Mini;
|
|
30
|
+
export declare function standardFlattenRoot(htmlstrings: MiniHtmlString): MiniHtmlString;
|
|
31
|
+
export declare function flatten(htmlStringArray: MiniHtmlString[], flattenRootFn?: typeof standardFlattenRoot): MiniHtmlString;
|
|
32
|
+
export declare function flattenValues(miniHtmlString: MiniHtmlString): MiniHtmlString;
|
|
33
|
+
export declare function resolveMiniValue(value: MiniValue, parentMini: Mini, slotId: string): ResolvedMiniValue;
|
|
34
|
+
export type StringArray = string[] | TemplateStringsArray;
|
|
35
|
+
export type ResolvedMiniHtmlString = {
|
|
36
|
+
stringLiterals: StringArray;
|
|
37
|
+
values: ResolvedMiniValue[];
|
|
38
|
+
slots: string[];
|
|
39
|
+
render: (target: Element | HTMLElement, cacheAndCursor?: CacheAndCursor) => CacheAndCursor;
|
|
40
|
+
};
|
|
41
|
+
export type ResolvedMiniValue = PrimitiveValue | ResolvedMiniHtmlString;
|