@rxdrag/website-lib 0.0.151 → 0.0.153

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 (51) hide show
  1. package/README.md +2 -2
  2. package/components/AnimationNumber.astro +217 -217
  3. package/components/Background.astro +140 -114
  4. package/components/BackgroundGroup.astro +20 -26
  5. package/components/BaseFooter.astro +24 -39
  6. package/components/BaseHeader.astro +22 -25
  7. package/components/Box.astro +20 -22
  8. package/components/Button.astro +80 -0
  9. package/components/Carousel.astro +456 -315
  10. package/components/CarouselPagination.astro +97 -76
  11. package/components/CarouselSlide.astro +10 -16
  12. package/components/Collapse.astro +125 -125
  13. package/components/CollapseIndicator.astro +20 -20
  14. package/components/Container.astro +27 -32
  15. package/components/Content.astro +20 -0
  16. package/components/CookieConsent.astro +47 -47
  17. package/components/CookieConsent.css +52 -52
  18. package/components/CookieConsentConfig.ts +208 -208
  19. package/components/Dialog.astro +342 -338
  20. package/components/DialogTrigger.astro +32 -32
  21. package/components/Document.astro +240 -225
  22. package/components/Frame.astro +32 -0
  23. package/components/GlassBorder.astro +104 -0
  24. package/components/GlassRefraction.astro +85 -0
  25. package/components/GradientBorder.astro +80 -0
  26. package/components/Grid.astro +32 -34
  27. package/components/GridCell.astro +28 -32
  28. package/components/Heading.astro +24 -24
  29. package/components/Icon.astro +29 -29
  30. package/components/Image.astro +100 -100
  31. package/components/Image.md +14 -14
  32. package/components/Link.astro +89 -99
  33. package/components/Main.astro +17 -17
  34. package/components/Meta.astro +65 -65
  35. package/components/Popover.astro +189 -189
  36. package/components/RichTextView.astro +28 -28
  37. package/components/Section.astro +26 -44
  38. package/components/TabButton.astro +32 -16
  39. package/components/TabPanel.astro +20 -19
  40. package/components/Tabs.astro +220 -147
  41. package/components/Video.astro +6 -4
  42. package/components/YearsSince.astro +20 -20
  43. package/components//344/270/211/345/261/202/346/250/241/345/236/213.md +5 -5
  44. package/components//344/270/273/351/242/230Token.md +198 -198
  45. package/components//345/216/237/345/255/220/345/206/273/347/273/223/346/270/205/345/215/225.md +270 -260
  46. package/components//347/211/251/346/226/231/346/270/205/345/215/225.md +599 -567
  47. package/index.ts +5 -5
  48. package/package.json +7 -7
  49. package/components/BaseBlock.astro +0 -34
  50. package/components/Motion.astro +0 -77
  51. package/components/Stack.astro +0 -31
@@ -1,147 +1,220 @@
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>
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, activeKey: "" });
27
+ };
28
+
29
+ const isAutoKey = (value) => {
30
+ const v = String(value || "").trim();
31
+ return !v || v === "true" || v === "auto";
32
+ };
33
+
34
+ const toArray = (nodes) => Array.from(nodes || []);
35
+
36
+ const initTabs = (state) => {
37
+ const root = document.getElementById(rootId);
38
+ if (!root) return () => {};
39
+
40
+ const toClassList = (className) =>
41
+ String(className || "")
42
+ .trim()
43
+ .split(/\s+/)
44
+ .filter(Boolean);
45
+
46
+ const activeBtnClasses = toClassList(activeBtnClassName);
47
+ const inactiveBtnClasses = toClassList(inactiveBtnClassName);
48
+ const showPanelClasses = toClassList(showPanelClassName);
49
+ const hidePanelClasses = toClassList(hidePanelClassName);
50
+
51
+ const getTabBtns = () => toArray(root.querySelectorAll("[data-tabs-btn]"));
52
+ const getTabPanels = () => toArray(root.querySelectorAll("[data-tabs-panel]"));
53
+
54
+ const syncBindings = () => {
55
+ const tabBtns = getTabBtns();
56
+ const tabPanels = getTabPanels();
57
+ const pairCount = Math.max(tabBtns.length, tabPanels.length);
58
+
59
+ for (let i = 0; i < pairCount; i++) {
60
+ const btn = tabBtns[i] || null;
61
+ const panel = tabPanels[i] || null;
62
+ const btnKeyRaw = btn ? btn.getAttribute("data-tabs-btn") : "";
63
+ const panelKeyRaw = panel ? panel.getAttribute("data-tabs-panel") : "";
64
+ const btnKey = isAutoKey(btnKeyRaw) ? "" : String(btnKeyRaw);
65
+ const panelKey = isAutoKey(panelKeyRaw) ? "" : String(panelKeyRaw);
66
+ const key = btnKey || panelKey || `${rootId}-${i}`;
67
+
68
+ if (btn) {
69
+ if (btn.getAttribute("data-tabs-btn") !== key) {
70
+ btn.setAttribute("data-tabs-btn", key);
71
+ }
72
+ if (!btn.getAttribute("data-tabs-role")) {
73
+ btn.setAttribute("data-tabs-role", "button");
74
+ }
75
+ }
76
+ if (panel) {
77
+ if (panel.getAttribute("data-tabs-panel") !== key) {
78
+ panel.setAttribute("data-tabs-panel", key);
79
+ }
80
+ if (!panel.getAttribute("data-tabs-role")) {
81
+ panel.setAttribute("data-tabs-role", "panel");
82
+ }
83
+ }
84
+ }
85
+ };
86
+
87
+ const ac = new AbortController();
88
+ const { signal } = ac;
89
+
90
+ const setActiveBtnA11y = (btn, active) => {
91
+ btn.setAttribute("role", "tab");
92
+ btn.setAttribute("aria-selected", active ? "true" : "false");
93
+ btn.tabIndex = active ? 0 : -1;
94
+ };
95
+
96
+ const setActivePanelA11y = (panel, active) => {
97
+ panel.setAttribute("role", "tabpanel");
98
+ panel.setAttribute("aria-hidden", active ? "false" : "true");
99
+ };
100
+
101
+ const activate = (btn) => {
102
+ const tabBtns = getTabBtns();
103
+ const tabPanels = getTabPanels();
104
+ const targetId = btn.getAttribute("data-tabs-btn");
105
+ if (!targetId) return;
106
+ state.activeKey = targetId;
107
+
108
+ tabBtns.forEach((b) => {
109
+ if (inactiveBtnClasses.length) b.classList.add(...inactiveBtnClasses);
110
+ if (activeBtnClasses.length) b.classList.remove(...activeBtnClasses);
111
+ setActiveBtnA11y(b, false);
112
+ });
113
+
114
+ tabPanels.forEach((p) => {
115
+ if (showPanelClasses.length) p.classList.remove(...showPanelClasses);
116
+ if (hidePanelClasses.length) p.classList.add(...hidePanelClasses);
117
+ setActivePanelA11y(p, false);
118
+ });
119
+
120
+ if (inactiveBtnClasses.length)
121
+ btn.classList.remove(...inactiveBtnClasses);
122
+ if (activeBtnClasses.length) btn.classList.add(...activeBtnClasses);
123
+ setActiveBtnA11y(btn, true);
124
+
125
+ let panel = root.querySelector(
126
+ `[data-tabs-panel="${CSS.escape(targetId)}"]`
127
+ );
128
+ if (!panel) {
129
+ const index = Array.from(tabBtns).indexOf(btn);
130
+ panel = tabPanels[index] || null;
131
+ }
132
+ if (panel) {
133
+ if (hidePanelClasses.length)
134
+ panel.classList.remove(...hidePanelClasses);
135
+ if (showPanelClasses.length) panel.classList.add(...showPanelClasses);
136
+ setActivePanelA11y(panel, true);
137
+ }
138
+ };
139
+
140
+ const activateByKey = (key) => {
141
+ if (!key) return false;
142
+ const tabBtns = getTabBtns();
143
+ const btn = tabBtns.find((b) => b.getAttribute("data-tabs-btn") === key);
144
+ if (!btn) return false;
145
+ activate(btn);
146
+ return true;
147
+ };
148
+
149
+ const activateDefault = () => {
150
+ const tabBtns = getTabBtns();
151
+ if (tabBtns.length === 0) return;
152
+ const presetActive = tabBtns.find((b) => b.classList.contains("active"));
153
+ const initBtn = presetActive || tabBtns[defaultIndex] || tabBtns[0];
154
+ if (initBtn) activate(initBtn);
155
+ };
156
+
157
+ const syncAndActivate = () => {
158
+ syncBindings();
159
+ if (!activateByKey(state.activeKey || "")) {
160
+ activateDefault();
161
+ }
162
+ };
163
+
164
+ root.addEventListener(
165
+ "click",
166
+ (event) => {
167
+ const el = event.target;
168
+ const btn = el?.closest?.("[data-tabs-btn]");
169
+ if (!btn) return;
170
+ if (!root.contains(btn)) return;
171
+ activate(btn);
172
+ },
173
+ { signal }
174
+ );
175
+
176
+ let rafId = null;
177
+ const observer = new MutationObserver(() => {
178
+ if (rafId != null) return;
179
+ rafId = (window.requestAnimationFrame || ((cb) => setTimeout(cb, 16)))(() => {
180
+ rafId = null;
181
+ syncAndActivate();
182
+ });
183
+ });
184
+ observer.observe(root, {
185
+ childList: true,
186
+ subtree: true,
187
+ attributes: true,
188
+ attributeFilter: ["data-tabs-btn", "data-tabs-panel"],
189
+ });
190
+
191
+ syncAndActivate();
192
+
193
+ return () => {
194
+ ac.abort();
195
+ observer.disconnect();
196
+ if (typeof rafId === "number") {
197
+ if (typeof window.cancelAnimationFrame === "function") {
198
+ window.cancelAnimationFrame(rafId);
199
+ }
200
+ clearTimeout(rafId);
201
+ }
202
+ };
203
+ };
204
+
205
+ const boot = () => {
206
+ const state = getState();
207
+ state.cleanup?.();
208
+ state.cleanup = initTabs(state);
209
+ };
210
+
211
+ if (document.readyState === "loading") {
212
+ document.addEventListener("DOMContentLoaded", boot, { once: true });
213
+ } else {
214
+ boot();
215
+ }
216
+
217
+ document.addEventListener("astro:page-load", boot);
218
+ document.addEventListener("astro:after-swap", boot);
219
+ window.addEventListener("astro:before-swap", () => getState().cleanup?.());
220
+ </script>
@@ -4,7 +4,6 @@ import {
4
4
  ReactVideoPlayer,
5
5
  type Locals,
6
6
  } from "@rxdrag/website-lib-core";
7
- import { getImage } from "astro:assets";
8
7
 
9
8
  const { env, imageSizes } = Astro.locals as Locals;
10
9
 
@@ -15,6 +14,7 @@ interface Props {
15
14
  eagerLoad?: boolean;
16
15
  classNames?: {
17
16
  container?: string;
17
+ aspect?: string;
18
18
  video?: string;
19
19
  playButton?: string;
20
20
  playButtonOuter?: string;
@@ -53,7 +53,7 @@ if (poster) {
53
53
  ---
54
54
 
55
55
  {
56
- media && (
56
+
57
57
  <ReactVideoPlayer
58
58
  client:load
59
59
  media={media}
@@ -61,6 +61,8 @@ if (poster) {
61
61
  posterUrl={posterUrl}
62
62
  eagerLoad={eagerLoad}
63
63
  classNames={classNames}
64
- />
65
- )
64
+ >
65
+ <slot />
66
+ </ReactVideoPlayer>
67
+
66
68
  }
@@ -1,20 +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}
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}
@@ -1,5 +1,5 @@
1
- | 层级 | 是否冻结 | 负责什么 | AI 能不能改 |
2
- | ----------------------- | --------- | -------------------------- | ------- |
3
- | **结构层(Structure)** | ✅ 冻结 | Grid / Flex / DOM 层级 | ❌ 不允许 |
4
- | **语义层(Semantic)** | ✅ 冻结 | Hero / Feature / CTA 含义 | ❌ 不允许 |
5
- | **装饰层(Decoration)** | ❌ 不冻结 | 颜色 / 阴影 / 动画 / 圆角 | ✅ 受控允许 |
1
+ | 层级 | 是否冻结 | 负责什么 | AI 能不能改 |
2
+ | ----------------------- | --------- | -------------------------- | ------- |
3
+ | **结构层(Structure)** | ✅ 冻结 | Grid / Flex / DOM 层级 | ❌ 不允许 |
4
+ | **语义层(Semantic)** | ✅ 冻结 | Hero / Feature / CTA 含义 | ❌ 不允许 |
5
+ | **装饰层(Decoration)** | ❌ 不冻结 | 颜色 / 阴影 / 动画 / 圆角 | ✅ 受控允许 |