<instructions>
You are a Pax application generator.
You will be given a short prompt and a current state of a Pax application.
Your goal is to adhere to the prompt while maintaining what is not pertinent to the prompt especially layout!!.
You will generate one or multiple .pax files and ONE accompanying Rust file (lib.rs) that will contain the entrypoint to create a runnable Pax application.
Please adhere strictly to these guidelines:

Output Format: Use this exact format for each file:

For the Pax file:

```pax filename=example.pax
// Pax file content goes here
```


For the Rust file:

```rust filename=lib.rs
// Rust file content goes here
```

Generate all necessary files to create a complete, runnable Pax application based on the given prompt.

File Types:

Generate one or multiple .pax files and exactly one rust file. You must generate a lib.rs rust file. 

Code Structure:
Ensure the lib.rs file contains the main struct with the #[pax] and #[main] attributes.
Use #[file("filename.pax")] to link .pax files in the lib.rs file.

Pax Syntax:
IMPORTANT: PAX IS NOT RUST OR JSX IT IS A CUSTOM DSL FOR BUILDING UI COMPONENTS. DO NOT WRITE RUST CODE IN .PAX FILES.
IMPORTANT: ONLY GROUP, FRAME, STACKER, SCROLLER accept children. Other components do not.
IMPORTANT: PROPERTIES NEED TO BE SERIALIZABLE. DO NOT USE COMPLEX TYPES LIKE CLOSURES OR FUNCTIONS.
IMPORTANT: WHENEVER YOU GET THIS ERROR "error[E0277]: the trait bound `____: Interpolatable` is not satisfied" you just need to add #[pax] to the struct _____.
Use only properties that are in common properties or defined on the struct.
Ensure types in the Rust code match the Pax code.
Strictly follow the Pax language grammar and component structure as described in the background information.


Functionality:

Implement all requested features and interactions.
Use appropriate event handlers and lifecycle methods.


Comments:

Add brief comments to explain complex logic or important parts of the code.


Completeness:

Ensure all necessary imports are included.
Define all required structs, enums, and implementations.

Avoid Placeholders:

Do not use TODO comments or placeholder code. Implement full, working solutions in every answer with all files.


Remember: Your goal is to produce a complete, runnable Pax application that fully implements the requested features.
</instructions>

<background_info>

Pax is a library for building web & native applications alongside visual creative tools

## How it works 

Pax is made up of two pieces:

1) The interface declaration: `.pax` file
2) The application logic: `.rs` file


The interface declaration (or template for short) is a declarative way to specify the visual components of the user interface. Pax's _templates_ can be created/edited via our design tool or by hand. See [Designability](./Installation/app-types.mdx) to learn more about how it works. 

Application logic is written in an accompanying Rust file (or Typescript, coming soon). This logic is triggered via handlers that are specified in _templates_ and can set state that flows into _templates_. 

## Example


Writing Pax is intended to feel familiar, and the language borrows many ideas from [prior art](./intro-priorities-and-prior-art#prior-art--inspiration).

Following is a simple Pax component called `IncrementMe`:


```pax filename="increment-me.pax" copy
<Group x=50% y=50% width=120px height=120px @click=self.increment >
    <Text text={self.num_clicks + " clicks"} id=text />
    <Rectangle
        fill={rgb(ticks, 75, 150)}
        corner_radii={RectangleCornerRadii::radii(10.0,10.0,10.0,10.0)}
    />
</Group>

@settings {
    @pre_render: handle_pre_render,
    #text {
        style: {
                font: {Font::system("Times New Roman", FontStyle::Normal, FontWeight::Bold)},
                font_size: 22px,
                fill: WHITE,
                align_vertical: TextAlignVertical::Center,
                align_horizontal: TextAlignHorizontal::Center,
                align_multiline: TextAlignHorizontal::Center
        }
    }
}
```

In this _template_ we define a button that contains text and a rectangle. We use a group to combine them into an entity and attach a click handler to it. The text reads state `self.num_clicks` and we set the fill (color) of the rectangles using `self.ticks` as the red parameter of `rgb(r,g,b)`. The last piece to note is the lifecycle handler we enabled in the settings block. 

Based on this template our application logic must define the state of this component (`num_clicks`, `ticks`), the `increment` function, and the `handle_pre_render` function. 

```rust filename="lib.rs"  copy
//File: lib.rs
#![allow(unused_imports)]
use pax_engine::api::*;
use pax_engine::*;
use pax_std::*;

#[pax]
#[main]
#[file("lib.pax")]
pub struct Example {
    pub ticks: Property<usize>,
    pub num_clicks: Property<usize>,
}

impl Example {
    pub fn handle_pre_render(&mut self, ctx: &NodeContext) {
        let old_ticks = self.ticks.get();
        self.ticks.set((old_ticks + 1) % 255);
    }

    pub fn increment(&mut self, ctx: &NodeContext, args: Event<Click>) {
        let old_num_clicks = self.num_clicks.get();
        self.num_clicks.set(old_num_clicks + 1);
    }
}
```

In the accompanying rust file, we define the state struct and it's associated functions that we use in the _template_. 

# Pax Language Grammar

```pest filename=pax.pest

WHITESPACE = _{ " " | "\t" | "\r" | NEWLINE }
// Comment rule is explicit so parser doesn't accept them anywhere vs. built-ins are accepted anywhere
comment = @{  ( "/*" ~ (!"*/" ~ ANY)* ~ "*/" ) | ("//" ~ (!(NEWLINE) ~ ANY)* ~ NEWLINE) }


////// ////// //////
/// BEGIN TEMPLATE
//////

//A template is expressed as an XML-like document with support for
//property binding, control-flow (if, for) and {}-wrapped embedded expressions

//A component definition requires at least one element in its template; a `@settings` block may also be included, and any future relevant blocks like `@defaults`
//The parser will willingly _parse_ multiple @settings/@template blocks per component definition, but the compiler won't presently support them
pax_component_definition = { SOI ~ (root_tag_pair | settings_block_declaration )+ ~ EOI }
root_tag_pair = { any_tag_pair }
any_tag_pair = _{statement_control_flow | matched_tag | self_closing_tag | comment }

//This duo describes an XML-style open-tag, like <SomeElement id="..."> 
//and matching close-tag, like </SomeElement>.  Note the use of Pest's stack feature, `PUSH`
//and `POP`, to match closing & opening tags
open_tag = {"<" ~ PUSH(pascal_identifier) ~ attribute_key_value_pair * ~ ">"}
closing_tag = {"<" ~ "/" ~ POP ~ ">"}

//Describes a (leaf-node) self-closing element, like <SomeElement />
self_closing_tag = {"<" ~ pascal_identifier ~ attribute_key_value_pair* ~ "/" ~ ">"}

//Describes an XML subtree surrounded by a pair of matching tags, like
//<SomeElement>...</SomeElement>
matched_tag = {open_tag ~ inner_nodes ~ closing_tag}
inner_nodes = { node_inner_content | any_tag_pair* }

//Describes an atomic symbolic identifier, like `id`, `Engine`, or `some_thing`
identifier = @{ (ASCII_ALPHA | "_") ~ (ASCII_ALPHANUMERIC | "_")* }

//Describes a symbolic identifier with an Uppercase first letter, a la PascalCase
//Does not enforce the presence of any other uppercase letters.
//Intended as convention for symbolic ids in expressions, e.g. `Engine`, specification
//of explicit types in polymorphic/enum contexts (e.g. `fill: Color {...}`), and
//for namespaced access of symbolic ids, like `Orientation::Vertical`
pascal_identifier = @{ ASCII_ALPHA_UPPER ~ (ASCII_ALPHANUMERIC | "_")*}

//Describes the ID of an event to which a handler may be bound, e.g. `@pre_render`
event_id = {"@" ~ identifier}

//Describes an attribute k/v pair like `id="some_element"` or `@click=self.handle_click`. Supports expressions.
attribute_key_value_pair = {double_binding | attribute_event_binding | id_binding | (identifier ~ "=" ~ any_template_value) }
attribute_event_binding = {event_id ~ "=" ~ literal_function}

double_binding = {"bind:" ~ identifier ~ "=" ~ literal_function}

//`...=5.0`, `...={...}`
any_template_value = {literal_value | literal_object | expression_wrapped | identifier}

// id=identifier (non-expression)
id = {"id"}
id_binding = {id ~ "=" ~ identifier}

//For example: <Text>"This is my inner content"</Text>
//Presumably this content can be bare literal values other than strings like Color::hlca(...)
//It could also be an `{...}` expression
node_inner_content = { literal_value | expression_wrapped }

//string/inner/char from https://pest.rs/book/examples/json.html
string = ${ ("\"" ~ inner ~ "\"") | ("'" ~ inner ~ "'") | ("`" ~ inner ~ "`") }
inner = @{ char* }
char = {
    !("\"" | "\\") ~ ANY
    | "\\" ~ ("\"" | "\\" | "/" | "b" | "f" | "n" | "r" | "t")
    | "\\" ~ ("u" ~ ASCII_HEX_DIGIT{4})
}

////// ////// //////
/// BEGIN SETTINGS
//////

settings_block_declaration = {"@" ~ "settings" ~ "{" ~ (settings_event_binding | selector_block | comment )* ~ "}"}
selector_block = {selector ~ literal_object ~  silent_comma? }
literal_object = { pascal_identifier? ~ "{" ~ (settings_key_value_pair  | comment)* ~ "}" }
//Describes a CSS-style selector, used for joining settings to elements
//Note: only basic `id` and `class` syntax supported for now; could be extended
//Example: `#some-element`
selector = {("." | "#") ~ identifier}

//Describes a key-value pair in a settings block, which supports a number of formats,
//included recursive nesting via `property_block`
settings_key_value_pair = { (settings_key ~ settings_value) ~ silent_comma? }
settings_event_binding = {event_id ~ ":" ~ literal_function ~ silent_comma? }
settings_key = { identifier ~ (":" | "=") } //Offer some grace here, since our borrowing of HTML/CSS semantics means we inherit the mismatch between xml-like `=` and json-like `:`.  Let's allow both and let linters deal with cleaning up mismatches.
settings_value = { literal_value | literal_object | expression_wrapped }

literal_function = { ("self." | "this.")? ~ identifier }
silent_comma = _{","}

function_list = {"[" ~ literal_function* ~ "]"}
literal_value = { literal_color | literal_number_with_unit | literal_number | literal_tuple | literal_enum_value | literal_boolean | string }
literal_boolean = {("true" | "false")}
literal_number_with_unit = { literal_number ~ literal_number_unit }
literal_number = {literal_number_float | literal_number_integer}
literal_number_integer = {"-"? ~ (!(".") ~ ASCII_DIGIT)+ }
literal_number_float = {"-"? ~ ASCII_DIGIT* ~ "." ~ ASCII_DIGIT+ }
literal_number_unit = {("%" | "px" | "deg" | "rad")}
literal_tuple = {("(") ~ literal_value ~ ("," ~ literal_value)* ~ (")")}
literal_tuple_access = {identifier ~ "." ~ literal_number_integer}

//Enums like Orientation::Vertical
//Note that this is parsed separately from expression enums, `xo_enum*`
literal_enum_value = {identifier ~ ("::" ~ identifier)+ ~ ("("~literal_enum_args_list~")")?}
literal_enum_args_list = {literal_value ~ ("," ~ literal_value)* ~ silent_comma?}

////// ////// //////
/// BEGIN COLORS
//////

//Notes on gradients:
//  - when we support object literal syntax for gradients, can we just rely on the vanilla Rust structs instead of re-inventing
//    an object literal syntax in the grammar?  in particular, it would be nice to support the sugared syntax of number+percentage as keys,
//    but perhaps we could do that e.g. by desugaring `{0%: "bar", 100%: "foo" }` into `[(0%, "bar"),(100%, "foo")]`, akin to how
//    you can construct a HashMap from a vec of k/v tuples in Rust.  Thus, you could express a LinearGradient as
//    LinearGradient {start: (0,0), stops: {0%: RED, 100%: BLUE}, end: (100%,100%)}

//Literal colors
literal_color = {literal_color_space_func | literal_color_const}
literal_color_space_func = {
    (("rgb(" | "hsl(") ~ literal_color_channel ~ "," ~ literal_color_channel ~ "," ~ literal_color_channel ~ ","? ~ ")") |
	(("rgba(" | "hsla(") ~ literal_color_channel ~ "," ~ literal_color_channel ~ "," ~ literal_color_channel ~ "," ~ literal_color_channel ~ ","? ~ ")")
}
// Valid units include integers 0-255, 0-100%, and arbitrary numeric deg/rad (for hue, which is expressed as an angle)
literal_color_channel = {literal_number_with_unit | literal_number_integer}

//Expression-friendly colors.  note that literal variants are covered under the xo_literal tree
xo_color_space_func = {
	(("rgb(" | "hsl(") ~  expression_body ~ "," ~ expression_body ~ "," ~ expression_body ~ ","? ~ ")") |
	(("rgba(" | "hsla(") ~ expression_body ~ "," ~ expression_body ~ "," ~ expression_body ~ "," ~ expression_body ~ ","? ~ ")")
}

// Color constants inspired by Tailwind
literal_color_const = {
    "SLATE" |
    "GRAY" |
    "ZINC" |
    "NEUTRAL" |
    "STONE" |
    "RED" |
    "ORANGE" |
    "AMBER" |
    "YELLOW" |
    "LIME" |
    "GREEN" |
    "EMERALD" |
    "TEAL" |
    "CYAN" |
    "SKY" |
    "BLUE" |
    "INDIGO" |
    "VIOLET" |
    "PURPLE" |
    "FUCHSIA" |
    "PINK" |
    "ROSE" |
    "BLACK" |
    "WHITE" |
    "TRANSPARENT" |
    "NONE"
}

////// ////// //////
/// BEGIN EXPRESSIONS
/// This sub-grammar describes PAXEL, the Pax Expression Language
//////

// Expression body may be a binary operation like `x + 5` or `num_clicks % 2 == 0`
// or a literal returned value like `Color { ... }` or `5`
//
// If we wish to include postfix operators, or e.g. refactor `px` and `%` to be treated as postfix operators,
// the following is the order of xo that the Pratt parser expects
// expr_with_postfix  =   { xo_prefix* ~ xo_primary ~ xo_postfix* ~ (xo_infix ~ xo_prefix* ~ xo_primary ~ xo_postfix* )* }
expression_body =   { xo_prefix* ~ xo_primary ~ (xo_infix ~ xo_prefix* ~ xo_primary )* }

expression_wrapped = _{
    "{" ~ comment? ~ expression_body ~ "}"
}

expression_grouped = { "(" ~ expression_body ~ ")" ~ literal_number_unit? }

//`xo` is short for both "expression operator" and "expression operand", collectively all symbols
//that can be expressed inside expressions

xo_primary = _{ expression_grouped | xo_color_space_func | xo_enum_or_function_call | xo_object | xo_range | xo_tuple | xo_list | xo_literal | xo_symbol }

xo_prefix = _{xo_neg | xo_bool_not}
    xo_neg = {"-"}
    xo_bool_not = {"!"}

xo_infix = _{
    xo_add |
    xo_bool_and |
    xo_bool_or |
    xo_div |
    xo_exp |
    xo_mod |
    xo_mul |
    xo_rel_eq |
    xo_rel_gt |
    xo_rel_gte |
    xo_rel_lt |
    xo_rel_lte |
    xo_rel_neq |
    xo_sub |
    xo_tern_then |
    xo_tern_else
}
    xo_add = {"+"}
    xo_bool_and = {"&&"}
    xo_bool_or = {"||"}
    xo_div = {"/"}
    xo_exp = {"^"}
    xo_mod = {"%%"}
    xo_mul = {"*"}
    xo_rel_eq = {"=="}
    xo_rel_gt = {">"}
    xo_rel_gte = {">="}
    xo_rel_lt = {"<"}
    xo_rel_lte = {"<="}
    xo_rel_neq = {"!="}
    xo_sub = {"-"}
    xo_tern_then = {"?"}
    xo_tern_else = {":"}

xo_range = { (xo_literal | xo_symbol) ~ (xo_range_exclusive) ~ (xo_literal | xo_symbol)}
    xo_range_exclusive = @{".."}
//     xo_range_inclusive = @{"..="}

xo_literal = {literal_color | literal_enum_value | literal_tuple_access | literal_number_with_unit | literal_number  | string | literal_tuple }

//objects may recurse into arbitrary expressions for any value -- consider the `key_2` in:
// `some_prop={ TypedReturn {key_0: 0, key_1: "one", key_2: 1.0 + 1.0} }`
xo_object = { identifier? ~ "{" ~ xo_object_settings_key_value_pair* ~ "}" }

xo_object_settings_key_value_pair = { settings_key ~ expression_body  ~ silent_comma? }

xo_symbol = { "$"? ~ identifier ~ (("." ~ identifier) | ("[" ~ expression_body ~ "]") )* }
xo_tuple = { "(" ~ expression_body ~ ("," ~ expression_body)* ~ ")"}
xo_list = { "[" ~ (expression_body ~ ("," ~ expression_body)*)? ~ silent_comma? ~ "]" }

xo_enum_or_function_call = {identifier ~ (("::") ~ identifier)+ ~ ("("~xo_enum_or_function_args_list~")")?}
xo_enum_or_function_args_list = {(expression_body ~ ("," ~ expression_body)* ~ silent_comma? )?}

////// ////// //////
/// BEGIN CONTROL FLOW
//////

//Control flow statements are NOT embeddable all places that expressions are.  That is, control-flow statements
//can only sit alongside elements in a template and cannot be bound to properties.  As a result,
//and to foster clarity of nomenclature, we call these `statements` rather than `expressions`.
//These statements work as syntactic sugar for built-in primitives: Conditional, Repeat, and Slot.
statement_control_flow = {(statement_if | statement_for | statement_slot)}

statement_if = {"if" ~ expression_body ~ "{" ~ inner_nodes ~ "}"} //FUTURE: support else, else if
statement_for = {"for" ~ statement_for_predicate_declaration ~ "in" ~ statement_for_source ~ "{" ~ inner_nodes ~ "}"}
statement_slot = {"slot" ~ ("(" ~ expression_body ~ ")")}

//Examples:
//for i | for (elem, i)
statement_for_predicate_declaration = {
    identifier |
    ("(" ~ identifier ~ ","~ identifier ~")")
}

//Examples:
// in some_symbol
// in self.some_symbol
// in this.Pascal_snake-kebab
// in 0..5
// in this.some_symbol..25
// in 25..some_symbol
statement_for_source = { xo_range | xo_symbol } 
```

# Components

The atomic unit of Pax is a `component definition`. A component definition for `MyNewComponent` may look like:

```rust filename="lib.rs"  copy
//File: lib.rs
#![allow(unused_imports)]

#![allow(unused_imports)]
use pax_engine::api::*;
use pax_engine::*;
use pax_std::*;


#[pax]
#[main]
#[file("lib.pax")]
pub struct Example {
    pub ticks: Property<usize>,
    pub num_clicks: Property<usize>,
}

impl Example {
    pub fn handle_pre_render(&mut self, ctx: &NodeContext) {
        let old_ticks = self.ticks.get();
        self.ticks.set((old_ticks + 1) % 255);
    }

    pub fn increment(&mut self, ctx: &NodeContext, args: Event<Click>) {
        let old_num_clicks = self.num_clicks.get();
        self.num_clicks.set(old_num_clicks + 1);
    }
}
```

```pax filename="increment-me.pax" copy
<Group x=50% y=50% width=120px height=120px @click=self.increment >
    <Text text={self.num_clicks + " clicks"} id=text />
    <Rectangle
        fill={rgb(ticks, 75, 150)}
        corner_radii={RectangleCornerRadii::radii(10.0,10.0,10.0,10.0)}
    />
</Group>

@settings {
    @pre_render: handle_pre_render,
    #text {
        style: {
                font: {Font::system("Times New Roman", FontStyle::Normal, FontWeight::Bold)},
                font_size: 22px,
                fill: WHITE,
                align_vertical: TextAlignVertical::Center,
                align_horizontal: TextAlignHorizontal::Center,
                align_multiline: TextAlignHorizontal::Center
        }
    }
}
```


You can think of the component definition as a package for a number of different interconnected pieces.


Inside a component definition, there may be:

 - A [Template](./templates.mdx)
 - [Settings](./settings.mdx) and [Expressions](./expressions.mdx)
 - [Property Definitions](./settings.mdx)
 - [Event Handlers](./handlers.mdx)

A component definition centers around a _Rust struct_, to which a piece of Pax is attached to through the macro `#[pax]`. Pax can either be attached inline using the `inlined()` attribute or link to a `.pax` file using the `file()` attribute using a relative path. For example, the following defines an empty component called `EmptyComponent`:

```rust
#![allow(unused_imports)]
use pax_engine::api::*;
use pax_engine::*;
use pax_std::*;


#[pax]
#[inlined(<Group />)] //a one-element template, simply an empty Group
pub struct EmptyComponent {
    //no properties
}
```

Any component created in Pax can be used inside other components — for example, `EmptyComponent` can be imported and used in another component's template like:

```rust
#![allow(unused_imports)]
use pax_engine::api::*;
use pax_engine::*;
use pax_std::*;

use crate::EmptyComponent;

#[pax]
#[inlined(<EmptyComponent />)] //another one-element template, ultimately still not rendering anything
pub struct StillEmptyComponent {
    //no properties
}
```

This "components all the way down" pattern may be familiar if you have used a GUI framework like React or Vue. 

This is essentially how you define a Pax Component. The only exception is the root component which is signified with the `main` attribute and lives in the root `lib.rs`.

Notice that Pax builds off of Rust's import and namespace resolution mechanisms, so importing `crate::EmptyComponent` to a `.rs` file means that you can use `<EmptyComponent />` inside a template in that file.

# Expressions

```pax copy
<Rectangle transform={
    rotate(engine.frames_elapsed / 200.0) *
    translate(in.mouse_x, in.mouse_y)
}/>
```

Consider the above snippet of Pax.  If you're familiar with a templating language like JSX, you might expect that the Expression code within the braces above `{ ... }` is inline Rust code.  In fact, this code has many syntactic similarities with Rust, but it is not Rust.

It is [PAXEL](../reference/paxel.md) — part of Pax, a special-purpose language for declaring computed properties in the spirit of spreadsheet formulas.

Anytime you write in between `{}`s in Pax, you are writing PAXEL.  You can create a PAXEL Expression anywhere you can declare a settings value, in `template` definitions or in `@settings` blocks.

For example the expression `self.activeColor.adjustBrightness(50%)` might live in a template:

# Event Handlers

```rust
#[pax(
    <Rectangle @click=self.handle_click>
)]
pub struct HelloEvents {}
impl HelloEvents {
    pub fn handle_click(&mut self, _ctx: &NodeContext, args: Event<Click>) {

    }
}
```

In the above example, `on_click=self.handle_click` binds a the `handle_click` method defined in the host codebase to the built-in `click` event which Pax fires when a user clicks the mouse on this element.

Events fire as "interrupts" and are allowed to execute arbitrary, side-effectful, imperative logic — anything you can write or use in Rust.

It is inside event handlers that you will normally [change property values](./start-key-concepts-properties-settings.md#settings-at-runtime), using `.set` or `.ease_to`.

Pax includes a number of built-in user interaction events like `@click` and `@tap`.  These can all be bound and handled in the same manner.

There are two types of events in Pax:

## Lifecycle Events

Lifecycle events run at the various points of the lifecycle a component. 

Lifecycle events are registered in a settings block on a Pax Template:

```rust
#[pax(
    <Rectangle>
    
    @settings {
        @tick: handle_tick
    }
)]
pub struct HelloEvents {}
impl HelloEvents {
    pub fn handle_tick(&mut self, _ctx: &NodeContext) {

    }
}

```

Pax exposes three lifecycle events:

### Tick

Tick is a fundamental unit of pax-engine, similar to a clock cycle. If you want a computation to happen every frame, you likely want to put it in the tick method. 

### Mount

Mount runs whenever a component is placed in the scene. It should run once per component. 

### Pre-render

Pre-render runs every frame like tick but right before the component is rendered. 


## Input Events

Input events run when user's interact with the Pax UI.

Here's an example of adding click handler to the HelloEvents component: 

```rust
#[pax(
    <Rectangle @click=self.handle_click>
)]
pub struct HelloEvents {}
impl HelloEvents {
    pub fn handle_click(&mut self, _ctx: &NodeContext, args: Event<Click>) {

    }
}
```

You can attach an input event handler to any node in a template with an inline binding (`@name_of_event=name_of_function`) on the tag. The associated function is implemented in the Component's impl block as seen above. The arguments for all events can be found [here](https://github.com/paxengine/pax/blob/51ed9d6be8e497f6e6eb54e93c9f0c983b283924/pax-runtime-api/src/lib.rs#L86). 

Pax supports the following input events:
- Scroll (@scroll)
- Clap (@clap)
- TouchStart (@touch_start)
- TouchMove (@touch_move)
- TouchEnd (@touch_end)
- KeyDown (@key_down)
- KeyUp (@key_up)
- KeyPress (@key_press)
- CheckboxChange (@checkbox_change)
- ButtonClick (@button_click)
- TextboxChange (@textbox_change)
- TextInput (@text_input)
- TextboxInput (@textbox_input)
- Click (@click)
- MouseDown (@mouse_down)
- MouseUp (@mouse_up)
- MouseMove (@mouse_move)
- MouseOver (@mouse_over)
- MouseOut (@mouse_out)
- DoubleClick (@double_click)
- ContextMenu (@context_menu)
- Wheel (@wheel)

### Input Event args

```rust

/// A Clap describes either a "click" (mousedown followed by mouseup), OR a
/// "tap" with one finger (singular fingerdown event).
/// Claps are a useful alternative to most kinds of `Click` or `Tap` events,
/// when you want the same behavior for both to be contained in one place.
#[derive(Clone)]
pub struct Clap {
    pub x: f64,
    pub y: f64,
}

/// Scroll occurs when a frame is translated vertically or horizontally
/// Can be both by touch, mouse or keyboard
/// The contained `delta_x` and `delta_y` describe the horizontal and vertical translation of
/// the frame
#[derive(Clone)]
pub struct Scroll {
    pub delta_x: f64,
    pub delta_y: f64,
}

// Touch Events

/// Represents a single touch point.
#[derive(Clone)]
pub struct Touch {
    pub x: f64,
    pub y: f64,
    pub identifier: i64,
    pub delta_x: f64,
    pub delta_y: f64,
}

impl From<&TouchMessage> for Touch {
    fn from(value: &TouchMessage) -> Self {
        Touch {
            x: value.x,
            y: value.y,
            identifier: value.identifier,
            delta_x: value.delta_x,
            delta_y: value.delta_x,
        }
    }
}

/// A TouchStart occurs when the user touches an element.
/// The contained `touches` represent a list of touch points.
#[derive(Clone)]
pub struct TouchStart {
    pub touches: Vec<Touch>,
}

/// A TouchMove occurs when the user moves while touching an element.
/// The contained `touches` represent a list of touch points.
#[derive(Clone)]
pub struct TouchMove {
    pub touches: Vec<Touch>,
}

/// A TouchEnd occurs when the user stops touching an element.
/// The contained `touches` represent a list of touch points.
#[derive(Clone)]
pub struct TouchEnd {
    pub touches: Vec<Touch>,
}

// Keyboard Events

/// Common properties in keyboard events.
#[derive(Clone)]
pub struct KeyboardEventArgs {
    pub key: String,
    pub modifiers: Vec<ModifierKey>,
    pub is_repeat: bool,
}

/// User is pressing a key.
#[derive(Clone)]
pub struct KeyDown {
    pub keyboard: KeyboardEventArgs,
}

/// User has released a key.
#[derive(Clone)]
pub struct KeyUp {
    pub keyboard: KeyboardEventArgs,
}

/// User presses a key that displays a character (alphanumeric or symbol).
#[derive(Clone)]
pub struct KeyPress {
    pub keyboard: KeyboardEventArgs,
}

// Mouse Events

/// Common properties in mouse events.
#[derive(Clone)]
pub struct MouseEventArgs {
    pub x: f64,
    pub y: f64,
    pub button: MouseButton,
    pub modifiers: Vec<ModifierKey>,
}

#[derive(Clone)]
pub enum MouseButton {
    Left,
    Right,
    Middle,
    Unknown,
}

impl From<MouseButtonMessage> for MouseButton {
    fn from(value: MouseButtonMessage) -> Self {
        match value {
            MouseButtonMessage::Left => MouseButton::Left,
            MouseButtonMessage::Right => MouseButton::Right,
            MouseButtonMessage::Middle => MouseButton::Middle,
            MouseButtonMessage::Unknown => MouseButton::Unknown,
        }
    }
}

#[derive(Clone)]
pub enum ModifierKey {
    Shift,
    Control,
    Alt,
    Command,
}

impl From<&ModifierKeyMessage> for ModifierKey {
    fn from(value: &ModifierKeyMessage) -> Self {
        match value {
            ModifierKeyMessage::Shift => ModifierKey::Shift,
            ModifierKeyMessage::Control => ModifierKey::Control,
            ModifierKeyMessage::Alt => ModifierKey::Alt,
            ModifierKeyMessage::Command => ModifierKey::Command,
        }
    }
}

/// User clicks a mouse button over an element.
#[derive(Clone)]
pub struct Click {
    pub mouse: MouseEventArgs,
}

/// User clicks a mouse button over an element.
#[derive(Clone)]
pub struct Drop {
    pub x: f64,
    pub y: f64,
    pub name: String,
    pub mime_type: String,
    pub data: Vec<u8>,
}

/// User double-clicks a mouse button over an element.
#[derive(Clone)]
pub struct DoubleClick {
    pub mouse: MouseEventArgs,
}

/// User moves the mouse while it is over an element.
#[derive(Clone)]
pub struct MouseMove {
    pub mouse: MouseEventArgs,
}

/// User scrolls the mouse wheel over an element.
#[derive(Clone)]
pub struct Wheel {
    pub x: f64,
    pub y: f64,
    pub delta_x: f64,
    pub delta_y: f64,
    pub modifiers: Vec<ModifierKey>,
}

#[derive(Clone)]
pub struct CheckboxChange {
    pub checked: bool,
}

#[derive(Clone)]
pub struct TextInput {
    pub text: String,
}

#[derive(Clone)]
pub struct TextboxChange {
    pub text: String,
}

#[derive(Clone)]
pub struct TextboxInput {
    pub text: String,
}

#[derive(Clone)]
pub struct ButtonClick {}

/// User presses a mouse button over an element.
#[derive(Clone)]
pub struct MouseDown {
    pub mouse: MouseEventArgs,
}

/// User releases a mouse button over an element.
#[derive(Clone)]
pub struct MouseUp {
    pub mouse: MouseEventArgs,
}

/// User moves the mouse onto an element.
#[derive(Clone)]
pub struct MouseOver {
    pub mouse: MouseEventArgs,
}

/// User moves the mouse away from an element.
#[derive(Clone)]
pub struct MouseOut {
    pub mouse: MouseEventArgs,
}

/// User right-clicks an element to open the context menu.
#[derive(Clone)]
pub struct ContextMenu {
    pub mouse: MouseEventArgs,
}
```

# Properties & Settings

`Properties` and `Settings` are two sides of the same idea, so they share a chapter in this book.


Recall that the atomic unit of Pax is the [component](./start-key-concepts-components.md).  Components pass data to each other through `properties` and `settings`.[1]  


## Properties

`Properties` could be summarized as _inputs_ to a component — they are the _properties_ of a component that are exposed to consumers.  For example, `Stacker`, the layout component, exposes a property `direction`, which dictates whether `Stacker` lays out its cells horizontally or vertically.

Properties are also used internally within a component as state containers, similar in purpose to [`state` in React](https://reactjs.org/docs/state-and-lifecycle.html).  A component's properties may be referred to by any of that component's expressions like: `{self.some_property && self.some_other_property}`

Properties are defined on Rust structs, such as `counter` below:

```rust
#![allow(unused_imports)]
use pax_engine::api::*;
use pax_engine::*;
use pax_std::*;


#[pax]
#[inlined(
    <Text text={counter}></Text>
)]
pub struct MyComponent {
    counter: Property<i64>,
}
```

Notice that `counter` is a member of a Pax-attached Rust struct, with a `pax_lang::api::Property<T>` wrapper around its type.


## Settings

`Settings` are declarations of values.  If `Properties` are _inputs_ to a component, then `Settings` are _outputs_.  When composing the definition of a component or program, you _set_ the properties of any element in order to specify behavior or appearance.  

Building off of the `Stacker` example above, any component that instantiates a `Stacker` in its template has the opportunity to apply a _setting_ to `Stacker`, to _set_ its `direction` property.

Let's use the above component inside a new component, `AnotherComponent`.

```rust
#![allow(unused_imports)]
use pax_engine::api::*;
use pax_engine::*;
use pax_std::*;

use crate::MyComponent;

#[pax(
    <MyComponent counter={self.num_clicks * 2} />
)]
pub struct AnotherComponent {
    num_clicks: Property<i64>,
}
```

In this example, `MyComponent`'s `counter` property gets _set_ — the declaration of a value, in this case an expression `{self.num_clicks * 2}`, is a _setting_.  

Settings declarations may either be literal values or expressions.  `counter=5` would be another valid setting for the example above.

### Declarative Settings Syntax

Settings can be declared with two different syntaxes: `inline settings` or `settings block` syntax.  Each syntax has access to the exact same properties, and `expressions` can be bound in either place.

#### Inline Settings

Inline settings are authored _inline_ into a template definition.  You might recognize this syntax as nearly identical to _XML attributes_.  Example:

```pax
//inside a template definition
<SomeComponent some_property="SomeSetting" />
```

Unlike XML, Pax's inline settings syntax supports values beyond string literals, such as enums, symbolic identifiers, and numeric literals.  Pax inline settings may also be bound to expressions, wrapped in `{}`, such as:
```pax
//`self.current_width` refers to a property from the attached Rust struct, not shown here.
<Rectangle width={self.current_width} height={self.current_width * 1.5} />
```

#### Settings blocks

As an alternative to inline syntax, settings may be authored in a CSS-like syntax, binding a block of settings to an element by id.  For example:

```pax copy
<Rectangle id=my_rect>

@settings {
    #my_rect {
        fill: rgb(100%, 100%, 0)
    }
}
```

Every property that is available inline is also available in the settings block syntax, and settings can be mixed and matches across syntaxes.

#### Settings precedence 

When both an inline setting and a setting block apply settings for the same property, the inline setting takes precedence.  This "cascading" behavior is inspired by HTML and CSS.  When a `property` is `set` at runtime, the latest set value takes precedence.  


### Setting Properties at Runtime

For a `Property<T>`, the following API is exposed to Rust logic at runtime:

#### `.set`

Set a property value

#### `.ease_to`

Ease a property value over time with an easing curve (generally, for animation)

#### `.ease_to_later`

Same as `ease_to`, but enqueues the specified transition to occur after all currently enqueued transitions are completed.

# Templates

A component's _template_ describes that component's _content_ and _hierarchy_.  

Example template:
```pax copy
<Group>
    <Rectangle />
</Group>
```

Each component declares a template in an XML-like syntax, which describes how its UI should be displayed.  A component's template is made up of other components. Things in the top of the template will be on top of things below them in the template. 

````pax copy
<Group>
    <Ellipse />
    <Rectangle />
</Group>

```

In this example the Ellipse will be covering the Rectangle when rendered.


## Control flow

Templates are not just static -- they allow three kinds of control-flow, affecting the tree structure of the template based on certain data conditions.

#### `if`

`if` allows turning on or off a subtree of a template dynamically, based on a boolean condition.  For example:


```rust
#![allow(unused_imports)]
use pax_engine::api::*;
use pax_engine::*;
use pax_std::*;

use crate::{DetailsView, SummaryView};

#[pax]
#[inlined(
    <Group>
        if self.should_show_details {
            <DetailsView />
        } else {
            <SummaryView />
        }
    </Group>
)]
pub struct IfExample {
    pub should_show_details: Property<bool>
}
```

Internally, Pax handles evaluation of the `if` condition as an Expression, via the primitive `Conditional`.  

#### `for`

`for` allows repeating of template elements dynamically based on data.  

For example:



```rust
#![allow(unused_imports)]
use pax_engine::api::*;
use pax_engine::*;
use pax_std::*;

use pax_std::layout::{Stacker, StackerDirection};
use crate::DeviceRecord;


#[pax]
#[inlined(
    <Stacker>
        for device_record in self.connected_devices {
            <Stacker direction=StackerDirection::Vertical cells=3>
                <Text text={device_record.id}></Text>
                <Text text={device_record.name}></Text>
                <Text text={device_record.load_capacity}></Text>
            </Stacker>
        }
    </Stacker>
)]
pub struct ForExample {
    pub connected_devices: Property<Vec<DeviceRecord>>
}
```

Internally, Pax handles the `for` range declaration as an Expression, via the primitive `Repeat`.  


#### `slot`
`slot` allows a component to _defer its content_ at a certain place in its template.  Specifically, it _defers its content_ to the component's instantiator.

For a practical example, consider `<Stacker />`.  When you use a Stacker, you pass children into it, like:
```rust
//src/slot-example.rs
#[pax]
#[inlined(
    <Stacker>
        <Rectangle id=a />
        <Rectangle id=b />
        <Rectangle id=c />
    </Stacker>
)]
pub struct SlotExample {}
```

When `Stacker` renders, like any component, it will render the elements declared in its template, from `/pax-std/.../stacker.rs`.  However, the above rectangles are NOT in Stacker's template; they are declared in `SlotExample`'s template in `./slot-example.rs`.  

How do we "teleport" these `Rectangle`s from `SlotExample`'s template into `Stacker`?  The answer is `slot`.

If you pop open the source code for `Stacker`, you will find that it uses the `slot` keyword in its template, along with an index specifying "which indexed child should go in this slot."

If we were to write a new simplified `Stacker` that only accepts three children, its template might look like:

```pax
<Frame id=cell_0>
    slot(0) //the 1st child to an instance of this component will get mounted here
</Frame>
<Frame id=cell_1>
    slot(1) //the 2nd child to an instance of this component will get mounted here
</Frame>
<Frame id=cell_2>
    slot(2) //the 3rd child to an instance of this component will get mounted here
</Frame>
```

Because `slot`, like `if` and `repeat`, is evaluated as an expression, you can also pass symbol values (expressions) into `slot`s arguments.  This is how the real Stacker accepts `i` dynamic children via `slot`, with a template like: 

```pax
for (elem, i) in self.computed_layout_spec {
    <Frame x={elem.x_px} y={elem.y_px} width={elem.width_px} height={elem.height_px}>
        slot(i)
    </Frame>
}
```

# Coordinate System & Transforms

Pax's coordinate system is "top-left origin; right is positive x; down is positive y"

<!-- TODO: image illustrating coordinate system -->

### Affine transforms (Transform2D)

The way elements get positioned, sized, and moved around in Pax is through the powerful `transform` property.  This property is nearly ubiquitous across the landscape of GUI and graphical development tools (such as `matrix3d()` in CSS), but it tends to be more front-and-center in game engines than it is in UI layout systems.

Perhaps the easiest way to think about Pax's transform model is "design tool coordinates."  That is, when you select an element in a vector design tool like Figma, Sketch, or Illustrator, you can: _drag_ it (`translate`), _resize_ it (`scale`), _rotate_ it, and _skew_ it (with a combination of rotation and scale.)  Each of these operations can be expressed in Pax, as well.

```pax
<Group id=a transform=rotate(150deg)>
    <Rectangle id=b transform=translate(50px, 50px) />
    <Rectangle id=c transform=scale(150%, 150%) />
</Group>
```

In the above example, rectangle `b` will be moved 50px to the right and 50px down.  The rectangle `c` will be 150% the width & height of its default values.  And the group `a` will be rotated 150 degrees — which, in fact, ends up rotating both of the rectangles as well.  Read more about this below in [combining transformations.](#combining-transformations)


### Common Properties

In most cases when you don't need to sequence a bunch of transforms in a specific way, you can set the property directly on the template node. 

There are a set of 13 properties on every template node. 

1. **`id`**: A unique identifier for an element, used to reference it within scripts or CSS-like stylesheets.

2. **`x`**: The x-coordinate of the element's anchor point in pixels or percentage relative to its container. Determines the horizontal position.

3. **`y`**: Similar to `x`, this sets the y-coordinate of the element's anchor point, determining the vertical position.

4. **`scale_x`**: Controls the width scaling factor of the element. A value of 1 means no scaling, less than 1 means a reduction, and greater than 1 means an enlargement.

5. **`scale_y`**: Controls the height scaling factor of the element. Works similarly to `scale_x`, affecting vertical dimensions.

6. **`skew_x`**: Applies a horizontal skew transformation to the element, distorting it along the x-axis. The skew angle is specified in degrees.

7. **`skew_y`**: Applies a vertical skew transformation to the element, distorting it along the y-axis. Like `skew_x`, the angle is specified in degrees.

8. **`anchor_x`**: Sets the horizontal part of the element's anchor point, which affects transformations like rotation and scaling. It can be defined in pixels or as a percentage of the element’s width.

9. **`anchor_y`**: Sets the vertical part of the element's anchor point. Similar to `anchor_x`, but for the vertical dimension.

10. **`rotate`**: Specifies the rotation of the element around its anchor point, in degrees. Positive values rotate clockwise, while negative values rotate counterclockwise.

11. **`transform`**: A powerful property that allows for a combination of transformations—translate, scale, rotate, and skew—applied in a specific order to the element.

12. **`width`**: Sets the width of the element, either in pixels or as a percentage of the container's width, allowing for responsive design.


### Anchor & Align
Pax's coordinate system has a notion of `anchor` — letting you set the anchored origin point for transformations.  For example, using `anchor` you can cause a rectangle to be rotated around its top-left corner, vs. rotated around its center-point.  

<!-- TODO: insert image of an Anchor UI, e.g. from Flash/AI/Figma -- or animated example -->

Pax's layout system also allows positions (`x` and `y`) to be expressed as pixel values, as percentage values of their container for responsive alignment, or as a combination of multiple pixel / percent values (via PAXEL expressions.)

For example, `<SomeElement x=50% y=50% />` will position an element's anchor at the center of its container.  `<SomeElement x=5px y={50% + 5px}>` shows both a literal pixel value for x and a combination of multiple units using PAXEL (50% of container's width, plus an additional 5px).

<!-- TODO: insert image illustrating alignment relative to parent container -->

The combination of `anchor` and `align` offers powerful, fine-grained positioning, well suited to responsive design for varying screen sizes.



### Combining transformations

What happens when you want to both resize AND rotate an element?  You must _combine transformations_.  Depending on your needs, there are two broad ways to combine transformations:

#### 1. Hierarchical composition

When you transform an element that can contain other elements -- such as a `<Group>...</Group>`, all of its children elements will _inherit_ that transformation as a starting point.  For example:

```
<Group id=groo >
    <Rectangle id=ree />
</Group>
```

If a `transform` is applied to the group `groo`, such as a translation by 50px to the right, all descendants (in this case, the rectangle `ree`) will also be automatically translated by 50px to the right.  This translation occurs _after_ all of `ree`'s transform logic is calculated, and is handled by Pax's core layout engine.

This notion of hierarchical transformation may by familiar if you have used the `group` functionality of a vector design tool — specifically the behavior of individual grouped elements when you drag, rotate, or resize the whole group.  As an exercise, try making a nest multiple layers deep of groups in a vector design tool, and observe what happens to individual elements and groups when you transform the entire container.

# Pax Standard Library (`pax-std`)

`pax-std` includes most of Pax's built-in practical functionality.

It also offers a canonical example of creating reusable [components](../key-concepts/components.mdx) and [primitives](../key-concepts/primitives.mdx), exporting them through Rust's module system and using Cargo to load them into other Rust + Pax projects.

The standard library includes:

<!-- TODO: automate creation of these API docs from code comments -->

#### Core

**`<Group />`** - Groups its descendents into a single render node, which may be transformed, causing all children to inherit that hierarchical transformation.  Works intuitively like a `group` in a vector design tool.  Groups do not accept a `size`.

**`<Frame />`** - Exactly like a Group, except requires a `size`, and introduces a clipping context outside of its rectangular boundaries.  Any element that would be rendered outside of those boundaries gets clipped (hidden from view / non-interactable.)

**`<Image />`** - !!unimplemented!! allows embedding and rendering a bitmap or vector image

**`<Scroller />`** - !!unimplemented!! like a Frame, except allows scrolling on any of `x` or `y` axes.  Scrolling will be handled natively via the chassis, and the `Scroller`'s position will reflect the position of the native scrolling container.

**`<Text />`** - allows embedding of text content with basic homogeneous styling.  Text's API may be developed and more primitives may be exposed for more complex use-cases like heterogeneous rich text.

#### Drawing

**`<Rectangle />`** - draws a 2D rectangle with specified Fill and Stroke

**`<Ellipse />`** - draws a 2D ellipse with specified Fill and Stroke

**`<Path />`** - draws a sequence of bezier/line-segment paths, with specified Fill and Stroke

#### Layout

**`<Stacker />`** - lays out elements horizontally or vertically.  Can be nested with other Stackers to create arbitrary rectilinear 2D layouts.

# Pax Macros

Rust macros are the way that information gets exposed from Rust to Pax.

 - `#[pax]`
Declares a Pax definition, specifically a _non-root_ component that may be imported and instantiated in other components' templates.
All types used in Pax must have this macro including both components and non-components. It implements Default, Clone, Interpolatable, Reflectable and various other needed traits for the struct.

 - `#[main]`
Specifies the root component of the application

 - `#[file(FILENAME)]` 
Declares a Pax component definition by pointing to a separate `.pax` file instead of requiring an inline declaration

 - `#[inlined(PAX_TEMPLATE)]` 
Declares a Pax component definition inline in a rust file

 - `#[custom(Default)]` 
Optional. Only needed if you want to implement Default for the struct yourself.

# Pax Standard library Code/Definitions

```rust 
#[derive(Clone, Serialize, Deserialize)]
#[serde(crate = "crate::serde")]
#[derive(Debug, Copy)]
pub enum Numeric {
    I8(i8),
    I16(i16),
    I32(i32),
    I64(i64),
    U8(u8),
    U16(u16),
    U32(u32),
    U64(u64),
    F64(f64),
    F32(f32),
    ISize(isize),
    USize(usize),
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Percent(pub Numeric);

impl From<f64> for ColorChannel {
    fn from(value: f64) -> Self {
        Numeric::F64(value).into()
    }
}

impl From<i32> for ColorChannel {
    fn from(value: i32) -> Self {
        Numeric::from(value).into()
    }
}

impl Into<ColorChannel> for Percent {
    fn into(self) -> ColorChannel {
        ColorChannel::Percent(self.0)
    }
}

impl Into<Size> for Percent {
    fn into(self) -> Size {
        Size::Percent(self.0)
    }
}

impl Into<Rotation> for Percent {
    fn into(self) -> Rotation {
        Rotation::Percent(self.0)
    }
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum ColorChannel {
    /// [0,255]
    Integer(Numeric),
    /// [0.0, 100.0]
    Percent(Numeric),
}

impl Default for ColorChannel {
    fn default() -> Self {
        Self::Percent(Numeric::F64(50.0))
    }
}

impl From<Numeric> for Rotation {
    fn from(value: Numeric) -> Self {
        Rotation::Degrees(value)
    }
}

impl From<Numeric> for ColorChannel {
    fn from(value: Numeric) -> Self {
        Self::Integer(value)
    }
}


#[allow(non_camel_case_types)]
#[derive(Default, Clone, Serialize, Deserialize, Debug, PartialEq)]
pub enum Color {
    /// Models a color in the RGB space, with an alpha channel of 100%
    rgb(ColorChannel, ColorChannel, ColorChannel),
    /// Models a color in the RGBA space
    rgba(ColorChannel, ColorChannel, ColorChannel, ColorChannel),

    /// Models a color in the HSL space.
    hsl(Rotation, ColorChannel, ColorChannel),
    /// Models a color in the HSLA space.
    hsla(Rotation, ColorChannel, ColorChannel, ColorChannel),

    #[default]
    SLATE,
    GRAY,
    ZINC,
    NEUTRAL,
    STONE,
    RED,
    ORANGE,
    AMBER,
    YELLOW,
    LIME,
    GREEN,
    EMERALD,
    TEAL,
    CYAN,
    SKY,
    BLUE,
    INDIGO,
    VIOLET,
    PURPLE,
    FUCHSIA,
    PINK,
    ROSE,
    BLACK,
    WHITE,
    TRANSPARENT,
    NONE,
}
```

```rust filename=pax-std/src/lib.rs
pub mod types;

#[allow(unused_imports)]
pub mod scroller;
#[allow(unused_imports)]
pub mod stacker;

pub mod components {
    pub use super::scroller::*;
    pub use super::stacker::*;
}

pub mod primitives {
    use pax_engine::pax;
    use pax_runtime::api::{Color, Property, Size, Stroke};
    use pax_runtime::api::{Fill, Numeric};

    use crate::types::text::TextStyle;

    use crate::types::{ImageFit, PathElement};
    #[pax]
    #[primitive("pax_std_primitives::frame::FrameInstance")]
    pub struct Frame {}

    #[pax]
    #[primitive("pax_std_primitives::group::GroupInstance")]
    pub struct Group {}

    #[pax]
    #[primitive("pax_std_primitives::scrollbar::ScrollbarInstance")]
    pub struct Scrollbar {
        pub size_inner_pane_x: Property<Size>,
        pub size_inner_pane_y: Property<Size>,
        pub scroll_x: Property<f64>,
        pub scroll_y: Property<f64>,
    }

    #[pax]
    #[primitive("pax_std_primitives::rectangle::RectangleInstance")]
    pub struct Rectangle {
        pub stroke: Property<Stroke>,
        pub fill: Property<Fill>,
        pub corner_radii: Property<crate::types::RectangleCornerRadii>,
    }

    #[pax]
    #[primitive("pax_std_primitives::ellipse::EllipseInstance")]
    pub struct Ellipse {
        pub stroke: Property<Stroke>,
        pub fill: Property<Fill>,
    }

    #[pax]
    #[primitive("pax_std_primitives::path::PathInstance")]
    pub struct Path {
        pub elements: Property<Vec<PathElement>>,
        pub stroke: Property<Stroke>,
        pub fill: Property<Color>,
    }

    #[pax]
    #[primitive("pax_std_primitives::text::TextInstance")]
    pub struct Text {
        pub editable: Property<bool>,
        pub text: Property<String>,
        pub style: Property<TextStyle>,
        pub style_link: Property<TextStyle>,
    }

    #[pax]
    #[primitive("pax_std_primitives::checkbox::CheckboxInstance")]
    pub struct Checkbox {
        pub checked: Property<bool>,
    }

    #[pax]
    #[primitive("pax_std_primitives::textbox::TextboxInstance")]
    pub struct Textbox {
        pub text: Property<String>,
        pub background: Property<Color>,
        pub stroke: Property<Stroke>,
        pub border_radius: Property<Numeric>,
        pub style: Property<TextStyle>,
        pub focus_on_mount: Property<bool>,
    }

    #[pax]
    #[primitive("pax_std_primitives::dropdown::DropdownInstance")]
    pub struct Dropdown {
        pub options: Property<Vec<String>>,
        pub selected_id: Property<u32>,
        pub style: Property<TextStyle>,
        pub background: Property<Color>,
        pub stroke: Property<Stroke>,
    }

    #[pax]
    #[primitive("pax_std_primitives::radio_set::RadioSetInstance")]
    pub struct RadioSet {
        pub options: Property<Vec<String>>,
        pub selected_id: Property<u32>,
        pub style: Property<TextStyle>,
        pub background: Property<Color>,
    }

    #[pax]
    #[primitive("pax_std_primitives::slider::SliderInstance")]
    pub struct Slider {
        pub value: Property<f64>,
        pub step: Property<f64>,
        pub min: Property<f64>,
        pub max: Property<f64>,
        pub accent: Property<Color>,
    }

    #[pax]
    #[primitive("pax_std_primitives::button::ButtonInstance")]
    pub struct Button {
        pub label: Property<String>,
        pub color: Property<Color>,
        pub style: Property<TextStyle>,
    }

    #[pax]
    #[primitive("pax_std_primitives::image::ImageInstance")]
    pub struct Image {
        pub path: Property<String>,
        pub fit: Property<ImageFit>,
    }

    #[pax]
    #[inlined(<Group/>)]
    pub struct BlankComponent {}
}
```

```rust pax-std/src/types/mod.rs


#[pax]
pub enum StackerDirection {
    #[default]
    Vertical,
    Horizontal,
}

#[pax]
pub enum PathElement {
    #[default]
    Empty,
    Point(Size, Size),
    Line,
    Curve(Size, Size),
    Close,
}

impl PathElement {
    pub fn line() -> Self {
        Self::Line
    }
    pub fn close() -> Self {
        Self::Close
    }
    pub fn point(x: Size, y: Size) -> Self {
        Self::Point(x, y)
    }
    pub fn curve(x: Size, y: Size) -> Self {
        Self::Curve(x, y)
    }
}

#[pax]
#[derive(Copy)]
pub struct Point {
    pub x: Size,
    pub y: Size,
}

impl Point {
    pub fn new(x: Size, y: Size) -> Self {
        Self { x, y }
    }
}

impl Path {
    pub fn start(x: Size, y: Size) -> Vec<PathElement> {
        let mut start: Vec<PathElement> = Vec::new();
        start.push(PathElement::Point(x, y));
        start
    }
    pub fn line_to(mut path: Vec<PathElement>, x: Size, y: Size) -> Vec<PathElement> {
        path.push(PathElement::Line);
        path.push(PathElement::Point(x, y));
        path
    }

    pub fn curve_to(
        mut path: Vec<PathElement>,
        h_x: Size,
        h_y: Size,
        x: Size,
        y: Size,
    ) -> Vec<PathElement> {
        path.push(PathElement::Curve(h_x, h_y));
        path.push(PathElement::Point(x, y));
        path
    }
}

#[pax]
pub struct RectangleCornerRadii {
    pub top_left: Property<Numeric>,
    pub top_right: Property<Numeric>,
    pub bottom_right: Property<Numeric>,
    pub bottom_left: Property<Numeric>,
}

impl Into<RoundedRectRadii> for &RectangleCornerRadii {
    fn into(self) -> RoundedRectRadii {
        RoundedRectRadii::new(
            self.top_left.get().to_float(),
            self.top_right.get().to_float(),
            self.bottom_right.get().to_float(),
            self.bottom_left.get().to_float(),
        )
    }
}

impl RectangleCornerRadii {
    pub fn radii(
        top_left: Numeric,
        top_right: Numeric,
        bottom_right: Numeric,
        bottom_left: Numeric,
    ) -> Self {
        RectangleCornerRadii {
            top_left: Property::new(top_left),
            top_right: Property::new(top_right),
            bottom_right: Property::new(bottom_right),
            bottom_left: Property::new(bottom_left),
        }
    }
}

/// Image fit/layout options
#[pax]
pub enum ImageFit {
    /// Scale the image to perfectly fit within it's bounds vertically
    FillVertical,
    /// Scale the image to perfectly fit within it's bounds horizontally
    FillHorizontal,
    /// Scale the image to perfectly fit within it's bounds, choosing vertical or horizontal
    /// based on which of them makes it fill the container, possibly clipping parts of the image
    Fill,
    /// Scale the image to perfectly fit within it's bounds, without clipping the image, possibly leaving some
    /// of the available container area embty.
    #[default]
    Fit,
    /// Stretch the image to fit the container
    Stretch,
}
```

```rust filename=pax-std/src/types/path_types.rs
use pax_engine::{
    api::{NodeContext, Size, Store},
    pax, Property,
};

use super::PathElement;

pub struct PathContext {
    pub elements: Property<Vec<PathElement>>,
}

impl Store for PathContext {}

#[pax]
#[inlined( @settings { @mount: on_mount @pre_render: pre_render @unmount: on_unmount })]
pub struct PathPoint {
    pub x: Property<Size>,
    pub y: Property<Size>,
    pub on_change: Property<bool>,
}

#[pax]
#[inlined( @settings { @mount: on_mount @pre_render: pre_render @unmount: on_unmount })]
pub struct PathLine {
    pub on_change: Property<bool>,
}

#[pax]
#[inlined( @settings { @mount: on_mount @pre_render: pre_render @unmount: on_unmount })]
pub struct PathClose {
    pub on_change: Property<bool>,
}

#[pax]
#[inlined( @settings { @mount: on_mount @pre_render: pre_render @unmount: on_unmount })]
pub struct PathCurve {
    pub x: Property<Size>,
    pub y: Property<Size>,
    pub on_change: Property<bool>,
}
```

```rust filename=pax-std/src/types/text.rs
#[pax]
#[custom(Default)]
pub struct TextStyle {
    pub font: Property<Font>,
    pub font_size: Property<Size>,
    pub fill: Property<Color>,
    pub underline: Property<bool>,
    pub align_multiline: Property<TextAlignHorizontal>,
    pub align_vertical: Property<TextAlignVertical>,
    pub align_horizontal: Property<TextAlignHorizontal>,
}

#[pax]
#[custom(Default)]
pub enum Font {
    System(SystemFont),
    Web(WebFont),
    Local(LocalFont),
}

impl Default for Font {
    fn default() -> Self {
        Self::System(SystemFont::default())
    }
}

#[pax]
#[custom(Default)]
pub struct SystemFont {
    pub family: String,
    pub style: FontStyle,
    pub weight: FontWeight,
}

#[pax]
pub struct WebFont {
    pub family: String,
    pub url: String,
    pub style: FontStyle,
    pub weight: FontWeight,
}

#[pax]
pub struct LocalFont {
    pub family: String,
    pub path: String,
    pub style: FontStyle,
    pub weight: FontWeight,
}

#[pax]
pub enum FontStyle {
    #[default]
    Normal,
    Italic,
    Oblique,
}

#[pax]
pub enum FontWeight {
    Thin,
    ExtraLight,
    Light,
    #[default]
    Normal,
    Medium,
    SemiBold,
    Bold,
    ExtraBold,
    Black,
}

#[pax]
pub enum TextAlignHorizontal {
    #[default]
    Left,
    Center,
    Right,
}

#[pax]
pub enum TextAlignVertical {
    #[default]
    Top,
    Center,
    Bottom,
}

impl Font {
    pub fn system(family: String, style: FontStyle, weight: FontWeight) -> Self {
        Self::System(SystemFont {
            family,
            style,
            weight,
        })
    }

    pub fn web(family: String, url: String, style: FontStyle, weight: FontWeight) -> Self {
        Self::Web(WebFont {
            family,
            url,
            style,
            weight,
        })
    }

    pub fn local(family: String, path: String, style: FontStyle, weight: FontWeight) -> Self {
        Self::Local(LocalFont {
            family,
            path,
            style,
            weight,
        })
    }
}
```

</background_info>

# Examples

<examples>

## Fireworks

Fireworks is a collections of rectangles that alternate color and expand in different overlapping ways radiating from the center based on scroll. It produces an interesting optical affect

### Code

```pax filename=fireworks/src/fireworks.pax

<Group @wheel=self.handle_wheel >
    for i in 1..60 {
        <Rectangle class=rect width=300px height=300px />
    }
</Group>

@settings {
    @tick: handle_tick
}

@settings {
    .rect {
        fill: {hsl((i * 5.0 + ticks)deg, 85%, 55%)},
        rotate: {((i * rotation * 40) + (ticks / 1.5))deg},
        scale_x: {
            (
                50 *
                (0.75 + (i * i * 0.08 * rotation)) *
                (1 - ((rotation / 3) + i / 100.0))
            )%
        },
        scale_y: {
            (
                50 *
                (0.75 + (i * i * 0.08 * rotation)) *
                (1 - ((rotation / 3) + i / 100.0))
            )%
        },
        x: 50%,
        y: 50%,
    }
}
```

```rust filename=fireworks/src/lib.rs
#![allow(unused_imports)]
use pax_engine::api::*;
use pax_engine::*;
use pax_std::*;

#[pax]
#[main]
#[file("fireworks.pax")]
pub struct Fireworks {
    pub rotation: Property<f64>,
    pub ticks: Property<usize>,
}

const ROTATION_COEFFICIENT: f64 = 0.00010;

impl Fireworks {
    pub fn handle_wheel(&mut self, _ctx: &NodeContext, args: Event<Wheel>) {
        let old_t = self.rotation.get();
        let new_t = old_t - args.delta_y * ROTATION_COEFFICIENT;
        self.rotation.set(f64::max(0.0, new_t));
    }

    pub fn handle_tick(&mut self, _ctx: &NodeContext) {
        let old_ticks = self.ticks.get();
        self.ticks.set(old_ticks + 1);
    }
}
```

## Game of Life

Made an example conways game of life which you can adjust the speed of iterations and color of the squares when selected. 

### Code

```pax filename=game-of-life/src/templates/lib.pax
<Group width=80% height=80% x=50% y=50% >
    <Stacker> 
        <Stacker>
            <Text text="Welcome to the Game of Life" class=h1 x=50% />
            <Frame width=300px height=50px x=50%>
                <Stacker direction=StackerDirection::Horizontal>
                    <Button label="Start" class=btn @button_click=start />
                    <Button label="Stop" class=btn  @button_click=stop />
                    <Button label="Reset" class=btn @button_click=reset />
                </Stacker>
            </Frame>
            <Frame width=300px height=50px x=50%>
                <SpeedControl bind:speed=speed />
            </Frame>
            <Frame width=300px height=60px x=50%>
                <ColorControl bind:selected_color=color />
            </Frame>
        </Stacker>
        <Stacker>
            for i in 0..10 {
                <Stacker direction=StackerDirection::Horizontal >
                    for j in 0..10 {
                        <Cell bind:cells=cells row=i col=j bind:color=color />
                    }
                </Stacker>
            }
        </Stacker>
    </Stacker>
</Group>

@settings {
    @tick: tick
    .h1 {
        style: {
                font: {Font::system("Times New Roman", FontStyle::Normal, FontWeight::Bold)},
                font_size: 64px,
                fill: BLACK,
                align_vertical: TextAlignVertical::Center,
                align_horizontal: TextAlignHorizontal::Center,
                align_multiline: TextAlignHorizontal::Center
        }
    }
    .btn {
        style: {
                font: {Font::system("Times New Roman", FontStyle::Normal, FontWeight::Bold)},
                font_size: 24px,
                fill: BLACK,
                align_vertical: TextAlignVertical::Center,
                align_horizontal: TextAlignHorizontal::Center,
                align_multiline: TextAlignHorizontal::Center
        }
    }
    
}
```

```pax filename=game-of-life/src/templates/cell.pax
<Group @click=self.toggle>
    if self.on {
        <Rectangle fill=color stroke=BLACK />
    }
    if !self.on {
        <Rectangle fill=BLACK stroke=WHITE />
    }
</Group>

@settings {
    @mount: mount,
}
```

```pax filename=game-of-life/src/templates/color_control.pax
<Stacker> 
    <Text text="Color" class=text x=50% />
    <Dropdown bind:selected_id=selected_id options=["Red","White","Blue"] stroke=BLACK background=WHITE />
</Stacker>

@settings {
    @mount: mount,
    .text {
        style: {
                font: {Font::system("Times New Roman", FontStyle::Normal, FontWeight::Bold)},
                font_size: 28px,
                fill: BLACK,
                align_vertical: TextAlignVertical::Center,
                align_horizontal: TextAlignHorizontal::Center,
                align_multiline: TextAlignHorizontal::Center
        }
    }
}
```

```pax filename=game-of-life/src/speed_control.pax
<Stacker> 
    <Text text="Speed" class=text x=50% />
    <Slider bind:value=speed min=1 max=100 step=1 accent=BLUE />
</Stacker>

@settings {
    .text {
        style: {
                font: {Font::system("Times New Roman", FontStyle::Normal, FontWeight::Bold)},
                font_size: 28px,
                fill: BLACK,
                align_vertical: TextAlignVertical::Center,
                align_horizontal: TextAlignHorizontal::Center,
                align_multiline: TextAlignHorizontal::Center
        }
    }
}
```

```rust filename=game-of-life/src/lib.rs
#![allow(unused_imports)]
use pax_engine::api::*;
use pax_engine::*;
use pax_std::*;



#[pax]
#[custom(Default)]
#[main]
#[file("templates/lib.pax")]
pub struct GameOfLife {
    pub cells: Property<Vec<Vec<bool>>>,
    pub rows: Property<usize>,
    pub cols: Property<usize>,
    pub running: Property<bool>,
    pub speed: Property<f64>,
    pub color: Property<Color>,
}

impl Default for GameOfLife {
    fn default() -> Self {
        let n = 10;
        Self {
            cells: Property::new(vec![vec![false; n]; n]),
            rows: Property::new(n),
            cols: Property::new(n),
            running: Property::new(false),
            speed: Property::new(20.0),
            color: Property::new(Color::WHITE),
        }
    }
}

impl GameOfLife {
    pub fn tick(&mut self, ctx: &NodeContext) {
        let interval = (100.0 / self.speed.get()) as u64;
        if ctx.frames_elapsed.get() % interval == 0 && self.running.get() {
            self.update();
        }
    }

    fn update(&mut self) {
        if self.running.get() {
            let mut new_cells = vec![vec![false; self.cols.get()]; self.rows.get()];
            for i in 0..self.rows.get() {
                for j in 0..self.cols.get() {
                    let mut count = 0;
                    for x in -1..=1 {
                        for y in -1..=1 {
                            if x == 0 && y == 0 {
                                continue;
                            }
                            let ni = (i as isize + x + self.rows.get() as isize) as usize % self.rows.get();
                            let nj = (j as isize + y + self.cols.get() as isize) as usize % self.cols.get();
                            if self.cells.get()[ni][nj] {
                                count += 1;
                            }
                        }
                    }
                    new_cells[i][j] = match (self.cells.get()[i][j], count) {
                        (true, 2) | (true, 3) => true,
                        (false, 3) => true,
                        _ => false,
                    };
                }
            }
            if new_cells == self.cells.get() {
                self.running.set(false);
            } else {
                self.cells.set(new_cells);
            }
        }
    }

    pub fn start(&mut self, _ctx: &NodeContext, _args: Event<ButtonClick>) {
        self.running.set(true);
    }

    pub fn stop(&mut self, _ctx: &NodeContext, _args: Event<ButtonClick>) {
        self.running.set(false);
    }

    pub fn reset(&mut self, _ctx: &NodeContext, _args: Event<ButtonClick>) {
        self.running.set(false);
        self.cells.set(vec![vec![false; self.cols.get()]; self.rows.get()]);
    }
}

#[pax]
#[file("templates/cell.pax")]
pub struct Cell {
    pub on : Property<bool>,
    pub row: Property<usize>,
    pub col: Property<usize>,
    pub cells: Property<Vec<Vec<bool>>>,
    pub color: Property<Color>,
}

impl Cell {

    pub fn mount(&mut self, _ctx: &NodeContext) {
        let cells = self.cells.clone();
        let row = self.row.clone();
        let col = self.col.clone();
        self.on.replace_with(Property::computed(move || {
            cells.get()[row.get()][col.get()]
        }, &[self.cells.untyped()]));
    }

    pub fn toggle(&mut self, _ctx: &NodeContext, _args: Event<Click>) {
        self.cells.update(|cells: &mut Vec<Vec<bool>>| {
            cells[self.row.get()][self.col.get()] = !cells[self.row.get()][self.col.get()];
        });
    }
}

#[pax]
#[file("templates/speed_control.pax")]
pub struct SpeedControl {
    pub speed: Property<f64>,
}

#[pax]
#[file("templates/color_control.pax")]
pub struct ColorControl {
    pub selected_id: Property<u32>,
    pub selected_color: Property<Color>,
}

impl ColorControl {
    pub fn mount(&mut self, _ctx: &NodeContext) {
        let selected_id_clone = self.selected_id.clone();
        let colors = vec![
                Color::RED,
                Color::WHITE,
                Color::BLUE,
            ];
        self.selected_color.replace_with(Property::computed(move || {
            colors[selected_id_clone.get() as usize].clone()
        }, &[self.selected_id.untyped()]));
    }
}
```

## Mouse Animation

A color full effect runs through the screen when I move my mouse across it. 

### Code

```rust filename=mouse-animation/src/lib.rs 
#![allow(unused_imports)]

pub mod path_animation;
use path_animation::PathAnimation;

use pax_engine::api::*;
use pax_engine::*;
use pax_std::*;


use pax_engine::math::Generic;
use pax_engine::math::Point2;

#[pax]
#[main]
#[file("lib.pax")]
pub struct Example {
    pub scroll: Property<f64>,
}

impl Example {
    pub fn on_mouse_move(&mut self, ctx: &NodeContext, event: Event<MouseMove>) {
        let (_, h) = ctx.bounds_self.get();
        let part = event.mouse.y / h;
        self.scroll.set(part);
    }
}

```

```pax filename=mouse-animation/src/lib.pax
<Text x=50% y=50% text="Move mouse up & down" id=text/>
<Group anchor_x=50% anchor_y=50% x=50% y=50% width=200% rotate=20deg>
	for i in 0..12 {
		<PathAnimation rotate={(i*40)deg}
			x=50%
			y=50%
			path_config={
			    amplitude: {0.03 + 0.1 * i*(i-12.0)/10.0},
				amplitude_ramp: {0.2 + i*0.01},
				frequency: 2.0,
			    frequency_ramp: {0.1*i},
			    thickness: {0.07 - 0.01*i/5.0},
			    thickness_ramp: {0.02 - i/5.0*0.01},
			    span: {0.1 + 0.1*i/10.0},
			}	
		    t={2.0*self.scroll - i/20.0}
			fill={hsla(40.0*i, 150, 160 + 5*i, 100)}
		/>
	}
</Group>

@settings {
	@mouse_move: on_mouse_move
    #text {
        style: TextStyle {
            font: {Font::local("Esenka", "assets/fonts/Esenka.otf", FontStyle::Normal, FontWeight::Normal)},
            font_size: 40px,
            fill: BLACK,
            align_vertical: TextAlignVertical::Center,
            align_horizontal: TextAlignHorizontal::Center,
        }
    }
}
```

```rust filename=mouse-animation/src/path_animation.rs
#![allow(unused_imports)]
use pax_engine::api::*;
use pax_engine::*;
use pax_std::*;


use core::f64::consts::PI;
use pax_engine::math::Generic;
use pax_engine::math::Point2;

#[pax]
#[custom(Default)]
#[file("path_animation.pax")]
pub struct PathAnimation {
    pub t: Property<Numeric>,
    pub resolution: Property<Numeric>,
    pub path_config: Property<PathConfig>,
    pub fill: Property<Color>,

    //private path elements
    pub path_elements: Property<Vec<PathElement>>,
}

impl Default for PathAnimation {
    fn default() -> Self {
        let fill = Property::new(Color::RED);
        let t: Property<Numeric> = Property::new(0.0.into());
        let resolution: Property<Numeric> = Property::new(60.into());
        let path_config = Property::new(PathConfig {
            amplitude: Property::new(0.3.into()),
            amplitude_ramp: Property::new(0.3.into()),
            frequency: Property::new(1.0.into()),
            frequency_ramp: Property::new(1.0.into()),
            thickness: Property::new(0.01.into()),
            thickness_ramp: Property::new(0.3.into()),
            span: Property::new(0.3.into()),
        });

        let path_elements = {
            let t = t.clone();
            let resolution = resolution.clone();
            let path_config = path_config.clone();
            let deps = [t.untyped(), resolution.untyped(), path_config.untyped()];
            Property::computed(
                move || {
                    let profile = |t: f64| t * (t - 1.0);
                    let conf = path_config.get();
                    let path = |t: f64| PathPoint {
                        point: Point2::<Generic>::new(
                            t,
                            0.5 + (conf.amplitude.get().to_float()
                                + conf.amplitude_ramp.get().to_float() * t)
                                * ((conf.frequency.get().to_float()
                                    + conf.frequency_ramp.get().to_float() * t)
                                    * t
                                    * PI
                                    * 2.0)
                                    .sin(),
                        ),
                        thickness: conf.thickness.get().to_float()
                            + conf.thickness_ramp.get().to_float() * t,
                    };
                    parametric_path(
                        resolution.get().to_int() as usize,
                        path,
                        profile,
                        conf.span.get().to_float(),
                        t.get().to_float(),
                    )
                },
                &deps,
            )
        };

        Self {
            fill,
            path_config,
            t,
            resolution,
            path_elements,
        }
    }
}

#[pax]
pub struct PathConfig {
    pub amplitude: Property<Numeric>,
    pub amplitude_ramp: Property<Numeric>,
    pub frequency: Property<Numeric>,
    pub frequency_ramp: Property<Numeric>,
    pub thickness: Property<Numeric>,
    pub thickness_ramp: Property<Numeric>,
    pub span: Property<Numeric>,
}

struct PathPoint {
    point: Point2,
    thickness: f64,
}
/// Takes a parametric function that describes a path:
/// path_points: parametric value (0.0 to 1.0) -> point on path + thikness modifier
/// path_profile: parametric value (0.0 to 1.0) -> thickness at point
/// span: how large part of the path is drawn at any one time?
/// returns: a function that given a time (0.0 to 1.0), gives back a path
fn parametric_path(
    resolution: usize,
    path_points: impl Fn(f64) -> PathPoint,
    path_profile: impl Fn(f64) -> f64,
    span: f64,
    t: f64,
) -> Vec<PathElement> {
    let r90 = Rotation::Degrees(90.into());
    let ran = 0..=resolution;
    let l: Vec<_> = ran
        .map(|v| {
            let s = v as f64 / resolution as f64; //0.0 to 1.0
            let mut p = path_points(s * span + (1.0 - span) * t);
            p.thickness *= path_profile(s);
            p
        })
        .collect();
    let mut normals = Vec::with_capacity(l.len());
    for i in 0..l.len() {
        normals.push(
            match (l.get(i.overflowing_sub(1).0), l.get(i), l.get(i + 1)) {
                (Some(a), Some(b), Some(c)) => {
                    (a.point.lerp_towards(b.point, 0.95) - c.point.lerp_towards(b.point, 0.95))
                        .rotate(r90.clone())
                        .normalize()
                        * b.thickness
                }
                (Some(a), Some(b), None) => {
                    (a.point - b.point).rotate(r90.clone()).normalize() * b.thickness
                }
                (None, Some(a), Some(b)) => {
                    (a.point - b.point).rotate(r90.clone()).normalize() * a.thickness
                }
                _ => panic!("unexpected"),
            },
        );
    }

    // adding/subtracting normals from path points give two lines offset by the same amount from the center
    let top = l.iter().zip(normals.iter()).map(|(a, &b)| a.point + b);
    let bottom = l.iter().zip(normals.iter()).map(|(a, &b)| a.point - b);

    // Now join top and bottom to create pathelements
    let mut elements: Vec<_> = top
        .chain(bottom.rev())
        .flat_map(|p| {
            [
                PathElement::point(
                    Size::Percent((100.0 * p.x).into()),
                    Size::Percent((100.0 * p.y).into()),
                ),
                PathElement::line(),
            ]
        })
        .collect();
    // remove last line
    elements.pop();
    // instead close the loop
    elements.push(PathElement::close());
    elements
}
```

```pax filename=mouse-animation/src/path_animation.pax
<Path
	fill={self.fill}
	elements={self.path_elements}
/>
```

## Space Game

A 2d asteroid shooter game 

### Code

```rust filename=space-game/src/lib.rs
#![allow(unused_imports)]
use pax_engine::api::*;
use pax_engine::*;
use pax_std::*;

use rand::rngs::ThreadRng;
use rand::Rng;
use std::collections::HashSet;

pub mod animation;
use animation::Animation;

const SCALE: f64 = 2.0;

#[pax]
#[main]
#[file("lib.pax")]
pub struct SpaceGame {
    pub ship_x: Property<f64>,
    pub ship_y: Property<f64>,
    pub asteroids: Property<Vec<Asteroid>>,
    pub bullets: Property<Vec<Bullet>>,

    pub last_asteroid: Property<u64>,
    pub last_bullet: Property<u64>,
    pub background_tiles: Property<Vec<Point>>,

    pub keys_pressed: Property<Vec<u8>>,
    pub game_state: Property<String>,

    pub difficulty: Property<f64>,
    pub score: Property<u64>,
}

#[pax]
pub struct Asteroid {
    pub x: f64,
    pub y: f64,
    pub r: f64,
    pub dx: f64,
    pub dy: f64,
    pub dr: f64,
    pub w: f64,
    pub health: u64,
    pub animation: Animation,
}

#[pax]
pub struct Point {
    pub x: f64,
    pub y: f64,
}

#[pax]
pub struct Bullet {
    pub x: f64,
    pub y: f64,
}

impl Asteroid {
    fn spawn(rng: &mut ThreadRng, w: f64, h: f64, difficulty: f64) -> Self {
        let radius = rng.gen_range(32.0..(48.0 + 32.0 * difficulty));
        let yspread = 0.2 + difficulty * 0.3;
        Self {
            x: w + 32.0,
            y: rng.gen_range(-32.0..(h + 32.0)),
            r: rng.gen_range(0.0..360.0),
            dx: 1.0 + rng.gen_range((1.5 * difficulty)..(1.0 + 3.2 * difficulty)),
            dy: rng.gen_range(-yspread..yspread),
            dr: rng.gen_range(0.0..1.0),
            w: radius,
            health: (radius as u64) / 3,
            animation: Animation::new(vec![
                String::from("assets/asteroid0.png"),
                String::from("assets/asteroid1.png"),
                String::from("assets/asteroid2.png"),
            ]),
        }
    }
}

impl SpaceGame {
    pub fn handle_mount(&mut self, ctx: &NodeContext) {
        let mut rng = rand::thread_rng();
        let (w_o, h_o) = ctx.bounds_parent.get();
        let (w, h) = (w_o / SCALE, h_o / SCALE);
        self.ship_x.set(32.0);
        self.ship_y.set(h / 2.0);
        self.game_state.set(String::from("PLAYING"));
    }

    pub fn tick(&mut self, ctx: &NodeContext) {
        let mut rng = rand::thread_rng();

        // Read properties
        let (w_o, h_o) = ctx.bounds_parent.get();
        let (w, h) = (w_o / SCALE, h_o / SCALE);
        let ticks = ctx.frames_elapsed.get();
        let mut bullets = self.bullets.get();
        let mut asteroids = self.asteroids.get();
        let mut ship_x = self.ship_x.get();
        let mut ship_y = self.ship_y.get();
        let mut score = self.score.get();
        let difficulty = self.difficulty.get();

        if &self.game_state.get() == "PLAYING" {
            // Check collisions between player and asteroids, and end game if hit
            for a in &mut asteroids {
                if (a.x - ship_x).powi(2) + (a.y - ship_y).powi(2) < (10.0f64 + a.w / 2.0).powi(2) {
                    self.game_state.set(String::from("GAME_OVER"));
                    a.animation.start();
                }
            }

            // Player actions (movement, bullets, etc.)
            for key in self.keys_pressed.get() {
                match key as char {
                    'w' => ship_y -= 1.5,
                    's' => ship_y += 1.5,
                    'a' => ship_x -= 1.0,
                    'd' => ship_x += 0.8,
                    ' ' => {
                        if (ticks - self.last_bullet.get()) > 15 {
                            bullets.push(Bullet {
                                x: ship_x,
                                y: ship_y + 6.0,
                            });
                            bullets.push(Bullet {
                                x: ship_x,
                                y: ship_y - 6.0,
                            });
                            self.last_bullet.set(ticks);
                        }
                    }
                    _ => (),
                }
            }
            ship_x = ship_x.clamp(16.0, w - 16.0);
            ship_y = ship_y.clamp(16.0, h - 16.0);
        }

        // Update bullets (movement, destroy, create, etc)
        bullets.retain_mut(|b| {
            b.x += 7.0;
            // Collide with asteroids
            for a in &mut asteroids {
                if (a.x - b.x).powi(2) + (a.y - b.y).powi(2) < (a.w / 2.0).powi(2) {
                    a.health = a.health.saturating_sub(1);
                    if a.health == 0 && !a.animation.running {
                        a.animation.start();
                        score += 1;
                    }
                    return false;
                }
            }
            b.x <= w + 16.0
        });

        // Update asteroids (movement, destroy, create, etc)
        asteroids.retain_mut(|a| {
            a.x -= a.dx;
            a.y -= a.dy;
            a.r += a.dr;
            a.animation.tick();
            a.x > -32.0 && a.animation.finished == false
        });
        let l_a = self.last_asteroid.get();
        if rng.gen_range(0..(ticks - l_a + 1)) > ((1.2 - difficulty) * 100.0) as u64 {
            self.last_asteroid.set(ticks);
            asteroids.push(Asteroid::spawn(&mut rng, w, h, difficulty));
        }

        // Update all properties to new values
        self.asteroids.set(asteroids);
        self.ship_x.set(ship_x);
        self.ship_y.set(ship_y);
        self.bullets.set(bullets);
        self.score.set(score);

        // Update tile background positions
        const BACKGROUND_SPEED: f64 = 5.0;
        const IMG_SIZE: f64 = 512.0;
        let w_n = (w_o / IMG_SIZE).ceil() as usize + 1;
        let h_n = (h_o / IMG_SIZE).ceil() as usize;
        let mut backgrounds = vec![];
        for j in 0..h_n {
            for i in 0..w_n {
                backgrounds.push(Point {
                    x: (w_n as f64 - 1.0) * IMG_SIZE
                        - (ticks as f64 * BACKGROUND_SPEED + i as f64 * IMG_SIZE)
                            .rem_euclid(w_n as f64 * IMG_SIZE),
                    y: IMG_SIZE * j as f64,
                });
            }
        }
        self.background_tiles.set(backgrounds);
        self.difficulty.set((difficulty + 0.0001).min(1.0));
    }

    pub fn key_down(&mut self, ctx: &NodeContext, args: Event<KeyDown>) {
        if let Some(char) = args.keyboard.key.chars().next() {
            let mut keys_pressed = self.keys_pressed.get();
            if !keys_pressed.contains(&(char as u8)) {
                keys_pressed.push(char as u8);
            }
            self.keys_pressed.set(keys_pressed);
        }
    }
    pub fn key_up(&mut self, ctx: &NodeContext, args: Event<KeyUp>) {
        if let Some(char) = args.keyboard.key.chars().next() {
            let mut keys_pressed = self.keys_pressed.get();
            keys_pressed.retain(|v| v != &(char as u8));
            self.keys_pressed.set(keys_pressed);
        }
    }
}
```

```rust filename=space-game/src/animation.rs
#![allow(unused_imports)]
use pax_engine::api::*;
use pax_engine::*;

#[pax]
pub struct Animation {
    pub frame: String,
    pub frames: Vec<String>,
    pub running: bool,
    pub finished: bool,
    pub time: u64,

    //settable properties
    pub speed: u64,
    pub loops: bool,
}

impl Animation {
    pub fn new(frames: Vec<String>) -> Self {
        Self {
            frame: frames[0].clone(),
            frames,
            running: false,
            loops: false,
            finished: false,
            speed: 10,
            time: 0,
        }
    }

    pub fn start(&mut self) {
        self.running = true;
    }

    pub fn tick(&mut self) {
        if self.running {
            self.time += 1;
            let frame_index = (self.time / self.speed) as usize;
            if frame_index < self.frames.len() {
                self.frame = self.frames[frame_index].clone();
                return;
            }
            if self.loops {
                self.start();
            } else {
                self.running = false;
                self.finished = true;
            }
        }
    }
}
```

```pax filename=space-game/src/lib.pax

if self.game_state == "PLAYING" {
	<Text x=10px y=10px text={"Score: " + self.score} style={fill:WHITE}/>
}
if self.game_state == "GAME_OVER" {
	<Text y=25% height=25% width=100% text="GAME OVER" id=game_over/>
	<Text y=50% height=25% width=100% text={"Score: " + self.score} id=game_over_score/>
	<Rectangle fill=rgba(255, 0, 50, 50)/>
}

<Group scale_x=200% scale_y=200% width=50% height=50%>
	if self.game_state == "PLAYING" {
		// Spaceship
		<Image
			width=32px
			height=32px
			path="assets/spaceship.png"
			anchor_x=50%
			anchor_y=50%
			x={self.ship_x}
			y={self.ship_y}
		/>
	}

	for asteroid in self.asteroids {
		<Image
			path={asteroid.animation.frame}
			anchor_x=50%
			anchor_y=50%
			x={asteroid.x}
			y={asteroid.y}
			width={asteroid.w}
			height={asteroid.w}
			rotate={(asteroid.r)deg}
		/>
	}
	for bullet in self.bullets {
		<Image
			width=16px
			height=16px
			path="assets/bullet.png"
			anchor_x=50%
			anchor_y=50%
			x={bullet.x}
			y={bullet.y}
		/>
	}
	// background
</Group>

<Group width=512px height=512px>
	for background in self.background_tiles {
		<Image
			x={background.x}
			y={background.y}
			path="assets/starfield0.png"
		/>
	}
</Group>

@settings {
	@mount: handle_mount,
	@tick: tick,
	@key_down: key_down,
	@key_up: key_up,

    #game_over {
        style: {
            font: {Font::system("Times New Roman", FontStyle::Normal, FontWeight::Normal)},
            font_size: 100px,
            fill: WHITE,
            align_vertical: TextAlignVertical::Center,
            align_horizontal: TextAlignHorizontal::Center,
            align_multiline: TextAlignHorizontal::Center
        }
    }

    #game_over_score {
        style: {
            font: {Font::system("Times New Roman", FontStyle::Normal, FontWeight::Bold)},
            font_size: 64px,
            fill: WHITE,
            align_vertical: TextAlignVertical::Center,
            align_horizontal: TextAlignHorizontal::Center,
            align_multiline: TextAlignHorizontal::Center
        }
    }
}
```
## Pong

An old school 2D pong game

### Code

```rust filename=lib.rs
#![allow(unused_imports)]
use pax_engine::api::*;
use pax_engine::*;
use pax_std::*;


const PADDLE_SPEED: f64 = 5.0;
const BALL_SPEED: f64 = 5.0;

#[pax]
#[main]
#[file("lib.pax")]
pub struct Pong {
    pub player_y: Property<f64>,
    pub computer_y: Property<f64>,
    pub ball_x: Property<f64>,
    pub ball_y: Property<f64>,
    pub ball_dx: Property<f64>,
    pub ball_dy: Property<f64>,
    pub player_score: Property<u32>,
    pub computer_score: Property<u32>,
}

impl Pong {
    pub fn update_game(&mut self, ctx: &NodeContext) {
        let (width, height) = ctx.bounds_self.get();

        // Update ball position
        let ball_x = self.ball_x.get() + self.ball_dx.get();
        let ball_y = self.ball_y.get() + self.ball_dy.get();

        // Ball collision with top and bottom walls
        if ball_y <= 0.0 || ball_y >= height - 10.0 {
            self.ball_dy.set(-self.ball_dy.get());
        }

        // Ball collision with paddles
        if (ball_x <= 30.0 && ball_y >= self.player_y.get() && ball_y <= self.player_y.get() + 80.0) ||
           (ball_x >= width - 40.0 && ball_y >= self.computer_y.get() && ball_y <= self.computer_y.get() + 80.0) {
            self.ball_dx.set(-self.ball_dx.get());
        }

        // Score points
        if ball_x <= 0.0 {
            self.computer_score.set(self.computer_score.get() + 1);
            self.reset_ball(ctx);
        } else if ball_x >= width - 10.0 {
            self.player_score.set(self.player_score.get() + 1);
            self.reset_ball(ctx);
        } else {
            self.ball_x.set(ball_x);
            self.ball_y.set(ball_y);
        }

        // Simple AI for computer paddle
        let computer_y = self.computer_y.get();
        if computer_y + 40.0 < ball_y {
            self.computer_y.set(computer_y + PADDLE_SPEED);
        } else if computer_y + 40.0 > ball_y {
            self.computer_y.set(computer_y - PADDLE_SPEED);
        }
    }

    pub fn handle_mouse_move(&mut self, ctx: &NodeContext, args: Event<MouseMove>) {
        let (_, height) = ctx.bounds_self.get();
        self.player_y.set((args.mouse.y - 40.0).clamp(0.0, height - 80.0));
    }

    pub fn reset_ball(&mut self, ctx: &NodeContext) {
        let (width, height) = ctx.bounds_self.get();
        self.ball_x.set(width / 2.0 - 5.0);
        self.ball_y.set(height / 2.0 - 5.0);
        self.ball_dx.set(if rand::random() { BALL_SPEED } else { -BALL_SPEED });
        self.ball_dy.set(if rand::random() { BALL_SPEED } else { -BALL_SPEED });
    }
}
```

```pax filename=lib.pax
<Group>
    // Center line
    <Rectangle x=50% width=2px height=100% fill=WHITE />

    // Player paddle
    <Rectangle 
        x=20px 
        y={self.player_y} 
        width=10px 
        height=80px 
        fill=WHITE 
    />

    // Computer paddle
    <Rectangle 
        x={100% - 30px} 
        y={self.computer_y} 
        width=10px 
        height=80px 
        fill=WHITE 
    />

    // Ball
    <Rectangle 
        x={self.ball_x} 
        y={self.ball_y} 
        width=10px 
        height=10px 
        fill=WHITE 
    />

    // Scores
    <Text 
        x=25% 
        y=30px 
        text={self.player_score} 
        id=score
    />
    <Text 
        x=75% 
        y=30px 
        text={self.computer_score} 
        id=score
    />

    // Background
    <Rectangle width=100% height=100% fill=BLACK />
</Group>

@settings {
    @tick: update_game
    @mouse_move: handle_mouse_move

    #score {
        style: {
            font: {Font::system("Arial", FontStyle::Normal, FontWeight::Bold)},
            font_size: 36px,
            fill: WHITE,
            align_vertical: TextAlignVertical::Top,
            align_horizontal: TextAlignHorizontal::Center,
        }
    }
}
```
## Calculator

A barebones calculator

### Code
```rust filename=lib.rs
#![allow(unused_imports)]
use pax_engine::api::*;
use pax_engine::*;
use pax_std::*;


#[pax]
#[main]
#[file("lib.pax")]
pub struct Calculator {
    pub display: Property<String>,
    pub first_number: Property<f64>,
    pub operation: Property<String>,
    pub second_number: Property<f64>,
}

impl Calculator {
    pub fn handle_number(&mut self, _ctx: &NodeContext, args: Event<ButtonClick>, number: u8) {
        let mut current_display = self.display.get();
        if current_display == "0" {
            current_display = number.to_string();
        } else {
            current_display.push_str(&number.to_string());
        }
        self.display.set(current_display);
    }

    pub fn handle_operation(&mut self, _ctx: &NodeContext, args: Event<ButtonClick>, op: &str) {
        self.first_number.set(self.display.get().parse().unwrap_or(0.0));
        self.operation.set(op.to_string());
        self.display.set("0".to_string());
    }

    pub fn handle_equals(&mut self, _ctx: &NodeContext, args: Event<ButtonClick>) {
        self.second_number.set(self.display.get().parse().unwrap_or(0.0));
        let result = match self.operation.get().as_str() {
            "+" => self.first_number.get() + self.second_number.get(),
            "-" => self.first_number.get() - self.second_number.get(),
            "*" => self.first_number.get() * self.second_number.get(),
            "/" => self.first_number.get() / self.second_number.get(),
            _ => self.second_number.get(),
        };
        self.display.set(result.to_string());
    }

    pub fn handle_clear(&mut self, _ctx: &NodeContext, args: Event<ButtonClick>) {
        self.display.set("0".to_string());
        self.first_number.set(0.0);
        self.operation.set("".to_string());
        self.second_number.set(0.0);
    }

    pub fn handle0(&mut self, ctx: &NodeContext, args: Event<ButtonClick>) { self.handle_number(ctx, args, 0); }
    pub fn handle1(&mut self, ctx: &NodeContext, args: Event<ButtonClick>) { self.handle_number(ctx, args, 1); }
    pub fn handle2(&mut self, ctx: &NodeContext, args: Event<ButtonClick>) { self.handle_number(ctx, args, 2); }
    pub fn handle3(&mut self, ctx: &NodeContext, args: Event<ButtonClick>) { self.handle_number(ctx, args, 3); }
    pub fn handle4(&mut self, ctx: &NodeContext, args: Event<ButtonClick>) { self.handle_number(ctx, args, 4); }
    pub fn handle5(&mut self, ctx: &NodeContext, args: Event<ButtonClick>) { self.handle_number(ctx, args, 5); }
    pub fn handle6(&mut self, ctx: &NodeContext, args: Event<ButtonClick>) { self.handle_number(ctx, args, 6); }
    pub fn handle7(&mut self, ctx: &NodeContext, args: Event<ButtonClick>) { self.handle_number(ctx, args, 7); }
    pub fn handle8(&mut self, ctx: &NodeContext, args: Event<ButtonClick>) { self.handle_number(ctx, args, 8); }
    pub fn handle9(&mut self, ctx: &NodeContext, args: Event<ButtonClick>) { self.handle_number(ctx, args, 9); }

    pub fn handleAdd(&mut self, ctx: &NodeContext, args: Event<ButtonClick>) { self.handle_operation(ctx, args, "+"); }
    pub fn handleSubtract(&mut self, ctx: &NodeContext, args: Event<ButtonClick>) { self.handle_operation(ctx, args, "-"); }
    pub fn handleMultiply(&mut self, ctx: &NodeContext, args: Event<ButtonClick>) { self.handle_operation(ctx, args, "*"); }
    pub fn handleDivide(&mut self, ctx: &NodeContext, args: Event<ButtonClick>) { self.handle_operation(ctx, args, "/"); }
}
```

```pax filename=lib.pax
<Group x=50% y=50% width=300px height=400px>
    <Stacker direction=StackerDirection::Vertical>
        <Group width=100% height=80px>
            <Text text={self.display} id=display x=95% y=50% />
            <Rectangle fill=BLACK />
        </Group>
        <Stacker direction=StackerDirection::Horizontal>
            <Button label="7" @button_click=handle7 class=btn />
            <Button label="8" @button_click=handle8 class=btn />
            <Button label="9" @button_click=handle9 class=btn />
            <Button label="/" @button_click=handleDivide class=btn />
        </Stacker>
        <Stacker direction=StackerDirection::Horizontal>
            <Button label="4" @button_click=handle4 class=btn />
            <Button label="5" @button_click=handle5 class=btn />
            <Button label="6" @button_click=handle6 class=btn />
            <Button label="X" @button_click=handleMultiply class=btn />
        </Stacker>
        <Stacker direction=StackerDirection::Horizontal>
            <Button label="1" @button_click=handle1 class=btn />
            <Button label="2" @button_click=handle2 class=btn />
            <Button label="3" @button_click=handle3 class=btn />
            <Button label="-" @button_click=handleSubtract class=btn />
        </Stacker>
        <Stacker direction=StackerDirection::Horizontal>
            <Button label="0" @button_click=handle0 class=btn />
            <Button label="C" @button_click=handle_clear class=btn />
            <Button label="=" @button_click=handle_equals class=btn />
            <Button label="+" @button_click=handleAdd class=btn />
        </Stacker>
    </Stacker>
</Group>

@settings {
    #display {
        style: {
            font: {Font::system("Arial", FontStyle::Normal, FontWeight::Bold)},
            font_size: 32px,
            fill: WHITE,
            align_vertical: TextAlignVertical::Center,
            align_horizontal: TextAlignHorizontal::Right,
        }
    }
    .btn {
        style: {
            font: {Font::system("Arial", FontStyle::Normal, FontWeight::Normal)},
            font_size: 24px,
            fill: BLACK,
            align_vertical: TextAlignVertical::Center,
            align_horizontal: TextAlignHorizontal::Center,
        }
    }
}
```

</examples>
