npm package: @servlyadmin/runtime-solid
Description: Solid.js wrapper for Servly runtime renderer
Author: Servly
Latest version: 0.1.36

# @servlyadmin/runtime-solid

Solid.js wrapper for Servly runtime renderer. Render Servly components in your Solid applications with full slot support, state management, and fine-grained reactivity.

## Installation

```bash
npm install @servlyadmin/runtime-solid
# or
yarn add @servlyadmin/runtime-solid
# or
pnpm add @servlyadmin/runtime-solid
```

## Requirements

- Solid.js 1.0.0 or higher
- @servlyadmin/runtime-core (installed automatically)

## Quick Start

```tsx
import { ServlyComponent } from '@servlyadmin/runtime-solid';

function App() {
  return (
    <ServlyComponent
      id="my-component"
      props={{ title: 'Hello World' }}
      onLoad={(data) => console.log('Loaded:', data)}
      onError={(error) => console.error('Error:', error)}
    />
  );
}
```

## API Reference

### ServlyComponent Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `id` | `string` | **required** | Component ID from the registry |
| `version` | `string` | `'latest'` | Version specifier |
| `props` | `object` | `{}` | Props to pass to the component |
| `slots` | `SlotContent` | `undefined` | Slot content keyed by slot name |
| `fallback` | `JSX.Element` | `undefined` | Custom loading UI |
| `errorFallback` | `(error, retry) => JSX.Element` | `undefined` | Custom error UI |
| `onError` | `(error: Error) => void` | `undefined` | Error callback |
| `onLoad` | `(data: ComponentData) => void` | `undefined` | Load callback |
| `onStateChange` | `(event: StateChangeEvent) => void` | `undefined` | State change callback |
| `onReady` | `() => void` | `undefined` | Ready callback |
| `class` | `string` | `undefined` | CSS class for wrapper |
| `style` | `JSX.CSSProperties` | `undefined` | Inline styles |
| `showSkeleton` | `boolean` | `true` | Show loading skeleton |
| `cacheStrategy` | `CacheStrategy` | `'memory'` | Caching strategy |
| `retryConfig` | `Partial<RetryConfig>` | `undefined` | Retry configuration |
| `eventHandlers` | `object` | `undefined` | Event handlers |
| `enableStateManager` | `boolean` | `false` | Enable state management |
| `initialState` | `object` | `undefined` | Initial state |
| `children` | `JSX.Element` | `undefined` | Default slot content |
| `ref` | `(instance) => void` | `undefined` | Instance reference |

### Slot Content

```tsx
import { ServlyComponent } from '@servlyadmin/runtime-solid';

function App() {
  return (
    <ServlyComponent
      id="my-component"
      slots={{
        header: <h1>Custom Header</h1>,
        footer: <p>Custom Footer</p>,
      }}
    >
      {/* Children go to default slot */}
      <p>Default content</p>
    </ServlyComponent>
  );
}
```

### Custom Loading/Error States

```tsx
import { ServlyComponent } from '@servlyadmin/runtime-solid';

function App() {
  return (
    <ServlyComponent
      id="my-component"
      fallback={<div>Loading...</div>}
      errorFallback={(error, retry) => (
        <div>
          <p>Error: {error.message}</p>
          <button onClick={retry}>Retry</button>
        </div>
      )}
    />
  );
}
```

## Advanced Usage

### With State Management

```tsx
import { createSignal } from 'solid-js';
import { ServlyComponent } from '@servlyadmin/runtime-solid';

function Counter() {
  const [count, setCount] = createSignal(0);

  return (
    <ServlyComponent
      id="counter-component"
      props={{ count: count() }}
      enableStateManager
      initialState={{ count: 0 }}
      onStateChange={(event) => {
        if (event.key === 'count') {
          setCount(event.value);
        }
      }}
    />
  );
}
```

### Using Context and Hooks

```tsx
import { ServlyProvider, useServlyContext, useServlyState } from '@servlyadmin/runtime-solid';

function App() {
  return (
    <ServlyProvider initialState={{ user: null }}>
      <UserProfile />
    </ServlyProvider>
  );
}

function UserProfile() {
  const { stateManager } = useServlyContext();
  const { state, set, get } = useServlyState('user');

  return (
    <div>
      <p>User: {state()?.name}</p>
      <button onClick={() => set('user.name', 'John')}>
        Set Name
      </button>
    </div>
  );
}
```

### With Event Handlers

```tsx
import { ServlyComponent } from '@servlyadmin/runtime-solid';

function Form() {
  const handlers = {
    'submit-btn': {
      onClick: (event: Event) => {
        console.log('Submit clicked!');
      },
    },
    'email-input': {
      onChange: (event: Event) => {
        const input = event.target as HTMLInputElement;
        console.log('Email:', input.value);
      },
    },
  };

  return (
    <ServlyComponent
      id="form-component"
      eventHandlers={handlers}
    />
  );
}
```

### Accessing Component Instance

```tsx
import { ServlyComponent, ServlyComponentInstance } from '@servlyadmin/runtime-solid';

function App() {
  let instance: ServlyComponentInstance;

  return (
    <div>
      <ServlyComponent
        id="my-component"
        ref={(inst) => { instance = inst; }}
      />
      <button onClick={() => instance.reload()}>Reload</button>
      <button onClick={() => instance.update({ newProp: 'value' })}>
        Update Props
      </button>
    </div>
  );
}
```

### Reactive Props

```tsx
import { createSignal, createEffect } from 'solid-js';
import { ServlyComponent } from '@servlyadmin/runtime-solid';

function ReactiveExample() {
  const [count, setCount] = createSignal(0);
  const [title, setTitle] = createSignal('Hello');

  // Props are automatically reactive
  return (
    <div>
      <ServlyComponent
        id="my-component"
        props={{
          count: count(),
          title: title(),
        }}
      />
      <button onClick={() => setCount(c => c + 1)}>Increment</button>
      <input
        value={title()}
        onInput={(e) => setTitle(e.currentTarget.value)}
      />
    </div>
  );
}
```

### Version Specifiers

```tsx
// Exact version
<ServlyComponent id="my-component" version="1.2.3" />

// Caret range (compatible with)
<ServlyComponent id="my-component" version="^1.0.0" />

// Tilde range (approximately)
<ServlyComponent id="my-component" version="~1.2.0" />

// Latest version
<ServlyComponent id="my-component" version="latest" />
```

### Caching Strategies

```tsx
// Memory cache (default) - fastest, cleared on page refresh
<ServlyComponent id="my-component" cacheStrategy="memory" />

// LocalStorage cache - persists across sessions
<ServlyComponent id="my-component" cacheStrategy="localStorage" />

// No caching - always fetch fresh
<ServlyComponent id="my-component" cacheStrategy="none" />
```

## TypeScript Support

Full TypeScript support is included:

```typescript
import type {
  ServlyComponentProps,
  ServlyComponentInstance,
  SlotContent,
  ServlyContextValue,
  BindingContext,
  ComponentData,
  StateChangeEvent,
} from '@servlyadmin/runtime-solid';
```

## Re-exported Utilities

```typescript
import {
  // Fetching
  fetchComponent,
  prefetchComponents,
  setRegistryUrl,
  
  // Caching
  invalidateCache,
  clearAllCaches,
  
  // Version utilities
  parseVersion,
  compareVersions,
  
  // State management
  StateManager,
  getValueByPath,
  
  // Event system
  EventSystem,
  getEventSystem,
} from '@servlyadmin/runtime-solid';
```

## Fine-Grained Reactivity

Solid.js's fine-grained reactivity means that only the parts of your component that depend on changed values will update:

```tsx
import { createSignal } from 'solid-js';
import { ServlyComponent } from '@servlyadmin/runtime-solid';

function OptimizedExample() {
  const [a, setA] = createSignal(1);
  const [b, setB] = createSignal(2);

  // Only elements bound to 'a' will update when setA is called
  // Only elements bound to 'b' will update when setB is called
  return (
    <ServlyComponent
      id="my-component"
      props={{ a: a(), b: b() }}
    />
  );
}
```

## License

MIT