@pubinfo/core 2.0.0 → 2.0.2
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/dist/{AppSetting-DqVYDIHj.js → AppSetting-C-uQWp09.js} +15 -15
- package/dist/{HCheckList.vue_vue_type_script_setup_true_lang-SrNklW3P.js → HCheckList.vue_vue_type_script_setup_true_lang-Dix75g7Y.js} +1 -1
- package/dist/{HToggle-DGTP9jYA.js → HToggle-CkLtDSqB.js} +1 -1
- package/dist/{PreferencesContent-5NtwK9RQ.js → PreferencesContent-uLLIbpgi.js} +4 -4
- package/dist/{SettingBreadcrumb-BudqQsuJ.js → SettingBreadcrumb-eOf8TqIs.js} +3 -3
- package/dist/{SettingCopyright-VUberG4R.js → SettingCopyright-DwaL1fDm.js} +2 -2
- package/dist/{SettingEnableTransition-C6NYf021.js → SettingEnableTransition-CBybF9vH.js} +2 -2
- package/dist/{SettingHome-BTaeKgwN.js → SettingHome-DZjnXioZ.js} +2 -2
- package/dist/{SettingMenu-D9Aon2LP.js → SettingMenu-BoDFUNC2.js} +3 -3
- package/dist/{SettingMode-DaqVd9Mq.js → SettingMode-BjC403k0.js} +1 -1
- package/dist/{SettingNavSearch-N4JIheIk.js → SettingNavSearch-l7X-Iwjk.js} +2 -2
- package/dist/{SettingOther-tLulcors.js → SettingOther-C07luGm-.js} +2 -2
- package/dist/{SettingPage-CEjWB45R.js → SettingPage-CpCp1Tnk.js} +2 -2
- package/dist/{SettingTabbar-DyeLhcCT.js → SettingTabbar-BpvyU_8s.js} +3 -3
- package/dist/{SettingThemes-C2M3tsVl.js → SettingThemes-BNqblNbu.js} +1 -1
- package/dist/{SettingToolbar-DI7de6i0.js → SettingToolbar-C-s6o0qU.js} +2 -2
- package/dist/{SettingTopbar-BgIoXeAq.js → SettingTopbar-DlASsEm4.js} +3 -3
- package/dist/{SettingWidthMode-DIAU4s5e.js → SettingWidthMode-DUhpdqt0.js} +1 -1
- package/dist/{TopThinMode-JNUHrJI2.js → TopThinMode-C4ENwLBo.js} +1 -1
- package/dist/{colors-DxWfHM_v.js → colors-DEL1DLxl.js} +1 -1
- package/dist/features/stores/modules/user.d.ts +2 -2
- package/dist/{index-D4v4g8FJ.js → index-BAQ3G_yS.js} +26 -26
- package/dist/{index-BFRIv97x.js → index-BC4fIMeo.js} +2 -2
- package/dist/{index-BH-vHGvk.js → index-C5-BAU1l.js} +1 -1
- package/dist/{index-5fRpGyLW.js → index-Cl9ha8wq.js} +4 -4
- package/dist/{index-CNVn3Ubv.js → index-CqRJBmZ2.js} +2 -2
- package/dist/{index-Cf-u1Zqh.js → index-DhzrIShp.js} +1 -1
- package/dist/{index-Dv7UUFkD.js → index-Dm0Yz_my.js} +972 -968
- package/dist/{index-DQGnbEGS.js → index-DoyP74bp.js} +2 -2
- package/dist/{index-C7xIGcDc.js → index-RctfGvXs.js} +6 -6
- package/dist/index.js +1 -1
- package/dist/{pick-VFuUwFn-.js → pick-BvpiopvO.js} +1 -1
- package/dist/style.css +1 -1
- package/package.json +5 -5
- package/src/built-in/authentication/pages/change-password/components/ChangePasswordForm/index.vue +1 -1
- package/src/built-in/layout-component/components/Header/TopMode/index.vue +2 -2
- package/src/built-in/layout-component/components/Menu/item.vue +6 -6
- package/src/built-in/layout-component/components/Topbar/Tabbar/MoreAction.vue +42 -24
- package/src/built-in/layout-component/components/Topbar/Tabbar/index.vue +43 -25
- package/src/features/stores/modules/user.ts +3 -3
- package/types/menu.d.ts +1 -1
- package/types/user.d.ts +3 -3
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pubinfo/core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "2.0.
|
|
4
|
+
"version": "2.0.2",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
"pinia": "^3.0.3",
|
|
27
27
|
"vue": "^3.5.17",
|
|
28
28
|
"vue-router": "^4.5.1",
|
|
29
|
-
"@pubinfo/config": "2.0.
|
|
30
|
-
"@pubinfo/vite": "2.0.
|
|
29
|
+
"@pubinfo/config": "2.0.2",
|
|
30
|
+
"@pubinfo/vite": "2.0.2"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@alova/adapter-axios": "^2.0.16",
|
|
@@ -85,8 +85,8 @@
|
|
|
85
85
|
"vite-plugin-dts": "^4.5.4",
|
|
86
86
|
"vue": "^3.5.17",
|
|
87
87
|
"vue-router": "^4.5.1",
|
|
88
|
-
"@pubinfo/config": "2.0.
|
|
89
|
-
"@pubinfo/vite": "2.0.
|
|
88
|
+
"@pubinfo/config": "2.0.2",
|
|
89
|
+
"@pubinfo/vite": "2.0.2"
|
|
90
90
|
},
|
|
91
91
|
"scripts": {
|
|
92
92
|
"dev": "vite build -w -m watch",
|
package/src/built-in/authentication/pages/change-password/components/ChangePasswordForm/index.vue
CHANGED
|
@@ -62,7 +62,7 @@ const rules: Record<string, Rule[]> = {
|
|
|
62
62
|
async function submit() {
|
|
63
63
|
try {
|
|
64
64
|
await changePasswordForm.value?.validate();
|
|
65
|
-
await userStore.
|
|
65
|
+
await userStore.changePassword({
|
|
66
66
|
oldPassword: formState.password,
|
|
67
67
|
newPassword: formState.newPassword,
|
|
68
68
|
token: props.token,
|
|
@@ -120,10 +120,10 @@ onMounted(() => {
|
|
|
120
120
|
<template v-if="iconName(index === menuStore.actived, item.meta?.icon, item.meta?.activeIcon)">
|
|
121
121
|
<!-- 当存在 iconOptions 且 boxType 不为 'null' 时,展示带边框/渐变的盒子效果 -->
|
|
122
122
|
<PubinfoIcon
|
|
123
|
-
v-if="item.meta?.iconOptions"
|
|
123
|
+
v-if="item.meta?.iconOptions?.boxType && item.meta.iconOptions.boxType !== 'null'"
|
|
124
124
|
:name="iconName(index === menuStore.actived, item.meta?.icon, item.meta?.activeIcon)!"
|
|
125
125
|
small
|
|
126
|
-
:box="
|
|
126
|
+
:box="item.meta.iconOptions.boxType as any"
|
|
127
127
|
:size="18"
|
|
128
128
|
:angle="item.meta.iconOptions.angle"
|
|
129
129
|
:background="item.meta.iconOptions.background"
|
|
@@ -57,10 +57,10 @@ const iconOptions = computed(() => ((props.item.meta as any)?.iconOptions) as un
|
|
|
57
57
|
iconColor?: string
|
|
58
58
|
});
|
|
59
59
|
|
|
60
|
-
//
|
|
61
|
-
const computedBoxType = computed(() => {
|
|
62
|
-
const bt = iconOptions.value?.boxType
|
|
63
|
-
return bt && bt !== 'null' ? bt :
|
|
60
|
+
// 统一盒子类型:仅当显式为 square/prism 时启用盒子
|
|
61
|
+
const computedBoxType = computed<'square' | 'prism' | undefined>(() => {
|
|
62
|
+
const bt = iconOptions.value?.boxType;
|
|
63
|
+
return bt && bt !== 'null' ? bt : undefined;
|
|
64
64
|
});
|
|
65
65
|
|
|
66
66
|
// 统一安全的图标颜色(仅 AntD 图标使用);无配置则为 undefined
|
|
@@ -112,10 +112,10 @@ defineExpose({
|
|
|
112
112
|
<template v-if="icon && icon !== 'system-point'">
|
|
113
113
|
<!-- 有 iconOptions 时启用带边框/渐变的盒子效果 -->
|
|
114
114
|
<PubinfoIcon
|
|
115
|
-
v-if="iconOptions"
|
|
115
|
+
v-if="iconOptions && computedBoxType"
|
|
116
116
|
small
|
|
117
117
|
:name="icon"
|
|
118
|
-
:box="computedBoxType
|
|
118
|
+
:box="computedBoxType!"
|
|
119
119
|
:size="20"
|
|
120
120
|
:angle="iconOptions?.angle"
|
|
121
121
|
:background="iconOptions?.background"
|
|
@@ -91,14 +91,7 @@ function stripPath(fullPath: string) {
|
|
|
91
91
|
return fullPath.split(/[?#]/)[0];
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
//
|
|
95
|
-
function findRouteRecordByElement(element: Tabbar.recordRaw) {
|
|
96
|
-
const pathOnly = stripPath(element.fullPath);
|
|
97
|
-
const all = [...routeStore.flatSystemRoutes, ...routeStore.flatRoutes] as any[];
|
|
98
|
-
return all.find(r => r.path === pathOnly);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// 解析该 tab 的 iconOptions(优先当前路由,其次面包屑链路上最近的一个)
|
|
94
|
+
// 解析该 tab 的 iconOptions(优先使用实际匹配的路由记录,兼容动态路由)
|
|
102
95
|
function resolveIconOptions(element: Tabbar.recordRaw): undefined | {
|
|
103
96
|
boxType?: 'square' | 'prism' | 'null'
|
|
104
97
|
angle?: number | string
|
|
@@ -106,22 +99,47 @@ function resolveIconOptions(element: Tabbar.recordRaw): undefined | {
|
|
|
106
99
|
radius?: number | string
|
|
107
100
|
iconColor?: string
|
|
108
101
|
} {
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
102
|
+
const resolved = router.resolve(element.fullPath);
|
|
103
|
+
const matched = [...(resolved.matched as any[])].reverse();
|
|
104
|
+
const matchedRecordWithIcon = matched.find(record => (record?.meta as any)?.iconOptions);
|
|
105
|
+
if (matchedRecordWithIcon?.meta?.iconOptions) {
|
|
106
|
+
return matchedRecordWithIcon.meta.iconOptions as any;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const pathOnly = stripPath(element.fullPath);
|
|
110
|
+
const all = [...routeStore.flatSystemRoutes, ...routeStore.flatRoutes] as any[];
|
|
111
|
+
let record = element.routeName
|
|
112
|
+
? all.find(r => r.name === element.routeName)
|
|
113
|
+
: undefined;
|
|
114
|
+
|
|
115
|
+
if (!record) {
|
|
116
|
+
record = all.find(r => r.path === pathOnly);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
let options = (record?.meta as any)?.iconOptions;
|
|
120
|
+
if (!options && record?.meta?.breadcrumbNeste?.length) {
|
|
121
|
+
const found = [...record.meta.breadcrumbNeste].reverse().find((it: any) => it?.iconOptions);
|
|
113
122
|
options = found?.iconOptions;
|
|
114
123
|
}
|
|
115
124
|
return options;
|
|
116
125
|
}
|
|
117
126
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
127
|
+
type ResolvedIconOptions = ReturnType<typeof resolveIconOptions>;
|
|
128
|
+
|
|
129
|
+
const dropdownIconOptions = computed<Record<string, ResolvedIconOptions>>(() => {
|
|
130
|
+
return tabbarStore.list.reduce<Record<string, ResolvedIconOptions>>((acc, element) => {
|
|
131
|
+
acc[element.tabId] = resolveIconOptions(element);
|
|
132
|
+
return acc;
|
|
133
|
+
}, {} as Record<string, ResolvedIconOptions>);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
function computeBoxType(options: ResolvedIconOptions): 'square' | 'prism' | undefined {
|
|
137
|
+
const bt = options?.boxType;
|
|
138
|
+
return bt && bt !== 'null' ? bt : undefined;
|
|
121
139
|
}
|
|
122
140
|
|
|
123
|
-
function getSafeIconColor(options:
|
|
124
|
-
return
|
|
141
|
+
function getSafeIconColor(options: ResolvedIconOptions): string | undefined {
|
|
142
|
+
return options?.iconColor || undefined;
|
|
125
143
|
}
|
|
126
144
|
</script>
|
|
127
145
|
|
|
@@ -165,21 +183,21 @@ function getSafeIconColor(options: ReturnType<typeof resolveIconOptions>): strin
|
|
|
165
183
|
<div :key="element.tabId" class="title" :title="element.customTitleList.find(item => item.fullPath === element.fullPath)?.title || generateTitle(element.title)" @click="router.push(element.fullPath)">
|
|
166
184
|
<template v-if="settingsStore.settings.tabbar.enableIcon && iconName(element.tabId === activedTabId, element.icon, element.activeIcon)">
|
|
167
185
|
<PubinfoIcon
|
|
168
|
-
v-if="
|
|
186
|
+
v-if="computeBoxType(dropdownIconOptions[element.tabId])"
|
|
169
187
|
small
|
|
170
188
|
:name="iconName(element.tabId === activedTabId, element.icon, element.activeIcon)!"
|
|
171
|
-
:box="computeBoxType(
|
|
189
|
+
:box="(computeBoxType(dropdownIconOptions[element.tabId]) as 'square' | 'prism')"
|
|
172
190
|
:size="16"
|
|
173
|
-
:angle="
|
|
174
|
-
:background="
|
|
175
|
-
:radius="
|
|
176
|
-
:color="(iconName(element.tabId === activedTabId, element.icon, element.activeIcon) || '').startsWith('antd:') ? (getSafeIconColor(
|
|
191
|
+
:angle="dropdownIconOptions[element.tabId]?.angle"
|
|
192
|
+
:background="dropdownIconOptions[element.tabId]?.background"
|
|
193
|
+
:radius="dropdownIconOptions[element.tabId]?.radius"
|
|
194
|
+
:color="(iconName(element.tabId === activedTabId, element.icon, element.activeIcon) || '').startsWith('antd:') ? (getSafeIconColor(dropdownIconOptions[element.tabId]) || '#ffffff') : undefined"
|
|
177
195
|
/>
|
|
178
196
|
<PubinfoIcon
|
|
179
197
|
v-else
|
|
180
198
|
:name="iconName(element.tabId === activedTabId, element.icon, element.activeIcon)!"
|
|
181
199
|
:size="16"
|
|
182
|
-
:color="(iconName(element.tabId === activedTabId, element.icon, element.activeIcon) || '').startsWith('antd:') ? getSafeIconColor(
|
|
200
|
+
:color="(iconName(element.tabId === activedTabId, element.icon, element.activeIcon) || '').startsWith('antd:') ? getSafeIconColor(dropdownIconOptions[element.tabId]) : undefined"
|
|
183
201
|
/>
|
|
184
202
|
</template>
|
|
185
203
|
{{ element.customTitleList.find(item => item.fullPath === element.fullPath)?.title || generateTitle(element.title) }}
|
|
@@ -246,14 +246,7 @@ function stripPath(fullPath: string) {
|
|
|
246
246
|
return fullPath.split(/[?#]/)[0];
|
|
247
247
|
}
|
|
248
248
|
|
|
249
|
-
//
|
|
250
|
-
function findRouteRecordByElement(element: Tabbar.recordRaw) {
|
|
251
|
-
const pathOnly = stripPath(element.fullPath);
|
|
252
|
-
const all = [...routeStore.flatSystemRoutes, ...routeStore.flatRoutes] as any[];
|
|
253
|
-
return all.find(r => r.path === pathOnly);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
// 解析该 tab 的 iconOptions(优先当前路由,其次面包屑链路上最近的一个)
|
|
249
|
+
// 解析该 tab 的 iconOptions(优先使用实际匹配的路由记录,兼容动态路由)
|
|
257
250
|
function resolveIconOptions(element: Tabbar.recordRaw): undefined | {
|
|
258
251
|
boxType?: 'square' | 'prism' | 'null'
|
|
259
252
|
angle?: number | string
|
|
@@ -261,24 +254,49 @@ function resolveIconOptions(element: Tabbar.recordRaw): undefined | {
|
|
|
261
254
|
radius?: number | string
|
|
262
255
|
iconColor?: string
|
|
263
256
|
} {
|
|
264
|
-
const
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
257
|
+
const resolved = router.resolve(element.fullPath);
|
|
258
|
+
const matched = [...(resolved.matched as any[])].reverse();
|
|
259
|
+
const matchedRecordWithIcon = matched.find(record => (record?.meta as any)?.iconOptions);
|
|
260
|
+
if (matchedRecordWithIcon?.meta?.iconOptions) {
|
|
261
|
+
return matchedRecordWithIcon.meta.iconOptions as any;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const pathOnly = stripPath(element.fullPath);
|
|
265
|
+
const all = [...routeStore.flatSystemRoutes, ...routeStore.flatRoutes] as any[];
|
|
266
|
+
let record = element.routeName
|
|
267
|
+
? all.find(r => r.name === element.routeName)
|
|
268
|
+
: undefined;
|
|
269
|
+
|
|
270
|
+
if (!record) {
|
|
271
|
+
record = all.find(r => r.path === pathOnly);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
let options = (record?.meta as any)?.iconOptions;
|
|
275
|
+
if (!options && record?.meta?.breadcrumbNeste?.length) {
|
|
276
|
+
const found = [...record.meta.breadcrumbNeste].reverse().find((it: any) => it?.iconOptions);
|
|
268
277
|
options = found?.iconOptions;
|
|
269
278
|
}
|
|
270
279
|
return options;
|
|
271
280
|
}
|
|
272
281
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
return
|
|
282
|
+
type ResolvedIconOptions = ReturnType<typeof resolveIconOptions>;
|
|
283
|
+
|
|
284
|
+
const tabIconOptions = computed<Record<string, ResolvedIconOptions>>(() => {
|
|
285
|
+
return tabbarStore.list.reduce<Record<string, ResolvedIconOptions>>((acc, element) => {
|
|
286
|
+
acc[element.tabId] = resolveIconOptions(element);
|
|
287
|
+
return acc;
|
|
288
|
+
}, {} as Record<string, ResolvedIconOptions>);
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
// 统一盒子类型:仅在显式指定为 square/prism 时启用盒子
|
|
292
|
+
function computeBoxType(options: ResolvedIconOptions): 'square' | 'prism' | undefined {
|
|
293
|
+
const bt = options?.boxType;
|
|
294
|
+
return bt && bt !== 'null' ? bt : undefined;
|
|
277
295
|
}
|
|
278
296
|
|
|
279
297
|
// 仅 AntD 图标使用安全颜色;无配置则为 undefined
|
|
280
|
-
function getSafeIconColor(options:
|
|
281
|
-
return
|
|
298
|
+
function getSafeIconColor(options: ResolvedIconOptions): string | undefined {
|
|
299
|
+
return options?.iconColor || undefined;
|
|
282
300
|
}
|
|
283
301
|
|
|
284
302
|
onMounted(() => {
|
|
@@ -368,15 +386,15 @@ onUnmounted(() => {
|
|
|
368
386
|
<template v-if="settingsStore.settings.tabbar.enableIcon && iconName(element.tabId === activedTabId, element.icon, element.activeIcon)">
|
|
369
387
|
<!-- 有 iconOptions 时启用带边框/渐变的盒子效果,与 Menu 保持一致 -->
|
|
370
388
|
<PubinfoIcon
|
|
371
|
-
v-if="
|
|
389
|
+
v-if="computeBoxType(tabIconOptions[element.tabId])"
|
|
372
390
|
small
|
|
373
391
|
:name="iconName(element.tabId === activedTabId, element.icon, element.activeIcon)!"
|
|
374
|
-
:box="computeBoxType(
|
|
392
|
+
:box="(computeBoxType(tabIconOptions[element.tabId]) as 'square' | 'prism')"
|
|
375
393
|
:size="16"
|
|
376
|
-
:angle="
|
|
377
|
-
:background="
|
|
378
|
-
:radius="
|
|
379
|
-
:color="(iconName(element.tabId === activedTabId, element.icon, element.activeIcon) || '').startsWith('antd:') ? (getSafeIconColor(
|
|
394
|
+
:angle="tabIconOptions[element.tabId]?.angle"
|
|
395
|
+
:background="tabIconOptions[element.tabId]?.background"
|
|
396
|
+
:radius="tabIconOptions[element.tabId]?.radius"
|
|
397
|
+
:color="(iconName(element.tabId === activedTabId, element.icon, element.activeIcon) || '').startsWith('antd:') ? (getSafeIconColor(tabIconOptions[element.tabId]) || '#ffffff') : undefined"
|
|
380
398
|
class="icon"
|
|
381
399
|
/>
|
|
382
400
|
<!-- 无 iconOptions 时保持原样(纯图标),但若提供图标色也生效 -->
|
|
@@ -384,7 +402,7 @@ onUnmounted(() => {
|
|
|
384
402
|
v-else
|
|
385
403
|
:name="iconName(element.tabId === activedTabId, element.icon, element.activeIcon)!"
|
|
386
404
|
:size="16"
|
|
387
|
-
:color="(iconName(element.tabId === activedTabId, element.icon, element.activeIcon) || '').startsWith('antd:') ? getSafeIconColor(
|
|
405
|
+
:color="(iconName(element.tabId === activedTabId, element.icon, element.activeIcon) || '').startsWith('antd:') ? getSafeIconColor(tabIconOptions[element.tabId]) : undefined"
|
|
388
406
|
class="icon"
|
|
389
407
|
/>
|
|
390
408
|
</template>
|
|
@@ -37,7 +37,7 @@ export interface UserStore {
|
|
|
37
37
|
logout: () => void
|
|
38
38
|
|
|
39
39
|
/** 修改密码 */
|
|
40
|
-
|
|
40
|
+
changePassword: (form: API.putRbacUserChangePasswordParams & {
|
|
41
41
|
token?: string | string[]
|
|
42
42
|
}) => Promise<API.ResponseDataVoid>
|
|
43
43
|
|
|
@@ -174,7 +174,7 @@ const useUserStore = defineStore<STORE_NAME.USER, UserStore>(
|
|
|
174
174
|
* @param form - 包含要修改的密码和令牌的表单数据
|
|
175
175
|
* @returns 修改密码的结果
|
|
176
176
|
*/
|
|
177
|
-
async function
|
|
177
|
+
async function changePassword(form: API.putRbacUserChangePasswordParams & { token?: string | string[] }) {
|
|
178
178
|
const headers = {} as AxiosRequestHeaders;
|
|
179
179
|
if (form.token) {
|
|
180
180
|
headers.authorization = form.token;
|
|
@@ -232,7 +232,7 @@ const useUserStore = defineStore<STORE_NAME.USER, UserStore>(
|
|
|
232
232
|
getPermissions,
|
|
233
233
|
login,
|
|
234
234
|
logout,
|
|
235
|
-
|
|
235
|
+
changePassword,
|
|
236
236
|
changeOrg,
|
|
237
237
|
setToken,
|
|
238
238
|
clean,
|
package/types/menu.d.ts
CHANGED