diff --git a/packages/element-web-module-api/element-web-module-api.api.md b/packages/element-web-module-api/element-web-module-api.api.md index a93fdbbfb3..56fa2bb06b 100644 --- a/packages/element-web-module-api/element-web-module-api.api.md +++ b/packages/element-web-module-api/element-web-module-api.api.md @@ -283,6 +283,7 @@ export type OriginalMessageComponentProps = { // @public export interface Profile { displayName?: string; + isGuest?: boolean; userId?: string; } @@ -312,6 +313,9 @@ export interface UserIdentifierCustomisations { }): string | null; } +// @public +export function useWatchable(watchable: Watchable): T; + // @public export type Variables = { count?: number; diff --git a/packages/element-web-module-api/package.json b/packages/element-web-module-api/package.json index a3c6a78a47..c98d0803f3 100644 --- a/packages/element-web-module-api/package.json +++ b/packages/element-web-module-api/package.json @@ -39,6 +39,7 @@ "@types/semver": "^7.5.8", "@vitest/coverage-v8": "^3.0.4", "matrix-web-i18n": "^3.3.0", + "rollup-plugin-external-globals": "^0.13.0", "semver": "^7.6.3", "typescript": "^5.7.3", "vite": "^6.1.6", diff --git a/packages/element-web-module-api/src/api/profile.ts b/packages/element-web-module-api/src/api/profile.ts index 097a28d86f..5a09537587 100644 --- a/packages/element-web-module-api/src/api/profile.ts +++ b/packages/element-web-module-api/src/api/profile.ts @@ -12,6 +12,10 @@ import { Watchable } from "./watchable.ts"; * @public */ export interface Profile { + /** + * Indicates whether the user is a guest user. + */ + isGuest?: boolean; /** * The user ID of the logged-in user, if undefined then no user is logged in. */ diff --git a/packages/element-web-module-api/src/api/watchable.ts b/packages/element-web-module-api/src/api/watchable.ts index 4bd8d74239..2f82a9b732 100644 --- a/packages/element-web-module-api/src/api/watchable.ts +++ b/packages/element-web-module-api/src/api/watchable.ts @@ -5,6 +5,8 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE files in the repository root for full details. */ +import { useEffect, useState } from "react"; + type WatchFn = (value: T) => void; function shallowCompare(obj1: T, obj2: T): boolean { @@ -55,3 +57,21 @@ export class Watchable { this.listeners.delete(listener); } } + +/** + * A React hook to use an updated Watchable value. + * @param watchable - The Watchable instance to watch. + * @returns The live value of the Watchable. + * @public + */ +export function useWatchable(watchable: Watchable): T { + const [value, setValue] = useState(watchable.value); + useEffect(() => { + setValue(watchable.value); + watchable.watch(setValue); + return (): void => { + watchable.unwatch(setValue); + }; + }, [watchable]); + return value; +} diff --git a/packages/element-web-module-api/vite.config.ts b/packages/element-web-module-api/vite.config.ts index 6b0d47a8a2..01d3eebba6 100644 --- a/packages/element-web-module-api/vite.config.ts +++ b/packages/element-web-module-api/vite.config.ts @@ -9,6 +9,7 @@ import { dirname, resolve } from "node:path"; import { fileURLToPath } from "node:url"; import { defineConfig } from "vite"; import dts from "vite-plugin-dts"; +import externalGlobals from "rollup-plugin-external-globals"; const __dirname = dirname(fileURLToPath(import.meta.url)); @@ -23,9 +24,18 @@ export default defineConfig({ target: "esnext", sourcemap: true, }, - plugins: [dts()], + plugins: [ + dts(), + externalGlobals({ + // Reuse React from the host app + react: "window.React", + }), + ], define: { __VERSION__: JSON.stringify(process.env.npm_package_version), + // Use production mode for the build as it is tested against production builds of Element Web, + // this is required for React JSX versions to be compatible. + process: { env: { NODE_ENV: "production" } }, }, test: { coverage: {