willa-workspace 0.0.3-alpha.2739b3e → 0.0.4
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/example/src/App.tsx +22 -5
- package/example/src/catalog/defineDoc.tsx +1 -0
- package/example/src/catalog/registry.ts +1 -0
- package/example/src/docs/Anchor.demo.tsx +6 -0
- package/example/src/docs/Breadcrumb.demo.tsx +6 -0
- package/example/src/docs/Button.demo.tsx +6 -0
- package/example/src/docs/FloatButton.demo.tsx +23 -4
- package/example/src/docs/Lightbox.demo.tsx +8 -4
- package/example/src/docs/List.demo.tsx +12 -0
- package/example/src/docs/Mdx.demo.tsx +46 -3
- package/example/src/docs/Pagination.demo.tsx +6 -0
- package/example/src/docs/SiteNav.demo.tsx +65 -0
- package/example/src/docs/WillaShell.demo.tsx +88 -0
- package/package.json +1 -1
- package/packages/willa/package.json +1 -1
- package/packages/willa/src/Mdx/index.tsx +5 -1
- package/packages/willa/src/WillaShell/index.tsx +2 -0
- package/packages/willa-ai/package.json +1 -1
- package/packages/willa-content/package.json +1 -1
- package/packages/willa-content/src/components/Anchor/index.tsx +41 -19
- package/packages/willa-content/src/components/Breadcrumb/index.tsx +19 -11
- package/packages/willa-content/src/components/Button/index.tsx +56 -33
- package/packages/willa-content/src/components/FloatButton/index.css +46 -1
- package/packages/willa-content/src/components/FloatButton/index.tsx +30 -4
- package/packages/willa-content/src/components/Lightbox/index.tsx +53 -0
- package/packages/willa-content/src/components/List/index.tsx +40 -23
- package/packages/willa-content/src/components/Pagination/index.tsx +23 -10
- package/packages/willa-content/src/themes/dark.css +5 -2
- package/packages/willa-content/src/themes/light.css +3 -0
- package/packages/willa-form/package.json +1 -1
- package/packages/willa-layout/package.json +1 -1
- package/packages/willa-layout/src/components/WillaShell/index.css +5 -0
- package/packages/willa-layout/src/components/WillaShell/index.tsx +20 -0
- package/packages/willa-layout/src/index.ts +2 -0
- package/packages/willa-shared/package.json +1 -1
- package/packages/willa-shared/src/index.ts +1 -0
- package/packages/willa-shared/src/link.ts +11 -0
- package/packages/willa-shared/src/virtualScroll.ts +1 -1
- package/packages/willa-widgets/package.json +1 -1
- package/packages/willa-widgets/src/components/Mdx/index.tsx +5 -0
- package/packages/willa-widgets/src/components/SiteNav/index.tsx +35 -18
- package/packages/willa-widgets/src/index.ts +1 -1
package/example/src/App.tsx
CHANGED
|
@@ -20,6 +20,7 @@ import { PageHeader } from "willa/PageHeader";
|
|
|
20
20
|
import { Typography } from "willa/Typography";
|
|
21
21
|
import { SearchInput } from "willa/SearchInput";
|
|
22
22
|
import { Skeleton } from "willa/Skeleton";
|
|
23
|
+
import { WillaShell } from "willa/WillaShell";
|
|
23
24
|
import "willa/AppShell.css";
|
|
24
25
|
import "willa/Anchor.css";
|
|
25
26
|
import "willa/Callout.css";
|
|
@@ -29,6 +30,7 @@ import "willa/PageHeader.css";
|
|
|
29
30
|
import "willa/SearchInput.css";
|
|
30
31
|
import "willa/Skeleton.css";
|
|
31
32
|
import "willa/Typography.css";
|
|
33
|
+
import "willa/WillaShell.css";
|
|
32
34
|
|
|
33
35
|
import {
|
|
34
36
|
componentDocRegistry,
|
|
@@ -190,6 +192,7 @@ const docChineseNames: Record<string, string> = {
|
|
|
190
192
|
VideoLink: "视频链接",
|
|
191
193
|
Watermark: "水印",
|
|
192
194
|
WebEmbed: "网页嵌入",
|
|
195
|
+
WillaShell: "Willa 作用域",
|
|
193
196
|
XPostEmbed: "X 内容嵌入",
|
|
194
197
|
};
|
|
195
198
|
|
|
@@ -292,6 +295,7 @@ export function App() {
|
|
|
292
295
|
const [isDocLoading, setIsDocLoading] = useState(false);
|
|
293
296
|
const [docError, setDocError] = useState<string | null>(null);
|
|
294
297
|
const [sidebarQuery, setSidebarQuery] = useState(getInitialSidebarQuery);
|
|
298
|
+
const [isCompactSidebar, setIsCompactSidebar] = useState(getIsCompactSidebar);
|
|
295
299
|
const [expandedDocGroups, setExpandedDocGroups] = useState(() =>
|
|
296
300
|
getDefaultExpandedDocGroups(!getIsCompactSidebar()),
|
|
297
301
|
);
|
|
@@ -318,6 +322,12 @@ export function App() {
|
|
|
318
322
|
(count, group) => count + group.docs.length,
|
|
319
323
|
0,
|
|
320
324
|
);
|
|
325
|
+
const backToTopFloatButtonProps = isCompactSidebar
|
|
326
|
+
? {
|
|
327
|
+
hoverTextColor: "var(--willa-text-strong)",
|
|
328
|
+
variant: "ghost" as const,
|
|
329
|
+
}
|
|
330
|
+
: {};
|
|
321
331
|
|
|
322
332
|
const startAnchorItems: Array<AnchorItem> = [
|
|
323
333
|
{
|
|
@@ -387,7 +397,7 @@ export function App() {
|
|
|
387
397
|
);
|
|
388
398
|
|
|
389
399
|
const sidebar = (
|
|
390
|
-
<div className="docs-sidebar
|
|
400
|
+
<div className="docs-sidebar">
|
|
391
401
|
<div className="docs-sidebar-top">
|
|
392
402
|
<a className="docs-brand" href={`#/${usagePageId}`}>
|
|
393
403
|
<span className="docs-brand-mark">W</span>
|
|
@@ -496,9 +506,11 @@ export function App() {
|
|
|
496
506
|
useEffect(() => {
|
|
497
507
|
const media = window.matchMedia(sidebarCompactQuery);
|
|
498
508
|
const updateExpandedGroups = () => {
|
|
509
|
+
setIsCompactSidebar(media.matches);
|
|
499
510
|
setExpandedDocGroups(getDefaultExpandedDocGroups(!media.matches));
|
|
500
511
|
};
|
|
501
512
|
|
|
513
|
+
updateExpandedGroups();
|
|
502
514
|
media.addEventListener("change", updateExpandedGroups);
|
|
503
515
|
|
|
504
516
|
return () => {
|
|
@@ -570,7 +582,7 @@ export function App() {
|
|
|
570
582
|
}, [activeEntry]);
|
|
571
583
|
|
|
572
584
|
return (
|
|
573
|
-
|
|
585
|
+
<WillaShell>
|
|
574
586
|
<AppShell className="docs-app" sidebar={sidebar} sidebarWidth="324px">
|
|
575
587
|
<div className="docs-main" ref={docsMainRef}>
|
|
576
588
|
<PageHeader
|
|
@@ -580,7 +592,7 @@ export function App() {
|
|
|
580
592
|
actions={renderDocsActions("docs-actions docs-header-actions")}
|
|
581
593
|
/>
|
|
582
594
|
|
|
583
|
-
<div className="docs-content
|
|
595
|
+
<div className="docs-content">
|
|
584
596
|
{activeId === usagePageId ? (
|
|
585
597
|
<UsageGuide />
|
|
586
598
|
) : loadedDoc ? (
|
|
@@ -607,7 +619,12 @@ export function App() {
|
|
|
607
619
|
</div>
|
|
608
620
|
</div>
|
|
609
621
|
</AppShell>
|
|
610
|
-
<FloatButton
|
|
611
|
-
|
|
622
|
+
<FloatButton
|
|
623
|
+
backToTop
|
|
624
|
+
ariaLabel="回到顶部"
|
|
625
|
+
tooltip="回到顶部"
|
|
626
|
+
{...backToTopFloatButtonProps}
|
|
627
|
+
/>
|
|
628
|
+
</WillaShell>
|
|
612
629
|
);
|
|
613
630
|
}
|
|
@@ -187,6 +187,12 @@ export default defineDoc({
|
|
|
187
187
|
type: "Partial<Record<AnchorSlot, string>>",
|
|
188
188
|
description: "按语义槽位追加 className,用于定制局部样式。",
|
|
189
189
|
},
|
|
190
|
+
{
|
|
191
|
+
name: "renderLink",
|
|
192
|
+
type: "(props: WillaRenderLinkProps) => ReactNode",
|
|
193
|
+
description:
|
|
194
|
+
"自定义目录项链接渲染,可接入客户端路由;未传时渲染原生 a 标签。",
|
|
195
|
+
},
|
|
190
196
|
{
|
|
191
197
|
name: "styles",
|
|
192
198
|
type: "Partial<Record<AnchorSlot, CSSProperties>>",
|
|
@@ -141,6 +141,12 @@ export default defineDoc({
|
|
|
141
141
|
defaultValue: "<ChevronRightIcon />",
|
|
142
142
|
description: "分隔符,默认使用箭头图标。",
|
|
143
143
|
},
|
|
144
|
+
{
|
|
145
|
+
name: "renderLink",
|
|
146
|
+
type: "(props: WillaRenderLinkProps) => ReactNode",
|
|
147
|
+
description:
|
|
148
|
+
"自定义非当前项链接渲染,可接入客户端路由;未传时渲染原生 a 标签。",
|
|
149
|
+
},
|
|
144
150
|
{
|
|
145
151
|
name: "BreadcrumbItem.label",
|
|
146
152
|
type: "ReactNode",
|
|
@@ -226,6 +226,12 @@ export default defineDoc({
|
|
|
226
226
|
type: "string",
|
|
227
227
|
description: "传入后渲染为链接按钮。",
|
|
228
228
|
},
|
|
229
|
+
{
|
|
230
|
+
name: "renderLink",
|
|
231
|
+
type: "(props: WillaRenderLinkProps) => ReactNode",
|
|
232
|
+
description:
|
|
233
|
+
"自定义链接渲染。传入 href 时可接入客户端路由,未传时渲染原生 a 标签;disabled 或 loading 时不会调用。",
|
|
234
|
+
},
|
|
229
235
|
{
|
|
230
236
|
name: "icon",
|
|
231
237
|
type: "ReactNode",
|
|
@@ -64,6 +64,8 @@ const BackToTopPreview = () => {
|
|
|
64
64
|
</Stack>
|
|
65
65
|
<FloatButton
|
|
66
66
|
backToTop
|
|
67
|
+
variant="ghost"
|
|
68
|
+
hoverTextColor="var(--willa-text-strong)"
|
|
67
69
|
target={() => document.querySelector("[data-float-button-scroll]")}
|
|
68
70
|
/>
|
|
69
71
|
</div>
|
|
@@ -214,7 +216,9 @@ const CustomColorPreview = () => {
|
|
|
214
216
|
label="上线中心"
|
|
215
217
|
description="查看待发布项"
|
|
216
218
|
backgroundColor="#1f2937"
|
|
219
|
+
hoverBackgroundColor="#111827"
|
|
217
220
|
textColor="#f8fafc"
|
|
221
|
+
hoverTextColor="#ffffff"
|
|
218
222
|
badge="2"
|
|
219
223
|
/>
|
|
220
224
|
</div>
|
|
@@ -452,7 +456,9 @@ export default defineDoc({
|
|
|
452
456
|
label="上线中心"
|
|
453
457
|
description="查看待发布项"
|
|
454
458
|
backgroundColor="#1f2937"
|
|
459
|
+
hoverBackgroundColor="#111827"
|
|
455
460
|
textColor="#f8fafc"
|
|
461
|
+
hoverTextColor="#ffffff"
|
|
456
462
|
badge="2"
|
|
457
463
|
/>
|
|
458
464
|
</div>;
|
|
@@ -498,6 +504,8 @@ export default defineDoc({
|
|
|
498
504
|
<FloatButton
|
|
499
505
|
icon={<ArrowUpIcon />}
|
|
500
506
|
backToTop
|
|
507
|
+
variant="ghost"
|
|
508
|
+
hoverTextColor="var(--willa-text-strong)"
|
|
501
509
|
target={() => document.querySelector("[data-float-button-scroll]")}
|
|
502
510
|
/>
|
|
503
511
|
</div>;
|
|
@@ -536,22 +544,33 @@ export default defineDoc({
|
|
|
536
544
|
type: "string",
|
|
537
545
|
description: "自定义按钮背景色。",
|
|
538
546
|
},
|
|
547
|
+
{
|
|
548
|
+
name: "hoverBackgroundColor",
|
|
549
|
+
type: "string",
|
|
550
|
+
description: "自定义 hover 状态背景色。ghost 未传时保持透明。",
|
|
551
|
+
},
|
|
539
552
|
{
|
|
540
553
|
name: "textColor",
|
|
541
554
|
type: "string",
|
|
542
555
|
description: "自定义按钮文字和图标颜色。",
|
|
543
556
|
},
|
|
557
|
+
{
|
|
558
|
+
name: "hoverTextColor",
|
|
559
|
+
type: "string",
|
|
560
|
+
description: "自定义 hover 状态文字和图标颜色。",
|
|
561
|
+
},
|
|
544
562
|
{
|
|
545
563
|
name: "variant",
|
|
546
|
-
type: '"default" | "primary"',
|
|
564
|
+
type: '"default" | "primary" | "ghost"',
|
|
547
565
|
defaultValue: '"default"',
|
|
548
|
-
description: "视觉变体。",
|
|
566
|
+
description: "视觉变体。ghost 会隐藏背景、边框和阴影,只保留内容。",
|
|
549
567
|
},
|
|
550
568
|
{
|
|
551
569
|
name: "shape",
|
|
552
570
|
type: '"circle" | "square"',
|
|
553
|
-
defaultValue: "
|
|
554
|
-
description:
|
|
571
|
+
defaultValue: "backToTop 为圆形,否则为方形",
|
|
572
|
+
description:
|
|
573
|
+
"按钮形状。未传时普通悬浮按钮使用方形,回到顶部按钮使用圆形。",
|
|
555
574
|
},
|
|
556
575
|
{
|
|
557
576
|
name: "size",
|
|
@@ -69,7 +69,8 @@ export default defineDoc({
|
|
|
69
69
|
id: "lightbox",
|
|
70
70
|
name: "Lightbox",
|
|
71
71
|
packageName: "willa/Lightbox",
|
|
72
|
-
description:
|
|
72
|
+
description:
|
|
73
|
+
"占满视口的图片预览弹层,打开时会锁定页面滚动,并支持 Escape 关闭和左右方向键切换。",
|
|
73
74
|
imports: [
|
|
74
75
|
{ name: "Button", from: "willa/Button" },
|
|
75
76
|
{ name: "Image", from: "willa/Image" },
|
|
@@ -152,17 +153,20 @@ export default defineDoc({
|
|
|
152
153
|
{
|
|
153
154
|
name: "onClose",
|
|
154
155
|
type: "() => void",
|
|
155
|
-
description:
|
|
156
|
+
description:
|
|
157
|
+
"受控模式下弹层需要关闭时触发;点击背景、点击图片或按 Escape 都会调用。",
|
|
156
158
|
},
|
|
157
159
|
{
|
|
158
160
|
name: "onPrev",
|
|
159
161
|
type: "() => void",
|
|
160
|
-
description:
|
|
162
|
+
description:
|
|
163
|
+
"可选的上一张图片操作;传入后左侧按钮和 ArrowLeft 都会调用。",
|
|
161
164
|
},
|
|
162
165
|
{
|
|
163
166
|
name: "onNext",
|
|
164
167
|
type: "() => void",
|
|
165
|
-
description:
|
|
168
|
+
description:
|
|
169
|
+
"可选的下一张图片操作;传入后右侧按钮和 ArrowRight 都会调用。",
|
|
166
170
|
},
|
|
167
171
|
{
|
|
168
172
|
name: "backdrop",
|
|
@@ -912,6 +912,12 @@ export default defineDoc({
|
|
|
912
912
|
type: "(item: ListItem) => ReactNode",
|
|
913
913
|
description: "完全自定义单条渲染。",
|
|
914
914
|
},
|
|
915
|
+
{
|
|
916
|
+
name: "renderLink",
|
|
917
|
+
type: "(props: WillaRenderLinkProps) => ReactNode",
|
|
918
|
+
description:
|
|
919
|
+
"自定义条目链接渲染,可接入客户端路由;仅在条目有 href 且未禁用时调用。",
|
|
920
|
+
},
|
|
915
921
|
{
|
|
916
922
|
name: "onItemsChange",
|
|
917
923
|
type: "(items: Array<ListItem>) => void",
|
|
@@ -1000,6 +1006,12 @@ export default defineDoc({
|
|
|
1000
1006
|
type: "HTMLAnchorElement['target']",
|
|
1001
1007
|
description: "链接打开方式。",
|
|
1002
1008
|
},
|
|
1009
|
+
{
|
|
1010
|
+
name: "ListItem.rel",
|
|
1011
|
+
type: "HTMLAnchorElement['rel']",
|
|
1012
|
+
description:
|
|
1013
|
+
"链接 rel 属性;target 为 _blank 且未传 rel 时默认使用 noreferrer。",
|
|
1014
|
+
},
|
|
1003
1015
|
{
|
|
1004
1016
|
name: "virtualScrollItemHeight",
|
|
1005
1017
|
type: "number",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { unindent } from "aidly";
|
|
2
|
-
import { useState, type ElementType } from "react";
|
|
2
|
+
import { useState, type ComponentProps, type ElementType } from "react";
|
|
3
3
|
import { Lightbox } from "willa/Lightbox";
|
|
4
|
-
import { Mdx } from "willa/Mdx";
|
|
4
|
+
import { Mdx, type MdxComponents } from "willa/Mdx";
|
|
5
5
|
|
|
6
6
|
import "willa/Mdx.css";
|
|
7
7
|
|
|
@@ -30,6 +30,28 @@ const galleryImages = [
|
|
|
30
30
|
const resolveDemoAssetUrl = (_articleSourcePath: string, assetPath: string) =>
|
|
31
31
|
assetPath;
|
|
32
32
|
|
|
33
|
+
const ArticleLink = (props: ComponentProps<"a">) => {
|
|
34
|
+
const { children, style, ...rest } = props;
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<a
|
|
38
|
+
{...rest}
|
|
39
|
+
style={{
|
|
40
|
+
color: "var(--willa-color-blue)",
|
|
41
|
+
fontWeight: 720,
|
|
42
|
+
textUnderlineOffset: "0.18em",
|
|
43
|
+
...style,
|
|
44
|
+
}}
|
|
45
|
+
>
|
|
46
|
+
{children}
|
|
47
|
+
</a>
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const mdxComponents = {
|
|
52
|
+
a: ArticleLink,
|
|
53
|
+
} satisfies MdxComponents;
|
|
54
|
+
|
|
33
55
|
const DemoMdxContent = (props: Record<string, unknown>) => {
|
|
34
56
|
const components = (props.components ?? {}) as Record<string, ElementType>;
|
|
35
57
|
const H1 = components.h1 ?? "h1";
|
|
@@ -258,6 +280,7 @@ const MdxPreview = () => {
|
|
|
258
280
|
articleSourcePath="/posts/demo.mdx"
|
|
259
281
|
resolveAssetUrl={resolveDemoAssetUrl}
|
|
260
282
|
openLightbox={setLightbox}
|
|
283
|
+
components={mdxComponents}
|
|
261
284
|
/>
|
|
262
285
|
{lightbox?.selectedImage ? (
|
|
263
286
|
<Lightbox
|
|
@@ -282,12 +305,25 @@ export default defineDoc({
|
|
|
282
305
|
component: MdxPreview,
|
|
283
306
|
},
|
|
284
307
|
code: unindent(`
|
|
285
|
-
import { Mdx } from "willa/Mdx";
|
|
308
|
+
import { Mdx, type MdxComponents } from "willa/Mdx";
|
|
286
309
|
import "willa/Mdx.css";
|
|
287
310
|
|
|
288
311
|
const resolveAssetUrl = (_articleSourcePath: string, assetPath: string) =>
|
|
289
312
|
assetPath;
|
|
290
313
|
|
|
314
|
+
const mdxComponents = {
|
|
315
|
+
a: ({ href, children, ...props }) =>
|
|
316
|
+
href?.startsWith("https://") ? (
|
|
317
|
+
<a href={href} target="_blank" rel="noreferrer" {...props}>
|
|
318
|
+
{children}
|
|
319
|
+
</a>
|
|
320
|
+
) : (
|
|
321
|
+
<a href={href} {...props}>
|
|
322
|
+
{children}
|
|
323
|
+
</a>
|
|
324
|
+
),
|
|
325
|
+
} satisfies MdxComponents;
|
|
326
|
+
|
|
291
327
|
function DemoMdxContent(props) {
|
|
292
328
|
const {
|
|
293
329
|
h1: H1 = "h1",
|
|
@@ -313,6 +349,7 @@ export default defineDoc({
|
|
|
313
349
|
Content={DemoMdxContent}
|
|
314
350
|
articleSourcePath="/posts/demo.mdx"
|
|
315
351
|
resolveAssetUrl={resolveAssetUrl}
|
|
352
|
+
components={mdxComponents}
|
|
316
353
|
/>;
|
|
317
354
|
`),
|
|
318
355
|
props: [
|
|
@@ -334,6 +371,12 @@ export default defineDoc({
|
|
|
334
371
|
required: true,
|
|
335
372
|
description: "把 MDX 中的相对资源转换为可访问 URL。",
|
|
336
373
|
},
|
|
374
|
+
{
|
|
375
|
+
name: "components",
|
|
376
|
+
type: "MdxComponents",
|
|
377
|
+
description:
|
|
378
|
+
"覆盖内置 MDX 组件映射。可接管链接、标题、图片或自定义组件策略,未覆盖的项继续使用 Willa 默认映射。",
|
|
379
|
+
},
|
|
337
380
|
{
|
|
338
381
|
name: "openLightbox",
|
|
339
382
|
type: "(state: LightboxState | null) => void",
|
|
@@ -219,6 +219,12 @@ export default defineDoc({
|
|
|
219
219
|
description:
|
|
220
220
|
"返回页码链接地址;适合文章列表、搜索结果等需要真实 URL 的分页。",
|
|
221
221
|
},
|
|
222
|
+
{
|
|
223
|
+
name: "renderLink",
|
|
224
|
+
type: "(props: WillaRenderLinkProps) => ReactNode",
|
|
225
|
+
description:
|
|
226
|
+
"自定义页码链接渲染,可接入客户端路由;仅在 getPageHref 返回地址且页码可点击时调用。",
|
|
227
|
+
},
|
|
222
228
|
{
|
|
223
229
|
name: "getEllipsisPage",
|
|
224
230
|
type: "(context: PaginationEllipsisContext) => number",
|
|
@@ -12,6 +12,17 @@ const navItems: Array<SiteNavItem> = [
|
|
|
12
12
|
{ label: "价格", href: "#pricing" },
|
|
13
13
|
];
|
|
14
14
|
|
|
15
|
+
const routeNavItems: Array<SiteNavItem> = [
|
|
16
|
+
{ label: "组件", href: "/components", active: true },
|
|
17
|
+
{ label: "文档", href: "/docs" },
|
|
18
|
+
{
|
|
19
|
+
label: "GitHub",
|
|
20
|
+
href: "https://github.com/imtaotao/willa",
|
|
21
|
+
target: "_blank",
|
|
22
|
+
rel: "noreferrer",
|
|
23
|
+
},
|
|
24
|
+
];
|
|
25
|
+
|
|
15
26
|
export default defineDoc({
|
|
16
27
|
id: "site-nav",
|
|
17
28
|
name: "SiteNav",
|
|
@@ -91,6 +102,54 @@ export default defineDoc({
|
|
|
91
102
|
/>
|
|
92
103
|
),
|
|
93
104
|
},
|
|
105
|
+
{
|
|
106
|
+
title: "路由链接",
|
|
107
|
+
code: `
|
|
108
|
+
import { Link } from "react-router-dom";
|
|
109
|
+
import { SiteNav, type SiteNavItem } from "willa/SiteNav";
|
|
110
|
+
import "willa/SiteNav.css";
|
|
111
|
+
|
|
112
|
+
const items: Array<SiteNavItem> = [
|
|
113
|
+
{ label: "组件", href: "/components", active: true },
|
|
114
|
+
{ label: "文档", href: "/docs" },
|
|
115
|
+
{
|
|
116
|
+
label: "GitHub",
|
|
117
|
+
href: "https://github.com/imtaotao/willa",
|
|
118
|
+
target: "_blank",
|
|
119
|
+
rel: "noreferrer",
|
|
120
|
+
},
|
|
121
|
+
];
|
|
122
|
+
|
|
123
|
+
<SiteNav
|
|
124
|
+
brand="Willa"
|
|
125
|
+
brandHref="/"
|
|
126
|
+
items={items}
|
|
127
|
+
renderLink={({ href, children, ...props }) =>
|
|
128
|
+
href.startsWith("http") ? (
|
|
129
|
+
<a href={href} {...props}>
|
|
130
|
+
{children}
|
|
131
|
+
</a>
|
|
132
|
+
) : (
|
|
133
|
+
<Link to={href} {...props}>
|
|
134
|
+
{children}
|
|
135
|
+
</Link>
|
|
136
|
+
)
|
|
137
|
+
}
|
|
138
|
+
/>;
|
|
139
|
+
`,
|
|
140
|
+
content: (
|
|
141
|
+
<SiteNav
|
|
142
|
+
brand="Willa"
|
|
143
|
+
brandHref="/"
|
|
144
|
+
items={routeNavItems}
|
|
145
|
+
renderLink={({ href, children, ...props }) => (
|
|
146
|
+
<a href={href} {...props}>
|
|
147
|
+
{children}
|
|
148
|
+
</a>
|
|
149
|
+
)}
|
|
150
|
+
/>
|
|
151
|
+
),
|
|
152
|
+
},
|
|
94
153
|
],
|
|
95
154
|
props: [
|
|
96
155
|
{
|
|
@@ -126,6 +185,12 @@ export default defineDoc({
|
|
|
126
185
|
defaultValue: "false",
|
|
127
186
|
description: "是否吸附在页面顶部。",
|
|
128
187
|
},
|
|
188
|
+
{
|
|
189
|
+
name: "renderLink",
|
|
190
|
+
type: "(props: WillaRenderLinkProps) => ReactNode",
|
|
191
|
+
description:
|
|
192
|
+
"自定义品牌和导航项链接渲染,可接入客户端路由;未传时渲染原生 a 标签。",
|
|
193
|
+
},
|
|
129
194
|
{
|
|
130
195
|
name: "SiteNavItem.label",
|
|
131
196
|
type: "ReactNode",
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { WillaShell } from "willa/WillaShell";
|
|
2
|
+
import "willa/WillaShell.css";
|
|
3
|
+
|
|
4
|
+
import { defineDoc } from "#example/catalog/defineDoc";
|
|
5
|
+
|
|
6
|
+
const shellStyle = {
|
|
7
|
+
border: "1px solid var(--willa-border)",
|
|
8
|
+
borderRadius: "0.75rem",
|
|
9
|
+
padding: "1rem",
|
|
10
|
+
background: "var(--willa-surface)",
|
|
11
|
+
} as const;
|
|
12
|
+
|
|
13
|
+
export default defineDoc({
|
|
14
|
+
id: "willa-shell",
|
|
15
|
+
name: "WillaShell",
|
|
16
|
+
displayName: "Willa 作用域",
|
|
17
|
+
category: "layout",
|
|
18
|
+
packageName: "willa/WillaShell",
|
|
19
|
+
description: "为 Willa 组件提供统一的 .willa-shell 作用域和基础文本样式。",
|
|
20
|
+
imports: [{ name: "WillaShell", from: "willa/WillaShell" }],
|
|
21
|
+
css: "willa/WillaShell.css",
|
|
22
|
+
demo: {
|
|
23
|
+
name: "WillaShell",
|
|
24
|
+
component: WillaShell,
|
|
25
|
+
props: { style: shellStyle },
|
|
26
|
+
children: "页面或应用根节点可以包裹在 WillaShell 内。",
|
|
27
|
+
},
|
|
28
|
+
code: `
|
|
29
|
+
import { WillaShell } from "willa/WillaShell";
|
|
30
|
+
import "willa/WillaShell.css";
|
|
31
|
+
|
|
32
|
+
<WillaShell>
|
|
33
|
+
页面或应用根节点可以包裹在 WillaShell 内。
|
|
34
|
+
</WillaShell>;
|
|
35
|
+
`,
|
|
36
|
+
sections: [
|
|
37
|
+
{
|
|
38
|
+
title: "自定义根元素",
|
|
39
|
+
code: `
|
|
40
|
+
<WillaShell
|
|
41
|
+
as="main"
|
|
42
|
+
style={{
|
|
43
|
+
border: "1px solid var(--willa-border)",
|
|
44
|
+
borderRadius: "0.75rem",
|
|
45
|
+
padding: "1rem",
|
|
46
|
+
background: "var(--willa-surface)",
|
|
47
|
+
}}
|
|
48
|
+
>
|
|
49
|
+
<strong>文档页面</strong>
|
|
50
|
+
<p style={{ color: "var(--willa-text-soft)", margin: "0.5rem 0 0" }}>
|
|
51
|
+
WillaShell 会保留传入的根元素属性,并追加 willa-shell className。
|
|
52
|
+
</p>
|
|
53
|
+
</WillaShell>;
|
|
54
|
+
`,
|
|
55
|
+
content: (
|
|
56
|
+
<WillaShell as="main" style={shellStyle}>
|
|
57
|
+
<strong>文档页面</strong>
|
|
58
|
+
<p
|
|
59
|
+
style={{
|
|
60
|
+
color: "var(--willa-text-soft)",
|
|
61
|
+
margin: "0.5rem 0 0",
|
|
62
|
+
}}
|
|
63
|
+
>
|
|
64
|
+
WillaShell 会保留传入的根元素属性,并追加 willa-shell className。
|
|
65
|
+
</p>
|
|
66
|
+
</WillaShell>
|
|
67
|
+
),
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
props: [
|
|
71
|
+
{
|
|
72
|
+
name: "children",
|
|
73
|
+
type: "ReactNode",
|
|
74
|
+
description: "需要获得 Willa 作用域的页面或局部内容。",
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: "as",
|
|
78
|
+
type: "ElementType",
|
|
79
|
+
defaultValue: '"div"',
|
|
80
|
+
description: "自定义渲染标签或组件。",
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: "className",
|
|
84
|
+
type: "string",
|
|
85
|
+
description: "追加到根节点的 className,会和 willa-shell 合并。",
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
});
|
package/package.json
CHANGED