# Auto-Generated Packages

## Overview

Myop's **Auto-Generated Packages** feature automatically creates framework-specific npm packages for your Myop components. These packages provide fully typed, tree-shakeable wrappers that integrate seamlessly with your application's framework, enabling a superior developer experience with IDE autocompletion and type safety.

## Table of Contents

- [How It Works](#how-it-works)
- [Benefits](#benefits)
- [Installation](#installation)
- [Framework-Specific Guides](#framework-specific-guides)
  - [React](#react)
  - [Vue](#vue)
  - [Angular](#angular)
  - [TypeScript (Vanilla)](#typescript-vanilla)
  - [React Native](#react-native)
- [Type Definitions](#type-definitions)
- [Configuration Options](#configuration-options)
- [Best Practices](#best-practices)

## How It Works

When you create a Myop HTML component with type definitions, the Myop server automatically generates npm-installable packages for each supported framework. These packages are:

1. **Generated on-demand**: Packages are created dynamically when requested via the npm install URL
2. **Framework-specific**: Each package includes proper peer dependencies and idioms for its target framework
3. **Fully typed**: TypeScript declarations are extracted from your component's `<script type="myop/types">` block
4. **Thin wrappers**: The actual component logic runs at runtime - packages only contain typed wrapper code (~6KB total)

### Package Generation Flow

```
Your HTML Component
        ↓
<script type="myop/types">
  interface MyopInitData { ... }
  interface MyopCtaPayloads { ... }
</script>
        ↓
Myop Server extracts types
        ↓
Generates framework-specific package
        ↓
Returns npm-installable .tgz
```

## Benefits

| Benefit | Description |
|---------|-------------|
| **Type Safety** | Full TypeScript support with IDE autocompletion for data and events |
| **Zero Bundle Bloat** | ~6KB total for all components regardless of quantity |
| **Hot Updates** | Update components without redeploying your application |
| **Developer Experience** | Typed event handlers auto-generated from your CTA definitions |
| **Framework Native** | Packages feel native to each framework's patterns and idioms |
| **No Build Step** | Install directly from URL - no compilation required |

## Installation

Auto-generated packages are installed directly from the Myop API using a URL-based npm install:

```bash
# General pattern
npm install https://cloud.myop.dev/npm/{component-id}/{framework}

# Example for React
npm install https://cloud.myop.dev/npm/abc123-def456/react

# Example for Vue
npm install https://cloud.myop.dev/npm/abc123-def456/vue

# Example for Angular
npm install https://cloud.myop.dev/npm/abc123-def456/angular

# Example for TypeScript/Vanilla JS
npm install https://cloud.myop.dev/npm/abc123-def456/typescript

# Example for React Native
npm install https://cloud.myop.dev/npm/abc123-def456/react-native
```

### Package.json Reference

You can also add packages directly to your `package.json`:

```json
{
  "dependencies": {
    "@myop/users-table": "https://cloud.myop.dev/npm/abc123-def456/react",
    "@myop/dashboard-widget": "https://cloud.myop.dev/npm/xyz789-uvw012/react"
  }
}
```

## Framework-Specific Guides

### React

#### Installation

```bash
# Install the host package (required)
npm install @myop/react @myop/sdk

# Install your auto-generated component
npm install https://cloud.myop.dev/npm/{component-id}/react
```

#### Usage

```tsx
import { UsersTable } from "@myop/users-table";

function App() {
  const users = [
    { id: 1, name: "Alice", email: "alice@example.com", role: "Admin" },
    { id: 2, name: "Bob", email: "bob@example.com", role: "User" },
  ];

  return (
    <UsersTable
      data={{ rows: users }}
      onRowClicked={(payload) => {
        console.log("Selected user:", payload.rowData);
      }}
      onDeleteClicked={(payload) => {
        deleteUser(payload.userId);
      }}
      onExportRequested={(payload) => {
        exportToFormat(payload.format);
      }}
      style={{ width: 600, height: 400 }}
    />
  );
}
```

#### Generated Package Structure

The React package generates a `forwardRef` wrapper component:

```typescript
import { MyopComponent } from "@myop/react";
import { forwardRef } from "react";

export const UsersTable = forwardRef<any, UsersTableProps>((props, ref) => (
  <MyopComponent
    {...props}
    componentId="{component-id}"
    ref={ref}
  />
));
```

#### Peer Dependencies

- `react >= 17.0.0`
- `@myop/react`

---

### Vue

#### Installation

```bash
# Install the host package (required)
npm install @myop/vue @myop/sdk

# Install your auto-generated component
npm install https://cloud.myop.dev/npm/{component-id}/vue
```

#### Usage

```vue
<script setup lang="ts">
import { UsersTable } from "@myop/users-table";
import { ref } from "vue";

const users = ref([
  { id: 1, name: "Alice", email: "alice@example.com", role: "Admin" },
  { id: 2, name: "Bob", email: "bob@example.com", role: "User" },
]);

function handleRowClicked(payload: { rowIndex: number; rowData: any }) {
  console.log("Selected user:", payload.rowData);
}

function handleDeleteClicked(payload: { userId: string }) {
  deleteUser(payload.userId);
}
</script>

<template>
  <UsersTable
    :data="{ rows: users }"
    @row-clicked="handleRowClicked"
    @delete-clicked="handleDeleteClicked"
    :style="{ width: '600px', height: '400px' }"
  />
</template>
```

#### Generated Package Structure

The Vue package generates a `defineComponent` wrapper:

```typescript
import { defineComponent, h } from "vue";
import { MyopComponent } from "@myop/vue";

export const UsersTable = defineComponent({
  name: "UsersTable",
  props: { /* typed props */ },
  emits: ["load", "error", "sizeChange", "cta", "row-clicked", "delete-clicked"],
  setup(props, { emit }) {
    return () => h(MyopComponent, {
      ...props,
      componentId: "{component-id}",
      onLoad: (component) => emit("load", component),
      onCta: (action, payload) => emit(action, payload),
    });
  },
});
```

#### Peer Dependencies

- `vue >= 3.0.0`
- `@myop/vue`

---

### Angular

#### Installation

```bash
# Install the host package (required)
npm install @myop/angular @myop/sdk

# Install your auto-generated component
npm install https://cloud.myop.dev/npm/{component-id}/angular
```

#### tsconfig.json Configuration

For Angular, you must configure TypeScript to compile from node_modules:

```json
{
  "compilerOptions": {
    "outDir": "./out-tsc/app"
  },
  "include": [
    "src/**/*.d.ts",
    "src/**/*.ts",
    "node_modules/@myop/**/*.ts"
  ]
}
```

#### Usage

```typescript
import { Component } from "@angular/core";
import { UsersTable } from "@myop/users-table";

@Component({
  selector: "app-root",
  standalone: true,
  imports: [UsersTable],
  template: `
    <users-table
      [data]="{ rows: users }"
      (rowClicked)="onRowClicked($event)"
      (deleteClicked)="onDeleteClicked($event)"
      [style]="{ width: '600px', height: '400px' }"
    />
  `,
})
export class AppComponent {
  users = [
    { id: 1, name: "Alice", email: "alice@example.com", role: "Admin" },
    { id: 2, name: "Bob", email: "bob@example.com", role: "User" },
  ];

  onRowClicked(payload: { rowIndex: number; rowData: any }) {
    console.log("Selected user:", payload.rowData);
  }

  onDeleteClicked(payload: { userId: string }) {
    this.deleteUser(payload.userId);
  }
}
```

#### Generated Package Structure

The Angular package generates a standalone component:

```typescript
import { Component, Input, Output, EventEmitter } from "@angular/core";
import { MyopComponent } from "@myop/angular";

@Component({
  selector: "users-table",
  standalone: true,
  imports: [MyopComponent],
  template: `
    <myop-component
      [componentId]="componentId"
      [data]="data"
      (load)="load.emit($event)"
      (cta)="handleCta($event)"
    />
  `,
})
export class UsersTable {
  componentId = "{component-id}";

  @Input() data: UsersTableData | undefined;
  @Output() load = new EventEmitter<any>();
  @Output() rowClicked = new EventEmitter<RowClickedPayload>();
  @Output() deleteClicked = new EventEmitter<DeleteClickedPayload>();

  handleCta(event: { action: string; payload: any }) {
    // Route to typed output
  }
}
```

#### Peer Dependencies

- `@angular/core >= 17.0.0`
- `@myop/angular`

---

### TypeScript (Vanilla)

For vanilla JavaScript/TypeScript applications without a framework.

#### Installation

```bash
# Install the SDK (required)
npm install @myop/sdk

# Install your auto-generated component
npm install https://cloud.myop.dev/npm/{component-id}/typescript
```

#### Usage

```typescript
import { createUsersTable } from "@myop/users-table";

async function initComponent() {
  const usersTable = await createUsersTable({
    container: document.getElementById("users-table-container"),
    data: {
      rows: [
        { id: 1, name: "Alice", email: "alice@example.com", role: "Admin" },
        { id: 2, name: "Bob", email: "bob@example.com", role: "User" },
      ],
    },
    onLoad: (component) => {
      console.log("Component loaded:", component);
    },
    onError: (error) => {
      console.error("Error:", error);
    },
    // Generic CTA handler
    onCta: (action, payload) => {
      console.log("Action:", action, "Payload:", payload);
    },
    // Typed action handlers (auto-generated from CTA definitions)
    onRowClicked: (payload) => {
      console.log("Row clicked:", payload.rowData);
    },
    onDeleteClicked: (payload) => {
      deleteUser(payload.userId);
    },
  });

  // Wait for initialization
  await usersTable.initiated();

  // Update data
  usersTable.update({ rows: newUsers });

  // Get current data
  const currentData = usersTable.getData();

  // Subscribe to specific actions
  usersTable.on("export-requested", (payload) => {
    exportToFormat(payload.format);
  });

  // Cleanup
  usersTable.dispose();
}
```

#### Generated Package Structure

The TypeScript package generates a factory function:

```typescript
import { hostSDK } from "@myop/sdk/host";
import { CloudRepository } from "@myop/sdk/helpers";

export interface CreateUsersTableOptions {
  container: HTMLElement;
  data?: UsersTableData;
  onLoad?: (component: any) => void;
  onError?: (error: string) => void;
  onCta?: (action: string, payload: any) => void;
  onRowClicked?: (payload: RowClickedPayload) => void;
  onDeleteClicked?: (payload: DeleteClickedPayload) => void;
}

export async function createUsersTable(options: CreateUsersTableOptions) {
  const config = await CloudRepository.Main.fetchComponentV2("{component-id}");
  const component = await hostSDK.loadComponent(config, options.container, {
    data: options.data,
  });

  // Setup handlers and return interface...
  return {
    update: (data) => component.props.myop_init_interface(data),
    getData: () => component.props,
    on: (action, handler) => { /* subscribe */ },
    onRowClicked: (handler) => { /* typed subscribe */ },
    dispose: () => component.dispose(),
    initiated: () => component.initiated(),
  };
}
```

#### Peer Dependencies

- `@myop/sdk`

---

### React Native

For React Native mobile applications using WebView.

#### Installation

```bash
# Install the host package (required)
npm install @myop/react-native react-native-webview

# Install your auto-generated component
npm install https://cloud.myop.dev/npm/{component-id}/react-native
```

#### Usage

```tsx
import React, { useState } from "react";
import { View, StyleSheet } from "react-native";
import { UsersTable } from "@myop/users-table";

function App() {
  const [component, setComponent] = useState(null);

  const users = [
    { id: 1, name: "Alice", email: "alice@example.com", role: "Admin" },
    { id: 2, name: "Bob", email: "bob@example.com", role: "User" },
  ];

  return (
    <View style={styles.container}>
      <UsersTable
        data={{ rows: users }}
        onLoad={(proxy) => setComponent(proxy)}
        onError={(error) => console.error("Error:", error)}
        onRowClicked={(payload) => {
          console.log("Row clicked:", payload.rowData);
        }}
        onDeleteClicked={(payload) => {
          deleteUser(payload.userId);
        }}
        style={styles.table}
        scrollEnabled={false}
        zoomEnabled={false}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1 },
  table: { flex: 1 },
});
```

#### Component Proxy Interface

The `onLoad` callback provides a proxy for programmatic control:

```typescript
interface IMyopComponentProxy {
  id: string;

  props: {
    myop_init_interface: (data: any) => void;
    myop_cta_handler: ((action: string, payload?: any) => void) | null;
  };

  element: {
    set(path: string, value: any): void;
    get(path: string): Promise<any>;
    style: {
      set(property: string, value: string): void;
      get(property: string): Promise<string>;
    };
  };

  dispose(): void;
  hide(): void;
  show(): void;
  inspect(): void;
}
```

#### Generated Package Structure

The React Native package generates a `forwardRef` wrapper with `useImperativeHandle`:

```typescript
import { MyopComponent } from "@myop/react-native";
import { forwardRef, useImperativeHandle } from "react";

export const UsersTable = forwardRef<any, UsersTableProps>((props, ref) => {
  const componentRef = useRef(null);

  useImperativeHandle(ref, () => ({
    update: (data) => componentRef.current?.props.myop_init_interface(data),
    getComponent: () => componentRef.current,
  }));

  return (
    <MyopComponent
      {...props}
      componentId="{component-id}"
      onLoad={(proxy) => {
        componentRef.current = proxy;
        props.onLoad?.(proxy);
      }}
    />
  );
});
```

#### Peer Dependencies

- `react >= 17.0.0`
- `react-native >= 0.70.0`
- `@myop/react-native`

---

## Type Definitions

For auto-generated packages to extract types, your Myop HTML component must include a `<script type="myop/types">` block:

```html
<!DOCTYPE html>
<html>
<head>
  <script type="myop/types">
    // Data passed to the component via myop_init_interface
    interface MyopInitData {
      rows: Array<{
        id: number;
        name: string;
        email: string;
        role: string;
      }>;
      columns?: string[];
      sortable?: boolean;
    }

    // Events emitted via myop_cta_handler
    interface MyopCtaPayloads {
      "row-clicked": {
        rowIndex: number;
        rowData: any;
      };
      "delete-clicked": {
        userId: string;
      };
      "export-requested": {
        format: "csv" | "json" | "xlsx";
      };
    }
  </script>
</head>
<body>
  <!-- Component HTML -->
</body>
</html>
```

### Type Naming Conventions

The package generator looks for these type names (in order of preference):

1. `MyopInitData` - Data interface for component initialization
2. `*Props`, `*Input`, `*Config` - Alternative naming patterns
3. First `interface` or `type` declaration

For CTA payloads:

1. `MyopCtaPayloads` - CTA event payloads
2. Second `interface` or `type` declaration

### Action Name Conversion

CTA action names in kebab-case are automatically converted to PascalCase for typed handlers:

| CTA Action | React Handler | Vue Event | Angular Output |
|------------|---------------|-----------|----------------|
| `row-clicked` | `onRowClicked` | `@row-clicked` | `(rowClicked)` |
| `delete-clicked` | `onDeleteClicked` | `@delete-clicked` | `(deleteClicked)` |
| `export-requested` | `onExportRequested` | `@export-requested` | `(exportRequested)` |

---

## Configuration Options

### Preloading Components

Preload components for faster rendering:

```typescript
// React
import { preloadComponents, isPreloaded } from "@myop/react";

await preloadComponents(["component-1", "component-2"]);

if (isPreloaded("component-1")) {
  console.log("Component will render instantly");
}
```

```typescript
// Vue
import { preloadComponents, isPreloaded } from "@myop/vue";

await preloadComponents(["component-1", "component-2"]);
```

```typescript
// Angular
import { preloadComponents, isPreloaded } from "@myop/angular";

await preloadComponents(["component-1", "component-2"]);
```

### Custom Cloud Repository

Configure a custom Myop server URL:

```typescript
// React
import { setCloudRepositoryUrl, enableLocalDev } from "@myop/react";

// Production custom endpoint
setCloudRepositoryUrl("https://custom.myop.dev");

// Local development (localhost:9292)
enableLocalDev();
```

### Environment and Preview Modes

Load components from different environments:

```tsx
// React - Load from staging
<UsersTable
  data={data}
  environment="staging"
/>

// React - Load unpublished preview
<UsersTable
  data={data}
  preview={true}
/>

// React - Staging preview
<UsersTable
  data={data}
  environment="staging"
  preview={true}
/>
```

```vue
<!-- Vue -->
<UsersTable
  :data="data"
  environment="staging"
  :preview="true"
/>
```

```html
<!-- Angular -->
<users-table
  [data]="data"
  environment="staging"
  [preview]="true"
/>
```

---

## Best Practices

### 1. Define Clear Type Contracts

Always provide comprehensive type definitions in your component:

```typescript
interface MyopInitData {
  // Document each field
  /** List of items to display */
  items: Item[];
  /** Optional title for the component */
  title?: string;
  /** Theme configuration */
  theme?: "light" | "dark";
}

interface MyopCtaPayloads {
  /** Fired when an item is selected */
  "item-selected": {
    itemId: string;
    itemData: Item;
  };
}
```

### 2. Use Semantic Action Names

Use descriptive, kebab-case action names:

```typescript
// Good
"file-uploaded"
"user-logged-in"
"form-submitted"
"row-selected"

// Avoid
"click"
"action1"
"doThing"
```

### 3. Leverage Preloading

Preload components on app initialization for instant rendering:

```typescript
// In your app's entry point
import { preloadComponents } from "@myop/react";

// Preload critical components
preloadComponents([
  "dashboard-widget",
  "navigation-menu",
  "user-profile",
]);
```

### 4. Handle Loading and Error States

Always provide loading and error handling:

```tsx
// React
import { MyopLoader, MyopFallback } from "@myop/react";

<UsersTable
  data={data}
  loader={<MyopLoader />}
  fallback={<MyopFallback />}
  fadeDuration={300}
/>
```

```vue
<!-- Vue - Using slots -->
<UsersTable :data="data" :fadeDuration="300">
  <template #loader>
    <CustomLoader />
  </template>
  <template #fallback>
    <ErrorMessage @retry="reload" />
  </template>
</UsersTable>
```

### 5. TypeScript Project Configuration

For Angular projects, ensure your `tsconfig.json` includes node_modules:

```json
{
  "include": [
    "src/**/*.ts",
    "node_modules/@myop/**/*.ts"
  ]
}
```

---

## Additional Resources

- [React Integration Guide](/docs/learnMyop/ReactHost)
- [Vue Integration Guide](/docs/learnMyop/Vue)
- [Angular Integration Guide](/docs/learnMyop/Angular)
- [HTML Component Development](/docs/learnMyop/html-components)
- [Myop Dashboard](https://dashboard.myop.dev)
- [API Documentation](https://docs.myop.dev)