@rxdrag/website-lib-core 0.0.21 → 0.0.22

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rxdrag/website-lib-core",
3
- "version": "0.0.21",
3
+ "version": "0.0.22",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./index.ts"
@@ -25,9 +25,9 @@
25
25
  "eslint": "^7.32.0",
26
26
  "typescript": "^5",
27
27
  "@rxdrag/entify-hooks": "0.2.43",
28
- "@rxdrag/tsconfig": "0.2.0",
28
+ "@rxdrag/eslint-config-custom": "0.2.12",
29
29
  "@rxdrag/slate-preview": "1.2.57",
30
- "@rxdrag/eslint-config-custom": "0.2.12"
30
+ "@rxdrag/tsconfig": "0.2.0"
31
31
  },
32
32
  "dependencies": {
33
33
  "clsx": "^2.1.0",
@@ -35,7 +35,7 @@
35
35
  "lodash-es": "^4.17.21",
36
36
  "react": "^18.2.0",
37
37
  "react-dom": "^18.2.0",
38
- "@rxdrag/rxcms-models": "0.3.50"
38
+ "@rxdrag/rxcms-models": "0.3.51"
39
39
  },
40
40
  "peerDependencies": {
41
41
  "astro": "^4.0.0 || ^5.0.0"
@@ -10,12 +10,11 @@ export const initLinks = () => {
10
10
  links.forEach((anchorLink) => {
11
11
  // 从链接URL中提取路径部分
12
12
  try {
13
- const linkUrl = new URL(anchorLink.href);
13
+ const linkUrl = anchorLink.href ? new URL(anchorLink.href) : null;
14
14
  const linkPath =
15
15
  anchorLink.dataset.activedPath === "true"
16
- ? linkUrl.pathname
16
+ ? linkUrl?.pathname
17
17
  : anchorLink.dataset.activedPath;
18
- console.log("====>", linkPath, currentPath);
19
18
  // 检查当前路径是否与链接路径匹配或是其子路径
20
19
  if (
21
20
  currentPath === linkPath ||
@@ -66,14 +66,15 @@ export class PageLoader implements IPageLoader {
66
66
 
67
67
  try {
68
68
  // 使用标志来确保回调只执行一次
69
- let hasExecuted = false;
69
+ //let hasExecuted = false;
70
70
 
71
71
  // 主事件处理函数,调用所有注册的回调
72
72
  const handleEvent = () => {
73
+ console.log("===>页面转场事件触发,执行回调");
73
74
  // 如果已经执行过,则不再执行
74
- if (hasExecuted) return;
75
+ //if (hasExecuted) return;
75
76
 
76
- hasExecuted = true;
77
+ //hasExecuted = true;
77
78
 
78
79
  // 执行所有回调
79
80
  this.callbacks.forEach((callback) => {
@@ -85,9 +86,9 @@ export class PageLoader implements IPageLoader {
85
86
  });
86
87
 
87
88
  // 重置执行标志,允许下一次页面转场时再次执行
88
- setTimeout(() => {
89
- hasExecuted = false;
90
- }, 100);
89
+ // setTimeout(() => {
90
+ // hasExecuted = false;
91
+ // }, 100);
91
92
  };
92
93
 
93
94
  // 只监听一个事件,优先使用 astro:page-load
@@ -16,7 +16,7 @@ import {
16
16
  queryProductCategories,
17
17
  queryProducts,
18
18
  queryUserPosts,
19
- searchProducts,
19
+ fulltextSearch,
20
20
  } from "./lib";
21
21
  import { IQueryOptions } from "@rxdrag/entify-hooks";
22
22
  import { queryAllProducts } from "./lib/queryAllProducts";
@@ -72,8 +72,8 @@ export class Entify implements IEntify {
72
72
  return await queryFeaturedProducts(count, this.envVariables);
73
73
  }
74
74
 
75
- public async getLatestPosts(count?: number) {
76
- return await queryLatestPosts(count, this.envVariables);
75
+ public async getLatestPosts(count?: number, coverSize?: TSize) {
76
+ return await queryLatestPosts(count, coverSize, this.envVariables);
77
77
  }
78
78
 
79
79
  public async getHomePage(): Promise<Page | undefined> {
@@ -371,8 +371,8 @@ export class Entify implements IEntify {
371
371
  return (await queryUserPosts({ userId }, this.envVariables))?.items;
372
372
  }
373
373
 
374
- public async searchProducts(keyword: string) {
375
- return await searchProducts(keyword, this.envVariables);
374
+ public async fulltextSearch(keyword: string, imageSize: TSize | undefined) {
375
+ return await fulltextSearch(keyword, imageSize,this.envVariables);
376
376
  }
377
377
 
378
378
  public async getUserPaths() {
@@ -8,7 +8,7 @@ import {
8
8
  TProductCategory,
9
9
  TUser,
10
10
  } from "./view-model";
11
- import { Lang, Page, PageType, Theme, Website } from "@rxdrag/rxcms-models";
11
+ import { Lang, Page, PageType, SearchIndex, Theme, Website } from "@rxdrag/rxcms-models";
12
12
 
13
13
  export type PostsOptions = {
14
14
  category?: string;
@@ -43,7 +43,7 @@ export interface IEntify {
43
43
 
44
44
  getFeaturedProducts(count?: number): Promise<TProduct[] | undefined>;
45
45
 
46
- getLatestPosts(count?: number): Promise<TPost[] | undefined>;
46
+ getLatestPosts(count?: number, coverSize?: TSize): Promise<TPost[] | undefined>;
47
47
 
48
48
  getPosts(options: PostsOptions): Promise<TPost[] | undefined>;
49
49
 
@@ -123,7 +123,7 @@ export interface IEntify {
123
123
 
124
124
  getUserPosts(userId: string): Promise<TPost[] | undefined>;
125
125
 
126
- searchProducts(keyword: string): Promise<ListResult<TProduct> | undefined>;
126
+ fulltextSearch(keyword: string, imageSize: TSize | undefined): Promise<ListResult<SearchIndex> | undefined>;
127
127
 
128
128
  getUserPaths(): Promise<unknown>;
129
129
 
@@ -0,0 +1,61 @@
1
+ import {
2
+ PublishableStatus,
3
+ SearchIndex,
4
+ SearchIndexBoolExp,
5
+ SearchIndexOrderBy,
6
+ SearchIndexDistinctExp,
7
+ SearchIndexQueryOptions,
8
+ SearchIndexFields,
9
+ MediaQueryOptions,
10
+ } from "@rxdrag/rxcms-models";
11
+ import { queryEntityList } from "./queryEntityList";
12
+ import { ListResult } from "@rxdrag/entify-hooks";
13
+ import { EnvVariables, TSize } from "../types";
14
+
15
+ export async function fulltextSearch(
16
+ keyword: string,
17
+ imageSize: TSize | undefined,
18
+ envVariables: EnvVariables
19
+ ) {
20
+
21
+ const queryOptions = new SearchIndexQueryOptions(
22
+ [
23
+ SearchIndexFields.id,
24
+ SearchIndexFields.title,
25
+ SearchIndexFields.summary,
26
+ SearchIndexFields.sourceId,
27
+ SearchIndexFields.sourceType,
28
+ SearchIndexFields.sourceLang,
29
+ SearchIndexFields.sourceSlug,
30
+ ],
31
+ {
32
+ limit: 100,
33
+ where: {
34
+ sourceLang: {
35
+ _eq: envVariables.language,
36
+ },
37
+ [SearchIndexFields.sourceStatus]: {
38
+ _eq: PublishableStatus.published,
39
+ },
40
+ content: {
41
+ _match: keyword,
42
+ },
43
+ }
44
+ }
45
+ ).media(new MediaQueryOptions().file([
46
+ "thumbnail(width:400, height:320)",
47
+ "url",
48
+ imageSize
49
+ ? `resize(width:${imageSize.width}, height:${imageSize.height})`
50
+ : "resize(width:500, height:400)",
51
+ ])).setNoQuery(!keyword);
52
+
53
+ const result = await queryEntityList<
54
+ SearchIndex,
55
+ SearchIndexBoolExp,
56
+ SearchIndexOrderBy,
57
+ SearchIndexDistinctExp
58
+ >(queryOptions, envVariables);
59
+
60
+ return result as ListResult<SearchIndex> | undefined;
61
+ }
@@ -25,5 +25,5 @@ export * from "./queryProductsInMenu";
25
25
  export * from "./queryUserPosts";
26
26
  export * from "./queryWebSiteSettings";
27
27
  export * from "./upsertEntity";
28
- export * from "./searchProducts";
28
+ export * from "./fulltextSearch";
29
29
  export * from "./sendEmail";
@@ -12,11 +12,12 @@ import {
12
12
  PublishableStatus,
13
13
  } from "@rxdrag/rxcms-models";
14
14
  import { queryEntityList } from "./queryEntityList";
15
- import { EnvVariables } from "../types";
15
+ import { EnvVariables, TSize } from "../types";
16
16
  import { TPost } from "../view-model";
17
17
 
18
18
  export async function queryLatestPosts(
19
19
  count: number = 2,
20
+ coverSize: TSize | undefined,
20
21
  envVariables: EnvVariables
21
22
  ) {
22
23
  const result = await queryEntityList<
@@ -56,7 +57,7 @@ export async function queryLatestPosts(
56
57
  .cover(
57
58
  new MediaQueryOptions().file([
58
59
  "thumbnail",
59
- "resize(width:480, height:180)",
60
+ `resize(width:${coverSize?.width || 480}, height:${coverSize?.height || 180})`,
60
61
  ])
61
62
  )
62
63
  .author(
@@ -76,6 +76,8 @@ export interface QuoteRequest {
76
76
  company?: string;
77
77
  message?: string;
78
78
  fromCta?: string;
79
+ // 电话或者whatsapp
80
+ mobile?: string;
79
81
  // 蜜罐字段,用于检测机器人
80
82
  phone: string;
81
83
  // 一个加密字段,用于防机器人,点击时附加一个加密的字符串
@@ -91,12 +93,17 @@ export type ContactFormProps = {
91
93
  submitAlign?: "left" | "center" | "right";
92
94
  actionUrl?: string;
93
95
  formSalt: string;
96
+ classNames?: {
97
+ submit?: string;
98
+ container?: string;
99
+ };
94
100
  labels?: {
95
101
  name?: string;
96
102
  email?: string;
97
103
  company?: string;
98
104
  message?: string;
99
105
  submit?: string;
106
+ mobile?: string;
100
107
  };
101
108
  };
102
109
 
@@ -107,6 +114,7 @@ export const ContactForm = forwardRef<HTMLDivElement, ContactFormProps>(
107
114
  actionUrl = "/api/ask-for-quote",
108
115
  formSalt,
109
116
  labels = {},
117
+ classNames = {},
110
118
  } = props;
111
119
  const [formData, setFormData] = useState<QuoteRequest>({
112
120
  name: "",
@@ -115,6 +123,8 @@ export const ContactForm = forwardRef<HTMLDivElement, ContactFormProps>(
115
123
  message: "",
116
124
  phone: "", // 初始化蜜罐字段
117
125
  });
126
+ const submitClassName = classNames.submit || "btn-primary";
127
+ const containerClassName = classNames.container || "gap-y-6";
118
128
  // 错误状态
119
129
  const [errors, setErrors] = useState<FormErrors>({});
120
130
  const [submitting, setSubmitting] = useState(false);
@@ -236,8 +246,21 @@ export const ContactForm = forwardRef<HTMLDivElement, ContactFormProps>(
236
246
  return (
237
247
  <div
238
248
  ref={ref}
239
- className="py-4 grid max-w-2xl grid-cols-1 gap-x-6 gap-y-6 sm:grid-cols-2"
249
+ className={clsx(
250
+ "py-4 grid max-w-2xl grid-cols-1 gap-x-6 sm:grid-cols-2",
251
+ containerClassName
252
+ )}
240
253
  >
254
+ <Input
255
+ className="sm:col-span-1"
256
+ inputClassName="mt-2 block w-full rounded-md outline-none border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-sky-600 sm:text-sm sm:leading-6"
257
+ label={labels?.name || "Your Name"}
258
+ labelClassName="block text-sm font-medium leading-6 text-gray-900"
259
+ name="name"
260
+ value={formData.name}
261
+ onChange={handleChange}
262
+ error={errors.name}
263
+ />
241
264
  <Input
242
265
  className="sm:col-span-1"
243
266
  inputClassName="mt-2 block w-full rounded-md outline-none border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-sky-600 sm:text-sm sm:leading-6"
@@ -254,15 +277,16 @@ export const ContactForm = forwardRef<HTMLDivElement, ContactFormProps>(
254
277
  <Input
255
278
  className="sm:col-span-1"
256
279
  inputClassName="mt-2 block w-full rounded-md outline-none border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-sky-600 sm:text-sm sm:leading-6"
257
- label={labels?.name || "Your Name"}
280
+ label={labels?.mobile || "Your tel"}
258
281
  labelClassName="block text-sm font-medium leading-6 text-gray-900"
259
- name="name"
260
- value={formData.name}
282
+ name="mobile"
283
+ required={true}
284
+ autoFocus={true}
285
+ value={formData.mobile}
261
286
  onChange={handleChange}
262
- error={errors.name}
263
287
  />
264
288
  <Input
265
- className="col-span-full"
289
+ className="sm:col-span-1"
266
290
  inputClassName="mt-2 block w-full rounded-md outline-none border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-sky-600 sm:text-sm sm:leading-6"
267
291
  label={labels?.company || "Company"}
268
292
  labelClassName="block text-sm font-medium leading-6 text-gray-900"
@@ -309,7 +333,10 @@ export const ContactForm = forwardRef<HTMLDivElement, ContactFormProps>(
309
333
  </div>
310
334
  )}
311
335
  <Submit
312
- className="flex gap-2 items-center relative shadow-sm btn btn-primary btn-lg nowrap"
336
+ className={clsx(
337
+ "flex gap-2 items-center relative shadow-sm btn btn-lg nowrap",
338
+ submitClassName
339
+ )}
313
340
  title={labels?.submit || "Send Message"}
314
341
  spinner={
315
342
  <div className="left-8 flex items-center justify-center">
@@ -9,6 +9,11 @@ export type MediasProps = {
9
9
  // Aspect ratio, format is `aspect-[width/height]`
10
10
  aspect?: string;
11
11
  thumbnailAspect?: string;
12
+ classNames?: {
13
+ mainArea?: string;
14
+ navigation?: string;
15
+ thumbnail?: string;
16
+ }
12
17
  };
13
18
 
14
19
  export const Medias = forwardRef<HTMLDivElement, MediasProps>((props, ref) => {
@@ -18,8 +23,10 @@ export const Medias = forwardRef<HTMLDivElement, MediasProps>((props, ref) => {
18
23
  children,
19
24
  aspect = "aspect-[1/1]",
20
25
  thumbnailAspect = "aspect-[5/4]",
26
+ classNames,
21
27
  ...rest
22
28
  } = props;
29
+ const { mainArea, navigation, thumbnail } = classNames || {};
23
30
  const [selectedId, setSelectedId] = useState<string | undefined | null>(
24
31
  value?.externalVideoUrl ? "video" : value?.medias?.[0]?.id || ""
25
32
  );
@@ -136,7 +143,7 @@ export const Medias = forwardRef<HTMLDivElement, MediasProps>((props, ref) => {
136
143
  <div ref={ref} className={clsx("flex flex-col", className)} {...rest}>
137
144
  {children}
138
145
  {/* Main display area */}
139
- <div className={clsx("relative group")}>
146
+ <div className={clsx("relative group", mainArea)}>
140
147
  {canPrevious && (
141
148
  <button
142
149
  onClick={handlePrevious}
@@ -211,7 +218,7 @@ export const Medias = forwardRef<HTMLDivElement, MediasProps>((props, ref) => {
211
218
  </div>
212
219
 
213
220
  {/* Thumbnail navigation */}
214
- <div className="relative mt-4">
221
+ <div className={clsx("relative mt-4", navigation)}>
215
222
  <div className="flex items-stretch gap-2">
216
223
  {totalItems > 6 && (
217
224
  <button
@@ -222,7 +229,8 @@ export const Medias = forwardRef<HTMLDivElement, MediasProps>((props, ref) => {
222
229
  "transition-colors duration-200 rounded-l-md",
223
230
  !canPrevious
224
231
  ? "bg-gray-100 text-gray-400 cursor-not-allowed"
225
- : "bg-gray-200 hover:bg-gray-300 text-gray-700"
232
+ : "bg-gray-200 hover:bg-gray-300 text-gray-700",
233
+ thumbnail,
226
234
  )}
227
235
  aria-label="Previous"
228
236
  >
@@ -1,77 +0,0 @@
1
- import {
2
- Product,
3
- ProductBoolExp,
4
- ProductOrderBy,
5
- ProductDistinctExp,
6
- ProductFields,
7
- ProductQueryOptions,
8
- PublishableStatus,
9
- } from "@rxdrag/rxcms-models";
10
- import { queryEntityList } from "./queryEntityList";
11
- import { newQueryProductsMediaOptions } from "./newQueryProductsMediaOptions";
12
- import { ListResult } from "@rxdrag/entify-hooks";
13
- import { EnvVariables } from "../types";
14
- import { TProduct } from "../view-model";
15
-
16
- export async function searchProducts(
17
- keyword: string,
18
- envVariables: EnvVariables
19
- ) {
20
- const keyExp = keyword
21
- ? {
22
- _or: [
23
- {
24
- title: {
25
- _like: `%${keyword}%`,
26
- },
27
- },
28
- {
29
- [ProductFields.description]: {
30
- _like: `%${keyword}%`,
31
- },
32
- },
33
- ],
34
- }
35
- : undefined;
36
-
37
- const keyArray = keyExp ? [keyExp] : [];
38
-
39
- const queryOptions = new ProductQueryOptions(
40
- [
41
- ProductFields.id,
42
- ProductFields.slug,
43
- ProductFields.title,
44
- ProductFields.shortTitle,
45
- ProductFields.description,
46
- ],
47
- {
48
- limit: 100,
49
- where: {
50
- _and: [
51
- {
52
- lang: {
53
- abbr: {
54
- _eq: envVariables.language,
55
- },
56
- },
57
- },
58
- {
59
- [ProductFields.status]: {
60
- _eq: PublishableStatus.published,
61
- },
62
- },
63
- ...keyArray,
64
- ],
65
- },
66
- orderBy: [{ [ProductFields.seqValue]: "asc" }],
67
- }
68
- ).mediaPivots(newQueryProductsMediaOptions());
69
-
70
- const result = await queryEntityList<
71
- Product,
72
- ProductBoolExp,
73
- ProductOrderBy,
74
- ProductDistinctExp
75
- >(queryOptions, envVariables);
76
- return result as ListResult<TProduct> | undefined;
77
- }