@rxdrag/website-lib 0.0.122 → 0.0.124
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/components/CookieConsent.astro +41 -0
- package/components/CookieConsent.css +52 -0
- package/components/CookieConsentConfig.ts +208 -0
- package/components/DialogTrigger.astro +7 -1
- package/components/Heading.astro +24 -0
- package/components/Image.astro +66 -10
- package/components/Image.md +15 -0
- package/components/Image.type.ts +226 -0
- package/components/Motion.astro +77 -0
- package/components/RichTextView.astro +14 -33
- package/components/TabButton.astro +16 -0
- package/components/TabPanel.astro +19 -0
- package/components/Tabs.astro +147 -0
- package/components/YearsSince.astro +20 -0
- package/components//347/211/251/346/226/231/346/270/205/345/215/225.md +93 -30
- package/index.ts +2 -1
- package/package.json +10 -9
- package/components/Icon.astro +0 -30
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from "astro/types";
|
|
3
|
+
|
|
4
|
+
type WhileInViewPreset =
|
|
5
|
+
| "fade"
|
|
6
|
+
| "fade-up"
|
|
7
|
+
| "fade-down"
|
|
8
|
+
| "fade-left"
|
|
9
|
+
| "fade-right"
|
|
10
|
+
| "zoom-in"
|
|
11
|
+
| "zoom-out"
|
|
12
|
+
| "slide-up"
|
|
13
|
+
| "slide-down"
|
|
14
|
+
| "slide-left"
|
|
15
|
+
| "slide-right";
|
|
16
|
+
|
|
17
|
+
type WhileInViewConfig = {
|
|
18
|
+
preset?: WhileInViewPreset;
|
|
19
|
+
once?: boolean;
|
|
20
|
+
duration?: number;
|
|
21
|
+
delay?: number;
|
|
22
|
+
easing?: string;
|
|
23
|
+
offset?: number;
|
|
24
|
+
anchorPlacement?: string;
|
|
25
|
+
anchor?: string;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
interface Props extends HTMLAttributes<"div"> {
|
|
29
|
+
as?: string;
|
|
30
|
+
class?: string;
|
|
31
|
+
className?: string;
|
|
32
|
+
whileInView?: WhileInViewPreset | WhileInViewConfig;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const {
|
|
36
|
+
as = "div",
|
|
37
|
+
whileInView,
|
|
38
|
+
class: cls,
|
|
39
|
+
className,
|
|
40
|
+
...rest
|
|
41
|
+
} = Astro.props;
|
|
42
|
+
|
|
43
|
+
const Tag = as as any;
|
|
44
|
+
|
|
45
|
+
const config: WhileInViewConfig | undefined =
|
|
46
|
+
typeof whileInView === "string" ? { preset: whileInView } : whileInView;
|
|
47
|
+
|
|
48
|
+
const dataAos = config?.preset;
|
|
49
|
+
const dataAosOnce = config?.once;
|
|
50
|
+
const dataAosDuration = config?.duration;
|
|
51
|
+
const dataAosDelay = config?.delay;
|
|
52
|
+
const dataAosEasing = config?.easing;
|
|
53
|
+
const dataAosOffset = config?.offset;
|
|
54
|
+
const dataAosAnchorPlacement = config?.anchorPlacement;
|
|
55
|
+
const dataAosAnchor = config?.anchor;
|
|
56
|
+
|
|
57
|
+
const aosAttrs = dataAos
|
|
58
|
+
? {
|
|
59
|
+
"data-aos": dataAos,
|
|
60
|
+
"data-aos-once":
|
|
61
|
+
typeof dataAosOnce === "boolean" ? String(dataAosOnce) : undefined,
|
|
62
|
+
"data-aos-duration":
|
|
63
|
+
typeof dataAosDuration === "number" ? String(dataAosDuration) : undefined,
|
|
64
|
+
"data-aos-delay":
|
|
65
|
+
typeof dataAosDelay === "number" ? String(dataAosDelay) : undefined,
|
|
66
|
+
"data-aos-easing": dataAosEasing,
|
|
67
|
+
"data-aos-offset":
|
|
68
|
+
typeof dataAosOffset === "number" ? String(dataAosOffset) : undefined,
|
|
69
|
+
"data-aos-anchor-placement": dataAosAnchorPlacement,
|
|
70
|
+
"data-aos-anchor": dataAosAnchor,
|
|
71
|
+
}
|
|
72
|
+
: {};
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
<Tag class:list={[cls, className]} {...aosAttrs} {...rest}>
|
|
76
|
+
<slot />
|
|
77
|
+
</Tag>
|
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
LeafPreviewView,
|
|
5
|
-
slatePreviews,
|
|
6
|
-
} from "@rxdrag/slate-preview";
|
|
7
|
-
import type { TSlateLeaf } from "@rxdrag/slate-preview";
|
|
8
|
-
import { ElementPreview } from "@rxdrag/slate-preview";
|
|
2
|
+
import { mdxToTiptap, TiptapPreview } from "@rxdrag/tiptap-preview";
|
|
9
3
|
import { PRODUCT_KEY, ProductCard } from "@rxdrag/website-lib-core";
|
|
4
|
+
import React from "react";
|
|
10
5
|
|
|
11
6
|
interface Props {
|
|
12
7
|
value?: string;
|
|
@@ -15,33 +10,19 @@ interface Props {
|
|
|
15
10
|
}
|
|
16
11
|
|
|
17
12
|
const { value = "", class: className, style } = Astro.props;
|
|
18
|
-
const
|
|
19
|
-
|
|
13
|
+
const tiptapValue = mdxToTiptap(value);
|
|
14
|
+
|
|
15
|
+
const ProductBlock = (props: { attrs?: Record<string, unknown> }) => {
|
|
16
|
+
return React.createElement(ProductCard as any, {
|
|
17
|
+
node: (props.attrs || {}) as any,
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
const customBlocks = {
|
|
21
|
+
[PRODUCT_KEY]: ProductBlock,
|
|
22
|
+
product: ProductBlock,
|
|
23
|
+
};
|
|
20
24
|
---
|
|
21
25
|
|
|
22
26
|
<div class={className} style={style}>
|
|
23
|
-
{
|
|
24
|
-
nodes?.map((node, index) => {
|
|
25
|
-
// 递归处理节点的函数
|
|
26
|
-
const renderNode = (node: any) => {
|
|
27
|
-
// 纯文本节点
|
|
28
|
-
if (typeof node.text !== 'undefined') {
|
|
29
|
-
return <LeafPreviewView node={node as TSlateLeaf} />;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// 有子节点的元素
|
|
33
|
-
if (node.children && node.children.length > 0) {
|
|
34
|
-
return (
|
|
35
|
-
<ElementPreview node={node} previews={previews}>
|
|
36
|
-
{node.children.map((child: any) => renderNode(child))}
|
|
37
|
-
</ElementPreview>
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
return null;
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
return renderNode(node);
|
|
45
|
-
})
|
|
46
|
-
}
|
|
27
|
+
<TiptapPreview value={tiptapValue} customBlocks={customBlocks} />
|
|
47
28
|
</div>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
interface Props {
|
|
3
|
+
class?: string;
|
|
4
|
+
className?: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const { class: className, className: className2, ...props } = Astro.props;
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
<button
|
|
11
|
+
class:list={["tab-btn", className, className2]}
|
|
12
|
+
data-tabs-btn="true"
|
|
13
|
+
{...props}
|
|
14
|
+
>
|
|
15
|
+
<slot />
|
|
16
|
+
</button>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
interface Props {
|
|
3
|
+
class?: string;
|
|
4
|
+
active?: boolean | string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const { class: className, active, ...props } = Astro.props;
|
|
8
|
+
const isActive =
|
|
9
|
+
active === true ||
|
|
10
|
+
(typeof active === "string" && (active === "" || active === "true"));
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
<div
|
|
14
|
+
data-tabs-panel=""
|
|
15
|
+
class:list={["tab-content", className, isActive ? "block" : "hidden"]}
|
|
16
|
+
{...props}
|
|
17
|
+
>
|
|
18
|
+
<slot />
|
|
19
|
+
</div>
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
---
|
|
2
|
+
const rootId = crypto.randomUUID();
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
class?: string;
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const { class: className, className: className2, ...props } = Astro.props;
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<div data-tabs-root id={rootId} class:list={[className, className2]} {...props}>
|
|
13
|
+
<slot />
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
<script is:inline define:vars={{ rootId }}>
|
|
17
|
+
const defaultIndex = 0;
|
|
18
|
+
const activeBtnClassName = "active";
|
|
19
|
+
const inactiveBtnClassName = "";
|
|
20
|
+
const showPanelClassName = "block";
|
|
21
|
+
const hidePanelClassName = "hidden";
|
|
22
|
+
|
|
23
|
+
const getState = () => {
|
|
24
|
+
const w = window;
|
|
25
|
+
const all = (w.__tabs__ ||= {});
|
|
26
|
+
return (all[rootId] ||= { cleanup: null });
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const initTabs = () => {
|
|
30
|
+
const root = document.getElementById(rootId);
|
|
31
|
+
if (!root) return () => {};
|
|
32
|
+
|
|
33
|
+
const toClassList = (className) =>
|
|
34
|
+
String(className || "")
|
|
35
|
+
.trim()
|
|
36
|
+
.split(/\s+/)
|
|
37
|
+
.filter(Boolean);
|
|
38
|
+
|
|
39
|
+
const activeBtnClasses = toClassList(activeBtnClassName);
|
|
40
|
+
const inactiveBtnClasses = toClassList(inactiveBtnClassName);
|
|
41
|
+
const showPanelClasses = toClassList(showPanelClassName);
|
|
42
|
+
const hidePanelClasses = toClassList(hidePanelClassName);
|
|
43
|
+
|
|
44
|
+
const tabBtns = root.querySelectorAll("[data-tabs-btn]");
|
|
45
|
+
const tabPanels = root.querySelectorAll("[data-tabs-panel]");
|
|
46
|
+
|
|
47
|
+
if (tabBtns.length === 0 || tabPanels.length === 0) {
|
|
48
|
+
return () => {};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const pairCount = Math.min(tabBtns.length, tabPanels.length);
|
|
52
|
+
for (let i = 0; i < pairCount; i++) {
|
|
53
|
+
const btn = tabBtns[i];
|
|
54
|
+
const panel = tabPanels[i];
|
|
55
|
+
const key = `${rootId}-${i}`;
|
|
56
|
+
|
|
57
|
+
const btnKey = btn.getAttribute("data-tabs-btn");
|
|
58
|
+
if (!btnKey) btn.setAttribute("data-tabs-btn", key);
|
|
59
|
+
|
|
60
|
+
const panelKey = panel.getAttribute("data-tabs-panel");
|
|
61
|
+
if (!panelKey) panel.setAttribute("data-tabs-panel", key);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const ac = new AbortController();
|
|
65
|
+
const { signal } = ac;
|
|
66
|
+
|
|
67
|
+
const setActiveBtnA11y = (btn, active) => {
|
|
68
|
+
btn.setAttribute("role", "tab");
|
|
69
|
+
btn.setAttribute("aria-selected", active ? "true" : "false");
|
|
70
|
+
btn.tabIndex = active ? 0 : -1;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const setActivePanelA11y = (panel, active) => {
|
|
74
|
+
panel.setAttribute("role", "tabpanel");
|
|
75
|
+
panel.setAttribute("aria-hidden", active ? "false" : "true");
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const activate = (btn) => {
|
|
79
|
+
const targetId = btn.getAttribute("data-tabs-btn");
|
|
80
|
+
if (!targetId) return;
|
|
81
|
+
|
|
82
|
+
tabBtns.forEach((b) => {
|
|
83
|
+
if (inactiveBtnClasses.length) b.classList.add(...inactiveBtnClasses);
|
|
84
|
+
if (activeBtnClasses.length) b.classList.remove(...activeBtnClasses);
|
|
85
|
+
setActiveBtnA11y(b, false);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
tabPanels.forEach((p) => {
|
|
89
|
+
if (showPanelClasses.length) p.classList.remove(...showPanelClasses);
|
|
90
|
+
if (hidePanelClasses.length) p.classList.add(...hidePanelClasses);
|
|
91
|
+
setActivePanelA11y(p, false);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
if (inactiveBtnClasses.length)
|
|
95
|
+
btn.classList.remove(...inactiveBtnClasses);
|
|
96
|
+
if (activeBtnClasses.length) btn.classList.add(...activeBtnClasses);
|
|
97
|
+
setActiveBtnA11y(btn, true);
|
|
98
|
+
|
|
99
|
+
let panel = root.querySelector(
|
|
100
|
+
`[data-tabs-panel="${CSS.escape(targetId)}"]`
|
|
101
|
+
);
|
|
102
|
+
if (!panel) {
|
|
103
|
+
const index = Array.from(tabBtns).indexOf(btn);
|
|
104
|
+
panel = tabPanels[index] || null;
|
|
105
|
+
}
|
|
106
|
+
if (panel) {
|
|
107
|
+
if (hidePanelClasses.length)
|
|
108
|
+
panel.classList.remove(...hidePanelClasses);
|
|
109
|
+
if (showPanelClasses.length) panel.classList.add(...showPanelClasses);
|
|
110
|
+
setActivePanelA11y(panel, true);
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
document.addEventListener(
|
|
115
|
+
"click",
|
|
116
|
+
(event) => {
|
|
117
|
+
const el = event.target;
|
|
118
|
+
const btn = el?.closest?.("[data-tabs-btn]");
|
|
119
|
+
if (!btn) return;
|
|
120
|
+
if (!root.contains(btn)) return;
|
|
121
|
+
activate(btn);
|
|
122
|
+
},
|
|
123
|
+
{ signal }
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
const initBtn = tabBtns[defaultIndex] || tabBtns[0];
|
|
127
|
+
if (initBtn) activate(initBtn);
|
|
128
|
+
|
|
129
|
+
return () => ac.abort();
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const boot = () => {
|
|
133
|
+
const state = getState();
|
|
134
|
+
state.cleanup?.();
|
|
135
|
+
state.cleanup = initTabs();
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
if (document.readyState === "loading") {
|
|
139
|
+
document.addEventListener("DOMContentLoaded", boot, { once: true });
|
|
140
|
+
} else {
|
|
141
|
+
boot();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
document.addEventListener("astro:page-load", boot);
|
|
145
|
+
document.addEventListener("astro:after-swap", boot);
|
|
146
|
+
window.addEventListener("astro:before-swap", () => getState().cleanup?.());
|
|
147
|
+
</script>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
interface Props {
|
|
3
|
+
startYear?: number;
|
|
4
|
+
minYears?: number;
|
|
5
|
+
offset?: number;
|
|
6
|
+
suffix?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const {
|
|
10
|
+
startYear = 2006,
|
|
11
|
+
minYears = 20,
|
|
12
|
+
offset = 0,
|
|
13
|
+
suffix = "+",
|
|
14
|
+
} = Astro.props;
|
|
15
|
+
|
|
16
|
+
const currentYear = new Date().getFullYear();
|
|
17
|
+
const years = Math.max(minYears, currentYear - startYear + offset);
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
{years}{suffix}
|