@iobroker/adapter-react-v5 8.2.7 → 8.2.9
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 +6 -0
- package/build/Components/FileBrowser.d.ts +38 -1
- package/build/Components/FileBrowser.js +88 -2
- package/build/Components/FileBrowser.js.map +1 -1
- package/build/Components/ObjectBrowser.d.ts +14 -1
- package/build/Components/ObjectBrowser.js +113 -3
- package/build/Components/ObjectBrowser.js.map +1 -1
- package/build/Components/objectBrowser.types.d.ts +23 -0
- package/build/index.d.ts +2 -2
- package/build/index.js.map +1 -1
- package/package.json +12 -12
|
@@ -27,6 +27,10 @@ export declare class ObjectBrowserClass extends Component<ObjectBrowserProps, Ob
|
|
|
27
27
|
private readonly tableRef;
|
|
28
28
|
private pausedSubscribes;
|
|
29
29
|
private selectFirst;
|
|
30
|
+
/** Last navigation that was applied from `navigateTo` or reported via `onNavigateTo` (loop guard). */
|
|
31
|
+
private lastNav;
|
|
32
|
+
/** True while applying `navigateTo`, so the derived-state watcher does not echo it back. */
|
|
33
|
+
private applyingNav;
|
|
30
34
|
private root;
|
|
31
35
|
private readonly states;
|
|
32
36
|
private subscribes;
|
|
@@ -244,10 +248,19 @@ export declare class ObjectBrowserClass extends Component<ObjectBrowserProps, Ob
|
|
|
244
248
|
renderHandleRight(): JSX.Element;
|
|
245
249
|
private renderHeader;
|
|
246
250
|
private renderToast;
|
|
251
|
+
/** Derive the current navigation target from the dialog/selection state. */
|
|
252
|
+
private getStateNav;
|
|
253
|
+
private static navEqual;
|
|
254
|
+
/** Apply a navigation target coming from the parent (`navigateTo`): select + open the dialog. */
|
|
255
|
+
private applyNavigateTo;
|
|
256
|
+
/** Apply the initial `navigateTo` after the tree has loaded (called from componentDidMount). */
|
|
257
|
+
private applyInitialNavigateTo;
|
|
258
|
+
/** Reconcile `navigateTo` (parent/URL) with the browser's selection/dialog state. */
|
|
259
|
+
private reconcileNavigation;
|
|
247
260
|
/**
|
|
248
261
|
* Called when component is updated.
|
|
249
262
|
*/
|
|
250
|
-
componentDidUpdate(): void;
|
|
263
|
+
componentDidUpdate(prevProps: ObjectBrowserProps): void;
|
|
251
264
|
scrollToItem(id: string): void;
|
|
252
265
|
private renderCustomDialog;
|
|
253
266
|
private onUpdate;
|
|
@@ -788,6 +788,10 @@ export class ObjectBrowserClass extends Component {
|
|
|
788
788
|
tableRef;
|
|
789
789
|
pausedSubscribes = false;
|
|
790
790
|
selectFirst;
|
|
791
|
+
/** Last navigation that was applied from `navigateTo` or reported via `onNavigateTo` (loop guard). */
|
|
792
|
+
lastNav = null;
|
|
793
|
+
/** True while applying `navigateTo`, so the derived-state watcher does not echo it back. */
|
|
794
|
+
applyingNav = false;
|
|
791
795
|
root = null;
|
|
792
796
|
states = {};
|
|
793
797
|
subscribes = [];
|
|
@@ -1229,12 +1233,18 @@ export class ObjectBrowserClass extends Component {
|
|
|
1229
1233
|
// reset filter
|
|
1230
1234
|
this.setState({ filter: { ...DEFAULT_FILTER }, columnsForAdmin }, () => {
|
|
1231
1235
|
this.doFilter();
|
|
1232
|
-
this.setState({ loaded: true, updating: false }, () => this.expandAllSelected(() =>
|
|
1236
|
+
this.setState({ loaded: true, updating: false }, () => this.expandAllSelected(() => {
|
|
1237
|
+
this.onAfterSelect();
|
|
1238
|
+
this.applyInitialNavigateTo();
|
|
1239
|
+
}));
|
|
1233
1240
|
});
|
|
1234
1241
|
}
|
|
1235
1242
|
else {
|
|
1236
1243
|
this.doFilter();
|
|
1237
|
-
this.setState({ loaded: true, updating: false, columnsForAdmin }, () => this.expandAllSelected(() =>
|
|
1244
|
+
this.setState({ loaded: true, updating: false, columnsForAdmin }, () => this.expandAllSelected(() => {
|
|
1245
|
+
this.onAfterSelect();
|
|
1246
|
+
this.applyInitialNavigateTo();
|
|
1247
|
+
}));
|
|
1238
1248
|
}
|
|
1239
1249
|
}
|
|
1240
1250
|
catch (error) {
|
|
@@ -4407,10 +4417,109 @@ export class ObjectBrowserClass extends Component {
|
|
|
4407
4417
|
return (React.createElement(Snackbar, { open: !!this.state.toast, autoHideDuration: 3000, onClick: () => this.setState({ toast: '' }), onClose: () => this.setState({ toast: '' }), message: this.state.toast, action: React.createElement(IconButton, { size: "small", "aria-label": "close", color: "inherit", onClick: () => this.setState({ toast: '' }) },
|
|
4408
4418
|
React.createElement(IconClose, { fontSize: "small" })) }));
|
|
4409
4419
|
}
|
|
4420
|
+
// --- Routing (navigateTo / onNavigateTo) ---
|
|
4421
|
+
// The browser never reads the URL itself; the parent drives it via `navigateTo` and is informed
|
|
4422
|
+
// of user navigation via `onNavigateTo`. All URL parsing/writing lives in the parent component.
|
|
4423
|
+
/** Derive the current navigation target from the dialog/selection state. */
|
|
4424
|
+
getStateNav() {
|
|
4425
|
+
if (this.state.editObjectDialog) {
|
|
4426
|
+
return { mode: 'edit', id: this.state.editObjectDialog };
|
|
4427
|
+
}
|
|
4428
|
+
if (this.state.customDialog && this.state.customDialog.length === 1 && !this.state.customDialogAll) {
|
|
4429
|
+
return { mode: 'settings', id: this.state.customDialog[0] };
|
|
4430
|
+
}
|
|
4431
|
+
if (this.state.viewFileDialog) {
|
|
4432
|
+
return { mode: 'viewFile', id: this.state.viewFileDialog };
|
|
4433
|
+
}
|
|
4434
|
+
if (this.state.selected.length === 1 && this.state.selected[0]) {
|
|
4435
|
+
return { mode: 'select', id: this.state.selected[0] };
|
|
4436
|
+
}
|
|
4437
|
+
return null;
|
|
4438
|
+
}
|
|
4439
|
+
static navEqual(a, b) {
|
|
4440
|
+
if (!a || !b) {
|
|
4441
|
+
return !a && !b;
|
|
4442
|
+
}
|
|
4443
|
+
return a.mode === b.mode && a.id === b.id;
|
|
4444
|
+
}
|
|
4445
|
+
/** Apply a navigation target coming from the parent (`navigateTo`): select + open the dialog. */
|
|
4446
|
+
applyNavigateTo(nav) {
|
|
4447
|
+
this.applyingNav = true;
|
|
4448
|
+
const done = () => {
|
|
4449
|
+
this.applyingNav = false;
|
|
4450
|
+
};
|
|
4451
|
+
if (!nav?.id) {
|
|
4452
|
+
// No target: just close any open dialog (keep the current selection).
|
|
4453
|
+
this.setState({ editObjectDialog: '', customDialog: null, viewFileDialog: '' }, done);
|
|
4454
|
+
return;
|
|
4455
|
+
}
|
|
4456
|
+
const { id } = nav;
|
|
4457
|
+
const open = () => {
|
|
4458
|
+
if (nav.mode === 'edit') {
|
|
4459
|
+
this.setState({ editObjectDialog: id, editObjectAlias: false, customDialog: null, viewFileDialog: '' }, done);
|
|
4460
|
+
}
|
|
4461
|
+
else if (nav.mode === 'settings') {
|
|
4462
|
+
this.setState({ customDialog: [id], customDialogAll: false, editObjectDialog: '', viewFileDialog: '' }, done);
|
|
4463
|
+
}
|
|
4464
|
+
else if (nav.mode === 'viewFile') {
|
|
4465
|
+
this.setState({ viewFileDialog: id, editObjectDialog: '', customDialog: null }, done);
|
|
4466
|
+
}
|
|
4467
|
+
else {
|
|
4468
|
+
this.setState({ editObjectDialog: '', customDialog: null, viewFileDialog: '' }, done);
|
|
4469
|
+
}
|
|
4470
|
+
};
|
|
4471
|
+
// Select the target (if needed), expand to it and scroll into view, then open the dialog.
|
|
4472
|
+
if (this.state.selected.length === 1 && this.state.selected[0] === id) {
|
|
4473
|
+
open();
|
|
4474
|
+
}
|
|
4475
|
+
else {
|
|
4476
|
+
this.onSelect(id, false, () => this.expandAllSelected(() => {
|
|
4477
|
+
this.scrollToItem(id);
|
|
4478
|
+
open();
|
|
4479
|
+
}));
|
|
4480
|
+
}
|
|
4481
|
+
}
|
|
4482
|
+
/** Apply the initial `navigateTo` after the tree has loaded (called from componentDidMount). */
|
|
4483
|
+
applyInitialNavigateTo() {
|
|
4484
|
+
const nav = this.props.navigateTo ?? null;
|
|
4485
|
+
if (nav?.id) {
|
|
4486
|
+
this.lastNav = nav;
|
|
4487
|
+
this.applyNavigateTo(nav);
|
|
4488
|
+
}
|
|
4489
|
+
else {
|
|
4490
|
+
// Don't push the restored-from-localStorage selection into the URL on load.
|
|
4491
|
+
this.lastNav = this.getStateNav();
|
|
4492
|
+
}
|
|
4493
|
+
}
|
|
4494
|
+
/** Reconcile `navigateTo` (parent/URL) with the browser's selection/dialog state. */
|
|
4495
|
+
reconcileNavigation(prevProps) {
|
|
4496
|
+
if (this.props.navigateTo === undefined && !this.props.onNavigateTo) {
|
|
4497
|
+
return; // routing not used by this consumer
|
|
4498
|
+
}
|
|
4499
|
+
if (this.applyingNav) {
|
|
4500
|
+
return; // currently applying a target; ignore the intermediate state
|
|
4501
|
+
}
|
|
4502
|
+
const propNav = this.props.navigateTo ?? null;
|
|
4503
|
+
const stateNav = this.getStateNav();
|
|
4504
|
+
if (ObjectBrowserClass.navEqual(propNav, stateNav)) {
|
|
4505
|
+
this.lastNav = stateNav;
|
|
4506
|
+
return;
|
|
4507
|
+
}
|
|
4508
|
+
if (!ObjectBrowserClass.navEqual(propNav, prevProps.navigateTo ?? null)) {
|
|
4509
|
+
// The parent (URL) drove a change → apply it to the browser.
|
|
4510
|
+
this.lastNav = propNav;
|
|
4511
|
+
this.applyNavigateTo(propNav);
|
|
4512
|
+
}
|
|
4513
|
+
else if (!ObjectBrowserClass.navEqual(stateNav, this.lastNav)) {
|
|
4514
|
+
// The user changed selection/dialog → report it so the parent can update the URL.
|
|
4515
|
+
this.lastNav = stateNav;
|
|
4516
|
+
this.props.onNavigateTo?.(stateNav);
|
|
4517
|
+
}
|
|
4518
|
+
}
|
|
4410
4519
|
/**
|
|
4411
4520
|
* Called when component is updated.
|
|
4412
4521
|
*/
|
|
4413
|
-
componentDidUpdate() {
|
|
4522
|
+
componentDidUpdate(prevProps) {
|
|
4414
4523
|
if (this.tableRef.current) {
|
|
4415
4524
|
const scrollBarWidth = this.tableRef.current.offsetWidth - this.tableRef.current.clientWidth;
|
|
4416
4525
|
if (this.state.scrollBarWidth !== scrollBarWidth) {
|
|
@@ -4420,6 +4529,7 @@ export class ObjectBrowserClass extends Component {
|
|
|
4420
4529
|
this.scrollToItem(this.selectFirst);
|
|
4421
4530
|
}
|
|
4422
4531
|
}
|
|
4532
|
+
this.reconcileNavigation(prevProps);
|
|
4423
4533
|
}
|
|
4424
4534
|
scrollToItem(id) {
|
|
4425
4535
|
this.selectFirst = '';
|