@iobroker/json-config 9.0.2 → 9.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/build/JsonConfigComponent/ConfigCustom.js +8 -4
- package/build/JsonConfigComponent/ConfigCustom.js.map +1 -1
- package/build/JsonConfigComponent/ConfigCustomErrorBoundary.d.ts +32 -0
- package/build/JsonConfigComponent/ConfigCustomErrorBoundary.js +45 -0
- package/build/JsonConfigComponent/ConfigCustomErrorBoundary.js.map +1 -0
- package/build/JsonConfigComponent/i18n/de.json +2 -0
- package/build/JsonConfigComponent/i18n/en.json +2 -0
- package/build/index.d.ts +11 -0
- package/build/index.js +11 -0
- package/build/index.js.map +1 -1
- package/build/types.d.ts +13 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1822,8 +1822,9 @@ The schema is used here: https://github.com/SchemaStore/schemastore/blob/6da29cd
|
|
|
1822
1822
|
### **WORK IN PROGRESS**
|
|
1823
1823
|
-->
|
|
1824
1824
|
## Changelog
|
|
1825
|
-
### 9.0.
|
|
1825
|
+
### 9.0.3 (2026-07-25)
|
|
1826
1826
|
- (@GermanBluefox) Breaking: React 19 + MUI 9 + TS 6
|
|
1827
|
+
- (@GermanBluefox) Added loading of the new custom components
|
|
1827
1828
|
|
|
1828
1829
|
### 8.5.5 (2026-07-24)
|
|
1829
1830
|
- (@GermanBluefox) Trying to improve the behaviour of tabs
|
|
@@ -5,6 +5,7 @@ import * as IconsMaterial from '@mui/icons-material';
|
|
|
5
5
|
import * as AdapterReact from '@iobroker/gui-components';
|
|
6
6
|
import { I18n } from '@iobroker/gui-components';
|
|
7
7
|
import ConfigGeneric from './ConfigGeneric';
|
|
8
|
+
import ConfigCustomErrorBoundary from './ConfigCustomErrorBoundary';
|
|
8
9
|
import * as JsonConfig from '../';
|
|
9
10
|
init({
|
|
10
11
|
name: 'iobroker_admin',
|
|
@@ -107,7 +108,9 @@ export default class ConfigCustom extends ConfigGeneric {
|
|
|
107
108
|
{
|
|
108
109
|
name: uniqueName,
|
|
109
110
|
entry: url,
|
|
110
|
-
|
|
111
|
+
// Components of the current GUI API generation are always built as ES
|
|
112
|
+
// modules, so the former `bundlerType` schema attribute is obsolete.
|
|
113
|
+
type: 'module',
|
|
111
114
|
},
|
|
112
115
|
]);
|
|
113
116
|
setPromise = loadRemote(`${uniqueName}/${fileToLoad}`);
|
|
@@ -143,9 +146,10 @@ export default class ConfigCustom extends ConfigGeneric {
|
|
|
143
146
|
render() {
|
|
144
147
|
const CustomComponent = this.state.Component;
|
|
145
148
|
const schema = this.props.schema || {};
|
|
146
|
-
const item = CustomComponent ? (React.createElement(
|
|
147
|
-
|
|
148
|
-
|
|
149
|
+
const item = CustomComponent ? (React.createElement(ConfigCustomErrorBoundary, { name: schema.name, url: schema.url },
|
|
150
|
+
React.createElement(CustomComponent, { ...this.props,
|
|
151
|
+
// @ts-expect-error BF (2024-12-18) Remove after the 7.4 will be mainstream. All following lines
|
|
152
|
+
socket: this.props.oContext.socket, theme: this.props.oContext.theme, themeType: this.props.oContext.themeType, instance: this.props.oContext.instance, adapterName: this.props.oContext.adapterName, systemConfig: this.props.oContext.systemConfig, forceUpdate: this.props.oContext.forceUpdate }))) : this.state.error ? (React.createElement("div", null, this.state.error)) : (React.createElement(LinearProgress, null));
|
|
149
153
|
if (schema.newLine) {
|
|
150
154
|
return (React.createElement(React.Fragment, null,
|
|
151
155
|
React.createElement("div", { style: { flexBasis: '100%', height: 0 } }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConfigCustom.js","sourceRoot":"src/","sources":["JsonConfigComponent/ConfigCustom.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { type JSX } from 'react';\nimport { LinearProgress } from '@mui/material';\nimport { registerRemotes, loadRemote, init } from '@module-federation/runtime';\n\nimport * as IconsMaterial from '@mui/icons-material';\n\nimport * as AdapterReact from '@iobroker/gui-components';\nimport { I18n } from '@iobroker/gui-components';\n\nimport ConfigGeneric, { type ConfigGenericProps, type ConfigGenericState } from './ConfigGeneric';\nimport * as JsonConfig from '../';\nimport type { ConfigItemCustom } from '../types';\n\ninterface ConfigCustomProps extends ConfigGenericProps {\n schema: ConfigItemCustom;\n}\n\ninterface ConfigCustomState extends ConfigGenericState {\n Component: React.FC<ConfigGenericProps> | null;\n error: string;\n}\n\ninit({\n name: 'iobroker_admin',\n shared: {\n '@iobroker/gui-components': {\n lib: () => AdapterReact,\n version: '*',\n },\n '@mui/icons-material': {\n lib: () => IconsMaterial,\n version: '*',\n },\n '@iobroker/json-config': {\n lib: () => JsonConfig,\n version: '*',\n },\n },\n remotes: [],\n});\n\nexport default class ConfigCustom extends ConfigGeneric<ConfigCustomProps, ConfigCustomState> {\n static runningLoads: Record<string, Promise<{ default: Record<string, React.FC<ConfigGenericProps>> } | null>> = {};\n\n constructor(props: ConfigCustomProps) {\n super(props);\n // schema.url - location of Widget\n // schema.name - Component name\n // schema.i18n - i18n\n\n Object.assign(this.state, {\n Component: null,\n error: '',\n });\n }\n\n // load component dynamically\n async componentDidMount(): Promise<void> {\n if (!this.props.schema.url) {\n console.error('URL is empty. Cannot load custom component!');\n this.setState({ error: 'URL is empty. Cannot load custom component!' });\n return;\n }\n\n let url;\n if (this.props.schema.url.startsWith('http:') || this.props.schema.url.startsWith('https:')) {\n url = this.props.schema.url;\n } else if (this.props.schema.url.startsWith('./')) {\n url = `${window.location.protocol}//${window.location.host}${this.props.schema.url.replace(/^\\./, '')}`;\n } else {\n url = `${window.location.protocol}//${window.location.host}/adapter/${this.props.oContext.adapterName}/${this.props.schema.url}`;\n }\n const [uniqueName, fileToLoad, ...componentNameParts] = this.props.schema.name.split('/');\n const componentName = componentNameParts.join('/');\n if (!url) {\n console.error(\n 'Cannot find URL for custom component! Please define \"url\" as \"custom/customComponents.js\" in the schema',\n );\n return;\n }\n if (!uniqueName || !fileToLoad || !componentName) {\n console.error(\n 'Invalid format of \"name\"! Please define \"name\" as \"ConfigCustomBackItUpSet/Components/AdapterExist\" in the schema',\n );\n return;\n }\n let setPromise: Promise<{ default: Record<string, React.FC<ConfigGenericProps>> } | null> | undefined =\n ConfigCustom.runningLoads[`${url}!${fileToLoad}`];\n\n if (!(setPromise instanceof Promise)) {\n let i18nPromise: Promise<void> | undefined;\n if (this.props.schema.i18n === true) {\n // load i18n from files\n const pos = url.lastIndexOf('/');\n let i18nURL: string;\n if (pos !== -1) {\n i18nURL = url.substring(0, pos);\n } else {\n i18nURL = url;\n }\n const lang = I18n.getLanguage();\n const file = `${i18nURL}/i18n/${lang}.json`;\n\n i18nPromise = fetch(file)\n .then(data => data.json())\n .then(json => I18n.extendTranslations(json, lang))\n .catch(error => {\n if (lang !== 'en') {\n // try to load English\n fetch(`${i18nURL}/i18n/en.json`)\n .then(data => data.json())\n .then(json => I18n.extendTranslations(json, lang))\n .catch(err => console.log(`Cannot load i18n \"${file}\": ${err}`));\n return;\n }\n console.log(`Cannot load i18n \"${file}\": ${error}`);\n });\n } else if (this.props.schema.i18n && typeof this.props.schema.i18n === 'object') {\n try {\n I18n.extendTranslations(this.props.schema.i18n);\n } catch (error) {\n console.error(`Cannot import i18n: ${error}`);\n }\n }\n try {\n console.log(url, uniqueName, fileToLoad, componentName);\n\n registerRemotes(\n [\n {\n name: uniqueName,\n entry: url,\n type: this.props.schema.bundlerType || undefined,\n },\n ],\n // force: true // may be needed to side-load remotes after the fact.\n );\n setPromise = loadRemote(`${uniqueName}/${fileToLoad}`);\n if (i18nPromise instanceof Promise) {\n setPromise = Promise.all([setPromise, i18nPromise]).then(result => result[0]);\n }\n // remember promise\n ConfigCustom.runningLoads[`${url}!${fileToLoad}`] = setPromise;\n } catch (error) {\n console.error(error);\n this.setState({ error: `Cannot import from ${this.props.schema.url}: ${error}` });\n }\n }\n try {\n const component: Record<string, React.FC<ConfigGenericProps>> | undefined = (await setPromise)?.default;\n\n if (!component?.[componentName]) {\n const keys = Object.keys(component || {});\n console.error('URL is empty. Cannot load custom component!');\n this.setState({\n error: `Component ${this.props.schema.name} not found in ${this.props.schema.url}. Found: ${keys.join(', ')}`,\n });\n } else {\n this.setState({ Component: component[componentName] });\n }\n } catch (error) {\n console.error(error);\n this.setState({ error: `Cannot import from ${this.props.schema.url}: ${error}` });\n }\n }\n\n render(): JSX.Element {\n const CustomComponent: React.FC<ConfigGenericProps> | null = this.state.Component;\n const schema = this.props.schema || ({} as ConfigItemCustom);\n\n const item = CustomComponent ? (\n <CustomComponent\n {...this.props}\n // @ts-expect-error BF (2024-12-18) Remove after the 7.4 will be mainstream. All following lines\n socket={this.props.oContext.socket}\n theme={this.props.oContext.theme}\n themeType={this.props.oContext.themeType}\n instance={this.props.oContext.instance}\n adapterName={this.props.oContext.adapterName}\n systemConfig={this.props.oContext.systemConfig}\n forceUpdate={this.props.oContext.forceUpdate}\n />\n ) : this.state.error ? (\n <div>{this.state.error}</div>\n ) : (\n <LinearProgress />\n );\n\n if (schema.newLine) {\n return (\n <>\n <div style={{ flexBasis: '100%', height: 0 }} />\n {item}\n </>\n );\n }\n\n return item;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ConfigCustom.js","sourceRoot":"src/","sources":["JsonConfigComponent/ConfigCustom.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { type JSX } from 'react';\nimport { LinearProgress } from '@mui/material';\nimport { registerRemotes, loadRemote, init } from '@module-federation/runtime';\n\nimport * as IconsMaterial from '@mui/icons-material';\n\nimport * as AdapterReact from '@iobroker/gui-components';\nimport { I18n } from '@iobroker/gui-components';\n\nimport ConfigGeneric, { type ConfigGenericProps, type ConfigGenericState } from './ConfigGeneric';\nimport ConfigCustomErrorBoundary from './ConfigCustomErrorBoundary';\nimport * as JsonConfig from '../';\nimport type { ConfigItemCustom } from '../types';\n\ninterface ConfigCustomProps extends ConfigGenericProps {\n schema: ConfigItemCustom;\n}\n\ninterface ConfigCustomState extends ConfigGenericState {\n Component: React.FC<ConfigGenericProps> | null;\n error: string;\n}\n\ninit({\n name: 'iobroker_admin',\n shared: {\n '@iobroker/gui-components': {\n lib: () => AdapterReact,\n version: '*',\n },\n '@mui/icons-material': {\n lib: () => IconsMaterial,\n version: '*',\n },\n '@iobroker/json-config': {\n lib: () => JsonConfig,\n version: '*',\n },\n },\n remotes: [],\n});\n\nexport default class ConfigCustom extends ConfigGeneric<ConfigCustomProps, ConfigCustomState> {\n static runningLoads: Record<string, Promise<{ default: Record<string, React.FC<ConfigGenericProps>> } | null>> = {};\n\n constructor(props: ConfigCustomProps) {\n super(props);\n // schema.url - location of Widget\n // schema.name - Component name\n // schema.i18n - i18n\n\n Object.assign(this.state, {\n Component: null,\n error: '',\n });\n }\n\n // load component dynamically\n async componentDidMount(): Promise<void> {\n if (!this.props.schema.url) {\n console.error('URL is empty. Cannot load custom component!');\n this.setState({ error: 'URL is empty. Cannot load custom component!' });\n return;\n }\n\n let url;\n if (this.props.schema.url.startsWith('http:') || this.props.schema.url.startsWith('https:')) {\n url = this.props.schema.url;\n } else if (this.props.schema.url.startsWith('./')) {\n url = `${window.location.protocol}//${window.location.host}${this.props.schema.url.replace(/^\\./, '')}`;\n } else {\n url = `${window.location.protocol}//${window.location.host}/adapter/${this.props.oContext.adapterName}/${this.props.schema.url}`;\n }\n const [uniqueName, fileToLoad, ...componentNameParts] = this.props.schema.name.split('/');\n const componentName = componentNameParts.join('/');\n if (!url) {\n console.error(\n 'Cannot find URL for custom component! Please define \"url\" as \"custom/customComponents.js\" in the schema',\n );\n return;\n }\n if (!uniqueName || !fileToLoad || !componentName) {\n console.error(\n 'Invalid format of \"name\"! Please define \"name\" as \"ConfigCustomBackItUpSet/Components/AdapterExist\" in the schema',\n );\n return;\n }\n let setPromise: Promise<{ default: Record<string, React.FC<ConfigGenericProps>> } | null> | undefined =\n ConfigCustom.runningLoads[`${url}!${fileToLoad}`];\n\n if (!(setPromise instanceof Promise)) {\n let i18nPromise: Promise<void> | undefined;\n if (this.props.schema.i18n === true) {\n // load i18n from files\n const pos = url.lastIndexOf('/');\n let i18nURL: string;\n if (pos !== -1) {\n i18nURL = url.substring(0, pos);\n } else {\n i18nURL = url;\n }\n const lang = I18n.getLanguage();\n const file = `${i18nURL}/i18n/${lang}.json`;\n\n i18nPromise = fetch(file)\n .then(data => data.json())\n .then(json => I18n.extendTranslations(json, lang))\n .catch(error => {\n if (lang !== 'en') {\n // try to load English\n fetch(`${i18nURL}/i18n/en.json`)\n .then(data => data.json())\n .then(json => I18n.extendTranslations(json, lang))\n .catch(err => console.log(`Cannot load i18n \"${file}\": ${err}`));\n return;\n }\n console.log(`Cannot load i18n \"${file}\": ${error}`);\n });\n } else if (this.props.schema.i18n && typeof this.props.schema.i18n === 'object') {\n try {\n I18n.extendTranslations(this.props.schema.i18n);\n } catch (error) {\n console.error(`Cannot import i18n: ${error}`);\n }\n }\n try {\n console.log(url, uniqueName, fileToLoad, componentName);\n\n registerRemotes(\n [\n {\n name: uniqueName,\n entry: url,\n // Components of the current GUI API generation are always built as ES\n // modules, so the former `bundlerType` schema attribute is obsolete.\n type: 'module',\n },\n ],\n // force: true // may be needed to side-load remotes after the fact.\n );\n setPromise = loadRemote(`${uniqueName}/${fileToLoad}`);\n if (i18nPromise instanceof Promise) {\n setPromise = Promise.all([setPromise, i18nPromise]).then(result => result[0]);\n }\n // remember promise\n ConfigCustom.runningLoads[`${url}!${fileToLoad}`] = setPromise;\n } catch (error) {\n console.error(error);\n this.setState({ error: `Cannot import from ${this.props.schema.url}: ${error}` });\n }\n }\n try {\n const component: Record<string, React.FC<ConfigGenericProps>> | undefined = (await setPromise)?.default;\n\n if (!component?.[componentName]) {\n const keys = Object.keys(component || {});\n console.error('URL is empty. Cannot load custom component!');\n this.setState({\n error: `Component ${this.props.schema.name} not found in ${this.props.schema.url}. Found: ${keys.join(', ')}`,\n });\n } else {\n this.setState({ Component: component[componentName] });\n }\n } catch (error) {\n console.error(error);\n this.setState({ error: `Cannot import from ${this.props.schema.url}: ${error}` });\n }\n }\n\n render(): JSX.Element {\n const CustomComponent: React.FC<ConfigGenericProps> | null = this.state.Component;\n const schema = this.props.schema || ({} as ConfigItemCustom);\n\n const item = CustomComponent ? (\n // The custom component is third-party code, so a render error must not take down the\n // whole configuration page with it.\n <ConfigCustomErrorBoundary\n name={schema.name}\n url={schema.url}\n >\n <CustomComponent\n {...this.props}\n // @ts-expect-error BF (2024-12-18) Remove after the 7.4 will be mainstream. All following lines\n socket={this.props.oContext.socket}\n theme={this.props.oContext.theme}\n themeType={this.props.oContext.themeType}\n instance={this.props.oContext.instance}\n adapterName={this.props.oContext.adapterName}\n systemConfig={this.props.oContext.systemConfig}\n forceUpdate={this.props.oContext.forceUpdate}\n />\n </ConfigCustomErrorBoundary>\n ) : this.state.error ? (\n <div>{this.state.error}</div>\n ) : (\n <LinearProgress />\n );\n\n if (schema.newLine) {\n return (\n <>\n <div style={{ flexBasis: '100%', height: 0 }} />\n {item}\n </>\n );\n }\n\n return item;\n }\n}\n"]}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React, { type JSX } from 'react';
|
|
2
|
+
interface ConfigCustomErrorBoundaryProps {
|
|
3
|
+
/** Component name as defined in the schema: `<remote>/<file>/<Component>` */
|
|
4
|
+
name: string;
|
|
5
|
+
/** URL the remote was loaded from */
|
|
6
|
+
url?: string;
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
}
|
|
9
|
+
interface ConfigCustomErrorBoundaryState {
|
|
10
|
+
error: Error | null;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Catches render errors of custom components that adapters provide via module federation.
|
|
14
|
+
*
|
|
15
|
+
* A custom component is third-party code built against a specific generation of
|
|
16
|
+
* `@iobroker/gui-components` / `@iobroker/json-config`. One built against an older generation
|
|
17
|
+
* (React 18 / MUI 6) can throw while rendering inside a newer admin, because it calls APIs that
|
|
18
|
+
* no longer exist. Without this boundary React unmounts the whole tree on such a throw, so a
|
|
19
|
+
* single outdated adapter would blank the entire configuration page.
|
|
20
|
+
*
|
|
21
|
+
* Note that error boundaries only catch errors thrown while rendering, in lifecycle methods and
|
|
22
|
+
* in constructors of the subtree below them. Errors from event handlers or async callbacks are
|
|
23
|
+
* not caught here; failures while *loading* a remote are handled in `ConfigCustom`.
|
|
24
|
+
*/
|
|
25
|
+
export default class ConfigCustomErrorBoundary extends React.Component<ConfigCustomErrorBoundaryProps, ConfigCustomErrorBoundaryState> {
|
|
26
|
+
constructor(props: ConfigCustomErrorBoundaryProps);
|
|
27
|
+
static getDerivedStateFromError(error: Error): ConfigCustomErrorBoundaryState;
|
|
28
|
+
componentDidCatch(error: Error, info: React.ErrorInfo): void;
|
|
29
|
+
componentDidUpdate(prevProps: ConfigCustomErrorBoundaryProps): void;
|
|
30
|
+
render(): JSX.Element;
|
|
31
|
+
}
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { InfoBox, I18n } from '@iobroker/gui-components';
|
|
3
|
+
/**
|
|
4
|
+
* Catches render errors of custom components that adapters provide via module federation.
|
|
5
|
+
*
|
|
6
|
+
* A custom component is third-party code built against a specific generation of
|
|
7
|
+
* `@iobroker/gui-components` / `@iobroker/json-config`. One built against an older generation
|
|
8
|
+
* (React 18 / MUI 6) can throw while rendering inside a newer admin, because it calls APIs that
|
|
9
|
+
* no longer exist. Without this boundary React unmounts the whole tree on such a throw, so a
|
|
10
|
+
* single outdated adapter would blank the entire configuration page.
|
|
11
|
+
*
|
|
12
|
+
* Note that error boundaries only catch errors thrown while rendering, in lifecycle methods and
|
|
13
|
+
* in constructors of the subtree below them. Errors from event handlers or async callbacks are
|
|
14
|
+
* not caught here; failures while *loading* a remote are handled in `ConfigCustom`.
|
|
15
|
+
*/
|
|
16
|
+
export default class ConfigCustomErrorBoundary extends React.Component {
|
|
17
|
+
constructor(props) {
|
|
18
|
+
super(props);
|
|
19
|
+
this.state = { error: null };
|
|
20
|
+
}
|
|
21
|
+
static getDerivedStateFromError(error) {
|
|
22
|
+
return { error };
|
|
23
|
+
}
|
|
24
|
+
componentDidCatch(error, info) {
|
|
25
|
+
console.error(`Custom component "${this.props.name}" from "${this.props.url || 'unknown URL'}" crashed while rendering. ` +
|
|
26
|
+
`It was probably built for an older admin version.`, error, info.componentStack);
|
|
27
|
+
}
|
|
28
|
+
componentDidUpdate(prevProps) {
|
|
29
|
+
// A different component deserves a fresh attempt, otherwise it would inherit the error state
|
|
30
|
+
if (this.state.error && (prevProps.name !== this.props.name || prevProps.url !== this.props.url)) {
|
|
31
|
+
this.setState({ error: null });
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
render() {
|
|
35
|
+
if (!this.state.error) {
|
|
36
|
+
return React.createElement(React.Fragment, null, this.props.children);
|
|
37
|
+
}
|
|
38
|
+
return (React.createElement(InfoBox, { type: "error", iconPosition: "top" },
|
|
39
|
+
React.createElement("div", null,
|
|
40
|
+
React.createElement("div", { style: { fontWeight: 'bold' } }, I18n.t('jc_Cannot display the custom component "%s"', this.props.name)),
|
|
41
|
+
React.createElement("div", null, I18n.t('jc_It was probably built for an older admin version. Please update the adapter.')),
|
|
42
|
+
React.createElement("div", { style: { marginTop: 8, fontStyle: 'italic', wordBreak: 'break-word' } }, this.state.error.message || String(this.state.error)))));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=ConfigCustomErrorBoundary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConfigCustomErrorBoundary.js","sourceRoot":"src/","sources":["JsonConfigComponent/ConfigCustomErrorBoundary.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAExC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAczD;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,OAAO,OAAO,yBAA0B,SAAQ,KAAK,CAAC,SAG5D;IACG,YAAY,KAAqC;QAC7C,KAAK,CAAC,KAAK,CAAC,CAAC;QACb,IAAI,CAAC,KAAK,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACjC,CAAC;IAED,MAAM,CAAC,wBAAwB,CAAC,KAAY;QACxC,OAAO,EAAE,KAAK,EAAE,CAAC;IACrB,CAAC;IAED,iBAAiB,CAAC,KAAY,EAAE,IAAqB;QACjD,OAAO,CAAC,KAAK,CACT,qBAAqB,IAAI,CAAC,KAAK,CAAC,IAAI,WAAW,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,aAAa,6BAA6B;YACvG,mDAAmD,EACvD,KAAK,EACL,IAAI,CAAC,cAAc,CACtB,CAAC;IACN,CAAC;IAED,kBAAkB,CAAC,SAAyC;QACxD,6FAA6F;QAC7F,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,SAAS,CAAC,GAAG,KAAK,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/F,IAAI,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACnC,CAAC;IACL,CAAC;IAED,MAAM;QACF,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YACpB,OAAO,0CAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAI,CAAC;QACtC,CAAC;QAED,OAAO,CACH,oBAAC,OAAO,IACJ,IAAI,EAAC,OAAO,EACZ,YAAY,EAAC,KAAK;YAElB;gBACI,6BAAK,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,IAC7B,IAAI,CAAC,CAAC,CAAC,6CAA6C,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CACrE;gBACN,iCACK,IAAI,CAAC,CAAC,CAAC,iFAAiF,CAAC,CACxF;gBACN,6BAAK,KAAK,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,IACrE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CACnD,CACJ,CACA,CACb,CAAC;IACN,CAAC;CACJ","sourcesContent":["import React, { type JSX } from 'react';\n\nimport { InfoBox, I18n } from '@iobroker/gui-components';\n\ninterface ConfigCustomErrorBoundaryProps {\n /** Component name as defined in the schema: `<remote>/<file>/<Component>` */\n name: string;\n /** URL the remote was loaded from */\n url?: string;\n children: React.ReactNode;\n}\n\ninterface ConfigCustomErrorBoundaryState {\n error: Error | null;\n}\n\n/**\n * Catches render errors of custom components that adapters provide via module federation.\n *\n * A custom component is third-party code built against a specific generation of\n * `@iobroker/gui-components` / `@iobroker/json-config`. One built against an older generation\n * (React 18 / MUI 6) can throw while rendering inside a newer admin, because it calls APIs that\n * no longer exist. Without this boundary React unmounts the whole tree on such a throw, so a\n * single outdated adapter would blank the entire configuration page.\n *\n * Note that error boundaries only catch errors thrown while rendering, in lifecycle methods and\n * in constructors of the subtree below them. Errors from event handlers or async callbacks are\n * not caught here; failures while *loading* a remote are handled in `ConfigCustom`.\n */\nexport default class ConfigCustomErrorBoundary extends React.Component<\n ConfigCustomErrorBoundaryProps,\n ConfigCustomErrorBoundaryState\n> {\n constructor(props: ConfigCustomErrorBoundaryProps) {\n super(props);\n this.state = { error: null };\n }\n\n static getDerivedStateFromError(error: Error): ConfigCustomErrorBoundaryState {\n return { error };\n }\n\n componentDidCatch(error: Error, info: React.ErrorInfo): void {\n console.error(\n `Custom component \"${this.props.name}\" from \"${this.props.url || 'unknown URL'}\" crashed while rendering. ` +\n `It was probably built for an older admin version.`,\n error,\n info.componentStack,\n );\n }\n\n componentDidUpdate(prevProps: ConfigCustomErrorBoundaryProps): void {\n // A different component deserves a fresh attempt, otherwise it would inherit the error state\n if (this.state.error && (prevProps.name !== this.props.name || prevProps.url !== this.props.url)) {\n this.setState({ error: null });\n }\n }\n\n render(): JSX.Element {\n if (!this.state.error) {\n return <>{this.props.children}</>;\n }\n\n return (\n <InfoBox\n type=\"error\"\n iconPosition=\"top\"\n >\n <div>\n <div style={{ fontWeight: 'bold' }}>\n {I18n.t('jc_Cannot display the custom component \"%s\"', this.props.name)}\n </div>\n <div>\n {I18n.t('jc_It was probably built for an older admin version. Please update the adapter.')}\n </div>\n <div style={{ marginTop: 8, fontStyle: 'italic', wordBreak: 'break-word' }}>\n {this.state.error.message || String(this.state.error)}\n </div>\n </div>\n </InfoBox>\n );\n }\n}\n"]}
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"jc_Cannot create credential: %s": "Anmeldeinformationen konnten nicht erstellt werden: %s",
|
|
16
16
|
"jc_Cannot decode license": "Lizenz kann nicht entschlüsselt werden",
|
|
17
17
|
"jc_Cannot determine position: System settings are empty and GPS detection is disabled in browser": "Position kann nicht bestimmt werden: Die Systemeinstellungen sind leer und die GPS-Erkennung ist im Browser deaktiviert",
|
|
18
|
+
"jc_Cannot display the custom component \"%s\"": "Die benutzerdefinierte Komponente \"%s\" kann nicht angezeigt werden",
|
|
18
19
|
"jc_Cannot read licenses: %s": "Lizenzen können nicht gelesen werden: %s",
|
|
19
20
|
"jc_Cannot retrieve options, as instance is offline": "Optionen können nicht abgerufen werden, da die Instanz offline ist",
|
|
20
21
|
"jc_Cannot save configuration because of error in configuration": "Die Konfiguration konnte aufgrund eines Fehlers nicht gespeichert werden.",
|
|
@@ -63,6 +64,7 @@
|
|
|
63
64
|
"jc_Invalid JSON file.": "Ungültige JSON-Datei.",
|
|
64
65
|
"jc_Invalid JSON format. Expected an array.": "Ungültiges JSON-Format. Array erwartet.",
|
|
65
66
|
"jc_Invalid YAML": "Ungültiges YAML",
|
|
67
|
+
"jc_It was probably built for an older admin version. Please update the adapter.": "Sie wurde vermutlich für eine ältere Admin-Version erstellt. Bitte den Adapter aktualisieren.",
|
|
66
68
|
"jc_JSON editor": "JSON-Editor",
|
|
67
69
|
"jc_Latitude": "Breite",
|
|
68
70
|
"jc_License %s": "Lizenz %s",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"jc_Cannot create credential: %s": "Cannot create credential: %s",
|
|
16
16
|
"jc_Cannot decode license": "Cannot decode license",
|
|
17
17
|
"jc_Cannot determine position: System settings are empty and GPS detection is disabled in browser": "Cannot determine position: System settings are empty and GPS detection is disabled in browser",
|
|
18
|
+
"jc_Cannot display the custom component \"%s\"": "Cannot display the custom component \"%s\"",
|
|
18
19
|
"jc_Cannot read licenses: %s": "Cannot read licenses: %s",
|
|
19
20
|
"jc_Cannot retrieve options, as instance is offline": "Cannot retrieve options, as instance is offline",
|
|
20
21
|
"jc_Cannot save configuration because of error in configuration": "Cannot save configuration because of error in configuration",
|
|
@@ -63,6 +64,7 @@
|
|
|
63
64
|
"jc_Invalid JSON file.": "Invalid JSON file.",
|
|
64
65
|
"jc_Invalid JSON format. Expected an array.": "Invalid JSON format. Expected an array.",
|
|
65
66
|
"jc_Invalid YAML": "Invalid YAML",
|
|
67
|
+
"jc_It was probably built for an older admin version. Please update the adapter.": "It was probably built for an older admin version. Please update the adapter.",
|
|
66
68
|
"jc_JSON editor": "JSON editor",
|
|
67
69
|
"jc_Latitude": "Latitude",
|
|
68
70
|
"jc_License %s": "License %s",
|
package/build/index.d.ts
CHANGED
|
@@ -4,4 +4,15 @@ import ConfigPanel from './JsonConfigComponent/ConfigPanel';
|
|
|
4
4
|
import ConfigGeneric from './JsonConfigComponent/ConfigGeneric';
|
|
5
5
|
export type { DeviceManagerPropsProps, ConfigGenericProps, ConfigGenericState, } from './JsonConfigComponent/ConfigGeneric';
|
|
6
6
|
export type { ConfigItemType, ConfigItemConfirmData, ConfigItem, ConfigItemAlive, ConfigItemSelectOption, ConfigItemPanel, ConfigItemPattern, ConfigItemChip, ConfigItemComponent, ConfigItemTabs, ConfigItemText, ConfigItemColor, ConfigItemCheckbox, ConfigItemNumber, ConfigItemQrCode, ConfigItemQrCodeSendTo, ConfigItemPassword, ConfigItemObjectId, ConfigItemSlider, ConfigItemTopic, ConfigItemIP, ConfigItemUser, ConfigItemStaticDivider, ConfigItemStaticHeader, ConfigItemStaticImage, ConfigItemStaticText, ConfigItemRoom, ConfigItemFunc, ConfigItemSelect, ConfigItemAutocomplete, ConfigItemSetState, ConfigItemAutocompleteSendTo, ConfigItemAccordion, ConfigItemDivider, ConfigItemHeader, ConfigItemCoordinates, ConfigItemCustom, ConfigItemDatePicker, ConfigItemDeviceManager, ConfigItemLanguage, ConfigItemPort, ConfigItemImageSendTo, ConfigItemSendTo, ConfigItemState, ConfigItemTextSendTo, ConfigItemSelectSendTo, ConfigItemTable, ConfigItemTimePicker, ConfigItemCertCollection, ConfigItemCRON, ConfigItemCertificateSelect, ConfigItemCredentialSelect, ConfigItemLicense, ConfigItemCertificates, ConfigItemCheckLicense, ConfigItemUUID, ConfigItemJsonEditor, ConfigItemYamlEditor, ConfigItemInterface, ConfigItemImageUpload, ConfigItemInstanceSelect, ConfigItemFile, ConfigItemFileSelector, ConfigItemAny, BackEndCommandType, BackEndCommandGeneric, BackEndCommandNoOperation, BackEndCommandRefresh, BackEndCommandOpenLink, BackEndCommandMessage, BackEndCommand, } from './types';
|
|
7
|
+
/**
|
|
8
|
+
* Generation of the GUI API this build of `@iobroker/json-config` provides.
|
|
9
|
+
*
|
|
10
|
+
* A custom component declares the generation it was built against via `guiApi` in its jsonConfig
|
|
11
|
+
* schema. Generation `2` is `@iobroker/gui-components` (React 19 / MUI 9); everything below was
|
|
12
|
+
* built against the legacy `@iobroker/adapter-react-v5` (React 18 / MUI 6) and cannot run here,
|
|
13
|
+
* because the shared React/MUI singletons it expects are no longer provided.
|
|
14
|
+
*
|
|
15
|
+
* Bump this only when a change actually breaks components built against the previous generation.
|
|
16
|
+
*/
|
|
17
|
+
export declare const GUI_API_GENERATION = 2;
|
|
7
18
|
export { JsonConfig, JsonConfigComponent, ConfigPanel, ConfigGeneric };
|
package/build/index.js
CHANGED
|
@@ -2,5 +2,16 @@ import JsonConfig from './JsonConfig';
|
|
|
2
2
|
import JsonConfigComponent from './JsonConfigComponent';
|
|
3
3
|
import ConfigPanel from './JsonConfigComponent/ConfigPanel';
|
|
4
4
|
import ConfigGeneric from './JsonConfigComponent/ConfigGeneric';
|
|
5
|
+
/**
|
|
6
|
+
* Generation of the GUI API this build of `@iobroker/json-config` provides.
|
|
7
|
+
*
|
|
8
|
+
* A custom component declares the generation it was built against via `guiApi` in its jsonConfig
|
|
9
|
+
* schema. Generation `2` is `@iobroker/gui-components` (React 19 / MUI 9); everything below was
|
|
10
|
+
* built against the legacy `@iobroker/adapter-react-v5` (React 18 / MUI 6) and cannot run here,
|
|
11
|
+
* because the shared React/MUI singletons it expects are no longer provided.
|
|
12
|
+
*
|
|
13
|
+
* Bump this only when a change actually breaks components built against the previous generation.
|
|
14
|
+
*/
|
|
15
|
+
export const GUI_API_GENERATION = 2;
|
|
5
16
|
export { JsonConfig, JsonConfigComponent, ConfigPanel, ConfigGeneric };
|
|
6
17
|
//# sourceMappingURL=index.js.map
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"src/","sources":["index.tsx"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,cAAc,CAAC;AACtC,OAAO,mBAAmB,MAAM,uBAAuB,CAAC;AACxD,OAAO,WAAW,MAAM,mCAAmC,CAAC;AAC5D,OAAO,aAAa,MAAM,qCAAqC,CAAC;AAkFhE,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC","sourcesContent":["import JsonConfig from './JsonConfig';\nimport JsonConfigComponent from './JsonConfigComponent';\nimport ConfigPanel from './JsonConfigComponent/ConfigPanel';\nimport ConfigGeneric from './JsonConfigComponent/ConfigGeneric';\n\nexport type {\n DeviceManagerPropsProps,\n ConfigGenericProps,\n ConfigGenericState,\n} from './JsonConfigComponent/ConfigGeneric';\n\nexport type {\n ConfigItemType,\n ConfigItemConfirmData,\n ConfigItem,\n ConfigItemAlive,\n ConfigItemSelectOption,\n ConfigItemPanel,\n ConfigItemPattern,\n ConfigItemChip,\n ConfigItemComponent,\n ConfigItemTabs,\n ConfigItemText,\n ConfigItemColor,\n ConfigItemCheckbox,\n ConfigItemNumber,\n ConfigItemQrCode,\n ConfigItemQrCodeSendTo,\n ConfigItemPassword,\n ConfigItemObjectId,\n ConfigItemSlider,\n ConfigItemTopic,\n ConfigItemIP,\n ConfigItemUser,\n ConfigItemStaticDivider,\n ConfigItemStaticHeader,\n ConfigItemStaticImage,\n ConfigItemStaticText,\n ConfigItemRoom,\n ConfigItemFunc,\n ConfigItemSelect,\n ConfigItemAutocomplete,\n ConfigItemSetState,\n ConfigItemAutocompleteSendTo,\n ConfigItemAccordion,\n ConfigItemDivider,\n ConfigItemHeader,\n ConfigItemCoordinates,\n ConfigItemCustom,\n ConfigItemDatePicker,\n ConfigItemDeviceManager,\n ConfigItemLanguage,\n ConfigItemPort,\n ConfigItemImageSendTo,\n ConfigItemSendTo,\n ConfigItemState,\n ConfigItemTextSendTo,\n ConfigItemSelectSendTo,\n ConfigItemTable,\n ConfigItemTimePicker,\n ConfigItemCertCollection,\n ConfigItemCRON,\n ConfigItemCertificateSelect,\n ConfigItemCredentialSelect,\n ConfigItemLicense,\n ConfigItemCertificates,\n ConfigItemCheckLicense,\n ConfigItemUUID,\n ConfigItemJsonEditor,\n ConfigItemYamlEditor,\n ConfigItemInterface,\n ConfigItemImageUpload,\n ConfigItemInstanceSelect,\n ConfigItemFile,\n ConfigItemFileSelector,\n ConfigItemAny,\n BackEndCommandType,\n BackEndCommandGeneric,\n BackEndCommandNoOperation,\n BackEndCommandRefresh,\n BackEndCommandOpenLink,\n BackEndCommandMessage,\n BackEndCommand,\n} from './types';\n\nexport { JsonConfig, JsonConfigComponent, ConfigPanel, ConfigGeneric };\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"src/","sources":["index.tsx"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,cAAc,CAAC;AACtC,OAAO,mBAAmB,MAAM,uBAAuB,CAAC;AACxD,OAAO,WAAW,MAAM,mCAAmC,CAAC;AAC5D,OAAO,aAAa,MAAM,qCAAqC,CAAC;AAkFhE;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAEpC,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC","sourcesContent":["import JsonConfig from './JsonConfig';\nimport JsonConfigComponent from './JsonConfigComponent';\nimport ConfigPanel from './JsonConfigComponent/ConfigPanel';\nimport ConfigGeneric from './JsonConfigComponent/ConfigGeneric';\n\nexport type {\n DeviceManagerPropsProps,\n ConfigGenericProps,\n ConfigGenericState,\n} from './JsonConfigComponent/ConfigGeneric';\n\nexport type {\n ConfigItemType,\n ConfigItemConfirmData,\n ConfigItem,\n ConfigItemAlive,\n ConfigItemSelectOption,\n ConfigItemPanel,\n ConfigItemPattern,\n ConfigItemChip,\n ConfigItemComponent,\n ConfigItemTabs,\n ConfigItemText,\n ConfigItemColor,\n ConfigItemCheckbox,\n ConfigItemNumber,\n ConfigItemQrCode,\n ConfigItemQrCodeSendTo,\n ConfigItemPassword,\n ConfigItemObjectId,\n ConfigItemSlider,\n ConfigItemTopic,\n ConfigItemIP,\n ConfigItemUser,\n ConfigItemStaticDivider,\n ConfigItemStaticHeader,\n ConfigItemStaticImage,\n ConfigItemStaticText,\n ConfigItemRoom,\n ConfigItemFunc,\n ConfigItemSelect,\n ConfigItemAutocomplete,\n ConfigItemSetState,\n ConfigItemAutocompleteSendTo,\n ConfigItemAccordion,\n ConfigItemDivider,\n ConfigItemHeader,\n ConfigItemCoordinates,\n ConfigItemCustom,\n ConfigItemDatePicker,\n ConfigItemDeviceManager,\n ConfigItemLanguage,\n ConfigItemPort,\n ConfigItemImageSendTo,\n ConfigItemSendTo,\n ConfigItemState,\n ConfigItemTextSendTo,\n ConfigItemSelectSendTo,\n ConfigItemTable,\n ConfigItemTimePicker,\n ConfigItemCertCollection,\n ConfigItemCRON,\n ConfigItemCertificateSelect,\n ConfigItemCredentialSelect,\n ConfigItemLicense,\n ConfigItemCertificates,\n ConfigItemCheckLicense,\n ConfigItemUUID,\n ConfigItemJsonEditor,\n ConfigItemYamlEditor,\n ConfigItemInterface,\n ConfigItemImageUpload,\n ConfigItemInstanceSelect,\n ConfigItemFile,\n ConfigItemFileSelector,\n ConfigItemAny,\n BackEndCommandType,\n BackEndCommandGeneric,\n BackEndCommandNoOperation,\n BackEndCommandRefresh,\n BackEndCommandOpenLink,\n BackEndCommandMessage,\n BackEndCommand,\n} from './types';\n\n/**\n * Generation of the GUI API this build of `@iobroker/json-config` provides.\n *\n * A custom component declares the generation it was built against via `guiApi` in its jsonConfig\n * schema. Generation `2` is `@iobroker/gui-components` (React 19 / MUI 9); everything below was\n * built against the legacy `@iobroker/adapter-react-v5` (React 18 / MUI 6) and cannot run here,\n * because the shared React/MUI singletons it expects are no longer provided.\n *\n * Bump this only when a change actually breaks components built against the previous generation.\n */\nexport const GUI_API_GENERATION = 2;\n\nexport { JsonConfig, JsonConfigComponent, ConfigPanel, ConfigGeneric };\n"]}
|
package/build/types.d.ts
CHANGED
|
@@ -714,10 +714,22 @@ export interface ConfigItemCustom extends ConfigItem {
|
|
|
714
714
|
type: 'custom';
|
|
715
715
|
/** location of Widget, like "custom/customComponents.js" */
|
|
716
716
|
url: string;
|
|
717
|
-
/**
|
|
717
|
+
/**
|
|
718
|
+
* @deprecated Ignored since GUI API generation 2 - such components are always built as ES
|
|
719
|
+
* modules. Still accepted so existing configurations stay valid, and can be removed.
|
|
720
|
+
*/
|
|
718
721
|
bundlerType?: 'module';
|
|
719
722
|
/** Component name, like "ConfigCustomBackItUpSet/Components/AdapterExist" */
|
|
720
723
|
name: string;
|
|
724
|
+
/**
|
|
725
|
+
* Generation of the GUI API this component was built against.
|
|
726
|
+
*
|
|
727
|
+
* `2` means it uses `@iobroker/gui-components` (React 19 / MUI 9). Omitted or `1` means it was
|
|
728
|
+
* built against the legacy `@iobroker/adapter-react-v5` (React 18 / MUI 6). A component that
|
|
729
|
+
* declares an older generation than the admin provides is not loaded at all, because the shared
|
|
730
|
+
* React/MUI singletons it was built against no longer exist.
|
|
731
|
+
*/
|
|
732
|
+
guiApi?: number;
|
|
721
733
|
/** i18n */
|
|
722
734
|
i18n: boolean | Record<string, string>;
|
|
723
735
|
/** custom properties */
|