@lightningjs/solid
Advanced tools
Comparing version 0.14.4 to 0.15.0
import { createSignal, mergeProps as mergeProps$1, createRoot, createRenderEffect, createMemo, createComponent as createComponent$1, untrack, splitProps } from 'solid-js'; | ||
export { ErrorBoundary, For, Index, Match, Show, Suspense, SuspenseList, Switch } from 'solid-js'; | ||
import { MainCoreDriver, RendererMain } from '@lightningjs/renderer'; | ||
import { createElement as createElement$1, spread as spread$1, use as use$1, insert as insert$1 } from '@lightningjs/solid'; | ||
import { createElement as createElement$1, spread as spread$1 } from '@lightningjs/solid'; | ||
@@ -44,5 +44,5 @@ /* | ||
let createShader; | ||
function startLightningRenderer(options = {}) { | ||
function startLightningRenderer(options = {}, rootId = 'app') { | ||
const driver = new MainCoreDriver(); | ||
renderer = new RendererMain(options, options.rootId || 'app', driver); | ||
renderer = new RendererMain(options, rootId, driver); | ||
createShader = renderer.createShader.bind(renderer); | ||
@@ -98,4 +98,2 @@ return renderer; | ||
this.splice(nodeIndexToRemove, 1); | ||
// Dont remove from parent as that causes extra work | ||
node._queueDelete = true; | ||
} | ||
@@ -124,2 +122,6 @@ } | ||
function isDevEnv() { | ||
return import.meta.env && import.meta.env.DEV; | ||
} | ||
const isDev = isDevEnv() || false; | ||
const config = { | ||
@@ -132,3 +134,2 @@ debug: false, | ||
}, | ||
enableRecursiveRemoval: false, | ||
fontSettings: { | ||
@@ -158,3 +159,11 @@ fontFamily: 'Ubuntu', | ||
function hasDebug(node) { | ||
return isObject(node) && node.debug; | ||
} | ||
function log(msg, node, ...args) { | ||
if (isDev) { | ||
if (config.debug || hasDebug(node) || hasDebug(args[0])) { | ||
console.log(msg, node, ...args); | ||
} | ||
} | ||
} | ||
@@ -164,2 +173,5 @@ function isFunc(item) { | ||
} | ||
function isObject(item) { | ||
return typeof item === 'object'; | ||
} | ||
function isArray(item) { | ||
@@ -185,2 +197,18 @@ return Array.isArray(item); | ||
} | ||
function flattenStyles(obj, result = {}) { | ||
if (isArray(obj)) { | ||
obj.forEach(item => { | ||
flattenStyles(item, result); | ||
}); | ||
} else if (obj) { | ||
// handle the case where the object is not an array | ||
for (const key in obj) { | ||
// be careful of 0 values | ||
if (result[key] === undefined) { | ||
result[key] = obj[key]; | ||
} | ||
} | ||
} | ||
return result; | ||
} | ||
@@ -273,3 +301,3 @@ /* | ||
function assertTruthy(condition, message) { | ||
if (import.meta.env.PROD) return; | ||
if (isProductionEnvironment()) return; | ||
if (!condition) { | ||
@@ -279,2 +307,10 @@ throw new Error(message || 'Assertion failed'); | ||
} | ||
/** | ||
* Checks import.meta if env is production | ||
* | ||
* @returns | ||
*/ | ||
function isProductionEnvironment() { | ||
return import.meta.env && import.meta.env.PROD; | ||
} | ||
@@ -538,3 +574,5 @@ /* | ||
this._effects = v; | ||
this.shader = convertEffectsToShader(v); | ||
if (this.rendered) { | ||
this.shader = convertEffectsToShader(v); | ||
} | ||
} | ||
@@ -652,20 +690,19 @@ get parent() { | ||
destroy() { | ||
if (this.lng && this._queueDelete) { | ||
this.lng.destroy(); | ||
if (this._queueDelete) { | ||
this.lng?.destroy(); | ||
} | ||
} | ||
set style(values) { | ||
const passedArray = isArray(values); | ||
const styleArray = passedArray ? values.filter(v => v) : [values]; | ||
if (isArray(values)) { | ||
this._style = flattenStyles(values); | ||
} else { | ||
this._style = values; | ||
} | ||
// Keys set in JSX are more important | ||
styleArray.forEach(value => { | ||
for (const key in value) { | ||
// be careful of 0 values | ||
if (this[key] === undefined) { | ||
this[key] = value[key]; | ||
} | ||
for (const key in this._style) { | ||
// be careful of 0 values | ||
if (this[key] === undefined) { | ||
this[key] = this._style[key]; | ||
} | ||
}); | ||
// reverse the array so the first style is the most important | ||
this._style = passedArray ? Object.assign({}, ...styleArray.reverse()) : values; | ||
} | ||
} | ||
@@ -678,2 +715,19 @@ get style() { | ||
} | ||
getChildById(id) { | ||
return this.children.find(c => c.id === id); | ||
} | ||
searchChildrenById(id) { | ||
// traverse all the childrens children | ||
for (const child of this.children) { | ||
if (child.id === id) { | ||
return child; | ||
} | ||
if (child instanceof ElementNode) { | ||
const found = child.searchChildrenById(id); | ||
if (found) { | ||
return found; | ||
} | ||
} | ||
} | ||
} | ||
set states(states) { | ||
@@ -697,2 +751,3 @@ this._states = new States(this._stateChanged.bind(this), states); | ||
if (this.hasChildren) { | ||
log('Layout: ', this); | ||
isFunc(this.onBeforeLayout) && this.onBeforeLayout.call(this, child, dimensions); | ||
@@ -714,3 +769,3 @@ if (this.display === 'flex') { | ||
} | ||
const states = config.stateMapperHook?.(this, this.states) || this.states; | ||
const states = this.states; | ||
if (this._undoStyles || this.style && keyExists(this.style, states)) { | ||
@@ -754,2 +809,6 @@ this._undoStyles = this._undoStyles || []; | ||
} | ||
if (!parent.rendered) { | ||
console.warn('Parent not rendered yet: ', this); | ||
return; | ||
} | ||
if (this.rendered) { | ||
@@ -773,2 +832,5 @@ console.warn('Node already rendered: ', this); | ||
} | ||
if (node._effects) { | ||
this.shader = convertEffectsToShader(node._effects); | ||
} | ||
if (node.isTextNode()) { | ||
@@ -792,4 +854,4 @@ props = { | ||
} | ||
log('Rendering: ', this, props); | ||
node.lng = renderer.createTextNode(props); | ||
isFunc(this.onCreate) && this.onCreate.call(this, node); | ||
if (isFunc(node.onLoad)) { | ||
@@ -822,2 +884,3 @@ node.lng.on('loaded', node.onLoad); | ||
} | ||
log('Rendering: ', this, props); | ||
node.lng = renderer.createNode(props); | ||
@@ -830,5 +893,6 @@ if (node.onFail) { | ||
} | ||
isFunc(this.onCreate) && this.onCreate.call(this, node); | ||
} | ||
node.rendered = true; | ||
isFunc(this.onCreate) && this.onCreate.call(this, node); | ||
// L3 Inspector adds div to the lng object | ||
@@ -846,2 +910,5 @@ //@ts-expect-error - div is not in the typings | ||
c.render(); | ||
} else if (c.text !== '') { | ||
// Solid Show uses an empty text node as a placeholder | ||
console.warn('TextNode outside of <Text>: ', c); | ||
} | ||
@@ -900,27 +967,2 @@ }); | ||
const Canvas = (props = {}) => { | ||
const renderer = startLightningRenderer(props.options); | ||
const init = renderer.init(); | ||
function rootRef(root) { | ||
root.renderer = renderer; | ||
if (isFunc(props.ref)) { | ||
props.ref(root); | ||
} else { | ||
props.ref = root; | ||
} | ||
init.then(() => { | ||
root.lng = renderer.root; | ||
root.children.forEach(c => c.render()); | ||
isFunc(props.onFirstRender) && props.onFirstRender(root); | ||
}).catch(console.error); | ||
} | ||
return (() => { | ||
var _el$ = createElement$1("canvas"); | ||
var _ref$ = rootRef; | ||
typeof _ref$ === "function" ? use$1(_ref$, _el$) : rootRef = _el$; | ||
insert$1(_el$, () => props.children); | ||
return _el$; | ||
})(); | ||
}; | ||
function createRenderer$1({ | ||
@@ -1179,20 +1221,5 @@ createElement, | ||
*/ | ||
/** | ||
* Recursively removes all child nodes from the given element node and destroys the node itself. | ||
* | ||
* @param {SolidNode} node - the node | ||
* @return {void} | ||
*/ | ||
function removeChildrenNode(node) { | ||
if (node instanceof ElementNode) { | ||
for (const children of node.children ?? []) { | ||
removeChildrenNode(children); | ||
} | ||
node.destroy(); | ||
} | ||
} | ||
var universalLightning = { | ||
createElement(name) { | ||
const node = new ElementNode(name); | ||
return node; | ||
return new ElementNode(name); | ||
}, | ||
@@ -1208,2 +1235,3 @@ createTextNode(text) { | ||
replaceText(node, value) { | ||
log('Replace Text: ', node, value); | ||
node.text = value; | ||
@@ -1218,15 +1246,10 @@ const parent = node.parent; | ||
insertNode(parent, node, anchor) { | ||
if (parent) { | ||
parent.children.insert(node, anchor); | ||
node._queueDelete = false; | ||
if (node.name === 'TextNode') { | ||
// TextNodes can be placed outside of <text> nodes when <Show> is used as placeholder | ||
if (parent.isTextNode()) { | ||
parent.text = parent.getText(); | ||
} | ||
return; | ||
} | ||
if (renderer.root && parent.rendered && node.render) { | ||
node.render(); | ||
} | ||
log('INSERT: ', parent, node, anchor); | ||
parent.children.insert(node, anchor); | ||
node._queueDelete = false; | ||
if (node instanceof ElementNode) { | ||
parent.rendered && node.render(); | ||
} else if (parent.isTextNode()) { | ||
// TextNodes can be placed outside of <text> nodes when <Show> is used as placeholder | ||
parent.text = parent.getText(); | ||
} | ||
@@ -1238,12 +1261,10 @@ }, | ||
removeNode(parent, node) { | ||
log('REMOVE: ', parent, node); | ||
parent.children.remove(node); | ||
node._queueDelete = true; | ||
if (node instanceof ElementNode) { | ||
if (config.enableRecursiveRemoval) { | ||
queueMicrotask(() => removeChildrenNode(node)); | ||
} else { | ||
// Solid replacesNodes to move them (via insert and remove), | ||
// so we need to wait for the next microtask to destroy the node | ||
// in the event it gets a new parent. | ||
queueMicrotask(() => node.destroy()); | ||
} | ||
// Solid replacesNodes to move them (via insert and remove), | ||
// so we need to wait for the next microtask to destroy the node | ||
// in the event it gets a new parent. | ||
queueMicrotask(() => node.destroy()); | ||
} | ||
@@ -1258,8 +1279,6 @@ }, | ||
getNextSibling(node) { | ||
if (node.parent) { | ||
const children = node.parent.children || []; | ||
const index = children.indexOf(node) + 1; | ||
if (index < children.length) { | ||
return children[index]; | ||
} | ||
const children = node.parent.children || []; | ||
const index = children.indexOf(node) + 1; | ||
if (index < children.length) { | ||
return children[index]; | ||
} | ||
@@ -1289,6 +1308,11 @@ return undefined; | ||
const solidRenderer = createRenderer(universalLightning); | ||
// TODO: This is a hack to get the `render()` function to work as it is used now in the demo app | ||
// There's gotta be a better way to fix it | ||
const render = solidRenderer.render; | ||
const render = async function (code, node) { | ||
const renderer = startLightningRenderer(config.rendererOptions, node); | ||
await renderer.init(); | ||
const rootNode = new ElementNode('App'); | ||
rootNode.lng = renderer.root; | ||
rootNode.rendered = true; | ||
// @ts-expect-error - code is jsx element and not SolidElement yet | ||
return solidRenderer.render(code, rootNode); | ||
}; | ||
const { | ||
@@ -1382,3 +1406,3 @@ effect, | ||
export { Canvas, config as Config, Dynamic, ElementNode, Text, intrinsicTypes as Types, View, activeElement, createComponent, createElement, createShader, createTextNode, deg2rad, effect, hexColor, insert, insertNode, memo, mergeProps, render, renderer, setActiveElement, setProp, spread, startLightningRenderer, use }; | ||
export { config as Config, Dynamic, ElementNode, Text, intrinsicTypes as Types, View, activeElement, createComponent, createElement, createShader, createTextNode, deg2rad, effect, hexColor, insert, insertNode, memo, mergeProps, render, renderer, setActiveElement, setProp, spread, startLightningRenderer, use }; | ||
//# sourceMappingURL=index.js.map |
@@ -19,2 +19,1 @@ /* | ||
export * from './View.jsx'; | ||
export * from './Canvas.jsx'; |
@@ -19,4 +19,6 @@ /* | ||
*/ | ||
//import.meta.env = import.meta.env || { 'MODE': 'development' }; | ||
export const isDev = import.meta.env.MODE === 'development'; | ||
function isDevEnv() { | ||
return import.meta.env && import.meta.env.DEV; | ||
} | ||
export const isDev = isDevEnv() || false; | ||
export const config = { | ||
@@ -29,3 +31,2 @@ debug: false, | ||
}, | ||
enableRecursiveRemoval: false, | ||
fontSettings: { | ||
@@ -32,0 +33,0 @@ fontFamily: 'Ubuntu', |
@@ -48,6 +48,4 @@ /* | ||
this.splice(nodeIndexToRemove, 1); | ||
// Dont remove from parent as that causes extra work | ||
node._queueDelete = true; | ||
} | ||
} | ||
} |
@@ -17,7 +17,7 @@ /* | ||
*/ | ||
import { renderer, createShader } from '../renderer/index.js'; | ||
import { renderer, createShader } from '../lightningInit.js'; | ||
import Children from './children.js'; | ||
import States from './states.js'; | ||
import calculateFlex from '../flex.js'; | ||
import { log, isArray, isNumber, isFunc, keyExists } from '../utils.js'; | ||
import { log, isArray, isNumber, isFunc, keyExists, flattenStyles, } from '../utils.js'; | ||
import { config } from '../../config.js'; | ||
@@ -108,2 +108,3 @@ import { setActiveElement } from '../activeElement.js'; | ||
id; | ||
debug; | ||
name; | ||
@@ -209,3 +210,5 @@ lng; | ||
this._effects = v; | ||
this.shader = convertEffectsToShader(v); | ||
if (this.rendered) { | ||
this.shader = convertEffectsToShader(v); | ||
} | ||
} | ||
@@ -329,20 +332,20 @@ get parent() { | ||
destroy() { | ||
if (this.lng && this._queueDelete) { | ||
this.lng.destroy(); | ||
if (this._queueDelete) { | ||
this.lng?.destroy(); | ||
} | ||
} | ||
set style(values) { | ||
const passedArray = isArray(values); | ||
const styleArray = passedArray ? values.filter((v) => v) : [values]; | ||
if (isArray(values)) { | ||
this._style = flattenStyles(values); | ||
} | ||
else { | ||
this._style = values; | ||
} | ||
// Keys set in JSX are more important | ||
styleArray.forEach((value) => { | ||
for (const key in value) { | ||
// be careful of 0 values | ||
if (this[key] === undefined) { | ||
this[key] = value[key]; | ||
} | ||
for (const key in this._style) { | ||
// be careful of 0 values | ||
if (this[key] === undefined) { | ||
this[key] = this._style[key]; | ||
} | ||
}); | ||
// reverse the array so the first style is the most important | ||
this._style = (passedArray ? Object.assign({}, ...styleArray.reverse()) : values); | ||
} | ||
} | ||
@@ -355,2 +358,19 @@ get style() { | ||
} | ||
getChildById(id) { | ||
return this.children.find((c) => c.id === id); | ||
} | ||
searchChildrenById(id) { | ||
// traverse all the childrens children | ||
for (const child of this.children) { | ||
if (child.id === id) { | ||
return child; | ||
} | ||
if (child instanceof ElementNode) { | ||
const found = child.searchChildrenById(id); | ||
if (found) { | ||
return found; | ||
} | ||
} | ||
} | ||
} | ||
set states(states) { | ||
@@ -392,3 +412,3 @@ this._states = new States(this._stateChanged.bind(this), states); | ||
} | ||
const states = config.stateMapperHook?.(this, this.states) || this.states; | ||
const states = this.states; | ||
if (this._undoStyles || (this.style && keyExists(this.style, states))) { | ||
@@ -427,2 +447,6 @@ this._undoStyles = this._undoStyles || []; | ||
} | ||
if (!parent.rendered) { | ||
console.warn('Parent not rendered yet: ', this); | ||
return; | ||
} | ||
if (this.rendered) { | ||
@@ -445,2 +469,5 @@ console.warn('Node already rendered: ', this); | ||
} | ||
if (node._effects) { | ||
this.shader = convertEffectsToShader(node._effects); | ||
} | ||
if (node.isTextNode()) { | ||
@@ -468,3 +495,2 @@ props = { | ||
node.lng = renderer.createTextNode(props); | ||
isFunc(this.onCreate) && this.onCreate.call(this, node); | ||
if (isFunc(node.onLoad)) { | ||
@@ -506,5 +532,5 @@ node.lng.on('loaded', node.onLoad); | ||
} | ||
isFunc(this.onCreate) && this.onCreate.call(this, node); | ||
} | ||
node.rendered = true; | ||
isFunc(this.onCreate) && this.onCreate.call(this, node); | ||
// L3 Inspector adds div to the lng object | ||
@@ -523,2 +549,6 @@ //@ts-expect-error - div is not in the typings | ||
} | ||
else if (c.text !== '') { | ||
// Solid Show uses an empty text node as a placeholder | ||
console.warn('TextNode outside of <Text>: ', c); | ||
} | ||
}); | ||
@@ -525,0 +555,0 @@ } |
@@ -19,8 +19,17 @@ /* eslint-disable @typescript-eslint/unbound-method */ | ||
import { createRenderer } from 'solid-js/universal'; | ||
import universalLightning from './universal/lightning.js'; | ||
import { config } from '../config.js'; | ||
import { startLightningRenderer } from './lightningInit.js'; | ||
import universalLightning from './solidUniversal.js'; | ||
import { ElementNode } from './node/index.js'; | ||
import { splitProps, createMemo, untrack } from 'solid-js'; | ||
const solidRenderer = createRenderer(universalLightning); | ||
// TODO: This is a hack to get the `render()` function to work as it is used now in the demo app | ||
// There's gotta be a better way to fix it | ||
export const render = solidRenderer.render; | ||
export const render = async function (code, node) { | ||
const renderer = startLightningRenderer(config.rendererOptions, node); | ||
await renderer.init(); | ||
const rootNode = new ElementNode('App'); | ||
rootNode.lng = renderer.root; | ||
rootNode.rendered = true; | ||
// @ts-expect-error - code is jsx element and not SolidElement yet | ||
return solidRenderer.render(code, rootNode); | ||
}; | ||
export const { effect, memo, createComponent, createElement, createTextNode, insertNode, insert, spread, setProp, mergeProps, use, } = solidRenderer; | ||
@@ -27,0 +36,0 @@ /** |
@@ -19,5 +19,8 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ | ||
import { config, isDev } from '../config.js'; | ||
function hasDebug(node) { | ||
return isObject(node) && node.debug; | ||
} | ||
export function log(msg, node, ...args) { | ||
if (isDev) { | ||
if (config.debug || (isObject(node) && node.debug)) { | ||
if (config.debug || hasDebug(node) || hasDebug(args[0])) { | ||
console.log(msg, node, ...args); | ||
@@ -53,1 +56,18 @@ } | ||
} | ||
export function flattenStyles(obj, result = {}) { | ||
if (isArray(obj)) { | ||
obj.forEach((item) => { | ||
flattenStyles(item, result); | ||
}); | ||
} | ||
else if (obj) { | ||
// handle the case where the object is not an array | ||
for (const key in obj) { | ||
// be careful of 0 values | ||
if (result[key] === undefined) { | ||
result[key] = obj[key]; | ||
} | ||
} | ||
} | ||
return result; | ||
} |
@@ -22,3 +22,3 @@ /* | ||
export * from './components/index.js'; | ||
export * from './core/renderer/index.js'; | ||
export * from './core/lightningInit.js'; | ||
export * from './core/render.js'; | ||
@@ -25,0 +25,0 @@ export { config as Config } from './config.js'; |
export * from './Text.jsx'; | ||
export * from './View.jsx'; | ||
export * from './Canvas.jsx'; |
@@ -1,4 +0,3 @@ | ||
import type { AnimationSettings } from '@lightningjs/renderer'; | ||
import type { AnimationSettings, RendererMainSettings } from '@lightningjs/renderer'; | ||
import type { IntrinsicTextNodeStyleProps } from './intrinsicTypes.js'; | ||
import { type ElementNode } from './core/node/index.js'; | ||
interface Config { | ||
@@ -9,4 +8,3 @@ debug: boolean; | ||
fontSettings: Partial<IntrinsicTextNodeStyleProps>; | ||
enableRecursiveRemoval: boolean; | ||
stateMapperHook?: (node: ElementNode, states: Array<string>) => Array<string>; | ||
rendererOptions?: Partial<RendererMainSettings>; | ||
} | ||
@@ -13,0 +11,0 @@ export declare const isDev: boolean; |
@@ -1,2 +0,2 @@ | ||
import { createShader } from '../renderer/index.js'; | ||
import { createShader } from '../lightningInit.js'; | ||
import { type IntrinsicCommonProps, type NodeStyles, type TextStyles } from '../../index.js'; | ||
@@ -7,2 +7,3 @@ import Children from './children.js'; | ||
export interface TextNode { | ||
id?: string; | ||
name: string; | ||
@@ -30,2 +31,3 @@ text: string; | ||
id?: string; | ||
debug?: boolean; | ||
name: string; | ||
@@ -82,2 +84,4 @@ lng: INode | undefined; | ||
get hasChildren(): boolean; | ||
getChildById(id: string): SolidNode; | ||
searchChildrenById(id: string): SolidNode | undefined; | ||
set states(states: NodeStates); | ||
@@ -84,0 +88,0 @@ get states(): States; |
@@ -1,4 +0,4 @@ | ||
import type { SolidNode } from './node/index.js'; | ||
import { type SolidNode } from './node/index.js'; | ||
import { type JSX } from 'solid-js'; | ||
export declare const render: (code: () => JSX.Element, node?: SolidNode) => () => void; | ||
export declare const render: (code: () => JSX.Element, node?: string | HTMLElement | undefined) => Promise<() => void>; | ||
export declare const effect: <T>(fn: (prev?: T) => T, init?: T) => void, memo: <T>(fn: () => T, equal: boolean) => () => T, createComponent: <T>(Comp: (props: T) => SolidNode, props: T) => SolidNode, createElement: (tag: string) => SolidNode, createTextNode: (value: string) => SolidNode, insertNode: (parent: SolidNode, node: SolidNode, anchor?: SolidNode) => void, insert: <T>(parent: any, accessor: T | (() => T), marker?: any) => SolidNode, spread: <T>(node: any, accessor: T | (() => T), skipChildren?: Boolean) => void, setProp: <T>(node: SolidNode, name: string, value: T, prev?: T) => T, mergeProps: (...sources: unknown[]) => unknown, use: <A, T>(fn: (element: SolidNode, arg: A) => T, element: SolidNode, arg: A) => T; | ||
@@ -5,0 +5,0 @@ /** |
@@ -1,2 +0,2 @@ | ||
import type { SolidNode } from './node/index.js'; | ||
import type { SolidNode, SolidStyles } from './node/index.js'; | ||
export declare function log(msg: string, node: SolidNode, ...args: any[]): void; | ||
@@ -10,1 +10,2 @@ export declare function isFunc(item: unknown): item is (...args: unknown[]) => unknown; | ||
export declare function keyExists(obj: Record<string, unknown>, keys: (string | number | symbol)[]): boolean; | ||
export declare function flattenStyles(obj: SolidStyles | undefined | (SolidStyles | undefined)[], result?: Record<string, unknown>): SolidStyles; |
@@ -6,3 +6,3 @@ import './jsx-runtime.js'; | ||
export * from './components/index.js'; | ||
export * from './core/renderer/index.js'; | ||
export * from './core/lightningInit.js'; | ||
export * from './core/render.js'; | ||
@@ -9,0 +9,0 @@ export { config as Config } from './config.js'; |
@@ -26,3 +26,2 @@ import { type AnimationSettings, type Dimensions, type FadeOutEffectProps, type GlitchEffectProps, type GrayscaleEffectProps, type INode, type INodeWritableProps, type ITextNodeWritableProps, type LinearGradientEffectProps, type NodeFailedPayload, type NodeLoadedPayload, type RadialGradientEffectProps, type RadialProgressEffectProps } from '@lightningjs/renderer'; | ||
id?: string; | ||
onCreate?: (target: ElementNode) => void; | ||
onLoad?: (target: INode, nodeLoadedPayload: NodeLoadedPayload) => void; | ||
@@ -78,3 +77,3 @@ onFail?: (target: INode, nodeFailedPayload: NodeFailedPayload) => void; | ||
style?: IntrinsicTextNodeStyleProps | (IntrinsicTextNodeStyleProps | undefined)[] | undefined; | ||
children: string | string[]; | ||
children?: string | (string | undefined)[]; | ||
} | ||
@@ -81,0 +80,0 @@ export type NodeStyles = IntrinsicNodeStyleProps; |
{ | ||
"name": "@lightningjs/solid", | ||
"version": "0.14.4", | ||
"version": "0.15.0", | ||
"description": "Lightning renderer for solid universal", | ||
@@ -53,6 +53,6 @@ "type": "module", | ||
"prettier": "^3.2.5", | ||
"rollup": "^4.12.0", | ||
"rollup": "^4.13.0", | ||
"rollup-preset-solid": "^2.0.1", | ||
"solid-js": "^1.8.15", | ||
"typescript": "^5.3.3" | ||
"solid-js": "^1.8.16", | ||
"typescript": "^5.4.2" | ||
}, | ||
@@ -67,3 +67,3 @@ "lint-staged": { | ||
"dependencies": { | ||
"@lightningjs/renderer": "^0.7.6", | ||
"@lightningjs/renderer": "^0.8.1", | ||
"@lightningjs/solid": "file:" | ||
@@ -70,0 +70,0 @@ }, |
@@ -20,2 +20,1 @@ /* | ||
export * from './View.jsx'; | ||
export * from './Canvas.jsx'; |
@@ -20,5 +20,7 @@ /* | ||
import type { AnimationSettings } from '@lightningjs/renderer'; | ||
import type { | ||
AnimationSettings, | ||
RendererMainSettings, | ||
} from '@lightningjs/renderer'; | ||
import type { IntrinsicTextNodeStyleProps } from './intrinsicTypes.js'; | ||
import { type ElementNode } from './core/node/index.js'; | ||
@@ -30,8 +32,9 @@ interface Config { | ||
fontSettings: Partial<IntrinsicTextNodeStyleProps>; | ||
enableRecursiveRemoval: boolean; | ||
stateMapperHook?: (node: ElementNode, states: Array<string>) => Array<string>; | ||
rendererOptions?: Partial<RendererMainSettings>; | ||
} | ||
//import.meta.env = import.meta.env || { 'MODE': 'development' }; | ||
export const isDev = import.meta.env.MODE === 'development'; | ||
function isDevEnv(): boolean { | ||
return import.meta.env && import.meta.env.DEV; | ||
} | ||
export const isDev = isDevEnv() || false; | ||
@@ -45,3 +48,2 @@ export const config: Config = { | ||
}, | ||
enableRecursiveRemoval: false, | ||
fontSettings: { | ||
@@ -48,0 +50,0 @@ fontFamily: 'Ubuntu', |
@@ -56,6 +56,4 @@ /* | ||
this.splice(nodeIndexToRemove, 1); | ||
// Dont remove from parent as that causes extra work | ||
node._queueDelete = true; | ||
} | ||
} | ||
} |
@@ -18,3 +18,3 @@ /* | ||
import { renderer, createShader } from '../renderer/index.js'; | ||
import { renderer, createShader } from '../lightningInit.js'; | ||
import { | ||
@@ -31,3 +31,10 @@ type BorderStyleObject, | ||
import calculateFlex from '../flex.js'; | ||
import { log, isArray, isNumber, isFunc, keyExists } from '../utils.js'; | ||
import { | ||
log, | ||
isArray, | ||
isNumber, | ||
isFunc, | ||
keyExists, | ||
flattenStyles, | ||
} from '../utils.js'; | ||
import { config } from '../../config.js'; | ||
@@ -137,2 +144,3 @@ import { setActiveElement } from '../activeElement.js'; | ||
export interface TextNode { | ||
id?: string; | ||
name: string; | ||
@@ -167,2 +175,3 @@ text: string; | ||
id?: string; | ||
debug?: boolean; | ||
name: string; | ||
@@ -281,3 +290,5 @@ lng: INode | undefined; | ||
this._effects = v; | ||
this.shader = convertEffectsToShader(v); | ||
if (this.rendered) { | ||
this.shader = convertEffectsToShader(v); | ||
} | ||
} | ||
@@ -422,4 +433,4 @@ | ||
destroy() { | ||
if (this.lng && this._queueDelete) { | ||
this.lng.destroy(); | ||
if (this._queueDelete) { | ||
this.lng?.destroy(); | ||
} | ||
@@ -429,17 +440,14 @@ } | ||
set style(values: SolidStyles | (SolidStyles | undefined)[]) { | ||
const passedArray = isArray(values); | ||
const styleArray = passedArray ? values.filter((v) => v) : [values]; | ||
if (isArray(values)) { | ||
this._style = flattenStyles(values); | ||
} else { | ||
this._style = values; | ||
} | ||
// Keys set in JSX are more important | ||
styleArray.forEach((value) => { | ||
for (const key in value) { | ||
// be careful of 0 values | ||
if (this[key as keyof SolidStyles] === undefined) { | ||
this[key as keyof SolidStyles] = value[key as keyof SolidStyles]; | ||
} | ||
for (const key in this._style) { | ||
// be careful of 0 values | ||
if (this[key as keyof SolidStyles] === undefined) { | ||
this[key as keyof SolidStyles] = this._style[key as keyof SolidStyles]; | ||
} | ||
}); | ||
// reverse the array so the first style is the most important | ||
this._style = ( | ||
passedArray ? Object.assign({}, ...styleArray.reverse()) : values | ||
) as SolidStyles; | ||
} | ||
} | ||
@@ -455,2 +463,21 @@ | ||
getChildById(id: string) { | ||
return this.children.find((c) => c.id === id); | ||
} | ||
searchChildrenById(id: string): SolidNode | undefined { | ||
// traverse all the childrens children | ||
for (const child of this.children) { | ||
if (child.id === id) { | ||
return child; | ||
} | ||
if (child instanceof ElementNode) { | ||
const found = child.searchChildrenById(id); | ||
if (found) { | ||
return found; | ||
} | ||
} | ||
} | ||
} | ||
set states(states: NodeStates) { | ||
@@ -501,3 +528,3 @@ this._states = new States(this._stateChanged.bind(this), states); | ||
const states = config.stateMapperHook?.(this, this.states) || this.states; | ||
const states = this.states; | ||
@@ -545,2 +572,7 @@ if (this._undoStyles || (this.style && keyExists(this.style, states))) { | ||
if (!parent.rendered) { | ||
console.warn('Parent not rendered yet: ', this); | ||
return; | ||
} | ||
if (this.rendered) { | ||
@@ -569,2 +601,6 @@ console.warn('Node already rendered: ', this); | ||
if (node._effects) { | ||
this.shader = convertEffectsToShader(node._effects); | ||
} | ||
if (node.isTextNode()) { | ||
@@ -596,4 +632,2 @@ props = { | ||
isFunc(this.onCreate) && this.onCreate.call(this, node); | ||
if (isFunc(node.onLoad)) { | ||
@@ -640,7 +674,7 @@ node.lng.on('loaded', node.onLoad); | ||
} | ||
isFunc(this.onCreate) && this.onCreate.call(this, node); | ||
} | ||
node.rendered = true; | ||
isFunc(this.onCreate) && this.onCreate.call(this, node); | ||
// L3 Inspector adds div to the lng object | ||
@@ -659,2 +693,5 @@ //@ts-expect-error - div is not in the typings | ||
(c as ElementNode).render(); | ||
} else if (c.text !== '') { | ||
// Solid Show uses an empty text node as a placeholder | ||
console.warn('TextNode outside of <Text>: ', c); | ||
} | ||
@@ -661,0 +698,0 @@ }); |
@@ -20,14 +20,22 @@ /* eslint-disable @typescript-eslint/unbound-method */ | ||
import { createRenderer } from 'solid-js/universal'; | ||
import universalLightning from './universal/lightning.js'; | ||
import type { SolidNode } from './node/index.js'; | ||
import { splitProps, type JSX, createMemo, untrack } from 'solid-js'; | ||
import { config } from '../config.js'; | ||
import { startLightningRenderer } from './lightningInit.js'; | ||
import universalLightning from './solidUniversal.js'; | ||
import { ElementNode, type SolidNode } from './node/index.js'; | ||
import { splitProps, createMemo, untrack, type JSX } from 'solid-js'; | ||
const solidRenderer = createRenderer<SolidNode>(universalLightning); | ||
// TODO: This is a hack to get the `render()` function to work as it is used now in the demo app | ||
// There's gotta be a better way to fix it | ||
export const render = solidRenderer.render as unknown as ( | ||
export const render = async function ( | ||
code: () => JSX.Element, | ||
node?: SolidNode, | ||
) => () => void; | ||
node?: string | HTMLElement | undefined, | ||
) { | ||
const renderer = startLightningRenderer(config.rendererOptions, node); | ||
await renderer.init(); | ||
const rootNode = new ElementNode('App'); | ||
rootNode.lng = renderer.root!; | ||
rootNode.rendered = true; | ||
// @ts-expect-error - code is jsx element and not SolidElement yet | ||
return solidRenderer.render(code, rootNode); | ||
}; | ||
@@ -34,0 +42,0 @@ export const { |
@@ -20,7 +20,11 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ | ||
import { config, isDev } from '../config.js'; | ||
import type { SolidNode } from './node/index.js'; | ||
import type { SolidNode, SolidStyles } from './node/index.js'; | ||
function hasDebug(node: any) { | ||
return isObject(node) && node.debug; | ||
} | ||
export function log(msg: string, node: SolidNode, ...args: any[]) { | ||
if (isDev) { | ||
if (config.debug || (isObject(node) && node.debug)) { | ||
if (config.debug || hasDebug(node) || hasDebug(args[0])) { | ||
console.log(msg, node, ...args); | ||
@@ -68,1 +72,22 @@ } | ||
} | ||
export function flattenStyles( | ||
obj: SolidStyles | undefined | (SolidStyles | undefined)[], | ||
result: Record<string, unknown> = {}, | ||
): SolidStyles { | ||
if (isArray(obj)) { | ||
obj.forEach((item) => { | ||
flattenStyles(item, result); | ||
}); | ||
} else if (obj) { | ||
// handle the case where the object is not an array | ||
for (const key in obj) { | ||
// be careful of 0 values | ||
if (result[key as keyof SolidStyles] === undefined) { | ||
result[key as keyof SolidStyles] = obj[key as keyof SolidStyles]; | ||
} | ||
} | ||
} | ||
return result; | ||
} |
@@ -31,3 +31,3 @@ /* | ||
export * from './components/index.js'; | ||
export * from './core/renderer/index.js'; | ||
export * from './core/lightningInit.js'; | ||
export * from './core/render.js'; | ||
@@ -34,0 +34,0 @@ export { config as Config } from './config.js'; |
@@ -62,3 +62,2 @@ /* | ||
id?: string; | ||
onCreate?: (target: ElementNode) => void; | ||
onLoad?: (target: INode, nodeLoadedPayload: NodeLoadedPayload) => void; | ||
@@ -144,3 +143,3 @@ onFail?: (target: INode, nodeFailedPayload: NodeFailedPayload) => void; | ||
| undefined; | ||
children: string | string[]; | ||
children?: string | (string | undefined)[]; | ||
} | ||
@@ -147,0 +146,0 @@ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
265910
58
4341
+ Added@lightningjs/renderer@0.8.4(transitive)
- Removed@lightningjs/renderer@0.7.6(transitive)
Updated@lightningjs/renderer@^0.8.1