Skip to content

Latest commit

 

History

History
467 lines (356 loc) · 7.43 KB

File metadata and controls

467 lines (356 loc) · 7.43 KB

Schema Operators Reference

This document describes the operators available in the schema system for declarative UI logic.

Table of Contents


Data Access Operators

$store

Access reactive store values.

Syntax:

{
  $store: 'storeName.propertyPath';
}

Examples:

// Simple property access
{
  $store: 'userStore.name';
}

// Nested property access
{
  $store: 'userStore.profile.email';
}

// Array access
{
  $store: 'templateStore.templates';
}

Notes:

  • Returns an accessor (function) for reactive updates
  • Cannot access entire store (must specify property)
  • Automatically unwraps nested accessors

Transformation Operators

$map

Transform arrays or single objects by selecting/reshaping properties.

Syntax:

{
  $map: {
    items: <source>,
    select: { <key>: '<value>' | '$item.<path>' }
  }
}

Examples:

Transform array:

{
  $map: {
    items: { $store: 'templateStore.templates' },
    select: {
      id: '$item.id',
      name: '$item.meta.name',
      icon: '$item.meta.icon'
    }
  }
}
// Input: [{ id: '1', meta: { name: 'Default', icon: 'home' } }, ...]
// Output: [{ id: '1', name: 'Default', icon: 'home' }, ...]

Transform single object:

{
  $map: {
    items: { $store: 'templateStore.currentTemplate' },
    select: {
      id: '$item.id',
      name: '$item.meta.name',
      icon: '$item.meta.icon'
    }
  }
}
// Input: { id: 'default', meta: { name: 'Default', icon: 'home' } }
// Output: { id: 'default', name: 'Default', icon: 'home' }

With constants:

{
  $map: {
    items: [{ id: 1 }, { id: 2 }],
    select: {
      id: '$item.id',
      type: 'template',  // constant value
      active: true
    }
  }
}
// Output: [{ id: 1, type: 'template', active: true }, ...]

Notes:

  • Use $item.<path> to reference properties from source items
  • Supports both arrays and single objects
  • Returns accessor if source is an accessor
  • Nested property paths supported: $item.user.profile.email

$pick

Extract specific properties from an object.

Syntax:

{
  $pick: {
    from: <source>,
    props: ['<prop1>', '<prop2>', ...]
  }
}

Example:

{
  $pick: {
    from: { $store: 'userStore.profile' },
    props: ['name', 'email']
  }
}
// Input: { name: 'Alice', email: 'alice@example.com', id: '123', role: 'admin' }
// Output: { name: 'Alice', email: 'alice@example.com' }

Use Cases:

  • Simple property extraction (subset of object)
  • For transformation/reshaping, use $map instead

$expr

Evaluate JavaScript expressions with context variables.

Syntax:

{
  $expr: '<javascript-expression>';
}

Examples:

// Template literals
{
  $expr: '`/space/${space.uuid}`';
}

// Calculations
{
  $expr: 'count * 2 + 1';
}

// Conditionals
{
  $expr: 'user.role === "admin" ? "Edit" : "View"';
}

Notes:

  • Has access to context variables
  • Returns evaluated result
  • Use with caution - errors return undefined

Action Operators

$action

Call store methods, with support for argument extraction from callbacks.

Syntax:

{
  $action: 'storeName.methodName',
  args?: [<arg1>, <arg2>, ...]
}

Examples:

Simple action:

{
  onClick: {
    $action: 'modalStore.openModal',
    args: ['settings']
  }
}

Extract property from callback argument:

{
  onSelect: {
    $action: 'templateStore.switchTemplate',
    args: ['$arg.id']  // Extract .id from first callback argument
  }
}
// When onSelect is called with { id: 'abc', name: 'Template' }
// Calls: templateStore.switchTemplate('abc')

Deep property extraction:

{
  onSubmit: {
    $action: 'userStore.updateEmail',
    args: ['$arg.user.profile.email']
  }
}

Pass entire argument:

{
  onChange: {
    $action: 'formStore.updateField',
    args: ['$arg']  // Pass entire first argument
  }
}

Mixed arguments:

{
  onUpdate: {
    $action: 'store.update',
    args: [
      '$arg.id',              // Extract from callback
      'static-value',         // Static value
      { $expr: 'context.id' } // Dynamic value
    ]
  }
}

Notes:

  • $arg - passes entire first callback argument
  • $arg.<path> - extracts property from first callback argument
  • Automatically extracts event.target.value from DOM events
  • Supports relative path navigation for routeStore.navigate

Conditional Operators

$if

Conditional rendering based on boolean condition.

Syntax:

{
  $if: {
    condition: <boolean-expression>,
    then: <schema-node>,
    else?: <schema-node>
  }
}

Example:

{
  type: '$if',
  props: {
    condition: { $store: 'modalStore.isOpen' },
    then: {
      type: 'we-modal',
      props: { ... },
      children: [ ... ]
    },
    else: {
      type: 'we-text',
      children: ['Modal closed']
    }
  }
}

Notes:

  • else branch is optional
  • Automatically unwraps accessors in condition

$not

Logical NOT operator.

Syntax:

{ $not: <boolean-expression> }

Example:

{
  condition: {
    $not: {
      $store: 'userStore.isLoggedIn';
    }
  }
}

Comparison Operators

$eq

Equality comparison.

Syntax:

{ $eq: [<value1>, <value2>] }

Example:

{
  condition: {
    $eq: [{ $store: 'userStore.role' }, 'admin'];
  }
}

$ne

Not equal comparison.

Syntax:

{ $ne: [<value1>, <value2>] }

Example:

{
  condition: {
    $ne: [{ $store: 'templateStore.currentId' }, 'default'];
  }
}

Composing Operators

Operators can be composed together for complex logic:

{
  type: 'PopoverMenu',
  props: {
    // Transform array of templates
    options: {
      $map: {
        items: { $store: 'templateStore.templates' },
        select: {
          id: '$item.id',
          name: '$item.meta.name',
          icon: '$item.meta.icon'
        }
      }
    },
    // Transform single template object
    selectedOption: {
      $map: {
        items: { $store: 'templateStore.currentTemplate' },
        select: {
          id: '$item.id',
          name: '$item.meta.name',
          icon: '$item.meta.icon'
        }
      }
    },
    // Extract id from selected option and pass to action
    onSelect: {
      $action: 'templateStore.switchTemplate',
      args: ['$arg.id']
    }
  }
}

Best Practices

  1. Use $map for transformation, $pick for simple extraction
  2. Use $arg.<path> to extract properties in action callbacks
  3. Keep expressions simple - complex logic should be in stores
  4. Leverage composition - combine operators for complex scenarios
  5. Handle edge cases - operators return safe defaults (empty arrays, undefined, etc.)

Error Handling

  • Missing store/property: Returns undefined
  • Invalid $expr: Returns undefined and logs error
  • Non-array/object in $map: Returns []
  • Missing action method: Returns undefined
  • Invalid $arg path: Returns undefined