# @interopio/workspaces-ui-web-components

This is a library based on [Web Components](https://developer.mozilla.org/en-US/docs/Web/API/Web_components) for building a custom [Workspaces App](https://docs.interop.io/desktop/capabilities/windows/workspaces/overview/index.html#workspaces_concepts-frame) for [**io.Connect Desktop**](https://docs.interop.io/desktop/getting-started/what-is-io-connect-desktop/general-overview/index.html) or [**io.Connect Browser**](https://docs.interop.io/browser/getting-started/what-is-io-connect-browser/index.html) projects. Internally, the [`@interopio/workspaces-ui-web-components`](https://www.npmjs.com/package/@interopio/workspaces-ui-web-components) library uses the [`lit`](https://www.npmjs.com/package/lit) package.

## Prerequisites

To be able to create and use a Workspaces App, the following is required:

- a licensed [**io.Connect Desktop**](https://docs.interop.io/desktop/getting-started/what-is-io-connect-desktop/general-overview/index.html) or [**io.Connect Browser**](https://docs.interop.io/browser/getting-started/what-is-io-connect-browser/index.html) platform;

- for **io.Connect Desktop**, you must have a valid [Workspaces App definition](https://docs.interop.io/desktop/developers/configuration/application/index.html#app_definition-workspaces_app);

- for **io.Connect Browser**, you must [enable Workspaces](https://docs.interop.io/browser/capabilities/windows/workspaces/enabling-workspaces/index.html) properly in your [Main app](https://docs.interop.io/browser/developers/browser-platform/overview/index.html) (Browser Platform);

## Installation

To use the library in your project, execute the following command:

```cmd
npm install @interopio/workspaces-ui-web-components
```

## Usage

The [`@interopio/workspaces-ui-web-components`](https://www.npmjs.com/package/@interopio/workspaces-ui-web-components) library exports default Web Components and types for that enable you to customize the structure of your Workspaces App. The library also exposes an API with methods that provide the default Workspaces App functionalities. You can use the default components directly, or you can replace them with your custom ones.

### Creating Custom Components

To create a custom component for your Workspaces App, it's recommended to define a custom class the implements the interface of the respective default component exported by the library. This will help you determine the default properties that will be set by the library and passed to your custom component.

The following example demonstrates how to implement custom components for the Workspaces Logo element, the Workspace Tab element, and the Group Header Buttons element of the Workspaces App:

```javascript
import { GroupHeaderButtonsElement, WorkspacesLogoElement, WorkspaceTabElement, } from "@interopio/workspaces-ui-web-components";

// Replacing the Workspaces App logo.
export class CustomWorkspacesLogo extends HTMLElement implements WorkspacesLogoElement {
    constructor() {
        super();

        const shadow = this.attachShadow({ mode: "open" });
        const customLogo = document.createElement("div");

        customLogo.innerHTML = "My Custom Logo";
        shadow.appendChild(customLogo);
    }
};

customElements.define("custom-workspaces-logo", CustomWorkspacesLogo);

// Replacing the default Workspace tab with a custom one.
// This will replace all Workspace tabs in the Workspaces App.
export class CustomWorkspacesTab extends HTMLElement implements WorkspaceTabElement {
    private customContent: HTMLDivElement;
    private _isSelected = false;

    constructor() {
        super();

        const shadow = this.attachShadow({ mode: "open" });

        this.customContent = document.createElement("div");
        this.changeSelectedText();

        shadow.appendChild(this.customContent);
    }

    public get isSelected(): boolean {
        return this._isSelected;
    }

    public set isSelected(value: boolean) {
        this._isSelected = value;
        this.changeSelectedText();
    }

    private changeSelectedText() {
        this.customContent.innerHTML = this.isSelected ? "Selected" : "Not Selected";
    }
};

customElements.define("custom-workspaces-tab", CustomWorkspacesTab);

// Replacing the default group header buttons with a custom button.
// This will replace the buttons in all window groups within the Workspace.
export class CustomGroupHeaderButtons extends HTMLElement implements GroupHeaderButtonsElement {
    constructor() {
        super();

        let count = 0;

        const shadow = this.attachShadow({ mode: "open" });
        const btn = document.createElement("button");

        btn.innerText = "Add";
        btn.addEventListener("click", () => {
            count++;
            span.innerText = count.toString();
        });

        const span = document.createElement("span");

        span.innerText = "0";

        shadow.appendChild(btn);
        shadow.appendChild(span);
    }
};

customElements.define("custom-group-header-buttons", CustomGroupHeaderButtons);
```

### Creating a Custom Workspaces App

After defining your custom components, you must pass them to the main `Workspaces` component by using its `components` property in order to create your custom Workspaces App. You must also initialize the respective io.Connect library with the proper configuration and either pass the initialized API object as a value to the `io` property of the `Workspaces` component, or attach it to the global `window` object. For **io.Connect Desktop** projects, you must initialize and configure the [`@interopio/desktop`](https://www.npmjs.com/package/@interopio/desktop) library. For **io.Connect Browser** projects, you must initialize and configure either the [`@interopio/browser-platform`](https://www.npmjs.com/package/@interopio/browser-platform) or the [`@interopio/browser`](https://www.npmjs.com/package/@interopio/browser) library, depending on whether you'll [use the Workspaces App as a Main app](https://docs.interop.io/browser/capabilities/windows/workspaces/enabling-workspaces/index.html#main_app-using_the_main_app_as_a_workspaces_app). Without the properly initialized io.Connect API object, the [`@interopio/workspaces-ui-web-components`](https://www.npmjs.com/package/@interopio/workspaces-ui-web-components) library won't be able to function.

#### io.Connect Desktop

The following example demonstrates how to create a custom Workspaces App for an **io.Connect Desktop** project and properly initialize the [`@interopio/desktop`](https://www.npmjs.com/package/@interopio/desktop) library:

```javascript
import Workspaces from "@interopio/workspaces-ui-web-components";
import IODesktop from "@interopio/desktop";
import IOWorkspaces from "@interopio/workspaces-api";
import { CustomWorkspacesLogo, CustomWorkspacesTab, CustomGroupHeaderButtons } from "./MyCustomComponents"

// Configuration for the `@interopio/desktop` library.
// It's mandatory to provide the factory function for initializing the Workspaces API,
// and also to initialize the App Management API in `"skipIcons"` or `"full"` mode.
const config = {
    libraries: [IOWorkspaces],
    appManager: "skipIcons"
};

// Initializing the `@interopio/desktop` library.
const io = await IODesktop(config);

// Attaching the initialized API object to the global `window` object.
window.io = io;

// Alternatively, you can use the `io` property of the instantiated `Workspaces` component
// to pass the initialized io.Connect API to the `@interopio/workspaces-ui-web-components` library:
// workspacesElement.io = io;

const workspacesElement = new Workspaces();

// Passing custom components to the `Workspaces` component.
workspacesElement.components = {
    header: {
        logo: CustomWorkspacesLogo,
        workspaceTab: CustomWorkspacesTab
    },
    groupHeader: {
        buttons: CustomGroupHeaderButtons
    }
};

// Rendering the Workspaces App.
document.body.appendChild(workspacesElement);
```

#### io.Connect Browser

The following example demonstrates how to create a custom Workspaces App for an **io.Connect Browser** project and properly [enable Workspaces](https://docs.interop.io/browser/capabilities/windows/workspaces/enabling-workspaces/index.html) when your Workspaces App will be used as a Main app as well:

```javascript
import Workspaces from "@interopio/workspaces-ui-web-components";
import IOBrowserPlatform from "@interopio/browser-platform";
import IOWorkspaces from "@interopio/workspaces-api";
import { CustomWorkspacesLogo, CustomWorkspacesTab, CustomGroupHeaderButtons } from "./MyCustomComponents"

// Configuration for the `@interopio/browser-platform` library.
const config = {
    licenseKey: "my-license-key",
    workspaces: {
        // Provide the location of your Workspaces App.
        src: "https://my-workspaces-app.com",
        // Specify that your Workspaces App will be a Main app too.
        isFrame: true
    },
    browser: {
        // Provide the factory function for initializing the Workspaces API.
        libraries: [IOWorkspaces]
    }
};

// Initializing the `@interopio/browser-platform` library.
const { io } = await IOBrowserPlatform(config);

// Attaching the initialized API object to the global `window` object.
window.io = io;

// Alternatively, you can use the `io` property of the instantiated `Workspaces` component
// to pass the initialized io.Connect API to the `@interopio/workspaces-ui-web-components` library:
// workspacesElement.io = io;

const workspacesElement = new Workspaces();

// Passing custom components to the `Workspaces` component.
workspacesElement.components = {
    header: {
        logo: CustomWorkspacesLogo,
        workspaceTab: CustomWorkspacesTab
    },
    groupHeader: {
        buttons: CustomGroupHeaderButtons
    }
};

// Rendering the Workspaces App.
document.body.appendChild(workspacesElement);
```