@rxdrag/website-lib-core 0.0.4 → 0.0.7

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.
Files changed (168) hide show
  1. package/index.ts +1 -0
  2. package/package.json +12 -13
  3. package/src/entify/Entify.ts +365 -0
  4. package/{dist/entify/index.d.ts → src/entify/index.ts} +4 -4
  5. package/src/entify/lib/createEntifyClient.ts +23 -0
  6. package/{dist/entify/lib/index.d.ts → src/entify/lib/index.ts} +29 -29
  7. package/src/entify/lib/langFields.ts +12 -0
  8. package/src/entify/lib/newAvatarQueryOptions.ts +5 -0
  9. package/src/entify/lib/newOgImageQueryOptions.ts +6 -0
  10. package/src/entify/lib/newPageMetaOptions.ts +20 -0
  11. package/src/entify/lib/newQueryPostOptions.ts +41 -0
  12. package/src/entify/lib/newQueryProductOptions.ts +90 -0
  13. package/src/entify/lib/newQueryProductsMediaOptions.ts +26 -0
  14. package/src/entify/lib/queryAllProducts.ts +27 -0
  15. package/src/entify/lib/queryEntityList.ts +44 -0
  16. package/src/entify/lib/queryFeaturedProducts.ts +47 -0
  17. package/src/entify/lib/queryLangs.ts +47 -0
  18. package/src/entify/lib/queryLatestPosts.ts +65 -0
  19. package/src/entify/lib/queryOneEntity.ts +67 -0
  20. package/src/entify/lib/queryOnePostById.ts +21 -0
  21. package/src/entify/lib/queryOnePostBySlug.ts +21 -0
  22. package/src/entify/lib/queryOnePostCategoryBySlug.ts +30 -0
  23. package/src/entify/lib/queryOneProductById.ts +20 -0
  24. package/src/entify/lib/queryOneProductBySlug.ts +21 -0
  25. package/src/entify/lib/queryOneProductCategoryBySlug.ts +30 -0
  26. package/src/entify/lib/queryOneTheme.ts +76 -0
  27. package/src/entify/lib/queryOneUser.ts +38 -0
  28. package/src/entify/lib/queryPostCategories.ts +48 -0
  29. package/src/entify/lib/queryPostSlugs.ts +32 -0
  30. package/src/entify/lib/queryPosts.ts +92 -0
  31. package/src/entify/lib/queryProductCategories.ts +44 -0
  32. package/src/entify/lib/queryProducts.ts +69 -0
  33. package/src/entify/lib/queryProductsInMenu.ts +31 -0
  34. package/src/entify/lib/queryUserIds.ts +24 -0
  35. package/src/entify/lib/queryUserPosts.ts +74 -0
  36. package/src/entify/lib/queryWebSiteSettings.ts +29 -0
  37. package/src/entify/lib/searchProducts.ts +70 -0
  38. package/src/entify/lib/sendEmail.ts +8 -0
  39. package/src/entify/lib/toQueryOptions.ts +20 -0
  40. package/src/entify/lib/upsertEntity.ts +9 -0
  41. package/src/entify/types/index.ts +2 -0
  42. package/src/entify/types/utils.ts +4 -0
  43. package/src/entify/types/variables.ts +7 -0
  44. package/src/entify/view-model/funcs.ts +271 -0
  45. package/src/entify/view-model/index.ts +2 -0
  46. package/src/entify/view-model/models.ts +143 -0
  47. package/{dist/index.d.ts → src/index.ts} +5 -5
  48. package/src/motion/consts.ts +598 -0
  49. package/{dist/motion/index.d.ts → src/motion/index.ts} +2 -2
  50. package/src/motion/types.ts +46 -0
  51. package/src/react/components/EnquiryForm/Input.tsx +52 -0
  52. package/src/react/components/EnquiryForm/Submit.tsx +30 -0
  53. package/src/react/components/EnquiryForm/Textarea.tsx +51 -0
  54. package/src/react/components/EnquiryForm/index.tsx +334 -0
  55. package/src/react/components/GoogleConsent/CookieItemPanel.tsx +81 -0
  56. package/src/react/components/GoogleConsent/CumtomizedModal.tsx +149 -0
  57. package/src/react/components/GoogleConsent/GoogleConsent.tsx +101 -0
  58. package/src/react/components/GoogleConsent/README.md +1 -0
  59. package/src/react/components/GoogleConsent/gtags.ts +68 -0
  60. package/src/react/components/GoogleConsent/index.ts +3 -0
  61. package/src/react/components/GoogleConsent/types.ts +18 -0
  62. package/src/react/components/GoogleConsent//345/217/202/350/200/203.md +4 -0
  63. package/src/react/components/Medias/index.tsx +347 -0
  64. package/src/react/components/ProductCard/ProductCard.tsx +23 -0
  65. package/src/react/components/ProductCard/ProductCardPreview.tsx +12 -0
  66. package/src/react/components/ProductCard/ProductCta/index.tsx +41 -0
  67. package/src/react/components/ProductCard/ProductCta/style.css +4 -0
  68. package/src/react/components/ProductCard/ProductDescription/index.tsx +13 -0
  69. package/src/react/components/ProductCard/ProductDescription/style.css +6 -0
  70. package/src/react/components/ProductCard/ProductMedia/index.tsx +34 -0
  71. package/src/react/components/ProductCard/ProductMedia/style.css +6 -0
  72. package/src/react/components/ProductCard/ProductTitle/index.tsx +7 -0
  73. package/src/react/components/ProductCard/ProductTitle/style.css +4 -0
  74. package/src/react/components/ProductCard/ProductView.tsx +35 -0
  75. package/{dist/react/components/ProductCard/index.d.ts → src/react/components/ProductCard/index.ts} +6 -6
  76. package/src/react/components/ProductCard/useQueryProduct.ts +32 -0
  77. package/src/react/components/RichTextOutline/index.tsx +76 -0
  78. package/src/react/components/RichTextOutline/useAcitviedHeading.ts +54 -0
  79. package/src/react/components/RichTextOutline/useAnchorScroll.ts +24 -0
  80. package/src/react/components/Scroller.tsx +7 -0
  81. package/src/react/components/SearchInput.tsx +34 -0
  82. package/src/react/components/Share/index.tsx +69 -0
  83. package/src/react/components/Share/socials.tsx +79 -0
  84. package/src/react/components/Share//350/265/204/346/226/231.md +7 -0
  85. package/src/react/components/ToTop/index.tsx +33 -0
  86. package/src/react/components/ToTop.tsx +33 -0
  87. package/{dist/react/components/index.d.ts → src/react/components/index.ts} +8 -8
  88. package/src/react/hooks/index.ts +1 -0
  89. package/src/react/hooks/useScroll.ts +23 -0
  90. package/{dist/react/index.d.ts → src/react/index.ts} +2 -2
  91. package/src/robots.ts +4 -0
  92. package/src/scripts/actions.ts +304 -0
  93. package/src/scripts/consts.ts +32 -0
  94. package/src/scripts/events.ts +33 -0
  95. package/{dist/scripts/index.d.ts → src/scripts/index.ts} +3 -3
  96. package/dist/entify/Entify.d.ts +0 -138
  97. package/dist/entify/lib/createEntifyClient.d.ts +0 -3
  98. package/dist/entify/lib/langFields.d.ts +0 -2
  99. package/dist/entify/lib/newAvatarQueryOptions.d.ts +0 -2
  100. package/dist/entify/lib/newOgImageQueryOptions.d.ts +0 -2
  101. package/dist/entify/lib/newPageMetaOptions.d.ts +0 -2
  102. package/dist/entify/lib/newQueryPostOptions.d.ts +0 -3
  103. package/dist/entify/lib/newQueryProductOptions.d.ts +0 -3
  104. package/dist/entify/lib/newQueryProductsMediaOptions.d.ts +0 -3
  105. package/dist/entify/lib/queryAllProducts.d.ts +0 -4
  106. package/dist/entify/lib/queryEntityList.d.ts +0 -3
  107. package/dist/entify/lib/queryFeaturedProducts.d.ts +0 -4
  108. package/dist/entify/lib/queryLangs.d.ts +0 -4
  109. package/dist/entify/lib/queryLatestPosts.d.ts +0 -4
  110. package/dist/entify/lib/queryOneEntity.d.ts +0 -5
  111. package/dist/entify/lib/queryOnePostById.d.ts +0 -3
  112. package/dist/entify/lib/queryOnePostBySlug.d.ts +0 -3
  113. package/dist/entify/lib/queryOnePostCategoryBySlug.d.ts +0 -3
  114. package/dist/entify/lib/queryOneProductById.d.ts +0 -3
  115. package/dist/entify/lib/queryOneProductBySlug.d.ts +0 -3
  116. package/dist/entify/lib/queryOneProductCategoryBySlug.d.ts +0 -3
  117. package/dist/entify/lib/queryOneTheme.d.ts +0 -3
  118. package/dist/entify/lib/queryOneUser.d.ts +0 -3
  119. package/dist/entify/lib/queryPostCategories.d.ts +0 -4
  120. package/dist/entify/lib/queryPostSlugs.d.ts +0 -4
  121. package/dist/entify/lib/queryPosts.d.ts +0 -10
  122. package/dist/entify/lib/queryProductCategories.d.ts +0 -4
  123. package/dist/entify/lib/queryProducts.d.ts +0 -6
  124. package/dist/entify/lib/queryProductsInMenu.d.ts +0 -2
  125. package/dist/entify/lib/queryUserIds.d.ts +0 -4
  126. package/dist/entify/lib/queryUserPosts.d.ts +0 -9
  127. package/dist/entify/lib/queryWebSiteSettings.d.ts +0 -3
  128. package/dist/entify/lib/searchProducts.d.ts +0 -4
  129. package/dist/entify/lib/sendEmail.d.ts +0 -3
  130. package/dist/entify/lib/toQueryOptions.d.ts +0 -3
  131. package/dist/entify/lib/upsertEntity.d.ts +0 -2
  132. package/dist/entify/types/index.d.ts +0 -2
  133. package/dist/entify/types/utils.d.ts +0 -4
  134. package/dist/entify/types/variables.d.ts +0 -7
  135. package/dist/entify/view-model/funcs.d.ts +0 -20
  136. package/dist/entify/view-model/index.d.ts +0 -2
  137. package/dist/entify/view-model/models.d.ts +0 -119
  138. package/dist/index.mjs +0 -40514
  139. package/dist/index.mjs.map +0 -1
  140. package/dist/motion/consts.d.ts +0 -77
  141. package/dist/motion/types.d.ts +0 -26
  142. package/dist/react/components/EnquiryForm/Input.d.ts +0 -15
  143. package/dist/react/components/EnquiryForm/Submit.d.ts +0 -8
  144. package/dist/react/components/EnquiryForm/Textarea.d.ts +0 -13
  145. package/dist/react/components/EnquiryForm/index.d.ts +0 -22
  146. package/dist/react/components/Medias/index.d.ts +0 -8
  147. package/dist/react/components/ProductCard/ProductCard.d.ts +0 -15
  148. package/dist/react/components/ProductCard/ProductCardPreview.d.ts +0 -2
  149. package/dist/react/components/ProductCard/ProductCta/index.d.ts +0 -5
  150. package/dist/react/components/ProductCard/ProductDescription/index.d.ts +0 -2
  151. package/dist/react/components/ProductCard/ProductMedia/index.d.ts +0 -7
  152. package/dist/react/components/ProductCard/ProductTitle/index.d.ts +0 -2
  153. package/dist/react/components/ProductCard/ProductView.d.ts +0 -5
  154. package/dist/react/components/ProductCard/useQueryProduct.d.ts +0 -2
  155. package/dist/react/components/RichTextOutline/index.d.ts +0 -8
  156. package/dist/react/components/RichTextOutline/useAcitviedHeading.d.ts +0 -1
  157. package/dist/react/components/Scroller.d.ts +0 -3
  158. package/dist/react/components/SearchInput.d.ts +0 -2
  159. package/dist/react/components/Share/index.d.ts +0 -6
  160. package/dist/react/components/Share/socials.d.ts +0 -10
  161. package/dist/react/components/ToTop.d.ts +0 -5
  162. package/dist/react/hooks/index.d.ts +0 -1
  163. package/dist/react/hooks/useScroll.d.ts +0 -2
  164. package/dist/robots.d.ts +0 -2
  165. package/dist/scripts/actions.d.ts +0 -85
  166. package/dist/scripts/consts.d.ts +0 -21
  167. package/dist/scripts/events.d.ts +0 -11
  168. package/dist/style.css +0 -98
@@ -0,0 +1,6 @@
1
+ .x-figure .product-media {
2
+ overflow: hidden;
3
+ display: flex;
4
+ align-items: center;
5
+ justify-content: center;
6
+ }
@@ -0,0 +1,7 @@
1
+ import { HTMLAttributes } from "react";
2
+ import "./style.css";
3
+
4
+ export function ProductTitle(props: HTMLAttributes<HTMLHeadingElement>) {
5
+ const { className, ...rest } = props;
6
+ return <h3 className={"product-title " + className} {...rest} />;
7
+ }
@@ -0,0 +1,4 @@
1
+ .x-figure .product-title{
2
+ margin-top: 0.6rem;
3
+ padding-top: 0;
4
+ }
@@ -0,0 +1,35 @@
1
+ import { Product } from "@rxdrag/rxcms-models";
2
+ import { ProductCardProps } from "./ProductCard";
3
+ import { Figcaption, Figure, FigureContent } from "@rxdrag/slate-preview";
4
+ import { ProductMedia } from "./ProductMedia";
5
+ import { ProductTitle } from "./ProductTitle";
6
+ import { ProductDescription } from "./ProductDescription";
7
+ import { ProductCta } from "./ProductCta";
8
+
9
+ export function ProductView(
10
+ props: {
11
+ product?: Product;
12
+ } & ProductCardProps
13
+ ) {
14
+ const { product, node } = props;
15
+
16
+ const title = node?.title || product?.title;
17
+ const description = node?.description || product?.description;
18
+
19
+ return (
20
+ <Figure>
21
+ <FigureContent width={node?.width} align={node?.align}>
22
+ <a href={`/products/${product?.slug}`}>
23
+ <ProductMedia product={product} aspect={node?.aspect} />
24
+ </a>
25
+ </FigureContent>
26
+ <Figcaption width={node?.width} align={node?.align}>
27
+ <a href={`/products/${product?.slug}`}>
28
+ <ProductTitle>{title}</ProductTitle>
29
+ </a>
30
+ <ProductDescription>{description}</ProductDescription>
31
+ <ProductCta product={product} />
32
+ </Figcaption>
33
+ </Figure>
34
+ );
35
+ }
@@ -1,6 +1,6 @@
1
- export * from "./ProductCta";
2
- export * from "./ProductTitle";
3
- export * from "./ProductDescription";
4
- export * from "./ProductCard";
5
- export * from "./ProductCardPreview";
6
- export * from "./ProductMedia";
1
+ export * from "./ProductCta";
2
+ export * from "./ProductTitle";
3
+ export * from "./ProductDescription";
4
+ export * from "./ProductCard";
5
+ export * from "./ProductCardPreview";
6
+ export * from "./ProductMedia";
@@ -0,0 +1,32 @@
1
+ import { useEffect, useRef, useState } from "react";
2
+ import { Product } from "@rxdrag/rxcms-models";
3
+
4
+ export function useQueryProduct(productId?: string, websiteId?: string) {
5
+ const active = useRef<boolean>(false);
6
+ const [product, setProduct] = useState<Product | undefined>({});
7
+
8
+ const url = websiteId
9
+ ? `/${websiteId}/api/product/${productId}`
10
+ : `/api/product/${productId}`;
11
+
12
+ useEffect(() => {
13
+ if (active.current && !productId) {
14
+ return;
15
+ }
16
+
17
+ fetch(url)
18
+ .then((res) => res.json())
19
+ .then((data) => {
20
+ setProduct(data);
21
+ active.current = true;
22
+ });
23
+ }, [productId]);
24
+
25
+ useEffect(() => {
26
+ return () => {
27
+ active.current = false;
28
+ };
29
+ });
30
+
31
+ return product;
32
+ }
@@ -0,0 +1,76 @@
1
+ import { extractOutline, mdxToSlate } from "@rxdrag/slate-preview";
2
+ import { forwardRef, ReactNode, useEffect } from "react";
3
+ import { useAcitviedHeading } from "./useAcitviedHeading";
4
+ import clsx from "clsx";
5
+
6
+ export type RichTextOutlineProps = {
7
+ className?: string;
8
+ itemClassName?: string;
9
+ value?: string;
10
+ //滚动偏移量
11
+ yOffset?: number;
12
+ style?: React.CSSProperties;
13
+ };
14
+
15
+ export const RichTextOutline = forwardRef<
16
+ HTMLUListElement,
17
+ RichTextOutlineProps
18
+ >((props, ref) => {
19
+ const { className, itemClassName, value, yOffset = 100, ...rest } = props;
20
+ const activiedId = useAcitviedHeading();
21
+ const nodes = mdxToSlate(value ?? "");
22
+ const outline = extractOutline(nodes ?? []);
23
+
24
+ useEffect(() => {
25
+ const handleHashChange = () => {
26
+ const element = document.getElementById(
27
+ window.location.hash.substring(1)
28
+ );
29
+ if (element) {
30
+ const y =
31
+ element.getBoundingClientRect().top + window.scrollY - yOffset;
32
+ window.scrollTo({ top: y, behavior: "smooth" });
33
+ }
34
+ };
35
+
36
+ window.addEventListener("hashchange", handleHashChange);
37
+
38
+ return () => {
39
+ window.removeEventListener("hashchange", handleHashChange);
40
+ };
41
+ }, []);
42
+
43
+ return outline?.length ? (
44
+ <ul ref={ref} className={className} {...rest}>
45
+ {outline?.map((item, index) => {
46
+ return (
47
+ <li
48
+ key={item?.key + index}
49
+ className={clsx(
50
+ activiedId === item?.key ? "actived" : "",
51
+ itemClassName
52
+ )}
53
+ >
54
+ <a
55
+ href={`#${item?.key}`}
56
+ onClick={(e) => {
57
+ e.preventDefault();
58
+ const element = document.getElementById(item?.key);
59
+ if (element) {
60
+ const yOffset = -100; // 偏移量
61
+ const y =
62
+ element.getBoundingClientRect().top +
63
+ window.scrollY +
64
+ yOffset;
65
+ window.scrollTo({ top: y, behavior: "smooth" });
66
+ }
67
+ }}
68
+ >
69
+ {item?.text}
70
+ </a>
71
+ </li>
72
+ );
73
+ })}
74
+ </ul>
75
+ ) : null;
76
+ });
@@ -0,0 +1,54 @@
1
+ import { useCallback, useEffect, useState } from 'react';
2
+
3
+ export function useAcitviedHeading() {
4
+ const [activeId, setActiveId] = useState<string | null>(null);
5
+
6
+ const handleScroll = useCallback(() => {
7
+ const anchorElements = document.querySelectorAll('a[href^="#"]');
8
+ let closestId = null;
9
+ let closestDistance = Infinity;
10
+
11
+ anchorElements.forEach((element) => {
12
+ const id = element.getAttribute('href')?.slice(1) || '';
13
+ const targetElement = document.getElementById(id);
14
+ if (targetElement) {
15
+ const { top } = targetElement.getBoundingClientRect();
16
+ const distance = Math.abs(top);
17
+ // 寻找最接近视口顶部但不超过视口顶部的锚点
18
+ if (top <= 160 && distance < closestDistance) {
19
+ closestId = id;
20
+ closestDistance = distance;
21
+ }
22
+ }
23
+ });
24
+
25
+ setActiveId(closestId);
26
+ }, []);
27
+
28
+ useEffect(() => {
29
+ const handleHashChange = () => {
30
+ const hash = window.location.hash.substring(1); // 获取哈希值(去掉#)
31
+ setActiveId(hash);
32
+
33
+ const element = document.getElementById(hash);
34
+ if (element) {
35
+ const yOffset = -100; // 偏移量
36
+ const y = element.getBoundingClientRect().top + window.scrollY - yOffset;
37
+ window.scrollTo({ top: y, behavior: 'smooth' });
38
+ }
39
+ };
40
+
41
+ window.addEventListener('hashchange', handleHashChange);
42
+ window.addEventListener('scroll', handleScroll);
43
+
44
+ // 初始化时检查当前哈希值
45
+ handleHashChange();
46
+
47
+ return () => {
48
+ window.removeEventListener('hashchange', handleHashChange);
49
+ window.removeEventListener('scroll', handleScroll);
50
+ };
51
+ }, [handleScroll]);
52
+
53
+ return activeId;
54
+ }
@@ -0,0 +1,24 @@
1
+ import { useCallback, useEffect } from 'react';
2
+
3
+ export function useAnchorScroll() {
4
+ const handleAnchorClick = useCallback((event: MouseEvent): void => {
5
+ const target = event.target as HTMLAnchorElement;
6
+ if (target.tagName === 'A' && target.getAttribute('href')?.startsWith('#')) {
7
+ event.preventDefault();
8
+ const id = target.getAttribute('href')?.slice(1);
9
+ const element = document.getElementById(id || '');
10
+ if (element) {
11
+ const yOffset = -100; // 假设你想要元素距离顶部100px
12
+ const y = element.getBoundingClientRect().top + window.pageYOffset + yOffset;
13
+ window.scrollTo({ top: y, behavior: 'smooth' });
14
+ }
15
+ }
16
+ }, []);
17
+
18
+ useEffect(() => {
19
+ document.addEventListener('click', handleAnchorClick);
20
+ return () => document.removeEventListener('click', handleAnchorClick);
21
+ }, [handleAnchorClick]);
22
+ }
23
+
24
+ export default useAnchorScroll;
@@ -0,0 +1,7 @@
1
+ import { useScroll } from "../hooks";
2
+
3
+ export function Scroller(props: { threshold?: number }) {
4
+ const { threshold } = props;
5
+ useScroll(threshold);
6
+ return <></>;
7
+ }
@@ -0,0 +1,34 @@
1
+ import { forwardRef, useState } from "react";
2
+
3
+ export type SearchProps = React.InputHTMLAttributes<HTMLInputElement>;
4
+
5
+ export const SearchInput = forwardRef<HTMLInputElement, SearchProps>(
6
+ (props, ref) => {
7
+ const [keyword, setKeyword] = useState<string>();
8
+
9
+ // const navigate = useNavigate();
10
+ // const [, setOpen] = useXModalState();
11
+
12
+ const handleKeyEnter = (event: React.KeyboardEvent<HTMLElement>) => {
13
+ if (event.key !== "Enter" || !keyword) {
14
+ return;
15
+ }
16
+ // setOpen?.(false);
17
+ const encodedKeyword = encodeURIComponent(keyword || "");
18
+ if (encodedKeyword) {
19
+ //navigate(`/search?keyword=${encodedKeyword}`);
20
+ }
21
+ };
22
+
23
+ return (
24
+ <input
25
+ ref={ref}
26
+ name="q"
27
+ onKeyDown={handleKeyEnter}
28
+ value={keyword}
29
+ onChange={(e) => setKeyword(e.target.value)}
30
+ {...props}
31
+ />
32
+ );
33
+ }
34
+ );
@@ -0,0 +1,69 @@
1
+ import { forwardRef, useEffect, useState } from "react";
2
+ import type { IconListType } from "./socials";
3
+ import { iconList } from "./socials";
4
+ import clsx from "clsx";
5
+
6
+ export type ShareProps = {
7
+ socials?: string[],
8
+ size?: "xs" | "sm" | "md" | "lg" | "xl",
9
+ className?: string,
10
+ }
11
+
12
+ function getPageDetails() {
13
+ if (typeof window === 'undefined') {
14
+ return null;
15
+ }
16
+ const details = {
17
+ url: window?.location?.href,
18
+ title: document?.title || "null",
19
+ description: 'null', // 默认为空字符串
20
+ };
21
+
22
+ const descriptionMetaTag = document.querySelector('meta[name="description"]');
23
+ if (descriptionMetaTag) {
24
+ details.description = (descriptionMetaTag as HTMLMetaElement).content;
25
+ }
26
+
27
+ return details;
28
+ }
29
+
30
+ export const Share = forwardRef<HTMLDivElement, ShareProps>((props: ShareProps, ref) => {
31
+ const { className, ...rest } = props;
32
+ const [socialList, setSolicalList] = useState<IconListType>();
33
+
34
+ const details = getPageDetails();
35
+
36
+ useEffect(() => {
37
+ setSolicalList(iconList)
38
+ }, [props.socials]);
39
+
40
+ // 生成每个社交媒体的分享链接
41
+ const generateLink = (key: string) => {
42
+ const social = iconList[key];
43
+ if (!social) return '#';
44
+ return social.url(details?.url || "", details?.title, details?.description);
45
+ };
46
+
47
+
48
+ return (
49
+ <div ref={ref} className={clsx("flex items-center", className)}>
50
+ <div className="flex space-x-3">
51
+ {Object.keys(socialList || {}).map((key) => (
52
+ <a
53
+ key={key}
54
+ href={generateLink(key)}
55
+ target="_blank"
56
+ rel="noopener noreferrer"
57
+ title={`Share on ${iconList[key].title}`}
58
+ className="flex h-6 w-6 items-center justify-center text-gray-400 hover:text-gray-500"
59
+ >
60
+ <svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24" focusable="false" aria-hidden="true">
61
+ {iconList[key].path}
62
+ </svg>
63
+ </a>
64
+ ))
65
+ }
66
+ </div>
67
+ </div>
68
+ );
69
+ });
@@ -0,0 +1,79 @@
1
+
2
+ export interface IconListType {
3
+ [key: string]: {
4
+ title: string;
5
+ path: JSX.Element;
6
+ url: (l: string, t?: string, ti?: string) => string;
7
+ color: string;
8
+ viewBox?: string;
9
+ };
10
+ }
11
+
12
+ export const iconList: IconListType = {
13
+ linkedin: {
14
+ title: "LinkedIn",
15
+ path: (
16
+ <path d="M6.5 21.5h-5v-13h5v13zM4 6.5C2.5 6.5 1.5 5.3 1.5 4s1-2.4 2.5-2.4c1.6 0 2.5 1 2.6 2.5 0 1.4-1 2.5-2.6 2.5zm11.5 6c-1 0-2 1-2 2v7h-5v-13h5V10s1.6-1.5 4-1.5c3 0 5 2.2 5 6.3v6.7h-5v-7c0-1-1-2-2-2z" />
17
+ ),
18
+ color: "#0073b1",
19
+ url: (l, t, ti) =>
20
+ `https://www.linkedin.com/sharing/share-offsite/?url=${encodeURIComponent(l)}&title=${encodeURIComponent(ti || "")}&summary=${encodeURIComponent(t || "")}`,
21
+ },
22
+ facebook: {
23
+ title: "Facebook",
24
+ path: (
25
+ <path d="M24 12a12 12 0 10-13.9 11.9v-8.4h-3V12h3V9.4c0-3 1.8-4.7 4.6-4.7l2.6.2v3h-1.5c-1.5 0-2 .9-2 1.8V12h3.4l-.5 3.5h-2.8v8.4A12 12 0 0024 12z" />
26
+ ),
27
+ color: "#0076FB",
28
+ url: (l) => `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(l)}`,
29
+ },
30
+ twitter: {
31
+ title: "X",
32
+ path: (
33
+ <path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"></path>
34
+ ),
35
+ color: "#0F1419",
36
+ url: (l, t) => `https://twitter.com/intent/tweet?text=${t}&url=${encodeURIComponent(l)}`,
37
+ },
38
+ whatsapp: {
39
+ title: "WhatsApp",
40
+ path: (
41
+ <path d="M17.5 14.4l-2-1c-.3 0-.5-.1-.7.2l-1 1.1c-.1.2-.3.3-.6.1s-1.3-.5-2.4-1.5a9 9 0 01-1.7-2c-.1-.3 0-.5.2-.6l.4-.6c.2-.1.2-.3.3-.5v-.5L9 7c-.2-.6-.4-.5-.6-.5h-.6c-.2 0-.5 0-.8.4-.2.3-1 1-1 2.5s1 2.8 1.2 3c.2.2 2.1 3.2 5.1 4.5l1.7.6a4 4 0 001.9.2c.5-.1 1.7-.8 2-1.5.2-.6.2-1.2.1-1.4l-.5-.3M12 21.8a9.9 9.9 0 01-5-1.4l-.4-.2-3.7 1 1-3.7-.2-.3a9.9 9.9 0 01-1.5-5.3 9.9 9.9 0 0116.8-7 9.8 9.8 0 013 7 9.9 9.9 0 01-10 9.9m8.4-18.3A11.8 11.8 0 0012.1 0 12 12 0 001.8 17.8L0 24l6.4-1.6a11.9 11.9 0 005.6 1.4 12 12 0 0012-11.9 11.8 11.8 0 00-3.5-8.4z" />
42
+ ),
43
+ color: "#25D366",
44
+ url: (l, t) => `https://api.whatsapp.com/send?text=${encodeURIComponent(t || "")} ${encodeURIComponent(l)}`,
45
+ },
46
+ reddit: {
47
+ title: "Reddit",
48
+ path: (
49
+ <path d="M12 0A12 12 0 000 12a12 12 0 0012 12 12 12 0 0012-12A12 12 0 0012 0zm5.01 4.74c.69 0 1.25.56 1.25 1.25a1.25 1.25 0 01-2.5.06l-2.6-.55-.8 3.75c1.83.07 3.48.63 4.68 1.49.3-.31.73-.5 1.2-.5.97 0 1.76.8 1.76 1.76 0 .72-.43 1.33-1.01 1.61a3.11 3.11 0 01.04.52c0 2.7-3.13 4.87-7 4.87-3.88 0-7-2.17-7-4.87 0-.18 0-.36.04-.53A1.75 1.75 0 014.03 12a1.75 1.75 0 012.96-1.26 8.52 8.52 0 014.74-1.5l.89-4.17a.34.34 0 01.14-.2.35.35 0 01.24-.04l2.9.62a1.21 1.21 0 011.11-.7zM9.25 12a1.25 1.25 0 101.25 1.25c0-.69-.56-1.25-1.25-1.25zm5.5 0a1.25 1.25 0 000 2.5 1.25 1.25 0 000-2.5zm-5.47 3.99a.33.33 0 00-.23.1.33.33 0 000 .46c.84.84 2.49.91 2.96.91.48 0 2.1-.06 2.96-.91a.36.36 0 00.03-.47.33.33 0 00-.46 0c-.55.54-1.68.73-2.51.73-.83 0-1.98-.2-2.51-.73a.33.33 0 00-.24-.1z" />
50
+ ),
51
+ color: "#FF4500",
52
+ url: (l, t) => `https://www.reddit.com/submit?url=${encodeURIComponent(l)}&title=${encodeURIComponent(t || "")}`,
53
+ },
54
+ // telegram: {
55
+ // title: "Telegram",
56
+ // path: (
57
+ // <path d="M23.91 3.79L20.3 20.84c-.25 1.21-.98 1.5-2 .94l-5.5-4.07-2.66 2.57c-.3.3-.55.56-1.1.56-.72 0-.6-.27-.84-.95L6.3 13.7.85 12c-1.18-.35-1.19-1.16.26-1.75l21.26-8.2c.97-.43 1.9.24 1.53 1.73z" />
58
+ // ),
59
+ // color: "#0088CC",
60
+ // url: (l, t) => `https://telegram.me/share/msg?url=${encodeURIComponent(l)}&text=${encodeURIComponent(t || "")}`,
61
+ // },
62
+
63
+ // pinterest: {
64
+ // title: "Pinterest",
65
+ // path: (
66
+ // <path d="M0 12C0 17.123 3.211 21.497 7.73 23.218C7.62 22.281 7.503 20.736 7.755 19.652C7.972 18.72 9.156 13.714 9.156 13.714C9.156 13.714 8.799 12.999 8.799 11.94C8.799 10.28 9.761 9.04 10.96 9.04C11.98 9.04 12.472 9.805 12.472 10.722C12.472 11.747 11.819 13.279 11.482 14.7C11.201 15.889 12.079 16.859 13.251 16.859C15.374 16.859 17.007 14.62 17.007 11.388C17.007 8.527 14.951 6.528 12.016 6.528C8.618 6.528 6.623 9.077 6.623 11.712C6.623 12.739 7.018 13.839 7.512 14.438C7.55412 14.4832 7.58387 14.5386 7.59841 14.5986C7.61295 14.6587 7.61177 14.7215 7.595 14.781C7.504 15.159 7.302 15.97 7.263 16.136C7.21 16.354 7.09 16.401 6.863 16.295C5.371 15.601 4.439 13.42 4.439 11.668C4.439 7.899 7.176 4.439 12.331 4.439C16.475 4.439 19.696 7.392 19.696 11.338C19.696 15.455 17.101 18.769 13.497 18.769C12.286 18.769 11.149 18.139 10.759 17.396C10.759 17.396 10.16 19.678 10.015 20.236C9.733 21.32 8.951 22.692 8.466 23.471C9.584 23.815 10.77 24 12 24C18.627 24 24 18.627 24 12C24 5.373 18.627 0 12 0C5.373 0 0 5.373 0 12Z" />
67
+ // ),
68
+ // color: "#c8232c",
69
+ // url: (l) => `http://pinterest.com/pin/create/link/?url=${encodeURIComponent(l)}`,
70
+ // },
71
+ // email: {
72
+ // title: "Email",
73
+ // path: (
74
+ // <path d="M20 4H4a2 2 0 00-2 2v12c0 1.1.9 2 2 2h16a2 2 0 002-2V6a2 2 0 00-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z" />
75
+ // ),
76
+ // color: "#E53E3E",
77
+ // url: (l, t) => `mailto:?body=${encodeURIComponent(l)}&subject=${encodeURIComponent(t || "")}`,
78
+ // },
79
+ };
@@ -0,0 +1,7 @@
1
+
2
+ Facebook调试:https://developers.facebook.com/tools/debug/
3
+
4
+ https://developer.twitter.com/en/docs/tweets/optimize-with-cards/guides/getting-started
5
+ https://developers.facebook.com/docs/sharing/webmasters/
6
+ https://developers.pinterest.com/docs/rich-pins/rich-pins/
7
+ https://www.linkedin.com/help/linkedin/answer/a521928/making-your-website-shareable-on-linkedin?lang=en
@@ -0,0 +1,33 @@
1
+ import clsx from "clsx"
2
+ import { forwardRef } from "react"
3
+
4
+ export type ToTopProps = {
5
+ className?: string,
6
+ children?: React.ReactNode
7
+ }
8
+
9
+ export const ToTop = forwardRef<HTMLDivElement, ToTopProps>((
10
+ props, ref) => {
11
+ const { className, children, ...rest } = props
12
+ const handleClick = () => {
13
+ window.scrollTo({ top: 0, behavior: "smooth" })
14
+ }
15
+
16
+ return <div
17
+ ref={ref}
18
+ className={
19
+ clsx(
20
+ "fixed bottom-4 right-4 hidden user-select-none scrolling:flex cursor-pointer transition duration-300 ease-in-out z-50",
21
+ className,
22
+ )
23
+ }
24
+ {...rest}
25
+ onClick={handleClick}
26
+ >
27
+ {
28
+ children || <svg className="h-6 w-6" width="1.5rem" height="1.5rem" fill="none" viewBox="0 0 24 24" stroke="currentColor">
29
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 15l7-7 7 7" />
30
+ </svg>
31
+ }
32
+ </div>
33
+ })
@@ -0,0 +1,33 @@
1
+ import clsx from "clsx"
2
+ import { forwardRef } from "react"
3
+
4
+ export type XToTopProps = {
5
+ className?: string,
6
+ children?: React.ReactNode
7
+ }
8
+
9
+ export const ToTop = forwardRef<HTMLDivElement, XToTopProps>((
10
+ props, ref) => {
11
+ const { className, children, ...rest } = props
12
+ const handleClick = () => {
13
+ window.scrollTo({ top: 0, behavior: "smooth" })
14
+ }
15
+
16
+ return <div
17
+ ref={ref}
18
+ className={
19
+ clsx(
20
+ "fixed bottom-4 right-4 hidden user-select-none scrolling:flex cursor-pointer transition duration-300 ease-in-out z-50",
21
+ className,
22
+ )
23
+ }
24
+ {...rest}
25
+ onClick={handleClick}
26
+ >
27
+ {
28
+ children || <svg className="h-6 w-6" width="1.5rem" height="1.5rem" fill="none" viewBox="0 0 24 24" stroke="currentColor">
29
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 15l7-7 7 7" />
30
+ </svg>
31
+ }
32
+ </div>
33
+ })
@@ -1,8 +1,8 @@
1
- export * from "./EnquiryForm";
2
- export * from "./Medias";
3
- export * from "./ProductCard";
4
- export * from "./RichTextOutline";
5
- export * from "./Share";
6
- export * from "./Scroller";
7
- export * from "./SearchInput";
8
- export * from "./ToTop";
1
+ export * from "./EnquiryForm";
2
+ export * from "./Medias";
3
+ export * from "./ProductCard";
4
+ export * from "./RichTextOutline";
5
+ export * from "./Share";
6
+ export * from "./Scroller";
7
+ export * from "./SearchInput";
8
+ export * from "./ToTop";
@@ -0,0 +1 @@
1
+ export * from "./useScroll"
@@ -0,0 +1,23 @@
1
+ import { useCallback, useEffect } from "react";
2
+
3
+ export const defualtThreshold = 10;
4
+
5
+ export function useScroll(threshold: number = defualtThreshold) {
6
+
7
+ const onScroll = useCallback(() => {
8
+ const scrolling = (window.scrollY > threshold);
9
+
10
+ if (scrolling) {
11
+ document.body.classList.add('scrolling');
12
+ } else {
13
+ document.body.classList.remove('scrolling');
14
+ }
15
+
16
+ }, [threshold]);
17
+
18
+ useEffect(() => {
19
+ window.addEventListener("scroll", onScroll);
20
+ return () => window.removeEventListener("scroll", onScroll);
21
+ }, [onScroll]);
22
+
23
+ }
@@ -1,2 +1,2 @@
1
- export * from "./components";
2
- export * from "./hooks";
1
+ export * from "./components";
2
+ export * from "./hooks";
package/src/robots.ts ADDED
@@ -0,0 +1,4 @@
1
+ export const disallowAllRobots = `User-agent: *
2
+ Disallow: /`;
3
+ export const allowAllRobots = `User-agent: *
4
+ Disallow:`;