@ds-mo/ui 1.11.4 → 2.0.0
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 +38 -62
- package/dist/.build-stamp +1 -1
- package/dist/components/ds-bar-nav.js +1 -1
- package/dist/components/ds-bar-nav.js.map +1 -1
- package/dist/components/ds-checkbox.js +1 -1
- package/dist/components/ds-field.js +1 -1
- package/dist/components/ds-panel-nav.js +1 -1
- package/dist/components/ds-panel-tools.js +1 -1
- package/dist/components/ds-slider.js +1 -1
- package/dist/components/ds-toggle.js +1 -1
- package/dist/components/p-BOQnc-M4.js +2 -0
- package/dist/components/p-BOQnc-M4.js.map +1 -0
- package/dist/types/components/BarNav/BarNav.d.ts +2 -17
- package/dist/types/components/BarNav/bar-nav-utils.d.ts +3 -3
- package/dist/types/components.d.ts +2 -28
- package/package.json +1 -1
- package/src/angular/proxies.ts +3 -8
- package/src/react/ds-bar-nav.ts +2 -8
- package/src/wc/components/BarNav/BarNav.tsx +4 -76
- package/src/wc/components/BarNav/bar-nav-utils.ts +3 -12
- package/src/wc/components.d.ts +2 -28
- package/dist/components/p-Dl1GvZQ2.js +0 -2
- package/dist/components/p-Dl1GvZQ2.js.map +0 -1
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
import type { NavChromeStyle } from '../../nav/nav-chrome';
|
|
13
13
|
import type { MenuItemData } from '../Menu/menu-types';
|
|
14
14
|
import { isTabDivider } from '../TabGroup/tab-item-utils';
|
|
15
|
-
import type {
|
|
15
|
+
import type { BarNavTab } from './bar-nav-types';
|
|
16
16
|
import {
|
|
17
17
|
deriveBarNavValueFromUrl,
|
|
18
18
|
parseJsonArrayProp,
|
|
@@ -61,15 +61,6 @@ export class BarNav {
|
|
|
61
61
|
/** ID of the currently active tab. Overridden when `currentUrl` + `basePath` are set. */
|
|
62
62
|
@Prop({ mutable: true }) value: string = '';
|
|
63
63
|
|
|
64
|
-
/**
|
|
65
|
-
* Action items rendered in the right section.
|
|
66
|
-
* Set via JS property: `el.actions = [...]`. Replace the array reference to update.
|
|
67
|
-
*/
|
|
68
|
-
@Prop() actions: BarNavActionItem[] = [];
|
|
69
|
-
|
|
70
|
-
/** JSON fallback for `actions` — useful when framework bindings don't propagate arrays. */
|
|
71
|
-
@Prop({ attribute: 'actions-json' }) actionsJson: string = '';
|
|
72
|
-
|
|
73
64
|
/**
|
|
74
65
|
* Fallback heading shown when no tabs are provided.
|
|
75
66
|
* When tabs are present the heading is hidden.
|
|
@@ -85,11 +76,7 @@ export class BarNav {
|
|
|
85
76
|
/** Emitted when the active tab changes. Detail = tab id. */
|
|
86
77
|
@Event() dsTabChange!: EventEmitter<string>;
|
|
87
78
|
|
|
88
|
-
/** Emitted when an action button is toggled. Detail = { id, selected }. */
|
|
89
|
-
@Event() dsActionChange!: EventEmitter<{ id: string; selected: boolean }>;
|
|
90
|
-
|
|
91
79
|
@State() private resolvedTabs: BarNavTab[] = [];
|
|
92
|
-
@State() private resolvedActions: BarNavActionItem[] = [];
|
|
93
80
|
@State() private urlDerivedValue: string = '';
|
|
94
81
|
@State() private hideTabsForDetailRoute = false;
|
|
95
82
|
@State() private tabsCollapsed = false;
|
|
@@ -154,8 +141,6 @@ export class BarNav {
|
|
|
154
141
|
|
|
155
142
|
@Watch('tabs')
|
|
156
143
|
@Watch('tabsJson')
|
|
157
|
-
@Watch('actions')
|
|
158
|
-
@Watch('actionsJson')
|
|
159
144
|
@Watch('currentUrl')
|
|
160
145
|
@Watch('basePath')
|
|
161
146
|
onHostPropsChange() {
|
|
@@ -284,16 +269,7 @@ export class BarNav {
|
|
|
284
269
|
|
|
285
270
|
/** Re-resolve props assigned by the host after componentWillLoad (Angular ngAfterViewInit). */
|
|
286
271
|
private syncHostPropsIfNeeded() {
|
|
287
|
-
if (
|
|
288
|
-
shouldResyncBarNavProps(
|
|
289
|
-
this.resolvedTabs,
|
|
290
|
-
this.tabs,
|
|
291
|
-
this.tabsJson,
|
|
292
|
-
this.resolvedActions,
|
|
293
|
-
this.actions,
|
|
294
|
-
this.actionsJson,
|
|
295
|
-
)
|
|
296
|
-
) {
|
|
272
|
+
if (shouldResyncBarNavProps(this.resolvedTabs, this.tabs, this.tabsJson)) {
|
|
297
273
|
this.applyHostProps();
|
|
298
274
|
} else if (this.currentUrl && this.basePath) {
|
|
299
275
|
this.syncValueFromUrl();
|
|
@@ -361,27 +337,15 @@ export class BarNav {
|
|
|
361
337
|
}
|
|
362
338
|
}
|
|
363
339
|
|
|
364
|
-
/** Width
|
|
340
|
+
/** Width available for the tab row or collapsed trigger. */
|
|
365
341
|
private getLeftZoneAvailableWidth(): number {
|
|
366
342
|
if (!this.headerEl) return 0;
|
|
367
343
|
|
|
368
344
|
const headerStyle = getComputedStyle(this.headerEl);
|
|
369
|
-
const gap = parseFloat(headerStyle.columnGap || headerStyle.gap || '0') || 0;
|
|
370
|
-
const actionsEl = this.headerEl.querySelector('.bar-nav__actions') as HTMLElement | null;
|
|
371
|
-
const actionsWidth = actionsEl?.offsetWidth ?? 0;
|
|
372
345
|
const horizontalPadding =
|
|
373
346
|
(parseFloat(headerStyle.paddingLeft) || 0) + (parseFloat(headerStyle.paddingRight) || 0);
|
|
374
|
-
const spacing = this.tabsCollapsed
|
|
375
|
-
? parseFloat(
|
|
376
|
-
getComputedStyle(this.headerEl).getPropertyValue('--dimension-space-100').trim(),
|
|
377
|
-
) || 8
|
|
378
|
-
: actionsEl
|
|
379
|
-
? gap
|
|
380
|
-
: 0;
|
|
381
|
-
const available =
|
|
382
|
-
this.headerEl.clientWidth - horizontalPadding - actionsWidth - spacing;
|
|
383
347
|
|
|
384
|
-
return Math.max(0,
|
|
348
|
+
return Math.max(0, this.headerEl.clientWidth - horizontalPadding);
|
|
385
349
|
}
|
|
386
350
|
|
|
387
351
|
private getTabsIntrinsicWidth(): number {
|
|
@@ -474,12 +438,6 @@ export class BarNav {
|
|
|
474
438
|
: (this.tabs ?? []);
|
|
475
439
|
}
|
|
476
440
|
|
|
477
|
-
private incomingActions(): BarNavActionItem[] {
|
|
478
|
-
return this.actionsJson
|
|
479
|
-
? parseJsonArrayProp(this.actionsJson, [])
|
|
480
|
-
: (this.actions ?? []);
|
|
481
|
-
}
|
|
482
|
-
|
|
483
441
|
private applyHostProps() {
|
|
484
442
|
const nextBasePath = this.basePath;
|
|
485
443
|
const sectionChanged =
|
|
@@ -492,7 +450,6 @@ export class BarNav {
|
|
|
492
450
|
this.committedSection = '';
|
|
493
451
|
this.pendingSection = nextBasePath;
|
|
494
452
|
this.resolvedTabs = [];
|
|
495
|
-
this.resolvedActions = this.incomingActions();
|
|
496
453
|
this.resetTabOverflowLayout();
|
|
497
454
|
return;
|
|
498
455
|
}
|
|
@@ -516,7 +473,6 @@ export class BarNav {
|
|
|
516
473
|
this.digestTabsConfig(tabs) !== this.digestTabsConfig(this.resolvedTabs);
|
|
517
474
|
|
|
518
475
|
this.resolvedTabs = tabs;
|
|
519
|
-
this.resolvedActions = this.incomingActions();
|
|
520
476
|
this.syncValueFromUrl();
|
|
521
477
|
this.committedSection = nextBasePath;
|
|
522
478
|
if (tabsConfigChanged) {
|
|
@@ -572,11 +528,6 @@ export class BarNav {
|
|
|
572
528
|
this.selectTab((e as CustomEvent<string>).detail);
|
|
573
529
|
}
|
|
574
530
|
|
|
575
|
-
private handleActionChange(actionId: string, e: Event) {
|
|
576
|
-
const selected = (e as CustomEvent<boolean>).detail;
|
|
577
|
-
this.dsActionChange.emit({ id: actionId, selected });
|
|
578
|
-
}
|
|
579
|
-
|
|
580
531
|
private toggleTabMenu() {
|
|
581
532
|
if (this.menuOpen) {
|
|
582
533
|
this.menuOpen = false;
|
|
@@ -736,29 +687,6 @@ export class BarNav {
|
|
|
736
687
|
</button>
|
|
737
688
|
)}
|
|
738
689
|
|
|
739
|
-
{hasTabs &&
|
|
740
|
-
this.tabLayoutCommitted &&
|
|
741
|
-
this.tabsCollapsed &&
|
|
742
|
-
this.resolvedActions.length > 0 && (
|
|
743
|
-
<div class="bar-nav__between" aria-hidden="true" />
|
|
744
|
-
)}
|
|
745
|
-
|
|
746
|
-
{this.resolvedActions.length > 0 && (
|
|
747
|
-
<div class="bar-nav__actions">
|
|
748
|
-
{this.resolvedActions.map(action => (
|
|
749
|
-
<ds-bar-nav-action
|
|
750
|
-
key={action.id}
|
|
751
|
-
icon={action.icon}
|
|
752
|
-
selected={action.selected ?? false}
|
|
753
|
-
dot={action.dot ?? false}
|
|
754
|
-
inactive={action.inactive}
|
|
755
|
-
aria-label={action.ariaLabel ?? action.id}
|
|
756
|
-
onDsChange={(e: Event) => this.handleActionChange(action.id, e)}
|
|
757
|
-
/>
|
|
758
|
-
))}
|
|
759
|
-
</div>
|
|
760
|
-
)}
|
|
761
|
-
|
|
762
690
|
</header>
|
|
763
691
|
|
|
764
692
|
{hasTabs && this.tabLayoutCommitted && this.tabsCollapsed && (
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getSelectableTabs } from '../TabGroup/tab-item-utils';
|
|
2
|
-
import type {
|
|
2
|
+
import type { BarNavTab } from './bar-nav-types';
|
|
3
3
|
|
|
4
4
|
export interface BarNavUrlState {
|
|
5
5
|
/** Tab id derived from the URL, or empty when none applies. */
|
|
@@ -44,24 +44,15 @@ export function shouldResyncBarNavProps(
|
|
|
44
44
|
resolvedTabs: BarNavTab[],
|
|
45
45
|
tabs: BarNavTab[],
|
|
46
46
|
tabsJson: string,
|
|
47
|
-
resolvedActions: BarNavActionItem[],
|
|
48
|
-
actions: BarNavActionItem[],
|
|
49
|
-
actionsJson: string,
|
|
50
47
|
): boolean {
|
|
51
48
|
const tabsIncoming = tabsJson
|
|
52
49
|
? parseJsonArrayProp(tabsJson, [])
|
|
53
50
|
: (tabs ?? []);
|
|
54
|
-
const actionsIncoming = actionsJson
|
|
55
|
-
? parseJsonArrayProp(actionsJson, [])
|
|
56
|
-
: (actions ?? []);
|
|
57
51
|
|
|
58
|
-
return
|
|
59
|
-
(resolvedTabs.length === 0 && tabsIncoming.length > 0) ||
|
|
60
|
-
(resolvedActions.length === 0 && actionsIncoming.length > 0)
|
|
61
|
-
);
|
|
52
|
+
return resolvedTabs.length === 0 && tabsIncoming.length > 0;
|
|
62
53
|
}
|
|
63
54
|
|
|
64
|
-
/** Parse tabs
|
|
55
|
+
/** Parse tabs from either a JSON attribute string or a JS property array. */
|
|
65
56
|
export function parseJsonArrayProp<T>(value: string | T[] | undefined, fallback: T[]): T[] {
|
|
66
57
|
if (Array.isArray(value)) return value;
|
|
67
58
|
if (typeof value === 'string' && value !== '') {
|
package/src/wc/components.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { AccordionItemData } from "./components/Accordion/Accordion";
|
|
|
9
9
|
import { NavChromeStyle } from "./nav/nav-chrome";
|
|
10
10
|
import { BadgeSurface, BadgeVariant } from "./components/Badge/Badge";
|
|
11
11
|
import { BannerContrast, BannerIntent } from "./components/Banner/Banner";
|
|
12
|
-
import {
|
|
12
|
+
import { BarNavTab } from "./components/BarNav/bar-nav-types";
|
|
13
13
|
import { BarNavActionBackground } from "./components/BarNavAction/BarNavAction";
|
|
14
14
|
import { BreadcrumbItem } from "./components/Breadcrumb/Breadcrumb";
|
|
15
15
|
import { ButtonBackground, ButtonContrast, ButtonElevation, ButtonIntent, ButtonSize, ButtonVariant } from "./components/Button/Button";
|
|
@@ -47,7 +47,7 @@ export { AccordionItemData } from "./components/Accordion/Accordion";
|
|
|
47
47
|
export { NavChromeStyle } from "./nav/nav-chrome";
|
|
48
48
|
export { BadgeSurface, BadgeVariant } from "./components/Badge/Badge";
|
|
49
49
|
export { BannerContrast, BannerIntent } from "./components/Banner/Banner";
|
|
50
|
-
export {
|
|
50
|
+
export { BarNavTab } from "./components/BarNav/bar-nav-types";
|
|
51
51
|
export { BarNavActionBackground } from "./components/BarNavAction/BarNavAction";
|
|
52
52
|
export { BreadcrumbItem } from "./components/Breadcrumb/Breadcrumb";
|
|
53
53
|
export { ButtonBackground, ButtonContrast, ButtonElevation, ButtonIntent, ButtonSize, ButtonVariant } from "./components/Button/Button";
|
|
@@ -192,16 +192,6 @@ export namespace Components {
|
|
|
192
192
|
"showDismiss": boolean;
|
|
193
193
|
}
|
|
194
194
|
interface DsBarNav {
|
|
195
|
-
/**
|
|
196
|
-
* Action items rendered in the right section. Set via JS property: `el.actions = [...]`. Replace the array reference to update.
|
|
197
|
-
* @default []
|
|
198
|
-
*/
|
|
199
|
-
"actions": BarNavActionItem[];
|
|
200
|
-
/**
|
|
201
|
-
* JSON fallback for `actions` — useful when framework bindings don't propagate arrays.
|
|
202
|
-
* @default ''
|
|
203
|
-
*/
|
|
204
|
-
"actionsJson": string;
|
|
205
195
|
/**
|
|
206
196
|
* Section base path (e.g. `/dashboard/safety`). Used with `currentUrl` to derive `value`.
|
|
207
197
|
* @default ''
|
|
@@ -1240,7 +1230,6 @@ declare global {
|
|
|
1240
1230
|
};
|
|
1241
1231
|
interface HTMLDsBarNavElementEventMap {
|
|
1242
1232
|
"dsTabChange": string;
|
|
1243
|
-
"dsActionChange": { id: string; selected: boolean };
|
|
1244
1233
|
}
|
|
1245
1234
|
interface HTMLDsBarNavElement extends Components.DsBarNav, HTMLStencilElement {
|
|
1246
1235
|
addEventListener<K extends keyof HTMLDsBarNavElementEventMap>(type: K, listener: (this: HTMLDsBarNavElement, ev: DsBarNavCustomEvent<HTMLDsBarNavElementEventMap[K]>) => any, options?: boolean | AddEventListenerOptions): void;
|
|
@@ -1880,16 +1869,6 @@ declare namespace LocalJSX {
|
|
|
1880
1869
|
"showDismiss"?: boolean;
|
|
1881
1870
|
}
|
|
1882
1871
|
interface DsBarNav {
|
|
1883
|
-
/**
|
|
1884
|
-
* Action items rendered in the right section. Set via JS property: `el.actions = [...]`. Replace the array reference to update.
|
|
1885
|
-
* @default []
|
|
1886
|
-
*/
|
|
1887
|
-
"actions"?: BarNavActionItem[];
|
|
1888
|
-
/**
|
|
1889
|
-
* JSON fallback for `actions` — useful when framework bindings don't propagate arrays.
|
|
1890
|
-
* @default ''
|
|
1891
|
-
*/
|
|
1892
|
-
"actionsJson"?: string;
|
|
1893
1872
|
/**
|
|
1894
1873
|
* Section base path (e.g. `/dashboard/safety`). Used with `currentUrl` to derive `value`.
|
|
1895
1874
|
* @default ''
|
|
@@ -1909,10 +1888,6 @@ declare namespace LocalJSX {
|
|
|
1909
1888
|
* @default 'dashboard'
|
|
1910
1889
|
*/
|
|
1911
1890
|
"navStyle"?: NavChromeStyle;
|
|
1912
|
-
/**
|
|
1913
|
-
* Emitted when an action button is toggled. Detail = { id, selected }.
|
|
1914
|
-
*/
|
|
1915
|
-
"onDsActionChange"?: (event: DsBarNavCustomEvent<{ id: string; selected: boolean }>) => void;
|
|
1916
1891
|
/**
|
|
1917
1892
|
* Emitted when the active tab changes. Detail = tab id.
|
|
1918
1893
|
*/
|
|
@@ -2907,7 +2882,6 @@ declare namespace LocalJSX {
|
|
|
2907
2882
|
"navStyle": NavChromeStyle;
|
|
2908
2883
|
"tabsJson": string;
|
|
2909
2884
|
"value": string;
|
|
2910
|
-
"actionsJson": string;
|
|
2911
2885
|
"heading": string | undefined;
|
|
2912
2886
|
"basePath": string;
|
|
2913
2887
|
"currentUrl": string;
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{g as r}from"./p-BQq26pt9.js";function t(t,e,n){if(!t||!e){return{value:"",hideTabs:false}}if(t!==e&&!t.startsWith(`${e}/`)){return{value:"",hideTabs:false}}const s=t.slice(e.length);const a=s.startsWith("/")?s.slice(1).split("/")[0]:"";const u=r(n);if(!a){return{value:u[0]?.id??"",hideTabs:false}}const i=u.find((r=>r.id===a));if(i){return{value:i.id,hideTabs:false}}return{value:"",hideTabs:true}}function e(r,t,e,s,a,u){const i=e?n(e,[]):t??[];const f=u?n(u,[]):a??[];return r.length===0&&i.length>0||s.length===0&&f.length>0}function n(r,t){if(Array.isArray(r))return r;if(typeof r==="string"&&r!==""){try{const e=JSON.parse(r);return Array.isArray(e)?e:t}catch{return t}}return t}export{t as d,n as p,e as s};
|
|
2
|
-
//# sourceMappingURL=p-Dl1GvZQ2.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["deriveBarNavValueFromUrl","path","basePath","tabs","value","hideTabs","startsWith","remainder","slice","length","seg","split","selectableTabs","getSelectableTabs","id","tab","find","t","shouldResyncBarNavProps","resolvedTabs","tabsJson","resolvedActions","actions","actionsJson","tabsIncoming","parseJsonArrayProp","actionsIncoming","fallback","Array","isArray","parsed","JSON","parse"],"sources":["src/wc/components/BarNav/bar-nav-utils.ts"],"sourcesContent":["import { getSelectableTabs } from '../TabGroup/tab-item-utils';\nimport type { BarNavActionItem, BarNavTab } from './bar-nav-types';\n\nexport interface BarNavUrlState {\n /** Tab id derived from the URL, or empty when none applies. */\n value: string;\n /** When true, tabs should be hidden (e.g. non-tab child routes like detail pages). */\n hideTabs: boolean;\n}\n\n/** Derive BarNav tab selection from `currentUrl` relative to `basePath`.\n * Mirrors motive-webapp-lab `resolveBarNavState` tab-selection semantics. */\nexport function deriveBarNavValueFromUrl(\n path: string,\n basePath: string,\n tabs: BarNavTab[],\n): BarNavUrlState {\n if (!path || !basePath) {\n return { value: '', hideTabs: false };\n }\n\n if (path !== basePath && !path.startsWith(`${basePath}/`)) {\n return { value: '', hideTabs: false };\n }\n\n const remainder = path.slice(basePath.length);\n const seg = remainder.startsWith('/') ? remainder.slice(1).split('/')[0] : '';\n const selectableTabs = getSelectableTabs(tabs);\n\n if (!seg) {\n return { value: selectableTabs[0]?.id ?? '', hideTabs: false };\n }\n\n const tab = selectableTabs.find(t => t.id === seg);\n if (tab) {\n return { value: tab.id, hideTabs: false };\n }\n\n return { value: '', hideTabs: true };\n}\n\n/** True when host array/json props have data but resolved internal state is still empty. */\nexport function shouldResyncBarNavProps(\n resolvedTabs: BarNavTab[],\n tabs: BarNavTab[],\n tabsJson: string,\n resolvedActions: BarNavActionItem[],\n actions: BarNavActionItem[],\n actionsJson: string,\n): boolean {\n const tabsIncoming = tabsJson\n ? parseJsonArrayProp(tabsJson, [])\n : (tabs ?? []);\n const actionsIncoming = actionsJson\n ? parseJsonArrayProp(actionsJson, [])\n : (actions ?? []);\n\n return (\n (resolvedTabs.length === 0 && tabsIncoming.length > 0) ||\n (resolvedActions.length === 0 && actionsIncoming.length > 0)\n );\n}\n\n/** Parse tabs/actions from either a JSON attribute string or a JS property array. */\nexport function parseJsonArrayProp<T>(value: string | T[] | undefined, fallback: T[]): T[] {\n if (Array.isArray(value)) return value;\n if (typeof value === 'string' && value !== '') {\n try {\n const parsed = JSON.parse(value);\n return Array.isArray(parsed) ? parsed : fallback;\n } catch {\n return fallback;\n }\n }\n return fallback;\n}\n"],"mappings":"6CAYgBA,EACdC,EACAC,EACAC,GAEA,IAAKF,IAASC,EAAU,CACtB,MAAO,CAAEE,MAAO,GAAIC,SAAU,M,CAGhC,GAAIJ,IAASC,IAAaD,EAAKK,WAAW,GAAGJ,MAAc,CACzD,MAAO,CAAEE,MAAO,GAAIC,SAAU,M,CAGhC,MAAME,EAAYN,EAAKO,MAAMN,EAASO,QACtC,MAAMC,EAAMH,EAAUD,WAAW,KAAOC,EAAUC,MAAM,GAAGG,MAAM,KAAK,GAAK,GAC3E,MAAMC,EAAiBC,EAAkBV,GAEzC,IAAKO,EAAK,CACR,MAAO,CAAEN,MAAOQ,EAAe,IAAIE,IAAM,GAAIT,SAAU,M,CAGzD,MAAMU,EAAMH,EAAeI,MAAKC,GAAKA,EAAEH,KAAOJ,IAC9C,GAAIK,EAAK,CACP,MAAO,CAAEX,MAAOW,EAAID,GAAIT,SAAU,M,CAGpC,MAAO,CAAED,MAAO,GAAIC,SAAU,KAChC,CAGM,SAAUa,EACdC,EACAhB,EACAiB,EACAC,EACAC,EACAC,GAEA,MAAMC,EAAeJ,EACjBK,EAAmBL,EAAU,IAC5BjB,GAAQ,GACb,MAAMuB,EAAkBH,EACpBE,EAAmBF,EAAa,IAC/BD,GAAW,GAEhB,OACGH,EAAaV,SAAW,GAAKe,EAAaf,OAAS,GACnDY,EAAgBZ,SAAW,GAAKiB,EAAgBjB,OAAS,CAE9D,CAGM,SAAUgB,EAAsBrB,EAAiCuB,GACrE,GAAIC,MAAMC,QAAQzB,GAAQ,OAAOA,EACjC,UAAWA,IAAU,UAAYA,IAAU,GAAI,CAC7C,IACE,MAAM0B,EAASC,KAAKC,MAAM5B,GAC1B,OAAOwB,MAAMC,QAAQC,GAAUA,EAASH,C,CACxC,MACA,OAAOA,C,EAGX,OAAOA,CACT,Q","ignoreList":[]}
|