@rxdrag/website-lib 0.0.121 → 0.0.123

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,6 +1,8 @@
1
1
  ---
2
2
  interface Props {
3
3
  dialogId: string;
4
+ openableKey?: string;
5
+ as?: string;
4
6
  callToAction?: string;
5
7
  class?: string;
6
8
  className?: string;
@@ -8,16 +10,20 @@ interface Props {
8
10
 
9
11
  const {
10
12
  dialogId,
13
+ openableKey,
14
+ as: _as,
11
15
  callToAction,
12
16
  class: _class,
13
17
  className,
14
18
  ...rest
15
19
  } = Astro.props;
20
+
21
+ const resolvedDialogId = dialogId || openableKey;
16
22
  ---
17
23
 
18
24
  <button
19
25
  type="button"
20
- data-modal-open={dialogId}
26
+ data-modal-open={resolvedDialogId}
21
27
  data-call-to-action={callToAction}
22
28
  class:list={[className, _class]}
23
29
  {...rest}
@@ -41,6 +41,7 @@ if (!resolvedMeta || !resolvedTitle) {
41
41
  try {
42
42
  const pathname = Astro.url?.pathname || "";
43
43
  const slug = typeof Astro.params?.slug === "string" ? Astro.params.slug : undefined;
44
+ const id = typeof Astro.params?.id === "string" ? Astro.params.id : undefined;
44
45
 
45
46
  if (slug && pathname.startsWith("/posts/categories/")) {
46
47
  const category = await rx.getPostCategoryBySlug(slug);
@@ -52,6 +53,11 @@ if (!resolvedMeta || !resolvedTitle) {
52
53
  const page = await rx.getPageByType(PageType.ProductList);
53
54
  resolvedTitle = resolvedTitle ?? category?.name ?? "Products";
54
55
  resolvedMeta = resolvedMeta ?? page?.meta;
56
+ } else if (id && pathname.startsWith("/profiles/")) {
57
+ const user = await rx.getOneUser(id);
58
+ const page = await rx.getPageByType(PageType.Profile);
59
+ resolvedTitle = resolvedTitle ?? user?.name ?? "Profile";
60
+ resolvedMeta = resolvedMeta ?? page?.meta;
55
61
  } else if (slug && pathname.startsWith("/posts/")) {
56
62
  const post = await rx.getPostBySlug(slug, { width: 1200, height: 600 });
57
63
  resolvedTitle = resolvedTitle ?? post?.title;
@@ -0,0 +1,21 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+
4
+ interface Props extends HTMLAttributes<"h1" | "h2" | "h3" | "h4" | "h5" | "h6"> {
5
+ level: 1 | 2 | 3 | 4 | 5 | 6;
6
+ className?: string;
7
+ }
8
+
9
+ const { level, className, class: classAttr, ...rest } = Astro.props;
10
+
11
+ if (typeof level !== "number" || level < 1 || level > 6) {
12
+ console.log("[Heading] invalid level", level);
13
+ throw new Error("Heading.astro: prop 'level' must be a number from 1 to 6");
14
+ }
15
+
16
+ const Tag = `h${level}`;
17
+ ---
18
+
19
+ <Tag class:list={[className, classAttr]} {...rest}>
20
+ <slot />
21
+ </Tag>
@@ -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 { mdxToSlate } from "@rxdrag/slate-preview";
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 previews = { ...slatePreviews, [PRODUCT_KEY]: ProductCard };
19
- const nodes = mdxToSlate(value);
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,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}
@@ -2,12 +2,12 @@
2
2
 
3
3
  > 外贸 toB 独立站物料体系,按冻结层级分类
4
4
 
5
- | 分类 | 数量 | 说明 |
6
- |------|------|------|
7
- | 完全冻结原子 | 14 | 语义和接口永不改变 |
8
- | 半冻结原子 | 4 | 规则冻结,形态可扩展 |
9
- | 业务组件 | 9 | 包含复杂交互逻辑 |
10
- | 设计器模板 | 52 | 一键生成常用结构 |
5
+ | 分类 | 数量 | 说明 |
6
+ | ------------ | ---- | -------------------- |
7
+ | 完全冻结原子 | 14 | 语义和接口永不改变 |
8
+ | 半冻结原子 | 4 | 规则冻结,形态可扩展 |
9
+ | 业务组件 | 10 | 包含复杂交互逻辑 |
10
+ | 设计器模板 | 52 | 一键生成常用结构 |
11
11
 
12
12
  ---
13
13
 
@@ -29,11 +29,12 @@
29
29
  ### 1. 结构原子
30
30
 
31
31
  **Section(区块)**
32
+
32
33
  ```ts
33
34
  import type { HTMLAttributes } from "astro/types";
34
35
  import type { BackgroundConfig } from "@rxdrag/website-lib-core";
35
36
 
36
- interface SectionProps extends HTMLAttributes<'section'> {
37
+ interface SectionProps extends HTMLAttributes<"section"> {
37
38
  className?: string;
38
39
  containerClassName?: string;
39
40
  backgrounds?: BackgroundConfig[];
@@ -42,11 +43,12 @@ interface SectionProps extends HTMLAttributes<'section'> {
42
43
  ```
43
44
 
44
45
  **BaseHeader(基础 Header 容器壳)**
46
+
45
47
  ```ts
46
48
  import type { HTMLAttributes } from "astro/types";
47
49
  import type { BackgroundConfig } from "@rxdrag/website-lib-core";
48
50
 
49
- interface BaseHeaderProps extends HTMLAttributes<'header'> {
51
+ interface BaseHeaderProps extends HTMLAttributes<"header"> {
50
52
  className?: string;
51
53
  containerClassName?: string;
52
54
  backgrounds?: BackgroundConfig[];
@@ -55,11 +57,12 @@ interface BaseHeaderProps extends HTMLAttributes<'header'> {
55
57
  ```
56
58
 
57
59
  **BaseFooter(基础 Footer 容器壳)**
60
+
58
61
  ```ts
59
62
  import type { HTMLAttributes } from "astro/types";
60
63
  import type { BackgroundConfig } from "@rxdrag/website-lib-core";
61
64
 
62
- interface BaseFooterProps extends HTMLAttributes<'footer'> {
65
+ interface BaseFooterProps extends HTMLAttributes<"footer"> {
63
66
  className?: string;
64
67
  containerClassName?: string;
65
68
  backgrounds?: BackgroundConfig[];
@@ -68,34 +71,56 @@ interface BaseFooterProps extends HTMLAttributes<'footer'> {
68
71
  ```
69
72
 
70
73
  **Container(容器)**
74
+
71
75
  ```ts
72
76
  import type { HTMLAttributes } from "astro/types";
73
77
 
74
- interface ContainerProps extends HTMLAttributes<'div'> {
78
+ interface ContainerProps extends HTMLAttributes<"div"> {
75
79
  className?: string;
76
80
  }
77
81
  ```
78
82
 
79
83
  **BaseBlock(基础容器壳)**
84
+
80
85
  ```ts
81
86
  import type { HTMLAttributes } from "astro/types";
82
87
  import type { BackgroundConfig } from "@rxdrag/website-lib-core";
83
88
 
84
- interface BaseBlockProps extends HTMLAttributes<'div'> {
89
+ interface BaseBlockProps extends HTMLAttributes<"div"> {
85
90
  baseClass?: string | string[];
86
91
  className?: string;
87
92
  backgrounds?: BackgroundConfig[];
88
93
  }
89
94
  ```
90
95
 
96
+ **Layout(页面壳 / Document Wrapper)**
97
+
98
+ ```ts
99
+ import type { PageMeta } from "@rxdrag/rxcms-models";
100
+
101
+ interface LayoutProps {
102
+ lang?: string;
103
+ title?: string;
104
+ meta?: PageMeta;
105
+ class?: string;
106
+ className?: string;
107
+ }
108
+ ```
109
+
110
+ - 语义:页面级文档壳,负责 `<html>/<head>/<body>` 结构
111
+ - SEO:支持传入 `title` 与 `meta`(`PageMeta`)
112
+ - 插槽:支持 `<slot name="head" />` 向 head 注入自定义内容(预加载/脚本/样式等)
113
+ - 每个模板都要实现一个,但是接口保持不变
114
+
91
115
  ### 2. 布局原子
92
116
 
93
117
  **Grid(网格)**
118
+
94
119
  ```ts
95
120
  import type { HTMLAttributes } from "astro/types";
96
121
  import type { BackgroundConfig } from "@rxdrag/website-lib-core";
97
122
 
98
- interface GridProps extends HTMLAttributes<'div'> {
123
+ interface GridProps extends HTMLAttributes<"div"> {
99
124
  patternName?: string;
100
125
  className?: string;
101
126
  backgrounds?: BackgroundConfig[];
@@ -103,22 +128,24 @@ interface GridProps extends HTMLAttributes<'div'> {
103
128
  ```
104
129
 
105
130
  **GridCell(网格单元)**
131
+
106
132
  ```ts
107
133
  import type { HTMLAttributes } from "astro/types";
108
134
  import type { BackgroundConfig } from "@rxdrag/website-lib-core";
109
135
 
110
- interface GridCellProps extends HTMLAttributes<'div'> {
136
+ interface GridCellProps extends HTMLAttributes<"div"> {
111
137
  className?: string;
112
138
  backgrounds?: BackgroundConfig[];
113
139
  }
114
140
  ```
115
141
 
116
142
  **Stack(堆叠)**
143
+
117
144
  ```ts
118
145
  import type { HTMLAttributes } from "astro/types";
119
146
  import type { BackgroundConfig } from "@rxdrag/website-lib-core";
120
147
 
121
- interface StackProps extends HTMLAttributes<'div'> {
148
+ interface StackProps extends HTMLAttributes<"div"> {
122
149
  className?: string;
123
150
  backgrounds?: BackgroundConfig[];
124
151
  }
@@ -131,35 +158,49 @@ interface StackProps extends HTMLAttributes<'div'> {
131
158
 
132
159
  **Heading(标题)**
133
160
 
134
- - 不单独定义 Heading 原子
135
- - 直接使用原生 `h1/h2/h3/h4` 标签表达语义
161
+ ```ts
162
+ import type { HTMLAttributes } from "astro/types";
163
+
164
+ interface HeadingProps
165
+ extends HTMLAttributes<"h1" | "h2" | "h3" | "h4" | "h5" | "h6"> {
166
+ level: 1 | 2 | 3 | 4 | 5 | 6;
167
+ className?: string;
168
+ }
169
+ ```
170
+
171
+ - 语义:标题
172
+ - 通过 `level` 渲染对应的 `h1~h6`
136
173
  - 视觉样式(字号/字重/行高/响应式)统一通过 `class` / `className`(Tailwind,如 `text-2xl md:text-4xl font-semibold`)表达
137
174
 
138
175
  **P(段落)**
176
+
139
177
  ```ts
140
178
  import type { HTMLAttributes } from "astro/types";
141
179
 
142
- interface PProps extends HTMLAttributes<'p'> {
143
- }
180
+ interface PProps extends HTMLAttributes<"p"> {}
144
181
  ```
182
+
145
183
  - 语义:段落文本(块级),适合正文描述、说明文案、长文本
146
184
 
147
185
  **Span(行内文本)**
186
+
148
187
  ```ts
149
188
  import type { HTMLAttributes } from "astro/types";
150
189
 
151
- interface SpanProps extends HTMLAttributes<'span'> {
152
- }
190
+ interface SpanProps extends HTMLAttributes<"span"> {}
153
191
  ```
192
+
154
193
  - 语义:行内文本(inline),适合按钮旁提示、小标签、句内强调、短文本片段
155
194
  - 文本样式(字号/字重/颜色/行高/响应式)统一通过 `class`(Tailwind,如 `text-sm md:text-base text-muted-foreground`)表达
156
195
 
157
196
  **Image(图片)**
197
+
158
198
  - 不在 `website-lib` 中定义 Image 原子组件
159
199
  - 推荐直接使用 Astro 官方 `astro:assets` 的 `Image` 组件(构建期生成优化后的图片与 srcset)
160
200
  - `website-lib/components/Image.astro` 仅用于兼容旧代码(`mediaRef/fileField/resize` 取图),后续逐步下线
161
201
 
162
202
  **Picture(响应式图片)**
203
+
163
204
  ```ts
164
205
  import type { HTMLAttributes } from "astro/types";
165
206
 
@@ -170,46 +211,52 @@ type PictureSource = {
170
211
  sizes?: string;
171
212
  };
172
213
 
173
- interface PictureProps extends HTMLAttributes<'picture'> {
214
+ interface PictureProps extends HTMLAttributes<"picture"> {
174
215
  className?: string;
175
216
  sources?: PictureSource[];
176
- imgProps: Omit<HTMLAttributes<'img'>, 'src'> & {
217
+ imgProps: Omit<HTMLAttributes<"img">, "src"> & {
177
218
  src: string;
178
219
  };
179
220
  }
180
221
  ```
222
+
181
223
  - 语义:响应式图片容器(picture/source/img),用于 art-direction、不同断点/格式(如 webp/avif)切换
182
224
  - 规则:结构固定为 `<picture><source* /><img /></picture>`,AI 只允许改 `sources/imgProps` 内容,不改结构
183
225
  - 样式:通过 `className` 或原生 `class`(Tailwind)控制
184
226
 
185
227
  **Video(视频)**
228
+
186
229
  ```ts
187
230
  import type { HTMLAttributes } from "astro/types";
188
231
 
189
- interface VideoProps extends HTMLAttributes<'video'> {
232
+ interface VideoProps extends HTMLAttributes<"video"> {
190
233
  src: string;
191
234
  poster?: string;
192
235
  }
193
236
  ```
237
+
194
238
  - 语义:视频(对应原生 video 标签或视频播放器)
195
239
  - 是否 controls/自动播放/静音/inline 等通过原生属性 + `class` 表达
196
240
 
197
241
  **Icon(图标)**
242
+
198
243
  ```ts
199
244
  import type { HTMLAttributes } from "astro/types";
200
245
 
201
- interface IconProps extends HTMLAttributes<'span'> {
246
+ interface IconProps extends HTMLAttributes<"span"> {
202
247
  className?: string;
203
248
  icon?: string;
204
249
  svg?: string;
205
250
  }
206
251
  ```
252
+
207
253
  - 语义:图标(装饰性或功能性图标)
208
254
  - icon:图标名,支持 iconify(如 `mdi:check`)或本地图标 `local:xxx`(由 Entify 在运行时加载 svg)
209
255
  - svg:直接传入 svg 字符串(优先级低于 local 图标加载)
210
256
  - 大小/颜色/旋转/动画等统一通过 `className`(Tailwind,如 `w-6 h-6 text-blue-500 rotate-90`)表达
211
257
 
212
258
  **hr(分割线)**
259
+
213
260
  - 不单独定义 hr 原子
214
261
  - 直接使用原生 `<hr>` 标签表达语义
215
262
  - 视觉样式(边框颜色/粗细/间距/响应式)统一通过 `class`(Tailwind,如 `border-t border-gray-300 my-8`)表达
@@ -220,7 +267,7 @@ interface IconProps extends HTMLAttributes<'span'> {
220
267
  import type { HTMLAttributes } from "astro/types";
221
268
  import type { LinkType } from "@rxdrag/website-lib-core";
222
269
 
223
- interface LinkProps extends HTMLAttributes<'a'> {
270
+ interface LinkProps extends HTMLAttributes<"a"> {
224
271
  type?: LinkType | string;
225
272
  to?: string;
226
273
  className?: string;
@@ -265,23 +312,26 @@ interface LinkProps extends HTMLAttributes<'a'> {
265
312
  - 对齐控制(Align):使用 Tailwind 的 `text-center`/`justify-center`/`items-center` 等工具类,不需要 Align 组件
266
313
 
267
314
  **Badge(徽标)**
315
+
268
316
  ```ts
269
317
  import type { HTMLAttributes } from "astro/types";
270
318
 
271
- interface BadgeProps extends HTMLAttributes<'span'> {
319
+ interface BadgeProps extends HTMLAttributes<"span"> {
272
320
  className?: string;
273
321
  tone?: "info" | "success" | "warning" | "error" | "neutral";
274
322
  }
275
323
  ```
324
+
276
325
  - 语义:状态标签、分类标签等
277
326
  - tone:语义化的颜色变体(info/success/warning/error/neutral)
278
327
  - 样式通过 `className` 和 `tone` 组合控制
279
328
 
280
329
  **Input(输入框)**
330
+
281
331
  ```ts
282
332
  import type { HTMLAttributes } from "astro/types";
283
333
 
284
- interface InputProps extends Omit<HTMLAttributes<'input'>, 'type'> {
334
+ interface InputProps extends Omit<HTMLAttributes<"input">, "type"> {
285
335
  label?: string;
286
336
  name: string;
287
337
  type?: "text" | "email" | "tel" | "number" | "password" | "url";
@@ -295,16 +345,18 @@ interface InputProps extends Omit<HTMLAttributes<'input'>, 'type'> {
295
345
  fieldStyle?: "default" | "label-inline" | string;
296
346
  }
297
347
  ```
348
+
298
349
  - 语义:基础文本输入框(支持文本/邮箱/电话/数字/密码/URL 类型)
299
350
  - 包含 label/input/error 提示的完整结构
300
351
  - fieldStyle:支持不同布局样式(default: label 在上方,label-inline: label 在左侧)
301
352
  - 样式通过 className/labelClassName/inputClassName 控制
302
353
 
303
354
  **Textarea(多行输入)**
355
+
304
356
  ```ts
305
357
  import type { HTMLAttributes } from "astro/types";
306
358
 
307
- interface TextareaProps extends Omit<HTMLAttributes<'textarea'>, 'rows'> {
359
+ interface TextareaProps extends Omit<HTMLAttributes<"textarea">, "rows"> {
308
360
  label?: string;
309
361
  name: string;
310
362
  required?: boolean;
@@ -318,16 +370,18 @@ interface TextareaProps extends Omit<HTMLAttributes<'textarea'>, 'rows'> {
318
370
  fieldStyle?: "default" | "label-inline" | string;
319
371
  }
320
372
  ```
373
+
321
374
  - 语义:多行文本输入框
322
375
  - 包含 label/textarea/error 提示的完整结构
323
376
  - fieldStyle:支持不同布局样式(同 Input)
324
377
  - 样式通过 className/labelClassName/inputClassName 控制
325
378
 
326
379
  **Checkbox/Radio(复选/单选)**
380
+
327
381
  ```ts
328
382
  import type { HTMLAttributes } from "astro/types";
329
383
 
330
- interface CheckboxProps extends Omit<HTMLAttributes<'input'>, 'type'> {
384
+ interface CheckboxProps extends Omit<HTMLAttributes<"input">, "type"> {
331
385
  label?: string;
332
386
  name: string;
333
387
  value?: string;
@@ -343,6 +397,7 @@ interface RadioProps extends CheckboxProps {
343
397
  // 继承 Checkbox 的所有属性
344
398
  }
345
399
  ```
400
+
346
401
  - 语义:复选框(Checkbox)或单选框(Radio)
347
402
  - 包含 label/input/error 提示的完整结构
348
403
  - 用于同意条款、选项选择等场景
@@ -355,6 +410,7 @@ interface RadioProps extends CheckboxProps {
355
410
  > 设计趋势变化快、形态多变,或包含复杂交互逻辑,不纳入冻结原子清单
356
411
 
357
412
  **AnimationNumber(数字动画)**
413
+
358
414
  ```ts
359
415
  interface AnimationNumberProps {
360
416
  start?: number;
@@ -367,62 +423,86 @@ interface AnimationNumberProps {
367
423
  fractionDigits?: number;
368
424
  }
369
425
  ```
426
+
370
427
  - 职责:数字滚动动画(从 start 滚动到 end)
371
428
  - 特点:IntersectionObserver 视口检测、缓动动画、支持整数/浮点数、可配置是否只播放一次
372
429
  - 使用:`import AnimationNumber from '@rxdrag/website-lib/components/AnimationNumber.astro'`
373
430
  - 不作为原子原因:包含复杂的动画逻辑、视口检测、MutationObserver 等业务逻辑(218 行代码)
374
431
 
432
+ **YearsSince(年限计算)**
433
+
434
+ ```ts
435
+ interface YearsSinceProps {
436
+ startYear?: number;
437
+ minYears?: number;
438
+ offset?: number;
439
+ suffix?: string;
440
+ }
441
+ ```
442
+
443
+ - 职责:根据起始年份计算当前年数差,并支持最小年数/偏移量/后缀
444
+ - 使用:`import YearsSince from '@rxdrag/website-lib/components/YearsSince.astro'`
445
+
375
446
  > 以下是包含复杂交互逻辑和状态管理的组件,作为可复用的业务组件由开发者直接导入使用
376
447
 
377
448
  **Dialog(对话框/弹窗)**
449
+
378
450
  - 职责:模态对话框,支持原生 `<dialog>` 和降级方案
379
451
  - 特点:包含打开/关闭动画、backdrop 控制、焦点管理、ESC/点击外部关闭、多种定位方式(center/top)
380
452
  - 使用:`import Dialog from '@rxdrag/website-lib/components/Dialog.astro'`
381
453
  - 不作为原子原因:交互逻辑复杂(375 行代码),包含状态机、动画协调、原生 API 降级处理等业务逻辑
382
454
 
383
455
  **Popover(弹出面板)**
456
+
384
457
  - 职责:悬浮展开面板,支持 hover/click 触发
385
458
  - 特点:包含高度动画、hover 延迟、点击外部关闭、ESC 关闭、全局 popover 协调
386
459
  - 使用:`import Popover from '@rxdrag/website-lib/components/Popover.astro'`
387
460
  - 不作为原子原因:交互逻辑复杂(188 行代码),包含事件协调、动画状态管理等业务逻辑
388
461
 
389
462
  **Collapse(折叠面板)**
463
+
390
464
  - 职责:可折叠内容区域(手风琴)
391
465
  - 特点:包含高度动画、初始状态支持、aria 属性管理、支持 Astro SPA 导航
392
466
  - 使用:`import Collapse from '@rxdrag/website-lib/components/Collapse.astro'`
393
467
  - 不作为原子原因:交互逻辑复杂(126 行代码),包含动画状态管理、transitionend 事件处理等业务逻辑
394
468
 
395
469
  **ContactForm(询盘表单)**
470
+
396
471
  - 职责:完整询盘表单(字段渲染 + 校验 + 提交 + 防机器人 + 上传)
397
472
  - 特点:内置 email/message 校验、honeypot(phone)防机器人、encryptedField 加密字段、提交状态与错误提示、可配置字段列表(fields)
398
473
  - 使用:`import { ContactForm } from '@rxdrag/website-lib-core/src/react/components/ContactForm'`
399
474
  - 不作为原子原因:包含实际业务逻辑与提交流程,不适合作为冻结原子
400
475
 
401
476
  **Carousel(轮播)**
477
+
402
478
  - 职责:图片/内容轮播展示
403
479
  - 特点:自动播放、手动切换、无限循环、指示器、响应式、触摸滑动支持
404
480
  - 使用:`import Carousel from '@rxdrag/website-lib/components/Carousel.astro'`(待实现)
405
481
  - 不作为原子原因:交互逻辑复杂,包含自动播放定时器、触摸事件处理、动画状态管理等业务逻辑
406
482
 
407
483
  **Tabs(标签页)**
484
+
408
485
  - 职责:标签页切换展示
409
486
  - 特点:支持水平/垂直布局、键盘导航、URL 同步、懒加载内容
410
487
  - 使用:`import Tabs from '@rxdrag/website-lib/components/Tabs.astro'`(待实现)
411
488
  - 不作为原子原因:交互逻辑复杂,包含状态管理、键盘事件处理、URL 路由同步等业务逻辑
412
489
 
413
490
  **Card(卡片)**
491
+
414
492
  - 职责:内容卡片容器(图片 + 标题 + 描述 + 操作按钮等)
415
493
  - 特点:支持多种布局变体(横向/纵向)、悬停效果、阴影/边框样式、可点击/可展开
416
494
  - 使用:`import Card from '@rxdrag/website-lib/components/Card.astro'`(待实现)
417
495
  - 不作为原子原因:组合结构复杂,包含多个子元素(header/body/footer)和交互状态,形态多变
418
496
 
419
497
  **Medias(图片画廊)**
498
+
420
499
  - 职责:图片/视频画廊展示(主图 + 缩略图导航)
421
500
  - 特点:缩略图切换、键盘控制(方向键)、图片缩放、视频播放、左右箭头导航、支持横向/纵向缩略图布局
422
501
  - 使用:`import { Medias } from '@rxdrag/website-lib-core/src/react/components/Medias'`
423
502
  - 不作为原子原因:交互逻辑复杂(264 行代码),包含状态管理、键盘事件处理、缩略图滚动计算等业务逻辑
424
503
 
425
504
  **说明**:
505
+
426
506
  - 这些组件形态多变、易滥用,不适合作为冻结原子
427
507
  - 它们包含的 JavaScript 业务逻辑无法简化为设计器模板
428
508
  - 开发者可以直接导入使用,或根据具体需求自行封装变体
@@ -463,7 +543,7 @@ interface AnimationNumberProps {
463
543
  - **Announcement Bar(顶部通知栏)**:用设计器提供一个"Announcement Bar 模板/Designer":一键生成顶部通知栏(促销信息/公告),支持配置文案、链接、背景色、关闭按钮、多条轮播
464
544
  - **Hero Section(首屏大图)**:用设计器提供一个"Hero Section 模板/Designer":一键生成首屏区块(背景图/视频 + 标题 + 副标题 + CTA 按钮),支持配置背景类型、文字对齐、叠加层、高度等
465
545
  - **Stats Section(数据统计)**:用设计器提供一个"Stats Section 模板/Designer":一键生成数据统计区块(多个数字+标签的展示),支持配置数字、标签、图标、列数、动画效果(配合 AnimationNumber)
466
- - **CTA Section(大横幅CTA)**:用设计器提供一个"CTA Section 模板/Designer":一键生成页面中间的行动号召横幅(背景 + 标题 + 描述 + CTA 按钮),支持配置背景、按钮样式
546
+ - **CTA Section(大横幅 CTA)**:用设计器提供一个"CTA Section 模板/Designer":一键生成页面中间的行动号召横幅(背景 + 标题 + 描述 + CTA 按钮),支持配置背景、按钮样式
467
547
  - **Team Section(团队展示)**:用设计器提供一个"Team Section 模板/Designer":一键生成团队成员展示区块(头像 + 姓名 + 职位 + 社交链接),支持配置列数、卡片样式
468
548
  - **Process/Steps(流程/步骤)**:用设计器提供一个"Process/Steps 模板/Designer":一键生成流程/步骤展示(步骤编号 + 标题 + 描述 + 连接线),支持配置横向/纵向布局、步骤数量、图标
469
549
  - **Pricing Table(价格表)**:用设计器提供一个"Pricing Table 模板/Designer":一键生成定价方案展示(方案名称 + 价格 + 功能列表 + CTA 按钮),支持配置列数、高亮推荐方案、货币符号
package/index.ts CHANGED
@@ -1,4 +1,12 @@
1
1
  // Do not write code directly here, instead use the `src` folder!
2
2
  // Then, use this file to export everything you want your user to access.
3
3
 
4
- export {};
4
+ export { default as Link } from "./components/Link.astro";
5
+ export { default as Meta } from "./components/Meta.astro";
6
+ export { default as Dialog } from "./components/Dialog.astro";
7
+ export { default as DialogTrigger } from "./components/DialogTrigger.astro";
8
+ export { default as ModalTrigger } from "./components/DialogTrigger.astro";
9
+ export { default as Document } from "./components/Document.astro";
10
+ export { default as Motion } from "./components/Motion.astro";
11
+ export { default as RichTextView } from "./components/RichTextView.astro";
12
+ export { default as AnimationNumber } from "./components/AnimationNumber.astro";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rxdrag/website-lib",
3
- "version": "0.0.121",
3
+ "version": "0.0.123",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./index.ts",
@@ -23,22 +23,22 @@
23
23
  "@types/react": "^19.1.0",
24
24
  "@types/react-dom": "^19.1.0",
25
25
  "astro": "^4.0.0",
26
- "eslint": "^7.32.0",
26
+ "eslint": "^9.39.2",
27
27
  "gsap": "^3.12.7",
28
28
  "typescript": "^5",
29
- "@rxdrag/eslint-config-custom": "0.2.12",
30
- "@rxdrag/slate-preview": "1.2.63",
31
- "@rxdrag/rxcms-models": "0.3.96",
32
- "@rxdrag/entify-hooks": "0.2.77",
33
- "@rxdrag/tsconfig": "0.2.0"
29
+ "@rxdrag/rxcms-models": "0.3.97",
30
+ "@rxdrag/entify-hooks": "0.2.78",
31
+ "@rxdrag/eslint-config-custom": "0.2.13",
32
+ "@rxdrag/tsconfig": "0.2.1",
33
+ "@rxdrag/tiptap-preview": "0.0.2"
34
34
  },
35
35
  "dependencies": {
36
36
  "aos": "3.0.0-beta.6",
37
37
  "clsx": "^2.1.0",
38
38
  "react": "^19.1.0",
39
39
  "react-dom": "^19.1.0",
40
- "@rxdrag/website-lib-core": "0.0.115",
41
- "@rxdrag/rxcms-models": "0.3.96"
40
+ "@rxdrag/website-lib-core": "0.0.119",
41
+ "@rxdrag/rxcms-models": "0.3.97"
42
42
  },
43
43
  "peerDependencies": {
44
44
  "astro": "^4.0.0 || ^5.0.0"