@solidtv/renderer 1.0.3 → 1.0.5
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/src/core/CoreNode.d.ts +32 -0
- package/dist/src/core/CoreNode.js +8 -0
- package/dist/src/core/CoreNode.js.map +1 -1
- package/dist/src/core/Stage.js +3 -0
- package/dist/src/core/Stage.js.map +1 -1
- package/dist/src/main-api/Inspector.js +80 -7
- package/dist/src/main-api/Inspector.js.map +1 -1
- package/dist/src/main-api/Renderer.js +6 -6
- package/dist/src/main-api/Renderer.js.map +1 -1
- package/dist/src/utils.d.ts +1 -0
- package/dist/src/utils.js +3 -0
- package/dist/src/utils.js.map +1 -1
- package/dist/tsconfig.dist.tsbuildinfo +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +1 -1
- package/src/core/CoreNode.ts +42 -0
- package/src/core/Stage.ts +3 -0
- package/src/main-api/Inspector.ts +89 -7
- package/src/main-api/Renderer.ts +6 -6
- package/src/utils.ts +6 -0
package/src/core/Stage.ts
CHANGED
|
@@ -979,6 +979,9 @@ export class Stage {
|
|
|
979
979
|
data,
|
|
980
980
|
imageType: props.imageType,
|
|
981
981
|
interactive: props.interactive ?? false,
|
|
982
|
+
preventDestroy: props.preventDestroy,
|
|
983
|
+
componentName: props.componentName,
|
|
984
|
+
componentLocation: props.componentLocation,
|
|
982
985
|
};
|
|
983
986
|
}
|
|
984
987
|
|
|
@@ -9,7 +9,7 @@ import type {
|
|
|
9
9
|
IAnimationController,
|
|
10
10
|
AnimationControllerState,
|
|
11
11
|
} from '../common/IAnimationController.js';
|
|
12
|
-
import {
|
|
12
|
+
import { ENABLE_INSPECTOR } from '../utils.js';
|
|
13
13
|
import { CoreTextNode, type CoreTextNodeProps } from '../core/CoreTextNode.js';
|
|
14
14
|
import type { Texture } from '../core/textures/Texture.js';
|
|
15
15
|
import { TextureType } from '../core/textures/Texture.js';
|
|
@@ -230,8 +230,59 @@ const knownProperties = new Set<string>([
|
|
|
230
230
|
'parent',
|
|
231
231
|
'data',
|
|
232
232
|
'text',
|
|
233
|
+
'componentName',
|
|
234
|
+
'componentLocation',
|
|
233
235
|
]);
|
|
234
236
|
|
|
237
|
+
/**
|
|
238
|
+
* Convert a PascalCase or camelCase component name to a valid custom-element
|
|
239
|
+
* tag name by inserting hyphens before uppercase letters and lower-casing.
|
|
240
|
+
* A mandatory "x-" prefix is added so the name always contains a hyphen,
|
|
241
|
+
* which is required by the Custom Elements spec.
|
|
242
|
+
*
|
|
243
|
+
* Examples:
|
|
244
|
+
* "MyButton" → "x-my-button"
|
|
245
|
+
* "FocusRing" → "x-focus-ring"
|
|
246
|
+
* "view" → "x-view"
|
|
247
|
+
*/
|
|
248
|
+
function toCustomElementTag(componentName: string): string {
|
|
249
|
+
const kebab = componentName
|
|
250
|
+
.replace(/([A-Z])/g, '-$1')
|
|
251
|
+
.toLowerCase()
|
|
252
|
+
.replace(/^-/, ''); // strip leading hyphen if name starts with uppercase
|
|
253
|
+
return `${kebab}-x`;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Registry of custom element tag names that have already been defined so we
|
|
258
|
+
* only call customElements.define() once per unique component name.
|
|
259
|
+
*/
|
|
260
|
+
const registeredCustomElements = new Set<string>();
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Ensure a minimal custom element class is registered for the given tag name.
|
|
264
|
+
* The element extends HTMLElement with no additional behaviour; its only
|
|
265
|
+
* purpose is to make Chrome DevTools show the component name in the Elements
|
|
266
|
+
* panel.
|
|
267
|
+
*/
|
|
268
|
+
function ensureCustomElement(tagName: string): void {
|
|
269
|
+
if (registeredCustomElements.has(tagName)) {
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
registeredCustomElements.add(tagName);
|
|
273
|
+
|
|
274
|
+
// Guard: skip if already defined (e.g. by another module) or if the
|
|
275
|
+
// Custom Elements API is unavailable (SSR / test environments).
|
|
276
|
+
if (
|
|
277
|
+
typeof customElements === 'undefined' ||
|
|
278
|
+
customElements.get(tagName) !== undefined
|
|
279
|
+
) {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
customElements.define(tagName, class extends HTMLElement {});
|
|
284
|
+
}
|
|
285
|
+
|
|
235
286
|
export class Inspector {
|
|
236
287
|
private root: HTMLElement | null = null;
|
|
237
288
|
private canvas: HTMLCanvasElement | null = null;
|
|
@@ -289,7 +340,7 @@ export class Inspector {
|
|
|
289
340
|
private animationStatsTimer: number | null = null;
|
|
290
341
|
|
|
291
342
|
constructor(canvas: HTMLCanvasElement, settings: RendererMainSettings) {
|
|
292
|
-
if (
|
|
343
|
+
if (!ENABLE_INSPECTOR) return;
|
|
293
344
|
|
|
294
345
|
if (!settings) {
|
|
295
346
|
throw new Error('settings is required');
|
|
@@ -732,14 +783,29 @@ export class Inspector {
|
|
|
732
783
|
id: number,
|
|
733
784
|
properties: CoreNodeProps | CoreTextNodeProps,
|
|
734
785
|
): HTMLElement {
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
786
|
+
// Use a custom element tag when the node carries a componentName so that
|
|
787
|
+
// Chrome DevTools' Elements panel shows the framework component name
|
|
788
|
+
// instead of a generic <div>.
|
|
789
|
+
const componentName = (properties as CoreNodeProps).componentName;
|
|
790
|
+
let el: HTMLElement;
|
|
791
|
+
|
|
792
|
+
if (componentName) {
|
|
793
|
+
const tagName = toCustomElementTag(componentName);
|
|
794
|
+
ensureCustomElement(tagName);
|
|
795
|
+
el = document.createElement(tagName);
|
|
796
|
+
// Store the original PascalCase name as a readable attribute.
|
|
797
|
+
// el.setAttribute('data-component', componentName);
|
|
798
|
+
} else {
|
|
799
|
+
el = document.createElement('div');
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
el.style.position = 'absolute';
|
|
803
|
+
el.id = id.toString();
|
|
738
804
|
|
|
739
805
|
// set initial properties
|
|
740
806
|
for (const key in properties) {
|
|
741
807
|
this.updateNodeProperty(
|
|
742
|
-
|
|
808
|
+
el,
|
|
743
809
|
// really typescript? really?
|
|
744
810
|
key as keyof CoreNodeProps,
|
|
745
811
|
properties[key as keyof CoreNodeProps],
|
|
@@ -747,7 +813,7 @@ export class Inspector {
|
|
|
747
813
|
);
|
|
748
814
|
}
|
|
749
815
|
|
|
750
|
-
return
|
|
816
|
+
return el;
|
|
751
817
|
}
|
|
752
818
|
|
|
753
819
|
createNodes(node: CoreNode): boolean {
|
|
@@ -1205,6 +1271,22 @@ export class Inspector {
|
|
|
1205
1271
|
}
|
|
1206
1272
|
return;
|
|
1207
1273
|
}
|
|
1274
|
+
|
|
1275
|
+
// Component metadata – handled when the element is created in createDiv;
|
|
1276
|
+
// re-applied here to support dynamic updates (rare but possible).
|
|
1277
|
+
if (property === 'componentName' && value) {
|
|
1278
|
+
const tagName = toCustomElementTag(String(value));
|
|
1279
|
+
ensureCustomElement(tagName);
|
|
1280
|
+
// div.setAttribute('data-component', String(value));
|
|
1281
|
+
return;
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
if (property === 'componentLocation' && value) {
|
|
1285
|
+
// Expose the source path so Chrome DevTools extensions and VS Code's
|
|
1286
|
+
// browser debugger can offer "open in editor" functionality.
|
|
1287
|
+
// div.setAttribute('data-location', String(value));
|
|
1288
|
+
return;
|
|
1289
|
+
}
|
|
1208
1290
|
}
|
|
1209
1291
|
|
|
1210
1292
|
updateViewport(
|
package/src/main-api/Renderer.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ExtractProps, TextureMap } from '../core/CoreTextureManager.js';
|
|
2
2
|
import { EventEmitter } from '../common/EventEmitter.js';
|
|
3
|
-
import {
|
|
3
|
+
import { ENABLE_INSPECTOR } from '../utils.js';
|
|
4
4
|
import { Stage, type StageOptions } from '../core/Stage.js';
|
|
5
5
|
import { CoreNode, type CoreNodeProps } from '../core/CoreNode.js';
|
|
6
6
|
import { type CoreTextNodeProps } from '../core/CoreTextNode.js';
|
|
@@ -620,7 +620,7 @@ export class RendererMain extends EventEmitter {
|
|
|
620
620
|
}
|
|
621
621
|
|
|
622
622
|
// Initialize inspector (if enabled)
|
|
623
|
-
if (inspector &&
|
|
623
|
+
if (inspector && ENABLE_INSPECTOR) {
|
|
624
624
|
this.inspector = new inspector(canvas, settings as RendererMainSettings);
|
|
625
625
|
}
|
|
626
626
|
}
|
|
@@ -683,7 +683,7 @@ export class RendererMain extends EventEmitter {
|
|
|
683
683
|
): INode<ShNode> {
|
|
684
684
|
const node = this.stage.createNode(props as Partial<CoreNodeProps>);
|
|
685
685
|
|
|
686
|
-
if (
|
|
686
|
+
if (ENABLE_INSPECTOR && this.inspector) {
|
|
687
687
|
return this.inspector.createNode(node) as unknown as INode<ShNode>;
|
|
688
688
|
}
|
|
689
689
|
|
|
@@ -707,7 +707,7 @@ export class RendererMain extends EventEmitter {
|
|
|
707
707
|
createTextNode(props: Partial<ITextNodeProps>): ITextNode {
|
|
708
708
|
const textNode = this.stage.createTextNode(props as CoreTextNodeProps);
|
|
709
709
|
|
|
710
|
-
if (
|
|
710
|
+
if (ENABLE_INSPECTOR && this.inspector) {
|
|
711
711
|
return this.inspector.createTextNode(textNode) as unknown as ITextNode;
|
|
712
712
|
}
|
|
713
713
|
|
|
@@ -724,7 +724,7 @@ export class RendererMain extends EventEmitter {
|
|
|
724
724
|
* @returns
|
|
725
725
|
*/
|
|
726
726
|
destroyNode(node: INode) {
|
|
727
|
-
if (
|
|
727
|
+
if (ENABLE_INSPECTOR && this.inspector) {
|
|
728
728
|
this.inspector.destroyNode(node.id);
|
|
729
729
|
}
|
|
730
730
|
|
|
@@ -888,7 +888,7 @@ export class RendererMain extends EventEmitter {
|
|
|
888
888
|
stageOptions[key] = options[key]!;
|
|
889
889
|
}
|
|
890
890
|
|
|
891
|
-
if (options.inspector !== undefined &&
|
|
891
|
+
if (options.inspector !== undefined && ENABLE_INSPECTOR) {
|
|
892
892
|
if (options.inspector === false) {
|
|
893
893
|
this.inspector?.destroy();
|
|
894
894
|
this.inspector = null;
|
package/src/utils.ts
CHANGED
|
@@ -77,6 +77,12 @@ export const CALCULATE_FPS =
|
|
|
77
77
|
? __calculateFps__
|
|
78
78
|
: !isProductionEnvironment;
|
|
79
79
|
|
|
80
|
+
declare const __enableInspector__: boolean;
|
|
81
|
+
export const ENABLE_INSPECTOR =
|
|
82
|
+
typeof __enableInspector__ !== 'undefined'
|
|
83
|
+
? __enableInspector__
|
|
84
|
+
: !isProductionEnvironment;
|
|
85
|
+
|
|
80
86
|
// Works on WebOS 4!!
|
|
81
87
|
declare const __dirtyQuadBuffer__: boolean;
|
|
82
88
|
export const DIRTY_QUAD_BUFFER =
|