# Ordering UI

A Vue.js component library for dynamic JSON-driven UIs with template preprocessing.

## JsonRenderer

Renders Vue components from JSON templates with support for built-in and remote components.

```vue
<template>
  <JsonRenderer 
    :json-template="processedTemplate" 
    :built-in-component-loader="loadBuiltIn"
    :props-loader="loadProps" 
  />
</template>

<script setup>
import { JsonRenderer } from '@/engine'
import { renderJsonWithContext } from '@/preprocessor'

// Context for template processing
const context = {
  userType: 'premium',
  isLoggedIn: true,
  deviceType: 'tablet'
}

// JSON template with conditional rendering using preprocessor
const template = {
  component: 'div',
  props: { class: 'container' },
  children: [
    {
      component: { type: 'BUILT_IN', id: 'OrderButton' },
      props: { variant: 'primary' },
      if: "{{ userType === 'premium' }}" // conditional with template
    },
    {
      component: 'span',
      props: { class: 'welcome-message' },
      children: ["Welcome {{ userType }} user!"],
      if: "{{ isLoggedIn }}"
    },
    {
      component: { type: 'REMOTE', url: 'https://cdn.example.com/components.js', name: 'TabletWidget' },
      propsGetterId: 'widget-123',
      if: "{{ deviceType === 'tablet' && isLoggedIn }}" // complex condition
    }
  ]
}

// Process template with context before rendering
const processedTemplate = renderJsonWithContext(template, context)

// Load built-in components
const loadBuiltIn = async (id) => {
  const { default: component } = await import(`./components/${id}.vue`)
  return component
}

// Load dynamic props
const loadProps = (id) => {
  return { userId: 123, theme: 'dark' }
}
</script>
```

### Passing Components via Props (Static Props Only)

JsonRenderer can resolve `BUILT_IN` / `REMOTE` descriptors inside **static props (top-level only)**.
This is useful for passing a component as a prop to simulate slots.

```js
const template = {
  component: { type: 'BUILT_IN', id: 'Card' },
  props: {
    // top-level static prop only
    headerComponent: { type: 'BUILT_IN', id: 'OrderButton' },
    footerComponent: {
      type: 'REMOTE',
      url: 'https://cdn.example.com/components.js',
      name: 'FooterActions'
    }
  }
}
```

In your receiving component (e.g. `Card`), render the prop with `component`:

```vue
<template>
  <div class="card">
    <component :is="headerComponent" />
    <slot />
    <component :is="footerComponent" />
  </div>
</template>
```

### Component Types

- **HTML tags**: `"div"`, `"button"`, etc.
- **Built-in**: `{ type: 'BUILT_IN', id: 'ComponentName' }`
- **Remote**: `{ type: 'REMOTE', url: 'https://...', name: 'ExportName' }`

## Preprocessor

Processes JSON templates with context variables using `{{ }}` syntax.

```js
import { renderJsonWithContext, renderTemplateWithContext } from '@/preprocessor'

// Template string processing
const template = "Hello {{ name }}, you are {{ age }} years old"
const context = { name: 'John', age: 30 }
const result = renderTemplateWithContext(template, context)
// "Hello John, you are 30 years old"

// Boolean expressions
const condition = "{{ deviceType === 'tablet' }}"
const isTablet = renderTemplateWithContext(condition, { deviceType: 'tablet' })
// true

// JSON object processing
const jsonTemplate = {
  title: "User: {{ name }}",
  enabled: "{{ isActive }}",
  count: "{{ items * 2 }}",
  nested: {
    message: "Status: {{ status === 'active' ? 'online' : 'offline' }}"
  }
}

const processedJson = renderJsonWithContext(jsonTemplate, {
  name: 'Alice',
  isActive: true,
  items: 5,
  status: 'active'
})
// {
//   title: "User: Alice",
//   enabled: true,
//   count: 10,
//   nested: { message: "Status: online" }
// }
```

### Context Rules

- Only primitive values: `string`, `number`, `boolean`, `null`
- No arrays, objects, functions, or undefined
- Template expressions must be JSON-serializable
