--- url: /concepts/animation.md --- # Animation CanvasEngine provides powerful tools for creating animations. At the core of the animation system are `animatedSignal` and `animatedSequence`. ## `animatedSignal` An `animatedSignal` is a special type of signal whose changes can be animated over time. It's built on top of the reactive system and integrates with `popmotion` for the animation logic. ### Creation You create an `animatedSignal` by providing an initial value and optional animation options: ```html ``` ### Updating Value You can update the value of an `animatedSignal` in two ways: 1. **`set(newValue, options?)`**: This method animates the signal from its current value to `newValue`. It returns a Promise that resolves when the animation is complete. You can optionally provide animation options specific to this transition. ```html ``` 2. **`update(updaterFn)`**: This method takes a function that receives the current value and should return the new value. The transition to the new value will be animated using the default or previously set animation options for the signal. ```html ``` ### Accessing Value To get the current value of an `animatedSignal`, you call it as a function: ```html ``` ### Animation State Each `animatedSignal` has an `animatedState` property. This is a `WritableSignal` that holds an object with the following properties: * `current`: The current value of the signal during an animation. * `start`: The value at the beginning of the current or last animation. * `end`: The target value of the current or last animation. You can subscribe to this state to react to changes during an animation: ```html ``` ### Example ```html ``` ## `animatedSequence` The `animatedSequence` function allows you to orchestrate multiple animations, running them sequentially or in parallel. This is particularly useful for creating complex animation timelines. ### How it Works `animatedSequence` takes an array as its argument. Each element in this array can be either: 1. A function that returns a `Promise` (typically an `animatedSignal.set()` call). These functions are executed one after another (sequentially). 2. An array of such promise-returning functions. All functions within this inner array are executed simultaneously (in parallel). The sequence will only proceed to the next step once all promises in the parallel block have resolved. ### Usage ```html ``` ### Key Features: * **Sequential Execution**: Animations in the main array are performed one by one. * **Parallel Execution**: Animations within a nested array are performed concurrently. * **Promise-based**: It leverages Promises to manage the timing and completion of animations. The `animatedSequence` function itself returns a Promise that resolves when the entire sequence is finished. This structure provides a flexible way to define intricate animation chains. --- --- url: /presets/bar.md --- # Bar ## Usage ```html ``` ## Props | Prop | Type | Required | Default | Description | |------|------|----------|---------|-------------| | backgroundColor | string | No | '#333333' | Background color of the bar | | foregroundColor | string | No | '#ffffff' | Color of the progress bar | | value | number | Yes | - | Current value of the progress bar | | maxValue | number | Yes | - | Maximum value of the progress bar | | width | number | Yes | - | Width of the bar in pixels | | height | number | Yes | - | Height of the bar in pixels | --- --- url: /components/button.md --- # Button The Button component provides an interactive button with visual feedback for different states (normal, hover, pressed, disabled). It supports both sprite-based and graphics-based rendering approaches. ## Basic Usage ```html ``` ### Button with Multiple Elements ```html ``` When `children` are provided, they take priority over the `text` property. ## Custom Background You can provide a custom background component: ```html ``` ```` ## TypeScript Types ```typescript interface ButtonStyle { backgroundColor?: { normal?: string; hover?: string; pressed?: string; disabled?: string; }; border?: { color?: string; width?: number; radius?: number; }; text?: { color?: string; fontSize?: number; fontFamily?: string; }; textures?: { normal?: string; hover?: string; pressed?: string; disabled?: string; }; } interface ButtonProps { text?: string; disabled?: boolean; click?: (event: FederatedPointerEvent) => void; hoverEnter?: (event: FederatedPointerEvent) => void; hoverLeave?: (event: FederatedPointerEvent) => void; pressDown?: (event: FederatedPointerEvent) => void; pressUp?: (event: FederatedPointerEvent) => void; style?: ButtonStyle; width?: number; height?: number; x?: number; y?: number; alpha?: number; visible?: boolean; cursor?: string; controls?: ControlsDirective | JoystickControls; controlName?: string; shape?: 'rect' | 'circle' | 'ellipse'; background?: Element | ComponentFunction; children?: Element[]; } ```` --- --- url: /components/canvas.md --- # Canvas Component `Canvas` is the root component of a CanvasEngine scene. Use it once at the top of your application component to create the PixiJS application and host every canvas-rendered child component. ## Minimal example ```html ``` The start component passed to `bootstrapCanvas` must begin with `Canvas`. ## Layout example `Canvas` can also receive layout props, which makes it useful for HUDs, menus, and centered game screens. ```html ``` ## Options You can use CanvasEngine display and layout props, plus renderer options supported by PixiJS. ::: tip Use `Canvas` for the scene root. Use `Container` to group or lay out content inside the scene. ::: --- --- url: /concepts/child-component.md --- # Child Component A child component is a component that is defined inside another component. `child.ce` ```html ``` `parent.ce` ```html ``` ## Input props You can define input props for a child component. `child.ce` ```html ``` In this example, the `title` prop is passed to the `Text` component. > Not need to import `defineProps` in the child component. Use in component parent: `parent.ce` ```html ``` ::: tip Note that retrieved properties, **even static ones**, are transformed into signals and you must read them into the child as signals. Example: `title()` ::: ## Emits Use `defineEmits()` when a child component needs to send an event to its parent. `child.ce` ```html ``` `parent.ce` ```html ``` > Not need to import `defineEmits` in the child component. ::: tip callbacks compatibility Classic function props in `defineProps()` are still supported for compatibility, but `defineEmits()` is recommended for child-to-parent events. ::: ::: tip If you don't want to set the default values, just do: ```html ``` ::: --- --- url: /concepts/slot.md --- # Children Components Slots In CanvasEngine, you can access child components that are passed to a parent component. ```html ``` How to access the children components in the `Child` component? ## Basic Usage In the `Child` component, you can access the children components using the `defineProps()` function. ```html ``` Children are accessible as an array, where `children[0]` is the first child, `children[1]` is the second child, etc. ## Multiple Children You can pass multiple children to a component: ```html @for (child of children) { } ``` ## Dynamic Child Switching You can dynamically switch between children using signals. You can also use the `attach` prop to attach a child to a container. ```html ``` This pattern is useful for creating dynamic interfaces where you need to swap components based on certain conditions or user interactions. --- --- url: /advanced/conditional-rendering.md --- # Conditional Rendering The `cond()` function allows you to conditionally render elements based on reactive signals or static boolean values. It supports if/else if/else patterns for complex conditional logic. ## Basic Usage ### Simple Condition ```typescript import { cond, signal, h, Text } from 'canvasengine'; const isVisible = signal(true); const conditionalText = cond( isVisible, () => h(Text, { text: 'I am visible!' }) ); ``` ### With Else ```typescript const conditionalText = cond( isVisible, () => h(Text, { text: 'Visible' }), () => h(Text, { text: 'Hidden' }) // else case ); ``` ## Advanced Usage ### Multiple Conditions (else if) ```typescript const status = signal('loading'); const statusDisplay = cond( () => status() === 'loading', () => h(Text, { text: 'Loading...', color: 'yellow' }), [() => status() === 'error', () => h(Text, { text: 'Error!', color: 'red' })], // else if [() => status() === 'success', () => h(Text, { text: 'Success!', color: 'green' })], // else if () => h(Text, { text: 'Unknown status', color: 'gray' }) // else ); ``` ### Grade System Example ```typescript const score = signal(85); const gradeDisplay = cond( () => score() >= 90, () => h(Text, { text: 'A+', color: 'gold' }), [() => score() >= 80, () => h(Text, { text: 'A', color: 'green' })], [() => score() >= 70, () => h(Text, { text: 'B', color: 'blue' })], [() => score() >= 60, () => h(Text, { text: 'C', color: 'orange' })], () => h(Text, { text: 'F', color: 'red' }) // else ); ``` ## Condition Types The `cond()` function accepts three types of conditions: 1. **Signals**: Reactive values that trigger re-evaluation when changed 2. **Static booleans**: Simple true/false values 3. **Functions**: Functions that return boolean values (automatically converted to computed signals) ### Examples ```typescript // Signal condition const showElement = signal(true); cond(showElement, () => h(Text, { text: 'Signal condition' })); // Static boolean condition cond(true, () => h(Text, { text: 'Static condition' })); // Function condition (reactive) const user = signal({ role: 'admin' }); cond( () => user().role === 'admin', () => h(Text, { text: 'Admin panel' }) ); ``` ## Reactivity All conditions are reactive. When any signal used in the conditions changes, the `cond()` function automatically re-evaluates and updates the rendered element: ```typescript const userRole = signal('guest'); const navigation = cond( () => userRole() === 'admin', () => h(Container, { children: [ h(Text, { text: 'Admin Dashboard' }), h(Text, { text: 'User Management' }), h(Text, { text: 'Settings' }) ]}), [() => userRole() === 'user', () => h(Container, { children: [ h(Text, { text: 'Dashboard' }), h(Text, { text: 'Profile' }) ]})], () => h(Text, { text: 'Please log in' }) // guest ); // Changing the role will automatically update the UI userRole.set('admin'); // Shows admin navigation userRole.set('user'); // Shows user navigation userRole.set('guest'); // Shows login message ``` ## Performance * **Lazy evaluation**: Only the matching condition's element is created * **Automatic cleanup**: Previous elements are properly destroyed when conditions change * **Optimized updates**: Elements are only updated when the matching condition actually changes ## Best Practices 1. **Order matters**: Conditions are evaluated in order, the first `true` condition wins 2. **Use functions for complex logic**: Convert complex boolean expressions to functions for better reactivity 3. **Provide fallbacks**: Always consider adding an `else` case for unexpected states 4. **Keep conditions simple**: Complex logic should be extracted to computed signals or functions ```typescript // Good: Simple, readable conditions const theme = signal('dark'); cond( () => theme() === 'dark', () => h(Text, { text: 'Dark mode', color: 'white' }), () => h(Text, { text: 'Light mode', color: 'black' }) ); // Better: Extract complex logic const isDarkMode = computed(() => { const currentTheme = theme(); const userPreference = getUserPreference(); const systemPreference = getSystemPreference(); return currentTheme === 'dark' || (currentTheme === 'auto' && (userPreference === 'dark' || systemPreference === 'dark')); }); cond( isDarkMode, () => h(Text, { text: 'Dark mode', color: 'white' }), () => h(Text, { text: 'Light mode', color: 'black' }) ); ``` --- --- url: /api/context.md --- # Context The context is an object that is automatically provided to all components in the component tree. It contains shared resources and utilities that are available throughout your application. ## Available Properties The context object contains the following properties: | Name | Type | Description | |------|------|-------------| | `app` | `() => Application \| null` | Function that returns the PixiJS Application instance. Returns `null` until the canvas is rendered. | | `canvasSize` | `Signal<{ width: number, height: number }>` | Signal containing the current width and height of the canvas. Updates automatically when the canvas is resized. | | `globalLoader` | `GlobalAssetLoader` | Global asset loader instance that tracks loading progress of all assets across the component tree. See [GlobalAssetLoader documentation](/components/sprite.html#global-asset-loader) for more details. | | `tick` | `Signal` | Signal containing the ticker information. Updates on each frame with timing and frame data. See [Tick interface](#tick-interface) below. | | `rootElement` | `Element` | The root Canvas element. See [Element documentation](./element.md) for more details. | ## Tick Interface The `tick` signal contains the following properties: | Property | Type | Description | |----------|------|-------------| | `timestamp` | `number` | Current timestamp in milliseconds | | `deltaTime` | `number` | Time elapsed since the last frame in milliseconds | | `frame` | `number` | Current frame number | | `deltaRatio` | `number` | Ratio of deltaTime to the target frame time (useful for frame-independent animations) | ## Accessing Context You can access the context through the `element.props.context` property in any component: ```html ``` ## Examples ### Using Canvas Size for Responsive Layouts ```html ``` ### Tracking Asset Loading Progress ```html ``` ### Using Tick for Frame-Independent Animations ```html ``` ### Accessing PixiJS Application ```html ``` --- --- url: /concepts/dependencies.md --- # Dependencies The `dependencies` prop allows you to delay component mounting until all specified dependencies are ready (not `undefined`). This is useful for scenarios where a component needs to wait for asynchronous data loading or reactive signals to become available before rendering. ## Overview When you provide a `dependencies` prop to a component, the component will not mount until all dependencies are defined. Dependencies can be: * **Signals**: Reactive signals that may start as `undefined` and become defined later * **Promises**: Async operations that resolve to a value (must not resolve to `undefined`) * **Direct values**: Any value that is not `undefined` ## Basic Usage ### With Signal Dependencies ```html ``` In this example, the `Container` and its children will not mount until `userData` becomes defined. The `mount` hook will only be called after the signal is set to a value. ### With Promise Dependencies ```html ``` The component will wait for the promise to resolve before mounting. If the promise resolves to `undefined`, the component will not mount. ### Mixed Dependencies You can combine signals and promises: ```html ``` The component will mount only when both the signal becomes defined AND the promise resolves to a non-undefined value. ## Using with h() Function When using CanvasEngine without the compiler, you can pass dependencies using the `h()` function: ```typescript import { h, signal, Container, Text } from 'canvasengine'; const userData = signal(undefined); // Later... userData.set({ name: 'Alice' }); const component = h(Container, { dependencies: [userData] }, h(Text, { text: 'User loaded!' }) ); ``` ## Behavior * **Immediate mounting**: If all dependencies are already defined when the component is created, it mounts immediately * **Delayed mounting**: If any dependency is `undefined`, the component waits and subscribes to signal changes * **Reactive updates**: For signal dependencies, the component automatically subscribes and mounts when all signals become defined * **Promise handling**: Promise dependencies are awaited, and the component mounts if the resolved value is not `undefined` * **No dependencies**: If the `dependencies` prop is not provided, the component mounts normally ## Use Cases ### Loading Game Assets ```html ``` ### Waiting for User Authentication ```html ``` ### Conditional Component Rendering ```html ``` ## Important Notes * A dependency is considered "ready" when its value is **not** `undefined` * The value `null` is considered ready (only `undefined` blocks mounting) * All dependencies must be ready simultaneously for the component to mount * Once mounted, the component will not unmount if dependencies become `undefined` again * The `mount` hook is only called after all dependencies are ready --- --- url: /components/dom-container.md --- # DOMContainer Component The `DOMContainer` component provides a bridge between the canvas rendering system and traditional DOM manipulation. It allows you to render standard DOM elements within your canvas application while maintaining proper transform hierarchy and visibility. This component is especially useful for rendering form elements like ``, `