@iobroker/json-config 8.5.4 → 8.5.5
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
CHANGED
|
@@ -1822,6 +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
|
+
### 8.5.5 (2026-07-24)
|
|
1826
|
+
- (@GermanBluefox) Trying to improve the behaviour of tabs
|
|
1827
|
+
|
|
1825
1828
|
### 8.5.4 (2026-07-23)
|
|
1826
1829
|
- (@GermanBluefox) Corrected the displaying of zero number values
|
|
1827
1830
|
- (@GermanBluefox) Trying to improve the behaviour of tabs
|
|
@@ -16,6 +16,12 @@ interface ConfigTabsState extends ConfigGenericState {
|
|
|
16
16
|
hidden: boolean;
|
|
17
17
|
disabled: boolean;
|
|
18
18
|
}> | null;
|
|
19
|
+
/**
|
|
20
|
+
* Width (px) reserved on the container while a tab switch is in progress, or undefined when
|
|
21
|
+
* no switch is pending. Prevents the shrink-to-fit dialog from collapsing during the frame
|
|
22
|
+
* where the freshly-mounted panel still renders no content. See pinWidthForTransition().
|
|
23
|
+
*/
|
|
24
|
+
contentMinWidth?: number;
|
|
19
25
|
}
|
|
20
26
|
export default class ConfigTabs extends ConfigGeneric<ConfigTabsProps, ConfigTabsState> {
|
|
21
27
|
/** Below this width the tabs collapse into a burger menu */
|
|
@@ -28,12 +34,23 @@ export default class ConfigTabs extends ConfigGeneric<ConfigTabsProps, ConfigTab
|
|
|
28
34
|
private resizeObserver;
|
|
29
35
|
private resizeRaf;
|
|
30
36
|
private calculateTimeoutTable;
|
|
37
|
+
private pinTimeout;
|
|
31
38
|
private readonly refDiv;
|
|
32
39
|
constructor(props: ConfigTabsProps);
|
|
33
40
|
onTabError: (attr?: string, error?: string) => void;
|
|
34
41
|
hasTabErrors: (tabName: string) => boolean;
|
|
35
42
|
componentDidMount(): Promise<void>;
|
|
36
43
|
componentWillUnmount(): void;
|
|
44
|
+
/**
|
|
45
|
+
* Freeze the current container width for the duration of a tab switch. Switching tabs remounts
|
|
46
|
+
* the panel (key={tab}), and a freshly-mounted ConfigPanel renders `null` for a frame or two
|
|
47
|
+
* while it computes its calculated values. In that gap the widest content is just the tab bar,
|
|
48
|
+
* so the shrink-to-fit dialog collapses and then grows back - the visible width "jump".
|
|
49
|
+
*
|
|
50
|
+
* We capture the width shown by the outgoing tab and apply it as a temporary minWidth floor, then
|
|
51
|
+
* release it shortly after so genuine resizes (window/dialog) keep working normally afterwards.
|
|
52
|
+
*/
|
|
53
|
+
private pinWidthForTransition;
|
|
37
54
|
measureWidth: () => void;
|
|
38
55
|
onHashTabsChanged: () => void;
|
|
39
56
|
onMenuChange(tab: string): void;
|
|
@@ -30,6 +30,7 @@ export default class ConfigTabs extends ConfigGeneric {
|
|
|
30
30
|
resizeObserver = null;
|
|
31
31
|
resizeRaf = null;
|
|
32
32
|
calculateTimeoutTable = null;
|
|
33
|
+
pinTimeout = null;
|
|
33
34
|
refDiv;
|
|
34
35
|
constructor(props) {
|
|
35
36
|
super(props);
|
|
@@ -130,9 +131,38 @@ export default class ConfigTabs extends ConfigGeneric {
|
|
|
130
131
|
clearTimeout(this.calculateTimeoutTable);
|
|
131
132
|
this.calculateTimeoutTable = null;
|
|
132
133
|
}
|
|
134
|
+
if (this.pinTimeout) {
|
|
135
|
+
clearTimeout(this.pinTimeout);
|
|
136
|
+
this.pinTimeout = null;
|
|
137
|
+
}
|
|
133
138
|
window.removeEventListener('hashchange', this.onHashTabsChanged, false);
|
|
134
139
|
super.componentWillUnmount();
|
|
135
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* Freeze the current container width for the duration of a tab switch. Switching tabs remounts
|
|
143
|
+
* the panel (key={tab}), and a freshly-mounted ConfigPanel renders `null` for a frame or two
|
|
144
|
+
* while it computes its calculated values. In that gap the widest content is just the tab bar,
|
|
145
|
+
* so the shrink-to-fit dialog collapses and then grows back - the visible width "jump".
|
|
146
|
+
*
|
|
147
|
+
* We capture the width shown by the outgoing tab and apply it as a temporary minWidth floor, then
|
|
148
|
+
* release it shortly after so genuine resizes (window/dialog) keep working normally afterwards.
|
|
149
|
+
*/
|
|
150
|
+
pinWidthForTransition() {
|
|
151
|
+
const width = this.refDiv.current?.clientWidth;
|
|
152
|
+
if (!width) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
if (this.pinTimeout) {
|
|
156
|
+
clearTimeout(this.pinTimeout);
|
|
157
|
+
}
|
|
158
|
+
if (this.state.contentMinWidth !== width) {
|
|
159
|
+
this.setState({ contentMinWidth: width });
|
|
160
|
+
}
|
|
161
|
+
this.pinTimeout = setTimeout(() => {
|
|
162
|
+
this.pinTimeout = null;
|
|
163
|
+
this.setState({ contentMinWidth: undefined });
|
|
164
|
+
}, 500);
|
|
165
|
+
}
|
|
136
166
|
measureWidth = () => {
|
|
137
167
|
const width = this.refDiv.current?.clientWidth;
|
|
138
168
|
if (!width) {
|
|
@@ -170,12 +200,14 @@ export default class ConfigTabs extends ConfigGeneric {
|
|
|
170
200
|
}
|
|
171
201
|
if (tab !== undefined && tab !== this.state.tab) {
|
|
172
202
|
(window._localStorage || window.localStorage).setItem(`${this.props.dialogName || 'App'}.${this.props.oContext.adapterName}`, tab);
|
|
203
|
+
this.pinWidthForTransition();
|
|
173
204
|
this.setState({ tab });
|
|
174
205
|
}
|
|
175
206
|
}
|
|
176
207
|
};
|
|
177
208
|
onMenuChange(tab) {
|
|
178
209
|
(window._localStorage || window.localStorage).setItem(`${this.props.dialogName || 'App'}.${this.props.oContext.adapterName}`, tab);
|
|
210
|
+
this.pinWidthForTransition();
|
|
179
211
|
this.setState({ tab }, () => {
|
|
180
212
|
if (this.props.root) {
|
|
181
213
|
const hash = (window.location.hash || '').split('/');
|
|
@@ -279,7 +311,9 @@ export default class ConfigTabs extends ConfigGeneric {
|
|
|
279
311
|
if (!this.state.tab) {
|
|
280
312
|
return null;
|
|
281
313
|
}
|
|
282
|
-
return (React.createElement("div", { style:
|
|
314
|
+
return (React.createElement("div", { style: this.state.contentMinWidth !== undefined
|
|
315
|
+
? { ...styles.tabs, minWidth: this.state.contentMinWidth }
|
|
316
|
+
: styles.tabs, ref: this.refDiv },
|
|
283
317
|
tabs,
|
|
284
318
|
React.createElement(ConfigPanel, { oContext: this.props.oContext, withoutSaveButtons: this.props.withoutSaveButtons, isParentTab: true, changed: this.props.changed, key: this.state.tab, expertMode: this.props.expertMode, index: 1001, arrayIndex: this.props.arrayIndex, globalData: this.props.globalData, commandRunning: this.props.commandRunning, style: {
|
|
285
319
|
...styles.panel,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConfigTabs.js","sourceRoot":"./src/","sources":["JsonConfigComponent/ConfigTabs.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { type JSX } from 'react';\n\nimport { Tabs, Tab, IconButton, Toolbar, Menu, MenuItem, ListItemIcon, Box } from '@mui/material';\nimport { Menu as MenuIcon, Error as ErrorIcon } from '@mui/icons-material';\n\nimport type { ConfigItemTabs } from '../types';\nimport ConfigGeneric, { type ConfigGenericProps, type ConfigGenericState } from './ConfigGeneric';\nimport ConfigPanel from './ConfigPanel';\n\nconst styles: Record<string, React.CSSProperties> = {\n tabs: {\n height: '100%',\n width: '100%',\n },\n panel: {\n width: '100%',\n display: 'block',\n },\n panelWithIcons: {\n height: 'calc(100% - 72px)',\n },\n panelWithoutIcons: {\n height: 'calc(100% - 48px)',\n },\n};\n\ninterface ConfigTabsProps extends ConfigGenericProps {\n schema: ConfigItemTabs;\n dialogName?: string;\n withoutSaveButtons?: boolean;\n}\n\ninterface ConfigTabsState extends ConfigGenericState {\n tab?: string;\n /** Show the burger menu instead of the tab bar (true only for very narrow widths). Decided with hysteresis. */\n useMenu: boolean;\n openMenu: HTMLButtonElement | null;\n tabErrors: Record<string, Record<string, string>>; // tab -> attr -> error\n calculatedValuesTable: Record<string, { hidden: boolean; disabled: boolean }> | null;\n}\n\nexport default class ConfigTabs extends ConfigGeneric<ConfigTabsProps, ConfigTabsState> {\n /** Below this width the tabs collapse into a burger menu */\n private static readonly MENU_WIDTH = 600;\n /**\n * Dead-band around MENU_WIDTH. A scrollbar appearing/disappearing on a tab change shifts\n * clientWidth by ~15px; without this dead-band that would toggle bar<->menu and flicker.\n */\n private static readonly MENU_HYSTERESIS = 40;\n\n private resizeObserver: ResizeObserver | null = null;\n private resizeRaf: number | null = null;\n private calculateTimeoutTable: ReturnType<typeof setTimeout> | null = null;\n\n private readonly refDiv: React.RefObject<HTMLDivElement>;\n\n constructor(props: ConfigTabsProps) {\n super(props);\n let tab: string | undefined;\n\n if (this.props.root) {\n // read the path from hash\n // #tab-instances/config/system.adapter.ping.0/<TAB-NAME-OR-INDEX>\n const hash = (window.location.hash || '').replace(/^#/, '').split('/');\n if (hash.length >= 3 && hash[1] === 'config') {\n const tabS = hash[3];\n const tabN = parseInt(tabS, 10);\n if (tabS && tabN.toString() === tabS) {\n if (tabN >= 0 && tabN < Object.keys(this.props.schema.items).length) {\n tab = Object.keys(this.props.schema.items)[tabN];\n }\n } else if (tabS && Object.keys(this.props.schema.items).includes(tabS)) {\n tab = tabS;\n }\n\n // install on hash change handler\n window.addEventListener('hashchange', this.onHashTabsChanged, false);\n }\n }\n\n if (tab === undefined) {\n tab =\n (((window as any)._localStorage as Storage) || window.localStorage).getItem(\n `${this.props.dialogName || 'App'}.${this.props.oContext.adapterName}`,\n ) || Object.keys(this.props.schema.items)[0];\n if (!Object.keys(this.props.schema.items).includes(tab)) {\n tab = Object.keys(this.props.schema.items)[0];\n }\n }\n this.refDiv = React.createRef();\n\n Object.assign(this.state, { tab, useMenu: false, openMenu: null, tabErrors: {} });\n }\n\n onTabError = (attr?: string, error?: string): void => {\n const currentTab = this.state.tab;\n if (!currentTab && attr) {\n // Forward to parent if no current tab\n this.props.onError(attr, error);\n return;\n }\n\n const newTabErrors = { ...this.state.tabErrors };\n\n if (currentTab) {\n newTabErrors[currentTab] ||= {};\n }\n\n if (currentTab && attr) {\n if (!error) {\n delete newTabErrors[currentTab][attr];\n // Clean up empty tab error objects\n if (Object.keys(newTabErrors[currentTab]).length === 0) {\n delete newTabErrors[currentTab];\n }\n } else {\n newTabErrors[currentTab][attr] = error;\n }\n }\n\n this.setState({ tabErrors: newTabErrors });\n\n // Also forward to parent\n this.props.onError(attr, error);\n };\n\n hasTabErrors = (tabName: string): boolean => {\n return !!this.state.tabErrors[tabName] && Object.keys(this.state.tabErrors[tabName]).length > 0;\n };\n\n async componentDidMount(): Promise<void> {\n await super.componentDidMount();\n // Measure the real width synchronously so the first painted frame already\n // uses the correct breakpoint (no visible tabs -> menu switch).\n this.measureWidth();\n // Keep the width up to date on later layout changes (dialog open animation,\n // async detail loading, window/dialog resize) instead of freezing a\n // transient - possibly too narrow - initial measurement.\n if (this.refDiv.current && typeof ResizeObserver !== 'undefined') {\n this.resizeObserver = new ResizeObserver(() => {\n // Coalesce bursts into a single measurement per frame. This also breaks the\n // ResizeObserver feedback loop: switching bar<->menu changes the layout, which\n // would otherwise notify the observer again immediately and cause flickering.\n if (this.resizeRaf !== null) {\n return;\n }\n this.resizeRaf = window.requestAnimationFrame(() => {\n this.resizeRaf = null;\n this.measureWidth();\n });\n });\n this.resizeObserver.observe(this.refDiv.current);\n }\n }\n\n componentWillUnmount(): void {\n if (this.resizeRaf !== null) {\n window.cancelAnimationFrame(this.resizeRaf);\n this.resizeRaf = null;\n }\n if (this.resizeObserver) {\n this.resizeObserver.disconnect();\n this.resizeObserver = null;\n }\n if (this.calculateTimeoutTable) {\n clearTimeout(this.calculateTimeoutTable);\n this.calculateTimeoutTable = null;\n }\n window.removeEventListener('hashchange', this.onHashTabsChanged, false);\n super.componentWillUnmount();\n }\n\n measureWidth = (): void => {\n const width = this.refDiv.current?.clientWidth;\n if (!width) {\n return;\n }\n // Decide with hysteresis whether to collapse the tabs into the burger menu. Switch to the\n // menu once the width drops below MENU_WIDTH, but only switch back to the tab bar once it\n // grows past MENU_WIDTH + MENU_HYSTERESIS. The dead-band in between prevents a scrollbar\n // that appears/disappears on a tab change (shifting the width by ~15px) from toggling the\n // layout back and forth, which is what caused the flickering.\n let useMenu = this.state.useMenu;\n if (!useMenu && width < ConfigTabs.MENU_WIDTH) {\n useMenu = true;\n } else if (useMenu && width > ConfigTabs.MENU_WIDTH + ConfigTabs.MENU_HYSTERESIS) {\n useMenu = false;\n }\n if (useMenu !== this.state.useMenu) {\n this.setState({ useMenu });\n }\n };\n\n onHashTabsChanged = (): void => {\n const hash = (window.location.hash || '').replace(/^#/, '').split('/');\n if (hash.length > 3 && hash[1] === 'config') {\n const tabS = hash[3];\n const tabN = parseInt(tabS, 10);\n let tab;\n if (tabN.toString() === tabS) {\n if (tabN >= 0 && tabN < Object.keys(this.props.schema.items).length) {\n tab = Object.keys(this.props.schema.items)[tabN];\n }\n } else if (Object.keys(this.props.schema.items).includes(tabS)) {\n tab = tabS;\n }\n if (tab !== undefined && tab !== this.state.tab) {\n (((window as any)._localStorage as Storage) || window.localStorage).setItem(\n `${this.props.dialogName || 'App'}.${this.props.oContext.adapterName}`,\n tab,\n );\n this.setState({ tab });\n }\n }\n };\n\n onMenuChange(tab: string): void {\n (((window as any)._localStorage as Storage) || window.localStorage).setItem(\n `${this.props.dialogName || 'App'}.${this.props.oContext.adapterName}`,\n tab,\n );\n this.setState({ tab }, () => {\n if (this.props.root) {\n const hash = (window.location.hash || '').split('/');\n if (hash.length >= 3 && hash[1] === 'config') {\n hash[3] = this.state.tab || '';\n window.location.hash = hash.join('/');\n }\n }\n });\n }\n\n updateCalculatedValuesForTable(): void {\n if (this.calculateTimeoutTable) {\n clearTimeout(this.calculateTimeoutTable);\n }\n this.calculateTimeoutTable = setTimeout(async (): Promise<void> => {\n this.calculateTimeoutTable = null;\n const items = this.props.schema.items;\n const calculatedValuesTable: Record<string, { hidden: boolean; disabled: boolean }> = {};\n for (const name in items) {\n let disabled: boolean;\n if (items[name].expertMode && !this.props.expertMode) {\n calculatedValuesTable[name] = { hidden: true, disabled: false };\n continue;\n }\n\n if (this.props.custom) {\n const hidden = !!(await this.executeCustom(\n items[name].hidden,\n this.props.data,\n this.props.customObj,\n this.props.oContext.instanceObj,\n this.props.index,\n this.props.globalData,\n ));\n if (hidden) {\n calculatedValuesTable[name] = { hidden: true, disabled: false };\n continue;\n }\n disabled = !!(await this.executeCustom(\n items[name].disabled,\n this.props.data,\n this.props.customObj,\n this.props.oContext.instanceObj,\n this.props.index,\n this.props.globalData,\n ));\n calculatedValuesTable[name] = { hidden, disabled };\n } else {\n const hidden = !!(await this.execute(\n items[name].hidden,\n false,\n this.props.data,\n this.props.index,\n this.props.globalData,\n ));\n if (hidden) {\n calculatedValuesTable[name] = { hidden: true, disabled: false };\n continue;\n }\n disabled = !!(await this.execute(\n items[name].disabled,\n false,\n this.props.data,\n this.props.index,\n this.props.globalData,\n ));\n calculatedValuesTable[name] = { hidden: false, disabled };\n }\n }\n\n if (JSON.stringify(calculatedValuesTable) !== JSON.stringify(this.state.calculatedValuesTable)) {\n this.setState({ calculatedValuesTable });\n }\n }, 50);\n }\n\n render(): JSX.Element | null {\n const items = this.props.schema.items;\n let withIcons = false;\n\n this.updateCalculatedValuesForTable();\n if (!this.state.calculatedValuesTable) {\n return null;\n }\n const elements: { icon: React.JSX.Element | null; label: string; name: string; disabled: boolean }[] = [];\n\n Object.keys(items)\n .filter(name => !this.state.calculatedValuesTable?.[name]?.hidden)\n .map(name => {\n const icon = this.getIcon(items[name].icon);\n withIcons ||= !!icon;\n elements.push({\n icon,\n disabled: !!this.state.calculatedValuesTable?.[name]?.disabled,\n label: this.getText(items[name].label),\n name,\n });\n });\n\n if (!elements.find(item => item.name === this.state.tab)) {\n // Select the first tab if the current tab is not available\n setTimeout(() => this.setState({ tab: elements[0].name }), 50);\n }\n\n let tabs: React.JSX.Element;\n if (this.state.useMenu && elements.length > 2) {\n tabs = (\n <Toolbar\n style={{\n top: 2,\n backgroundColor: this.props.oContext.themeType === 'dark' ? '#222' : '#DDD',\n }}\n variant=\"dense\"\n >\n <IconButton\n onClick={(event: React.MouseEvent<HTMLButtonElement>) =>\n this.setState({ openMenu: event.currentTarget })\n }\n >\n <MenuIcon />\n </IconButton>\n {this.state.openMenu ? (\n <Menu\n open={!0}\n anchorEl={this.state.openMenu}\n onClose={() => this.setState({ openMenu: null })}\n >\n {elements.map(el => {\n const hasErrors = this.hasTabErrors(el.name);\n return (\n <MenuItem\n disabled={el.disabled}\n key={el.name}\n onClick={() => {\n this.setState({ openMenu: null }, () => this.onMenuChange(el.name));\n }}\n selected={el.name === this.state.tab}\n sx={hasErrors ? { color: 'error.main' } : undefined}\n >\n {withIcons ? <ListItemIcon>{el.icon}</ListItemIcon> : null}\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5, width: '100%' }}>\n {el.label}\n {hasErrors && <ErrorIcon sx={{ fontSize: 16, color: 'error.main' }} />}\n </Box>\n </MenuItem>\n );\n })}\n </Menu>\n ) : null}\n </Toolbar>\n );\n } else {\n tabs = (\n <Tabs\n variant=\"scrollable\"\n scrollButtons=\"auto\"\n style={this.props.schema.tabsStyle}\n value={this.state.tab}\n onChange={(_e, tab: string): void => this.onMenuChange(tab)}\n >\n {elements.map(el => {\n const hasErrors = this.hasTabErrors(el.name);\n const label = hasErrors ? (\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>\n {el.label}\n <ErrorIcon sx={{ fontSize: 16, color: 'error.main' }} />\n </Box>\n ) : (\n el.label\n );\n\n return (\n <Tab\n id={el.name}\n wrapped\n disabled={el.disabled}\n key={el.name}\n value={el.name}\n iconPosition={this.props.schema.iconPosition || 'start'}\n icon={el.icon || undefined}\n label={label}\n sx={hasErrors ? { '& .MuiTab-wrapper': { color: 'error.main' } } : undefined}\n />\n );\n })}\n </Tabs>\n );\n }\n if (!this.state.tab) {\n return null;\n }\n return (\n <div\n style={styles.tabs}\n ref={this.refDiv}\n >\n {tabs}\n <ConfigPanel\n oContext={this.props.oContext}\n withoutSaveButtons={this.props.withoutSaveButtons}\n isParentTab\n changed={this.props.changed}\n key={this.state.tab}\n expertMode={this.props.expertMode}\n index={1001}\n arrayIndex={this.props.arrayIndex}\n globalData={this.props.globalData}\n commandRunning={this.props.commandRunning}\n style={{\n ...styles.panel,\n ...(withIcons ? styles.panelWithIcons : styles.panelWithoutIcons),\n }}\n common={this.props.common}\n alive={this.props.alive}\n themeName={this.props.themeName}\n data={this.props.data}\n originalData={this.props.originalData}\n onChange={this.props.onChange}\n onError={this.onTabError}\n customObj={this.props.customObj}\n custom={this.props.custom}\n schema={items[this.state.tab]}\n table={this.props.table}\n withIcons={withIcons}\n customComponents={this.props.customComponents}\n />\n </div>\n );\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ConfigTabs.js","sourceRoot":"./src/","sources":["JsonConfigComponent/ConfigTabs.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { type JSX } from 'react';\n\nimport { Tabs, Tab, IconButton, Toolbar, Menu, MenuItem, ListItemIcon, Box } from '@mui/material';\nimport { Menu as MenuIcon, Error as ErrorIcon } from '@mui/icons-material';\n\nimport type { ConfigItemTabs } from '../types';\nimport ConfigGeneric, { type ConfigGenericProps, type ConfigGenericState } from './ConfigGeneric';\nimport ConfigPanel from './ConfigPanel';\n\nconst styles: Record<string, React.CSSProperties> = {\n tabs: {\n height: '100%',\n width: '100%',\n },\n panel: {\n width: '100%',\n display: 'block',\n },\n panelWithIcons: {\n height: 'calc(100% - 72px)',\n },\n panelWithoutIcons: {\n height: 'calc(100% - 48px)',\n },\n};\n\ninterface ConfigTabsProps extends ConfigGenericProps {\n schema: ConfigItemTabs;\n dialogName?: string;\n withoutSaveButtons?: boolean;\n}\n\ninterface ConfigTabsState extends ConfigGenericState {\n tab?: string;\n /** Show the burger menu instead of the tab bar (true only for very narrow widths). Decided with hysteresis. */\n useMenu: boolean;\n openMenu: HTMLButtonElement | null;\n tabErrors: Record<string, Record<string, string>>; // tab -> attr -> error\n calculatedValuesTable: Record<string, { hidden: boolean; disabled: boolean }> | null;\n /**\n * Width (px) reserved on the container while a tab switch is in progress, or undefined when\n * no switch is pending. Prevents the shrink-to-fit dialog from collapsing during the frame\n * where the freshly-mounted panel still renders no content. See pinWidthForTransition().\n */\n contentMinWidth?: number;\n}\n\nexport default class ConfigTabs extends ConfigGeneric<ConfigTabsProps, ConfigTabsState> {\n /** Below this width the tabs collapse into a burger menu */\n private static readonly MENU_WIDTH = 600;\n /**\n * Dead-band around MENU_WIDTH. A scrollbar appearing/disappearing on a tab change shifts\n * clientWidth by ~15px; without this dead-band that would toggle bar<->menu and flicker.\n */\n private static readonly MENU_HYSTERESIS = 40;\n\n private resizeObserver: ResizeObserver | null = null;\n private resizeRaf: number | null = null;\n private calculateTimeoutTable: ReturnType<typeof setTimeout> | null = null;\n private pinTimeout: ReturnType<typeof setTimeout> | null = null;\n\n private readonly refDiv: React.RefObject<HTMLDivElement>;\n\n constructor(props: ConfigTabsProps) {\n super(props);\n let tab: string | undefined;\n\n if (this.props.root) {\n // read the path from hash\n // #tab-instances/config/system.adapter.ping.0/<TAB-NAME-OR-INDEX>\n const hash = (window.location.hash || '').replace(/^#/, '').split('/');\n if (hash.length >= 3 && hash[1] === 'config') {\n const tabS = hash[3];\n const tabN = parseInt(tabS, 10);\n if (tabS && tabN.toString() === tabS) {\n if (tabN >= 0 && tabN < Object.keys(this.props.schema.items).length) {\n tab = Object.keys(this.props.schema.items)[tabN];\n }\n } else if (tabS && Object.keys(this.props.schema.items).includes(tabS)) {\n tab = tabS;\n }\n\n // install on hash change handler\n window.addEventListener('hashchange', this.onHashTabsChanged, false);\n }\n }\n\n if (tab === undefined) {\n tab =\n (((window as any)._localStorage as Storage) || window.localStorage).getItem(\n `${this.props.dialogName || 'App'}.${this.props.oContext.adapterName}`,\n ) || Object.keys(this.props.schema.items)[0];\n if (!Object.keys(this.props.schema.items).includes(tab)) {\n tab = Object.keys(this.props.schema.items)[0];\n }\n }\n this.refDiv = React.createRef();\n\n Object.assign(this.state, { tab, useMenu: false, openMenu: null, tabErrors: {} });\n }\n\n onTabError = (attr?: string, error?: string): void => {\n const currentTab = this.state.tab;\n if (!currentTab && attr) {\n // Forward to parent if no current tab\n this.props.onError(attr, error);\n return;\n }\n\n const newTabErrors = { ...this.state.tabErrors };\n\n if (currentTab) {\n newTabErrors[currentTab] ||= {};\n }\n\n if (currentTab && attr) {\n if (!error) {\n delete newTabErrors[currentTab][attr];\n // Clean up empty tab error objects\n if (Object.keys(newTabErrors[currentTab]).length === 0) {\n delete newTabErrors[currentTab];\n }\n } else {\n newTabErrors[currentTab][attr] = error;\n }\n }\n\n this.setState({ tabErrors: newTabErrors });\n\n // Also forward to parent\n this.props.onError(attr, error);\n };\n\n hasTabErrors = (tabName: string): boolean => {\n return !!this.state.tabErrors[tabName] && Object.keys(this.state.tabErrors[tabName]).length > 0;\n };\n\n async componentDidMount(): Promise<void> {\n await super.componentDidMount();\n // Measure the real width synchronously so the first painted frame already\n // uses the correct breakpoint (no visible tabs -> menu switch).\n this.measureWidth();\n // Keep the width up to date on later layout changes (dialog open animation,\n // async detail loading, window/dialog resize) instead of freezing a\n // transient - possibly too narrow - initial measurement.\n if (this.refDiv.current && typeof ResizeObserver !== 'undefined') {\n this.resizeObserver = new ResizeObserver(() => {\n // Coalesce bursts into a single measurement per frame. This also breaks the\n // ResizeObserver feedback loop: switching bar<->menu changes the layout, which\n // would otherwise notify the observer again immediately and cause flickering.\n if (this.resizeRaf !== null) {\n return;\n }\n this.resizeRaf = window.requestAnimationFrame(() => {\n this.resizeRaf = null;\n this.measureWidth();\n });\n });\n this.resizeObserver.observe(this.refDiv.current);\n }\n }\n\n componentWillUnmount(): void {\n if (this.resizeRaf !== null) {\n window.cancelAnimationFrame(this.resizeRaf);\n this.resizeRaf = null;\n }\n if (this.resizeObserver) {\n this.resizeObserver.disconnect();\n this.resizeObserver = null;\n }\n if (this.calculateTimeoutTable) {\n clearTimeout(this.calculateTimeoutTable);\n this.calculateTimeoutTable = null;\n }\n if (this.pinTimeout) {\n clearTimeout(this.pinTimeout);\n this.pinTimeout = null;\n }\n window.removeEventListener('hashchange', this.onHashTabsChanged, false);\n super.componentWillUnmount();\n }\n\n /**\n * Freeze the current container width for the duration of a tab switch. Switching tabs remounts\n * the panel (key={tab}), and a freshly-mounted ConfigPanel renders `null` for a frame or two\n * while it computes its calculated values. In that gap the widest content is just the tab bar,\n * so the shrink-to-fit dialog collapses and then grows back - the visible width \"jump\".\n *\n * We capture the width shown by the outgoing tab and apply it as a temporary minWidth floor, then\n * release it shortly after so genuine resizes (window/dialog) keep working normally afterwards.\n */\n private pinWidthForTransition(): void {\n const width = this.refDiv.current?.clientWidth;\n if (!width) {\n return;\n }\n if (this.pinTimeout) {\n clearTimeout(this.pinTimeout);\n }\n if (this.state.contentMinWidth !== width) {\n this.setState({ contentMinWidth: width });\n }\n this.pinTimeout = setTimeout(() => {\n this.pinTimeout = null;\n this.setState({ contentMinWidth: undefined });\n }, 500);\n }\n\n measureWidth = (): void => {\n const width = this.refDiv.current?.clientWidth;\n if (!width) {\n return;\n }\n // Decide with hysteresis whether to collapse the tabs into the burger menu. Switch to the\n // menu once the width drops below MENU_WIDTH, but only switch back to the tab bar once it\n // grows past MENU_WIDTH + MENU_HYSTERESIS. The dead-band in between prevents a scrollbar\n // that appears/disappears on a tab change (shifting the width by ~15px) from toggling the\n // layout back and forth, which is what caused the flickering.\n let useMenu = this.state.useMenu;\n if (!useMenu && width < ConfigTabs.MENU_WIDTH) {\n useMenu = true;\n } else if (useMenu && width > ConfigTabs.MENU_WIDTH + ConfigTabs.MENU_HYSTERESIS) {\n useMenu = false;\n }\n if (useMenu !== this.state.useMenu) {\n this.setState({ useMenu });\n }\n };\n\n onHashTabsChanged = (): void => {\n const hash = (window.location.hash || '').replace(/^#/, '').split('/');\n if (hash.length > 3 && hash[1] === 'config') {\n const tabS = hash[3];\n const tabN = parseInt(tabS, 10);\n let tab;\n if (tabN.toString() === tabS) {\n if (tabN >= 0 && tabN < Object.keys(this.props.schema.items).length) {\n tab = Object.keys(this.props.schema.items)[tabN];\n }\n } else if (Object.keys(this.props.schema.items).includes(tabS)) {\n tab = tabS;\n }\n if (tab !== undefined && tab !== this.state.tab) {\n (((window as any)._localStorage as Storage) || window.localStorage).setItem(\n `${this.props.dialogName || 'App'}.${this.props.oContext.adapterName}`,\n tab,\n );\n this.pinWidthForTransition();\n this.setState({ tab });\n }\n }\n };\n\n onMenuChange(tab: string): void {\n (((window as any)._localStorage as Storage) || window.localStorage).setItem(\n `${this.props.dialogName || 'App'}.${this.props.oContext.adapterName}`,\n tab,\n );\n this.pinWidthForTransition();\n this.setState({ tab }, () => {\n if (this.props.root) {\n const hash = (window.location.hash || '').split('/');\n if (hash.length >= 3 && hash[1] === 'config') {\n hash[3] = this.state.tab || '';\n window.location.hash = hash.join('/');\n }\n }\n });\n }\n\n updateCalculatedValuesForTable(): void {\n if (this.calculateTimeoutTable) {\n clearTimeout(this.calculateTimeoutTable);\n }\n this.calculateTimeoutTable = setTimeout(async (): Promise<void> => {\n this.calculateTimeoutTable = null;\n const items = this.props.schema.items;\n const calculatedValuesTable: Record<string, { hidden: boolean; disabled: boolean }> = {};\n for (const name in items) {\n let disabled: boolean;\n if (items[name].expertMode && !this.props.expertMode) {\n calculatedValuesTable[name] = { hidden: true, disabled: false };\n continue;\n }\n\n if (this.props.custom) {\n const hidden = !!(await this.executeCustom(\n items[name].hidden,\n this.props.data,\n this.props.customObj,\n this.props.oContext.instanceObj,\n this.props.index,\n this.props.globalData,\n ));\n if (hidden) {\n calculatedValuesTable[name] = { hidden: true, disabled: false };\n continue;\n }\n disabled = !!(await this.executeCustom(\n items[name].disabled,\n this.props.data,\n this.props.customObj,\n this.props.oContext.instanceObj,\n this.props.index,\n this.props.globalData,\n ));\n calculatedValuesTable[name] = { hidden, disabled };\n } else {\n const hidden = !!(await this.execute(\n items[name].hidden,\n false,\n this.props.data,\n this.props.index,\n this.props.globalData,\n ));\n if (hidden) {\n calculatedValuesTable[name] = { hidden: true, disabled: false };\n continue;\n }\n disabled = !!(await this.execute(\n items[name].disabled,\n false,\n this.props.data,\n this.props.index,\n this.props.globalData,\n ));\n calculatedValuesTable[name] = { hidden: false, disabled };\n }\n }\n\n if (JSON.stringify(calculatedValuesTable) !== JSON.stringify(this.state.calculatedValuesTable)) {\n this.setState({ calculatedValuesTable });\n }\n }, 50);\n }\n\n render(): JSX.Element | null {\n const items = this.props.schema.items;\n let withIcons = false;\n\n this.updateCalculatedValuesForTable();\n if (!this.state.calculatedValuesTable) {\n return null;\n }\n const elements: { icon: React.JSX.Element | null; label: string; name: string; disabled: boolean }[] = [];\n\n Object.keys(items)\n .filter(name => !this.state.calculatedValuesTable?.[name]?.hidden)\n .map(name => {\n const icon = this.getIcon(items[name].icon);\n withIcons ||= !!icon;\n elements.push({\n icon,\n disabled: !!this.state.calculatedValuesTable?.[name]?.disabled,\n label: this.getText(items[name].label),\n name,\n });\n });\n\n if (!elements.find(item => item.name === this.state.tab)) {\n // Select the first tab if the current tab is not available\n setTimeout(() => this.setState({ tab: elements[0].name }), 50);\n }\n\n let tabs: React.JSX.Element;\n if (this.state.useMenu && elements.length > 2) {\n tabs = (\n <Toolbar\n style={{\n top: 2,\n backgroundColor: this.props.oContext.themeType === 'dark' ? '#222' : '#DDD',\n }}\n variant=\"dense\"\n >\n <IconButton\n onClick={(event: React.MouseEvent<HTMLButtonElement>) =>\n this.setState({ openMenu: event.currentTarget })\n }\n >\n <MenuIcon />\n </IconButton>\n {this.state.openMenu ? (\n <Menu\n open={!0}\n anchorEl={this.state.openMenu}\n onClose={() => this.setState({ openMenu: null })}\n >\n {elements.map(el => {\n const hasErrors = this.hasTabErrors(el.name);\n return (\n <MenuItem\n disabled={el.disabled}\n key={el.name}\n onClick={() => {\n this.setState({ openMenu: null }, () => this.onMenuChange(el.name));\n }}\n selected={el.name === this.state.tab}\n sx={hasErrors ? { color: 'error.main' } : undefined}\n >\n {withIcons ? <ListItemIcon>{el.icon}</ListItemIcon> : null}\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5, width: '100%' }}>\n {el.label}\n {hasErrors && <ErrorIcon sx={{ fontSize: 16, color: 'error.main' }} />}\n </Box>\n </MenuItem>\n );\n })}\n </Menu>\n ) : null}\n </Toolbar>\n );\n } else {\n tabs = (\n <Tabs\n variant=\"scrollable\"\n scrollButtons=\"auto\"\n style={this.props.schema.tabsStyle}\n value={this.state.tab}\n onChange={(_e, tab: string): void => this.onMenuChange(tab)}\n >\n {elements.map(el => {\n const hasErrors = this.hasTabErrors(el.name);\n const label = hasErrors ? (\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>\n {el.label}\n <ErrorIcon sx={{ fontSize: 16, color: 'error.main' }} />\n </Box>\n ) : (\n el.label\n );\n\n return (\n <Tab\n id={el.name}\n wrapped\n disabled={el.disabled}\n key={el.name}\n value={el.name}\n iconPosition={this.props.schema.iconPosition || 'start'}\n icon={el.icon || undefined}\n label={label}\n sx={hasErrors ? { '& .MuiTab-wrapper': { color: 'error.main' } } : undefined}\n />\n );\n })}\n </Tabs>\n );\n }\n if (!this.state.tab) {\n return null;\n }\n return (\n <div\n style={\n this.state.contentMinWidth !== undefined\n ? { ...styles.tabs, minWidth: this.state.contentMinWidth }\n : styles.tabs\n }\n ref={this.refDiv}\n >\n {tabs}\n <ConfigPanel\n oContext={this.props.oContext}\n withoutSaveButtons={this.props.withoutSaveButtons}\n isParentTab\n changed={this.props.changed}\n key={this.state.tab}\n expertMode={this.props.expertMode}\n index={1001}\n arrayIndex={this.props.arrayIndex}\n globalData={this.props.globalData}\n commandRunning={this.props.commandRunning}\n style={{\n ...styles.panel,\n ...(withIcons ? styles.panelWithIcons : styles.panelWithoutIcons),\n }}\n common={this.props.common}\n alive={this.props.alive}\n themeName={this.props.themeName}\n data={this.props.data}\n originalData={this.props.originalData}\n onChange={this.props.onChange}\n onError={this.onTabError}\n customObj={this.props.customObj}\n custom={this.props.custom}\n schema={items[this.state.tab]}\n table={this.props.table}\n withIcons={withIcons}\n customComponents={this.props.customComponents}\n />\n </div>\n );\n }\n}\n"]}
|