Skip to main content

Hooks & API

UI Extensions provide hooks to access store context, settings, session tokens, storage, and the current resource.

Extension API​

Every extension receives an ExtensionApi object that provides access to all platform capabilities:

interface ExtensionApi {
target: ExtensionTarget; // The current extension target
settings: Record<string, unknown>; // Extension settings
store: StoreContext; // Store information
resource?: ResourceContext; // Current resource (product, order, etc.)
setHeight(height: number): void; // Update container height
sessionToken: SessionToken; // Session token for API calls
storage: ExtensionStorage; // Key-value storage
i18n: I18n; // Internationalization
}

StoreContext​

interface StoreContext {
domain: string; // Store domain (e.g. "mystore.qumra.store")
locale: string; // Current locale
currency: string; // Store currency code
}

ResourceContext​

interface ResourceContext {
id: string; // Resource ID
type: string; // Resource type (product, order, customer)
data?: Record<string, unknown>; // Additional resource data
}

useApi()​

Access the full Extension API from any component within an extension:

import { useApi } from "@qumra/riwaq";

function MyExtension() {
const api = useApi();

return (
<div>
<p>Store: {api.store.domain}</p>
<p>Locale: {api.store.locale}</p>
<p>Currency: {api.store.currency}</p>
{api.resource && (
<p>Resource: {api.resource.type} #{api.resource.id}</p>
)}
</div>
);
}

useSettings()​

Access the extension's configured settings:

import { useSettings } from "@qumra/riwaq";

function MyExtension() {
const settings = useSettings();

return (
<div>
<h3>{settings.title as string}</h3>
<p>Show badge: {settings.showBadge ? "Yes" : "No"}</p>
<p>Max items: {settings.maxItems as number}</p>
</div>
);
}

Settings are defined in the extension configuration. See Settings for details on defining settings fields.

useSessionToken()​

Get a session token for making authenticated API calls from the extension:

import { useSessionToken } from "@qumra/riwaq";

function MyExtension() {
const sessionToken = useSessionToken();

async function fetchData() {
const token = await sessionToken.get();

const response = await fetch("https://your-app.com/api/data", {
headers: {
Authorization: `Bearer ${token}`,
},
});

return response.json();
}

return <button onClick={fetchData}>Load Data</button>;
}

SessionToken Interface​

MethodReturn TypeDescription
get()Promise<string>Get a valid session token. Refreshes automatically if expired.

useExtensionLanguage()​

Get the current language/locale of the extension context:

import { useExtensionLanguage } from "@qumra/riwaq";

function MyExtension() {
const language = useExtensionLanguage();

return <p>Current language: {language}</p>; // "ar", "en", etc.
}

useStorage()​

Persist key-value data within the extension's scope:

import { useStorage } from "@qumra/riwaq";
import { useState, useEffect } from "react";

function MyExtension() {
const storage = useStorage();
const [count, setCount] = useState(0);

useEffect(() => {
// Load saved value
storage.get("viewCount").then((value) => {
if (value) setCount(Number(value));
});
}, []);

async function incrementCount() {
const newCount = count + 1;
setCount(newCount);
await storage.set("viewCount", String(newCount));
}

return (
<div>
<p>Views: {count}</p>
<button onClick={incrementCount}>Increment</button>
</div>
);
}

ExtensionStorage Interface​

MethodReturn TypeDescription
get(key)Promise<string | null>Get a stored value by key.
set(key, value)Promise<void>Store a value.
delete(key)Promise<void>Delete a stored value.

useResource()​

Access the current resource (product, order, customer) when the extension is rendered in a resource context:

import { useResource } from "@qumra/riwaq";

function ProductExtension() {
const resource = useResource();

if (!resource) return <p>No resource context</p>;

return (
<div>
<p>Type: {resource.type}</p>
<p>ID: {resource.id}</p>
{resource.data && (
<pre>{JSON.stringify(resource.data, null, 2)}</pre>
)}
</div>
);
}

setHeight()​

Dynamically adjust the extension container height:

import { useApi } from "@qumra/riwaq";
import { useEffect, useRef } from "react";

function MyExtension() {
const api = useApi();
const ref = useRef<HTMLDivElement>(null);

useEffect(() => {
if (ref.current) {
api.setHeight(ref.current.scrollHeight);
}
});

return <div ref={ref}>{/* Content */}</div>;
}

i18n​

Translate strings with replacements:

import { useApi } from "@qumra/riwaq";

function MyExtension() {
const { i18n } = useApi();

return (
<p>{i18n.translate("greeting", { name: "Ahmed" })}</p>
// Output: "Hello, Ahmed!" (based on translation files)
);
}