@rxdrag/website-lib-core 0.0.9 → 0.0.10

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.
@@ -1,12 +1,12 @@
1
- import { DATA_MOTION_POPUP, PopupAnimationConfig } from "../motion";
1
+ import { DATA_MOTION_OPENABLE, OpenableAnimationConfig } from "../motion";
2
2
  import { applyAnimation } from "./applyAnimation";
3
3
  import { gsap } from "gsap/dist/gsap";
4
4
  import {
5
5
  EVENT_OPEN,
6
6
  EVENT_CLOSE,
7
- DATA_POPUP,
8
- DATA_POPUP_ROLE,
9
- PopupRole,
7
+ DATA_OPENABLE,
8
+ DATA_OPENABLE_ROLE,
9
+ OpenAble,
10
10
  EVENT_SELECT,
11
11
  EVENT_UNSELECT,
12
12
  } from "./consts";
@@ -126,14 +126,14 @@ export class EventBus {
126
126
  }
127
127
  }
128
128
 
129
- export class PopupController {
129
+ export class OpenableController {
130
130
  constructor(protected doc: Document | undefined) {}
131
131
  protected unmountHandlers: (() => void)[] = [];
132
132
  protected eventBus = new EventBus();
133
133
 
134
134
  mount() {
135
135
  this.unmount();
136
- this.initPopupAnimations();
136
+ this.initOpenableAnimations();
137
137
  }
138
138
 
139
139
  unmount() {
@@ -142,38 +142,38 @@ export class PopupController {
142
142
  }
143
143
  /**
144
144
  * 打开弹出层
145
- * @param popupKey - 弹出层的唯一标识
145
+ * @param openableKey - 弹出层的唯一标识
146
146
  * @param target - 触发打开的目标元素
147
147
  */
148
- open = (popupKey: string, target: HTMLElement): void => {
148
+ open = (openableKey: string, target: HTMLElement): void => {
149
149
  if (!this.doc) return;
150
150
 
151
151
  try {
152
152
  // 查找 Modal 容器
153
- const modalContainer = this.getPopupContainer(popupKey);
153
+ const modalContainer = this.getOpenableContainer(openableKey);
154
154
  if (modalContainer) {
155
155
  modalContainer.classList.add("open");
156
- this.eventBus.emit(EVENT_OPEN, { key: popupKey, target });
156
+ this.eventBus.emit(EVENT_OPEN, { key: openableKey, target });
157
157
  } else {
158
- console.warn(`未找到弹出层: ${popupKey}`);
158
+ console.warn(`未找到弹出层: ${openableKey}`);
159
159
  }
160
160
  } catch (error) {
161
- console.error(`打开弹出层失败: ${popupKey}`, error);
161
+ console.error(`打开弹出层失败: ${openableKey}`, error);
162
162
  }
163
163
  };
164
164
 
165
165
  /**
166
166
  * 关闭弹出层
167
- * @param popupKey - 弹出层的唯一标识
167
+ * @param openableKey - 弹出层的唯一标识
168
168
  * @param target - 可选的目标元素,如果提供则使用该元素,否则查找容器
169
169
  */
170
- close = (popupKey: string, target?: HTMLElement): void => {
170
+ close = (openableKey: string, target?: HTMLElement): void => {
171
171
  if (!this.doc) return;
172
172
 
173
173
  try {
174
- const container = target || this.getPopupContainer(popupKey);
174
+ const container = target || this.getOpenableContainer(openableKey);
175
175
  if (!container) {
176
- console.warn(`找不到弹出层容器: ${popupKey}`);
176
+ console.warn(`找不到弹出层容器: ${openableKey}`);
177
177
  return;
178
178
  }
179
179
 
@@ -182,28 +182,30 @@ export class PopupController {
182
182
 
183
183
  // 触发关闭事件
184
184
  this.eventBus.emit(EVENT_CLOSE, {
185
- key: popupKey,
185
+ key: openableKey,
186
186
  target: container,
187
187
  });
188
188
  } catch (error) {
189
- console.error(`关闭弹出层失败: ${popupKey}`, error);
189
+ console.error(`关闭弹出层失败: ${openableKey}`, error);
190
190
  }
191
191
  };
192
192
 
193
193
  /**
194
194
  * 获取弹出层容器元素
195
- * @param popupKey - 弹出层的唯一标识
195
+ * @param openableKey - 弹出层的唯一标识
196
196
  * @returns 弹出层容器元素,如果未找到则返回undefined
197
197
  */
198
- getPopupContainer = (popupKey: string): HTMLElement | undefined => {
198
+ getOpenableContainer = (openableKey: string): HTMLElement | undefined => {
199
199
  if (!this.doc) return undefined;
200
200
 
201
201
  try {
202
202
  return this.doc.querySelector(
203
- `[${DATA_POPUP}="${popupKey}"][${DATA_POPUP_ROLE}="${PopupRole.ModalContainer}"], [${DATA_POPUP}="${popupKey}"][${DATA_POPUP_ROLE}="${PopupRole.PopoverContainer}"]`
203
+ `[${DATA_OPENABLE}="${openableKey}"][${DATA_OPENABLE_ROLE}="${OpenAble.ModalContainer}"],
204
+ [${DATA_OPENABLE}="${openableKey}"][${DATA_OPENABLE_ROLE}="${OpenAble.PopoverContainer}"],
205
+ [${DATA_OPENABLE}="${openableKey}"][${DATA_OPENABLE_ROLE}="${OpenAble.CollapseContainer}"]`
204
206
  ) as HTMLElement | undefined;
205
207
  } catch (error) {
206
- console.error(`获取弹出层容器失败: ${popupKey}`, error);
208
+ console.error(`获取弹出层容器失败: ${openableKey}`, error);
207
209
  return undefined;
208
210
  }
209
211
  };
@@ -212,22 +214,36 @@ export class PopupController {
212
214
  * 初始化弹窗动画
213
215
  * @returns 清理函数
214
216
  */
215
- initPopupAnimations = () => {
217
+ initOpenableAnimations = () => {
216
218
  const unsubscribe = this.onOpenAll((event) => {
217
219
  const openResponseElements = this.doc?.querySelectorAll(
218
- `[${DATA_MOTION_POPUP}]`
220
+ `[${DATA_MOTION_OPENABLE}]`
221
+ );
222
+ const containerElement = this.getOpenableContainer(event.key);
223
+ //处理循环嵌套的情况
224
+ const subContainers = containerElement?.querySelectorAll(
225
+ `[${DATA_OPENABLE_ROLE}="${OpenAble.CollapseContainer}"],
226
+ [${DATA_OPENABLE_ROLE}="${OpenAble.ModalContainer}"],
227
+ [${DATA_OPENABLE_ROLE}="${OpenAble.PopoverContainer}"]`
219
228
  );
220
- const containerElement = this.getPopupContainer(event.key);
221
229
  //响应open事件
222
230
  openResponseElements?.forEach((element) => {
231
+ let isInSubContainer = false;
232
+ subContainers?.forEach((subContainer) => {
233
+ if (subContainer.contains(element)) {
234
+ isInSubContainer = true;
235
+ return;
236
+ }
237
+ });
223
238
  if (
224
239
  this.doc?.defaultView &&
225
240
  element instanceof this.doc.defaultView?.HTMLElement &&
226
- containerElement?.contains(element)
241
+ containerElement?.contains(element) &&
242
+ !isInSubContainer
227
243
  ) {
228
- if (element.dataset.motionPopup) {
229
- const animation = JSON.parse(element.dataset.motionPopup) as
230
- | PopupAnimationConfig
244
+ if (element.dataset.motionOpenable) {
245
+ const animation = JSON.parse(element.dataset.motionOpenable) as
246
+ | OpenableAnimationConfig
231
247
  | undefined;
232
248
  if (animation?.initial) {
233
249
  applyInitialState(element, animation.initial);
@@ -241,7 +257,7 @@ export class PopupController {
241
257
 
242
258
  return () => {
243
259
  const closeResponseElements = this.doc?.querySelectorAll(
244
- `[${DATA_MOTION_POPUP}]`
260
+ `[${DATA_MOTION_OPENABLE}]`
245
261
  );
246
262
 
247
263
  //响应close事件
@@ -251,11 +267,11 @@ export class PopupController {
251
267
  element instanceof this.doc?.defaultView.HTMLElement
252
268
  ) {
253
269
  if (
254
- element.dataset.motionPopup &&
270
+ element.dataset.motionOpenable &&
255
271
  containerElement?.contains(element)
256
272
  ) {
257
- const animation = JSON.parse(element.dataset.motionPopup) as
258
- | PopupAnimationConfig
273
+ const animation = JSON.parse(element.dataset.motionOpenable) as
274
+ | OpenableAnimationConfig
259
275
  | undefined;
260
276
  if (animation?.close) {
261
277
  // 首先终止该元素上可能正在进行的所有动画(包括open动画)
@@ -278,22 +294,22 @@ export class PopupController {
278
294
  };
279
295
 
280
296
  public onOpen = (
281
- popupKey: string,
297
+ openableKey: string,
282
298
  callback: (event: PopupEvent) => VoidFunction | void
283
299
  ): (() => void) => {
284
300
  return this.onOpenAll((event) => {
285
- if (event.key === popupKey) {
301
+ if (event.key === openableKey) {
286
302
  return callback(event);
287
303
  }
288
304
  });
289
305
  };
290
306
 
291
307
  public onClose = (
292
- popupKey: string,
308
+ openableKey: string,
293
309
  callback: (event: PopupEvent) => void
294
310
  ) => {
295
311
  return this.onCloseAll((event) => {
296
- if (event.key === popupKey) {
312
+ if (event.key === openableKey) {
297
313
  callback(event);
298
314
  }
299
315
  });
@@ -1,7 +1,7 @@
1
- import { DATA_POPUP, DATA_POPUP_ROLE, PopupRole } from "./consts";
2
- import { PopupController } from "./popup";
1
+ import { DATA_OPENABLE, DATA_OPENABLE_ROLE, OpenAble } from "./consts";
2
+ import { OpenableController } from "./OpenableController";
3
3
 
4
- export class PopoverController extends PopupController {
4
+ export class PopoverController extends OpenableController {
5
5
  private static instances: Record<string, PopoverController> = {};
6
6
  private constructor(doc?: Document) {
7
7
  super(doc);
@@ -47,15 +47,15 @@ export class PopoverController extends PopupController {
47
47
  //console.log("====> mount popover", this.doc);
48
48
  super.mount();
49
49
  // 获取所有的 Popover 实例
50
- const popups = this.doc?.querySelectorAll(`[${DATA_POPUP}]`);
50
+ const popups = this.doc?.querySelectorAll(`[${DATA_OPENABLE}]`);
51
51
  popups?.forEach((popup) => {
52
- const popupKey = popup.getAttribute(DATA_POPUP);
52
+ const openableKey = popup.getAttribute(DATA_OPENABLE);
53
53
  //处理鼠标交互事件
54
- if (popupKey && popup) {
54
+ if (openableKey && popup) {
55
55
  if (
56
- popup.getAttribute(DATA_POPUP_ROLE) === PopupRole.PopoverContainer
56
+ popup.getAttribute(DATA_OPENABLE_ROLE) === OpenAble.PopoverContainer
57
57
  ) {
58
- const unsub = this.initPopover(popupKey, popup as HTMLElement);
58
+ const unsub = this.initPopover(openableKey, popup as HTMLElement);
59
59
  this.unmountHandlers.push(unsub);
60
60
  }
61
61
  }
@@ -68,12 +68,12 @@ export class PopoverController extends PopupController {
68
68
 
69
69
  /**
70
70
  * 初始化Popover的鼠标交互事件
71
- * @param popupKey - 弹出层的唯一标识
71
+ * @param openableKey - 弹出层的唯一标识
72
72
  * @param element - 弹出层的 DOM 元素
73
73
  * @returns 清理函数,用于移除事件监听器
74
74
  */
75
75
  public initPopover = (
76
- popupKey: string,
76
+ openableKey: string,
77
77
  element: HTMLElement
78
78
  ): (() => void) => {
79
79
  if (!this.doc) return () => {};
@@ -81,11 +81,11 @@ export class PopoverController extends PopupController {
81
81
  try {
82
82
  // 创建新的事件处理函数
83
83
  const handleMouseEnter = () => {
84
- this.open(popupKey, element);
84
+ this.open(openableKey, element);
85
85
  };
86
86
 
87
87
  const handleMouseLeave = () => {
88
- this.close(popupKey);
88
+ this.close(openableKey);
89
89
  };
90
90
 
91
91
  // 添加新的事件监听器
@@ -104,7 +104,7 @@ export class PopoverController extends PopupController {
104
104
  element.removeEventListener("touchend", handleMouseLeave, options as EventListenerOptions);
105
105
  };
106
106
  } catch (error) {
107
- console.error(`初始化Popover事件失败: ${popupKey}`, error);
107
+ console.error(`初始化Popover事件失败: ${openableKey}`, error);
108
108
  return () => {};
109
109
  }
110
110
  };
@@ -8,7 +8,7 @@ import {
8
8
  import { AnimationConfig } from "../motion";
9
9
  import { applyAnimation } from "./applyAnimation";
10
10
  import { EVENT_SELECT, EVENT_UNSELECT } from "./consts";
11
- import { EventBus, SelectionEvent } from "./popup";
11
+ import { EventBus, SelectionEvent } from "./OpenableController";
12
12
 
13
13
  export class TabsController {
14
14
  private static instances: Record<string, TabsController> = {};
@@ -1,8 +1,8 @@
1
1
  //弹层ID
2
- export const DATA_POPUP = "data-popup";
2
+ export const DATA_OPENABLE = "data-openable";
3
3
 
4
- //弹层角色,取值:PopupRole
5
- export const DATA_POPUP_ROLE = "data-popup-role";
4
+ //弹层角色,取值:Openable
5
+ export const DATA_OPENABLE_ROLE = "data-openable-role";
6
6
 
7
7
  //弹层CTA,用于跟踪用户点击行为
8
8
  export const DATA_POPUP_CTA = "data-popup-cta";
@@ -10,19 +10,22 @@ export const DATA_POPUP_CTA = "data-popup-cta";
10
10
  //已经进入过视窗
11
11
  export const DATA_VIEWPORT_ENTERED = "data-viewport-entered";
12
12
 
13
- export enum PopupRole {
13
+ export enum OpenAble {
14
14
  PopoverContainer = "popover-container",
15
15
  PopoverPanel = "popover-panel",
16
16
  ModalContainer = "modal-container",
17
17
  ModalTrigger = "modal-trigger",
18
18
  ModalPanel = "modal-panel",
19
19
  ModalCloser = "modal-closer",
20
+ CollapseContainer = "collapse-container",
21
+ CollapsePanel = "collapse-panel",
22
+ CollapseTrigger = "collapse-trigger",
20
23
  }
21
24
 
22
25
  /** 弹出层打开事件名称 */
23
- export const EVENT_OPEN = "popup-open";
26
+ export const EVENT_OPEN = "openable-open";
24
27
  /** 弹出层关闭事件名称 */
25
- export const EVENT_CLOSE = "popup-close";
28
+ export const EVENT_CLOSE = "openable-close";
26
29
 
27
30
  /** 元素选中事件名称,比如tab切换 */
28
31
  export const EVENT_SELECT = "element-select";
@@ -3,6 +3,7 @@ export * from "./utils";
3
3
  export * from "./ModalController";
4
4
  export * from "./AnimateController";
5
5
  export * from "./AosController";
6
+ export * from "./CollapseController";
6
7
  export * from "./PopoverController";
7
8
  export * from "./PageLoader";
8
9
  export * from "./TabsController";
@@ -42,7 +42,7 @@ export interface IEntify {
42
42
 
43
43
  getPostPaths(): Promise<unknown>;
44
44
 
45
- getPostBySlug(slug: string, coverSize: TSize | undefined): Promise<unknown>;
45
+ getPostBySlug(slug: string, coverSize: TSize | undefined): Promise<TPost | undefined>;
46
46
 
47
47
  getPostSlugs(): Promise<Array<string | undefined>>;
48
48
 
@@ -7,7 +7,6 @@ import {
7
7
  MediaOnProductFields,
8
8
  AttachmentOnProductQueryOptions,
9
9
  AttachmentOnProductFields,
10
- ProductRelatedPivotQueryOptions,
11
10
  ProductCategoryFields,
12
11
  } from "@rxdrag/rxcms-models";
13
12
  import { TSize } from "../types";
@@ -52,6 +51,8 @@ export function newQueryProductOptions(imagSize?: TSize) {
52
51
  ProductFields.extends,
53
52
  ProductFields.description,
54
53
  ProductFields.features,
54
+ ProductFields.relatedSlugs,
55
+ ProductFields.relatedSlugs,
55
56
  ])
56
57
  .meta(newPageMetaOptions())
57
58
  .mediaPivots(creatProductMediaOptions(imagSize))
@@ -71,16 +72,6 @@ export function newQueryProductOptions(imagSize?: TSize) {
71
72
  ]).file(["url"])
72
73
  )
73
74
  )
74
- .relatedPivot(
75
- new ProductRelatedPivotQueryOptions().target(
76
- new ProductQueryOptions()
77
- .title()
78
- .shortTitle()
79
- .slug()
80
- .description()
81
- .mediaPivots(creatProductMediaOptions())
82
- )
83
- )
84
75
  .category([
85
76
  ProductCategoryFields.id,
86
77
  ProductCategoryFields.slug,
@@ -1,21 +1,63 @@
1
- import { Product, ProductBoolExp, ProductOrderBy, ProductDistinctExp } from "@rxdrag/rxcms-models";
1
+ import {
2
+ Product,
3
+ ProductBoolExp,
4
+ ProductOrderBy,
5
+ ProductDistinctExp,
6
+ } from "@rxdrag/rxcms-models";
2
7
  import { newQueryProductOptions } from "./newQueryProductOptions";
3
8
  import { queryOneEntity } from "./queryOneEntity";
4
9
  import { EnvVariables, TSize } from "../types";
5
- import { TProduct } from "../view-model";
10
+ import { productToViewModel, TProduct } from "../view-model";
11
+ import { queryEntityList } from "./queryEntityList";
6
12
 
7
- export async function queryOneProductBySlug(slug: string, imageSize: TSize | undefined, envVariables: EnvVariables) {
13
+ export async function queryOneProductBySlug(
14
+ slug: string,
15
+ imageSize: TSize | undefined,
16
+ envVariables: EnvVariables
17
+ ) {
18
+ const product = await queryOneEntity<
19
+ Product,
20
+ ProductBoolExp,
21
+ ProductOrderBy,
22
+ ProductDistinctExp
23
+ >(
24
+ newQueryProductOptions(imageSize).setQueryArgs({
25
+ where: {
26
+ slug: {
27
+ _eq: slug,
28
+ },
29
+ },
30
+ }),
31
+ envVariables
32
+ );
33
+
34
+ if (!product) {
35
+ return product;
36
+ }
37
+
38
+ const tProduct = productToViewModel(product)!;
8
39
 
9
- const product = await queryOneEntity<Product, ProductBoolExp, ProductOrderBy, ProductDistinctExp>(
10
- newQueryProductOptions(imageSize)
11
- .setQueryArgs({
40
+ if (product?.relatedSlugs?.length) {
41
+ const result = await queryEntityList<
42
+ Product,
43
+ ProductBoolExp,
44
+ ProductOrderBy,
45
+ ProductDistinctExp
46
+ >(
47
+ newQueryProductOptions(imageSize).setQueryArgs({
12
48
  where: {
13
49
  slug: {
14
- "_eq": slug
50
+ _in: product?.relatedSlugs,
15
51
  },
16
52
  },
17
53
  }),
18
- envVariables
19
- );
20
- return product as TProduct | undefined;
54
+ envVariables
55
+ );
56
+
57
+ tProduct.related = result?.items?.map((pro) => productToViewModel(pro)) as
58
+ | TProduct[]
59
+ | undefined;
60
+ }
61
+
62
+ return tProduct;
21
63
  }
@@ -21,13 +21,7 @@ export async function queryOneTheme(envVariables: EnvVariables) {
21
21
  ThemeDistinctExp
22
22
  >(
23
23
  new ThemeQueryOptions(
24
- [
25
- ThemeFields.id,
26
- ThemeFields.name,
27
- ThemeFields.css,
28
- ThemeFields.settings,
29
- ThemeFields.tailwindConfig,
30
- ],
24
+ [ThemeFields.id, ThemeFields.name, ThemeFields.settings],
31
25
  {
32
26
  where: {
33
27
  lang: {
@@ -1,12 +1,10 @@
1
1
  import {
2
2
  AttachmentOnProduct,
3
3
  Media,
4
- MediaOnProduct,
5
4
  Post,
6
5
  PostCategory,
7
6
  Product,
8
7
  ProductCategory,
9
- ProductRelatedPivot,
10
8
  User,
11
9
  WebsiteSettings,
12
10
  } from "@rxdrag/rxcms-models";
@@ -116,23 +114,9 @@ export function productToViewModel(product?: Product): TProduct | undefined {
116
114
  attachments:
117
115
  product?.attachmentPivots &&
118
116
  attachmentsToViewModel(product?.attachmentPivots),
119
- related: relatedPovitToViewModel(product?.relatedPivot),
120
117
  };
121
118
  }
122
119
 
123
- export function relatedPovitToViewModel(
124
- related?: ProductRelatedPivot[]
125
- ): TProduct[] | undefined {
126
- if (!related) {
127
- return undefined;
128
- }
129
- return related.map((relatedPivot) => {
130
- return productToViewModel({
131
- ...relatedPivot.target,
132
- seqValue: relatedPivot.seqValue,
133
- })!;
134
- });
135
- }
136
120
 
137
121
  export function productListToViewModel(
138
122
  products?: ListResult<Product>
package/src/lib/utils.ts CHANGED
@@ -31,11 +31,15 @@ export function productsPagination(options: {
31
31
  });
32
32
  }
33
33
 
34
- export function productBreadcrumbs(product?: TProduct) {
34
+ export function productBreadcrumbs(
35
+ product?: TProduct,
36
+ homeTitle: string = "Home",
37
+ productsTitle: string = "Products"
38
+ ) {
35
39
  // 生成面包屑
36
40
  const breadcrumbs: TBreadcrumbItem[] = [
37
- { title: "Home", href: "/" },
38
- { title: "Products", href: "/products/page/1" },
41
+ { title: homeTitle, href: "/" },
42
+ { title: productsTitle, href: "/products/page/1" },
39
43
  ];
40
44
 
41
45
  const category = product?.category;
@@ -51,11 +55,15 @@ export function productBreadcrumbs(product?: TProduct) {
51
55
  return breadcrumbs;
52
56
  }
53
57
 
54
- export function productListBreadcrumbs(category?: TProductCategory | null) {
58
+ export function productListBreadcrumbs(
59
+ category?: TProductCategory | null,
60
+ homeTitle: string = "Home",
61
+ productsTitle: string = "Products"
62
+ ) {
55
63
  // 生成面包屑
56
64
  const breadcrumbs: TBreadcrumbItem[] = [
57
- { title: "Home", href: "/" },
58
- { title: "Products", href: "/products/page/1" },
65
+ { title: homeTitle, href: "/" },
66
+ { title: productsTitle, href: "/products/page/1" },
59
67
  ];
60
68
  if (category?.name) {
61
69
  breadcrumbs.push({
@@ -65,11 +73,15 @@ export function productListBreadcrumbs(category?: TProductCategory | null) {
65
73
  return breadcrumbs;
66
74
  }
67
75
 
68
- export function postBreadcrumbs(post?: TPost) {
76
+ export function postBreadcrumbs(
77
+ post: TPost | undefined,
78
+ homeTitle: string = "Home",
79
+ postsTitle: string = "Posts"
80
+ ) {
69
81
  // 生成面包屑
70
82
  const breadcrumbs: TBreadcrumbItem[] = [
71
- { title: "Home", href: "/" },
72
- { title: "Posts", href: "/posts/page/1" },
83
+ { title: homeTitle, href: "/" },
84
+ { title: postsTitle, href: "/posts/page/1" },
73
85
  ];
74
86
 
75
87
  const category = post?.category;
@@ -85,11 +97,15 @@ export function postBreadcrumbs(post?: TPost) {
85
97
  return breadcrumbs;
86
98
  }
87
99
 
88
- export function postListBreadcrumbs(category?: TPostCategory) {
100
+ export function postListBreadcrumbs(
101
+ category?: TPostCategory | null,
102
+ homeTitle: string = "Home",
103
+ postsTitle: string = "Posts"
104
+ ) {
89
105
  // 生成面包屑
90
106
  const breadcrumbs: TBreadcrumbItem[] = [
91
- { title: "Home", href: "/" },
92
- { title: "Blog", href: "/posts/page/1" },
107
+ { title: homeTitle, href: "/" },
108
+ { title: postsTitle, href: "/posts/page/1" },
93
109
  ];
94
110
  if (category?.name) {
95
111
  breadcrumbs.push({
@@ -99,10 +115,10 @@ export function postListBreadcrumbs(category?: TPostCategory) {
99
115
  return breadcrumbs;
100
116
  }
101
117
 
102
- export function pageBreadcrumbs(title: string) {
118
+ export function pageBreadcrumbs(title: string, homeTitle: string = "Home") {
103
119
  // 生成面包屑
104
120
  const breadcrumbs: TBreadcrumbItem[] = [
105
- { title: "Home", href: "/" },
121
+ { title: homeTitle, href: "/" },
106
122
  { title },
107
123
  ];
108
124
  return breadcrumbs;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  AnchorOffsets,
3
3
  AosAnimationConfig,
4
- PopupAnimationConfig,
4
+ OpenableAnimationConfig,
5
5
  AnimationConfig,
6
6
  } from "./types";
7
7
 
@@ -17,7 +17,7 @@ export const DATA_MOTION_TAP = "data-motion-tap";
17
17
  //入视图
18
18
  export const DATA_MOTION_INVIEW = "data-motion-inview";
19
19
  //弹层动画,有动作的组件联动
20
- export const DATA_MOTION_POPUP = "data-motion-popup";
20
+ export const DATA_MOTION_OPENABLE = "data-motion-openable";
21
21
  //数字动画
22
22
  export const DATA_MOTION_NUMBER = "data-motion-number";
23
23
  export const DATA_MOTION_NUMBER_ONCE = "data-motion-number-once";
@@ -340,7 +340,7 @@ export const AOS_ANIMATIONS: Record<string, AosAnimationConfig | undefined> = {
340
340
 
341
341
  export const POPUP_ANIMATIONS: Record<
342
342
  string,
343
- PopupAnimationConfig | undefined
343
+ OpenableAnimationConfig | undefined
344
344
  > = {
345
345
  // 缩放效果
346
346
  scale: {
@@ -1,12 +1,12 @@
1
1
  import { merge } from "lodash-es";
2
- import { PopupAnimationConfig } from "./types";
2
+ import { OpenableAnimationConfig } from "./types";
3
3
  import { POPUP_ANIMATIONS } from "./consts";
4
4
 
5
5
  export function normalizePopupAnimation(
6
- motion?: PopupAnimationConfig | string
6
+ motion?: OpenableAnimationConfig | string
7
7
  ) {
8
8
  let presetKey: string | undefined;
9
- let normalMotion: PopupAnimationConfig | undefined;
9
+ let normalMotion: OpenableAnimationConfig | undefined;
10
10
  if (typeof motion === "string") {
11
11
  presetKey = motion;
12
12
  } else {
@@ -122,7 +122,7 @@ export type HoverAnimationConfig = AnimationConfig & {
122
122
  exit?: AnimationConfig;
123
123
  };
124
124
 
125
- export type PopupAnimationConfig = AnimationConfig & {
125
+ export type OpenableAnimationConfig = AnimationConfig & {
126
126
  // 初始状态设置 (gsap.set) - 立即应用,不产生动画
127
127
  initial?: AnimationStyles;
128
128
  // 打开时的动画