<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 pax file which will be the main template Pax application.
PLEASE DO NOT GENERATE ANY TEXT EXPLAINING THE CODE, JUST THE CODE!
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
```

File Types:

Generate one .pax 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: PAX's RGBA color specification has a range of 0-255 for each channel including alpha.
IMPORTANT: YOU CANNOT CHAIN CLASSES OR IDS IN SETTINGS BLOCKS
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.
Strictly follow the Pax language grammar and component structure as described in the background information.

Avoid Placeholders:
Do not use TODO comments or placeholder code. Implement full, working solutions in every answer with all files.
</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::Web(
                    "ff-real-headline-pro",
                    "https://use.typekit.net/ivu7epf.css",
                    FontStyle::Normal,
                    FontWeight::Light,
                )},
                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_kit::*;

#[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 = {identifier ~ "=" ~ "bind" ~ ":" ~ literal_function}

//`...=5.0`, `...={...}`
any_template_value = {literal_value | literal_object | expression_wrapped | 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 ~")")
}

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_kit::*;


#[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::Web(
                    "ff-real-headline-pro",
                    "https://use.typekit.net/ivu7epf.css",
                    FontStyle::Normal,
                    FontWeight::Light,
                )},
                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_kit::*;


#[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_kit::*;

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)


# Properties & Settings

`Properties` and `Settings` are two sides of the same idea, so they share a chapter in this book.
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_kit::*;


#[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_kit::*;

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. You can use an id (#id) or a class (.class) to reference settings in a block.
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.  


# 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:


```pax
    <Group>
        if self.should_show_details {
            <DetailsView />
        } else {
            <SummaryView />
        }
    </Group>
```

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:



```pax
    <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>
```

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:
```pax
    <Stacker>
        <Rectangle id=a />
        <Rectangle id=b />
        <Rectangle id=c />
    </Stacker>
```

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"

### 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.  

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).

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:

#### 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

#### Layout

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


```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 its bounds vertically
    FillVertical,
    /// Scale the image to perfectly fit within its bounds horizontally
    FillHorizontal,
    /// Scale the image to perfectly fit within its 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 its bounds, without clipping the image, possibly leaving some
    /// of the available container area empty.
    #[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::Web(
                "ff-real-headline-pro",
                "https://use.typekit.net/ivu7epf.css",
                FontStyle::Normal,
                FontWeight::Light,
        )
    }
}

#[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 web(family: String, url: String, style: FontStyle, weight: FontWeight) -> Self {
        Self::Web(WebFont {
            family,
            url,
            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_kit::*;

#[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 speed=bind:speed />
            </Frame>
            <Frame width=300px height=60px x=50%>
                <ColorControl selected_color=bind:color />
            </Frame>
        </Stacker>
        <Stacker>
            for i in 0..10 {
                <Stacker direction=StackerDirection::Horizontal >
                    for j in 0..10 {
                        <Cell cells=bind:cells row=i col=j color=bind:color />
                    }
                </Stacker>
            }
        </Stacker>
    </Stacker>
</Group>

@settings {
    @tick: tick
    .h1 {
        style: {
                font: {Font::Web(
                "ff-real-headline-pro",
                "https://use.typekit.net/ivu7epf.css",
                FontStyle::Normal,
                FontWeight::Light,
            )},
                font_size: 64px,
                fill: BLACK,
                align_vertical: TextAlignVertical::Center,
                align_horizontal: TextAlignHorizontal::Center,
                align_multiline: TextAlignHorizontal::Center
        }
    }
    .btn {
        style: {
                font: {Font::Web(
                "ff-real-headline-pro",
                "https://use.typekit.net/ivu7epf.css",
                FontStyle::Normal,
                FontWeight::Light,
            )},
                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 selected_id=bind:selected_id options=["Red","White","Blue"] stroke=BLACK background=WHITE />
</Stacker>

@settings {
    @mount: mount,
    .text {
        style: {
               font: {Font::Web(
                "ff-real-headline-pro",
                "https://use.typekit.net/ivu7epf.css",
                FontStyle::Normal,
                FontWeight::Light,
            )},
                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 value=bind:speed min=1 max=100 step=1 accent=BLUE />
</Stacker>

@settings {
    .text {
        style: {
                font: {Font::Web(
                "ff-real-headline-pro",
                "https://use.typekit.net/ivu7epf.css",
                FontStyle::Normal,
                FontWeight::Light,
            )},
                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_kit::*;



#[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()]));
    }
}
```
## Pong

An old school 2D pong game

### Code

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


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::Web(
                "ff-real-headline-pro",
                "https://use.typekit.net/ivu7epf.css",
                FontStyle::Normal,
                FontWeight::Light,
            )},
            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_kit::*;


#[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::Web(
                "ff-real-headline-pro",
                "https://use.typekit.net/ivu7epf.css",
                FontStyle::Normal,
                FontWeight::Light,
            )},
            font_size: 32px,
            fill: WHITE,
            align_vertical: TextAlignVertical::Center,
            align_horizontal: TextAlignHorizontal::Right,
        }
    }
    .btn {
        style: {
            font: {Font::Web(
                "ff-real-headline-pro",
                "https://use.typekit.net/ivu7epf.css",
                FontStyle::Normal,
                FontWeight::Light,
            )},
            font_size: 24px,
            fill: BLACK,
            align_vertical: TextAlignVertical::Center,
            align_horizontal: TextAlignHorizontal::Center,
        }
    }
}
```

## Marketing Website

A scrollable marketing website for a product. 

```pax filename=lib.pax
<Scroller scroll_height=400% x=0% y=0% width=100% height=100%>
    <Stacker width={100% + 10px} height=100% y=0% x=0% direction=StackerDirection::Vertical sizes=[Some(750px), None, None]>
        <Group x=0 height=750px skew_y=0.00rad skew_x=0.00rad rotate=0.00rad>
            <Image width=500px height=500px x={100% - 80px} y=53.06% source=ImageSource::Url("assets/placeholder.jpg")/>
            <Group rotate=0.00rad skew_x=0.00rad x=10% y=41.45% height=430.05px width=466.31px>
                <Button style={
                    font: Font::Web(
                        "Roboto",
                        "https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap",
                        FontStyle::Normal,
                        FontWeight::Normal)
                    font_size: 12px
                    fill: rgba(30, 28, 30, 255)
                    align_vertical: TextAlignVertical::Center
                    align_horizontal: TextAlignHorizontal::Center
                    align_multiline: TextAlignHorizontal::Center
                    underline: false
                } 
                    rotate=0.00rad skew_x=0.00rad width=245px height=36px x=0.02% y=0.00% label="PRODUCT: BUILD UI 10X FASTER - >" outline={
                        color: rgba(24, 22, 19, 100)
                        width: 1.00px
                    } 
                    color=rgba(246, 240, 234, 255)/>
                <Text width=519.48px height=120.52px y=52.97px style={
                    font: Font::Web(
                        "Inter", "https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap", FontStyle::Normal, 
                            FontWeight::Normal)
                    font_size: 48px
                    fill: rgba(0, 0, 0, 255)
                    align_vertical: TextAlignVertical::Center
                    align_horizontal: TextAlignHorizontal::Left
                    align_multiline: TextAlignHorizontal::Left
                    underline: false
                } 
                    text="What if your website could optimize itself?"/>
                <Text width=420px x=4.56px y=191.55px height=85px style={
                    font: Font::Web(
                        "Inter", "https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap", FontStyle::Normal, 
                            FontWeight::Normal)
                    font_size: 24.00px
                    fill: rgba(33, 31, 29, 155)
                    align_vertical: TextAlignVertical::Top
                    align_horizontal: TextAlignHorizontal::Left
                    align_multiline: TextAlignHorizontal::Left
                    underline: false
                } 
                    text="Imagine a frontend engineer and growth marketer optimizing your website 24/7. That's Coframe."/>
                <Button style={
                    font: Font::Web(
                        "Noto Sans",
                        "https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap",
                        FontStyle::Normal,
                        FontWeight::Normal)
                    font_size: 16px
                    fill: rgba(0, 0, 0, 255)
                    align_vertical: TextAlignVertical::Center
                    align_horizontal: TextAlignHorizontal::Center
                    align_multiline: TextAlignHorizontal::Center
                    underline: false
                } 
                    label="Get in touch" color=rgba(244, 240, 234, 255) rotate=0.00rad skew_x=0.00rad width=195px height=54px x=229.56px 
                    y=330.66px outline={
                        color: rgba(11, 0, 0, 255)
                        width: 1.00px
                    } hover_color=rgba(0, 6, 14, 255)/>
                <Button style={
                    font: Font::Web(
                        "Noto Sans",
                        "https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap",
                        FontStyle::Normal,
                        FontWeight::Normal)
                    font_size: 16px
                    fill: rgba(255, 255, 255, 255)
                    align_vertical: TextAlignVertical::Center
                    align_horizontal: TextAlignHorizontal::Center
                    align_multiline: TextAlignHorizontal::Center
                    underline: false
                } 
                    label="Start optimizing" color=rgba(0, 1, 13, 255) rotate=0.00rad skew_x=0.00rad width=195px height=54px x=4.55px 
                    y=330.66px hover_color=rgba(138, 137, 137, 255)/>
                <Text width=321.84px x=5.52px y=410.46px height=19.59px style={
                    font: Font::Web(
                        "Inter", "https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap", FontStyle::Normal, 
                            FontWeight::Normal)
                    font_size: 14.00px
                    fill: rgba(33, 31, 29, 155)
                    align_vertical: TextAlignVertical::Top
                    align_horizontal: TextAlignHorizontal::Left
                    align_multiline: TextAlignHorizontal::Left
                    underline: false
                } 
                    text="Get started for free. Integration takes 5 minutes"/>
            </Group>
            <Stacker direction=StackerDireciton::Horizontal y=0 x=0 height=70px width=100% sizes=[None, Some(500px), None]>
                <Group rotate=0.00rad skew_x=0.00rad skew_y=0.00rad>
                    <Stacker width=114.70px height=30.00px direction=StackerDirection::Horizontal y=20.00px x=14.72px>
                        <Group skew_x=0.00rad rotate=0.00rad skew_y=0.00rad>
                            <Image source=ImageSource::Url("assets/placeholder.jpg") skew_y=0.00rad skew_x=0.00rad rotate=0.00rad x=0/>
                        </Group>
                        <Group skew_y=0.00rad skew_x=0.00rad rotate=0.00rad>
                            <Text style={
                                font: Font::Web(
                                    "Noto Sans",
                                    "https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap",
                                    FontStyle::Normal,
                                    FontWeight::Normal)
                                font_size: 16px
                                fill: rgba(0, 0, 0, 255)
                                align_vertical: TextAlignVertical::Center
                                align_horizontal: TextAlignHorizontal::Center
                                align_multiline: TextAlignHorizontal::Center
                                underline: false
                            } 
                                text="Logo" skew_x=0.00rad rotate=0.00rad height=100% skew_y=0.00rad/>
                        </Group>
                    </Stacker>
                </Group>
                <Group skew_x=0.00rad rotate=0.00rad skew_y=0.00rad>
                    <Stacker x=0.00% y=0.00% direction=StackerDireciton::Horizontal>
                        <Group skew_x=0.00rad rotate=0.00rad skew_y=0.00rad>
                            <Text style={
                                font: Font::Web(
                                    "Source Sans Pro",
                                    "https://fonts.googleapis.com/css2?family=Source+Sans+Pro:ital,wght@0,200;0,300;0,400;0,600;0,700;0,900;1,200;1,300;1,400;1,600;1,700;1,900&display=swap",
                                    FontStyle::Normal,
                                    FontWeight::Normal)
                                font_size: 16px
                                fill: rgba(0, 0, 0, 255)
                                align_vertical: TextAlignVertical::Center
                                align_horizontal: TextAlignHorizontal::Center
                                align_multiline: TextAlignHorizontal::Center
                                underline: false
                            } 
                                text="Product" skew_x=0.00rad rotate=0.00rad skew_y=0.00rad width=100% height=100%/>
                        </Group>
                        <Group skew_y=0.00rad rotate=0.00rad skew_x=0.00rad>
                            <Text style={
                                font: Font::Web(
                                    "Source Sans Pro",
                                    "https://fonts.googleapis.com/css2?family=Source+Sans+Pro:ital,wght@0,200;0,300;0,400;0,600;0,700;0,900;1,200;1,300;1,400;1,600;1,700;1,900&display=swap",
                                    FontStyle::Normal,
                                    FontWeight::Normal)
                                font_size: 16px
                                fill: rgba(0, 0, 0, 255)
                                align_vertical: TextAlignVertical::Center
                                align_horizontal: TextAlignHorizontal::Center
                                align_multiline: TextAlignHorizontal::Center
                                underline: false
                            } 
                                text="Documentation" rotate=0.00rad width=100% height=100%/>
                        </Group>
                        <Group skew_y=0.00rad skew_x=0.00rad rotate=0.00rad>
                            <Text style={
                                font: Font::Web(
                                    "Source Sans Pro",
                                    "https://fonts.googleapis.com/css2?family=Source+Sans+Pro:ital,wght@0,200;0,300;0,400;0,600;0,700;0,900;1,200;1,300;1,400;1,600;1,700;1,900&display=swap",
                                    FontStyle::Normal,
                                    FontWeight::Normal)
                                font_size: 16px
                                fill: rgba(0, 0, 0, 255)
                                align_vertical: TextAlignVertical::Center
                                align_horizontal: TextAlignHorizontal::Center
                                align_multiline: TextAlignHorizontal::Center
                                underline: false
                            } 
                                text="Contact" skew_x=0.00rad rotate=0.00rad skew_y=0.00rad width=100% height=100%/>
                        </Group>
                        <Group skew_x=0.00rad rotate=0.00rad skew_y=0.00rad>
                            <Text style={
                                font: Font::Web(
                                    "Source Sans Pro",
                                    "https://fonts.googleapis.com/css2?family=Source+Sans+Pro:ital,wght@0,200;0,300;0,400;0,600;0,700;0,900;1,200;1,300;1,400;1,600;1,700;1,900&display=swap",
                                    FontStyle::Normal,
                                    FontWeight::Normal)
                                font_size: 16px
                                fill: rgba(0, 0, 0, 255)
                                align_vertical: TextAlignVertical::Center
                                align_horizontal: TextAlignHorizontal::Center
                                align_multiline: TextAlignHorizontal::Center
                                underline: false
                            } 
                                text="Careers" skew_x=0.00rad rotate=0.00rad skew_y=0.00rad width=100% height=100%/>
                        </Group>
                    </Stacker>
                </Group>
                <Group rotate=0.00rad skew_x=0.00rad skew_y=0.00rad>
                    <Button style={
                        font: Font::Web(
                            "Source Sans Pro",
                            "https://fonts.googleapis.com/css2?family=Source+Sans+Pro:ital,wght@0,200;0,300;0,400;0,600;0,700;0,900;1,200;1,300;1,400;1,600;1,700;1,900&display=swap",
                            FontStyle::Normal,
                            FontWeight::Normal)
                        font_size: 20.00px
                        fill: rgba(255, 255, 255, 255)
                        align_vertical: TextAlignVertical::Center
                        align_horizontal: TextAlignHorizontal::Center
                        align_multiline: TextAlignHorizontal::Center
                        underline: false
                    } 
                        label="Get started" color=rgba(0, 3, 13, 255) rotate=0.00rad skew_x=0.00rad skew_y=0.00rad width=145px height=56px 
                        x={100% - 20px} y=10px/>
                </Group>
            </Stacker>
            <Rectangle fill=rgba(246, 240, 234, 255) skew_x=0.00rad rotate=0.00rad stroke={
                color: rgba(100, 116, 139, 255)
                width: 1.00px
            } 
                x=0.00% y=0.00%/>
        </Group>
        <Group skew_x=0.00rad rotate=0.00rad skew_y=0.00rad>
            <Rectangle fill=rgba(249, 248, 248, 255) skew_y=0.00rad skew_x=0.00rad rotate=0.00rad stroke={
                color: rgba(100, 116, 139, 255)
                width: 1.00px
            }/>
        </Group>
        <Group rotate=0.00rad skew_x=0.00rad skew_y=0.00rad>
            <Rectangle fill=rgb(150, 150, 150) rotate=0.00rad skew_y=0.00rad skew_x=0.00rad/>
        </Group>
    </Stacker>
</Scroller>

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


## Form

A basic form for e-commerce

```pax filename=lib.pax
<Group x=43.87% y=45.56% width=43.43% height=67.04% id=form_group>
    <Stacker direction=StackerDirection::Vertical gutter=20px y=102.66% x=100.00% height=102.66% sizes=[Some(10%), None, Some(10%)]>
        <Text text="Basic Form" id=form_title style={
            font: Font::Web(
                "Roboto",
                "https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap",
                FontStyle::Normal,
                FontWeight::Normal)
            font_size: 30.00px
            fill: rgba(0, 0, 0, 255)
            align_vertical: TextAlignVertical::Top
            align_horizontal: TextAlignHorizontal::Left
            align_multiline: TextAlignHorizontal::Left
            underline: false
        }/>
        <Stacker direction=StackerDirection::Vertical gutter=10px skew_x=0.00rad rotate=0.00rad skew_y=0.00rad>
            <Textbox id=name_input placeholder="Enter your name"/>
            <Textbox id=password_input placeholder="Enter your password"/>
            <Textbox id=email_input placeholder="Enter your email"/>
            <Textbox id=address_input placeholder="Enter your address"/>
            <Stacker direction=StackerDirection::Horizontal sizes=[Some(50%), None, None] gutter=10px>
                <Textbox id=credit_card_input placeholder="Credit card number"/>
                <Textbox id=expiry_date_input placeholder="Expiry date"/>
                <Textbox id=cvv_input placeholder="CVV"/>
            </Stacker>
        </Stacker>
        <Button label="Submit" id=submit_button @button_click=self.handle_submit/>
    </Stacker>
</Group>

@settings {
    #form_title {
        style: {
            font: {Font::Web("ff-real-headline-pro", "https://use.typekit.net/ivu7epf.css", FontStyle::Normal, FontWeight::Light)}
            font_size: 24px
            fill: BLACK
            align_vertical: TextAlignVertical::Center
            align_horizontal: TextAlignHorizontal::Center
        }
    }
    #name_input {
        style: {
            font: {Font::Web("ff-real-headline-pro", "https://use.typekit.net/ivu7epf.css", FontStyle::Normal, FontWeight::Light)}
            font_size: 18px
            fill: BLACK
            align_vertical: TextAlignVertical::Center
            align_horizontal: TextAlignHorizontal::Left
        }
    }
    #password_input {
        style: {
            font: {Font::Web("ff-real-headline-pro", "https://use.typekit.net/ivu7epf.css", FontStyle::Normal, FontWeight::Light)}
            font_size: 18px
            fill: BLACK
            align_vertical: TextAlignVertical::Center
            align_horizontal: TextAlignHorizontal::Left
        }
    }
    #email_input {
        style: {
            font: {Font::Web("ff-real-headline-pro", "https://use.typekit.net/ivu7epf.css", FontStyle::Normal, FontWeight::Light)}
            font_size: 18px
            fill: BLACK
            align_vertical: TextAlignVertical::Center
            align_horizontal: TextAlignHorizontal::Left
        }
    }
    #address_input {
        style: {
            font: {Font::Web("ff-real-headline-pro", "https://use.typekit.net/ivu7epf.css", FontStyle::Normal, FontWeight::Light)}
            font_size: 18px
            fill: BLACK
            align_vertical: TextAlignVertical::Center
            align_horizontal: TextAlignHorizontal::Left
        }
    }
    #credit_card_input {
        style: {
            font: {Font::Web("ff-real-headline-pro", "https://use.typekit.net/ivu7epf.css", FontStyle::Normal, FontWeight::Light)}
            font_size: 18px
            fill: BLACK
            align_vertical: TextAlignVertical::Center
            align_horizontal: TextAlignHorizontal::Left
        }
    }
    #expiry_date_input {
        style: {
            font: {Font::Web("ff-real-headline-pro", "https://use.typekit.net/ivu7epf.css", FontStyle::Normal, FontWeight::Light)}
            font_size: 18px
            fill: BLACK
            align_vertical: TextAlignVertical::Center
            align_horizontal: TextAlignHorizontal::Left
        }
    }
    #cvv_input {
        style: {
            font: {Font::Web("ff-real-headline-pro", "https://use.typekit.net/ivu7epf.css", FontStyle::Normal, FontWeight::Light)}
            font_size: 18px
            fill: BLACK
            align_vertical: TextAlignVertical::Center
            align_horizontal: TextAlignHorizontal::Left
        }
    }
    #submit_button {
        style: {
            font: {Font::Web("ff-real-headline-pro", "https://use.typekit.net/ivu7epf.css", FontStyle::Normal, FontWeight::Light)}
            font_size: 18px
            fill: WHITE
            align_vertical: TextAlignVertical::Center
            align_horizontal: TextAlignHorizontal::Center
        }
        color: rgba(0, 128, 0, 255)
    }
    #form_group {
        fill: rgba(0, 255, 0, 255)
    }
}
```




</examples>
