# Examples

Copy-paste-friendly snippets for common AsukaDesigner workflows.

## 1. Minimal package setup

```ts
import { createAsukaDesigner } from 'asuka-designer';

const designer = createAsukaDesigner('#app');
```

## 2. Minimal browser setup

```html
<div id="app"></div>
<link rel="stylesheet" href="./dist/product/asukadesigner.min.css" />
<script type="module">
  import { createAsukaDesigner } from './dist/product/asukadesigner.min.js';
  const designer = createAsukaDesigner('#app');
</script>
```

## 3. Product-designer layout

```ts
const designer = createAsukaDesigner('#app', {
  layout: {
    left: {
      items: [
        { kind: 'views', label: 'Views', icon: 'views', type: 'floating' },
        { kind: 'designs', label: 'Designs', icon: 'brush', type: 'floating' },
        { kind: 'text', label: 'Text', icon: 'text', type: 'floating' },
        { kind: 'image', label: 'Images', icon: 'images', type: 'floating' },
        { kind: 'shapes', label: 'Shapes', icon: 'customize', type: 'floating' },
        { kind: 'layers', label: 'Layers', icon: 'layers', type: 'floating' },
        { kind: 'marker', label: 'Marker', icon: 'marker', type: 'floating' },
        { kind: 'drawingAreas', label: 'Drawing Areas', icon: 'pencil', type: 'floating' },
        { kind: 'elements', label: 'Elements', icon: 'puzzle', type: 'floating' },
      ],
    },
    top: {
      collapsed: false,
      items: [
        { kind: 'magnifier', label: 'Magnifier', icon: 'magnifying-glass', type: 'floating' },
        { kind: 'ruler', label: 'Ruler', icon: 'ruler', type: 'floating' },
        { kind: 'zoom', label: 'Zoom', icon: 'zoom', type: 'floating' },
        { kind: 'download', label: 'Download', icon: 'download', type: 'floating' },
      ],
    },
    right: { items: [] },
    bottom: { items: [] },
  },
});
```

No `zone` property is needed on items.

## 4. Drawer mounted in a custom container

```ts
const designer = createAsukaDesigner('#app', {
  layout: {
    left: {
      items: [
        {
          kind: 'download',
          label: 'Download',
          icon: 'download',
          type: 'drawer',
          mountTarget: '#download-drawer-host',
        },
      ],
    },
  },
});
```

Runtime:

```ts
designer.util.modules.setMountTarget('download', '#download-drawer-host');
designer.util.modules.clearMountTarget('download');
```

## 5. Right sidebar as panels

```ts
const designer = createAsukaDesigner('#app', {
  layout: {
    right: {
      type: 'panels',
      items: [
        { kind: 'layers', label: 'Layers', icon: 'layers', type: 'floating' },
        { kind: 'views', label: 'Views', icon: 'views', type: 'floating' },
      ],
    },
  },
});
```

```ts
designer.layout.setZoneType('right', 'panels');
designer.layout.setZoneType('right', 'inline');
designer.layout.setZoneType('right', 'default');
```

## 6. Configure the contextual selection menu

```ts
const designer = createAsukaDesigner('#app', {
  layout: {
    selectionMenu: {
      type: 'popover',
      items: ['font-family', 'text-formatting', 'text-curve', 'colors'],
      open: true,
    },
  },
});
```

Runtime:

```ts
designer.layout.selectionMenu.setItems(['font-family', 'text-formatting', 'colors']);
designer.layout.selectionMenu.setType('popover');
```

## 7. Work with multiple views

```ts
const frontId = designer.api.getActiveViewId();
const backId = designer.api.addView({ name: 'Back' });

designer.api.setActiveView(backId);
await designer.api.addText({ text: 'Back side' });

designer.api.setActiveView(frontId);
```

## 8. Add text, images, and shapes

```ts
await designer.api.addText({
  text: 'Headline',
  fontSize: 56,
  fontWeight: '700',
});

await designer.api.addImage({
  url: 'https://example.com/image.png',
  name: 'Example image',
});

await designer.engine.canvas2d?.addShape({
  kind: 'rect',
  width: 180,
  height: 100,
  fill: '#111827',
});
```

## 9. Configure upload strategy

```ts
const designer = createAsukaDesigner('#app', {
  moduleConfig: {
    upload: {
      strategy: 'remote',
      endpoint: '/upload.php',
      method: 'POST',
      mapResponseToUrl: (json) => json.url,
    },
  },
});
```

Per-call override:

```ts
await designer.api.addImage({
  file,
  upload: {
    strategy: 'remote',
    endpoint: '/upload.php',
    method: 'POST',
    fieldName: 'image',
    mapResponseToUrl: (json) => json.url,
  },
});
```

Custom handler override:

```ts
await designer.api.addImage({
  file,
  upload: {
    strategy: 'remote',
    handler: async (file) => {
      const body = new FormData();
      body.append('image', file, file.name);
      const response = await fetch('/api/asuka/upload', { method: 'POST', body });
      const json = await response.json();
      return json.url;
    },
  },
});
```

The configured upload policy is also reused by `MediaInput`, `ImageField`, and `IconField`.

## 10. Configure external image providers

```ts
const designer = createAsukaDesigner('#app', {
  integrations: {
    pixabay: { apiKey: '...' },
    pexels: { apiKey: '...' },
  },
});
```

Provider modules are only shown when the corresponding integration is available and allowed by permissions/licence features.

## 11. Configure fonts

```ts
const designer = createAsukaDesigner('#app', {
  fonts: {
    system: [{ family: 'Arial' }, { family: 'Georgia' }],
    google: [
      { family: 'Inter', weights: [400, 600, 700] },
      { family: 'Poppins', weights: [400, 500, 700] },
    ],
    custom: [
      {
        family: 'MyFont',
        url: '/fonts/my-font.woff2',
        format: 'woff2',
        weight: 400,
        style: 'normal',
      },
    ],
  },
});
```

Runtime:

```ts
designer.api.addSystemFont({ family: 'Arial' });
await designer.api.addGoogleFont({ family: 'Inter', weights: [400, 700] });
await designer.api.addCustomFont({ family: 'MyFont', url: '/fonts/my-font.woff2', format: 'woff2' });
```

## 12. Full state save and restore

```ts
const fullState = designer.util.state.exportFull();
await saveToDatabase(fullState);
```

```ts
const fullState = await loadFromDatabase();

const restored = createAsukaDesigner('#app', {
  initialState: fullState,
});
```

## 13. Document-only save and restore

```ts
const documentState = designer.util.state.exportPart('document');
await saveDesign(documentState);
```

```ts
const documentState = await loadDesign();

const restored = createAsukaDesigner('#app', {
  initialState: documentState,
});
```

## 14. Local draft recovery

```ts
const saveDraft = () => {
  designer.util.state.saveToStorage(designer.util.state.exportFull(), {
    key: 'asuka-draft',
  });
};

const restored = designer.util.state.loadFromStorage({ key: 'asuka-draft' });
if (restored) {
  designer.util.state.importFull(restored);
}
```

## 15. Download/export

```ts
await designer.engine.exports.download(undefined, { format: 'png' });
await designer.engine.exports.downloadAllViews({ format: 'png' });
```

## 16. Pricing

```ts
const total = designer.api.getPrice(29.99);
const formatted = designer.util.formatPrice(total);
const breakdown = designer.api.getPriceUiBreakdown(29.99);
```

## 17. Permissions

```ts
const designer = createAsukaDesigner('#app', {
  permissions: {
    canAddText: true,
    canUploadImage: false,
    canDeleteObject: false,
    canDownload: true,
  },
});
```

## 18. Translations

```ts
const designer = createAsukaDesigner('#app', {
  i18n: {
    locale: 'fr',
    fallbackLocale: 'en',
    translations: {
      fr: {
        common: {
          save: 'Enregistrer',
          cancel: 'Annuler',
          close: 'Fermer',
        },
        menu: {
          views: 'Vues',
          layers: 'Calques',
          download: 'Télécharger',
        },
      },
    },
  },
});
```

## 19. Add a custom module

```ts
designer.registerModule({
  id: 'my-module',
  label: 'My module',
  icon: 'puzzle',
  displayMode: 'floating',
  render: ({ context }) => context.ui.el('div', null, 'Hello from a custom module'),
});

designer.layout.addItem('left', {
  kind: 'my-module',
  label: 'My module',
  icon: 'puzzle',
  type: 'floating',
});
```

The same module can be declared as an initialization shortcut when it only has
one layout placement:

```js
const designer = createAsukaDesigner('#app', {
  layout: {
    left: {
      items: [{
        kind: 'my-module',
        label: 'My module',
        icon: 'puzzle',
        type: 'floating',
        module: {
          supportedEngines: ['fabric', '3d'],
          render: ({ context }) => context.ui.el('div', null, 'Hello from a custom module'),
        },
      }],
    },
  },
});
```

## 20. Shell sizing and responsive controls

```ts
const designer = createAsukaDesigner('#app', {
  shell: {
    width: '100%',
    height: '80vh',
    maxWidth: '1440px',
  },
  uiScaling: {
    keepControlsReadable: true,
    keepHelpersReadable: true,
    baseControlSize: 20,
    baseTouchControlSize: 28,
    minHelperStrokeWidth: 1,
  },
});
```

## 21. Debug boot/state/layout

```ts
const designer = createAsukaDesigner('#app', {
  debug: {
    boot: true,
    state: true,
    layout: true,
  },
});
```

## Suggested reading order

1. [Quick start](./quick-start.md)
2. [API overview](./api-overview.md)
3. [Layout](./layout.md)
4. [Overlays and mount targets](./overlays.md)
5. [Built-in modules](./modules-built-in.md)
6. [Custom modules](./modules-custom.md)
7. [Internationalization](./i18n.md)
8. [Translation keys reference](./translation-keys.md)
9. [State and persistence](./state-and-persistence.md)
10. [Events and listeners](./events-and-listeners.md)
## 13. Replace the product/template state at runtime

A complete browser-global HTML example is available here:

```txt
examples/replace-state-hot.html
```

The recommended flow for replacing a full product/template is:

```js
const fullState = await fetch('/api/templates/template-1/state').then((response) => response.json());

designer = designer.util.state.replaceProduct(fullState, {
  recreate: true,
});
```

When your backend returns only a document payload, use:

```js
designer.util.state.importPart('document', documentState, {
  replaceViews: true,
  replaceSnapshots: true,
});

designer.util.state.rebuildActiveViewFromDocument();
```

For host-driven imports in a restricted production UI, keep the UI actions hidden but allow the runtime import permissions:

```js
permissions: {
  canUseStateTools: true,
  canImportJson: true,
}
```
