├── .changeset ├── README.md ├── breezy-aliens-report.md ├── chubby-lights-send.md ├── config.json ├── great-pets-add.md ├── major-foxes-type.md ├── short-dancers-punch.md └── solid-rocks-decide.md ├── .github ├── CODEOWNERS ├── dco.yml ├── k8s_config.yaml ├── renovate.json └── workflows │ └── ci.yml ├── .gitignore ├── .husky └── pre-commit ├── .prettierignore ├── .prettierrc.yaml ├── LICENSE ├── README.md ├── SECURITY.md ├── api-extractor.json ├── charts └── example-widget-mui │ ├── .helmignore │ ├── Chart.yaml │ ├── templates │ ├── NOTES.txt │ ├── _helpers.tpl │ ├── deployment.yaml │ ├── hpa.yaml │ ├── ingress.yaml │ ├── service.yaml │ ├── serviceaccount.yaml │ └── tests │ │ └── test-connection.yaml │ └── values.yaml ├── containers └── widget-server │ ├── .dockerignore │ ├── .gitignore │ ├── CHANGELOG.md │ ├── Dockerfile │ ├── README.md │ ├── e2e │ ├── container.spec.ts │ └── fixtures │ │ ├── index.html │ │ └── index.js │ ├── files │ ├── content-security-policy.conf │ ├── default.conf │ ├── listen.conf │ ├── listen.ipv4.conf │ ├── mimetypes.conf │ └── provide_environment.sh │ ├── package.json │ └── playwright.config.ts ├── docs └── adrs │ ├── adr000-template.md │ ├── adr001-use-adrs-to-document-decisions.md │ ├── adr002-use-prettier-as-a-code-formatter.md │ ├── adr003-use-an-nginx-base-container-as-deployment-artifact.md │ ├── adr004-versioning-and-release-notes.md │ ├── adr005-widget-and-module-export-structure.md │ ├── adr006-e2e-testing.md │ └── adr007-data-validation.md ├── eslint.config.mjs ├── example-widget-mui ├── Dockerfile ├── README.md ├── docs │ └── widget-overview.png ├── i18next-parser.config.js ├── index.html ├── package.json ├── public │ ├── favicon.ico │ ├── locales │ │ ├── de │ │ │ └── translation.json │ │ └── en │ │ │ └── translation.json │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── AllRoomsPage │ │ ├── AllRoomsPage.test.tsx │ │ ├── AllRoomsPage.tsx │ │ └── index.ts │ ├── App │ │ ├── App.test.tsx │ │ ├── App.tsx │ │ └── index.ts │ ├── DicePage │ │ ├── DicePage.test.tsx │ │ ├── DicePage.tsx │ │ └── index.ts │ ├── IdentityPage │ │ ├── IdentityPage.test.tsx │ │ ├── IdentityPage.tsx │ │ └── index.tsx │ ├── ImagePage │ │ ├── Image.tsx │ │ ├── ImageListView.tsx │ │ ├── ImagePage.test.tsx │ │ ├── ImagePage.tsx │ │ └── index.ts │ ├── InvitationsPage │ │ ├── InvitationsPage.test.tsx │ │ ├── InvitationsPage.tsx │ │ └── index.ts │ ├── ModalPage │ │ ├── ModalDialog.test.tsx │ │ ├── ModalDialog.tsx │ │ ├── ModalPage.test.tsx │ │ ├── ModalPage.tsx │ │ └── index.ts │ ├── NavigationPage │ │ ├── NavigationBar.tsx │ │ ├── NavigationPage.test.tsx │ │ ├── NavigationPage.tsx │ │ └── index.ts │ ├── PowerLevelsPage │ │ ├── PowerLevelsPage.test.tsx │ │ ├── PowerLevelsPage.tsx │ │ ├── index.ts │ │ ├── powerLevelsApi.test.ts │ │ ├── powerLevelsApi.ts │ │ ├── roomMembersApi.test.ts │ │ └── roomMembersApi.ts │ ├── RelationsPage │ │ ├── RelationsPage.test.tsx │ │ ├── RelationsPage.tsx │ │ ├── index.ts │ │ ├── roomMessagesApi.test.ts │ │ ├── roomMessagesApi.ts │ │ └── testUtils.ts │ ├── RoomPage │ │ ├── RoomPage.test.tsx │ │ ├── RoomPage.tsx │ │ └── index.ts │ ├── ThemePage │ │ ├── ThemePage.test.tsx │ │ ├── ThemePage.tsx │ │ └── index.ts │ ├── WelcomePage │ │ ├── WelcomePage.test.tsx │ │ ├── WelcomePage.tsx │ │ └── index.tsx │ ├── events │ │ ├── index.ts │ │ ├── messageCollectionEvent.test.ts │ │ ├── messageCollectionEvent.ts │ │ ├── reactionEvent.test.ts │ │ ├── reactionEvent.ts │ │ ├── roomMessageEvent.test.ts │ │ ├── roomMessageEvent.ts │ │ ├── roomNameEvent.test.ts │ │ ├── roomNameEvent.ts │ │ ├── throwDiceEvent.test.ts │ │ ├── throwDiceEvent.ts │ │ ├── uploadImageEvent.test.ts │ │ ├── uploadedImageEvent.ts │ │ ├── validation.test.ts │ │ └── validation.ts │ ├── i18n.ts │ ├── logo.svg │ ├── main.tsx │ ├── setupTests.ts │ ├── store │ │ ├── StoreProvider.tsx │ │ ├── baseApi.ts │ │ ├── index.ts │ │ └── store.ts │ ├── types.d.ts │ ├── utils.ts │ ├── vite-env.d.ts │ └── vitest.d.ts ├── tsconfig.json ├── tsconfig.node.json ├── vite.config.ts └── vitest.config.ts ├── package.json ├── packages ├── api │ ├── CHANGELOG.md │ ├── README.md │ ├── api-extractor.json │ ├── api-report.api.md │ ├── package.json │ ├── src │ │ ├── api │ │ │ ├── WidgetApiImpl.test.ts │ │ │ ├── WidgetApiImpl.ts │ │ │ ├── extras │ │ │ │ ├── capabilities.test.ts │ │ │ │ ├── capabilities.ts │ │ │ │ ├── displayName.test.ts │ │ │ │ ├── displayName.ts │ │ │ │ ├── events.test.ts │ │ │ │ ├── events.ts │ │ │ │ ├── index.ts │ │ │ │ ├── navigateTo.test.ts │ │ │ │ ├── navigateTo.ts │ │ │ │ ├── originServerTs.test.ts │ │ │ │ ├── originServerTs.ts │ │ │ │ ├── powerLevel.test.ts │ │ │ │ ├── powerLevel.ts │ │ │ │ ├── redactions.test.ts │ │ │ │ ├── redactions.ts │ │ │ │ ├── relatesTo.test.ts │ │ │ │ ├── relatesTo.ts │ │ │ │ ├── roomMember.test.ts │ │ │ │ └── roomMember.ts │ │ │ ├── index.ts │ │ │ ├── parameters.test.ts │ │ │ ├── parameters.ts │ │ │ ├── registration.test.ts │ │ │ ├── registration.ts │ │ │ ├── types.ts │ │ │ ├── utils.test.ts │ │ │ └── utils.ts │ │ └── index.ts │ ├── tsconfig.json │ └── vitest.config.ts ├── mui │ ├── CHANGELOG.md │ ├── README.md │ ├── api-extractor.json │ ├── api-report.api.md │ ├── i18next-parser.config.js │ ├── package.json │ ├── src │ │ ├── components │ │ │ ├── ElementAvatar │ │ │ │ ├── ElementAvatar.test.tsx │ │ │ │ ├── ElementAvatar.tsx │ │ │ │ ├── createAvatarUrl.test.ts │ │ │ │ ├── createAvatarUrl.ts │ │ │ │ ├── getInitialLetter.test.ts │ │ │ │ ├── getInitialLetter.ts │ │ │ │ ├── index.ts │ │ │ │ ├── useIdColorHash.test.ts │ │ │ │ └── useIdColorHash.ts │ │ │ ├── LoadingView │ │ │ │ ├── LoadingView.test.tsx │ │ │ │ ├── LoadingView.tsx │ │ │ │ └── index.ts │ │ │ ├── MissingCapabilitiesError │ │ │ │ ├── MissingCapabilitiesError.test.tsx │ │ │ │ ├── MissingCapabilitiesError.tsx │ │ │ │ └── index.ts │ │ │ ├── MuiCapabilitiesGuard │ │ │ │ ├── MuiCapabilitiesGuard.test.tsx │ │ │ │ ├── MuiCapabilitiesGuard.tsx │ │ │ │ └── index.ts │ │ │ ├── MuiThemeProvider │ │ │ │ ├── EmotionCacheProvider.tsx │ │ │ │ ├── MuiThemeProvider.test.tsx │ │ │ │ ├── MuiThemeProvider.tsx │ │ │ │ ├── environment.test.ts │ │ │ │ ├── environment.ts │ │ │ │ ├── index.ts │ │ │ │ ├── nonce.ts │ │ │ │ ├── theme.test.tsx │ │ │ │ └── theme.ts │ │ │ ├── MuiWidgetApiProvider │ │ │ │ ├── ChildError.test.tsx │ │ │ │ ├── ChildError.tsx │ │ │ │ ├── CopyableCode.test.tsx │ │ │ │ ├── CopyableCode.tsx │ │ │ │ ├── MissingParametersError.test.tsx │ │ │ │ ├── MissingParametersError.tsx │ │ │ │ ├── MobileClientError.test.tsx │ │ │ │ ├── MobileClientError.tsx │ │ │ │ ├── MuiWidgetApiProvider.test.tsx │ │ │ │ ├── MuiWidgetApiProvider.tsx │ │ │ │ ├── OutsideClientError.test.tsx │ │ │ │ ├── OutsideClientError.tsx │ │ │ │ └── index.ts │ │ │ └── index.ts │ │ ├── i18n │ │ │ ├── i18n.ts │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── locales │ │ │ ├── de │ │ │ │ └── widget-toolkit.json │ │ │ └── en │ │ │ │ └── widget-toolkit.json │ │ ├── setupTests.ts │ │ └── vitest.d.ts │ ├── tsconfig.json │ └── vitest.config.ts ├── react │ ├── CHANGELOG.md │ ├── README.md │ ├── api-extractor.json │ ├── api-report.api.md │ ├── package.json │ ├── src │ │ ├── components │ │ │ ├── CapabilitiesGuard │ │ │ │ ├── CapabilitiesGuard.test.tsx │ │ │ │ ├── CapabilitiesGuard.tsx │ │ │ │ └── index.ts │ │ │ ├── ThemeSelectionProvider │ │ │ │ ├── ThemeSelectionProvider.test.tsx │ │ │ │ ├── ThemeSelectionProvider.tsx │ │ │ │ └── index.ts │ │ │ ├── WidgetApiProvider │ │ │ │ ├── WidgetApiProvider.test.tsx │ │ │ │ ├── WidgetApiProvider.tsx │ │ │ │ ├── context.ts │ │ │ │ └── index.ts │ │ │ └── index.ts │ │ ├── index.ts │ │ └── setupTests.ts │ ├── tsconfig.json │ └── vitest.config.ts └── testing │ ├── CHANGELOG.md │ ├── README.md │ ├── api-extractor.json │ ├── api-report.api.md │ ├── package.json │ ├── src │ ├── api │ │ ├── index.ts │ │ ├── mockWidgetApi.test.ts │ │ ├── mockWidgetApi.ts │ │ ├── utils.test.ts │ │ └── utils.ts │ └── index.ts │ ├── tsconfig.json │ └── vitest.config.ts ├── rollup.config.mjs ├── scripts ├── license-header.txt ├── postpack.js ├── prepack.js └── publishAllPackages.js ├── tsconfig.json ├── vitest.config.ts └── yarn.lock /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /.changeset/breezy-aliens-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@matrix-widget-toolkit/mui': patch 3 | --- 4 | 5 | Upgrade react-i18next to 15.5.2 6 | -------------------------------------------------------------------------------- /.changeset/chubby-lights-send.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@matrix-widget-toolkit/testing': minor 3 | '@matrix-widget-toolkit/api': minor 4 | --- 5 | 6 | Add support for the delayed events 7 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@1.6.3/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "linked": [], 6 | "access": "public", 7 | "baseBranch": "main", 8 | "updateInternalDependencies": "patch", 9 | "ignore": ["@matrix-widget-toolkit/example-widget-mui"], 10 | "privatePackages": { 11 | "version": true, 12 | "tag": true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.changeset/great-pets-add.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@matrix-widget-toolkit/testing': patch 3 | '@matrix-widget-toolkit/react': patch 4 | '@matrix-widget-toolkit/api': patch 5 | '@matrix-widget-toolkit/mui': patch 6 | --- 7 | 8 | Update vitest to 3.2.1 and update deprecated workspace config to projects config 9 | -------------------------------------------------------------------------------- /.changeset/major-foxes-type.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@matrix-widget-toolkit/mui': patch 3 | --- 4 | 5 | Update i18next to 24.2.3 6 | -------------------------------------------------------------------------------- /.changeset/short-dancers-punch.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@matrix-widget-toolkit/testing': patch 3 | '@matrix-widget-toolkit/react': patch 4 | '@matrix-widget-toolkit/api': patch 5 | '@matrix-widget-toolkit/mui': patch 6 | --- 7 | 8 | Update Vite package 9 | -------------------------------------------------------------------------------- /.changeset/solid-rocks-decide.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@matrix-widget-toolkit/mui': patch 3 | --- 4 | 5 | Update i18next to 25.2.1 6 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # This file registers ownership for the code. 2 | # Review from a member of the corresponding code owner is required to merge pull requests. 3 | # 4 | # The last matching pattern takes precedence. 5 | # https://help.github.com/articles/about-codeowners/ 6 | 7 | * @nordeck/matrix-os-maintainers 8 | -------------------------------------------------------------------------------- /.github/dco.yml: -------------------------------------------------------------------------------- 1 | --- 2 | require: 3 | members: false 4 | -------------------------------------------------------------------------------- /.github/k8s_config.yaml: -------------------------------------------------------------------------------- 1 | namespace: 'matrix-widget-toolkit' 2 | release-label: 'app.kubernetes.io/instance' 3 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | node ./node_modules/lint-staged/bin/lint-staged.js 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | build/ 2 | coverage/ 3 | lib/ 4 | node_modules/ 5 | api-report.api.md 6 | 7 | # Ignore the helm chart 8 | charts/ 9 | -------------------------------------------------------------------------------- /.prettierrc.yaml: -------------------------------------------------------------------------------- 1 | # Use single quotes instead of double quotes. 2 | # (this will not affect JSX) 3 | singleQuote: true 4 | 5 | plugins: ['prettier-plugin-organize-imports'] 6 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | Nordeck establishes a clear process for reporting and addressing security vulnerabilities in our supported products and systems. It fosters collaboration with researchers and stakeholders, ensuring issues are resolved promptly to protect our users and strengthen trust in our organization. 4 | 5 | ## Supported Versions 6 | 7 | | Package | Version | Supported | 8 | | ------------------------------------ | ------- | ------------------ | 9 | | @matrix-widget-toolkit/api | >= 4.x | :white_check_mark: | 10 | | @matrix-widget-toolkit/mui | >= 2.x | :white_check_mark: | 11 | | @matrix-widget-toolkit/react | >= 2.x | :white_check_mark: | 12 | | @matrix-widget-toolkit/testing | >= 3.x | :white_check_mark: | 13 | | @matrix-widget-toolkit/widget-server | >= 1.x | :white_check_mark: | 14 | 15 | ## Reporting a Vulnerability 16 | 17 | If you have discovered a security issue with our products, please submit a report to security@nordeck.net, with the following information: 18 | 19 | - Your contact email address 20 | - The vulnerability description 21 | - The steps to reproduce it and a proof of concept 22 | - The assumed impact and recommended fix 23 | 24 | Nordeck does not provide compensation in exchange for information pertaining to security vulnerabilities under this policy. We may choose not to pursue, contact, or otherwise interact with reporters who decline to identify themselves when making the report. We will deal in good faith with reporting parties who comply with these guidelines. We may choose to disregard submissions by parties who submit a high volume of low-quality reports. 25 | 26 | For more detailed information, please read Nordeck's full [Vulnerability Disclosure Policy](https://github.com/nordeck/.github/blob/main/SECURITY.md). 27 | -------------------------------------------------------------------------------- /api-extractor.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", 3 | "mainEntryPointFilePath": "/lib/src/index.d.ts", 4 | "newlineKind": "os", 5 | 6 | "apiReport": { 7 | "enabled": true, 8 | "reportFileName": "api-report", 9 | "reportFolder": "/" 10 | }, 11 | "docModel": { 12 | "enabled": false 13 | }, 14 | "dtsRollup": { 15 | "enabled": true, 16 | "untrimmedFilePath": "/build/index.d.ts" 17 | }, 18 | "tsdocMetadata": { 19 | "enabled": false 20 | }, 21 | 22 | "messages": { 23 | "extractorMessageReporting": { 24 | "default": { 25 | "logLevel": "warning" 26 | }, 27 | 28 | "ae-missing-release-tag": { 29 | "logLevel": "none" 30 | }, 31 | 32 | "ae-wrong-input-file-type": { 33 | "logLevel": "none" 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /charts/example-widget-mui/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /charts/example-widget-mui/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: example-widget-mui 3 | description: An example that showcases the features of the Matrix Widget Toolkit 4 | type: application 5 | version: 0.1.0 6 | appVersion: "0.0.0" 7 | home: https://github.com/nordeck/matrix-widget-toolkit 8 | -------------------------------------------------------------------------------- /charts/example-widget-mui/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | 1. Get the application URL by running these commands: 2 | {{- if .Values.ingress.enabled }} 3 | {{- range $host := .Values.ingress.hosts }} 4 | {{- range .paths }} 5 | http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} 6 | {{- end }} 7 | {{- end }} 8 | {{- else if contains "NodePort" .Values.service.type }} 9 | export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "example-widget-mui.fullname" . }}) 10 | export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") 11 | echo http://$NODE_IP:$NODE_PORT 12 | {{- else if contains "LoadBalancer" .Values.service.type }} 13 | NOTE: It may take a few minutes for the LoadBalancer IP to be available. 14 | You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "example-widget-mui.fullname" . }}' 15 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "example-widget-mui.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") 16 | echo http://$SERVICE_IP:{{ .Values.service.port }} 17 | {{- else if contains "ClusterIP" .Values.service.type }} 18 | export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "example-widget-mui.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") 19 | export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") 20 | echo "Visit http://127.0.0.1:8080 to use your application" 21 | kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT 22 | {{- end }} 23 | -------------------------------------------------------------------------------- /charts/example-widget-mui/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "example-widget-mui.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Create a default fully qualified app name. 10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 11 | If release name contains chart name it will be used as a full name. 12 | */}} 13 | {{- define "example-widget-mui.fullname" -}} 14 | {{- if .Values.fullnameOverride }} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 16 | {{- else }} 17 | {{- $name := default .Chart.Name .Values.nameOverride }} 18 | {{- if contains $name .Release.Name }} 19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 20 | {{- else }} 21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | 26 | {{/* 27 | Create chart name and version as used by the chart label. 28 | */}} 29 | {{- define "example-widget-mui.chart" -}} 30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 31 | {{- end }} 32 | 33 | {{/* 34 | Common labels 35 | */}} 36 | {{- define "example-widget-mui.labels" -}} 37 | helm.sh/chart: {{ include "example-widget-mui.chart" . }} 38 | {{ include "example-widget-mui.selectorLabels" . }} 39 | {{- if .Chart.AppVersion }} 40 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 41 | {{- end }} 42 | app.kubernetes.io/managed-by: {{ .Release.Service }} 43 | {{- end }} 44 | 45 | {{/* 46 | Selector labels 47 | */}} 48 | {{- define "example-widget-mui.selectorLabels" -}} 49 | app.kubernetes.io/name: {{ include "example-widget-mui.name" . }} 50 | app.kubernetes.io/instance: {{ .Release.Name }} 51 | {{- end }} 52 | 53 | {{/* 54 | Create the name of the service account to use 55 | */}} 56 | {{- define "example-widget-mui.serviceAccountName" -}} 57 | {{- if .Values.serviceAccount.create }} 58 | {{- default (include "example-widget-mui.fullname" .) .Values.serviceAccount.name }} 59 | {{- else }} 60 | {{- default "default" .Values.serviceAccount.name }} 61 | {{- end }} 62 | {{- end }} 63 | -------------------------------------------------------------------------------- /charts/example-widget-mui/templates/hpa.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.autoscaling.enabled }} 2 | apiVersion: autoscaling/v2beta1 3 | kind: HorizontalPodAutoscaler 4 | metadata: 5 | name: {{ include "example-widget-mui.fullname" . }} 6 | labels: 7 | {{- include "example-widget-mui.labels" . | nindent 4 }} 8 | spec: 9 | scaleTargetRef: 10 | apiVersion: apps/v1 11 | kind: Deployment 12 | name: {{ include "example-widget-mui.fullname" . }} 13 | minReplicas: {{ .Values.autoscaling.minReplicas }} 14 | maxReplicas: {{ .Values.autoscaling.maxReplicas }} 15 | metrics: 16 | {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} 17 | - type: Resource 18 | resource: 19 | name: cpu 20 | targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} 21 | {{- end }} 22 | {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} 23 | - type: Resource 24 | resource: 25 | name: memory 26 | targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} 27 | {{- end }} 28 | {{- end }} 29 | -------------------------------------------------------------------------------- /charts/example-widget-mui/templates/ingress.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.ingress.enabled -}} 2 | {{- $fullName := include "example-widget-mui.fullname" . -}} 3 | {{- $svcPort := .Values.service.port -}} 4 | {{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} 5 | {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} 6 | {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} 7 | {{- end }} 8 | {{- end }} 9 | {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} 10 | apiVersion: networking.k8s.io/v1 11 | {{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} 12 | apiVersion: networking.k8s.io/v1beta1 13 | {{- else -}} 14 | apiVersion: extensions/v1beta1 15 | {{- end }} 16 | kind: Ingress 17 | metadata: 18 | name: {{ $fullName }} 19 | labels: 20 | {{- include "example-widget-mui.labels" . | nindent 4 }} 21 | {{- with .Values.ingress.annotations }} 22 | annotations: 23 | {{- toYaml . | nindent 4 }} 24 | {{- end }} 25 | spec: 26 | {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} 27 | ingressClassName: {{ .Values.ingress.className }} 28 | {{- end }} 29 | {{- if .Values.ingress.tls }} 30 | tls: 31 | {{- range .Values.ingress.tls }} 32 | - hosts: 33 | {{- range .hosts }} 34 | - {{ . | quote }} 35 | {{- end }} 36 | secretName: {{ .secretName }} 37 | {{- end }} 38 | {{- end }} 39 | rules: 40 | {{- range .Values.ingress.hosts }} 41 | - host: {{ .host | quote }} 42 | http: 43 | paths: 44 | {{- range .paths }} 45 | - path: {{ .path }} 46 | {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} 47 | pathType: {{ .pathType }} 48 | {{- end }} 49 | backend: 50 | {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} 51 | service: 52 | name: {{ $fullName }} 53 | port: 54 | number: {{ $svcPort }} 55 | {{- else }} 56 | serviceName: {{ $fullName }} 57 | servicePort: {{ $svcPort }} 58 | {{- end }} 59 | {{- end }} 60 | {{- end }} 61 | {{- end }} 62 | -------------------------------------------------------------------------------- /charts/example-widget-mui/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "example-widget-mui.fullname" . }} 5 | labels: 6 | {{- include "example-widget-mui.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "example-widget-mui.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /charts/example-widget-mui/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "example-widget-mui.serviceAccountName" . }} 6 | labels: 7 | {{- include "example-widget-mui.labels" . | nindent 4 }} 8 | {{- with .Values.serviceAccount.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | {{- end }} 13 | -------------------------------------------------------------------------------- /charts/example-widget-mui/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "example-widget-mui.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "example-widget-mui.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: ['wget'] 14 | args: ['{{ include "example-widget-mui.fullname" . }}:{{ .Values.service.port }}'] 15 | restartPolicy: Never 16 | -------------------------------------------------------------------------------- /charts/example-widget-mui/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for example-widget-mui. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | 5 | replicaCount: 1 6 | 7 | image: 8 | repository: ghcr.io/nordeck/matrix-widget-toolkit/example-widget-mui 9 | pullPolicy: IfNotPresent 10 | # Overrides the image tag whose default is the chart appVersion. 11 | tag: "" 12 | 13 | imagePullSecrets: [] 14 | nameOverride: "" 15 | fullnameOverride: "" 16 | 17 | serviceAccount: 18 | # Specifies whether a service account should be created 19 | create: false 20 | # Annotations to add to the service account 21 | annotations: {} 22 | # The name of the service account to use. 23 | # If not set and create is true, a name is generated using the fullname template 24 | name: "" 25 | 26 | podAnnotations: {} 27 | 28 | podSecurityContext: {} 29 | # fsGroup: 2000 30 | 31 | securityContext: 32 | capabilities: 33 | drop: 34 | - ALL 35 | readOnlyRootFilesystem: true 36 | runAsNonRoot: true 37 | 38 | service: 39 | type: ClusterIP 40 | port: 8080 41 | 42 | ingress: 43 | enabled: false 44 | className: "" 45 | annotations: {} 46 | # kubernetes.io/ingress.class: nginx 47 | # kubernetes.io/tls-acme: "true" 48 | hosts: 49 | - host: chart-example.local 50 | paths: 51 | - path: / 52 | pathType: ImplementationSpecific 53 | tls: [] 54 | # - secretName: chart-example-tls 55 | # hosts: 56 | # - chart-example.local 57 | 58 | resources: {} 59 | # We usually recommend not to specify default resources and to leave this as a conscious 60 | # choice for the user. This also increases chances charts run on environments with little 61 | # resources, such as Minikube. If you do want to specify resources, uncomment the following 62 | # lines, adjust them as necessary, and remove the curly braces after 'resources:'. 63 | # limits: 64 | # cpu: 100m 65 | # memory: 128Mi 66 | # requests: 67 | # cpu: 100m 68 | # memory: 128Mi 69 | 70 | autoscaling: 71 | enabled: false 72 | minReplicas: 1 73 | maxReplicas: 100 74 | targetCPUUtilizationPercentage: 80 75 | # targetMemoryUtilizationPercentage: 80 76 | 77 | nodeSelector: {} 78 | 79 | tolerations: [] 80 | 81 | affinity: {} 82 | -------------------------------------------------------------------------------- /containers/widget-server/.dockerignore: -------------------------------------------------------------------------------- 1 | # ignore all files except the build folder 2 | * 3 | !/files 4 | -------------------------------------------------------------------------------- /containers/widget-server/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | /test-results/ 3 | /playwright-report/ 4 | /playwright/.cache/ 5 | -------------------------------------------------------------------------------- /containers/widget-server/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # `@matrix-widget-toolkit/widget-server` 2 | 3 | ## 1.1.1 4 | 5 | ### Patch Changes 6 | 7 | - 7cde085: Add cache control header to assets folder. 8 | 9 | ## 1.1.0 10 | 11 | ### Minor Changes 12 | 13 | - e449db3: Adds configurable listen directive 14 | - 1fdc00d: Adds proper mime type config for js, mjs and cjs files 15 | 16 | ## 1.0.6 17 | 18 | ### Patch Changes 19 | 20 | - b2aa6c3: Bump nginx from 1.27.0-alpine-perl to 1.27.2-alpine-perl 21 | 22 | ## 1.0.5 23 | 24 | ### Patch Changes 25 | 26 | - 2168cd4: Emotion cache is now prepended, so it works with Vite builds 27 | 28 | ## 1.0.4 29 | 30 | ### Patch Changes 31 | 32 | - 0d245f6: Bump nginx from 1.25.0-alpine-perl to 1.25.2-alpine-perl. 33 | 34 | ## 1.0.3 35 | 36 | ### Patch Changes 37 | 38 | - aeae7b0: Bump nginx from 1.23.4-alpine-perl to 1.25.0-alpine-perl. 39 | 40 | ## 1.0.2 41 | 42 | ### Patch Changes 43 | 44 | - 7003627: Bump `nginx:alpine-perl` from 1.23.3 to 1.23.4. 45 | 46 | ## 1.0.1 47 | 48 | ### Patch Changes 49 | 50 | - c8f8826: Bump `nginx:alpine-perl` to 1.23.3. 51 | 52 | ## 1.0.0 53 | 54 | Initial release 55 | -------------------------------------------------------------------------------- /containers/widget-server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nginx:1.27.4-alpine-perl 2 | 3 | # Install envsubst 4 | RUN apk add --no-cache gettext 5 | 6 | # Make sure all directories are accessible by the non-root user 7 | # Inspired by https://hub.docker.com/r/nginxinc/nginx-unprivileged 8 | RUN set -x\ 9 | && chown -R 101:0 /var/cache/nginx \ 10 | && chmod -R g+w /var/cache/nginx \ 11 | && chown -R 101:0 /etc/nginx \ 12 | && chmod -R g+w /etc/nginx \ 13 | && sed -i '/user nginx;/d' /etc/nginx/nginx.conf \ 14 | && sed -i 's,/var/run/nginx.pid,/tmp/nginx.pid,' /etc/nginx/nginx.conf 15 | 16 | # The nginx base image already creates the nginx user with UID 101 and GUI 101 17 | USER 101 18 | 19 | # Add the nginx configuration 20 | COPY files/default.conf /etc/nginx/conf.d/ 21 | 22 | # Store the CSP header in a separate file to make it replacable in the deployment. 23 | COPY files/content-security-policy.conf /etc/nginx/conf.d/custom/ 24 | 25 | # Setup the default listen directive. You can map other files to it 26 | # on your deployments to support different configs (e.g. IPv4-only). 27 | COPY files/listen.conf /etc/nginx/conf.d/custom/ 28 | 29 | # Add mimetypes configuration 30 | COPY files/mimetypes.conf /etc/nginx/conf.d/custom/ 31 | 32 | # Create a new entrypoint that exports a __ENVIRONMENT_SCRIPT__ variable 33 | # from all REACT_APP_* environment variables. 34 | COPY files/provide_environment.sh / 35 | 36 | # Declare volumes where the nginx needs to write to. This is required 37 | # if the container is stared with a read-only file system. 38 | VOLUME /var/cache/nginx /tmp 39 | 40 | ENTRYPOINT [ "/provide_environment.sh" ] 41 | CMD [ "nginx", "-g", "daemon off; load_module \"modules/ngx_http_perl_module.so\"; env __ENVIRONMENT_SCRIPT__; env __CSP_FONT_SRC__; env __CSP_STYLE_SRC__; env __CSP_SCRIPT_SRC__; env __CSP_IMG_SRC__; env __CSP_CONNECT_SRC__;" ] 42 | -------------------------------------------------------------------------------- /containers/widget-server/e2e/container.spec.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { expect, test } from '@playwright/test'; 18 | 19 | test.describe('widget-server', () => { 20 | test.beforeEach(async ({ page }) => { 21 | await page.goto(''); 22 | }); 23 | 24 | test('should have title', async ({ page }) => { 25 | await expect(page).toHaveTitle(/welcome to the widget toolkit/i); 26 | }); 27 | 28 | test('should have history API fallback', async ({ page }) => { 29 | await page.goto('/test'); 30 | await expect(page).toHaveTitle(/welcome to the widget toolkit/i); 31 | }); 32 | 33 | test('should show environment', async ({ page }) => { 34 | await expect(page.locator('#environment')).toHaveText( 35 | '{"REACT_APP_EXAMPLE":"example"}', 36 | ); 37 | }); 38 | 39 | test('should include webpack nonce', async ({ page }) => { 40 | await expect(page.locator('#webpack')).toHaveText(/nonce is working!/i); 41 | }); 42 | 43 | test('should have X-Content-Type-Options header set', async ({ request }) => { 44 | const response = await request.get(''); 45 | 46 | expect(response.headers()['x-content-type-options']).toBe('nosniff'); 47 | }); 48 | 49 | test('should have CSP header set', async ({ request }) => { 50 | const response = await request.get(''); 51 | 52 | expect(response.headers()['content-security-policy']).toBeDefined(); 53 | }); 54 | }); 55 | -------------------------------------------------------------------------------- /containers/widget-server/e2e/fixtures/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Welcome to the widget toolkit! 5 | 6 | 7 | 8 |

Welcome to the widget toolkit!

9 |

This is your environment:

10 |
No environment
11 |
The NONCE is not present.
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /containers/widget-server/e2e/fixtures/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | const el = document.getElementById('environment'); 18 | try { 19 | el.innerText = JSON.stringify( 20 | JSON.parse(window.atob(window.__ENVIRONMENT__)), 21 | ); 22 | } catch { 23 | el.innerText = 'Could not find the environment :-('; 24 | } 25 | 26 | // check if we are allowed to create a new script tag 27 | const script = document.createElement('script'); 28 | script.nonce = window.NONCE; 29 | script.text = 30 | "document.getElementById('webpack').innerText = 'NONCE is working!'"; 31 | document.body.appendChild(script); 32 | -------------------------------------------------------------------------------- /containers/widget-server/files/content-security-policy.conf: -------------------------------------------------------------------------------- 1 | add_header Content-Security-Policy "default-src 'none'; font-src 'self' data: $__CSP_FONT_SRC__; style-src 'self' $__STYLE_CSP_NONCE__ $__CSP_STYLE_SRC__; script-src 'self' $__STYLE_CSP_NONCE__ $__CSP_SCRIPT_SRC__; img-src 'self' data: $__CSP_IMG_SRC__; connect-src 'self' $__CSP_CONNECT_SRC__; manifest-src 'self';"; 2 | -------------------------------------------------------------------------------- /containers/widget-server/files/default.conf: -------------------------------------------------------------------------------- 1 | # enable gzip 2 | gzip on; 3 | gzip_types application/javascript text/plain text/css application/json; 4 | 5 | # skip the version in the "server" header 6 | server_tokens off; 7 | 8 | # make the __ENVIRONMENT_SCRIPT__ environment variable available for the perl ssi extension 9 | perl_set $__ENVIRONMENT_SCRIPT__ 'sub { return $ENV{"__ENVIRONMENT_SCRIPT__"}; }'; 10 | 11 | # provide additional variables that can be used in the CSP 12 | perl_set $__CSP_FONT_SRC__ 'sub {return $ENV{"__CSP_FONT_SRC__"}; }'; 13 | perl_set $__CSP_STYLE_SRC__ 'sub {return $ENV{"__CSP_STYLE_SRC__"}; }'; 14 | perl_set $__CSP_SCRIPT_SRC__ 'sub {return $ENV{"__CSP_SCRIPT_SRC__"}; }'; 15 | perl_set $__CSP_IMG_SRC__ 'sub {return $ENV{"__CSP_IMG_SRC__"}; }'; 16 | perl_set $__CSP_CONNECT_SRC__ 'sub {return $ENV{"__CSP_CONNECT_SRC__"}; }'; 17 | 18 | server { 19 | # include additional configuration that is located in separate files (CSP, listen, ...) 20 | include /etc/nginx/conf.d/custom/*.conf; 21 | 22 | # Disable automatic detection of content types 23 | add_header X-Content-Type-Options "nosniff"; 24 | 25 | # never cache files by default 26 | add_header Cache-Control "public, max-age=0, must-revalidate"; 27 | 28 | # Generate nonce from request_id should be sufficient: 29 | # https://serverfault.com/questions/934801/is-it-a-good-idea-to-use-nginx-request-id-for-csp-nonce-value 30 | set $cspNonce $request_id; 31 | # Generate CSP nonce entry that is used for both the injected style and 32 | # script tags 33 | set $__STYLE_CSP_NONCE__ "'nonce-${cspNonce}'"; 34 | # Generate a script that sets the nonce 35 | set $__STYLE_NONCE_SCRIPT__ "window.NONCE = '${cspNonce}';"; 36 | # Combine environment config and nonce 37 | set $__INJECT_SCRIPT_TAG__ ""; 38 | 39 | root /usr/share/nginx/html; 40 | 41 | location / { 42 | # enable SSI for the files. We use it to inject the environment variables 43 | ssi on; 44 | try_files $uri $uri/ /index.html; 45 | } 46 | 47 | # cache all files in the "/static" and "/assets" folder (css, js, ...) because 48 | # they have a hash in the filename. 49 | location /static { 50 | add_header Cache-Control "public, max-age=31556926, immutable"; 51 | } 52 | 53 | location /assets { 54 | add_header Cache-Control "public, max-age=31556926, immutable"; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /containers/widget-server/files/listen.conf: -------------------------------------------------------------------------------- 1 | listen [::]:8080 ipv6only=off; -------------------------------------------------------------------------------- /containers/widget-server/files/listen.ipv4.conf: -------------------------------------------------------------------------------- 1 | listen 8080; -------------------------------------------------------------------------------- /containers/widget-server/files/mimetypes.conf: -------------------------------------------------------------------------------- 1 | include mime.types; 2 | types 3 | { 4 | application/javascript js cjs mjs; 5 | } 6 | -------------------------------------------------------------------------------- /containers/widget-server/files/provide_environment.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Create a new entrypoint that exports a __ENVIRONMENT_SCRIPT__ variable 4 | # from all REACT_APP_* environment variables. The variable contains a 5 | # variable assignment to window.__ENVIRONMENT__ that should be put 6 | # into a 26 | 27 | 32 | 33 | 38 | 39 | 40 | 41 | 42 |
43 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /example-widget-mui/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nordeck/matrix-widget-toolkit/05c406c1827044eaad85bbb6fe8a9703c759eedd/example-widget-mui/public/favicon.ico -------------------------------------------------------------------------------- /example-widget-mui/public/locales/de/translation.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigation": { 3 | "welcome": { 4 | "title": "Willkommen" 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /example-widget-mui/public/locales/en/translation.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigation": { 3 | "welcome": { 4 | "title": "Welcome" 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /example-widget-mui/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nordeck/matrix-widget-toolkit/05c406c1827044eaad85bbb6fe8a9703c759eedd/example-widget-mui/public/logo192.png -------------------------------------------------------------------------------- /example-widget-mui/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nordeck/matrix-widget-toolkit/05c406c1827044eaad85bbb6fe8a9703c759eedd/example-widget-mui/public/logo512.png -------------------------------------------------------------------------------- /example-widget-mui/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Example Widget", 3 | "name": "Example Widget", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /example-widget-mui/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /example-widget-mui/src/AllRoomsPage/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export { AllRoomsPage } from './AllRoomsPage'; 18 | -------------------------------------------------------------------------------- /example-widget-mui/src/App/App.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { WidgetApiImpl } from '@matrix-widget-toolkit/api'; 18 | import { render, screen } from '@testing-library/react'; 19 | import { expect, it } from 'vitest'; 20 | import { App } from './App'; 21 | 22 | it('should render error message', async () => { 23 | const widgetApiPromise = WidgetApiImpl.create(); 24 | 25 | render(); 26 | 27 | await expect( 28 | screen.findByText(/only runs as a widget/i), 29 | ).resolves.toBeInTheDocument(); 30 | }); 31 | -------------------------------------------------------------------------------- /example-widget-mui/src/App/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export { App } from './App'; 18 | -------------------------------------------------------------------------------- /example-widget-mui/src/DicePage/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export { DicePage } from './DicePage'; 18 | -------------------------------------------------------------------------------- /example-widget-mui/src/IdentityPage/index.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export { IdentityPage } from './IdentityPage'; 18 | -------------------------------------------------------------------------------- /example-widget-mui/src/ImagePage/Image.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { useWidgetApi } from '@matrix-widget-toolkit/react'; 18 | import React, { useCallback, useEffect, useState } from 'react'; 19 | 20 | type ImageProps = { 21 | alt?: string; 22 | /** 23 | * MXC URI of the image that should be shown 24 | */ 25 | contentUrl: string; 26 | }; 27 | 28 | /** 29 | * Component that loads the image from the content repository and displays it. 30 | */ 31 | export const Image: React.FC = function ({ 32 | contentUrl, 33 | ...imageProps 34 | }) { 35 | const [dataUrl, setDataUrl] = useState(); 36 | const widgetApi = useWidgetApi(); 37 | 38 | const handleLoad = useCallback(() => { 39 | if (dataUrl) { 40 | URL.revokeObjectURL(dataUrl); 41 | } 42 | }, [dataUrl]); 43 | 44 | useEffect(() => { 45 | (async () => { 46 | try { 47 | const result = await widgetApi.downloadFile(contentUrl); 48 | 49 | if (!(result.file instanceof Blob)) { 50 | throw new Error('Got non Blob file response'); 51 | } 52 | 53 | const downloadedFileDataUrl = URL.createObjectURL(result.file); 54 | setDataUrl(downloadedFileDataUrl); 55 | } catch (error) { 56 | console.log('Error downloading file', error); 57 | } 58 | })(); 59 | }, [contentUrl, widgetApi]); 60 | 61 | if (dataUrl === undefined) { 62 | return null; 63 | } 64 | 65 | return ( 66 | 72 | ); 73 | }; 74 | -------------------------------------------------------------------------------- /example-widget-mui/src/ImagePage/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export { ImagePage } from './ImagePage'; 18 | -------------------------------------------------------------------------------- /example-widget-mui/src/InvitationsPage/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export { InvitationsPage } from './InvitationsPage'; 18 | -------------------------------------------------------------------------------- /example-widget-mui/src/ModalPage/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export { ModalDialog } from './ModalDialog'; 18 | export { ModalPage } from './ModalPage'; 19 | -------------------------------------------------------------------------------- /example-widget-mui/src/NavigationPage/NavigationBar.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import ArrowCircleLeftIcon from '@mui/icons-material/ArrowCircleLeft'; 18 | import { AppBar, IconButton, Toolbar, Typography } from '@mui/material'; 19 | import { Link } from 'react-router-dom'; 20 | 21 | export function NavigationBar({ title }: { title: string }) { 22 | return ( 23 | 24 | 25 | 33 | 34 | 35 | 36 | {title} 37 | 38 | 39 | 40 | ); 41 | } 42 | -------------------------------------------------------------------------------- /example-widget-mui/src/NavigationPage/NavigationPage.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { render, screen, within } from '@testing-library/react'; 18 | import axe from 'axe-core'; 19 | import { ComponentType, PropsWithChildren } from 'react'; 20 | import { MemoryRouter } from 'react-router-dom'; 21 | import { beforeEach, describe, expect, it } from 'vitest'; 22 | import { NavigationPage } from './NavigationPage'; 23 | 24 | describe('', () => { 25 | let wrapper: ComponentType; 26 | 27 | beforeEach(() => { 28 | wrapper = ({ children }: PropsWithChildren) => ( 29 | {children} 30 | ); 31 | }); 32 | 33 | it('should render without exploding', () => { 34 | render(, { wrapper }); 35 | 36 | const list = screen.getByRole('list', { name: 'Navigation' }); 37 | 38 | expect( 39 | within(list).getByRole('listitem', { name: 'Welcome' }), 40 | ).toHaveAccessibleDescription('Example on widget parameters'); 41 | }); 42 | 43 | it('should have no accessibility violations', async () => { 44 | const { container } = render(, { wrapper }); 45 | 46 | expect(await axe.run(container)).toHaveNoViolations(); 47 | }); 48 | }); 49 | -------------------------------------------------------------------------------- /example-widget-mui/src/NavigationPage/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export { NavigationBar } from './NavigationBar'; 18 | export { NavigationPage } from './NavigationPage'; 19 | -------------------------------------------------------------------------------- /example-widget-mui/src/PowerLevelsPage/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export { PowerLevelsPage } from './PowerLevelsPage'; 18 | -------------------------------------------------------------------------------- /example-widget-mui/src/RelationsPage/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export { RelationsPage } from './RelationsPage'; 18 | -------------------------------------------------------------------------------- /example-widget-mui/src/RelationsPage/testUtils.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { RoomEvent, StateEvent } from '@matrix-widget-toolkit/api'; 18 | import { 19 | MessageCollectionEvent, 20 | ReactionEvent, 21 | RoomMessageEvent, 22 | } from '../events'; 23 | 24 | export function mockMessageCollectionEvent({ 25 | state_key = '', 26 | content = {}, 27 | }: { 28 | state_key?: string; 29 | content?: Partial; 30 | } = {}): StateEvent { 31 | return { 32 | type: 'net.nordeck.message_collection', 33 | sender: '@user-id', 34 | state_key, 35 | content: { eventIds: ['$message-event-id'], ...content }, 36 | origin_server_ts: 0, 37 | event_id: '$collection-event-id', 38 | room_id: '!room-id', 39 | }; 40 | } 41 | 42 | export function mockRoomMessageEvent({ 43 | content = {}, 44 | }: { 45 | state_key?: string; 46 | content?: Partial; 47 | } = {}): RoomEvent { 48 | return { 49 | type: 'm.room.message', 50 | sender: '@user-id', 51 | content: { msgtype: 'm.text', body: 'My message', ...content }, 52 | origin_server_ts: 0, 53 | event_id: '$message-event-id', 54 | room_id: '!room-id', 55 | }; 56 | } 57 | 58 | export function mockReactionEvent({ 59 | event_id = '$event-id-0', 60 | 'm.relates_to': content = {}, 61 | }: { 62 | event_id?: string; 63 | 'm.relates_to'?: Partial; 64 | } = {}): RoomEvent { 65 | return { 66 | type: 'm.reaction', 67 | sender: '@user-id', 68 | content: { 69 | 'm.relates_to': { 70 | rel_type: 'm.annotation', 71 | event_id: '$message-event-id', 72 | key: 'X', 73 | ...content, 74 | }, 75 | }, 76 | origin_server_ts: 0, 77 | event_id, 78 | room_id: '!room-id', 79 | }; 80 | } 81 | -------------------------------------------------------------------------------- /example-widget-mui/src/RoomPage/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export { RoomPage } from './RoomPage'; 18 | -------------------------------------------------------------------------------- /example-widget-mui/src/ThemePage/ThemePage.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { render, screen } from '@testing-library/react'; 18 | import axe from 'axe-core'; 19 | import { ComponentType, PropsWithChildren } from 'react'; 20 | import { MemoryRouter } from 'react-router-dom'; 21 | import { beforeEach, describe, expect, it } from 'vitest'; 22 | import { ThemePage } from './ThemePage'; 23 | 24 | describe('', () => { 25 | let wrapper: ComponentType; 26 | 27 | beforeEach(() => { 28 | wrapper = ({ children }: PropsWithChildren) => ( 29 | {children} 30 | ); 31 | }); 32 | 33 | it('should render without exploding', async () => { 34 | render(, { wrapper }); 35 | 36 | expect( 37 | screen.getByRole('link', { name: 'Back to navigation' }), 38 | ).toBeInTheDocument(); 39 | 40 | await expect( 41 | screen.findByRole('heading', { name: /theme/i }), 42 | ).resolves.toBeInTheDocument(); 43 | }); 44 | 45 | it('should have no accessibility violations', async () => { 46 | const { container } = render(, { wrapper }); 47 | 48 | await expect( 49 | screen.findByRole('heading', { name: /theme/i }), 50 | ).resolves.toBeInTheDocument(); 51 | 52 | expect(await axe.run(container)).toHaveNoViolations(); 53 | }, 15000); 54 | 55 | // As this page shows primarily the visual theming, so we skip exhaustive 56 | // testing for it. 57 | }); 58 | -------------------------------------------------------------------------------- /example-widget-mui/src/ThemePage/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export { ThemePage } from './ThemePage'; 18 | -------------------------------------------------------------------------------- /example-widget-mui/src/WelcomePage/WelcomePage.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { ElementAvatar } from '@matrix-widget-toolkit/mui'; 18 | import { useWidgetApi } from '@matrix-widget-toolkit/react'; 19 | import { Box, Card, CardContent, CardHeader, Typography } from '@mui/material'; 20 | import { ReactElement } from 'react'; 21 | import { NavigationBar } from '../NavigationPage'; 22 | 23 | /** 24 | * A component that shows the user information that were given in the widget URL. 25 | */ 26 | export const WelcomePage = (): ReactElement => { 27 | const widgetApi = useWidgetApi(); 28 | const userDisplayName = 29 | widgetApi.widgetParameters.displayName ?? widgetApi.widgetParameters.userId; 30 | 31 | return ( 32 | <> 33 | 34 | 35 | 36 | 37 | 44 | } 45 | title={`Welcome ${userDisplayName}`} 46 | /> 47 | 48 | 49 | Your Device ID 50 | 51 | 52 | 53 | {widgetApi.widgetParameters.deviceId} 54 | 55 | 56 | 57 | 58 | 59 | ); 60 | }; 61 | -------------------------------------------------------------------------------- /example-widget-mui/src/WelcomePage/index.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export { WelcomePage } from './WelcomePage'; 18 | -------------------------------------------------------------------------------- /example-widget-mui/src/events/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export { 18 | STATE_EVENT_MESSAGE_COLLECTION, 19 | isValidMessageCollectionEvent, 20 | } from './messageCollectionEvent'; 21 | export type { MessageCollectionEvent } from './messageCollectionEvent'; 22 | export { ROOM_EVENT_REACTION, isValidReactionEvent } from './reactionEvent'; 23 | export type { ReactionEvent } from './reactionEvent'; 24 | export { 25 | ROOM_EVENT_ROOM_MESSAGE, 26 | isValidRoomMessageEvent, 27 | } from './roomMessageEvent'; 28 | export type { RoomMessageEvent } from './roomMessageEvent'; 29 | export { STATE_EVENT_ROOM_NAME, isValidRoomNameEvent } from './roomNameEvent'; 30 | export type { RoomNameEvent } from './roomNameEvent'; 31 | export { 32 | STATE_EVENT_THROW_DICE, 33 | isValidThrowDiceEvent, 34 | } from './throwDiceEvent'; 35 | export type { ThrowDiceEvent } from './throwDiceEvent'; 36 | export { 37 | ROOM_EVENT_UPLOADED_IMAGE, 38 | isValidUploadedImage, 39 | } from './uploadedImageEvent'; 40 | export type { UploadedImageEvent } from './uploadedImageEvent'; 41 | -------------------------------------------------------------------------------- /example-widget-mui/src/events/messageCollectionEvent.test.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { describe, expect, it } from 'vitest'; 18 | import { isValidMessageCollectionEvent } from './messageCollectionEvent'; 19 | 20 | describe('isValidMessageCollectionEvent', () => { 21 | it('should accept event', () => { 22 | expect( 23 | isValidMessageCollectionEvent({ 24 | content: { 25 | eventIds: ['$event-0'], 26 | }, 27 | event_id: '$event-id', 28 | origin_server_ts: 0, 29 | room_id: '!room-id', 30 | state_key: '', 31 | sender: '@user-id', 32 | type: 'net.nordeck.message_collection', 33 | }), 34 | ).toBe(true); 35 | }); 36 | 37 | it('should accept additional properties', () => { 38 | expect( 39 | isValidMessageCollectionEvent({ 40 | content: { 41 | eventIds: [], 42 | additional: 'tmp', 43 | }, 44 | event_id: '$event-id', 45 | origin_server_ts: 0, 46 | room_id: '!room-id', 47 | state_key: '', 48 | sender: '@user-id', 49 | type: 'net.nordeck.message_collection', 50 | }), 51 | ).toBe(true); 52 | }); 53 | 54 | it.each([ 55 | { eventIds: undefined }, 56 | { eventIds: null }, 57 | { eventIds: 'text' }, 58 | { eventIds: [undefined] }, 59 | { eventIds: [null] }, 60 | ])('should reject event with patch %j', (patch: object) => { 61 | expect( 62 | isValidMessageCollectionEvent({ 63 | content: { 64 | eventIds: [], 65 | ...patch, 66 | }, 67 | event_id: '$event-id', 68 | origin_server_ts: 0, 69 | room_id: '!room-id', 70 | state_key: '', 71 | sender: '@user-id', 72 | type: 'net.nordeck.message_collection', 73 | }), 74 | ).toBe(false); 75 | }); 76 | }); 77 | -------------------------------------------------------------------------------- /example-widget-mui/src/events/messageCollectionEvent.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { isStateEvent, StateEvent } from '@matrix-widget-toolkit/api'; 18 | import Joi from 'joi'; 19 | import { isValidEvent } from './validation'; 20 | 21 | /** 22 | * The event type of the message collection. 23 | */ 24 | export const STATE_EVENT_MESSAGE_COLLECTION = 'net.nordeck.message_collection'; 25 | 26 | export type MessageCollectionEvent = { 27 | eventIds: string[]; 28 | }; 29 | 30 | const messageCollectionEventSchema = Joi.object({ 31 | eventIds: Joi.array().items(Joi.string()).required(), 32 | }).unknown(); 33 | 34 | /** 35 | * Validates that `event` has a valid structure for a 36 | * {@link MessageCollectionEvent}. 37 | * 38 | * @param event - The event to validate. 39 | * @returns true, if the event is valid. 40 | */ 41 | export function isValidMessageCollectionEvent( 42 | event: StateEvent, 43 | ): event is StateEvent { 44 | return ( 45 | isValidEvent( 46 | event, 47 | STATE_EVENT_MESSAGE_COLLECTION, 48 | messageCollectionEventSchema, 49 | ) && isStateEvent(event) 50 | ); 51 | } 52 | -------------------------------------------------------------------------------- /example-widget-mui/src/events/reactionEvent.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { RoomEvent } from '@matrix-widget-toolkit/api'; 18 | import Joi from 'joi'; 19 | import { isValidEvent } from './validation'; 20 | 21 | /** 22 | * The event type of the reaction. 23 | */ 24 | export const ROOM_EVENT_REACTION = 'm.reaction'; 25 | 26 | export type ReactionEvent = { 27 | 'm.relates_to': { 28 | rel_type: string; 29 | event_id: string; 30 | key: string; 31 | }; 32 | }; 33 | 34 | const reactionEventSchema = Joi.object({ 35 | 'm.relates_to': Joi.object({ 36 | rel_type: Joi.string().required(), 37 | event_id: Joi.string().required(), 38 | key: Joi.string().required(), 39 | }) 40 | .unknown() 41 | .required(), 42 | }).unknown(); 43 | 44 | /** 45 | * Validates that `event` has a valid structure for a 46 | * {@link ReactionEvent}. 47 | * 48 | * @param event - The event to validate. 49 | * @returns true, if the event is valid. 50 | */ 51 | export function isValidReactionEvent( 52 | event: RoomEvent, 53 | ): event is RoomEvent { 54 | return isValidEvent(event, ROOM_EVENT_REACTION, reactionEventSchema); 55 | } 56 | -------------------------------------------------------------------------------- /example-widget-mui/src/events/roomMessageEvent.test.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { describe, expect, it } from 'vitest'; 18 | import { isValidRoomMessageEvent } from './roomMessageEvent'; 19 | 20 | describe('isValidRoomMessageEvent', () => { 21 | it('should accept event', () => { 22 | expect( 23 | isValidRoomMessageEvent({ 24 | content: { 25 | msgtype: 'm.text', 26 | body: 'My message', 27 | }, 28 | event_id: '$event-id', 29 | origin_server_ts: 0, 30 | room_id: '!room-id', 31 | sender: '@user-id', 32 | type: 'm.room.message', 33 | }), 34 | ).toBe(true); 35 | }); 36 | 37 | it('should accept additional properties', () => { 38 | expect( 39 | isValidRoomMessageEvent({ 40 | content: { 41 | msgtype: 'm.text', 42 | body: 'My message', 43 | additional: 'tmp', 44 | }, 45 | event_id: '$event-id', 46 | origin_server_ts: 0, 47 | room_id: '!room-id', 48 | sender: '@user-id', 49 | type: 'm.room.message', 50 | }), 51 | ).toBe(true); 52 | }); 53 | 54 | it.each([ 55 | { msgtype: undefined }, 56 | { msgtype: null }, 57 | { msgtype: 5 }, 58 | { body: undefined }, 59 | { body: null }, 60 | { body: 5 }, 61 | ])('should reject event with patch %j', (patch: object) => { 62 | expect( 63 | isValidRoomMessageEvent({ 64 | content: { 65 | msgtype: 'm.text', 66 | body: 'My message', 67 | ...patch, 68 | }, 69 | event_id: '$event-id', 70 | origin_server_ts: 0, 71 | room_id: '!room-id', 72 | sender: '@user-id', 73 | type: 'm.room.message', 74 | }), 75 | ).toBe(false); 76 | }); 77 | }); 78 | -------------------------------------------------------------------------------- /example-widget-mui/src/events/roomMessageEvent.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { RoomEvent } from '@matrix-widget-toolkit/api'; 18 | import Joi from 'joi'; 19 | import { isValidEvent } from './validation'; 20 | 21 | /** 22 | * The event type of the room message. 23 | */ 24 | export const ROOM_EVENT_ROOM_MESSAGE = 'm.room.message'; 25 | 26 | export type RoomMessageEvent = { 27 | msgtype: string; 28 | body: string; 29 | }; 30 | 31 | const roomMessageEventSchema = Joi.object({ 32 | msgtype: Joi.string().required(), 33 | body: Joi.string().required(), 34 | }).unknown(); 35 | 36 | /** 37 | * Validates that `event` has a valid structure for a 38 | * {@link RoomMessageEvent}. 39 | * 40 | * @param event - The event to validate. 41 | * @returns true, if the event is valid. 42 | */ 43 | export function isValidRoomMessageEvent( 44 | event: RoomEvent, 45 | ): event is RoomEvent { 46 | return isValidEvent(event, ROOM_EVENT_ROOM_MESSAGE, roomMessageEventSchema); 47 | } 48 | -------------------------------------------------------------------------------- /example-widget-mui/src/events/roomNameEvent.test.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { describe, expect, it } from 'vitest'; 18 | import { isValidRoomNameEvent } from './roomNameEvent'; 19 | 20 | describe('isValidRoomNameEvent', () => { 21 | it('should accept event', () => { 22 | expect( 23 | isValidRoomNameEvent({ 24 | content: { 25 | name: 'Room', 26 | }, 27 | event_id: '$event-id', 28 | origin_server_ts: 0, 29 | room_id: '!room-id', 30 | state_key: '', 31 | sender: '@user-id', 32 | type: 'm.room.name', 33 | }), 34 | ).toBe(true); 35 | }); 36 | 37 | it('should accept additional properties', () => { 38 | expect( 39 | isValidRoomNameEvent({ 40 | content: { 41 | name: 'Room', 42 | additional: 'tmp', 43 | }, 44 | event_id: '$event-id', 45 | origin_server_ts: 0, 46 | room_id: '!room-id', 47 | state_key: '', 48 | sender: '@user-id', 49 | type: 'm.room.name', 50 | }), 51 | ).toBe(true); 52 | }); 53 | 54 | it.each([{ name: undefined }, { name: null }, { name: 111 }])( 55 | 'should reject event with patch %j', 56 | (patch: object) => { 57 | expect( 58 | isValidRoomNameEvent({ 59 | content: { 60 | name: 'Room', 61 | ...patch, 62 | }, 63 | event_id: '$event-id', 64 | origin_server_ts: 0, 65 | room_id: '!room-id', 66 | state_key: '', 67 | sender: '@user-id', 68 | type: 'm.room.name', 69 | }), 70 | ).toBe(false); 71 | }, 72 | ); 73 | }); 74 | -------------------------------------------------------------------------------- /example-widget-mui/src/events/roomNameEvent.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { StateEvent } from '@matrix-widget-toolkit/api'; 18 | import Joi from 'joi'; 19 | import { isValidEvent } from './validation'; 20 | 21 | /** 22 | * The event type of the room name. 23 | */ 24 | export const STATE_EVENT_ROOM_NAME = 'm.room.name'; 25 | 26 | export type RoomNameEvent = { 27 | name: string; 28 | }; 29 | 30 | // based on https://github.com/matrix-org/matrix-spec/blob/03cdea4b57320926a6da73ad3b3f6c7f4fd0a7c2/data/event-schemas/schema/m.room.name.yaml 31 | const roomNameEventSchema = Joi.object({ 32 | name: Joi.string().required(), 33 | }).unknown(); 34 | 35 | /** 36 | * Validates that `event` has a valid structure for a 37 | * {@link RoomNameStateEventContent}. 38 | * 39 | * @param event - The event to validate. 40 | * @returns true, if the event is valid. 41 | */ 42 | export function isValidRoomNameEvent( 43 | event: StateEvent, 44 | ): event is StateEvent { 45 | return isValidEvent(event, STATE_EVENT_ROOM_NAME, roomNameEventSchema); 46 | } 47 | -------------------------------------------------------------------------------- /example-widget-mui/src/events/throwDiceEvent.test.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { describe, expect, it } from 'vitest'; 18 | import { isValidThrowDiceEvent } from './throwDiceEvent'; 19 | 20 | describe('isValidThrowDiceEvent', () => { 21 | it('should accept event', () => { 22 | expect( 23 | isValidThrowDiceEvent({ 24 | content: { 25 | pips: 5, 26 | }, 27 | event_id: '$event-id', 28 | origin_server_ts: 0, 29 | room_id: '!room-id', 30 | sender: '@user-id', 31 | type: 'net.nordeck.throw_dice', 32 | }), 33 | ).toBe(true); 34 | }); 35 | 36 | it('should accept additional properties', () => { 37 | expect( 38 | isValidThrowDiceEvent({ 39 | content: { 40 | pips: 5, 41 | additional: 'tmp', 42 | }, 43 | event_id: '$event-id', 44 | origin_server_ts: 0, 45 | room_id: '!room-id', 46 | sender: '@user-id', 47 | type: 'net.nordeck.throw_dice', 48 | }), 49 | ).toBe(true); 50 | }); 51 | 52 | it.each([{ pips: undefined }, { pips: null }, { pips: 'text' }])( 53 | 'should reject event with patch %j', 54 | (patch) => { 55 | expect( 56 | isValidThrowDiceEvent({ 57 | content: { 58 | name: 'Room', 59 | ...patch, 60 | }, 61 | event_id: '$event-id', 62 | origin_server_ts: 0, 63 | room_id: '!room-id', 64 | sender: '@user-id', 65 | type: 'net.nordeck.throw_dice', 66 | }), 67 | ).toBe(false); 68 | }, 69 | ); 70 | }); 71 | -------------------------------------------------------------------------------- /example-widget-mui/src/events/throwDiceEvent.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { RoomEvent } from '@matrix-widget-toolkit/api'; 18 | import Joi from 'joi'; 19 | import { isValidEvent } from './validation'; 20 | 21 | /** 22 | * The event type of the room name. 23 | */ 24 | export const STATE_EVENT_THROW_DICE = 'net.nordeck.throw_dice'; 25 | 26 | export type ThrowDiceEvent = { 27 | pips: number; 28 | }; 29 | 30 | const throwDiceEventSchema = Joi.object({ 31 | pips: Joi.number().required(), 32 | }).unknown(); 33 | 34 | /** 35 | * Validates that `event` has a valid structure for a 36 | * {@link ThrowDiceStateEventContent}. 37 | * 38 | * @param event - The event to validate. 39 | * @returns true, if the event is valid. 40 | */ 41 | export function isValidThrowDiceEvent( 42 | event: RoomEvent, 43 | ): event is RoomEvent { 44 | return isValidEvent(event, STATE_EVENT_THROW_DICE, throwDiceEventSchema); 45 | } 46 | -------------------------------------------------------------------------------- /example-widget-mui/src/events/uploadImageEvent.test.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { describe, expect, it } from 'vitest'; 18 | import { isValidUploadedImage } from './uploadedImageEvent'; 19 | 20 | describe('isValidUploadedImage', () => { 21 | it('should accept event', () => { 22 | expect( 23 | isValidUploadedImage({ 24 | content: { 25 | name: 'image', 26 | size: 554, 27 | url: 'https://example.org', 28 | }, 29 | event_id: '$event-id', 30 | origin_server_ts: 0, 31 | room_id: '!room-id', 32 | sender: '@user-id', 33 | type: 'net.nordeck.uploaded_image', 34 | }), 35 | ).toBe(true); 36 | }); 37 | 38 | it.each([ 39 | { name: undefined, size: undefined, url: undefined }, 40 | { name: undefined, size: 564, url: 'https://example.org' }, 41 | { name: 'image', size: undefined, url: 'https://example.org' }, 42 | { name: 'image', size: undefined, url: undefined }, 43 | ])('should reject event with patch %j', (patch: object) => { 44 | expect( 45 | isValidUploadedImage({ 46 | content: { 47 | name: 'Room', 48 | ...patch, 49 | }, 50 | event_id: '$event-id', 51 | origin_server_ts: 0, 52 | room_id: '!room-id', 53 | sender: '@user-id', 54 | type: 'net.nordeck.uploaded_image', 55 | }), 56 | ).toBe(false); 57 | }); 58 | }); 59 | -------------------------------------------------------------------------------- /example-widget-mui/src/events/uploadedImageEvent.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { RoomEvent } from '@matrix-widget-toolkit/api'; 18 | import Joi from 'joi'; 19 | import { isValidEvent } from './validation'; 20 | 21 | /** 22 | * The event type of the upload image. 23 | */ 24 | export const ROOM_EVENT_UPLOADED_IMAGE = 'net.nordeck.uploaded_image'; 25 | 26 | export type UploadedImageEvent = { 27 | name: string; 28 | size: number; 29 | url: string; 30 | }; 31 | 32 | const uploadedImageEventSchema = Joi.object({ 33 | name: Joi.string().required(), 34 | size: Joi.number().required(), 35 | url: Joi.string().required(), 36 | }).unknown(); 37 | 38 | /** 39 | * Validates that `event` has a valid structure for a 40 | * {@link UploadedImageRoomEventContent}. 41 | * 42 | * @param event - The event to validate. 43 | * @returns true, if the event is valid. 44 | */ 45 | export function isValidUploadedImage( 46 | event: RoomEvent, 47 | ): event is RoomEvent { 48 | return isValidEvent( 49 | event, 50 | ROOM_EVENT_UPLOADED_IMAGE, 51 | uploadedImageEventSchema, 52 | ); 53 | } 54 | -------------------------------------------------------------------------------- /example-widget-mui/src/events/validation.test.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { RoomEvent } from '@matrix-widget-toolkit/api'; 18 | import Joi from 'joi'; 19 | import { beforeEach, describe, expect, it } from 'vitest'; 20 | import { isValidEvent } from './validation'; 21 | 22 | const exampleSchema = Joi.object({ 23 | key: Joi.string(), 24 | }); 25 | 26 | describe('isValidEvent', () => { 27 | let event: RoomEvent; 28 | 29 | beforeEach(() => { 30 | event = { 31 | content: { 32 | key: 'test', 33 | }, 34 | event_id: '$event-id', 35 | origin_server_ts: 1000, 36 | room_id: '!room-id', 37 | sender: '@user-id', 38 | type: 'com.example.event', 39 | }; 40 | }); 41 | 42 | it('should validate event type', () => { 43 | event.type = 'com.example.other'; 44 | 45 | expect(isValidEvent(event, 'com.example.event', exampleSchema)).toEqual( 46 | false, 47 | ); 48 | }); 49 | 50 | it('should skip events without content', () => { 51 | event.content = undefined; 52 | 53 | expect(isValidEvent(event, 'com.example.event', exampleSchema)).toEqual( 54 | false, 55 | ); 56 | }); 57 | 58 | it('should validate event content', () => { 59 | event.content = { other: 'my-value' }; 60 | 61 | expect(isValidEvent(event, 'com.example.event', exampleSchema)).toEqual( 62 | false, 63 | ); 64 | }); 65 | 66 | it('should validate successful', () => { 67 | expect(isValidEvent(event, 'com.example.event', exampleSchema)).toEqual( 68 | true, 69 | ); 70 | }); 71 | }); 72 | -------------------------------------------------------------------------------- /example-widget-mui/src/events/validation.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { RoomEvent, StateEvent } from '@matrix-widget-toolkit/api'; 18 | import Joi from 'joi'; 19 | 20 | export function isValidEvent( 21 | event: RoomEvent | StateEvent, 22 | eventType: string, 23 | schema: Joi.AnySchema, 24 | ): boolean { 25 | if (event.type !== eventType) { 26 | return false; 27 | } 28 | 29 | if (!event.content || typeof event.content !== 'object') { 30 | return false; 31 | } 32 | 33 | const result = schema.validate(event.content); 34 | 35 | if (result.error) { 36 | // TODO: Log here if desired: console.warn('Error while validating event', result.error); 37 | return false; 38 | } 39 | 40 | return true; 41 | } 42 | -------------------------------------------------------------------------------- /example-widget-mui/src/i18n.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { 18 | WidgetApiLanguageDetector, 19 | WidgetToolkitI18nBackend, 20 | } from '@matrix-widget-toolkit/mui'; 21 | import i18n from 'i18next'; 22 | import ChainedBackend from 'i18next-chained-backend'; 23 | import HttpBackend from 'i18next-http-backend'; 24 | import { initReactI18next } from 'react-i18next'; 25 | 26 | i18n 27 | .use(ChainedBackend) 28 | .use(WidgetApiLanguageDetector) 29 | .use(initReactI18next) 30 | .init({ 31 | fallbackLng: 'en', 32 | debug: process.env.NODE_ENV === 'development', 33 | 34 | interpolation: { 35 | escapeValue: false, // not needed for react!! 36 | }, 37 | 38 | backend: { 39 | backends: [HttpBackend, WidgetToolkitI18nBackend], 40 | }, 41 | 42 | supportedLngs: ['en', 'de'], 43 | nonExplicitSupportedLngs: true, 44 | }); 45 | 46 | export default i18n; 47 | -------------------------------------------------------------------------------- /example-widget-mui/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example-widget-mui/src/main.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { WidgetApiImpl } from '@matrix-widget-toolkit/api'; 18 | import { EventDirection, WidgetEventCapability } from 'matrix-widget-api'; 19 | import React from 'react'; 20 | import { createRoot } from 'react-dom/client'; 21 | import { App } from './App'; 22 | import { STATE_EVENT_ROOM_NAME } from './events'; 23 | import './i18n'; 24 | 25 | // Initiate the widget API on startup. The Client will initiate 26 | // the connection with `capabilities` and we need to make sure 27 | // that the message doesn't get lost while we are initiating React. 28 | const widgetApiPromise = WidgetApiImpl.create({ 29 | // You can specify which capabilities should be requested at startup. One 30 | // can also request capabilities after the application started. 31 | capabilities: [ 32 | WidgetEventCapability.forStateEvent( 33 | EventDirection.Receive, 34 | STATE_EVENT_ROOM_NAME, 35 | ), 36 | ], 37 | }); 38 | 39 | const container = document.getElementById('root'); 40 | const root = createRoot(container!); 41 | root.render( 42 | 43 | 44 | , 45 | ); 46 | -------------------------------------------------------------------------------- /example-widget-mui/src/store/StoreProvider.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { useWidgetApi } from '@matrix-widget-toolkit/react'; 18 | import { PropsWithChildren, ReactElement, useState } from 'react'; 19 | import { Provider } from 'react-redux'; 20 | import { createStore } from './store'; 21 | 22 | /** 23 | * Create and provide the redux store 24 | */ 25 | export function StoreProvider({ children }: PropsWithChildren): ReactElement { 26 | const widgetApi = useWidgetApi(); 27 | const [store] = useState(() => createStore({ widgetApi })); 28 | 29 | return {children}; 30 | } 31 | -------------------------------------------------------------------------------- /example-widget-mui/src/store/baseApi.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { SerializedError } from '@reduxjs/toolkit'; 18 | import { 19 | Api, 20 | BaseQueryFn, 21 | coreModuleName, 22 | createApi, 23 | fakeBaseQuery, 24 | reactHooksModuleName, 25 | } from '@reduxjs/toolkit/query/react'; 26 | 27 | /** 28 | * The basis API that can be extended by {@code baseApi.injectEndpoints({})}. 29 | * 30 | * The API must not provide any endpoints to avoid any bidirectional 31 | * dependencies with this file. 32 | * 33 | * @remarks See also https://redux-toolkit.js.org/rtk-query/usage/code-splitting 34 | */ 35 | export const baseApi: Api< 36 | BaseQueryFn, 37 | EmptyObject, 38 | 'baseApi', 39 | never, 40 | typeof coreModuleName | typeof reactHooksModuleName 41 | > = createApi({ 42 | reducerPath: 'baseApi', 43 | baseQuery: fakeBaseQuery(), 44 | endpoints: () => ({}), 45 | }); 46 | -------------------------------------------------------------------------------- /example-widget-mui/src/store/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export { baseApi } from './baseApi'; 18 | export { createStore } from './store'; 19 | export type { ThunkExtraArgument } from './store'; 20 | export { StoreProvider } from './StoreProvider'; 21 | -------------------------------------------------------------------------------- /example-widget-mui/src/store/store.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { WidgetApi } from '@matrix-widget-toolkit/api'; 18 | import { configureStore } from '@reduxjs/toolkit'; 19 | import { baseApi } from './baseApi'; 20 | 21 | /** Options for {@link createStore}. */ 22 | type CreateStoreOpts = { 23 | /** The widget api instance. */ 24 | widgetApi: WidgetApi; 25 | }; 26 | 27 | /** 28 | * Create the react store. 29 | * 30 | * @param param0 - {@link CreateStoreOpts} 31 | * @returns an initialized store instance 32 | */ 33 | export function createStore({ widgetApi }: CreateStoreOpts) { 34 | const roomId = widgetApi.widgetParameters.roomId; 35 | const userId = widgetApi.widgetParameters.userId; 36 | 37 | if (!roomId || !userId) { 38 | throw new Error('roomId or userId empty'); 39 | } 40 | 41 | const store = configureStore({ 42 | reducer: { 43 | // register the extensible RTK Query API 44 | [baseApi.reducerPath]: baseApi.reducer, 45 | }, 46 | middleware: (getDefaultMiddleware) => 47 | getDefaultMiddleware({ 48 | thunk: { 49 | extraArgument: { 50 | // make the widgetApi available for the RTK Query endpoints 51 | widgetApi, 52 | } as ThunkExtraArgument, 53 | }, 54 | }).concat(baseApi.middleware), 55 | }); 56 | 57 | return store; 58 | } 59 | 60 | /** 61 | * Extra arguments that can be retrieved from the API 62 | */ 63 | export type ThunkExtraArgument = { 64 | widgetApi: WidgetApi; 65 | }; 66 | -------------------------------------------------------------------------------- /example-widget-mui/src/types.d.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * In TypeScript {} means any object. 19 | * Define an explicit type for an empty object here. 20 | */ 21 | type EmptyObject = Record; 22 | -------------------------------------------------------------------------------- /example-widget-mui/src/utils.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | const isError = (err: unknown): err is Error => err instanceof Error; 18 | 19 | export { isError }; 20 | -------------------------------------------------------------------------------- /example-widget-mui/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /// 18 | -------------------------------------------------------------------------------- /example-widget-mui/src/vitest.d.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import 'vitest'; 18 | 19 | interface AxeMatchers { 20 | toHaveNoViolations: () => R; 21 | } 22 | 23 | declare module 'vitest' { 24 | // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-empty-object-type 25 | interface Assertion extends AxeMatchers {} 26 | // eslint-disable-next-line @typescript-eslint/no-empty-object-type 27 | interface AsymmetricMatchersContaining extends AxeMatchers {} 28 | } 29 | -------------------------------------------------------------------------------- /example-widget-mui/tsconfig.json: -------------------------------------------------------------------------------- 1 | // Package specific tsconfig that extends the root one. 2 | { 3 | "extends": "../tsconfig.json", 4 | "compilerOptions": { 5 | "rootDir": ".", 6 | "noEmit": true 7 | }, 8 | "include": ["src"], 9 | "references": [ 10 | { 11 | "path": "./tsconfig.node.json" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /example-widget-mui/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "allowSyntheticDefaultImports": true, 8 | "strict": true 9 | }, 10 | "include": ["vite.config.ts"] 11 | } 12 | -------------------------------------------------------------------------------- /example-widget-mui/vite.config.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import basicSsl from '@vitejs/plugin-basic-ssl'; 18 | import react from '@vitejs/plugin-react-swc'; 19 | import { Plugin, PluginOption, defineConfig } from 'vite'; 20 | 21 | const plugins: [Plugin | PluginOption] = [react()]; 22 | let port = 5173; 23 | 24 | if (process.env.VITE_DEV_SSL === 'true') { 25 | plugins.push(basicSsl()); 26 | port = 5174; 27 | } 28 | 29 | // https://vitejs.dev/config/ 30 | export default defineConfig({ 31 | esbuild: { 32 | target: 'es2020', 33 | }, 34 | build: { 35 | outDir: 'build', 36 | commonjsOptions: { 37 | strictRequires: true, 38 | }, 39 | }, 40 | resolve: { 41 | dedupe: [ 42 | 'react', 43 | 'react-dom', 44 | '@matrix-widget-toolkit/react', 45 | '@matrix-widget-toolkit/mui', 46 | '@matrix-widget-toolkit/api', 47 | 'react-redux', 48 | '@mui/material', 49 | ], 50 | }, 51 | server: { 52 | fs: { 53 | allow: ['..'], 54 | }, 55 | port, 56 | strictPort: true, 57 | }, 58 | preview: { 59 | port: port - 1000, 60 | strictPort: true, 61 | }, 62 | plugins, 63 | // Use the env prefix from CRA for backward compatibility. 64 | envPrefix: 'REACT_APP_', 65 | }); 66 | -------------------------------------------------------------------------------- /example-widget-mui/vitest.config.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /// 18 | 19 | import { defineConfig } from 'vite'; 20 | 21 | export default defineConfig({ 22 | test: { 23 | environment: 'happy-dom', 24 | setupFiles: ['./src/setupTests.ts'], 25 | exclude: ['build'], 26 | }, 27 | }); 28 | -------------------------------------------------------------------------------- /packages/api/api-extractor.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", 3 | 4 | "extends": "../../api-extractor.json" 5 | } 6 | -------------------------------------------------------------------------------- /packages/api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@matrix-widget-toolkit/api", 3 | "version": "4.1.2", 4 | "description": "A simplified layer on top of matrix-widget-api to use build widgets.", 5 | "author": "Nordeck IT + Consulting GmbH", 6 | "license": "Apache-2.0", 7 | "source": "./src/index.ts", 8 | "types": "./src/index.ts", 9 | "exports": { 10 | "import": "./src/index.ts", 11 | "require": "./src/index.ts" 12 | }, 13 | "type": "module", 14 | "devDependencies": { 15 | "@rollup/plugin-commonjs": "28.0.3", 16 | "@types/node": "22.15.30", 17 | "@types/qs": "6.14.0", 18 | "@vitest/coverage-v8": "3.2.2", 19 | "typescript": "5.8.3", 20 | "vite": "6.3.5", 21 | "vitest": "3.2.2" 22 | }, 23 | "scripts": { 24 | "build": "tsc && rollup --config ../../rollup.config.mjs", 25 | "tsc": "tsc", 26 | "lint": "eslint .", 27 | "test": "echo \"Tests have to run from root project\"", 28 | "depcheck": "depcheck --ignores=@types/node,@rollup/plugin-commonjs,@vitest/coverage-v8 --ignore-dirs=lib", 29 | "prepack": "node ../../scripts/prepack.js", 30 | "postpack": "node ../../scripts/postpack.js", 31 | "translate": "echo \"Nothing to translate\"", 32 | "check-api-report": "api-extractor run --verbose", 33 | "generate-api-report": "tsc && api-extractor run --verbose --local", 34 | "clean": "yarn run clean:build", 35 | "clean:build": "rm -rf lib", 36 | "clean:cache": "echo 'script not implemented package'" 37 | }, 38 | "dependencies": { 39 | "joi": "17.13.3", 40 | "matrix-widget-api": "1.13.1", 41 | "qs": "6.14.0", 42 | "rxjs": "7.8.2" 43 | }, 44 | "repository": { 45 | "type": "git", 46 | "url": "https://github.com/nordeck/matrix-widget-toolkit.git", 47 | "directory": "packages/api" 48 | }, 49 | "publishConfig": { 50 | "module": "./build/esm/index.js", 51 | "main": "./build/cjs/index.cjs", 52 | "types": "./build/esm/index.d.ts", 53 | "exports": { 54 | ".": { 55 | "module": "./build/esm/index.js", 56 | "import": { 57 | "types": "./build/esm/index.d.ts", 58 | "default": "./build/esm/index.js" 59 | }, 60 | "require": { 61 | "types": "./build/cjs/index.d.cts", 62 | "default": "./build/cjs/index.cjs" 63 | } 64 | }, 65 | "./package.json": "./package.json" 66 | } 67 | }, 68 | "files": [ 69 | "build" 70 | ], 71 | "keywords": [ 72 | "matrix", 73 | "widget", 74 | "matrix-widget-api" 75 | ] 76 | } 77 | -------------------------------------------------------------------------------- /packages/api/src/api/extras/capabilities.test.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { Symbols } from 'matrix-widget-api'; 18 | import { describe, expect, it } from 'vitest'; 19 | import { generateRoomTimelineCapabilities } from './capabilities'; 20 | 21 | describe('generateRoomTimelineCapabilities', () => { 22 | it('should request permissions for multiple rooms', () => { 23 | expect(generateRoomTimelineCapabilities(['!room1', '!room2'])).toEqual([ 24 | 'org.matrix.msc2762.timeline:!room1', 25 | 'org.matrix.msc2762.timeline:!room2', 26 | ]); 27 | }); 28 | 29 | it('should request permissions for all rooms', () => { 30 | expect(generateRoomTimelineCapabilities(Symbols.AnyRoom)).toEqual([ 31 | 'org.matrix.msc2762.timeline:*', 32 | ]); 33 | }); 34 | 35 | it('should handle empty room array', () => { 36 | expect(generateRoomTimelineCapabilities([])).toEqual([]); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /packages/api/src/api/extras/capabilities.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { Symbols } from 'matrix-widget-api'; 18 | 19 | /** 20 | * Generate a list of capabilities to access the timeline of other rooms. 21 | * If enabled, all previously or future capabilities will apply to _all_ 22 | * selected rooms. 23 | * If `Symbols.AnyRoom` is passed, this is expanded to all joined 24 | * or invited rooms the client is able to see, current and future. 25 | * 26 | * @param roomIds - a list of room ids or `@link Symbols.AnyRoom`. 27 | * @returns the generated capabilities. 28 | */ 29 | export function generateRoomTimelineCapabilities( 30 | roomIds: string[] | Symbols.AnyRoom, 31 | ): string[] { 32 | if (roomIds === Symbols.AnyRoom) { 33 | return ['org.matrix.msc2762.timeline:*']; 34 | } 35 | 36 | if (Array.isArray(roomIds)) { 37 | return roomIds.map((id) => `org.matrix.msc2762.timeline:${id}`); 38 | } 39 | 40 | return []; 41 | } 42 | -------------------------------------------------------------------------------- /packages/api/src/api/extras/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export { generateRoomTimelineCapabilities } from './capabilities'; 18 | export { getRoomMemberDisplayName } from './displayName'; 19 | export { 20 | isRoomEvent, 21 | isStateEvent, 22 | isValidRoomEvent, 23 | isValidStateEvent as isValidStateEVent, 24 | isValidToDeviceMessageEvent, 25 | } from './events'; 26 | export { WIDGET_CAPABILITY_NAVIGATE, navigateToRoom } from './navigateTo'; 27 | export type { NavigateToRoomOptions } from './navigateTo'; 28 | export { compareOriginServerTS } from './originServerTs'; 29 | export { 30 | STATE_EVENT_POWER_LEVELS, 31 | calculateUserPowerLevel, 32 | hasActionPower, 33 | hasRoomEventPower, 34 | hasStateEventPower, 35 | isValidPowerLevelStateEvent, 36 | } from './powerLevel'; 37 | export type { PowerLevelsActions, PowerLevelsStateEvent } from './powerLevel'; 38 | export { 39 | ROOM_EVENT_REDACTION, 40 | isValidRedactionEvent, 41 | observeRedactionEvents, 42 | redactEvent, 43 | } from './redactions'; 44 | export type { Redaction, RedactionRoomEvent } from './redactions'; 45 | export { 46 | getContent, 47 | getOriginalEventId, 48 | isValidEventWithRelatesTo, 49 | } from './relatesTo'; 50 | export type { 51 | EventWithRelatesTo, 52 | NewContentRelatesTo, 53 | RelatesTo, 54 | RoomEventOrNewContent, 55 | } from './relatesTo'; 56 | export { 57 | STATE_EVENT_ROOM_MEMBER, 58 | isValidRoomMemberStateEvent, 59 | } from './roomMember'; 60 | export type { 61 | MembershipState, 62 | RoomMemberStateEventContent, 63 | } from './roomMember'; 64 | -------------------------------------------------------------------------------- /packages/api/src/api/extras/navigateTo.test.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { beforeEach, describe, expect, it, Mocked, vi } from 'vitest'; 18 | import { WidgetApi } from '../types'; 19 | import { navigateToRoom } from './navigateTo'; 20 | 21 | describe('navigateToRoom', () => { 22 | let widgetApi: Mocked; 23 | 24 | beforeEach(() => { 25 | widgetApi = { 26 | widgetId: 'widget-id', 27 | widgetParameters: { isOpenedByClient: true }, 28 | navigateTo: vi.fn(), 29 | } as Partial as Mocked; 30 | }); 31 | 32 | it('should navigate', async () => { 33 | await expect( 34 | navigateToRoom(widgetApi, '!my-room-id:example.org'), 35 | ).resolves.toBeUndefined(); 36 | 37 | expect(widgetApi.navigateTo).toHaveBeenCalledWith( 38 | 'https://matrix.to/#/!my-room-id%3Aexample.org', 39 | ); 40 | }); 41 | 42 | it('should navigate and pass a homeserver in via', async () => { 43 | await expect( 44 | navigateToRoom(widgetApi, '!my-room-id:example.org', { 45 | via: ['matrix.com'], 46 | }), 47 | ).resolves.toBeUndefined(); 48 | 49 | expect(widgetApi.navigateTo).toHaveBeenCalledWith( 50 | 'https://matrix.to/#/!my-room-id%3Aexample.org?via=matrix.com', 51 | ); 52 | }); 53 | 54 | it('should navigate and pass multiple homeservers in via', async () => { 55 | await expect( 56 | navigateToRoom(widgetApi, '!my-room-id:example.org', { 57 | via: ['matrix.com', 'example.com'], 58 | }), 59 | ).resolves.toBeUndefined(); 60 | 61 | expect(widgetApi.navigateTo).toHaveBeenCalledWith( 62 | 'https://matrix.to/#/!my-room-id%3Aexample.org?via=matrix.com&via=example.com', 63 | ); 64 | }); 65 | }); 66 | -------------------------------------------------------------------------------- /packages/api/src/api/extras/navigateTo.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { stringify } from 'qs'; 18 | import { WidgetApi } from '../types'; 19 | 20 | /** 21 | * The capability that needs to be requested in order to navigate to another room. 22 | */ 23 | export const WIDGET_CAPABILITY_NAVIGATE = 'org.matrix.msc2931.navigate'; 24 | 25 | /** 26 | * Options for the {@link navigateToRoom} function. 27 | */ 28 | export type NavigateToRoomOptions = { 29 | /** 30 | * Optional, array of one or more homeserver domains to discover the room. 31 | */ 32 | via?: string[]; 33 | }; 34 | 35 | /** 36 | * Navigate the client to another matrix room. 37 | * 38 | * @remarks This requires the {@link WIDGET_CAPABILITY_NAVIGATE} capability. 39 | * 40 | * @param widgetApi - the {@link WidgetApi} instance. 41 | * @param roomId - the room ID. 42 | * @param opts - {@link NavigateToRoomOptions} 43 | */ 44 | export async function navigateToRoom( 45 | widgetApi: WidgetApi, 46 | roomId: string, 47 | opts: NavigateToRoomOptions = {}, 48 | ): Promise { 49 | const { via = [] } = opts; 50 | const params = stringify( 51 | { via }, 52 | { addQueryPrefix: true, arrayFormat: 'repeat' }, 53 | ); 54 | const url = `https://matrix.to/#/${encodeURIComponent(roomId)}${params}`; 55 | await widgetApi.navigateTo(url); 56 | } 57 | -------------------------------------------------------------------------------- /packages/api/src/api/extras/originServerTs.test.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { describe, expect, it } from 'vitest'; 18 | import { RoomEvent } from '../types'; 19 | import { compareOriginServerTS } from './originServerTs'; 20 | 21 | describe('compareOriginServerTS', () => { 22 | function createEvent(originServerTs: number): RoomEvent { 23 | return { 24 | origin_server_ts: originServerTs, 25 | } as Partial as RoomEvent; 26 | } 27 | 28 | it('should sort earlier events first (a equals b)', () => { 29 | const eventA = createEvent(10000); 30 | const eventB = createEvent(10000); 31 | 32 | expect(compareOriginServerTS(eventA, eventB)).toEqual(0); 33 | }); 34 | 35 | it('should sort earlier events first (b before a)', () => { 36 | const eventA = createEvent(10000); 37 | const eventB = createEvent(20000); 38 | 39 | expect(compareOriginServerTS(eventA, eventB)).toBeLessThan(0); 40 | }); 41 | 42 | it('should sort earlier events first (a before b)', () => { 43 | const eventA = createEvent(20000); 44 | const eventB = createEvent(10000); 45 | 46 | expect(compareOriginServerTS(eventA, eventB)).toBeGreaterThan(0); 47 | }); 48 | }); 49 | -------------------------------------------------------------------------------- /packages/api/src/api/extras/originServerTs.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { RoomEvent } from '../types'; 18 | 19 | /** 20 | * Compares two room events by their origin server timestamp. 21 | * 22 | * @param a - A room event 23 | * @param b - A room event 24 | * @returns Either zero if the timestamp is equal, \>0 if a is newer, or \<0 if 25 | * b is newer. 26 | */ 27 | export function compareOriginServerTS( 28 | a: RoomEvent, 29 | b: RoomEvent, 30 | ): number { 31 | return a.origin_server_ts - b.origin_server_ts; 32 | } 33 | -------------------------------------------------------------------------------- /packages/api/src/api/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export * from './extras'; 18 | export { 19 | extractRawWidgetParameters, 20 | extractWidgetApiParameters, 21 | extractWidgetParameters, 22 | parseWidgetId, 23 | } from './parameters'; 24 | export type { WidgetApiParameters, WidgetId } from './parameters'; 25 | export { 26 | generateWidgetRegistrationUrl, 27 | hasWidgetParameters, 28 | repairWidgetRegistration, 29 | } from './registration'; 30 | export { WidgetParameter } from './types'; 31 | export type { 32 | RoomEvent, 33 | StateEvent, 34 | ToDeviceMessageEvent, 35 | TurnServer, 36 | WidgetApi, 37 | WidgetConfig, 38 | WidgetParameters, 39 | WidgetRegistration, 40 | } from './types'; 41 | export { 42 | makeEventFromSendStateEventResult, 43 | sendStateEventWithEventResult, 44 | } from './utils'; 45 | export { WidgetApiImpl } from './WidgetApiImpl'; 46 | export type { WidgetApiOptions } from './WidgetApiImpl'; 47 | -------------------------------------------------------------------------------- /packages/api/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * @packageDocumentation This is package that wraps `matrix-widget-api` to 19 | * provide a more convenient API. 20 | */ 21 | 22 | export * from './api'; 23 | -------------------------------------------------------------------------------- /packages/api/tsconfig.json: -------------------------------------------------------------------------------- 1 | // Package specific tsconfig that extends the root one. 2 | { 3 | "extends": "../../tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "lib", 6 | "rootDir": "." 7 | }, 8 | "include": ["src"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/api/vitest.config.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /// 18 | 19 | import { defineConfig } from 'vite'; 20 | 21 | export default defineConfig({ 22 | test: { 23 | environment: 'happy-dom', 24 | exclude: ['build', 'lib'], 25 | }, 26 | }); 27 | -------------------------------------------------------------------------------- /packages/mui/api-extractor.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", 3 | 4 | "extends": "../../api-extractor.json" 5 | } 6 | -------------------------------------------------------------------------------- /packages/mui/api-report.api.md: -------------------------------------------------------------------------------- 1 | ## API Report File for "@matrix-widget-toolkit/mui" 2 | 3 | > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). 4 | 5 | ```ts 6 | 7 | import { AvatarProps } from '@mui/material'; 8 | import { BackendModule } from 'i18next'; 9 | import { Capability } from 'matrix-widget-api'; 10 | import { ForwardRefExoticComponent } from 'react'; 11 | import LanguageDetector from 'i18next-browser-languagedetector'; 12 | import { PropsWithChildren } from 'react'; 13 | import { ReactElement } from 'react'; 14 | import { RefAttributes } from 'react'; 15 | import { WidgetApi } from '@matrix-widget-toolkit/api'; 16 | import { WidgetEventCapability } from 'matrix-widget-api'; 17 | import { WidgetRegistration } from '@matrix-widget-toolkit/api'; 18 | 19 | // @public 20 | export const ElementAvatar: ForwardRefExoticComponent & RefAttributes>; 21 | 22 | // @public 23 | export type ElementAvatarProps = { 24 | userId: string; 25 | displayName?: string; 26 | avatarUrl?: string; 27 | } & AvatarProps; 28 | 29 | // @public 30 | export function getEnvironment(name: string): string | undefined; 31 | 32 | // @public 33 | export function getEnvironment(name: string, defaultValue: string): string; 34 | 35 | // @public 36 | export function getNonce(): string | undefined; 37 | 38 | // @public 39 | export function MuiCapabilitiesGuard({ capabilities, children, }: MuiCapabilitiesGuardProps): ReactElement; 40 | 41 | // @public 42 | export type MuiCapabilitiesGuardProps = PropsWithChildren<{ 43 | capabilities: Array; 44 | }>; 45 | 46 | // @public 47 | export function MuiThemeProvider({ children, }: MuiThemeProviderProps): ReactElement; 48 | 49 | // @public 50 | export type MuiThemeProviderProps = PropsWithChildren; 51 | 52 | // @public 53 | export function MuiWidgetApiProvider({ widgetRegistration, widgetApiPromise, children, }: MuiWidgetApiProviderProps): ReactElement; 54 | 55 | // @public 56 | export type MuiWidgetApiProviderProps = PropsWithChildren<{ 57 | widgetRegistration?: WidgetRegistration; 58 | widgetApiPromise: Promise; 59 | }>; 60 | 61 | // @public 62 | export class WidgetApiLanguageDetector extends LanguageDetector { 63 | constructor(); 64 | } 65 | 66 | // @public 67 | export const WidgetToolkitI18nBackend: BackendModule; 68 | 69 | ``` 70 | -------------------------------------------------------------------------------- /packages/mui/i18next-parser.config.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | const i18NextParserConfig = { 18 | locales: ['en', 'de'], 19 | output: 'src/locales/$LOCALE/$NAMESPACE.json', 20 | sort: true, 21 | resetDefaultValueLocale: 'en', 22 | }; 23 | 24 | export default i18NextParserConfig; 25 | -------------------------------------------------------------------------------- /packages/mui/src/components/ElementAvatar/createAvatarUrl.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { getEnvironment } from '../MuiThemeProvider'; 18 | 19 | export function createAvatarUrl( 20 | url: string, 21 | { size = 60 }: { size?: number } = {}, 22 | ): string { 23 | const mxcPrefix = 'mxc://'; 24 | 25 | if (url.indexOf(mxcPrefix) !== 0) { 26 | return url; 27 | } 28 | 29 | const mxcUrl = url.slice(mxcPrefix.length); 30 | 31 | // TODO: Instead of retrieving the home server from an env variable, it would 32 | // be good to get this passed by the widget host, e.g. as an URL parameter. 33 | // In general our tight CSP makes it difficult to load images from this 34 | // source. 35 | // We could already access the home server URL by using the domain part of the 36 | // current users id and resolving the home server URL from the well-known 37 | // endpoint. However, this would also require a broad connect-src in the CSP. 38 | const homeServer = getEnvironment( 39 | 'REACT_APP_HOME_SERVER_URL', 40 | 'https://matrix-client.matrix.org', 41 | ); 42 | const imageUrl = new URL( 43 | `/_matrix/media/r0/thumbnail/${mxcUrl}?width=${size}&height=${size}&method=crop`, 44 | homeServer, 45 | ); 46 | return imageUrl.toString(); 47 | } 48 | -------------------------------------------------------------------------------- /packages/mui/src/components/ElementAvatar/getInitialLetter.test.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { describe, expect, it } from 'vitest'; 18 | import { getInitialLetter } from './getInitialLetter'; 19 | 20 | describe('getInitialLetter', () => { 21 | it.each` 22 | value | letter 23 | ${'@user-id'} | ${'U'} 24 | ${'Alice'} | ${'A'} 25 | ${'#room-id'} | ${'R'} 26 | `( 27 | 'should detect %letter as the initial letter of %value', 28 | ({ letter, value }) => { 29 | expect(getInitialLetter(value)).toBe(letter); 30 | }, 31 | ); 32 | }); 33 | -------------------------------------------------------------------------------- /packages/mui/src/components/ElementAvatar/getInitialLetter.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // Based on the way Element selects the initial letter 18 | // https://github.com/matrix-org/matrix-react-sdk/blob/667ec166d736dfb0ac49f67398a8b7a13db7d5ef/src/Avatar.ts#L121 19 | export function getInitialLetter(name: string): string | undefined { 20 | if (name.length < 1) { 21 | return undefined; 22 | } 23 | 24 | const initial = name[0]; 25 | if ((initial === '@' || initial === '#' || initial === '+') && name[1]) { 26 | name = name.substring(1); 27 | } 28 | 29 | // rely on the grapheme cluster splitter in the Intl.Segmenter to get the first character 30 | return Array.from(new Intl.Segmenter().segment(name)) 31 | .map(({ segment }) => segment) 32 | .slice(0, 1)[0] 33 | .toUpperCase(); 34 | } 35 | -------------------------------------------------------------------------------- /packages/mui/src/components/ElementAvatar/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export { ElementAvatar } from './ElementAvatar'; 18 | export type { ElementAvatarProps } from './ElementAvatar'; 19 | -------------------------------------------------------------------------------- /packages/mui/src/components/ElementAvatar/useIdColorHash.test.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { describe, expect, it } from 'vitest'; 18 | import { useIdColorHash } from './useIdColorHash'; 19 | 20 | describe('useIdColorHash', () => { 21 | it('should generate stable hashes from ids', () => { 22 | expect(useIdColorHash('@oliver.sand:matrix.org')).toMatchInlineSnapshot( 23 | `3`, 24 | ); 25 | expect( 26 | useIdColorHash('!OFRzoSUQYSjIXMEZDS:datanauten.de'), 27 | ).toMatchInlineSnapshot(`5`); 28 | expect( 29 | useIdColorHash('!vbSFpwCIcbnazhtFTT:matrix.org'), 30 | ).toMatchInlineSnapshot(`1`); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /packages/mui/src/components/ElementAvatar/useIdColorHash.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * Determines a number for a given Matrix ID or room ID, helps disambiguating users 19 | * who are trying to impersonate someone else. 20 | * 21 | * {@link https://github.com/element-hq/compound-web/blob/5950e6827aaaca5a0b2540093f0b168ca590e8ca/src/components/Avatar/useIdColorHash.ts#L23} 22 | * @copyright Copyright 2023 New Vector Ltd 23 | * 24 | * @param id - a Matrix ID or room ID 25 | * @returns a hash of the ID provided 26 | */ 27 | export function useIdColorHash(id: string): number { 28 | const MIN = 1; 29 | const MAX = 6; 30 | // Sum up the values of all the char codes in the string 31 | const charCodeSum = id.split('').reduce((sum, char) => { 32 | return sum + char.charCodeAt(0); 33 | }, 0); 34 | return (charCodeSum % MAX) + MIN; 35 | } 36 | 37 | export const isColorHash = (value: number): value is 1 | 2 | 3 | 4 | 5 | 6 => { 38 | return [1, 2, 3, 4, 5, 6].includes(value); 39 | }; 40 | -------------------------------------------------------------------------------- /packages/mui/src/components/LoadingView/LoadingView.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { render, screen } from '@testing-library/react'; 18 | import axe from 'axe-core'; 19 | import { describe, expect, it } from 'vitest'; 20 | import { LoadingView } from './LoadingView'; 21 | 22 | describe('', () => { 23 | it('should display a loading animation if displayed long enough', async () => { 24 | render(); 25 | 26 | expect(await screen.findByText('Loading…')).toBeInTheDocument(); 27 | }); 28 | 29 | it('should have no accessibility violations', async () => { 30 | const { container } = render(); 31 | 32 | expect(await screen.findByText('Loading…')).toBeInTheDocument(); 33 | expect(await axe.run(container)).toHaveNoViolations(); 34 | }); 35 | 36 | it('should not render a loading animation before a certain time is over', () => { 37 | render(); 38 | 39 | expect(screen.queryByText('Loading…')).not.toBeInTheDocument(); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /packages/mui/src/components/LoadingView/LoadingView.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { Box, CircularProgress, Typography } from '@mui/material'; 18 | import { ReactElement, useId } from 'react'; 19 | import { useTranslation } from 'react-i18next'; 20 | import { useTimeout } from 'react-use'; 21 | 22 | export function LoadingView(): ReactElement { 23 | const id = useId(); 24 | const [isLongLoad] = useTimeout(100); 25 | const { t } = useTranslation('widget-toolkit'); 26 | 27 | return isLongLoad() ? ( 28 | 29 | 30 | 31 | 32 | {t('loading.message', 'Loading…')} 33 | 34 | 35 | ) : ( 36 | <> 37 | ); 38 | } 39 | -------------------------------------------------------------------------------- /packages/mui/src/components/LoadingView/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export { LoadingView } from './LoadingView'; 18 | -------------------------------------------------------------------------------- /packages/mui/src/components/MissingCapabilitiesError/MissingCapabilitiesError.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { render, screen } from '@testing-library/react'; 18 | import userEvent from '@testing-library/user-event'; 19 | import axe from 'axe-core'; 20 | import { describe, expect, it, vi } from 'vitest'; 21 | import { MissingCapabilitiesError } from './MissingCapabilitiesError'; 22 | 23 | describe('', () => { 24 | it('should render without exploding', () => { 25 | render(); 26 | 27 | expect(screen.getByText('Missing capabilities')).toBeInTheDocument(); 28 | expect(screen.getByText(/the minimum capabilities/i)).toBeInTheDocument(); 29 | }); 30 | 31 | it('should have no accessibility violations', async () => { 32 | const { container } = render( 33 | , 34 | ); 35 | 36 | expect(await axe.run(container)).toHaveNoViolations(); 37 | }); 38 | 39 | it('should re-request capabilities', async () => { 40 | const onRetry = vi.fn(); 41 | render(); 42 | 43 | await userEvent.click( 44 | screen.getByRole('button', { name: /request capabilities/i }), 45 | ); 46 | 47 | expect(onRetry).toHaveBeenCalled(); 48 | }); 49 | }); 50 | -------------------------------------------------------------------------------- /packages/mui/src/components/MissingCapabilitiesError/MissingCapabilitiesError.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import ErrorIcon from '@mui/icons-material/Error'; 18 | import { Alert, AlertTitle, Box, Button, Typography } from '@mui/material'; 19 | import { DispatchWithoutAction, ReactElement } from 'react'; 20 | import { useTranslation } from 'react-i18next'; 21 | 22 | export function MissingCapabilitiesError({ 23 | onRetry, 24 | }: { 25 | onRetry: DispatchWithoutAction; 26 | }): ReactElement { 27 | const { t } = useTranslation('widget-toolkit'); 28 | 29 | return ( 30 | 31 | }> 32 | 33 | {t('missing-capabilities.title', 'Missing capabilities')} 34 | 35 | 36 | 37 | {t( 38 | 'missing-capabilities.instructions', 39 | 'The minimum capabilities required for this widget are missing. Make sure to grant all requested capabilities.', 40 | )} 41 | 42 | 43 | 44 | 50 | 51 | 52 | 53 | ); 54 | } 55 | -------------------------------------------------------------------------------- /packages/mui/src/components/MissingCapabilitiesError/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export { MissingCapabilitiesError } from './MissingCapabilitiesError'; 18 | -------------------------------------------------------------------------------- /packages/mui/src/components/MuiCapabilitiesGuard/MuiCapabilitiesGuard.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { CapabilitiesGuard } from '@matrix-widget-toolkit/react'; 18 | import { Capability, WidgetEventCapability } from 'matrix-widget-api'; 19 | import { PropsWithChildren, ReactElement } from 'react'; 20 | import { LoadingView } from '../LoadingView'; 21 | import { MissingCapabilitiesError } from '../MissingCapabilitiesError'; 22 | 23 | /** 24 | * Props for the {@link MuiCapabilitiesGuard} component. 25 | */ 26 | export type MuiCapabilitiesGuardProps = PropsWithChildren<{ 27 | /** 28 | * Required capabilities to display the `children`. 29 | */ 30 | capabilities: Array; 31 | }>; 32 | 33 | /** 34 | * A guard that ask the user for capabilities and only shows the `children` 35 | * if all capabilities were accepted. 36 | * If capabilities are denied, a message and a button to retry is displayed 37 | * instead. 38 | * @param param0 - {@link MuiCapabilitiesGuardProps} 39 | */ 40 | export function MuiCapabilitiesGuard({ 41 | capabilities, 42 | children, 43 | }: MuiCapabilitiesGuardProps): ReactElement { 44 | return ( 45 | 50 | {children} 51 | 52 | ); 53 | } 54 | -------------------------------------------------------------------------------- /packages/mui/src/components/MuiCapabilitiesGuard/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export { MuiCapabilitiesGuard } from './MuiCapabilitiesGuard'; 18 | export type { MuiCapabilitiesGuardProps } from './MuiCapabilitiesGuard'; 19 | -------------------------------------------------------------------------------- /packages/mui/src/components/MuiThemeProvider/EmotionCacheProvider.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import createCache from '@emotion/cache'; 18 | import { CacheProvider } from '@emotion/react'; 19 | import { PropsWithChildren } from 'react'; 20 | import { getNonce } from './nonce'; 21 | 22 | // https://mui.com/material-ui/guides/content-security-policy/ 23 | 24 | function createEmotionCache() { 25 | return createCache({ 26 | key: 'widget', 27 | nonce: getNonce(), 28 | prepend: true, 29 | }); 30 | } 31 | 32 | const cache = createEmotionCache(); 33 | 34 | export function EmotionCacheProvider({ children }: PropsWithChildren) { 35 | return {children}; 36 | } 37 | -------------------------------------------------------------------------------- /packages/mui/src/components/MuiThemeProvider/environment.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | declare global { 18 | interface Window { 19 | __ENVIRONMENT__: string | undefined; 20 | } 21 | } 22 | 23 | const getWindowEnvironment = () => { 24 | let environment: { [key: string]: string | undefined } = {}; 25 | 26 | if (typeof window.__ENVIRONMENT__ === 'string') { 27 | const encoded = window.__ENVIRONMENT__; 28 | // check if mustache placeholder hasn't been replaced for some reason. 29 | if (!encoded.match(/^{{.*}}$/)) { 30 | try { 31 | environment = JSON.parse(atob(encoded)); 32 | } catch { 33 | console.warn( 34 | 'window.__ENVIRONMENT__ has an unexpected format', 35 | encoded, 36 | ); 37 | } 38 | } 39 | } 40 | return environment; 41 | }; 42 | 43 | const environment = getWindowEnvironment(); 44 | 45 | /** 46 | * Reads environment variables starting with `REACT_APP_` from a global variable 47 | * at runtime and falls back to `process.env` build time variables. 48 | * 49 | * @param name - The name of the environment variable, should start with 50 | * `REACT_APP_`. 51 | */ 52 | export function getEnvironment(name: string): string | undefined; 53 | /** 54 | * Reads environment variables starting with `REACT_APP_` from a global variable 55 | * at runtime and falls back to `process.env` build time variables. 56 | * 57 | * @param name - The name of the environment variable, should start with 58 | * `REACT_APP_`. 59 | * @param defaultValue - The default value to return if the environment variable 60 | * is not provided. 61 | */ 62 | export function getEnvironment(name: string, defaultValue: string): string; 63 | 64 | export function getEnvironment( 65 | name: string, 66 | defaultValue?: string, 67 | ): string | undefined { 68 | const value = environment[name] || process.env[name]; 69 | return value ?? defaultValue; 70 | } 71 | -------------------------------------------------------------------------------- /packages/mui/src/components/MuiThemeProvider/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export { getEnvironment } from './environment'; 18 | export { MuiThemeProvider } from './MuiThemeProvider'; 19 | export type { MuiThemeProviderProps } from './MuiThemeProvider'; 20 | export { getNonce } from './nonce'; 21 | -------------------------------------------------------------------------------- /packages/mui/src/components/MuiThemeProvider/nonce.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * Retrieve the nonce passed by our Docker base image. 19 | * @returns A nonce that can be used to perform operations that are disabled in 20 | * our CSP by default. 21 | */ 22 | export function getNonce(): string | undefined { 23 | return (window as unknown as Record)['NONCE']; 24 | } 25 | -------------------------------------------------------------------------------- /packages/mui/src/components/MuiWidgetApiProvider/ChildError.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { render, screen } from '@testing-library/react'; 18 | import axe from 'axe-core'; 19 | import { describe, expect, it } from 'vitest'; 20 | import { ChildError } from './ChildError'; 21 | 22 | describe('', () => { 23 | it('should render without exploding', () => { 24 | const error = new Error('Hello World'); 25 | render(); 26 | 27 | expect(screen.getByText('Ohh no!')).toBeInTheDocument(); 28 | expect( 29 | screen.getByText(/an error occured inside the widget/i), 30 | ).toBeInTheDocument(); 31 | expect(screen.getByText(/Hello World/)).toBeInTheDocument(); 32 | }); 33 | 34 | it('should have no accessibility violations', async () => { 35 | const error = new Error('Hello World'); 36 | const { container } = render(); 37 | 38 | expect(await axe.run(container)).toHaveNoViolations(); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /packages/mui/src/components/MuiWidgetApiProvider/ChildError.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import ErrorIcon from '@mui/icons-material/Error'; 18 | import { Alert, AlertTitle, Box, Typography } from '@mui/material'; 19 | import { ReactElement } from 'react'; 20 | import { useTranslation } from 'react-i18next'; 21 | import { CopyableCode } from './CopyableCode'; 22 | 23 | export function ChildError({ error }: { error: Error }): ReactElement { 24 | const { t } = useTranslation('widget-toolkit'); 25 | 26 | return ( 27 | 28 | }> 29 | {t('error.title', 'Ohh no!')} 30 | 31 | 32 | {t( 33 | 'error.instructions', 34 | 'An error occured inside the widget. You can try to reopen the widget.', 35 | )} 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | ); 44 | } 45 | -------------------------------------------------------------------------------- /packages/mui/src/components/MuiWidgetApiProvider/CopyableCode.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import CheckOutlinedIcon from '@mui/icons-material/CheckOutlined'; 18 | import ContentCopyOutlinedIcon from '@mui/icons-material/ContentCopyOutlined'; 19 | import { Box, IconButton, Paper } from '@mui/material'; 20 | import { ReactElement, useState } from 'react'; 21 | import { useTranslation } from 'react-i18next'; 22 | import { useCopyToClipboard } from 'react-use'; 23 | 24 | export function CopyableCode({ code }: { code: string }): ReactElement { 25 | const { t } = useTranslation('widget-toolkit'); 26 | const [hasCopied, setHasCopied] = useState(false); 27 | const [, copyToClipboard] = useCopyToClipboard(); 28 | 29 | const copyLabel = t('code.copy-to-clipboard', 'Copy to clipboard'); 30 | 31 | return ( 32 | 33 | 34 | 35 | 36 | {code} 37 | 38 | 39 | 40 | ({ 42 | position: 'absolute', 43 | right: theme.spacing(1), 44 | bottom: theme.spacing(1), 45 | })} 46 | onClick={() => { 47 | copyToClipboard(code); 48 | setHasCopied(true); 49 | }} 50 | onBlur={() => setHasCopied(false)} 51 | aria-label={copyLabel} 52 | > 53 | {hasCopied ? : } 54 | 55 | 56 | 57 | ); 58 | } 59 | -------------------------------------------------------------------------------- /packages/mui/src/components/MuiWidgetApiProvider/MobileClientError.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { render, screen } from '@testing-library/react'; 18 | import axe from 'axe-core'; 19 | import { describe, expect, it } from 'vitest'; 20 | import { MobileClientError } from './MobileClientError'; 21 | 22 | describe('', () => { 23 | it('should render without exploding', () => { 24 | render(); 25 | 26 | expect( 27 | screen.getByText('Mobile clients are not supported'), 28 | ).toBeInTheDocument(); 29 | expect( 30 | screen.getByText(/the widget doesn't work in mobile clients/i), 31 | ).toBeInTheDocument(); 32 | }); 33 | 34 | it('should have no accessibility violations', async () => { 35 | const { container } = render(); 36 | 37 | expect(await axe.run(container)).toHaveNoViolations(); 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /packages/mui/src/components/MuiWidgetApiProvider/MobileClientError.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import ErrorIcon from '@mui/icons-material/Error'; 18 | import { Alert, AlertTitle, Box } from '@mui/material'; 19 | import { ReactElement } from 'react'; 20 | import { useTranslation } from 'react-i18next'; 21 | 22 | export function MobileClientError(): ReactElement { 23 | const { t } = useTranslation('widget-toolkit'); 24 | 25 | return ( 26 | 27 | }> 28 | 29 | {t('mobile-client.title', 'Mobile clients are not supported')} 30 | 31 | 32 | {t( 33 | 'mobile-client.instructions', 34 | "The widget doesn't work in mobile clients due to technical limitations. Open the widget on you Desktop or Web client.", 35 | )} 36 | 37 | 38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /packages/mui/src/components/MuiWidgetApiProvider/MuiWidgetApiProvider.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { 18 | extractWidgetParameters as extractWidgetParametersMocked, 19 | hasWidgetParameters as hasWidgetParametersMocked, 20 | WidgetApi, 21 | } from '@matrix-widget-toolkit/api'; 22 | import { render, screen } from '@testing-library/react'; 23 | import { beforeEach, describe, expect, it, Mocked, vi } from 'vitest'; 24 | import { MuiWidgetApiProvider } from './MuiWidgetApiProvider'; 25 | 26 | vi.mock('@matrix-widget-toolkit/api'); 27 | 28 | const hasWidgetParameters = vi.mocked(hasWidgetParametersMocked); 29 | 30 | const extractWidgetParameters = vi.mocked(extractWidgetParametersMocked); 31 | 32 | describe('WidgetApiProvider', () => { 33 | let widgetApi: Mocked; 34 | let widgetApiPromise: Promise; 35 | 36 | beforeEach(() => { 37 | widgetApi = { 38 | widgetId: 'widget-id', 39 | widgetParameters: { isOpenedByClient: true }, 40 | rerequestInitialCapabilities: vi.fn(), 41 | hasInitialCapabilities: vi.fn(), 42 | sendRoomEvent: vi.fn(), 43 | } as Partial> as Mocked; 44 | 45 | widgetApiPromise = Promise.resolve(widgetApi); 46 | 47 | extractWidgetParameters.mockReturnValue({ isOpenedByClient: true }); 48 | }); 49 | 50 | it('should render without exploding', async () => { 51 | hasWidgetParameters.mockReturnValue(true); 52 | widgetApi.hasInitialCapabilities.mockReturnValue(true); 53 | 54 | render( 55 | 56 |
Children
57 |
, 58 | ); 59 | 60 | expect(await screen.findByText('Children')).toBeInTheDocument(); 61 | }); 62 | }); 63 | -------------------------------------------------------------------------------- /packages/mui/src/components/MuiWidgetApiProvider/OutsideClientError.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { render, screen } from '@testing-library/react'; 18 | import axe from 'axe-core'; 19 | import { describe, expect, it } from 'vitest'; 20 | import { OutsideClientError } from './OutsideClientError'; 21 | 22 | describe('', () => { 23 | it('should render without exploding', () => { 24 | render(); 25 | 26 | expect(screen.getByText('Only runs as a widget')).toBeInTheDocument(); 27 | expect( 28 | screen.getByText(/you need to register this URL as a widget/i), 29 | ).toBeInTheDocument(); 30 | expect(screen.getByText(/\/addwidget/)).toBeInTheDocument(); 31 | }); 32 | 33 | it('should have no accessibility violations', async () => { 34 | const { container } = render(); 35 | 36 | expect(await axe.run(container)).toHaveNoViolations(); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /packages/mui/src/components/MuiWidgetApiProvider/OutsideClientError.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { generateWidgetRegistrationUrl } from '@matrix-widget-toolkit/api'; 18 | import ErrorIcon from '@mui/icons-material/Error'; 19 | import { Alert, AlertTitle, Box, Typography } from '@mui/material'; 20 | import { ReactElement } from 'react'; 21 | import { useTranslation } from 'react-i18next'; 22 | import { CopyableCode } from './CopyableCode'; 23 | 24 | export function OutsideClientError(): ReactElement { 25 | const { t } = useTranslation('widget-toolkit'); 26 | 27 | return ( 28 | 29 | }> 30 | 31 | {t('outside-client.title', 'Only runs as a widget')} 32 | 33 | 34 | 35 | {t( 36 | 'outside-client.instructions', 37 | "You need to register this URL as a widget, it's not possible to use it standalone. Run this command in the matrix room you want to register the widget in:", 38 | )} 39 | 40 | 41 | 42 | 47 | 48 | 49 | 50 | ); 51 | } 52 | -------------------------------------------------------------------------------- /packages/mui/src/components/MuiWidgetApiProvider/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export { MuiWidgetApiProvider } from './MuiWidgetApiProvider'; 18 | export type { MuiWidgetApiProviderProps } from './MuiWidgetApiProvider'; 19 | -------------------------------------------------------------------------------- /packages/mui/src/components/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export * from './ElementAvatar'; 18 | export * from './MuiCapabilitiesGuard'; 19 | export * from './MuiThemeProvider'; 20 | export * from './MuiWidgetApiProvider'; 21 | -------------------------------------------------------------------------------- /packages/mui/src/i18n/i18n.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { extractWidgetParameters } from '@matrix-widget-toolkit/api'; 18 | import LanguageDetector, { 19 | CustomDetector, 20 | } from 'i18next-browser-languagedetector'; 21 | import resourcesToBackend from 'i18next-resources-to-backend'; 22 | 23 | /** 24 | * Backend for usage with `i18n-next` that provides translations for internal 25 | * messages. 26 | */ 27 | export const WidgetToolkitI18nBackend = resourcesToBackend((lng, ns, clb) => { 28 | import(`../locales/${lng}/${ns}.json`) 29 | .then((resources) => clb(null, resources)) 30 | .catch((err) => clb(err, undefined)); 31 | }); 32 | 33 | /** 34 | * A language detector that reads the language from the widget url. 35 | */ 36 | export class WidgetApiLanguageDetector extends LanguageDetector { 37 | constructor() { 38 | super(undefined, { 39 | // prefer the widget api and fallback to the browser settings. 40 | order: ['widgetApi', 'navigator'], 41 | }); 42 | 43 | const widgetApiLanguageDetector: CustomDetector = { 44 | name: 'widgetApi', 45 | lookup: () => { 46 | const { clientLanguage } = extractWidgetParameters(); 47 | return clientLanguage; 48 | }, 49 | }; 50 | 51 | this.addDetector(widgetApiLanguageDetector); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /packages/mui/src/i18n/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export { WidgetApiLanguageDetector, WidgetToolkitI18nBackend } from './i18n'; 18 | -------------------------------------------------------------------------------- /packages/mui/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * @packageDocumentation This package provides a MUI theme that fits to 19 | * the default Element theme. 20 | */ 21 | 22 | export * from './components'; 23 | export * from './i18n'; 24 | -------------------------------------------------------------------------------- /packages/mui/src/locales/de/widget-toolkit.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": { 3 | "copy-to-clipboard": "In die Zwischenablage kopieren" 4 | }, 5 | "error": { 6 | "instructions": "Im Widget ist ein Fehler aufgetreten. Der Fehler kann eventuell durch erneutes Öffnen des Widgets behoben werden.", 7 | "title": "Ohh nein!" 8 | }, 9 | "loading": { 10 | "message": "Lädt…" 11 | }, 12 | "missing-capabilities": { 13 | "instructions": "Die minimal erforderlichen Rechte für dieses Widget fehlen. Es müssen alle angefragen Rechte erteilt werden.", 14 | "request-capabilities": "Rechte erteilen", 15 | "title": "Fehlende Rechte" 16 | }, 17 | "missing-parameters": { 18 | "completed": { 19 | "instructions": "Widget Konfiguration abgeschlossen, das Widget muss erneut geöffnet werden.", 20 | "title": "Widget Konfiguration abgeschlossen" 21 | }, 22 | "instructions": "Das Widget ist nicht korrekt registriert. Es muss sichergestellt werden, das alle Parameter in der URL enthalten sind:", 23 | "permissions-error": { 24 | "close": "Schließen", 25 | "instructions": "Fehlende Berechtigungen, das Widget konnte nicht konfiguriert werden. Die Korrektur muss durch einen Raum-Administrator durchgeführt werden.", 26 | "title": "Fehler" 27 | }, 28 | "repair": "Registrierung korrigieren", 29 | "repair-instructions": "Die Widget Registrierung kann entweder manuell oder automatisch korrigiert werden:", 30 | "title": "Fehlerhafte Widget Registrierung" 31 | }, 32 | "mobile-client": { 33 | "instructions": "Aufgrund von technischen Limitationen funktioniert das Widget nicht in den mobilen Apps. Das Widget muss in einer Desktop oder Web App geöffnet werden.", 34 | "title": "Mobile Apps werden nicht unterstützt" 35 | }, 36 | "outside-client": { 37 | "instructions": "Diese URL muss als Widget registiert werden und kann nicht direkt aufgerufen werden. Mit dem folgenden Kommando kann das Widget in einem Raum eingerichtet werden:", 38 | "title": "Nur als Widget ausführbar" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /packages/mui/src/locales/en/widget-toolkit.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": { 3 | "copy-to-clipboard": "Copy to clipboard" 4 | }, 5 | "error": { 6 | "instructions": "An error occured inside the widget. You can try to reopen the widget.", 7 | "title": "Ohh no!" 8 | }, 9 | "loading": { 10 | "message": "Loading…" 11 | }, 12 | "missing-capabilities": { 13 | "instructions": "The minimum capabilities required for this widget are missing. Make sure to grant all requested capabilities.", 14 | "request-capabilities": "Request capabilities", 15 | "title": "Missing capabilities" 16 | }, 17 | "missing-parameters": { 18 | "completed": { 19 | "instructions": "Configuration completed, reopen the widget to start using it.", 20 | "title": "Widget configuration complete" 21 | }, 22 | "instructions": "The widget is not registered correctly. Make sure to include the correct parameters in the widget URL:", 23 | "permissions-error": { 24 | "close": "Close", 25 | "instructions": "Insufficient permissions, could not configure widget. Only room admins can configure the widget.", 26 | "title": "Error" 27 | }, 28 | "repair": "Repair registration", 29 | "repair-instructions": "You can either modify the widget registration manually or fix it automatically:", 30 | "title": "Wrong widget registration" 31 | }, 32 | "mobile-client": { 33 | "instructions": "The widget doesn't work in mobile clients due to technical limitations. Open the widget on you Desktop or Web client.", 34 | "title": "Mobile clients are not supported" 35 | }, 36 | "outside-client": { 37 | "instructions": "You need to register this URL as a widget, it's not possible to use it standalone. Run this command in the matrix room you want to register the widget in:", 38 | "title": "Only runs as a widget" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /packages/mui/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 18 | // allows you to do things like: 19 | // expect(element).toHaveTextContent(/react/i) 20 | // learn more: https://github.com/testing-library/jest-dom 21 | import '@testing-library/jest-dom/vitest'; 22 | 23 | // Make sure to initialize i18n (see mock below) 24 | import i18n from 'i18next'; 25 | 26 | import { cleanup } from '@testing-library/react'; 27 | import { AxeResults } from 'axe-core'; 28 | import { initReactI18next } from 'react-i18next'; 29 | import { afterEach, expect } from 'vitest'; 30 | 31 | i18n.use(initReactI18next).init({ 32 | fallbackLng: 'en', 33 | interpolation: { 34 | escapeValue: false, 35 | }, 36 | resources: { en: {} }, 37 | }); 38 | 39 | // Add support for axe 40 | expect.extend({ 41 | toHaveNoViolations(results: AxeResults) { 42 | const violations = results.violations ?? []; 43 | 44 | return { 45 | pass: violations.length === 0, 46 | actual: violations, 47 | message() { 48 | if (violations.length === 0) { 49 | return ''; 50 | } 51 | 52 | return `Expected no accessibility violations but received some. 53 | 54 | ${violations 55 | .map( 56 | (violation) => `[${violation.impact}] ${violation.id} 57 | ${violation.description} 58 | ${violation.helpUrl} 59 | `, 60 | ) 61 | .join('\n')} 62 | `; 63 | }, 64 | }; 65 | }, 66 | }); 67 | 68 | afterEach(() => { 69 | cleanup(); 70 | }); 71 | -------------------------------------------------------------------------------- /packages/mui/src/vitest.d.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import 'vitest'; 18 | 19 | interface AxeMatchers { 20 | toHaveNoViolations: () => R; 21 | } 22 | 23 | declare module 'vitest' { 24 | // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-empty-object-type 25 | interface Assertion extends AxeMatchers {} 26 | // eslint-disable-next-line @typescript-eslint/no-empty-object-type 27 | interface AsymmetricMatchersContaining extends AxeMatchers {} 28 | } 29 | -------------------------------------------------------------------------------- /packages/mui/tsconfig.json: -------------------------------------------------------------------------------- 1 | // Package specific tsconfig that extends the root one. 2 | { 3 | "extends": "../../tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "lib", 6 | "rootDir": "." 7 | }, 8 | "include": ["src"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/mui/vitest.config.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /// 18 | 19 | import { defineConfig } from 'vite'; 20 | 21 | export default defineConfig({ 22 | test: { 23 | environment: 'happy-dom', 24 | setupFiles: ['./src/setupTests.ts'], 25 | exclude: ['build', 'lib'], 26 | }, 27 | }); 28 | -------------------------------------------------------------------------------- /packages/react/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # `@matrix-widget-toolkit/react` 2 | 3 | ## 2.0.5 4 | 5 | ### Patch Changes 6 | 7 | - 97618fd: WidgetRegistration options for WidgetApiPromise can now have a requiredParameters list that will be checked upon registation. 8 | - Updated dependencies [97618fd] 9 | - Updated dependencies [f451122] 10 | - Updated dependencies [c91c947] 11 | - @matrix-widget-toolkit/api@4.1.0 12 | 13 | ## 2.0.4 14 | 15 | ### Patch Changes 16 | 17 | - Updated dependencies [76314a9] 18 | - Updated dependencies [14f1795] 19 | - @matrix-widget-toolkit/api@4.0.0 20 | 21 | ## 2.0.3 22 | 23 | ### Patch Changes 24 | 25 | - 55d42f1: Fix the esm exports and lodash exports 26 | - Updated dependencies [55d42f1] 27 | - @matrix-widget-toolkit/api@3.4.2 28 | 29 | ## 2.0.2 30 | 31 | ### Patch Changes 32 | 33 | - f00e7cf: Migrate to vitejs and vitest 34 | - Updated dependencies [f00e7cf] 35 | - @matrix-widget-toolkit/api@3.4.1 36 | 37 | ## 2.0.1 38 | 39 | ### Patch Changes 40 | 41 | - 9a54c89: Update to MUI 6 and latest React / Redux dependencies 42 | 43 | ## 2.0.0 44 | 45 | ### Major Changes 46 | 47 | - 71bd53c: Upgrade to React 18 48 | 49 | ## 1.0.6 50 | 51 | ### Patch Changes 52 | 53 | - cabc33d: Switched Node.js version to 20. We encourage all consuming projects to also switch to this version. 54 | - Updated dependencies [cabc33d] 55 | - @matrix-widget-toolkit/api@3.2.2 56 | 57 | ## 1.0.5 58 | 59 | ### Patch Changes 60 | 61 | - a021ec7: Bump `matrix-widget-api` from 1.1.1 to 1.3.1. 62 | - Updated dependencies [a021ec7] 63 | - Updated dependencies [a021ec7] 64 | - @matrix-widget-toolkit/api@3.2.0 65 | 66 | ## 1.0.4 67 | 68 | ### Patch Changes 69 | 70 | - Updated dependencies [df0fef9] 71 | - @matrix-widget-toolkit/api@3.0.0 72 | 73 | ## 1.0.3 74 | 75 | ### Patch Changes 76 | 77 | - Updated dependencies [aa806cf] 78 | - Updated dependencies [6584d71] 79 | - @matrix-widget-toolkit/api@2.0.0 80 | 81 | ## 1.0.2 82 | 83 | ### Patch Changes 84 | 85 | - 0c6d595: Bump `react-use` from 17.3.2 to 17.4.0. 86 | 87 | ## 1.0.1 88 | 89 | Initial release 90 | -------------------------------------------------------------------------------- /packages/react/api-extractor.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", 3 | 4 | "extends": "../../api-extractor.json" 5 | } 6 | -------------------------------------------------------------------------------- /packages/react/src/components/CapabilitiesGuard/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export { CapabilitiesGuard } from './CapabilitiesGuard'; 18 | export type { CapabilitiesGuardProps } from './CapabilitiesGuard'; 19 | -------------------------------------------------------------------------------- /packages/react/src/components/ThemeSelectionProvider/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export { 18 | ThemeSelectionProvider, 19 | useThemeSelection, 20 | } from './ThemeSelectionProvider'; 21 | export type { 22 | Theme, 23 | ThemeSelectionContextType, 24 | ThemeSelectionProviderProps, 25 | } from './ThemeSelectionProvider'; 26 | -------------------------------------------------------------------------------- /packages/react/src/components/WidgetApiProvider/context.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { WidgetApi } from '@matrix-widget-toolkit/api'; 18 | import { createContext, useContext } from 'react'; 19 | 20 | export const WidgetApiContext = createContext(undefined); 21 | 22 | /** 23 | * Hook for accessing the widget API. 24 | * 25 | * @remarks Can only be called inside a `WidgetApiProvider` 26 | * (or WidgetApiMockProvider in tests). 27 | * 28 | * @returns A fully initialized widget API. 29 | */ 30 | export const useWidgetApi = (): WidgetApi => { 31 | const context = useContext(WidgetApiContext); 32 | if (context === undefined) { 33 | throw new Error( 34 | 'useWidgetApi must be used within a WidgetApiProvider (or WidgetApiMockProvider in tests)', 35 | ); 36 | } 37 | return context; 38 | }; 39 | 40 | /** 41 | * Provides a custom instance of the `WidgetApi` to the context. 42 | * 43 | * @remarks Should only be used in tests. 44 | */ 45 | export const WidgetApiMockProvider = WidgetApiContext.Provider; 46 | -------------------------------------------------------------------------------- /packages/react/src/components/WidgetApiProvider/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export { WidgetApiMockProvider, useWidgetApi } from './context'; 18 | export { WidgetApiProvider } from './WidgetApiProvider'; 19 | export type { WidgetApiProviderProps } from './WidgetApiProvider'; 20 | -------------------------------------------------------------------------------- /packages/react/src/components/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export * from './CapabilitiesGuard'; 18 | export * from './ThemeSelectionProvider'; 19 | export * from './WidgetApiProvider'; 20 | -------------------------------------------------------------------------------- /packages/react/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * @packageDocumentation This is package that provides a Widget API 19 | * intergration for React apps. 20 | */ 21 | 22 | export * from './components'; 23 | -------------------------------------------------------------------------------- /packages/react/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 18 | // allows you to do things like: 19 | // expect(element).toHaveTextContent(/react/i) 20 | // learn more: https://github.com/testing-library/jest-dom 21 | import '@testing-library/jest-dom/vitest'; 22 | 23 | import { cleanup } from '@testing-library/react'; 24 | import { afterEach } from 'vitest'; 25 | 26 | afterEach(() => { 27 | cleanup(); 28 | }); 29 | -------------------------------------------------------------------------------- /packages/react/tsconfig.json: -------------------------------------------------------------------------------- 1 | // Package specific tsconfig that extends the root one. 2 | { 3 | "extends": "../../tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "lib", 6 | "rootDir": "." 7 | }, 8 | "include": ["src"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/react/vitest.config.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /// 18 | 19 | import { defineConfig } from 'vite'; 20 | 21 | export default defineConfig({ 22 | test: { 23 | environment: 'happy-dom', 24 | setupFiles: ['./src/setupTests.ts'], 25 | exclude: ['build', 'lib'], 26 | }, 27 | }); 28 | -------------------------------------------------------------------------------- /packages/testing/api-extractor.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", 3 | 4 | "extends": "../../api-extractor.json" 5 | } 6 | -------------------------------------------------------------------------------- /packages/testing/api-report.api.md: -------------------------------------------------------------------------------- 1 | ## API Report File for "@matrix-widget-toolkit/testing" 2 | 3 | > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). 4 | 5 | ```ts 6 | 7 | import { Mocked } from 'vitest'; 8 | import { RoomEvent } from '@matrix-widget-toolkit/api'; 9 | import { StateEvent } from '@matrix-widget-toolkit/api'; 10 | import { ToDeviceMessageEvent } from '@matrix-widget-toolkit/api'; 11 | import { WidgetApi } from '@matrix-widget-toolkit/api'; 12 | 13 | // @public 14 | export type MockedWidgetApi = { 15 | stop: () => void; 16 | mockSendRoomEvent(event: RoomEvent): RoomEvent; 17 | mockSendStateEvent(event: StateEvent): StateEvent; 18 | mockSendToDeviceMessage(event: ToDeviceMessageEvent): ToDeviceMessageEvent; 19 | clearRoomEvents(opts?: { 20 | type?: string; 21 | }): void; 22 | clearStateEvents(opts?: { 23 | type?: string; 24 | }): void; 25 | } & Mocked; 26 | 27 | // @public 28 | export function mockWidgetApi(opts?: { 29 | userId?: string; 30 | roomId?: string; 31 | widgetId?: string; 32 | }): MockedWidgetApi; 33 | 34 | ``` 35 | -------------------------------------------------------------------------------- /packages/testing/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@matrix-widget-toolkit/testing", 3 | "version": "3.0.4", 4 | "description": "Testing support for @matrix-widget-toolkit/api.", 5 | "author": "Nordeck IT + Consulting GmbH", 6 | "license": "Apache-2.0", 7 | "source": "./src/index.ts", 8 | "types": "./src/index.ts", 9 | "exports": { 10 | "import": "./src/index.ts", 11 | "require": "./src/index.ts" 12 | }, 13 | "type": "module", 14 | "devDependencies": { 15 | "@types/node": "22.15.30", 16 | "@vitest/coverage-v8": "3.2.2", 17 | "typescript": "5.8.3", 18 | "vite": "6.3.5", 19 | "vitest": "3.2.2" 20 | }, 21 | "scripts": { 22 | "build": "tsc && rollup --config ../../rollup.config.mjs", 23 | "tsc": "tsc", 24 | "lint": "eslint .", 25 | "test": "echo \"Tests have to run from root project\"", 26 | "depcheck": "depcheck --ignores=@types/node,@vitest/coverage-v8,lodash,lodash-es,@types/lodash-es --ignore-dirs=lib", 27 | "prepack": "node ../../scripts/prepack.js", 28 | "postpack": "node ../../scripts/postpack.js", 29 | "translate": "echo \"Nothing to translate\"", 30 | "check-api-report": "api-extractor run --verbose", 31 | "generate-api-report": "tsc && api-extractor run --verbose --local", 32 | "clean": "yarn run clean:build", 33 | "clean:build": "rm -rf lib", 34 | "clean:cache": "echo 'script not implemented package'" 35 | }, 36 | "dependencies": { 37 | "@matrix-widget-toolkit/api": "^4.0.0", 38 | "matrix-widget-api": "1.13.1", 39 | "rxjs": "7.8.2" 40 | }, 41 | "repository": { 42 | "type": "git", 43 | "url": "https://github.com/nordeck/matrix-widget-toolkit.git", 44 | "directory": "packages/testing" 45 | }, 46 | "publishConfig": { 47 | "module": "./build/esm/index.js", 48 | "main": "./build/cjs/index.cjs", 49 | "types": "./build/esm/index.d.ts", 50 | "exports": { 51 | ".": { 52 | "module": "./build/esm/index.js", 53 | "import": { 54 | "types": "./build/esm/index.d.ts", 55 | "default": "./build/esm/index.js" 56 | }, 57 | "require": { 58 | "types": "./build/cjs/index.d.cts", 59 | "default": "./build/cjs/index.cjs" 60 | } 61 | }, 62 | "./package.json": "./package.json" 63 | } 64 | }, 65 | "files": [ 66 | "build" 67 | ], 68 | "keywords": [ 69 | "matrix", 70 | "widget", 71 | "matrix-widget-api" 72 | ] 73 | } 74 | -------------------------------------------------------------------------------- /packages/testing/src/api/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export { mockWidgetApi } from './mockWidgetApi'; 18 | export type { MockedWidgetApi } from './mockWidgetApi'; 19 | -------------------------------------------------------------------------------- /packages/testing/src/api/utils.test.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { describe, expect, it } from 'vitest'; 18 | import { deepEqual, uniqueId } from './utils'; 19 | 20 | describe('uniqueId', () => { 21 | it('should generate unique ids with a prefix', () => { 22 | const id1 = uniqueId('$event-'); 23 | const id2 = uniqueId('$event-'); 24 | expect(id1).not.toEqual(id2); 25 | expect(id1).toMatch(/^\$event-\d+$/); 26 | expect(id2).toMatch(/^\$event-\d+$/); 27 | }); 28 | }); 29 | 30 | describe('deepEqual', () => { 31 | it('should return true for deeply equal objects', () => { 32 | const obj1 = { a: 1, b: { c: 2 } }; 33 | const obj2 = { a: 1, b: { c: 2 } }; 34 | expect(deepEqual(obj1, obj2)).toBe(true); 35 | }); 36 | 37 | it('should return false for objects with different values', () => { 38 | const obj1 = { a: 1, b: { c: 2 } }; 39 | const obj2 = { a: 1, b: { c: 3 } }; 40 | expect(deepEqual(obj1, obj2)).toBe(false); 41 | }); 42 | 43 | it('should return false for objects with different keys', () => { 44 | const obj1 = { a: 1, b: { c: 2 } }; 45 | const obj2 = { a: 1, b: { d: 2 } }; 46 | expect(deepEqual(obj1, obj2)).toBe(false); 47 | }); 48 | 49 | it('should return true for deeply equal arrays', () => { 50 | const arr1 = [1, [2, 3]]; 51 | const arr2 = [1, [2, 3]]; 52 | expect(deepEqual(arr1, arr2)).toBe(true); 53 | }); 54 | 55 | it('should return false for arrays with different values', () => { 56 | const arr1 = [1, [2, 3]]; 57 | const arr2 = [1, [2, 4]]; 58 | expect(deepEqual(arr1, arr2)).toBe(false); 59 | }); 60 | }); 61 | -------------------------------------------------------------------------------- /packages/testing/src/api/utils.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // These 2 functions originally were using lodash. These are replacements for them. 18 | export const uniqueId = ( 19 | (counter) => 20 | (str = '') => 21 | `${str}${++counter}` 22 | )(0); 23 | 24 | // eslint-disable-next-line @typescript-eslint/no-explicit-any -- This is a generic deepEqual function therefore it can accept any type. 25 | export function deepEqual(x: any, y: any): boolean { 26 | const ok = Object.keys, 27 | tx = typeof x, 28 | ty = typeof y; 29 | return x && y && tx === 'object' && tx === ty 30 | ? ok(x).length === ok(y).length && 31 | ok(x).every((key) => deepEqual(x[key], y[key])) 32 | : x === y; 33 | } 34 | -------------------------------------------------------------------------------- /packages/testing/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * @packageDocumentation Testing support for \@matrix-widget-toolkit/api. 19 | */ 20 | export * from './api'; 21 | -------------------------------------------------------------------------------- /packages/testing/tsconfig.json: -------------------------------------------------------------------------------- 1 | // Package specific tsconfig that extends the root one. 2 | { 3 | "extends": "../../tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "lib", 6 | "rootDir": "." 7 | }, 8 | "include": ["src"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/testing/vitest.config.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /// 18 | 19 | import { defineConfig } from 'vite'; 20 | 21 | export default defineConfig({ 22 | test: { 23 | environment: 'happy-dom', 24 | exclude: ['build', 'lib'], 25 | }, 26 | }); 27 | -------------------------------------------------------------------------------- /rollup.config.mjs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import commonjs from '@rollup/plugin-commonjs'; 18 | 19 | /** 20 | * @type {import('rollup').RollupOptions} 21 | */ 22 | const config = { 23 | input: 'lib/src/index.js', 24 | plugins: [commonjs()], 25 | output: [ 26 | { 27 | file: 'build/cjs/index.cjs', 28 | format: 'cjs', 29 | interop: 'auto', 30 | }, 31 | { 32 | file: 'build/esm/index.js', 33 | format: 'es', 34 | }, 35 | ], 36 | }; 37 | 38 | export default config; 39 | -------------------------------------------------------------------------------- /scripts/license-header.txt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright <%= YEAR %> <%= NAME %> 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | -------------------------------------------------------------------------------- /scripts/postpack.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is executed in the postpack step of "npm pack" / "npm publish". 3 | * It reverts the temporary changes to the package.json. 4 | */ 5 | 6 | const PACKAGE_PATH = 'package.json'; 7 | const PACKAGE_PATH_BACKUP = 'package.json-prepack'; 8 | 9 | import * as fs from 'fs'; 10 | 11 | fs.renameSync(PACKAGE_PATH_BACKUP, PACKAGE_PATH); 12 | -------------------------------------------------------------------------------- /scripts/publishAllPackages.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Publish all non-published packages to the NPM registry. 3 | * 4 | * !!! This script is intended to only be run by the github workflow! !!! 5 | */ 6 | 7 | import * as child_process from 'child_process'; 8 | import * as fs from 'fs'; 9 | import * as path from 'path'; 10 | 11 | const packages = fs.readdirSync('packages'); 12 | 13 | for (var pkg of packages) { 14 | const packagePath = path.resolve('packages', pkg); 15 | 16 | if (!fs.lstatSync(packagePath).isDirectory()) { 17 | continue; 18 | } 19 | 20 | const { name, version } = JSON.parse( 21 | fs.readFileSync(path.resolve(packagePath, 'package.json')), 22 | ); 23 | 24 | if (!versionNeedsUpload(name, version)) { 25 | console.log(`✅ Package ${name} already up-to-date`); 26 | continue; 27 | } 28 | 29 | console.log(`🔄 Publish package ${name}@${version}`); 30 | 31 | child_process.execSync( 32 | 'npm publish --registry https://registry.npmjs.org --access public', 33 | { 34 | cwd: packagePath, 35 | }, 36 | ); 37 | 38 | console.log(`✅ Package ${name} published`); 39 | } 40 | 41 | // Create the git tags so the changesets CLI will create the proper GitHub releases 42 | console.log(child_process.execSync('yarn changeset tag').toString()); 43 | 44 | console.log('Done!'); 45 | 46 | function versionNeedsUpload(name, version) { 47 | try { 48 | const result = child_process.execSync( 49 | `npm view "${name}@${version}" --registry https://registry.npmjs.org --json`, 50 | ); 51 | 52 | // this line throws if not exists 53 | JSON.parse(result.toString()); 54 | 55 | return false; 56 | } catch (_) { 57 | return true; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | // This is the root tsconfig that is extended by the individual packages 2 | { 3 | "compilerOptions": { 4 | "target": "es5", 5 | "lib": ["dom", "dom.iterable", "esnext"], 6 | "allowJs": true, 7 | "skipLibCheck": true, 8 | "esModuleInterop": true, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "noFallthroughCasesInSwitch": true, 13 | "module": "esnext", 14 | "moduleResolution": "node", 15 | "resolveJsonModule": true, 16 | "isolatedModules": true, 17 | "jsx": "react-jsx", 18 | "noEmit": false, 19 | "declaration": true 20 | }, 21 | "exclude": ["node_modules"], 22 | // Include all source code for building 23 | "include": ["example-widget-mui/src", "packages/*/src"] 24 | } 25 | -------------------------------------------------------------------------------- /vitest.config.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Nordeck IT + Consulting GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { defineConfig } from 'vitest/config'; 18 | 19 | export default defineConfig({ 20 | test: { 21 | // These are all the packages using vitest. The containers folder is excluded since it is using playwright. 22 | projects: ['example-widget-mui', 'packages/*'], 23 | }, 24 | }); 25 | --------------------------------------------------------------------------------