pixi-solid 0.1.21 → 0.2.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/dist/components/bind-props/bind-children.js.map +1 -1
- package/dist/components/bind-props/bind-props.js.map +1 -1
- package/dist/components/bind-props/point-property-names.js.map +1 -1
- package/dist/components/bind-props/set-point-property.js.map +1 -1
- package/dist/components/component-factories.js.map +1 -1
- package/dist/index.js +3 -3
- package/dist/on-resize.js +11 -16
- package/dist/on-resize.js.map +1 -1
- package/dist/on-tick.js.map +1 -1
- package/dist/pixi-application/context.js +2 -1
- package/dist/pixi-application/context.js.map +1 -1
- package/dist/pixi-application/get-pixi-app.js +1 -1
- package/dist/pixi-application/get-pixi-app.js.map +1 -1
- package/dist/pixi-application/get-renderer.js +18 -0
- package/dist/pixi-application/get-renderer.js.map +1 -0
- package/dist/pixi-application/get-ticker.js +4 -8
- package/dist/pixi-application/get-ticker.js.map +1 -1
- package/dist/pixi-application/pixi-application-provider.js +17 -14
- package/dist/pixi-application/pixi-application-provider.js.map +1 -1
- package/dist/pixi-application/pixi-application.js.map +1 -1
- package/dist/pixi-canvas.js.map +1 -1
- package/dist/types/index.d.ts +1 -2
- package/dist/types/pixi-application/context.d.ts +2 -4
- package/dist/types/pixi-application/get-renderer.d.ts +8 -0
- package/dist/types/pixi-application/get-ticker.d.ts +3 -7
- package/dist/types/pixi-application/index.d.ts +2 -1
- package/dist/types/testing/index.d.ts +3 -9
- package/dist/types/testing/pixi-renderer-mock.d.ts +24 -0
- package/dist/types/testing/test-root.d.ts +9 -0
- package/dist/types/testing/test-root.test.d.ts +1 -0
- package/dist/types/use-pixi-screen/use-pixi-screen.d.ts +2 -3
- package/dist/types/use-pixi-screen/use-pixi-screen.test.d.ts +1 -0
- package/dist/types/{delay.d.ts → utils/delay.d.ts} +3 -2
- package/dist/types/utils/index.d.ts +4 -2
- package/dist/types/utils/object-fit-container.test.d.ts +1 -0
- package/dist/types/utils/object-fit.d.ts +41 -2
- package/dist/types/utils/object-fit.test.d.ts +1 -0
- package/dist/use-pixi-screen/pixi-screen-store.js.map +1 -1
- package/dist/use-pixi-screen/use-pixi-screen.js +6 -7
- package/dist/use-pixi-screen/use-pixi-screen.js.map +1 -1
- package/dist/{delay.js → utils/delay.js} +3 -3
- package/dist/utils/delay.js.map +1 -0
- package/dist/utils/index.js +3 -2
- package/dist/utils/object-fit.js +160 -22
- package/dist/utils/object-fit.js.map +1 -1
- package/dist/utils/smooth-damp.js.map +1 -1
- package/dist/utils/spring.js.map +1 -1
- package/package.json +1 -1
- package/dist/delay.js.map +0 -1
- /package/dist/types/{testing/index.test.d.ts → on-resize.test.d.ts} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bind-children.js","names":[],"sources":["../../../src/components/bind-props/bind-children.ts"],"sourcesContent":["import type * as Pixi from \"pixi.js\";\nimport { children as resolveChildren, createRenderEffect } from \"solid-js\";\nimport type { JSX } from \"solid-js\";\n\nexport class InvalidChildTypeError extends Error {\n constructor(cause: Error) {\n super(\n \"Invalid pixi-solid child type. Children must be pixi-solid or PixiJS element. Did you accidentally pass an invalid child to a pixi-solid parent?\",\n { cause },\n );\n this.name = \"InvalidChildTypeError\";\n }\n}\n\nexport const bindChildrenToContainer = (parent: Pixi.Container, children?: JSX.Element): void => {\n const resolvedChildren = resolveChildren(() => children);\n\n const canAddChild = \"addChildAt\" in parent;\n\n if (!canAddChild) {\n throw new Error(\"Parent does not support children.\");\n }\n\n createRenderEffect(() => {\n const nextChildren = resolvedChildren.toArray().filter(Boolean) as unknown as Pixi.Container[];\n\n try {\n for (let i = 0; i < nextChildren.length; i += 1) {\n parent.addChildAt(nextChildren[i], i);\n }\n } catch (error) {\n if (error instanceof Error) {\n console.error(\"Invalid children\", nextChildren);\n throw new InvalidChildTypeError(error);\n } else {\n throw error;\n }\n }\n });\n};\n\nexport const bindChildrenToRenderLayer = (\n parent: Pixi.RenderLayer,\n children?: JSX.Element,\n): void => {\n const resolvedChildren = resolveChildren(() => children);\n\n createRenderEffect((prevChildren: Pixi.Container[] | undefined) => {\n const nextChildren = resolvedChildren.toArray().filter(Boolean) as unknown as Pixi.Container[];\n\n try {\n if (prevChildren) {\n for (let i = 0; i < prevChildren.length; i += 1) {\n const child = prevChildren[i];\n if (nextChildren.includes(child)) continue;\n\n parent.detach(child);\n }\n }\n\n for (let i = 0; i < nextChildren.length; i += 1) {\n parent.attach(nextChildren[i]);\n }\n } catch (error) {\n if (error instanceof Error) {\n console.error(\"Invalid children\", nextChildren);\n throw new InvalidChildTypeError(error);\n } else {\n throw error;\n }\n }\n\n return nextChildren;\n });\n};\n"],"mappings":";;AAIA,IAAa,wBAAb,cAA2C,MAAM;CAC/C,YAAY,OAAc;
|
|
1
|
+
{"version":3,"file":"bind-children.js","names":[],"sources":["../../../src/components/bind-props/bind-children.ts"],"sourcesContent":["import type * as Pixi from \"pixi.js\";\nimport { children as resolveChildren, createRenderEffect } from \"solid-js\";\nimport type { JSX } from \"solid-js\";\n\nexport class InvalidChildTypeError extends Error {\n constructor(cause: Error) {\n super(\n \"Invalid pixi-solid child type. Children must be pixi-solid or PixiJS element. Did you accidentally pass an invalid child to a pixi-solid parent?\",\n { cause },\n );\n this.name = \"InvalidChildTypeError\";\n }\n}\n\nexport const bindChildrenToContainer = (parent: Pixi.Container, children?: JSX.Element): void => {\n const resolvedChildren = resolveChildren(() => children);\n\n const canAddChild = \"addChildAt\" in parent;\n\n if (!canAddChild) {\n throw new Error(\"Parent does not support children.\");\n }\n\n createRenderEffect(() => {\n const nextChildren = resolvedChildren.toArray().filter(Boolean) as unknown as Pixi.Container[];\n\n try {\n for (let i = 0; i < nextChildren.length; i += 1) {\n parent.addChildAt(nextChildren[i], i);\n }\n } catch (error) {\n if (error instanceof Error) {\n console.error(\"Invalid children\", nextChildren);\n throw new InvalidChildTypeError(error);\n } else {\n throw error;\n }\n }\n });\n};\n\nexport const bindChildrenToRenderLayer = (\n parent: Pixi.RenderLayer,\n children?: JSX.Element,\n): void => {\n const resolvedChildren = resolveChildren(() => children);\n\n createRenderEffect((prevChildren: Pixi.Container[] | undefined) => {\n const nextChildren = resolvedChildren.toArray().filter(Boolean) as unknown as Pixi.Container[];\n\n try {\n if (prevChildren) {\n for (let i = 0; i < prevChildren.length; i += 1) {\n const child = prevChildren[i];\n if (nextChildren.includes(child)) continue;\n\n parent.detach(child);\n }\n }\n\n for (let i = 0; i < nextChildren.length; i += 1) {\n parent.attach(nextChildren[i]);\n }\n } catch (error) {\n if (error instanceof Error) {\n console.error(\"Invalid children\", nextChildren);\n throw new InvalidChildTypeError(error);\n } else {\n throw error;\n }\n }\n\n return nextChildren;\n });\n};\n"],"mappings":";;AAIA,IAAa,wBAAb,cAA2C,MAAM;CAC/C,YAAY,OAAc;EACxB,MACE,oJACA,EAAE,OAAO,CACV;EACD,KAAK,OAAO;;;AAIhB,IAAa,2BAA2B,QAAwB,eAAiC;CAC/F,MAAM,mBAAmB,eAAsB,WAAS;CAIxD,IAAI,EAFgB,gBAAgB,SAGlC,MAAM,IAAI,MAAM,oCAAoC;CAGtD,yBAAyB;EACvB,MAAM,eAAe,iBAAiB,SAAS,CAAC,OAAO,QAAQ;EAE/D,IAAI;GACF,KAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK,GAC5C,OAAO,WAAW,aAAa,IAAI,EAAE;WAEhC,OAAO;GACd,IAAI,iBAAiB,OAAO;IAC1B,QAAQ,MAAM,oBAAoB,aAAa;IAC/C,MAAM,IAAI,sBAAsB,MAAM;UAEtC,MAAM;;GAGV;;AAGJ,IAAa,6BACX,QACA,eACS;CACT,MAAM,mBAAmB,eAAsB,WAAS;CAExD,oBAAoB,iBAA+C;EACjE,MAAM,eAAe,iBAAiB,SAAS,CAAC,OAAO,QAAQ;EAE/D,IAAI;GACF,IAAI,cACF,KAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK,GAAG;IAC/C,MAAM,QAAQ,aAAa;IAC3B,IAAI,aAAa,SAAS,MAAM,EAAE;IAElC,OAAO,OAAO,MAAM;;GAIxB,KAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK,GAC5C,OAAO,OAAO,aAAa,GAAG;WAEzB,OAAO;GACd,IAAI,iBAAiB,OAAO;IAC1B,QAAQ,MAAM,oBAAoB,aAAa;IAC/C,MAAM,IAAI,sBAAsB,MAAM;UAEtC,MAAM;;EAIV,OAAO;GACP"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bind-props.js","names":[],"sources":["../../../src/components/bind-props/bind-props.ts"],"sourcesContent":["import type * as Pixi from \"pixi.js\";\nimport { createRenderEffect, onCleanup, on } from \"solid-js\";\n\nimport type { ContainerProps } from \"../component-factories\";\n\nimport { bindChildrenToContainer, bindChildrenToRenderLayer } from \"./bind-children\";\nimport { isEventProperty } from \"./is-event-property\";\nimport {\n isPointProperty,\n setPointProperty,\n isPointAxisProperty,\n setPointAxisProperty,\n} from \"./set-point-property\";\n\n/**\n * Binds the props to a Pixi instance with subscriptions to maintain reactivity.\n *\n * This is specifically for the runtime props that can't be set at initialisation. These props will be set on the Pixi instance immediately after it is created but before rendering.\n *\n * @param instance The Pixi instance we want to bind the props to.\n * @param props The props object.\n */\nexport const bindRuntimeProps = <\n InstanceType extends Pixi.Container,\n OptionsType extends ContainerProps<InstanceType>,\n>(\n instance: InstanceType,\n props: OptionsType,\n): void => {\n createRenderEffect(() => {\n for (const key in props) {\n if (key === \"as\") continue;\n\n if (key === \"ref\") {\n (props[key] as unknown as (arg: any) => void)(instance);\n\n continue;\n } else if (key === \"children\") {\n if (\"attach\" in instance && \"detach\" in instance) {\n bindChildrenToRenderLayer(instance as unknown as Pixi.RenderLayer, props.children);\n } else {\n bindChildrenToContainer(instance, props.children);\n }\n\n continue;\n }\n\n if (isPointProperty(key)) {\n createRenderEffect(() => setPointProperty(instance, key, props[key]));\n\n continue;\n }\n\n if (isPointAxisProperty(key)) {\n createRenderEffect(() => setPointAxisProperty(instance, key, props[key]));\n continue;\n }\n\n if (isEventProperty(key)) {\n createRenderEffect(() => {\n const eventName = key.slice(2);\n const eventHandler = props[key];\n\n if (eventHandler) {\n instance.on(eventName, eventHandler as any);\n onCleanup(() => {\n instance.off(eventName, eventHandler as any);\n });\n }\n });\n\n continue;\n }\n\n if (key in instance) {\n createRenderEffect(() => ((instance as any)[key] = props[key]));\n continue;\n }\n }\n });\n};\n\n/**\n * Binds the props to a Pixi instance with subscriptions to maintain reactivity.\n *\n * This is specifically for the initialisation props that can be set at the time of instance creation. These props will be passed into the Pixi class during instantiation but won't be set on the instance until they are changed again. This is to avoid side effects that can be caused by setting certain props after the instance is created, such as the AnimatedSprite's `textures` prop which stops the animation if it was already instantiated with `autoplay: true`.\n *\n * @param instance The Pixi instance we want to bind the props to.\n * @param props The props object.\n */\nexport const bindInitialisationProps = <\n InstanceType extends Pixi.Container,\n OptionsType extends ContainerProps<InstanceType>,\n>(\n instance: InstanceType,\n props: OptionsType,\n): void => {\n createRenderEffect<boolean>((defer) => {\n for (const key in props) {\n if (isPointProperty(key)) {\n createRenderEffect(\n on(\n () => props[key],\n () => {\n return setPointProperty(instance, key, props[key]);\n },\n { defer },\n ),\n );\n\n continue;\n }\n\n if (key in instance) {\n createRenderEffect(\n on(\n () => props[key],\n () => {\n (instance as any)[key] = props[key];\n },\n { defer },\n ),\n );\n }\n }\n\n return false;\n }, true);\n\n /**\n * Do not throw an error here for invalid prop names because there are some initialisation props that are not available as public properties. We want to allow users to pass these props but not try to set them on the instance.\n */\n};\n"],"mappings":";;;;;;;;;;;;;AAsBA,IAAa,oBAIX,UACA,UACS;
|
|
1
|
+
{"version":3,"file":"bind-props.js","names":[],"sources":["../../../src/components/bind-props/bind-props.ts"],"sourcesContent":["import type * as Pixi from \"pixi.js\";\nimport { createRenderEffect, onCleanup, on } from \"solid-js\";\n\nimport type { ContainerProps } from \"../component-factories\";\n\nimport { bindChildrenToContainer, bindChildrenToRenderLayer } from \"./bind-children\";\nimport { isEventProperty } from \"./is-event-property\";\nimport {\n isPointProperty,\n setPointProperty,\n isPointAxisProperty,\n setPointAxisProperty,\n} from \"./set-point-property\";\n\n/**\n * Binds the props to a Pixi instance with subscriptions to maintain reactivity.\n *\n * This is specifically for the runtime props that can't be set at initialisation. These props will be set on the Pixi instance immediately after it is created but before rendering.\n *\n * @param instance The Pixi instance we want to bind the props to.\n * @param props The props object.\n */\nexport const bindRuntimeProps = <\n InstanceType extends Pixi.Container,\n OptionsType extends ContainerProps<InstanceType>,\n>(\n instance: InstanceType,\n props: OptionsType,\n): void => {\n createRenderEffect(() => {\n for (const key in props) {\n if (key === \"as\") continue;\n\n if (key === \"ref\") {\n (props[key] as unknown as (arg: any) => void)(instance);\n\n continue;\n } else if (key === \"children\") {\n if (\"attach\" in instance && \"detach\" in instance) {\n bindChildrenToRenderLayer(instance as unknown as Pixi.RenderLayer, props.children);\n } else {\n bindChildrenToContainer(instance, props.children);\n }\n\n continue;\n }\n\n if (isPointProperty(key)) {\n createRenderEffect(() => setPointProperty(instance, key, props[key]));\n\n continue;\n }\n\n if (isPointAxisProperty(key)) {\n createRenderEffect(() => setPointAxisProperty(instance, key, props[key]));\n continue;\n }\n\n if (isEventProperty(key)) {\n createRenderEffect(() => {\n const eventName = key.slice(2);\n const eventHandler = props[key];\n\n if (eventHandler) {\n instance.on(eventName, eventHandler as any);\n onCleanup(() => {\n instance.off(eventName, eventHandler as any);\n });\n }\n });\n\n continue;\n }\n\n if (key in instance) {\n createRenderEffect(() => ((instance as any)[key] = props[key]));\n continue;\n }\n }\n });\n};\n\n/**\n * Binds the props to a Pixi instance with subscriptions to maintain reactivity.\n *\n * This is specifically for the initialisation props that can be set at the time of instance creation. These props will be passed into the Pixi class during instantiation but won't be set on the instance until they are changed again. This is to avoid side effects that can be caused by setting certain props after the instance is created, such as the AnimatedSprite's `textures` prop which stops the animation if it was already instantiated with `autoplay: true`.\n *\n * @param instance The Pixi instance we want to bind the props to.\n * @param props The props object.\n */\nexport const bindInitialisationProps = <\n InstanceType extends Pixi.Container,\n OptionsType extends ContainerProps<InstanceType>,\n>(\n instance: InstanceType,\n props: OptionsType,\n): void => {\n createRenderEffect<boolean>((defer) => {\n for (const key in props) {\n if (isPointProperty(key)) {\n createRenderEffect(\n on(\n () => props[key],\n () => {\n return setPointProperty(instance, key, props[key]);\n },\n { defer },\n ),\n );\n\n continue;\n }\n\n if (key in instance) {\n createRenderEffect(\n on(\n () => props[key],\n () => {\n (instance as any)[key] = props[key];\n },\n { defer },\n ),\n );\n }\n }\n\n return false;\n }, true);\n\n /**\n * Do not throw an error here for invalid prop names because there are some initialisation props that are not available as public properties. We want to allow users to pass these props but not try to set them on the instance.\n */\n};\n"],"mappings":";;;;;;;;;;;;;AAsBA,IAAa,oBAIX,UACA,UACS;CACT,yBAAyB;EACvB,KAAK,MAAM,OAAO,OAAO;GACvB,IAAI,QAAQ,MAAM;GAElB,IAAI,QAAQ,OAAO;IACjB,MAAO,KAAuC,SAAS;IAEvD;UACK,IAAI,QAAQ,YAAY;IAC7B,IAAI,YAAY,YAAY,YAAY,UACtC,0BAA0B,UAAyC,MAAM,SAAS;SAElF,wBAAwB,UAAU,MAAM,SAAS;IAGnD;;GAGF,IAAI,gBAAgB,IAAI,EAAE;IACxB,yBAAyB,iBAAiB,UAAU,KAAK,MAAM,KAAK,CAAC;IAErE;;GAGF,IAAI,oBAAoB,IAAI,EAAE;IAC5B,yBAAyB,qBAAqB,UAAU,KAAK,MAAM,KAAK,CAAC;IACzE;;GAGF,IAAI,gBAAgB,IAAI,EAAE;IACxB,yBAAyB;KACvB,MAAM,YAAY,IAAI,MAAM,EAAE;KAC9B,MAAM,eAAe,MAAM;KAE3B,IAAI,cAAc;MAChB,SAAS,GAAG,WAAW,aAAoB;MAC3C,gBAAgB;OACd,SAAS,IAAI,WAAW,aAAoB;QAC5C;;MAEJ;IAEF;;GAGF,IAAI,OAAO,UAAU;IACnB,yBAA0B,SAAkB,OAAO,MAAM,KAAM;IAC/D;;;GAGJ;;;;;;;;;;AAWJ,IAAa,2BAIX,UACA,UACS;CACT,oBAA6B,UAAU;EACrC,KAAK,MAAM,OAAO,OAAO;GACvB,IAAI,gBAAgB,IAAI,EAAE;IACxB,mBACE,SACQ,MAAM,YACN;KACJ,OAAO,iBAAiB,UAAU,KAAK,MAAM,KAAK;OAEpD,EAAE,OAAO,CACV,CACF;IAED;;GAGF,IAAI,OAAO,UACT,mBACE,SACQ,MAAM,YACN;IACJ,SAAkB,OAAO,MAAM;MAEjC,EAAE,OAAO,CACV,CACF;;EAIL,OAAO;IACN,KAAK"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"point-property-names.js","names":[],"sources":["../../../src/components/bind-props/point-property-names.ts"],"sourcesContent":["// Common point properties available on all Container-based components\nexport const COMMON_POINT_PROP_NAMES = [\"position\", \"scale\", \"pivot\", \"skew\"] as const;\n\nexport type CommonPointPropName = (typeof COMMON_POINT_PROP_NAMES)[number];\n\n// Anchor properties only available on Sprite-like components (Sprite, Text, etc.)\nexport const ANCHOR_POINT_PROP_NAMES = [\"anchor\"] as const;\n\nexport type AnchorPointPropName = (typeof ANCHOR_POINT_PROP_NAMES)[number];\n\n// Tiling properties only available on TilingSprite\nexport const TILING_POINT_PROP_NAMES = [\"tilePosition\", \"tileScale\"] as const;\n\nexport type TilingPointPropName = (typeof TILING_POINT_PROP_NAMES)[number];\n\n// All point properties (for runtime checking)\nexport const POINT_PROP_NAMES = [\n ...COMMON_POINT_PROP_NAMES,\n ...ANCHOR_POINT_PROP_NAMES,\n ...TILING_POINT_PROP_NAMES,\n] as const;\n\nexport type PointPropName = (typeof POINT_PROP_NAMES)[number];\n\nexport const POINT_PROP_NAMES_SET: Set<string> = new Set(POINT_PROP_NAMES);\n\n// Common axis properties available on all Container-based components\nexport const COMMON_POINT_PROP_AXIS_NAMES = [\n \"positionX\",\n \"positionY\",\n \"scaleX\",\n \"scaleY\",\n \"pivotX\",\n \"pivotY\",\n \"skewX\",\n \"skewY\",\n] as const;\n\nexport type CommonPointAxisPropName = (typeof COMMON_POINT_PROP_AXIS_NAMES)[number];\n\n// Anchor axis properties only available on Sprite-like components\nexport const ANCHOR_POINT_PROP_AXIS_NAMES = [\"anchorX\", \"anchorY\"] as const;\n\nexport type AnchorPointAxisPropName = (typeof ANCHOR_POINT_PROP_AXIS_NAMES)[number];\n\n// Tiling axis properties only available on TilingSprite\nexport const TILING_POINT_PROP_AXIS_NAMES = [\n \"tilePositionX\",\n \"tilePositionY\",\n \"tileScaleX\",\n \"tileScaleY\",\n] as const;\n\nexport type TilingPointAxisPropName = (typeof TILING_POINT_PROP_AXIS_NAMES)[number];\n\n// All axis properties (for runtime checking)\nexport const POINT_PROP_AXIS_NAMES = [\n ...COMMON_POINT_PROP_AXIS_NAMES,\n ...ANCHOR_POINT_PROP_AXIS_NAMES,\n ...TILING_POINT_PROP_AXIS_NAMES,\n] as const;\n\nexport type PointAxisPropName = (typeof POINT_PROP_AXIS_NAMES)[number];\n\nexport const POINT_PROP_AXIS_NAMES_SET: Set<string> = new Set(POINT_PROP_AXIS_NAMES);\n\nexport const ALL_VALID_PROP_NAMES_SET: Set<string> = new Set([\n ...POINT_PROP_NAMES_SET,\n ...POINT_PROP_AXIS_NAMES_SET,\n]);\n\nexport const POINT_PROP_AXIS_MAP = POINT_PROP_AXIS_NAMES.reduce((map, name) => {\n const axisName = name[name.length - 1].toLowerCase() as \"x\" | \"y\";\n const propertyName = name.slice(0, -1);\n map.set(name, { propertyName, axisName });\n return map;\n}, new Map<string, { propertyName: string; axisName: \"x\" | \"y\" }>());\n"],"mappings":";AACA,IAAa,0BAA0B;CAAC;CAAY;CAAS;CAAS;CAAO;AAK7E,IAAa,0BAA0B,CAAC,SAAS;AAKjD,IAAa,0BAA0B,CAAC,gBAAgB,YAAY;AAKpE,IAAa,mBAAmB;CAC9B,GAAG;CACH,GAAG;CACH,GAAG;CACJ;AAID,IAAa,uBAAoC,IAAI,IAAI,iBAAiB;AAG1E,IAAa,+BAA+B;CAC1C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AAKD,IAAa,+BAA+B,CAAC,WAAW,UAAU;AAKlE,IAAa,+BAA+B;CAC1C;CACA;CACA;CACA;CACD;AAKD,IAAa,wBAAwB;CACnC,GAAG;CACH,GAAG;CACH,GAAG;CACJ;AAID,IAAa,4BAAyC,IAAI,IAAI,sBAAsB;AAE/B,IAAI,IAAI,CAC3D,GAAG,sBACH,GAAG,0BACJ,CAAC;AAEF,IAAa,sBAAsB,sBAAsB,QAAQ,KAAK,SAAS;CAC7E,MAAM,WAAW,KAAK,KAAK,SAAS,GAAG,aAAa;CACpD,MAAM,eAAe,KAAK,MAAM,GAAG,GAAG;
|
|
1
|
+
{"version":3,"file":"point-property-names.js","names":[],"sources":["../../../src/components/bind-props/point-property-names.ts"],"sourcesContent":["// Common point properties available on all Container-based components\nexport const COMMON_POINT_PROP_NAMES = [\"position\", \"scale\", \"pivot\", \"skew\"] as const;\n\nexport type CommonPointPropName = (typeof COMMON_POINT_PROP_NAMES)[number];\n\n// Anchor properties only available on Sprite-like components (Sprite, Text, etc.)\nexport const ANCHOR_POINT_PROP_NAMES = [\"anchor\"] as const;\n\nexport type AnchorPointPropName = (typeof ANCHOR_POINT_PROP_NAMES)[number];\n\n// Tiling properties only available on TilingSprite\nexport const TILING_POINT_PROP_NAMES = [\"tilePosition\", \"tileScale\"] as const;\n\nexport type TilingPointPropName = (typeof TILING_POINT_PROP_NAMES)[number];\n\n// All point properties (for runtime checking)\nexport const POINT_PROP_NAMES = [\n ...COMMON_POINT_PROP_NAMES,\n ...ANCHOR_POINT_PROP_NAMES,\n ...TILING_POINT_PROP_NAMES,\n] as const;\n\nexport type PointPropName = (typeof POINT_PROP_NAMES)[number];\n\nexport const POINT_PROP_NAMES_SET: Set<string> = new Set(POINT_PROP_NAMES);\n\n// Common axis properties available on all Container-based components\nexport const COMMON_POINT_PROP_AXIS_NAMES = [\n \"positionX\",\n \"positionY\",\n \"scaleX\",\n \"scaleY\",\n \"pivotX\",\n \"pivotY\",\n \"skewX\",\n \"skewY\",\n] as const;\n\nexport type CommonPointAxisPropName = (typeof COMMON_POINT_PROP_AXIS_NAMES)[number];\n\n// Anchor axis properties only available on Sprite-like components\nexport const ANCHOR_POINT_PROP_AXIS_NAMES = [\"anchorX\", \"anchorY\"] as const;\n\nexport type AnchorPointAxisPropName = (typeof ANCHOR_POINT_PROP_AXIS_NAMES)[number];\n\n// Tiling axis properties only available on TilingSprite\nexport const TILING_POINT_PROP_AXIS_NAMES = [\n \"tilePositionX\",\n \"tilePositionY\",\n \"tileScaleX\",\n \"tileScaleY\",\n] as const;\n\nexport type TilingPointAxisPropName = (typeof TILING_POINT_PROP_AXIS_NAMES)[number];\n\n// All axis properties (for runtime checking)\nexport const POINT_PROP_AXIS_NAMES = [\n ...COMMON_POINT_PROP_AXIS_NAMES,\n ...ANCHOR_POINT_PROP_AXIS_NAMES,\n ...TILING_POINT_PROP_AXIS_NAMES,\n] as const;\n\nexport type PointAxisPropName = (typeof POINT_PROP_AXIS_NAMES)[number];\n\nexport const POINT_PROP_AXIS_NAMES_SET: Set<string> = new Set(POINT_PROP_AXIS_NAMES);\n\nexport const ALL_VALID_PROP_NAMES_SET: Set<string> = new Set([\n ...POINT_PROP_NAMES_SET,\n ...POINT_PROP_AXIS_NAMES_SET,\n]);\n\nexport const POINT_PROP_AXIS_MAP = POINT_PROP_AXIS_NAMES.reduce((map, name) => {\n const axisName = name[name.length - 1].toLowerCase() as \"x\" | \"y\";\n const propertyName = name.slice(0, -1);\n map.set(name, { propertyName, axisName });\n return map;\n}, new Map<string, { propertyName: string; axisName: \"x\" | \"y\" }>());\n"],"mappings":";AACA,IAAa,0BAA0B;CAAC;CAAY;CAAS;CAAS;CAAO;AAK7E,IAAa,0BAA0B,CAAC,SAAS;AAKjD,IAAa,0BAA0B,CAAC,gBAAgB,YAAY;AAKpE,IAAa,mBAAmB;CAC9B,GAAG;CACH,GAAG;CACH,GAAG;CACJ;AAID,IAAa,uBAAoC,IAAI,IAAI,iBAAiB;AAG1E,IAAa,+BAA+B;CAC1C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AAKD,IAAa,+BAA+B,CAAC,WAAW,UAAU;AAKlE,IAAa,+BAA+B;CAC1C;CACA;CACA;CACA;CACD;AAKD,IAAa,wBAAwB;CACnC,GAAG;CACH,GAAG;CACH,GAAG;CACJ;AAID,IAAa,4BAAyC,IAAI,IAAI,sBAAsB;AAE/B,IAAI,IAAI,CAC3D,GAAG,sBACH,GAAG,0BACJ,CAAC;AAEF,IAAa,sBAAsB,sBAAsB,QAAQ,KAAK,SAAS;CAC7E,MAAM,WAAW,KAAK,KAAK,SAAS,GAAG,aAAa;CACpD,MAAM,eAAe,KAAK,MAAM,GAAG,GAAG;CACtC,IAAI,IAAI,MAAM;EAAE;EAAc;EAAU,CAAC;CACzC,OAAO;mBACN,IAAI,KAA4D,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"set-point-property.js","names":[],"sources":["../../../src/components/bind-props/set-point-property.ts"],"sourcesContent":["import type * as Pixi from \"pixi.js\";\n\nimport {\n POINT_PROP_NAMES_SET,\n POINT_PROP_AXIS_MAP,\n POINT_PROP_AXIS_NAMES_SET,\n} from \"./point-property-names\";\nimport type { PointAxisPropName, PointPropName } from \"./point-property-names\";\n\nexport const isPointProperty = (propName: string): propName is PointPropName =>\n POINT_PROP_NAMES_SET.has(propName);\n\nexport const setPointProperty = <T>(node: Pixi.Container, name: PointPropName, value: T): void => {\n if (typeof value === \"number\") {\n (node as any)[name].set(value);\n return;\n }\n\n (node as any)[name].set((value as any).x, (value as any).y);\n};\n\nexport const isPointAxisProperty = (propName: string): propName is PointAxisPropName =>\n POINT_PROP_AXIS_NAMES_SET.has(propName);\n\nexport const setPointAxisProperty = <T>(\n node: Pixi.Container,\n name: PointAxisPropName,\n value: T,\n): void => {\n const axisInfo = POINT_PROP_AXIS_MAP.get(name);\n if (axisInfo) {\n (node as any)[axisInfo.propertyName][axisInfo.axisName] = value;\n }\n};\n"],"mappings":";;AASA,IAAa,mBAAmB,aAC9B,qBAAqB,IAAI,SAAS;AAEpC,IAAa,oBAAuB,MAAsB,MAAqB,UAAmB;
|
|
1
|
+
{"version":3,"file":"set-point-property.js","names":[],"sources":["../../../src/components/bind-props/set-point-property.ts"],"sourcesContent":["import type * as Pixi from \"pixi.js\";\n\nimport {\n POINT_PROP_NAMES_SET,\n POINT_PROP_AXIS_MAP,\n POINT_PROP_AXIS_NAMES_SET,\n} from \"./point-property-names\";\nimport type { PointAxisPropName, PointPropName } from \"./point-property-names\";\n\nexport const isPointProperty = (propName: string): propName is PointPropName =>\n POINT_PROP_NAMES_SET.has(propName);\n\nexport const setPointProperty = <T>(node: Pixi.Container, name: PointPropName, value: T): void => {\n if (typeof value === \"number\") {\n (node as any)[name].set(value);\n return;\n }\n\n (node as any)[name].set((value as any).x, (value as any).y);\n};\n\nexport const isPointAxisProperty = (propName: string): propName is PointAxisPropName =>\n POINT_PROP_AXIS_NAMES_SET.has(propName);\n\nexport const setPointAxisProperty = <T>(\n node: Pixi.Container,\n name: PointAxisPropName,\n value: T,\n): void => {\n const axisInfo = POINT_PROP_AXIS_MAP.get(name);\n if (axisInfo) {\n (node as any)[axisInfo.propertyName][axisInfo.axisName] = value;\n }\n};\n"],"mappings":";;AASA,IAAa,mBAAmB,aAC9B,qBAAqB,IAAI,SAAS;AAEpC,IAAa,oBAAuB,MAAsB,MAAqB,UAAmB;CAChG,IAAI,OAAO,UAAU,UAAU;EAC7B,KAAc,MAAM,IAAI,MAAM;EAC9B;;CAGF,KAAc,MAAM,IAAK,MAAc,GAAI,MAAc,EAAE;;AAG7D,IAAa,uBAAuB,aAClC,0BAA0B,IAAI,SAAS;AAEzC,IAAa,wBACX,MACA,MACA,UACS;CACT,MAAM,WAAW,oBAAoB,IAAI,KAAK;CAC9C,IAAI,UACF,KAAc,SAAS,cAAc,SAAS,YAAY"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component-factories.js","names":[],"sources":["../../src/components/component-factories.ts"],"sourcesContent":["import type * as Pixi from \"pixi.js\";\nimport type { JSX, Ref } from \"solid-js\";\nimport { createRenderEffect, on, splitProps, onCleanup } from \"solid-js\";\n\nimport { getTicker } from \"../pixi-application\";\n\nimport { bindInitialisationProps, bindRuntimeProps } from \"./bind-props\";\nimport type { PixiSolidEventHandlerMap } from \"./bind-props/event-names\";\nimport { PIXI_SOLID_EVENT_HANDLER_NAMES } from \"./bind-props/event-names\";\nimport type {\n CommonPointAxisPropName,\n AnchorPointAxisPropName,\n TilingPointAxisPropName,\n} from \"./bind-props/point-property-names\";\nimport {\n COMMON_POINT_PROP_AXIS_NAMES,\n ANCHOR_POINT_PROP_AXIS_NAMES,\n TILING_POINT_PROP_AXIS_NAMES,\n} from \"./bind-props/point-property-names\";\n\n/**\n * Common point axis properties available on all Container-based components\n */\nexport type CommonPointAxisProps = Partial<Record<CommonPointAxisPropName, number>>;\n\n/**\n * Anchor point axis properties available on Sprite-like components\n */\nexport type AnchorPointAxisProps = Partial<Record<AnchorPointAxisPropName, number>>;\n\n/**\n * Tiling point axis properties available on TilingSprite\n */\nexport type TilingPointAxisProps = Partial<Record<TilingPointAxisPropName, number>>;\n\n/**\n * This is a utility type useful for extending the props of custom components to allow props to be passed through to the underlying Pixi instance.\n *\n * If you don't require them all it's recommended to narrow the type by using Pick or Omit the props to only allow the ones you need.\n *\n * @example PixiComponentProps<Pixi.SpriteOptions>.\n */\nexport type PixiComponentProps<\n ComponentOptions extends Pixi.ContainerOptions = Pixi.ContainerOptions,\n> = PixiSolidEventHandlerMap & CommonPointAxisProps & Omit<ComponentOptions, \"children\">;\n\ntype RefAsProps<Component> = {\n ref?: Ref<Component>;\n as?: Component;\n};\n\ntype PixiComponent<Props, Instance> = (props: Props) => Instance & JSX.Element;\n\n/**\n * Prop definition for basic Container components (position, scale, pivot, skew only)\n */\nexport type ContainerProps<Component> = PixiSolidEventHandlerMap &\n CommonPointAxisProps &\n RefAsProps<Component> & {\n children?: JSX.Element;\n };\n\n/**\n * Prop definition for components that cannot have children\n */\nexport type LeafProps<Component> = PixiSolidEventHandlerMap &\n CommonPointAxisProps &\n RefAsProps<Component>;\n\n/**\n * Prop definition for Sprite-like components (includes anchor properties)\n */\nexport type SpriteProps<Component> = PixiSolidEventHandlerMap &\n CommonPointAxisProps &\n AnchorPointAxisProps &\n RefAsProps<Component>;\n\nexport type AnimatedSpriteProps<Component> = SpriteProps<Component> &\n Pick<Pixi.AnimatedSpriteOptions, \"autoUpdate\">;\n\ntype AnimatedSpriteLike = Pixi.Container & {\n autoUpdate: boolean;\n update: (ticker: Pixi.Ticker) => void;\n};\n\n/**\n * Prop definition for TilingSprite (includes anchor and tiling properties)\n */\nexport type TilingSpriteProps<Component> = PixiSolidEventHandlerMap &\n CommonPointAxisProps &\n AnchorPointAxisProps &\n TilingPointAxisProps &\n RefAsProps<Component>;\n\n/**\n * Prop definition for filter components\n */\nexport type FilterProps<Component> = RefAsProps<Component>;\n\n// Keys that are specific to Solid components and not Pixi props\nexport const SOLID_PROP_KEYS = [\"ref\", \"as\", \"children\"] as const;\n\n// Combined keys for splitting props\nconst CONTAINER_RUNTIME_KEYS = [\n ...SOLID_PROP_KEYS,\n ...PIXI_SOLID_EVENT_HANDLER_NAMES,\n ...COMMON_POINT_PROP_AXIS_NAMES,\n] as const;\n\n// Sprite components don't accept \"children\" since they can't have children\nconst SPRITE_RUNTIME_KEYS = [\n \"ref\",\n \"as\",\n ...PIXI_SOLID_EVENT_HANDLER_NAMES,\n ...COMMON_POINT_PROP_AXIS_NAMES,\n ...ANCHOR_POINT_PROP_AXIS_NAMES,\n] as const;\n\nconst TILING_SPRITE_RUNTIME_KEYS = [\n \"ref\",\n \"as\",\n ...PIXI_SOLID_EVENT_HANDLER_NAMES,\n ...COMMON_POINT_PROP_AXIS_NAMES,\n ...ANCHOR_POINT_PROP_AXIS_NAMES,\n ...TILING_POINT_PROP_AXIS_NAMES,\n] as const;\n\nexport const createContainerComponent = <\n InstanceType extends Pixi.Container,\n OptionsType extends object,\n>(\n PixiClass: new (props: OptionsType) => InstanceType,\n): PixiComponent<Omit<OptionsType, \"children\"> & ContainerProps<InstanceType>, InstanceType> => {\n return (props): InstanceType & JSX.Element => {\n const [runtimeProps, initialisationProps] = splitProps(props, CONTAINER_RUNTIME_KEYS);\n\n const instance = props.as || new PixiClass(initialisationProps as any);\n\n bindInitialisationProps(instance, initialisationProps);\n bindRuntimeProps(instance, runtimeProps);\n\n onCleanup(() => {\n if (\"attach\" in instance) {\n // Means it's a render layer so we don't want to destroy children as they are managed elsewhere in the tree.\n instance.destroy({ children: false });\n } else {\n instance.destroy({ children: true });\n }\n });\n\n return instance as InstanceType & JSX.Element;\n };\n};\n\nexport const createLeafComponent = <\n InstanceType extends Pixi.Container,\n OptionsType extends object,\n>(\n PixiClass: new (props: OptionsType) => InstanceType,\n): PixiComponent<Omit<OptionsType, \"children\"> & LeafProps<InstanceType>, InstanceType> => {\n return (\n props: Omit<OptionsType, \"children\"> & LeafProps<InstanceType>,\n ): InstanceType & JSX.Element => {\n return createContainerComponent<InstanceType, OptionsType>(PixiClass)(props);\n };\n};\n\nexport const createSpriteComponent = <\n InstanceType extends Pixi.Container,\n OptionsType extends object,\n>(\n PixiClass: new (props: OptionsType) => InstanceType,\n): PixiComponent<Omit<OptionsType, \"children\"> & SpriteProps<InstanceType>, InstanceType> => {\n return (\n props: Omit<OptionsType, \"children\"> & SpriteProps<InstanceType>,\n ): InstanceType & JSX.Element => {\n const [runtimeProps, initialisationProps] = splitProps(props, SPRITE_RUNTIME_KEYS);\n\n const instance = props.as || new PixiClass(initialisationProps as any);\n\n bindInitialisationProps(instance, initialisationProps);\n bindRuntimeProps(instance, runtimeProps);\n\n onCleanup(() => {\n instance.destroy({ children: true });\n });\n\n return instance as InstanceType & JSX.Element;\n };\n};\n\nexport const createAnimatedSpriteComponent = <\n InstanceType extends AnimatedSpriteLike,\n OptionsType extends object,\n>(\n PixiClass: new (props: OptionsType) => InstanceType,\n): PixiComponent<\n Omit<OptionsType, \"children\"> & AnimatedSpriteProps<InstanceType>,\n InstanceType\n> => {\n return (\n props: Omit<OptionsType, \"children\"> & AnimatedSpriteProps<InstanceType>,\n ): InstanceType & JSX.Element => {\n // Specifically separate `autoUpdate` as we handle it manually below.\n const [runtimeProps, update, initialisationProps] = splitProps(props, SPRITE_RUNTIME_KEYS, [\n \"autoUpdate\",\n ]);\n\n const instance = props.as || new PixiClass(initialisationProps as any);\n\n // Set this to false to override Pixi's default shared ticker behaviour.\n instance.autoUpdate = false;\n\n createRenderEffect(\n on(\n () => update.autoUpdate,\n (autoUpdate) => {\n const updateInstance = (ticker: Pixi.Ticker) => {\n instance.update(ticker);\n };\n\n if (autoUpdate !== false) {\n const ticker = getTicker();\n ticker.add(updateInstance);\n onCleanup(() => {\n ticker.remove(updateInstance);\n });\n }\n },\n ),\n );\n\n bindInitialisationProps(instance, initialisationProps);\n bindRuntimeProps(instance, runtimeProps);\n\n onCleanup(() => {\n instance.destroy({ children: true });\n });\n\n return instance as InstanceType & JSX.Element;\n };\n};\n\nexport const createTilingSpriteComponent = <\n InstanceType extends Pixi.Container,\n OptionsType extends object,\n>(\n PixiClass: new (props: OptionsType) => InstanceType,\n): PixiComponent<Omit<OptionsType, \"children\"> & TilingSpriteProps<InstanceType>, InstanceType> => {\n return (\n props: Omit<OptionsType, \"children\"> & TilingSpriteProps<InstanceType>,\n ): InstanceType & JSX.Element => {\n const [runtimeProps, initialisationProps] = splitProps(props, TILING_SPRITE_RUNTIME_KEYS);\n\n const instance = props.as || new PixiClass(initialisationProps as any);\n\n bindInitialisationProps(instance, initialisationProps);\n bindRuntimeProps(instance, runtimeProps);\n\n onCleanup(() => {\n instance.destroy({ children: true });\n });\n\n return instance as InstanceType & JSX.Element;\n };\n};\n\nexport const createFilterComponent = <InstanceType extends Pixi.Filter, OptionsType extends object>(\n PixiClass: new (props: OptionsType) => InstanceType,\n): PixiComponent<OptionsType & FilterProps<InstanceType>, InstanceType> => {\n return (props: OptionsType & FilterProps<InstanceType>): InstanceType & JSX.Element => {\n const [runtimeProps, initialisationProps] = splitProps(props, [\"ref\", \"as\"]);\n\n const instance = props.as || new PixiClass(initialisationProps as any);\n\n for (const key in initialisationProps) {\n if (key === \"as\") continue;\n\n if (key === \"ref\") {\n createRenderEffect(() => {\n // Solid converts the ref prop to a callback function\n (props[key] as unknown as (arg: any) => void)(instance);\n });\n } else if (key === \"children\") {\n throw new Error(`Cannot set children on non-container instance.`);\n } else {\n createRenderEffect(\n on(\n () => props[key as keyof typeof initialisationProps],\n () => {\n (instance as any)[key] = initialisationProps[key];\n },\n { defer: true },\n ),\n );\n }\n }\n\n for (const key in runtimeProps) {\n if (key === \"as\") continue;\n\n if (key === \"ref\") {\n createRenderEffect(() => {\n // Solid converts the ref prop to a callback function\n (props[key] as unknown as (arg: any) => void)(instance);\n });\n }\n }\n\n onCleanup(() => {\n instance.destroy();\n });\n\n return instance as InstanceType & JSX.Element;\n };\n};\n"],"mappings":";;;;;AAuGA,IAAM,yBAAyB;CAC7B,GAAG;EAJ2B;EAAO;EAAM;EAIxC;CACH,GAAG;CACH,GAAG;CACJ;AAGD,IAAM,sBAAsB;CAC1B;CACA;CACA,GAAG;CACH,GAAG;CACH,GAAG;CACJ;AAED,IAAM,6BAA6B;CACjC;CACA;CACA,GAAG;CACH,GAAG;CACH,GAAG;CACH,GAAG;CACJ;AAED,IAAa,4BAIX,cAC8F;AAC9F,SAAQ,UAAsC;EAC5C,MAAM,CAAC,cAAc,uBAAuB,WAAW,OAAO,uBAAuB;EAErF,MAAM,WAAW,MAAM,MAAM,IAAI,UAAU,oBAA2B;AAEtE,0BAAwB,UAAU,oBAAoB;AACtD,mBAAiB,UAAU,aAAa;AAExC,kBAAgB;AACd,OAAI,YAAY,SAEd,UAAS,QAAQ,EAAE,UAAU,OAAO,CAAC;OAErC,UAAS,QAAQ,EAAE,UAAU,MAAM,CAAC;IAEtC;AAEF,SAAO;;;AAIX,IAAa,uBAIX,cACyF;AACzF,SACE,UAC+B;AAC/B,SAAO,yBAAoD,UAAU,CAAC,MAAM;;;AAIhF,IAAa,yBAIX,cAC2F;AAC3F,SACE,UAC+B;EAC/B,MAAM,CAAC,cAAc,uBAAuB,WAAW,OAAO,oBAAoB;EAElF,MAAM,WAAW,MAAM,MAAM,IAAI,UAAU,oBAA2B;AAEtE,0BAAwB,UAAU,oBAAoB;AACtD,mBAAiB,UAAU,aAAa;AAExC,kBAAgB;AACd,YAAS,QAAQ,EAAE,UAAU,MAAM,CAAC;IACpC;AAEF,SAAO;;;AAIX,IAAa,iCAIX,cAIG;AACH,SACE,UAC+B;EAE/B,MAAM,CAAC,cAAc,QAAQ,uBAAuB,WAAW,OAAO,qBAAqB,CACzF,aACD,CAAC;EAEF,MAAM,WAAW,MAAM,MAAM,IAAI,UAAU,oBAA2B;AAGtE,WAAS,aAAa;AAEtB,qBACE,SACQ,OAAO,aACZ,eAAe;GACd,MAAM,kBAAkB,WAAwB;AAC9C,aAAS,OAAO,OAAO;;AAGzB,OAAI,eAAe,OAAO;IACxB,MAAM,SAAS,WAAW;AAC1B,WAAO,IAAI,eAAe;AAC1B,oBAAgB;AACd,YAAO,OAAO,eAAe;MAC7B;;IAGP,CACF;AAED,0BAAwB,UAAU,oBAAoB;AACtD,mBAAiB,UAAU,aAAa;AAExC,kBAAgB;AACd,YAAS,QAAQ,EAAE,UAAU,MAAM,CAAC;IACpC;AAEF,SAAO;;;AAIX,IAAa,+BAIX,cACiG;AACjG,SACE,UAC+B;EAC/B,MAAM,CAAC,cAAc,uBAAuB,WAAW,OAAO,2BAA2B;EAEzF,MAAM,WAAW,MAAM,MAAM,IAAI,UAAU,oBAA2B;AAEtE,0BAAwB,UAAU,oBAAoB;AACtD,mBAAiB,UAAU,aAAa;AAExC,kBAAgB;AACd,YAAS,QAAQ,EAAE,UAAU,MAAM,CAAC;IACpC;AAEF,SAAO"}
|
|
1
|
+
{"version":3,"file":"component-factories.js","names":[],"sources":["../../src/components/component-factories.ts"],"sourcesContent":["import type * as Pixi from \"pixi.js\";\nimport type { JSX, Ref } from \"solid-js\";\nimport { createRenderEffect, on, splitProps, onCleanup } from \"solid-js\";\n\nimport { getTicker } from \"../pixi-application\";\n\nimport { bindInitialisationProps, bindRuntimeProps } from \"./bind-props\";\nimport type { PixiSolidEventHandlerMap } from \"./bind-props/event-names\";\nimport { PIXI_SOLID_EVENT_HANDLER_NAMES } from \"./bind-props/event-names\";\nimport type {\n CommonPointAxisPropName,\n AnchorPointAxisPropName,\n TilingPointAxisPropName,\n} from \"./bind-props/point-property-names\";\nimport {\n COMMON_POINT_PROP_AXIS_NAMES,\n ANCHOR_POINT_PROP_AXIS_NAMES,\n TILING_POINT_PROP_AXIS_NAMES,\n} from \"./bind-props/point-property-names\";\n\n/**\n * Common point axis properties available on all Container-based components\n */\nexport type CommonPointAxisProps = Partial<Record<CommonPointAxisPropName, number>>;\n\n/**\n * Anchor point axis properties available on Sprite-like components\n */\nexport type AnchorPointAxisProps = Partial<Record<AnchorPointAxisPropName, number>>;\n\n/**\n * Tiling point axis properties available on TilingSprite\n */\nexport type TilingPointAxisProps = Partial<Record<TilingPointAxisPropName, number>>;\n\n/**\n * This is a utility type useful for extending the props of custom components to allow props to be passed through to the underlying Pixi instance.\n *\n * If you don't require them all it's recommended to narrow the type by using Pick or Omit the props to only allow the ones you need.\n *\n * @example PixiComponentProps<Pixi.SpriteOptions>.\n */\nexport type PixiComponentProps<\n ComponentOptions extends Pixi.ContainerOptions = Pixi.ContainerOptions,\n> = PixiSolidEventHandlerMap & CommonPointAxisProps & Omit<ComponentOptions, \"children\">;\n\ntype RefAsProps<Component> = {\n ref?: Ref<Component>;\n as?: Component;\n};\n\ntype PixiComponent<Props, Instance> = (props: Props) => Instance & JSX.Element;\n\n/**\n * Prop definition for basic Container components (position, scale, pivot, skew only)\n */\nexport type ContainerProps<Component> = PixiSolidEventHandlerMap &\n CommonPointAxisProps &\n RefAsProps<Component> & {\n children?: JSX.Element;\n };\n\n/**\n * Prop definition for components that cannot have children\n */\nexport type LeafProps<Component> = PixiSolidEventHandlerMap &\n CommonPointAxisProps &\n RefAsProps<Component>;\n\n/**\n * Prop definition for Sprite-like components (includes anchor properties)\n */\nexport type SpriteProps<Component> = PixiSolidEventHandlerMap &\n CommonPointAxisProps &\n AnchorPointAxisProps &\n RefAsProps<Component>;\n\nexport type AnimatedSpriteProps<Component> = SpriteProps<Component> &\n Pick<Pixi.AnimatedSpriteOptions, \"autoUpdate\">;\n\ntype AnimatedSpriteLike = Pixi.Container & {\n autoUpdate: boolean;\n update: (ticker: Pixi.Ticker) => void;\n};\n\n/**\n * Prop definition for TilingSprite (includes anchor and tiling properties)\n */\nexport type TilingSpriteProps<Component> = PixiSolidEventHandlerMap &\n CommonPointAxisProps &\n AnchorPointAxisProps &\n TilingPointAxisProps &\n RefAsProps<Component>;\n\n/**\n * Prop definition for filter components\n */\nexport type FilterProps<Component> = RefAsProps<Component>;\n\n// Keys that are specific to Solid components and not Pixi props\nexport const SOLID_PROP_KEYS = [\"ref\", \"as\", \"children\"] as const;\n\n// Combined keys for splitting props\nconst CONTAINER_RUNTIME_KEYS = [\n ...SOLID_PROP_KEYS,\n ...PIXI_SOLID_EVENT_HANDLER_NAMES,\n ...COMMON_POINT_PROP_AXIS_NAMES,\n] as const;\n\n// Sprite components don't accept \"children\" since they can't have children\nconst SPRITE_RUNTIME_KEYS = [\n \"ref\",\n \"as\",\n ...PIXI_SOLID_EVENT_HANDLER_NAMES,\n ...COMMON_POINT_PROP_AXIS_NAMES,\n ...ANCHOR_POINT_PROP_AXIS_NAMES,\n] as const;\n\nconst TILING_SPRITE_RUNTIME_KEYS = [\n \"ref\",\n \"as\",\n ...PIXI_SOLID_EVENT_HANDLER_NAMES,\n ...COMMON_POINT_PROP_AXIS_NAMES,\n ...ANCHOR_POINT_PROP_AXIS_NAMES,\n ...TILING_POINT_PROP_AXIS_NAMES,\n] as const;\n\nexport const createContainerComponent = <\n InstanceType extends Pixi.Container,\n OptionsType extends object,\n>(\n PixiClass: new (props: OptionsType) => InstanceType,\n): PixiComponent<Omit<OptionsType, \"children\"> & ContainerProps<InstanceType>, InstanceType> => {\n return (props): InstanceType & JSX.Element => {\n const [runtimeProps, initialisationProps] = splitProps(props, CONTAINER_RUNTIME_KEYS);\n\n const instance = props.as || new PixiClass(initialisationProps as any);\n\n bindInitialisationProps(instance, initialisationProps);\n bindRuntimeProps(instance, runtimeProps);\n\n onCleanup(() => {\n if (\"attach\" in instance) {\n // Means it's a render layer so we don't want to destroy children as they are managed elsewhere in the tree.\n instance.destroy({ children: false });\n } else {\n instance.destroy({ children: true });\n }\n });\n\n return instance as InstanceType & JSX.Element;\n };\n};\n\nexport const createLeafComponent = <\n InstanceType extends Pixi.Container,\n OptionsType extends object,\n>(\n PixiClass: new (props: OptionsType) => InstanceType,\n): PixiComponent<Omit<OptionsType, \"children\"> & LeafProps<InstanceType>, InstanceType> => {\n return (\n props: Omit<OptionsType, \"children\"> & LeafProps<InstanceType>,\n ): InstanceType & JSX.Element => {\n return createContainerComponent<InstanceType, OptionsType>(PixiClass)(props);\n };\n};\n\nexport const createSpriteComponent = <\n InstanceType extends Pixi.Container,\n OptionsType extends object,\n>(\n PixiClass: new (props: OptionsType) => InstanceType,\n): PixiComponent<Omit<OptionsType, \"children\"> & SpriteProps<InstanceType>, InstanceType> => {\n return (\n props: Omit<OptionsType, \"children\"> & SpriteProps<InstanceType>,\n ): InstanceType & JSX.Element => {\n const [runtimeProps, initialisationProps] = splitProps(props, SPRITE_RUNTIME_KEYS);\n\n const instance = props.as || new PixiClass(initialisationProps as any);\n\n bindInitialisationProps(instance, initialisationProps);\n bindRuntimeProps(instance, runtimeProps);\n\n onCleanup(() => {\n instance.destroy({ children: true });\n });\n\n return instance as InstanceType & JSX.Element;\n };\n};\n\nexport const createAnimatedSpriteComponent = <\n InstanceType extends AnimatedSpriteLike,\n OptionsType extends object,\n>(\n PixiClass: new (props: OptionsType) => InstanceType,\n): PixiComponent<\n Omit<OptionsType, \"children\"> & AnimatedSpriteProps<InstanceType>,\n InstanceType\n> => {\n return (\n props: Omit<OptionsType, \"children\"> & AnimatedSpriteProps<InstanceType>,\n ): InstanceType & JSX.Element => {\n // Specifically separate `autoUpdate` as we handle it manually below.\n const [runtimeProps, update, initialisationProps] = splitProps(props, SPRITE_RUNTIME_KEYS, [\n \"autoUpdate\",\n ]);\n\n const instance = props.as || new PixiClass(initialisationProps as any);\n\n // Set this to false to override Pixi's default shared ticker behaviour.\n instance.autoUpdate = false;\n\n createRenderEffect(\n on(\n () => update.autoUpdate,\n (autoUpdate) => {\n const updateInstance = (ticker: Pixi.Ticker) => {\n instance.update(ticker);\n };\n\n if (autoUpdate !== false) {\n const ticker = getTicker();\n ticker.add(updateInstance);\n onCleanup(() => {\n ticker.remove(updateInstance);\n });\n }\n },\n ),\n );\n\n bindInitialisationProps(instance, initialisationProps);\n bindRuntimeProps(instance, runtimeProps);\n\n onCleanup(() => {\n instance.destroy({ children: true });\n });\n\n return instance as InstanceType & JSX.Element;\n };\n};\n\nexport const createTilingSpriteComponent = <\n InstanceType extends Pixi.Container,\n OptionsType extends object,\n>(\n PixiClass: new (props: OptionsType) => InstanceType,\n): PixiComponent<Omit<OptionsType, \"children\"> & TilingSpriteProps<InstanceType>, InstanceType> => {\n return (\n props: Omit<OptionsType, \"children\"> & TilingSpriteProps<InstanceType>,\n ): InstanceType & JSX.Element => {\n const [runtimeProps, initialisationProps] = splitProps(props, TILING_SPRITE_RUNTIME_KEYS);\n\n const instance = props.as || new PixiClass(initialisationProps as any);\n\n bindInitialisationProps(instance, initialisationProps);\n bindRuntimeProps(instance, runtimeProps);\n\n onCleanup(() => {\n instance.destroy({ children: true });\n });\n\n return instance as InstanceType & JSX.Element;\n };\n};\n\nexport const createFilterComponent = <InstanceType extends Pixi.Filter, OptionsType extends object>(\n PixiClass: new (props: OptionsType) => InstanceType,\n): PixiComponent<OptionsType & FilterProps<InstanceType>, InstanceType> => {\n return (props: OptionsType & FilterProps<InstanceType>): InstanceType & JSX.Element => {\n const [runtimeProps, initialisationProps] = splitProps(props, [\"ref\", \"as\"]);\n\n const instance = props.as || new PixiClass(initialisationProps as any);\n\n for (const key in initialisationProps) {\n if (key === \"as\") continue;\n\n if (key === \"ref\") {\n createRenderEffect(() => {\n // Solid converts the ref prop to a callback function\n (props[key] as unknown as (arg: any) => void)(instance);\n });\n } else if (key === \"children\") {\n throw new Error(`Cannot set children on non-container instance.`);\n } else {\n createRenderEffect(\n on(\n () => props[key as keyof typeof initialisationProps],\n () => {\n (instance as any)[key] = initialisationProps[key];\n },\n { defer: true },\n ),\n );\n }\n }\n\n for (const key in runtimeProps) {\n if (key === \"as\") continue;\n\n if (key === \"ref\") {\n createRenderEffect(() => {\n // Solid converts the ref prop to a callback function\n (props[key] as unknown as (arg: any) => void)(instance);\n });\n }\n }\n\n onCleanup(() => {\n instance.destroy();\n });\n\n return instance as InstanceType & JSX.Element;\n };\n};\n"],"mappings":";;;;;AAuGA,IAAM,yBAAyB;CAC7B,GAAG;EAJ2B;EAAO;EAAM;EAIxC;CACH,GAAG;CACH,GAAG;CACJ;AAGD,IAAM,sBAAsB;CAC1B;CACA;CACA,GAAG;CACH,GAAG;CACH,GAAG;CACJ;AAED,IAAM,6BAA6B;CACjC;CACA;CACA,GAAG;CACH,GAAG;CACH,GAAG;CACH,GAAG;CACJ;AAED,IAAa,4BAIX,cAC8F;CAC9F,QAAQ,UAAsC;EAC5C,MAAM,CAAC,cAAc,uBAAuB,WAAW,OAAO,uBAAuB;EAErF,MAAM,WAAW,MAAM,MAAM,IAAI,UAAU,oBAA2B;EAEtE,wBAAwB,UAAU,oBAAoB;EACtD,iBAAiB,UAAU,aAAa;EAExC,gBAAgB;GACd,IAAI,YAAY,UAEd,SAAS,QAAQ,EAAE,UAAU,OAAO,CAAC;QAErC,SAAS,QAAQ,EAAE,UAAU,MAAM,CAAC;IAEtC;EAEF,OAAO;;;AAIX,IAAa,uBAIX,cACyF;CACzF,QACE,UAC+B;EAC/B,OAAO,yBAAoD,UAAU,CAAC,MAAM;;;AAIhF,IAAa,yBAIX,cAC2F;CAC3F,QACE,UAC+B;EAC/B,MAAM,CAAC,cAAc,uBAAuB,WAAW,OAAO,oBAAoB;EAElF,MAAM,WAAW,MAAM,MAAM,IAAI,UAAU,oBAA2B;EAEtE,wBAAwB,UAAU,oBAAoB;EACtD,iBAAiB,UAAU,aAAa;EAExC,gBAAgB;GACd,SAAS,QAAQ,EAAE,UAAU,MAAM,CAAC;IACpC;EAEF,OAAO;;;AAIX,IAAa,iCAIX,cAIG;CACH,QACE,UAC+B;EAE/B,MAAM,CAAC,cAAc,QAAQ,uBAAuB,WAAW,OAAO,qBAAqB,CACzF,aACD,CAAC;EAEF,MAAM,WAAW,MAAM,MAAM,IAAI,UAAU,oBAA2B;EAGtE,SAAS,aAAa;EAEtB,mBACE,SACQ,OAAO,aACZ,eAAe;GACd,MAAM,kBAAkB,WAAwB;IAC9C,SAAS,OAAO,OAAO;;GAGzB,IAAI,eAAe,OAAO;IACxB,MAAM,SAAS,WAAW;IAC1B,OAAO,IAAI,eAAe;IAC1B,gBAAgB;KACd,OAAO,OAAO,eAAe;MAC7B;;IAGP,CACF;EAED,wBAAwB,UAAU,oBAAoB;EACtD,iBAAiB,UAAU,aAAa;EAExC,gBAAgB;GACd,SAAS,QAAQ,EAAE,UAAU,MAAM,CAAC;IACpC;EAEF,OAAO;;;AAIX,IAAa,+BAIX,cACiG;CACjG,QACE,UAC+B;EAC/B,MAAM,CAAC,cAAc,uBAAuB,WAAW,OAAO,2BAA2B;EAEzF,MAAM,WAAW,MAAM,MAAM,IAAI,UAAU,oBAA2B;EAEtE,wBAAwB,UAAU,oBAAoB;EACtD,iBAAiB,UAAU,aAAa;EAExC,gBAAgB;GACd,SAAS,QAAQ,EAAE,UAAU,MAAM,CAAC;IACpC;EAEF,OAAO"}
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { getPixiApp } from "./pixi-application/get-pixi-app.js";
|
|
2
2
|
import { getTicker } from "./pixi-application/get-ticker.js";
|
|
3
3
|
import { PixiApplicationProvider, TickerProvider } from "./pixi-application/pixi-application-provider.js";
|
|
4
|
-
import {
|
|
4
|
+
import { getRenderer } from "./pixi-application/get-renderer.js";
|
|
5
5
|
import { onResize } from "./on-resize.js";
|
|
6
6
|
import { onTick } from "./on-tick.js";
|
|
7
|
-
import { createAsyncDelay, delay } from "./delay.js";
|
|
8
7
|
import { AnimatedSprite, BitmapText, Container, Graphics, HTMLText, MeshPlane, MeshRope, NineSliceSprite, ParticleContainer, PerspectiveMesh, RenderContainer, RenderLayer, Sprite, Text, TilingSprite } from "./components/components.js";
|
|
9
8
|
import { PixiCanvas } from "./pixi-canvas.js";
|
|
10
|
-
|
|
9
|
+
import { usePixiScreen } from "./use-pixi-screen/use-pixi-screen.js";
|
|
10
|
+
export { AnimatedSprite, BitmapText, Container, Graphics, HTMLText, MeshPlane, MeshRope, NineSliceSprite, ParticleContainer, PerspectiveMesh, PixiApplicationProvider, PixiCanvas, RenderContainer, RenderLayer, Sprite, Text, TickerProvider, TilingSprite, getPixiApp, getRenderer, getTicker, onResize, onTick, usePixiScreen };
|
package/dist/on-resize.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { getPixiApp } from "./pixi-application/get-pixi-app.js";
|
|
2
|
-
import {
|
|
3
|
-
import { createEffect, on } from "solid-js";
|
|
2
|
+
import { onCleanup } from "solid-js";
|
|
4
3
|
//#region src/on-resize.ts
|
|
5
4
|
/**
|
|
6
5
|
*
|
|
@@ -20,20 +19,16 @@ var onResize = (resizeCallback) => {
|
|
|
20
19
|
} catch {
|
|
21
20
|
throw new Error("onResize must be used within a PixiApplicationProvider or a PixiCanvas");
|
|
22
21
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
screen.y
|
|
34
|
-
], () => {
|
|
35
|
-
resizeCallback(pixiApp.renderer.screen);
|
|
36
|
-
}, { defer: false }));
|
|
22
|
+
resizeCallback(pixiApp.renderer.screen);
|
|
23
|
+
const handleResize = () => {
|
|
24
|
+
queueMicrotask(() => {
|
|
25
|
+
resizeCallback(pixiApp.renderer.screen);
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
pixiApp.renderer.addListener("resize", handleResize);
|
|
29
|
+
onCleanup(() => {
|
|
30
|
+
pixiApp.renderer.removeListener("resize", handleResize);
|
|
31
|
+
});
|
|
37
32
|
};
|
|
38
33
|
//#endregion
|
|
39
34
|
export { onResize };
|
package/dist/on-resize.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"on-resize.js","names":[],"sources":["../src/on-resize.ts"],"sourcesContent":["import type * as Pixi from \"pixi.js\";\nimport {
|
|
1
|
+
{"version":3,"file":"on-resize.js","names":[],"sources":["../src/on-resize.ts"],"sourcesContent":["import type * as Pixi from \"pixi.js\";\nimport { onCleanup } from \"solid-js\";\n\nimport { getPixiApp } from \"./pixi-application\";\n\n/**\n *\n * A SolidJS hook that runs a callback function whenever the PixiJS renderer is resized.\n * The callback is automatically removed when the component or hook's owning computation is cleaned up.\n *\n * This hook must be called from a component that is a descendant of `PixiCanvas` or `PixiApplicationProvider`.\n *\n * @param resizeCallback - A callback function that receives the updated screen dimensions as a `Pixi.Rectangle` object. This function will be called immediately upon hook initialization and then on every subsequent resize event.\n *\n * We listen for the renderer's \"resize\" event so this hook will work correctly whether the window is resized or just the DOM element the PixiCanvas is inside of changes size.\n */\nexport const onResize = (resizeCallback: (screen: Pixi.Rectangle) => void): void => {\n let pixiApp: Pixi.Application;\n\n try {\n pixiApp = getPixiApp();\n } catch {\n throw new Error(\"onResize must be used within a PixiApplicationProvider or a PixiCanvas\");\n }\n\n // Ensure initial callback happens during setup.\n resizeCallback(pixiApp.renderer.screen);\n\n const handleResize = () => {\n // Keep onResize event-driven (fires for every renderer resize event), but schedule the\n // callback after the current emit cycle so usePixiScreen listeners have already synchronized\n // their reactive values. This avoids stale reads when both hooks are used together.\n queueMicrotask(() => {\n resizeCallback(pixiApp.renderer.screen);\n });\n };\n\n pixiApp.renderer.addListener(\"resize\", handleResize);\n\n onCleanup(() => {\n pixiApp.renderer.removeListener(\"resize\", handleResize);\n });\n};\n"],"mappings":";;;;;;;;;;;;;;AAgBA,IAAa,YAAY,mBAA2D;CAClF,IAAI;CAEJ,IAAI;EACF,UAAU,YAAY;SAChB;EACN,MAAM,IAAI,MAAM,yEAAyE;;CAI3F,eAAe,QAAQ,SAAS,OAAO;CAEvC,MAAM,qBAAqB;EAIzB,qBAAqB;GACnB,eAAe,QAAQ,SAAS,OAAO;IACvC;;CAGJ,QAAQ,SAAS,YAAY,UAAU,aAAa;CAEpD,gBAAgB;EACd,QAAQ,SAAS,eAAe,UAAU,aAAa;GACvD"}
|
package/dist/on-tick.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"on-tick.js","names":[],"sources":["../src/on-tick.ts"],"sourcesContent":["import type * as Pixi from \"pixi.js\";\nimport { UPDATE_PRIORITY } from \"pixi.js\";\nimport { onCleanup, useContext } from \"solid-js\";\n\nimport { TickerContext } from \"./pixi-application\";\n\n/**\n * onTick\n *\n * A custom SolidJS hook that registers a callback function to be executed on every frame\n * of the PIXI.Application's ticker. The callback is automatically removed when the\n * component or hook's owning computation is cleaned up.\n *\n * This hook must be called from a component that is a descendant of `PixiCanvas`,\n * `PixiApplicationProvider`, or `TickerProvider`.\n *\n * @param tickerCallback - The function to call on each ticker update. It receives\n * the `Pixi.Ticker` instance as its argument.\n * @param priority - An optional priority level for the ticker callback.\n *\n */\nexport const onTick = (\n tickerCallback: Pixi.TickerCallback<Pixi.Ticker>,\n priority: Pixi.UPDATE_PRIORITY = UPDATE_PRIORITY.NORMAL,\n): void => {\n const ticker = useContext(TickerContext);\n\n if (!ticker) {\n throw new Error(\n \"onTick must be used within a PixiApplicationProvider, PixiCanvas or a TickerProvider\",\n );\n }\n\n ticker.add(tickerCallback, ticker, priority);\n\n onCleanup(() => {\n ticker.remove(tickerCallback, ticker);\n });\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAqBA,IAAa,UACX,gBACA,WAAiC,gBAAgB,WACxC;CACT,MAAM,SAAS,WAAW,cAAc;
|
|
1
|
+
{"version":3,"file":"on-tick.js","names":[],"sources":["../src/on-tick.ts"],"sourcesContent":["import type * as Pixi from \"pixi.js\";\nimport { UPDATE_PRIORITY } from \"pixi.js\";\nimport { onCleanup, useContext } from \"solid-js\";\n\nimport { TickerContext } from \"./pixi-application\";\n\n/**\n * onTick\n *\n * A custom SolidJS hook that registers a callback function to be executed on every frame\n * of the PIXI.Application's ticker. The callback is automatically removed when the\n * component or hook's owning computation is cleaned up.\n *\n * This hook must be called from a component that is a descendant of `PixiCanvas`,\n * `PixiApplicationProvider`, or `TickerProvider`.\n *\n * @param tickerCallback - The function to call on each ticker update. It receives\n * the `Pixi.Ticker` instance as its argument.\n * @param priority - An optional priority level for the ticker callback.\n *\n */\nexport const onTick = (\n tickerCallback: Pixi.TickerCallback<Pixi.Ticker>,\n priority: Pixi.UPDATE_PRIORITY = UPDATE_PRIORITY.NORMAL,\n): void => {\n const ticker = useContext(TickerContext);\n\n if (!ticker) {\n throw new Error(\n \"onTick must be used within a PixiApplicationProvider, PixiCanvas or a TickerProvider\",\n );\n }\n\n ticker.add(tickerCallback, ticker, priority);\n\n onCleanup(() => {\n ticker.remove(tickerCallback, ticker);\n });\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAqBA,IAAa,UACX,gBACA,WAAiC,gBAAgB,WACxC;CACT,MAAM,SAAS,WAAW,cAAc;CAExC,IAAI,CAAC,QACH,MAAM,IAAI,MACR,uFACD;CAGH,OAAO,IAAI,gBAAgB,QAAQ,SAAS;CAE5C,gBAAgB;EACd,OAAO,OAAO,gBAAgB,OAAO;GACrC"}
|
|
@@ -2,7 +2,8 @@ import { createContext } from "solid-js";
|
|
|
2
2
|
//#region src/pixi-application/context.ts
|
|
3
3
|
var PixiAppContext = createContext();
|
|
4
4
|
var TickerContext = createContext();
|
|
5
|
+
var ScreenStoreContext = createContext();
|
|
5
6
|
//#endregion
|
|
6
|
-
export { PixiAppContext, TickerContext };
|
|
7
|
+
export { PixiAppContext, ScreenStoreContext, TickerContext };
|
|
7
8
|
|
|
8
9
|
//# sourceMappingURL=context.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","names":[],"sources":["../../src/pixi-application/context.ts"],"sourcesContent":["import type * as Pixi from \"pixi.js\";\nimport { createContext } from \"solid-js\";\n\nimport type { PixiScreenDimensions } from \"../use-pixi-screen/pixi-screen-store\";\n\nexport const PixiAppContext = createContext<
|
|
1
|
+
{"version":3,"file":"context.js","names":[],"sources":["../../src/pixi-application/context.ts"],"sourcesContent":["import type * as Pixi from \"pixi.js\";\nimport { createContext } from \"solid-js\";\n\nimport type { PixiScreenDimensions } from \"../use-pixi-screen/pixi-screen-store\";\n\nexport const PixiAppContext = createContext<Pixi.Application>();\n\nexport const TickerContext = createContext<Pixi.Ticker>();\n\nexport const ScreenStoreContext = createContext<Readonly<PixiScreenDimensions>>();\n"],"mappings":";;AAKA,IAAa,iBAAiB,eAAiC;AAE/D,IAAa,gBAAgB,eAA4B;AAEzD,IAAa,qBAAqB,eAA+C"}
|
|
@@ -10,7 +10,7 @@ import { useContext } from "solid-js";
|
|
|
10
10
|
var getPixiApp = () => {
|
|
11
11
|
const appContext = useContext(PixiAppContext);
|
|
12
12
|
if (!appContext) throw new Error("getPixiApp must be used within a PixiApplicationProvider or a PixiCanvas");
|
|
13
|
-
return appContext
|
|
13
|
+
return appContext;
|
|
14
14
|
};
|
|
15
15
|
//#endregion
|
|
16
16
|
export { getPixiApp };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-pixi-app.js","names":[],"sources":["../../src/pixi-application/get-pixi-app.ts"],"sourcesContent":["import type * as Pixi from \"pixi.js\";\nimport { useContext } from \"solid-js\";\n\nimport { PixiAppContext } from \"./context\";\n\n/**\n * A custom SolidJS hook to access the root Pixi.Application instance.\n * This hook must be called from a component that is a descendant of `PixiApplicationProvider` or `PixiCanvas`.\n *\n * @returns The Pixi.Application instance provided by the `PixiApplication` component.\n */\nexport const getPixiApp = (): Pixi.Application => {\n const appContext = useContext(PixiAppContext);\n\n if (!appContext) {\n throw new Error(\"getPixiApp must be used within a PixiApplicationProvider or a PixiCanvas\");\n }\n\n return appContext
|
|
1
|
+
{"version":3,"file":"get-pixi-app.js","names":[],"sources":["../../src/pixi-application/get-pixi-app.ts"],"sourcesContent":["import type * as Pixi from \"pixi.js\";\nimport { useContext } from \"solid-js\";\n\nimport { PixiAppContext } from \"./context\";\n\n/**\n * A custom SolidJS hook to access the root Pixi.Application instance.\n * This hook must be called from a component that is a descendant of `PixiApplicationProvider` or `PixiCanvas`.\n *\n * @returns The Pixi.Application instance provided by the `PixiApplication` component.\n */\nexport const getPixiApp = (): Pixi.Application => {\n const appContext = useContext(PixiAppContext);\n\n if (!appContext) {\n throw new Error(\"getPixiApp must be used within a PixiApplicationProvider or a PixiCanvas\");\n }\n\n return appContext;\n};\n"],"mappings":";;;;;;;;;AAWA,IAAa,mBAAqC;CAChD,MAAM,aAAa,WAAW,eAAe;CAE7C,IAAI,CAAC,YACH,MAAM,IAAI,MAAM,2EAA2E;CAG7F,OAAO"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { PixiAppContext } from "./context.js";
|
|
2
|
+
import { useContext } from "solid-js";
|
|
3
|
+
//#region src/pixi-application/get-renderer.ts
|
|
4
|
+
/**
|
|
5
|
+
* A custom SolidJS hook to access the root Pixi Renderer instance.
|
|
6
|
+
* This hook must be called from a component that is a descendant of `PixiApplicationProvider` or `PixiCanvas`.
|
|
7
|
+
*
|
|
8
|
+
* @returns The Pixi.Renderer instance.
|
|
9
|
+
*/
|
|
10
|
+
var getRenderer = () => {
|
|
11
|
+
const appContext = useContext(PixiAppContext);
|
|
12
|
+
if (!appContext) throw new Error("getRenderer must be used within a PixiApplicationProvider or a PixiCanvas");
|
|
13
|
+
return appContext.renderer;
|
|
14
|
+
};
|
|
15
|
+
//#endregion
|
|
16
|
+
export { getRenderer };
|
|
17
|
+
|
|
18
|
+
//# sourceMappingURL=get-renderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-renderer.js","names":[],"sources":["../../src/pixi-application/get-renderer.ts"],"sourcesContent":["import type * as Pixi from \"pixi.js\";\nimport { useContext } from \"solid-js\";\n\nimport { PixiAppContext } from \"./context\";\n\n/**\n * A custom SolidJS hook to access the root Pixi Renderer instance.\n * This hook must be called from a component that is a descendant of `PixiApplicationProvider` or `PixiCanvas`.\n *\n * @returns The Pixi.Renderer instance.\n */\nexport const getRenderer = (): Pixi.Renderer => {\n const appContext = useContext(PixiAppContext);\n\n if (!appContext) {\n throw new Error(\"getRenderer must be used within a PixiApplicationProvider or a PixiCanvas\");\n }\n\n return appContext.renderer;\n};\n"],"mappings":";;;;;;;;;AAWA,IAAa,oBAAmC;CAC9C,MAAM,aAAa,WAAW,eAAe;CAE7C,IAAI,CAAC,YACH,MAAM,IAAI,MAAM,4EAA4E;CAG9F,OAAO,WAAW"}
|
|
@@ -2,18 +2,14 @@ import { TickerContext } from "./context.js";
|
|
|
2
2
|
import { useContext } from "solid-js";
|
|
3
3
|
//#region src/pixi-application/get-ticker.ts
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* A custom SolidJS hook that provides access to the Pixi Ticker instance.
|
|
6
|
+
* This hook must be called from a component that is a descendant of `PixiApplicationProvider`, `PixiCanvas` or `TickerProvider`.
|
|
6
7
|
*
|
|
7
|
-
*
|
|
8
|
-
* This hook must be called from a component that is a descendant of `PixiApplication`.
|
|
9
|
-
* Or a descendant of `TickerProvider` if being used for testing without an application.
|
|
10
|
-
*
|
|
11
|
-
* @returns The PIXI.Ticker instance from the application context.
|
|
12
|
-
* @throws Will throw an error if used outside of a `PixiApplication` or `TickerProvider` context.
|
|
8
|
+
* @returns The Pixi.Ticker instance from the nearest context provider.
|
|
13
9
|
*/
|
|
14
10
|
var getTicker = () => {
|
|
15
11
|
const ticker = useContext(TickerContext);
|
|
16
|
-
if (!ticker) throw new Error("getTicker must be used within a
|
|
12
|
+
if (!ticker) throw new Error("getTicker must be used within a PixiApplicationProvider, PixiCanvas, or TickerProvider");
|
|
17
13
|
return ticker;
|
|
18
14
|
};
|
|
19
15
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-ticker.js","names":[],"sources":["../../src/pixi-application/get-ticker.ts"],"sourcesContent":["import type * as Pixi from \"pixi.js\";\nimport { useContext } from \"solid-js\";\n\nimport { TickerContext } from \"./context\";\n\n/**\n *
|
|
1
|
+
{"version":3,"file":"get-ticker.js","names":[],"sources":["../../src/pixi-application/get-ticker.ts"],"sourcesContent":["import type * as Pixi from \"pixi.js\";\nimport { useContext } from \"solid-js\";\n\nimport { TickerContext } from \"./context\";\n\n/**\n * A custom SolidJS hook that provides access to the Pixi Ticker instance.\n * This hook must be called from a component that is a descendant of `PixiApplicationProvider`, `PixiCanvas` or `TickerProvider`.\n *\n * @returns The Pixi.Ticker instance from the nearest context provider.\n */\nexport const getTicker = (): Pixi.Ticker => {\n const ticker = useContext(TickerContext);\n if (!ticker) {\n throw new Error(\n \"getTicker must be used within a PixiApplicationProvider, PixiCanvas, or TickerProvider\",\n );\n }\n return ticker;\n};\n"],"mappings":";;;;;;;;;AAWA,IAAa,kBAA+B;CAC1C,MAAM,SAAS,WAAW,cAAc;CACxC,IAAI,CAAC,QACH,MAAM,IAAI,MACR,yFACD;CAEH,OAAO"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PixiAppContext, TickerContext } from "./context.js";
|
|
1
|
+
import { PixiAppContext, ScreenStoreContext, TickerContext } from "./context.js";
|
|
2
2
|
import { createPixiApplication } from "./pixi-application.js";
|
|
3
3
|
import { createPixiScreenStore } from "../use-pixi-screen/pixi-screen-store.js";
|
|
4
4
|
import { Show, createResource, onCleanup, splitProps, useContext } from "solid-js";
|
|
@@ -19,9 +19,9 @@ var PixiApplicationProvider = (props) => {
|
|
|
19
19
|
const [appResource] = createResource(async () => {
|
|
20
20
|
if (externallyProvidedApp) return externallyProvidedApp;
|
|
21
21
|
const existingContext = useContext(PixiAppContext);
|
|
22
|
-
if (existingContext
|
|
23
|
-
externallyProvidedApp = existingContext
|
|
24
|
-
return existingContext
|
|
22
|
+
if (existingContext) {
|
|
23
|
+
externallyProvidedApp = existingContext;
|
|
24
|
+
return existingContext;
|
|
25
25
|
}
|
|
26
26
|
const [, initialisationProps] = splitProps(props, ["children", "existingApp"]);
|
|
27
27
|
return await createPixiApplication(initialisationProps);
|
|
@@ -36,19 +36,22 @@ var PixiApplicationProvider = (props) => {
|
|
|
36
36
|
},
|
|
37
37
|
children: (app) => {
|
|
38
38
|
const pixiScreenStore = createPixiScreenStore(app().renderer);
|
|
39
|
-
const contextValue = {
|
|
40
|
-
app: app(),
|
|
41
|
-
pixiScreenStore
|
|
42
|
-
};
|
|
43
39
|
return createComponent(PixiAppContext.Provider, {
|
|
44
|
-
value
|
|
40
|
+
get value() {
|
|
41
|
+
return app();
|
|
42
|
+
},
|
|
45
43
|
get children() {
|
|
46
|
-
return createComponent(
|
|
47
|
-
|
|
48
|
-
return app().ticker;
|
|
49
|
-
},
|
|
44
|
+
return createComponent(ScreenStoreContext.Provider, {
|
|
45
|
+
value: pixiScreenStore,
|
|
50
46
|
get children() {
|
|
51
|
-
return
|
|
47
|
+
return createComponent(TickerContext.Provider, {
|
|
48
|
+
get value() {
|
|
49
|
+
return app().ticker;
|
|
50
|
+
},
|
|
51
|
+
get children() {
|
|
52
|
+
return props.children;
|
|
53
|
+
}
|
|
54
|
+
});
|
|
52
55
|
}
|
|
53
56
|
});
|
|
54
57
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pixi-application-provider.js","names":["Pixi","JSX","ParentProps","createResource","onCleanup","Show","splitProps","useContext","createPixiScreenStore","PixiAppContext","TickerContext","createPixiApplication","PixiApplicationProps","Partial","Omit","ApplicationOptions","children","Element","existingApp","Application","PixiApplicationProvider","props","externallyProvidedApp","appResource","existingContext","
|
|
1
|
+
{"version":3,"file":"pixi-application-provider.js","names":["Pixi","JSX","ParentProps","createResource","onCleanup","Show","splitProps","useContext","createPixiScreenStore","PixiAppContext","TickerContext","ScreenStoreContext","createPixiApplication","PixiApplicationProps","Partial","Omit","ApplicationOptions","children","Element","existingApp","Application","PixiApplicationProvider","props","externallyProvidedApp","appResource","existingContext","initialisationProps","destroy","_$createComponent","when","app","pixiScreenStore","renderer","Provider","value","ticker","TickerProviderProps","Ticker","TickerProvider"],"sources":["../../src/pixi-application/pixi-application-provider.tsx"],"sourcesContent":["import type * as Pixi from \"pixi.js\";\nimport type { JSX, ParentProps } from \"solid-js\";\nimport { createResource, onCleanup, Show, splitProps, useContext } from \"solid-js\";\n\nimport { createPixiScreenStore } from \"../use-pixi-screen/pixi-screen-store\";\n\nimport { PixiAppContext, TickerContext, ScreenStoreContext } from \"./context\";\nimport { createPixiApplication } from \"./pixi-application\";\n\n/**\n * Props for the `PixiApplication` component. It extends the PIXI.ApplicationOptions\n * minus the `children` and `resizeTo` properties, which are handled by pixi-solid internally.\n * There is also an optional `existingApp` property to pass in an already created Pixi.Application instance, which will be used instead of creating a new one.\n */\nexport type PixiApplicationProps = Partial<\n Omit<Pixi.ApplicationOptions, \"children\" | \"resizeTo\">\n> & {\n children?: JSX.Element;\n existingApp?: Pixi.Application;\n};\n\n/**\n * A SolidJS component that creates a Pixi.Application instance and works as a context provider.\n * It provides the application instance through context to be used by child components\n * and custom hooks like `getPixiApp`, `onTick`, `getTicker` and `usePixiScreen`.\n *\n * This component should only be used once in your application.\n *\n * @param props The properties to configure the Pixi.js Application.\n *\n */\nexport const PixiApplicationProvider = (props: PixiApplicationProps): JSX.Element => {\n let externallyProvidedApp: Pixi.Application | undefined = props.existingApp;\n\n const [appResource] = createResource(async () => {\n if (externallyProvidedApp) {\n return externallyProvidedApp;\n }\n\n const existingContext = useContext(PixiAppContext);\n if (existingContext) {\n externallyProvidedApp = existingContext;\n return existingContext;\n }\n\n const [, initialisationProps] = splitProps(props, [\"children\", \"existingApp\"]);\n return await createPixiApplication(initialisationProps);\n });\n\n onCleanup(() => {\n // Only destroy the app if it was created here.\n if (externallyProvidedApp) return;\n appResource()?.destroy(true, { children: true });\n });\n\n return (\n <Show when={appResource()}>\n {(app) => {\n const pixiScreenStore = createPixiScreenStore(app().renderer);\n\n return (\n <PixiAppContext.Provider value={app()}>\n <ScreenStoreContext.Provider value={pixiScreenStore}>\n <TickerContext.Provider value={app().ticker}>{props.children}</TickerContext.Provider>\n </ScreenStoreContext.Provider>\n </PixiAppContext.Provider>\n );\n }}\n </Show>\n );\n};\n\nexport type TickerProviderProps = ParentProps<{ ticker: Pixi.Ticker }>;\n\n/**\n * This is only required if you want a ticker without the Pixi Application.\n * For applications that want to use multiple tickers or for testing a store that relies on the ticker related utilities.\n * It provides context for the `onTick`, `delay`, `createAsyncDelay` and `getTicker` utilities.\n *\n * The ticker instance you want to use needs to be passed in as a prop so it can be manually controlled from the outside for testing.\n */\nexport const TickerProvider = (props: TickerProviderProps): JSX.Element => {\n return <TickerContext.Provider value={props.ticker}>{props.children}</TickerContext.Provider>;\n};\n"],"mappings":";;;;;;;;;;;;;;;;AA+BA,IAAaqB,2BAA2BC,UAA6C;CACnF,IAAIC,wBAAsDD,MAAMH;CAEhE,MAAM,CAACK,eAAerB,eAAe,YAAY;EAC/C,IAAIoB,uBACF,OAAOA;EAGT,MAAME,kBAAkBlB,WAAWE,eAAe;EAClD,IAAIgB,iBAAiB;GACnBF,wBAAwBE;GACxB,OAAOA;;EAGT,MAAM,GAAGC,uBAAuBpB,WAAWgB,OAAO,CAAC,YAAY,cAAc,CAAC;EAC9E,OAAO,MAAMV,sBAAsBc,oBAAoB;GACvD;CAEFtB,gBAAgB;EAEd,IAAImB,uBAAuB;EAC3BC,aAAa,EAAEG,QAAQ,MAAM,EAAEV,UAAU,MAAM,CAAC;GAChD;CAEF,OAAAW,gBACGvB,MAAI;EAAA,IAACwB,OAAI;GAAA,OAAEL,aAAa;;EAAAP,WACrBa,QAAQ;GACR,MAAMC,kBAAkBvB,sBAAsBsB,KAAK,CAACE,SAAS;GAE7D,OAAAJ,gBACGnB,eAAewB,UAAQ;IAAA,IAACC,QAAK;KAAA,OAAEJ,KAAK;;IAAA,IAAAb,WAAA;KAAA,OAAAW,gBAClCjB,mBAAmBsB,UAAQ;MAACC,OAAOH;MAAe,IAAAd,WAAA;OAAA,OAAAW,gBAChDlB,cAAcuB,UAAQ;QAAA,IAACC,QAAK;SAAA,OAAEJ,KAAK,CAACK;;QAAM,IAAAlB,WAAA;SAAA,OAAGK,MAAML;;QAAQ,CAAA;;MAAA,CAAA;;IAAA,CAAA;;EAInE,CAAA;;;;;;;;;AAcP,IAAaqB,kBAAkBhB,UAA4C;CACzE,OAAAM,gBAAQlB,cAAcuB,UAAQ;EAAA,IAACC,QAAK;GAAA,OAAEZ,MAAMa;;EAAM,IAAAlB,WAAA;GAAA,OAAGK,MAAML;;EAAQ,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pixi-application.js","names":[],"sources":["../../src/pixi-application/pixi-application.ts"],"sourcesContent":["import type * as Pixi from \"pixi.js\";\nimport { Application } from \"pixi.js\";\n\nexport type PixiApplicationProps = Partial<Omit<Pixi.ApplicationOptions, \"children\" | \"resizeTo\">>;\n\nexport const createPixiApplication = async (\n props?: PixiApplicationProps,\n): Promise<Pixi.Application> => {\n const app = new Application();\n await app.init({\n resolution: window.devicePixelRatio,\n autoDensity: true,\n ...props,\n });\n\n app.canvas.style.display = \"block\";\n app.canvas.style.position = \"absolute\";\n app.canvas.style.top = \"0\";\n app.canvas.style.left = \"0\";\n app.canvas.style.width = \"100%\";\n app.canvas.style.height = \"100%\";\n\n return app;\n};\n"],"mappings":";;AAKA,IAAa,wBAAwB,OACnC,UAC8B;CAC9B,MAAM,MAAM,IAAI,aAAa;
|
|
1
|
+
{"version":3,"file":"pixi-application.js","names":[],"sources":["../../src/pixi-application/pixi-application.ts"],"sourcesContent":["import type * as Pixi from \"pixi.js\";\nimport { Application } from \"pixi.js\";\n\nexport type PixiApplicationProps = Partial<Omit<Pixi.ApplicationOptions, \"children\" | \"resizeTo\">>;\n\nexport const createPixiApplication = async (\n props?: PixiApplicationProps,\n): Promise<Pixi.Application> => {\n const app = new Application();\n await app.init({\n resolution: window.devicePixelRatio,\n autoDensity: true,\n ...props,\n });\n\n app.canvas.style.display = \"block\";\n app.canvas.style.position = \"absolute\";\n app.canvas.style.top = \"0\";\n app.canvas.style.left = \"0\";\n app.canvas.style.width = \"100%\";\n app.canvas.style.height = \"100%\";\n\n return app;\n};\n"],"mappings":";;AAKA,IAAa,wBAAwB,OACnC,UAC8B;CAC9B,MAAM,MAAM,IAAI,aAAa;CAC7B,MAAM,IAAI,KAAK;EACb,YAAY,OAAO;EACnB,aAAa;EACb,GAAG;EACJ,CAAC;CAEF,IAAI,OAAO,MAAM,UAAU;CAC3B,IAAI,OAAO,MAAM,WAAW;CAC5B,IAAI,OAAO,MAAM,MAAM;CACvB,IAAI,OAAO,MAAM,OAAO;CACxB,IAAI,OAAO,MAAM,QAAQ;CACzB,IAAI,OAAO,MAAM,SAAS;CAE1B,OAAO"}
|
package/dist/pixi-canvas.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pixi-canvas.js","names":["Pixi","JSX","onCleanup","onMount","bindRuntimeProps","ContainerProps","getPixiApp","PixiApplicationProvider","OmitColonEvents","T","K","PixiCanvasProps","children","Element","ref","el","HTMLDivElement","Omit","HTMLAttributes","Partial","ApplicationOptions","isDomPropKey","key","startsWith","test","splitPixiCanvasProps","props","wrapperProps","applicationOptions","value","Record","InnerPixiCanvas","canvasWrapElement","pixiApp","Application","Error","stage","Container","previousResizeTo","HTMLElement","Window","resizeObserver","ResizeObserver","resizeTo","queueResize","observe","disconnect","undefined","_el$","_tmpl$","_$use","userRef","_$spread","_$mergeProps","style","position","_$insert","canvas","PixiCanvas","_$createComponent"],"sources":["../src/pixi-canvas.tsx"],"sourcesContent":["import type * as Pixi from \"pixi.js\";\nimport type { JSX } from \"solid-js\";\nimport { onCleanup, onMount } from \"solid-js\";\n\nimport { bindRuntimeProps } from \"./components\";\nimport type { ContainerProps } from \"./components\";\nimport { getPixiApp, PixiApplicationProvider } from \"./pixi-application\";\n\n// Helper type to remove colon event handlers from JSX attributes\ntype OmitColonEvents<T> = {\n [K in keyof T as K extends `on:${string}` ? never : K]: T[K];\n};\n\nexport type PixiCanvasProps = {\n children: JSX.Element;\n ref?: (el: HTMLDivElement) => void;\n} & OmitColonEvents<Omit<JSX.HTMLAttributes<HTMLDivElement>, \"children\" | \"ref\">> &\n Partial<Omit<Pixi.ApplicationOptions, \"children\" | \"resizeTo\">>;\n\nconst isDomPropKey = (key: string): boolean => {\n if (key === \"class\" || key === \"classList\" || key === \"style\") return true;\n if (key === \"id\" || key === \"title\" || key === \"role\" || key === \"tabIndex\") return true;\n if (key.startsWith(\"aria-\") || key.startsWith(\"data-\")) return true;\n if (/^on[A-Z]/.test(key)) return true;\n\n return false;\n};\n\nconst splitPixiCanvasProps = (props: PixiCanvasProps) => {\n const wrapperProps: JSX.HTMLAttributes<HTMLDivElement> = {};\n const applicationOptions: Partial<Omit<Pixi.ApplicationOptions, \"children\" | \"resizeTo\">> = {};\n\n for (const key in props) {\n if (key === \"children\") continue;\n const value = props[key as keyof PixiCanvasProps];\n\n if (key === \"ref\" || isDomPropKey(key)) {\n (wrapperProps as Record<string, unknown>)[key] = value;\n } else {\n (applicationOptions as Record<string, unknown>)[key] = value;\n }\n }\n\n return { applicationOptions, wrapperProps };\n};\n\nconst InnerPixiCanvas = (props: {\n children: JSX.Element;\n wrapperProps?: JSX.HTMLAttributes<HTMLDivElement>;\n}): JSX.Element => {\n let canvasWrapElement: HTMLDivElement | undefined;\n let pixiApp: Pixi.Application;\n\n try {\n pixiApp = getPixiApp();\n } catch {\n throw new Error(\n \"InnerPixiCanvas must be used within a PixiApplicationProvider or a PixiCanvas\",\n );\n }\n\n bindRuntimeProps(pixiApp.stage, {\n children: props.children,\n } as ContainerProps<Pixi.Container>);\n\n let previousResizeTo: HTMLElement | Window;\n let resizeObserver: ResizeObserver | undefined;\n\n onMount(() => {\n if (!canvasWrapElement) return;\n previousResizeTo = pixiApp.resizeTo;\n pixiApp.resizeTo = canvasWrapElement;\n pixiApp.queueResize();\n resizeObserver = new ResizeObserver(() => {\n pixiApp.queueResize();\n });\n resizeObserver.observe(canvasWrapElement);\n });\n\n onCleanup(() => {\n if (!canvasWrapElement) return;\n pixiApp.resizeTo = previousResizeTo;\n resizeObserver?.disconnect();\n resizeObserver = undefined;\n });\n\n return (\n <div\n {...props.wrapperProps}\n ref={(el) => {\n canvasWrapElement = el;\n const userRef = props.wrapperProps?.ref;\n if (typeof userRef === \"function\") {\n userRef(el);\n }\n }}\n style={{\n position: \"relative\",\n /* Disables the callout/menu on long-press */\n [\"-webkit-touch-callout\"]: \"none\",\n /* Disables text selection */\n [\"-webkit-user-select\"]: \"none\",\n [\"user-select\"]: \"none\",\n ...(typeof props.wrapperProps?.style === \"object\" ? props.wrapperProps.style : {}),\n }}\n >\n {pixiApp.canvas}\n </div>\n );\n};\n\n/**\n * PixiCanvas\n *\n * A small wrapper that mounts the PIXI application's canvas element into the DOM\n * and automatically resizes it.\n *\n * - Works with or without a surrounding `PixiApplicationProvider` component.\n * - If used inside `PixiApplicationProvider`, it will use the provided context.\n * - If used standalone, it will create its own PixiApplication and provide context.\n * - Accepts pixi-solid components as children, which will be rendered inside the canvas.\n *\n * Props:\n * @param props.children - JSX content to render inside the canvas wrapper.\n * @param props - DOM props for the wrapper and Pixi ApplicationOptions (except 'children' and 'resizeTo').\n */\n\nexport const PixiCanvas = (props: PixiCanvasProps): JSX.Element => {\n const { applicationOptions, wrapperProps } = splitPixiCanvasProps(props);\n return (\n <PixiApplicationProvider {...applicationOptions}>\n <InnerPixiCanvas wrapperProps={wrapperProps}>{props.children}</InnerPixiCanvas>\n </PixiApplicationProvider>\n );\n};\n"],"mappings":";;;;;;;AAmBA,IAAMqB,gBAAgBC,QAAyB;
|
|
1
|
+
{"version":3,"file":"pixi-canvas.js","names":["Pixi","JSX","onCleanup","onMount","bindRuntimeProps","ContainerProps","getPixiApp","PixiApplicationProvider","OmitColonEvents","T","K","PixiCanvasProps","children","Element","ref","el","HTMLDivElement","Omit","HTMLAttributes","Partial","ApplicationOptions","isDomPropKey","key","startsWith","test","splitPixiCanvasProps","props","wrapperProps","applicationOptions","value","Record","InnerPixiCanvas","canvasWrapElement","pixiApp","Application","Error","stage","Container","previousResizeTo","HTMLElement","Window","resizeObserver","ResizeObserver","resizeTo","queueResize","observe","disconnect","undefined","_el$","_tmpl$","_$use","userRef","_$spread","_$mergeProps","style","position","_$insert","canvas","PixiCanvas","_$createComponent"],"sources":["../src/pixi-canvas.tsx"],"sourcesContent":["import type * as Pixi from \"pixi.js\";\nimport type { JSX } from \"solid-js\";\nimport { onCleanup, onMount } from \"solid-js\";\n\nimport { bindRuntimeProps } from \"./components\";\nimport type { ContainerProps } from \"./components\";\nimport { getPixiApp, PixiApplicationProvider } from \"./pixi-application\";\n\n// Helper type to remove colon event handlers from JSX attributes\ntype OmitColonEvents<T> = {\n [K in keyof T as K extends `on:${string}` ? never : K]: T[K];\n};\n\nexport type PixiCanvasProps = {\n children: JSX.Element;\n ref?: (el: HTMLDivElement) => void;\n} & OmitColonEvents<Omit<JSX.HTMLAttributes<HTMLDivElement>, \"children\" | \"ref\">> &\n Partial<Omit<Pixi.ApplicationOptions, \"children\" | \"resizeTo\">>;\n\nconst isDomPropKey = (key: string): boolean => {\n if (key === \"class\" || key === \"classList\" || key === \"style\") return true;\n if (key === \"id\" || key === \"title\" || key === \"role\" || key === \"tabIndex\") return true;\n if (key.startsWith(\"aria-\") || key.startsWith(\"data-\")) return true;\n if (/^on[A-Z]/.test(key)) return true;\n\n return false;\n};\n\nconst splitPixiCanvasProps = (props: PixiCanvasProps) => {\n const wrapperProps: JSX.HTMLAttributes<HTMLDivElement> = {};\n const applicationOptions: Partial<Omit<Pixi.ApplicationOptions, \"children\" | \"resizeTo\">> = {};\n\n for (const key in props) {\n if (key === \"children\") continue;\n const value = props[key as keyof PixiCanvasProps];\n\n if (key === \"ref\" || isDomPropKey(key)) {\n (wrapperProps as Record<string, unknown>)[key] = value;\n } else {\n (applicationOptions as Record<string, unknown>)[key] = value;\n }\n }\n\n return { applicationOptions, wrapperProps };\n};\n\nconst InnerPixiCanvas = (props: {\n children: JSX.Element;\n wrapperProps?: JSX.HTMLAttributes<HTMLDivElement>;\n}): JSX.Element => {\n let canvasWrapElement: HTMLDivElement | undefined;\n let pixiApp: Pixi.Application;\n\n try {\n pixiApp = getPixiApp();\n } catch {\n throw new Error(\n \"InnerPixiCanvas must be used within a PixiApplicationProvider or a PixiCanvas\",\n );\n }\n\n bindRuntimeProps(pixiApp.stage, {\n children: props.children,\n } as ContainerProps<Pixi.Container>);\n\n let previousResizeTo: HTMLElement | Window;\n let resizeObserver: ResizeObserver | undefined;\n\n onMount(() => {\n if (!canvasWrapElement) return;\n previousResizeTo = pixiApp.resizeTo;\n pixiApp.resizeTo = canvasWrapElement;\n pixiApp.queueResize();\n resizeObserver = new ResizeObserver(() => {\n pixiApp.queueResize();\n });\n resizeObserver.observe(canvasWrapElement);\n });\n\n onCleanup(() => {\n if (!canvasWrapElement) return;\n pixiApp.resizeTo = previousResizeTo;\n resizeObserver?.disconnect();\n resizeObserver = undefined;\n });\n\n return (\n <div\n {...props.wrapperProps}\n ref={(el) => {\n canvasWrapElement = el;\n const userRef = props.wrapperProps?.ref;\n if (typeof userRef === \"function\") {\n userRef(el);\n }\n }}\n style={{\n position: \"relative\",\n /* Disables the callout/menu on long-press */\n [\"-webkit-touch-callout\"]: \"none\",\n /* Disables text selection */\n [\"-webkit-user-select\"]: \"none\",\n [\"user-select\"]: \"none\",\n ...(typeof props.wrapperProps?.style === \"object\" ? props.wrapperProps.style : {}),\n }}\n >\n {pixiApp.canvas}\n </div>\n );\n};\n\n/**\n * PixiCanvas\n *\n * A small wrapper that mounts the PIXI application's canvas element into the DOM\n * and automatically resizes it.\n *\n * - Works with or without a surrounding `PixiApplicationProvider` component.\n * - If used inside `PixiApplicationProvider`, it will use the provided context.\n * - If used standalone, it will create its own PixiApplication and provide context.\n * - Accepts pixi-solid components as children, which will be rendered inside the canvas.\n *\n * Props:\n * @param props.children - JSX content to render inside the canvas wrapper.\n * @param props - DOM props for the wrapper and Pixi ApplicationOptions (except 'children' and 'resizeTo').\n */\n\nexport const PixiCanvas = (props: PixiCanvasProps): JSX.Element => {\n const { applicationOptions, wrapperProps } = splitPixiCanvasProps(props);\n return (\n <PixiApplicationProvider {...applicationOptions}>\n <InnerPixiCanvas wrapperProps={wrapperProps}>{props.children}</InnerPixiCanvas>\n </PixiApplicationProvider>\n );\n};\n"],"mappings":";;;;;;;AAmBA,IAAMqB,gBAAgBC,QAAyB;CAC7C,IAAIA,QAAQ,WAAWA,QAAQ,eAAeA,QAAQ,SAAS,OAAO;CACtE,IAAIA,QAAQ,QAAQA,QAAQ,WAAWA,QAAQ,UAAUA,QAAQ,YAAY,OAAO;CACpF,IAAIA,IAAIC,WAAW,QAAQ,IAAID,IAAIC,WAAW,QAAQ,EAAE,OAAO;CAC/D,IAAI,WAAWC,KAAKF,IAAI,EAAE,OAAO;CAEjC,OAAO;;AAGT,IAAMG,wBAAwBC,UAA2B;CACvD,MAAMC,eAAmD,EAAE;CAC3D,MAAMC,qBAAsF,EAAE;CAE9F,KAAK,MAAMN,OAAOI,OAAO;EACvB,IAAIJ,QAAQ,YAAY;EACxB,MAAMO,QAAQH,MAAMJ;EAEpB,IAAIA,QAAQ,SAASD,aAAaC,IAAI,EACpC,aAA0CA,OAAOO;OAEjD,mBAAgDP,OAAOO;;CAI3D,OAAO;EAAED;EAAoBD;EAAc;;AAG7C,IAAMI,mBAAmBL,UAGN;CACjB,IAAIM;CACJ,IAAIC;CAEJ,IAAI;EACFA,UAAU3B,YAAY;SAChB;EACN,MAAM,IAAI6B,MACR,gFACD;;CAGH/B,iBAAiB6B,QAAQG,OAAO,EAC9BxB,UAAUc,MAAMd,UACjB,CAAmC;CAEpC,IAAI0B;CACJ,IAAIG;CAEJtC,cAAc;EACZ,IAAI,CAAC6B,mBAAmB;EACxBM,mBAAmBL,QAAQU;EAC3BV,QAAQU,WAAWX;EACnBC,QAAQW,aAAa;EACrBH,iBAAiB,IAAIC,qBAAqB;GACxCT,QAAQW,aAAa;IACrB;EACFH,eAAeI,QAAQb,kBAAkB;GACzC;CAEF9B,gBAAgB;EACd,IAAI,CAAC8B,mBAAmB;EACxBC,QAAQU,WAAWL;EACnBG,gBAAgBK,YAAY;EAC5BL,iBAAiBM,KAAAA;GACjB;CAEF,cAAA;EAAA,IAAAC,OAAAC,QAAA;EAAAC,KAGUnC,OAAO;GACXiB,oBAAoBjB;GACpB,MAAMoC,UAAUzB,MAAMC,cAAcb;GACpC,IAAI,OAAOqC,YAAY,YACrBA,QAAQpC,GAAG;KAEdiC,KAAA;EAAAI,OAAAJ,MAAAK,iBAPG3B,MAAMC,cAAY,EAAA,IAQtB2B,QAAK;GAAA,OAAE;IACLC,UAAU;KAET,0BAA0B;KAE1B,wBAAwB;KACxB,gBAAgB;IACjB,GAAI,OAAO7B,MAAMC,cAAc2B,UAAU,WAAW5B,MAAMC,aAAa2B,QAAQ,EAAE;IAClF;KAAA,CAAA,EAAA,OAAA,KAAA;EAAAE,OAAAR,YAEAf,QAAQwB,OAAM;EAAA,OAAAT;KAAA;;;;;;;;;;;;;;;;;AAqBrB,IAAaU,cAAchC,UAAwC;CACjE,MAAM,EAAEE,oBAAoBD,iBAAiBF,qBAAqBC,MAAM;CACxE,OAAAiC,gBACGpD,yBAAuB8C,WAAKzB,oBAAkB,EAAA,IAAAhB,WAAA;EAAA,OAAA+C,gBAC5C5B,iBAAe;GAAeJ;GAAY,IAAAf,WAAA;IAAA,OAAGc,MAAMd;;GAAQ,CAAA;IAAA,CAAA,CAAA"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -2,8 +2,7 @@ export type { AnimatedSpriteProps, ContainerProps, LeafProps, SpriteProps, Tilin
|
|
|
2
2
|
export { onResize } from "./on-resize";
|
|
3
3
|
export { onTick } from "./on-tick";
|
|
4
4
|
export type { PixiApplicationProps } from "./pixi-application";
|
|
5
|
-
export { getPixiApp, getTicker, PixiApplicationProvider, TickerProvider } from "./pixi-application";
|
|
6
|
-
export { createAsyncDelay, delay } from "./delay";
|
|
5
|
+
export { getPixiApp, getTicker, getRenderer, PixiApplicationProvider, TickerProvider, } from "./pixi-application";
|
|
7
6
|
export type { PixiCanvasProps } from "./pixi-canvas";
|
|
8
7
|
export { PixiCanvas } from "./pixi-canvas";
|
|
9
8
|
export { AnimatedSprite, BitmapText, Container, Graphics, HTMLText, MeshPlane, MeshRope, NineSliceSprite, ParticleContainer, PerspectiveMesh, RenderContainer, RenderLayer, Sprite, Text, TilingSprite, } from "./components";
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import type * as Pixi from "pixi.js";
|
|
2
2
|
import type { PixiScreenDimensions } from "../use-pixi-screen/pixi-screen-store";
|
|
3
|
-
export declare const PixiAppContext: import("solid-js").Context<
|
|
4
|
-
app: Pixi.Application;
|
|
5
|
-
pixiScreenStore: Readonly<PixiScreenDimensions>;
|
|
6
|
-
} | undefined>;
|
|
3
|
+
export declare const PixiAppContext: import("solid-js").Context<Pixi.Application<Pixi.Renderer> | undefined>;
|
|
7
4
|
export declare const TickerContext: import("solid-js").Context<Pixi.Ticker | undefined>;
|
|
5
|
+
export declare const ScreenStoreContext: import("solid-js").Context<Readonly<PixiScreenDimensions> | undefined>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type * as Pixi from "pixi.js";
|
|
2
|
+
/**
|
|
3
|
+
* A custom SolidJS hook to access the root Pixi Renderer instance.
|
|
4
|
+
* This hook must be called from a component that is a descendant of `PixiApplicationProvider` or `PixiCanvas`.
|
|
5
|
+
*
|
|
6
|
+
* @returns The Pixi.Renderer instance.
|
|
7
|
+
*/
|
|
8
|
+
export declare const getRenderer: () => Pixi.Renderer;
|
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
import type * as Pixi from "pixi.js";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* A custom SolidJS hook that provides access to the Pixi Ticker instance.
|
|
4
|
+
* This hook must be called from a component that is a descendant of `PixiApplicationProvider`, `PixiCanvas` or `TickerProvider`.
|
|
4
5
|
*
|
|
5
|
-
*
|
|
6
|
-
* This hook must be called from a component that is a descendant of `PixiApplication`.
|
|
7
|
-
* Or a descendant of `TickerProvider` if being used for testing without an application.
|
|
8
|
-
*
|
|
9
|
-
* @returns The PIXI.Ticker instance from the application context.
|
|
10
|
-
* @throws Will throw an error if used outside of a `PixiApplication` or `TickerProvider` context.
|
|
6
|
+
* @returns The Pixi.Ticker instance from the nearest context provider.
|
|
11
7
|
*/
|
|
12
8
|
export declare const getTicker: () => Pixi.Ticker;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
export { PixiAppContext, TickerContext } from "./context";
|
|
1
|
+
export { PixiAppContext, TickerContext, ScreenStoreContext } from "./context";
|
|
2
2
|
export { getPixiApp } from "./get-pixi-app";
|
|
3
3
|
export { getTicker } from "./get-ticker";
|
|
4
4
|
export { createPixiApplication } from "./pixi-application";
|
|
5
5
|
export type { PixiApplicationProps } from "./pixi-application-provider";
|
|
6
6
|
export { PixiApplicationProvider, TickerProvider } from "./pixi-application-provider";
|
|
7
|
+
export { getRenderer } from "./get-renderer";
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
dispose: () => void;
|
|
5
|
-
};
|
|
6
|
-
/**
|
|
7
|
-
* Calls pixi solid components in a pure Solid root without mounting to the Canvas.
|
|
8
|
-
*/
|
|
9
|
-
export declare const mountHeadless: (component: () => JSX.Element) => (() => void);
|
|
1
|
+
export { mountHeadless, withTestRoot } from "./test-root";
|
|
2
|
+
export { createMockApp, createMockRenderer, TestPixiProvider } from "./pixi-renderer-mock";
|
|
3
|
+
export type { MockRenderer } from "./pixi-renderer-mock";
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type * as Pixi from "pixi.js";
|
|
2
|
+
import type { JSX, ParentProps } from "solid-js";
|
|
3
|
+
export type MockRenderer = {
|
|
4
|
+
screen: {
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
x: number;
|
|
8
|
+
y: number;
|
|
9
|
+
};
|
|
10
|
+
addListener: (event: string, listener: () => void) => void;
|
|
11
|
+
removeListener: (event: string, listener: () => void) => void;
|
|
12
|
+
emitResize: (nextScreen?: Partial<{
|
|
13
|
+
width: number;
|
|
14
|
+
height: number;
|
|
15
|
+
x: number;
|
|
16
|
+
y: number;
|
|
17
|
+
}>) => void;
|
|
18
|
+
};
|
|
19
|
+
export declare const createMockRenderer: () => MockRenderer;
|
|
20
|
+
export declare const createMockApp: (renderer: MockRenderer) => Pixi.Application;
|
|
21
|
+
export declare const TestPixiProvider: (props: ParentProps<{
|
|
22
|
+
app: Pixi.Application;
|
|
23
|
+
renderer: MockRenderer;
|
|
24
|
+
}>) => JSX.Element;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { JSX } from "solid-js";
|
|
2
|
+
export declare const withTestRoot: <T>(setup: () => T) => {
|
|
3
|
+
value: T;
|
|
4
|
+
dispose: () => void;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Calls pixi solid components in a pure Solid root without mounting to the Canvas.
|
|
8
|
+
*/
|
|
9
|
+
export declare const mountHeadless: (component: () => JSX.Element) => (() => void);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import type { PixiScreenDimensions } from "./pixi-screen-store";
|
|
2
2
|
/**
|
|
3
3
|
*
|
|
4
|
-
* A hook that provides the current dimensions of the Pixi application's screen
|
|
5
|
-
* The properties of the returned object
|
|
4
|
+
* A hook that provides a reactive object with the current dimensions of the Pixi application's screen.
|
|
5
|
+
* The properties of the returned object update automatically when the screen size changes.
|
|
6
6
|
*
|
|
7
7
|
* This hook must be called from a component that is a descendant of `PixiCanvas` or `PixiApplicationProvider`.
|
|
8
8
|
*
|
|
9
|
-
* @returns An object containing the width and height of the Pixi screen.
|
|
10
9
|
*/
|
|
11
10
|
export declare const usePixiScreen: () => Readonly<PixiScreenDimensions>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
export type AsyncDelayFunction = (delayMs: number, signal?: AbortSignal) => Promise<void>;
|
|
1
2
|
/**
|
|
2
3
|
* Runs a callback when a given number of milliseconds has passed on the ticker.
|
|
3
4
|
*
|
|
4
|
-
* It is guaranteed to be in sync with the
|
|
5
|
+
* It is guaranteed to be in sync with the current Ticker context and uses accumulated deltaMs not an external time measurement.
|
|
5
6
|
*
|
|
6
7
|
* @param delayMs - Number of milliseconds to wait (measured in the ticker's time units).
|
|
7
8
|
*
|
|
@@ -27,4 +28,4 @@ export declare const delay: (delayMs: number, callback?: () => void) => void;
|
|
|
27
28
|
*
|
|
28
29
|
* @throws {Error} If called outside of a `PixiApplicationProvider` or `TickerProvider` context.
|
|
29
30
|
*/
|
|
30
|
-
export declare const createAsyncDelay: () =>
|
|
31
|
+
export declare const createAsyncDelay: () => AsyncDelayFunction;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
export type { ObjectFitMode } from "./object-fit";
|
|
2
|
-
export { objectFit } from "./object-fit";
|
|
1
|
+
export type { ObjectFitMode, ObjectPosition, ObjectFitContainerProps } from "./object-fit";
|
|
2
|
+
export { objectFit, ObjectFitContainer } from "./object-fit";
|
|
3
3
|
export { useSmoothDamp } from "./smooth-damp";
|
|
4
4
|
export type { Spring, UseSpringProps } from "./spring";
|
|
5
5
|
export { useSpring } from "./spring";
|
|
6
|
+
export { createAsyncDelay, delay } from "./delay";
|
|
7
|
+
export type { AsyncDelayFunction } from "./delay";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,12 +1,51 @@
|
|
|
1
1
|
import type * as Pixi from "pixi.js";
|
|
2
|
-
|
|
2
|
+
import type { JSX } from "solid-js";
|
|
3
|
+
import type { PixiComponentProps } from "../components";
|
|
4
|
+
export type ObjectFitMode = "cover" | "contain" | "fill" | "scale-down" | "none";
|
|
5
|
+
export type ObjectPosition = "center" | "top" | "right" | "bottom" | "left" | "top-left" | "top-right" | "bottom-left" | "bottom-right" | {
|
|
6
|
+
x: number;
|
|
7
|
+
y: number;
|
|
8
|
+
};
|
|
3
9
|
/**
|
|
4
10
|
* Scale an object to fit within the given bounds according to the specified fit mode.
|
|
11
|
+
*
|
|
12
|
+
* This function sets the scale and position properties of the object to fit within the bounds while respecting the aspect ratio based on the fit mode.
|
|
13
|
+
*
|
|
5
14
|
* @param object The object to be scaled.
|
|
6
15
|
* @param bounds The bounds it should fit within.
|
|
7
16
|
* @param fitMode The object fit mode to apply.
|
|
17
|
+
* @param position Optional object position anchor. Defaults to center.
|
|
8
18
|
*/
|
|
9
19
|
export declare const objectFit: (object: Pixi.Container, bounds: {
|
|
10
20
|
width: number;
|
|
11
21
|
height: number;
|
|
12
|
-
}, fitMode: ObjectFitMode) => void;
|
|
22
|
+
}, fitMode: ObjectFitMode, position?: ObjectPosition) => void;
|
|
23
|
+
export type ObjectFitContainerProps = PixiComponentProps & {
|
|
24
|
+
width: number;
|
|
25
|
+
height: number;
|
|
26
|
+
children: JSX.Element;
|
|
27
|
+
fitMode: ObjectFitMode;
|
|
28
|
+
objectPosition?: ObjectPosition;
|
|
29
|
+
observeBounds?: boolean;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* This component allows the parent container to dictate the size of its children.
|
|
33
|
+
*
|
|
34
|
+
* Each child is wrapped in a container and object-fit scaling is applied to the wrapping container based on the width and height values passed as props.
|
|
35
|
+
*
|
|
36
|
+
* If multiple children are passed, each one will be wrapped, scaled and positioned independently according to the fit mode and object position.
|
|
37
|
+
*
|
|
38
|
+
* If you want to apply the same object-fit behavior to multiple children as a group, wrap them in a parent `Container` and pass that single container as the child to `ObjectFitContainer`.
|
|
39
|
+
*
|
|
40
|
+
* Accepts all standard pixi-solid `Container` props (position, scale, mask, events, etc.) on the outer
|
|
41
|
+
* container. The `width`, `height`, `fitMode`, and `objectPosition` props control how children are scaled
|
|
42
|
+
* and aligned within the bounds. Set `observeBounds={true}` to enable ticker-based local-bounds watching.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```tsx
|
|
46
|
+
* <ObjectFitContainer x={100} y={100} width={800} height={600} fitMode="contain" objectPosition="top-left">
|
|
47
|
+
* <Sprite texture={texture} />
|
|
48
|
+
* </ObjectFitContainer>
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export declare const ObjectFitContainer: (props: ObjectFitContainerProps) => JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pixi-screen-store.js","names":[],"sources":["../../src/use-pixi-screen/pixi-screen-store.ts"],"sourcesContent":["import type * as Pixi from \"pixi.js\";\nimport { batch, onCleanup } from \"solid-js\";\nimport { createStore } from \"solid-js/store\";\n\nexport type PixiScreenDimensions = {\n width: number;\n height: number;\n left: number;\n right: number;\n bottom: number;\n top: number;\n x: number;\n y: number;\n};\n\nexport const createPixiScreenStore = (renderer: Pixi.Renderer): Readonly<PixiScreenDimensions> => {\n const [pixiScreen, setPixiScreen] = createStore<PixiScreenDimensions>({\n width: renderer.screen.width,\n height: renderer.screen.height,\n get left() {\n return this.x;\n },\n get right() {\n return this.x + this.width;\n },\n get top() {\n return this.y;\n },\n get bottom() {\n return this.y + this.height;\n },\n x: renderer.screen.x,\n y: renderer.screen.y,\n });\n\n const handleResize = () => {\n batch(() => {\n setPixiScreen(\"width\", renderer.screen.width);\n setPixiScreen(\"height\", renderer.screen.height);\n setPixiScreen(\"x\", renderer.screen.x);\n setPixiScreen(\"y\", renderer.screen.y);\n });\n };\n\n renderer.addListener(\"resize\", handleResize);\n\n onCleanup(() => {\n renderer.removeListener(\"resize\", handleResize);\n });\n\n return pixiScreen;\n};\n"],"mappings":";;;AAeA,IAAa,yBAAyB,aAA4D;CAChG,MAAM,CAAC,YAAY,iBAAiB,YAAkC;EACpE,OAAO,SAAS,OAAO;EACvB,QAAQ,SAAS,OAAO;EACxB,IAAI,OAAO;
|
|
1
|
+
{"version":3,"file":"pixi-screen-store.js","names":[],"sources":["../../src/use-pixi-screen/pixi-screen-store.ts"],"sourcesContent":["import type * as Pixi from \"pixi.js\";\nimport { batch, onCleanup } from \"solid-js\";\nimport { createStore } from \"solid-js/store\";\n\nexport type PixiScreenDimensions = {\n width: number;\n height: number;\n left: number;\n right: number;\n bottom: number;\n top: number;\n x: number;\n y: number;\n};\n\nexport const createPixiScreenStore = (renderer: Pixi.Renderer): Readonly<PixiScreenDimensions> => {\n const [pixiScreen, setPixiScreen] = createStore<PixiScreenDimensions>({\n width: renderer.screen.width,\n height: renderer.screen.height,\n get left() {\n return this.x;\n },\n get right() {\n return this.x + this.width;\n },\n get top() {\n return this.y;\n },\n get bottom() {\n return this.y + this.height;\n },\n x: renderer.screen.x,\n y: renderer.screen.y,\n });\n\n const handleResize = () => {\n batch(() => {\n setPixiScreen(\"width\", renderer.screen.width);\n setPixiScreen(\"height\", renderer.screen.height);\n setPixiScreen(\"x\", renderer.screen.x);\n setPixiScreen(\"y\", renderer.screen.y);\n });\n };\n\n renderer.addListener(\"resize\", handleResize);\n\n onCleanup(() => {\n renderer.removeListener(\"resize\", handleResize);\n });\n\n return pixiScreen;\n};\n"],"mappings":";;;AAeA,IAAa,yBAAyB,aAA4D;CAChG,MAAM,CAAC,YAAY,iBAAiB,YAAkC;EACpE,OAAO,SAAS,OAAO;EACvB,QAAQ,SAAS,OAAO;EACxB,IAAI,OAAO;GACT,OAAO,KAAK;;EAEd,IAAI,QAAQ;GACV,OAAO,KAAK,IAAI,KAAK;;EAEvB,IAAI,MAAM;GACR,OAAO,KAAK;;EAEd,IAAI,SAAS;GACX,OAAO,KAAK,IAAI,KAAK;;EAEvB,GAAG,SAAS,OAAO;EACnB,GAAG,SAAS,OAAO;EACpB,CAAC;CAEF,MAAM,qBAAqB;EACzB,YAAY;GACV,cAAc,SAAS,SAAS,OAAO,MAAM;GAC7C,cAAc,UAAU,SAAS,OAAO,OAAO;GAC/C,cAAc,KAAK,SAAS,OAAO,EAAE;GACrC,cAAc,KAAK,SAAS,OAAO,EAAE;IACrC;;CAGJ,SAAS,YAAY,UAAU,aAAa;CAE5C,gBAAgB;EACd,SAAS,eAAe,UAAU,aAAa;GAC/C;CAEF,OAAO"}
|
|
@@ -1,19 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ScreenStoreContext } from "../pixi-application/context.js";
|
|
2
2
|
import { useContext } from "solid-js";
|
|
3
3
|
//#region src/use-pixi-screen/use-pixi-screen.ts
|
|
4
4
|
/**
|
|
5
5
|
*
|
|
6
|
-
* A hook that provides the current dimensions of the Pixi application's screen
|
|
7
|
-
* The properties of the returned object
|
|
6
|
+
* A hook that provides a reactive object with the current dimensions of the Pixi application's screen.
|
|
7
|
+
* The properties of the returned object update automatically when the screen size changes.
|
|
8
8
|
*
|
|
9
9
|
* This hook must be called from a component that is a descendant of `PixiCanvas` or `PixiApplicationProvider`.
|
|
10
10
|
*
|
|
11
|
-
* @returns An object containing the width and height of the Pixi screen.
|
|
12
11
|
*/
|
|
13
12
|
var usePixiScreen = () => {
|
|
14
|
-
const
|
|
15
|
-
if (!
|
|
16
|
-
return
|
|
13
|
+
const pixiScreenStore = useContext(ScreenStoreContext);
|
|
14
|
+
if (!pixiScreenStore) throw new Error("usePixiScreen must be used within a PixiApplicationProvider or PixiCanvas");
|
|
15
|
+
return pixiScreenStore;
|
|
17
16
|
};
|
|
18
17
|
//#endregion
|
|
19
18
|
export { usePixiScreen };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-pixi-screen.js","names":[],"sources":["../../src/use-pixi-screen/use-pixi-screen.ts"],"sourcesContent":["import { useContext } from \"solid-js\";\n\nimport {
|
|
1
|
+
{"version":3,"file":"use-pixi-screen.js","names":[],"sources":["../../src/use-pixi-screen/use-pixi-screen.ts"],"sourcesContent":["import { useContext } from \"solid-js\";\n\nimport { ScreenStoreContext } from \"../pixi-application\";\n\nimport type { PixiScreenDimensions } from \"./pixi-screen-store\";\n\n/**\n *\n * A hook that provides a reactive object with the current dimensions of the Pixi application's screen.\n * The properties of the returned object update automatically when the screen size changes.\n *\n * This hook must be called from a component that is a descendant of `PixiCanvas` or `PixiApplicationProvider`.\n *\n */\nexport const usePixiScreen = (): Readonly<PixiScreenDimensions> => {\n const pixiScreenStore = useContext(ScreenStoreContext);\n if (!pixiScreenStore) {\n throw new Error(\"usePixiScreen must be used within a PixiApplicationProvider or PixiCanvas\");\n }\n return pixiScreenStore;\n};\n"],"mappings":";;;;;;;;;;;AAcA,IAAa,sBAAsD;CACjE,MAAM,kBAAkB,WAAW,mBAAmB;CACtD,IAAI,CAAC,iBACH,MAAM,IAAI,MAAM,4EAA4E;CAE9F,OAAO"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { TickerContext } from "
|
|
1
|
+
import { TickerContext } from "../pixi-application/context.js";
|
|
2
2
|
import { useContext } from "solid-js";
|
|
3
|
-
//#region src/delay.ts
|
|
3
|
+
//#region src/utils/delay.ts
|
|
4
4
|
/**
|
|
5
5
|
* Runs a callback when a given number of milliseconds has passed on the ticker.
|
|
6
6
|
*
|
|
7
|
-
* It is guaranteed to be in sync with the
|
|
7
|
+
* It is guaranteed to be in sync with the current Ticker context and uses accumulated deltaMs not an external time measurement.
|
|
8
8
|
*
|
|
9
9
|
* @param delayMs - Number of milliseconds to wait (measured in the ticker's time units).
|
|
10
10
|
*
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delay.js","names":[],"sources":["../../src/utils/delay.ts"],"sourcesContent":["import type * as Pixi from \"pixi.js\";\nimport { useContext } from \"solid-js\";\n\nimport { TickerContext } from \"../pixi-application\";\n\nexport type AsyncDelayFunction = (delayMs: number, signal?: AbortSignal) => Promise<void>;\n\n/**\n * Runs a callback when a given number of milliseconds has passed on the ticker.\n *\n * It is guaranteed to be in sync with the current Ticker context and uses accumulated deltaMs not an external time measurement.\n *\n * @param delayMs - Number of milliseconds to wait (measured in the ticker's time units).\n *\n * @param callback - A callback function that will fire when the delayMs time has passed.\n *\n * @throws {Error} If called outside of a `PixiApplicationProvider` or `TickerProvider` context.\n *\n * @note It will not run the callback if the ticker is paused or stopped.\n *\n */\nexport const delay = (delayMs: number, callback?: () => void): void => {\n const ticker = useContext(TickerContext);\n if (!ticker) {\n throw new Error(\"`delay` must be used within a PixiApplicationProvider or a TickerProvider.\");\n }\n\n let timeDelayed = 0;\n\n const internalCallback = () => {\n timeDelayed += ticker.deltaMS;\n if (timeDelayed < delayMs) return;\n callback?.();\n ticker.remove(internalCallback);\n };\n\n ticker.add(internalCallback);\n};\n\nconst asyncDelay = async (ticker: Pixi.Ticker, delayMs: number, signal?: AbortSignal) => {\n let timeDelayed = 0;\n let resolvePromise: (value: void | PromiseLike<void>) => void;\n\n const promise = new Promise<void>((resolve) => {\n resolvePromise = resolve;\n });\n\n const internalCallback = () => {\n timeDelayed += ticker.deltaMS;\n if (timeDelayed < delayMs) return;\n resolvePromise();\n };\n\n const handleAbort = () => {\n ticker.remove(internalCallback);\n resolvePromise();\n };\n\n if (signal?.aborted) {\n // Already aborted before we even started\n return;\n }\n\n signal?.addEventListener(\"abort\", handleAbort);\n\n ticker.add(internalCallback);\n await promise;\n ticker.remove(internalCallback);\n signal?.removeEventListener(\"abort\", handleAbort);\n};\n\n/**\n * Create a delay function that waits until a given number of milliseconds has passed on the current Ticker context before resolving.\n *\n * This function must be called inside a `PixiApplicationProvider` or `TickerProvider` context.\n *\n * @param signal - Optional AbortSignal to resolve the delay early\n * @returns An async function we can await to delay events in sync with time passed on the Ticker.\n *\n * Simply await for it to resolve in an async context. If the signal aborts, the promise resolves immediately.\n *\n * @note It will not resolve if the ticker is paused or stopped.\n *\n * @throws {Error} If called outside of a `PixiApplicationProvider` or `TickerProvider` context.\n */\nexport const createAsyncDelay = (): AsyncDelayFunction => {\n const ticker = useContext(TickerContext);\n\n if (!ticker) {\n throw new Error(\n \"`createAsyncDelay` must be used within a PixiApplicationProvider or a TickerProvider. The returned delay function can be called in an async context but `createAsyncDelay` must be called in a synchronous scope within a PixiApplicationProvider or a TickerProvider\",\n );\n }\n const delayWithTicker = (delayMs: number, signal?: AbortSignal) =>\n asyncDelay(ticker, delayMs, signal);\n\n return delayWithTicker;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;AAqBA,IAAa,SAAS,SAAiB,aAAgC;CACrE,MAAM,SAAS,WAAW,cAAc;CACxC,IAAI,CAAC,QACH,MAAM,IAAI,MAAM,6EAA6E;CAG/F,IAAI,cAAc;CAElB,MAAM,yBAAyB;EAC7B,eAAe,OAAO;EACtB,IAAI,cAAc,SAAS;EAC3B,YAAY;EACZ,OAAO,OAAO,iBAAiB;;CAGjC,OAAO,IAAI,iBAAiB;;AAG9B,IAAM,aAAa,OAAO,QAAqB,SAAiB,WAAyB;CACvF,IAAI,cAAc;CAClB,IAAI;CAEJ,MAAM,UAAU,IAAI,SAAe,YAAY;EAC7C,iBAAiB;GACjB;CAEF,MAAM,yBAAyB;EAC7B,eAAe,OAAO;EACtB,IAAI,cAAc,SAAS;EAC3B,gBAAgB;;CAGlB,MAAM,oBAAoB;EACxB,OAAO,OAAO,iBAAiB;EAC/B,gBAAgB;;CAGlB,IAAI,QAAQ,SAEV;CAGF,QAAQ,iBAAiB,SAAS,YAAY;CAE9C,OAAO,IAAI,iBAAiB;CAC5B,MAAM;CACN,OAAO,OAAO,iBAAiB;CAC/B,QAAQ,oBAAoB,SAAS,YAAY;;;;;;;;;;;;;;;;AAiBnD,IAAa,yBAA6C;CACxD,MAAM,SAAS,WAAW,cAAc;CAExC,IAAI,CAAC,QACH,MAAM,IAAI,MACR,wQACD;CAEH,MAAM,mBAAmB,SAAiB,WACxC,WAAW,QAAQ,SAAS,OAAO;CAErC,OAAO"}
|
package/dist/utils/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { objectFit } from "./object-fit.js";
|
|
1
|
+
import { ObjectFitContainer, objectFit } from "./object-fit.js";
|
|
2
2
|
import { useSmoothDamp } from "./smooth-damp.js";
|
|
3
3
|
import { useSpring } from "./spring.js";
|
|
4
|
-
|
|
4
|
+
import { createAsyncDelay, delay } from "./delay.js";
|
|
5
|
+
export { ObjectFitContainer, createAsyncDelay, delay, objectFit, useSmoothDamp, useSpring };
|
package/dist/utils/object-fit.js
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const originalWidth = object.width / object.scale.x;
|
|
10
|
-
const originalHeight = object.height / object.scale.y;
|
|
1
|
+
import { onTick } from "../on-tick.js";
|
|
2
|
+
import { Container } from "../components/components.js";
|
|
3
|
+
import { Index, children, createEffect, on, onCleanup, splitProps } from "solid-js";
|
|
4
|
+
import { createComponent, mergeProps } from "solid-js/web";
|
|
5
|
+
//#region src/utils/object-fit.tsx
|
|
6
|
+
var objectFitWithLocalBounds = (object, bounds, fitMode, position, localBounds) => {
|
|
7
|
+
const originalWidth = localBounds.width;
|
|
8
|
+
const originalHeight = localBounds.height;
|
|
11
9
|
if (originalWidth === 0 || originalHeight === 0 || bounds.width === 0 || bounds.height === 0) return;
|
|
12
10
|
const widthRatio = bounds.width / originalWidth;
|
|
13
11
|
const heightRatio = bounds.height / originalHeight;
|
|
@@ -31,22 +29,162 @@ var objectFit = (object, bounds, fitMode) => {
|
|
|
31
29
|
scaleY = heightRatio;
|
|
32
30
|
break;
|
|
33
31
|
case "scale-down":
|
|
34
|
-
|
|
35
|
-
scaleX = 1;
|
|
36
|
-
scaleY = 1;
|
|
37
|
-
} else {
|
|
38
|
-
const scaleDown = Math.min(widthRatio, heightRatio);
|
|
39
|
-
scaleX = scaleDown;
|
|
40
|
-
scaleY = scaleDown;
|
|
41
|
-
}
|
|
32
|
+
scaleX = scaleY = Math.min(1, Math.min(widthRatio, heightRatio));
|
|
42
33
|
break;
|
|
43
|
-
|
|
34
|
+
case "none": break;
|
|
44
35
|
}
|
|
45
36
|
object.scale.set(scaleX, scaleY);
|
|
46
|
-
|
|
47
|
-
|
|
37
|
+
const resolvedPosition = resolveObjectPosition(position);
|
|
38
|
+
const scaledWidth = localBounds.width * scaleX;
|
|
39
|
+
const scaledHeight = localBounds.height * scaleY;
|
|
40
|
+
object.x = -localBounds.x * scaleX + (bounds.width - scaledWidth) * resolvedPosition.x;
|
|
41
|
+
object.y = -localBounds.y * scaleY + (bounds.height - scaledHeight) * resolvedPosition.y;
|
|
42
|
+
};
|
|
43
|
+
var resolveObjectPosition = (position) => {
|
|
44
|
+
const defaultPosition = {
|
|
45
|
+
x: .5,
|
|
46
|
+
y: .5
|
|
47
|
+
};
|
|
48
|
+
if (!position) return defaultPosition;
|
|
49
|
+
if (typeof position === "object") return position;
|
|
50
|
+
switch (position) {
|
|
51
|
+
case "top": return {
|
|
52
|
+
x: .5,
|
|
53
|
+
y: 0
|
|
54
|
+
};
|
|
55
|
+
case "right": return {
|
|
56
|
+
x: 1,
|
|
57
|
+
y: .5
|
|
58
|
+
};
|
|
59
|
+
case "bottom": return {
|
|
60
|
+
x: .5,
|
|
61
|
+
y: 1
|
|
62
|
+
};
|
|
63
|
+
case "left": return {
|
|
64
|
+
x: 0,
|
|
65
|
+
y: .5
|
|
66
|
+
};
|
|
67
|
+
case "top-left": return {
|
|
68
|
+
x: 0,
|
|
69
|
+
y: 0
|
|
70
|
+
};
|
|
71
|
+
case "top-right": return {
|
|
72
|
+
x: 1,
|
|
73
|
+
y: 0
|
|
74
|
+
};
|
|
75
|
+
case "bottom-left": return {
|
|
76
|
+
x: 0,
|
|
77
|
+
y: 1
|
|
78
|
+
};
|
|
79
|
+
case "bottom-right": return {
|
|
80
|
+
x: 1,
|
|
81
|
+
y: 1
|
|
82
|
+
};
|
|
83
|
+
default: return defaultPosition;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* Scale an object to fit within the given bounds according to the specified fit mode.
|
|
88
|
+
*
|
|
89
|
+
* This function sets the scale and position properties of the object to fit within the bounds while respecting the aspect ratio based on the fit mode.
|
|
90
|
+
*
|
|
91
|
+
* @param object The object to be scaled.
|
|
92
|
+
* @param bounds The bounds it should fit within.
|
|
93
|
+
* @param fitMode The object fit mode to apply.
|
|
94
|
+
* @param position Optional object position anchor. Defaults to center.
|
|
95
|
+
*/
|
|
96
|
+
var objectFit = (object, bounds, fitMode, position = "center") => {
|
|
97
|
+
objectFitWithLocalBounds(object, bounds, fitMode, position, object.getLocalBounds());
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* This component allows the parent container to dictate the size of its children.
|
|
101
|
+
*
|
|
102
|
+
* Each child is wrapped in a container and object-fit scaling is applied to the wrapping container based on the width and height values passed as props.
|
|
103
|
+
*
|
|
104
|
+
* If multiple children are passed, each one will be wrapped, scaled and positioned independently according to the fit mode and object position.
|
|
105
|
+
*
|
|
106
|
+
* If you want to apply the same object-fit behavior to multiple children as a group, wrap them in a parent `Container` and pass that single container as the child to `ObjectFitContainer`.
|
|
107
|
+
*
|
|
108
|
+
* Accepts all standard pixi-solid `Container` props (position, scale, mask, events, etc.) on the outer
|
|
109
|
+
* container. The `width`, `height`, `fitMode`, and `objectPosition` props control how children are scaled
|
|
110
|
+
* and aligned within the bounds. Set `observeBounds={true}` to enable ticker-based local-bounds watching.
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* ```tsx
|
|
114
|
+
* <ObjectFitContainer x={100} y={100} width={800} height={600} fitMode="contain" objectPosition="top-left">
|
|
115
|
+
* <Sprite texture={texture} />
|
|
116
|
+
* </ObjectFitContainer>
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
var ObjectFitContainer = (props) => {
|
|
120
|
+
const [local, rest] = splitProps(props, [
|
|
121
|
+
"width",
|
|
122
|
+
"height",
|
|
123
|
+
"fitMode",
|
|
124
|
+
"objectPosition",
|
|
125
|
+
"observeBounds",
|
|
126
|
+
"children"
|
|
127
|
+
]);
|
|
128
|
+
const resolvedChildren = children(() => local.children);
|
|
129
|
+
const innerContainerSet = /* @__PURE__ */ new Set();
|
|
130
|
+
const cachedBoundsMap = /* @__PURE__ */ new WeakMap();
|
|
131
|
+
createEffect(() => {
|
|
132
|
+
local.width;
|
|
133
|
+
local.height;
|
|
134
|
+
local.fitMode;
|
|
135
|
+
local.objectPosition;
|
|
136
|
+
resolvedChildren();
|
|
137
|
+
for (const child of innerContainerSet) objectFit(child, local, local.fitMode, local.objectPosition);
|
|
138
|
+
});
|
|
139
|
+
createEffect(on(() => local.observeBounds, (observeBounds) => {
|
|
140
|
+
if (observeBounds !== true) return;
|
|
141
|
+
onTick(() => {
|
|
142
|
+
for (const child of innerContainerSet) {
|
|
143
|
+
const nextLocalBounds = child.getLocalBounds();
|
|
144
|
+
let previousLocalBounds = cachedBoundsMap.get(child);
|
|
145
|
+
if (!previousLocalBounds || previousLocalBounds.x !== nextLocalBounds.x || previousLocalBounds.y !== nextLocalBounds.y || previousLocalBounds.width !== nextLocalBounds.width || previousLocalBounds.height !== nextLocalBounds.height) {
|
|
146
|
+
if (!previousLocalBounds) {
|
|
147
|
+
previousLocalBounds = {
|
|
148
|
+
x: nextLocalBounds.x,
|
|
149
|
+
y: nextLocalBounds.y,
|
|
150
|
+
width: nextLocalBounds.width,
|
|
151
|
+
height: nextLocalBounds.height
|
|
152
|
+
};
|
|
153
|
+
cachedBoundsMap.set(child, previousLocalBounds);
|
|
154
|
+
} else {
|
|
155
|
+
previousLocalBounds.x = nextLocalBounds.x;
|
|
156
|
+
previousLocalBounds.y = nextLocalBounds.y;
|
|
157
|
+
previousLocalBounds.width = nextLocalBounds.width;
|
|
158
|
+
previousLocalBounds.height = nextLocalBounds.height;
|
|
159
|
+
}
|
|
160
|
+
objectFitWithLocalBounds(child, local, local.fitMode, local.objectPosition ?? "center", nextLocalBounds);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
}));
|
|
165
|
+
return createComponent(Container, mergeProps(rest, { get children() {
|
|
166
|
+
return createComponent(Index, {
|
|
167
|
+
get each() {
|
|
168
|
+
return resolvedChildren.toArray();
|
|
169
|
+
},
|
|
170
|
+
children: (child, index) => {
|
|
171
|
+
return createComponent(Container, {
|
|
172
|
+
label: `object-fit-child-wrapper-${index}`,
|
|
173
|
+
ref: (el) => {
|
|
174
|
+
innerContainerSet.add(el);
|
|
175
|
+
onCleanup(() => {
|
|
176
|
+
innerContainerSet.delete(el);
|
|
177
|
+
});
|
|
178
|
+
},
|
|
179
|
+
get children() {
|
|
180
|
+
return child();
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
} }));
|
|
48
186
|
};
|
|
49
187
|
//#endregion
|
|
50
|
-
export { objectFit };
|
|
188
|
+
export { ObjectFitContainer, objectFit };
|
|
51
189
|
|
|
52
190
|
//# sourceMappingURL=object-fit.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"object-fit.js","names":[],"sources":["../../src/utils/object-fit.ts"],"sourcesContent":["import type * as Pixi from \"pixi.js\";\n\nexport type ObjectFitMode = \"cover\" | \"contain\" | \"fill\" | \"scale-down\";\n\n/**\n * Scale an object to fit within the given bounds according to the specified fit mode.\n * @param object The object to be scaled.\n * @param bounds The bounds it should fit within.\n * @param fitMode The object fit mode to apply.\n */\nexport const objectFit = (\n object: Pixi.Container,\n bounds: { width: number; height: number },\n fitMode: ObjectFitMode,\n): void => {\n const originalWidth = object.width / object.scale.x;\n const originalHeight = object.height / object.scale.y;\n\n if (originalWidth === 0 || originalHeight === 0 || bounds.width === 0 || bounds.height === 0)\n return;\n\n const widthRatio = bounds.width / originalWidth;\n const heightRatio = bounds.height / originalHeight;\n\n let scaleX = 1;\n let scaleY = 1;\n\n // biome-ignore lint/nursery/noUnnecessaryConditions: <explanation>\n switch (fitMode) {\n case \"cover\": {\n const coverScale = Math.max(widthRatio, heightRatio);\n scaleX = coverScale;\n scaleY = coverScale;\n break;\n }\n case \"contain\": {\n const containScale = Math.min(widthRatio, heightRatio);\n scaleX = containScale;\n scaleY = containScale;\n break;\n }\n case \"fill\": {\n scaleX = widthRatio;\n scaleY = heightRatio;\n break;\n }\n case \"scale-down\": {\n // If the object is smaller than the container, it's 'none' (no scaling up).\n // Otherwise, it's 'contain'.\n if (originalWidth <= bounds.width && originalHeight <= bounds.height) {\n scaleX = 1;\n scaleY = 1;\n } else {\n const scaleDown = Math.min(widthRatio, heightRatio);\n scaleX = scaleDown;\n scaleY = scaleDown;\n }\n break;\n }\n default:\n // Default to no scaling if an unknown fitMode is provided\n break;\n }\n\n object.scale.set(scaleX, scaleY);\n\n // Center the object\n object.x = (bounds.width - object.width) / 2;\n object.y = (bounds.height - object.height) / 2;\n};\n"],"mappings":";;;;;;;AAUA,IAAa,aACX,QACA,QACA,YACS;CACT,MAAM,gBAAgB,OAAO,QAAQ,OAAO,MAAM;CAClD,MAAM,iBAAiB,OAAO,SAAS,OAAO,MAAM;AAEpD,KAAI,kBAAkB,KAAK,mBAAmB,KAAK,OAAO,UAAU,KAAK,OAAO,WAAW,EACzF;CAEF,MAAM,aAAa,OAAO,QAAQ;CAClC,MAAM,cAAc,OAAO,SAAS;CAEpC,IAAI,SAAS;CACb,IAAI,SAAS;AAGb,SAAQ,SAAR;EACE,KAAK,SAAS;GACZ,MAAM,aAAa,KAAK,IAAI,YAAY,YAAY;AACpD,YAAS;AACT,YAAS;AACT;;EAEF,KAAK,WAAW;GACd,MAAM,eAAe,KAAK,IAAI,YAAY,YAAY;AACtD,YAAS;AACT,YAAS;AACT;;EAEF,KAAK;AACH,YAAS;AACT,YAAS;AACT;EAEF,KAAK;AAGH,OAAI,iBAAiB,OAAO,SAAS,kBAAkB,OAAO,QAAQ;AACpE,aAAS;AACT,aAAS;UACJ;IACL,MAAM,YAAY,KAAK,IAAI,YAAY,YAAY;AACnD,aAAS;AACT,aAAS;;AAEX;EAEF,QAEE;;AAGJ,QAAO,MAAM,IAAI,QAAQ,OAAO;AAGhC,QAAO,KAAK,OAAO,QAAQ,OAAO,SAAS;AAC3C,QAAO,KAAK,OAAO,SAAS,OAAO,UAAU"}
|
|
1
|
+
{"version":3,"file":"object-fit.js","names":["Pixi","JSX","createEffect","splitProps","children","Index","onCleanup","on","PixiComponentProps","Container","onTick","ObjectFitMode","ObjectPosition","x","y","objectFitWithLocalBounds","object","bounds","width","height","fitMode","position","localBounds","originalWidth","originalHeight","widthRatio","heightRatio","scaleX","scaleY","coverScale","Math","max","containScale","min","scale","set","resolvedPosition","resolveObjectPosition","scaledWidth","scaledHeight","defaultPosition","objectFit","getLocalBounds","ObjectFitContainerProps","Element","objectPosition","observeBounds","ObjectFitContainer","props","local","rest","resolvedChildren","innerContainerSet","Set","cachedBoundsMap","WeakMap","child","nextLocalBounds","previousLocalBounds","get","_$createComponent","_$mergeProps","each","toArray","index","label","ref","el","add","delete"],"sources":["../../src/utils/object-fit.tsx"],"sourcesContent":["import type * as Pixi from \"pixi.js\";\nimport type { JSX } from \"solid-js\";\nimport { createEffect, splitProps, children, Index, onCleanup, on } from \"solid-js\";\n\nimport type { PixiComponentProps } from \"../components\";\nimport { Container } from \"../components/components\";\nimport { onTick } from \"../on-tick\";\n\nexport type ObjectFitMode = \"cover\" | \"contain\" | \"fill\" | \"scale-down\" | \"none\";\n\nexport type ObjectPosition =\n | \"center\"\n | \"top\"\n | \"right\"\n | \"bottom\"\n | \"left\"\n | \"top-left\"\n | \"top-right\"\n | \"bottom-left\"\n | \"bottom-right\"\n | { x: number; y: number };\n\nconst objectFitWithLocalBounds = (\n object: Pixi.Container,\n bounds: { width: number; height: number },\n fitMode: ObjectFitMode,\n position: ObjectPosition,\n localBounds: { x: number; y: number; width: number; height: number },\n): void => {\n const originalWidth = localBounds.width;\n const originalHeight = localBounds.height;\n\n if (originalWidth === 0 || originalHeight === 0 || bounds.width === 0 || bounds.height === 0)\n return;\n\n const widthRatio = bounds.width / originalWidth;\n const heightRatio = bounds.height / originalHeight;\n\n let scaleX = 1;\n let scaleY = 1;\n\n switch (fitMode) {\n case \"cover\": {\n const coverScale = Math.max(widthRatio, heightRatio);\n scaleX = coverScale;\n scaleY = coverScale;\n break;\n }\n case \"contain\": {\n const containScale = Math.min(widthRatio, heightRatio);\n scaleX = containScale;\n scaleY = containScale;\n break;\n }\n case \"fill\": {\n scaleX = widthRatio;\n scaleY = heightRatio;\n break;\n }\n case \"scale-down\": {\n scaleX = scaleY = Math.min(1, Math.min(widthRatio, heightRatio));\n break;\n }\n case \"none\":\n break;\n }\n\n object.scale.set(scaleX, scaleY);\n const resolvedPosition = resolveObjectPosition(position);\n const scaledWidth = localBounds.width * scaleX;\n const scaledHeight = localBounds.height * scaleY;\n\n object.x = -localBounds.x * scaleX + (bounds.width - scaledWidth) * resolvedPosition.x;\n object.y = -localBounds.y * scaleY + (bounds.height - scaledHeight) * resolvedPosition.y;\n};\n\nconst resolveObjectPosition = (position: ObjectPosition | undefined): { x: number; y: number } => {\n const defaultPosition = { x: 0.5, y: 0.5 };\n\n if (!position) {\n return defaultPosition;\n }\n\n if (typeof position === \"object\") {\n return position;\n }\n\n switch (position) {\n case \"top\":\n return { x: 0.5, y: 0 };\n case \"right\":\n return { x: 1, y: 0.5 };\n case \"bottom\":\n return { x: 0.5, y: 1 };\n case \"left\":\n return { x: 0, y: 0.5 };\n case \"top-left\":\n return { x: 0, y: 0 };\n case \"top-right\":\n return { x: 1, y: 0 };\n case \"bottom-left\":\n return { x: 0, y: 1 };\n case \"bottom-right\":\n return { x: 1, y: 1 };\n case \"center\":\n default:\n return defaultPosition;\n }\n};\n\n/**\n * Scale an object to fit within the given bounds according to the specified fit mode.\n *\n * This function sets the scale and position properties of the object to fit within the bounds while respecting the aspect ratio based on the fit mode.\n *\n * @param object The object to be scaled.\n * @param bounds The bounds it should fit within.\n * @param fitMode The object fit mode to apply.\n * @param position Optional object position anchor. Defaults to center.\n */\nexport const objectFit = (\n object: Pixi.Container,\n bounds: { width: number; height: number },\n fitMode: ObjectFitMode,\n position: ObjectPosition = \"center\",\n): void => {\n objectFitWithLocalBounds(object, bounds, fitMode, position, object.getLocalBounds());\n};\n\nexport type ObjectFitContainerProps = PixiComponentProps & {\n width: number;\n height: number;\n children: JSX.Element;\n fitMode: ObjectFitMode;\n objectPosition?: ObjectPosition;\n observeBounds?: boolean;\n};\n\n/**\n * This component allows the parent container to dictate the size of its children.\n *\n * Each child is wrapped in a container and object-fit scaling is applied to the wrapping container based on the width and height values passed as props.\n *\n * If multiple children are passed, each one will be wrapped, scaled and positioned independently according to the fit mode and object position.\n *\n * If you want to apply the same object-fit behavior to multiple children as a group, wrap them in a parent `Container` and pass that single container as the child to `ObjectFitContainer`.\n *\n * Accepts all standard pixi-solid `Container` props (position, scale, mask, events, etc.) on the outer\n * container. The `width`, `height`, `fitMode`, and `objectPosition` props control how children are scaled\n * and aligned within the bounds. Set `observeBounds={true}` to enable ticker-based local-bounds watching.\n *\n * @example\n * ```tsx\n * <ObjectFitContainer x={100} y={100} width={800} height={600} fitMode=\"contain\" objectPosition=\"top-left\">\n * <Sprite texture={texture} />\n * </ObjectFitContainer>\n * ```\n */\nexport const ObjectFitContainer = (props: ObjectFitContainerProps): JSX.Element => {\n const [local, rest] = splitProps(props, [\n \"width\",\n \"height\",\n \"fitMode\",\n \"objectPosition\",\n \"observeBounds\",\n \"children\",\n ]);\n\n const resolvedChildren = children(() => local.children);\n const innerContainerSet = new Set<Pixi.Container>();\n const cachedBoundsMap = new WeakMap<\n Pixi.Container,\n { x: number; y: number; width: number; height: number }\n >();\n\n createEffect(() => {\n void local.width;\n void local.height;\n void local.fitMode;\n void local.objectPosition;\n void resolvedChildren();\n\n for (const child of innerContainerSet) {\n objectFit(child, local, local.fitMode, local.objectPosition);\n }\n });\n\n createEffect(\n on(\n () => local.observeBounds,\n (observeBounds) => {\n if (observeBounds !== true) {\n return;\n }\n\n onTick(() => {\n for (const child of innerContainerSet) {\n const nextLocalBounds = child.getLocalBounds();\n let previousLocalBounds = cachedBoundsMap.get(child);\n\n if (\n !previousLocalBounds ||\n previousLocalBounds.x !== nextLocalBounds.x ||\n previousLocalBounds.y !== nextLocalBounds.y ||\n previousLocalBounds.width !== nextLocalBounds.width ||\n previousLocalBounds.height !== nextLocalBounds.height\n ) {\n if (!previousLocalBounds) {\n previousLocalBounds = {\n x: nextLocalBounds.x,\n y: nextLocalBounds.y,\n width: nextLocalBounds.width,\n height: nextLocalBounds.height,\n };\n cachedBoundsMap.set(child, previousLocalBounds);\n } else {\n previousLocalBounds.x = nextLocalBounds.x;\n previousLocalBounds.y = nextLocalBounds.y;\n previousLocalBounds.width = nextLocalBounds.width;\n previousLocalBounds.height = nextLocalBounds.height;\n }\n\n objectFitWithLocalBounds(\n child,\n local,\n local.fitMode,\n local.objectPosition ?? \"center\",\n nextLocalBounds,\n );\n }\n }\n });\n },\n ),\n );\n\n return (\n <Container {...rest}>\n <Index each={resolvedChildren.toArray()}>\n {(child, index) => {\n return (\n <Container\n label={`object-fit-child-wrapper-${index}`}\n ref={(el) => {\n innerContainerSet.add(el);\n onCleanup(() => {\n innerContainerSet.delete(el);\n });\n }}\n >\n {child()}\n </Container>\n );\n }}\n </Index>\n </Container>\n );\n};\n"],"mappings":";;;;;AAsBA,IAAMe,4BACJC,QACAC,QACAG,SACAC,UACAC,gBACS;CACT,MAAMC,gBAAgBD,YAAYJ;CAClC,MAAMM,iBAAiBF,YAAYH;CAEnC,IAAII,kBAAkB,KAAKC,mBAAmB,KAAKP,OAAOC,UAAU,KAAKD,OAAOE,WAAW,GACzF;CAEF,MAAMM,aAAaR,OAAOC,QAAQK;CAClC,MAAMG,cAAcT,OAAOE,SAASK;CAEpC,IAAIG,SAAS;CACb,IAAIC,SAAS;CAEb,QAAQR,SAAR;EACE,KAAK,SAAS;GACZ,MAAMS,aAAaC,KAAKC,IAAIN,YAAYC,YAAY;GACpDC,SAASE;GACTD,SAASC;GACT;;EAEF,KAAK,WAAW;GACd,MAAMG,eAAeF,KAAKG,IAAIR,YAAYC,YAAY;GACtDC,SAASK;GACTJ,SAASI;GACT;;EAEF,KAAK;GACHL,SAASF;GACTG,SAASF;GACT;EAEF,KAAK;GACHC,SAASC,SAASE,KAAKG,IAAI,GAAGH,KAAKG,IAAIR,YAAYC,YAAY,CAAC;GAChE;EAEF,KAAK,QACH;;CAGJV,OAAOkB,MAAMC,IAAIR,QAAQC,OAAO;CAChC,MAAMQ,mBAAmBC,sBAAsBhB,SAAS;CACxD,MAAMiB,cAAchB,YAAYJ,QAAQS;CACxC,MAAMY,eAAejB,YAAYH,SAASS;CAE1CZ,OAAOH,IAAI,CAACS,YAAYT,IAAIc,UAAUV,OAAOC,QAAQoB,eAAeF,iBAAiBvB;CACrFG,OAAOF,IAAI,CAACQ,YAAYR,IAAIc,UAAUX,OAAOE,SAASoB,gBAAgBH,iBAAiBtB;;AAGzF,IAAMuB,yBAAyBhB,aAAmE;CAChG,MAAMmB,kBAAkB;EAAE3B,GAAG;EAAKC,GAAG;EAAK;CAE1C,IAAI,CAACO,UACH,OAAOmB;CAGT,IAAI,OAAOnB,aAAa,UACtB,OAAOA;CAGT,QAAQA,UAAR;EACE,KAAK,OACH,OAAO;GAAER,GAAG;GAAKC,GAAG;GAAG;EACzB,KAAK,SACH,OAAO;GAAED,GAAG;GAAGC,GAAG;GAAK;EACzB,KAAK,UACH,OAAO;GAAED,GAAG;GAAKC,GAAG;GAAG;EACzB,KAAK,QACH,OAAO;GAAED,GAAG;GAAGC,GAAG;GAAK;EACzB,KAAK,YACH,OAAO;GAAED,GAAG;GAAGC,GAAG;GAAG;EACvB,KAAK,aACH,OAAO;GAAED,GAAG;GAAGC,GAAG;GAAG;EACvB,KAAK,eACH,OAAO;GAAED,GAAG;GAAGC,GAAG;GAAG;EACvB,KAAK,gBACH,OAAO;GAAED,GAAG;GAAGC,GAAG;GAAG;EAEvB,SACE,OAAO0B;;;;;;;;;;;;;AAcb,IAAaC,aACXzB,QACAC,QACAG,SACAC,WAA2B,aAClB;CACTN,yBAAyBC,QAAQC,QAAQG,SAASC,UAAUL,OAAO0B,gBAAgB,CAAC;;;;;;;;;;;;;;;;;;;;;;AAgCtF,IAAaK,sBAAsBC,UAAgD;CACjF,MAAM,CAACC,OAAOC,QAAQ/C,WAAW6C,OAAO;EACtC;EACA;EACA;EACA;EACA;EACA;EACD,CAAC;CAEF,MAAMG,mBAAmB/C,eAAe6C,MAAM7C,SAAS;CACvD,MAAMgD,oCAAoB,IAAIC,KAAqB;CACnD,MAAMC,kCAAkB,IAAIC,SAGzB;CAEHrD,mBAAmB;EACjB,MAAWgB;EACX,MAAWC;EACX,MAAWC;EACX,MAAWyB;EACX,kBAAuB;EAEvB,KAAK,MAAMW,SAASJ,mBAClBX,UAAUe,OAAOP,OAAOA,MAAM7B,SAAS6B,MAAMJ,eAAe;GAE9D;CAEF3C,aACEK,SACQ0C,MAAMH,gBACXA,kBAAkB;EACjB,IAAIA,kBAAkB,MACpB;EAGFpC,aAAa;GACX,KAAK,MAAM8C,SAASJ,mBAAmB;IACrC,MAAMK,kBAAkBD,MAAMd,gBAAgB;IAC9C,IAAIgB,sBAAsBJ,gBAAgBK,IAAIH,MAAM;IAEpD,IACE,CAACE,uBACDA,oBAAoB7C,MAAM4C,gBAAgB5C,KAC1C6C,oBAAoB5C,MAAM2C,gBAAgB3C,KAC1C4C,oBAAoBxC,UAAUuC,gBAAgBvC,SAC9CwC,oBAAoBvC,WAAWsC,gBAAgBtC,QAC/C;KACA,IAAI,CAACuC,qBAAqB;MACxBA,sBAAsB;OACpB7C,GAAG4C,gBAAgB5C;OACnBC,GAAG2C,gBAAgB3C;OACnBI,OAAOuC,gBAAgBvC;OACvBC,QAAQsC,gBAAgBtC;OACzB;MACDmC,gBAAgBnB,IAAIqB,OAAOE,oBAAoB;YAC1C;MACLA,oBAAoB7C,IAAI4C,gBAAgB5C;MACxC6C,oBAAoB5C,IAAI2C,gBAAgB3C;MACxC4C,oBAAoBxC,QAAQuC,gBAAgBvC;MAC5CwC,oBAAoBvC,SAASsC,gBAAgBtC;;KAG/CJ,yBACEyC,OACAP,OACAA,MAAM7B,SACN6B,MAAMJ,kBAAkB,UACxBY,gBACD;;;IAGL;GAGR,CAAC;CAED,OAAAG,gBACGnD,WAASoD,WAAKX,MAAI,EAAA,IAAA9C,WAAA;EAAA,OAAAwD,gBAChBvD,OAAK;GAAA,IAACyD,OAAI;IAAA,OAAEX,iBAAiBY,SAAS;;GAAA3D,WACnCoD,OAAOQ,UAAU;IACjB,OAAAJ,gBACGnD,WAAS;KACRwD,OAAO,4BAA4BD;KAAOE,MACpCC,OAAO;MACXf,kBAAkBgB,IAAID,GAAG;MACzB7D,gBAAgB;OACd8C,kBAAkBiB,OAAOF,GAAG;QAC5B;;KACH,IAAA/D,WAAA;MAAA,OAEAoD,OAAO;;KAAA,CAAA;;GAGb,CAAA;IAAA,CAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"smooth-damp.js","names":[],"sources":["../../src/utils/smooth-damp.ts"],"sourcesContent":["import type { Accessor } from \"solid-js\";\nimport { createSignal } from \"solid-js\";\nimport { createMutable } from \"solid-js/store\";\n\nimport { onTick } from \"../on-tick\";\n\n/**\n * Smoothly dampens a value towards a target over time.\n * This is similar to Unity's Mathf.SmoothDamp function.\n *\n * @param current - The current value.\n * @param target - The target value.\n * @param velocity - A reference to the current velocity. This should be persistent between calls.\n * @param smoothTimeMs - The approximate time it will take to reach the target in milliseconds. Smaller values will reach the target faster.\n * @param maxSpeed - Optionally, the maximum speed the value can move in units per second. Defaults to Infinity.\n * @param deltaTime - The time since the last call in seconds. Defaults to 1/60 (assuming 60 FPS).\n * @param precision - Optionally, the threshold for snapping the value to the target. If the absolute difference between the current and target value is less than this, it snaps to the target. Defaults to 0.01.\n * @returns The new current value.\n */\nexport const smoothDamp = (\n current: number,\n target: number,\n velocity: { value: number },\n smoothTimeMs: number = 300,\n maxSpeed: number = Infinity,\n deltaTime: number = 1 / 60,\n precision: number = 0.01, // Added precision parameter with a default\n): number => {\n if (current === target) return current;\n\n // Check precision and velocity before doing calculations\n if (Math.abs(current - target) < precision && Math.abs(velocity.value) < precision) {\n velocity.value = 0; // Reset velocity\n return target; // Snap to target and return early\n }\n\n const smoothTime = smoothTimeMs / 1000; // Convert smoothTimeMs to seconds\n const omega = 2 / smoothTime;\n const x = omega * deltaTime;\n const exp = 1 / (1 + x + 0.48 * x * x + 0.235 * x * x * x);\n const change = current - target;\n const temp = (velocity.value + omega * change) * deltaTime;\n velocity.value = (velocity.value - omega * temp) * exp;\n\n let result = target + (change + temp) * exp;\n\n // Clamp to max speed\n if (maxSpeed !== Infinity) {\n const maxChange = maxSpeed * deltaTime;\n result = current + Math.max(-maxChange, Math.min(maxChange, result - current));\n }\n\n return result;\n};\n\n/**\n * A SolidJS hook that provides a smoothly damped signal towards a target value.\n * Internally manages velocity and continuous updates synced to the Pixi ticker.\n *\n * @param to - An accessor for the target value to damp towards.\n * @param smoothTimeMs - The approximate time it will take to reach the target in milliseconds. Smaller values will reach the target faster. Defaults to 300ms.\n * @param maxSpeed - Optionally, the maximum speed the value can move in units per second. Defaults to Infinity.\n * @returns A signal containing the current damped value.\n */\n\nexport type UseSmoothDampProps = {\n to: () => number;\n smoothTimeMs?: () => number;\n maxSpeed?: () => number;\n};\n\nexport type SmoothDamp = {\n value: Accessor<number>;\n velocity: Accessor<number>;\n};\n\nexport const useSmoothDamp = (props: UseSmoothDampProps): SmoothDamp => {\n const [current, setCurrent] = createSignal(props.to());\n const velocity = createMutable({ value: 0 });\n\n const update = (deltaTimeMS: number) => {\n const currentValue = current();\n const currentTarget = props.to();\n\n if (currentValue === currentTarget) {\n velocity.value = 0;\n return;\n }\n\n const deltaTime = deltaTimeMS / 1000; // Convert milliseconds to seconds\n const newCurrent = smoothDamp(\n currentValue,\n currentTarget,\n velocity,\n props.smoothTimeMs?.(),\n props.maxSpeed?.(),\n deltaTime,\n );\n setCurrent(newCurrent);\n };\n\n onTick((ticker) => {\n update(ticker.deltaMS);\n });\n\n return {\n value: current,\n velocity: () => velocity.value,\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;AAmBA,IAAa,cACX,SACA,QACA,UACA,eAAuB,KACvB,WAAmB,UACnB,YAAoB,IAAI,IACxB,YAAoB,QACT;
|
|
1
|
+
{"version":3,"file":"smooth-damp.js","names":[],"sources":["../../src/utils/smooth-damp.ts"],"sourcesContent":["import type { Accessor } from \"solid-js\";\nimport { createSignal } from \"solid-js\";\nimport { createMutable } from \"solid-js/store\";\n\nimport { onTick } from \"../on-tick\";\n\n/**\n * Smoothly dampens a value towards a target over time.\n * This is similar to Unity's Mathf.SmoothDamp function.\n *\n * @param current - The current value.\n * @param target - The target value.\n * @param velocity - A reference to the current velocity. This should be persistent between calls.\n * @param smoothTimeMs - The approximate time it will take to reach the target in milliseconds. Smaller values will reach the target faster.\n * @param maxSpeed - Optionally, the maximum speed the value can move in units per second. Defaults to Infinity.\n * @param deltaTime - The time since the last call in seconds. Defaults to 1/60 (assuming 60 FPS).\n * @param precision - Optionally, the threshold for snapping the value to the target. If the absolute difference between the current and target value is less than this, it snaps to the target. Defaults to 0.01.\n * @returns The new current value.\n */\nexport const smoothDamp = (\n current: number,\n target: number,\n velocity: { value: number },\n smoothTimeMs: number = 300,\n maxSpeed: number = Infinity,\n deltaTime: number = 1 / 60,\n precision: number = 0.01, // Added precision parameter with a default\n): number => {\n if (current === target) return current;\n\n // Check precision and velocity before doing calculations\n if (Math.abs(current - target) < precision && Math.abs(velocity.value) < precision) {\n velocity.value = 0; // Reset velocity\n return target; // Snap to target and return early\n }\n\n const smoothTime = smoothTimeMs / 1000; // Convert smoothTimeMs to seconds\n const omega = 2 / smoothTime;\n const x = omega * deltaTime;\n const exp = 1 / (1 + x + 0.48 * x * x + 0.235 * x * x * x);\n const change = current - target;\n const temp = (velocity.value + omega * change) * deltaTime;\n velocity.value = (velocity.value - omega * temp) * exp;\n\n let result = target + (change + temp) * exp;\n\n // Clamp to max speed\n if (maxSpeed !== Infinity) {\n const maxChange = maxSpeed * deltaTime;\n result = current + Math.max(-maxChange, Math.min(maxChange, result - current));\n }\n\n return result;\n};\n\n/**\n * A SolidJS hook that provides a smoothly damped signal towards a target value.\n * Internally manages velocity and continuous updates synced to the Pixi ticker.\n *\n * @param to - An accessor for the target value to damp towards.\n * @param smoothTimeMs - The approximate time it will take to reach the target in milliseconds. Smaller values will reach the target faster. Defaults to 300ms.\n * @param maxSpeed - Optionally, the maximum speed the value can move in units per second. Defaults to Infinity.\n * @returns A signal containing the current damped value.\n */\n\nexport type UseSmoothDampProps = {\n to: () => number;\n smoothTimeMs?: () => number;\n maxSpeed?: () => number;\n};\n\nexport type SmoothDamp = {\n value: Accessor<number>;\n velocity: Accessor<number>;\n};\n\nexport const useSmoothDamp = (props: UseSmoothDampProps): SmoothDamp => {\n const [current, setCurrent] = createSignal(props.to());\n const velocity = createMutable({ value: 0 });\n\n const update = (deltaTimeMS: number) => {\n const currentValue = current();\n const currentTarget = props.to();\n\n if (currentValue === currentTarget) {\n velocity.value = 0;\n return;\n }\n\n const deltaTime = deltaTimeMS / 1000; // Convert milliseconds to seconds\n const newCurrent = smoothDamp(\n currentValue,\n currentTarget,\n velocity,\n props.smoothTimeMs?.(),\n props.maxSpeed?.(),\n deltaTime,\n );\n setCurrent(newCurrent);\n };\n\n onTick((ticker) => {\n update(ticker.deltaMS);\n });\n\n return {\n value: current,\n velocity: () => velocity.value,\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;AAmBA,IAAa,cACX,SACA,QACA,UACA,eAAuB,KACvB,WAAmB,UACnB,YAAoB,IAAI,IACxB,YAAoB,QACT;CACX,IAAI,YAAY,QAAQ,OAAO;CAG/B,IAAI,KAAK,IAAI,UAAU,OAAO,GAAG,aAAa,KAAK,IAAI,SAAS,MAAM,GAAG,WAAW;EAClF,SAAS,QAAQ;EACjB,OAAO;;CAIT,MAAM,QAAQ,KADK,eAAe;CAElC,MAAM,IAAI,QAAQ;CAClB,MAAM,MAAM,KAAK,IAAI,IAAI,MAAO,IAAI,IAAI,OAAQ,IAAI,IAAI;CACxD,MAAM,SAAS,UAAU;CACzB,MAAM,QAAQ,SAAS,QAAQ,QAAQ,UAAU;CACjD,SAAS,SAAS,SAAS,QAAQ,QAAQ,QAAQ;CAEnD,IAAI,SAAS,UAAU,SAAS,QAAQ;CAGxC,IAAI,aAAa,UAAU;EACzB,MAAM,YAAY,WAAW;EAC7B,SAAS,UAAU,KAAK,IAAI,CAAC,WAAW,KAAK,IAAI,WAAW,SAAS,QAAQ,CAAC;;CAGhF,OAAO;;AAwBT,IAAa,iBAAiB,UAA0C;CACtE,MAAM,CAAC,SAAS,cAAc,aAAa,MAAM,IAAI,CAAC;CACtD,MAAM,WAAW,cAAc,EAAE,OAAO,GAAG,CAAC;CAE5C,MAAM,UAAU,gBAAwB;EACtC,MAAM,eAAe,SAAS;EAC9B,MAAM,gBAAgB,MAAM,IAAI;EAEhC,IAAI,iBAAiB,eAAe;GAClC,SAAS,QAAQ;GACjB;;EAGF,MAAM,YAAY,cAAc;EAShC,WARmB,WACjB,cACA,eACA,UACA,MAAM,gBAAgB,EACtB,MAAM,YAAY,EAClB,UAES,CAAW;;CAGxB,QAAQ,WAAW;EACjB,OAAO,OAAO,QAAQ;GACtB;CAEF,OAAO;EACL,OAAO;EACP,gBAAgB,SAAS;EAC1B"}
|
package/dist/utils/spring.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spring.js","names":[],"sources":["../../src/utils/spring.ts"],"sourcesContent":["import type { Accessor } from \"solid-js\";\nimport { createSignal } from \"solid-js\";\n\nimport { onTick } from \"../on-tick\";\n\n/**\n * @typedef {Object} UseSpringProps\n * @property {Accessor<number>} to - An accessor for the target value for the spring.\n * @property {Accessor<number>} [stiffness=10] - Effective range from 0 - 100. Controls the spring's resistance to displacement.\n * @property {Accessor<number>} [damping=30] - Effective range from 0 - 100. Controls the amount of friction or resistance to motion.\n * @property {Accessor<number>} [mass=20] - Effective range from 0 - 100. Controls the inertia of the spring.\n */\nexport type UseSpringProps = {\n to: () => number;\n stiffness?: () => number;\n damping?: () => number;\n mass?: () => number;\n};\n\nexport type Spring = {\n value: Accessor<number>;\n velocity: Accessor<number>;\n};\n\n/**\n * A SolidJS hook that provides a spring-animated signal towards a target value.\n * Internally manages the spring physics and continuous updates synced to the Pixi ticker.\n *\n * @param {UseSpringProps} props - The properties for the spring animation.\n * @returns {Accessor<number>} A signal containing the current spring-animated value.\n */\nexport const useSpring = (props: UseSpringProps): Spring => {\n const [value, setValue] = createSignal(props.to());\n const [velocity, setVelocity] = createSignal(0);\n\n const update = (deltaTimeMS: number) => {\n const targetInput = props.to();\n const currentValue = value();\n const currentVelocity = velocity();\n\n if (targetInput === currentValue) return;\n\n // Settling condition: if output is very close to input and velocity is negligible,\n // snap to input and stop calculations.\n if (Math.abs(currentVelocity) < 0.1 && Math.abs(currentValue - targetInput) < 0.01) {\n setVelocity(0);\n setValue(targetInput);\n return;\n }\n\n const deltaTime = deltaTimeMS / 1000; // Convert milliseconds to seconds\n\n // Get current spring properties, using defaults if not provided\n const stiffness = percentToValueBetweenRange(props.stiffness?.() ?? 10, -1, -300);\n const damping = percentToValueBetweenRange(props.damping?.() ?? 30, -0.4, -20);\n const mass = percentToValueBetweenRange(props.mass?.() ?? 20, 0.1, 10);\n\n const springX = stiffness * (currentValue - targetInput);\n const damperX = damping * currentVelocity;\n const amplitude = (springX + damperX) / mass;\n\n setVelocity((prev) => prev + amplitude * deltaTime);\n setValue(currentValue + currentVelocity * deltaTime);\n };\n\n onTick((ticker) => {\n update(ticker.deltaMS);\n });\n\n return { value, velocity };\n};\n\n// Helper to convert 0-100 percent range to internal calculation range\nconst percentToValueBetweenRange = (percent: number, min: number, max: number) =>\n (percent * (max - min)) / 100 + min;\n"],"mappings":";;;;;;;;;;AA+BA,IAAa,aAAa,UAAkC;CAC1D,MAAM,CAAC,OAAO,YAAY,aAAa,MAAM,IAAI,CAAC;CAClD,MAAM,CAAC,UAAU,eAAe,aAAa,EAAE;CAE/C,MAAM,UAAU,gBAAwB;EACtC,MAAM,cAAc,MAAM,IAAI;EAC9B,MAAM,eAAe,OAAO;EAC5B,MAAM,kBAAkB,UAAU;
|
|
1
|
+
{"version":3,"file":"spring.js","names":[],"sources":["../../src/utils/spring.ts"],"sourcesContent":["import type { Accessor } from \"solid-js\";\nimport { createSignal } from \"solid-js\";\n\nimport { onTick } from \"../on-tick\";\n\n/**\n * @typedef {Object} UseSpringProps\n * @property {Accessor<number>} to - An accessor for the target value for the spring.\n * @property {Accessor<number>} [stiffness=10] - Effective range from 0 - 100. Controls the spring's resistance to displacement.\n * @property {Accessor<number>} [damping=30] - Effective range from 0 - 100. Controls the amount of friction or resistance to motion.\n * @property {Accessor<number>} [mass=20] - Effective range from 0 - 100. Controls the inertia of the spring.\n */\nexport type UseSpringProps = {\n to: () => number;\n stiffness?: () => number;\n damping?: () => number;\n mass?: () => number;\n};\n\nexport type Spring = {\n value: Accessor<number>;\n velocity: Accessor<number>;\n};\n\n/**\n * A SolidJS hook that provides a spring-animated signal towards a target value.\n * Internally manages the spring physics and continuous updates synced to the Pixi ticker.\n *\n * @param {UseSpringProps} props - The properties for the spring animation.\n * @returns {Accessor<number>} A signal containing the current spring-animated value.\n */\nexport const useSpring = (props: UseSpringProps): Spring => {\n const [value, setValue] = createSignal(props.to());\n const [velocity, setVelocity] = createSignal(0);\n\n const update = (deltaTimeMS: number) => {\n const targetInput = props.to();\n const currentValue = value();\n const currentVelocity = velocity();\n\n if (targetInput === currentValue) return;\n\n // Settling condition: if output is very close to input and velocity is negligible,\n // snap to input and stop calculations.\n if (Math.abs(currentVelocity) < 0.1 && Math.abs(currentValue - targetInput) < 0.01) {\n setVelocity(0);\n setValue(targetInput);\n return;\n }\n\n const deltaTime = deltaTimeMS / 1000; // Convert milliseconds to seconds\n\n // Get current spring properties, using defaults if not provided\n const stiffness = percentToValueBetweenRange(props.stiffness?.() ?? 10, -1, -300);\n const damping = percentToValueBetweenRange(props.damping?.() ?? 30, -0.4, -20);\n const mass = percentToValueBetweenRange(props.mass?.() ?? 20, 0.1, 10);\n\n const springX = stiffness * (currentValue - targetInput);\n const damperX = damping * currentVelocity;\n const amplitude = (springX + damperX) / mass;\n\n setVelocity((prev) => prev + amplitude * deltaTime);\n setValue(currentValue + currentVelocity * deltaTime);\n };\n\n onTick((ticker) => {\n update(ticker.deltaMS);\n });\n\n return { value, velocity };\n};\n\n// Helper to convert 0-100 percent range to internal calculation range\nconst percentToValueBetweenRange = (percent: number, min: number, max: number) =>\n (percent * (max - min)) / 100 + min;\n"],"mappings":";;;;;;;;;;AA+BA,IAAa,aAAa,UAAkC;CAC1D,MAAM,CAAC,OAAO,YAAY,aAAa,MAAM,IAAI,CAAC;CAClD,MAAM,CAAC,UAAU,eAAe,aAAa,EAAE;CAE/C,MAAM,UAAU,gBAAwB;EACtC,MAAM,cAAc,MAAM,IAAI;EAC9B,MAAM,eAAe,OAAO;EAC5B,MAAM,kBAAkB,UAAU;EAElC,IAAI,gBAAgB,cAAc;EAIlC,IAAI,KAAK,IAAI,gBAAgB,GAAG,MAAO,KAAK,IAAI,eAAe,YAAY,GAAG,KAAM;GAClF,YAAY,EAAE;GACd,SAAS,YAAY;GACrB;;EAGF,MAAM,YAAY,cAAc;EAGhC,MAAM,YAAY,2BAA2B,MAAM,aAAa,IAAI,IAAI,IAAI,KAAK;EACjF,MAAM,UAAU,2BAA2B,MAAM,WAAW,IAAI,IAAI,KAAM,IAAI;EAC9E,MAAM,OAAO,2BAA2B,MAAM,QAAQ,IAAI,IAAI,IAAK,GAAG;EAItE,MAAM,aAFU,aAAa,eAAe,eAC5B,UAAU,mBACc;EAExC,aAAa,SAAS,OAAO,YAAY,UAAU;EACnD,SAAS,eAAe,kBAAkB,UAAU;;CAGtD,QAAQ,WAAW;EACjB,OAAO,OAAO,QAAQ;GACtB;CAEF,OAAO;EAAE;EAAO;EAAU;;AAI5B,IAAM,8BAA8B,SAAiB,KAAa,QAC/D,WAAW,MAAM,OAAQ,MAAM"}
|
package/package.json
CHANGED
package/dist/delay.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"delay.js","names":[],"sources":["../src/delay.ts"],"sourcesContent":["import type * as Pixi from \"pixi.js\";\nimport { useContext } from \"solid-js\";\n\nimport { TickerContext } from \"./pixi-application\";\n\n/**\n * Runs a callback when a given number of milliseconds has passed on the ticker.\n *\n * It is guaranteed to be in sync with the shared ticker and uses accumulated deltaMs not an external time measurement.\n *\n * @param delayMs - Number of milliseconds to wait (measured in the ticker's time units).\n *\n * @param callback - A callback function that will fire when the delayMs time has passed.\n *\n * @throws {Error} If called outside of a `PixiApplicationProvider` or `TickerProvider` context.\n *\n * @note It will not run the callback if the ticker is paused or stopped.\n *\n */\nexport const delay = (delayMs: number, callback?: () => void): void => {\n const ticker = useContext(TickerContext);\n if (!ticker) {\n throw new Error(\"`delay` must be used within a PixiApplicationProvider or a TickerProvider.\");\n }\n\n let timeDelayed = 0;\n\n const internalCallback = () => {\n timeDelayed += ticker.deltaMS;\n if (timeDelayed < delayMs) return;\n callback?.();\n ticker.remove(internalCallback);\n };\n\n ticker.add(internalCallback);\n};\n\nconst asyncDelay = async (ticker: Pixi.Ticker, delayMs: number, signal?: AbortSignal) => {\n let timeDelayed = 0;\n let resolvePromise: (value: void | PromiseLike<void>) => void;\n\n const promise = new Promise<void>((resolve) => {\n resolvePromise = resolve;\n });\n\n const internalCallback = () => {\n timeDelayed += ticker.deltaMS;\n if (timeDelayed < delayMs) return;\n resolvePromise();\n };\n\n const handleAbort = () => {\n ticker.remove(internalCallback);\n resolvePromise();\n };\n\n if (signal?.aborted) {\n // Already aborted before we even started\n return;\n }\n\n signal?.addEventListener(\"abort\", handleAbort);\n\n ticker.add(internalCallback);\n await promise;\n ticker.remove(internalCallback);\n signal?.removeEventListener(\"abort\", handleAbort);\n};\n\n/**\n * Create a delay function that waits until a given number of milliseconds has passed on the current Ticker context before resolving.\n *\n * This function must be called inside a `PixiApplicationProvider` or `TickerProvider` context.\n *\n * @param signal - Optional AbortSignal to resolve the delay early\n * @returns An async function we can await to delay events in sync with time passed on the Ticker.\n *\n * Simply await for it to resolve in an async context. If the signal aborts, the promise resolves immediately.\n *\n * @note It will not resolve if the ticker is paused or stopped.\n *\n * @throws {Error} If called outside of a `PixiApplicationProvider` or `TickerProvider` context.\n */\nexport const createAsyncDelay = (): ((delayMs: number, signal?: AbortSignal) => Promise<void>) => {\n const ticker = useContext(TickerContext);\n\n if (!ticker) {\n throw new Error(\n \"`createAsyncDelay` must be used within a PixiApplicationProvider or a TickerProvider. The returned delay function can be called in an async context but `createAsyncDelay` must be called in a synchronous scope within a PixiApplicationProvider or a TickerProvider\",\n );\n }\n const delayWithTicker = (delayMs: number, signal?: AbortSignal) =>\n asyncDelay(ticker, delayMs, signal);\n\n return delayWithTicker;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;AAmBA,IAAa,SAAS,SAAiB,aAAgC;CACrE,MAAM,SAAS,WAAW,cAAc;AACxC,KAAI,CAAC,OACH,OAAM,IAAI,MAAM,6EAA6E;CAG/F,IAAI,cAAc;CAElB,MAAM,yBAAyB;AAC7B,iBAAe,OAAO;AACtB,MAAI,cAAc,QAAS;AAC3B,cAAY;AACZ,SAAO,OAAO,iBAAiB;;AAGjC,QAAO,IAAI,iBAAiB;;AAG9B,IAAM,aAAa,OAAO,QAAqB,SAAiB,WAAyB;CACvF,IAAI,cAAc;CAClB,IAAI;CAEJ,MAAM,UAAU,IAAI,SAAe,YAAY;AAC7C,mBAAiB;GACjB;CAEF,MAAM,yBAAyB;AAC7B,iBAAe,OAAO;AACtB,MAAI,cAAc,QAAS;AAC3B,kBAAgB;;CAGlB,MAAM,oBAAoB;AACxB,SAAO,OAAO,iBAAiB;AAC/B,kBAAgB;;AAGlB,KAAI,QAAQ,QAEV;AAGF,SAAQ,iBAAiB,SAAS,YAAY;AAE9C,QAAO,IAAI,iBAAiB;AAC5B,OAAM;AACN,QAAO,OAAO,iBAAiB;AAC/B,SAAQ,oBAAoB,SAAS,YAAY;;;;;;;;;;;;;;;;AAiBnD,IAAa,yBAAqF;CAChG,MAAM,SAAS,WAAW,cAAc;AAExC,KAAI,CAAC,OACH,OAAM,IAAI,MACR,wQACD;CAEH,MAAM,mBAAmB,SAAiB,WACxC,WAAW,QAAQ,SAAS,OAAO;AAErC,QAAO"}
|
|
File without changes
|