Make shared component build work in isolation (#31066)

* Make shared component build work in isolation

 * Add deps that were missing because they were getting picked up
   from element-web main but shared-components needs itself
 * Exclude test files from dts generation
 * Bump version

* Change all the shared-component import to be the built artifact

* Don't randomly inhale eslint configs in parent dirs please

* maybe we don't need this anymore?

* maybe fix build

* Maybe fix docker build

* More build faff

 * build:res on the parent as part of shared component prepare
 * link shared component repo inn docker build

* 💅

* 💅x2

* Try converting the translation keys to a .d.ts file manually

so it gets bundled rather than left as a relative import to the json
file

* add the script

* Add this back for 2nd time now I think

* Shouldn't need this anymore

* patch-package on prepare

because we're patching a dev dependency so it won't be there if we're
installed as a dependency

* Unused import

* Prettier compliance

* Only use counterpart from shared components

as per comment

* Import shared components CSS

* Prettier

* Call the one from shared components

rather than recurse infinitely

* Hopefully make tests work

* wake up, comment goes before import

* Fix lint errors

* Fix dupe TranslationKey export

* Update compound-web to fix type error

An update to @types.react adds the 'hint' value to the enum of the
'popover' attribute and this version of compound-web uses the maching
verson of @types/react so they don't conflict.

* Maybe, hopefully, get the types working?

Please?

* Add copyright header to i18nkeys

as eslint complains otherwise since it's now in src

* prettier

* stop running shared-component tests in EW

* update snapshots

because flex is now from an external stylesheet I guess

* More snapshots

* Manual class update

* Avoid bundling compound bits

Because a) it's silly and b) it means we end up bundling a copy of
floating-ui too which causes absolute madness with its useDelayGroup
contexts.

* ignore test util files for coverage

* Add !important

because the styles are being applied in a different order now

* Another !important because css order has changed

* Try adding it here to make the test files ignored

* More !important

* commit yarn lock change

* Add shared components coverage file

* Update snapshots

Because the line height was being overridden to 22.5px somehow by
something I can't find, and now isn't: surely the normal 1.5rem is
more sensible.

* Update snapshots, attempt 2

* Another !important

* More snapshot updates

* Add test for i18n wrappers

& add test script

* lint

* Prettier

* Hopefully run shared component tests

* don't need this bit for non-matrix

* install ew deps

* rigfht coverage location

* Rename job here too

* Try different coverage filename

* Fix copyrights & comment

* Typo

Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>

---------

Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
David Baker
2025-11-03 16:26:47 +00:00
committed by GitHub
parent 486d4d59bc
commit b0cdbf5eff
133 changed files with 1708 additions and 319 deletions

View File

@@ -34,10 +34,6 @@ jobs:
- name: Install element web dependencies - name: Install element web dependencies
run: yarn install --frozen-lockfile run: yarn install --frozen-lockfile
- name: Build Element Web resources
# Needed to prepare language files
run: "yarn build:res"
- name: Install dependencies - name: Install dependencies
working-directory: packages/shared-components working-directory: packages/shared-components
run: yarn install --frozen-lockfile run: yarn install --frozen-lockfile

View File

@@ -35,10 +35,6 @@ jobs:
- name: Typecheck - name: Typecheck
run: "yarn run lint:types" run: "yarn run lint:types"
- name: Build Element Web resources
# Needed to prepare language files for shared components
run: "yarn build:res"
- name: Install Shared Component Dependencies - name: Install Shared Component Dependencies
run: "yarn --cwd packages/shared-components install" run: "yarn --cwd packages/shared-components install"
@@ -91,10 +87,6 @@ jobs:
- name: Run Linter - name: Run Linter
run: "yarn run lint:js" run: "yarn run lint:js"
- name: Build Element Web resources
# Needed to prepare language files for shared components
run: "yarn build:res"
- name: Install Shared Component Deps - name: Install Shared Component Deps
run: "yarn --cwd packages/shared-components install --frozen-lockfile" run: "yarn --cwd packages/shared-components install --frozen-lockfile"

View File

@@ -29,8 +29,8 @@ env:
permissions: {} permissions: {}
jobs: jobs:
jest: jest_ew:
name: Jest name: Jest (Element Web)
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
strategy: strategy:
fail-fast: false fail-fast: false
@@ -93,13 +93,13 @@ jobs:
complete: complete:
name: jest-tests name: jest-tests
needs: jest needs: jest_ew
if: always() if: always()
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
permissions: permissions:
statuses: write statuses: write
steps: steps:
- if: needs.jest.result != 'skipped' && needs.jest.result != 'success' - if: needs.jest_ew.result != 'skipped' && needs.jest_ew.result != 'success'
run: exit 1 run: exit 1
- name: Skip SonarCloud in merge queue - name: Skip SonarCloud in merge queue
@@ -112,3 +112,56 @@ jobs:
context: SonarCloud Code Analysis context: SonarCloud Code Analysis
sha: ${{ github.sha }} sha: ${{ github.sha }}
target_url: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} target_url: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
jest_sc:
name: Jest (Shared Components)
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
with:
repository: ${{ inputs.matrix-js-sdk-sha && 'element-hq/element-web' || github.repository }}
- name: Yarn cache
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6
with:
node-version: "lts/*"
cache: "yarn"
- name: Install EW Deps
run: "yarn install"
- name: Install Shared Component Deps
working-directory: "packages/shared-components"
run: "yarn install"
- name: Jest Cache
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: /tmp/jest_cache
key: ${{ hashFiles('**/yarn.lock') }}
- name: Get number of CPU cores
id: cpu-cores
uses: SimenB/github-actions-cpu-cores@97ba232459a8e02ff6121db9362b09661c875ab8 # v2
- name: Run tests
working-directory: "packages/shared-components"
run: |
yarn test \
--coverage=${{ env.ENABLE_COVERAGE }} \
--ci \
--max-workers ${{ steps.cpu-cores.outputs.count }} \
--cacheDirectory /tmp/jest_cache
env:
# tell jest to use coloured output
FORCE_COLOR: true
- name: Upload Artifact
if: env.ENABLE_COVERAGE == 'true'
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with:
name: coverage-sharedcomponents
path: |
packages/shared-components/coverage
!packages/shared-components/coverage/lcov-report

1
.gitignore vendored
View File

@@ -36,3 +36,4 @@ storybook-static
/packages/shared-components/node_modules /packages/shared-components/node_modules
/packages/shared-components/dist /packages/shared-components/dist
/packages/shared-components/src/i18nKeys.d.ts

View File

@@ -17,7 +17,7 @@ const config: Config = {
// This is needed to be able to load dual CJS/ESM WASM packages e.g. rust crypto & matrix-wywiwyg // This is needed to be able to load dual CJS/ESM WASM packages e.g. rust crypto & matrix-wywiwyg
customExportConditions: ["browser", "node"], customExportConditions: ["browser", "node"],
}, },
testMatch: ["<rootDir>/test/**/*-test.[tj]s?(x)", "<rootDir>/packages/*/src/**/*.test.[t]s?(x)"], testMatch: ["<rootDir>/test/**/*-test.[tj]s?(x)"],
globalSetup: "<rootDir>/test/globalSetup.ts", globalSetup: "<rootDir>/test/globalSetup.ts",
setupFiles: ["jest-canvas-mock", "web-streams-polyfill/polyfill"], setupFiles: ["jest-canvas-mock", "web-streams-polyfill/polyfill"],
setupFilesAfterEnv: ["<rootDir>/test/setupTests.ts"], setupFilesAfterEnv: ["<rootDir>/test/setupTests.ts"],

View File

@@ -83,6 +83,7 @@
"dependencies": { "dependencies": {
"@babel/runtime": "^7.12.5", "@babel/runtime": "^7.12.5",
"@element-hq/element-web-module-api": "1.4.1", "@element-hq/element-web-module-api": "1.4.1",
"@element-hq/web-shared-components": "file:packages/shared-components",
"@fontsource/inconsolata": "^5", "@fontsource/inconsolata": "^5",
"@fontsource/inter": "^5", "@fontsource/inter": "^5",
"@formatjs/intl-segmenter": "^11.5.7", "@formatjs/intl-segmenter": "^11.5.7",
@@ -104,7 +105,6 @@
"browserslist": "^4.23.2", "browserslist": "^4.23.2",
"classnames": "^2.2.6", "classnames": "^2.2.6",
"commonmark": "^0.31.0", "commonmark": "^0.31.0",
"counterpart": "^0.18.6",
"css-tree": "^3.0.0", "css-tree": "^3.0.0",
"diff-dom": "^5.0.0", "diff-dom": "^5.0.0",
"diff-match-patch": "^1.0.5", "diff-match-patch": "^1.0.5",

View File

@@ -1,4 +1,5 @@
module.exports = { module.exports = {
root: true,
plugins: ["matrix-org", "eslint-plugin-react-compiler"], plugins: ["matrix-org", "eslint-plugin-react-compiler"],
extends: [ extends: [
"plugin:matrix-org/babel", "plugin:matrix-org/babel",

View File

@@ -1 +1,2 @@
dist/ dist/
i18n/i18nKeys.d.ts

View File

@@ -0,0 +1,21 @@
module.exports = {
sourceMaps: true,
presets: [
[
"@babel/preset-env",
{
include: ["@babel/plugin-transform-class-properties"],
},
],
["@babel/preset-typescript", { allowDeclareFields: true }],
"@babel/preset-react",
],
plugins: [
"@babel/plugin-proposal-export-default-from",
"@babel/plugin-transform-numeric-separator",
"@babel/plugin-transform-object-rest-spread",
"@babel/plugin-transform-optional-chaining",
"@babel/plugin-transform-nullish-coalescing-operator",
"@babel/plugin-transform-runtime",
],
};

View File

@@ -0,0 +1,58 @@
/*
Copyright 2025 Element Creations Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import { env } from "process";
import type { Config } from "jest";
const config: Config = {
testEnvironment: "jsdom",
testEnvironmentOptions: {
url: "http://localhost/",
},
testMatch: ["<rootDir>/src/**/*.test.[tj]s?(x)"],
setupFilesAfterEnv: ["<rootDir>/src/test/setupTests.ts"],
moduleNameMapper: {
// Support CSS module
"\\.(module.css)$": "identity-obj-proxy",
"\\.(css|scss|pcss)$": "<rootDir>/__mocks__/cssMock.js",
"\\.(gif|png|ttf|woff2)$": "<rootDir>/__mocks__/imageMock.js",
"\\.svg$": "<rootDir>/__mocks__/svg.js",
"\\$webapp/i18n/languages.json": "<rootDir>/../../__mocks__/languages.json",
"^react$": "<rootDir>/node_modules/react",
"^react-dom$": "<rootDir>/node_modules/react-dom",
"waveWorker\\.min\\.js": "<rootDir>/__mocks__/empty.js",
"context-filter-polyfill": "<rootDir>/__mocks__/empty.js",
"workers/(.+)Factory": "<rootDir>/__mocks__/workerFactoryMock.js",
},
transformIgnorePatterns: [
"/node_modules/(?!(mime|matrix-js-sdk|uuid|p-retry|is-network-error|react-merge-refs)).+$",
],
collectCoverageFrom: [
"<rootDir>/src/**/*.{js,ts,tsx}",
"<rootDir>/packages/**/*.{js,ts,tsx}",
// Coverage chokes on type definition files
"!<rootDir>/src/**/*.d.ts",
],
coverageReporters: ["text-summary", "lcov"],
testResultsProcessor: "@casualbot/jest-sonar-reporter",
prettierPath: null,
moduleDirectories: ["node_modules", "./src/test/utils"],
};
// if we're running under GHA, enable the GHA reporter
if (env["GITHUB_ACTIONS"] !== undefined) {
const reporters: Config["reporters"] = [["github-actions", { silent: false }], "summary"];
// if we're running against the develop branch, also enable the slow test reporter
if (env["GITHUB_REF"] == "refs/heads/develop") {
reporters.push("<rootDir>/test/slowReporter.cjs");
}
config.reporters = reporters;
}
export default config;

View File

@@ -19,6 +19,10 @@
"types": "./dist/element-web-shared-components.d.ts", "types": "./dist/element-web-shared-components.d.ts",
"default": "./dist/element-web-shared-components.mjs" "default": "./dist/element-web-shared-components.mjs"
} }
},
"./dist/element-web-shared-components.css": {
"require": "./dist/element-web-shared-components.css",
"import": "./dist/element-web-shared-components.css"
} }
}, },
"types": "dist/element-web-shared-components.d.ts", "types": "dist/element-web-shared-components.d.ts",
@@ -30,8 +34,8 @@
"package.json" "package.json"
], ],
"scripts": { "scripts": {
"postinstall": "patch-package", "test": "jest",
"prepare": "vite build", "prepare": "patch-package && yarn --cwd ../.. build:res && ts-node scripts/gatherTranslationKeys.ts && vite build",
"storybook": "storybook dev -p 6007", "storybook": "storybook dev -p 6007",
"build-storybook": "storybook build", "build-storybook": "storybook build",
"lint": "yarn lint:types && yarn lint:js", "lint": "yarn lint:types && yarn lint:js",
@@ -42,9 +46,13 @@
"test:storybook:update": "playwright-screenshots --entrypoint yarn --with-node-modules && playwright-screenshots --entrypoint /work/node_modules/.bin/test-storybook --with-node-modules --url http://host.docker.internal:6007/ --updateSnapshot" "test:storybook:update": "playwright-screenshots --entrypoint yarn --with-node-modules && playwright-screenshots --entrypoint /work/node_modules/.bin/test-storybook --with-node-modules --url http://host.docker.internal:6007/ --updateSnapshot"
}, },
"dependencies": { "dependencies": {
"classnames": "^2.5.1",
"counterpart": "^0.18.6",
"lodash": "^4.17.21",
"matrix-web-i18n": "^3.4.0", "matrix-web-i18n": "^3.4.0",
"patch-package": "^8.0.1", "patch-package": "^8.0.1",
"counterpart": "^0.18.6" "react-merge-refs": "^3.0.2",
"temporal-polyfill": "^0.3.0"
}, },
"devDependencies": { "devDependencies": {
"@storybook/addon-a11y": "^9.1.10", "@storybook/addon-a11y": "^9.1.10",
@@ -53,13 +61,21 @@
"@storybook/icons": "^1.6.0", "@storybook/icons": "^1.6.0",
"@storybook/react-vite": "^9.1.10", "@storybook/react-vite": "^9.1.10",
"@storybook/test-runner": "^0.23.0", "@storybook/test-runner": "^0.23.0",
"@testing-library/dom": "^10.4.1",
"@testing-library/react": "^16.3.0",
"@types/counterpart": "^0.18.4",
"@types/lodash": "^4.17.20",
"@types/react": "^19.2.2",
"concurrently": "^9.2.1", "concurrently": "^9.2.1",
"eslint": "8", "eslint": "8",
"eslint-plugin-matrix-org": "^3.0.0",
"eslint-plugin-storybook": "^10.0.0", "eslint-plugin-storybook": "^10.0.0",
"jest": "^30.2.0",
"jest-image-snapshot": "^6.5.1", "jest-image-snapshot": "^6.5.1",
"patch-package": "^8.0.1", "patch-package": "^8.0.1",
"prettier": "^3.6.2", "prettier": "^3.6.2",
"storybook": "^9.1.10", "storybook": "^9.1.10",
"ts-node": "^10.9.2",
"typescript": "^5.9.3", "typescript": "^5.9.3",
"vite": "^7.1.9", "vite": "^7.1.9",
"vite-plugin-dts": "^4.5.4", "vite-plugin-dts": "^4.5.4",
@@ -68,5 +84,9 @@
"engines": { "engines": {
"node": ">=20.0.0" "node": ">=20.0.0"
}, },
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e",
"peerDependencies": {
"@vector-im/compound-design-tokens": "^6.0.0",
"@vector-im/compound-web": "^8.2.5"
}
} }

View File

@@ -0,0 +1,61 @@
/*
Copyright 2025 Element Creations Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
// Gathers all the translation keys from element-web's en_EN.json into a TypeScript type definition file
// that exports a type `TranslationKey` which is a union of all supported translation keys.
// This prevents having to import the json file and make typescript do the work as this results in vite-dts
// generating an import to the json file in the .d.ts which doesn't work at runtime: this way, the type
// gets put into the bundle.
// XXX: It should *not* be in the 'src' directory, being a generated file, but if it isn't then the type
// bundler won't bundle the types and will leave the file as a relative import, which will break.
import * as fs from "fs";
import * as path from "path";
const i18nStringsPath = path.resolve(__dirname, "../../../src/i18n/strings/en_EN.json");
const outPath = path.resolve(__dirname, "../src/i18nKeys.d.ts");
function gatherKeys(obj: any, prefix: string[] = []): string[] {
if (typeof obj !== "object" || obj === null) return [];
let keys: string[] = [];
for (const key of Object.keys(obj)) {
const value = obj[key];
// add the path (for both leaves and intermediates as then we include plurals)
keys.push([...prefix, key].join("|"));
if (typeof value === "object" && value !== null) {
// If the value is an object, recurse
keys = keys.concat(gatherKeys(value, [...prefix, key]));
}
}
return keys;
}
function main() {
const json = JSON.parse(fs.readFileSync(i18nStringsPath, "utf8"));
const keys = gatherKeys(json);
const typeDef =
"/*\n" +
" * Copyright 2025 Element Creations Ltd.\n" +
" *\n" +
" * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial\n" +
" * Please see LICENSE files in the repository root for full details.\n" +
" */\n" +
"\n" +
"// This file is auto-generated by gatherTranslationKeys.ts\n" +
"// Do not edit manually.\n\n" +
"export type TranslationKey =\n" +
keys.map((k) => ` | \"${k}\"`).join("\n") +
";\n";
fs.mkdirSync(path.dirname(outPath), { recursive: true });
fs.writeFileSync(outPath, typeDef, "utf8");
console.log(`Wrote ${keys.length} keys to ${outPath}`);
}
if (require.main === module) {
main();
}

View File

@@ -6,7 +6,7 @@
*/ */
.audioPlayer { .audioPlayer {
padding: var(--cpd-space-4x) var(--cpd-space-3x) var(--cpd-space-3x) var(--cpd-space-3x); padding: var(--cpd-space-4x) var(--cpd-space-3x) var(--cpd-space-3x) var(--cpd-space-3x) !important;
} }
.mediaInfo { .mediaInfo {

View File

@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`AudioPlayerView renders the audio player in default state 1`] = ` exports[`AudioPlayerView renders the audio player in default state 1`] = `
<div> <div>

View File

@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`Clock renders the clock 1`] = ` exports[`Clock renders the clock 1`] = `
<div> <div>

View File

@@ -6,6 +6,6 @@
*/ */
.button { .button {
border-radius: 32px; border-radius: 32px !important;
background-color: var(--cpd-color-bg-subtle-primary); background-color: var(--cpd-color-bg-subtle-primary) !important;
} }

View File

@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`PlayPauseButton renders the button in default state 1`] = ` exports[`PlayPauseButton renders the button in default state 1`] = `
<div> <div>

View File

@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`Seekbar renders the clock 1`] = ` exports[`Seekbar renders the clock 1`] = `
<div> <div>

View File

@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`AvatarWithDetails renders a textual event 1`] = ` exports[`AvatarWithDetails renders a textual event 1`] = `
<div> <div>

View File

@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`TextualEventView renders a textual event 1`] = ` exports[`TextualEventView renders a textual event 1`] = `
<div> <div>

View File

@@ -5,4 +5,4 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details. Please see LICENSE files in the repository root for full details.
*/ */
export { TextualEventView } from "./TextualEventView"; export { TextualEventView, type TextualEventViewSnapshot } from "./TextualEventView";

View File

@@ -21,12 +21,17 @@ export * from "./utils/Box";
export * from "./utils/Flex"; export * from "./utils/Flex";
// Utils // Utils
export { setLanguage } from "./utils/i18n"; export * from "./utils/i18n";
export * from "./utils/humanize"; export * from "./utils/humanize";
export * from "./utils/DateUtils"; export * from "./utils/DateUtils";
export * from "./utils/numbers"; export * from "./utils/numbers";
export * from "./utils/FormattingUtils";
// MVVM // MVVM
export * from "./viewmodel"; export * from "./viewmodel";
export * from "./useMockedViewModel"; export * from "./useMockedViewModel";
export * from "./useViewModel"; export * from "./useViewModel";
// i18n (we must export this directly in order to not confuse the type bundler, it seems,
// otherwise it will leave it as a relative import rather than bundling it)
export type * from "./i18nKeys.d.ts";

View File

@@ -7,7 +7,7 @@
.mediaBody { .mediaBody {
background-color: var(--cpd-color-bg-subtle-secondary); background-color: var(--cpd-color-bg-subtle-secondary);
border-radius: var(--cpd-space-2x); border-radius: var(--cpd-space-2x) !important;
max-width: 243px; /* use max-width instead of width so it fits within right panels */ max-width: 243px; /* use max-width instead of width so it fits within right panels */
font: var(--cpd-font-body-md-regular); font: var(--cpd-font-body-md-regular);

View File

@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`MediaBody renders the media body 1`] = ` exports[`MediaBody renders the media body 1`] = `
<div> <div>

View File

@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`Pill renders the pill 1`] = ` exports[`Pill renders the pill 1`] = `
<div> <div>

View File

@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`PillInput renders only the input without children 1`] = ` exports[`PillInput renders only the input without children 1`] = `
<div> <div>

View File

@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`RichItem renders the item in default state 1`] = ` exports[`RichItem renders the item in default state 1`] = `
<div> <div>

View File

@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`RichItem renders the list 1`] = ` exports[`RichItem renders the list 1`] = `
<div> <div>

View File

@@ -0,0 +1,22 @@
/*
Copyright 2025 Element Creations Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import fetchMock from "fetch-mock-jest";
import { setLanguage } from "../../src/utils/i18n";
import en from "../../../../src/i18n/strings/en_EN.json";
export function setupLanguageMock(): void {
fetchMock
.get("/i18n/languages.json", {
en: "en_EN.json",
})
.get("end:en_EN.json", en);
}
setupLanguageMock();
setLanguage("en");

View File

@@ -0,0 +1,47 @@
/*
Copyright 2025 Element Creations Ltd.
Copyright 2024 New Vector Ltd.
Copyright 2022 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
// Copied from element-web/test/test-utils because, seemingly, if we
// set that as the modules directory to use it directly, it fails to
// actually put the right thing in the context somehow.
import React, { type ReactElement } from "react";
// eslint-disable-next-line no-restricted-imports
import { render, type RenderOptions } from "@testing-library/react";
import { TooltipProvider } from "@vector-im/compound-web";
const wrapWithTooltipProvider = (Wrapper: RenderOptions["wrapper"]) => {
return ({ children }: { children: React.ReactNode }) => {
if (Wrapper) {
return (
<Wrapper>
<TooltipProvider>{children}</TooltipProvider>
</Wrapper>
);
} else {
return <TooltipProvider>{children}</TooltipProvider>;
}
};
};
const customRender = (ui: ReactElement, options: RenderOptions = {}): ReturnType<typeof render> => {
return render(ui, {
...options,
wrapper: wrapWithTooltipProvider(options?.wrapper) as RenderOptions["wrapper"],
}) as ReturnType<typeof render>;
};
// eslint-disable-next-line no-restricted-imports
export * from "@testing-library/react";
/**
* This custom render function wraps your component with a TooltipProvider.
* See https://testing-library.com/docs/react-testing-library/setup/#custom-render
*/
export { customRender as render };

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2025 Element Creations Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
import counterpart from "counterpart";
import { registerTranslations, setMissingEntryGenerator, getLocale, setLocale } from "./i18n";
describe("i18n utils", () => {
beforeEach(() => {
jest.clearAllMocks();
});
it("should wrap registerTranslations", () => {
jest.spyOn(counterpart, "registerTranslations");
registerTranslations("en", { test: "This is a test" });
expect(counterpart.registerTranslations).toHaveBeenCalledWith("en", { test: "This is a test" });
});
it("should wrap setMissingEntryGenerator", () => {
jest.spyOn(counterpart, "setMissingEntryGenerator");
const dummyFn = jest.fn();
setMissingEntryGenerator(dummyFn);
expect(counterpart.setMissingEntryGenerator).toHaveBeenCalledWith(dummyFn);
});
it("should wrap getLocale", () => {
jest.spyOn(counterpart, "getLocale");
getLocale();
expect(counterpart.getLocale).toHaveBeenCalled();
});
it("should wrap setLocale", () => {
jest.spyOn(counterpart, "setLocale");
setLocale("en");
expect(counterpart.setLocale).toHaveBeenCalledWith("en");
});
});

View File

@@ -22,10 +22,10 @@
* @return a React <span> component if any non-strings were used in substitutions, otherwise a string * @return a React <span> component if any non-strings were used in substitutions, otherwise a string
*/ */
import React from "react"; import React from "react";
import { type TranslationKey as _TranslationKey, KEY_SEPARATOR } from "matrix-web-i18n"; import { KEY_SEPARATOR } from "matrix-web-i18n";
import counterpart from "counterpart"; import counterpart from "counterpart";
import type Translations from "../../../../src/i18n/strings/en_EN.json"; import type { TranslationKey } from "../index";
// @ts-ignore - $webapp is a webpack resolve alias pointing to the output directory, see webpack config // @ts-ignore - $webapp is a webpack resolve alias pointing to the output directory, see webpack config
import webpackLangJsonUrl from "$webapp/i18n/languages.json"; import webpackLangJsonUrl from "$webapp/i18n/languages.json";
@@ -45,16 +45,23 @@ counterpart.setSeparator(KEY_SEPARATOR);
const FALLBACK_LOCALE = "en"; const FALLBACK_LOCALE = "en";
counterpart.setFallbackLocale(FALLBACK_LOCALE); counterpart.setFallbackLocale(FALLBACK_LOCALE);
/** // export wrappers around these functions because if we used counterpart directly from
* A type representing the union of possible keys into the translation file using `|` delimiter to access nested fields. // element-web, it operates on a different instance of counterpart
* @example `common|error` to access `error` within the `common` sub-object. export function registerTranslations(locale: string, data: object): void {
* { counterpart.registerTranslations(locale, data);
* "common": { }
* "error": "Error"
* } export function setMissingEntryGenerator(callback: (value: string) => void): void {
* } counterpart.setMissingEntryGenerator(callback);
*/ }
export type TranslationKey = _TranslationKey<typeof Translations>;
export function getLocale(): string {
return counterpart.getLocale();
}
export function setLocale(value: string): string {
return counterpart.setLocale(value);
}
// Function which only purpose is to mark that a string is translatable // Function which only purpose is to mark that a string is translatable
// Does not actually do anything. It's helpful for automatic extraction of translatable strings // Does not actually do anything. It's helpful for automatic extraction of translatable strings

View File

@@ -17,7 +17,7 @@
"lib": ["es2022", "es2024.promise", "dom", "dom.iterable"], "lib": ["es2022", "es2024.promise", "dom", "dom.iterable"],
"strict": true, "strict": true,
"paths": { "paths": {
"jest-matrix-react": ["../../test/test-utils/jest-matrix-react"], "jest-matrix-react": ["./src/test/utils/jest-matrix-react"],
"rollup/parseAst": ["./node_modules/rollup/dist/parseAst"] "rollup/parseAst": ["./node_modules/rollup/dist/parseAst"]
} }
}, },

View File

@@ -26,7 +26,7 @@ export default defineConfig({
rollupOptions: { rollupOptions: {
// make sure to externalize deps that shouldn't be bundled // make sure to externalize deps that shouldn't be bundled
// into your library // into your library
external: ["react", "react-dom"], external: ["react", "react-dom", "@vector-im/compound-design-tokens", "@vector-im/compound-web"],
output: { output: {
// Provide global variables to use in the UMD build // Provide global variables to use in the UMD build
// for externalized deps // for externalized deps
@@ -43,5 +43,12 @@ export default defineConfig({
$webapp: resolve(__dirname, "..", "..", "webapp"), $webapp: resolve(__dirname, "..", "..", "webapp"),
}, },
}, },
plugins: [dts({ rollupTypes: true, include: ["src/**/*.{ts,tsx}"], copyDtsFiles: true })], plugins: [
dts({
rollupTypes: true,
include: ["src/**/*.{ts,tsx}"],
exclude: ["src/**/*.test.{ts,tsx}"],
copyDtsFiles: true,
}),
],
}); });

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

View File

@@ -153,7 +153,7 @@ Please see LICENSE files in the repository root for full details.
.mx_MediaBody { .mx_MediaBody {
/* leave space for the timestamp */ /* leave space for the timestamp */
padding-right: 48px; padding-right: 48px !important;
} }
.mx_MImageBody { .mx_MImageBody {

View File

@@ -17,4 +17,10 @@ else
fi fi
DIST_VERSION=$("$DIR"/normalize-version.sh "$DIST_VERSION") DIST_VERSION=$("$DIR"/normalize-version.sh "$DIST_VERSION")
yarn --cwd packages/shared-components install
yarn --cwd packages/shared-components link
yarn link @element-hq/web-shared-components
VERSION=$DIST_VERSION yarn build VERSION=$DIST_VERSION yarn build

View File

@@ -44,3 +44,11 @@ fi
yarn link matrix-js-sdk yarn link matrix-js-sdk
[ -d matrix-analytics-events ] && yarn link @matrix-org/analytics-events [ -d matrix-analytics-events ] && yarn link @matrix-org/analytics-events
yarn install --frozen-lockfile $@ yarn install --frozen-lockfile $@
# Link shared components
pushd packages/shared-components
yarn link
yarn install --frozen-lockfile
popd
yarn link @element-hq/web-shared-components

View File

@@ -6,12 +6,12 @@ sonar.organization=element-hq
sonar.sources=src,res,packages/shared-components/src sonar.sources=src,res,packages/shared-components/src
sonar.tests=test,playwright,src,packages sonar.tests=test,playwright,src,packages
sonar.test.inclusions=test/*,playwright/*,src/**/*.test.*,packages/*/src/**/*.test.* sonar.test.inclusions=test/*,playwright/*,src/**/*.test.*,packages/*/src/**/*.test.*,packages/*/src/test/**/*
sonar.exclusions=__mocks__,docs,element.io,nginx sonar.exclusions=__mocks__,docs,element.io,nginx
sonar.cpd.exclusions=src/i18n/strings/*.json sonar.cpd.exclusions=src/i18n/strings/*.json
sonar.typescript.tsconfigPath=./tsconfig.json sonar.typescript.tsconfigPath=./tsconfig.json
sonar.javascript.lcov.reportPaths=coverage/lcov.info sonar.javascript.lcov.reportPaths=coverage/lcov.info,packages/shared-components/coverage/lcov.info
sonar.coverage.exclusions=\ sonar.coverage.exclusions=\
test/**/*,\ test/**/*,\
playwright/**/*,\ playwright/**/*,\
@@ -21,5 +21,6 @@ sonar.coverage.exclusions=\
src/components/views/dialogs/devtools/**/*,\ src/components/views/dialogs/devtools/**/*,\
src/utils/SessionLock.ts,\ src/utils/SessionLock.ts,\
src/**/*.d.ts,\ src/**/*.d.ts,\
src/vector/mobile_guide/**/* src/vector/mobile_guide/**/* \
packages/shared-components/src/test/**/*
sonar.testExecutionReportPaths=coverage/jest-sonar-report.xml sonar.testExecutionReportPaths=coverage/jest-sonar-report.xml

View File

@@ -13,7 +13,7 @@ import { type Optional } from "matrix-events-sdk";
import { _t, getUserLanguage } from "./languageHandler"; import { _t, getUserLanguage } from "./languageHandler";
import { getUserTimezone } from "./TimezoneHandler"; import { getUserTimezone } from "./TimezoneHandler";
export { formatSeconds } from "../packages/shared-components/src/utils/DateUtils"; export { formatSeconds } from "@element-hq/web-shared-components";
export const MINUTE_MS = 60000; export const MINUTE_MS = 60000;
export const HOUR_MS = MINUTE_MS * 60; export const HOUR_MS = MINUTE_MS * 60;

View File

@@ -9,7 +9,8 @@ Please see LICENSE files in the repository root for full details.
*/ */
// Import i18n.tsx instead of languageHandler to avoid circular deps // Import i18n.tsx instead of languageHandler to avoid circular deps
import { _td, type TranslationKey } from "../../packages/shared-components/src/utils/i18n"; import { _td, type TranslationKey } from "@element-hq/web-shared-components";
import { IS_MAC, IS_ELECTRON, Key } from "../Keyboard"; import { IS_MAC, IS_ELECTRON, Key } from "../Keyboard";
import { type IBaseSetting } from "../settings/Settings"; import { type IBaseSetting } from "../settings/Settings";
import { type KeyCombo } from "../KeyBindingsManager"; import { type KeyCombo } from "../KeyBindingsManager";

View File

@@ -8,9 +8,9 @@ Please see LICENSE files in the repository root for full details.
import React, { type JSX, type ReactNode } from "react"; import React, { type JSX, type ReactNode } from "react";
import { Text, Heading, Button, Separator } from "@vector-im/compound-web"; import { Text, Heading, Button, Separator } from "@vector-im/compound-web";
import PopOutIcon from "@vector-im/compound-design-tokens/assets/web/icons/pop-out"; import PopOutIcon from "@vector-im/compound-design-tokens/assets/web/icons/pop-out";
import { Flex } from "@element-hq/web-shared-components";
import SdkConfig from "../../SdkConfig"; import SdkConfig from "../../SdkConfig";
import { Flex } from "../../../packages/shared-components/src/utils/Flex";
import { _t } from "../../languageHandler"; import { _t } from "../../languageHandler";
import { Icon as AppleIcon } from "../../../res/themes/element/img/compound/apple.svg"; import { Icon as AppleIcon } from "../../../res/themes/element/img/compound/apple.svg";
import { Icon as MicrosoftIcon } from "../../../res/themes/element/img/compound/microsoft.svg"; import { Icon as MicrosoftIcon } from "../../../res/themes/element/img/compound/microsoft.svg";

View File

@@ -9,13 +9,13 @@ Please see LICENSE files in the repository root for full details.
import EventEmitter from "events"; import EventEmitter from "events";
import { SimpleObservable } from "matrix-widget-api"; import { SimpleObservable } from "matrix-widget-api";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { clamp } from "@element-hq/web-shared-components";
import { UPDATE_EVENT } from "../stores/AsyncStore"; import { UPDATE_EVENT } from "../stores/AsyncStore";
import { arrayFastResample } from "../utils/arrays"; import { arrayFastResample } from "../utils/arrays";
import { type IDestroyable } from "../utils/IDestroyable"; import { type IDestroyable } from "../utils/IDestroyable";
import { PlaybackClock } from "./PlaybackClock"; import { PlaybackClock } from "./PlaybackClock";
import { createAudioContext, decodeOgg } from "./compat"; import { createAudioContext, decodeOgg } from "./compat";
import { clamp } from "../../packages/shared-components/src/utils/numbers";
import { DEFAULT_WAVEFORM, PLAYBACK_WAVEFORM_SAMPLES } from "./consts"; import { DEFAULT_WAVEFORM, PLAYBACK_WAVEFORM_SAMPLES } from "./consts";
import { PlaybackEncoder } from "../PlaybackEncoder"; import { PlaybackEncoder } from "../PlaybackEncoder";

View File

@@ -1,16 +1,14 @@
/* /*
Copyrimport { type IAmplitudePayload, type ITimingPayload, PayloadEvent, WORKLET_NAME } from "./consts"; Copyright 2024 New Vector Ltd.
import { percentageOf } from "../../packages/shared-components/src/utils/numbers";
// from AudioWorkletGlobalScope: https://developer.mozilla.org/en-US/docs/Web/API/AudioWorkletGlobalScope" 2024 New Vector Ltd.
Copyright 2021 The Matrix.org Foundation C.I.C. Copyright 2021 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details. Please see LICENSE files in the repository root for full details.
*/ */
import { percentageOf } from "@element-hq/web-shared-components";
import { type IAmplitudePayload, type ITimingPayload, PayloadEvent, WORKLET_NAME } from "./consts"; import { type IAmplitudePayload, type ITimingPayload, PayloadEvent, WORKLET_NAME } from "./consts";
import { percentageOf } from "../../packages/shared-components/src/utils/numbers";
// from AudioWorkletGlobalScope: https://developer.mozilla.org/en-US/docs/Web/API/AudioWorkletGlobalScope // from AudioWorkletGlobalScope: https://developer.mozilla.org/en-US/docs/Web/API/AudioWorkletGlobalScope
declare const currentTime: number; declare const currentTime: number;

View File

@@ -11,6 +11,7 @@ import encoderPath from "opus-recorder/dist/encoderWorker.min.js";
import { SimpleObservable } from "matrix-widget-api"; import { SimpleObservable } from "matrix-widget-api";
import EventEmitter from "events"; import EventEmitter from "events";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { clamp } from "@element-hq/web-shared-components";
import MediaDeviceHandler from "../MediaDeviceHandler"; import MediaDeviceHandler from "../MediaDeviceHandler";
import { type IDestroyable } from "../utils/IDestroyable"; import { type IDestroyable } from "../utils/IDestroyable";
@@ -19,7 +20,6 @@ import { PayloadEvent, WORKLET_NAME } from "./consts";
import { UPDATE_EVENT } from "../stores/AsyncStore"; import { UPDATE_EVENT } from "../stores/AsyncStore";
import { createAudioContext } from "./compat"; import { createAudioContext } from "./compat";
import { FixedRollingArray } from "../utils/FixedRollingArray"; import { FixedRollingArray } from "../utils/FixedRollingArray";
import { clamp } from "../../packages/shared-components/src/utils/numbers";
import recorderWorkletFactory from "./recorderWorkletFactory"; import recorderWorkletFactory from "./recorderWorkletFactory";
const CHANNELS = 1; // stereo isn't important const CHANNELS = 1; // stereo isn't important

View File

@@ -7,10 +7,10 @@ Please see LICENSE files in the repository root for full details.
*/ */
import React, { type ChangeEvent, type CSSProperties, type ReactNode } from "react"; import React, { type ChangeEvent, type CSSProperties, type ReactNode } from "react";
import { percentageOf } from "@element-hq/web-shared-components";
import { type PlaybackInterface } from "../../../audio/Playback"; import { type PlaybackInterface } from "../../../audio/Playback";
import { MarkedExecution } from "../../../utils/MarkedExecution"; import { MarkedExecution } from "../../../utils/MarkedExecution";
import { percentageOf } from "../../../../packages/shared-components/src/utils/numbers";
import { _t } from "../../../languageHandler"; import { _t } from "../../../languageHandler";
interface IProps { interface IProps {

View File

@@ -7,9 +7,9 @@ Please see LICENSE files in the repository root for full details.
*/ */
import React from "react"; import React from "react";
import { Clock } from "@element-hq/web-shared-components";
import { type IRecordingUpdate } from "../../../audio/VoiceRecording"; import { type IRecordingUpdate } from "../../../audio/VoiceRecording";
import { Clock } from "../../../../packages/shared-components/src/audio/Clock";
import { MarkedExecution } from "../../../utils/MarkedExecution"; import { MarkedExecution } from "../../../utils/MarkedExecution";
import { type VoiceMessageRecording } from "../../../audio/VoiceMessageRecording"; import { type VoiceMessageRecording } from "../../../audio/VoiceMessageRecording";

View File

@@ -7,8 +7,8 @@ Please see LICENSE files in the repository root for full details.
*/ */
import React from "react"; import React from "react";
import { Clock } from "@element-hq/web-shared-components";
import { Clock } from "../../../../packages/shared-components/src/audio/Clock";
import { type Playback, PlaybackState } from "../../../audio/Playback"; import { type Playback, PlaybackState } from "../../../audio/Playback";
import { UPDATE_EVENT } from "../../../stores/AsyncStore"; import { UPDATE_EVENT } from "../../../stores/AsyncStore";

View File

@@ -7,11 +7,11 @@ Please see LICENSE files in the repository root for full details.
*/ */
import React from "react"; import React from "react";
import { percentageOf } from "@element-hq/web-shared-components";
import { arraySeed, arrayTrimFill } from "../../../utils/arrays"; import { arraySeed, arrayTrimFill } from "../../../utils/arrays";
import Waveform from "./Waveform"; import Waveform from "./Waveform";
import { type Playback } from "../../../audio/Playback"; import { type Playback } from "../../../audio/Playback";
import { percentageOf } from "../../../../packages/shared-components/src/utils/numbers";
import { PLAYBACK_WAVEFORM_SAMPLES } from "../../../audio/consts"; import { PLAYBACK_WAVEFORM_SAMPLES } from "../../../audio/consts";
interface IProps { interface IProps {

View File

@@ -8,6 +8,7 @@ Please see LICENSE files in the repository root for full details.
import React, { type HTMLProps, useContext } from "react"; import React, { type HTMLProps, useContext } from "react";
import { type Beacon, BeaconEvent, LocationAssetType } from "matrix-js-sdk/src/matrix"; import { type Beacon, BeaconEvent, LocationAssetType } from "matrix-js-sdk/src/matrix";
import { humanizeTime } from "@element-hq/web-shared-components";
import MatrixClientContext from "../../../contexts/MatrixClientContext"; import MatrixClientContext from "../../../contexts/MatrixClientContext";
import { useEventEmitterState } from "../../../hooks/useEventEmitter"; import { useEventEmitterState } from "../../../hooks/useEventEmitter";
@@ -18,7 +19,6 @@ import BeaconStatus from "./BeaconStatus";
import { BeaconDisplayStatus } from "./displayStatus"; import { BeaconDisplayStatus } from "./displayStatus";
import StyledLiveBeaconIcon from "./StyledLiveBeaconIcon"; import StyledLiveBeaconIcon from "./StyledLiveBeaconIcon";
import ShareLatestLocation from "./ShareLatestLocation"; import ShareLatestLocation from "./ShareLatestLocation";
import { humanizeTime } from "../../../../packages/shared-components/src/utils/humanize";
interface Props { interface Props {
beacon: Beacon; beacon: Beacon;

View File

@@ -12,6 +12,7 @@ import { KnownMembership } from "matrix-js-sdk/src/types";
import { type MatrixCall } from "matrix-js-sdk/src/webrtc/call"; import { type MatrixCall } from "matrix-js-sdk/src/webrtc/call";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { uniqBy } from "lodash"; import { uniqBy } from "lodash";
import { RichList, RichItem, PillInput, Pill } from "@element-hq/web-shared-components";
import { Icon as EmailPillAvatarIcon } from "../../../../res/img/icon-email-pill-avatar.svg"; import { Icon as EmailPillAvatarIcon } from "../../../../res/img/icon-email-pill-avatar.svg";
import { _t, _td } from "../../../languageHandler"; import { _t, _td } from "../../../languageHandler";
@@ -63,10 +64,6 @@ import AskInviteAnywayDialog, { type UnknownProfiles } from "./AskInviteAnywayDi
import { SdkContextClass } from "../../../contexts/SDKContext"; import { SdkContextClass } from "../../../contexts/SDKContext";
import { type UserProfilesStore } from "../../../stores/UserProfilesStore"; import { type UserProfilesStore } from "../../../stores/UserProfilesStore";
import InviteProgressBody from "./InviteProgressBody.tsx"; import InviteProgressBody from "./InviteProgressBody.tsx";
import { RichList } from "../../../../packages/shared-components/src/rich-list/RichList";
import { RichItem } from "../../../../packages/shared-components/src/rich-list/RichItem";
import { PillInput } from "../../../../packages/shared-components/src/pill-input/PillInput";
import { Pill } from "../../../../packages/shared-components/src/pill-input/Pill";
// we have a number of types defined from the Matrix spec which can't reasonably be altered here. // we have a number of types defined from the Matrix spec which can't reasonably be altered here.
/* eslint-disable camelcase */ /* eslint-disable camelcase */

View File

@@ -12,8 +12,8 @@ import { debounce } from "lodash";
import classNames from "classnames"; import classNames from "classnames";
import React, { type ChangeEvent, type FormEvent } from "react"; import React, { type ChangeEvent, type FormEvent } from "react";
import { type SecretStorage } from "matrix-js-sdk/src/matrix"; import { type SecretStorage } from "matrix-js-sdk/src/matrix";
import { Flex } from "@element-hq/web-shared-components";
import { Flex } from "../../../../../packages/shared-components/src/utils/Flex";
import { _t } from "../../../../languageHandler"; import { _t } from "../../../../languageHandler";
import { EncryptionCard } from "../../settings/encryption/EncryptionCard"; import { EncryptionCard } from "../../settings/encryption/EncryptionCard";
import { EncryptionCardButtons } from "../../settings/encryption/EncryptionCardButtons"; import { EncryptionCardButtons } from "../../settings/encryption/EncryptionCardButtons";

View File

@@ -6,13 +6,13 @@ Please see LICENSE files in the repository root for full details.
*/ */
import React, { type JSX, useCallback, useId, useState } from "react"; import React, { type JSX, useCallback, useId, useState } from "react";
import { _t } from "@element-hq/web-shared-components";
import SettingsStore from "../../../settings/SettingsStore"; import SettingsStore from "../../../settings/SettingsStore";
import { type SettingLevel } from "../../../settings/SettingLevel"; import { type SettingLevel } from "../../../settings/SettingLevel";
import { SETTINGS, type StringSettingKey } from "../../../settings/Settings"; import { SETTINGS, type StringSettingKey } from "../../../settings/Settings";
import { useSettingValueAt } from "../../../hooks/useSettings.ts"; import { useSettingValueAt } from "../../../hooks/useSettings.ts";
import Dropdown, { type DropdownProps } from "./Dropdown.tsx"; import Dropdown, { type DropdownProps } from "./Dropdown.tsx";
import { _t } from "../../../../packages/shared-components/src/utils/i18n.tsx";
interface Props { interface Props {
settingKey: StringSettingKey; settingKey: StringSettingKey;

View File

@@ -9,6 +9,7 @@ Please see LICENSE files in the repository root for full details.
import React, { type Dispatch } from "react"; import React, { type Dispatch } from "react";
import { DATA_BY_CATEGORY, getEmojiFromUnicode, type Emoji as IEmoji } from "@matrix-org/emojibase-bindings"; import { DATA_BY_CATEGORY, getEmojiFromUnicode, type Emoji as IEmoji } from "@matrix-org/emojibase-bindings";
import { clamp } from "@element-hq/web-shared-components";
import classNames from "classnames"; import classNames from "classnames";
import { _t } from "../../../languageHandler"; import { _t } from "../../../languageHandler";
@@ -27,7 +28,6 @@ import {
Type, Type,
} from "../../../accessibility/RovingTabIndex"; } from "../../../accessibility/RovingTabIndex";
import { Key } from "../../../Keyboard"; import { Key } from "../../../Keyboard";
import { clamp } from "../../../../packages/shared-components/src/utils/numbers";
import { type ButtonEvent } from "../elements/AccessibleButton"; import { type ButtonEvent } from "../elements/AccessibleButton";
export const CATEGORY_HEADER_HEIGHT = 20; export const CATEGORY_HEADER_HEIGHT = 20;

View File

@@ -10,6 +10,7 @@ import React, { type JSX, createRef } from "react";
import { type MatrixEvent } from "matrix-js-sdk/src/matrix"; import { type MatrixEvent } from "matrix-js-sdk/src/matrix";
import { CallErrorCode, CallState } from "matrix-js-sdk/src/webrtc/call"; import { CallErrorCode, CallState } from "matrix-js-sdk/src/webrtc/call";
import classNames from "classnames"; import classNames from "classnames";
import { Clock } from "@element-hq/web-shared-components";
import { _t } from "../../../languageHandler"; import { _t } from "../../../languageHandler";
import MemberAvatar from "../avatars/MemberAvatar"; import MemberAvatar from "../avatars/MemberAvatar";
@@ -18,7 +19,6 @@ import { LegacyCallEventGrouperEvent } from "../../structures/LegacyCallEventGro
import AccessibleButton from "../elements/AccessibleButton"; import AccessibleButton from "../elements/AccessibleButton";
import InfoTooltip, { InfoTooltipKind } from "../elements/InfoTooltip"; import InfoTooltip, { InfoTooltipKind } from "../elements/InfoTooltip";
import { formatPreciseDuration } from "../../../DateUtils"; import { formatPreciseDuration } from "../../../DateUtils";
import { Clock } from "../../../../packages/shared-components/src/audio/Clock";
const MAX_NON_NARROW_WIDTH = (450 / 70) * 100; const MAX_NON_NARROW_WIDTH = (450 / 70) * 100;

View File

@@ -10,6 +10,7 @@ import React, { type JSX, useEffect, useMemo } from "react";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { type IContent } from "matrix-js-sdk/src/matrix"; import { type IContent } from "matrix-js-sdk/src/matrix";
import { type MediaEventContent } from "matrix-js-sdk/src/types"; import { type MediaEventContent } from "matrix-js-sdk/src/types";
import { AudioPlayerView } from "@element-hq/web-shared-components";
import { type Playback } from "../../../audio/Playback"; import { type Playback } from "../../../audio/Playback";
import InlineSpinner from "../elements/InlineSpinner"; import InlineSpinner from "../elements/InlineSpinner";
@@ -20,7 +21,6 @@ import { PlaybackManager } from "../../../audio/PlaybackManager";
import RoomContext, { TimelineRenderingType } from "../../../contexts/RoomContext"; import RoomContext, { TimelineRenderingType } from "../../../contexts/RoomContext";
import MediaProcessingError from "./shared/MediaProcessingError"; import MediaProcessingError from "./shared/MediaProcessingError";
import { AudioPlayerViewModel } from "../../../viewmodels/audio/AudioPlayerViewModel"; import { AudioPlayerViewModel } from "../../../viewmodels/audio/AudioPlayerViewModel";
import { AudioPlayerView } from "../../../../packages/shared-components/src/audio/AudioPlayerView";
interface IState { interface IState {
error?: boolean; error?: boolean;

View File

@@ -8,8 +8,7 @@ Please see LICENSE files in the repository root for full details.
import React, { type ComponentType } from "react"; import React, { type ComponentType } from "react";
import { Text } from "@vector-im/compound-web"; import { Text } from "@vector-im/compound-web";
import { Flex } from "@element-hq/web-shared-components";
import { Flex } from "../../../../packages/shared-components/src/utils/Flex";
interface Props { interface Props {
Icon: ComponentType<React.SVGAttributes<SVGElement>>; Icon: ComponentType<React.SVGAttributes<SVGElement>>;

View File

@@ -39,6 +39,7 @@ import ErrorIcon from "@vector-im/compound-design-tokens/assets/web/icons/error"
import ErrorSolidIcon from "@vector-im/compound-design-tokens/assets/web/icons/error-solid"; import ErrorSolidIcon from "@vector-im/compound-design-tokens/assets/web/icons/error-solid";
import ChevronDownIcon from "@vector-im/compound-design-tokens/assets/web/icons/chevron-down"; import ChevronDownIcon from "@vector-im/compound-design-tokens/assets/web/icons/chevron-down";
import { JoinRule, type Room } from "matrix-js-sdk/src/matrix"; import { JoinRule, type Room } from "matrix-js-sdk/src/matrix";
import { Box, Flex } from "@element-hq/web-shared-components";
import BaseCard from "./BaseCard.tsx"; import BaseCard from "./BaseCard.tsx";
import { _t } from "../../../languageHandler.tsx"; import { _t } from "../../../languageHandler.tsx";
@@ -46,9 +47,7 @@ import RoomAvatar from "../avatars/RoomAvatar.tsx";
import { E2EStatus } from "../../../utils/ShieldUtils.ts"; import { E2EStatus } from "../../../utils/ShieldUtils.ts";
import { type RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks.ts"; import { type RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks.ts";
import RoomName from "../elements/RoomName.tsx"; import RoomName from "../elements/RoomName.tsx";
import { Flex } from "../../../../packages/shared-components/src/utils/Flex";
import { Linkify, topicToHtml } from "../../../HtmlUtils.tsx"; import { Linkify, topicToHtml } from "../../../HtmlUtils.tsx";
import { Box } from "../../../../packages/shared-components/src/utils/Box";
import { useRoomSummaryCardViewModel } from "../../viewmodels/right_panel/RoomSummaryCardViewModel.tsx"; import { useRoomSummaryCardViewModel } from "../../viewmodels/right_panel/RoomSummaryCardViewModel.tsx";
import { useRoomTopicViewModel } from "../../viewmodels/right_panel/RoomSummaryCardTopicViewModel.tsx"; import { useRoomTopicViewModel } from "../../viewmodels/right_panel/RoomSummaryCardTopicViewModel.tsx";

View File

@@ -9,10 +9,10 @@ import React from "react";
import { type User, type RoomMember } from "matrix-js-sdk/src/matrix"; import { type User, type RoomMember } from "matrix-js-sdk/src/matrix";
import { Text, Button, InlineSpinner, Badge } from "@vector-im/compound-web"; import { Text, Button, InlineSpinner, Badge } from "@vector-im/compound-web";
import { VerifiedIcon } from "@vector-im/compound-design-tokens/assets/web/icons"; import { VerifiedIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import { Flex } from "@element-hq/web-shared-components";
import { useUserInfoVerificationViewModel } from "../../../viewmodels/right_panel/user_info/UserInfoHeaderVerificationViewModel"; import { useUserInfoVerificationViewModel } from "../../../viewmodels/right_panel/user_info/UserInfoHeaderVerificationViewModel";
import { type IDevice } from "../UserInfo"; import { type IDevice } from "../UserInfo";
import { Flex } from "../../../../../packages/shared-components/src/utils/Flex";
import { _t } from "../../../../languageHandler"; import { _t } from "../../../../languageHandler";
export const UserInfoHeaderVerificationView: React.FC<{ export const UserInfoHeaderVerificationView: React.FC<{

View File

@@ -8,11 +8,11 @@ Please see LICENSE files in the repository root for full details.
import React, { type JSX } from "react"; import React, { type JSX } from "react";
import { type User, type RoomMember } from "matrix-js-sdk/src/matrix"; import { type User, type RoomMember } from "matrix-js-sdk/src/matrix";
import { Heading, Tooltip, Text } from "@vector-im/compound-web"; import { Heading, Tooltip, Text } from "@vector-im/compound-web";
import { Flex } from "@element-hq/web-shared-components";
import { useUserfoHeaderViewModel } from "../../../viewmodels/right_panel/user_info/UserInfoHeaderViewModel"; import { useUserfoHeaderViewModel } from "../../../viewmodels/right_panel/user_info/UserInfoHeaderViewModel";
import MemberAvatar from "../../avatars/MemberAvatar"; import MemberAvatar from "../../avatars/MemberAvatar";
import { Container, type Member, type IDevice } from "../UserInfo"; import { Container, type Member, type IDevice } from "../UserInfo";
import { Flex } from "../../../../../packages/shared-components/src/utils/Flex";
import PresenceLabel from "../../rooms/PresenceLabel"; import PresenceLabel from "../../rooms/PresenceLabel";
import CopyableText from "../../elements/CopyableText"; import CopyableText from "../../elements/CopyableText";
import { UserInfoHeaderVerificationView } from "./UserInfoHeaderVerificationView"; import { UserInfoHeaderVerificationView } from "./UserInfoHeaderVerificationView";

View File

@@ -11,6 +11,7 @@ import classNames from "classnames";
import { Resizable, type Size } from "re-resizable"; import { Resizable, type Size } from "re-resizable";
import { type Room } from "matrix-js-sdk/src/matrix"; import { type Room } from "matrix-js-sdk/src/matrix";
import { type IWidget } from "matrix-widget-api"; import { type IWidget } from "matrix-widget-api";
import { clamp, percentageOf, percentageWithin } from "@element-hq/web-shared-components";
import AppTile from "../elements/AppTile"; import AppTile from "../elements/AppTile";
import dis from "../../../dispatcher/dispatcher"; import dis from "../../../dispatcher/dispatcher";
@@ -22,7 +23,6 @@ import ResizeHandle from "../elements/ResizeHandle";
import Resizer, { type IConfig } from "../../../resizer/resizer"; import Resizer, { type IConfig } from "../../../resizer/resizer";
import PercentageDistributor from "../../../resizer/distributors/percentage"; import PercentageDistributor from "../../../resizer/distributors/percentage";
import { Container, WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore"; import { Container, WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore";
import { clamp, percentageOf, percentageWithin } from "../../../../packages/shared-components/src/utils/numbers";
import UIStore from "../../../stores/UIStore"; import UIStore from "../../../stores/UIStore";
import { type ActionPayload } from "../../../dispatcher/payloads"; import { type ActionPayload } from "../../../dispatcher/payloads";
import Spinner from "../elements/Spinner"; import Spinner from "../elements/Spinner";

View File

@@ -9,8 +9,8 @@ import { Search, Text, Button, Tooltip, InlineSpinner } from "@vector-im/compoun
import React from "react"; import React from "react";
import InviteIcon from "@vector-im/compound-design-tokens/assets/web/icons/user-add"; import InviteIcon from "@vector-im/compound-design-tokens/assets/web/icons/user-add";
import { UserAddIcon } from "@vector-im/compound-design-tokens/assets/web/icons"; import { UserAddIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import { Flex } from "@element-hq/web-shared-components";
import { Flex } from "../../../../../packages/shared-components/src/utils/Flex";
import { type MemberListViewState } from "../../../viewmodels/memberlist/MemberListViewModel"; import { type MemberListViewState } from "../../../viewmodels/memberlist/MemberListViewModel";
import { _t } from "../../../../languageHandler"; import { _t } from "../../../../languageHandler";

View File

@@ -7,8 +7,8 @@ Please see LICENSE files in the repository root for full details.
import { Form } from "@vector-im/compound-web"; import { Form } from "@vector-im/compound-web";
import React, { type JSX, useCallback } from "react"; import React, { type JSX, useCallback } from "react";
import { Flex } from "@element-hq/web-shared-components";
import { Flex } from "../../../../../packages/shared-components/src/utils/Flex";
import { import {
type MemberWithSeparator, type MemberWithSeparator,
SEPARATOR, SEPARATOR,

View File

@@ -8,8 +8,7 @@ Please see LICENSE files in the repository root for full details.
import React, { type JSX } from "react"; import React, { type JSX } from "react";
import EmailIcon from "@vector-im/compound-design-tokens/assets/web/icons/email-solid"; import EmailIcon from "@vector-im/compound-design-tokens/assets/web/icons/email-solid";
import UserAddIcon from "@vector-im/compound-design-tokens/assets/web/icons/user-add-solid"; import UserAddIcon from "@vector-im/compound-design-tokens/assets/web/icons/user-add-solid";
import { Flex } from "@element-hq/web-shared-components";
import { Flex } from "../../../../../../../packages/shared-components/src/utils/Flex";
interface Props { interface Props {
isThreePid: boolean; isThreePid: boolean;

View File

@@ -12,8 +12,8 @@ import NotificationOffIcon from "@vector-im/compound-design-tokens/assets/web/ic
import VideoCallIcon from "@vector-im/compound-design-tokens/assets/web/icons/video-call-solid"; import VideoCallIcon from "@vector-im/compound-design-tokens/assets/web/icons/video-call-solid";
import EmailIcon from "@vector-im/compound-design-tokens/assets/web/icons/email-solid"; import EmailIcon from "@vector-im/compound-design-tokens/assets/web/icons/email-solid";
import { UnreadCounter, Unread } from "@vector-im/compound-web"; import { UnreadCounter, Unread } from "@vector-im/compound-web";
import { Flex } from "@element-hq/web-shared-components";
import { Flex } from "../../../../packages/shared-components/src/utils/Flex";
import { type RoomNotificationState } from "../../../stores/notifications/RoomNotificationState"; import { type RoomNotificationState } from "../../../stores/notifications/RoomNotificationState";
import { useTypedEventEmitterState } from "../../../hooks/useEventEmitter"; import { useTypedEventEmitterState } from "../../../hooks/useEventEmitter";
import { NotificationStateEvents } from "../../../stores/notifications/NotificationState"; import { NotificationStateEvents } from "../../../stores/notifications/NotificationState";

View File

@@ -19,14 +19,13 @@ import ErrorIcon from "@vector-im/compound-design-tokens/assets/web/icons/error-
import PublicIcon from "@vector-im/compound-design-tokens/assets/web/icons/public"; import PublicIcon from "@vector-im/compound-design-tokens/assets/web/icons/public";
import { JoinRule, type Room } from "matrix-js-sdk/src/matrix"; import { JoinRule, type Room } from "matrix-js-sdk/src/matrix";
import { type ViewRoomOpts } from "@matrix-org/react-sdk-module-api/lib/lifecycles/RoomViewLifecycle"; import { type ViewRoomOpts } from "@matrix-org/react-sdk-module-api/lib/lifecycles/RoomViewLifecycle";
import { Flex, Box } from "@element-hq/web-shared-components";
import { useRoomName } from "../../../../hooks/useRoomName.ts"; import { useRoomName } from "../../../../hooks/useRoomName.ts";
import { RightPanelPhases } from "../../../../stores/right-panel/RightPanelStorePhases.ts"; import { RightPanelPhases } from "../../../../stores/right-panel/RightPanelStorePhases.ts";
import { useMatrixClientContext } from "../../../../contexts/MatrixClientContext.tsx"; import { useMatrixClientContext } from "../../../../contexts/MatrixClientContext.tsx";
import { useRoomMemberCount, useRoomMembers } from "../../../../hooks/useRoomMembers.ts"; import { useRoomMemberCount, useRoomMembers } from "../../../../hooks/useRoomMembers.ts";
import { _t } from "../../../../languageHandler.tsx"; import { _t } from "../../../../languageHandler.tsx";
import { Flex } from "../../../../../packages/shared-components/src/utils/Flex";
import { Box } from "../../../../../packages/shared-components/src/utils/Box";
import { getPlatformCallTypeProps, useRoomCall } from "../../../../hooks/room/useRoomCall.tsx"; import { getPlatformCallTypeProps, useRoomCall } from "../../../../hooks/room/useRoomCall.tsx";
import { useRoomThreadNotifications } from "../../../../hooks/room/useRoomThreadNotifications.ts"; import { useRoomThreadNotifications } from "../../../../hooks/room/useRoomThreadNotifications.ts";
import { useGlobalNotificationState } from "../../../../hooks/useGlobalNotificationState.ts"; import { useGlobalNotificationState } from "../../../../hooks/useGlobalNotificationState.ts";

View File

@@ -9,9 +9,9 @@ import React, { type JSX, type PropsWithChildren } from "react";
import { Button } from "@vector-im/compound-web"; import { Button } from "@vector-im/compound-web";
import ChatIcon from "@vector-im/compound-design-tokens/assets/web/icons/chat"; import ChatIcon from "@vector-im/compound-design-tokens/assets/web/icons/chat";
import RoomIcon from "@vector-im/compound-design-tokens/assets/web/icons/room"; import RoomIcon from "@vector-im/compound-design-tokens/assets/web/icons/room";
import { Flex } from "@element-hq/web-shared-components";
import type { RoomListViewState } from "../../../viewmodels/roomlist/RoomListViewModel"; import type { RoomListViewState } from "../../../viewmodels/roomlist/RoomListViewModel";
import { Flex } from "../../../../../packages/shared-components/src/utils/Flex";
import { _t } from "../../../../languageHandler"; import { _t } from "../../../../languageHandler";
import { FilterKey } from "../../../../stores/room-list-v3/skip-list/filters"; import { FilterKey } from "../../../../stores/room-list-v3/skip-list/filters";
import { type PrimaryFilter } from "../../../viewmodels/roomlist/useFilteredRooms"; import { type PrimaryFilter } from "../../../viewmodels/roomlist/useFilteredRooms";

View File

@@ -15,9 +15,9 @@ import PreferencesIcon from "@vector-im/compound-design-tokens/assets/web/icons/
import SettingsIcon from "@vector-im/compound-design-tokens/assets/web/icons/settings"; import SettingsIcon from "@vector-im/compound-design-tokens/assets/web/icons/settings";
import VideoCallIcon from "@vector-im/compound-design-tokens/assets/web/icons/video-call"; import VideoCallIcon from "@vector-im/compound-design-tokens/assets/web/icons/video-call";
import ChatIcon from "@vector-im/compound-design-tokens/assets/web/icons/chat"; import ChatIcon from "@vector-im/compound-design-tokens/assets/web/icons/chat";
import { Flex } from "@element-hq/web-shared-components";
import { _t } from "../../../../languageHandler"; import { _t } from "../../../../languageHandler";
import { Flex } from "../../../../../packages/shared-components/src/utils/Flex";
import { import {
type RoomListHeaderViewState, type RoomListHeaderViewState,
useRoomListHeaderViewModel, useRoomListHeaderViewModel,

View File

@@ -19,9 +19,9 @@ import NotificationIcon from "@vector-im/compound-design-tokens/assets/web/icons
import NotificationOffIcon from "@vector-im/compound-design-tokens/assets/web/icons/notifications-off-solid"; import NotificationOffIcon from "@vector-im/compound-design-tokens/assets/web/icons/notifications-off-solid";
import CheckIcon from "@vector-im/compound-design-tokens/assets/web/icons/check"; import CheckIcon from "@vector-im/compound-design-tokens/assets/web/icons/check";
import { type Room } from "matrix-js-sdk/src/matrix"; import { type Room } from "matrix-js-sdk/src/matrix";
import { Flex } from "@element-hq/web-shared-components";
import { _t } from "../../../../languageHandler"; import { _t } from "../../../../languageHandler";
import { Flex } from "../../../../../packages/shared-components/src/utils/Flex";
import { import {
type RoomListItemMenuViewState, type RoomListItemMenuViewState,
useRoomListItemMenuViewModel, useRoomListItemMenuViewModel,

View File

@@ -8,9 +8,9 @@
import React, { type JSX, memo, useCallback, useEffect, useRef, useState } from "react"; import React, { type JSX, memo, useCallback, useEffect, useRef, useState } from "react";
import { type Room } from "matrix-js-sdk/src/matrix"; import { type Room } from "matrix-js-sdk/src/matrix";
import classNames from "classnames"; import classNames from "classnames";
import { Flex } from "@element-hq/web-shared-components";
import { useRoomListItemViewModel } from "../../../viewmodels/roomlist/RoomListItemViewModel"; import { useRoomListItemViewModel } from "../../../viewmodels/roomlist/RoomListItemViewModel";
import { Flex } from "../../../../../packages/shared-components/src/utils/Flex";
import { RoomListItemMenuView } from "./RoomListItemMenuView"; import { RoomListItemMenuView } from "./RoomListItemMenuView";
import { NotificationDecoration } from "../NotificationDecoration"; import { NotificationDecoration } from "../NotificationDecoration";
import { RoomAvatarView } from "../../avatars/RoomAvatarView"; import { RoomAvatarView } from "../../avatars/RoomAvatarView";

View File

@@ -6,13 +6,13 @@ Please see LICENSE files in the repository root for full details.
*/ */
import React, { useState, useCallback } from "react"; import React, { useState, useCallback } from "react";
import { Flex } from "@element-hq/web-shared-components";
import { shouldShowComponent } from "../../../../customisations/helpers/UIComponents"; import { shouldShowComponent } from "../../../../customisations/helpers/UIComponents";
import { UIComponent } from "../../../../settings/UIFeature"; import { UIComponent } from "../../../../settings/UIFeature";
import { RoomListSearch } from "./RoomListSearch"; import { RoomListSearch } from "./RoomListSearch";
import { RoomListHeaderView } from "./RoomListHeaderView"; import { RoomListHeaderView } from "./RoomListHeaderView";
import { RoomListView } from "./RoomListView"; import { RoomListView } from "./RoomListView";
import { Flex } from "../../../../../packages/shared-components/src/utils/Flex";
import { _t } from "../../../../languageHandler"; import { _t } from "../../../../languageHandler";
import { getKeyBindingsManager } from "../../../../KeyBindingsManager"; import { getKeyBindingsManager } from "../../../../KeyBindingsManager";
import { KeyBindingAction } from "../../../../accessibility/KeyboardShortcuts"; import { KeyBindingAction } from "../../../../accessibility/KeyboardShortcuts";

View File

@@ -8,9 +8,9 @@
import React, { type JSX, useEffect, useId, useRef, useState, type RefObject } from "react"; import React, { type JSX, useEffect, useId, useRef, useState, type RefObject } from "react";
import { ChatFilter, IconButton } from "@vector-im/compound-web"; import { ChatFilter, IconButton } from "@vector-im/compound-web";
import ChevronDownIcon from "@vector-im/compound-design-tokens/assets/web/icons/chevron-down"; import ChevronDownIcon from "@vector-im/compound-design-tokens/assets/web/icons/chevron-down";
import { Flex } from "@element-hq/web-shared-components";
import type { RoomListViewState } from "../../../viewmodels/roomlist/RoomListViewModel"; import type { RoomListViewState } from "../../../viewmodels/roomlist/RoomListViewModel";
import { Flex } from "../../../../../packages/shared-components/src/utils/Flex";
import { _t } from "../../../../languageHandler"; import { _t } from "../../../../languageHandler";
interface RoomListPrimaryFiltersProps { interface RoomListPrimaryFiltersProps {

View File

@@ -10,6 +10,7 @@ import { Button } from "@vector-im/compound-web";
import ExploreIcon from "@vector-im/compound-design-tokens/assets/web/icons/explore"; import ExploreIcon from "@vector-im/compound-design-tokens/assets/web/icons/explore";
import SearchIcon from "@vector-im/compound-design-tokens/assets/web/icons/search"; import SearchIcon from "@vector-im/compound-design-tokens/assets/web/icons/search";
import DialPadIcon from "@vector-im/compound-design-tokens/assets/web/icons/dial-pad"; import DialPadIcon from "@vector-im/compound-design-tokens/assets/web/icons/dial-pad";
import { Flex } from "@element-hq/web-shared-components";
import { IS_MAC, Key } from "../../../../Keyboard"; import { IS_MAC, Key } from "../../../../Keyboard";
import { _t } from "../../../../languageHandler"; import { _t } from "../../../../languageHandler";
@@ -20,7 +21,6 @@ import { MetaSpace } from "../../../../stores/spaces";
import { Action } from "../../../../dispatcher/actions"; import { Action } from "../../../../dispatcher/actions";
import PosthogTrackers from "../../../../PosthogTrackers"; import PosthogTrackers from "../../../../PosthogTrackers";
import defaultDispatcher from "../../../../dispatcher/dispatcher"; import defaultDispatcher from "../../../../dispatcher/dispatcher";
import { Flex } from "../../../../../packages/shared-components/src/utils/Flex";
import { useTypedEventEmitterState } from "../../../../hooks/useEventEmitter"; import { useTypedEventEmitterState } from "../../../../hooks/useEventEmitter";
import LegacyCallHandler, { LegacyCallHandlerEvent } from "../../../../LegacyCallHandler"; import LegacyCallHandler, { LegacyCallHandlerEvent } from "../../../../LegacyCallHandler";

View File

@@ -10,6 +10,7 @@ import React, { type JSX } from "react";
import { EventType, type MatrixEvent, type Room, RoomStateEvent } from "matrix-js-sdk/src/matrix"; import { EventType, type MatrixEvent, type Room, RoomStateEvent } from "matrix-js-sdk/src/matrix";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { Button, Text } from "@vector-im/compound-web"; import { Button, Text } from "@vector-im/compound-web";
import { Flex } from "@element-hq/web-shared-components";
import { MatrixClientPeg } from "../../../MatrixClientPeg"; import { MatrixClientPeg } from "../../../MatrixClientPeg";
import { _t } from "../../../languageHandler"; import { _t } from "../../../languageHandler";
@@ -19,7 +20,6 @@ import { isValid3pidInvite } from "../../../RoomInvite";
import { Action } from "../../../dispatcher/actions"; import { Action } from "../../../dispatcher/actions";
import ErrorDialog from "../dialogs/ErrorDialog"; import ErrorDialog from "../dialogs/ErrorDialog";
import BaseCard from "../right_panel/BaseCard"; import BaseCard from "../right_panel/BaseCard";
import { Flex } from "../../../../packages/shared-components/src/utils/Flex";
interface IProps { interface IProps {
event: MatrixEvent; event: MatrixEvent;

View File

@@ -11,6 +11,7 @@ import { logger } from "matrix-js-sdk/src/logger";
import { EditInPlace, Alert, ErrorMessage } from "@vector-im/compound-web"; import { EditInPlace, Alert, ErrorMessage } from "@vector-im/compound-web";
import PopOutIcon from "@vector-im/compound-design-tokens/assets/web/icons/pop-out"; import PopOutIcon from "@vector-im/compound-design-tokens/assets/web/icons/pop-out";
import SignOutIcon from "@vector-im/compound-design-tokens/assets/web/icons/sign-out"; import SignOutIcon from "@vector-im/compound-design-tokens/assets/web/icons/sign-out";
import { Flex } from "@element-hq/web-shared-components";
import { _t } from "../../../languageHandler"; import { _t } from "../../../languageHandler";
import { OwnProfileStore } from "../../../stores/OwnProfileStore"; import { OwnProfileStore } from "../../../stores/OwnProfileStore";
@@ -26,7 +27,6 @@ import AccessibleButton from "../elements/AccessibleButton";
import LogoutDialog, { shouldShowLogoutDialog } from "../dialogs/LogoutDialog"; import LogoutDialog, { shouldShowLogoutDialog } from "../dialogs/LogoutDialog";
import Modal from "../../../Modal"; import Modal from "../../../Modal";
import defaultDispatcher from "../../../dispatcher/dispatcher"; import defaultDispatcher from "../../../dispatcher/dispatcher";
import { Flex } from "../../../../packages/shared-components/src/utils/Flex";
const SpinnerToast: React.FC<{ children?: ReactNode }> = ({ children }) => ( const SpinnerToast: React.FC<{ children?: ReactNode }> = ({ children }) => (
<> <>

View File

@@ -6,8 +6,7 @@
*/ */
import React, { type JSX, type PropsWithChildren } from "react"; import React, { type JSX, type PropsWithChildren } from "react";
import { Flex } from "@element-hq/web-shared-components";
import { Flex } from "../../../../../packages/shared-components/src/utils/Flex";
/** /**
* A component for emphasised text within an {@link EncryptionCard} * A component for emphasised text within an {@link EncryptionCard}

View File

@@ -18,6 +18,7 @@ import {
M_POLL_START, M_POLL_START,
} from "matrix-js-sdk/src/matrix"; } from "matrix-js-sdk/src/matrix";
import { type Optional } from "matrix-events-sdk"; import { type Optional } from "matrix-events-sdk";
import { TextualEventView } from "@element-hq/web-shared-components";
import SettingsStore from "../settings/SettingsStore"; import SettingsStore from "../settings/SettingsStore";
import type LegacyCallEventGrouper from "../components/structures/LegacyCallEventGrouper"; import type LegacyCallEventGrouper from "../components/structures/LegacyCallEventGrouper";
@@ -43,7 +44,6 @@ import { shouldDisplayAsBeaconTile } from "../utils/beacon/timeline";
import { type IBodyProps } from "../components/views/messages/IBodyProps"; import { type IBodyProps } from "../components/views/messages/IBodyProps";
import { ModuleApi } from "../modules/Api"; import { ModuleApi } from "../modules/Api";
import { TextualEventViewModel } from "../viewmodels/event-tiles/TextualEventViewModel"; import { TextualEventViewModel } from "../viewmodels/event-tiles/TextualEventViewModel";
import { TextualEventView } from "../../packages/shared-components/src/event-tiles/TextualEventView";
import { ElementCallEventType } from "../call-types"; import { ElementCallEventType } from "../call-types";
// Subset of EventTile's IProps plus some mixins // Subset of EventTile's IProps plus some mixins

View File

@@ -5,19 +5,11 @@
* Please see LICENSE files in the repository root for full details. * Please see LICENSE files in the repository root for full details.
*/ */
import counterpart from "counterpart";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { type Optional } from "matrix-events-sdk"; import { type Optional } from "matrix-events-sdk";
import { MapWithDefault } from "matrix-js-sdk/src/utils"; import { MapWithDefault } from "matrix-js-sdk/src/utils";
import { type TranslationStringsObject } from "@matrix-org/react-sdk-module-api"; import { type TranslationStringsObject } from "@matrix-org/react-sdk-module-api";
import _ from "lodash"; import _ from "lodash";
import SettingsStore from "./settings/SettingsStore";
import PlatformPeg from "./PlatformPeg";
import { SettingLevel } from "./settings/SettingLevel";
import { retry } from "./utils/promise";
import SdkConfig from "./SdkConfig";
import { ModuleRunner } from "./modules/ModuleRunner";
import { import {
_t, _t,
normalizeLanguageKey, normalizeLanguageKey,
@@ -25,7 +17,18 @@ import {
type IVariables, type IVariables,
KEY_SEPARATOR, KEY_SEPARATOR,
getLangsJson, getLangsJson,
} from "../packages/shared-components/src/utils/i18n"; registerTranslations,
setLocale,
getLocale,
setMissingEntryGenerator as setMissingEntryGeneratorSharedComponents,
} from "@element-hq/web-shared-components";
import SettingsStore from "./settings/SettingsStore";
import PlatformPeg from "./PlatformPeg";
import { SettingLevel } from "./settings/SettingLevel";
import { retry } from "./utils/promise";
import SdkConfig from "./SdkConfig";
import { ModuleRunner } from "./modules/ModuleRunner";
export { export {
_t, _t,
@@ -40,7 +43,7 @@ export {
normalizeLanguageKey, normalizeLanguageKey,
getNormalizedLanguageKeys, getNormalizedLanguageKeys,
substitute, substitute,
} from "../packages/shared-components/src/utils/i18n"; } from "@element-hq/web-shared-components";
const i18nFolder = "i18n/"; const i18nFolder = "i18n/";
@@ -100,7 +103,7 @@ export function getUserLanguage(): string {
// Currently only used in unit tests to avoid having to load // Currently only used in unit tests to avoid having to load
// the translations in element-web // the translations in element-web
export function setMissingEntryGenerator(f: (value: string) => void): void { export function setMissingEntryGenerator(f: (value: string) => void): void {
counterpart.setMissingEntryGenerator(f); setMissingEntryGeneratorSharedComponents(f);
} }
export async function setLanguage(...preferredLangs: string[]): Promise<void> { export async function setLanguage(...preferredLangs: string[]): Promise<void> {
@@ -116,8 +119,8 @@ export async function setLanguage(...preferredLangs: string[]): Promise<void> {
const languageData = await getLanguageRetry(i18nFolder + availableLanguages[chosenLanguage]); const languageData = await getLanguageRetry(i18nFolder + availableLanguages[chosenLanguage]);
counterpart.registerTranslations(chosenLanguage, languageData); registerTranslations(chosenLanguage, languageData);
counterpart.setLocale(chosenLanguage); setLocale(chosenLanguage);
await SettingsStore.setValue("language", null, SettingLevel.DEVICE, chosenLanguage); await SettingsStore.setValue("language", null, SettingLevel.DEVICE, chosenLanguage);
// Adds a lot of noise to test runs, so disable logging there. // Adds a lot of noise to test runs, so disable logging there.
@@ -128,7 +131,7 @@ export async function setLanguage(...preferredLangs: string[]): Promise<void> {
// Set 'en' as fallback language: // Set 'en' as fallback language:
if (chosenLanguage !== "en") { if (chosenLanguage !== "en") {
const fallbackLanguageData = await getLanguageRetry(i18nFolder + availableLanguages["en"]); const fallbackLanguageData = await getLanguageRetry(i18nFolder + availableLanguages["en"]);
counterpart.registerTranslations("en", fallbackLanguageData); registerTranslations("en", fallbackLanguageData);
} }
await registerCustomTranslations(); await registerCustomTranslations();
@@ -166,7 +169,7 @@ export function getLanguageFromBrowser(): string {
} }
export function getCurrentLanguage(): string { export function getCurrentLanguage(): string {
return counterpart.getLocale(); return getLocale();
} }
/** /**
@@ -258,7 +261,7 @@ function doRegisterTranslations(customTranslations: TranslationStringsObject): v
// Finally, tell counterpart about our translations // Finally, tell counterpart about our translations
for (const [lang, translations] of langs) { for (const [lang, translations] of langs) {
counterpart.registerTranslations(lang, translations); registerTranslations(lang, translations);
} }
} }

View File

@@ -6,7 +6,7 @@ Please see LICENSE files in the repository root for full details.
*/ */
import { type I18nApi as II18nApi, type Variables, type Translations } from "@element-hq/element-web-module-api"; import { type I18nApi as II18nApi, type Variables, type Translations } from "@element-hq/element-web-module-api";
import counterpart from "counterpart"; import { registerTranslations } from "@element-hq/web-shared-components";
import { _t, getCurrentLanguage, type TranslationKey } from "../languageHandler.tsx"; import { _t, getCurrentLanguage, type TranslationKey } from "../languageHandler.tsx";
@@ -32,7 +32,7 @@ export class I18nApi implements II18nApi {
// Finally, tell counterpart about our translations // Finally, tell counterpart about our translations
for (const lang in langs) { for (const lang in langs) {
counterpart.registerTranslations(lang, langs[lang]); registerTranslations(lang, langs[lang]);
} }
} }

View File

@@ -9,10 +9,10 @@ Please see LICENSE files in the repository root for full details.
import React, { type ReactNode } from "react"; import React, { type ReactNode } from "react";
import { STABLE_MSC4133_EXTENDED_PROFILES, UNSTABLE_MSC4133_EXTENDED_PROFILES } from "matrix-js-sdk/src/matrix"; import { STABLE_MSC4133_EXTENDED_PROFILES, UNSTABLE_MSC4133_EXTENDED_PROFILES } from "matrix-js-sdk/src/matrix";
// Import these directly from shared-components to avoid circular deps
import { _t, _td, type TranslationKey } from "@element-hq/web-shared-components";
import { type MediaPreviewConfig } from "../@types/media_preview.ts"; import { type MediaPreviewConfig } from "../@types/media_preview.ts";
// Import i18n.tsx instead of languageHandler to avoid circular deps
import { _t, _td, type TranslationKey } from "../../packages/shared-components/src/utils/i18n";
import DeviceIsolationModeController from "./controllers/DeviceIsolationModeController.ts"; import DeviceIsolationModeController from "./controllers/DeviceIsolationModeController.ts";
import { import {
NotificationBodyEnabledController, NotificationBodyEnabledController,

View File

@@ -10,11 +10,11 @@ import { type Room, RoomStateEvent, type MatrixEvent } from "matrix-js-sdk/src/m
import { type Optional } from "matrix-events-sdk"; import { type Optional } from "matrix-events-sdk";
import { MapWithDefault, recursiveMapToObject } from "matrix-js-sdk/src/utils"; import { MapWithDefault, recursiveMapToObject } from "matrix-js-sdk/src/utils";
import { type IWidget } from "matrix-widget-api"; import { type IWidget } from "matrix-widget-api";
import { clamp, defaultNumber, sum } from "@element-hq/web-shared-components";
import SettingsStore from "../../settings/SettingsStore"; import SettingsStore from "../../settings/SettingsStore";
import WidgetStore, { type IApp } from "../WidgetStore"; import WidgetStore, { type IApp } from "../WidgetStore";
import { WidgetType } from "../../widgets/WidgetType"; import { WidgetType } from "../../widgets/WidgetType";
import { clamp, defaultNumber, sum } from "../../../packages/shared-components/src/utils/numbers";
import defaultDispatcher from "../../dispatcher/dispatcher"; import defaultDispatcher from "../../dispatcher/dispatcher";
import { ReadyWatchingStore } from "../ReadyWatchingStore"; import { ReadyWatchingStore } from "../ReadyWatchingStore";
import { SettingLevel } from "../../settings/SettingLevel"; import { SettingLevel } from "../../settings/SettingLevel";

Some files were not shown because too many files have changed in this diff Show More