> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sdk.fdo.alexvwan.me/llms.txt
> Use this file to discover all available pages before exploring further.

# INJECTED LIBRARIES

# Injected Libraries and Helpers

This document describes the libraries, CSS frameworks, and helper functions that are automatically available in the FDO iframe UI runtime.

These are injected by the FDO application host for plugin UI code. They should not be assumed to exist in the plugin backend/runtime, bootstrap paths, or backend-side render-error fallbacks unless the current host/runtime explicitly proves that.

For the full backend-vs-iframe runtime contract, see [RENDER\_RUNTIME\_CONTRACT.md](./RENDER_RUNTIME_CONTRACT.md).

## Important Boundary: Third-Party Imports

In iframe UI runtime (`render()` / `renderOnLoad()` execution):

* arbitrary npm package `import` / `require` is not a supported contract
* only host-injected globals and helpers are guaranteed

If you need a new UI library in iframe code, it must be added by FDO host injection and documented here first.

Backend/plugin runtime code can still import npm dependencies that are bundled with the plugin artifact.

## Teaching Boundary: Injected Libraries vs DOM Helpers

SDK DOM helpers are still a best practice for general SDK-native structured UI because they give authors a typed, reusable way to build consistent markup and styling.

But this injected-libraries guide serves a different purpose:

* teach iframe-only host-injected globals
* teach browser-only runtime behavior
* teach the `UI_MESSAGE` backend bridge pattern

So examples in this guide may intentionally use plain markup plus `renderOnLoad()` wiring instead of DOM helpers, in order to keep the lesson focused.

Use this rule:

* general SDK-native structured UI: DOM helpers are preferred
* injected-library/runtime-boundary teaching: plain markup is acceptable when it keeps the example focused

If you do use styled DOM helpers in `render()`, `renderHTML(...)` remains mandatory so the extracted goober CSS is emitted with the markup.

## Important Boundary: JSX-Compatible Markup

Even when you use plain markup in injected-library examples, remember that `render()` output is consumed by the FDO host transform, not inserted as unconstrained raw HTML.

That means the safest mental model is:

* plain markup is acceptable here for teaching focus
* but it still needs to be JSX-compatible for the host render pipeline

Examples of what to prefer:

* `<br />` instead of `<br>`
* inline element styles or DOM-helper styling instead of raw `<style>` blocks in `render()`
* escaped code samples inside `<code>` blocks, for example `&#123;` and `&#125;`

Examples of what to avoid:

* raw `<style>` tags in `render()`
* raw object/function braces inside code samples shown directly in JSX-visible markup

Clipboard note:

* if UI code wants to copy data outside the iframe sandbox, prefer a host-mediated clipboard path
* if UI code wants to read clipboard data, also prefer a host-mediated clipboard path
* in the SDK, use the clipboard privileged-action contract instead of assuming direct Electron clipboard access from plugin UI code

## Table of Contents

* [CSS Libraries](#css-libraries)
* [JavaScript Libraries](#javascript-libraries)
* [Window Helper Functions](#window-helper-functions)
* [Usage Examples](#usage-examples)

## CSS Libraries

The following CSS libraries are automatically loaded in the iframe UI runtime:

### Pure CSS (purecss.io)

A set of small, responsive CSS modules that you can use in every web project.

**Available Classes:**

* `.pure-g` - Grid container
* `.pure-u-*` - Grid units (e.g., `.pure-u-1-2` for 50% width)
* `.pure-button` - Button styles
* `.pure-form` - Form layouts
* `.pure-table` - Table styles
* `.pure-menu` - Menu/navigation styles

**Example:**

```html theme={null}
<div class="pure-g">
    <div class="pure-u-1-2">Half width column</div>
    <div class="pure-u-1-2">Half width column</div>
</div>
```

### Highlight.js

Syntax highlighting for code blocks with the "VS" theme.

**Usage:**

```html theme={null}
<pre><code class="language-javascript">
const hello = "world";
</code></pre>
<script>hljs.highlightAll();</script>
```

**Available via:**

* CSS: Pre-loaded VS theme
* JS: `window.hljs` object

### Notyf

Modern notification library for displaying toast messages.

**Available via:**

* CSS: Pre-loaded styles
* JS: `window.Notyf` class

**Example:**

```javascript theme={null}
const notyf = new Notyf({
    duration: 3000,
    position: { x: 'right', y: 'top' }
});
notyf.success('Operation successful!');
notyf.error('Something went wrong!');
```

## JavaScript Libraries

### FontAwesome

Complete icon library with all icon sets (solid, regular, brands).

**Available Sets:**

* FontAwesome Solid
* FontAwesome Regular
* FontAwesome Brands

**Usage:**

```html theme={null}
<i class="fas fa-home"></i>
<i class="far fa-star"></i>
<i class="fab fa-github"></i>
```

### Split Grid

Advanced grid splitter for creating resizable layouts.

**Available via:** `window.Split` function

**Example:**

```javascript theme={null}
Split({
    columnGutters: [{
        track: 1,
        element: document.querySelector('.gutter-col-1'),
    }],
    rowGutters: [{
        track: 1,
        element: document.querySelector('.gutter-row-1'),
    }]
});
```

### Goober

Lightweight CSS-in-JS library (already exposed via SDK's DOM classes).

**Available via:** `window.goober`

**Note:** While goober is loaded, the SDK's DOM classes provide a more convenient interface for styling. Refer to the SDK documentation for usage.

### ACE Editor

Powerful code editor component.

**Available via:** `window.ace`

**Example:**

```javascript theme={null}
const editor = ace.edit("editor");
editor.setTheme("ace/theme/monokai");
editor.session.setMode("ace/mode/javascript");
```

## Window Helper Functions

These helper functions are injected into the iframe UI runtime `window` object.

### `createBackendReq(type, data)`

Creates a request to your plugin's backend transport.

**Parameters:**

* `type` (string): The backend transport type
* `data` (any, optional): The data to send to the backend

**Returns:** `Promise<any>` - The response from the backend

**Example:**

```javascript theme={null}
const result = await window.createBackendReq("UI_MESSAGE", {
    handler: "plugin.getUserData",
    content: { userId: 123 }
});
console.log(result);
```

For production plugins, register handlers in `init()` and call them through `UI_MESSAGE`. Do not assume arbitrary handler names are transport types.

If a `UI_MESSAGE` handler returns a privileged-action envelope for `requestPrivilegedAction`, extract the validated request object before sending it to the host bridge:

```javascript theme={null}
const envelopeOrRequest = await window.createBackendReq("UI_MESSAGE", {
    handler: "plugin.buildPrivilegedRequest",
    content: { /* handler payload */ }
});

const requestPayload =
    envelopeOrRequest?.result?.request ??
    envelopeOrRequest?.request ??
    envelopeOrRequest;

const response = await window.createBackendReq("requestPrivilegedAction", requestPayload);
```

Do not pass the entire backend envelope object directly into `requestPrivilegedAction`.

### `waitForElement(selector, callback, timeout)`

Waits for an element to appear in the DOM.

**Parameters:**

* `selector` (string): CSS selector for the element
* `callback` (function): Callback function called when element is found
* `timeout` (number, optional): Timeout in milliseconds (default: 5000)

**Example:**

```javascript theme={null}
window.waitForElement('#my-dynamic-element', (element) => {
    console.log('Element found:', element);
    element.style.color = 'red';
}, 10000);
```

### `executeInjectedScript(scriptContent)`

Executes a script in the plugin context.

**Parameters:**

* `scriptContent` (string): The JavaScript code to execute

**Example:**

```javascript theme={null}
window.executeInjectedScript(`
    console.log('This code runs in the plugin context');
    // Your dynamic script here
`);
```

### `addGlobalEventListener(eventType, callback)`

Adds a global event listener to the window.

**Parameters:**

* `eventType` (string): The event type (e.g., 'click', 'keydown')
* `callback` (function): The event handler function

**Example:**

```javascript theme={null}
window.addGlobalEventListener('resize', (event) => {
    console.log('Window resized:', window.innerWidth, window.innerHeight);
});
```

### `removeGlobalEventListener(eventType, callback)`

Removes a global event listener from the window.

**Parameters:**

* `eventType` (string): The event type
* `callback` (function): The event handler function to remove

**Example:**

```javascript theme={null}
const handleResize = (event) => {
    console.log('Resize event');
};

window.addGlobalEventListener('resize', handleResize);
// Later...
window.removeGlobalEventListener('resize', handleResize);
```

### `applyClassToSelector(className, selector)`

Applies a CSS class to an element matching the selector.

**Parameters:**

* `className` (string): The CSS class name to add
* `selector` (string): CSS selector for the target element

**Example:**

```javascript theme={null}
window.applyClassToSelector('highlight', '#my-element');
```

## Usage Examples

### Example 1: Creating a Notification System

```javascript theme={null}
export default class NotificationPlugin extends FDO_SDK {
    render() {
        return `
            <div>
                <button onclick="showSuccess()">Show Success</button>
                <button onclick="showError()">Show Error</button>
            </div>
            <script>
                const notyf = new Notyf({
                    duration: 3000,
                    position: { x: 'right', y: 'top' }
                });
                
                function showSuccess() {
                    notyf.success('Operation completed successfully!');
                }
                
                function showError() {
                    notyf.error('An error occurred!');
                }
            </script>
        `;
    }
}
```

### Example 2: Code Editor with Syntax Highlighting

```javascript theme={null}
export default class CodeEditorPlugin extends FDO_SDK {
    render() {
        return `
            <div id="editor" style="height: 400px;"></div>
            <script>
                window.waitForElement('#editor', (element) => {
                    const editor = ace.edit("editor");
                    editor.setTheme("ace/theme/monokai");
                    editor.session.setMode("ace/mode/javascript");
                    editor.setValue("// Start coding...");
                });
            </script>
        `;
    }
}
```

### Example 3: Responsive Grid Layout

```javascript theme={null}
export default class GridLayoutPlugin extends FDO_SDK {
    render() {
        return `
            <div class="pure-g">
                <div class="pure-u-1 pure-u-md-1-2 pure-u-lg-1-3">
                    <div class="pure-button">Column 1</div>
                </div>
                <div class="pure-u-1 pure-u-md-1-2 pure-u-lg-1-3">
                    <div class="pure-button">Column 2</div>
                </div>
                <div class="pure-u-1 pure-u-md-1-2 pure-u-lg-1-3">
                    <div class="pure-button">Column 3</div>
                </div>
            </div>
        `;
    }
}
```

### Example 4: Backend Communication

```javascript theme={null}
export default class DataPlugin extends FDO_SDK {
    init() {
        PluginRegistry.registerHandler("data.getActive", async (content) => {
            return { filter: content?.filter ?? "active", items: [] };
        });
    }
    
    render() {
        return `
            <div id="data-container">Loading...</div>
            <script>
                window.waitForElement('#data-container', async (element) => {
                    try {
                        const data = await window.createBackendReq("UI_MESSAGE", {
                            handler: "data.getActive",
                            content: { filter: "active" }
                        });
                        element.innerHTML = JSON.stringify(data, null, 2);
                    } catch (error) {
                        element.innerHTML = 'Error loading data';
                    }
                });
            </script>
        `;
    }
}
```

### Example 5: Split Panel Layout

```javascript theme={null}
export default class SplitPanelPlugin extends FDO_SDK {
    render() {
        return `
            <style>
                .grid {
                    display: grid;
                    grid-template-columns: 1fr 10px 1fr;
                    height: 400px;
                }
                .gutter {
                    background-color: #ccc;
                    cursor: col-resize;
                }
                .panel {
                    padding: 20px;
                    overflow: auto;
                }
            </style>
            <div class="grid">
                <div class="panel">Left Panel</div>
                <div class="gutter gutter-col-1"></div>
                <div class="panel">Right Panel</div>
            </div>
            <script>
                Split({
                    columnGutters: [{
                        track: 1,
                        element: document.querySelector('.gutter-col-1'),
                    }]
                });
            </script>
        `;
    }
}
```

## Best Practices

1. **Use TypeScript types:** The SDK provides TypeScript definitions for all window helper functions
2. **Error handling:** Always wrap backend requests in try-catch blocks
3. **Element waiting:** Use `waitForElement` instead of `setTimeout` for DOM-dependent code
4. **Cleanup:** Remove event listeners when they're no longer needed
5. **CSP Compliance:** Be aware of Content Security Policy restrictions in the plugin environment

## Additional Resources

* [Pure CSS Documentation](https://purecss.io/)
* [Highlight.js Documentation](https://highlightjs.org/)
* [Notyf Documentation](https://github.com/caroso1222/notyf)
* [FontAwesome Icons](https://fontawesome.com/icons)
* [Split Grid Documentation](https://github.com/nathancahill/split/tree/master/packages/splitjs)
* [ACE Editor Documentation](https://ace.c9.io/)
