@vc-shell/framework 1.0.71 → 1.0.73
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/CHANGELOG.md +25 -0
- package/core/composables/usePermissions/index.ts +21 -8
- package/core/composables/useUser/index.ts +5 -4
- package/core/plugins/modularity/index.ts +17 -2
- package/core/utilities/index.ts +1 -0
- package/core/utilities/kebabToCamel.ts +7 -0
- package/dist/core/composables/usePermissions/index.d.ts +1 -2
- package/dist/core/composables/usePermissions/index.d.ts.map +1 -1
- package/dist/core/composables/useUser/index.d.ts.map +1 -1
- package/dist/core/plugins/modularity/index.d.ts +4 -1
- package/dist/core/plugins/modularity/index.d.ts.map +1 -1
- package/dist/core/utilities/index.d.ts +1 -0
- package/dist/core/utilities/index.d.ts.map +1 -1
- package/dist/core/utilities/kebabToCamel.d.ts +2 -0
- package/dist/core/utilities/kebabToCamel.d.ts.map +1 -0
- package/dist/framework.mjs +11483 -11161
- package/dist/index.css +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/shared/components/blade-navigation/components/vc-blade-navigation/index.d.ts +5 -7
- package/dist/shared/components/blade-navigation/components/vc-blade-navigation/index.d.ts.map +1 -1
- package/dist/shared/components/blade-navigation/components/vc-blade-navigation/vc-blade-navigation.vue.d.ts +5 -5
- package/dist/shared/components/blade-navigation/components/vc-blade-navigation/vc-blade-navigation.vue.d.ts.map +1 -1
- package/dist/shared/components/blade-navigation/composables/useBladeNavigation/index.d.ts +20 -4
- package/dist/shared/components/blade-navigation/composables/useBladeNavigation/index.d.ts.map +1 -1
- package/dist/shared/components/blade-navigation/types/index.d.ts +1 -1
- package/dist/shared/components/blade-navigation/types/index.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/ui/components/atoms/vc-link/vc-link.stories.d.ts.map +1 -1
- package/dist/ui/components/molecules/vc-select/index.d.ts +26 -26
- package/dist/ui/components/molecules/vc-select/vc-select.vue.d.ts +26 -26
- package/dist/ui/components/molecules/vc-select/vc-select.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-bar/vc-app-bar.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/vc-app.vue.d.ts.map +1 -1
- package/package.json +5 -4
- package/shared/components/blade-navigation/components/vc-blade-navigation/vc-blade-navigation.vue +6 -10
- package/shared/components/blade-navigation/composables/useBladeNavigation/index.ts +148 -62
- package/shared/components/blade-navigation/types/index.ts +1 -1
- package/shared/pages/LoginPage/components/login/Login.vue +1 -1
- package/ui/components/atoms/vc-link/vc-link.stories.ts +0 -1
- package/ui/components/atoms/vc-link/vc-link.vue +2 -2
- package/ui/components/molecules/vc-select/vc-select.vue +5 -5
- package/ui/components/organisms/vc-app/_internal/vc-app-bar/vc-app-bar.vue +1 -0
- package/ui/components/organisms/vc-app/vc-app.vue +6 -3
- package/dist/injectionSymbols.d.ts +0 -6
- package/dist/injectionSymbols.d.ts.map +0 -1
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
nextTick,
|
|
12
12
|
} from "vue";
|
|
13
13
|
import * as _ from "lodash-es";
|
|
14
|
-
import { useRouter,
|
|
14
|
+
import { useRouter, RouteLocationNormalized } from "vue-router";
|
|
15
15
|
import { usePermissions } from "../../../../../core/composables";
|
|
16
16
|
import {
|
|
17
17
|
IBladeContainer,
|
|
@@ -22,98 +22,136 @@ import {
|
|
|
22
22
|
BladeComponentInternalInstance,
|
|
23
23
|
BladeNavigationPlugin,
|
|
24
24
|
notification,
|
|
25
|
+
BladePageComponent,
|
|
25
26
|
} from "../../../..";
|
|
26
27
|
import { bladeNavigationInstance } from "./../../plugin";
|
|
28
|
+
import pattern from "url-pattern";
|
|
29
|
+
import { useLocalStorage } from "@vueuse/core";
|
|
27
30
|
|
|
31
|
+
interface BladeData {
|
|
32
|
+
blade?: string;
|
|
33
|
+
param?: string;
|
|
34
|
+
options?: string;
|
|
35
|
+
}
|
|
28
36
|
interface IUseBladeNavigation {
|
|
29
37
|
readonly blades: Ref<IBladeContainer[]>;
|
|
30
|
-
readonly
|
|
31
|
-
readonly
|
|
38
|
+
readonly workspaceOptions: Ref<Record<string, unknown>>;
|
|
39
|
+
readonly workspaceParam: Ref<string>;
|
|
40
|
+
readonly lastBladeData: Ref<BladeData>;
|
|
32
41
|
bladesRefs: Ref<IBladeRef[]>;
|
|
33
|
-
openBlade: <Blade extends ComponentPublicInstance = ComponentPublicInstance>(
|
|
34
|
-
blade,
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
onOpen,
|
|
38
|
-
onClose,
|
|
39
|
-
}: IBladeEvent<Blade>) => void;
|
|
42
|
+
openBlade: <Blade extends ComponentPublicInstance = ComponentPublicInstance>(
|
|
43
|
+
{ blade, param, options, onOpen, onClose }: IBladeEvent<Blade>,
|
|
44
|
+
isWorkspace?: boolean
|
|
45
|
+
) => void;
|
|
40
46
|
closeBlade: (index: number) => Promise<boolean>;
|
|
41
47
|
onParentCall: (index: number, args: IParentCallArgs) => void;
|
|
48
|
+
/**
|
|
49
|
+
* Resolves blades from vue-router's navigation guard 'to' param. Used to display blades after page reload or accessing via direct link.
|
|
50
|
+
* Returns a string containing the URL of the latest opened workspace.
|
|
51
|
+
* @param to
|
|
52
|
+
* @returns string
|
|
53
|
+
*/
|
|
54
|
+
resolveBlades: (to: RouteLocationNormalized) => string;
|
|
55
|
+
resolveLastBlade: (pages: BladePageComponent[]) => void;
|
|
56
|
+
resolveUnknownRoutes: (to: RouteLocationNormalized) => string;
|
|
42
57
|
}
|
|
43
58
|
|
|
44
59
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
45
|
-
const
|
|
46
|
-
const
|
|
60
|
+
const workspaceOptions: Ref<Record<string, any>> = ref();
|
|
61
|
+
const workspaceParam: Ref<string> = ref();
|
|
62
|
+
|
|
63
|
+
const lastBladeData = useLocalStorage<BladeData>("VC_BLADE_DATA", {});
|
|
47
64
|
|
|
48
65
|
export function useBladeNavigation(): IUseBladeNavigation {
|
|
49
66
|
const router = useRouter();
|
|
50
|
-
const
|
|
67
|
+
const urlPattern = new pattern("(/:workspace(/:blade(/:param)))");
|
|
51
68
|
const { checkPermission } = usePermissions();
|
|
52
69
|
const isPrevented = ref(false);
|
|
70
|
+
const routes = router.getRoutes();
|
|
53
71
|
|
|
54
72
|
const instance: BladeComponentInternalInstance = getCurrentInstance();
|
|
55
73
|
const navigationInstance =
|
|
56
74
|
(instance && inject<BladeNavigationPlugin>("bladeNavigationPlugin")) || bladeNavigationInstance;
|
|
57
75
|
|
|
58
76
|
watch(
|
|
59
|
-
navigationInstance
|
|
77
|
+
navigationInstance?.blades,
|
|
60
78
|
(newVal) => {
|
|
61
|
-
|
|
79
|
+
if (newVal) {
|
|
80
|
+
const workspace = navigationInstance.bladesRefs.value[0]?.blade;
|
|
81
|
+
const lastBlade = newVal[newVal.length - 1];
|
|
62
82
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
83
|
+
if (workspace && workspace.blade.url) {
|
|
84
|
+
if (lastBlade && lastBlade.blade.url) {
|
|
85
|
+
const url = urlPattern.stringify({
|
|
86
|
+
workspace: workspace?.blade.url.substring(1),
|
|
87
|
+
blade: lastBlade?.blade.url.substring(1),
|
|
88
|
+
param: lastBlade?.param,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
addEntryToLocation(url);
|
|
92
|
+
} else {
|
|
93
|
+
const url = workspace?.blade.url;
|
|
94
|
+
if (url) {
|
|
95
|
+
clearParentData();
|
|
96
|
+
addEntryToLocation(url);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
68
99
|
}
|
|
69
|
-
} else if (!lastBlade) {
|
|
70
|
-
clearParentData();
|
|
71
|
-
addEntryToLocation(route.path);
|
|
72
100
|
}
|
|
73
101
|
},
|
|
74
102
|
{ deep: true }
|
|
75
103
|
);
|
|
76
104
|
|
|
77
|
-
async function
|
|
78
|
-
|
|
79
|
-
param,
|
|
80
|
-
options,
|
|
81
|
-
onOpen,
|
|
82
|
-
onClose,
|
|
83
|
-
}: IBladeEvent<Blade>) {
|
|
84
|
-
const caller = instance && instance.vnode.type;
|
|
105
|
+
async function openWorkspace({ blade, param, options }: IBladeEvent) {
|
|
106
|
+
await closeBlade(0);
|
|
85
107
|
|
|
86
108
|
const bladeComponent = unref(blade);
|
|
109
|
+
|
|
110
|
+
if (!isPrevented.value) {
|
|
111
|
+
workspaceOptions.value = unref(options);
|
|
112
|
+
workspaceParam.value = unref(param);
|
|
113
|
+
|
|
114
|
+
await router.replace(bladeComponent.url);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async function openBlade<Blade extends ComponentPublicInstance>(
|
|
119
|
+
{ blade, param, options, onOpen, onClose }: IBladeEvent<Blade>,
|
|
120
|
+
isWorkspace = false
|
|
121
|
+
) {
|
|
122
|
+
if (isWorkspace) {
|
|
123
|
+
openWorkspace({ blade, param, options });
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// caller blade component from instance
|
|
128
|
+
const instanceComponent = instance && instance.vnode.type;
|
|
129
|
+
|
|
130
|
+
// Caller blade index in blades array
|
|
87
131
|
const callerIndex = navigationInstance.bladesRefs.value.findIndex((item) => {
|
|
88
|
-
return _.isEqual(item.blade.blade,
|
|
132
|
+
return _.isEqual(item.blade.blade, instanceComponent);
|
|
89
133
|
});
|
|
90
|
-
const existingChild =
|
|
91
|
-
callerIndex >= 0 ? navigationInstance.bladesRefs.value[callerIndex + 1]?.blade.blade : undefined;
|
|
92
|
-
const index = caller?.idx ? caller.idx : 0;
|
|
93
134
|
|
|
94
|
-
|
|
135
|
+
// Trying to determine if the calling blade already has a child in order to replace it
|
|
136
|
+
const isBladeAlreadyExist =
|
|
137
|
+
callerIndex >= 0 ? navigationInstance.bladesRefs.value[callerIndex + 1]?.blade.blade : undefined;
|
|
95
138
|
|
|
96
|
-
|
|
97
|
-
|
|
139
|
+
// Blade we want to open
|
|
140
|
+
const bladeComponent = unref(blade);
|
|
98
141
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
parentBladeParam.value = unref(param);
|
|
142
|
+
// Check if caller blade has idx
|
|
143
|
+
const index = instanceComponent?.idx ? instanceComponent.idx : 0;
|
|
102
144
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
} else {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
114
|
-
if (!isPrevented.value) {
|
|
115
|
-
await addBlade(bladeComponent, param, options, onOpen, onClose, index);
|
|
116
|
-
}
|
|
145
|
+
if (isBladeAlreadyExist === undefined) {
|
|
146
|
+
bladeComponent.idx = index ? index + 1 : 1;
|
|
147
|
+
} else if (isBladeAlreadyExist) {
|
|
148
|
+
await closeBlade(
|
|
149
|
+
navigationInstance.blades.value.findIndex((x: IBladeContainer) => x.idx === isBladeAlreadyExist.idx)
|
|
150
|
+
);
|
|
151
|
+
bladeComponent.idx = isBladeAlreadyExist.idx;
|
|
152
|
+
}
|
|
153
|
+
if (!isPrevented.value) {
|
|
154
|
+
await addBlade(bladeComponent, param, options, onOpen, onClose, index);
|
|
117
155
|
}
|
|
118
156
|
}
|
|
119
157
|
|
|
@@ -136,8 +174,9 @@ export function useBladeNavigation(): IUseBladeNavigation {
|
|
|
136
174
|
}
|
|
137
175
|
}
|
|
138
176
|
if (!isPrevented.value) {
|
|
139
|
-
|
|
140
|
-
|
|
177
|
+
const blade = navigationInstance.blades.value[index];
|
|
178
|
+
if (typeof blade?.onClose === "function") {
|
|
179
|
+
blade?.onClose?.();
|
|
141
180
|
}
|
|
142
181
|
|
|
143
182
|
navigationInstance.blades.value.splice(index);
|
|
@@ -199,23 +238,70 @@ export function useBladeNavigation(): IUseBladeNavigation {
|
|
|
199
238
|
}
|
|
200
239
|
|
|
201
240
|
function addEntryToLocation(params: string) {
|
|
202
|
-
history.
|
|
241
|
+
history.replaceState({}, null, "#" + params);
|
|
203
242
|
}
|
|
204
243
|
|
|
205
244
|
async function clearParentData() {
|
|
206
245
|
nextTick(() => {
|
|
207
|
-
|
|
208
|
-
|
|
246
|
+
workspaceOptions.value = undefined;
|
|
247
|
+
workspaceParam.value = undefined;
|
|
209
248
|
});
|
|
210
249
|
}
|
|
211
250
|
|
|
251
|
+
function resolveBlades(to: RouteLocationNormalized) {
|
|
252
|
+
const data = urlPattern.match(to.path);
|
|
253
|
+
|
|
254
|
+
const resolvedRoute = (bladeUrl: string) => routes.find((r) => r.path === "/" + bladeUrl);
|
|
255
|
+
|
|
256
|
+
if (resolvedRoute(data?.workspace) && to.path !== "/" + data.workspace) {
|
|
257
|
+
if (resolvedRoute(data?.blade)) {
|
|
258
|
+
lastBladeData.value = {
|
|
259
|
+
blade: "/" + data?.blade,
|
|
260
|
+
param: data?.param,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return "/" + data.workspace;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function resolveUnknownRoutes(to: RouteLocationNormalized) {
|
|
269
|
+
if (routes.find((r) => r.path !== to.path)) {
|
|
270
|
+
closeBlade(0);
|
|
271
|
+
return "/";
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function clearSavedBladeData() {
|
|
276
|
+
lastBladeData.value = {};
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
280
|
+
async function setParentData({ param, options }: { param?: string; options?: Record<string, any> }) {
|
|
281
|
+
workspaceOptions.value = options;
|
|
282
|
+
workspaceParam.value = param;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function resolveLastBlade(pages: BladePageComponent[]) {
|
|
286
|
+
if (lastBladeData.value?.blade) {
|
|
287
|
+
const blade = pages?.find((b) => b.url === lastBladeData.value?.blade);
|
|
288
|
+
setParentData({ param: lastBladeData.value?.param });
|
|
289
|
+
openBlade({ blade, param: lastBladeData.value?.param });
|
|
290
|
+
clearSavedBladeData();
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
212
294
|
return {
|
|
213
295
|
blades: computed(() => navigationInstance.blades.value),
|
|
214
|
-
|
|
215
|
-
|
|
296
|
+
workspaceOptions: computed(() => workspaceOptions.value),
|
|
297
|
+
workspaceParam: computed(() => workspaceParam.value),
|
|
298
|
+
lastBladeData: computed(() => lastBladeData.value),
|
|
216
299
|
bladesRefs: navigationInstance.bladesRefs,
|
|
217
300
|
openBlade,
|
|
218
301
|
closeBlade,
|
|
219
302
|
onParentCall,
|
|
303
|
+
resolveBlades,
|
|
304
|
+
resolveUnknownRoutes,
|
|
305
|
+
resolveLastBlade,
|
|
220
306
|
};
|
|
221
307
|
}
|
|
@@ -23,7 +23,7 @@ export type CoreBladeComponentProps = {
|
|
|
23
23
|
export type BladePageComponent = BladeConstructor;
|
|
24
24
|
|
|
25
25
|
export type CoreBladeAdditionalSettings = {
|
|
26
|
-
url?: string
|
|
26
|
+
url?: `/${string}`;
|
|
27
27
|
permissions?: string | string[];
|
|
28
28
|
scope?: {
|
|
29
29
|
notificationClick?: (notification: PushNotification | Record<string, any>) => IBladeEvent;
|
|
@@ -176,7 +176,7 @@ import { useRouter } from "vue-router";
|
|
|
176
176
|
import { useIsFormValid, Field, useIsFormDirty, useForm } from "vee-validate";
|
|
177
177
|
import { useSettings, useUser } from "./../../../../../core/composables";
|
|
178
178
|
import { RequestPasswordResult, SignInResults } from "./../../../../../core/types";
|
|
179
|
-
import { CommonPageComposables } from "typings";
|
|
179
|
+
import { CommonPageComposables } from "./../../../../../typings";
|
|
180
180
|
import { asyncComputed } from "@vueuse/core";
|
|
181
181
|
import AzureAdIcon from "./../../../../../assets/img/AzureAd.svg";
|
|
182
182
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
'tw-cursor-not-allowed tw-text-[color:var(--link-text-color-disabled)] hover:tw-text-[color:var(--link-text-color-disabled)] tw-no-underline':
|
|
7
7
|
disabled,
|
|
8
8
|
}"
|
|
9
|
-
@click="
|
|
9
|
+
@click="onClickFn"
|
|
10
10
|
>
|
|
11
11
|
<slot></slot>
|
|
12
12
|
</div>
|
|
@@ -26,7 +26,7 @@ export interface Emits {
|
|
|
26
26
|
const props = defineProps<Props>();
|
|
27
27
|
const emit = defineEmits<Emits>();
|
|
28
28
|
|
|
29
|
-
function
|
|
29
|
+
function onClickFn(): void {
|
|
30
30
|
if (!props.disabled) {
|
|
31
31
|
emit("click");
|
|
32
32
|
}
|
|
@@ -202,7 +202,7 @@
|
|
|
202
202
|
<div
|
|
203
203
|
v-if="isOpened"
|
|
204
204
|
ref="dropdownRef"
|
|
205
|
-
v-on-click-outside="
|
|
205
|
+
v-on-click-outside="[toggleDropdown, { ignore: [dropdownToggleRef] }]"
|
|
206
206
|
class="tw-flex tw-flex-col tw-box-border tw-max-h-[300px] tw-h-auto tw-z-10 tw-overflow-hidden tw-absolute tw-bg-[color:var(--select-background-color)] tw-border tw-border-solid tw-border-[color:var(--select-border-color)] tw-border-t-[color:var(--select-background-color)] tw-rounded-b-[var(--select-border-radius)] tw-p-2"
|
|
207
207
|
:style="dropdownStyle"
|
|
208
208
|
>
|
|
@@ -251,7 +251,7 @@
|
|
|
251
251
|
</template>
|
|
252
252
|
|
|
253
253
|
<!-- eslint-disable @typescript-eslint/no-explicit-any -->
|
|
254
|
-
<script lang="ts" setup generic="T
|
|
254
|
+
<script lang="ts" setup generic="T, P extends {results?: T[]; totalCount?: number }">
|
|
255
255
|
import { ref, computed, watch, toRefs, nextTick, Ref } from "vue";
|
|
256
256
|
import { vOnClickOutside } from "@vueuse/components";
|
|
257
257
|
import * as _ from "lodash-es";
|
|
@@ -272,7 +272,7 @@ type FloatingInstanceType = UseFloatingReturn & {
|
|
|
272
272
|
};
|
|
273
273
|
};
|
|
274
274
|
|
|
275
|
-
type Option = T
|
|
275
|
+
type Option = T & P["results"][number];
|
|
276
276
|
|
|
277
277
|
defineSlots<{
|
|
278
278
|
/**
|
|
@@ -882,10 +882,10 @@ function onInput(e: Event) {
|
|
|
882
882
|
}
|
|
883
883
|
|
|
884
884
|
const newValue = (e.target as HTMLInputElement).value;
|
|
885
|
-
|
|
885
|
+
emitValueFunc(newValue);
|
|
886
886
|
}
|
|
887
887
|
|
|
888
|
-
function
|
|
888
|
+
function emitValueFunc(val: string) {
|
|
889
889
|
emitValueFn = () => {
|
|
890
890
|
emit("search", val);
|
|
891
891
|
onSearch(val);
|
|
@@ -109,9 +109,12 @@ const onMenuItemClick = function ({ item }: { item: BladeMenu }) {
|
|
|
109
109
|
if (item.clickHandler && typeof item.clickHandler === "function") {
|
|
110
110
|
item.clickHandler(instance?.exposed);
|
|
111
111
|
} else {
|
|
112
|
-
openBlade(
|
|
113
|
-
|
|
114
|
-
|
|
112
|
+
openBlade(
|
|
113
|
+
{
|
|
114
|
+
blade: markRaw(item.component),
|
|
115
|
+
},
|
|
116
|
+
true
|
|
117
|
+
);
|
|
115
118
|
}
|
|
116
119
|
};
|
|
117
120
|
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { NotificationTemplateConstructor } from "./core/types";
|
|
2
|
-
import { BladePageComponent } from "./shared/components/blade-navigation/types";
|
|
3
|
-
import { InjectionKey } from "vue";
|
|
4
|
-
export declare const pagesSymbol: InjectionKey<BladePageComponent[]>;
|
|
5
|
-
export declare const notificationTemplatesSymbol: InjectionKey<NotificationTemplateConstructor[]>;
|
|
6
|
-
//# sourceMappingURL=injectionSymbols.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"injectionSymbols.d.ts","sourceRoot":"","sources":["../injectionSymbols.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,+BAA+B,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,4CAA4C,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,KAAK,CAAC;AAEnC,eAAO,MAAM,WAAW,oCAAwD,CAAC;AACjF,eAAO,MAAM,2BAA2B,iDAEvC,CAAC"}
|