# Development Guide: Usage Guide

This guide describes the standard `office-sdk` open flow, parameters, return values, and instance lifecycle. For component-level APIs, see the API Reference.

## Basic Flow#

The example below assumes a native browser ESM page, or that `/office-sdk/UI.js` has already been dynamically loaded as described in Getting Started. When integrating with a Vite, Webpack, or similar application project, use the runtime dynamic import pattern from the getting started guide.

    import "/office-sdk/preload.js";
    import OfficeSdk from "/office-sdk/UI.js";

    const { docType, widget } = await OfficeSdk.openfile(
      {
        docId: "demo-001",
        fileName: "demo.docx",
        file
      },
      {
        userData: {
          userId: "u1",
          clientId: "web-001",
          nickName: "Alice",
          opts: { color: "#2F80ED" }
        },
        uiOptions: {
          showTopBar: true,
          showBottomBar: true
        },
        mode: {
          readOnly: false,
          lang: "en-US"
        }
      }
    );

    const app = await widget.mount("#office-container").render();
    app.Document.setZoom(120);

## openfile Signature#

    function openfile(
      fileData: OfficeWidgetFileData,
      options?: OfficeSdkOpenOptions | null
    ): Promise<OfficeWidgetOpenResult>;

To create a blank document, call `OfficeSdk.createfile(1 | 2 | 3, options)`, where `1`, `2`, and `3` represent DOCX, XLSX, and PPTX. Its return value and widget lifecycle match `openfile(...)`.

## fileData Parameter#

    type OfficeWidgetFileData = {
      docId?: string;
      fileName: string;
      file: File | Blob | ArrayBuffer | ArrayBufferView | string;
    };

Field | Required | Description
--- | --- | ---
`docId` | No | Document ID used for caching and instance lifecycle identification. If omitted, the SDK generates one from file information.
`fileName` | Yes | File name. The extension is used to identify the document type. `openfile(...)` currently supports `doc`, `docx`, `xls`, `xlsx`, and `pptx`.
`file` | Yes | File content or a browser-accessible file URL. Supports `File`/`Blob`, `ArrayBuffer`, `TypedArray`, plus `blob:`, `data:`, `http(s):`, `file:`, absolute paths beginning with `/`, and relative paths beginning with `./` or `../`. A plain string such as `files/a.docx` is not recognized as a URL. Do not pass `null` or `undefined`.

## options Parameter#

    type OfficeSdkOpenOptions = {
      userData?: OfficeSdkUser | null;
      uiOptions?: OfficeSdkUiOptions;
      mode?: OfficeSdkOpenMode;
    };

    type OfficeSdkUser = {
      clientId?: string;
      userId?: string;
      nickName?: string;
      avatar?: string;
      opts?: Record<string, unknown>;
    };

    type OfficeSdkUiOptions = {
      showTopBar?: boolean;
      showBottomBar?: boolean;
    };

    type OfficeSdkOpenMode = {
      readOnly?: boolean;
      lang?: "zh-CN" | "en-US" | (string & {});
    };

Field | Description
--- | ---
`userData` | Current user information. If omitted, a default user is filled in: `nickName: "Local User"`, `avatar: ""`, and `opts.color: "#2F80ED"`.
`uiOptions.showTopBar` | Whether to show the top toolbar. If omitted, the SDK default layout is used.
`uiOptions.showBottomBar` | Whether to show the bottom status bar. If omitted, the SDK default layout is used.
`mode.readOnly` | Whether to open in read-only mode.
`mode.lang` | Document language, such as `zh-CN` or `en-US`. If omitted, the SDK falls back to `window.lang`, `<html lang>`, and then browser language.

## Return Value#

    type OfficeWidgetOpenResult = {
      docType: number;
      widget: OfficeWidgetApp;
    };

    type OfficeWidgetApp = {
      mount(target: string | HTMLElement): OfficeWidgetApp;
      render(): Promise<OfficeRenderedApp>;
      close(): Promise<void>;
      readonly docId: string;
      readonly docType: number;
      readonly docTypeName: string | null;
    };

`docType` values:

Value | Type
--- | ---
`1` | Word / DOCX
`2` | Excel / XLSX
`3` | PowerPoint / PPTX

`widget.mount(target)` accepts `HTMLElement` and strings. Strings beginning with `#`, `.`, or `[` are treated as CSS selectors; other strings are treated as DOM element IDs:

    widget.mount("#office-container");
    widget.mount("office-container");
    widget.mount(document.getElementById("office-container")!);

`widget.render()` waits until the document is ready and returns the public `app` API object. You can then call:

    app.Document.setZoom(120);
    app.UndoRedo.undo();

After a successful mount, `widget.docTypeName` is `"WORD"`, `"EXCEL"`, or `"PPT"`; before mount completes, it is `null`.

## Instance Lifecycle#

`widget.close()` closes the current document instance and releases runtime resources.

Method | Description | Recommended Timing
--- | --- | ---
`close()` | Closes the current widget and releases the document instance, internal event listeners, and mount resources. | Call before page unload, before the host component unmounts, or before opening another file.

Call it:

- Before route changes or before the host component unmounts
- Before the user selects and opens a new file
- When the current document viewer is no longer needed

Example:

    let currentWidget: OfficeWidgetApp | null = null;

    async function openFile(file: File) {
      await currentWidget?.close();

      const { widget } = await OfficeSdk.openfile({
        docId: `local-${Date.now()}`,
        fileName: file.name,
        file
      });

      currentWidget = widget;
      return widget.mount("#office-container").render();
    }

    async function disposeViewer() {
      await currentWidget?.close();
      currentWidget = null;
    }

## URL File Example#

    const { widget } = await OfficeSdk.openfile({
      docId: "report-xlsx",
      fileName: "report.xlsx",
      file: "https://example.com/report.xlsx"
    });

    const app = await widget.mount("#office-container").render();

## Reopening Files#

Destroy the old instance before reopening:

    let currentWidget = null;

    async function replaceFile(file) {
      await currentWidget?.close();

      const { widget } = await OfficeSdk.openfile({
        docId: `local-${Date.now()}`,
        fileName: file.name,
        file
      });

      const app = await widget.mount("#office-container").render();
      currentWidget = widget;
      return app;
    }

## Event Example#

Events are registered through component-level `addEventListener`. Choose the component by event ownership: document loading, export, and zoom events belong to `Document`; selection events belong to `Selection`; undo/redo events belong to `UndoRedo`.

    function onUndoRedoStateChange() {
      console.log("undo/redo changed");
    }

    const status = app.UndoRedo.addEventListener("UNDO_REDO_STATE_CHANGE", onUndoRedoStateChange);

    if (status !== "ok") {
      console.warn(status);
    }

    app.UndoRedo.removeEventListener("UNDO_REDO_STATE_CHANGE", onUndoRedoStateChange);

Supported event names and payloads for each document type are listed in the API Reference.